From 87a4fc1081d51f70545a5a4732f70ebdfb8e5dc1 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Thu, 21 Oct 2021 03:17:51 +0200 Subject: [PATCH 01/21] doc: require Sphinx 3.4.3 For enums documented according to the requirements in chapter "Structure, union, and enumeration documentation" of https://www.kernel.org/doc/html/latest/doc-guide/kernel-doc.html errors occur with Sphinx 2.4.4 which disappear with Sphinx 3.4.3, e.g. /builds/u-boot/custodians/u-boot-efi/doc/api/sysreset:6: ./include/sysreset.h:60:Unknown interpreted text role "enum". Sphinx 3.4.3 is the version used by Debian in the current release. Signed-off-by: Heinrich Schuchardt --- doc/sphinx/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/sphinx/requirements.txt b/doc/sphinx/requirements.txt index af79d2c119..4555a94d30 100644 --- a/doc/sphinx/requirements.txt +++ b/doc/sphinx/requirements.txt @@ -1,4 +1,4 @@ docutils==0.16 -Sphinx==2.4.4 +Sphinx==3.4.3 sphinx_rtd_theme six From 1da0b6ab2a2183b1c9e4cf3623d3e796931c861f Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Thu, 23 Sep 2021 11:06:16 +0200 Subject: [PATCH 02/21] doc: add system reset to API documentation Complete the Sphinx documentation in include/sysreset.h Add the include to the generated HTML documentation of the U-Boot API. Signed-off-by: Heinrich Schuchardt --- doc/api/index.rst | 1 + doc/api/sysreset.rst | 7 ++++++ include/sysreset.h | 53 ++++++++++++++++++++++++++++---------------- 3 files changed, 42 insertions(+), 19 deletions(-) create mode 100644 doc/api/sysreset.rst diff --git a/doc/api/index.rst b/doc/api/index.rst index ea02aa5715..281d1dca96 100644 --- a/doc/api/index.rst +++ b/doc/api/index.rst @@ -15,5 +15,6 @@ U-Boot API documentation rng sandbox serial + sysreset timer unicode diff --git a/doc/api/sysreset.rst b/doc/api/sysreset.rst new file mode 100644 index 0000000000..a51b06c387 --- /dev/null +++ b/doc/api/sysreset.rst @@ -0,0 +1,7 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +System reset +============ + +.. kernel-doc:: include/sysreset.h + :internal: diff --git a/include/sysreset.h b/include/sysreset.h index 701e4f5c86..9d4ed87cea 100644 --- a/include/sysreset.h +++ b/include/sysreset.h @@ -9,43 +9,55 @@ struct udevice; +/** + * enum sysreset_t - system reset types + */ enum sysreset_t { - SYSRESET_WARM, /* Reset CPU, keep GPIOs active */ - SYSRESET_COLD, /* Reset CPU and GPIOs */ - SYSRESET_POWER, /* Reset PMIC (remove and restore power) */ - SYSRESET_POWER_OFF, /* Turn off power */ - + /** @SYSRESET_WARM: reset CPU, keep GPIOs active */ + SYSRESET_WARM, + /** @SYSRESET_COLD: reset CPU and GPIOs */ + SYSRESET_COLD, + /** @SYSRESET_POWER: reset PMIC (remove and restore power) */ + SYSRESET_POWER, + /** @SYSRESET_POWER_OFF: turn off power */ + SYSRESET_POWER_OFF, + /** @SYSRESET_COUNT: number of available reset types */ SYSRESET_COUNT, }; +/** + * struct sysreset_ops - operations of system reset drivers + */ struct sysreset_ops { /** - * request() - request a sysreset of the given type + * @request: request a sysreset of the given type * * Note that this function may return before the reset takes effect. * + * @dev: Device to be used for system reset * @type: Reset type to request - * @return -EINPROGRESS if the reset has been started and - * will complete soon, -EPROTONOSUPPORT if not supported - * by this device, 0 if the reset has already happened - * (in which case this method will not actually return) + * Return: + * -EINPROGRESS if the reset has been started and + * will complete soon, -EPROTONOSUPPORT if not supported + * by this device, 0 if the reset has already happened + * (in which case this method will not actually return) */ int (*request)(struct udevice *dev, enum sysreset_t type); /** - * get_status() - get printable reset status information + * @get_status: get printable reset status information * * @dev: Device to check * @buf: Buffer to receive the textual reset information * @size: Size of the passed buffer - * @return 0 if OK, -ve on error + * Return: 0 if OK, -ve on error */ int (*get_status)(struct udevice *dev, char *buf, int size); /** - * get_last() - get information on the last reset + * @get_last: get information on the last reset * * @dev: Device to check - * @return last reset state (enum sysreset_t) or -ve error + * Return: last reset state (enum :enum:`sysreset_t`) or -ve error */ int (*get_last)(struct udevice *dev); }; @@ -55,8 +67,9 @@ struct sysreset_ops { /** * sysreset_request() - request a sysreset * + * @dev: Device to be used for system reset * @type: Reset type to request - * @return 0 if OK, -EPROTONOSUPPORT if not supported by this device + * Return: 0 if OK, -EPROTONOSUPPORT if not supported by this device */ int sysreset_request(struct udevice *dev, enum sysreset_t type); @@ -66,7 +79,7 @@ int sysreset_request(struct udevice *dev, enum sysreset_t type); * @dev: Device to check * @buf: Buffer to receive the textual reset information * @size: Size of the passed buffer - * @return 0 if OK, -ve on error + * Return: 0 if OK, -ve on error */ int sysreset_get_status(struct udevice *dev, char *buf, int size); @@ -74,7 +87,7 @@ int sysreset_get_status(struct udevice *dev, char *buf, int size); * sysreset_get_last() - get information on the last reset * * @dev: Device to check - * @return last reset state (enum sysreset_t) or -ve error + * Return: last reset state (enum sysreset_t) or -ve error */ int sysreset_get_last(struct udevice *dev); @@ -88,7 +101,7 @@ int sysreset_get_last(struct udevice *dev); * If this function fails to reset, it will display a message and halt * * @type: Reset type to request - * @return -EINPROGRESS if a reset is in progress, -ENOSYS if not available + * Return: -EINPROGRESS if a reset is in progress, -ENOSYS if not available */ int sysreset_walk(enum sysreset_t type); @@ -101,7 +114,7 @@ int sysreset_walk(enum sysreset_t type); * * If no device prives the information, this function returns -ENOENT * - * @return last reset state (enum sysreset_t) or -ve error + * Return: last reset state (enum sysreset_t) or -ve error */ int sysreset_get_last_walk(void); @@ -110,6 +123,8 @@ int sysreset_get_last_walk(void); * * This calls sysreset_walk(). If it returns, indicating that reset is not * supported, it prints a message and halts. + * + * @type: Reset type to request */ void sysreset_walk_halt(enum sysreset_t type); From 2443fd7032ffb28626f5705b9003269196d1e0f4 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Mon, 11 Oct 2021 14:59:48 +0200 Subject: [PATCH 03/21] doc: add python3-pkg-resources to build dependencies tools/binman/control.py imports Python package pkg_resources. Signed-off-by: Heinrich Schuchardt Reviewed-by: Simon Glass --- doc/build/gcc.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/build/gcc.rst b/doc/build/gcc.rst index 6c4b4ad7a0..cdd7970032 100644 --- a/doc/build/gcc.rst +++ b/doc/build/gcc.rst @@ -27,9 +27,9 @@ Depending on the build targets further packages maybe needed device-tree-compiler dfu-util efitools flex gdisk graphviz imagemagick \ liblz4-tool libguestfs-tools libncurses-dev libpython3-dev libsdl2-dev \ libssl-dev lz4 lzma lzma-alone openssl pkg-config python3 \ - python3-coverage python3-pycryptodome python3-pyelftools python3-pytest \ - python3-sphinxcontrib.apidoc python3-sphinx-rtd-theme python3-virtualenv \ - swig + python3-coverage python3-pkg-resources python3-pycryptodome \ + python3-pyelftools python3-pytest python3-sphinxcontrib.apidoc \ + python3-sphinx-rtd-theme python3-virtualenv swig SUSE based ~~~~~~~~~~ From 0c83c8ac407e4d889c4c0541070c191a3d977299 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Tue, 19 Oct 2021 09:25:52 +0200 Subject: [PATCH 04/21] doc: Remove obsolete README.440-DDR-performance file The PPC 440 support has been removed in commit 98f705c9cefd ("powerpc: remove 4xx support") already, so this file is certainly not required anymore. Signed-off-by: Thomas Huth Reviewed-by: Stefan Roese --- doc/README.440-DDR-performance | 90 ---------------------------------- 1 file changed, 90 deletions(-) delete mode 100644 doc/README.440-DDR-performance diff --git a/doc/README.440-DDR-performance b/doc/README.440-DDR-performance deleted file mode 100644 index 66b97bc9b5..0000000000 --- a/doc/README.440-DDR-performance +++ /dev/null @@ -1,90 +0,0 @@ -AMCC suggested to set the PMU bit to 0 for best performace on the -PPC440 DDR controller. The 440er common DDR setup files (sdram.c & -spd_sdram.c) are changed accordingly. So all 440er boards using -these setup routines will automatically receive this performance -increase. - -Please see below some benchmarks done by AMCC to demonstrate this -performance changes: - - ----------------------------------------- -SDRAM0_CFG0[PMU] = 1 (U-Boot default for Bamboo, Yosemite and Yellowstone) ----------------------------------------- -Stream benchmark results -------------------------------------------------------------- -This system uses 8 bytes per DOUBLE PRECISION word. -------------------------------------------------------------- -Array size = 2000000, Offset = 0 -Total memory required = 45.8 MB. -Each test is run 10 times, but only -the *best* time for each is used. -------------------------------------------------------------- -Your clock granularity/precision appears to be 1 microseconds. -Each test below will take on the order of 112345 microseconds. - (= 112345 clock ticks) -Increase the size of the arrays if this shows that you are not getting -at least 20 clock ticks per test. -------------------------------------------------------------- -WARNING -- The above is only a rough guideline. -For best results, please be sure you know the precision of your system -timer. -------------------------------------------------------------- -Function Rate (MB/s) RMS time Min time Max time -Copy: 256.7683 0.1248 0.1246 0.1250 -Scale: 246.0157 0.1302 0.1301 0.1302 -Add: 255.0316 0.1883 0.1882 0.1885 -Triad: 253.1245 0.1897 0.1896 0.1899 - - -TTCP Benchmark Results -ttcp-t: socket -ttcp-t: connect -ttcp-t: buflen=8192, nbuf=2048, align=16384/0, port=5000 tcp -> -localhost -ttcp-t: 16777216 bytes in 0.28 real seconds = 454.29 Mbit/sec +++ -ttcp-t: 2048 I/O calls, msec/call = 0.14, calls/sec = 7268.57 -ttcp-t: 0.0user 0.1sys 0:00real 60% 0i+0d 0maxrss 0+2pf 3+1506csw - ----------------------------------------- -SDRAM0_CFG0[PMU] = 0 (Suggested modification) -Setting PMU = 0 provides a noticeable performance improvement *2% to -5% improvement in memory performance. -*Improves the Mbit/sec for TTCP benchmark by almost 76%. ----------------------------------------- -Stream benchmark results -------------------------------------------------------------- -This system uses 8 bytes per DOUBLE PRECISION word. -------------------------------------------------------------- -Array size = 2000000, Offset = 0 -Total memory required = 45.8 MB. -Each test is run 10 times, but only -the *best* time for each is used. -------------------------------------------------------------- -Your clock granularity/precision appears to be 1 microseconds. -Each test below will take on the order of 120066 microseconds. - (= 120066 clock ticks) -Increase the size of the arrays if this shows that you are not getting -at least 20 clock ticks per test. -------------------------------------------------------------- -WARNING -- The above is only a rough guideline. -For best results, please be sure you know the precision of your system -timer. -------------------------------------------------------------- -Function Rate (MB/s) RMS time Min time Max time -Copy: 262.5167 0.1221 0.1219 0.1223 -Scale: 258.4856 0.1238 0.1238 0.1240 -Add: 262.5404 0.1829 0.1828 0.1831 -Triad: 266.8594 0.1800 0.1799 0.1802 - -TTCP Benchmark Results -ttcp-t: socket -ttcp-t: connect -ttcp-t: buflen=8192, nbuf=2048, align=16384/0, port=5000 tcp -> -localhost -ttcp-t: 16777216 bytes in 0.16 real seconds = 804.06 Mbit/sec +++ -ttcp-t: 2048 I/O calls, msec/call = 0.08, calls/sec = 12864.89 -ttcp-t: 0.0user 0.0sys 0:00real 46% 0i+0d 0maxrss 0+2pf 120+1csw - - -2006-07-28, Stefan Roese From 6b7b9ff14daa130f220310810963acb9e0c36c6d Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Thu, 9 Sep 2021 07:27:10 +0200 Subject: [PATCH 05/21] configs: add mkeficapsule to tools-only_defconfig mkeficapsule is used to create capsules for UEFI firmware update. To ease inclusion into U-Boot tools packages of Linux distributions we should add it to the tools-only_defconfig. Provide dummy values for CONFIG_AVB_BUF_ADDR, CONFIG_AVB_BUF_SIZE to satisfy Kconfig. Suggested-by: Vagrant Cascadian Signed-off-by: Heinrich Schuchardt Signed-off-by: Heinrich Schuchardt --- configs/tools-only_defconfig | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/configs/tools-only_defconfig b/configs/tools-only_defconfig index 64a015b355..d0e34cb7fa 100644 --- a/configs/tools-only_defconfig +++ b/configs/tools-only_defconfig @@ -7,6 +7,8 @@ CONFIG_ANDROID_BOOT_IMAGE=y CONFIG_FIT=y CONFIG_FIT_SIGNATURE=y CONFIG_MISC_INIT_F=y +CONFIG_AVB_BUF_ADDR=0x0 +CONFIG_AVB_BUF_SIZE=0x8192 # CONFIG_CMD_BOOTD is not set # CONFIG_CMD_BOOTM is not set # CONFIG_CMD_ELF is not set @@ -31,4 +33,7 @@ CONFIG_SYSRESET=y # CONFIG_VIRTIO_MMIO is not set # CONFIG_VIRTIO_PCI is not set # CONFIG_VIRTIO_SANDBOX is not set -# CONFIG_EFI_LOADER is not set +CONFIG_EFI_CAPSULE_ON_DISK=y +CONFIG_EFI_CAPSULE_FIRMWARE_FIT=y +CONFIG_EFI_CAPSULE_FIRMWARE_RAW=y +CONFIG_EFI_CAPSULE_AUTHENTICATE=y From 39a37adf51f88aca245c40ce8652be5c9c5277b9 Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Thu, 16 Sep 2021 17:53:27 +0900 Subject: [PATCH 06/21] efi_selftest: Use EFI_SIMPLE_NETWORK_PROTOCOL::GetStatus() for media check According to the UEF specification v2.9, the main purpose of the EFI_SIMPLE_NETWORK_PROTOCOL::GetStatus() is for checking the link status via EFI_SIMPLE_NETWORK_MODE::MediaPresent. So this uses net->get_status() for checking the link status before running network test. Signed-off-by: Masami Hiramatsu Reviewed-by: Heinrich Schuchardt --- lib/efi_selftest/efi_selftest_snp.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/lib/efi_selftest/efi_selftest_snp.c b/lib/efi_selftest/efi_selftest_snp.c index 79f0467803..cb0db7eea2 100644 --- a/lib/efi_selftest/efi_selftest_snp.c +++ b/lib/efi_selftest/efi_selftest_snp.c @@ -309,6 +309,18 @@ static int execute(void) return EFI_ST_FAILURE; } + /* Check media connected */ + ret = net->get_status(net, NULL, NULL); + if (ret != EFI_SUCCESS) { + efi_st_error("Failed to get status"); + return EFI_ST_FAILURE; + } + if (net->mode && net->mode->media_present_supported && + !net->mode->media_present) { + efi_st_error("Network media is not connected"); + return EFI_ST_FAILURE; + } + /* * Send DHCP discover message */ From 9845b924369cc71457a21e78b5f9e6f7af43532d Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Thu, 16 Sep 2021 17:53:36 +0900 Subject: [PATCH 07/21] efi_selftest: Do not check EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT Do not check EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT in packet receiving loop. This depends on the implementation and not related to whether the packet can be received or not. Whether the received packets are available or not is ensured by wait_for_packet, and that is already done in the loop. Signed-off-by: Masami Hiramatsu Reviewed-by: Heinrich Schuchardt --- lib/efi_selftest/efi_selftest_snp.c | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/lib/efi_selftest/efi_selftest_snp.c b/lib/efi_selftest/efi_selftest_snp.c index cb0db7eea2..c5366c872c 100644 --- a/lib/efi_selftest/efi_selftest_snp.c +++ b/lib/efi_selftest/efi_selftest_snp.c @@ -340,8 +340,6 @@ static int execute(void) events[0] = timer; events[1] = net->wait_for_packet; for (;;) { - u32 int_status; - /* * Wait for packet to be received or timer event. */ @@ -367,15 +365,6 @@ static int execute(void) * Receive packet */ buffer_size = sizeof(buffer); - ret = net->get_status(net, &int_status, NULL); - if (ret != EFI_SUCCESS) { - efi_st_error("Failed to get status"); - return EFI_ST_FAILURE; - } - if (!(int_status & EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT)) { - efi_st_error("RX interrupt not set"); - return EFI_ST_FAILURE; - } ret = net->receive(net, NULL, &buffer_size, &buffer, &srcaddr, &destaddr, NULL); if (ret != EFI_SUCCESS) { From 28fc87ee3ae8730fc556757cff05480b5cf94381 Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Thu, 16 Sep 2021 17:53:44 +0900 Subject: [PATCH 08/21] efi_selftest: Receive the packets until the receive buffer is empty Repeatedly receive the packets until the receive buffer is empty. If the buffer is empty, EFI_SIMPLE_NETWORK_PROTOCOL::Receive() returns EFI_NOT_READY. We don't need to use the wait_for_event() every time. Signed-off-by: Masami Hiramatsu Reviewed-by: Heinrich Schuchardt --- lib/efi_selftest/efi_selftest_snp.c | 69 ++++++++++++++++------------- 1 file changed, 38 insertions(+), 31 deletions(-) diff --git a/lib/efi_selftest/efi_selftest_snp.c b/lib/efi_selftest/efi_selftest_snp.c index c5366c872c..818cbfcacd 100644 --- a/lib/efi_selftest/efi_selftest_snp.c +++ b/lib/efi_selftest/efi_selftest_snp.c @@ -362,39 +362,46 @@ static int execute(void) continue; } /* - * Receive packet + * Receive packets until buffer is empty */ - buffer_size = sizeof(buffer); - ret = net->receive(net, NULL, &buffer_size, &buffer, - &srcaddr, &destaddr, NULL); - if (ret != EFI_SUCCESS) { - efi_st_error("Failed to receive packet"); - return EFI_ST_FAILURE; - } - /* - * Check the packet is meant for this system. - * Unfortunately QEMU ignores the broadcast flag. - * So we have to check for broadcasts too. - */ - if (memcmp(&destaddr, &net->mode->current_address, ARP_HLEN) && - memcmp(&destaddr, BROADCAST_MAC, ARP_HLEN)) - continue; - /* - * Check this is a DHCP reply - */ - if (buffer.p.eth_hdr.et_protlen != ntohs(PROT_IP) || - buffer.p.ip_udp.ip_hl_v != 0x45 || - buffer.p.ip_udp.ip_p != IPPROTO_UDP || - buffer.p.ip_udp.udp_src != ntohs(67) || - buffer.p.ip_udp.udp_dst != ntohs(68) || - buffer.p.dhcp_hdr.op != BOOTREPLY) - continue; - /* - * We successfully received a DHCP reply. - */ - break; - } + for (;;) { + buffer_size = sizeof(buffer); + ret = net->receive(net, NULL, &buffer_size, &buffer, + &srcaddr, &destaddr, NULL); + if (ret == EFI_NOT_READY) { + /* The received buffer is empty. */ + break; + } + if (ret != EFI_SUCCESS) { + efi_st_error("Failed to receive packet"); + return EFI_ST_FAILURE; + } + /* + * Check the packet is meant for this system. + * Unfortunately QEMU ignores the broadcast flag. + * So we have to check for broadcasts too. + */ + if (memcmp(&destaddr, &net->mode->current_address, ARP_HLEN) && + memcmp(&destaddr, BROADCAST_MAC, ARP_HLEN)) + continue; + /* + * Check this is a DHCP reply + */ + if (buffer.p.eth_hdr.et_protlen != ntohs(PROT_IP) || + buffer.p.ip_udp.ip_hl_v != 0x45 || + buffer.p.ip_udp.ip_p != IPPROTO_UDP || + buffer.p.ip_udp.udp_src != ntohs(67) || + buffer.p.ip_udp.udp_dst != ntohs(68) || + buffer.p.dhcp_hdr.op != BOOTREPLY) + continue; + /* + * We successfully received a DHCP reply. + */ + goto received; + } + } +received: /* * Write a log message. */ From c779e0d923189a85eb1fa3a0a214541cf4795a19 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Fri, 24 Sep 2021 18:30:17 -0600 Subject: [PATCH 09/21] efi_loader: Drop code that doesn't work with driver model This code should never have been added as it builds a new feature on top of legacy code. This has already been improved with the dependency on BLK. Add a dependency on DM_ETH also, to avoid needing to deal with this old code. Boards which want EFI_LOADER should migrate to driver model first. Signed-off-by: Simon Glass Reviewed-by: Heinrich Schuchardt --- lib/efi_driver/Makefile | 2 +- lib/efi_loader/Kconfig | 1 + lib/efi_loader/efi_device_path.c | 94 +++++++------------------------- lib/efi_loader/efi_disk.c | 48 ---------------- 4 files changed, 22 insertions(+), 123 deletions(-) diff --git a/lib/efi_driver/Makefile b/lib/efi_driver/Makefile index 83baa1c9a4..f2b6c05cc2 100644 --- a/lib/efi_driver/Makefile +++ b/lib/efi_driver/Makefile @@ -6,6 +6,6 @@ # object inclusion implicitly depends on it obj-y += efi_uclass.o -ifeq ($(CONFIG_BLK)$(CONFIG_PARTITIONS),yy) +ifeq ($(CONFIG_PARTITIONS),y) obj-y += efi_block_device.o endif diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig index 83d584a60e..06633e90a1 100644 --- a/lib/efi_loader/Kconfig +++ b/lib/efi_loader/Kconfig @@ -11,6 +11,7 @@ config EFI_LOADER # We need EFI_STUB_32BIT to be set on x86_32 with EFI_STUB depends on !EFI_STUB || !X86 || X86_64 || EFI_STUB_32BIT depends on BLK + depends on DM_ETH || !NET default y if !ARM || SYS_CPU = armv7 || SYS_CPU = armv8 select LIB_UUID select PARTITION_UUIDS diff --git a/lib/efi_loader/efi_device_path.c b/lib/efi_loader/efi_device_path.c index cbdb466da4..a09090a32e 100644 --- a/lib/efi_loader/efi_device_path.c +++ b/lib/efi_loader/efi_device_path.c @@ -46,7 +46,7 @@ static const struct efi_device_path_vendor ROOT = { .guid = U_BOOT_GUID, }; -#if defined(CONFIG_DM_MMC) && defined(CONFIG_MMC) +#if defined(CONFIG_MMC) /* * Determine if an MMC device is an SD card. * @@ -486,7 +486,6 @@ bool efi_dp_is_multi_instance(const struct efi_device_path *dp) return p->sub_type == DEVICE_PATH_SUB_TYPE_INSTANCE_END; } -#ifdef CONFIG_DM /* size of device-path not including END node for device and all parents * up to the root device. */ @@ -503,7 +502,6 @@ __maybe_unused static unsigned int dp_size(struct udevice *dev) case UCLASS_ETH: return dp_size(dev->parent) + sizeof(struct efi_device_path_mac_addr); -#ifdef CONFIG_BLK case UCLASS_BLK: switch (dev->parent->uclass->uc_drv->id) { #ifdef CONFIG_IDE @@ -511,12 +509,12 @@ __maybe_unused static unsigned int dp_size(struct udevice *dev) return dp_size(dev->parent) + sizeof(struct efi_device_path_atapi); #endif -#if defined(CONFIG_SCSI) && defined(CONFIG_DM_SCSI) +#if defined(CONFIG_SCSI) case UCLASS_SCSI: return dp_size(dev->parent) + sizeof(struct efi_device_path_scsi); #endif -#if defined(CONFIG_DM_MMC) && defined(CONFIG_MMC) +#if defined(CONFIG_MMC) case UCLASS_MMC: return dp_size(dev->parent) + sizeof(struct efi_device_path_sd_mmc_path); @@ -554,8 +552,7 @@ __maybe_unused static unsigned int dp_size(struct udevice *dev) default: return dp_size(dev->parent); } -#endif -#if defined(CONFIG_DM_MMC) && defined(CONFIG_MMC) +#if defined(CONFIG_MMC) case UCLASS_MMC: return dp_size(dev->parent) + sizeof(struct efi_device_path_sd_mmc_path); @@ -590,7 +587,7 @@ __maybe_unused static void *dp_fill(void *buf, struct udevice *dev) *vdp = ROOT; return &vdp[1]; } -#ifdef CONFIG_DM_ETH +#ifdef CONFIG_NET case UCLASS_ETH: { struct efi_device_path_mac_addr *dp = dp_fill(buf, dev->parent); @@ -607,7 +604,6 @@ __maybe_unused static void *dp_fill(void *buf, struct udevice *dev) return &dp[1]; } #endif -#ifdef CONFIG_BLK case UCLASS_BLK: switch (dev->parent->uclass->uc_drv->id) { #ifdef CONFIG_SANDBOX @@ -662,7 +658,7 @@ __maybe_unused static void *dp_fill(void *buf, struct udevice *dev) return &dp[1]; } #endif -#if defined(CONFIG_SCSI) && defined(CONFIG_DM_SCSI) +#if defined(CONFIG_SCSI) case UCLASS_SCSI: { struct efi_device_path_scsi *dp = dp_fill(buf, dev->parent); @@ -676,7 +672,7 @@ __maybe_unused static void *dp_fill(void *buf, struct udevice *dev) return &dp[1]; } #endif -#if defined(CONFIG_DM_MMC) && defined(CONFIG_MMC) +#if defined(CONFIG_MMC) case UCLASS_MMC: { struct efi_device_path_sd_mmc_path *sddp = dp_fill(buf, dev->parent); @@ -727,8 +723,7 @@ __maybe_unused static void *dp_fill(void *buf, struct udevice *dev) dev->name, dev->parent->uclass->uc_drv->id); return dp_fill(buf, dev->parent); } -#endif -#if defined(CONFIG_DM_MMC) && defined(CONFIG_MMC) +#if defined(CONFIG_MMC) case UCLASS_MMC: { struct efi_device_path_sd_mmc_path *sddp = dp_fill(buf, dev->parent); @@ -770,24 +765,18 @@ __maybe_unused static void *dp_fill(void *buf, struct udevice *dev) return dp_fill(buf, dev->parent); } } -#endif static unsigned dp_part_size(struct blk_desc *desc, int part) { unsigned dpsize; + struct udevice *dev; + int ret; -#ifdef CONFIG_BLK - { - struct udevice *dev; - int ret = blk_find_device(desc->if_type, desc->devnum, &dev); + ret = blk_find_device(desc->if_type, desc->devnum, &dev); - if (ret) - dev = desc->bdev->parent; - dpsize = dp_size(dev); - } -#else - dpsize = sizeof(ROOT) + sizeof(struct efi_device_path_usb); -#endif + if (ret) + dev = desc->bdev->parent; + dpsize = dp_size(dev); if (part == 0) /* the actual disk, not a partition */ return dpsize; @@ -877,36 +866,14 @@ static void *dp_part_node(void *buf, struct blk_desc *desc, int part) */ static void *dp_part_fill(void *buf, struct blk_desc *desc, int part) { -#ifdef CONFIG_BLK - { - struct udevice *dev; - int ret = blk_find_device(desc->if_type, desc->devnum, &dev); + struct udevice *dev; + int ret; - if (ret) - dev = desc->bdev->parent; - buf = dp_fill(buf, dev); - } -#else - /* - * We *could* make a more accurate path, by looking at if_type - * and handling all the different cases like we do for non- - * legacy (i.e. CONFIG_BLK=y) case. But most important thing - * is just to have a unique device-path for if_type+devnum. - * So map things to a fictitious USB device. - */ - struct efi_device_path_usb *udp; + ret = blk_find_device(desc->if_type, desc->devnum, &dev); - memcpy(buf, &ROOT, sizeof(ROOT)); - buf += sizeof(ROOT); - - udp = buf; - udp->dp.type = DEVICE_PATH_TYPE_MESSAGING_DEVICE; - udp->dp.sub_type = DEVICE_PATH_SUB_TYPE_MSG_USB; - udp->dp.length = sizeof(*udp); - udp->parent_port_number = desc->if_type; - udp->usb_interface = desc->devnum; - buf = &udp[1]; -#endif + if (ret) + dev = desc->bdev->parent; + buf = dp_fill(buf, dev); if (part == 0) /* the actual disk, not a partition */ return buf; @@ -1051,39 +1018,18 @@ struct efi_device_path *efi_dp_from_uart(void) #ifdef CONFIG_NET struct efi_device_path *efi_dp_from_eth(void) { -#ifndef CONFIG_DM_ETH - struct efi_device_path_mac_addr *ndp; -#endif void *buf, *start; unsigned dpsize = 0; assert(eth_get_dev()); -#ifdef CONFIG_DM_ETH dpsize += dp_size(eth_get_dev()); -#else - dpsize += sizeof(ROOT); - dpsize += sizeof(*ndp); -#endif start = buf = dp_alloc(dpsize + sizeof(END)); if (!buf) return NULL; -#ifdef CONFIG_DM_ETH buf = dp_fill(buf, eth_get_dev()); -#else - memcpy(buf, &ROOT, sizeof(ROOT)); - buf += sizeof(ROOT); - - ndp = buf; - ndp->dp.type = DEVICE_PATH_TYPE_MESSAGING_DEVICE; - ndp->dp.sub_type = DEVICE_PATH_SUB_TYPE_MSG_MAC_ADDR; - ndp->dp.length = sizeof(*ndp); - ndp->if_type = 1; /* Ethernet */ - memcpy(ndp->mac.addr, eth_get_ethaddr(), ARP_HLEN); - buf = &ndp[1]; -#endif *((struct efi_device_path *)buf) = END; diff --git a/lib/efi_loader/efi_disk.c b/lib/efi_loader/efi_disk.c index 988907ecb9..ef8b5c88ff 100644 --- a/lib/efi_loader/efi_disk.c +++ b/lib/efi_loader/efi_disk.c @@ -555,7 +555,6 @@ efi_status_t efi_disk_register(void) struct efi_disk_obj *disk; int disks = 0; efi_status_t ret; -#ifdef CONFIG_BLK struct udevice *dev; for (uclass_first_device_check(UCLASS_BLK, &dev); dev; @@ -583,54 +582,7 @@ efi_status_t efi_disk_register(void) &disk->header, desc, if_typename, desc->devnum, dev->name); } -#else - int i, if_type; - /* Search for all available disk devices */ - for (if_type = 0; if_type < IF_TYPE_COUNT; if_type++) { - const struct blk_driver *cur_drvr; - const char *if_typename; - - cur_drvr = blk_driver_lookup_type(if_type); - if (!cur_drvr) - continue; - - if_typename = cur_drvr->if_typename; - log_info("Scanning disks on %s...\n", if_typename); - for (i = 0; i < 4; i++) { - struct blk_desc *desc; - char devname[32] = { 0 }; /* dp->str is u16[32] long */ - - desc = blk_get_devnum_by_type(if_type, i); - if (!desc) - continue; - if (desc->type == DEV_TYPE_UNKNOWN) - continue; - - snprintf(devname, sizeof(devname), "%s%d", - if_typename, i); - - /* Add block device for the full device */ - ret = efi_disk_add_dev(NULL, NULL, if_typename, desc, - i, NULL, 0, &disk); - if (ret == EFI_NOT_READY) { - log_notice("Disk %s not ready\n", devname); - continue; - } - if (ret) { - log_err("ERROR: failure to add disk device %s, r = %lu\n", - devname, ret & ~EFI_ERROR_MASK); - return ret; - } - disks++; - - /* Partitions show up as block devices in EFI */ - disks += efi_disk_create_partitions - (&disk->header, desc, - if_typename, i, devname); - } - } -#endif log_info("Found %d disks\n", disks); return EFI_SUCCESS; From 91aa8476b2e6a5391677e08280db0e36ca1dd143 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Fri, 24 Sep 2021 18:30:18 -0600 Subject: [PATCH 10/21] efi: Add a separate maintainer entry for the app Separate this out slightly from the payload, with a new entry. We might consider renaming EFI PAYLOAD to EFI LOADER, but that would require quite a lot of file changes. Signed-off-by: Simon Glass Reviewed-by: Heinrich Schuchardt --- MAINTAINERS | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 8845c6fd75..5069f18806 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -693,6 +693,13 @@ F: drivers/core/ F: include/dm/ F: test/dm/ +EFI APP +M: Simon Glass +M: Heinrich Schuchardt +S: Maintained +W: https://u-boot.readthedocs.io/en/latest/develop/uefi/u-boot_on_efi.html +F: lib/efi/efi_app.c + EFI PAYLOAD M: Heinrich Schuchardt R: Alexander Graf From 8d76744e50115ee4fa94ace1f15103b0d1cfe3fb Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Fri, 24 Sep 2021 18:30:19 -0600 Subject: [PATCH 11/21] x86: Keep symbol information in u-boot ELF file At present this information is stripped when linking. It is useful to keep it around. Strip it from the .efi files instead. Signed-off-by: Simon Glass Signed-off-by: Heinrich Schuchardt --- arch/x86/config.mk | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/x86/config.mk b/arch/x86/config.mk index 7a8242562d..589f2aed2b 100644 --- a/arch/x86/config.mk +++ b/arch/x86/config.mk @@ -37,7 +37,7 @@ KBUILD_LDFLAGS += -m $(if $(IS_32BIT),elf_i386,elf_x86_64) LDFLAGS_EFI_PAYLOAD := -Bsymbolic -Bsymbolic-functions -shared --no-undefined -s OBJCOPYFLAGS_EFI := -j .text -j .sdata -j .data -j .dynamic -j .dynsym \ - -j .rel -j .rela -j .reloc + -j .rel -j .rela -j .reloc --strip-all # Compiler flags to be added when building UEFI applications CFLAGS_EFI := -fpic -fshort-wchar @@ -65,7 +65,7 @@ CPPFLAGS_crt0-efi-$(EFIARCH).o += $(CFLAGS_EFI) ifeq ($(CONFIG_EFI_APP),y) PLATFORM_CPPFLAGS += $(CFLAGS_EFI) -LDFLAGS_FINAL += -znocombreloc -shared -s +LDFLAGS_FINAL += -znocombreloc -shared LDSCRIPT := $(LDSCRIPT_EFI) else From e70be676ebc718b7d12caf56b24e8db383ccee62 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Fri, 24 Sep 2021 18:30:20 -0600 Subject: [PATCH 12/21] x86: Create a new header for EFI The setup routines are called from zimage but don't really belong in the zimage header. Add a new EFI header to house these. Add comments so it is clear what the functions do. Note that these functions are x86-specific. The zimage business is not used on other architectures. Signed-off-by: Simon Glass Reviewed-by: Heinrich Schuchardt --- arch/x86/include/asm/efi.h | 32 ++++++++++++++++++++++++++++++++ arch/x86/include/asm/zimage.h | 3 --- arch/x86/lib/zimage.c | 1 + 3 files changed, 33 insertions(+), 3 deletions(-) create mode 100644 arch/x86/include/asm/efi.h diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h new file mode 100644 index 0000000000..c1735e4dc5 --- /dev/null +++ b/arch/x86/include/asm/efi.h @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright Google LLC + */ + +#ifndef _ASM_EFI_H_ +#define _ASM_EFI_H_ + +struct efi_info; +struct screen_info; + +/** + * setup_video() - Set up the screen info in the x86 setup + * + * This is needed so Linux can use the display (when U-Boot is an EFI payload) + * + * @efi_info: Pointer to place to put the screen info in the x86 setup base + */ +void setup_video(struct screen_info *screen_info); + +/** + * setup_efi_info() - Set up the EFI info needed by Linux to boot + * + * This writes a suitable signature, table pointers, memory-map pointer, etc. + * These are needed for Linux to boot from U-Boot (when U-Boot is an EFI + * payload). + * + * @efi_info: Pointer to place to put the EFI info in the x86 setup base + */ +void setup_efi_info(struct efi_info *efi_info); + +#endif diff --git a/arch/x86/include/asm/zimage.h b/arch/x86/include/asm/zimage.h index 6679767d16..fa6e7f76e0 100644 --- a/arch/x86/include/asm/zimage.h +++ b/arch/x86/include/asm/zimage.h @@ -72,7 +72,4 @@ int setup_zimage(struct boot_params *setup_base, char *cmd_line, int auto_boot, */ void zimage_dump(struct boot_params *base_ptr); -void setup_video(struct screen_info *screen_info); -void setup_efi_info(struct efi_info *efi_info); - #endif diff --git a/arch/x86/lib/zimage.c b/arch/x86/lib/zimage.c index 9938c80a42..7ce02226ef 100644 --- a/arch/x86/lib/zimage.c +++ b/arch/x86/lib/zimage.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #ifdef CONFIG_SYS_COREBOOT #include From 567dfef2fe4affe28e8e65b54677f24995b98a5e Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Fri, 24 Sep 2021 18:30:21 -0600 Subject: [PATCH 13/21] x86: Show some EFI info with the bdinfo command It is useful to see some basic EFI info with the command as it forms part of the information about a board. Add a hook for this and show the table address as a start. While here, fix an invalid cast in setup_efi_info(). Note that this function is using a data structure defined by Linux so we cannot change it. Also note that ulong is used since this is the standard in U-Boot (>6k uses), despite there being quite a bit of the more verbose uintptr_t (930 uses). Signed-off-by: Simon Glass Reviewed-by: Heinrich Schuchardt --- arch/x86/cpu/efi/payload.c | 13 +++++++++++-- arch/x86/include/asm/efi.h | 7 +++++++ arch/x86/lib/Makefile | 1 + arch/x86/lib/bdinfo.c | 22 ++++++++++++++++++++++ 4 files changed, 41 insertions(+), 2 deletions(-) create mode 100644 arch/x86/lib/bdinfo.c diff --git a/arch/x86/cpu/efi/payload.c b/arch/x86/cpu/efi/payload.c index 9a73b768e9..3a9f7d7286 100644 --- a/arch/x86/cpu/efi/payload.c +++ b/arch/x86/cpu/efi/payload.c @@ -280,15 +280,24 @@ void setup_efi_info(struct efi_info *efi_info) } efi_info->efi_memdesc_size = map->desc_size; efi_info->efi_memdesc_version = map->version; - efi_info->efi_memmap = (u32)(map->desc); + efi_info->efi_memmap = (ulong)(map->desc); efi_info->efi_memmap_size = size - sizeof(struct efi_entry_memmap); #ifdef CONFIG_EFI_STUB_64BIT efi_info->efi_systab_hi = table->sys_table >> 32; - efi_info->efi_memmap_hi = (u64)(u32)(map->desc) >> 32; + efi_info->efi_memmap_hi = (u64)(ulong)map->desc >> 32; signature = EFI64_LOADER_SIGNATURE; #else signature = EFI32_LOADER_SIGNATURE; #endif memcpy(&efi_info->efi_loader_signature, signature, 4); } + +void efi_show_bdinfo(void) +{ + struct efi_entry_systable *table = NULL; + int size, ret; + + ret = efi_info_get(EFIET_SYS_TABLE, (void **)&table, &size); + bdinfo_print_num_l("efi_table", (ulong)table); +} diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h index c1735e4dc5..dfd858b78b 100644 --- a/arch/x86/include/asm/efi.h +++ b/arch/x86/include/asm/efi.h @@ -29,4 +29,11 @@ void setup_video(struct screen_info *screen_info); */ void setup_efi_info(struct efi_info *efi_info); +/** + * efi_show_bdinfo() - Show information about EFI for the 'bdinfo' command + * + * This looks up the EFI table pointer and shows related info + */ +void efi_show_bdinfo(void); + #endif diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile index 65d9b3bd6a..18757b29aa 100644 --- a/arch/x86/lib/Makefile +++ b/arch/x86/lib/Makefile @@ -3,6 +3,7 @@ # (C) Copyright 2002-2006 # Wolfgang Denk, DENX Software Engineering, wd@denx.de. +obj-y += bdinfo.o ifndef CONFIG_X86_64 ifndef CONFIG_TPL_BUILD obj-y += bios.o diff --git a/arch/x86/lib/bdinfo.c b/arch/x86/lib/bdinfo.c new file mode 100644 index 0000000000..0cb79b01bd --- /dev/null +++ b/arch/x86/lib/bdinfo.c @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * x86-specific information for the 'bd' command + * + * Copyright 2021 Google LLC + */ + +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +void arch_print_bdinfo(void) +{ + bdinfo_print_num_l("prev table", gd->arch.table); + + if (IS_ENABLED(CONFIG_EFI_STUB)) + efi_show_bdinfo(); +} From fa00b6fc3f86c88bf7afe00253340f529eeacb6d Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Wed, 6 Oct 2021 14:10:14 +0200 Subject: [PATCH 14/21] efi_loader: don't load Shim's MOK database from file When using a file to store UEFI variables we must make sure that secure boot related variables are not loaded from this file. With commit 9ef82e29478c ("efi_loader: don't load signature database from file") this has already been implemented for variables defined in the UEFI specification. As most Linux distributions use Shim we should do the same for Shim's MOK database. Signed-off-by: Heinrich Schuchardt --- lib/efi_loader/efi_var_file.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/efi_loader/efi_var_file.c b/lib/efi_loader/efi_var_file.c index c7c6805ed0..76a2ff9e41 100644 --- a/lib/efi_loader/efi_var_file.c +++ b/lib/efi_loader/efi_var_file.c @@ -19,6 +19,13 @@ #define PART_STR_LEN 10 +/* GUID used by Shim to store the MOK database */ +#define SHIM_LOCK_GUID \ + EFI_GUID(0x605dab50, 0xe046, 0x4300, \ + 0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23) + +static const efi_guid_t shim_lock_guid = SHIM_LOCK_GUID; + /** * efi_set_blk_dev_to_system_partition() - select EFI system partition * @@ -175,6 +182,7 @@ efi_status_t efi_var_restore(struct efi_var_file *buf, bool safe) if (!safe && (efi_auth_var_get_type(var->name, &var->guid) != EFI_AUTH_VAR_NONE || + !guidcmp(&var->guid, &shim_lock_guid) || !(var->attr & EFI_VARIABLE_NON_VOLATILE))) continue; if (!var->length) From ebdea88d57d5e67b8f6e6cf615300eedbc7200a9 Mon Sep 17 00:00:00 2001 From: Ilias Apalodimas Date: Mon, 11 Oct 2021 15:10:23 +0300 Subject: [PATCH 15/21] efi_loader: Fix loaded image alignment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We are ignoring the alignment communicated via the PE/COFF header. Starting 5.10 the Linux kernel will loudly complain about it. For more details look at [1] (in linux kernel). So add a function that can allocate aligned EFI memory and use it for our relocated loaded image. [1] c32ac11da3f83 ("efi/libstub: arm64: Double check image alignment at entry") Signed-off-by: Ilias Apalodimas Tested-by: Vincent Stehlé Acked-by: Ard Biesheuvel Reviewed-by: Heinrich Schuchardt --- include/efi_loader.h | 2 ++ lib/efi_loader/efi_image_loader.c | 12 +++---- lib/efi_loader/efi_memory.c | 52 +++++++++++++++++++++++++++++++ 3 files changed, 60 insertions(+), 6 deletions(-) diff --git a/include/efi_loader.h b/include/efi_loader.h index c440962fe5..5cdc72345e 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -675,6 +675,8 @@ struct efi_device_path *efi_get_dp_from_boot(const efi_guid_t guid); #define efi_size_in_pages(size) (((size) + EFI_PAGE_MASK) >> EFI_PAGE_SHIFT) /* Generic EFI memory allocator, call this to get memory */ void *efi_alloc(uint64_t len, int memory_type); +/* Allocate pages on the specified alignment */ +void *efi_alloc_aligned_pages(u64 len, int memory_type, size_t align); /* More specific EFI memory allocator, called by EFI payloads */ efi_status_t efi_allocate_pages(enum efi_allocate_type type, enum efi_memory_type memory_type, diff --git a/lib/efi_loader/efi_image_loader.c b/lib/efi_loader/efi_image_loader.c index e9572d4d5d..eb95580538 100644 --- a/lib/efi_loader/efi_image_loader.c +++ b/lib/efi_loader/efi_image_loader.c @@ -898,9 +898,9 @@ efi_status_t efi_load_pe(struct efi_loaded_image_obj *handle, image_base = opt->ImageBase; efi_set_code_and_data_type(loaded_image_info, opt->Subsystem); handle->image_type = opt->Subsystem; - virt_size = ALIGN(virt_size, opt->SectionAlignment); - efi_reloc = efi_alloc(virt_size, - loaded_image_info->image_code_type); + efi_reloc = efi_alloc_aligned_pages(virt_size, + loaded_image_info->image_code_type, + opt->SectionAlignment); if (!efi_reloc) { log_err("Out of memory\n"); ret = EFI_OUT_OF_RESOURCES; @@ -914,9 +914,9 @@ efi_status_t efi_load_pe(struct efi_loaded_image_obj *handle, image_base = opt->ImageBase; efi_set_code_and_data_type(loaded_image_info, opt->Subsystem); handle->image_type = opt->Subsystem; - virt_size = ALIGN(virt_size, opt->SectionAlignment); - efi_reloc = efi_alloc(virt_size, - loaded_image_info->image_code_type); + efi_reloc = efi_alloc_aligned_pages(virt_size, + loaded_image_info->image_code_type, + opt->SectionAlignment); if (!efi_reloc) { log_err("Out of memory\n"); ret = EFI_OUT_OF_RESOURCES; diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c index f4acbee4f9..7f0b507281 100644 --- a/lib/efi_loader/efi_memory.c +++ b/lib/efi_loader/efi_memory.c @@ -549,6 +549,58 @@ efi_status_t efi_free_pages(uint64_t memory, efi_uintn_t pages) return ret; } +/** + * efi_alloc_aligned_pages - allocate + * + * @len: len in bytes + * @memory_type: usage type of the allocated memory + * @align: alignment in bytes + * Return: aligned memory or NULL + */ +void *efi_alloc_aligned_pages(u64 len, int memory_type, size_t align) +{ + u64 req_pages = efi_size_in_pages(len); + u64 true_pages = req_pages + efi_size_in_pages(align) - 1; + u64 free_pages; + u64 aligned_mem; + efi_status_t r; + u64 mem; + + /* align must be zero or a power of two */ + if (align & (align - 1)) + return NULL; + + /* Check for overflow */ + if (true_pages < req_pages) + return NULL; + + if (align < EFI_PAGE_SIZE) { + r = efi_allocate_pages(EFI_ALLOCATE_ANY_PAGES, memory_type, + req_pages, &mem); + return (r == EFI_SUCCESS) ? (void *)(uintptr_t)mem : NULL; + } + + r = efi_allocate_pages(EFI_ALLOCATE_ANY_PAGES, memory_type, + true_pages, &mem); + if (r != EFI_SUCCESS) + return NULL; + + aligned_mem = ALIGN(mem, align); + /* Free pages before alignment */ + free_pages = efi_size_in_pages(aligned_mem - mem); + if (free_pages) + efi_free_pages(mem, free_pages); + + /* Free trailing pages */ + free_pages = true_pages - (req_pages + free_pages); + if (free_pages) { + mem = aligned_mem + req_pages * EFI_PAGE_SIZE; + efi_free_pages(mem, free_pages); + } + + return (void *)(uintptr_t)aligned_mem; +} + /** * efi_allocate_pool - allocate memory from pool * From 0421735dd8ffc82db22c3767e7aa38c65fc7298e Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Fri, 15 Oct 2021 01:31:02 +0200 Subject: [PATCH 16/21] efi_loader: efi_dp_from_lo() don't copy GUID Instead of copying a GUID and then using a pointer to the copy for calling guidcmp(), just pass the pointer to the orginal GUID. Signed-off-by: Heinrich Schuchardt --- cmd/efidebug.c | 2 +- include/efi_loader.h | 3 ++- lib/efi_loader/efi_device_path.c | 5 +++-- lib/efi_loader/efi_helper.c | 2 +- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/cmd/efidebug.c b/cmd/efidebug.c index 67ab06aefc..5235dbb7c1 100644 --- a/cmd/efidebug.c +++ b/cmd/efidebug.c @@ -1169,7 +1169,7 @@ static void show_efi_boot_opt_data(u16 *varname16, void *data, size_t *size) printf(" file_path: %ls\n", dp_str); efi_free_pool(dp_str); - initrd_path = efi_dp_from_lo(&lo, &initrd_dp_size, lf2_initrd_guid); + initrd_path = efi_dp_from_lo(&lo, &initrd_dp_size, &lf2_initrd_guid); if (initrd_path) { dp_str = efi_dp_str(initrd_path); printf(" initrd_path: %ls\n", dp_str); diff --git a/include/efi_loader.h b/include/efi_loader.h index 5cdc72345e..6e806f9b0d 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -842,7 +842,8 @@ struct efi_load_option { }; struct efi_device_path *efi_dp_from_lo(struct efi_load_option *lo, - efi_uintn_t *size, efi_guid_t guid); + efi_uintn_t *size, + const efi_guid_t *guid); struct efi_device_path *efi_dp_concat(const struct efi_device_path *dp1, const struct efi_device_path *dp2); efi_status_t efi_deserialize_load_option(struct efi_load_option *lo, u8 *data, diff --git a/lib/efi_loader/efi_device_path.c b/lib/efi_loader/efi_device_path.c index a09090a32e..a588712ef1 100644 --- a/lib/efi_loader/efi_device_path.c +++ b/lib/efi_loader/efi_device_path.c @@ -1218,7 +1218,8 @@ ssize_t efi_dp_check_length(const struct efi_device_path *dp, */ struct efi_device_path *efi_dp_from_lo(struct efi_load_option *lo, - efi_uintn_t *size, efi_guid_t guid) + efi_uintn_t *size, + const efi_guid_t *guid) { struct efi_device_path *fp = lo->file_path; struct efi_device_path_vendor *vendor; @@ -1233,7 +1234,7 @@ efi_device_path *efi_dp_from_lo(struct efi_load_option *lo, continue; vendor = (struct efi_device_path_vendor *)fp; - if (!guidcmp(&vendor->guid, &guid)) + if (!guidcmp(&vendor->guid, guid)) return efi_dp_dup(fp); } log_debug("VenMedia(%pUl) not found in %ls\n", &guid, lo->label); diff --git a/lib/efi_loader/efi_helper.c b/lib/efi_loader/efi_helper.c index d03a736461..4c5b7cd2e1 100644 --- a/lib/efi_loader/efi_helper.c +++ b/lib/efi_loader/efi_helper.c @@ -83,7 +83,7 @@ struct efi_device_path *efi_get_dp_from_boot(const efi_guid_t guid) if (ret != EFI_SUCCESS) goto out; - tmp = efi_dp_from_lo(&lo, &size, guid); + tmp = efi_dp_from_lo(&lo, &size, &guid); if (!tmp) goto out; From fc42b8bb75927e81f5c774e677abb990d23f0c38 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Fri, 15 Oct 2021 01:47:40 +0200 Subject: [PATCH 17/21] efi_loader: simplify show_efi_boot_opt_data() Use printf code %pD for printing device paths. Signed-off-by: Heinrich Schuchardt --- cmd/efidebug.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/cmd/efidebug.c b/cmd/efidebug.c index 5235dbb7c1..70a4658012 100644 --- a/cmd/efidebug.c +++ b/cmd/efidebug.c @@ -1143,7 +1143,6 @@ static void show_efi_boot_opt_data(u16 *varname16, void *data, size_t *size) { struct efi_device_path *initrd_path = NULL; struct efi_load_option lo; - u16 *dp_str; efi_status_t ret; efi_uintn_t initrd_dp_size; const efi_guid_t lf2_initrd_guid = EFI_INITRD_MEDIA_GUID; @@ -1165,15 +1164,11 @@ static void show_efi_boot_opt_data(u16 *varname16, void *data, size_t *size) lo.attributes); printf(" label: %ls\n", lo.label); - dp_str = efi_dp_str(lo.file_path); - printf(" file_path: %ls\n", dp_str); - efi_free_pool(dp_str); + printf(" file_path: %pD\n", lo.file_path); initrd_path = efi_dp_from_lo(&lo, &initrd_dp_size, &lf2_initrd_guid); if (initrd_path) { - dp_str = efi_dp_str(initrd_path); - printf(" initrd_path: %ls\n", dp_str); - efi_free_pool(dp_str); + printf(" initrd_path: %pD\n", initrd_path); efi_free_pool(initrd_path); } From 05345425cab4202b356085afcac485614a9b52a9 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Fri, 15 Oct 2021 02:03:55 +0200 Subject: [PATCH 18/21] efi_loader: efi_dp_from_lo() unused parameter size Parameter size is never used in function efi_dp_from_lo(). Remove it. Signed-off-by: Heinrich Schuchardt Reviewed-by: Ilias Apalodimas --- cmd/efidebug.c | 3 +-- include/efi_loader.h | 1 - lib/efi_loader/efi_device_path.c | 2 -- lib/efi_loader/efi_helper.c | 2 +- 4 files changed, 2 insertions(+), 6 deletions(-) diff --git a/cmd/efidebug.c b/cmd/efidebug.c index 70a4658012..33a5135ee1 100644 --- a/cmd/efidebug.c +++ b/cmd/efidebug.c @@ -1144,7 +1144,6 @@ static void show_efi_boot_opt_data(u16 *varname16, void *data, size_t *size) struct efi_device_path *initrd_path = NULL; struct efi_load_option lo; efi_status_t ret; - efi_uintn_t initrd_dp_size; const efi_guid_t lf2_initrd_guid = EFI_INITRD_MEDIA_GUID; ret = efi_deserialize_load_option(&lo, data, size); @@ -1166,7 +1165,7 @@ static void show_efi_boot_opt_data(u16 *varname16, void *data, size_t *size) printf(" file_path: %pD\n", lo.file_path); - initrd_path = efi_dp_from_lo(&lo, &initrd_dp_size, &lf2_initrd_guid); + initrd_path = efi_dp_from_lo(&lo, &lf2_initrd_guid); if (initrd_path) { printf(" initrd_path: %pD\n", initrd_path); efi_free_pool(initrd_path); diff --git a/include/efi_loader.h b/include/efi_loader.h index 6e806f9b0d..3e5ac38042 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -842,7 +842,6 @@ struct efi_load_option { }; struct efi_device_path *efi_dp_from_lo(struct efi_load_option *lo, - efi_uintn_t *size, const efi_guid_t *guid); struct efi_device_path *efi_dp_concat(const struct efi_device_path *dp1, const struct efi_device_path *dp2); diff --git a/lib/efi_loader/efi_device_path.c b/lib/efi_loader/efi_device_path.c index a588712ef1..58fff81a2d 100644 --- a/lib/efi_loader/efi_device_path.c +++ b/lib/efi_loader/efi_device_path.c @@ -1209,7 +1209,6 @@ ssize_t efi_dp_check_length(const struct efi_device_path *dp, * initrd location * * @lo: EFI_LOAD_OPTION containing a valid device path - * @size: size of the discovered device path * @guid: guid to search for * * Return: @@ -1218,7 +1217,6 @@ ssize_t efi_dp_check_length(const struct efi_device_path *dp, */ struct efi_device_path *efi_dp_from_lo(struct efi_load_option *lo, - efi_uintn_t *size, const efi_guid_t *guid) { struct efi_device_path *fp = lo->file_path; diff --git a/lib/efi_loader/efi_helper.c b/lib/efi_loader/efi_helper.c index 4c5b7cd2e1..89833de222 100644 --- a/lib/efi_loader/efi_helper.c +++ b/lib/efi_loader/efi_helper.c @@ -83,7 +83,7 @@ struct efi_device_path *efi_get_dp_from_boot(const efi_guid_t guid) if (ret != EFI_SUCCESS) goto out; - tmp = efi_dp_from_lo(&lo, &size, &guid); + tmp = efi_dp_from_lo(&lo, &guid); if (!tmp) goto out; From 9ad37fe405a6fccba3555892ac9e64dbd37b0581 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Fri, 15 Oct 2021 02:33:33 +0200 Subject: [PATCH 19/21] efi_loader: avoid multiple local copies of lf2_initrd_guid Create the GUID as a global variable. Signed-off-by: Heinrich Schuchardt Reviewed-by: Ilias Apalodimas --- cmd/efidebug.c | 3 +-- include/efi_load_initrd.h | 1 + lib/efi_loader/efi_helper.c | 5 +++++ lib/efi_loader/efi_load_initrd.c | 3 +-- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/cmd/efidebug.c b/cmd/efidebug.c index 33a5135ee1..a977ca9c72 100644 --- a/cmd/efidebug.c +++ b/cmd/efidebug.c @@ -1144,7 +1144,6 @@ static void show_efi_boot_opt_data(u16 *varname16, void *data, size_t *size) struct efi_device_path *initrd_path = NULL; struct efi_load_option lo; efi_status_t ret; - const efi_guid_t lf2_initrd_guid = EFI_INITRD_MEDIA_GUID; ret = efi_deserialize_load_option(&lo, data, size); if (ret != EFI_SUCCESS) { @@ -1165,7 +1164,7 @@ static void show_efi_boot_opt_data(u16 *varname16, void *data, size_t *size) printf(" file_path: %pD\n", lo.file_path); - initrd_path = efi_dp_from_lo(&lo, &lf2_initrd_guid); + initrd_path = efi_dp_from_lo(&lo, &efi_lf2_initrd_guid); if (initrd_path) { printf(" initrd_path: %pD\n", initrd_path); efi_free_pool(initrd_path); diff --git a/include/efi_load_initrd.h b/include/efi_load_initrd.h index 478ae807c6..be5d5a7acb 100644 --- a/include/efi_load_initrd.h +++ b/include/efi_load_initrd.h @@ -16,6 +16,7 @@ #define EFI_INITRD_MEDIA_GUID \ EFI_GUID(0x5568e427, 0x68fc, 0x4f3d, \ 0xac, 0x74, 0xca, 0x55, 0x52, 0x31, 0xcc, 0x68) +extern const efi_guid_t efi_lf2_initrd_guid; struct efi_initrd_dp { struct efi_device_path_vendor vendor; diff --git a/lib/efi_loader/efi_helper.c b/lib/efi_loader/efi_helper.c index 89833de222..485384b7ee 100644 --- a/lib/efi_loader/efi_helper.c +++ b/lib/efi_loader/efi_helper.c @@ -13,6 +13,11 @@ #include #include +#if defined(CONFIG_CMD_EFIDEBUG) || defined(CONFIG_EFI_LOAD_FILE2_INITRD) +/* GUID used by Linux to identify the LoadFile2 protocol with the initrd */ +const efi_guid_t efi_lf2_initrd_guid = EFI_INITRD_MEDIA_GUID; +#endif + /** * efi_create_current_boot_var() - Return Boot#### name were #### is replaced by * the value of BootCurrent diff --git a/lib/efi_loader/efi_load_initrd.c b/lib/efi_loader/efi_load_initrd.c index e2a8063023..c5e6652e66 100644 --- a/lib/efi_loader/efi_load_initrd.c +++ b/lib/efi_loader/efi_load_initrd.c @@ -52,7 +52,6 @@ static efi_handle_t efi_initrd_handle; */ static efi_status_t get_initrd_fp(struct efi_device_path **initrd_fp) { - const efi_guid_t lf2_initrd_guid = EFI_INITRD_MEDIA_GUID; struct efi_device_path *dp = NULL; /* @@ -65,7 +64,7 @@ static efi_status_t get_initrd_fp(struct efi_device_path **initrd_fp) * We can then use this specific return value and not install the * protocol, while allowing the boot to continue */ - dp = efi_get_dp_from_boot(lf2_initrd_guid); + dp = efi_get_dp_from_boot(efi_lf2_initrd_guid); if (!dp) return EFI_INVALID_PARAMETER; From db61e70e0d2ab94f572a5ec0900c7c51fb686177 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Fri, 15 Oct 2021 02:59:15 +0200 Subject: [PATCH 20/21] efi_loader: efi_dp_from_lo() should skip VenMedia node The 'efidebug boot dump' command should not display the VenMedia() device path node preceding the device path of the initial ram disk. By letting efi_dp_from_lo() skip the VenMedia() device path node we can simplify the coding. Signed-off-by: Heinrich Schuchardt Reviewed-by: Ilias Apalodimas --- lib/efi_loader/efi_device_path.c | 2 +- lib/efi_loader/efi_helper.c | 19 +++++-------------- 2 files changed, 6 insertions(+), 15 deletions(-) diff --git a/lib/efi_loader/efi_device_path.c b/lib/efi_loader/efi_device_path.c index 58fff81a2d..c04439d16d 100644 --- a/lib/efi_loader/efi_device_path.c +++ b/lib/efi_loader/efi_device_path.c @@ -1233,7 +1233,7 @@ efi_device_path *efi_dp_from_lo(struct efi_load_option *lo, vendor = (struct efi_device_path_vendor *)fp; if (!guidcmp(&vendor->guid, guid)) - return efi_dp_dup(fp); + return efi_dp_dup(efi_dp_next(fp)); } log_debug("VenMedia(%pUl) not found in %ls\n", &guid, lo->label); diff --git a/lib/efi_loader/efi_helper.c b/lib/efi_loader/efi_helper.c index 485384b7ee..b80a6e07df 100644 --- a/lib/efi_loader/efi_helper.c +++ b/lib/efi_loader/efi_helper.c @@ -68,10 +68,8 @@ out: */ struct efi_device_path *efi_get_dp_from_boot(const efi_guid_t guid) { - struct efi_device_path *file_path = NULL; - struct efi_device_path *tmp = NULL; struct efi_load_option lo; - void *var_value = NULL; + void *var_value; efi_uintn_t size; efi_status_t ret; u16 var_name[16]; @@ -86,18 +84,11 @@ struct efi_device_path *efi_get_dp_from_boot(const efi_guid_t guid) ret = efi_deserialize_load_option(&lo, var_value, &size); if (ret != EFI_SUCCESS) - goto out; + goto err; - tmp = efi_dp_from_lo(&lo, &guid); - if (!tmp) - goto out; + return efi_dp_from_lo(&lo, &guid); - /* efi_dp_dup will just return NULL if efi_dp_next is NULL */ - file_path = efi_dp_dup(efi_dp_next(tmp)); - -out: - efi_free_pool(tmp); +err: free(var_value); - - return file_path; + return NULL; } From af484011f12e2aa37bcf4f9cbb4258dea4ef14ac Mon Sep 17 00:00:00 2001 From: Alistair Delva Date: Wed, 20 Oct 2021 21:31:31 +0000 Subject: [PATCH 21/21] efi_loader: Fix link of EFI apps with ld.lld When compiling U-Boot with ld.lld as the linker, the helloworld EFI app example fails to link: LD lib/efi_loader/helloworld_efi.so ld.lld: error: section: .dynamic is not contiguous with other relro sections LLD will always create RELRO program header regardless of target emulation, whereas BFD may automatically disable it for unsupported targets. Add -znorelro to disable it explicitly in all cases. Signed-off-by: Alistair Delva Cc: Heinrich Schuchardt Cc: Nick Desaulniers Reviewed-by: Heinrich Schuchardt --- scripts/Makefile.lib | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib index 07696e86bb..39f03398ed 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib @@ -403,7 +403,7 @@ $(obj)/%.efi: $(obj)/%_efi.so quiet_cmd_efi_ld = LD $@ cmd_efi_ld = $(LD) -nostdlib -znocombreloc -T $(EFI_LDS_PATH) -shared \ - -Bsymbolic -s $^ -o $@ + -Bsymbolic -znorelro -s $^ -o $@ EFI_LDS_PATH = $(srctree)/arch/$(ARCH)/lib/$(EFI_LDS)