boot: Move smbios-related functions to a separate file
This commit is contained in:
@@ -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"
|
||||
|
||||
@@ -270,6 +270,7 @@ libefi_sources = files(
|
||||
'random-seed.c',
|
||||
'secure-boot.c',
|
||||
'shim.c',
|
||||
'smbios.c',
|
||||
'ticks.c',
|
||||
'util.c',
|
||||
'vmm.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;
|
||||
}
|
||||
@@ -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);
|
||||
@@ -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"
|
||||
|
||||
+1
-180
@@ -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 */
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user