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:
Tom Rini 2020-05-18 08:17:29 -04:00
commit ed9a3aa645
22 changed files with 1117 additions and 55 deletions

View File

@ -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>

View File

@ -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

View File

@ -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

View File

@ -428,4 +428,10 @@
#size-cells = <0>;
status = "disabled";
};
firmware {
optee {
compatible = "linaro,optee-tz";
method = "smc";
};
};
};

View File

@ -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)

View File

@ -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);
}
}
}

View File

@ -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

View File

@ -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;

View File

@ -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);
}

View File

@ -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(

View 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

View File

@ -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
~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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
View 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_ */

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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;

View 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;
}