From: anonymix007 <48598263+anonymix007@users.noreply.github.com> Date: Wed, 11 Sep 2024 12:18:05 +0000 (+0300) Subject: boot: Move smbios-related functions to a separate file X-Git-Tag: v257-rc1~254^2~3 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=dd6a37e3353955acd911fe1a225bccf3005a5268;p=thirdparty%2Fsystemd.git boot: Move smbios-related functions to a separate file --- diff --git a/src/boot/efi/boot.c b/src/boot/efi/boot.c index a362f7a93f2..a8c7b6881fc 100644 --- a/src/boot/efi/boot.c +++ b/src/boot/efi/boot.c @@ -23,6 +23,7 @@ #include "sbat.h" #include "secure-boot.h" #include "shim.h" +#include "smbios.h" #include "ticks.h" #include "tpm2-pcr.h" #include "uki.h" diff --git a/src/boot/efi/meson.build b/src/boot/efi/meson.build index ce2e798daf1..0109793b7a9 100644 --- a/src/boot/efi/meson.build +++ b/src/boot/efi/meson.build @@ -270,6 +270,7 @@ libefi_sources = files( 'random-seed.c', 'secure-boot.c', 'shim.c', + 'smbios.c', 'ticks.c', 'util.c', 'vmm.c', diff --git a/src/boot/efi/smbios.c b/src/boot/efi/smbios.c new file mode 100644 index 00000000000..bea6577635f --- /dev/null +++ b/src/boot/efi/smbios.c @@ -0,0 +1,188 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#include "efi-string.h" +#include "efivars.h" +#include "proto/device-path.h" +#include "smbios.h" +#include "string-util-fundamental.h" +#include "util.h" + +#define SMBIOS_TABLE_GUID \ + GUID_DEF(0xeb9d2d31, 0x2d88, 0x11d3, 0x9a, 0x16, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d) +#define SMBIOS3_TABLE_GUID \ + GUID_DEF(0xf2fd1544, 0x9794, 0x4a2c, 0x99, 0x2e, 0xe5, 0xbb, 0xcf, 0x20, 0xe3, 0x94) + +typedef struct { + uint8_t anchor_string[4]; + uint8_t entry_point_structure_checksum; + uint8_t entry_point_length; + uint8_t major_version; + uint8_t minor_version; + uint16_t max_structure_size; + uint8_t entry_point_revision; + uint8_t formatted_area[5]; + uint8_t intermediate_anchor_string[5]; + uint8_t intermediate_checksum; + uint16_t table_length; + uint32_t table_address; + uint16_t number_of_smbios_structures; + uint8_t smbios_bcd_revision; +} _packed_ SmbiosEntryPoint; + +typedef struct { + uint8_t anchor_string[5]; + uint8_t entry_point_structure_checksum; + uint8_t entry_point_length; + uint8_t major_version; + uint8_t minor_version; + uint8_t docrev; + uint8_t entry_point_revision; + uint8_t reserved; + uint32_t table_maximum_size; + uint64_t table_address; +} _packed_ Smbios3EntryPoint; + +typedef struct { + uint8_t type; + uint8_t length; + uint8_t handle[2]; +} _packed_ SmbiosHeader; + +typedef struct { + SmbiosHeader header; + uint8_t vendor; + uint8_t bios_version; + uint16_t bios_segment; + uint8_t bios_release_date; + uint8_t bios_size; + uint64_t bios_characteristics; + uint8_t bios_characteristics_ext[2]; +} _packed_ SmbiosTableType0; + +typedef struct { + SmbiosHeader header; + uint8_t count; + char contents[]; +} _packed_ SmbiosTableType11; + +static const void *find_smbios_configuration_table(uint64_t *ret_size) { + assert(ret_size); + + const Smbios3EntryPoint *entry3 = find_configuration_table(MAKE_GUID_PTR(SMBIOS3_TABLE)); + if (entry3 && memcmp(entry3->anchor_string, "_SM3_", 5) == 0 && + entry3->entry_point_length <= sizeof(*entry3)) { + *ret_size = entry3->table_maximum_size; + return PHYSICAL_ADDRESS_TO_POINTER(entry3->table_address); + } + + const SmbiosEntryPoint *entry = find_configuration_table(MAKE_GUID_PTR(SMBIOS_TABLE)); + if (entry && memcmp(entry->anchor_string, "_SM_", 4) == 0 && + entry->entry_point_length <= sizeof(*entry)) { + *ret_size = entry->table_length; + return PHYSICAL_ADDRESS_TO_POINTER(entry->table_address); + } + + return NULL; +} + +static const SmbiosHeader *get_smbios_table(uint8_t type, size_t min_size, uint64_t *ret_size_left) { + uint64_t size = 0; + const uint8_t *p = find_smbios_configuration_table(&size); + if (!p) + return NULL; + + for (;;) { + if (size < sizeof(SmbiosHeader)) + return NULL; + + const SmbiosHeader *header = (const SmbiosHeader *) p; + + /* End of table. */ + if (header->type == 127) + return NULL; + + if (size < header->length) + return NULL; + + if (header->type == type) { + /* Table is smaller than the minimum expected size? Refuse */ + if (header->length < min_size) + return NULL; + + if (ret_size_left) + *ret_size_left = size; + return header; /* Yay! */ + } + + /* Skip over formatted area. */ + size -= header->length; + p += header->length; + + /* Special case: if there are no strings appended, we'll see two NUL bytes, skip over them */ + if (size >= 2 && p[0] == 0 && p[1] == 0) { + size -= 2; + p += 2; + continue; + } + + /* Skip over a populated string table. */ + bool first = true; + for (;;) { + const uint8_t *e = memchr(p, 0, size); + if (!e) + return NULL; + + if (!first && e == p) {/* Double NUL byte means we've reached the end of the string table. */ + p++; + size--; + break; + } + + size -= e + 1 - p; + p = e + 1; + first = false; + } + } + + return NULL; +} + +bool smbios_in_hypervisor(void) { + /* Look up BIOS Information (Type 0). */ + const SmbiosTableType0 *type0 = (const SmbiosTableType0 *) get_smbios_table(0, sizeof(SmbiosTableType0), /* left= */ NULL); + if (!type0) + return false; + + /* Bit 4 of 2nd BIOS characteristics extension bytes indicates virtualization. */ + return FLAGS_SET(type0->bios_characteristics_ext[1], 1 << 4); +} + +const char* smbios_find_oem_string(const char *name) { + uint64_t left; + + assert(name); + + const SmbiosTableType11 *type11 = (const SmbiosTableType11 *) get_smbios_table(11, sizeof(SmbiosTableType11), &left); + if (!type11) + return NULL; + + const char *s = type11->contents; + + assert(left >= type11->header.length); /* get_smbios_table() already validated this */ + left -= type11->header.length; + const char *limit = s + left; + + for (const char *p = s; p < limit; ) { + const char *e = memchr(p, 0, limit - p); + if (!e || e == p) /* Double NUL byte means we've reached the end of the OEM strings. */ + break; + + const char *eq = startswith8(p, name); + if (eq && *eq == '=') + return eq + 1; + + p = e + 1; + } + + return NULL; +} diff --git a/src/boot/efi/smbios.h b/src/boot/efi/smbios.h new file mode 100644 index 00000000000..5a05bfff00e --- /dev/null +++ b/src/boot/efi/smbios.h @@ -0,0 +1,8 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +#pragma once + +#include "efi.h" + +bool smbios_in_hypervisor(void); + +const char* smbios_find_oem_string(const char *name); diff --git a/src/boot/efi/stub.c b/src/boot/efi/stub.c index 4df993c5d0b..9664c95d57e 100644 --- a/src/boot/efi/stub.c +++ b/src/boot/efi/stub.c @@ -17,6 +17,7 @@ #include "sbat.h" #include "secure-boot.h" #include "shim.h" +#include "smbios.h" #include "splash.h" #include "tpm2-pcr.h" #include "uki.h" diff --git a/src/boot/efi/vmm.c b/src/boot/efi/vmm.c index 1d04509a1e8..fea4c446c02 100644 --- a/src/boot/efi/vmm.c +++ b/src/boot/efi/vmm.c @@ -10,6 +10,7 @@ #include "efi-string.h" #include "efivars.h" #include "proto/device-path.h" +#include "smbios.h" #include "string-util-fundamental.h" #include "util.h" #include "vmm.h" @@ -135,156 +136,6 @@ static bool cpuid_in_hypervisor(void) { return false; } -#define SMBIOS_TABLE_GUID \ - GUID_DEF(0xeb9d2d31, 0x2d88, 0x11d3, 0x9a, 0x16, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d) -#define SMBIOS3_TABLE_GUID \ - GUID_DEF(0xf2fd1544, 0x9794, 0x4a2c, 0x99, 0x2e, 0xe5, 0xbb, 0xcf, 0x20, 0xe3, 0x94) - -typedef struct { - uint8_t anchor_string[4]; - uint8_t entry_point_structure_checksum; - uint8_t entry_point_length; - uint8_t major_version; - uint8_t minor_version; - uint16_t max_structure_size; - uint8_t entry_point_revision; - uint8_t formatted_area[5]; - uint8_t intermediate_anchor_string[5]; - uint8_t intermediate_checksum; - uint16_t table_length; - uint32_t table_address; - uint16_t number_of_smbios_structures; - uint8_t smbios_bcd_revision; -} _packed_ SmbiosEntryPoint; - -typedef struct { - uint8_t anchor_string[5]; - uint8_t entry_point_structure_checksum; - uint8_t entry_point_length; - uint8_t major_version; - uint8_t minor_version; - uint8_t docrev; - uint8_t entry_point_revision; - uint8_t reserved; - uint32_t table_maximum_size; - uint64_t table_address; -} _packed_ Smbios3EntryPoint; - -typedef struct { - uint8_t type; - uint8_t length; - uint8_t handle[2]; -} _packed_ SmbiosHeader; - -typedef struct { - SmbiosHeader header; - uint8_t vendor; - uint8_t bios_version; - uint16_t bios_segment; - uint8_t bios_release_date; - uint8_t bios_size; - uint64_t bios_characteristics; - uint8_t bios_characteristics_ext[2]; -} _packed_ SmbiosTableType0; - -typedef struct { - SmbiosHeader header; - uint8_t count; - char contents[]; -} _packed_ SmbiosTableType11; - -static const void *find_smbios_configuration_table(uint64_t *ret_size) { - assert(ret_size); - - const Smbios3EntryPoint *entry3 = find_configuration_table(MAKE_GUID_PTR(SMBIOS3_TABLE)); - if (entry3 && memcmp(entry3->anchor_string, "_SM3_", 5) == 0 && - entry3->entry_point_length <= sizeof(*entry3)) { - *ret_size = entry3->table_maximum_size; - return PHYSICAL_ADDRESS_TO_POINTER(entry3->table_address); - } - - const SmbiosEntryPoint *entry = find_configuration_table(MAKE_GUID_PTR(SMBIOS_TABLE)); - if (entry && memcmp(entry->anchor_string, "_SM_", 4) == 0 && - entry->entry_point_length <= sizeof(*entry)) { - *ret_size = entry->table_length; - return PHYSICAL_ADDRESS_TO_POINTER(entry->table_address); - } - - return NULL; -} - -static const SmbiosHeader *get_smbios_table(uint8_t type, size_t min_size, uint64_t *ret_size_left) { - uint64_t size = 0; - const uint8_t *p = find_smbios_configuration_table(&size); - if (!p) - return NULL; - - for (;;) { - if (size < sizeof(SmbiosHeader)) - return NULL; - - const SmbiosHeader *header = (const SmbiosHeader *) p; - - /* End of table. */ - if (header->type == 127) - return NULL; - - if (size < header->length) - return NULL; - - if (header->type == type) { - /* Table is smaller than the minimum expected size? Refuse */ - if (header->length < min_size) - return NULL; - - if (ret_size_left) - *ret_size_left = size; - return header; /* Yay! */ - } - - /* Skip over formatted area. */ - size -= header->length; - p += header->length; - - /* Special case: if there are no strings appended, we'll see two NUL bytes, skip over them */ - if (size >= 2 && p[0] == 0 && p[1] == 0) { - size -= 2; - p += 2; - continue; - } - - /* Skip over a populated string table. */ - bool first = true; - for (;;) { - const uint8_t *e = memchr(p, 0, size); - if (!e) - return NULL; - - if (!first && e == p) {/* Double NUL byte means we've reached the end of the string table. */ - p++; - size--; - break; - } - - size -= e + 1 - p; - p = e + 1; - first = false; - } - } - - return NULL; -} - -static bool smbios_in_hypervisor(void) { - /* Look up BIOS Information (Type 0). */ - const SmbiosTableType0 *type0 = (const SmbiosTableType0 *) get_smbios_table(0, sizeof(SmbiosTableType0), /* left= */ NULL); - if (!type0) - return false; - - /* Bit 4 of 2nd BIOS characteristics extension bytes indicates virtualization. */ - return FLAGS_SET(type0->bios_characteristics_ext[1], 1 << 4); -} - bool in_hypervisor(void) { static int cache = -1; if (cache >= 0) @@ -294,36 +145,6 @@ bool in_hypervisor(void) { return cache; } -const char* smbios_find_oem_string(const char *name) { - uint64_t left; - - assert(name); - - const SmbiosTableType11 *type11 = (const SmbiosTableType11 *) get_smbios_table(11, sizeof(SmbiosTableType11), &left); - if (!type11) - return NULL; - - const char *s = type11->contents; - - assert(left >= type11->header.length); /* get_smbios_table() already validated this */ - left -= type11->header.length; - const char *limit = s + left; - - for (const char *p = s; p < limit; ) { - const char *e = memchr(p, 0, limit - p); - if (!e || e == p) /* Double NUL byte means we've reached the end of the OEM strings. */ - break; - - const char *eq = startswith8(p, name); - if (eq && *eq == '=') - return eq + 1; - - p = e + 1; - } - - return NULL; -} - #if defined(__i386__) || defined(__x86_64__) static uint32_t cpuid_leaf(uint32_t eax, char ret_sig[static 13], bool swapped) { /* zero-init as some queries explicitly require subleaf == 0 */ diff --git a/src/boot/efi/vmm.h b/src/boot/efi/vmm.h index 1d1037b32a5..ae9b5327675 100644 --- a/src/boot/efi/vmm.h +++ b/src/boot/efi/vmm.h @@ -9,5 +9,3 @@ EFI_STATUS vmm_open(EFI_HANDLE *ret_vmm_dev, EFI_FILE **ret_vmm_dir); bool in_hypervisor(void); bool is_confidential_vm(void); - -const char* smbios_find_oem_string(const char *name);