mirror of
https://github.com/u-boot/u-boot.git
synced 2024-12-13 14:53:28 +08:00
Pull request for UEFI sub-system for efi-2020-10-rc1 (4)
Improvements for the UEFI subsystem include: * support for read-only TEE-backed variables * allow to compile PK, KEK, db, dbx fixed values into U-Boot * bug fixes Python testing related changes comprise: * enable 'bootefi hello' for better test coverage * remove SKIP messages in UEFI Python tests The fitupd command is dropped. Build errors for the lsblk command are fixed. -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEbcT5xx8ppvoGt20zxIHbvCwFGsQFAl8QMDgACgkQxIHbvCwF GsQG1g/+P0a7gYDY9LV1CziXE5A3wCm1jTcjy/RemJ4c038V7flfX7beTcTeI8Gg 8aHDRTnmiPpU974WgiLBT19ok3LAL87PqlwMcui2YOXDhtNB49UXyY4vLqAE8Olq 2NEi9XsdtE5uKhoPLMf1b2vRzKaw6zcWOUP+BUycVCOQOqn2dPtotB/wFtVcVMKn q58VOCItIvPqNNRwVmcdKYBvp8gEtTebdV2gBlr4drrMTB1nG4BzPcya6hQw6SUL pMzHUAHRTiMR75taWkyvTY975Z+lX1Cn3JkS5RfdaT++ydNH3xFBpLyn1GTA1SRj 9g3p9QL/dXSZAtjGHg78YkWN6spCD/VHLAdMaUv6La/EoW6FBWrM25KH+yqEFfDe llqa8jJc9YBRtvRfFaKCKKoFcIivvnU72EmHsHdgB2wZea5mSF39lGb8onXGL8XS a4TwgQEdAhoGBM6sKG6g+n1wicLPEKlYAUqUEZquhCAyHWg/2TwY+ArcIZd3zPsy d59zoHOB7z27ypfYBAa8afN9qMpwcxzODok/UK2JKMkbpOdATNxmRBMB3VP6xyD+ W2l9Gmbg9oulScFUfbuZJ9jyQGC09OVVmDuk3DrY8/UnIL6ZN9QzsPKzZidmCsx6 ksGsMXmJL8vDqpZqm33H46WmX+sH75yBl4cxQ5njKr3RwKCe5hw= =y4Dr -----END PGP SIGNATURE----- Merge tag 'efi-2020-10-rc1-4' of https://gitlab.denx.de/u-boot/custodians/u-boot-efi Pull request for UEFI sub-system for efi-2020-10-rc1 (4) Improvements for the UEFI subsystem include: * support for read-only TEE-backed variables * allow to compile PK, KEK, db, dbx fixed values into U-Boot * bug fixes Python testing related changes comprise: * enable 'bootefi hello' for better test coverage * remove SKIP messages in UEFI Python tests The fitupd command is dropped. Build errors for the lsblk command are fixed.
This commit is contained in:
commit
fee68b98fe
@ -378,6 +378,7 @@ config CMD_BOOTEFI_HELLO_COMPILE
|
||||
config CMD_BOOTEFI_HELLO
|
||||
bool "Allow booting a standard EFI hello world for testing"
|
||||
depends on CMD_BOOTEFI_HELLO_COMPILE
|
||||
default y if CMD_BOOTEFI_SELFTEST
|
||||
help
|
||||
This adds a standard EFI hello world application to U-Boot so that
|
||||
it can be used with the 'bootefi hello' command. This is useful
|
||||
@ -489,13 +490,6 @@ config CMD_SPL_WRITE_SIZE
|
||||
flash used by Falcon-mode boot. See the documentation until CMD_SPL
|
||||
for detail.
|
||||
|
||||
config CMD_FITUPD
|
||||
bool "fitImage update command"
|
||||
depends on UPDATE_TFTP
|
||||
help
|
||||
Implements the 'fitupd' command, which allows to automatically
|
||||
store software updates present on a TFTP server in NOR Flash
|
||||
|
||||
config CMD_THOR_DOWNLOAD
|
||||
bool "thor - TIZEN 'thor' download"
|
||||
select DFU
|
||||
|
@ -62,7 +62,6 @@ obj-$(CONFIG_CMD_EXT4) += ext4.o
|
||||
obj-$(CONFIG_CMD_EXT2) += ext2.o
|
||||
obj-$(CONFIG_CMD_FAT) += fat.o
|
||||
obj-$(CONFIG_CMD_FDT) += fdt.o
|
||||
obj-$(CONFIG_CMD_FITUPD) += fitupd.o
|
||||
obj-$(CONFIG_CMD_FLASH) += flash.o
|
||||
obj-$(CONFIG_CMD_FPGA) += fpga.o
|
||||
obj-$(CONFIG_CMD_FPGAD) += fpgad.o
|
||||
|
30
cmd/fitupd.c
30
cmd/fitupd.c
@ -1,30 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* (C) Copyright 2011
|
||||
* Andreas Pretzsch, carpe noctem engineering, apr@cn-eng.de
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <command.h>
|
||||
#include <net.h>
|
||||
|
||||
static int do_fitupd(struct cmd_tbl *cmdtp, int flag, int argc,
|
||||
char *const argv[])
|
||||
{
|
||||
ulong addr = 0UL;
|
||||
|
||||
if (argc > 2)
|
||||
return CMD_RET_USAGE;
|
||||
|
||||
if (argc == 2)
|
||||
addr = simple_strtoul(argv[1], NULL, 16);
|
||||
|
||||
return update_tftp(addr, NULL, NULL);
|
||||
}
|
||||
|
||||
U_BOOT_CMD(fitupd, 2, 0, do_fitupd,
|
||||
"update from FIT image",
|
||||
"[addr]\n"
|
||||
"\t- run update from FIT image at addr\n"
|
||||
"\t or from tftp 'updatefile'"
|
||||
);
|
@ -5,6 +5,8 @@
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <blk.h>
|
||||
#include <command.h>
|
||||
#include <dm.h>
|
||||
|
||||
static int do_lsblk(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[])
|
||||
|
@ -1410,7 +1410,7 @@ static char env_help_text[] =
|
||||
#endif
|
||||
"env print [-a | name ...] - print environment\n"
|
||||
#if defined(CONFIG_CMD_NVEDIT_EFI)
|
||||
"env print -e [-guid guid|-all][-n] [name ...] - print UEFI environment\n"
|
||||
"env print -e [-guid guid] [-n] [name ...] - print UEFI environment\n"
|
||||
#endif
|
||||
#if defined(CONFIG_CMD_RUN)
|
||||
"env run var [...] - run commands in an environment variable\n"
|
||||
@ -1452,8 +1452,9 @@ U_BOOT_CMD_COMPLETE(
|
||||
"print environment variables",
|
||||
"[-a]\n - print [all] values of all environment variables\n"
|
||||
#if defined(CONFIG_CMD_NVEDIT_EFI)
|
||||
"printenv -e [-guid guid|-all][-n] [name ...]\n"
|
||||
"printenv -e [-guid guid][-n] [name ...]\n"
|
||||
" - print UEFI variable 'name' or all the variables\n"
|
||||
" \"-guid\": GUID xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\n"
|
||||
" \"-n\": suppress dumping variable's value\n"
|
||||
#endif
|
||||
"printenv name ...\n"
|
||||
@ -1487,7 +1488,7 @@ U_BOOT_CMD_COMPLETE(
|
||||
"-e [-guid guid][-nv][-bs][-rt][-at][-a][-v]\n"
|
||||
" [-i addr,size name], or [name [value ...]]\n"
|
||||
" - set UEFI variable 'name' to 'value' ...'\n"
|
||||
" \"-guid\": set vendor guid\n"
|
||||
" \"-guid\": GUID xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\n"
|
||||
" \"-nv\": set non-volatile attribute\n"
|
||||
" \"-bs\": set boot-service attribute\n"
|
||||
" \"-rt\": set runtime attribute\n"
|
||||
|
106
cmd/nvedit_efi.c
106
cmd/nvedit_efi.c
@ -52,8 +52,7 @@ static const struct {
|
||||
{EFI_CERT_TYPE_PKCS7_GUID, "EFI_CERT_TYPE_PKCS7_GUID"},
|
||||
};
|
||||
|
||||
/* "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" */
|
||||
static char unknown_guid[37];
|
||||
static const char unknown_guid[] = "";
|
||||
|
||||
/**
|
||||
* efi_guid_to_str() - convert guid to readable name
|
||||
@ -71,9 +70,6 @@ static const char *efi_guid_to_str(const efi_guid_t *guid)
|
||||
if (!guidcmp(guid, &efi_guid_text[i].guid))
|
||||
return efi_guid_text[i].text;
|
||||
|
||||
uuid_bin_to_str((unsigned char *)guid->b, unknown_guid,
|
||||
UUID_STR_FORMAT_GUID);
|
||||
|
||||
return unknown_guid;
|
||||
}
|
||||
|
||||
@ -115,7 +111,7 @@ static void efi_dump_single_var(u16 *name, const efi_guid_t *guid, bool verbose)
|
||||
goto out;
|
||||
|
||||
rtc_to_tm(time, &tm);
|
||||
printf("%ls:\n %s:\n", name, efi_guid_to_str(guid));
|
||||
printf("%ls:\n %pUl %s\n", name, guid, efi_guid_to_str(guid));
|
||||
if (attributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS)
|
||||
printf(" %04d-%02d-%02d %02d:%02d:%02d\n", tm.tm_year,
|
||||
tm.tm_mon, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);
|
||||
@ -136,50 +132,6 @@ out:
|
||||
free(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* efi_dump_vars() - show information about named UEFI variables
|
||||
*
|
||||
* @argc: Number of arguments (variables)
|
||||
* @argv: Argument (variable name) array
|
||||
* @verbose: if true, dump data
|
||||
* Return: CMD_RET_SUCCESS on success, or CMD_RET_RET_FAILURE
|
||||
*
|
||||
* Show information encoded in named UEFI variables
|
||||
*/
|
||||
static int efi_dump_vars(int argc, char *const argv[],
|
||||
const efi_guid_t *guid, bool verbose)
|
||||
{
|
||||
u16 *var_name16, *p;
|
||||
efi_uintn_t buf_size, size;
|
||||
|
||||
buf_size = 128;
|
||||
var_name16 = malloc(buf_size);
|
||||
if (!var_name16)
|
||||
return CMD_RET_FAILURE;
|
||||
|
||||
for (; argc > 0; argc--, argv++) {
|
||||
size = (utf8_utf16_strlen(argv[0]) + 1) * sizeof(u16);
|
||||
if (buf_size < size) {
|
||||
buf_size = size;
|
||||
p = realloc(var_name16, buf_size);
|
||||
if (!p) {
|
||||
free(var_name16);
|
||||
return CMD_RET_FAILURE;
|
||||
}
|
||||
var_name16 = p;
|
||||
}
|
||||
|
||||
p = var_name16;
|
||||
utf8_utf16_strcpy(&p, argv[0]);
|
||||
|
||||
efi_dump_single_var(var_name16, guid, verbose);
|
||||
}
|
||||
|
||||
free(var_name16);
|
||||
|
||||
return CMD_RET_SUCCESS;
|
||||
}
|
||||
|
||||
static bool match_name(int argc, char *const argv[], u16 *var_name16)
|
||||
{
|
||||
char *buf, *p;
|
||||
@ -225,10 +177,7 @@ static int efi_dump_var_all(int argc, char *const argv[],
|
||||
efi_uintn_t buf_size, size;
|
||||
efi_guid_t guid;
|
||||
efi_status_t ret;
|
||||
|
||||
if (argc && guid_p)
|
||||
/* simplified case */
|
||||
return efi_dump_vars(argc, argv, guid_p, verbose);
|
||||
bool match = false;
|
||||
|
||||
buf_size = 128;
|
||||
var_name16 = malloc(buf_size);
|
||||
@ -259,13 +208,18 @@ static int efi_dump_var_all(int argc, char *const argv[],
|
||||
return CMD_RET_FAILURE;
|
||||
}
|
||||
|
||||
if ((!guid_p || !guidcmp(guid_p, &guid)) &&
|
||||
(!argc || match_name(argc, argv, var_name16)))
|
||||
if (guid_p && guidcmp(guid_p, &guid))
|
||||
continue;
|
||||
if (!argc || match_name(argc, argv, var_name16)) {
|
||||
match = true;
|
||||
efi_dump_single_var(var_name16, &guid, verbose);
|
||||
}
|
||||
}
|
||||
|
||||
free(var_name16);
|
||||
|
||||
if (!match && argc == 1)
|
||||
printf("Error: \"%s\" not defined\n", argv[0]);
|
||||
|
||||
return CMD_RET_SUCCESS;
|
||||
}
|
||||
|
||||
@ -286,9 +240,8 @@ static int efi_dump_var_all(int argc, char *const argv[],
|
||||
int do_env_print_efi(struct cmd_tbl *cmdtp, int flag, int argc,
|
||||
char *const argv[])
|
||||
{
|
||||
efi_guid_t guid;
|
||||
const efi_guid_t *guid_p;
|
||||
bool default_guid, guid_any, verbose;
|
||||
const efi_guid_t *guid_p = NULL;
|
||||
bool verbose = true;
|
||||
efi_status_t ret;
|
||||
|
||||
/* Initialize EFI drivers */
|
||||
@ -299,31 +252,18 @@ int do_env_print_efi(struct cmd_tbl *cmdtp, int flag, int argc,
|
||||
return CMD_RET_FAILURE;
|
||||
}
|
||||
|
||||
default_guid = true;
|
||||
guid_any = false;
|
||||
verbose = true;
|
||||
for (argc--, argv++; argc > 0 && argv[0][0] == '-'; argc--, argv++) {
|
||||
if (!strcmp(argv[0], "-guid")) {
|
||||
efi_guid_t guid;
|
||||
|
||||
if (argc == 1)
|
||||
return CMD_RET_USAGE;
|
||||
|
||||
/* -a already specified */
|
||||
if (!default_guid && guid_any)
|
||||
return CMD_RET_USAGE;
|
||||
|
||||
argc--;
|
||||
argv++;
|
||||
if (uuid_str_to_bin(argv[0], guid.b,
|
||||
UUID_STR_FORMAT_GUID))
|
||||
return CMD_RET_USAGE;
|
||||
default_guid = false;
|
||||
} else if (!strcmp(argv[0], "-all")) {
|
||||
/* -guid already specified */
|
||||
if (!default_guid && !guid_any)
|
||||
return CMD_RET_USAGE;
|
||||
|
||||
guid_any = true;
|
||||
default_guid = false;
|
||||
guid_p = (const efi_guid_t *)guid.b;
|
||||
} else if (!strcmp(argv[0], "-n")) {
|
||||
verbose = false;
|
||||
} else {
|
||||
@ -331,13 +271,6 @@ int do_env_print_efi(struct cmd_tbl *cmdtp, int flag, int argc,
|
||||
}
|
||||
}
|
||||
|
||||
if (guid_any)
|
||||
guid_p = NULL;
|
||||
else if (default_guid)
|
||||
guid_p = &efi_global_variable_guid;
|
||||
else
|
||||
guid_p = (const efi_guid_t *)guid.b;
|
||||
|
||||
/* enumerate and show all UEFI variables */
|
||||
return efi_dump_var_all(argc, argv, guid_p, verbose);
|
||||
}
|
||||
@ -518,8 +451,7 @@ int do_env_set_efi(struct cmd_tbl *cmdtp, int flag, int argc,
|
||||
argv++;
|
||||
if (uuid_str_to_bin(argv[0], guid.b,
|
||||
UUID_STR_FORMAT_GUID)) {
|
||||
printf("## Guid not specified or in XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX format\n");
|
||||
return CMD_RET_FAILURE;
|
||||
return CMD_RET_USAGE;
|
||||
}
|
||||
default_guid = false;
|
||||
} else if (!strcmp(argv[0], "-bs")) {
|
||||
@ -567,8 +499,8 @@ int do_env_set_efi(struct cmd_tbl *cmdtp, int flag, int argc,
|
||||
}
|
||||
|
||||
if (verbose) {
|
||||
printf("GUID: %s\n", efi_guid_to_str((const efi_guid_t *)
|
||||
&guid));
|
||||
printf("GUID: %pUl %s\n", &guid,
|
||||
efi_guid_to_str((const efi_guid_t *)&guid));
|
||||
printf("Attributes: 0x%x\n", attributes);
|
||||
}
|
||||
|
||||
|
@ -48,6 +48,7 @@ CONFIG_CMD_GPT=y
|
||||
CONFIG_CMD_GPT_RENAME=y
|
||||
CONFIG_CMD_IDE=y
|
||||
CONFIG_CMD_I2C=y
|
||||
CONFIG_CMD_LSBLK=y
|
||||
CONFIG_CMD_OSD=y
|
||||
CONFIG_CMD_PCI=y
|
||||
CONFIG_CMD_READ=y
|
||||
|
@ -42,8 +42,6 @@ for USB based DFU (CONFIG_DFU_*) and DFU TFTP update
|
||||
The "dfu" command has been extended to support transfer via TFTP - one
|
||||
needs to type for example "dfu tftp 0 mmc 0"
|
||||
|
||||
This feature does not depend on "fitupd" command enabled.
|
||||
|
||||
As of this writing (SHA1:8d77576371381ade83de475bb639949b44941e8c v2015.10-rc2)
|
||||
the update.c code is not enabled (CONFIG_UPDATE_TFTP) by any board in the
|
||||
contemporary u-boot tree.
|
||||
|
@ -51,11 +51,6 @@ the mkimage tool. dtc tool with support for binary includes, e.g. in version
|
||||
to be prepared. Refer to the doc/uImage.FIT/ directory for more details on FIT
|
||||
images.
|
||||
|
||||
This mechanism can be also triggered by the command "fitupd".
|
||||
If an optional, non-zero address is provided as argument, the TFTP transfer
|
||||
is skipped and the image at this address is used.
|
||||
The fitupd command is enabled by CONFIG_CMD_FITUPD.
|
||||
|
||||
|
||||
Example .its files
|
||||
------------------
|
||||
|
@ -188,6 +188,15 @@ on the sandbox
|
||||
cd <U-Boot source directory>
|
||||
pytest.py test/py/tests/test_efi_secboot/test_signed.py --bd sandbox
|
||||
|
||||
UEFI binaries may be signed by Microsoft using the following certificates:
|
||||
|
||||
* KEK: Microsoft Corporation KEK CA 2011
|
||||
http://go.microsoft.com/fwlink/?LinkId=321185.
|
||||
* db: Microsoft Windows Production PCA 2011
|
||||
http://go.microsoft.com/fwlink/p/?linkid=321192.
|
||||
* db: Microsoft Corporation UEFI CA 2011
|
||||
http://go.microsoft.com/fwlink/p/?linkid=321194.
|
||||
|
||||
Using OP-TEE for EFI variables
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
@ -25,6 +25,8 @@ extern char __initdata_begin[], __initdata_end[];
|
||||
extern char __start_rodata[], __end_rodata[];
|
||||
extern char __efi_helloworld_begin[];
|
||||
extern char __efi_helloworld_end[];
|
||||
extern char __efi_var_file_begin[];
|
||||
extern char __efi_var_file_end[];
|
||||
|
||||
/* Start and end of .ctors section - used for constructor calls. */
|
||||
extern char __ctors_start[], __ctors_end[];
|
||||
|
@ -10,6 +10,16 @@
|
||||
|
||||
#define EFI_VARIABLE_READ_ONLY BIT(31)
|
||||
|
||||
enum efi_auth_var_type {
|
||||
EFI_AUTH_VAR_NONE = 0,
|
||||
EFI_AUTH_VAR_PK,
|
||||
EFI_AUTH_VAR_KEK,
|
||||
EFI_AUTH_VAR_DB,
|
||||
EFI_AUTH_VAR_DBX,
|
||||
EFI_AUTH_VAR_DBT,
|
||||
EFI_AUTH_VAR_DBR,
|
||||
};
|
||||
|
||||
/**
|
||||
* efi_get_variable() - retrieve value of a UEFI variable
|
||||
*
|
||||
@ -83,6 +93,10 @@ efi_status_t efi_query_variable_info_int(u32 attributes,
|
||||
|
||||
#define EFI_VAR_BUF_SIZE 0x4000
|
||||
|
||||
/*
|
||||
* This constant identifies the file format for storing UEFI variables in
|
||||
* struct efi_var_file.
|
||||
*/
|
||||
#define EFI_VAR_FILE_MAGIC 0x0161566966456255 /* UbEfiVa, version 1 */
|
||||
|
||||
/**
|
||||
@ -106,7 +120,7 @@ struct efi_var_entry {
|
||||
* struct efi_var_file - file for storing UEFI variables
|
||||
*
|
||||
* @reserved: unused, may be overwritten by memory probing
|
||||
* @magic: identifies file format
|
||||
* @magic: identifies file format, takes value %EFI_VAR_FILE_MAGIC
|
||||
* @length: length including header
|
||||
* @crc32: CRC32 without header
|
||||
* @var: variables
|
||||
@ -128,6 +142,14 @@ struct efi_var_file {
|
||||
*/
|
||||
efi_status_t efi_var_to_file(void);
|
||||
|
||||
/**
|
||||
* efi_var_restore() - restore EFI variables from buffer
|
||||
*
|
||||
* @buf: buffer
|
||||
* Return: status code
|
||||
*/
|
||||
efi_status_t efi_var_restore(struct efi_var_file *buf);
|
||||
|
||||
/**
|
||||
* efi_var_from_file() - read variables from file
|
||||
*
|
||||
@ -195,4 +217,20 @@ efi_status_t efi_var_mem_ins(u16 *variable_name,
|
||||
*/
|
||||
u64 efi_var_mem_free(void);
|
||||
|
||||
/**
|
||||
* efi_init_secure_state - initialize secure boot state
|
||||
*
|
||||
* Return: status code
|
||||
*/
|
||||
efi_status_t efi_init_secure_state(void);
|
||||
|
||||
/**
|
||||
* efi_auth_var_get_type() - convert variable name and guid to enum
|
||||
*
|
||||
* @name: name of UEFI variable
|
||||
* @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);
|
||||
|
||||
#endif
|
||||
|
@ -205,4 +205,47 @@ struct smm_variable_query_info {
|
||||
u32 attr;
|
||||
};
|
||||
|
||||
#define VAR_CHECK_VARIABLE_PROPERTY_REVISION 0x0001
|
||||
#define VAR_CHECK_VARIABLE_PROPERTY_READ_ONLY BIT(0)
|
||||
/**
|
||||
* struct var_check_property - Used to store variable properties in StMM
|
||||
*
|
||||
* @revision: magic revision number for variable property checking
|
||||
* @property: properties mask for the variable used in StMM.
|
||||
* Currently RO flag is supported
|
||||
* @attributes: variable attributes used in StMM checking when properties
|
||||
* for a variable are enabled
|
||||
* @minsize: minimum allowed size for variable payload checked against
|
||||
* smm_variable_access->datasize in StMM
|
||||
* @maxsize: maximum allowed size for variable payload checked against
|
||||
* smm_variable_access->datasize in StMM
|
||||
*
|
||||
* Defined in EDK2 as VAR_CHECK_VARIABLE_PROPERTY.
|
||||
*/
|
||||
struct var_check_property {
|
||||
u16 revision;
|
||||
u16 property;
|
||||
u32 attributes;
|
||||
efi_uintn_t minsize;
|
||||
efi_uintn_t maxsize;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct smm_variable_var_check_property - Used to communicate variable
|
||||
* properties with StMM
|
||||
*
|
||||
* @guid: vendor GUID
|
||||
* @name_size: size of EFI name
|
||||
* @property: variable properties struct
|
||||
* @name: variable name
|
||||
*
|
||||
* Defined in EDK2 as SMM_VARIABLE_COMMUNICATE_VAR_CHECK_VARIABLE_PROPERTY.
|
||||
*/
|
||||
struct smm_variable_var_check_property {
|
||||
efi_guid_t guid;
|
||||
efi_uintn_t name_size;
|
||||
struct var_check_property property;
|
||||
u16 name[];
|
||||
};
|
||||
|
||||
#endif /* _MM_COMMUNICATION_H_ */
|
||||
|
@ -27,13 +27,51 @@ config EFI_LOADER
|
||||
|
||||
if EFI_LOADER
|
||||
|
||||
choice
|
||||
prompt "Store for non-volatile UEFI variables"
|
||||
default EFI_VARIABLE_FILE_STORE
|
||||
help
|
||||
Select where non-volatile UEFI variables shall be stored.
|
||||
|
||||
config EFI_VARIABLE_FILE_STORE
|
||||
bool "Store non-volatile UEFI variables as file"
|
||||
depends on FAT_WRITE
|
||||
default y
|
||||
help
|
||||
Select tis option if you want non-volatile UEFI variables to be stored
|
||||
as file /ubootefi.var on the EFI system partition.
|
||||
Select this option if you want non-volatile UEFI variables to be
|
||||
stored as file /ubootefi.var on the EFI system partition.
|
||||
|
||||
config EFI_MM_COMM_TEE
|
||||
bool "UEFI variables storage service via OP-TEE"
|
||||
depends on OPTEE
|
||||
help
|
||||
If OP-TEE is present and running StandAloneMM, dispatch all UEFI
|
||||
variable related operations to that. The application will verify,
|
||||
authenticate and store the variables on an RPMB.
|
||||
|
||||
endchoice
|
||||
|
||||
config EFI_VARIABLES_PRESEED
|
||||
bool "Initial values for UEFI variables"
|
||||
depends on EFI_VARIABLE_FILE_STORE
|
||||
help
|
||||
Include a file with the initial values for non-volatile UEFI variables
|
||||
into the U-Boot binary. If this configuration option is set, changes
|
||||
to authentication related variables (PK, KEK, db, dbx) are not
|
||||
allowed.
|
||||
|
||||
if EFI_VARIABLES_PRESEED
|
||||
|
||||
config EFI_VAR_SEED_FILE
|
||||
string "File with initial values of non-volatile UEFI variables"
|
||||
default ubootefi.var
|
||||
help
|
||||
File with initial values of non-volatile UEFI variables. The file must
|
||||
be in the same format as the storage in the EFI system partition. The
|
||||
easiest way to create it is by setting the non-volatile variables in
|
||||
U-Boot. If a relative file path is used, it is relative to the source
|
||||
directory.
|
||||
|
||||
endif
|
||||
|
||||
config EFI_GET_TIME
|
||||
bool "GetTime() runtime service"
|
||||
@ -174,13 +212,4 @@ config EFI_SECURE_BOOT
|
||||
it is signed with a trusted key. To do that, you need to install,
|
||||
at least, PK, KEK and db.
|
||||
|
||||
config EFI_MM_COMM_TEE
|
||||
bool "UEFI variables storage service via OP-TEE"
|
||||
depends on OPTEE
|
||||
default n
|
||||
help
|
||||
If OP-TEE is present and running StandAloneMM, dispatch all UEFI variable
|
||||
related operations to that. The application will verify, authenticate and
|
||||
store the variables on an RPMB.
|
||||
|
||||
endif
|
||||
|
@ -6,7 +6,7 @@
|
||||
# This file only gets included with CONFIG_EFI_LOADER set, so all
|
||||
# object inclusion implicitly depends on it
|
||||
|
||||
asflags-y += -DHOST_ARCH="$(HOST_ARCH)"
|
||||
asflags-y += -DHOST_ARCH="$(HOST_ARCH)" -I.
|
||||
ccflags-y += -DHOST_ARCH="$(HOST_ARCH)"
|
||||
|
||||
CFLAGS_efi_boottime.o += \
|
||||
@ -42,6 +42,7 @@ obj-y += efi_variable_tee.o
|
||||
else
|
||||
obj-y += efi_variable.o
|
||||
obj-y += efi_var_file.o
|
||||
obj-$(CONFIG_EFI_VARIABLES_PRESEED) += efi_var_seed.o
|
||||
endif
|
||||
obj-y += efi_watchdog.o
|
||||
obj-$(CONFIG_LCD) += efi_gop.o
|
||||
@ -53,3 +54,6 @@ obj-$(CONFIG_GENERATE_SMBIOS_TABLE) += efi_smbios.o
|
||||
obj-$(CONFIG_EFI_RNG_PROTOCOL) += efi_rng.o
|
||||
obj-$(CONFIG_EFI_LOAD_FILE2_INITRD) += efi_load_initrd.o
|
||||
obj-y += efi_signature.o
|
||||
|
||||
EFI_VAR_SEED_FILE := $(subst $\",,$(CONFIG_EFI_VAR_SEED_FILE))
|
||||
$(obj)/efi_var_seed.o: $(srctree)/$(EFI_VAR_SEED_FILE)
|
||||
|
@ -9,6 +9,33 @@
|
||||
#include <efi_loader.h>
|
||||
#include <efi_variable.h>
|
||||
|
||||
enum efi_secure_mode {
|
||||
EFI_MODE_SETUP,
|
||||
EFI_MODE_USER,
|
||||
EFI_MODE_AUDIT,
|
||||
EFI_MODE_DEPLOYED,
|
||||
};
|
||||
|
||||
struct efi_auth_var_name_type {
|
||||
const u16 *name;
|
||||
const efi_guid_t *guid;
|
||||
const enum efi_auth_var_type type;
|
||||
};
|
||||
|
||||
static const struct efi_auth_var_name_type name_type[] = {
|
||||
{u"PK", &efi_global_variable_guid, EFI_AUTH_VAR_PK},
|
||||
{u"KEK", &efi_global_variable_guid, EFI_AUTH_VAR_KEK},
|
||||
{u"db", &efi_guid_image_security_database, EFI_AUTH_VAR_DB},
|
||||
{u"dbx", &efi_guid_image_security_database, EFI_AUTH_VAR_DBX},
|
||||
/* not used yet
|
||||
{u"dbt", &efi_guid_image_security_database, EFI_AUTH_VAR_DBT},
|
||||
{u"dbr", &efi_guid_image_security_database, EFI_AUTH_VAR_DBR},
|
||||
*/
|
||||
};
|
||||
|
||||
static bool efi_secure_boot;
|
||||
static enum efi_secure_mode efi_secure_mode;
|
||||
|
||||
/**
|
||||
* efi_efi_get_variable() - retrieve value of a UEFI variable
|
||||
*
|
||||
@ -138,3 +165,158 @@ efi_status_t EFIAPI efi_query_variable_info(
|
||||
|
||||
return EFI_EXIT(ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* efi_set_secure_state - modify secure boot state variables
|
||||
* @secure_boot: value of SecureBoot
|
||||
* @setup_mode: value of SetupMode
|
||||
* @audit_mode: value of AuditMode
|
||||
* @deployed_mode: value of DeployedMode
|
||||
*
|
||||
* Modify secure boot status related variables as indicated.
|
||||
*
|
||||
* Return: status code
|
||||
*/
|
||||
static efi_status_t efi_set_secure_state(u8 secure_boot, u8 setup_mode,
|
||||
u8 audit_mode, u8 deployed_mode)
|
||||
{
|
||||
efi_status_t ret;
|
||||
const u32 attributes_ro = EFI_VARIABLE_BOOTSERVICE_ACCESS |
|
||||
EFI_VARIABLE_RUNTIME_ACCESS |
|
||||
EFI_VARIABLE_READ_ONLY;
|
||||
const u32 attributes_rw = EFI_VARIABLE_BOOTSERVICE_ACCESS |
|
||||
EFI_VARIABLE_RUNTIME_ACCESS;
|
||||
|
||||
efi_secure_boot = secure_boot;
|
||||
|
||||
ret = efi_set_variable_int(L"SecureBoot", &efi_global_variable_guid,
|
||||
attributes_ro, sizeof(secure_boot),
|
||||
&secure_boot, false);
|
||||
if (ret != EFI_SUCCESS)
|
||||
goto err;
|
||||
|
||||
ret = efi_set_variable_int(L"SetupMode", &efi_global_variable_guid,
|
||||
attributes_ro, sizeof(setup_mode),
|
||||
&setup_mode, false);
|
||||
if (ret != EFI_SUCCESS)
|
||||
goto err;
|
||||
|
||||
ret = efi_set_variable_int(L"AuditMode", &efi_global_variable_guid,
|
||||
audit_mode || setup_mode ?
|
||||
attributes_ro : attributes_rw,
|
||||
sizeof(audit_mode), &audit_mode, false);
|
||||
if (ret != EFI_SUCCESS)
|
||||
goto err;
|
||||
|
||||
ret = efi_set_variable_int(L"DeployedMode",
|
||||
&efi_global_variable_guid,
|
||||
audit_mode || deployed_mode || setup_mode ?
|
||||
attributes_ro : attributes_rw,
|
||||
sizeof(deployed_mode), &deployed_mode,
|
||||
false);
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* efi_transfer_secure_state - handle a secure boot state transition
|
||||
* @mode: new state
|
||||
*
|
||||
* Depending on @mode, secure boot related variables are updated.
|
||||
* Those variables are *read-only* for users, efi_set_variable_int()
|
||||
* is called here.
|
||||
*
|
||||
* Return: status code
|
||||
*/
|
||||
static efi_status_t efi_transfer_secure_state(enum efi_secure_mode mode)
|
||||
{
|
||||
efi_status_t ret;
|
||||
|
||||
EFI_PRINT("Switching secure state from %d to %d\n", efi_secure_mode,
|
||||
mode);
|
||||
|
||||
if (mode == EFI_MODE_DEPLOYED) {
|
||||
ret = efi_set_secure_state(1, 0, 0, 1);
|
||||
if (ret != EFI_SUCCESS)
|
||||
goto err;
|
||||
} else if (mode == EFI_MODE_AUDIT) {
|
||||
ret = efi_set_variable_int(L"PK", &efi_global_variable_guid,
|
||||
EFI_VARIABLE_BOOTSERVICE_ACCESS |
|
||||
EFI_VARIABLE_RUNTIME_ACCESS,
|
||||
0, NULL, false);
|
||||
if (ret != EFI_SUCCESS)
|
||||
goto err;
|
||||
|
||||
ret = efi_set_secure_state(0, 1, 1, 0);
|
||||
if (ret != EFI_SUCCESS)
|
||||
goto err;
|
||||
} else if (mode == EFI_MODE_USER) {
|
||||
ret = efi_set_secure_state(1, 0, 0, 0);
|
||||
if (ret != EFI_SUCCESS)
|
||||
goto err;
|
||||
} else if (mode == EFI_MODE_SETUP) {
|
||||
ret = efi_set_secure_state(0, 1, 0, 0);
|
||||
if (ret != EFI_SUCCESS)
|
||||
goto err;
|
||||
} else {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
efi_secure_mode = mode;
|
||||
|
||||
return EFI_SUCCESS;
|
||||
|
||||
err:
|
||||
/* TODO: What action should be taken here? */
|
||||
printf("ERROR: Secure state transition failed\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
efi_status_t efi_init_secure_state(void)
|
||||
{
|
||||
enum efi_secure_mode mode = EFI_MODE_SETUP;
|
||||
u8 efi_vendor_keys = 0;
|
||||
efi_uintn_t size = 0;
|
||||
efi_status_t ret;
|
||||
|
||||
ret = efi_get_variable_int(L"PK", &efi_global_variable_guid,
|
||||
NULL, &size, NULL, NULL);
|
||||
if (ret == EFI_BUFFER_TOO_SMALL) {
|
||||
if (IS_ENABLED(CONFIG_EFI_SECURE_BOOT))
|
||||
mode = EFI_MODE_USER;
|
||||
}
|
||||
|
||||
ret = efi_transfer_secure_state(mode);
|
||||
if (ret != EFI_SUCCESS)
|
||||
return ret;
|
||||
|
||||
/* As we do not provide vendor keys this variable is always 0. */
|
||||
ret = efi_set_variable_int(L"VendorKeys",
|
||||
&efi_global_variable_guid,
|
||||
EFI_VARIABLE_BOOTSERVICE_ACCESS |
|
||||
EFI_VARIABLE_RUNTIME_ACCESS |
|
||||
EFI_VARIABLE_READ_ONLY,
|
||||
sizeof(efi_vendor_keys),
|
||||
&efi_vendor_keys, false);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* efi_secure_boot_enabled - return if secure boot is enabled or not
|
||||
*
|
||||
* Return: true if enabled, false if disabled
|
||||
*/
|
||||
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)
|
||||
{
|
||||
for (size_t i = 0; i < ARRAY_SIZE(name_type); ++i) {
|
||||
if (!u16_strcmp(name, name_type[i].name) &&
|
||||
!guidcmp(guid, name_type[i].guid))
|
||||
return name_type[i].type;
|
||||
}
|
||||
return EFI_AUTH_VAR_NONE;
|
||||
}
|
||||
|
@ -159,13 +159,7 @@ error:
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* efi_var_restore() - restore EFI variables from buffer
|
||||
*
|
||||
* @buf: buffer
|
||||
* Return: status code
|
||||
*/
|
||||
static efi_status_t __maybe_unused efi_var_restore(struct efi_var_file *buf)
|
||||
efi_status_t efi_var_restore(struct efi_var_file *buf)
|
||||
{
|
||||
struct efi_var_entry *var, *last_var;
|
||||
efi_status_t ret;
|
||||
|
17
lib/efi_loader/efi_var_seed.S
Normal file
17
lib/efi_loader/efi_var_seed.S
Normal file
@ -0,0 +1,17 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Predefined UEFI variables
|
||||
*
|
||||
* Copyright (c) 2020, Heinrich Schuchardt <xypron.glpk@gmx.de>
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
.section .rodata.efi_seed.init,"a"
|
||||
.balign 16
|
||||
.global __efi_var_file_begin
|
||||
__efi_var_file_begin:
|
||||
.incbin CONFIG_EFI_VAR_SEED_FILE
|
||||
.global __efi_var_file_end
|
||||
__efi_var_file_end:
|
||||
.balign 16
|
@ -5,12 +5,15 @@
|
||||
* Copyright (c) 2017 Rob Clark
|
||||
*/
|
||||
|
||||
#define LOG_CATEGORY LOGC_EFI
|
||||
|
||||
#include <common.h>
|
||||
#include <efi_loader.h>
|
||||
#include <efi_variable.h>
|
||||
#include <env.h>
|
||||
#include <env_internal.h>
|
||||
#include <hexdump.h>
|
||||
#include <log.h>
|
||||
#include <malloc.h>
|
||||
#include <rtc.h>
|
||||
#include <search.h>
|
||||
@ -18,166 +21,7 @@
|
||||
#include <crypto/pkcs7_parser.h>
|
||||
#include <linux/compat.h>
|
||||
#include <u-boot/crc.h>
|
||||
|
||||
enum efi_secure_mode {
|
||||
EFI_MODE_SETUP,
|
||||
EFI_MODE_USER,
|
||||
EFI_MODE_AUDIT,
|
||||
EFI_MODE_DEPLOYED,
|
||||
};
|
||||
|
||||
static bool efi_secure_boot;
|
||||
static enum efi_secure_mode efi_secure_mode;
|
||||
static u8 efi_vendor_keys;
|
||||
|
||||
/**
|
||||
* efi_set_secure_state - modify secure boot state variables
|
||||
* @secure_boot: value of SecureBoot
|
||||
* @setup_mode: value of SetupMode
|
||||
* @audit_mode: value of AuditMode
|
||||
* @deployed_mode: value of DeployedMode
|
||||
*
|
||||
* Modify secure boot status related variables as indicated.
|
||||
*
|
||||
* Return: status code
|
||||
*/
|
||||
static efi_status_t efi_set_secure_state(u8 secure_boot, u8 setup_mode,
|
||||
u8 audit_mode, u8 deployed_mode)
|
||||
{
|
||||
efi_status_t ret;
|
||||
const u32 attributes_ro = EFI_VARIABLE_BOOTSERVICE_ACCESS |
|
||||
EFI_VARIABLE_RUNTIME_ACCESS |
|
||||
EFI_VARIABLE_READ_ONLY;
|
||||
const u32 attributes_rw = EFI_VARIABLE_BOOTSERVICE_ACCESS |
|
||||
EFI_VARIABLE_RUNTIME_ACCESS;
|
||||
|
||||
efi_secure_boot = secure_boot;
|
||||
|
||||
ret = efi_set_variable_int(L"SecureBoot", &efi_global_variable_guid,
|
||||
attributes_ro, sizeof(secure_boot),
|
||||
&secure_boot, false);
|
||||
if (ret != EFI_SUCCESS)
|
||||
goto err;
|
||||
|
||||
ret = efi_set_variable_int(L"SetupMode", &efi_global_variable_guid,
|
||||
attributes_ro, sizeof(setup_mode),
|
||||
&setup_mode, false);
|
||||
if (ret != EFI_SUCCESS)
|
||||
goto err;
|
||||
|
||||
ret = efi_set_variable_int(L"AuditMode", &efi_global_variable_guid,
|
||||
audit_mode || setup_mode ?
|
||||
attributes_ro : attributes_rw,
|
||||
sizeof(audit_mode), &audit_mode, false);
|
||||
if (ret != EFI_SUCCESS)
|
||||
goto err;
|
||||
|
||||
ret = efi_set_variable_int(L"DeployedMode",
|
||||
&efi_global_variable_guid,
|
||||
audit_mode || deployed_mode || setup_mode ?
|
||||
attributes_ro : attributes_rw,
|
||||
sizeof(deployed_mode), &deployed_mode,
|
||||
false);
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* efi_transfer_secure_state - handle a secure boot state transition
|
||||
* @mode: new state
|
||||
*
|
||||
* Depending on @mode, secure boot related variables are updated.
|
||||
* Those variables are *read-only* for users, efi_set_variable_int()
|
||||
* is called here.
|
||||
*
|
||||
* Return: status code
|
||||
*/
|
||||
static efi_status_t efi_transfer_secure_state(enum efi_secure_mode mode)
|
||||
{
|
||||
efi_status_t ret;
|
||||
|
||||
EFI_PRINT("Switching secure state from %d to %d\n", efi_secure_mode,
|
||||
mode);
|
||||
|
||||
if (mode == EFI_MODE_DEPLOYED) {
|
||||
ret = efi_set_secure_state(1, 0, 0, 1);
|
||||
if (ret != EFI_SUCCESS)
|
||||
goto err;
|
||||
} else if (mode == EFI_MODE_AUDIT) {
|
||||
ret = efi_set_variable_int(L"PK", &efi_global_variable_guid,
|
||||
EFI_VARIABLE_BOOTSERVICE_ACCESS |
|
||||
EFI_VARIABLE_RUNTIME_ACCESS,
|
||||
0, NULL, false);
|
||||
if (ret != EFI_SUCCESS)
|
||||
goto err;
|
||||
|
||||
ret = efi_set_secure_state(0, 1, 1, 0);
|
||||
if (ret != EFI_SUCCESS)
|
||||
goto err;
|
||||
} else if (mode == EFI_MODE_USER) {
|
||||
ret = efi_set_secure_state(1, 0, 0, 0);
|
||||
if (ret != EFI_SUCCESS)
|
||||
goto err;
|
||||
} else if (mode == EFI_MODE_SETUP) {
|
||||
ret = efi_set_secure_state(0, 1, 0, 0);
|
||||
if (ret != EFI_SUCCESS)
|
||||
goto err;
|
||||
} else {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
efi_secure_mode = mode;
|
||||
|
||||
return EFI_SUCCESS;
|
||||
|
||||
err:
|
||||
/* TODO: What action should be taken here? */
|
||||
printf("ERROR: Secure state transition failed\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* efi_init_secure_state - initialize secure boot state
|
||||
*
|
||||
* Return: status code
|
||||
*/
|
||||
static efi_status_t efi_init_secure_state(void)
|
||||
{
|
||||
enum efi_secure_mode mode = EFI_MODE_SETUP;
|
||||
efi_uintn_t size = 0;
|
||||
efi_status_t ret;
|
||||
|
||||
ret = efi_get_variable_int(L"PK", &efi_global_variable_guid,
|
||||
NULL, &size, NULL, NULL);
|
||||
if (ret == EFI_BUFFER_TOO_SMALL) {
|
||||
if (IS_ENABLED(CONFIG_EFI_SECURE_BOOT))
|
||||
mode = EFI_MODE_USER;
|
||||
}
|
||||
|
||||
ret = efi_transfer_secure_state(mode);
|
||||
if (ret != EFI_SUCCESS)
|
||||
return ret;
|
||||
|
||||
/* As we do not provide vendor keys this variable is always 0. */
|
||||
ret = efi_set_variable_int(L"VendorKeys",
|
||||
&efi_global_variable_guid,
|
||||
EFI_VARIABLE_BOOTSERVICE_ACCESS |
|
||||
EFI_VARIABLE_RUNTIME_ACCESS |
|
||||
EFI_VARIABLE_READ_ONLY,
|
||||
sizeof(efi_vendor_keys),
|
||||
&efi_vendor_keys, false);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* efi_secure_boot_enabled - return if secure boot is enabled or not
|
||||
*
|
||||
* Return: true if enabled, false if disabled
|
||||
*/
|
||||
bool efi_secure_boot_enabled(void)
|
||||
{
|
||||
return efi_secure_boot;
|
||||
}
|
||||
#include <asm/sections.h>
|
||||
|
||||
#ifdef CONFIG_EFI_SECURE_BOOT
|
||||
static u8 pkcs7_hdr[] = {
|
||||
@ -292,6 +136,7 @@ static efi_status_t efi_variable_authenticate(u16 *variable,
|
||||
struct efi_time timestamp;
|
||||
struct rtc_time tm;
|
||||
u64 new_time;
|
||||
enum efi_auth_var_type var_type;
|
||||
efi_status_t ret;
|
||||
|
||||
var_sig = NULL;
|
||||
@ -368,18 +213,20 @@ static efi_status_t efi_variable_authenticate(u16 *variable,
|
||||
}
|
||||
|
||||
/* signature database used for authentication */
|
||||
if (u16_strcmp(variable, L"PK") == 0 ||
|
||||
u16_strcmp(variable, L"KEK") == 0) {
|
||||
var_type = efi_auth_var_get_type(variable, vendor);
|
||||
switch (var_type) {
|
||||
case EFI_AUTH_VAR_PK:
|
||||
case EFI_AUTH_VAR_KEK:
|
||||
/* with PK */
|
||||
truststore = efi_sigstore_parse_sigdb(L"PK");
|
||||
if (!truststore)
|
||||
goto err;
|
||||
} else if (u16_strcmp(variable, L"db") == 0 ||
|
||||
u16_strcmp(variable, L"dbx") == 0) {
|
||||
break;
|
||||
case EFI_AUTH_VAR_DB:
|
||||
case EFI_AUTH_VAR_DBX:
|
||||
/* with PK and KEK */
|
||||
truststore = efi_sigstore_parse_sigdb(L"KEK");
|
||||
truststore2 = efi_sigstore_parse_sigdb(L"PK");
|
||||
|
||||
if (!truststore) {
|
||||
if (!truststore2)
|
||||
goto err;
|
||||
@ -387,7 +234,8 @@ static efi_status_t efi_variable_authenticate(u16 *variable,
|
||||
truststore = truststore2;
|
||||
truststore2 = NULL;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
default:
|
||||
/* TODO: support private authenticated variables */
|
||||
goto err;
|
||||
}
|
||||
@ -506,6 +354,7 @@ efi_status_t efi_set_variable_int(u16 *variable_name, const efi_guid_t *vendor,
|
||||
efi_uintn_t ret;
|
||||
bool append, delete;
|
||||
u64 time = 0;
|
||||
enum efi_auth_var_type var_type;
|
||||
|
||||
if (!variable_name || !*variable_name || !vendor ||
|
||||
((attributes & EFI_VARIABLE_RUNTIME_ACCESS) &&
|
||||
@ -519,10 +368,16 @@ efi_status_t efi_set_variable_int(u16 *variable_name, const efi_guid_t *vendor,
|
||||
delete = !append && (!data_size || !attributes);
|
||||
|
||||
/* check attributes */
|
||||
var_type = efi_auth_var_get_type(variable_name, vendor);
|
||||
if (var) {
|
||||
if (ro_check && (var->attr & EFI_VARIABLE_READ_ONLY))
|
||||
return EFI_WRITE_PROTECTED;
|
||||
|
||||
if (IS_ENABLED(CONFIG_EFI_VARIABLES_PRESEED)) {
|
||||
if (var_type != EFI_AUTH_VAR_NONE)
|
||||
return EFI_WRITE_PROTECTED;
|
||||
}
|
||||
|
||||
/* attributes won't be changed */
|
||||
if (!delete &&
|
||||
((ro_check && var->attr != attributes) ||
|
||||
@ -540,12 +395,7 @@ efi_status_t efi_set_variable_int(u16 *variable_name, const efi_guid_t *vendor,
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
if (((!u16_strcmp(variable_name, L"PK") ||
|
||||
!u16_strcmp(variable_name, L"KEK")) &&
|
||||
!guidcmp(vendor, &efi_global_variable_guid)) ||
|
||||
((!u16_strcmp(variable_name, L"db") ||
|
||||
!u16_strcmp(variable_name, L"dbx")) &&
|
||||
!guidcmp(vendor, &efi_guid_image_security_database))) {
|
||||
if (var_type != EFI_AUTH_VAR_NONE) {
|
||||
/* authentication is mandatory */
|
||||
if (!(attributes &
|
||||
EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS)) {
|
||||
@ -604,7 +454,7 @@ efi_status_t efi_set_variable_int(u16 *variable_name, const efi_guid_t *vendor,
|
||||
if (ret != EFI_SUCCESS)
|
||||
return ret;
|
||||
|
||||
if (!u16_strcmp(variable_name, L"PK"))
|
||||
if (var_type == EFI_AUTH_VAR_PK)
|
||||
ret = efi_init_secure_state();
|
||||
else
|
||||
ret = EFI_SUCCESS;
|
||||
@ -747,5 +597,12 @@ efi_status_t efi_init_variables(void)
|
||||
if (ret != EFI_SUCCESS)
|
||||
return ret;
|
||||
|
||||
if (IS_ENABLED(CONFIG_EFI_VARIABLES_PRESEED)) {
|
||||
ret = efi_var_restore((struct efi_var_file *)
|
||||
__efi_var_file_begin);
|
||||
if (ret != EFI_SUCCESS)
|
||||
log_err("Invalid EFI variable seed\n");
|
||||
}
|
||||
|
||||
return efi_var_from_file();
|
||||
}
|
||||
|
@ -244,10 +244,92 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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,
|
||||
const efi_guid_t *vendor,
|
||||
struct var_check_property *var_property)
|
||||
{
|
||||
struct smm_variable_var_check_property *smm_property;
|
||||
efi_uintn_t payload_size;
|
||||
u8 *comm_buf = NULL;
|
||||
efi_status_t ret;
|
||||
|
||||
payload_size = sizeof(*smm_property) + name_size;
|
||||
if (payload_size > max_payload_size) {
|
||||
ret = EFI_INVALID_PARAMETER;
|
||||
goto out;
|
||||
}
|
||||
comm_buf = setup_mm_hdr((void **)&smm_property, payload_size,
|
||||
SMM_VARIABLE_FUNCTION_VAR_CHECK_VARIABLE_PROPERTY_SET,
|
||||
&ret);
|
||||
if (!comm_buf)
|
||||
goto out;
|
||||
|
||||
guidcpy(&smm_property->guid, vendor);
|
||||
smm_property->name_size = name_size;
|
||||
memcpy(&smm_property->property, var_property,
|
||||
sizeof(smm_property->property));
|
||||
memcpy(smm_property->name, variable_name, name_size);
|
||||
|
||||
ret = mm_communicate(comm_buf, payload_size);
|
||||
|
||||
out:
|
||||
free(comm_buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static efi_status_t get_property_int(u16 *variable_name, efi_uintn_t name_size,
|
||||
const efi_guid_t *vendor,
|
||||
struct var_check_property *var_property)
|
||||
{
|
||||
struct smm_variable_var_check_property *smm_property;
|
||||
efi_uintn_t payload_size;
|
||||
u8 *comm_buf = NULL;
|
||||
efi_status_t ret;
|
||||
|
||||
memset(var_property, 0, sizeof(*var_property));
|
||||
payload_size = sizeof(*smm_property) + name_size;
|
||||
if (payload_size > max_payload_size) {
|
||||
ret = EFI_INVALID_PARAMETER;
|
||||
goto out;
|
||||
}
|
||||
comm_buf = setup_mm_hdr((void **)&smm_property, payload_size,
|
||||
SMM_VARIABLE_FUNCTION_VAR_CHECK_VARIABLE_PROPERTY_GET,
|
||||
&ret);
|
||||
if (!comm_buf)
|
||||
goto out;
|
||||
|
||||
guidcpy(&smm_property->guid, vendor);
|
||||
smm_property->name_size = name_size;
|
||||
memcpy(smm_property->name, variable_name, name_size);
|
||||
|
||||
ret = mm_communicate(comm_buf, payload_size);
|
||||
/*
|
||||
* Currently only R/O property is supported in StMM.
|
||||
* Variables that are not set to R/O will not set the property in StMM
|
||||
* and the call will return EFI_NOT_FOUND. We are setting the
|
||||
* properties to 0x0 so checking against that is enough for the
|
||||
* EFI_NOT_FOUND case.
|
||||
*/
|
||||
if (ret == EFI_NOT_FOUND)
|
||||
ret = EFI_SUCCESS;
|
||||
if (ret != EFI_SUCCESS)
|
||||
goto out;
|
||||
memcpy(var_property, &smm_property->property, sizeof(*var_property));
|
||||
|
||||
out:
|
||||
free(comm_buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
efi_status_t efi_get_variable_int(u16 *variable_name, const efi_guid_t *vendor,
|
||||
u32 *attributes, efi_uintn_t *data_size,
|
||||
void *data, u64 *timep)
|
||||
{
|
||||
struct var_check_property var_property;
|
||||
struct smm_variable_access *var_acc;
|
||||
efi_uintn_t payload_size;
|
||||
efi_uintn_t name_size;
|
||||
@ -299,8 +381,16 @@ efi_status_t efi_get_variable_int(u16 *variable_name, const efi_guid_t *vendor,
|
||||
if (ret != EFI_SUCCESS)
|
||||
goto out;
|
||||
|
||||
if (attributes)
|
||||
ret = get_property_int(variable_name, name_size, vendor, &var_property);
|
||||
if (ret != EFI_SUCCESS)
|
||||
goto out;
|
||||
|
||||
if (attributes) {
|
||||
*attributes = var_acc->attr;
|
||||
if (var_property.property & VAR_CHECK_VARIABLE_PROPERTY_READ_ONLY)
|
||||
*attributes |= EFI_VARIABLE_READ_ONLY;
|
||||
}
|
||||
|
||||
if (data)
|
||||
memcpy(data, (u8 *)var_acc->name + var_acc->name_size,
|
||||
var_acc->data_size);
|
||||
@ -387,11 +477,13 @@ 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 ret, alt_ret = EFI_SUCCESS;
|
||||
struct var_check_property var_property;
|
||||
struct smm_variable_access *var_acc;
|
||||
efi_uintn_t payload_size;
|
||||
efi_uintn_t name_size;
|
||||
u8 *comm_buf = NULL;
|
||||
efi_status_t ret;
|
||||
bool ro;
|
||||
|
||||
if (!variable_name || variable_name[0] == 0 || !vendor) {
|
||||
ret = EFI_INVALID_PARAMETER;
|
||||
@ -401,7 +493,6 @@ efi_status_t efi_set_variable_int(u16 *variable_name, const efi_guid_t *vendor,
|
||||
ret = EFI_INVALID_PARAMETER;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Check payload size */
|
||||
name_size = u16_strsize(variable_name);
|
||||
payload_size = MM_VARIABLE_ACCESS_HEADER_SIZE + name_size + data_size;
|
||||
@ -410,12 +501,41 @@ efi_status_t efi_set_variable_int(u16 *variable_name, const efi_guid_t *vendor,
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Get communication buffer and initialize header */
|
||||
/*
|
||||
* Allocate the buffer early, before switching to RW (if needed)
|
||||
* so we won't need to account for any failures in reading/setting
|
||||
* the properties, if the allocation fails
|
||||
*/
|
||||
comm_buf = setup_mm_hdr((void **)&var_acc, payload_size,
|
||||
SMM_VARIABLE_FUNCTION_SET_VARIABLE, &ret);
|
||||
if (!comm_buf)
|
||||
goto out;
|
||||
|
||||
ro = !!(attributes & EFI_VARIABLE_READ_ONLY);
|
||||
attributes &= EFI_VARIABLE_MASK;
|
||||
|
||||
/*
|
||||
* The API has the ability to override RO flags. If no RO check was
|
||||
* requested switch the variable to RW for the duration of this call
|
||||
*/
|
||||
ret = get_property_int(variable_name, name_size, vendor,
|
||||
&var_property);
|
||||
if (ret != EFI_SUCCESS)
|
||||
goto out;
|
||||
|
||||
if (var_property.property & VAR_CHECK_VARIABLE_PROPERTY_READ_ONLY) {
|
||||
/* Bypass r/o check */
|
||||
if (!ro_check) {
|
||||
var_property.property &= ~VAR_CHECK_VARIABLE_PROPERTY_READ_ONLY;
|
||||
ret = set_property_int(variable_name, name_size, vendor, &var_property);
|
||||
if (ret != EFI_SUCCESS)
|
||||
goto out;
|
||||
} else {
|
||||
ret = EFI_WRITE_PROTECTED;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
/* Fill in contents */
|
||||
guidcpy(&var_acc->guid, vendor);
|
||||
var_acc->data_size = data_size;
|
||||
@ -426,10 +546,26 @@ efi_status_t efi_set_variable_int(u16 *variable_name, const efi_guid_t *vendor,
|
||||
|
||||
/* Communicate */
|
||||
ret = mm_communicate(comm_buf, payload_size);
|
||||
if (ret != EFI_SUCCESS)
|
||||
alt_ret = ret;
|
||||
|
||||
if (ro && !(var_property.property & VAR_CHECK_VARIABLE_PROPERTY_READ_ONLY)) {
|
||||
var_property.revision = VAR_CHECK_VARIABLE_PROPERTY_REVISION;
|
||||
var_property.property |= VAR_CHECK_VARIABLE_PROPERTY_READ_ONLY;
|
||||
var_property.attributes = attributes;
|
||||
var_property.minsize = 1;
|
||||
var_property.maxsize = var_acc->data_size;
|
||||
ret = set_property_int(variable_name, name_size, vendor, &var_property);
|
||||
}
|
||||
|
||||
if (alt_ret != EFI_SUCCESS)
|
||||
goto out;
|
||||
|
||||
if (!u16_strcmp(variable_name, L"PK"))
|
||||
alt_ret = efi_init_secure_state();
|
||||
out:
|
||||
free(comm_buf);
|
||||
return ret;
|
||||
return alt_ret == EFI_SUCCESS ? ret : alt_ret;
|
||||
}
|
||||
|
||||
efi_status_t efi_query_variable_info_int(u32 attributes,
|
||||
@ -586,5 +722,9 @@ efi_status_t efi_init_variables(void)
|
||||
MM_VARIABLE_COMMUNICATE_SIZE +
|
||||
max_payload_size;
|
||||
|
||||
ret = efi_init_secure_state();
|
||||
if (ret != EFI_SUCCESS)
|
||||
return ret;
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
@ -68,8 +68,8 @@ def test_efi_pre_commands(u_boot_console):
|
||||
u_boot_console.run_command('pci enum')
|
||||
|
||||
@pytest.mark.buildconfigspec('cmd_dhcp')
|
||||
def test_efi_dhcp(u_boot_console):
|
||||
"""Test the dhcp command.
|
||||
def test_efi_setup_dhcp(u_boot_console):
|
||||
"""Set up the network using DHCP.
|
||||
|
||||
The boardenv_* file may be used to enable/disable this test; see the
|
||||
comment at the beginning of this file.
|
||||
@ -77,7 +77,10 @@ def test_efi_dhcp(u_boot_console):
|
||||
|
||||
test_dhcp = u_boot_console.config.env.get('env__net_dhcp_server', False)
|
||||
if not test_dhcp:
|
||||
pytest.skip('No DHCP server available')
|
||||
env_vars = u_boot_console.config.env.get('env__net_static_env_vars', None)
|
||||
if not env_vars:
|
||||
pytest.skip('No DHCP server available')
|
||||
return None
|
||||
|
||||
u_boot_console.run_command('setenv autoload no')
|
||||
output = u_boot_console.run_command('dhcp')
|
||||
@ -88,7 +91,7 @@ def test_efi_dhcp(u_boot_console):
|
||||
|
||||
@pytest.mark.buildconfigspec('net')
|
||||
def test_efi_setup_static(u_boot_console):
|
||||
"""Set up a static IP configuration.
|
||||
"""Set up the network using a static IP configuration.
|
||||
|
||||
The configuration is provided by the boardenv_* file; see the comment at
|
||||
the beginning of this file.
|
||||
@ -96,7 +99,10 @@ def test_efi_setup_static(u_boot_console):
|
||||
|
||||
env_vars = u_boot_console.config.env.get('env__net_static_env_vars', None)
|
||||
if not env_vars:
|
||||
pytest.skip('No static network configuration is defined')
|
||||
test_dhcp = u_boot_console.config.env.get('env__net_dhcp_server', False)
|
||||
if not test_dhcp:
|
||||
pytest.skip('No static network configuration is defined')
|
||||
return None
|
||||
|
||||
for (var, val) in env_vars:
|
||||
u_boot_console.run_command('setenv %s %s' % (var, val))
|
||||
|
Loading…
Reference in New Issue
Block a user