diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Kconfig | 6 | ||||
-rw-r--r-- | lib/Makefile | 1 | ||||
-rw-r--r-- | lib/acpi/acpi_table.c | 4 | ||||
-rw-r--r-- | lib/efi_loader/Kconfig | 3 | ||||
-rw-r--r-- | lib/efi_loader/efi_bootbin.c | 87 | ||||
-rw-r--r-- | lib/efi_loader/elf_efi.ldsi | 74 | ||||
-rw-r--r-- | lib/mbedtls/Kconfig | 14 | ||||
-rw-r--r-- | lib/mbedtls/Makefile | 2 | ||||
-rw-r--r-- | lib/mbedtls/mbedtls_def_config.h | 4 | ||||
-rw-r--r-- | lib/mbedtls/sha256.c | 59 | ||||
-rw-r--r-- | lib/sha256.c | 67 | ||||
-rw-r--r-- | lib/sha256_common.c | 50 | ||||
-rw-r--r-- | lib/smbios.c | 445 |
13 files changed, 670 insertions, 146 deletions
diff --git a/lib/Kconfig b/lib/Kconfig index 8f1a96d98c4..baeb615626d 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -1091,6 +1091,12 @@ config GENERATE_SMBIOS_TABLE See also SYSINFO_SMBIOS which allows SMBIOS values to be provided in the devicetree. +config GENERATE_SMBIOS_TABLE_VERBOSE + bool "Generate a verbose SMBIOS (System Management BIOS) table" + depends on GENERATE_SMBIOS_TABLE + help + Provide verbose SMBIOS information. + endmenu config LIB_RATIONAL diff --git a/lib/Makefile b/lib/Makefile index 5cb3278d2ef..3595086af7c 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -77,6 +77,7 @@ obj-$(CONFIG_BLAKE2) += blake2/blake2b.o obj-$(CONFIG_$(XPL_)MD5_LEGACY) += md5.o obj-$(CONFIG_$(XPL_)SHA1_LEGACY) += sha1.o +obj-$(CONFIG_$(XPL_)SHA256) += sha256_common.o obj-$(CONFIG_$(XPL_)SHA256_LEGACY) += sha256.o obj-$(CONFIG_$(XPL_)SHA512_LEGACY) += sha512.o diff --git a/lib/acpi/acpi_table.c b/lib/acpi/acpi_table.c index 150f75027a5..c0ed24984af 100644 --- a/lib/acpi/acpi_table.c +++ b/lib/acpi/acpi_table.c @@ -273,7 +273,9 @@ int acpi_write_fadt(struct acpi_ctx *ctx, const struct acpi_writer *entry) return acpi_add_fadt(ctx, fadt); } +#ifndef CONFIG_QFW_ACPI ACPI_WRITER(5fadt, "FADT", acpi_write_fadt, 0); +#endif int acpi_write_madt(struct acpi_ctx *ctx, const struct acpi_writer *entry) { @@ -308,7 +310,9 @@ int acpi_write_madt(struct acpi_ctx *ctx, const struct acpi_writer *entry) return 0; } +#ifndef CONFIG_QFW_ACPI ACPI_WRITER(5madt, "MADT", acpi_write_madt, 0); +#endif void acpi_create_dbg2(struct acpi_dbg2_header *dbg2, int port_type, int port_subtype, diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig index c46ffe3a9d8..798dced475e 100644 --- a/lib/efi_loader/Kconfig +++ b/lib/efi_loader/Kconfig @@ -8,13 +8,14 @@ config EFI_LOADER SYS_CPU = armv7 || \ SYS_CPU = armv8) || \ X86 || RISCV || SANDBOX) + # We have not fully removed the requirement for some block device + depends on BLK # We need EFI_STUB_64BIT to be set on x86_64 with EFI_STUB depends on !EFI_STUB || !X86_64 || EFI_STUB_64BIT # We need EFI_STUB_32BIT to be set on x86_32 with EFI_STUB depends on !EFI_STUB || !X86 || X86_64 || EFI_STUB_32BIT depends on !EFI_APP default y if !ARM || SYS_CPU = armv7 || SYS_CPU = armv8 - select BLK select CHARSET # We need to send DM events, dynamically, in the EFI block driver select DM_EVENT diff --git a/lib/efi_loader/efi_bootbin.c b/lib/efi_loader/efi_bootbin.c index b677bbc3124..428991df88f 100644 --- a/lib/efi_loader/efi_bootbin.c +++ b/lib/efi_loader/efi_bootbin.c @@ -45,11 +45,63 @@ void efi_clear_bootdev(void) } /** + * calculate_paths() - Calculate the device and image patch from strings + * + * @dev: device, e.g. "MMC" + * @devnr: number of the device, e.g. "1:2" + * @path: path to file loaded + * @device_pathp: returns EFI device path + * @image_pathp: returns EFI image path + * Return: EFI_SUCCESS on success, else error code + */ +static efi_status_t calculate_paths(const char *dev, const char *devnr, + const char *path, + struct efi_device_path **device_pathp, + struct efi_device_path **image_pathp) +{ + struct efi_device_path *image, *device; + efi_status_t ret; + +#if IS_ENABLED(CONFIG_NETDEVICES) + if (!strcmp(dev, "Net") || !strcmp(dev, "Http")) { + ret = efi_net_set_dp(dev, devnr); + if (ret != EFI_SUCCESS) + return ret; + } +#endif + + ret = efi_dp_from_name(dev, devnr, path, &device, &image); + if (ret != EFI_SUCCESS) + return ret; + + *device_pathp = device; + if (image) { + /* FIXME: image should not contain device */ + struct efi_device_path *image_tmp = image; + + efi_dp_split_file_path(image, &device, &image); + efi_free_pool(image_tmp); + } + *image_pathp = image; + log_debug("- boot device %pD\n", device); + if (image) + log_debug("- image %pD\n", image); + + return EFI_SUCCESS; +} + +/** * efi_set_bootdev() - set boot device * * This function is called when a file is loaded, e.g. via the 'load' command. * We use the path to this file to inform the UEFI binary about the boot device. * + * For a valid image, it sets: + * - image_addr to the provided buffer + * - image_size to the provided buffer_size + * - bootefi_device_path to the EFI device-path + * - bootefi_image_path to the EFI image-path + * * @dev: device, e.g. "MMC" * @devnr: number of the device, e.g. "1:2" * @path: path to file loaded @@ -59,7 +111,6 @@ void efi_clear_bootdev(void) void efi_set_bootdev(const char *dev, const char *devnr, const char *path, void *buffer, size_t buffer_size) { - struct efi_device_path *device, *image; efi_status_t ret; log_debug("dev=%s, devnr=%s, path=%s, buffer=%p, size=%zx\n", dev, @@ -93,34 +144,12 @@ void efi_set_bootdev(const char *dev, const char *devnr, const char *path, image_addr = buffer; image_size = buffer_size; -#if IS_ENABLED(CONFIG_NETDEVICES) - if (!strcmp(dev, "Net") || !strcmp(dev, "Http")) { - ret = efi_net_set_dp(dev, devnr); - if (ret != EFI_SUCCESS) - goto error; - } -#endif - - ret = efi_dp_from_name(dev, devnr, path, &device, &image); - if (ret != EFI_SUCCESS) - goto error; - - bootefi_device_path = device; - if (image) { - /* FIXME: image should not contain device */ - struct efi_device_path *image_tmp = image; - - efi_dp_split_file_path(image, &device, &image); - efi_free_pool(image_tmp); + ret = calculate_paths(dev, devnr, path, &bootefi_device_path, + &bootefi_image_path); + if (ret) { + log_debug("- efi_dp_from_name() failed, err=%lx\n", ret); + efi_clear_bootdev(); } - bootefi_image_path = image; - log_debug("- boot device %pD\n", device); - if (image) - log_debug("- image %pD\n", image); - return; -error: - log_debug("- efi_dp_from_name() failed, err=%lx\n", ret); - efi_clear_bootdev(); } /** @@ -130,7 +159,7 @@ error: * @source_size: size of the UEFI image * Return: status code */ -efi_status_t efi_run_image(void *source_buffer, efi_uintn_t source_size) +static efi_status_t efi_run_image(void *source_buffer, efi_uintn_t source_size) { efi_handle_t mem_handle = NULL, handle; struct efi_device_path *file_path = NULL; diff --git a/lib/efi_loader/elf_efi.ldsi b/lib/efi_loader/elf_efi.ldsi new file mode 100644 index 00000000000..190a88fb69e --- /dev/null +++ b/lib/efi_loader/elf_efi.ldsi @@ -0,0 +1,74 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * U-Boot EFI linker script include + * + * Modified from elf_aarch64_efi.lds in gnu-efi + */ + +PHDRS +{ + data PT_LOAD FLAGS(3); /* SHF_WRITE | SHF_ALLOC */ +} + +ENTRY(_start) +SECTIONS +{ + .text 0x0 : { + _text = .; + *(.text.head) + *(.text) + *(.text.*) + *(.gnu.linkonce.t.*) + *(.srodata) + *(.rodata*) + . = ALIGN(16); + *(.dynamic); + . = ALIGN(512); + } + .rela.dyn : { *(.rela.dyn) } + .rela.plt : { *(.rela.plt) } + .rela.got : { *(.rela.got) } + .rela.data : { *(.rela.data) *(.rela.data*) } + . = ALIGN(4096); + _etext = .; + _text_size = . - _text; + .data : { + _data = .; + *(.sdata) + *(.data) + *(.data1) + *(.data.*) + *(.got.plt) + *(.got) + + /* + * The EFI loader doesn't seem to like a .bss section, so we + * stick it all into .data: + */ + . = ALIGN(16); + _bss = .; + *(.sbss) + *(.scommon) + *(.dynbss) + *(.bss) + *(.bss.*) + *(COMMON) + . = ALIGN(512); + _bss_end = .; + _edata = .; + } :data + _data_size = _edata - _data; + + . = ALIGN(4096); + .dynsym : { *(.dynsym) } + . = ALIGN(4096); + .dynstr : { *(.dynstr) } + . = ALIGN(4096); + .note.gnu.build-id : { *(.note.gnu.build-id) } + /DISCARD/ : { + *(.rel.reloc) + *(.eh_frame) + *(.note.GNU-stack) + } + .comment 0 : { *(.comment) } +} diff --git a/lib/mbedtls/Kconfig b/lib/mbedtls/Kconfig index 78167ffa252..aa82336ef14 100644 --- a/lib/mbedtls/Kconfig +++ b/lib/mbedtls/Kconfig @@ -297,6 +297,13 @@ config MD5_MBEDTLS This option enables support of hashing using MD5 algorithm with MbedTLS crypto library. +config HKDF_MBEDTLS + bool "Enable HKDF support with MbedTLS crypto library" + depends on MBEDTLS_LIB_CRYPTO + help + This option enables support of key derivation using HKDF algorithm + with MbedTLS crypto library. + if SPL config SPL_SHA1_MBEDTLS @@ -335,6 +342,13 @@ config SPL_MD5_MBEDTLS This option enables support of hashing using MD5 algorithm with MbedTLS crypto library. +config SPL_HKDF_MBEDTLS + bool "Enable HKDF support in SPL with MbedTLS crypto library" + depends on MBEDTLS_LIB_CRYPTO + help + This option enables support of key derivation using HKDF algorithm + with MbedTLS crypto library. + endif # SPL endif # MBEDTLS_LIB_CRYPTO diff --git a/lib/mbedtls/Makefile b/lib/mbedtls/Makefile index ce0a61e4054..e66c2018d97 100644 --- a/lib/mbedtls/Makefile +++ b/lib/mbedtls/Makefile @@ -33,6 +33,8 @@ mbedtls_lib_crypto-$(CONFIG_$(SPL_)SHA256_MBEDTLS) += \ $(MBEDTLS_LIB_DIR)/sha256.o mbedtls_lib_crypto-$(CONFIG_$(SPL_)SHA512_MBEDTLS) += \ $(MBEDTLS_LIB_DIR)/sha512.o +mbedtls_lib_crypto-$(CONFIG_$(SPL_)HKDF_MBEDTLS) += \ + $(MBEDTLS_LIB_DIR)/hkdf.o # MbedTLS X509 library obj-$(CONFIG_MBEDTLS_LIB_X509) += mbedtls_lib_x509.o diff --git a/lib/mbedtls/mbedtls_def_config.h b/lib/mbedtls/mbedtls_def_config.h index 1d2314e90e4..fd440c392f9 100644 --- a/lib/mbedtls/mbedtls_def_config.h +++ b/lib/mbedtls/mbedtls_def_config.h @@ -56,6 +56,10 @@ #endif #endif +#if CONFIG_IS_ENABLED(HKDF_MBEDTLS) +#define MBEDTLS_HKDF_C +#endif + #if defined CONFIG_MBEDTLS_LIB_X509 #if CONFIG_IS_ENABLED(X509_CERTIFICATE_PARSER) diff --git a/lib/mbedtls/sha256.c b/lib/mbedtls/sha256.c index 24aa58fa674..59edcb517df 100644 --- a/lib/mbedtls/sha256.c +++ b/lib/mbedtls/sha256.c @@ -10,6 +10,12 @@ #endif /* USE_HOSTCC */ #include <u-boot/sha256.h> +#include <mbedtls/md.h> + +#if CONFIG_IS_ENABLED(HKDF_MBEDTLS) +#include <mbedtls/hkdf.h> +#endif + const u8 sha256_der_prefix[SHA256_DER_LEN] = { 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, @@ -34,29 +40,34 @@ void sha256_finish(sha256_context *ctx, uint8_t digest[SHA256_SUM_LEN]) mbedtls_sha256_free(ctx); } -void sha256_csum_wd(const unsigned char *input, unsigned int ilen, - unsigned char *output, unsigned int chunk_sz) +int sha256_hmac(const unsigned char *key, int keylen, + const unsigned char *input, unsigned int ilen, + unsigned char *output) { - sha256_context ctx; - - sha256_starts(&ctx); - - if (IS_ENABLED(CONFIG_HW_WATCHDOG) || IS_ENABLED(CONFIG_WATCHDOG)) { - const unsigned char *curr = input; - const unsigned char *end = input + ilen; - int chunk; - - while (curr < end) { - chunk = end - curr; - if (chunk > chunk_sz) - chunk = chunk_sz; - sha256_update(&ctx, curr, chunk); - curr += chunk; - schedule(); - } - } else { - sha256_update(&ctx, input, ilen); - } - - sha256_finish(&ctx, output); + const mbedtls_md_info_t *md; + + md = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256); + if (!md) + return MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE; + + return mbedtls_md_hmac(md, key, keylen, input, ilen, output); +} + +#if CONFIG_IS_ENABLED(HKDF_MBEDTLS) +int sha256_hkdf(const unsigned char *salt, int saltlen, + const unsigned char *ikm, int ikmlen, + const unsigned char *info, int infolen, + unsigned char *output, int outputlen) +{ + const mbedtls_md_info_t *md; + + md = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256); + if (!md) + return MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE; + + return mbedtls_hkdf(md, salt, saltlen, + ikm, ikmlen, + info, infolen, + output, outputlen); } +#endif diff --git a/lib/sha256.c b/lib/sha256.c index fb195d988f1..c2e77c854b9 100644 --- a/lib/sha256.c +++ b/lib/sha256.c @@ -265,38 +265,53 @@ void sha256_finish(sha256_context * ctx, uint8_t digest[32]) PUT_UINT32_BE(ctx->state[7], digest, 28); } -/* - * Output = SHA-256( input buffer ). Trigger the watchdog every 'chunk_sz' - * bytes of input processed. - */ -void sha256_csum_wd(const unsigned char *input, unsigned int ilen, - unsigned char *output, unsigned int chunk_sz) +int sha256_hmac(const unsigned char *key, int keylen, + const unsigned char *input, unsigned int ilen, + unsigned char *output) { + int i; sha256_context ctx; -#if !defined(USE_HOSTCC) && \ - (defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)) - const unsigned char *end; - unsigned char *curr; - int chunk; -#endif + unsigned char keybuf[64]; + unsigned char k_ipad[64]; + unsigned char k_opad[64]; + unsigned char tmpbuf[32]; + int keybuf_len; + + if (keylen > 64) { + sha256_starts(&ctx); + sha256_update(&ctx, key, keylen); + sha256_finish(&ctx, keybuf); + + keybuf_len = 32; + } else { + memset(keybuf, 0, sizeof(keybuf)); + memcpy(keybuf, key, keylen); + keybuf_len = keylen; + } - sha256_starts(&ctx); + memset(k_ipad, 0x36, 64); + memset(k_opad, 0x5C, 64); -#if !defined(USE_HOSTCC) && \ - (defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)) - curr = (unsigned char *)input; - end = input + ilen; - while (curr < end) { - chunk = end - curr; - if (chunk > chunk_sz) - chunk = chunk_sz; - sha256_update(&ctx, curr, chunk); - curr += chunk; - schedule(); + for (i = 0; i < keybuf_len; i++) { + k_ipad[i] ^= keybuf[i]; + k_opad[i] ^= keybuf[i]; } -#else + + sha256_starts(&ctx); + sha256_update(&ctx, k_ipad, sizeof(k_ipad)); sha256_update(&ctx, input, ilen); -#endif + sha256_finish(&ctx, tmpbuf); + sha256_starts(&ctx); + sha256_update(&ctx, k_opad, sizeof(k_opad)); + sha256_update(&ctx, tmpbuf, sizeof(tmpbuf)); sha256_finish(&ctx, output); + + memset(k_ipad, 0, sizeof(k_ipad)); + memset(k_opad, 0, sizeof(k_opad)); + memset(tmpbuf, 0, sizeof(tmpbuf)); + memset(keybuf, 0, sizeof(keybuf)); + memset(&ctx, 0, sizeof(sha256_context)); + + return 0; } diff --git a/lib/sha256_common.c b/lib/sha256_common.c new file mode 100644 index 00000000000..7041abd26d9 --- /dev/null +++ b/lib/sha256_common.c @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * FIPS-180-2 compliant SHA-256 implementation + * + * Copyright (C) 2001-2003 Christophe Devine + */ + +#ifndef USE_HOSTCC +#include <u-boot/schedule.h> +#endif /* USE_HOSTCC */ +#include <string.h> +#include <u-boot/sha256.h> + +#include <linux/compiler_attributes.h> + +/* + * Output = SHA-256( input buffer ). Trigger the watchdog every 'chunk_sz' + * bytes of input processed. + */ +void sha256_csum_wd(const unsigned char *input, unsigned int ilen, + unsigned char *output, unsigned int chunk_sz) +{ + sha256_context ctx; +#if !defined(USE_HOSTCC) && \ + (defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)) + const unsigned char *end; + unsigned char *curr; + int chunk; +#endif + + sha256_starts(&ctx); + +#if !defined(USE_HOSTCC) && \ + (defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)) + curr = (unsigned char *)input; + end = input + ilen; + while (curr < end) { + chunk = end - curr; + if (chunk > chunk_sz) + chunk = chunk_sz; + sha256_update(&ctx, curr, chunk); + curr += chunk; + schedule(); + } +#else + sha256_update(&ctx, input, ilen); +#endif + + sha256_finish(&ctx, output); +} diff --git a/lib/smbios.c b/lib/smbios.c index defb6b42f45..78cee8c0c26 100644 --- a/lib/smbios.c +++ b/lib/smbios.c @@ -208,6 +208,43 @@ void get_str_from_dt(const struct map_sysinfo *nprop, char *str, size_t size) } /** + * smbios_get_val_si() - Get value from the devicetree or sysinfo + * + * @ctx: context of SMBIOS + * @prop: property to read + * @sysinfo_id: unique identifier for the value to be read + * @val_def: Default value + * Return: Valid value from sysinfo or device tree, otherwise val_def. + */ +static int smbios_get_val_si(struct smbios_ctx * __maybe_unused ctx, + const char * __maybe_unused prop, + int __maybe_unused sysinfo_id, int val_def) +{ +#if IS_ENABLED(CONFIG_GENERATE_SMBIOS_TABLE_VERBOSE) + int val; + + if (!ctx->dev) + return val_def; + + if (!sysinfo_get_int(ctx->dev, sysinfo_id, &val)) + return val; + + if (!IS_ENABLED(CONFIG_OF_CONTROL) || !prop) + return val_def; + + if (ofnode_valid(ctx->node) && !ofnode_read_u32(ctx->node, prop, &val)) + return val; + + /* + * If the node or property is not valid fallback and try the root + */ + if (!ofnode_read_u32(ofnode_root(), prop, &val)) + return val; +#endif + return val_def; +} + +/** * smbios_add_prop_si() - Add a property from the devicetree or sysinfo * * Sysinfo is used if available, with a fallback to devicetree @@ -226,9 +263,6 @@ static int smbios_add_prop_si(struct smbios_ctx *ctx, const char *prop, if (!dval || !*dval) dval = NULL; - if (!prop) - return smbios_add_string(ctx, dval); - if (sysinfo_id && ctx->dev) { char val[SMBIOS_STR_MAX]; @@ -236,6 +270,9 @@ static int smbios_add_prop_si(struct smbios_ctx *ctx, const char *prop, if (!ret) return smbios_add_string(ctx, val); } + if (!prop) + return smbios_add_string(ctx, dval); + if (IS_ENABLED(CONFIG_OF_CONTROL)) { const char *str = NULL; char str_dt[128] = { 0 }; @@ -331,15 +368,17 @@ static int smbios_write_type0(ulong *current, int handle, struct smbios_ctx *ctx) { struct smbios_type0 *t; - int len = sizeof(struct smbios_type0); + int len = sizeof(*t); t = map_sysmem(*current, len); - memset(t, 0, sizeof(struct smbios_type0)); + memset(t, 0, len); fill_smbios_header(t, SMBIOS_BIOS_INFORMATION, len, handle); smbios_set_eos(ctx, t->eos); - t->vendor = smbios_add_prop(ctx, NULL, "U-Boot"); + t->vendor = smbios_add_prop_si(ctx, NULL, SYSID_SM_BIOS_VENDOR, + "U-Boot"); - t->bios_ver = smbios_add_prop(ctx, "version", PLAIN_VERSION); + t->bios_ver = smbios_add_prop_si(ctx, "version", SYSID_SM_BIOS_VER, + PLAIN_VERSION); if (t->bios_ver) gd->smbios_version = ctx->last_str; log_debug("smbios_version = %p: '%s'\n", gd->smbios_version, @@ -348,7 +387,9 @@ static int smbios_write_type0(ulong *current, int handle, print_buffer((ulong)gd->smbios_version, gd->smbios_version, 1, strlen(gd->smbios_version) + 1, 0); #endif - t->bios_release_date = smbios_add_prop(ctx, NULL, U_BOOT_DMI_DATE); + t->bios_release_date = smbios_add_prop_si(ctx, NULL, + SYSID_SM_BIOS_REL_DATE, + U_BOOT_DMI_DATE); #ifdef CONFIG_ROM_SIZE if (CONFIG_ROM_SIZE < SZ_16M) { t->bios_rom_size = (CONFIG_ROM_SIZE / 65536) - 1; @@ -375,7 +416,7 @@ static int smbios_write_type0(ulong *current, int handle, t->ec_major_release = 0xff; t->ec_minor_release = 0xff; - len = t->length + smbios_string_table_len(ctx); + len = t->hdr.length + smbios_string_table_len(ctx); *current += len; unmap_sysmem(t); @@ -386,37 +427,38 @@ static int smbios_write_type1(ulong *current, int handle, struct smbios_ctx *ctx) { struct smbios_type1 *t; - int len = sizeof(struct smbios_type1); + int len = sizeof(*t); char *serial_str = env_get("serial#"); t = map_sysmem(*current, len); - memset(t, 0, sizeof(struct smbios_type1)); + memset(t, 0, len); fill_smbios_header(t, SMBIOS_SYSTEM_INFORMATION, len, handle); smbios_set_eos(ctx, t->eos); + t->manufacturer = smbios_add_prop_si(ctx, "manufacturer", SYSID_SM_SYSTEM_MANUFACTURER, NULL); t->product_name = smbios_add_prop_si(ctx, "product", - SYSID_SM_SYSTEM_PRODUCT, - NULL); - t->version = smbios_add_prop_si(ctx, "version", - SYSID_SM_SYSTEM_VERSION, + SYSID_SM_SYSTEM_PRODUCT, NULL); + t->version = smbios_add_prop_si(ctx, "version", SYSID_SM_SYSTEM_VERSION, NULL); if (serial_str) { t->serial_number = smbios_add_prop(ctx, NULL, serial_str); - strncpy((char *)t->uuid, serial_str, sizeof(t->uuid)); + strlcpy((char *)t->uuid, serial_str, sizeof(t->uuid)); } else { t->serial_number = smbios_add_prop_si(ctx, "serial", SYSID_SM_SYSTEM_SERIAL, NULL); } - t->wakeup_type = SMBIOS_WAKEUP_TYPE_UNKNOWN; - t->sku_number = smbios_add_prop_si(ctx, "sku", - SYSID_SM_SYSTEM_SKU, NULL); - t->family = smbios_add_prop_si(ctx, "family", - SYSID_SM_SYSTEM_FAMILY, NULL); - - len = t->length + smbios_string_table_len(ctx); + t->wakeup_type = smbios_get_val_si(ctx, "wakeup-type", + SYSID_SM_SYSTEM_WAKEUP, + SMBIOS_WAKEUP_TYPE_UNKNOWN); + t->sku_number = smbios_add_prop_si(ctx, "sku", SYSID_SM_SYSTEM_SKU, + NULL); + t->family = smbios_add_prop_si(ctx, "family", SYSID_SM_SYSTEM_FAMILY, + NULL); + + len = t->hdr.length + smbios_string_table_len(ctx); *current += len; unmap_sysmem(t); @@ -427,33 +469,53 @@ static int smbios_write_type2(ulong *current, int handle, struct smbios_ctx *ctx) { struct smbios_type2 *t; - int len = sizeof(struct smbios_type2); + int len = sizeof(*t); + u8 *eos_addr; + /* + * reserve the space for the dynamic bytes of contained object handles. + * TODO: len += <obj_handle_num> * SMBIOS_TYPE2_CON_OBJ_HANDLE_SIZE + * obj_handle_num can be from DT node "baseboard" or sysinfo driver. + */ t = map_sysmem(*current, len); - memset(t, 0, sizeof(struct smbios_type2)); + memset(t, 0, len); fill_smbios_header(t, SMBIOS_BOARD_INFORMATION, len, handle); - smbios_set_eos(ctx, t->eos); + + /* eos is at the end of the structure */ + eos_addr = (u8 *)t + len - sizeof(t->eos); + smbios_set_eos(ctx, eos_addr); + t->manufacturer = smbios_add_prop_si(ctx, "manufacturer", SYSID_SM_BASEBOARD_MANUFACTURER, NULL); t->product_name = smbios_add_prop_si(ctx, "product", - SYSID_SM_BASEBOARD_PRODUCT, - NULL); + SYSID_SM_BASEBOARD_PRODUCT, NULL); t->version = smbios_add_prop_si(ctx, "version", - SYSID_SM_BASEBOARD_VERSION, - NULL); - + SYSID_SM_BASEBOARD_VERSION, NULL); t->serial_number = smbios_add_prop_si(ctx, "serial", - SYSID_SM_BASEBOARD_SERIAL, - NULL); + SYSID_SM_BASEBOARD_SERIAL, NULL); t->asset_tag_number = smbios_add_prop_si(ctx, "asset-tag", SYSID_SM_BASEBOARD_ASSET_TAG, NULL); - t->feature_flags = SMBIOS_BOARD_FEATURE_HOSTING; - t->board_type = SMBIOS_BOARD_MOTHERBOARD; + t->feature_flags = smbios_get_val_si(ctx, "feature-flags", + SYSID_SM_BASEBOARD_FEATURE, 0); + + t->chassis_location = + smbios_add_prop_si(ctx, "chassis-location", + SYSID_SM_BASEBOARD_CHASSIS_LOCAT, NULL); + t->board_type = smbios_get_val_si(ctx, "board-type", + SYSID_SM_BASEBOARD_TYPE, + SMBIOS_BOARD_TYPE_UNKNOWN); + + /* + * TODO: + * Populate the Contained Object Handles if they exist + * t->number_contained_objects = <obj_handle_num>; + */ + t->chassis_handle = handle + 1; - len = t->length + smbios_string_table_len(ctx); + len = t->hdr.length + smbios_string_table_len(ctx); *current += len; unmap_sysmem(t); @@ -464,20 +526,77 @@ static int smbios_write_type3(ulong *current, int handle, struct smbios_ctx *ctx) { struct smbios_type3 *t; - int len = sizeof(struct smbios_type3); + int len = sizeof(*t); + u8 *eos_addr; + size_t elem_size = 0; + __maybe_unused u8 *elem_addr; + __maybe_unused u8 *sku_num_addr; + + /* + * reserve the space for the dynamic bytes of contained elements. + * TODO: elem_size = <element_count> * <element_record_length> + * element_count and element_record_length can be from DT node + * "chassis" or sysinfo driver. + */ + len += elem_size; t = map_sysmem(*current, len); - memset(t, 0, sizeof(struct smbios_type3)); + memset(t, 0, len); fill_smbios_header(t, SMBIOS_SYSTEM_ENCLOSURE, len, handle); - smbios_set_eos(ctx, t->eos); - t->manufacturer = smbios_add_prop(ctx, "manufacturer", NULL); - t->chassis_type = SMBIOS_ENCLOSURE_DESKTOP; - t->bootup_state = SMBIOS_STATE_SAFE; - t->power_supply_state = SMBIOS_STATE_SAFE; - t->thermal_state = SMBIOS_STATE_SAFE; - t->security_status = SMBIOS_SECURITY_NONE; - - len = t->length + smbios_string_table_len(ctx); +#if IS_ENABLED(CONFIG_GENERATE_SMBIOS_TABLE_VERBOSE) + elem_addr = (u8 *)t + offsetof(struct smbios_type3, sku_number); + sku_num_addr = elem_addr + elem_size; +#endif + /* eos is at the end of the structure */ + eos_addr = (u8 *)t + len - sizeof(t->eos); + smbios_set_eos(ctx, eos_addr); + + t->manufacturer = smbios_add_prop_si(ctx, "manufacturer", + SYSID_SM_ENCLOSURE_MANUFACTURER, + NULL); + t->chassis_type = smbios_get_val_si(ctx, "chassis-type", + SYSID_SM_ENCLOSURE_TYPE, + SMBIOS_ENCLOSURE_UNKNOWN); + t->bootup_state = smbios_get_val_si(ctx, "bootup-state", + SYSID_SM_ENCLOSURE_BOOTUP, + SMBIOS_STATE_UNKNOWN); + t->power_supply_state = smbios_get_val_si(ctx, "power-supply-state", + SYSID_SM_ENCLOSURE_POW, + SMBIOS_STATE_UNKNOWN); + t->thermal_state = smbios_get_val_si(ctx, "thermal-state", + SYSID_SM_ENCLOSURE_THERMAL, + SMBIOS_STATE_UNKNOWN); + t->security_status = smbios_get_val_si(ctx, "security-status", + SYSID_SM_ENCLOSURE_SECURITY, + SMBIOS_SECURITY_UNKNOWN); + +#if IS_ENABLED(CONFIG_GENERATE_SMBIOS_TABLE_VERBOSE) + t->version = smbios_add_prop_si(ctx, "version", + SYSID_SM_ENCLOSURE_VERSION, NULL); + t->serial_number = smbios_add_prop_si(ctx, "serial", + SYSID_SM_ENCLOSURE_SERIAL, NULL); + t->asset_tag_number = smbios_add_prop_si(ctx, "asset-tag", + SYSID_SM_BASEBOARD_ASSET_TAG, + NULL); + t->oem_defined = smbios_get_val_si(ctx, "oem-defined", + SYSID_SM_ENCLOSURE_OEM, 0); + t->height = smbios_get_val_si(ctx, "height", + SYSID_SM_ENCLOSURE_HEIGHT, 0); + t->number_of_power_cords = + smbios_get_val_si(ctx, "number-of-power-cords", + SYSID_SM_ENCLOSURE_POWCORE_NUM, 0); + + /* + * TODO: Populate the Contained Element Record if they exist + * t->element_count = <element_num>; + * t->element_record_length = <element_len>; + */ + + *sku_num_addr = smbios_add_prop_si(ctx, "sku", SYSID_SM_ENCLOSURE_SKU, + NULL); +#endif + + len = t->hdr.length + smbios_string_table_len(ctx); *current += len; unmap_sysmem(t); @@ -490,6 +609,8 @@ static void smbios_write_type4_dm(struct smbios_type4 *t, u16 processor_family = SMBIOS_PROCESSOR_FAMILY_UNKNOWN; const char *vendor = NULL; const char *name = NULL; + __maybe_unused void *id_data = NULL; + __maybe_unused size_t id_size = 0; #ifdef CONFIG_CPU char processor_name[49]; @@ -511,46 +632,234 @@ static void smbios_write_type4_dm(struct smbios_type4 *t, name = processor_name; } #endif + if (processor_family == SMBIOS_PROCESSOR_FAMILY_UNKNOWN) + processor_family = + smbios_get_val_si(ctx, "family", + SYSID_SM_PROCESSOR_FAMILY, + SMBIOS_PROCESSOR_FAMILY_UNKNOWN); + + if (processor_family == SMBIOS_PROCESSOR_FAMILY_EXT) + t->processor_family2 = + smbios_get_val_si(ctx, "family2", + SYSID_SM_PROCESSOR_FAMILY2, + SMBIOS_PROCESSOR_FAMILY_UNKNOWN); + + t->processor_family = processor_family; + t->processor_manufacturer = + smbios_add_prop_si(ctx, "manufacturer", + SYSID_SM_PROCESSOR_MANUFACT, vendor); + t->processor_version = smbios_add_prop_si(ctx, "version", + SYSID_SM_PROCESSOR_VERSION, + name); + +#if IS_ENABLED(CONFIG_GENERATE_SMBIOS_TABLE_VERBOSE) + if (t->processor_id[0] || t->processor_id[1] || + sysinfo_get_data(ctx->dev, SYSID_SM_PROCESSOR_ID, &id_data, + &id_size)) + return; - t->processor_family = 0xfe; - t->processor_family2 = processor_family; - t->processor_manufacturer = smbios_add_prop(ctx, NULL, vendor); - t->processor_version = smbios_add_prop(ctx, NULL, name); + if (id_data && id_size == sizeof(t->processor_id)) + memcpy((u8 *)t->processor_id, id_data, id_size); +#endif } static int smbios_write_type4(ulong *current, int handle, struct smbios_ctx *ctx) { struct smbios_type4 *t; - int len = sizeof(struct smbios_type4); + int len = sizeof(*t); + __maybe_unused void *hdl; + __maybe_unused size_t hdl_size; t = map_sysmem(*current, len); - memset(t, 0, sizeof(struct smbios_type4)); + memset(t, 0, len); fill_smbios_header(t, SMBIOS_PROCESSOR_INFORMATION, len, handle); smbios_set_eos(ctx, t->eos); - t->processor_type = SMBIOS_PROCESSOR_TYPE_CENTRAL; + t->socket_design = smbios_add_prop_si(ctx, "socket-design", + SYSID_SM_PROCESSOR_SOCKET, NULL); + t->processor_type = smbios_get_val_si(ctx, "processor-type", + SYSID_SM_PROCESSOR_TYPE, + SMBIOS_PROCESSOR_TYPE_UNKNOWN); smbios_write_type4_dm(t, ctx); - t->status = SMBIOS_PROCESSOR_STATUS_ENABLED; - t->processor_upgrade = SMBIOS_PROCESSOR_UPGRADE_NONE; - t->l1_cache_handle = 0xffff; - t->l2_cache_handle = 0xffff; - t->l3_cache_handle = 0xffff; - len = t->length + smbios_string_table_len(ctx); + t->status = smbios_get_val_si(ctx, "processor-status", + SYSID_SM_PROCESSOR_STATUS, + SMBIOS_PROCESSOR_STATUS_UNKNOWN); + t->processor_upgrade = + smbios_get_val_si(ctx, "upgrade", SYSID_SM_PROCESSOR_UPGRADE, + SMBIOS_PROCESSOR_UPGRADE_UNKNOWN); + + t->l1_cache_handle = SMBIOS_CACHE_HANDLE_NONE; + t->l2_cache_handle = SMBIOS_CACHE_HANDLE_NONE; + t->l3_cache_handle = SMBIOS_CACHE_HANDLE_NONE; + +#if IS_ENABLED(CONFIG_GENERATE_SMBIOS_TABLE_VERBOSE) + t->voltage = smbios_get_val_si(ctx, "voltage", + SYSID_SM_PROCESSOR_VOLTAGE, 0); + t->external_clock = smbios_get_val_si(ctx, "external-clock", + SYSID_SM_PROCESSOR_EXT_CLOCK, 0); + t->max_speed = smbios_get_val_si(ctx, "max-speed", + SYSID_SM_PROCESSOR_MAX_SPEED, 0); + t->current_speed = smbios_get_val_si(ctx, "current-speed", + SYSID_SM_PROCESSOR_CUR_SPEED, 0); + + /* Read the cache handles */ + if (!sysinfo_get_data(ctx->dev, SYSID_SM_CACHE_HANDLE, &hdl, + &hdl_size) && + (hdl_size == SYSINFO_CACHE_LVL_MAX * sizeof(u16))) { + u16 *handle = (u16 *)hdl; + + if (*handle) + t->l1_cache_handle = *handle; + + handle++; + if (*handle) + t->l2_cache_handle = *handle; + + handle++; + if (*handle) + t->l3_cache_handle = *handle; + } + + t->serial_number = smbios_add_prop_si(ctx, "serial", + SYSID_SM_PROCESSOR_SN, NULL); + t->asset_tag = smbios_add_prop_si(ctx, "asset-tag", + SYSID_SM_PROCESSOR_ASSET_TAG, NULL); + t->part_number = smbios_add_prop_si(ctx, "part-number", + SYSID_SM_PROCESSOR_PN, NULL); + t->core_count = smbios_get_val_si(ctx, "core-count", + SYSID_SM_PROCESSOR_CORE_CNT, 0); + t->core_enabled = smbios_get_val_si(ctx, "core-enabled", + SYSID_SM_PROCESSOR_CORE_EN, 0); + t->thread_count = smbios_get_val_si(ctx, "thread-count", + SYSID_SM_PROCESSOR_THREAD_CNT, 0); + t->processor_characteristics = + smbios_get_val_si(ctx, "characteristics", + SYSID_SM_PROCESSOR_CHARA, + SMBIOS_PROCESSOR_UND); + t->core_count2 = smbios_get_val_si(ctx, "core-count2", + SYSID_SM_PROCESSOR_CORE_CNT2, 0); + t->core_enabled2 = smbios_get_val_si(ctx, "core-enabled2", + SYSID_SM_PROCESSOR_CORE_EN2, 0); + t->thread_count2 = smbios_get_val_si(ctx, "thread-count2", + SYSID_SM_PROCESSOR_THREAD_CNT2, 0); + t->thread_enabled = smbios_get_val_si(ctx, "thread-enabled", + SYSID_SM_PROCESSOR_THREAD_EN, 0); +#endif + + len = t->hdr.length + smbios_string_table_len(ctx); + *current += len; + unmap_sysmem(t); + + return len; +} + +#if IS_ENABLED(CONFIG_GENERATE_SMBIOS_TABLE_VERBOSE) + +static int smbios_write_type7_1level(ulong *current, int handle, + struct smbios_ctx *ctx, int level) +{ + struct smbios_type7 *t; + int len = sizeof(*t); + void *hdl; + size_t hdl_size; + + t = map_sysmem(*current, len); + memset(t, 0, len); + fill_smbios_header(t, SMBIOS_CACHE_INFORMATION, len, handle); + smbios_set_eos(ctx, t->eos); + + t->socket_design = smbios_add_prop_si(ctx, "socket-design", + SYSID_SM_CACHE_SOCKET + level, + NULL); + t->config.data = smbios_get_val_si(ctx, "config", + SYSID_SM_CACHE_CONFIG + level, + (level - 1) | SMBIOS_CACHE_OP_UND); + t->max_size.data = smbios_get_val_si(ctx, "max-size", + SYSID_SM_CACHE_MAX_SIZE + level, + 0); + t->inst_size.data = smbios_get_val_si(ctx, "installed-size", + SYSID_SM_CACHE_INST_SIZE + level, + 0); + t->supp_sram_type.data = + smbios_get_val_si(ctx, "supported-sram-type", + SYSID_SM_CACHE_SUPSRAM_TYPE + level, + SMBIOS_CACHE_SRAM_TYPE_UNKNOWN); + t->curr_sram_type.data = + smbios_get_val_si(ctx, "current-sram-type", + SYSID_SM_CACHE_CURSRAM_TYPE + level, + SMBIOS_CACHE_SRAM_TYPE_UNKNOWN); + t->speed = smbios_get_val_si(ctx, "speed", SYSID_SM_CACHE_SPEED + level, + 0); + t->err_corr_type = smbios_get_val_si(ctx, "error-correction-type", + SYSID_SM_CACHE_ERRCOR_TYPE + level, + SMBIOS_CACHE_ERRCORR_UNKNOWN); + t->sys_cache_type = + smbios_get_val_si(ctx, "system-cache-type", + SYSID_SM_CACHE_SCACHE_TYPE + level, + SMBIOS_CACHE_SYSCACHE_TYPE_UNKNOWN); + t->associativity = smbios_get_val_si(ctx, "associativity", + SYSID_SM_CACHE_ASSOC + level, + SMBIOS_CACHE_ASSOC_UNKNOWN); + t->max_size2.data = smbios_get_val_si(ctx, "max-size2", + SYSID_SM_CACHE_MAX_SIZE2 + level, + 0); + t->inst_size2.data = + smbios_get_val_si(ctx, "installed-size2", + SYSID_SM_CACHE_INST_SIZE2 + level, 0); + + /* Save the cache handles */ + if (!sysinfo_get_data(ctx->dev, SYSID_SM_CACHE_HANDLE, &hdl, + &hdl_size)) { + if (hdl_size == SYSINFO_CACHE_LVL_MAX * sizeof(u16)) + *((u16 *)hdl + level) = handle; + } + + len = t->hdr.length + smbios_string_table_len(ctx); *current += len; unmap_sysmem(t); return len; } +static int smbios_write_type7(ulong *current, int handle, + struct smbios_ctx *ctx) +{ + int len = 0; + int i, level; + ofnode parent = ctx->node; + struct smbios_ctx ctx_bak; + + memcpy(&ctx_bak, ctx, sizeof(ctx_bak)); + + /* Get the number of level */ + level = smbios_get_val_si(ctx, NULL, SYSID_SM_CACHE_LEVEL, 0); + if (level >= SYSINFO_CACHE_LVL_MAX) /* Error, return 0-length */ + return 0; + + for (i = 0; i <= level; i++) { + char buf[9] = ""; + + if (!snprintf(buf, sizeof(buf), "l%d-cache", i + 1)) + return 0; + ctx->subnode_name = buf; + ctx->node = ofnode_find_subnode(parent, ctx->subnode_name); + len += smbios_write_type7_1level(current, handle++, ctx, i); + memcpy(ctx, &ctx_bak, sizeof(*ctx)); + } + return len; +} + +#endif /* #if IS_ENABLED(CONFIG_GENERATE_SMBIOS_TABLE_VERBOSE) */ + static int smbios_write_type32(ulong *current, int handle, struct smbios_ctx *ctx) { struct smbios_type32 *t; - int len = sizeof(struct smbios_type32); + int len = sizeof(*t); t = map_sysmem(*current, len); - memset(t, 0, sizeof(struct smbios_type32)); + memset(t, 0, len); fill_smbios_header(t, SMBIOS_SYSTEM_BOOT_INFORMATION, len, handle); smbios_set_eos(ctx, t->eos); @@ -564,10 +873,10 @@ static int smbios_write_type127(ulong *current, int handle, struct smbios_ctx *ctx) { struct smbios_type127 *t; - int len = sizeof(struct smbios_type127); + int len = sizeof(*t); t = map_sysmem(*current, len); - memset(t, 0, sizeof(struct smbios_type127)); + memset(t, 0, len); fill_smbios_header(t, SMBIOS_END_OF_TABLE, len, handle); *current += len; @@ -582,7 +891,11 @@ static struct smbios_write_method smbios_write_funcs[] = { { smbios_write_type2, "baseboard", }, /* Type 3 must immediately follow type 2 due to chassis handle. */ { smbios_write_type3, "chassis", }, - { smbios_write_type4, }, +#if IS_ENABLED(CONFIG_GENERATE_SMBIOS_TABLE_VERBOSE) + /* Type 7 must ahead of type 4 to get cache handles. */ + { smbios_write_type7, "cache", }, +#endif + { smbios_write_type4, "processor"}, { smbios_write_type32, }, { smbios_write_type127 }, }; @@ -599,7 +912,7 @@ ulong write_smbios_table(ulong addr) int i; ctx.node = ofnode_null(); - if (IS_ENABLED(CONFIG_OF_CONTROL) && CONFIG_IS_ENABLED(SYSINFO)) { + if (CONFIG_IS_ENABLED(SYSINFO)) { uclass_first_device(UCLASS_SYSINFO, &ctx.dev); if (ctx.dev) { int ret; |