aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/efi_loader/Kconfig1
-rw-r--r--lib/efi_loader/efi_boottime.c9
-rw-r--r--lib/efi_loader/efi_capsule.c36
-rw-r--r--lib/efi_loader/efi_device_path.c27
-rw-r--r--lib/efi_loader/efi_signature.c38
-rw-r--r--lib/efi_loader/efi_smbios.c2
-rw-r--r--lib/efi_loader/efi_tcg2.c314
-rw-r--r--lib/efi_loader/efi_var_common.c14
-rw-r--r--lib/efi_loader/efi_var_mem.c7
-rw-r--r--lib/efi_loader/efi_variable.c9
-rw-r--r--lib/efi_loader/efi_variable_tee.c16
-rw-r--r--lib/smbios-parser.c152
12 files changed, 514 insertions, 111 deletions
diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
index 06633e9..52f71c0 100644
--- a/lib/efi_loader/Kconfig
+++ b/lib/efi_loader/Kconfig
@@ -312,6 +312,7 @@ config EFI_TCG2_PROTOCOL
select SHA384
select SHA512
select HASH
+ select SMBIOS_PARSER
help
Provide a EFI_TCG2_PROTOCOL implementation using the TPM hardware
of the platform.
diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
index f0283b5..1823990 100644
--- a/lib/efi_loader/efi_boottime.c
+++ b/lib/efi_loader/efi_boottime.c
@@ -86,6 +86,8 @@ const efi_guid_t efi_guid_event_group_reset_system =
/* GUIDs of the Load File and Load File2 protocols */
const efi_guid_t efi_guid_load_file_protocol = EFI_LOAD_FILE_PROTOCOL_GUID;
const efi_guid_t efi_guid_load_file2_protocol = EFI_LOAD_FILE2_PROTOCOL_GUID;
+/* GUID of the SMBIOS table */
+const efi_guid_t smbios_guid = SMBIOS_TABLE_GUID;
static efi_status_t EFIAPI efi_disconnect_controller(
efi_handle_t controller_handle,
@@ -1690,8 +1692,9 @@ out:
*
* Return: status code
*/
-static efi_status_t EFIAPI efi_install_configuration_table_ext(efi_guid_t *guid,
- void *table)
+static efi_status_t
+EFIAPI efi_install_configuration_table_ext(const efi_guid_t *guid,
+ void *table)
{
EFI_ENTRY("%pUl, %p", guid, table);
return EFI_EXIT(efi_install_configuration_table(guid, table));
@@ -3001,7 +3004,7 @@ efi_status_t EFIAPI efi_start_image(efi_handle_t image_handle,
if (IS_ENABLED(CONFIG_EFI_TCG2_PROTOCOL)) {
if (image_obj->image_type == IMAGE_SUBSYSTEM_EFI_APPLICATION) {
- ret = efi_tcg2_measure_efi_app_invocation();
+ ret = efi_tcg2_measure_efi_app_invocation(image_obj);
if (ret != EFI_SUCCESS) {
log_warning("tcg2 measurement fails(0x%lx)\n",
ret);
diff --git a/lib/efi_loader/efi_capsule.c b/lib/efi_loader/efi_capsule.c
index b75e4bc..44f5da6 100644
--- a/lib/efi_loader/efi_capsule.c
+++ b/lib/efi_loader/efi_capsule.c
@@ -11,15 +11,20 @@
#include <common.h>
#include <efi_loader.h>
#include <efi_variable.h>
+#include <env.h>
+#include <fdtdec.h>
#include <fs.h>
#include <malloc.h>
#include <mapmem.h>
#include <sort.h>
+#include <asm/global_data.h>
#include <crypto/pkcs7.h>
#include <crypto/pkcs7_parser.h>
#include <linux/err.h>
+DECLARE_GLOBAL_DATA_PTR;
+
const efi_guid_t efi_guid_capsule_report = EFI_CAPSULE_REPORT_GUID;
static const efi_guid_t efi_guid_firmware_management_capsule_id =
EFI_FIRMWARE_MANAGEMENT_CAPSULE_ID_GUID;
@@ -251,6 +256,37 @@ out:
}
#if defined(CONFIG_EFI_CAPSULE_AUTHENTICATE)
+int __weak efi_get_public_key_data(void **pkey, efi_uintn_t *pkey_len)
+{
+ const void *fdt_blob = gd->fdt_blob;
+ const void *blob;
+ const char *cnode_name = "capsule-key";
+ const char *snode_name = "signature";
+ int sig_node;
+ int len;
+
+ sig_node = fdt_subnode_offset(fdt_blob, 0, snode_name);
+ if (sig_node < 0) {
+ log_err("Unable to get signature node offset\n");
+
+ return -FDT_ERR_NOTFOUND;
+ }
+
+ blob = fdt_getprop(fdt_blob, sig_node, cnode_name, &len);
+
+ if (!blob || len < 0) {
+ log_err("Unable to get capsule-key value\n");
+ *pkey = NULL;
+ *pkey_len = 0;
+
+ return -FDT_ERR_NOTFOUND;
+ }
+
+ *pkey = (void *)blob;
+ *pkey_len = len;
+
+ return 0;
+}
efi_status_t efi_capsule_authenticate(const void *capsule, efi_uintn_t capsule_size,
void **image, efi_uintn_t *image_size)
diff --git a/lib/efi_loader/efi_device_path.c b/lib/efi_loader/efi_device_path.c
index c04439d..735ed0b 100644
--- a/lib/efi_loader/efi_device_path.c
+++ b/lib/efi_loader/efi_device_path.c
@@ -1239,3 +1239,30 @@ efi_device_path *efi_dp_from_lo(struct efi_load_option *lo,
return NULL;
}
+
+/**
+ * search_gpt_dp_node() - search gpt device path node
+ *
+ * @device_path: device path
+ *
+ * Return: pointer to the gpt device path node
+ */
+struct efi_device_path *search_gpt_dp_node(struct efi_device_path *device_path)
+{
+ struct efi_device_path *dp = device_path;
+
+ while (dp) {
+ if (dp->type == DEVICE_PATH_TYPE_MEDIA_DEVICE &&
+ dp->sub_type == DEVICE_PATH_SUB_TYPE_HARD_DRIVE_PATH) {
+ struct efi_device_path_hard_drive_path *hd_dp =
+ (struct efi_device_path_hard_drive_path *)dp;
+
+ if (hd_dp->partmap_type == PART_FORMAT_GPT &&
+ hd_dp->signature_type == SIG_TYPE_GUID)
+ return dp;
+ }
+ dp = efi_dp_next(dp);
+ }
+
+ return NULL;
+}
diff --git a/lib/efi_loader/efi_signature.c b/lib/efi_loader/efi_signature.c
index bdd0988..6e3ee3c 100644
--- a/lib/efi_loader/efi_signature.c
+++ b/lib/efi_loader/efi_signature.c
@@ -7,6 +7,7 @@
#include <common.h>
#include <charset.h>
#include <efi_loader.h>
+#include <efi_variable.h>
#include <image.h>
#include <hexdump.h>
#include <malloc.h>
@@ -740,44 +741,15 @@ err:
*/
struct efi_signature_store *efi_sigstore_parse_sigdb(u16 *name)
{
- struct efi_signature_store *sigstore = NULL;
const efi_guid_t *vendor;
void *db;
efi_uintn_t db_size;
- efi_status_t ret;
-
- if (!u16_strcmp(name, L"PK") || !u16_strcmp(name, L"KEK")) {
- vendor = &efi_global_variable_guid;
- } else if (!u16_strcmp(name, L"db") || !u16_strcmp(name, L"dbx")) {
- vendor = &efi_guid_image_security_database;
- } else {
- EFI_PRINT("unknown signature database, %ls\n", name);
- return NULL;
- }
-
- /* retrieve variable data */
- db_size = 0;
- ret = EFI_CALL(efi_get_variable(name, vendor, NULL, &db_size, NULL));
- if (ret == EFI_NOT_FOUND) {
- EFI_PRINT("variable, %ls, not found\n", name);
- sigstore = calloc(sizeof(*sigstore), 1);
- return sigstore;
- } else if (ret != EFI_BUFFER_TOO_SMALL) {
- EFI_PRINT("Getting variable, %ls, failed\n", name);
- return NULL;
- }
- db = malloc(db_size);
+ vendor = efi_auth_var_get_guid(name);
+ db = efi_get_var(name, vendor, &db_size);
if (!db) {
- EFI_PRINT("Out of memory\n");
- return NULL;
- }
-
- ret = EFI_CALL(efi_get_variable(name, vendor, NULL, &db_size, db));
- if (ret != EFI_SUCCESS) {
- EFI_PRINT("Getting variable, %ls, failed\n", name);
- free(db);
- return NULL;
+ EFI_PRINT("variable, %ls, not found\n", name);
+ return calloc(sizeof(struct efi_signature_store), 1);
}
return efi_build_signature_store(db, db_size);
diff --git a/lib/efi_loader/efi_smbios.c b/lib/efi_loader/efi_smbios.c
index 2eb4cb1..fc0b233 100644
--- a/lib/efi_loader/efi_smbios.c
+++ b/lib/efi_loader/efi_smbios.c
@@ -13,8 +13,6 @@
#include <mapmem.h>
#include <smbios.h>
-static const efi_guid_t smbios_guid = SMBIOS_TABLE_GUID;
-
/*
* Install the SMBIOS table as a configuration table.
*
diff --git a/lib/efi_loader/efi_tcg2.c b/lib/efi_loader/efi_tcg2.c
index 74f0bef..ec20530 100644
--- a/lib/efi_loader/efi_tcg2.c
+++ b/lib/efi_loader/efi_tcg2.c
@@ -11,9 +11,11 @@
#include <common.h>
#include <dm.h>
#include <efi_loader.h>
+#include <efi_variable.h>
#include <efi_tcg2.h>
#include <log.h>
#include <malloc.h>
+#include <smbios.h>
#include <version_string.h>
#include <tpm-v2.h>
#include <u-boot/hash-checksum.h>
@@ -80,16 +82,21 @@ static const struct digest_info hash_algo_list[] = {
};
struct variable_info {
- u16 *name;
- const efi_guid_t *guid;
+ const u16 *name;
+ bool accept_empty;
+ u32 pcr_index;
};
static struct variable_info secure_variables[] = {
- {L"SecureBoot", &efi_global_variable_guid},
- {L"PK", &efi_global_variable_guid},
- {L"KEK", &efi_global_variable_guid},
- {L"db", &efi_guid_image_security_database},
- {L"dbx", &efi_guid_image_security_database},
+ {u"SecureBoot", true, 7},
+ {u"PK", true, 7},
+ {u"KEK", true, 7},
+ {u"db", true, 7},
+ {u"dbx", true, 7},
+ {u"dbt", false, 7},
+ {u"dbr", false, 7},
+ {u"DeployedMode", false, 1},
+ {u"AuditMode", false, 1},
};
#define MAX_HASH_COUNT ARRAY_SIZE(hash_algo_list)
@@ -1366,7 +1373,7 @@ static efi_status_t efi_append_scrtm_version(struct udevice *dev)
* Return: status code
*/
static efi_status_t tcg2_measure_variable(struct udevice *dev, u32 pcr_index,
- u32 event_type, u16 *var_name,
+ u32 event_type, const u16 *var_name,
const efi_guid_t *guid,
efi_uintn_t data_size, u8 *data)
{
@@ -1457,16 +1464,232 @@ error:
}
/**
+ * tcg2_measure_smbios() - measure smbios table
+ *
+ * @dev: TPM device
+ * @entry: pointer to the smbios_entry structure
+ *
+ * Return: status code
+ */
+static efi_status_t
+tcg2_measure_smbios(struct udevice *dev,
+ const struct smbios_entry *entry)
+{
+ efi_status_t ret;
+ struct smbios_header *smbios_copy;
+ struct smbios_handoff_table_pointers2 *event = NULL;
+ u32 event_size;
+
+ /*
+ * TCG PC Client PFP Spec says
+ * "SMBIOS structures that contain static configuration information
+ * (e.g. Platform Manufacturer Enterprise Number assigned by IANA,
+ * platform model number, Vendor and Device IDs for each SMBIOS table)
+ * that is relevant to the security of the platform MUST be measured".
+ * Device dependent parameters such as serial number are cleared to
+ * zero or spaces for the measurement.
+ */
+ event_size = sizeof(struct smbios_handoff_table_pointers2) +
+ FIELD_SIZEOF(struct efi_configuration_table, guid) +
+ entry->struct_table_length;
+ event = calloc(1, event_size);
+ if (!event) {
+ ret = EFI_OUT_OF_RESOURCES;
+ goto out;
+ }
+
+ event->table_description_size = sizeof(SMBIOS_HANDOFF_TABLE_DESC);
+ memcpy(event->table_description, SMBIOS_HANDOFF_TABLE_DESC,
+ sizeof(SMBIOS_HANDOFF_TABLE_DESC));
+ put_unaligned_le64(1, &event->number_of_tables);
+ guidcpy(&event->table_entry[0].guid, &smbios_guid);
+ smbios_copy = (struct smbios_header *)((uintptr_t)&event->table_entry[0].table);
+ memcpy(&event->table_entry[0].table,
+ (void *)((uintptr_t)entry->struct_table_address),
+ entry->struct_table_length);
+
+ smbios_prepare_measurement(entry, smbios_copy);
+
+ ret = tcg2_measure_event(dev, 1, EV_EFI_HANDOFF_TABLES2, event_size,
+ (u8 *)event);
+ if (ret != EFI_SUCCESS)
+ goto out;
+
+out:
+ free(event);
+
+ return ret;
+}
+
+/**
+ * find_smbios_table() - find smbios table
+ *
+ * Return: pointer to the smbios table
+ */
+static void *find_smbios_table(void)
+{
+ u32 i;
+
+ for (i = 0; i < systab.nr_tables; i++) {
+ if (!guidcmp(&smbios_guid, &systab.tables[i].guid))
+ return systab.tables[i].table;
+ }
+
+ return NULL;
+}
+
+/**
+ * tcg2_measure_gpt_table() - measure gpt table
+ *
+ * @dev: TPM device
+ * @loaded_image: handle to the loaded image
+ *
+ * Return: status code
+ */
+static efi_status_t
+tcg2_measure_gpt_data(struct udevice *dev,
+ struct efi_loaded_image_obj *loaded_image)
+{
+ efi_status_t ret;
+ efi_handle_t handle;
+ struct efi_handler *dp_handler;
+ struct efi_device_path *orig_device_path;
+ struct efi_device_path *device_path;
+ struct efi_device_path *dp;
+ struct efi_block_io *block_io;
+ struct efi_gpt_data *event = NULL;
+ efi_guid_t null_guid = NULL_GUID;
+ gpt_header *gpt_h;
+ gpt_entry *entry = NULL;
+ gpt_entry *gpt_e;
+ u32 num_of_valid_entry = 0;
+ u32 event_size;
+ u32 i;
+ u32 total_gpt_entry_size;
+
+ ret = efi_search_protocol(&loaded_image->header,
+ &efi_guid_loaded_image_device_path,
+ &dp_handler);
+ if (ret != EFI_SUCCESS)
+ return ret;
+
+ orig_device_path = dp_handler->protocol_interface;
+ if (!orig_device_path) /* no device path, skip GPT measurement */
+ return EFI_SUCCESS;
+
+ device_path = efi_dp_dup(orig_device_path);
+ if (!device_path)
+ return EFI_OUT_OF_RESOURCES;
+
+ dp = search_gpt_dp_node(device_path);
+ if (!dp) {
+ /* no GPT device path node found, skip GPT measurement */
+ ret = EFI_SUCCESS;
+ goto out1;
+ }
+
+ /* read GPT header */
+ dp->type = DEVICE_PATH_TYPE_END;
+ dp->sub_type = DEVICE_PATH_SUB_TYPE_END;
+ dp = device_path;
+ ret = EFI_CALL(systab.boottime->locate_device_path(&efi_block_io_guid,
+ &dp, &handle));
+ if (ret != EFI_SUCCESS)
+ goto out1;
+
+ ret = EFI_CALL(efi_handle_protocol(handle,
+ &efi_block_io_guid, (void **)&block_io));
+ if (ret != EFI_SUCCESS)
+ goto out1;
+
+ gpt_h = memalign(block_io->media->io_align, block_io->media->block_size);
+ if (!gpt_h) {
+ ret = EFI_OUT_OF_RESOURCES;
+ goto out2;
+ }
+
+ ret = block_io->read_blocks(block_io, block_io->media->media_id, 1,
+ block_io->media->block_size, gpt_h);
+ if (ret != EFI_SUCCESS)
+ goto out2;
+
+ /* read GPT entry */
+ total_gpt_entry_size = gpt_h->num_partition_entries *
+ gpt_h->sizeof_partition_entry;
+ entry = memalign(block_io->media->io_align, total_gpt_entry_size);
+ if (!entry) {
+ ret = EFI_OUT_OF_RESOURCES;
+ goto out2;
+ }
+
+ ret = block_io->read_blocks(block_io, block_io->media->media_id,
+ gpt_h->partition_entry_lba,
+ total_gpt_entry_size, entry);
+ if (ret != EFI_SUCCESS)
+ goto out2;
+
+ /* count valid GPT entry */
+ gpt_e = entry;
+ for (i = 0; i < gpt_h->num_partition_entries; i++) {
+ if (guidcmp(&null_guid, &gpt_e->partition_type_guid))
+ num_of_valid_entry++;
+
+ gpt_e = (gpt_entry *)((u8 *)gpt_e + gpt_h->sizeof_partition_entry);
+ }
+
+ /* prepare event data for measurement */
+ event_size = sizeof(struct efi_gpt_data) +
+ (num_of_valid_entry * gpt_h->sizeof_partition_entry);
+ event = calloc(1, event_size);
+ if (!event) {
+ ret = EFI_OUT_OF_RESOURCES;
+ goto out2;
+ }
+ memcpy(event, gpt_h, sizeof(gpt_header));
+ put_unaligned_le64(num_of_valid_entry, &event->number_of_partitions);
+
+ /* copy valid GPT entry */
+ gpt_e = entry;
+ num_of_valid_entry = 0;
+ for (i = 0; i < gpt_h->num_partition_entries; i++) {
+ if (guidcmp(&null_guid, &gpt_e->partition_type_guid)) {
+ memcpy((u8 *)event->partitions +
+ (num_of_valid_entry * gpt_h->sizeof_partition_entry),
+ gpt_e, gpt_h->sizeof_partition_entry);
+ num_of_valid_entry++;
+ }
+
+ gpt_e = (gpt_entry *)((u8 *)gpt_e + gpt_h->sizeof_partition_entry);
+ }
+
+ ret = tcg2_measure_event(dev, 5, EV_EFI_GPT_EVENT, event_size, (u8 *)event);
+ if (ret != EFI_SUCCESS)
+ goto out2;
+
+out2:
+ EFI_CALL(efi_close_protocol((efi_handle_t)block_io, &efi_block_io_guid,
+ NULL, NULL));
+ free(gpt_h);
+ free(entry);
+ free(event);
+out1:
+ efi_free_pool(device_path);
+
+ return ret;
+}
+
+/**
* efi_tcg2_measure_efi_app_invocation() - measure efi app invocation
*
* Return: status code
*/
-efi_status_t efi_tcg2_measure_efi_app_invocation(void)
+efi_status_t efi_tcg2_measure_efi_app_invocation(struct efi_loaded_image_obj *handle)
{
efi_status_t ret;
u32 pcr_index;
struct udevice *dev;
u32 event = 0;
+ struct smbios_entry *entry;
if (tcg2_efi_app_invoked)
return EFI_SUCCESS;
@@ -1485,6 +1708,17 @@ efi_status_t efi_tcg2_measure_efi_app_invocation(void)
if (ret != EFI_SUCCESS)
goto out;
+ entry = (struct smbios_entry *)find_smbios_table();
+ if (entry) {
+ ret = tcg2_measure_smbios(dev, entry);
+ if (ret != EFI_SUCCESS)
+ goto out;
+ }
+
+ ret = tcg2_measure_gpt_data(dev, handle);
+ if (ret != EFI_SUCCESS)
+ goto out;
+
for (pcr_index = 0; pcr_index <= 7; pcr_index++) {
ret = tcg2_measure_event(dev, pcr_index, EV_SEPARATOR,
sizeof(event), (u8 *)&event);
@@ -1591,54 +1825,38 @@ static efi_status_t tcg2_measure_secure_boot_variable(struct udevice *dev)
efi_uintn_t data_size;
u32 count, i;
efi_status_t ret;
+ u8 deployed_mode;
+ efi_uintn_t size;
+ u32 deployed_audit_pcr_index = 1;
+
+ size = sizeof(deployed_mode);
+ ret = efi_get_variable_int(u"DeployedMode", &efi_global_variable_guid,
+ NULL, &size, &deployed_mode, NULL);
+ if (ret != EFI_SUCCESS || !deployed_mode)
+ deployed_audit_pcr_index = 7;
count = ARRAY_SIZE(secure_variables);
for (i = 0; i < count; i++) {
- /*
- * According to the TCG2 PC Client PFP spec, "SecureBoot",
- * "PK", "KEK", "db" and "dbx" variables must be measured
- * even if they are empty.
- */
- data = efi_get_var(secure_variables[i].name,
- secure_variables[i].guid,
- &data_size);
+ const efi_guid_t *guid;
- ret = tcg2_measure_variable(dev, 7,
- EV_EFI_VARIABLE_DRIVER_CONFIG,
- secure_variables[i].name,
- secure_variables[i].guid,
- data_size, data);
- free(data);
- if (ret != EFI_SUCCESS)
- goto error;
- }
+ guid = efi_auth_var_get_guid(secure_variables[i].name);
- /*
- * TCG2 PC Client PFP spec says "dbt" and "dbr" are
- * measured if present and not empty.
- */
- data = efi_get_var(L"dbt",
- &efi_guid_image_security_database,
- &data_size);
- if (data) {
- ret = tcg2_measure_variable(dev, 7,
- EV_EFI_VARIABLE_DRIVER_CONFIG,
- L"dbt",
- &efi_guid_image_security_database,
- data_size, data);
- free(data);
- }
+ data = efi_get_var(secure_variables[i].name, guid, &data_size);
+ if (!data && !secure_variables[i].accept_empty)
+ continue;
- data = efi_get_var(L"dbr",
- &efi_guid_image_security_database,
- &data_size);
- if (data) {
- ret = tcg2_measure_variable(dev, 7,
+ if (u16_strcmp(u"DeployedMode", secure_variables[i].name))
+ secure_variables[i].pcr_index = deployed_audit_pcr_index;
+ if (u16_strcmp(u"AuditMode", secure_variables[i].name))
+ secure_variables[i].pcr_index = deployed_audit_pcr_index;
+
+ ret = tcg2_measure_variable(dev, secure_variables[i].pcr_index,
EV_EFI_VARIABLE_DRIVER_CONFIG,
- L"dbr",
- &efi_guid_image_security_database,
+ secure_variables[i].name, guid,
data_size, data);
free(data);
+ if (ret != EFI_SUCCESS)
+ goto error;
}
error:
diff --git a/lib/efi_loader/efi_var_common.c b/lib/efi_loader/efi_var_common.c
index a00bbf1..3cbb7c9 100644
--- a/lib/efi_loader/efi_var_common.c
+++ b/lib/efi_loader/efi_var_common.c
@@ -374,7 +374,8 @@ bool efi_secure_boot_enabled(void)
return efi_secure_boot;
}
-enum efi_auth_var_type efi_auth_var_get_type(u16 *name, const efi_guid_t *guid)
+enum efi_auth_var_type efi_auth_var_get_type(const u16 *name,
+ const efi_guid_t *guid)
{
for (size_t i = 0; i < ARRAY_SIZE(name_type); ++i) {
if (!u16_strcmp(name, name_type[i].name) &&
@@ -384,6 +385,15 @@ enum efi_auth_var_type efi_auth_var_get_type(u16 *name, const efi_guid_t *guid)
return EFI_AUTH_VAR_NONE;
}
+const efi_guid_t *efi_auth_var_get_guid(const u16 *name)
+{
+ for (size_t i = 0; i < ARRAY_SIZE(name_type); ++i) {
+ if (!u16_strcmp(name, name_type[i].name))
+ return name_type[i].guid;
+ }
+ return &efi_global_variable_guid;
+}
+
/**
* efi_get_var() - read value of an EFI variable
*
@@ -393,7 +403,7 @@ enum efi_auth_var_type efi_auth_var_get_type(u16 *name, const efi_guid_t *guid)
*
* Return: buffer with variable data or NULL
*/
-void *efi_get_var(u16 *name, const efi_guid_t *vendor, efi_uintn_t *size)
+void *efi_get_var(const u16 *name, const efi_guid_t *vendor, efi_uintn_t *size)
{
efi_status_t ret;
void *buf = NULL;
diff --git a/lib/efi_loader/efi_var_mem.c b/lib/efi_loader/efi_var_mem.c
index 3d335a8..13909b1 100644
--- a/lib/efi_loader/efi_var_mem.c
+++ b/lib/efi_loader/efi_var_mem.c
@@ -134,7 +134,7 @@ void __efi_runtime efi_var_mem_del(struct efi_var_entry *var)
}
efi_status_t __efi_runtime efi_var_mem_ins(
- u16 *variable_name,
+ const u16 *variable_name,
const efi_guid_t *vendor, u32 attributes,
const efi_uintn_t size1, const void *data1,
const efi_uintn_t size2, const void *data2,
@@ -274,8 +274,9 @@ efi_status_t efi_var_mem_init(void)
}
efi_status_t __efi_runtime
-efi_get_variable_mem(u16 *variable_name, const efi_guid_t *vendor, u32 *attributes,
- efi_uintn_t *data_size, void *data, u64 *timep)
+efi_get_variable_mem(const u16 *variable_name, const efi_guid_t *vendor,
+ u32 *attributes, efi_uintn_t *data_size, void *data,
+ u64 *timep)
{
efi_uintn_t old_size;
struct efi_var_entry *var;
diff --git a/lib/efi_loader/efi_variable.c b/lib/efi_loader/efi_variable.c
index fa2b6bc..5adc7f8 100644
--- a/lib/efi_loader/efi_variable.c
+++ b/lib/efi_loader/efi_variable.c
@@ -45,7 +45,7 @@
*
* Return: status code
*/
-static efi_status_t efi_variable_authenticate(u16 *variable,
+static efi_status_t efi_variable_authenticate(const u16 *variable,
const efi_guid_t *vendor,
efi_uintn_t *data_size,
const void **data, u32 given_attr,
@@ -194,7 +194,7 @@ err:
return ret;
}
#else
-static efi_status_t efi_variable_authenticate(u16 *variable,
+static efi_status_t efi_variable_authenticate(const u16 *variable,
const efi_guid_t *vendor,
efi_uintn_t *data_size,
const void **data, u32 given_attr,
@@ -205,7 +205,7 @@ static efi_status_t efi_variable_authenticate(u16 *variable,
#endif /* CONFIG_EFI_SECURE_BOOT */
efi_status_t __efi_runtime
-efi_get_variable_int(u16 *variable_name, const efi_guid_t *vendor,
+efi_get_variable_int(const u16 *variable_name, const efi_guid_t *vendor,
u32 *attributes, efi_uintn_t *data_size, void *data,
u64 *timep)
{
@@ -219,7 +219,8 @@ efi_get_next_variable_name_int(efi_uintn_t *variable_name_size,
return efi_get_next_variable_name_mem(variable_name_size, variable_name, vendor);
}
-efi_status_t efi_set_variable_int(u16 *variable_name, const efi_guid_t *vendor,
+efi_status_t efi_set_variable_int(const u16 *variable_name,
+ const efi_guid_t *vendor,
u32 attributes, efi_uintn_t data_size,
const void *data, bool ro_check)
{
diff --git a/lib/efi_loader/efi_variable_tee.c b/lib/efi_loader/efi_variable_tee.c
index 51920bc..281f886 100644
--- a/lib/efi_loader/efi_variable_tee.c
+++ b/lib/efi_loader/efi_variable_tee.c
@@ -284,7 +284,8 @@ out:
* StMM can store internal attributes and properties for variables, i.e enabling
* R/O variables
*/
-static efi_status_t set_property_int(u16 *variable_name, efi_uintn_t name_size,
+static efi_status_t set_property_int(const u16 *variable_name,
+ efi_uintn_t name_size,
const efi_guid_t *vendor,
struct var_check_property *var_property)
{
@@ -317,7 +318,8 @@ out:
return ret;
}
-static efi_status_t get_property_int(u16 *variable_name, efi_uintn_t name_size,
+static efi_status_t get_property_int(const u16 *variable_name,
+ efi_uintn_t name_size,
const efi_guid_t *vendor,
struct var_check_property *var_property)
{
@@ -361,7 +363,8 @@ out:
return ret;
}
-efi_status_t efi_get_variable_int(u16 *variable_name, const efi_guid_t *vendor,
+efi_status_t efi_get_variable_int(const u16 *variable_name,
+ const efi_guid_t *vendor,
u32 *attributes, efi_uintn_t *data_size,
void *data, u64 *timep)
{
@@ -502,9 +505,10 @@ out:
return ret;
}
-efi_status_t efi_set_variable_int(u16 *variable_name, const efi_guid_t *vendor,
- u32 attributes, efi_uintn_t data_size,
- const void *data, bool ro_check)
+efi_status_t efi_set_variable_int(const u16 *variable_name,
+ const efi_guid_t *vendor, u32 attributes,
+ efi_uintn_t data_size, const void *data,
+ bool ro_check)
{
efi_status_t ret, alt_ret = EFI_SUCCESS;
struct var_check_property var_property;
diff --git a/lib/smbios-parser.c b/lib/smbios-parser.c
index 34203f9..2b93929 100644
--- a/lib/smbios-parser.c
+++ b/lib/smbios-parser.c
@@ -39,10 +39,8 @@ const struct smbios_entry *smbios_entry(u64 address, u32 size)
return entry;
}
-static const struct smbios_header *next_header(const struct smbios_header *curr)
+static u8 *find_next_header(u8 *pos)
{
- u8 *pos = ((u8 *)curr) + curr->length;
-
/* search for _double_ NULL bytes */
while (!((*pos == 0) && (*(pos + 1) == 0)))
pos++;
@@ -50,13 +48,27 @@ static const struct smbios_header *next_header(const struct smbios_header *curr)
/* step behind the double NULL bytes */
pos += 2;
- return (struct smbios_header *)pos;
+ return pos;
+}
+
+static struct smbios_header *get_next_header(struct smbios_header *curr)
+{
+ u8 *pos = ((u8 *)curr) + curr->length;
+
+ return (struct smbios_header *)find_next_header(pos);
+}
+
+static const struct smbios_header *next_header(const struct smbios_header *curr)
+{
+ u8 *pos = ((u8 *)curr) + curr->length;
+
+ return (struct smbios_header *)find_next_header(pos);
}
const struct smbios_header *smbios_header(const struct smbios_entry *entry, int type)
{
const unsigned int num_header = entry->struct_count;
- const struct smbios_header *header = (struct smbios_header *)entry->struct_table_address;
+ const struct smbios_header *header = (struct smbios_header *)((uintptr_t)entry->struct_table_address);
for (unsigned int i = 0; i < num_header; i++) {
if (header->type == type)
@@ -68,8 +80,8 @@ const struct smbios_header *smbios_header(const struct smbios_entry *entry, int
return NULL;
}
-static const char *string_from_smbios_table(const struct smbios_header *header,
- int idx)
+static char *string_from_smbios_table(const struct smbios_header *header,
+ int idx)
{
unsigned int i = 1;
u8 *pos;
@@ -86,10 +98,10 @@ static const char *string_from_smbios_table(const struct smbios_header *header,
pos++;
}
- return (const char *)pos;
+ return (char *)pos;
}
-const char *smbios_string(const struct smbios_header *header, int index)
+char *smbios_string(const struct smbios_header *header, int index)
{
if (!header)
return NULL;
@@ -109,7 +121,7 @@ int smbios_update_version_full(void *smbios_tab, const char *version)
if (!hdr)
return log_msg_ret("tab", -ENOENT);
bios = (struct smbios_type0 *)hdr;
- ptr = (char *)smbios_string(hdr, bios->bios_ver);
+ ptr = smbios_string(hdr, bios->bios_ver);
if (!ptr)
return log_msg_ret("str", -ENOMEDIUM);
@@ -132,3 +144,123 @@ int smbios_update_version_full(void *smbios_tab, const char *version)
return 0;
}
+
+struct smbios_filter_param {
+ u32 offset;
+ u32 size;
+ bool is_string;
+};
+
+struct smbios_filter_table {
+ int type;
+ struct smbios_filter_param *params;
+ u32 count;
+};
+
+struct smbios_filter_param smbios_type1_filter_params[] = {
+ {offsetof(struct smbios_type1, serial_number),
+ FIELD_SIZEOF(struct smbios_type1, serial_number), true},
+ {offsetof(struct smbios_type1, uuid),
+ FIELD_SIZEOF(struct smbios_type1, uuid), false},
+ {offsetof(struct smbios_type1, wakeup_type),
+ FIELD_SIZEOF(struct smbios_type1, wakeup_type), false},
+};
+
+struct smbios_filter_param smbios_type2_filter_params[] = {
+ {offsetof(struct smbios_type2, serial_number),
+ FIELD_SIZEOF(struct smbios_type2, serial_number), true},
+ {offsetof(struct smbios_type2, chassis_location),
+ FIELD_SIZEOF(struct smbios_type2, chassis_location), false},
+};
+
+struct smbios_filter_param smbios_type3_filter_params[] = {
+ {offsetof(struct smbios_type3, serial_number),
+ FIELD_SIZEOF(struct smbios_type3, serial_number), true},
+ {offsetof(struct smbios_type3, asset_tag_number),
+ FIELD_SIZEOF(struct smbios_type3, asset_tag_number), true},
+};
+
+struct smbios_filter_param smbios_type4_filter_params[] = {
+ {offsetof(struct smbios_type4, serial_number),
+ FIELD_SIZEOF(struct smbios_type4, serial_number), true},
+ {offsetof(struct smbios_type4, asset_tag),
+ FIELD_SIZEOF(struct smbios_type4, asset_tag), true},
+ {offsetof(struct smbios_type4, part_number),
+ FIELD_SIZEOF(struct smbios_type4, part_number), true},
+ {offsetof(struct smbios_type4, core_count),
+ FIELD_SIZEOF(struct smbios_type4, core_count), false},
+ {offsetof(struct smbios_type4, core_enabled),
+ FIELD_SIZEOF(struct smbios_type4, core_enabled), false},
+ {offsetof(struct smbios_type4, thread_count),
+ FIELD_SIZEOF(struct smbios_type4, thread_count), false},
+ {offsetof(struct smbios_type4, core_count2),
+ FIELD_SIZEOF(struct smbios_type4, core_count2), false},
+ {offsetof(struct smbios_type4, core_enabled2),
+ FIELD_SIZEOF(struct smbios_type4, core_enabled2), false},
+ {offsetof(struct smbios_type4, thread_count2),
+ FIELD_SIZEOF(struct smbios_type4, thread_count2), false},
+ {offsetof(struct smbios_type4, voltage),
+ FIELD_SIZEOF(struct smbios_type4, voltage), false},
+};
+
+struct smbios_filter_table smbios_filter_tables[] = {
+ {SMBIOS_SYSTEM_INFORMATION, smbios_type1_filter_params,
+ ARRAY_SIZE(smbios_type1_filter_params)},
+ {SMBIOS_BOARD_INFORMATION, smbios_type2_filter_params,
+ ARRAY_SIZE(smbios_type2_filter_params)},
+ {SMBIOS_SYSTEM_ENCLOSURE, smbios_type3_filter_params,
+ ARRAY_SIZE(smbios_type3_filter_params)},
+ {SMBIOS_PROCESSOR_INFORMATION, smbios_type4_filter_params,
+ ARRAY_SIZE(smbios_type4_filter_params)},
+};
+
+static void clear_smbios_table(struct smbios_header *header,
+ struct smbios_filter_param *filter,
+ u32 count)
+{
+ u32 i;
+ char *str;
+ u8 string_id;
+
+ for (i = 0; i < count; i++) {
+ if (filter[i].is_string) {
+ string_id = *((u8 *)header + filter[i].offset);
+ if (string_id == 0) /* string is empty */
+ continue;
+
+ str = smbios_string(header, string_id);
+ if (!str)
+ continue;
+
+ /* string is cleared to space, keep '\0' terminator */
+ memset(str, ' ', strlen(str));
+
+ } else {
+ memset((void *)((u8 *)header + filter[i].offset),
+ 0, filter[i].size);
+ }
+ }
+}
+
+void smbios_prepare_measurement(const struct smbios_entry *entry,
+ struct smbios_header *smbios_copy)
+{
+ u32 i, j;
+ struct smbios_header *header;
+
+ for (i = 0; i < ARRAY_SIZE(smbios_filter_tables); i++) {
+ header = smbios_copy;
+ for (j = 0; j < entry->struct_count; j++) {
+ if (header->type == smbios_filter_tables[i].type)
+ break;
+
+ header = get_next_header(header);
+ }
+ if (j >= entry->struct_count)
+ continue;
+
+ clear_smbios_table(header,
+ smbios_filter_tables[i].params,
+ smbios_filter_tables[i].count);
+ }
+}