diff mbox series

[v5,21/28] efi: Support the efi command in the app

Message ID 20211204155657.2913911-15-sjg@chromium.org
State Changes Requested, archived
Delegated to: Heinrich Schuchardt
Headers show
Series efi: Improvements to U-Boot running on top of UEFI | expand

Commit Message

Simon Glass Dec. 4, 2021, 3:56 p.m. UTC
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>
---

(no changes since v1)

 cmd/Makefile      |  2 +-
 cmd/efi.c         | 48 ++++++++++++++++++++++++++++++++---------------
 include/efi.h     | 15 +++++++++++++++
 lib/efi/efi_app.c | 33 ++++++++++++++++++++++++++++++++
 4 files changed, 82 insertions(+), 16 deletions(-)

Comments

Heinrich Schuchardt Dec. 9, 2021, 8:27 p.m. UTC | #1
On 12/4/21 07:56, Simon Glass wrote:
> 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.

cmd/efi.c seems to be duplicating function do_efi_show_memmap(). In a
future patch we should try to move to using common code for commands efi
and efidebug.

Best regards

Heinrich

>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
> (no changes since v1)
>
>   cmd/Makefile      |  2 +-
>   cmd/efi.c         | 48 ++++++++++++++++++++++++++++++++---------------
>   include/efi.h     | 15 +++++++++++++++
>   lib/efi/efi_app.c | 33 ++++++++++++++++++++++++++++++++
>   4 files changed, 82 insertions(+), 16 deletions(-)
>
> diff --git a/cmd/Makefile b/cmd/Makefile
> index 891819ae0f6..df50625bde7 100644
> --- a/cmd/Makefile
> +++ b/cmd/Makefile
> @@ -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
> diff --git a/cmd/efi.c b/cmd/efi.c
> index d2400acbbba..c0384e0db28 100644
> --- 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);
> diff --git a/include/efi.h b/include/efi.h
> index 1dc806a1267..8a43430d3df 100644
> --- a/include/efi.h
> +++ b/include/efi.h
> @@ -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 */
> diff --git a/lib/efi/efi_app.c b/lib/efi/efi_app.c
> index 36e3f1de427..55fa1ac57d5 100644
> --- a/lib/efi/efi_app.c
> +++ b/lib/efi/efi_app.c
> @@ -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_print_str() - Print a UFT-16 string to the U-Boot console
>    *
>
Simon Glass Dec. 17, 2021, 4:37 p.m. UTC | #2
Hi Heinrich,

On Thu, 9 Dec 2021 at 13:27, Heinrich Schuchardt <xypron.glpk@gmx.de> wrote:
>
> On 12/4/21 07:56, Simon Glass wrote:
> > 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.
>
> cmd/efi.c seems to be duplicating function do_efi_show_memmap(). In a
> future patch we should try to move to using common code for commands efi
> and efidebug.

Yes and that depends on EFI_LOADER. Perhaps one day we can have a
common helper for this, e.g. in lib/efi ?

Regards,
Simon
AKASHI Takahiro Dec. 20, 2021, 2:38 a.m. UTC | #3
On Fri, Dec 17, 2021 at 09:37:21AM -0700, Simon Glass wrote:
> Hi Heinrich,
> 
> On Thu, 9 Dec 2021 at 13:27, Heinrich Schuchardt <xypron.glpk@gmx.de> wrote:
> >
> > On 12/4/21 07:56, Simon Glass wrote:
> > > 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.
> >
> > cmd/efi.c seems to be duplicating function do_efi_show_memmap(). In a
> > future patch we should try to move to using common code for commands efi
> > and efidebug.
> 
> Yes and that depends on EFI_LOADER. Perhaps one day we can have a
> common helper for this, e.g. in lib/efi ?

It will inevitably means that we should stick to *UEFI* interfaces
(not EFI_LOADER's internal interfaces like efi_xxx_yyy()) to implement
those commands, including most of efidebug subcommands.

-Takahiro Akashi


> Regards,
> Simon
Simon Glass Dec. 29, 2021, 1:36 p.m. UTC | #4
Hi Takahiro,

On Sun, 19 Dec 2021 at 19:38, AKASHI Takahiro
<takahiro.akashi@linaro.org> wrote:
>
> On Fri, Dec 17, 2021 at 09:37:21AM -0700, Simon Glass wrote:
> > Hi Heinrich,
> >
> > On Thu, 9 Dec 2021 at 13:27, Heinrich Schuchardt <xypron.glpk@gmx.de> wrote:
> > >
> > > On 12/4/21 07:56, Simon Glass wrote:
> > > > 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.
> > >
> > > cmd/efi.c seems to be duplicating function do_efi_show_memmap(). In a
> > > future patch we should try to move to using common code for commands efi
> > > and efidebug.
> >
> > Yes and that depends on EFI_LOADER. Perhaps one day we can have a
> > common helper for this, e.g. in lib/efi ?
>
> It will inevitably means that we should stick to *UEFI* interfaces
> (not EFI_LOADER's internal interfaces like efi_xxx_yyy()) to implement
> those commands, including most of efidebug subcommands.

That seems right to me, although of course there may be some 'inside
knowledge' for some subcommands.

Regards,
Simon
diff mbox series

Patch

diff --git a/cmd/Makefile b/cmd/Makefile
index 891819ae0f6..df50625bde7 100644
--- a/cmd/Makefile
+++ b/cmd/Makefile
@@ -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
diff --git a/cmd/efi.c b/cmd/efi.c
index d2400acbbba..c0384e0db28 100644
--- 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);
diff --git a/include/efi.h b/include/efi.h
index 1dc806a1267..8a43430d3df 100644
--- a/include/efi.h
+++ b/include/efi.h
@@ -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 */
diff --git a/lib/efi/efi_app.c b/lib/efi/efi_app.c
index 36e3f1de427..55fa1ac57d5 100644
--- a/lib/efi/efi_app.c
+++ b/lib/efi/efi_app.c
@@ -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_print_str() - Print a UFT-16 string to the U-Boot console
  *