Pull request for efi-2023-01-rc3

Documentation:
 
 * describe DM firmware needed for j721e_evm
 * describe management of UEFI security data base with eficonfig
 
 UEFI:
 
 * code clean-up for eficonfig command
 * fix handling of DHCP aknowledge
 * correct EFI memory type used for U-Boot code
 * unit test for FatToStr() truncation
 * add an EFI binary to print boot hart ID
 
 Other:
 
 * improve parameter checks in console functions
 * fix variable initialization in blk_get_device_part_str
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEEbcT5xx8ppvoGt20zxIHbvCwFGsQFAmOKVdQACgkQxIHbvCwF
 GsREQxAAlhx05eYwItq2n7oDV65h2yFl5YaGo35v9HPG8DrLoeOdw/IpNCQ+Naao
 0VyIg+uFM/qvFTIwfC1NDVlzOiDBQgaFiUhe1Zvq8n8lJNdfAwgXvFQU5MOyxcDa
 4RZBYpwN+kJ2+6P98xtl8jIOJZ7jO/BLcR7Xss9dP2B7IJcczMrj5Kl2heanXjnk
 zhMHx8WC4rrSBZM4NxyPd6e04qxz1L1r0A6U0ZmVT1ferdaBb7LoXkQk4fINhI6a
 Z+1UKzKvTWDynHmKuuK5ujFyBbE7COqVGnR6uabZxOk1CS7EEJJyDdzYA5F4yVlf
 6DSDTzE72jhRPa7AQnYtwQA/+IPwkfRXo7n4eRERi135onm7ufy+aww/yeZ3RdJF
 BN5BRhFmJPT/KfQK/JgDZ3aDDYFjdcB+h2nm57DWeKB0nq/xsAMHhJ4rrB2yu1kn
 dmNP9v9EZtvp0wG2H4nIeXd7kKBGG4qZRqhfzBfNYQ899dubBEKUXv+DEfqSnh6k
 3v4W0V8sPjjvY+2hgiYyBnmmJP/MEG0T21uppFC9AcUKfaSTElRqkRpr+wDkB5qL
 xHwHuXYRBaMuhycs2W/6D1D3UaGg8YYzgOidMt0Pq0T+pq4V1bDXIlixE9nXZGl6
 tqy3WKMcIu85AYYqwt0OZnF4DWx8v2pRLhyGbkSPVoadmeDEcmg=
 =UmdO
 -----END PGP SIGNATURE-----

Merge tag 'efi-2023-01-rc3' of https://source.denx.de/u-boot/custodians/u-boot-efi

Pull request for efi-2023-01-rc3

Documentation:

* describe DM firmware needed for j721e_evm
* describe management of UEFI security data base with eficonfig

UEFI:

* code clean-up for eficonfig command
* fix handling of DHCP aknowledge
* correct EFI memory type used for U-Boot code
* unit test for FatToStr() truncation
* add an EFI binary to print boot hart ID

Other:

* improve parameter checks in console functions
* fix variable initialization in blk_get_device_part_str
This commit is contained in:
Tom Rini 2022-12-04 10:01:48 -05:00
commit d2c5607edd
15 changed files with 600 additions and 124 deletions

View File

@ -452,8 +452,7 @@ struct efi_device_path *eficonfig_create_device_path(struct efi_device_path *dp_
struct efi_device_path *dp;
struct efi_device_path_file_path *fp;
fp_size = sizeof(struct efi_device_path) +
((u16_strlen(current_path) + 1) * sizeof(u16));
fp_size = sizeof(struct efi_device_path) + u16_strsize(current_path);
buf = calloc(1, fp_size + sizeof(END));
if (!buf)
return NULL;
@ -488,7 +487,7 @@ static efi_status_t eficonfig_file_selected(void *data)
if (!info)
return EFI_INVALID_PARAMETER;
if (!strcmp(info->file_name, "..")) {
if (!strcmp(info->file_name, "..\\")) {
struct eficonfig_filepath_info *iter;
struct list_head *pos, *n;
int is_last;
@ -1684,7 +1683,8 @@ static efi_status_t eficonfig_show_boot_selection(unsigned int *selected)
u32 i;
u16 *bootorder;
efi_status_t ret;
efi_uintn_t num, size;
u16 *var_name16 = NULL, *p;
efi_uintn_t num, size, buf_size;
struct efimenu *efi_menu;
struct list_head *pos, *n;
struct eficonfig_entry *entry;
@ -1708,14 +1708,43 @@ static efi_status_t eficonfig_show_boot_selection(unsigned int *selected)
}
/* list the remaining load option not included in the BootOrder */
for (i = 0; i <= 0xFFFF; i++) {
/* If the index is included in the BootOrder, skip it */
if (search_bootorder(bootorder, num, i, NULL))
continue;
buf_size = 128;
var_name16 = malloc(buf_size);
if (!var_name16)
return EFI_OUT_OF_RESOURCES;
ret = eficonfig_add_boot_selection_entry(efi_menu, i, selected);
if (ret != EFI_SUCCESS)
goto out;
var_name16[0] = 0;
for (;;) {
int index;
efi_guid_t guid;
size = buf_size;
ret = efi_get_next_variable_name_int(&size, var_name16, &guid);
if (ret == EFI_NOT_FOUND)
break;
if (ret == EFI_BUFFER_TOO_SMALL) {
buf_size = size;
p = realloc(var_name16, buf_size);
if (!p) {
free(var_name16);
return EFI_OUT_OF_RESOURCES;
}
var_name16 = p;
ret = efi_get_next_variable_name_int(&size, var_name16, &guid);
}
if (ret != EFI_SUCCESS) {
free(var_name16);
return ret;
}
if (efi_varname_is_load_option(var_name16, &index)) {
/* If the index is included in the BootOrder, skip it */
if (search_bootorder(bootorder, num, index, NULL))
continue;
ret = eficonfig_add_boot_selection_entry(efi_menu, index, selected);
if (ret != EFI_SUCCESS)
goto out;
}
if (efi_menu->count >= EFICONFIG_ENTRY_NUM_MAX - 1)
break;
@ -1733,6 +1762,8 @@ out:
}
eficonfig_destroy(efi_menu);
free(var_name16);
return ret;
}
@ -1995,6 +2026,8 @@ static efi_status_t eficonfig_create_change_boot_order_entry(struct efimenu *efi
u32 i;
char *title;
efi_status_t ret;
u16 *var_name16 = NULL, *p;
efi_uintn_t size, buf_size;
/* list the load option in the order of BootOrder variable */
for (i = 0; i < num; i++) {
@ -2007,17 +2040,45 @@ static efi_status_t eficonfig_create_change_boot_order_entry(struct efimenu *efi
}
/* list the remaining load option not included in the BootOrder */
for (i = 0; i < 0xFFFF; i++) {
buf_size = 128;
var_name16 = malloc(buf_size);
if (!var_name16)
return EFI_OUT_OF_RESOURCES;
var_name16[0] = 0;
for (;;) {
int index;
efi_guid_t guid;
if (efi_menu->count >= EFICONFIG_ENTRY_NUM_MAX - 2)
break;
/* If the index is included in the BootOrder, skip it */
if (search_bootorder(bootorder, num, i, NULL))
continue;
ret = eficonfig_add_change_boot_order_entry(efi_menu, i, false);
size = buf_size;
ret = efi_get_next_variable_name_int(&size, var_name16, &guid);
if (ret == EFI_NOT_FOUND)
break;
if (ret == EFI_BUFFER_TOO_SMALL) {
buf_size = size;
p = realloc(var_name16, buf_size);
if (!p) {
ret = EFI_OUT_OF_RESOURCES;
goto out;
}
var_name16 = p;
ret = efi_get_next_variable_name_int(&size, var_name16, &guid);
}
if (ret != EFI_SUCCESS)
goto out;
if (efi_varname_is_load_option(var_name16, &index)) {
/* If the index is included in the BootOrder, skip it */
if (search_bootorder(bootorder, num, index, NULL))
continue;
ret = eficonfig_add_change_boot_order_entry(efi_menu, index, false);
if (ret != EFI_SUCCESS)
goto out;
}
}
/* add "Save" and "Quit" entries */
@ -2036,9 +2097,9 @@ static efi_status_t eficonfig_create_change_boot_order_entry(struct efimenu *efi
goto out;
efi_menu->active = 0;
return EFI_SUCCESS;
out:
free(var_name16);
return ret;
}
@ -2271,17 +2332,48 @@ out:
efi_status_t eficonfig_delete_invalid_boot_option(struct eficonfig_media_boot_option *opt,
efi_status_t count)
{
u32 i, j;
u32 i;
efi_uintn_t size;
void *load_option;
struct efi_load_option lo;
u16 *var_name16 = NULL, *p;
u16 varname[] = u"Boot####";
efi_status_t ret = EFI_SUCCESS;
efi_uintn_t varname_size, buf_size;
for (i = 0; i <= 0xFFFF; i++) {
buf_size = 128;
var_name16 = malloc(buf_size);
if (!var_name16)
return EFI_OUT_OF_RESOURCES;
var_name16[0] = 0;
for (;;) {
int index;
efi_guid_t guid;
efi_uintn_t tmp;
efi_create_indexed_name(varname, sizeof(varname), "Boot", i);
varname_size = buf_size;
ret = efi_get_next_variable_name_int(&varname_size, var_name16, &guid);
if (ret == EFI_NOT_FOUND)
break;
if (ret == EFI_BUFFER_TOO_SMALL) {
buf_size = varname_size;
p = realloc(var_name16, buf_size);
if (!p) {
free(var_name16);
return EFI_OUT_OF_RESOURCES;
}
var_name16 = p;
ret = efi_get_next_variable_name_int(&varname_size, var_name16, &guid);
}
if (ret != EFI_SUCCESS) {
free(var_name16);
return ret;
}
if (!efi_varname_is_load_option(var_name16, &index))
continue;
efi_create_indexed_name(varname, sizeof(varname), "Boot", index);
load_option = efi_get_var(varname, &efi_global_variable_guid, &size);
if (!load_option)
continue;
@ -2293,15 +2385,15 @@ efi_status_t eficonfig_delete_invalid_boot_option(struct eficonfig_media_boot_op
if (size >= sizeof(efi_guid_bootmenu_auto_generated)) {
if (guidcmp(lo.optional_data, &efi_guid_bootmenu_auto_generated) == 0) {
for (j = 0; j < count; j++) {
if (opt[j].size == tmp &&
memcmp(opt[j].lo, load_option, tmp) == 0) {
opt[j].exist = true;
for (i = 0; i < count; i++) {
if (opt[i].size == tmp &&
memcmp(opt[i].lo, load_option, tmp) == 0) {
opt[i].exist = true;
break;
}
}
if (j == count) {
if (i == count) {
ret = delete_boot_option(i);
if (ret != EFI_SUCCESS) {
free(load_option);

View File

@ -600,7 +600,7 @@ static int do_efi_show_memmap(struct cmd_tbl *cmdtp, int flag,
ret = efi_get_memory_map(&map_size, memmap, NULL, NULL, NULL);
if (ret == EFI_BUFFER_TOO_SMALL) {
map_size += sizeof(struct efi_mem_desc); /* for my own */
ret = efi_allocate_pool(EFI_LOADER_DATA, map_size,
ret = efi_allocate_pool(EFI_BOOT_SERVICES_DATA, map_size,
(void *)&memmap);
if (ret != EFI_SUCCESS)
return CMD_RET_FAILURE;
@ -1010,17 +1010,6 @@ static void show_efi_boot_opt(u16 *varname16)
}
}
static int u16_tohex(u16 c)
{
if (c >= '0' && c <= '9')
return c - '0';
if (c >= 'A' && c <= 'F')
return c - 'A' + 10;
/* not hexadecimal */
return -1;
}
/**
* show_efi_boot_dump() - dump all UEFI load options
*
@ -1041,7 +1030,6 @@ static int do_efi_boot_dump(struct cmd_tbl *cmdtp, int flag,
u16 *var_name16, *p;
efi_uintn_t buf_size, size;
efi_guid_t guid;
int id, i, digit;
efi_status_t ret;
if (argc > 1)
@ -1074,16 +1062,7 @@ static int do_efi_boot_dump(struct cmd_tbl *cmdtp, int flag,
return CMD_RET_FAILURE;
}
if (memcmp(var_name16, u"Boot", 8))
continue;
for (id = 0, i = 0; i < 4; i++) {
digit = u16_tohex(var_name16[4 + i]);
if (digit < 0)
break;
id = (id << 4) + digit;
}
if (i == 4 && !var_name16[8])
if (efi_varname_is_load_option(var_name16, NULL))
show_efi_boot_opt(var_name16);
}

View File

@ -497,7 +497,7 @@ int serial_printf(const char *fmt, ...)
int fgetc(int file)
{
if (file < MAX_FILES) {
if ((unsigned int)file < MAX_FILES) {
/*
* Effectively poll for input wherever it may be available.
*/
@ -530,7 +530,7 @@ int fgetc(int file)
int ftstc(int file)
{
if (file < MAX_FILES)
if ((unsigned int)file < MAX_FILES)
return console_tstc(file);
return -1;
@ -538,20 +538,20 @@ int ftstc(int file)
void fputc(int file, const char c)
{
if (file < MAX_FILES)
if ((unsigned int)file < MAX_FILES)
console_putc(file, c);
}
void fputs(int file, const char *s)
{
if (file < MAX_FILES)
if ((unsigned int)file < MAX_FILES)
console_puts(file, s);
}
#ifdef CONFIG_CONSOLE_FLUSH_SUPPORT
void fflush(int file)
{
if (file < MAX_FILES)
if ((unsigned int)file < MAX_FILES)
console_flush(file);
}
#endif

View File

@ -433,25 +433,17 @@ int blk_get_device_part_str(const char *ifname, const char *dev_part_str,
int part;
struct disk_partition tmpinfo;
*dev_desc = NULL;
memset(info, 0, sizeof(*info));
#if IS_ENABLED(CONFIG_SANDBOX) || IS_ENABLED(CONFIG_SEMIHOSTING)
/*
* Special-case a pseudo block device "hostfs", to allow access to the
* host's own filesystem.
*/
if (0 == strcmp(ifname, "hostfs")) {
*dev_desc = NULL;
info->start = 0;
info->size = 0;
info->blksz = 0;
info->bootable = 0;
if (!strcmp(ifname, "hostfs")) {
strcpy((char *)info->type, BOOT_PART_TYPE);
strcpy((char *)info->name, "Host filesystem");
#if CONFIG_IS_ENABLED(PARTITION_UUIDS)
info->uuid[0] = 0;
#endif
#ifdef CONFIG_PARTITION_TYPE_GUID
info->type_guid[0] = 0;
#endif
return 0;
}
@ -462,19 +454,14 @@ int blk_get_device_part_str(const char *ifname, const char *dev_part_str,
* Special-case ubi, ubi goes through a mtd, rather than through
* a regular block device.
*/
if (0 == strcmp(ifname, "ubi")) {
if (!strcmp(ifname, "ubi")) {
if (!ubifs_is_mounted()) {
printf("UBIFS not mounted, use ubifsmount to mount volume first!\n");
return -EINVAL;
}
*dev_desc = NULL;
memset(info, 0, sizeof(*info));
strcpy((char *)info->type, BOOT_PART_TYPE);
strcpy((char *)info->name, "UBI");
#if CONFIG_IS_ENABLED(PARTITION_UUIDS)
info->uuid[0] = 0;
#endif
return 0;
}
#endif

View File

@ -209,7 +209,7 @@ GUID type
~~~~~~~~~
The HSS always picks up HSS payload from a GPT partition with
GIUD type "21686148-6449-6E6F-744E-656564454649" or sector '0' of the eMMC if no
GUID type "21686148-6449-6E6F-744E-656564454649" or sector '0' of the eMMC if no
GPT partition.
Booting
@ -460,7 +460,7 @@ GUID type
~~~~~~~~~
The HSS always picks up the HSS payload from a GPT partition with
GIUD type "21686148-6449-6E6F-744E-656564454649" or sector '0' of the eMMC if no
GUID type "21686148-6449-6E6F-744E-656564454649" or sector '0' of the eMMC if no
GPT partition.
Sample boot log from MPFS Icicle Kit

View File

@ -142,7 +142,11 @@ Sources:
Tree: https://github.com/OP-TEE/optee_os.git
Branch: master
4. U-Boot:
4. DM Firmware:
Tree: git://git.ti.com/processor-firmware/ti-linux-firmware.git
Branch: ti-linux-firmware
5. U-Boot:
Tree: https://source.denx.de/u-boot/u-boot
Branch: master
@ -150,37 +154,37 @@ Build procedure:
----------------
1. SYSFW:
.. code-block:: text
.. code-block:: bash
$ make CROSS_COMPILE=arm-linux-gnueabihf-
make CROSS_COMPILE=arm-linux-gnueabihf- SOC=j721e
2. ATF:
.. code-block:: text
.. code-block:: bash
$ make CROSS_COMPILE=aarch64-linux-gnu- ARCH=aarch64 PLAT=k3 TARGET_BOARD=generic SPD=opteed
make CROSS_COMPILE=aarch64-linux-gnu- ARCH=aarch64 PLAT=k3 TARGET_BOARD=generic SPD=opteed
3. OPTEE:
.. code-block:: text
.. code-block:: bash
$ make PLATFORM=k3-j721e CFG_ARM64_core=y
make PLATFORM=k3-j721e CFG_ARM64_core=y
4. U-Boot:
* 4.1 R5:
.. code-block:: text
.. code-block:: bash
$ make CROSS_COMPILE=arm-linux-gnueabihf- j721e_evm_r5_defconfig O=/tmp/r5
$ make CROSS_COMPILE=arm-linux-gnueabihf- O=/tmp/r5
make CROSS_COMPILE=arm-linux-gnueabihf- j721e_evm_r5_defconfig O=build/r5
make CROSS_COMPILE=arm-linux-gnueabihf- O=build/r5
* 4.2 A72:
.. code-block:: text
.. code-block:: bash
$ make CROSS_COMPILE=aarch64-linux-gnu- j721e_evm_a72_defconfig O=/tmp/a72
$ make CROSS_COMPILE=aarch64-linux-gnu- ATF=<path to ATF dir>/build/k3/generic/release/bl31.bin TEE=<path to OPTEE OS dir>/out/arm-plat-k3/core/tee-pager_v2.bin DM=<path to DM firmware image> O=/tmp/a72
make CROSS_COMPILE=aarch64-linux-gnu- j721e_evm_a72_defconfig O=build/a72
make CROSS_COMPILE=aarch64-linux-gnu- ATF=<ATF dir>/build/k3/generic/release/bl31.bin TEE=<OPTEE OS dir>/out/arm-plat-k3/core/tee-pager_v2.bin DM=<DM firmware>/ti-dm/j721e/ipc_echo_testb_mcu1_0_release_strip.xer5f O=build/a72
Target Images
--------------

View File

@ -13,49 +13,43 @@ Synopsis
Description
-----------
The "eficonfig" command uses U-Boot menu interface and provides
a menu-driven UEFI variable maintenance feature.
The "eficonfig" has the following menu entries.
The "eficonfig" command uses the U-Boot menu interface to provide a
menu-driven UEFI variable maintenance feature. These are the top level menu
entries:
Add Boot Option
Add new UEFI Boot Option.
User can edit description, file path, and optional_data.
Add a new UEFI Boot Option.
The user can edit description, file path, and optional_data.
The new boot opiton is appended to the boot order in the *BootOrder*
variable. The user may want to update the boot order using the
*Change Boot Order* menu entry.
Edit Boot Option
Edit the existing UEFI Boot Option
User can edit description, file path, and optional_data.
Edit an existing UEFI Boot Option.
The User can edit description, file path, and optional_data.
Change Boot Order
Change the order of UEFI BootOrder variable.
Change the boot order updating the UEFI BootOrder variable.
Delete Boot Option
Delete the UEFI Boot Option
Delete a UEFI Boot Option
Configuration
-------------
Secure Boot Configuration
Edit the UEFI Secure Boot Configuration
The "eficonfig" command is enabled by::
How to boot the system with a newly added UEFI Boot Option
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
CONFIG_CMD_EFICONFIG=y
The "eficonfig" command is used to set the UEFI boot options which are stored
in the UEFI variable Boot#### where #### is a hexadecimal number.
If CONFIG_BOOTMENU_DISABLE_UBOOT_CONSOLE is enabled, user can not enter
U-Boot console. In this case, bootmenu can be used to invoke "eficonfig"::
The command *bootefi bootmgr* can be used to boot by trying in sequence all
boot options selected by the variable *BootOrder*.
CONFIG_USE_PREBOOT=y
CONFIG_PREBOOT="setenv bootmenu_0 UEFI Maintenance Menu=eficonfig"
How to boot the system with newly added UEFI Boot Option
''''''''''''''''''''''''''''''''''''''''''''''''''''''''
"eficonfig" command is responsible for configuring the UEFI variables,
not directly handle the system boot.
The new Boot Option added by "eficonfig" is appended at the last entry
of UEFI BootOrder variable, user may want to change the boot order
through "Change Boot Order".
If the bootmenu is enabled, CONFIG_BOOTMENU_DISABLE_UBOOT_CONSOLE is enabled,
and "eficonfig" is configured as preboot command, the newly added Boot Options
are enumerated in the bootmenu when user exits from the eficonfig menu.
User may select the entry in the bootmenu to boot the system, or follow
are enumerated in the bootmenu when the user exits from the eficonfig menu.
The user may select the entry in the bootmenu to boot the system, or follow
the U-Boot configuration the system already has.
Auto boot with the UEFI Boot Option
@ -66,6 +60,44 @@ add "bootefi bootmgr" entry as a default or first bootmenu entry::
CONFIG_PREBOOT="setenv bootmenu_0 UEFI Boot Manager=bootefi bootmgr; setenv bootmenu_1 UEFI Maintenance Menu=eficonfig"
UEFI Secure Boot Configuration
''''''''''''''''''''''''''''''
The user can enroll the variables PK, KEK, db and dbx by selecting a file.
The "eficonfig" command only accepts signed EFI Signature List(s) with an
authenticated header, typically a ".auth" file.
To clear the PK, KEK, db and dbx, the user needs to enroll a null value
signed by PK or KEK.
Configuration
-------------
The "eficonfig" command is enabled by::
CONFIG_CMD_EFICONFIG=y
If CONFIG_BOOTMENU_DISABLE_UBOOT_CONSOLE is enabled, the user can not enter
U-Boot console. In this case, the bootmenu can be used to invoke "eficonfig"::
CONFIG_USE_PREBOOT=y
CONFIG_PREBOOT="setenv bootmenu_0 UEFI Maintenance Menu=eficonfig"
The only way U-Boot can currently store EFI variables on a tamper
resistant medium is via OP-TEE. The Kconfig option that enables that is::
CONFIG_EFI_MM_COMM_TEE=y.
It enables storing EFI variables on the RPMB partition of an eMMC device.
The UEFI Secure Boot Configuration menu entry is only available if the following
options are enabled::
CONFIG_EFI_SECURE_BOOT=y
CONFIG_EFI_MM_COMM_TEE=y
See also
--------
* :doc:`bootmenu<bootmenu>` provides a simple mechanism for creating menus with different boot items
* :doc:`bootmenu<bootmenu>` provides a simple mechanism for creating menus with
different boot items

View File

@ -707,6 +707,7 @@ int algo_to_len(const char *algo);
int efi_link_dev(efi_handle_t handle, struct udevice *dev);
int efi_unlink_dev(efi_handle_t handle);
bool efi_varname_is_load_option(u16 *var_name16, int *index);
/**
* efi_size_in_pages() - convert size in bytes to size in pages

View File

@ -12,6 +12,8 @@ ccflags-y += -DHOST_ARCH="$(HOST_ARCH)"
CFLAGS_efi_boottime.o += \
-DFW_VERSION="0x$(VERSION)" \
-DFW_PATCHLEVEL="0x$(PATCHLEVEL)"
CFLAGS_boothart.o := $(CFLAGS_EFI) -Os -ffreestanding
CFLAGS_REMOVE_boothart.o := $(CFLAGS_NON_EFI)
CFLAGS_helloworld.o := $(CFLAGS_EFI) -Os -ffreestanding
CFLAGS_REMOVE_helloworld.o := $(CFLAGS_NON_EFI)
CFLAGS_dtbdump.o := $(CFLAGS_EFI) -Os -ffreestanding
@ -19,6 +21,10 @@ CFLAGS_REMOVE_dtbdump.o := $(CFLAGS_NON_EFI)
CFLAGS_initrddump.o := $(CFLAGS_EFI) -Os -ffreestanding
CFLAGS_REMOVE_initrddump.o := $(CFLAGS_NON_EFI)
ifdef CONFIG_RISCV
always += boothart.efi
endif
ifneq ($(CONFIG_CMD_BOOTEFI_HELLO_COMPILE),)
always += helloworld.efi
targets += helloworld.o

335
lib/efi_loader/boothart.c Normal file
View File

@ -0,0 +1,335 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Check RISC-V boot hart ID
*
* Copyright 2022, Heinrich Schuchardt <xypron.glpk@gmx.de>
*
* This test program reads the boot HART ID both from the device-tree from the
* RISCV_EFI_BOOT_PROTOCOL and writes both values to the console.
*/
#include <efi_api.h>
#include <efi_riscv.h>
#include <linux/libfdt.h>
static const efi_guid_t riscv_efi_boot_protocol_guid =
RISCV_EFI_BOOT_PROTOCOL_GUID;
static const efi_guid_t fdt_guid = EFI_FDT_GUID;
static struct efi_system_table *systable;
static struct efi_boot_services *boottime;
static struct efi_simple_text_output_protocol *con_out;
static const char *fdt;
/**
* Print an unsigned 32bit value as decimal number to an u16 string
*
* @value: value to be printed
* @buf: pointer to buffer address
*/
static void uint2dec(u32 value, u16 *buf)
{
u16 *pos = buf;
int i;
u16 c;
u64 f;
/*
* Increment by .5 and multiply with
* (2 << 60) / 1,000,000,000 = 0x44B82FA0.9B5A52CC
* to move the first digit to bit 60-63.
*/
f = 0x225C17D0;
f += (0x9B5A52DULL * value) >> 28;
f += 0x44B82FA0ULL * value;
for (i = 0; i < 10; ++i) {
/* Write current digit */
c = f >> 60;
if (c || pos != buf)
*pos++ = c + '0';
/* Eliminate current digit */
f &= 0xfffffffffffffff;
/* Get next digit */
f *= 0xaULL;
}
if (pos == buf)
*pos++ = '0';
*pos = 0;
}
/**
* f2h() - convert FDT value to host endianness.
*
* UEFI code is always low endian. The FDT is big endian.
*
* @val: FDT value
* Return: converted value
*/
static uint32_t f2h(fdt32_t val)
{
char *buf = (char *)&val;
char i;
/* Swap the bytes */
i = buf[0]; buf[0] = buf[3]; buf[3] = i;
i = buf[1]; buf[1] = buf[2]; buf[2] = i;
return val;
}
/**
* memcomp() - compare two memory buffers
*
* s1: first buffer
* s2: second buffer
* n: size of buffers
* Return: 0 if both buffers have the same content
*/
static int memcomp(const void *s1, const void *s2, size_t n)
{
const char *pos1 = s1, *pos2 = s2;
for (size_t count = 0; count < n ; ++pos1, ++pos2, --count) {
if (*pos1 != *pos2)
return *pos1 - *pos2;
}
return 0;
}
/**
* strcomp() - compare to strings
*
* @buf1: first string
* @buf2: second string
* Return: 0 if both strings are the same
*/
static int strcomp(const char *buf1, const char *buf2)
{
for (; *buf1 || *buf2; ++buf1, ++buf2) {
if (*buf1 != *buf2)
return *buf1 - *buf2;
}
return 0;
}
/**
* get_property() - return value of a property of an FDT node
*
* A property of the root node or one of its direct children can be
* retrieved.
*
* @property name of the property
* @node name of the node or NULL for root node
* Return: value of the property
*/
static char *get_property(const char *property, const char *node)
{
struct fdt_header *header = (struct fdt_header *)fdt;
const fdt32_t *end;
const fdt32_t *pos;
const char *strings;
size_t level = 0;
const char *nodelabel = NULL;
if (!header) {
con_out->output_string(con_out, u"Missing device tree\r\n");
return NULL;
}
if (f2h(header->magic) != FDT_MAGIC) {
con_out->output_string(con_out, u"Wrong device tree magic\r\n");
return NULL;
}
pos = (fdt32_t *)(fdt + f2h(header->off_dt_struct));
end = &pos[f2h(header->totalsize) >> 2];
strings = fdt + f2h(header->off_dt_strings);
for (; pos < end;) {
switch (f2h(pos[0])) {
case FDT_BEGIN_NODE: {
const char *c = (char *)&pos[1];
size_t i;
if (level == 1)
nodelabel = c;
++level;
for (i = 0; c[i]; ++i)
;
pos = &pos[2 + (i >> 2)];
break;
}
case FDT_PROP: {
struct fdt_property *prop = (struct fdt_property *)pos;
const char *label = &strings[f2h(prop->nameoff)];
efi_status_t ret;
/* Check if this is the property to be returned */
if (!strcomp(property, label) &&
((level == 1 && !node) ||
(level == 2 && node &&
!strcomp(node, nodelabel)))) {
char *str;
efi_uintn_t len = f2h(prop->len);
if (!len)
return NULL;
/*
* The string might not be 0 terminated.
* It is safer to make a copy.
*/
ret = boottime->allocate_pool(
EFI_LOADER_DATA, len + 1,
(void **)&str);
if (ret != EFI_SUCCESS) {
con_out->output_string(
con_out,
u"AllocatePool failed\r\n");
return NULL;
}
boottime->copy_mem(str, &pos[3], len);
str[len] = 0;
return str;
}
pos = &pos[3 + ((f2h(prop->len) + 3) >> 2)];
break;
}
case FDT_NOP:
++pos;
break;
case FDT_END_NODE:
--level;
++pos;
break;
case FDT_END:
return NULL;
default:
con_out->output_string(
con_out, u"Invalid device tree token\r\n");
return NULL;
}
}
con_out->output_string(
con_out, u"Missing FDT_END token\r\n");
return NULL;
}
/**
* get_config_table() - get configuration table
*
* @guid: table GUID
* Return: pointer to table or NULL
*/
static void *get_config_table(const efi_guid_t *guid)
{
size_t i;
for (i = 0; i < systable->nr_tables; i++) {
if (!memcomp(guid, &systable->tables[i].guid, 16))
return systable->tables[i].table;
}
return NULL;
}
/**
* fdt_get_hart() - get hart ID via RISC-V device-tree
*
* @hartid: boot hart ID
* Return: status code
*/
static efi_status_t fdt_get_hart(efi_uintn_t *hartid)
{
char *str;
fdt = get_config_table(&fdt_guid);
if (!fdt) {
con_out->output_string(con_out, u"Missing device tree\r\n");
return EFI_NOT_FOUND;
}
str = get_property("boot-hartid", "chosen");
if (!str) {
con_out->output_string(con_out,
u"/chosen/boot-hartid missing\r\n");
return EFI_NOT_FOUND;
}
*hartid = f2h(*(fdt32_t *)str);
boottime->free_pool(str);
return EFI_SUCCESS;
}
/**
* prot_get_hart() - get hart ID via RISC-V Boot Protocol
*
* @hartid: boot hart ID
* Return: status code
*/
static efi_status_t prot_get_hart(efi_uintn_t *hartid)
{
efi_status_t ret;
struct riscv_efi_boot_protocol *prot;
/* Get RISC-V boot protocol */
ret = boottime->locate_protocol(&riscv_efi_boot_protocol_guid, NULL,
(void **)&prot);
if (ret != EFI_SUCCESS) {
con_out->output_string(
con_out, u"RISC-V Boot Protocol not available\r\n");
return ret;
}
/* Get boot hart ID from EFI protocol */
ret = prot->get_boot_hartid(prot, hartid);
if (ret != EFI_SUCCESS)
con_out->output_string(con_out,
u"Could not retrieve boot hart ID\r\n");
return ret;
}
/**
* efi_main() - entry point of the EFI application.
*
* @handle: handle of the loaded image
* @systab: system table
* Return: status code
*/
efi_status_t EFIAPI efi_main(efi_handle_t handle,
struct efi_system_table *systab)
{
efi_status_t ret;
efi_uintn_t hartid;
u16 buf[16];
systable = systab;
boottime = systable->boottime;
con_out = systable->con_out;
con_out->output_string(con_out,
u"\r\nBoot hart ID\r\n------------\r\n\r\n");
ret = fdt_get_hart(&hartid);
if (ret == EFI_SUCCESS) {
con_out->output_string(con_out, u"Device-tree: ");
uint2dec(hartid, buf);
con_out->output_string(con_out, buf);
con_out->output_string(con_out, u"\r\n");
}
ret = prot_get_hart(&hartid);
if (ret == EFI_SUCCESS) {
con_out->output_string(con_out, u"RISCV_EFI_BOOT_PROTOCOL: ");
uint2dec(hartid, buf);
con_out->output_string(con_out, buf);
con_out->output_string(con_out, u"\r\n");
}
con_out->output_string(con_out, u"\r\n");
boottime->exit(handle, EFI_SUCCESS, 0, NULL);
/* We should never arrive here */
return EFI_SUCCESS;
}

View File

@ -190,3 +190,36 @@ int efi_unlink_dev(efi_handle_t handle)
return 0;
}
static int u16_tohex(u16 c)
{
if (c >= '0' && c <= '9')
return c - '0';
if (c >= 'A' && c <= 'F')
return c - 'A' + 10;
/* not hexadecimal */
return -1;
}
bool efi_varname_is_load_option(u16 *var_name16, int *index)
{
int id, i, digit;
if (memcmp(var_name16, u"Boot", 8))
return false;
for (id = 0, i = 0; i < 4; i++) {
digit = u16_tohex(var_name16[4 + i]);
if (digit < 0)
break;
id = (id << 4) + digit;
}
if (i == 4 && !var_name16[8]) {
if (index)
*index = id;
return true;
}
return false;
}

View File

@ -823,7 +823,7 @@ 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_pg(uboot_start, uboot_pages, EFI_LOADER_DATA,
efi_add_memory_map_pg(uboot_start, uboot_pages, EFI_BOOT_SERVICES_CODE,
false);
#if defined(__aarch64__)
@ -857,7 +857,7 @@ int efi_memory_init(void)
/* Request a 32bit 64MB bounce buffer region */
uint64_t efi_bounce_buffer_addr = 0xffffffff;
if (efi_allocate_pages(EFI_ALLOCATE_MAX_ADDRESS, EFI_LOADER_DATA,
if (efi_allocate_pages(EFI_ALLOCATE_MAX_ADDRESS, EFI_BOOT_SERVICES_DATA,
(64 * 1024 * 1024) >> EFI_PAGE_SHIFT,
&efi_bounce_buffer_addr) != EFI_SUCCESS)
return -1;

View File

@ -30,6 +30,7 @@ static uchar **receive_buffer;
static size_t *receive_lengths;
static int rx_packet_idx;
static int rx_packet_num;
static struct efi_net_obj *netobj;
/*
* The notification function of this event is called in every timer cycle
@ -660,10 +661,16 @@ void efi_net_set_dhcp_ack(void *pkt, int len)
{
int maxsize = sizeof(*dhcp_ack);
if (!dhcp_ack)
if (!dhcp_ack) {
dhcp_ack = malloc(maxsize);
if (!dhcp_ack)
return;
}
memset(dhcp_ack, 0, maxsize);
memcpy(dhcp_ack, pkt, min(len, maxsize));
if (netobj)
netobj->pxe_mode.dhcp_ack = *dhcp_ack;
}
/**
@ -853,7 +860,6 @@ static efi_status_t EFIAPI efi_pxe_base_code_set_packets(
*/
efi_status_t efi_net_register(void)
{
struct efi_net_obj *netobj = NULL;
efi_status_t r;
int i;
@ -982,6 +988,7 @@ failure_to_add_protocol:
return r;
out_of_resources:
free(netobj);
netobj = NULL;
free(transmit_buffer);
if (receive_buffer)
for (i = 0; i < ETH_PACKETS_BATCH_RECV; i++)

View File

@ -178,7 +178,7 @@ static int test_fat_to_str(void)
boottime->set_mem(str, sizeof(str), 0);
unicode_collation_protocol->fat_to_str(unicode_collation_protocol, 6,
"U-BOOT", str);
"U-BOOT!", str);
if (efi_st_strcmp_16_8(str, "U-BOOT")) {
efi_st_error("fat_to_str returned \"%ps\"\n", str);
return EFI_ST_FAILURE;

View File

@ -1078,7 +1078,7 @@ static void dhcp_handler(uchar *pkt, unsigned dest, struct in_addr sip,
#endif /* CONFIG_SYS_BOOTFILE_PREFIX */
dhcp_packet_process_options(bp);
if (CONFIG_IS_ENABLED(EFI_LOADER) &&
CONFIG_IS_ENABLED(NET_DEVICES))
CONFIG_IS_ENABLED(NETDEVICES))
efi_net_set_dhcp_ack(pkt, len);
#if defined(CONFIG_SERVERIP_FROM_PROXYDHCP)