efi: Support the efi command in the app
authorSimon Glass <sjg@chromium.org>
Tue, 4 Jan 2022 10:51:12 +0000 (03:51 -0700)
committerHeinrich Schuchardt <heinrich.schuchardt@canonical.com>
Sat, 15 Jan 2022 09:57:22 +0000 (10:57 +0100)
At present the 'efi' command only works in the EFI payload. Update it to
work in the app too, so the memory map can be examined.

Signed-off-by: Simon Glass <sjg@chromium.org>
Signed-off-by: Heinrich Schuchardt <heinrich.schuchardt@canonical.com>
cmd/Makefile
cmd/efi.c
include/efi.h
lib/efi/efi_app.c

index e31ac15..6623d7e 100644 (file)
@@ -58,7 +58,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_STUB) += efi.o
+obj-$(CONFIG_EFI) += efi.o
 obj-$(CONFIG_CMD_EFIDEBUG) += efidebug.o
 obj-$(CONFIG_CMD_ELF) += elf.o
 obj-$(CONFIG_HUSH_PARSER) += exit.o
index d2400ac..c0384e0 100644 (file)
--- a/cmd/efi.c
+++ b/cmd/efi.c
@@ -13,6 +13,8 @@
 #include <sort.h>
 #include <asm/global_data.h>
 
+DECLARE_GLOBAL_DATA_PTR;
+
 static const char *const type_name[] = {
        "reserved",
        "loader_code",
@@ -217,37 +219,53 @@ static void efi_print_mem_table(struct efi_mem_desc *desc, int desc_size,
 static int do_efi_mem(struct cmd_tbl *cmdtp, int flag, int argc,
                      char *const argv[])
 {
-       struct efi_mem_desc *desc;
-       struct efi_entry_memmap *map;
+       struct efi_mem_desc *orig, *desc;
+       uint version, key;
+       int desc_size;
        int size, ret;
        bool skip_bs;
 
        skip_bs = !argc || *argv[0] != 'a';
-       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;
+       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, version %x, descr. size %#x\n",
-              gd->arch.table, map, size, map->version, map->desc_size);
-       if (map->version != EFI_MEM_DESC_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;
        }
 
-       desc = efi_build_mem_table(map->desc, size, map->desc_size, skip_bs);
+       desc = efi_build_mem_table(orig, size, desc_size, skip_bs);
        if (!desc) {
                ret = -ENOMEM;
                goto done;
        }
 
-       efi_print_mem_table(desc, map->desc_size, skip_bs);
+       efi_print_mem_table(desc, desc_size, skip_bs);
        free(desc);
+       if (IS_ENABLED(CONFIG_EFI_APP))
+               free(orig);
 done:
        if (ret)
                printf("Error: %d\n", ret);
index 3508ff8..9b7ba0d 100644 (file)
@@ -610,4 +610,19 @@ int efi_store_memory_map(struct efi_priv *priv);
  */
 int efi_call_exit_boot_services(void);
 
+/**
+ * efi_get_mmap() - Get the memory map from EFI
+ *
+ * This is used in the app. The caller must free *@descp when done
+ *
+ * @descp:     Returns allocated pointer to EFI memory map table
+ * @sizep:     Returns size of table in bytes
+ * @keyp:      Returns memory-map key
+ * @desc_sizep:        Returns size of each @desc_base record
+ * @versionp:  Returns version number of memory map
+ * @return 0 on success, -ve on error
+ */
+int efi_get_mmap(struct efi_mem_desc **descp, int *sizep, uint *keyp,
+                int *desc_sizep, uint *versionp);
+
 #endif /* _LINUX_EFI_H */
index 5c2593b..6980933 100644 (file)
@@ -32,6 +32,39 @@ int efi_info_get(enum efi_entry_t type, void **datap, int *sizep)
        return -ENOSYS;
 }
 
+int efi_get_mmap(struct efi_mem_desc **descp, int *sizep, uint *keyp,
+                int *desc_sizep, uint *versionp)
+{
+       struct efi_priv *priv = efi_get_priv();
+       struct efi_boot_services *boot = priv->sys_table->boottime;
+       efi_uintn_t size, desc_size, key;
+       struct efi_mem_desc *desc;
+       efi_status_t ret;
+       u32 version;
+
+       /* Get the memory map so we can switch off EFI */
+       size = 0;
+       ret = boot->get_memory_map(&size, NULL, &key, &desc_size, &version);
+       if (ret != EFI_BUFFER_TOO_SMALL)
+               return log_msg_ret("get", -ENOMEM);
+
+       desc = malloc(size);
+       if (!desc)
+               return log_msg_ret("mem", -ENOMEM);
+
+       ret = boot->get_memory_map(&size, desc, &key, &desc_size, &version);
+       if (ret)
+               return log_msg_ret("get", -EINVAL);
+
+       *descp = desc;
+       *sizep = size;
+       *desc_sizep = desc_size;
+       *versionp = version;
+       *keyp = key;
+
+       return 0;
+}
+
 /**
  * efi_bind_block() - bind a new block device to an EFI device
  *