From 6abd738e20dd09bdebc9e2f9ad6162cc4b1c678e Mon Sep 17 00:00:00 2001 From: Aristo Chen Date: Fri, 24 Jul 2026 09:26:56 +0000 Subject: efi: Unify the memory map output of 'efi mem' and 'efidebug memmap' The efi and efidebug commands each carried their own code for printing the EFI memory map, with separate tables of memory type and attribute names. The copies had drifted: efidebug knew EFI_PERSISTENT_MEMORY_TYPE while 'efi mem' printed it as '', neither table knew EFI_UNACCEPTED_MEMORY_TYPE, and the 'efi mem' printer had misaligned column headers, a broken '' line and a superfluous Virtual column: the map is identity mapped before SetVirtualAddressMap() is called, so the field carries no information at the time the command can run. Move the printing loop of 'efidebug memmap' into efi_common.c as efi_show_memmap(), which is linked into both commands, and use it from both. The second copy in 'efi mem' is deleted together with efi_print_mem_table() and the private sorting and merging code, including the 'all' argument. The memory type names follow the UEFI specification with the leading 'Efi' and the trailing 'Type' stripped, for example ConventionalMemory for EfiConventionalMemory, and the missing name for unaccepted memory is added. The type column is widened to fit the longest name, MemoryMappedIOPortSpace. The shared function iterates the map with the descriptor size reported by the firmware instead of assuming sizeof(struct efi_mem_desc). This matters for 'efi mem' under EDK II based firmware, which reports a descriptor size of 0x30. The memory map key, which was printed uninitialized on the payload path, is now initialized. The command documentation is updated with output captured from the app running under OVMF, and documents why virtual addresses are not shown. Suggested-by: Heinrich Schuchardt Signed-off-by: Aristo Chen --- cmd/efi.c | 221 ++----------------------------------------------------- cmd/efi_common.c | 121 ++++++++++++++++++++++++++++++ cmd/efidebug.c | 96 +----------------------- 3 files changed, 128 insertions(+), 310 deletions(-) (limited to 'cmd') diff --git a/cmd/efi.c b/cmd/efi.c index 687ccb52042..c49a873f3da 100644 --- a/cmd/efi.c +++ b/cmd/efi.c @@ -10,223 +10,19 @@ #include #include #include -#include #include #include DECLARE_GLOBAL_DATA_PTR; -static const char *const type_name[] = { - "reserved", - "loader_code", - "loader_data", - "bs_code", - "bs_data", - "rt_code", - "rt_data", - "conv", - "unusable", - "acpi_reclaim", - "acpi_nvs", - "io", - "io_port", - "pal_code", -}; - -static struct attr_info { - u64 val; - const char *name; -} mem_attr[] = { - { EFI_MEMORY_UC, "uncached" }, - { EFI_MEMORY_WC, "write-coalescing" }, - { EFI_MEMORY_WT, "write-through" }, - { EFI_MEMORY_WB, "write-back" }, - { EFI_MEMORY_UCE, "uncached & exported" }, - { EFI_MEMORY_WP, "write-protect" }, - { EFI_MEMORY_RP, "read-protect" }, - { EFI_MEMORY_XP, "execute-protect" }, - { EFI_MEMORY_NV, "non-volatile" }, - { EFI_MEMORY_MORE_RELIABLE, "higher reliability" }, - { EFI_MEMORY_RO, "read-only" }, - { EFI_MEMORY_SP, "specific purpose" }, - { EFI_MEMORY_RUNTIME, "needs runtime mapping" } -}; - -/* Maximum different attribute values we can track */ -#define ATTR_SEEN_MAX 30 - -static inline bool is_boot_services(int type) -{ - return type == EFI_LOADER_CODE || type == EFI_LOADER_DATA || - type == EFI_BOOT_SERVICES_CODE || - type == EFI_BOOT_SERVICES_DATA; -} - -static int h_cmp_entry(const void *v1, const void *v2) -{ - const struct efi_mem_desc *desc1 = v1; - const struct efi_mem_desc *desc2 = v2; - int64_t diff = desc1->physical_start - desc2->physical_start; - - /* - * Manually calculate the difference to avoid sign loss in the 64-bit - * to 32-bit conversion - */ - return diff < 0 ? -1 : diff > 0 ? 1 : 0; -} - -/** - * efi_build_mem_table() - make a sorted copy of the memory table - * - * @desc_base: Pointer to EFI memory map table - * @size: Size of table in bytes - * @desc_size: Size of each @desc_base record - * @skip_bs: True to skip boot-time memory and merge it with conventional - * memory. This will significantly reduce the number of table - * entries. - * Return: pointer to the new table. It should be freed with free() by the - * caller. - */ -static void *efi_build_mem_table(struct efi_mem_desc *desc_base, int size, - int desc_size, bool skip_bs) -{ - struct efi_mem_desc *desc, *end, *base, *dest, *prev; - int count; - u64 addr; - - base = malloc(size + sizeof(*desc)); - if (!base) { - debug("%s: Cannot allocate %#x bytes\n", __func__, size); - return NULL; - } - end = (void *)desc_base + size; - count = ((ulong)end - (ulong)desc_base) / desc_size; - memcpy(base, desc_base, (ulong)end - (ulong)desc_base); - qsort(base, count, desc_size, h_cmp_entry); - prev = NULL; - addr = 0; - dest = base; - end = (struct efi_mem_desc *)((ulong)base + count * desc_size); - for (desc = base; desc < end; - desc = efi_get_next_mem_desc(desc, desc_size)) { - bool merge = true; - u32 type = desc->type; - - if (type >= EFI_MAX_MEMORY_TYPE) { - printf("Memory map contains invalid entry type %u\n", - type); - continue; - } - - if (skip_bs && is_boot_services(desc->type)) - type = EFI_CONVENTIONAL_MEMORY; - - memcpy(dest, desc, desc_size); - dest->type = type; - if (!skip_bs || !prev) - merge = false; - else if (desc->physical_start != addr) - merge = false; - else if (type != EFI_CONVENTIONAL_MEMORY) - merge = false; - else if (prev->type != EFI_CONVENTIONAL_MEMORY) - merge = false; - - if (merge) { - prev->num_pages += desc->num_pages; - } else { - prev = dest; - dest = efi_get_next_mem_desc(dest, desc_size); - } - addr = desc->physical_start + (desc->num_pages << - EFI_PAGE_SHIFT); - } - - /* Mark the end */ - dest->type = EFI_MAX_MEMORY_TYPE; - - return base; -} - -static void efi_print_mem_table(struct efi_mem_desc *desc, int desc_size, - bool skip_bs) -{ - u64 attr_seen[ATTR_SEEN_MAX]; - int attr_seen_count; - int upto, i; - u64 addr; - - printf(" # %-14s %10s %10s %10s %s\n", "Type", "Physical", - "Virtual", "Size", "Attributes"); - - /* Keep track of all the different attributes we have seen */ - attr_seen_count = 0; - addr = 0; - for (upto = 0; desc->type != EFI_MAX_MEMORY_TYPE; - upto++, desc = efi_get_next_mem_desc(desc, desc_size)) { - const char *name; - u64 size; - - if (skip_bs && is_boot_services(desc->type)) - continue; - if (desc->physical_start != addr) { - printf(" %-14s %010llx %10s %010llx\n", "", - addr, "", desc->physical_start - addr); - } - size = desc->num_pages << EFI_PAGE_SHIFT; - - name = desc->type < ARRAY_SIZE(type_name) ? - type_name[desc->type] : ""; - printf("%2d %x:%-12s %010llx %010llx %010llx ", upto, - desc->type, name, desc->physical_start, - desc->virtual_start, size); - if (desc->attribute & EFI_MEMORY_RUNTIME) - putc('r'); - printf("%llx", desc->attribute & ~EFI_MEMORY_RUNTIME); - putc('\n'); - - for (i = 0; i < attr_seen_count; i++) { - if (attr_seen[i] == desc->attribute) - break; - } - if (i == attr_seen_count && i < ATTR_SEEN_MAX) - attr_seen[attr_seen_count++] = desc->attribute; - addr = desc->physical_start + size; - } - - printf("\nAttributes key:\n"); - for (i = 0; i < attr_seen_count; i++) { - u64 attr = attr_seen[i]; - bool first; - int j; - - printf("%c%llx: ", (attr & EFI_MEMORY_RUNTIME) ? 'r' : ' ', - attr & ~EFI_MEMORY_RUNTIME); - for (j = 0, first = true; j < ARRAY_SIZE(mem_attr); j++) { - if (attr & mem_attr[j].val) { - if (first) - first = false; - else - printf(", "); - printf("%s", mem_attr[j].name); - } - } - putc('\n'); - } - if (skip_bs) - printf("*Some areas are merged (use 'all' to see)\n"); -} - static int do_efi_mem(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { - struct efi_mem_desc *orig, *desc; - uint version, key; + struct efi_mem_desc *orig; + uint version, key = 0; int desc_size; int size, ret; - bool skip_bs; - skip_bs = !argc || *argv[0] != 'a'; if (IS_ENABLED(CONFIG_EFI_APP)) { ret = efi_get_mmap(&orig, &size, &key, &desc_size, &version); if (ret) { @@ -257,14 +53,7 @@ static int do_efi_mem(struct cmd_tbl *cmdtp, int flag, int argc, goto done; } - desc = efi_build_mem_table(orig, size, desc_size, skip_bs); - if (!desc) { - ret = -ENOMEM; - goto done; - } - - efi_print_mem_table(desc, desc_size, skip_bs); - free(desc); + efi_show_memmap(orig, size, desc_size); if (IS_ENABLED(CONFIG_EFI_APP)) free(orig); done: @@ -300,7 +89,7 @@ static int do_efi_tables(struct cmd_tbl *cmdtp, int flag, int argc, } static struct cmd_tbl efi_commands[] = { - U_BOOT_CMD_MKENT(mem, 1, 1, do_efi_mem, "", ""), + U_BOOT_CMD_MKENT(mem, 0, 1, do_efi_mem, "", ""), U_BOOT_CMD_MKENT(tables, 1, 1, do_efi_tables, "", ""), }; @@ -325,6 +114,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]\n" + "mem Dump memory map\n" "tables Dump tables" ); diff --git a/cmd/efi_common.c b/cmd/efi_common.c index d2f2b59e9e3..904747c5b32 100644 --- a/cmd/efi_common.c +++ b/cmd/efi_common.c @@ -8,8 +8,59 @@ #include #include +#include #include +/* Width of an EFI physical address in hexadecimal digits */ +#define EFI_PHYS_ADDR_WIDTH (int)(sizeof(efi_physical_addr_t) * 2) + +/* Width of the memory type column, sized for the longest type name */ +#define EFI_MEM_TYPE_WIDTH 23 + +/* + * The type names of the UEFI specification without the leading 'Efi' and + * the trailing 'Type' + */ +static const char *const efi_mem_type_string[] = { + [EFI_RESERVED_MEMORY_TYPE] = "ReservedMemory", + [EFI_LOADER_CODE] = "LoaderCode", + [EFI_LOADER_DATA] = "LoaderData", + [EFI_BOOT_SERVICES_CODE] = "BootServicesCode", + [EFI_BOOT_SERVICES_DATA] = "BootServicesData", + [EFI_RUNTIME_SERVICES_CODE] = "RuntimeServicesCode", + [EFI_RUNTIME_SERVICES_DATA] = "RuntimeServicesData", + [EFI_CONVENTIONAL_MEMORY] = "ConventionalMemory", + [EFI_UNUSABLE_MEMORY] = "UnusableMemory", + [EFI_ACPI_RECLAIM_MEMORY] = "ACPIReclaimMemory", + [EFI_ACPI_MEMORY_NVS] = "ACPIMemoryNVS", + [EFI_MMAP_IO] = "MemoryMappedIO", + [EFI_MMAP_IO_PORT] = "MemoryMappedIOPortSpace", + [EFI_PAL_CODE] = "PalCode", + [EFI_PERSISTENT_MEMORY_TYPE] = "PersistentMemory", + [EFI_UNACCEPTED_MEMORY_TYPE] = "UnacceptedMemory", +}; + +static const struct efi_mem_attrs { + const u64 bit; + const char *text; +} efi_mem_attrs[] = { + {EFI_MEMORY_UC, "UC"}, + {EFI_MEMORY_WC, "WC"}, + {EFI_MEMORY_WT, "WT"}, + {EFI_MEMORY_WB, "WB"}, + {EFI_MEMORY_UCE, "UCE"}, + {EFI_MEMORY_WP, "WP"}, + {EFI_MEMORY_RP, "RP"}, + {EFI_MEMORY_XP, "XP"}, + {EFI_MEMORY_NV, "NV"}, + {EFI_MEMORY_MORE_RELIABLE, "REL"}, + {EFI_MEMORY_RO, "RO"}, + {EFI_MEMORY_SP, "SP"}, + {EFI_MEMORY_CPU_CRYPTO, "CRYPT"}, + {EFI_MEMORY_HOT_PLUGGABLE, "HOTPL"}, + {EFI_MEMORY_RUNTIME, "RT"}, +}; + void efi_show_tables(struct efi_system_table *systab) { int i; @@ -21,3 +72,73 @@ void efi_show_tables(struct efi_system_table *systab) uuid_guid_get_str(tab->guid.b) ?: "(unknown)"); } } + +/** + * efi_mem_type_name() - get the name of an EFI memory type + * + * @type: memory type (enum efi_memory_type) + * Return: name of the memory type, or NULL if @type is unknown + */ +static const char *efi_mem_type_name(u32 type) +{ + if (type >= ARRAY_SIZE(efi_mem_type_string)) + return NULL; + + return efi_mem_type_string[type]; +} + +/** + * efi_print_mem_attrs() - print the names of set EFI memory attributes + * + * Prints the set attribute bits as a '|'-separated list of mnemonics, + * e.g. ' UC|WB|RT', preceded by a space. Prints nothing if no known + * attribute bit is set. + * + * @attributes: memory attributes (EFI_MEMORY_...) + */ +static void efi_print_mem_attrs(u64 attributes) +{ + int sep, i; + + for (sep = 0, i = 0; i < ARRAY_SIZE(efi_mem_attrs); i++) + if (attributes & efi_mem_attrs[i].bit) { + if (sep) { + putc('|'); + } else { + putc(' '); + sep = 1; + } + puts(efi_mem_attrs[i].text); + } +} + +void efi_show_memmap(struct efi_mem_desc *map, efi_uintn_t map_size, + efi_uintn_t desc_size) +{ + struct efi_mem_desc *end = (void *)map + map_size; + static const char sep[] = "========================"; + const char *type; + + printf("%-*s %-*s %-*s Attributes\n", + EFI_MEM_TYPE_WIDTH, "Type", + EFI_PHYS_ADDR_WIDTH, "Start", EFI_PHYS_ADDR_WIDTH, "End"); + printf("%.*s %.*s %.*s ==========\n", + EFI_MEM_TYPE_WIDTH, sep, + EFI_PHYS_ADDR_WIDTH, sep, EFI_PHYS_ADDR_WIDTH, sep); + + for (; map < end; map = efi_get_next_mem_desc(map, desc_size)) { + type = efi_mem_type_name(map->type) ?: "(unknown)"; + + printf("%-*s %.*llx-%.*llx", EFI_MEM_TYPE_WIDTH, type, + EFI_PHYS_ADDR_WIDTH, + (u64)map_to_sysmem((void *)(uintptr_t) + map->physical_start), + EFI_PHYS_ADDR_WIDTH, + (u64)map_to_sysmem((void *)(uintptr_t) + (map->physical_start + + map->num_pages * EFI_PAGE_SIZE))); + + efi_print_mem_attrs(map->attribute); + putc('\n'); + } +} diff --git a/cmd/efidebug.c b/cmd/efidebug.c index a6faa36b500..e55de04c699 100644 --- a/cmd/efidebug.c +++ b/cmd/efidebug.c @@ -574,70 +574,6 @@ static int do_efi_show_ecpt(struct cmd_tbl *cmdtp, int flag, int argc, } #endif /* CONFIG_IS_ENABLED(EFI_ECPT) */ -static const char * const efi_mem_type_string[] = { - [EFI_RESERVED_MEMORY_TYPE] = "RESERVED", - [EFI_LOADER_CODE] = "LOADER CODE", - [EFI_LOADER_DATA] = "LOADER DATA", - [EFI_BOOT_SERVICES_CODE] = "BOOT CODE", - [EFI_BOOT_SERVICES_DATA] = "BOOT DATA", - [EFI_RUNTIME_SERVICES_CODE] = "RUNTIME CODE", - [EFI_RUNTIME_SERVICES_DATA] = "RUNTIME DATA", - [EFI_CONVENTIONAL_MEMORY] = "CONVENTIONAL", - [EFI_UNUSABLE_MEMORY] = "UNUSABLE MEM", - [EFI_ACPI_RECLAIM_MEMORY] = "ACPI RECLAIM MEM", - [EFI_ACPI_MEMORY_NVS] = "ACPI NVS", - [EFI_MMAP_IO] = "IO", - [EFI_MMAP_IO_PORT] = "IO PORT", - [EFI_PAL_CODE] = "PAL", - [EFI_PERSISTENT_MEMORY_TYPE] = "PERSISTENT", -}; - -static const struct efi_mem_attrs { - const u64 bit; - const char *text; -} efi_mem_attrs[] = { - {EFI_MEMORY_UC, "UC"}, - {EFI_MEMORY_WC, "WC"}, - {EFI_MEMORY_WT, "WT"}, - {EFI_MEMORY_WB, "WB"}, - {EFI_MEMORY_UCE, "UCE"}, - {EFI_MEMORY_WP, "WP"}, - {EFI_MEMORY_RP, "RP"}, - {EFI_MEMORY_XP, "XP"}, - {EFI_MEMORY_NV, "NV"}, - {EFI_MEMORY_MORE_RELIABLE, "REL"}, - {EFI_MEMORY_RO, "RO"}, - {EFI_MEMORY_SP, "SP"}, - {EFI_MEMORY_CPU_CRYPTO, "CRYPT"}, - {EFI_MEMORY_HOT_PLUGGABLE, "HOTPL"}, - {EFI_MEMORY_RUNTIME, "RT"}, -}; - -/** - * print_memory_attributes() - print memory map attributes - * - * @attributes: Attribute value - * - * Print memory map attributes - */ -static void print_memory_attributes(u64 attributes) -{ - int sep, i; - - for (sep = 0, i = 0; i < ARRAY_SIZE(efi_mem_attrs); i++) - if (attributes & efi_mem_attrs[i].bit) { - if (sep) { - putc('|'); - } else { - putc(' '); - sep = 1; - } - puts(efi_mem_attrs[i].text); - } -} - -#define EFI_PHYS_ADDR_WIDTH (int)(sizeof(efi_physical_addr_t) * 2) - /** * do_efi_show_memmap() - show UEFI memory map * @@ -653,43 +589,15 @@ static void print_memory_attributes(u64 attributes) static int do_efi_show_memmap(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { - struct efi_mem_desc *memmap, *map; + struct efi_mem_desc *memmap; efi_uintn_t map_size; - const char *type; - int i; efi_status_t ret; ret = efi_get_memory_map_alloc(&map_size, &memmap); if (ret != EFI_SUCCESS) return CMD_RET_FAILURE; - printf("Type Start%.*s End%.*s Attributes\n", - EFI_PHYS_ADDR_WIDTH - 5, spc, EFI_PHYS_ADDR_WIDTH - 3, spc); - printf("================ %.*s %.*s ==========\n", - EFI_PHYS_ADDR_WIDTH, sep, EFI_PHYS_ADDR_WIDTH, sep); - /* - * Coverity check: dereferencing null pointer "map." - * This is a false positive as memmap will always be - * populated by allocate_pool() above. - */ - for (i = 0, map = memmap; i < map_size / sizeof(*map); map++, i++) { - if (map->type < ARRAY_SIZE(efi_mem_type_string)) - type = efi_mem_type_string[map->type]; - else - type = "(unknown)"; - - printf("%-16s %.*llx-%.*llx", type, - EFI_PHYS_ADDR_WIDTH, - (u64)map_to_sysmem((void *)(uintptr_t) - map->physical_start), - EFI_PHYS_ADDR_WIDTH, - (u64)map_to_sysmem((void *)(uintptr_t) - (map->physical_start + - map->num_pages * EFI_PAGE_SIZE))); - - print_memory_attributes(map->attribute); - putc('\n'); - } + efi_show_memmap(memmap, map_size, sizeof(*memmap)); efi_free_pool(memmap); -- cgit v1.3.1 From e394b1e848918019a0521f5e30f9f81d6e0d0ae6 Mon Sep 17 00:00:00 2001 From: Aristo Chen Date: Fri, 24 Jul 2026 09:26:57 +0000 Subject: efi: Print ISA-specific and unknown memory attributes The attribute mnemonic table did not cover EFI_MEMORY_ISA_VALID and the EFI_MEMORY_ISA_MASK field, and attribute bits without a mnemonic were silently dropped, so a memory map carrying ISA-specific, invalid or not yet known attributes displayed incomplete information without any hint that something was missing. Add a mnemonic for EFI_MEMORY_ISA_VALID and print the ISA-specific field as ISA= when it is valid, instead of decoding bits whose meaning U-Boot cannot know. Any remaining bits that match neither the mnemonic table nor the ISA field are printed as a hexadecimal value. Suggested-by: Heinrich Schuchardt Signed-off-by: Aristo Chen --- cmd/efi_common.c | 20 ++++++++++++++++++-- doc/usage/cmd/efi.rst | 5 ++++- include/efi.h | 7 ++++++- 3 files changed, 28 insertions(+), 4 deletions(-) (limited to 'cmd') diff --git a/cmd/efi_common.c b/cmd/efi_common.c index 904747c5b32..e57835d3bae 100644 --- a/cmd/efi_common.c +++ b/cmd/efi_common.c @@ -58,6 +58,7 @@ static const struct efi_mem_attrs { {EFI_MEMORY_SP, "SP"}, {EFI_MEMORY_CPU_CRYPTO, "CRYPT"}, {EFI_MEMORY_HOT_PLUGGABLE, "HOTPL"}, + {EFI_MEMORY_ISA_VALID, "ISA_VALID"}, {EFI_MEMORY_RUNTIME, "RT"}, }; @@ -91,13 +92,16 @@ static const char *efi_mem_type_name(u32 type) * efi_print_mem_attrs() - print the names of set EFI memory attributes * * Prints the set attribute bits as a '|'-separated list of mnemonics, - * e.g. ' UC|WB|RT', preceded by a space. Prints nothing if no known - * attribute bit is set. + * e.g. ' UC|WB|RT', preceded by a space. When EFI_MEMORY_ISA_VALID is + * set, the EFI_MEMORY_ISA_MASK field is printed as ISA=. Bits + * that have no mnemonic are printed as a hexadecimal value so that + * invalid or not yet known attributes are never dropped silently. * * @attributes: memory attributes (EFI_MEMORY_...) */ static void efi_print_mem_attrs(u64 attributes) { + u64 unknown = attributes; int sep, i; for (sep = 0, i = 0; i < ARRAY_SIZE(efi_mem_attrs); i++) @@ -109,7 +113,19 @@ static void efi_print_mem_attrs(u64 attributes) sep = 1; } puts(efi_mem_attrs[i].text); + unknown &= ~efi_mem_attrs[i].bit; } + + if (attributes & EFI_MEMORY_ISA_VALID) { + printf("%sISA=0x%llx", sep ? "|" : " ", + (attributes & EFI_MEMORY_ISA_MASK) >> + EFI_MEMORY_ISA_SHIFT); + sep = 1; + unknown &= ~EFI_MEMORY_ISA_MASK; + } + + if (unknown) + printf("%s0x%llx", sep ? "|" : " ", unknown); } void efi_show_memmap(struct efi_mem_desc *map, efi_uintn_t map_size, diff --git a/doc/usage/cmd/efi.rst b/doc/usage/cmd/efi.rst index 3ccdbe9410c..62a2638feca 100644 --- a/doc/usage/cmd/efi.rst +++ b/doc/usage/cmd/efi.rst @@ -45,7 +45,10 @@ Start, End Attributes The attributes of the region as a '|'-separated list of mnemonics, - e.g. UC for EFI_MEMORY_UC and RT for EFI_MEMORY_RUNTIME. + e.g. UC for EFI_MEMORY_UC and RT for EFI_MEMORY_RUNTIME. When the + region carries ISA-specific attributes (EFI_MEMORY_ISA_VALID is set), + the ISA-specific field is shown as ISA=. Attribute bits without + a mnemonic are shown as a hexadecimal value. efi tables ~~~~~~~~~~ diff --git a/include/efi.h b/include/efi.h index 71234d1b6fe..a4c21d7681d 100644 --- a/include/efi.h +++ b/include/efi.h @@ -268,6 +268,9 @@ enum efi_memory_type { #define EFI_MEMORY_CPU_CRYPTO ((u64)0x0000000000080000ULL) /* cryptographically protectable */ #define EFI_MEMORY_HOT_PLUGGABLE \ ((u64)0x0000000000100000ULL) /* hot pluggable */ +#define EFI_MEMORY_ISA_MASK ((u64)0x0FFFF00000000000ULL) /* ISA-specific attributes */ +#define EFI_MEMORY_ISA_SHIFT 44 +#define EFI_MEMORY_ISA_VALID ((u64)0x4000000000000000ULL) /* ISA_MASK field is valid */ #define EFI_MEMORY_RUNTIME ((u64)0x8000000000000000ULL) /* range requires runtime mapping */ #define EFI_MEM_DESC_VERSION 1 @@ -686,7 +689,9 @@ void efi_show_tables(struct efi_system_table *systab); * * Prints one line per descriptor with the memory type name, the physical * start and end address and the attributes as a '|'-separated list of - * mnemonics. + * mnemonics. The ISA-specific attribute field is printed as ISA= + * when EFI_MEMORY_ISA_VALID is set, and any remaining bits without a + * mnemonic are printed as a hexadecimal value. * * The virtual addresses of the descriptors are not shown: the map is * identity mapped before SetVirtualAddressMap() is called, so the field -- cgit v1.3.1 From d78ba22ab2df094a659a7ffa85e0787037f7e3a7 Mon Sep 17 00:00:00 2001 From: Scott Moser Date: Tue, 28 Jul 2026 12:33:28 -0700 Subject: efi_loader: fix use of uninitialized guid in variable enumeration loops efi_bootmgr_delete_invalid_boot_option(), eficonfig_show_boot_selection(), and eficonfig_create_change_boot_order_entry() each enumerate all EFI variables by repeatedly calling efi_next_variable_name() in a loop, passing the same efi_guid_t as both input and output. GetNextVariableName() needs the vendor GUID returned by the previous call, together with the variable name it returned, to know where to resume. In each of these loops the efi_guid_t was declared inside the loop body, so a new instance comes into scope on every iteration. Relying on it to still hold the previous iteration's value depends on the compiler reusing the same stack slot across iterations, which is undefined behavior. With a compiler that zero-initializes locals by default (e.g. clang, or gcc configured with -ftrivial-auto-var-init=zero), the GUID is cleared on every iteration, so the lookup of the variable name returned by the previous call fails and efi_init_obj_list() aborts: Cannot initialize UEFI sub-system ** Booting bootflow ... with efi Boot failed (err=-22) Move the efi_guid_t declarations out of the loops so the value written by the previous efi_next_variable_name() call is preserved across iterations. Fixes: 140a8959d48f ("eficonfig: use efi_get_next_variable_name_int()") Signed-off-by: Scott Moser Reviewed-by: Heinrich Schuchardt --- cmd/eficonfig.c | 4 ++-- lib/efi_loader/efi_bootmgr.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'cmd') diff --git a/cmd/eficonfig.c b/cmd/eficonfig.c index 4d060e3007c..d8e7ed6666a 100644 --- a/cmd/eficonfig.c +++ b/cmd/eficonfig.c @@ -1844,6 +1844,7 @@ static efi_status_t eficonfig_show_boot_selection(unsigned int *selected) struct efimenu *efi_menu; struct list_head *pos, *n; struct eficonfig_entry *entry; + efi_guid_t guid; efi_menu = calloc(1, sizeof(struct efimenu)); if (!efi_menu) @@ -1872,7 +1873,6 @@ static efi_status_t eficonfig_show_boot_selection(unsigned int *selected) var_name16[0] = 0; for (;;) { int index; - efi_guid_t guid; ret = efi_next_variable_name(&buf_size, &var_name16, &guid); if (ret == EFI_NOT_FOUND) @@ -2245,6 +2245,7 @@ static efi_status_t eficonfig_create_change_boot_order_entry(struct efimenu *efi u16 *var_name16 = NULL; efi_uintn_t size, buf_size; struct eficonfig_save_boot_order_data *save_data; + efi_guid_t guid; /* list the load option in the order of BootOrder variable */ for (i = 0; i < num; i++) { @@ -2265,7 +2266,6 @@ static efi_status_t eficonfig_create_change_boot_order_entry(struct efimenu *efi var_name16[0] = 0; for (;;) { int index; - efi_guid_t guid; if (efi_menu->count >= EFICONFIG_ENTRY_NUM_MAX - 2) break; diff --git a/lib/efi_loader/efi_bootmgr.c b/lib/efi_loader/efi_bootmgr.c index 8c9a9b5eb56..8938b214ceb 100644 --- a/lib/efi_loader/efi_bootmgr.c +++ b/lib/efi_loader/efi_bootmgr.c @@ -934,6 +934,7 @@ static efi_status_t efi_bootmgr_delete_invalid_boot_option(struct eficonfig_medi efi_status_t ret = EFI_SUCCESS; u16 *delete_index_list = NULL, *p; efi_uintn_t buf_size; + efi_guid_t guid; buf_size = 128; var_name16 = malloc(buf_size); @@ -943,7 +944,6 @@ static efi_status_t efi_bootmgr_delete_invalid_boot_option(struct eficonfig_medi var_name16[0] = 0; for (;;) { int index; - efi_guid_t guid; efi_uintn_t tmp; ret = efi_next_variable_name(&buf_size, &var_name16, &guid); -- cgit v1.3.1