Pull request for efi-2022-01-rc1-2
doc: Remove obsolete PPC4XX references UEFI: Implement missing TCG2 measurements Code clean up -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEbcT5xx8ppvoGt20zxIHbvCwFGsQFAmF4eZ8ACgkQxIHbvCwF GsSDRxAAlujYTep5xp0/yzSvUvS5ocJBstgw0YuO4GY1RtXN9Zgdd1PeETdEh7HW HKNOrx3Bk1LlyLeObyKX6Dq3p4PkYX8q4ciaWkTqPoId2LKeXYJGxABled6EW8OJ 68/smhQOoivQPuDTZsUCJXdsRnnoxAhO5S03JEgIZKeusOJjZQ5QVS0a91ovOllB sjMcpm4HDO0hkEo59ExP2unlRrBuB7L0VwA+SxvXB1e8vruWxye8i5Fw/hN9g73h Atrl9/Mbn1ppWqHgOMaMawxPhuceZjINpRJXIZ5H5m4bgwYrjk9HFJGV3C1eOo5a Vdc8/I1X5GXetn6kFae7vSJhU9QgHK1QsXjObs/ksOwS0+K4QRFc1X6aMkdO8QPI 3EfVUaeedDdzrQdtATu9L9a6dVuE79abNNevUglmZrvKWqgMIl61M1Ffl7IWuCJo t6YyCZmBvt4rNh1/UEbkL9d7y5lkoCJafe9EMYwZk0zfPamw08bB8KWDIJrm0P0w fnSdEDQdnHvFfZ//th/u7Q6zpfN9waxZ93mMvfBkmjCi8aa0GLMIStcYcOoJm+Z6 QdzaP5XPQ4gC2A7lqSOPwExUgvcfx0y6AuIoTdusqU7w5+obqnc+e4FN7UFxzr5K ZCf6+8JO3rbD9ptWpCEDFpFdMbq32MwGTKM2Jy7kL1nzGKcNdPE= =LkPN -----END PGP SIGNATURE----- Merge tag 'efi-2022-01-rc1-2' of https://source.denx.de/u-boot/custodians/u-boot-efi 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
This commit is contained in:
commit
670d657dfb
1
.mailmap
1
.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>
|
||||
|
@ -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
|
||||
-----------------------------
|
||||
|
||||
|
@ -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
|
@ -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
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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()
|
||||
|
@ -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_ */
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
*
|
||||
|
@ -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)
|
||||
{
|
||||
@ -1456,17 +1463,233 @@ error:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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,56 +1825,40 @@ 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,
|
||||
guid = efi_auth_var_get_guid(secure_variables[i].name);
|
||||
|
||||
data = efi_get_var(secure_variables[i].name, guid, &data_size);
|
||||
if (!data && !secure_variables[i].accept_empty)
|
||||
continue;
|
||||
|
||||
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,
|
||||
secure_variables[i].name,
|
||||
secure_variables[i].guid,
|
||||
secure_variables[i].name, guid,
|
||||
data_size, data);
|
||||
free(data);
|
||||
if (ret != EFI_SUCCESS)
|
||||
goto error;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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(L"dbr",
|
||||
&efi_guid_image_security_database,
|
||||
&data_size);
|
||||
if (data) {
|
||||
ret = tcg2_measure_variable(dev, 7,
|
||||
EV_EFI_VARIABLE_DRIVER_CONFIG,
|
||||
L"dbr",
|
||||
&efi_guid_image_security_database,
|
||||
data_size, data);
|
||||
free(data);
|
||||
}
|
||||
|
||||
error:
|
||||
return ret;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user