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 '<invalid>', neither table knew EFI_UNACCEPTED_MEMORY_TYPE, and the 'efi mem' printer had misaligned column headers, a broken '<gap>' 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 <xypron.glpk@gmx.de> Signed-off-by: Aristo Chen <aristo.chen@canonical.com>
120 lines
2.6 KiB
C
120 lines
2.6 KiB
C
// SPDX-License-Identifier: GPL-2.0+
|
|
/*
|
|
* (C) Copyright 2015 Google, Inc
|
|
* Written by Simon Glass <sjg@chromium.org>
|
|
*/
|
|
|
|
#include <command.h>
|
|
#include <efi.h>
|
|
#include <efi_api.h>
|
|
#include <errno.h>
|
|
#include <log.h>
|
|
#include <malloc.h>
|
|
#include <u-boot/uuid.h>
|
|
#include <asm/global_data.h>
|
|
|
|
DECLARE_GLOBAL_DATA_PTR;
|
|
|
|
static int do_efi_mem(struct cmd_tbl *cmdtp, int flag, int argc,
|
|
char *const argv[])
|
|
{
|
|
struct efi_mem_desc *orig;
|
|
uint version, key = 0;
|
|
int desc_size;
|
|
int size, ret;
|
|
|
|
if (IS_ENABLED(CONFIG_EFI_APP)) {
|
|
ret = efi_get_mmap(&orig, &size, &key, &desc_size, &version);
|
|
if (ret) {
|
|
printf("Cannot read memory map (err=%d)\n", ret);
|
|
return CMD_RET_FAILURE;
|
|
}
|
|
} else {
|
|
struct efi_entry_memmap *map;
|
|
|
|
ret = efi_info_get(EFIET_MEMORY_MAP, (void **)&map, &size);
|
|
switch (ret) {
|
|
case -ENOENT:
|
|
printf("No EFI table available\n");
|
|
goto done;
|
|
case -EPROTONOSUPPORT:
|
|
printf("Incorrect EFI table version\n");
|
|
goto done;
|
|
}
|
|
orig = map->desc;
|
|
desc_size = map->desc_size;
|
|
version = map->version;
|
|
}
|
|
printf("EFI table at %lx, memory map %p, size %x, key %x, version %x, descr. size %#x\n",
|
|
gd->arch.table, orig, size, key, version, desc_size);
|
|
if (version != EFI_MEM_DESC_VERSION) {
|
|
printf("Incorrect memory map version\n");
|
|
ret = -EPROTONOSUPPORT;
|
|
goto done;
|
|
}
|
|
|
|
efi_show_memmap(orig, size, desc_size);
|
|
if (IS_ENABLED(CONFIG_EFI_APP))
|
|
free(orig);
|
|
done:
|
|
if (ret)
|
|
printf("Error: %d\n", ret);
|
|
|
|
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, 0, 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[])
|
|
{
|
|
struct cmd_tbl *efi_cmd;
|
|
int ret;
|
|
|
|
if (argc < 2)
|
|
return CMD_RET_USAGE;
|
|
efi_cmd = find_cmd_tbl(argv[1], efi_commands, ARRAY_SIZE(efi_commands));
|
|
argc -= 2;
|
|
argv += 2;
|
|
if (!efi_cmd || argc > efi_cmd->maxargs)
|
|
return CMD_RET_USAGE;
|
|
|
|
ret = efi_cmd->cmd(efi_cmd, flag, argc, argv);
|
|
|
|
return cmd_process_error(efi_cmd, ret);
|
|
}
|
|
|
|
U_BOOT_CMD(
|
|
efi, 3, 1, do_efi,
|
|
"EFI access",
|
|
"mem Dump memory map\n"
|
|
"tables Dump tables"
|
|
);
|