From c5cc6da855c10d762c492d390b1e4059910259d1 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sun, 19 Mar 2023 16:18:08 +0100 Subject: efi_loader: support for Ctrl() device path node * Add the definitions for Ctrl() device path nodes. * Implement Ctrl() nodes in the device path to text protocol. Signed-off-by: Heinrich Schuchardt Reviewed-by: Simon Glass Reviewed-by: Ilias Apalodimas --- include/efi_api.h | 6 ++++++ lib/efi_loader/efi_device_path_to_text.c | 7 +++++++ 2 files changed, 13 insertions(+) diff --git a/include/efi_api.h b/include/efi_api.h index 2d18d25..c57868a 100644 --- a/include/efi_api.h +++ b/include/efi_api.h @@ -570,6 +570,7 @@ struct efi_mac_addr { #define DEVICE_PATH_TYPE_HARDWARE_DEVICE 0x01 # define DEVICE_PATH_SUB_TYPE_MEMORY 0x03 # define DEVICE_PATH_SUB_TYPE_VENDOR 0x04 +# define DEVICE_PATH_SUB_TYPE_CONTROLLER 0x05 struct efi_device_path_memory { struct efi_device_path dp; @@ -584,6 +585,11 @@ struct efi_device_path_vendor { u8 vendor_data[]; } __packed; +struct efi_device_path_controller { + struct efi_device_path dp; + u32 controller_number; +} __packed; + #define DEVICE_PATH_TYPE_ACPI_DEVICE 0x02 # define DEVICE_PATH_SUB_TYPE_ACPI_DEVICE 0x01 diff --git a/lib/efi_loader/efi_device_path_to_text.c b/lib/efi_loader/efi_device_path_to_text.c index 9062058..4b2ade3 100644 --- a/lib/efi_loader/efi_device_path_to_text.c +++ b/lib/efi_loader/efi_device_path_to_text.c @@ -77,6 +77,13 @@ static char *dp_hardware(char *s, struct efi_device_path *dp) s += sprintf(s, ")"); break; } + case DEVICE_PATH_SUB_TYPE_CONTROLLER: { + struct efi_device_path_controller *cdp = + (struct efi_device_path_controller *)dp; + + s += sprintf(s, "Ctrl(0x%0x)", cdp->controller_number); + break; + } default: s = dp_unknown(s, dp); break; -- cgit v1.1 From e472ef8a3d5e94a0f0bc5ad50a4a86a67316e876 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sun, 19 Mar 2023 16:18:09 +0100 Subject: efi_loader: fix device-path for USB devices EFI device paths for block devices must be unique. If a non-unique device path is discovered, probing of the block device fails. Currently we use UsbClass() device path nodes. As multiple devices may have the same vendor and product id these are non-unique. Instead we should use Usb() device path nodes. They include the USB port on the parent hub. Hence they are unique. A USB storage device may contain multiple logical units. These can be modeled as Ctrl() nodes. Reported-by: Patrick Delaunay Signed-off-by: Heinrich Schuchardt Reviewed-by: Simon Glass --- lib/efi_loader/efi_device_path.c | 45 +++++++++++++++++++++++++++++----------- 1 file changed, 33 insertions(+), 12 deletions(-) diff --git a/lib/efi_loader/efi_device_path.c b/lib/efi_loader/efi_device_path.c index 3b267b7..b6dd575 100644 --- a/lib/efi_loader/efi_device_path.c +++ b/lib/efi_loader/efi_device_path.c @@ -147,7 +147,7 @@ struct efi_device_path *efi_dp_shorten(struct efi_device_path *dp) * in practice fallback.efi just uses MEDIA:HARD_DRIVE * so not sure when we would see these other cases. */ - if (EFI_DP_TYPE(dp, MESSAGING_DEVICE, MSG_USB_CLASS) || + if (EFI_DP_TYPE(dp, MESSAGING_DEVICE, MSG_USB) || EFI_DP_TYPE(dp, MEDIA_DEVICE, HARD_DRIVE_PATH) || EFI_DP_TYPE(dp, MEDIA_DEVICE, FILE_PATH)) return dp; @@ -564,6 +564,11 @@ __maybe_unused static unsigned int dp_size(struct udevice *dev) return dp_size(dev->parent) + sizeof(struct efi_device_path_vendor) + 1; #endif +#ifdef CONFIG_USB + case UCLASS_MASS_STORAGE: + return dp_size(dev->parent) + + sizeof(struct efi_device_path_controller); +#endif #ifdef CONFIG_VIRTIO_BLK case UCLASS_VIRTIO: /* @@ -585,7 +590,7 @@ __maybe_unused static unsigned int dp_size(struct udevice *dev) case UCLASS_MASS_STORAGE: case UCLASS_USB_HUB: return dp_size(dev->parent) + - sizeof(struct efi_device_path_usb_class); + sizeof(struct efi_device_path_usb); default: /* just skip over unknown classes: */ return dp_size(dev->parent); @@ -742,6 +747,19 @@ __maybe_unused static void *dp_fill(void *buf, struct udevice *dev) return &dp[1]; } #endif +#if defined(CONFIG_USB) + case UCLASS_MASS_STORAGE: { + struct blk_desc *desc = desc = dev_get_uclass_plat(dev); + struct efi_device_path_controller *dp = + dp_fill(buf, dev->parent); + + dp->dp.type = DEVICE_PATH_TYPE_HARDWARE_DEVICE; + dp->dp.sub_type = DEVICE_PATH_SUB_TYPE_CONTROLLER; + dp->dp.length = sizeof(*dp); + dp->controller_number = desc->lun; + return &dp[1]; + } +#endif default: debug("%s(%u) %s: unhandled parent class: %s (%u)\n", __FILE__, __LINE__, __func__, @@ -767,19 +785,22 @@ __maybe_unused static void *dp_fill(void *buf, struct udevice *dev) #endif case UCLASS_MASS_STORAGE: case UCLASS_USB_HUB: { - struct efi_device_path_usb_class *udp = - dp_fill(buf, dev->parent); - struct usb_device *udev = dev_get_parent_priv(dev); - struct usb_device_descriptor *desc = &udev->descriptor; + struct efi_device_path_usb *udp = dp_fill(buf, dev->parent); + + switch (device_get_uclass_id(dev->parent)) { + case UCLASS_USB_HUB: { + struct usb_device *udev = dev_get_parent_priv(dev); + udp->parent_port_number = udev->portnr; + break; + } + default: + udp->parent_port_number = 0; + } udp->dp.type = DEVICE_PATH_TYPE_MESSAGING_DEVICE; - udp->dp.sub_type = DEVICE_PATH_SUB_TYPE_MSG_USB_CLASS; + udp->dp.sub_type = DEVICE_PATH_SUB_TYPE_MSG_USB; udp->dp.length = sizeof(*udp); - udp->vendor_id = desc->idVendor; - udp->product_id = desc->idProduct; - udp->device_class = desc->bDeviceClass; - udp->device_subclass = desc->bDeviceSubClass; - udp->device_protocol = desc->bDeviceProtocol; + udp->usb_interface = 0; return &udp[1]; } -- cgit v1.1 From 92b931b8ef3b08068f8911ecfd7482b3c4660320 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sun, 19 Mar 2023 08:59:33 +0100 Subject: efi_loader: move struct efi_device_path to efi.h Avoid forward declaration of struct efi_device_path. Signed-off-by: Heinrich Schuchardt Reviewed-by: Simon Glass Reviewed-by: Ilias Apalodimas --- include/efi.h | 13 ++++++++++++- include/efi_api.h | 6 ------ 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/include/efi.h b/include/efi.h index c3087d3..2f312da 100644 --- a/include/efi.h +++ b/include/efi.h @@ -52,7 +52,18 @@ #define EFI32_LOADER_SIGNATURE "EL32" #define EFI64_LOADER_SIGNATURE "EL64" -struct efi_device_path; +/** + * struct efi_device_path - device path protocol + * + * @type: device path type + * @sub_type: device path sub-type + * @length: length of the device path node including the header + */ +struct efi_device_path { + u8 type; + u8 sub_type; + u16 length; +} __packed; /* * The EFI spec defines the EFI_GUID as diff --git a/include/efi_api.h b/include/efi_api.h index c57868a..7f09253 100644 --- a/include/efi_api.h +++ b/include/efi_api.h @@ -557,12 +557,6 @@ struct efi_loaded_image { # define DEVICE_PATH_SUB_TYPE_INSTANCE_END 0x01 # define DEVICE_PATH_SUB_TYPE_END 0xff -struct efi_device_path { - u8 type; - u8 sub_type; - u16 length; -} __packed; - struct efi_mac_addr { u8 addr[32]; } __packed; -- cgit v1.1 From f606fab8dada798da801684bd6f53ddfb50494e2 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sun, 19 Mar 2023 09:20:22 +0100 Subject: efi_loader: move dp_alloc() to efi_alloc() The incumbent function efi_alloc() is unused. Replace dp_alloc() by a new function efi_alloc() that we can use more widely. Signed-off-by: Heinrich Schuchardt Reviewed-by: Ilias Apalodimas --- include/efi_loader.h | 4 ++-- lib/efi_loader/efi_device_path.c | 40 ++++++++++++---------------------- lib/efi_loader/efi_memory.c | 46 ++++++++++++++++++++++------------------ 3 files changed, 40 insertions(+), 50 deletions(-) diff --git a/include/efi_loader.h b/include/efi_loader.h index 1542b4b..cee04cb 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -724,8 +724,8 @@ efi_status_t efi_next_variable_name(efi_uintn_t *size, u16 **buf, * Return: size in pages */ #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 boot service data pool memory */ +void *efi_alloc(size_t len); /* 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 */ diff --git a/lib/efi_loader/efi_device_path.c b/lib/efi_loader/efi_device_path.c index b6dd575..d5cc495 100644 --- a/lib/efi_loader/efi_device_path.c +++ b/lib/efi_loader/efi_device_path.c @@ -63,20 +63,6 @@ static bool is_sd(struct blk_desc *desc) } #endif -static void *dp_alloc(size_t sz) -{ - void *buf; - - if (efi_allocate_pool(EFI_BOOT_SERVICES_DATA, sz, &buf) != - EFI_SUCCESS) { - debug("EFI: ERROR: out of memory in %s\n", __func__); - return NULL; - } - - memset(buf, 0, sz); - return buf; -} - /* * Iterate to next block in device-path, terminating (returning NULL) * at /End* node. @@ -302,7 +288,7 @@ struct efi_device_path *efi_dp_dup(const struct efi_device_path *dp) if (!dp) return NULL; - ndp = dp_alloc(sz); + ndp = efi_alloc(sz); if (!ndp) return NULL; memcpy(ndp, dp, sz); @@ -346,7 +332,7 @@ efi_device_path *efi_dp_append_or_concatenate(const struct efi_device_path *dp1, /* both dp1 and dp2 are non-null */ unsigned sz1 = efi_dp_size(dp1); unsigned sz2 = efi_dp_size(dp2); - void *p = dp_alloc(sz1 + sz2 + end_size); + void *p = efi_alloc(sz1 + sz2 + end_size); if (!p) return NULL; ret = p; @@ -409,7 +395,7 @@ struct efi_device_path *efi_dp_append_node(const struct efi_device_path *dp, ret = efi_dp_dup(dp); } else if (!dp) { size_t sz = node->length; - void *p = dp_alloc(sz + sizeof(END)); + void *p = efi_alloc(sz + sizeof(END)); if (!p) return NULL; memcpy(p, node, sz); @@ -418,7 +404,7 @@ struct efi_device_path *efi_dp_append_node(const struct efi_device_path *dp, } else { /* both dp and node are non-null */ size_t sz = efi_dp_size(dp); - void *p = dp_alloc(sz + node->length + sizeof(END)); + void *p = efi_alloc(sz + node->length + sizeof(END)); if (!p) return NULL; memcpy(p, dp, sz); @@ -439,7 +425,7 @@ struct efi_device_path *efi_dp_create_device_node(const u8 type, if (length < sizeof(struct efi_device_path)) return NULL; - ret = dp_alloc(length); + ret = efi_alloc(length); if (!ret) return ret; ret->type = type; @@ -461,7 +447,7 @@ struct efi_device_path *efi_dp_append_instance( return efi_dp_dup(dpi); sz = efi_dp_size(dp); szi = efi_dp_instance_size(dpi); - p = dp_alloc(sz + szi + 2 * sizeof(END)); + p = efi_alloc(sz + szi + 2 * sizeof(END)); if (!p) return NULL; ret = p; @@ -486,7 +472,7 @@ struct efi_device_path *efi_dp_get_next_instance(struct efi_device_path **dp, if (!dp || !*dp) return NULL; sz = efi_dp_instance_size(*dp); - p = dp_alloc(sz + sizeof(END)); + p = efi_alloc(sz + sizeof(END)); if (!p) return NULL; memcpy(p, *dp, sz + sizeof(END)); @@ -927,7 +913,7 @@ struct efi_device_path *efi_dp_from_part(struct blk_desc *desc, int part) { void *buf, *start; - start = buf = dp_alloc(dp_part_size(desc, part) + sizeof(END)); + start = buf = efi_alloc(dp_part_size(desc, part) + sizeof(END)); if (!buf) return NULL; @@ -954,7 +940,7 @@ struct efi_device_path *efi_dp_part_node(struct blk_desc *desc, int part) dpsize = sizeof(struct efi_device_path_cdrom_path); else dpsize = sizeof(struct efi_device_path_hard_drive_path); - buf = dp_alloc(dpsize); + buf = efi_alloc(dpsize); if (buf) dp_part_node(buf, desc, part); @@ -1028,7 +1014,7 @@ struct efi_device_path *efi_dp_from_file(struct blk_desc *desc, int part, dpsize += fpsize; - start = buf = dp_alloc(dpsize + sizeof(END)); + start = buf = efi_alloc(dpsize + sizeof(END)); if (!buf) return NULL; @@ -1056,7 +1042,7 @@ struct efi_device_path *efi_dp_from_uart(void) struct efi_device_path_uart *uart; size_t dpsize = sizeof(ROOT) + sizeof(*uart) + sizeof(END); - buf = dp_alloc(dpsize); + buf = efi_alloc(dpsize); if (!buf) return NULL; pos = buf; @@ -1082,7 +1068,7 @@ struct efi_device_path *efi_dp_from_eth(void) dpsize += dp_size(eth_get_dev()); - start = buf = dp_alloc(dpsize + sizeof(END)); + start = buf = efi_alloc(dpsize + sizeof(END)); if (!buf) return NULL; @@ -1102,7 +1088,7 @@ struct efi_device_path *efi_dp_from_mem(uint32_t memory_type, struct efi_device_path_memory *mdp; void *buf, *start; - start = buf = dp_alloc(sizeof(*mdp) + sizeof(END)); + start = buf = efi_alloc(sizeof(*mdp) + sizeof(END)); if (!buf) return NULL; diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c index b7bee98..8f82496 100644 --- a/lib/efi_loader/efi_memory.c +++ b/lib/efi_loader/efi_memory.c @@ -5,9 +5,12 @@ * Copyright (c) 2016 Alexander Graf */ +#define LOG_CATEGORY LOGC_EFI + #include #include #include +#include #include #include #include @@ -534,27 +537,6 @@ efi_status_t efi_allocate_pages(enum efi_allocate_type type, } /** - * efi_alloc() - allocate memory pages - * - * @len: size of the memory to be allocated - * @memory_type: usage type of the allocated memory - * Return: pointer to the allocated memory area or NULL - */ -void *efi_alloc(uint64_t len, int memory_type) -{ - uint64_t ret = 0; - uint64_t pages = efi_size_in_pages(len); - efi_status_t r; - - r = efi_allocate_pages(EFI_ALLOCATE_ANY_PAGES, memory_type, pages, - &ret); - if (r == EFI_SUCCESS) - return (void*)(uintptr_t)ret; - - return NULL; -} - -/** * efi_free_pages() - free memory pages * * @memory: start of the memory area to be freed @@ -673,6 +655,28 @@ efi_status_t efi_allocate_pool(enum efi_memory_type pool_type, efi_uintn_t size, } /** + * efi_alloc() - allocate boot services data pool memory + * + * Allocate memory from pool and zero it out. + * + * @size: number of bytes to allocate + * Return: pointer to allocated memory or NULL + */ +void *efi_alloc(size_t size) +{ + void *buf; + + if (efi_allocate_pool(EFI_BOOT_SERVICES_DATA, size, &buf) != + EFI_SUCCESS) { + log_err("out of memory"); + return NULL; + } + memset(buf, 0, size); + + return buf; +} + +/** * efi_free_pool() - free memory from pool * * @buffer: start of memory to be freed -- cgit v1.1 From bace47a59d2f6a60972a388d6be034ce20e92270 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sun, 19 Mar 2023 09:20:23 +0100 Subject: efi_loader: simplify efi_str_to_u16() Use efi_alloc() to allocate memory. Signed-off-by: Heinrich Schuchardt Reviewed-by: Simon Glass --- lib/efi_loader/efi_device_path_to_text.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/efi_loader/efi_device_path_to_text.c b/lib/efi_loader/efi_device_path_to_text.c index 4b2ade3..8c76d8b 100644 --- a/lib/efi_loader/efi_device_path_to_text.c +++ b/lib/efi_loader/efi_device_path_to_text.c @@ -32,11 +32,10 @@ static u16 *efi_str_to_u16(char *str) { efi_uintn_t len; u16 *out, *dst; - efi_status_t ret; len = sizeof(u16) * (utf8_utf16_strlen(str) + 1); - ret = efi_allocate_pool(EFI_BOOT_SERVICES_DATA, len, (void **)&out); - if (ret != EFI_SUCCESS) + out = efi_alloc(len); + if (!out) return NULL; dst = out; utf8_utf16_strcpy(&dst, str); -- cgit v1.1 From edf35a30278121e1affc9cc15b7aa26b9892e9d9 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 20 Mar 2023 08:30:05 +1300 Subject: efi: Set RUN_64BIT correctly for the EFI app The U-Boot EFI app can run as a 64-bit program, so set the Kconfig correctly in that case. Make sure it doesn't build SPL, since there is no need to switch from 32 to 64 bit when running. Signed-off-by: Simon Glass --- arch/x86/Kconfig | 4 ++-- configs/efi-x86_app64_defconfig | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 07be5cd..99e59d9 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -32,8 +32,8 @@ config X86_RUN_32BIT config X86_RUN_64BIT bool "64-bit" select X86_64 - select SPL - select SPL_SEPARATE_BSS + select SPL if !EFI_APP + select SPL_SEPARATE_BSS if !EFI_APP help Build U-Boot as a 64-bit binary with a 32-bit SPL. This is experimental and many features are missing. U-Boot SPL starts up, diff --git a/configs/efi-x86_app64_defconfig b/configs/efi-x86_app64_defconfig index dae4884..f1cf43c 100644 --- a/configs/efi-x86_app64_defconfig +++ b/configs/efi-x86_app64_defconfig @@ -4,6 +4,7 @@ CONFIG_ENV_SIZE=0x1000 CONFIG_DEFAULT_DEVICE_TREE="efi-x86_app" CONFIG_DEBUG_UART_BASE=0 CONFIG_DEBUG_UART_CLOCK=0 +CONFIG_X86_RUN_64BIT=y CONFIG_VENDOR_EFI=y CONFIG_TARGET_EFI_APP64=y CONFIG_DEBUG_UART=y -- cgit v1.1 From 90f2b5abb5d980e5df5311f78f062340a69302bb Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 20 Mar 2023 08:30:06 +1300 Subject: x86: Adjust bootparam.h to be more like linux This likely came from Linux originally, so update it to match v6.2 more. This has no functional change. Signed-off-by: Simon Glass --- arch/x86/include/asm/bootparam.h | 70 ++++++++++++++++++++++++++-------------- arch/x86/lib/zimage.c | 2 +- 2 files changed, 47 insertions(+), 25 deletions(-) diff --git a/arch/x86/include/asm/bootparam.h b/arch/x86/include/asm/bootparam.h index 7a3c1f5..ea816ca 100644 --- a/arch/x86/include/asm/bootparam.h +++ b/arch/x86/include/asm/bootparam.h @@ -9,19 +9,54 @@ #include #include -/* setup data types */ -enum { - SETUP_NONE = 0, - SETUP_E820_EXT, - SETUP_DTB, -}; +/* setup_data/setup_indirect types */ +#define SETUP_NONE 0 +#define SETUP_E820_EXT 1 +#define SETUP_DTB 2 +#define SETUP_PCI 3 +#define SETUP_EFI 4 +#define SETUP_APPLE_PROPERTIES 5 +#define SETUP_JAILHOUSE 6 +#define SETUP_CC_BLOB 7 +#define SETUP_IMA 8 +#define SETUP_RNG_SEED 9 +#define SETUP_ENUM_MAX SETUP_RNG_SEED + +#define SETUP_INDIRECT BIT(31) +#define SETUP_TYPE_MAX (SETUP_ENUM_MAX | SETUP_INDIRECT) + +/* ram_size flags */ +#define RAMDISK_IMAGE_START_MASK 0x07FF +#define RAMDISK_PROMPT_FLAG 0x8000 +#define RAMDISK_LOAD_FLAG 0x4000 + +/* loadflags */ +#define LOADED_HIGH BIT(0) +#define KASLR_FLAG BIT(1) +#define QUIET_FLAG BIT(5) +#define KEEP_SEGMENTS BIT(6) +#define CAN_USE_HEAP BIT(7) + +#define XLF_KERNEL_64 BIT(0) +#define XLF_CAN_BE_LOADED_ABOVE_4G BIT(1) +#define XLF_EFI_HANDOVER_32 BIT(2) +#define XLF_EFI_HANDOVER_64 BIT(3) +#define XLF_EFI_KEXEC BIT(4) /* extensible setup data list node */ struct setup_data { __u64 next; __u32 type; __u32 len; - __u8 data[0]; + __u8 data[]; +}; + +/* extensible setup indirect data node */ +struct setup_indirect { + __u32 type; + __u32 reserved; /* Reserved, must be set to zero. */ + __u64 len; + __u64 addr; }; /** @@ -34,9 +69,6 @@ struct setup_header { __u16 root_flags; __u32 syssize; __u16 ram_size; -#define RAMDISK_IMAGE_START_MASK 0x07FF -#define RAMDISK_PROMPT_FLAG 0x8000 -#define RAMDISK_LOAD_FLAG 0x4000 __u16 vid_mode; __u16 root_dev; __u16 boot_flag; @@ -44,15 +76,10 @@ struct setup_header { __u32 header; __u16 version; __u32 realmode_swtch; - __u16 start_sys; + __u16 start_sys_seg; __u16 kernel_version; __u8 type_of_loader; __u8 loadflags; -#define LOADED_HIGH BIT(0) -#define KASLR_FLAG BIT(1) -#define QUIET_FLAG BIT(5) -#define KEEP_SEGMENTS BIT(6) /* Obsolete */ -#define CAN_USE_HEAP BIT(7) __u16 setup_move_size; __u32 code32_start; __u32 ramdisk_image; @@ -65,13 +92,8 @@ struct setup_header { __u32 initrd_addr_max; __u32 kernel_alignment; __u8 relocatable_kernel; - u8 min_alignment; -#define XLF_KERNEL_64 BIT(0) -#define XLF_CAN_BE_LOADED_ABOVE_4G BIT(1) -#define XLF_EFI_HANDOVER_32 BIT(2) -#define XLF_EFI_HANDOVER_64 BIT(3) -#define XLF_EFI_KEXEC BIT(4) - u16 xloadflags; + __u8 min_alignment; + __u16 xloadflags; __u32 cmdline_size; __u32 hardware_subarch; __u64 hardware_subarch_data; @@ -81,7 +103,7 @@ struct setup_header { __u64 pref_address; __u32 init_size; __u32 handover_offset; - u32 kernel_info_offset; + __u32 kernel_info_offset; } __attribute__((packed)); struct sys_desc_table { diff --git a/arch/x86/lib/zimage.c b/arch/x86/lib/zimage.c index 9cc0449..a6d9151 100644 --- a/arch/x86/lib/zimage.c +++ b/arch/x86/lib/zimage.c @@ -655,7 +655,7 @@ void zimage_dump(struct boot_params *base_ptr) printf("%-20s %s\n", "", "Ancient kernel, using version 100"); print_num("Version", hdr->version); print_num("Real mode switch", hdr->realmode_swtch); - print_num("Start sys", hdr->start_sys); + print_num("Start sys seg", hdr->start_sys_seg); print_num("Kernel version", hdr->kernel_version); version = get_kernel_version(base_ptr, (void *)state.bzimage_addr); if (version) -- cgit v1.1 From 1404914ddd959d43138ed08544da8c816e0fa66d Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 20 Mar 2023 08:30:07 +1300 Subject: x86: Add return-value comment to cpu_jump_to_64bit() This does not mention what it returns. Add the missing documentation. Signed-off-by: Simon Glass --- arch/x86/include/asm/cpu.h | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/x86/include/asm/cpu.h b/arch/x86/include/asm/cpu.h index 3346012..073f80b 100644 --- a/arch/x86/include/asm/cpu.h +++ b/arch/x86/include/asm/cpu.h @@ -262,6 +262,7 @@ void cpu_call32(ulong code_seg32, ulong target, ulong table); * * @setup_base: Pointer to the setup.bin information for the kernel * @target: Pointer to the start of the kernel image + * Return: -EFAULT if the kernel returned; otherwise does not return */ int cpu_jump_to_64bit(ulong setup_base, ulong target); -- cgit v1.1 From 37c9f9cc86a2bcd8707d519945cecf08c079ef19 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 20 Mar 2023 08:30:08 +1300 Subject: x86: Support booting a 64-bit kernel from 64-bit U-Boot Add the missing code to handle this. For a 64-bit kernel the entry address is 0x200 bytes after the normal entry. Rename the parameter to boot_linux_kernel() accordingly. Update the comments to indicate that these are addresses, not pointers. Signed-off-by: Simon Glass --- arch/x86/include/asm/bootm.h | 12 ++++++------ arch/x86/lib/bootm.c | 25 +++++++++++++++++-------- arch/x86/lib/zimage.c | 15 +++++++++++++-- 3 files changed, 36 insertions(+), 16 deletions(-) diff --git a/arch/x86/include/asm/bootm.h b/arch/x86/include/asm/bootm.h index 109f686..3b64178 100644 --- a/arch/x86/include/asm/bootm.h +++ b/arch/x86/include/asm/bootm.h @@ -14,14 +14,14 @@ void bootm_announce_and_cleanup(void); * This boots a kernel image, either 32-bit or 64-bit. It will also work with * a self-extracting kernel, if you set @image_64bit to false. * - * @setup_base: Pointer to the setup.bin information for the kernel - * @load_address: Pointer to the start of the kernel image - * @image_64bit: true if the image is a raw 64-bit kernel, false if it - * is raw 32-bit or any type of self-extracting kernel - * such as a bzImage. + * @setup_base: Address of the setup.bin information for the kernel + * @entry: Address of the kernel entry point + * @image_64bit: true if the image is a raw 64-bit kernel, or a kernel + * which supports booting in 64-bit mode; false if it is raw 32-bit or any type + * of self-extracting kernel such as a bzImage. * Return: -ve error code. This function does not return if the kernel was * booted successfully. */ -int boot_linux_kernel(ulong setup_base, ulong load_address, bool image_64bit); +int boot_linux_kernel(ulong setup_base, ulong entry, bool image_64bit); #endif diff --git a/arch/x86/lib/bootm.c b/arch/x86/lib/bootm.c index 873e2bc..9beb376 100644 --- a/arch/x86/lib/bootm.c +++ b/arch/x86/lib/bootm.c @@ -149,7 +149,7 @@ error: return 1; } -int boot_linux_kernel(ulong setup_base, ulong load_address, bool image_64bit) +int boot_linux_kernel(ulong setup_base, ulong entry, bool image_64bit) { bootm_announce_and_cleanup(); @@ -161,14 +161,23 @@ int boot_linux_kernel(ulong setup_base, ulong load_address, bool image_64bit) puts("Cannot boot 64-bit kernel on 32-bit machine\n"); return -EFAULT; } - /* At present 64-bit U-Boot does not support booting a + /* + * At present 64-bit U-Boot only supports booting a 64-bit * kernel. - * TODO(sjg@chromium.org): Support booting both 32-bit and - * 64-bit kernels from 64-bit U-Boot. + * + * TODO(sjg@chromium.org): Support booting 32-bit kernels from + * 64-bit U-Boot */ -#if !CONFIG_IS_ENABLED(X86_64) - return cpu_jump_to_64bit(setup_base, load_address); -#endif + if (CONFIG_IS_ENABLED(X86_64)) { + typedef void (*h_func)(ulong zero, ulong setup); + h_func func; + + /* jump to Linux with rdi=0, rsi=setup_base */ + func = (h_func)entry; + func(0, setup_base); + } else { + return cpu_jump_to_64bit(setup_base, entry); + } } else { /* * Set %ebx, %ebp, and %edi to 0, %esi to point to the @@ -190,7 +199,7 @@ int boot_linux_kernel(ulong setup_base, ulong load_address, bool image_64bit) "movl $0, %%ebp\n" "cli\n" "jmp *%[kernel_entry]\n" - :: [kernel_entry]"a"(load_address), + :: [kernel_entry]"a"(entry), [boot_params] "S"(setup_base), "b"(0), "D"(0) ); diff --git a/arch/x86/lib/zimage.c b/arch/x86/lib/zimage.c index a6d9151..e5ea512 100644 --- a/arch/x86/lib/zimage.c +++ b/arch/x86/lib/zimage.c @@ -504,13 +504,24 @@ static int do_zboot_info(struct cmd_tbl *cmdtp, int flag, int argc, static int do_zboot_go(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { + struct boot_params *params = state.base_ptr; + struct setup_header *hdr = ¶ms->hdr; + bool image_64bit; + ulong entry; int ret; disable_interrupts(); + entry = state.load_address; + image_64bit = false; + if (IS_ENABLED(CONFIG_X86_RUN_64BIT) && + (hdr->xloadflags & XLF_KERNEL_64)) { + entry += 0x200; + image_64bit = true; + } + /* we assume that the kernel is in place */ - ret = boot_linux_kernel((ulong)state.base_ptr, state.load_address, - false); + ret = boot_linux_kernel((ulong)state.base_ptr, entry, image_64bit); printf("Kernel returned! (err=%d)\n", ret); return CMD_RET_FAILURE; -- cgit v1.1 From 5a2a1d8093d0372d7fc2ad1a9ae4893c888e6623 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 20 Mar 2023 08:30:09 +1300 Subject: x86: Exit EFI boot services before starting kernel When running the EFI app, we need to exit boot services before jumping to Linux. At some point it may be possible to jump to Linux and pass on the system table, and: * install the device-tree as configuration table * use LoadImage() to load the kernel image (e.g. from memory) * start the image with StartImage() This should allow the Linux efistub to be used. For now, this is not implemented. Signed-off-by: Simon Glass --- arch/x86/lib/bootm.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/arch/x86/lib/bootm.c b/arch/x86/lib/bootm.c index 9beb376..61cb7bc 100644 --- a/arch/x86/lib/bootm.c +++ b/arch/x86/lib/bootm.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -156,6 +157,23 @@ int boot_linux_kernel(ulong setup_base, ulong entry, bool image_64bit) #ifdef CONFIG_SYS_COREBOOT timestamp_add_now(TS_U_BOOT_START_KERNEL); #endif + + /* + * Exit EFI boot services just before jumping, after all console + * output, since the console won't be available afterwards. + */ + if (IS_ENABLED(CONFIG_EFI_APP)) { + int ret; + + ret = efi_store_memory_map(efi_get_priv()); + if (ret) + return ret; + printf("Exiting EFI boot services\n"); + ret = efi_call_exit_boot_services(); + if (ret) + return ret; + } + if (image_64bit) { if (!cpu_has_64bit()) { puts("Cannot boot 64-bit kernel on 32-bit machine\n"); -- cgit v1.1 From a6d263f59e8140801bd38f61cc837f244f31f418 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 20 Mar 2023 08:30:10 +1300 Subject: x86: Support zboot and bootm in the EFI app These have been disabled due to the rudimentary support available. It is a little better now, so enable these options. Signed-off-by: Simon Glass Reviewed-by: Heinrich Schuchardt --- configs/efi-x86_app32_defconfig | 2 +- configs/efi-x86_app64_defconfig | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/configs/efi-x86_app32_defconfig b/configs/efi-x86_app32_defconfig index 905f375..50975db 100644 --- a/configs/efi-x86_app32_defconfig +++ b/configs/efi-x86_app32_defconfig @@ -19,7 +19,7 @@ CONFIG_DISPLAY_BOARDINFO_LATE=y CONFIG_LAST_STAGE_INIT=y CONFIG_HUSH_PARSER=y CONFIG_SYS_PBSIZE=532 -# CONFIG_CMD_BOOTM is not set +CONFIG_CMD_BOOTZ=y CONFIG_CMD_PART=y # CONFIG_CMD_NET is not set CONFIG_CMD_TIME=y diff --git a/configs/efi-x86_app64_defconfig b/configs/efi-x86_app64_defconfig index f1cf43c..0fc358d 100644 --- a/configs/efi-x86_app64_defconfig +++ b/configs/efi-x86_app64_defconfig @@ -20,7 +20,7 @@ CONFIG_DISPLAY_BOARDINFO_LATE=y CONFIG_LAST_STAGE_INIT=y CONFIG_HUSH_PARSER=y CONFIG_SYS_PBSIZE=532 -# CONFIG_CMD_BOOTM is not set +CONFIG_CMD_BOOTZ=y CONFIG_CMD_PART=y # CONFIG_CMD_NET is not set CONFIG_CMD_CACHE=y -- cgit v1.1 From ac93275d79f85a169006a07e6a669b78970f381d Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 20 Mar 2023 08:30:11 +1300 Subject: efi: Add another tranch of GUIDs Provide information about the GUIDs supplied by QEMU, so far as it is known. These values are used in the 'efi table' command as well as the printf format string %sU Signed-off-by: Simon Glass --- include/efi_api.h | 19 +++++++++++++++++++ lib/uuid.c | 8 ++++++++ 2 files changed, 27 insertions(+) diff --git a/include/efi_api.h b/include/efi_api.h index 7f09253..c4512ee 100644 --- a/include/efi_api.h +++ b/include/efi_api.h @@ -1909,6 +1909,25 @@ struct efi_system_resource_table { EFI_GUID(0x4aafd29d, 0x68df, 0x49ee, 0x8a, 0xa9, \ 0x34, 0x7d, 0x37, 0x56, 0x65, 0xa7) +#define EFI_LZMA_COMPRESSED \ + EFI_GUID(0xee4e5898, 0x3914, 0x4259, 0x9d, 0x6e, \ + 0xdc, 0x7b, 0xd7, 0x94, 0x03, 0xcf) +#define EFI_DXE_SERVICES \ + EFI_GUID(0x05ad34ba, 0x6f02, 0x4214, 0x95, 0x2e, \ + 0x4d, 0xa0, 0x39, 0x8e, 0x2b, 0xb9) +#define EFI_HOB_LIST \ + EFI_GUID(0x7739f24c, 0x93d7, 0x11d4, 0x9a, 0x3a, \ + 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d) +#define EFI_MEMORY_TYPE \ + EFI_GUID(0x4c19049f, 0x4137, 0x4dd3, 0x9c, 0x10, \ + 0x8b, 0x97, 0xa8, 0x3f, 0xfd, 0xfa) +#define EFI_MEM_STATUS_CODE_REC \ + EFI_GUID(0x060cc026, 0x4c0d, 0x4dda, 0x8f, 0x41, \ + 0x59, 0x5f, 0xef, 0x00, 0xa5, 0x02) +#define EFI_GUID_EFI_ACPI1 \ + EFI_GUID(0xeb9d2d30, 0x2d88, 0x11d3, 0x9a, 0x16, \ + 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d) + /** * struct win_certificate_uefi_guid - A certificate that encapsulates * a GUID-specific signature diff --git a/lib/uuid.c b/lib/uuid.c index 465e1ac..5ea30a6 100644 --- a/lib/uuid.c +++ b/lib/uuid.c @@ -255,6 +255,14 @@ static const struct { EFI_CERT_TYPE_PKCS7_GUID, }, #endif +#ifdef CONFIG_EFI + { "EFI_LZMA_COMPRESSED", EFI_LZMA_COMPRESSED }, + { "EFI_DXE_SERVICES", EFI_DXE_SERVICES }, + { "EFI_HOB_LIST", EFI_HOB_LIST }, + { "EFI_MEMORY_TYPE", EFI_MEMORY_TYPE }, + { "EFI_MEM_STATUS_CODE_REC", EFI_MEM_STATUS_CODE_REC }, + { "EFI_GUID_EFI_ACPI1", EFI_GUID_EFI_ACPI1 }, +#endif }; /* -- cgit v1.1 From 4e5e49a3c7108c07a739c1f3fbd865e67fbef868 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 20 Mar 2023 08:30:12 +1300 Subject: efi: Include GUID names with EFI app and payload These are currently only available when running with EFI_LOADER. Expand this to include the app and payload, since it is useful to be able to decode things there. Signed-off-by: Simon Glass --- lib/uuid.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/uuid.c b/lib/uuid.c index 5ea30a6..96e1af3 100644 --- a/lib/uuid.c +++ b/lib/uuid.c @@ -102,7 +102,7 @@ static const struct { {"lvm", PARTITION_LINUX_LVM_GUID}, {"u-boot-env", PARTITION_U_BOOT_ENVIRONMENT}, #endif -#ifdef CONFIG_CMD_EFIDEBUG +#if defined(CONFIG_CMD_EFIDEBUG) || defined(CONFIG_EFI) { "Device Path", EFI_DEVICE_PATH_PROTOCOL_GUID, -- cgit v1.1 From 30c9646eff1e8559865e3eb6581c15e96660d254 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 20 Mar 2023 08:30:13 +1300 Subject: doc: Add help for the efi command This command currently has no help. Add some. Signed-off-by: Simon Glass --- doc/usage/cmd/efi.rst | 197 ++++++++++++++++++++++++++++++++++++++++++++++++++ doc/usage/index.rst | 1 + 2 files changed, 198 insertions(+) create mode 100644 doc/usage/cmd/efi.rst diff --git a/doc/usage/cmd/efi.rst b/doc/usage/cmd/efi.rst new file mode 100644 index 0000000..c029c42 --- /dev/null +++ b/doc/usage/cmd/efi.rst @@ -0,0 +1,197 @@ +.. SPDX-License-Identifier: GPL-2.0+ +.. Copyright 2020, Heinrich Schuchardt + +efi command +=========== + +Synopsis +-------- + +:: + + efi mem [all] + +Description +----------- + +The *efi* command provides information about the EFI environment U-Boot is +running in, when it is started from EFI. + +When running as an EFI app, this command queries EFI boot services for the +information. When running as an EFI payload, EFI boot services have been +stopped, so it uses the information collected by the boot stub before that +happened. + +efi mem +~~~~~~~ + +This shows the EFI memory map, sorted in order of physical address. + +This is normally a very large table. To help reduce the amount of detritus, +boot-time memory is normally merged with conventional memory. Use the 'all' +argument to show everything. + +The fields are as follows: + +# + Entry number (sequentially from 0) + +Type + Memory type. EFI has a large number of memory types. The type is shown in + the format : where in is the format number in hex and is the + name. + +Physical + Physical address + +Virtual + Virtual address + +Size + Size of memory area in bytes + +Attributes + Shows a code for memory attributes. The key for this is shown below the + table. + +Example +------- + +:: + + => efi mem + EFI table at 0, memory map 000000001ad38b60, size 1260, key a79, version 1, descr. size 0x30 + # Type Physical Virtual Size Attributes + 0 7:conv 0000000000 0000000000 00000a0000 f + 00000a0000 0000060000 + 1 7:conv 0000100000 0000000000 0000700000 f + 2 a:acpi_nvs 0000800000 0000000000 0000008000 f + 3 7:conv 0000808000 0000000000 0000008000 f + 4 a:acpi_nvs 0000810000 0000000000 00000f0000 f + 5 7:conv 0000900000 0000000000 001efef000 f + 6 6:rt_data 001f8ef000 0000000000 0000100000 rf + 7 5:rt_code 001f9ef000 0000000000 0000100000 rf + 8 0:reserved 001faef000 0000000000 0000080000 f + 9 9:acpi_reclaim 001fb6f000 0000000000 0000010000 f + 10 a:acpi_nvs 001fb7f000 0000000000 0000080000 f + 11 7:conv 001fbff000 0000000000 0000359000 f + 12 6:rt_data 001ff58000 0000000000 0000020000 rf + 13 a:acpi_nvs 001ff78000 0000000000 0000088000 f + 0020000000 0090000000 + 14 0:reserved 00b0000000 0000000000 0010000000 1 + + Attributes key: + f: uncached, write-coalescing, write-through, write-back + rf: uncached, write-coalescing, write-through, write-back, needs runtime mapping + 1: uncached + *Some areas are merged (use 'all' to see) + + + => efi mem all + EFI table at 0, memory map 000000001ad38bb0, size 1260, key a79, version 1, descr. size 0x30 + # Type Physical Virtual Size Attributes + 0 3:bs_code 0000000000 0000000000 0000001000 f + 1 7:conv 0000001000 0000000000 000009f000 f + 00000a0000 0000060000 + 2 7:conv 0000100000 0000000000 0000700000 f + 3 a:acpi_nvs 0000800000 0000000000 0000008000 f + 4 7:conv 0000808000 0000000000 0000008000 f + 5 a:acpi_nvs 0000810000 0000000000 00000f0000 f + 6 4:bs_data 0000900000 0000000000 0000c00000 f + 7 7:conv 0001500000 0000000000 000aa36000 f + 8 2:loader_data 000bf36000 0000000000 0010000000 f + 9 4:bs_data 001bf36000 0000000000 0000020000 f + 10 7:conv 001bf56000 0000000000 00021e1000 f + 11 1:loader_code 001e137000 0000000000 00000c4000 f + 12 7:conv 001e1fb000 0000000000 000009b000 f + 13 1:loader_code 001e296000 0000000000 00000e2000 f + 14 7:conv 001e378000 0000000000 000005b000 f + 15 4:bs_data 001e3d3000 0000000000 000001e000 f + 16 7:conv 001e3f1000 0000000000 0000016000 f + 17 4:bs_data 001e407000 0000000000 0000016000 f + 18 2:loader_data 001e41d000 0000000000 0000002000 f + 19 4:bs_data 001e41f000 0000000000 0000828000 f + 20 3:bs_code 001ec47000 0000000000 0000045000 f + 21 4:bs_data 001ec8c000 0000000000 0000001000 f + 22 3:bs_code 001ec8d000 0000000000 000000e000 f + 23 4:bs_data 001ec9b000 0000000000 0000001000 f + 24 3:bs_code 001ec9c000 0000000000 000002c000 f + 25 4:bs_data 001ecc8000 0000000000 0000001000 f + 26 3:bs_code 001ecc9000 0000000000 000000c000 f + 27 4:bs_data 001ecd5000 0000000000 0000006000 f + 28 3:bs_code 001ecdb000 0000000000 0000014000 f + 29 4:bs_data 001ecef000 0000000000 0000001000 f + 30 3:bs_code 001ecf0000 0000000000 000005b000 f + 31 4:bs_data 001ed4b000 0000000000 000000b000 f + 32 3:bs_code 001ed56000 0000000000 0000024000 f + 33 4:bs_data 001ed7a000 0000000000 0000006000 f + 34 3:bs_code 001ed80000 0000000000 0000010000 f + 35 4:bs_data 001ed90000 0000000000 0000002000 f + 36 3:bs_code 001ed92000 0000000000 0000025000 f + 37 4:bs_data 001edb7000 0000000000 0000003000 f + 38 3:bs_code 001edba000 0000000000 0000011000 f + 39 4:bs_data 001edcb000 0000000000 0000008000 f + 40 3:bs_code 001edd3000 0000000000 000002d000 f + 41 4:bs_data 001ee00000 0000000000 0000201000 f + 42 3:bs_code 001f001000 0000000000 0000024000 f + 43 4:bs_data 001f025000 0000000000 0000002000 f + 44 3:bs_code 001f027000 0000000000 0000009000 f + 45 4:bs_data 001f030000 0000000000 0000005000 f + 46 3:bs_code 001f035000 0000000000 000002f000 f + 47 4:bs_data 001f064000 0000000000 0000001000 f + 48 3:bs_code 001f065000 0000000000 0000005000 f + 49 4:bs_data 001f06a000 0000000000 0000005000 f + 50 3:bs_code 001f06f000 0000000000 0000007000 f + 51 4:bs_data 001f076000 0000000000 0000007000 f + 52 3:bs_code 001f07d000 0000000000 000000d000 f + 53 4:bs_data 001f08a000 0000000000 0000001000 f + 54 3:bs_code 001f08b000 0000000000 0000006000 f + 55 4:bs_data 001f091000 0000000000 0000004000 f + 56 3:bs_code 001f095000 0000000000 000000d000 f + 57 4:bs_data 001f0a2000 0000000000 0000003000 f + 58 3:bs_code 001f0a5000 0000000000 0000026000 f + 59 4:bs_data 001f0cb000 0000000000 0000005000 f + 60 3:bs_code 001f0d0000 0000000000 0000019000 f + 61 4:bs_data 001f0e9000 0000000000 0000004000 f + 62 3:bs_code 001f0ed000 0000000000 0000024000 f + 63 4:bs_data 001f111000 0000000000 0000008000 f + 64 3:bs_code 001f119000 0000000000 000000b000 f + 65 4:bs_data 001f124000 0000000000 0000001000 f + 66 3:bs_code 001f125000 0000000000 0000002000 f + 67 4:bs_data 001f127000 0000000000 0000002000 f + 68 3:bs_code 001f129000 0000000000 0000009000 f + 69 4:bs_data 001f132000 0000000000 0000003000 f + 70 3:bs_code 001f135000 0000000000 0000005000 f + 71 4:bs_data 001f13a000 0000000000 0000003000 f + 72 3:bs_code 001f13d000 0000000000 0000005000 f + 73 4:bs_data 001f142000 0000000000 0000003000 f + 74 3:bs_code 001f145000 0000000000 0000011000 f + 75 4:bs_data 001f156000 0000000000 000000b000 f + 76 3:bs_code 001f161000 0000000000 0000009000 f + 77 4:bs_data 001f16a000 0000000000 0000400000 f + 78 3:bs_code 001f56a000 0000000000 0000006000 f + 79 4:bs_data 001f570000 0000000000 0000001000 f + 80 3:bs_code 001f571000 0000000000 0000001000 f + 81 4:bs_data 001f572000 0000000000 0000002000 f + 82 3:bs_code 001f574000 0000000000 0000017000 f + 83 4:bs_data 001f58b000 0000000000 0000364000 f + 84 6:rt_data 001f8ef000 0000000000 0000100000 rf + 85 5:rt_code 001f9ef000 0000000000 0000100000 rf + 86 0:reserved 001faef000 0000000000 0000080000 f + 87 9:acpi_reclaim 001fb6f000 0000000000 0000010000 f + 88 a:acpi_nvs 001fb7f000 0000000000 0000080000 f + 89 4:bs_data 001fbff000 0000000000 0000201000 f + 90 7:conv 001fe00000 0000000000 00000e8000 f + 91 4:bs_data 001fee8000 0000000000 0000020000 f + 92 3:bs_code 001ff08000 0000000000 0000026000 f + 93 4:bs_data 001ff2e000 0000000000 0000009000 f + 94 3:bs_code 001ff37000 0000000000 0000021000 f + 95 6:rt_data 001ff58000 0000000000 0000020000 rf + 96 a:acpi_nvs 001ff78000 0000000000 0000088000 f + 0020000000 0090000000 + 97 0:reserved 00b0000000 0000000000 0010000000 1 + + Attributes key: + f: uncached, write-coalescing, write-through, write-back + rf: uncached, write-coalescing, write-through, write-back, needs runtime mapping + 1: uncached diff --git a/doc/usage/index.rst b/doc/usage/index.rst index d01d38c..bc85e1d 100644 --- a/doc/usage/index.rst +++ b/doc/usage/index.rst @@ -43,6 +43,7 @@ Shell commands cmd/dm cmd/ebtupdate cmd/echo + cmd/efi cmd/eficonfig cmd/env cmd/event -- cgit v1.1 From 041840eeeb129ab979cbc05d6c5fb80162f50add Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 20 Mar 2023 08:30:14 +1300 Subject: efi: Split out table-listing code into a new file This code is used with EFI_LOADER but is also useful (with some modifications) for the EFI app and payload. Move it into a shared file. Show the address of the table so it can be examined if needed. Also show the table name as unknown if necessary. Our list of GUIDs is fairly small. Signed-off-by: Simon Glass --- cmd/Makefile | 2 +- cmd/efi_common.c | 26 ++++++++++++++++++++++++++ cmd/efidebug.c | 6 +----- include/efi.h | 9 +++++++++ 4 files changed, 37 insertions(+), 6 deletions(-) create mode 100644 cmd/efi_common.c diff --git a/cmd/Makefile b/cmd/Makefile index 7198029..62f50e2 100644 --- a/cmd/Makefile +++ b/cmd/Makefile @@ -63,7 +63,7 @@ obj-$(CONFIG_CMD_ECHO) += echo.o obj-$(CONFIG_ENV_IS_IN_EEPROM) += eeprom.o obj-$(CONFIG_CMD_EEPROM) += eeprom.o obj-$(CONFIG_EFI) += efi.o -obj-$(CONFIG_CMD_EFIDEBUG) += efidebug.o +obj-$(CONFIG_CMD_EFIDEBUG) += efidebug.o efi_common.o obj-$(CONFIG_CMD_EFICONFIG) += eficonfig.o ifdef CONFIG_CMD_EFICONFIG ifdef CONFIG_EFI_MM_COMM_TEE diff --git a/cmd/efi_common.c b/cmd/efi_common.c new file mode 100644 index 0000000..f405609 --- /dev/null +++ b/cmd/efi_common.c @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Common code for EFI commands + * + * Copyright 2023 Google LLC + * Written by Simon Glass + */ + +#include +#include +#include +#include + +void efi_show_tables(struct efi_system_table *systab) +{ + int i; + + for (i = 0; i < systab->nr_tables; i++) { + struct efi_configuration_table *tab = &systab->tables[i]; + char guid_str[37]; + + uuid_bin_to_str(tab->guid.b, guid_str, 1); + printf("%p %pUl %s\n", tab->table, guid_str, + uuid_guid_get_str(tab->guid.b) ?: "(unknown)"); + } +} diff --git a/cmd/efidebug.c b/cmd/efidebug.c index e6959ed..9622430 100644 --- a/cmd/efidebug.c +++ b/cmd/efidebug.c @@ -649,11 +649,7 @@ static int do_efi_show_memmap(struct cmd_tbl *cmdtp, int flag, static int do_efi_show_tables(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { - efi_uintn_t i; - - for (i = 0; i < systab.nr_tables; ++i) - printf("%pUl (%pUs)\n", - &systab.tables[i].guid, &systab.tables[i].guid); + efi_show_tables(&systab); return CMD_RET_SUCCESS; } diff --git a/include/efi.h b/include/efi.h index 2f312da..f0e5faa 100644 --- a/include/efi.h +++ b/include/efi.h @@ -648,4 +648,13 @@ int efi_call_exit_boot_services(void); int efi_get_mmap(struct efi_mem_desc **descp, int *sizep, uint *keyp, int *desc_sizep, uint *versionp); +/** + * efi_show_tables() - Show a list of available tables + * + * Shows the address, GUID (and name where known) for each table + * + * @systab: System table containing the list of tables + */ +void efi_show_tables(struct efi_system_table *systab); + #endif /* _LINUX_EFI_H */ -- cgit v1.1 From 1d32eee4faedc11d98a342c92aa7d139d9b204cc Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 20 Mar 2023 08:30:15 +1300 Subject: efi: Support showing tables Add a command (for the app and payload) to display the tables provided by EFI. Note that for the payload the tables should always be present, so an error message is unnecessary and would bloat the code. Signed-off-by: Simon Glass --- cmd/Makefile | 2 +- cmd/efi.c | 31 ++++++++++++++++++++++++++++++- doc/usage/cmd/efi.rst | 22 ++++++++++++++++++++++ 3 files changed, 53 insertions(+), 2 deletions(-) diff --git a/cmd/Makefile b/cmd/Makefile index 62f50e2..d95833b 100644 --- a/cmd/Makefile +++ b/cmd/Makefile @@ -62,7 +62,7 @@ obj-$(CONFIG_CMD_EXTENSION) += extension_board.o obj-$(CONFIG_CMD_ECHO) += echo.o obj-$(CONFIG_ENV_IS_IN_EEPROM) += eeprom.o obj-$(CONFIG_CMD_EEPROM) += eeprom.o -obj-$(CONFIG_EFI) += efi.o +obj-$(CONFIG_EFI) += efi.o efi_common.o obj-$(CONFIG_CMD_EFIDEBUG) += efidebug.o efi_common.o obj-$(CONFIG_CMD_EFICONFIG) += eficonfig.o ifdef CONFIG_CMD_EFICONFIG diff --git a/cmd/efi.c b/cmd/efi.c index c0384e0..6cd5361 100644 --- a/cmd/efi.c +++ b/cmd/efi.c @@ -7,10 +7,12 @@ #include #include #include +#include #include #include #include #include +#include #include DECLARE_GLOBAL_DATA_PTR; @@ -273,8 +275,34 @@ done: return ret ? CMD_RET_FAILURE : 0; } +static int do_efi_tables(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + struct efi_system_table *systab; + + if (IS_ENABLED(CONFIG_EFI_APP)) { + systab = efi_get_sys_table(); + if (!systab) { + printf("Cannot read system table\n"); + return CMD_RET_FAILURE; + } + } else { + int size; + int ret; + + ret = efi_info_get(EFIET_SYS_TABLE, (void **)&systab, &size); + if (ret) /* this should not happen */ + return CMD_RET_FAILURE; + } + + efi_show_tables(systab); + + return 0; +} + static struct cmd_tbl efi_commands[] = { U_BOOT_CMD_MKENT(mem, 1, 1, do_efi_mem, "", ""), + U_BOOT_CMD_MKENT(tables, 1, 1, do_efi_tables, "", ""), }; static int do_efi(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) @@ -298,5 +326,6 @@ static int do_efi(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) U_BOOT_CMD( efi, 3, 1, do_efi, "EFI access", - "mem [all] Dump memory information [include boot services]" + "mem [all] Dump memory information [include boot services]\n" + "tables Dump tables" ); diff --git a/doc/usage/cmd/efi.rst b/doc/usage/cmd/efi.rst index c029c42..ef37ff2 100644 --- a/doc/usage/cmd/efi.rst +++ b/doc/usage/cmd/efi.rst @@ -10,6 +10,7 @@ Synopsis :: efi mem [all] + efi tables Description ----------- @@ -54,6 +55,14 @@ Attributes Shows a code for memory attributes. The key for this is shown below the table. +efi tables +~~~~~~~~~~ + +This shows a list of the EFI tables provided in the system table. These use +GUIDs so it is not possible in general to show the name of a table. But some +effort is made to provide a useful table, where the GUID is known by U-Boot. + + Example ------- @@ -195,3 +204,16 @@ Example f: uncached, write-coalescing, write-through, write-back rf: uncached, write-coalescing, write-through, write-back, needs runtime mapping 1: uncached + + + => efi tables + 000000001f8edf98 ee4e5898-3914-4259-9d6e-dc7bd79403cf EFI_LZMA_COMPRESSED + 000000001ff2ace0 05ad34ba-6f02-4214-952e-4da0398e2bb9 EFI_DXE_SERVICES + 000000001f8ea018 7739f24c-93d7-11d4-9a3a-0090273fc14d EFI_HOB_LIST + 000000001ff2bac0 4c19049f-4137-4dd3-9c10-8b97a83ffdfa EFI_MEMORY_TYPE + 000000001ff2cb10 49152e77-1ada-4764-b7a2-7afefed95e8b (unknown) + 000000001f9ac018 060cc026-4c0d-4dda-8f41-595fef00a502 EFI_MEM_STATUS_CODE_REC + 000000001f9ab000 eb9d2d31-2d88-11d3-9a16-0090273fc14d SMBIOS table + 000000001fb7e000 eb9d2d30-2d88-11d3-9a16-0090273fc14d EFI_GUID_EFI_ACPI1 + 000000001fb7e014 8868e871-e4f1-11d3-bc22-0080c73c8881 ACPI table + 000000001e654018 dcfa911d-26eb-469f-a220-38b7dc461220 (unknown) -- cgit v1.1 From ed10008babeb6750555f26fd8fbb4572489d635c Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 20 Mar 2023 08:30:16 +1300 Subject: efI: Allow packaging a kernel in the debugging script Add an option to package a kernel into the debugging script used for EFI. The name of the kernel must be added to the script. By default it is assumed that the kernel is built in the /tmp/kernel directory. Signed-off-by: Simon Glass --- scripts/build-efi.sh | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/scripts/build-efi.sh b/scripts/build-efi.sh index 46c2880..6b7df2e 100755 --- a/scripts/build-efi.sh +++ b/scripts/build-efi.sh @@ -18,12 +18,15 @@ # OVMF-pure-efi.x64.fd at # https://drive.google.com/file/d/1c39YI9QtpByGQ4V0UNNQtGqttEzS-eFV/view?usp=sharing +bzimage_fname=/tmp/kernel/arch/x86/boot/bzImage + set -e usage() { echo "Usage: $0 [-a | -p] [other opts]" 1>&2 echo 1>&2 echo " -a - Package up the app" 1>&2 + echo " -k - Add a kernel" 1>&2 echo " -o - Use old EFI app build (before 32/64 split)" 1>&2 echo " -p - Package up the payload" 1>&2 echo " -P - Create a partition table" 1>&2 @@ -52,11 +55,14 @@ serial= # before the 32/64 split of the app old= +# package up a kernel as well +kernel= + # Set ubdir to the build directory where you build U-Boot out-of-tree # We avoid in-tree build because it gets confusing trying different builds ubdir=/tmp/b/ -while getopts "aopPrsw" opt; do +while getopts "akopPrsw" opt; do case "${opt}" in a) type=app @@ -64,6 +70,9 @@ while getopts "aopPrsw" opt; do p) type=payload ;; + k) + kernel=1 + ;; r) run=1 ;; @@ -124,6 +133,9 @@ EOF # Copy files into the filesystem copy_files() { sudo cp $TMP/* $MNT + if [[ -n "${kernel}" ]]; then + sudo cp ${bzimage_fname} $MNT/vmlinuz + fi } # Create a filesystem on a raw device and copy in the files -- cgit v1.1 From 93e3364804ffd4a5d4a0df9c750a1859f9fe298b Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Thu, 23 Feb 2023 20:27:38 +0100 Subject: cmd: bootefi: allocate device-tree copy from high memory The bootefi command creates a copy of the device-tree within the first 127 MiB of memory. This may lead to overwriting previously loaded binaries (e.g. kernel, initrd). Linux EFI stub itself copies U-Boot's copy of the device-tree. This means there is not restriction for U-Boot to place the device-tree copy to any address. (Restrictions existed for 32bit ARM before Linux commit 7a1be318f579 ("ARM: 9012/1: move device tree mapping out of linear region") for legacy booting. Reported-by: Alexandre Ghiti Signed-off-by: Heinrich Schuchardt Tested-by: Alexandre Ghiti --- cmd/bootefi.c | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-) diff --git a/cmd/bootefi.c b/cmd/bootefi.c index 6618335..8aa15a6 100644 --- a/cmd/bootefi.c +++ b/cmd/bootefi.c @@ -204,25 +204,12 @@ static efi_status_t copy_fdt(void **fdtp) fdt_pages = efi_size_in_pages(fdt_totalsize(fdt) + 0x3000); fdt_size = fdt_pages << EFI_PAGE_SHIFT; - /* - * Safe fdt location is at 127 MiB. - * On the sandbox convert from the sandbox address space. - */ - new_fdt_addr = (uintptr_t)map_sysmem(fdt_ram_start + 0x7f00000 + - fdt_size, 0); - ret = efi_allocate_pages(EFI_ALLOCATE_MAX_ADDRESS, + ret = efi_allocate_pages(EFI_ALLOCATE_ANY_PAGES, EFI_ACPI_RECLAIM_MEMORY, fdt_pages, &new_fdt_addr); if (ret != EFI_SUCCESS) { - /* If we can't put it there, put it somewhere */ - new_fdt_addr = (ulong)memalign(EFI_PAGE_SIZE, fdt_size); - ret = efi_allocate_pages(EFI_ALLOCATE_MAX_ADDRESS, - EFI_ACPI_RECLAIM_MEMORY, fdt_pages, - &new_fdt_addr); - if (ret != EFI_SUCCESS) { - log_err("ERROR: Failed to reserve space for FDT\n"); - goto done; - } + log_err("ERROR: Failed to reserve space for FDT\n"); + goto done; } new_fdt = (void *)(uintptr_t)new_fdt_addr; memcpy(new_fdt, fdt, fdt_totalsize(fdt)); -- cgit v1.1