Loading...
// SPDX-License-Identifier: GPL-2.0+
/*
 * coreboot sysinfo driver
 *
 * Copyright 2023 Google LLC
 * Written by Simon Glass <sjg@chromium.org>
 */

#include <dm.h>
#include <smbios.h>
#include <sysinfo.h>
#include <asm/cb_sysinfo.h>

struct cb_sysinfo_priv {
	const struct smbios_type0 *bios;
	const struct smbios_type1 *system;
};

static int cb_get_str(struct udevice *dev, int id, size_t size, char *val)
{
	struct cb_sysinfo_priv *priv = dev_get_priv(dev);
	const char *str = NULL;

	switch (id) {
	case SYSID_BOARD_MODEL:
		if (priv->system)
			str = smbios_string(&priv->system->hdr,
					    priv->system->product_name);
		break;
	case SYSID_BOARD_MANUFACTURER:
		if (priv->system)
			str = smbios_string(&priv->system->hdr,
					    priv->system->manufacturer);
		break;
	case SYSID_PRIOR_STAGE_VERSION:
		if (priv->bios)
			str = smbios_string(&priv->bios->hdr,
					    priv->bios->bios_ver);
		break;
	case SYSID_PRIOR_STAGE_DATE:
		if (priv->bios)
			str = smbios_string(&priv->bios->hdr,
					    priv->bios->bios_release_date);
		break;
	}
	if (!str)
		return -ENOTSUPP;

	strlcpy(val, str, size);

	return  0;
}

static int cb_detect(struct udevice *dev)
{
	struct cb_sysinfo_priv *priv = dev_get_priv(dev);
	struct smbios_info info;
	int ret;

	ret = smbios_locate(lib_sysinfo.smbios_start, &info);
	if (ret)
		return 0;

	priv->bios = smbios_get_header(&info, SMBIOS_BIOS_INFORMATION);
	priv->system = smbios_get_header(&info, SMBIOS_SYSTEM_INFORMATION);

	return 0;
}

static const struct udevice_id sysinfo_coreboot_ids[] = {
	{ .compatible = "coreboot,sysinfo" },
	{ /* sentinel */ }
};

static const struct sysinfo_ops sysinfo_coreboot_ops = {
	.detect		= cb_detect,
	.get_str	= cb_get_str,
};

U_BOOT_DRIVER(sysinfo_coreboot) = {
	.name           = "sysinfo_coreboot",
	.id             = UCLASS_SYSINFO,
	.of_match       = sysinfo_coreboot_ids,
	.ops		= &sysinfo_coreboot_ops,
	.priv_auto	= sizeof(struct cb_sysinfo_priv),
};