aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Rini <trini@konsulko.com>2021-10-26 18:42:26 -0400
committerTom Rini <trini@konsulko.com>2021-10-26 18:42:52 -0400
commit670d657dfb6ede2957043dd0ac868297ac093857 (patch)
treef7ea85030daf5ee969e143bcef63099b3eae758a
parentc9661d0fee0fa57b2ae2442829ed4e6b014c6296 (diff)
parent65aa259aa723793f394abf81b7b0d639826e35b7 (diff)
downloadu-boot-WIP/26Oct2021.zip
u-boot-WIP/26Oct2021.tar.gz
u-boot-WIP/26Oct2021.tar.bz2
Merge tag 'efi-2022-01-rc1-2' of https://source.denx.de/u-boot/custodians/u-boot-efiWIP/26Oct2021
Pull request for efi-2022-01-rc1-2 doc: Remove obsolete PPC4XX references UEFI: Implement missing TCG2 measurements Code clean up # gpg: Signature made Tue 26 Oct 2021 05:56:47 PM EDT # gpg: using RSA key 6DC4F9C71F29A6FA06B76D33C481DBBC2C051AC4 # gpg: Good signature from "Heinrich Schuchardt <xypron.glpk@gmx.de>" [unknown] # gpg: aka "[jpeg image of size 1389]" [unknown] # Primary key fingerprint: 6DC4 F9C7 1F29 A6FA 06B7 6D33 C481 DBBC 2C05 1AC4
-rw-r--r--.mailmap1
-rw-r--r--doc/README.bedbug22
-rw-r--r--doc/README.mpc74xx22
-rw-r--r--doc/develop/uefi/uefi.rst124
-rw-r--r--include/blk.h3
-rw-r--r--include/efi_api.h2
-rw-r--r--include/efi_loader.h7
-rw-r--r--include/efi_tcg2.h27
-rw-r--r--include/efi_variable.h24
-rw-r--r--include/smbios.h17
-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
-rw-r--r--tools/mkeficapsule.c229
23 files changed, 715 insertions, 388 deletions
diff --git a/.mailmap b/.mailmap
index 93533d9..8e69f20 100644
--- a/.mailmap
+++ b/.mailmap
@@ -24,6 +24,7 @@ Boris Brezillon <bbrezillon@kernel.org> <boris.brezillon@bootlin.com>
Boris Brezillon <bbrezillon@kernel.org> <boris.brezillon@free-electrons.com>
Dirk Behme <dirk.behme@googlemail.com>
Fabio Estevam <fabio.estevam@nxp.com>
+Heinrich Schuchardt <xypron.glpk@gmx.de> <heinrich.schuchardt@canonical.com>
Jagan Teki <402jagan@gmail.com>
Jagan Teki <jaganna@gmail.com>
Jagan Teki <jaganna@xilinx.com>
diff --git a/doc/README.bedbug b/doc/README.bedbug
index 35e9d27..1a2acd0 100644
--- a/doc/README.bedbug
+++ b/doc/README.bedbug
@@ -2,8 +2,6 @@ BEDBUG Support for U-Boot
--------------------------
These changes implement the bedbug (emBEDded deBUGger) debugger in U-Boot.
-A specific implementation is made for the AMCC 405 processor but other flavors
-can be easily implemented.
#####################
### Modifications ###
@@ -12,25 +10,9 @@ can be easily implemented.
./common/Makefile
Included cmd_bedbug.c and bedbug.c in the Makefile.
-./common/command.c
- Added bedbug commands to command table.
-
./common/board.c
Added call to initialize debugger on startup.
-./arch/powerpc/cpu/ppc4xx/Makefile
- Added bedbug_405.c to the Makefile.
-
-./arch/powerpc/cpu/ppc4xx/start.S
- Added code to handle the debug exception (0x2000) on the 405.
- Also added code to handle critical exceptions since the debug
- is treated as critical on the 405.
-
-./arch/powerpc/cpu/ppc4xx/traps.c
- Added more detailed output for the program exception to tell
- if it is an illegal instruction, privileged instruction or
- a trap. Also added debug trap handler.
-
./include/ppc_asm.tmpl
Added code to handle critical exceptions
@@ -51,10 +33,6 @@ can be easily implemented.
hardware breakpoints and stepping through code. These
routines are common to all PowerPC processors.
-./arch/powerpc/cpu/ppc4xx/bedbug_405.c
- AMCC PPC405 specific debugger routines.
-
-
Bedbug support for the MPC860
-----------------------------
diff --git a/doc/README.mpc74xx b/doc/README.mpc74xx
deleted file mode 100644
index f81f1c2..0000000
--- a/doc/README.mpc74xx
+++ /dev/null
@@ -1,22 +0,0 @@
-This file contains status information for the port of U-Boot to the
-Motorola mpc74xx series of CPUs.
-
-Author: Josh Huber <huber@mclx.com>
- Mission Critical Linux, Inc.
-
-Currently the support for these CPUs is pretty minimal, but enough to
-get things going. (much like the support for the Galileo Eval Board)
-
-There is a framework in place to enable the L2 cache, and to program
-the BATs. Currently, there are still problems with the code which
-sets up the L2 cache, so it's not enabled. (IMHO, it shouldn't be
-anyway). Additionally, there is support for enabling the MMU, which
-we also don't do. The BATs are programmed just for the benefit of
-jumping into Linux in a sane configuration.
-
-Most of the code was based on other cpus supported by U-Boot.
-
-If you find any errors in the CPU setup code, please send us a note.
-
-Thanks,
-Josh
diff --git a/doc/develop/uefi/uefi.rst b/doc/develop/uefi/uefi.rst
index 4f2b8b0..f17138f 100644
--- a/doc/develop/uefi/uefi.rst
+++ b/doc/develop/uefi/uefi.rst
@@ -277,6 +277,130 @@ Enable ``CONFIG_OPTEE``, ``CONFIG_CMD_OPTEE_RPMB`` and ``CONFIG_EFI_MM_COMM_TEE`
[1] https://optee.readthedocs.io/en/latest/building/efi_vars/stmm.html
+Enabling UEFI Capsule Update feature
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Support has been added for the UEFI capsule update feature which
+enables updating the U-Boot image using the UEFI firmware management
+protocol (FMP). The capsules are not passed to the firmware through
+the UpdateCapsule runtime service. Instead, capsule-on-disk
+functionality is used for fetching the capsule from the EFI System
+Partition (ESP) by placing the capsule file under the
+\EFI\UpdateCapsule directory.
+
+The directory \EFI\UpdateCapsule is checked for capsules only within the
+EFI system partition on the device specified in the active boot option
+determined by reference to BootNext variable or BootOrder variable processing.
+The active Boot Variable is the variable with highest priority BootNext or
+within BootOrder that refers to a device found to be present. Boot variables
+in BootOrder but referring to devices not present are ignored when determining
+active boot variable.
+Before starting a capsule update make sure your capsules are installed in the
+correct ESP partition or set BootNext.
+
+Performing the update
+*********************
+
+Since U-boot doesn't currently support SetVariable at runtime there's a Kconfig
+option (CONFIG_EFI_IGNORE_OSINDICATIONS) to disable the OsIndications variable
+check. If that option is enabled just copy your capsule to \EFI\UpdateCapsule.
+
+If that option is disabled, you'll need to set the OsIndications variable with::
+
+ => setenv -e -nv -bs -rt -v OsIndications =0x04
+
+Finally, the capsule update can be initiated either by rebooting the board,
+which is the preferred method, or by issuing the following command::
+
+ => efidebug capsule disk-update
+
+**The efidebug command is should only be used during debugging/development.**
+
+Enabling Capsule Authentication
+*******************************
+
+The UEFI specification defines a way of authenticating the capsule to
+be updated by verifying the capsule signature. The capsule signature
+is computed and prepended to the capsule payload at the time of
+capsule generation. This signature is then verified by using the
+public key stored as part of the X509 certificate. This certificate is
+in the form of an efi signature list (esl) file, which is embedded as
+part of U-Boot.
+
+The capsule authentication feature can be enabled through the
+following config, in addition to the configs listed above for capsule
+update::
+
+ CONFIG_EFI_CAPSULE_AUTHENTICATE=y
+ CONFIG_EFI_CAPSULE_KEY_PATH=<path to .esl cert>
+
+The public and private keys used for the signing process are generated
+and used by the steps highlighted below::
+
+ 1. Install utility commands on your host
+ * OPENSSL
+ * efitools
+
+ 2. Create signing keys and certificate files on your host
+
+ $ openssl req -x509 -sha256 -newkey rsa:2048 -subj /CN=CRT/ \
+ -keyout CRT.key -out CRT.crt -nodes -days 365
+ $ cert-to-efi-sig-list CRT.crt CRT.esl
+
+ $ openssl x509 -in CRT.crt -out CRT.cer -outform DER
+ $ openssl x509 -inform DER -in CRT.cer -outform PEM -out CRT.pub.pem
+
+ $ openssl pkcs12 -export -out CRT.pfx -inkey CRT.key -in CRT.crt
+ $ openssl pkcs12 -in CRT.pfx -nodes -out CRT.pem
+
+The capsule file can be generated by using the GenerateCapsule.py
+script in EDKII::
+
+ $ ./BaseTools/BinWrappers/PosixLike/GenerateCapsule -e -o \
+ <capsule_file_name> --monotonic-count <val> --fw-version \
+ <val> --lsv <val> --guid \
+ e2bb9c06-70e9-4b14-97a3-5a7913176e3f --verbose \
+ --update-image-index <val> --signer-private-cert \
+ /path/to/CRT.pem --trusted-public-cert \
+ /path/to/CRT.pub.pem --other-public-cert /path/to/CRT.pub.pem \
+ <u-boot.bin>
+
+Place the capsule generated in the above step on the EFI System
+Partition under the EFI/UpdateCapsule directory
+
+Testing on QEMU
+***************
+
+Currently, support has been added on the QEMU ARM64 virt platform for
+updating the U-Boot binary as a raw image when the platform is booted
+in non-secure mode, i.e. with CONFIG_TFABOOT disabled. For this
+configuration, the QEMU platform needs to be booted with
+'secure=off'. The U-Boot binary placed on the first bank of the NOR
+flash at offset 0x0. The U-Boot environment is placed on the second
+NOR flash bank at offset 0x4000000.
+
+The capsule update feature is enabled with the following configuration
+settings::
+
+ CONFIG_MTD=y
+ CONFIG_FLASH_CFI_MTD=y
+ CONFIG_CMD_MTDPARTS=y
+ CONFIG_CMD_DFU=y
+ CONFIG_DFU_MTD=y
+ CONFIG_PCI_INIT_R=y
+ CONFIG_EFI_CAPSULE_ON_DISK=y
+ CONFIG_EFI_CAPSULE_FIRMWARE_MANAGEMENT=y
+ CONFIG_EFI_CAPSULE_FIRMWARE=y
+ CONFIG_EFI_CAPSULE_FIRMWARE_RAW=y
+
+In addition, the following config needs to be disabled(QEMU ARM specific)::
+
+ CONFIG_TFABOOT
+
+The capsule file can be generated by using the tools/mkeficapsule::
+
+ $ mkeficapsule --raw <u-boot.bin> --index 1 <capsule_file_name>
+
Executing the boot manager
~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/include/blk.h b/include/blk.h
index 19bab08..f0cc7ca 100644
--- a/include/blk.h
+++ b/include/blk.h
@@ -45,6 +45,9 @@ enum if_type {
#define BLK_PRD_SIZE 20
#define BLK_REV_SIZE 8
+#define PART_FORMAT_PCAT 0x1
+#define PART_FORMAT_GPT 0x2
+
/*
* Identifies the partition table type (ie. MBR vs GPT GUID) signature
*/
diff --git a/include/efi_api.h b/include/efi_api.h
index c8f959b..0accad0 100644
--- a/include/efi_api.h
+++ b/include/efi_api.h
@@ -120,7 +120,7 @@ struct efi_boot_services {
struct efi_device_path **device_path,
efi_handle_t *device);
efi_status_t (EFIAPI *install_configuration_table)(
- efi_guid_t *guid, void *table);
+ const efi_guid_t *guid, void *table);
efi_status_t (EFIAPI *load_image)(bool boot_policiy,
efi_handle_t parent_image,
diff --git a/include/efi_loader.h b/include/efi_loader.h
index 3e5ac38..d52e399 100644
--- a/include/efi_loader.h
+++ b/include/efi_loader.h
@@ -308,6 +308,8 @@ extern const efi_guid_t efi_guid_capsule_report;
extern const efi_guid_t efi_guid_firmware_management_protocol;
/* GUID for the ESRT */
extern const efi_guid_t efi_esrt_guid;
+/* GUID of the SMBIOS table */
+extern const efi_guid_t smbios_guid;
extern char __efi_runtime_start[], __efi_runtime_stop[];
extern char __efi_runtime_rel_start[], __efi_runtime_rel_stop[];
@@ -501,7 +503,7 @@ efi_status_t efi_init_variables(void);
void efi_variables_boot_exit_notify(void);
efi_status_t efi_tcg2_notify_exit_boot_services_failed(void);
/* Measure efi application invocation */
-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);
/* Measure efi application exit */
efi_status_t efi_tcg2_measure_efi_app_exit(void);
/* Called by bootefi to initialize root node */
@@ -818,7 +820,7 @@ efi_status_t EFIAPI efi_query_variable_info(
u64 *remaining_variable_storage_size,
u64 *maximum_variable_size);
-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);
/*
* See section 3.1.3 in the v2.7 UEFI spec for more details on
@@ -845,6 +847,7 @@ struct efi_device_path *efi_dp_from_lo(struct efi_load_option *lo,
const efi_guid_t *guid);
struct efi_device_path *efi_dp_concat(const struct efi_device_path *dp1,
const struct efi_device_path *dp2);
+struct efi_device_path *search_gpt_dp_node(struct efi_device_path *device_path);
efi_status_t efi_deserialize_load_option(struct efi_load_option *lo, u8 *data,
efi_uintn_t *size);
unsigned long efi_serialize_load_option(struct efi_load_option *lo, u8 **data);
diff --git a/include/efi_tcg2.h b/include/efi_tcg2.h
index 8f02d4f..50a59f9 100644
--- a/include/efi_tcg2.h
+++ b/include/efi_tcg2.h
@@ -210,6 +210,33 @@ struct efi_tcg2_uefi_variable_data {
u8 variable_data[1];
};
+/**
+ * struct tdUEFI_HANDOFF_TABLE_POINTERS2 - event log structure of SMBOIS tables
+ * @table_description_size: size of table description
+ * @table_description: table description
+ * @number_of_tables: number of uefi configuration table
+ * @table_entry: uefi configuration table entry
+ */
+#define SMBIOS_HANDOFF_TABLE_DESC "SmbiosTable"
+struct smbios_handoff_table_pointers2 {
+ u8 table_description_size;
+ u8 table_description[sizeof(SMBIOS_HANDOFF_TABLE_DESC)];
+ u64 number_of_tables;
+ struct efi_configuration_table table_entry[];
+} __packed;
+
+/**
+ * struct tdUEFI_GPT_DATA - event log structure of industry standard tables
+ * @uefi_partition_header: gpt partition header
+ * @number_of_partitions: the number of partition
+ * @partitions: partition entries
+ */
+struct efi_gpt_data {
+ gpt_header uefi_partition_header;
+ u64 number_of_partitions;
+ gpt_entry partitions[];
+} __packed;
+
struct efi_tcg2_protocol {
efi_status_t (EFIAPI * get_capability)(struct efi_tcg2_protocol *this,
struct efi_tcg2_boot_service_capability *capability);
diff --git a/include/efi_variable.h b/include/efi_variable.h
index 0440d35..03a3ecb 100644
--- a/include/efi_variable.h
+++ b/include/efi_variable.h
@@ -32,7 +32,8 @@ enum efi_auth_var_type {
* @timep: authentication time (seconds since start of epoch)
* Return: status code
*/
-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);
@@ -47,7 +48,8 @@ efi_status_t efi_get_variable_int(u16 *variable_name, const efi_guid_t *vendor,
* @ro_check: check the read only read only bit in attributes
* Return: status code
*/
-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);
@@ -224,7 +226,7 @@ void efi_var_mem_del(struct efi_var_entry *var);
* @time: time of authentication (as seconds since start of epoch)
* Result: status code
*/
-efi_status_t efi_var_mem_ins(u16 *variable_name,
+efi_status_t efi_var_mem_ins(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,
@@ -251,7 +253,16 @@ efi_status_t efi_init_secure_state(void);
* @guid: guid of UEFI variable
* Return: identifier for authentication related variables
*/
-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);
+
+/**
+ * efi_auth_var_get_guid() - get the predefined GUID for a variable name
+ *
+ * @name: name of UEFI variable
+ * Return: guid of UEFI variable
+ */
+const efi_guid_t *efi_auth_var_get_guid(const u16 *name);
/**
* efi_get_next_variable_name_mem() - Runtime common code across efi variable
@@ -280,8 +291,9 @@ efi_get_next_variable_name_mem(efi_uintn_t *variable_name_size, u16 *variable_na
* Return: status code
*/
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_get_variable_runtime() - runtime implementation of GetVariable()
diff --git a/include/smbios.h b/include/smbios.h
index aa6b6f3..acfcbfe 100644
--- a/include/smbios.h
+++ b/include/smbios.h
@@ -260,9 +260,9 @@ const struct smbios_header *smbios_header(const struct smbios_entry *entry, int
*
* @header: pointer to struct smbios_header
* @index: string index
- * @return: NULL or a valid const char pointer
+ * @return: NULL or a valid char pointer
*/
-const char *smbios_string(const struct smbios_header *header, int index);
+char *smbios_string(const struct smbios_header *header, int index);
/**
* smbios_update_version() - Update the version string
@@ -292,4 +292,17 @@ int smbios_update_version(const char *version);
*/
int smbios_update_version_full(void *smbios_tab, const char *version);
+/**
+ * smbios_prepare_measurement() - Update smbios table for the measurement
+ *
+ * TCG specification requires to measure static configuration information.
+ * This function clear the device dependent parameters such as
+ * serial number for the measurement.
+ *
+ * @entry: pointer to a struct smbios_entry
+ * @header: pointer to a struct smbios_header
+ */
+void smbios_prepare_measurement(const struct smbios_entry *entry,
+ struct smbios_header *header);
+
#endif /* _SMBIOS_H_ */
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);
+ }
+}
diff --git a/tools/mkeficapsule.c b/tools/mkeficapsule.c
index de0a628..4995ba4 100644
--- a/tools/mkeficapsule.c
+++ b/tools/mkeficapsule.c
@@ -4,22 +4,17 @@
* Author: AKASHI Takahiro
*/
-#include <errno.h>
#include <getopt.h>
#include <malloc.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <unistd.h>
#include <linux/types.h>
-#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
-#include "fdt_host.h"
-
typedef __u8 u8;
typedef __u16 u16;
typedef __u32 u32;
@@ -29,9 +24,6 @@ typedef __s32 s32;
#define aligned_u64 __aligned_u64
-#define SIGNATURE_NODENAME "signature"
-#define OVERLAY_NODENAME "__overlay__"
-
#ifndef __packed
#define __packed __attribute__((packed))
#endif
@@ -52,9 +44,6 @@ static struct option options[] = {
{"raw", required_argument, NULL, 'r'},
{"index", required_argument, NULL, 'i'},
{"instance", required_argument, NULL, 'I'},
- {"dtb", required_argument, NULL, 'D'},
- {"public key", required_argument, NULL, 'K'},
- {"overlay", no_argument, NULL, 'O'},
{"help", no_argument, NULL, 'h'},
{NULL, 0, NULL, 0},
};
@@ -68,187 +57,10 @@ static void print_usage(void)
"\t-r, --raw <raw image> new raw image file\n"
"\t-i, --index <index> update image index\n"
"\t-I, --instance <instance> update hardware instance\n"
- "\t-K, --public-key <key file> public key esl file\n"
- "\t-D, --dtb <dtb file> dtb file\n"
- "\t-O, --overlay the dtb file is an overlay\n"
"\t-h, --help print a help message\n",
tool_name);
}
-static int fdt_add_pub_key_data(void *sptr, void *dptr, size_t key_size,
- bool overlay)
-{
- int parent;
- int ov_node;
- int frag_node;
- int ret = 0;
-
- if (overlay) {
- /*
- * The signature would be stored in the
- * first fragment node of the overlay
- */
- frag_node = fdt_first_subnode(dptr, 0);
- if (frag_node == -FDT_ERR_NOTFOUND) {
- fprintf(stderr,
- "Couldn't find the fragment node: %s\n",
- fdt_strerror(frag_node));
- goto done;
- }
-
- ov_node = fdt_subnode_offset(dptr, frag_node, OVERLAY_NODENAME);
- if (ov_node == -FDT_ERR_NOTFOUND) {
- fprintf(stderr,
- "Couldn't find the __overlay__ node: %s\n",
- fdt_strerror(ov_node));
- goto done;
- }
- } else {
- ov_node = 0;
- }
-
- parent = fdt_subnode_offset(dptr, ov_node, SIGNATURE_NODENAME);
- if (parent == -FDT_ERR_NOTFOUND) {
- parent = fdt_add_subnode(dptr, ov_node, SIGNATURE_NODENAME);
- if (parent < 0) {
- ret = parent;
- if (ret != -FDT_ERR_NOSPACE) {
- fprintf(stderr,
- "Couldn't create signature node: %s\n",
- fdt_strerror(parent));
- }
- }
- }
- if (ret)
- goto done;
-
- /* Write the key to the FDT node */
- ret = fdt_setprop(dptr, parent, "capsule-key",
- sptr, key_size);
-
-done:
- if (ret)
- ret = ret == -FDT_ERR_NOSPACE ? -ENOSPC : -EIO;
-
- return ret;
-}
-
-static int add_public_key(const char *pkey_file, const char *dtb_file,
- bool overlay)
-{
- int ret;
- int srcfd = -1;
- int destfd = -1;
- void *sptr = NULL;
- void *dptr = NULL;
- off_t src_size;
- struct stat pub_key;
- struct stat dtb;
-
- /* Find out the size of the public key */
- srcfd = open(pkey_file, O_RDONLY);
- if (srcfd == -1) {
- fprintf(stderr, "%s: Can't open %s: %s\n",
- __func__, pkey_file, strerror(errno));
- ret = -1;
- goto err;
- }
-
- ret = fstat(srcfd, &pub_key);
- if (ret == -1) {
- fprintf(stderr, "%s: Can't stat %s: %s\n",
- __func__, pkey_file, strerror(errno));
- ret = -1;
- goto err;
- }
-
- src_size = pub_key.st_size;
-
- /* mmap the public key esl file */
- sptr = mmap(0, src_size, PROT_READ, MAP_SHARED, srcfd, 0);
- if (sptr == MAP_FAILED) {
- fprintf(stderr, "%s: Failed to mmap %s:%s\n",
- __func__, pkey_file, strerror(errno));
- ret = -1;
- goto err;
- }
-
- /* Open the dest FDT */
- destfd = open(dtb_file, O_RDWR);
- if (destfd == -1) {
- fprintf(stderr, "%s: Can't open %s: %s\n",
- __func__, dtb_file, strerror(errno));
- ret = -1;
- goto err;
- }
-
- ret = fstat(destfd, &dtb);
- if (ret == -1) {
- fprintf(stderr, "%s: Can't stat %s: %s\n",
- __func__, dtb_file, strerror(errno));
- goto err;
- }
-
- dtb.st_size += src_size + 0x30;
- if (ftruncate(destfd, dtb.st_size)) {
- fprintf(stderr, "%s: Can't expand %s: %s\n",
- __func__, dtb_file, strerror(errno));
- ret = -1;
- goto err;
- }
-
- errno = 0;
- /* mmap the dtb file */
- dptr = mmap(0, dtb.st_size, PROT_READ | PROT_WRITE, MAP_SHARED,
- destfd, 0);
- if (dptr == MAP_FAILED) {
- fprintf(stderr, "%s: Failed to mmap %s:%s\n",
- __func__, dtb_file, strerror(errno));
- ret = -1;
- goto err;
- }
-
- if (fdt_check_header(dptr)) {
- fprintf(stderr, "%s: Invalid FDT header\n", __func__);
- ret = -1;
- goto err;
- }
-
- ret = fdt_open_into(dptr, dptr, dtb.st_size);
- if (ret) {
- fprintf(stderr, "%s: Cannot expand FDT: %s\n",
- __func__, fdt_strerror(ret));
- ret = -1;
- goto err;
- }
-
- /* Copy the esl file to the expanded FDT */
- ret = fdt_add_pub_key_data(sptr, dptr, src_size, overlay);
- if (ret < 0) {
- fprintf(stderr, "%s: Unable to add public key to the FDT\n",
- __func__);
- ret = -1;
- goto err;
- }
-
- ret = 0;
-
-err:
- if (sptr)
- munmap(sptr, src_size);
-
- if (dptr)
- munmap(dptr, dtb.st_size);
-
- if (srcfd != -1)
- close(srcfd);
-
- if (destfd != -1)
- close(destfd);
-
- return ret;
-}
-
static int create_fwbin(char *path, char *bin, efi_guid_t *guid,
unsigned long index, unsigned long instance)
{
@@ -366,22 +178,16 @@ err_1:
int main(int argc, char **argv)
{
char *file;
- char *pkey_file;
- char *dtb_file;
efi_guid_t *guid;
unsigned long index, instance;
int c, idx;
- int ret;
- bool overlay = false;
file = NULL;
- pkey_file = NULL;
- dtb_file = NULL;
guid = NULL;
index = 0;
instance = 0;
for (;;) {
- c = getopt_long(argc, argv, "f:r:i:I:v:D:K:Oh", options, &idx);
+ c = getopt_long(argc, argv, "f:r:i:I:v:h", options, &idx);
if (c == -1)
break;
@@ -408,43 +214,22 @@ int main(int argc, char **argv)
case 'I':
instance = strtoul(optarg, NULL, 0);
break;
- case 'K':
- if (pkey_file) {
- printf("Public Key already specified\n");
- return -1;
- }
- pkey_file = optarg;
- break;
- case 'D':
- if (dtb_file) {
- printf("DTB file already specified\n");
- return -1;
- }
- dtb_file = optarg;
- break;
- case 'O':
- overlay = true;
- break;
case 'h':
print_usage();
return 0;
}
}
- /* need a fit image file or raw image file */
- if (!file && !pkey_file && !dtb_file) {
+ /* need an output file */
+ if (argc != optind + 1) {
print_usage();
exit(EXIT_FAILURE);
}
- if (pkey_file && dtb_file) {
- ret = add_public_key(pkey_file, dtb_file, overlay);
- if (ret == -1) {
- printf("Adding public key to the dtb failed\n");
- exit(EXIT_FAILURE);
- } else {
- exit(EXIT_SUCCESS);
- }
+ /* need a fit image file or raw image file */
+ if (!file) {
+ print_usage();
+ exit(EXIT_SUCCESS);
}
if (create_fwbin(argv[optind], file, guid, index, instance)