mirror of
https://github.com/Fishwaldo/u-boot.git
synced 2025-03-18 21:21:37 +00:00
Pull request for UEFI sub-system for efi-2020-07-rc3
A series of patches introduces the possibility to manage UEFI variables via an OP-TEE module. CONFIG_EFI_MM_COMM_TEE enables this. If this option is not specified the U-Boot behavior remains unchanged. A defconfig is provided for compile testing (lx2160ardb_tfa_stmm_defconfig). An incorrect UEFI memory allocation for fsl-layerscape is fixed -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEbcT5xx8ppvoGt20zxIHbvCwFGsQFAl7CLCQACgkQxIHbvCwF GsSwUA//X9OHUBYyVnP0IB8s58/un40DyipYZGmdQJkTvRUzQ6BHgQaTbJB56nax vXApU6agEgir5BuNow8/MCQ91YVdxpMMX64P+BuqqH/TeayIhbE4Wh2LBPqG1eWm xFqC8F5nZddSTgJ67rrXdZosG4e2KbRGDD2W6LP2g7DBmTM0AUFOZkWyu6dHk9oB bSkFDkSBfzd5/xdrYDAOEpYLz7TsrFprmUEwFe++b3Nnwj9t+IXyLDDsvJkvI8hw 5+aVmZibaPH2rcyHzIovc/M+uEqWE0NaKwvVPOvurkCC+wiOfspBBcIEwlfnZTCn apbqNbmhMwFVVE8zd+zrhp8uOJW/pCKiBTIWllRl1cHSHogj1aF/iQ2HyWfnpONV ySDCapYws97guN7nUuwiHW+7PfduHodz2J6IdT/+k6pw8tmcPwho5EvbKE5xCDVt YLsSB0ENXchnV4WBA4mehIaQ2UcNGlZDrx5rIlV3ukqSUtb2ZK2Waibs4JORv33+ sBAmxUTaUmBcU1u809+pFHd9wOsnrqUoOXHSxa3632hKuumIw+B5RCU8+wlgAa2i CI53z9A7S1ilRt8/JVIE0ttI6Y/kamUtPFZZHuXL+CbrZldQA+UxA8w8aCZm0QNS MBmv55HbEn6Mi4kqRJCBe0kdviHsjtfT0sDXsfZwKBAma7BfliQ= =I/PP -----END PGP SIGNATURE----- Merge tag 'efi-2020-07-rc3' of https://gitlab.denx.de/u-boot/custodians/u-boot-efi Pull request for UEFI sub-system for efi-2020-07-rc3 A series of patches introduces the possibility to manage UEFI variables via an OP-TEE module. CONFIG_EFI_MM_COMM_TEE enables this. If this option is not specified the U-Boot behavior remains unchanged. A defconfig is provided for compile testing (lx2160ardb_tfa_stmm_defconfig). An incorrect UEFI memory allocation for fsl-layerscape is fixed
This commit is contained in:
commit
ed9a3aa645
22 changed files with 1117 additions and 55 deletions
|
@ -635,6 +635,12 @@ F: cmd/efidebug.c
|
||||||
F: cmd/nvedit_efi.c
|
F: cmd/nvedit_efi.c
|
||||||
F: tools/file2include.c
|
F: tools/file2include.c
|
||||||
|
|
||||||
|
EFI VARIABLES VIA OP-TEE
|
||||||
|
M: Ilias Apalodimas <ilias.apalodimas@linaro.org>
|
||||||
|
S: Maintained
|
||||||
|
F: lib/efi_loader/efi_variable_tee.c
|
||||||
|
F: include/mm_communication.h
|
||||||
|
|
||||||
ENVIRONMENT
|
ENVIRONMENT
|
||||||
M: Joe Hershberger <joe.hershberger@ni.com>
|
M: Joe Hershberger <joe.hershberger@ni.com>
|
||||||
R: Wolfgang Denk <wd@denx.de>
|
R: Wolfgang Denk <wd@denx.de>
|
||||||
|
|
|
@ -1529,9 +1529,8 @@ int dram_init_banksize(void)
|
||||||
void efi_add_known_memory(void)
|
void efi_add_known_memory(void)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
phys_addr_t ram_start, start;
|
phys_addr_t ram_start;
|
||||||
phys_size_t ram_size;
|
phys_size_t ram_size;
|
||||||
u64 pages;
|
|
||||||
|
|
||||||
/* Add RAM */
|
/* Add RAM */
|
||||||
for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
|
for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
|
||||||
|
@ -1549,11 +1548,8 @@ void efi_add_known_memory(void)
|
||||||
gd->arch.resv_ram < ram_start + ram_size)
|
gd->arch.resv_ram < ram_start + ram_size)
|
||||||
ram_size = gd->arch.resv_ram - ram_start;
|
ram_size = gd->arch.resv_ram - ram_start;
|
||||||
#endif
|
#endif
|
||||||
start = (ram_start + EFI_PAGE_MASK) & ~EFI_PAGE_MASK;
|
efi_add_memory_map(ram_start, ram_size,
|
||||||
pages = (ram_size + EFI_PAGE_MASK) >> EFI_PAGE_SHIFT;
|
EFI_CONVENTIONAL_MEMORY);
|
||||||
|
|
||||||
efi_add_memory_map(start, pages, EFI_CONVENTIONAL_MEMORY,
|
|
||||||
false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -146,9 +146,8 @@ remove_psci_node:
|
||||||
fdt_add_mem_rsv(blob, (uintptr_t)&secondary_boot_code,
|
fdt_add_mem_rsv(blob, (uintptr_t)&secondary_boot_code,
|
||||||
*boot_code_size);
|
*boot_code_size);
|
||||||
#if CONFIG_IS_ENABLED(EFI_LOADER)
|
#if CONFIG_IS_ENABLED(EFI_LOADER)
|
||||||
efi_add_memory_map((uintptr_t)&secondary_boot_code,
|
efi_add_memory_map((uintptr_t)&secondary_boot_code, *boot_code_size,
|
||||||
ALIGN(*boot_code_size, EFI_PAGE_SIZE) >> EFI_PAGE_SHIFT,
|
EFI_RESERVED_MEMORY_TYPE);
|
||||||
EFI_RESERVED_MEMORY_TYPE, false);
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -428,4 +428,10 @@
|
||||||
#size-cells = <0>;
|
#size-cells = <0>;
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
firmware {
|
||||||
|
optee {
|
||||||
|
compatible = "linaro,optee-tz";
|
||||||
|
method = "smc";
|
||||||
|
};
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -69,11 +69,8 @@ void meson_board_add_reserved_memory(void *fdt, u64 start, u64 size)
|
||||||
if (ret)
|
if (ret)
|
||||||
printf("Could not reserve zone @ 0x%llx\n", start);
|
printf("Could not reserve zone @ 0x%llx\n", start);
|
||||||
|
|
||||||
if (IS_ENABLED(CONFIG_EFI_LOADER)) {
|
if (IS_ENABLED(CONFIG_EFI_LOADER))
|
||||||
efi_add_memory_map(start,
|
efi_add_memory_map(start, size, EFI_RESERVED_MEMORY_TYPE);
|
||||||
ALIGN(size, EFI_PAGE_SIZE) >> EFI_PAGE_SHIFT,
|
|
||||||
EFI_RESERVED_MEMORY_TYPE, false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int meson_generate_serial_ethaddr(void)
|
int meson_generate_serial_ethaddr(void)
|
||||||
|
|
|
@ -41,7 +41,7 @@ void efi_add_known_memory(void)
|
||||||
{
|
{
|
||||||
struct e820_entry e820[E820MAX];
|
struct e820_entry e820[E820MAX];
|
||||||
unsigned int i, num;
|
unsigned int i, num;
|
||||||
u64 start, pages, ram_top;
|
u64 start, ram_top;
|
||||||
int type;
|
int type;
|
||||||
|
|
||||||
num = install_e820_map(ARRAY_SIZE(e820), e820);
|
num = install_e820_map(ARRAY_SIZE(e820), e820);
|
||||||
|
@ -77,9 +77,7 @@ void efi_add_known_memory(void)
|
||||||
start + e820[i].size,
|
start + e820[i].size,
|
||||||
ram_top);
|
ram_top);
|
||||||
} else {
|
} else {
|
||||||
pages = ALIGN(e820[i].size, EFI_PAGE_SIZE)
|
efi_add_memory_map(start, e820[i].size, type);
|
||||||
>> EFI_PAGE_SHIFT;
|
|
||||||
efi_add_memory_map(start, pages, type, false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ F: board/freescale/lx2160a/
|
||||||
F: include/configs/lx2160a_common.h
|
F: include/configs/lx2160a_common.h
|
||||||
F: include/configs/lx2160ardb.h
|
F: include/configs/lx2160ardb.h
|
||||||
F: configs/lx2160ardb_tfa_defconfig
|
F: configs/lx2160ardb_tfa_defconfig
|
||||||
|
F: configs/lx2160ardb_tfa_stmm_defconfig
|
||||||
F: arch/arm/dts/fsl-lx2160a-rdb.dts
|
F: arch/arm/dts/fsl-lx2160a-rdb.dts
|
||||||
|
|
||||||
LX2160ARDB_SECURE_BOOT BOARD
|
LX2160ARDB_SECURE_BOOT BOARD
|
||||||
|
|
|
@ -489,8 +489,8 @@ int ft_board_setup(void *blob, bd_t *bd)
|
||||||
|
|
||||||
#ifdef CONFIG_EFI_LOADER
|
#ifdef CONFIG_EFI_LOADER
|
||||||
/* Reserve the spin table */
|
/* Reserve the spin table */
|
||||||
efi_add_memory_map(0, CONFIG_RPI_EFI_NR_SPIN_PAGES,
|
efi_add_memory_map(0, CONFIG_RPI_EFI_NR_SPIN_PAGES << EFI_PAGE_SHIFT,
|
||||||
EFI_RESERVED_MEMORY_TYPE, 0);
|
EFI_RESERVED_MEMORY_TYPE);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -151,14 +151,10 @@ done:
|
||||||
|
|
||||||
static void efi_reserve_memory(u64 addr, u64 size)
|
static void efi_reserve_memory(u64 addr, u64 size)
|
||||||
{
|
{
|
||||||
u64 pages;
|
|
||||||
|
|
||||||
/* Convert from sandbox address space. */
|
/* Convert from sandbox address space. */
|
||||||
addr = (uintptr_t)map_sysmem(addr, 0);
|
addr = (uintptr_t)map_sysmem(addr, 0);
|
||||||
pages = efi_size_in_pages(size + (addr & EFI_PAGE_MASK));
|
if (efi_add_memory_map(addr, size,
|
||||||
addr &= ~EFI_PAGE_MASK;
|
EFI_RESERVED_MEMORY_TYPE) != EFI_SUCCESS)
|
||||||
if (efi_add_memory_map(addr, pages, EFI_RESERVED_MEMORY_TYPE,
|
|
||||||
false) != EFI_SUCCESS)
|
|
||||||
printf("Reserved memory mapping failed addr %llx size %llx\n",
|
printf("Reserved memory mapping failed addr %llx size %llx\n",
|
||||||
addr, size);
|
addr, size);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1165,6 +1165,58 @@ static int do_efi_test(cmd_tbl_t *cmdtp, int flag,
|
||||||
return cp->cmd(cmdtp, flag, argc, argv);
|
return cp->cmd(cmdtp, flag, argc, argv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* do_efi_query_info() - QueryVariableInfo EFI service
|
||||||
|
*
|
||||||
|
* @cmdtp: Command table
|
||||||
|
* @flag: Command flag
|
||||||
|
* @argc: Number of arguments
|
||||||
|
* @argv: Argument array
|
||||||
|
* Return: CMD_RET_SUCCESS on success,
|
||||||
|
* CMD_RET_USAGE or CMD_RET_FAILURE on failure
|
||||||
|
*
|
||||||
|
* Implement efidebug "test" sub-command.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int do_efi_query_info(cmd_tbl_t *cmdtp, int flag,
|
||||||
|
int argc, char * const argv[])
|
||||||
|
{
|
||||||
|
efi_status_t ret;
|
||||||
|
u32 attr = 0;
|
||||||
|
u64 max_variable_storage_size;
|
||||||
|
u64 remain_variable_storage_size;
|
||||||
|
u64 max_variable_size;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 1; i < argc; i++) {
|
||||||
|
if (!strcmp(argv[i], "-bs"))
|
||||||
|
attr |= EFI_VARIABLE_BOOTSERVICE_ACCESS;
|
||||||
|
else if (!strcmp(argv[i], "-rt"))
|
||||||
|
attr |= EFI_VARIABLE_RUNTIME_ACCESS;
|
||||||
|
else if (!strcmp(argv[i], "-nv"))
|
||||||
|
attr |= EFI_VARIABLE_NON_VOLATILE;
|
||||||
|
else if (!strcmp(argv[i], "-at"))
|
||||||
|
attr |=
|
||||||
|
EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = EFI_CALL(efi_query_variable_info(attr,
|
||||||
|
&max_variable_storage_size,
|
||||||
|
&remain_variable_storage_size,
|
||||||
|
&max_variable_size));
|
||||||
|
if (ret != EFI_SUCCESS) {
|
||||||
|
printf("Error: Cannot query UEFI variables, r = %lu\n",
|
||||||
|
ret & ~EFI_ERROR_MASK);
|
||||||
|
return CMD_RET_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Max storage size %llu\n", max_variable_storage_size);
|
||||||
|
printf("Remaining storage size %llu\n", remain_variable_storage_size);
|
||||||
|
printf("Max variable size %llu\n", max_variable_size);
|
||||||
|
|
||||||
|
return CMD_RET_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
static cmd_tbl_t cmd_efidebug_sub[] = {
|
static cmd_tbl_t cmd_efidebug_sub[] = {
|
||||||
U_BOOT_CMD_MKENT(boot, CONFIG_SYS_MAXARGS, 1, do_efi_boot_opt, "", ""),
|
U_BOOT_CMD_MKENT(boot, CONFIG_SYS_MAXARGS, 1, do_efi_boot_opt, "", ""),
|
||||||
U_BOOT_CMD_MKENT(devices, CONFIG_SYS_MAXARGS, 1, do_efi_show_devices,
|
U_BOOT_CMD_MKENT(devices, CONFIG_SYS_MAXARGS, 1, do_efi_show_devices,
|
||||||
|
@ -1181,6 +1233,8 @@ static cmd_tbl_t cmd_efidebug_sub[] = {
|
||||||
"", ""),
|
"", ""),
|
||||||
U_BOOT_CMD_MKENT(test, CONFIG_SYS_MAXARGS, 1, do_efi_test,
|
U_BOOT_CMD_MKENT(test, CONFIG_SYS_MAXARGS, 1, do_efi_test,
|
||||||
"", ""),
|
"", ""),
|
||||||
|
U_BOOT_CMD_MKENT(query, CONFIG_SYS_MAXARGS, 1, do_efi_query_info,
|
||||||
|
"", ""),
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1252,7 +1306,9 @@ static char efidebug_help_text[] =
|
||||||
"efidebug tables\n"
|
"efidebug tables\n"
|
||||||
" - show UEFI configuration tables\n"
|
" - show UEFI configuration tables\n"
|
||||||
"efidebug test bootmgr\n"
|
"efidebug test bootmgr\n"
|
||||||
" - run simple bootmgr for test\n";
|
" - run simple bootmgr for test\n"
|
||||||
|
"efidebug query [-nv][-bs][-rt][-at]\n"
|
||||||
|
" - show size of UEFI variables store\n";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
U_BOOT_CMD(
|
U_BOOT_CMD(
|
||||||
|
|
85
configs/lx2160ardb_tfa_stmm_defconfig
Normal file
85
configs/lx2160ardb_tfa_stmm_defconfig
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
CONFIG_ARM=y
|
||||||
|
CONFIG_GIC_V3_ITS=y
|
||||||
|
CONFIG_TARGET_LX2160ARDB=y
|
||||||
|
CONFIG_TFABOOT=y
|
||||||
|
CONFIG_SYS_TEXT_BASE=0x82000000
|
||||||
|
CONFIG_SYS_MALLOC_F_LEN=0x6000
|
||||||
|
CONFIG_ENV_SIZE=0x2000
|
||||||
|
CONFIG_ENV_OFFSET=0x500000
|
||||||
|
CONFIG_ENV_SECT_SIZE=0x20000
|
||||||
|
CONFIG_DM_GPIO=y
|
||||||
|
CONFIG_EMC2305=y
|
||||||
|
CONFIG_FSPI_AHB_EN_4BYTE=y
|
||||||
|
CONFIG_NR_DRAM_BANKS=3
|
||||||
|
CONFIG_ARMV8_SEC_FIRMWARE_SUPPORT=y
|
||||||
|
CONFIG_SEC_FIRMWARE_ARMV8_PSCI=y
|
||||||
|
CONFIG_AHCI=y
|
||||||
|
CONFIG_FIT_VERBOSE=y
|
||||||
|
CONFIG_OF_BOARD_SETUP=y
|
||||||
|
CONFIG_OF_STDOUT_VIA_ALIAS=y
|
||||||
|
CONFIG_BOOTDELAY=10
|
||||||
|
CONFIG_USE_BOOTARGS=y
|
||||||
|
CONFIG_BOOTARGS="console=ttyAMA0,115200 root=/dev/ram0 earlycon=pl011,mmio32,0x21c0000 ramdisk_size=0x2000000 default_hugepagesz=1024m hugepagesz=1024m hugepages=2 pci=pcie_bus_perf"
|
||||||
|
# CONFIG_USE_BOOTCOMMAND is not set
|
||||||
|
CONFIG_MISC_INIT_R=y
|
||||||
|
CONFIG_CMD_GREPENV=y
|
||||||
|
CONFIG_CMD_NVEDIT_EFI=y
|
||||||
|
CONFIG_CMD_EEPROM=y
|
||||||
|
CONFIG_CMD_DM=y
|
||||||
|
CONFIG_CMD_GPT=y
|
||||||
|
CONFIG_CMD_I2C=y
|
||||||
|
CONFIG_CMD_MMC=y
|
||||||
|
CONFIG_CMD_PCI=y
|
||||||
|
CONFIG_CMD_USB=y
|
||||||
|
CONFIG_CMD_CACHE=y
|
||||||
|
CONFIG_CMD_EFIDEBUG=y
|
||||||
|
CONFIG_MP=y
|
||||||
|
CONFIG_OF_CONTROL=y
|
||||||
|
CONFIG_OF_BOARD_FIXUP=y
|
||||||
|
CONFIG_DEFAULT_DEVICE_TREE="fsl-lx2160a-rdb"
|
||||||
|
CONFIG_ENV_IS_IN_MMC=y
|
||||||
|
CONFIG_ENV_IS_IN_SPI_FLASH=y
|
||||||
|
CONFIG_ENV_ADDR=0x20500000
|
||||||
|
CONFIG_NET_RANDOM_ETHADDR=y
|
||||||
|
CONFIG_DM=y
|
||||||
|
CONFIG_SATA_CEVA=y
|
||||||
|
CONFIG_FSL_CAAM=y
|
||||||
|
CONFIG_DM_I2C=y
|
||||||
|
CONFIG_I2C_SET_DEFAULT_BUS_NUM=y
|
||||||
|
CONFIG_I2C_DEFAULT_BUS_NUMBER=0
|
||||||
|
CONFIG_DM_MMC=y
|
||||||
|
CONFIG_SUPPORT_EMMC_RPMB=y
|
||||||
|
CONFIG_FSL_ESDHC=y
|
||||||
|
CONFIG_MTD=y
|
||||||
|
CONFIG_DM_SPI_FLASH=y
|
||||||
|
CONFIG_SPI_FLASH_SPANSION=y
|
||||||
|
CONFIG_SPI_FLASH_STMICRO=y
|
||||||
|
# CONFIG_SPI_FLASH_USE_4K_SECTORS is not set
|
||||||
|
CONFIG_PHYLIB=y
|
||||||
|
CONFIG_PHY_AQUANTIA=y
|
||||||
|
CONFIG_PHY_ATHEROS=y
|
||||||
|
CONFIG_PHY_CORTINA=y
|
||||||
|
CONFIG_DM_ETH=y
|
||||||
|
CONFIG_DM_MDIO=y
|
||||||
|
CONFIG_E1000=y
|
||||||
|
CONFIG_FSL_LS_MDIO=y
|
||||||
|
CONFIG_PCI=y
|
||||||
|
CONFIG_DM_PCI=y
|
||||||
|
CONFIG_DM_PCI_COMPAT=y
|
||||||
|
CONFIG_PCIE_LAYERSCAPE=y
|
||||||
|
CONFIG_PCIE_LAYERSCAPE_GEN4=y
|
||||||
|
CONFIG_DM_RTC=y
|
||||||
|
CONFIG_RTC_PCF2127=y
|
||||||
|
CONFIG_DM_SCSI=y
|
||||||
|
CONFIG_DM_SERIAL=y
|
||||||
|
CONFIG_SPI=y
|
||||||
|
CONFIG_DM_SPI=y
|
||||||
|
CONFIG_NXP_FSPI=y
|
||||||
|
CONFIG_TEE=y
|
||||||
|
CONFIG_OPTEE=y
|
||||||
|
CONFIG_USB=y
|
||||||
|
CONFIG_DM_USB=y
|
||||||
|
CONFIG_USB_XHCI_HCD=y
|
||||||
|
CONFIG_USB_XHCI_DWC3=y
|
||||||
|
CONFIG_EFI_LOADER_BOUNCE_BUFFER=y
|
||||||
|
CONFIG_EFI_MM_COMM_TEE=y
|
|
@ -188,6 +188,23 @@ on the sandbox
|
||||||
cd <U-Boot source directory>
|
cd <U-Boot source directory>
|
||||||
pytest.py test/py/tests/test_efi_secboot/test_signed.py --bd sandbox
|
pytest.py test/py/tests/test_efi_secboot/test_signed.py --bd sandbox
|
||||||
|
|
||||||
|
Using OP-TEE for EFI variables
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Instead of implementing UEFI variable services inside U-Boot they can
|
||||||
|
also be provided in the secure world by a module for OP-TEE[1]. The
|
||||||
|
interface between U-Boot and OP-TEE for variable services is enabled by
|
||||||
|
CONFIG_EFI_MM_COMM_TEE=y.
|
||||||
|
|
||||||
|
Tianocore EDK II's standalone management mode driver for variables can
|
||||||
|
be linked to OP-TEE for this purpose. This module uses the Replay
|
||||||
|
Protected Memory Block (RPMB) of an eMMC device for persisting
|
||||||
|
non-volatile variables. When calling the variable services via the
|
||||||
|
OP-TEE API U-Boot's OP-TEE supplicant relays calls to the RPMB driver
|
||||||
|
which has to be enabled via CONFIG_SUPPORT_EMMC_RPMB=y.
|
||||||
|
|
||||||
|
[1] https://optee.readthedocs.io/ - OP-TEE documentation
|
||||||
|
|
||||||
Executing the boot manager
|
Executing the boot manager
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
|
|
@ -195,8 +195,8 @@ void meson_vpu_rsv_fb(void *fdt)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
#if defined(CONFIG_EFI_LOADER)
|
#if defined(CONFIG_EFI_LOADER)
|
||||||
efi_add_memory_map(meson_fb.base, meson_fb.fb_size >> EFI_PAGE_SHIFT,
|
efi_add_memory_map(meson_fb.base, meson_fb.fb_size,
|
||||||
EFI_RESERVED_MEMORY_TYPE, false);
|
EFI_RESERVED_MEMORY_TYPE);
|
||||||
#endif
|
#endif
|
||||||
#if defined(CONFIG_VIDEO_DT_SIMPLEFB)
|
#if defined(CONFIG_VIDEO_DT_SIMPLEFB)
|
||||||
meson_vpu_setup_simplefb(fdt);
|
meson_vpu_setup_simplefb(fdt);
|
||||||
|
|
|
@ -224,9 +224,9 @@ static int sunxi_de2_init(struct udevice *dev, ulong fbbase,
|
||||||
|
|
||||||
#ifdef CONFIG_EFI_LOADER
|
#ifdef CONFIG_EFI_LOADER
|
||||||
efi_add_memory_map(fbbase,
|
efi_add_memory_map(fbbase,
|
||||||
ALIGN(timing.hactive.typ * timing.vactive.typ *
|
timing.hactive.typ * timing.vactive.typ *
|
||||||
(1 << l2bpp) / 8, EFI_PAGE_SIZE) >> EFI_PAGE_SHIFT,
|
(1 << l2bpp) / 8,
|
||||||
EFI_RESERVED_MEMORY_TYPE, false);
|
EFI_RESERVED_MEMORY_TYPE);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -1196,10 +1196,8 @@ void *video_hw_init(void)
|
||||||
sunxi_engines_init();
|
sunxi_engines_init();
|
||||||
|
|
||||||
#ifdef CONFIG_EFI_LOADER
|
#ifdef CONFIG_EFI_LOADER
|
||||||
efi_add_memory_map(gd->fb_base,
|
efi_add_memory_map(gd->fb_base, sunxi_display.fb_size,
|
||||||
ALIGN(sunxi_display.fb_size, EFI_PAGE_SIZE) >>
|
EFI_RESERVED_MEMORY_TYPE);
|
||||||
EFI_PAGE_SHIFT,
|
|
||||||
EFI_RESERVED_MEMORY_TYPE, false);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
fb_dma_addr = gd->fb_base - CONFIG_SYS_SDRAM_BASE;
|
fb_dma_addr = gd->fb_base - CONFIG_SYS_SDRAM_BASE;
|
||||||
|
|
|
@ -545,8 +545,7 @@ efi_status_t efi_get_memory_map(efi_uintn_t *memory_map_size,
|
||||||
efi_uintn_t *descriptor_size,
|
efi_uintn_t *descriptor_size,
|
||||||
uint32_t *descriptor_version);
|
uint32_t *descriptor_version);
|
||||||
/* Adds a range into the EFI memory map */
|
/* Adds a range into the EFI memory map */
|
||||||
efi_status_t efi_add_memory_map(uint64_t start, uint64_t pages, int memory_type,
|
efi_status_t efi_add_memory_map(u64 start, u64 size, int memory_type);
|
||||||
bool overlap_only_ram);
|
|
||||||
/* Adds a conventional range into the EFI memory map */
|
/* Adds a conventional range into the EFI memory map */
|
||||||
efi_status_t efi_add_conventional_memory_map(u64 ram_start, u64 ram_end,
|
efi_status_t efi_add_conventional_memory_map(u64 ram_start, u64 ram_end,
|
||||||
u64 ram_top);
|
u64 ram_top);
|
||||||
|
|
208
include/mm_communication.h
Normal file
208
include/mm_communication.h
Normal file
|
@ -0,0 +1,208 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||||
|
/*
|
||||||
|
* Headers for EFI variable service via StandAloneMM, EDK2 application running
|
||||||
|
* in OP-TEE
|
||||||
|
*
|
||||||
|
* Copyright (c) 2017, Intel Corporation. All rights reserved.
|
||||||
|
* Copyright (C) 2020 Linaro Ltd. <sughosh.ganu@linaro.org>
|
||||||
|
* Copyright (C) 2020 Linaro Ltd. <ilias.apalodimas@linaro.org>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _MM_COMMUNICATION_H_
|
||||||
|
#define _MM_COMMUNICATION_H_
|
||||||
|
|
||||||
|
#include <part_efi.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Interface to the pseudo Trusted Application (TA), which provides a
|
||||||
|
* communication channel with the Standalone MM (Management Mode)
|
||||||
|
* Secure Partition running at Secure-EL0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define PTA_STMM_CMDID_COMMUNICATE 0
|
||||||
|
|
||||||
|
/* OP-TEE is using big endian GUIDs while UEFI uses little endian ones */
|
||||||
|
#define PTA_STMM_UUID { 0xed32d533, 0x99e6, 0x4209, {\
|
||||||
|
0x9c, 0xc0, 0x2d, 0x72, 0xcd, 0xd9, 0x98, 0xa7 } }
|
||||||
|
|
||||||
|
#define EFI_MM_VARIABLE_GUID \
|
||||||
|
EFI_GUID(0xed32d533, 0x99e6, 0x4209, \
|
||||||
|
0x9c, 0xc0, 0x2d, 0x72, 0xcd, 0xd9, 0x98, 0xa7)
|
||||||
|
|
||||||
|
/* Defined in EDK2 MdePkg/Include/Protocol/MmCommunication.h */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct efi_mm_communicate_header - Header used for SMM variable communication
|
||||||
|
|
||||||
|
* @header_guid: header use for disambiguation of content
|
||||||
|
* @message_len: length of the message. Does not include the size of the
|
||||||
|
* header
|
||||||
|
* @data: payload of the message
|
||||||
|
*
|
||||||
|
* Defined in EDK2 as EFI_MM_COMMUNICATE_HEADER.
|
||||||
|
* To avoid confusion in interpreting frames, the communication buffer should
|
||||||
|
* always begin with efi_mm_communicate_header.
|
||||||
|
*/
|
||||||
|
struct efi_mm_communicate_header {
|
||||||
|
efi_guid_t header_guid;
|
||||||
|
size_t message_len;
|
||||||
|
u8 data[];
|
||||||
|
};
|
||||||
|
|
||||||
|
#define MM_COMMUNICATE_HEADER_SIZE \
|
||||||
|
(sizeof(struct efi_mm_communicate_header))
|
||||||
|
|
||||||
|
/* Defined in EDK2 ArmPkg/Include/IndustryStandard/ArmStdSmc.h */
|
||||||
|
|
||||||
|
/* MM return error codes */
|
||||||
|
#define ARM_SMC_MM_RET_SUCCESS 0
|
||||||
|
#define ARM_SMC_MM_RET_NOT_SUPPORTED -1
|
||||||
|
#define ARM_SMC_MM_RET_INVALID_PARAMS -2
|
||||||
|
#define ARM_SMC_MM_RET_DENIED -3
|
||||||
|
#define ARM_SMC_MM_RET_NO_MEMORY -4
|
||||||
|
|
||||||
|
/* Defined in EDK2 MdeModulePkg/Include/Guid/SmmVariableCommon.h */
|
||||||
|
|
||||||
|
#define SMM_VARIABLE_FUNCTION_GET_VARIABLE 1
|
||||||
|
/*
|
||||||
|
* The payload for this function is
|
||||||
|
* SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME.
|
||||||
|
*/
|
||||||
|
#define SMM_VARIABLE_FUNCTION_GET_NEXT_VARIABLE_NAME 2
|
||||||
|
/*
|
||||||
|
* The payload for this function is SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE.
|
||||||
|
*/
|
||||||
|
#define SMM_VARIABLE_FUNCTION_SET_VARIABLE 3
|
||||||
|
/*
|
||||||
|
* The payload for this function is
|
||||||
|
* SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO.
|
||||||
|
*/
|
||||||
|
#define SMM_VARIABLE_FUNCTION_QUERY_VARIABLE_INFO 4
|
||||||
|
/*
|
||||||
|
* It is a notify event, no extra payload for this function.
|
||||||
|
*/
|
||||||
|
#define SMM_VARIABLE_FUNCTION_READY_TO_BOOT 5
|
||||||
|
/*
|
||||||
|
* It is a notify event, no extra payload for this function.
|
||||||
|
*/
|
||||||
|
#define SMM_VARIABLE_FUNCTION_EXIT_BOOT_SERVICE 6
|
||||||
|
/*
|
||||||
|
* The payload for this function is VARIABLE_INFO_ENTRY.
|
||||||
|
* The GUID in EFI_SMM_COMMUNICATE_HEADER is gEfiSmmVariableProtocolGuid.
|
||||||
|
*/
|
||||||
|
#define SMM_VARIABLE_FUNCTION_GET_STATISTICS 7
|
||||||
|
/*
|
||||||
|
* The payload for this function is SMM_VARIABLE_COMMUNICATE_LOCK_VARIABLE
|
||||||
|
*/
|
||||||
|
#define SMM_VARIABLE_FUNCTION_LOCK_VARIABLE 8
|
||||||
|
|
||||||
|
#define SMM_VARIABLE_FUNCTION_VAR_CHECK_VARIABLE_PROPERTY_SET 9
|
||||||
|
|
||||||
|
#define SMM_VARIABLE_FUNCTION_VAR_CHECK_VARIABLE_PROPERTY_GET 10
|
||||||
|
|
||||||
|
#define SMM_VARIABLE_FUNCTION_GET_PAYLOAD_SIZE 11
|
||||||
|
/*
|
||||||
|
* The payload for this function is
|
||||||
|
* SMM_VARIABLE_COMMUNICATE_RUNTIME_VARIABLE_CACHE_CONTEXT
|
||||||
|
*/
|
||||||
|
#define SMM_VARIABLE_FUNCTION_INIT_RUNTIME_VARIABLE_CACHE_CONTEXT 12
|
||||||
|
|
||||||
|
#define SMM_VARIABLE_FUNCTION_SYNC_RUNTIME_CACHE 13
|
||||||
|
/*
|
||||||
|
* The payload for this function is
|
||||||
|
* SMM_VARIABLE_COMMUNICATE_GET_RUNTIME_CACHE_INFO
|
||||||
|
*/
|
||||||
|
#define SMM_VARIABLE_FUNCTION_GET_RUNTIME_CACHE_INFO 14
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct smm_variable_communicate_header - Used for SMM variable communication
|
||||||
|
|
||||||
|
* @function: function to call in Smm.
|
||||||
|
* @ret_status: return status
|
||||||
|
* @data: payload
|
||||||
|
*
|
||||||
|
* Defined in EDK2 as SMM_VARIABLE_COMMUNICATE_HEADER.
|
||||||
|
*/
|
||||||
|
struct smm_variable_communicate_header {
|
||||||
|
efi_uintn_t function;
|
||||||
|
efi_status_t ret_status;
|
||||||
|
u8 data[];
|
||||||
|
};
|
||||||
|
|
||||||
|
#define MM_VARIABLE_COMMUNICATE_SIZE \
|
||||||
|
(sizeof(struct smm_variable_communicate_header))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct smm_variable_access - Used to communicate with StMM by
|
||||||
|
* SetVariable and GetVariable.
|
||||||
|
|
||||||
|
* @guid: vendor GUID
|
||||||
|
* @data_size: size of EFI variable data
|
||||||
|
* @name_size: size of EFI name
|
||||||
|
* @attr: attributes
|
||||||
|
* @name: variable name
|
||||||
|
*
|
||||||
|
* Defined in EDK2 as SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
struct smm_variable_access {
|
||||||
|
efi_guid_t guid;
|
||||||
|
efi_uintn_t data_size;
|
||||||
|
efi_uintn_t name_size;
|
||||||
|
u32 attr;
|
||||||
|
u16 name[];
|
||||||
|
};
|
||||||
|
|
||||||
|
#define MM_VARIABLE_ACCESS_HEADER_SIZE \
|
||||||
|
(sizeof(struct smm_variable_access))
|
||||||
|
/**
|
||||||
|
* struct smm_variable_payload_size - Used to get the max allowed
|
||||||
|
* payload used in StMM.
|
||||||
|
*
|
||||||
|
* @size: size to fill in
|
||||||
|
*
|
||||||
|
* Defined in EDK2 as SMM_VARIABLE_COMMUNICATE_GET_PAYLOAD_SIZE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
struct smm_variable_payload_size {
|
||||||
|
efi_uintn_t size;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct smm_variable_getnext - Used to communicate with StMM for
|
||||||
|
* GetNextVariableName.
|
||||||
|
*
|
||||||
|
* @guid: vendor GUID
|
||||||
|
* @name_size: size of the name of the variable
|
||||||
|
* @name: variable name
|
||||||
|
*
|
||||||
|
* Defined in EDK2 as SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME.
|
||||||
|
*/
|
||||||
|
struct smm_variable_getnext {
|
||||||
|
efi_guid_t guid;
|
||||||
|
efi_uintn_t name_size;
|
||||||
|
u16 name[];
|
||||||
|
};
|
||||||
|
|
||||||
|
#define MM_VARIABLE_GET_NEXT_HEADER_SIZE \
|
||||||
|
(sizeof(struct smm_variable_getnext))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct smm_variable_query_info - Used to communicate with StMM for
|
||||||
|
* QueryVariableInfo.
|
||||||
|
*
|
||||||
|
* @max_variable_storage: max available storage
|
||||||
|
* @remaining_variable_storage: remaining available storage
|
||||||
|
* @max_variable_size: max variable supported size
|
||||||
|
* @attr: attributes to query storage for
|
||||||
|
*
|
||||||
|
* Defined in EDK2 as SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO.
|
||||||
|
*/
|
||||||
|
struct smm_variable_query_info {
|
||||||
|
u64 max_variable_storage;
|
||||||
|
u64 remaining_variable_storage;
|
||||||
|
u64 max_variable_size;
|
||||||
|
u32 attr;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* _MM_COMMUNICATION_H_ */
|
|
@ -164,4 +164,13 @@ config EFI_SECURE_BOOT
|
||||||
it is signed with a trusted key. To do that, you need to install,
|
it is signed with a trusted key. To do that, you need to install,
|
||||||
at least, PK, KEK and db.
|
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
|
endif
|
||||||
|
|
|
@ -35,7 +35,11 @@ obj-y += efi_root_node.o
|
||||||
obj-y += efi_runtime.o
|
obj-y += efi_runtime.o
|
||||||
obj-y += efi_setup.o
|
obj-y += efi_setup.o
|
||||||
obj-$(CONFIG_EFI_UNICODE_COLLATION_PROTOCOL2) += efi_unicode_collation.o
|
obj-$(CONFIG_EFI_UNICODE_COLLATION_PROTOCOL2) += efi_unicode_collation.o
|
||||||
|
ifeq ($(CONFIG_EFI_MM_COMM_TEE),y)
|
||||||
|
obj-y += efi_variable_tee.o
|
||||||
|
else
|
||||||
obj-y += efi_variable.o
|
obj-y += efi_variable.o
|
||||||
|
endif
|
||||||
obj-y += efi_watchdog.o
|
obj-y += efi_watchdog.o
|
||||||
obj-$(CONFIG_LCD) += efi_gop.o
|
obj-$(CONFIG_LCD) += efi_gop.o
|
||||||
obj-$(CONFIG_DM_VIDEO) += efi_gop.o
|
obj-$(CONFIG_DM_VIDEO) += efi_gop.o
|
||||||
|
|
|
@ -229,7 +229,7 @@ static s64 efi_mem_carve_out(struct efi_mem_list *map,
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* efi_add_memory_map() - add memory area to the memory map
|
* efi_add_memory_map_pg() - add pages to the memory map
|
||||||
*
|
*
|
||||||
* @start: start address, must be a multiple of EFI_PAGE_SIZE
|
* @start: start address, must be a multiple of EFI_PAGE_SIZE
|
||||||
* @pages: number of pages to add
|
* @pages: number of pages to add
|
||||||
|
@ -237,8 +237,9 @@ static s64 efi_mem_carve_out(struct efi_mem_list *map,
|
||||||
* @overlap_only_ram: the memory area must overlap existing
|
* @overlap_only_ram: the memory area must overlap existing
|
||||||
* Return: status code
|
* Return: status code
|
||||||
*/
|
*/
|
||||||
efi_status_t efi_add_memory_map(uint64_t start, uint64_t pages, int memory_type,
|
static efi_status_t efi_add_memory_map_pg(u64 start, u64 pages,
|
||||||
bool overlap_only_ram)
|
int memory_type,
|
||||||
|
bool overlap_only_ram)
|
||||||
{
|
{
|
||||||
struct list_head *lhandle;
|
struct list_head *lhandle;
|
||||||
struct efi_mem_list *newlist;
|
struct efi_mem_list *newlist;
|
||||||
|
@ -343,6 +344,28 @@ efi_status_t efi_add_memory_map(uint64_t start, uint64_t pages, int memory_type,
|
||||||
return EFI_SUCCESS;
|
return EFI_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* efi_add_memory_map() - add memory area to the memory map
|
||||||
|
*
|
||||||
|
* @start: start address of the memory area
|
||||||
|
* @size: length in bytes of the memory area
|
||||||
|
* @memory_type: type of memory added
|
||||||
|
*
|
||||||
|
* Return: status code
|
||||||
|
*
|
||||||
|
* This function automatically aligns the start and size of the memory area
|
||||||
|
* to EFI_PAGE_SIZE.
|
||||||
|
*/
|
||||||
|
efi_status_t efi_add_memory_map(u64 start, u64 size, int memory_type)
|
||||||
|
{
|
||||||
|
u64 pages;
|
||||||
|
|
||||||
|
pages = efi_size_in_pages(size + (start & EFI_PAGE_MASK));
|
||||||
|
start &= ~EFI_PAGE_MASK;
|
||||||
|
|
||||||
|
return efi_add_memory_map_pg(start, pages, memory_type, false);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* efi_check_allocated() - validate address to be freed
|
* efi_check_allocated() - validate address to be freed
|
||||||
*
|
*
|
||||||
|
@ -469,7 +492,8 @@ efi_status_t efi_allocate_pages(int type, int memory_type,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reserve that map in our memory maps */
|
/* Reserve that map in our memory maps */
|
||||||
if (efi_add_memory_map(addr, pages, memory_type, true) != EFI_SUCCESS)
|
ret = efi_add_memory_map_pg(addr, pages, memory_type, true);
|
||||||
|
if (ret != EFI_SUCCESS)
|
||||||
/* Map would overlap, bail out */
|
/* Map would overlap, bail out */
|
||||||
return EFI_OUT_OF_RESOURCES;
|
return EFI_OUT_OF_RESOURCES;
|
||||||
|
|
||||||
|
@ -514,7 +538,8 @@ efi_status_t efi_free_pages(uint64_t memory, efi_uintn_t pages)
|
||||||
return EFI_INVALID_PARAMETER;
|
return EFI_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = efi_add_memory_map(memory, pages, EFI_CONVENTIONAL_MEMORY, false);
|
ret = efi_add_memory_map_pg(memory, pages, EFI_CONVENTIONAL_MEMORY,
|
||||||
|
false);
|
||||||
/* Merging of adjacent free regions is missing */
|
/* Merging of adjacent free regions is missing */
|
||||||
|
|
||||||
if (ret != EFI_SUCCESS)
|
if (ret != EFI_SUCCESS)
|
||||||
|
@ -680,8 +705,8 @@ efi_status_t efi_add_conventional_memory_map(u64 ram_start, u64 ram_end,
|
||||||
|
|
||||||
pages = (ram_end - ram_start) >> EFI_PAGE_SHIFT;
|
pages = (ram_end - ram_start) >> EFI_PAGE_SHIFT;
|
||||||
|
|
||||||
efi_add_memory_map(ram_start, pages,
|
efi_add_memory_map_pg(ram_start, pages,
|
||||||
EFI_CONVENTIONAL_MEMORY, false);
|
EFI_CONVENTIONAL_MEMORY, false);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Boards may indicate to the U-Boot memory core that they
|
* Boards may indicate to the U-Boot memory core that they
|
||||||
|
@ -691,14 +716,14 @@ efi_status_t efi_add_conventional_memory_map(u64 ram_start, u64 ram_end,
|
||||||
*/
|
*/
|
||||||
if (ram_top < ram_start) {
|
if (ram_top < ram_start) {
|
||||||
/* ram_top is before this region, reserve all */
|
/* ram_top is before this region, reserve all */
|
||||||
efi_add_memory_map(ram_start, pages,
|
efi_add_memory_map_pg(ram_start, pages,
|
||||||
EFI_BOOT_SERVICES_DATA, true);
|
EFI_BOOT_SERVICES_DATA, true);
|
||||||
} else if ((ram_top >= ram_start) && (ram_top < ram_end)) {
|
} else if ((ram_top >= ram_start) && (ram_top < ram_end)) {
|
||||||
/* ram_top is inside this region, reserve parts */
|
/* ram_top is inside this region, reserve parts */
|
||||||
pages = (ram_end - ram_top) >> EFI_PAGE_SHIFT;
|
pages = (ram_end - ram_top) >> EFI_PAGE_SHIFT;
|
||||||
|
|
||||||
efi_add_memory_map(ram_top, pages,
|
efi_add_memory_map_pg(ram_top, pages,
|
||||||
EFI_BOOT_SERVICES_DATA, true);
|
EFI_BOOT_SERVICES_DATA, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
return EFI_SUCCESS;
|
return EFI_SUCCESS;
|
||||||
|
@ -743,7 +768,8 @@ static void add_u_boot_and_runtime(void)
|
||||||
uboot_stack_size) & ~EFI_PAGE_MASK;
|
uboot_stack_size) & ~EFI_PAGE_MASK;
|
||||||
uboot_pages = ((uintptr_t)map_sysmem(gd->ram_top - 1, 0) -
|
uboot_pages = ((uintptr_t)map_sysmem(gd->ram_top - 1, 0) -
|
||||||
uboot_start + EFI_PAGE_MASK) >> EFI_PAGE_SHIFT;
|
uboot_start + EFI_PAGE_MASK) >> EFI_PAGE_SHIFT;
|
||||||
efi_add_memory_map(uboot_start, uboot_pages, EFI_LOADER_DATA, false);
|
efi_add_memory_map_pg(uboot_start, uboot_pages, EFI_LOADER_DATA,
|
||||||
|
false);
|
||||||
|
|
||||||
#if defined(__aarch64__)
|
#if defined(__aarch64__)
|
||||||
/*
|
/*
|
||||||
|
@ -762,8 +788,8 @@ static void add_u_boot_and_runtime(void)
|
||||||
runtime_end = (ulong)&__efi_runtime_stop;
|
runtime_end = (ulong)&__efi_runtime_stop;
|
||||||
runtime_end = (runtime_end + runtime_mask) & ~runtime_mask;
|
runtime_end = (runtime_end + runtime_mask) & ~runtime_mask;
|
||||||
runtime_pages = (runtime_end - runtime_start) >> EFI_PAGE_SHIFT;
|
runtime_pages = (runtime_end - runtime_start) >> EFI_PAGE_SHIFT;
|
||||||
efi_add_memory_map(runtime_start, runtime_pages,
|
efi_add_memory_map_pg(runtime_start, runtime_pages,
|
||||||
EFI_RUNTIME_SERVICES_CODE, false);
|
EFI_RUNTIME_SERVICES_CODE, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
int efi_memory_init(void)
|
int efi_memory_init(void)
|
||||||
|
|
|
@ -784,11 +784,10 @@ out:
|
||||||
efi_status_t efi_add_runtime_mmio(void *mmio_ptr, u64 len)
|
efi_status_t efi_add_runtime_mmio(void *mmio_ptr, u64 len)
|
||||||
{
|
{
|
||||||
struct efi_runtime_mmio_list *newmmio;
|
struct efi_runtime_mmio_list *newmmio;
|
||||||
u64 pages = (len + EFI_PAGE_MASK) >> EFI_PAGE_SHIFT;
|
|
||||||
uint64_t addr = *(uintptr_t *)mmio_ptr;
|
uint64_t addr = *(uintptr_t *)mmio_ptr;
|
||||||
efi_status_t ret;
|
efi_status_t ret;
|
||||||
|
|
||||||
ret = efi_add_memory_map(addr, pages, EFI_MMAP_IO, false);
|
ret = efi_add_memory_map(addr, len, EFI_MMAP_IO);
|
||||||
if (ret != EFI_SUCCESS)
|
if (ret != EFI_SUCCESS)
|
||||||
return EFI_OUT_OF_RESOURCES;
|
return EFI_OUT_OF_RESOURCES;
|
||||||
|
|
||||||
|
|
662
lib/efi_loader/efi_variable_tee.c
Normal file
662
lib/efi_loader/efi_variable_tee.c
Normal file
|
@ -0,0 +1,662 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0+
|
||||||
|
/*
|
||||||
|
* EFI variable service via OP-TEE
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 Linaro Ltd. <sughosh.ganu@linaro.org>
|
||||||
|
* Copyright (C) 2019 Linaro Ltd. <ilias.apalodimas@linaro.org>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <common.h>
|
||||||
|
#include <efi.h>
|
||||||
|
#include <efi_api.h>
|
||||||
|
#include <efi_loader.h>
|
||||||
|
#include <tee.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
#include <mm_communication.h>
|
||||||
|
|
||||||
|
static efi_uintn_t max_buffer_size; /* comm + var + func + data */
|
||||||
|
static efi_uintn_t max_payload_size; /* func + data */
|
||||||
|
|
||||||
|
struct mm_connection {
|
||||||
|
struct udevice *tee;
|
||||||
|
u32 session;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get_connection() - Retrieve OP-TEE session for a specific UUID.
|
||||||
|
*
|
||||||
|
* @conn: session buffer to fill
|
||||||
|
* Return: status code
|
||||||
|
*/
|
||||||
|
static int get_connection(struct mm_connection *conn)
|
||||||
|
{
|
||||||
|
static const struct tee_optee_ta_uuid uuid = PTA_STMM_UUID;
|
||||||
|
struct udevice *tee = NULL;
|
||||||
|
struct tee_open_session_arg arg;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
tee = tee_find_device(tee, NULL, NULL, NULL);
|
||||||
|
if (!tee)
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
memset(&arg, 0, sizeof(arg));
|
||||||
|
tee_optee_ta_uuid_to_octets(arg.uuid, &uuid);
|
||||||
|
rc = tee_open_session(tee, &arg, 0, NULL);
|
||||||
|
if (!rc) {
|
||||||
|
conn->tee = tee;
|
||||||
|
conn->session = arg.session;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* optee_mm_communicate() - Pass a buffer to StandaloneMM running in OP-TEE
|
||||||
|
*
|
||||||
|
* @comm_buf: locally allocted communcation buffer
|
||||||
|
* @dsize: buffer size
|
||||||
|
* Return: status code
|
||||||
|
*/
|
||||||
|
static efi_status_t optee_mm_communicate(void *comm_buf, ulong dsize)
|
||||||
|
{
|
||||||
|
ulong buf_size;
|
||||||
|
efi_status_t ret;
|
||||||
|
struct efi_mm_communicate_header *mm_hdr;
|
||||||
|
struct mm_connection conn = { NULL, 0 };
|
||||||
|
struct tee_invoke_arg arg;
|
||||||
|
struct tee_param param[2];
|
||||||
|
struct tee_shm *shm = NULL;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
if (!comm_buf)
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
|
||||||
|
mm_hdr = (struct efi_mm_communicate_header *)comm_buf;
|
||||||
|
buf_size = mm_hdr->message_len + sizeof(efi_guid_t) + sizeof(size_t);
|
||||||
|
|
||||||
|
if (dsize != buf_size)
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
|
||||||
|
rc = get_connection(&conn);
|
||||||
|
if (rc) {
|
||||||
|
log_err("Unable to open OP-TEE session (err=%d)\n", rc);
|
||||||
|
return EFI_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tee_shm_register(conn.tee, comm_buf, buf_size, 0, &shm)) {
|
||||||
|
log_err("Unable to register shared memory\n");
|
||||||
|
return EFI_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&arg, 0, sizeof(arg));
|
||||||
|
arg.func = PTA_STMM_CMDID_COMMUNICATE;
|
||||||
|
arg.session = conn.session;
|
||||||
|
|
||||||
|
memset(param, 0, sizeof(param));
|
||||||
|
param[0].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INOUT;
|
||||||
|
param[0].u.memref.size = buf_size;
|
||||||
|
param[0].u.memref.shm = shm;
|
||||||
|
param[1].attr = TEE_PARAM_ATTR_TYPE_VALUE_OUTPUT;
|
||||||
|
|
||||||
|
rc = tee_invoke_func(conn.tee, &arg, 2, param);
|
||||||
|
if (rc)
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
tee_shm_free(shm);
|
||||||
|
tee_close_session(conn.tee, conn.session);
|
||||||
|
|
||||||
|
switch (param[1].u.value.a) {
|
||||||
|
case ARM_SMC_MM_RET_SUCCESS:
|
||||||
|
ret = EFI_SUCCESS;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ARM_SMC_MM_RET_INVALID_PARAMS:
|
||||||
|
ret = EFI_INVALID_PARAMETER;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ARM_SMC_MM_RET_DENIED:
|
||||||
|
ret = EFI_ACCESS_DENIED;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ARM_SMC_MM_RET_NO_MEMORY:
|
||||||
|
ret = EFI_OUT_OF_RESOURCES;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
ret = EFI_ACCESS_DENIED;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mm_communicate() - Adjust the cmonnucation buffer to StandAlonneMM and send
|
||||||
|
* it to OP-TEE
|
||||||
|
*
|
||||||
|
* @comm_buf: locally allocted communcation buffer
|
||||||
|
* @dsize: buffer size
|
||||||
|
* Return: status code
|
||||||
|
*/
|
||||||
|
static efi_status_t mm_communicate(u8 *comm_buf, efi_uintn_t dsize)
|
||||||
|
{
|
||||||
|
efi_status_t ret;
|
||||||
|
struct efi_mm_communicate_header *mm_hdr;
|
||||||
|
struct smm_variable_communicate_header *var_hdr;
|
||||||
|
|
||||||
|
dsize += MM_COMMUNICATE_HEADER_SIZE + MM_VARIABLE_COMMUNICATE_SIZE;
|
||||||
|
mm_hdr = (struct efi_mm_communicate_header *)comm_buf;
|
||||||
|
var_hdr = (struct smm_variable_communicate_header *)mm_hdr->data;
|
||||||
|
|
||||||
|
ret = optee_mm_communicate(comm_buf, dsize);
|
||||||
|
if (ret != EFI_SUCCESS) {
|
||||||
|
log_err("%s failed!\n", __func__);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return var_hdr->ret_status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* setup_mm_hdr() - Allocate a buffer for StandAloneMM and initialize the
|
||||||
|
* header data.
|
||||||
|
*
|
||||||
|
* @dptr: pointer address of the corresponding StandAloneMM
|
||||||
|
* function
|
||||||
|
* @payload_size: buffer size
|
||||||
|
* @func: standAloneMM function number
|
||||||
|
* @ret: EFI return code
|
||||||
|
* Return: buffer or NULL
|
||||||
|
*/
|
||||||
|
static u8 *setup_mm_hdr(void **dptr, efi_uintn_t payload_size,
|
||||||
|
efi_uintn_t func, efi_status_t *ret)
|
||||||
|
{
|
||||||
|
const efi_guid_t mm_var_guid = EFI_MM_VARIABLE_GUID;
|
||||||
|
struct efi_mm_communicate_header *mm_hdr;
|
||||||
|
struct smm_variable_communicate_header *var_hdr;
|
||||||
|
u8 *comm_buf;
|
||||||
|
|
||||||
|
/* In the init function we initialize max_buffer_size with
|
||||||
|
* get_max_payload(). So skip the test if max_buffer_size is initialized
|
||||||
|
* StandAloneMM will perform similar checks and drop the buffer if it's
|
||||||
|
* too long
|
||||||
|
*/
|
||||||
|
if (max_buffer_size && max_buffer_size <
|
||||||
|
(MM_COMMUNICATE_HEADER_SIZE +
|
||||||
|
MM_VARIABLE_COMMUNICATE_SIZE +
|
||||||
|
payload_size)) {
|
||||||
|
*ret = EFI_INVALID_PARAMETER;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
comm_buf = calloc(1, MM_COMMUNICATE_HEADER_SIZE +
|
||||||
|
MM_VARIABLE_COMMUNICATE_SIZE +
|
||||||
|
payload_size);
|
||||||
|
if (!comm_buf) {
|
||||||
|
*ret = EFI_OUT_OF_RESOURCES;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
mm_hdr = (struct efi_mm_communicate_header *)comm_buf;
|
||||||
|
guidcpy(&mm_hdr->header_guid, &mm_var_guid);
|
||||||
|
mm_hdr->message_len = MM_VARIABLE_COMMUNICATE_SIZE + payload_size;
|
||||||
|
|
||||||
|
var_hdr = (struct smm_variable_communicate_header *)mm_hdr->data;
|
||||||
|
var_hdr->function = func;
|
||||||
|
if (dptr)
|
||||||
|
*dptr = var_hdr->data;
|
||||||
|
*ret = EFI_SUCCESS;
|
||||||
|
|
||||||
|
return comm_buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get_max_payload() - Get variable payload size from StandAloneMM.
|
||||||
|
*
|
||||||
|
* @size: size of the variable in storage
|
||||||
|
* Return: status code
|
||||||
|
*/
|
||||||
|
efi_status_t EFIAPI get_max_payload(efi_uintn_t *size)
|
||||||
|
{
|
||||||
|
struct smm_variable_payload_size *var_payload = NULL;
|
||||||
|
efi_uintn_t payload_size;
|
||||||
|
u8 *comm_buf = NULL;
|
||||||
|
efi_status_t ret;
|
||||||
|
|
||||||
|
if (!size) {
|
||||||
|
ret = EFI_INVALID_PARAMETER;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
payload_size = sizeof(*var_payload);
|
||||||
|
comm_buf = setup_mm_hdr((void **)&var_payload, payload_size,
|
||||||
|
SMM_VARIABLE_FUNCTION_GET_PAYLOAD_SIZE, &ret);
|
||||||
|
if (!comm_buf)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
ret = mm_communicate(comm_buf, payload_size);
|
||||||
|
if (ret != EFI_SUCCESS)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
*size = var_payload->size;
|
||||||
|
|
||||||
|
out:
|
||||||
|
free(comm_buf);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* efi_get_variable() - retrieve value of a UEFI variable
|
||||||
|
*
|
||||||
|
* This function implements the GetVariable runtime service.
|
||||||
|
*
|
||||||
|
* See the Unified Extensible Firmware Interface (UEFI) specification for
|
||||||
|
* details.
|
||||||
|
*
|
||||||
|
* @name: name of the variable
|
||||||
|
* @guid: vendor GUID
|
||||||
|
* @attr: attributes of the variable
|
||||||
|
* @data_size: size of the buffer to which the variable value is copied
|
||||||
|
* @data: buffer to which the variable value is copied
|
||||||
|
* Return: status code
|
||||||
|
*/
|
||||||
|
efi_status_t EFIAPI efi_get_variable(u16 *name, const efi_guid_t *guid,
|
||||||
|
u32 *attr, efi_uintn_t *data_size,
|
||||||
|
void *data)
|
||||||
|
{
|
||||||
|
struct smm_variable_access *var_acc;
|
||||||
|
efi_uintn_t payload_size;
|
||||||
|
efi_uintn_t name_size;
|
||||||
|
efi_uintn_t tmp_dsize;
|
||||||
|
u8 *comm_buf = NULL;
|
||||||
|
efi_status_t ret;
|
||||||
|
|
||||||
|
EFI_ENTRY("\"%ls\" %pUl %p %p %p", name, guid, attr, data_size, data);
|
||||||
|
|
||||||
|
if (!name || !guid || !data_size) {
|
||||||
|
ret = EFI_INVALID_PARAMETER;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check payload size */
|
||||||
|
name_size = u16_strsize(name);
|
||||||
|
if (name_size > max_payload_size - MM_VARIABLE_ACCESS_HEADER_SIZE) {
|
||||||
|
ret = EFI_INVALID_PARAMETER;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Trim output buffer size */
|
||||||
|
tmp_dsize = *data_size;
|
||||||
|
if (name_size + tmp_dsize >
|
||||||
|
max_payload_size - MM_VARIABLE_ACCESS_HEADER_SIZE) {
|
||||||
|
tmp_dsize = max_payload_size -
|
||||||
|
MM_VARIABLE_ACCESS_HEADER_SIZE -
|
||||||
|
name_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get communication buffer and initialize header */
|
||||||
|
payload_size = MM_VARIABLE_ACCESS_HEADER_SIZE + name_size + tmp_dsize;
|
||||||
|
comm_buf = setup_mm_hdr((void **)&var_acc, payload_size,
|
||||||
|
SMM_VARIABLE_FUNCTION_GET_VARIABLE, &ret);
|
||||||
|
if (!comm_buf)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
/* Fill in contents */
|
||||||
|
guidcpy(&var_acc->guid, guid);
|
||||||
|
var_acc->data_size = tmp_dsize;
|
||||||
|
var_acc->name_size = name_size;
|
||||||
|
var_acc->attr = attr ? *attr : 0;
|
||||||
|
memcpy(var_acc->name, name, name_size);
|
||||||
|
|
||||||
|
/* Communicate */
|
||||||
|
ret = mm_communicate(comm_buf, payload_size);
|
||||||
|
if (ret == EFI_SUCCESS || ret == EFI_BUFFER_TOO_SMALL) {
|
||||||
|
/* Update with reported data size for trimmed case */
|
||||||
|
*data_size = var_acc->data_size;
|
||||||
|
}
|
||||||
|
if (ret != EFI_SUCCESS)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
if (attr)
|
||||||
|
*attr = var_acc->attr;
|
||||||
|
if (data)
|
||||||
|
memcpy(data, (u8 *)var_acc->name + var_acc->name_size,
|
||||||
|
var_acc->data_size);
|
||||||
|
else
|
||||||
|
ret = EFI_INVALID_PARAMETER;
|
||||||
|
|
||||||
|
out:
|
||||||
|
free(comm_buf);
|
||||||
|
return EFI_EXIT(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* efi_get_next_variable_name() - enumerate the current variable names
|
||||||
|
*
|
||||||
|
* @variable_name_size: size of variable_name buffer in bytes
|
||||||
|
* @variable_name: name of uefi variable's name in u16
|
||||||
|
* @guid: vendor's guid
|
||||||
|
*
|
||||||
|
* This function implements the GetNextVariableName service.
|
||||||
|
*
|
||||||
|
* See the Unified Extensible Firmware Interface (UEFI) specification for
|
||||||
|
* details.
|
||||||
|
*
|
||||||
|
* Return: status code
|
||||||
|
*/
|
||||||
|
efi_status_t EFIAPI efi_get_next_variable_name(efi_uintn_t *variable_name_size,
|
||||||
|
u16 *variable_name,
|
||||||
|
efi_guid_t *guid)
|
||||||
|
{
|
||||||
|
struct smm_variable_getnext *var_getnext;
|
||||||
|
efi_uintn_t payload_size;
|
||||||
|
efi_uintn_t out_name_size;
|
||||||
|
efi_uintn_t in_name_size;
|
||||||
|
efi_uintn_t tmp_dsize;
|
||||||
|
efi_uintn_t name_size;
|
||||||
|
u8 *comm_buf = NULL;
|
||||||
|
efi_status_t ret;
|
||||||
|
|
||||||
|
EFI_ENTRY("%p \"%ls\" %pUl", variable_name_size, variable_name, guid);
|
||||||
|
|
||||||
|
if (!variable_name_size || !variable_name || !guid) {
|
||||||
|
ret = EFI_INVALID_PARAMETER;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
out_name_size = *variable_name_size;
|
||||||
|
in_name_size = u16_strsize(variable_name);
|
||||||
|
|
||||||
|
if (out_name_size < in_name_size) {
|
||||||
|
ret = EFI_INVALID_PARAMETER;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
name_size = u16_strsize(variable_name);
|
||||||
|
if (name_size > max_payload_size - MM_VARIABLE_GET_NEXT_HEADER_SIZE) {
|
||||||
|
ret = EFI_INVALID_PARAMETER;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Trim output buffer size */
|
||||||
|
tmp_dsize = *variable_name_size;
|
||||||
|
if (name_size + tmp_dsize >
|
||||||
|
max_payload_size - MM_VARIABLE_GET_NEXT_HEADER_SIZE) {
|
||||||
|
tmp_dsize = max_payload_size -
|
||||||
|
MM_VARIABLE_GET_NEXT_HEADER_SIZE -
|
||||||
|
name_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
payload_size = MM_VARIABLE_GET_NEXT_HEADER_SIZE + out_name_size;
|
||||||
|
comm_buf = setup_mm_hdr((void **)&var_getnext, payload_size,
|
||||||
|
SMM_VARIABLE_FUNCTION_GET_NEXT_VARIABLE_NAME,
|
||||||
|
&ret);
|
||||||
|
if (!comm_buf)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
/* Fill in contents */
|
||||||
|
guidcpy(&var_getnext->guid, guid);
|
||||||
|
var_getnext->name_size = out_name_size;
|
||||||
|
memcpy(var_getnext->name, variable_name, in_name_size);
|
||||||
|
memset((u8 *)var_getnext->name + in_name_size, 0x0,
|
||||||
|
out_name_size - in_name_size);
|
||||||
|
|
||||||
|
/* Communicate */
|
||||||
|
ret = mm_communicate(comm_buf, payload_size);
|
||||||
|
if (ret == EFI_SUCCESS || ret == EFI_BUFFER_TOO_SMALL) {
|
||||||
|
/* Update with reported data size for trimmed case */
|
||||||
|
*variable_name_size = var_getnext->name_size;
|
||||||
|
}
|
||||||
|
if (ret != EFI_SUCCESS)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
guidcpy(guid, &var_getnext->guid);
|
||||||
|
memcpy(variable_name, (u8 *)var_getnext->name,
|
||||||
|
var_getnext->name_size);
|
||||||
|
|
||||||
|
out:
|
||||||
|
free(comm_buf);
|
||||||
|
return EFI_EXIT(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* efi_set_variable() - set value of a UEFI variable
|
||||||
|
*
|
||||||
|
* This function implements the SetVariable runtime service.
|
||||||
|
*
|
||||||
|
* See the Unified Extensible Firmware Interface (UEFI) specification for
|
||||||
|
* details.
|
||||||
|
*
|
||||||
|
* @name: name of the variable
|
||||||
|
* @guid: vendor GUID
|
||||||
|
* @attr: attributes of the variable
|
||||||
|
* @data_size: size of the buffer with the variable value
|
||||||
|
* @data: buffer with the variable value
|
||||||
|
* Return: status code
|
||||||
|
*/
|
||||||
|
efi_status_t EFIAPI efi_set_variable(u16 *name, const efi_guid_t *guid,
|
||||||
|
u32 attr, efi_uintn_t data_size,
|
||||||
|
const void *data)
|
||||||
|
{
|
||||||
|
struct smm_variable_access *var_acc;
|
||||||
|
efi_uintn_t payload_size;
|
||||||
|
efi_uintn_t name_size;
|
||||||
|
u8 *comm_buf = NULL;
|
||||||
|
efi_status_t ret;
|
||||||
|
|
||||||
|
EFI_ENTRY("\"%ls\" %pUl %x %zu %p", name, guid, attr, data_size, data);
|
||||||
|
|
||||||
|
if (!name || name[0] == 0 || !guid) {
|
||||||
|
ret = EFI_INVALID_PARAMETER;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if (data_size > 0 && !data) {
|
||||||
|
ret = EFI_INVALID_PARAMETER;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check payload size */
|
||||||
|
name_size = u16_strsize(name);
|
||||||
|
payload_size = MM_VARIABLE_ACCESS_HEADER_SIZE + name_size + data_size;
|
||||||
|
if (payload_size > max_payload_size) {
|
||||||
|
ret = EFI_INVALID_PARAMETER;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get communication buffer and initialize header */
|
||||||
|
comm_buf = setup_mm_hdr((void **)&var_acc, payload_size,
|
||||||
|
SMM_VARIABLE_FUNCTION_SET_VARIABLE, &ret);
|
||||||
|
if (!comm_buf)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
/* Fill in contents */
|
||||||
|
guidcpy(&var_acc->guid, guid);
|
||||||
|
var_acc->data_size = data_size;
|
||||||
|
var_acc->name_size = name_size;
|
||||||
|
var_acc->attr = attr;
|
||||||
|
memcpy(var_acc->name, name, name_size);
|
||||||
|
memcpy((u8 *)var_acc->name + name_size, data, data_size);
|
||||||
|
|
||||||
|
/* Communicate */
|
||||||
|
ret = mm_communicate(comm_buf, payload_size);
|
||||||
|
|
||||||
|
out:
|
||||||
|
free(comm_buf);
|
||||||
|
return EFI_EXIT(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* efi_query_variable_info() - get information about EFI variables
|
||||||
|
*
|
||||||
|
* This function implements the QueryVariableInfo() runtime service.
|
||||||
|
*
|
||||||
|
* See the Unified Extensible Firmware Interface (UEFI) specification for
|
||||||
|
* details.
|
||||||
|
*
|
||||||
|
* @attributes: bitmask to select variables to be
|
||||||
|
* queried
|
||||||
|
* @maximum_variable_storage_size: maximum size of storage area for the
|
||||||
|
* selected variable types
|
||||||
|
* @remaining_variable_storage_size: remaining size of storage are for the
|
||||||
|
* selected variable types
|
||||||
|
* @maximum_variable_size: maximum size of a variable of the
|
||||||
|
* selected type
|
||||||
|
* Returns: status code
|
||||||
|
*/
|
||||||
|
efi_status_t EFIAPI __efi_runtime
|
||||||
|
efi_query_variable_info(u32 attributes, u64 *max_variable_storage_size,
|
||||||
|
u64 *remain_variable_storage_size,
|
||||||
|
u64 *max_variable_size)
|
||||||
|
{
|
||||||
|
struct smm_variable_query_info *mm_query_info;
|
||||||
|
efi_uintn_t payload_size;
|
||||||
|
efi_status_t ret;
|
||||||
|
u8 *comm_buf;
|
||||||
|
|
||||||
|
EFI_ENTRY("%x %p %p %p", attributes, max_variable_storage_size,
|
||||||
|
remain_variable_storage_size, max_variable_size);
|
||||||
|
|
||||||
|
payload_size = sizeof(*mm_query_info);
|
||||||
|
comm_buf = setup_mm_hdr((void **)&mm_query_info, payload_size,
|
||||||
|
SMM_VARIABLE_FUNCTION_QUERY_VARIABLE_INFO,
|
||||||
|
&ret);
|
||||||
|
if (!comm_buf)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
mm_query_info->attr = attributes;
|
||||||
|
ret = mm_communicate(comm_buf, payload_size);
|
||||||
|
if (ret != EFI_SUCCESS)
|
||||||
|
goto out;
|
||||||
|
*max_variable_storage_size = mm_query_info->max_variable_storage;
|
||||||
|
*remain_variable_storage_size =
|
||||||
|
mm_query_info->remaining_variable_storage;
|
||||||
|
*max_variable_size = mm_query_info->max_variable_size;
|
||||||
|
|
||||||
|
out:
|
||||||
|
free(comm_buf);
|
||||||
|
return EFI_EXIT(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* efi_get_variable_runtime() - runtime implementation of GetVariable()
|
||||||
|
*
|
||||||
|
* @variable_name: name of the variable
|
||||||
|
* @guid: vendor GUID
|
||||||
|
* @attributes: attributes of the variable
|
||||||
|
* @data_size: size of the buffer to which the variable value is copied
|
||||||
|
* @data: buffer to which the variable value is copied
|
||||||
|
* Return: status code
|
||||||
|
*/
|
||||||
|
static efi_status_t __efi_runtime EFIAPI
|
||||||
|
efi_get_variable_runtime(u16 *variable_name, const efi_guid_t *guid,
|
||||||
|
u32 *attributes, efi_uintn_t *data_size, void *data)
|
||||||
|
{
|
||||||
|
return EFI_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* efi_get_next_variable_name_runtime() - runtime implementation of
|
||||||
|
* GetNextVariable()
|
||||||
|
*
|
||||||
|
* @variable_name_size: size of variable_name buffer in byte
|
||||||
|
* @variable_name: name of uefi variable's name in u16
|
||||||
|
* @guid: vendor's guid
|
||||||
|
* Return: status code
|
||||||
|
*/
|
||||||
|
static efi_status_t __efi_runtime EFIAPI
|
||||||
|
efi_get_next_variable_name_runtime(efi_uintn_t *variable_name_size,
|
||||||
|
u16 *variable_name, efi_guid_t *guid)
|
||||||
|
{
|
||||||
|
return EFI_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* efi_query_variable_info() - get information about EFI variables
|
||||||
|
*
|
||||||
|
* This function implements the QueryVariableInfo() runtime service.
|
||||||
|
*
|
||||||
|
* See the Unified Extensible Firmware Interface (UEFI) specification for
|
||||||
|
* details.
|
||||||
|
*
|
||||||
|
* @attributes: bitmask to select variables to be
|
||||||
|
* queried
|
||||||
|
* @maximum_variable_storage_size: maximum size of storage area for the
|
||||||
|
* selected variable types
|
||||||
|
* @remaining_variable_storage_size: remaining size of storage are for the
|
||||||
|
* selected variable types
|
||||||
|
* @maximum_variable_size: maximum size of a variable of the
|
||||||
|
* selected type
|
||||||
|
* Return: status code
|
||||||
|
*/
|
||||||
|
efi_status_t EFIAPI __efi_runtime
|
||||||
|
efi_query_variable_info_runtime(u32 attributes, u64 *max_variable_storage_size,
|
||||||
|
u64 *remain_variable_storage_size,
|
||||||
|
u64 *max_variable_size)
|
||||||
|
{
|
||||||
|
return EFI_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* efi_set_variable_runtime() - runtime implementation of SetVariable()
|
||||||
|
*
|
||||||
|
* @variable_name: name of the variable
|
||||||
|
* @guid: vendor GUID
|
||||||
|
* @attributes: attributes of the variable
|
||||||
|
* @data_size: size of the buffer with the variable value
|
||||||
|
* @data: buffer with the variable value
|
||||||
|
* Return: status code
|
||||||
|
*/
|
||||||
|
static efi_status_t __efi_runtime EFIAPI
|
||||||
|
efi_set_variable_runtime(u16 *variable_name, const efi_guid_t *guid,
|
||||||
|
u32 attributes, efi_uintn_t data_size,
|
||||||
|
const void *data)
|
||||||
|
{
|
||||||
|
return EFI_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* efi_variables_boot_exit_notify() - notify ExitBootServices() is called
|
||||||
|
*/
|
||||||
|
void efi_variables_boot_exit_notify(void)
|
||||||
|
{
|
||||||
|
u8 *comm_buf;
|
||||||
|
efi_status_t ret;
|
||||||
|
|
||||||
|
comm_buf = setup_mm_hdr(NULL, 0,
|
||||||
|
SMM_VARIABLE_FUNCTION_EXIT_BOOT_SERVICE, &ret);
|
||||||
|
if (comm_buf)
|
||||||
|
ret = mm_communicate(comm_buf, 0);
|
||||||
|
else
|
||||||
|
ret = EFI_NOT_FOUND;
|
||||||
|
|
||||||
|
if (ret != EFI_SUCCESS)
|
||||||
|
log_err("Unable to notify StMM for ExitBootServices\n");
|
||||||
|
free(comm_buf);
|
||||||
|
|
||||||
|
/* Update runtime service table */
|
||||||
|
efi_runtime_services.query_variable_info =
|
||||||
|
efi_query_variable_info_runtime;
|
||||||
|
efi_runtime_services.get_variable = efi_get_variable_runtime;
|
||||||
|
efi_runtime_services.get_next_variable_name =
|
||||||
|
efi_get_next_variable_name_runtime;
|
||||||
|
efi_runtime_services.set_variable = efi_set_variable_runtime;
|
||||||
|
efi_update_table_header_crc32(&efi_runtime_services.hdr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* efi_init_variables() - initialize variable services
|
||||||
|
*
|
||||||
|
* Return: status code
|
||||||
|
*/
|
||||||
|
efi_status_t efi_init_variables(void)
|
||||||
|
{
|
||||||
|
efi_status_t ret;
|
||||||
|
|
||||||
|
ret = get_max_payload(&max_payload_size);
|
||||||
|
if (ret != EFI_SUCCESS)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
max_buffer_size = MM_COMMUNICATE_HEADER_SIZE +
|
||||||
|
MM_VARIABLE_COMMUNICATE_SIZE +
|
||||||
|
max_payload_size;
|
||||||
|
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue