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
@ -635,6 +635,12 @@ F: cmd/efidebug.c
|
||||
F: cmd/nvedit_efi.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
|
||||
M: Joe Hershberger <joe.hershberger@ni.com>
|
||||
R: Wolfgang Denk <wd@denx.de>
|
||||
|
@ -1529,9 +1529,8 @@ int dram_init_banksize(void)
|
||||
void efi_add_known_memory(void)
|
||||
{
|
||||
int i;
|
||||
phys_addr_t ram_start, start;
|
||||
phys_addr_t ram_start;
|
||||
phys_size_t ram_size;
|
||||
u64 pages;
|
||||
|
||||
/* Add RAM */
|
||||
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)
|
||||
ram_size = gd->arch.resv_ram - ram_start;
|
||||
#endif
|
||||
start = (ram_start + EFI_PAGE_MASK) & ~EFI_PAGE_MASK;
|
||||
pages = (ram_size + EFI_PAGE_MASK) >> EFI_PAGE_SHIFT;
|
||||
|
||||
efi_add_memory_map(start, pages, EFI_CONVENTIONAL_MEMORY,
|
||||
false);
|
||||
efi_add_memory_map(ram_start, ram_size,
|
||||
EFI_CONVENTIONAL_MEMORY);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -146,9 +146,8 @@ remove_psci_node:
|
||||
fdt_add_mem_rsv(blob, (uintptr_t)&secondary_boot_code,
|
||||
*boot_code_size);
|
||||
#if CONFIG_IS_ENABLED(EFI_LOADER)
|
||||
efi_add_memory_map((uintptr_t)&secondary_boot_code,
|
||||
ALIGN(*boot_code_size, EFI_PAGE_SIZE) >> EFI_PAGE_SHIFT,
|
||||
EFI_RESERVED_MEMORY_TYPE, false);
|
||||
efi_add_memory_map((uintptr_t)&secondary_boot_code, *boot_code_size,
|
||||
EFI_RESERVED_MEMORY_TYPE);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
@ -428,4 +428,10 @@
|
||||
#size-cells = <0>;
|
||||
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)
|
||||
printf("Could not reserve zone @ 0x%llx\n", start);
|
||||
|
||||
if (IS_ENABLED(CONFIG_EFI_LOADER)) {
|
||||
efi_add_memory_map(start,
|
||||
ALIGN(size, EFI_PAGE_SIZE) >> EFI_PAGE_SHIFT,
|
||||
EFI_RESERVED_MEMORY_TYPE, false);
|
||||
}
|
||||
if (IS_ENABLED(CONFIG_EFI_LOADER))
|
||||
efi_add_memory_map(start, size, EFI_RESERVED_MEMORY_TYPE);
|
||||
}
|
||||
|
||||
int meson_generate_serial_ethaddr(void)
|
||||
|
@ -41,7 +41,7 @@ void efi_add_known_memory(void)
|
||||
{
|
||||
struct e820_entry e820[E820MAX];
|
||||
unsigned int i, num;
|
||||
u64 start, pages, ram_top;
|
||||
u64 start, ram_top;
|
||||
int type;
|
||||
|
||||
num = install_e820_map(ARRAY_SIZE(e820), e820);
|
||||
@ -77,9 +77,7 @@ void efi_add_known_memory(void)
|
||||
start + e820[i].size,
|
||||
ram_top);
|
||||
} else {
|
||||
pages = ALIGN(e820[i].size, EFI_PAGE_SIZE)
|
||||
>> EFI_PAGE_SHIFT;
|
||||
efi_add_memory_map(start, pages, type, false);
|
||||
efi_add_memory_map(start, e820[i].size, type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ F: board/freescale/lx2160a/
|
||||
F: include/configs/lx2160a_common.h
|
||||
F: include/configs/lx2160ardb.h
|
||||
F: configs/lx2160ardb_tfa_defconfig
|
||||
F: configs/lx2160ardb_tfa_stmm_defconfig
|
||||
F: arch/arm/dts/fsl-lx2160a-rdb.dts
|
||||
|
||||
LX2160ARDB_SECURE_BOOT BOARD
|
||||
|
@ -489,8 +489,8 @@ int ft_board_setup(void *blob, bd_t *bd)
|
||||
|
||||
#ifdef CONFIG_EFI_LOADER
|
||||
/* Reserve the spin table */
|
||||
efi_add_memory_map(0, CONFIG_RPI_EFI_NR_SPIN_PAGES,
|
||||
EFI_RESERVED_MEMORY_TYPE, 0);
|
||||
efi_add_memory_map(0, CONFIG_RPI_EFI_NR_SPIN_PAGES << EFI_PAGE_SHIFT,
|
||||
EFI_RESERVED_MEMORY_TYPE);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
@ -151,14 +151,10 @@ done:
|
||||
|
||||
static void efi_reserve_memory(u64 addr, u64 size)
|
||||
{
|
||||
u64 pages;
|
||||
|
||||
/* Convert from sandbox address space. */
|
||||
addr = (uintptr_t)map_sysmem(addr, 0);
|
||||
pages = efi_size_in_pages(size + (addr & EFI_PAGE_MASK));
|
||||
addr &= ~EFI_PAGE_MASK;
|
||||
if (efi_add_memory_map(addr, pages, EFI_RESERVED_MEMORY_TYPE,
|
||||
false) != EFI_SUCCESS)
|
||||
if (efi_add_memory_map(addr, size,
|
||||
EFI_RESERVED_MEMORY_TYPE) != EFI_SUCCESS)
|
||||
printf("Reserved memory mapping failed addr %llx size %llx\n",
|
||||
addr, size);
|
||||
}
|
||||
|
@ -1165,6 +1165,58 @@ static int do_efi_test(cmd_tbl_t *cmdtp, int flag,
|
||||
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[] = {
|
||||
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,
|
||||
@ -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(query, CONFIG_SYS_MAXARGS, 1, do_efi_query_info,
|
||||
"", ""),
|
||||
};
|
||||
|
||||
/**
|
||||
@ -1252,7 +1306,9 @@ static char efidebug_help_text[] =
|
||||
"efidebug tables\n"
|
||||
" - show UEFI configuration tables\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
|
||||
|
||||
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>
|
||||
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
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
@ -195,8 +195,8 @@ void meson_vpu_rsv_fb(void *fdt)
|
||||
return;
|
||||
|
||||
#if defined(CONFIG_EFI_LOADER)
|
||||
efi_add_memory_map(meson_fb.base, meson_fb.fb_size >> EFI_PAGE_SHIFT,
|
||||
EFI_RESERVED_MEMORY_TYPE, false);
|
||||
efi_add_memory_map(meson_fb.base, meson_fb.fb_size,
|
||||
EFI_RESERVED_MEMORY_TYPE);
|
||||
#endif
|
||||
#if defined(CONFIG_VIDEO_DT_SIMPLEFB)
|
||||
meson_vpu_setup_simplefb(fdt);
|
||||
|
@ -224,9 +224,9 @@ static int sunxi_de2_init(struct udevice *dev, ulong fbbase,
|
||||
|
||||
#ifdef CONFIG_EFI_LOADER
|
||||
efi_add_memory_map(fbbase,
|
||||
ALIGN(timing.hactive.typ * timing.vactive.typ *
|
||||
(1 << l2bpp) / 8, EFI_PAGE_SIZE) >> EFI_PAGE_SHIFT,
|
||||
EFI_RESERVED_MEMORY_TYPE, false);
|
||||
timing.hactive.typ * timing.vactive.typ *
|
||||
(1 << l2bpp) / 8,
|
||||
EFI_RESERVED_MEMORY_TYPE);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
@ -1196,10 +1196,8 @@ void *video_hw_init(void)
|
||||
sunxi_engines_init();
|
||||
|
||||
#ifdef CONFIG_EFI_LOADER
|
||||
efi_add_memory_map(gd->fb_base,
|
||||
ALIGN(sunxi_display.fb_size, EFI_PAGE_SIZE) >>
|
||||
EFI_PAGE_SHIFT,
|
||||
EFI_RESERVED_MEMORY_TYPE, false);
|
||||
efi_add_memory_map(gd->fb_base, sunxi_display.fb_size,
|
||||
EFI_RESERVED_MEMORY_TYPE);
|
||||
#endif
|
||||
|
||||
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,
|
||||
uint32_t *descriptor_version);
|
||||
/* Adds a range into the EFI memory map */
|
||||
efi_status_t efi_add_memory_map(uint64_t start, uint64_t pages, int memory_type,
|
||||
bool overlap_only_ram);
|
||||
efi_status_t efi_add_memory_map(u64 start, u64 size, int memory_type);
|
||||
/* Adds a conventional range into the EFI memory map */
|
||||
efi_status_t efi_add_conventional_memory_map(u64 ram_start, u64 ram_end,
|
||||
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,
|
||||
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
|
||||
|
@ -35,7 +35,11 @@ obj-y += efi_root_node.o
|
||||
obj-y += efi_runtime.o
|
||||
obj-y += efi_setup.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
|
||||
endif
|
||||
obj-y += efi_watchdog.o
|
||||
obj-$(CONFIG_LCD) += 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
|
||||
* @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
|
||||
* Return: status code
|
||||
*/
|
||||
efi_status_t efi_add_memory_map(uint64_t start, uint64_t pages, int memory_type,
|
||||
bool overlap_only_ram)
|
||||
static efi_status_t efi_add_memory_map_pg(u64 start, u64 pages,
|
||||
int memory_type,
|
||||
bool overlap_only_ram)
|
||||
{
|
||||
struct list_head *lhandle;
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
@ -469,7 +492,8 @@ efi_status_t efi_allocate_pages(int type, int memory_type,
|
||||
}
|
||||
|
||||
/* 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 */
|
||||
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;
|
||||
}
|
||||
|
||||
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 */
|
||||
|
||||
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;
|
||||
|
||||
efi_add_memory_map(ram_start, pages,
|
||||
EFI_CONVENTIONAL_MEMORY, false);
|
||||
efi_add_memory_map_pg(ram_start, pages,
|
||||
EFI_CONVENTIONAL_MEMORY, false);
|
||||
|
||||
/*
|
||||
* 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) {
|
||||
/* ram_top is before this region, reserve all */
|
||||
efi_add_memory_map(ram_start, pages,
|
||||
EFI_BOOT_SERVICES_DATA, true);
|
||||
efi_add_memory_map_pg(ram_start, pages,
|
||||
EFI_BOOT_SERVICES_DATA, true);
|
||||
} else if ((ram_top >= ram_start) && (ram_top < ram_end)) {
|
||||
/* ram_top is inside this region, reserve parts */
|
||||
pages = (ram_end - ram_top) >> EFI_PAGE_SHIFT;
|
||||
|
||||
efi_add_memory_map(ram_top, pages,
|
||||
EFI_BOOT_SERVICES_DATA, true);
|
||||
efi_add_memory_map_pg(ram_top, pages,
|
||||
EFI_BOOT_SERVICES_DATA, true);
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
@ -743,7 +768,8 @@ static void add_u_boot_and_runtime(void)
|
||||
uboot_stack_size) & ~EFI_PAGE_MASK;
|
||||
uboot_pages = ((uintptr_t)map_sysmem(gd->ram_top - 1, 0) -
|
||||
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__)
|
||||
/*
|
||||
@ -762,8 +788,8 @@ static void add_u_boot_and_runtime(void)
|
||||
runtime_end = (ulong)&__efi_runtime_stop;
|
||||
runtime_end = (runtime_end + runtime_mask) & ~runtime_mask;
|
||||
runtime_pages = (runtime_end - runtime_start) >> EFI_PAGE_SHIFT;
|
||||
efi_add_memory_map(runtime_start, runtime_pages,
|
||||
EFI_RUNTIME_SERVICES_CODE, false);
|
||||
efi_add_memory_map_pg(runtime_start, runtime_pages,
|
||||
EFI_RUNTIME_SERVICES_CODE, false);
|
||||
}
|
||||
|
||||
int efi_memory_init(void)
|
||||
|
@ -784,11 +784,10 @@ out:
|
||||
efi_status_t efi_add_runtime_mmio(void *mmio_ptr, u64 len)
|
||||
{
|
||||
struct efi_runtime_mmio_list *newmmio;
|
||||
u64 pages = (len + EFI_PAGE_MASK) >> EFI_PAGE_SHIFT;
|
||||
uint64_t addr = *(uintptr_t *)mmio_ptr;
|
||||
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)
|
||||
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…
Reference in New Issue
Block a user