diff mbox series

qfw: Allocate ACPI memory using efi logic

Message ID 20220227142317.37235-1-agraf@csgraf.de
State Changes Requested, archived
Delegated to: Heinrich Schuchardt
Headers show
Series qfw: Allocate ACPI memory using efi logic | expand

Commit Message

Alexander Graf Feb. 27, 2022, 2:23 p.m. UTC
When we allocate ACPI tables dynamically as part of the qfw ACPI loading
code and then later want to boot a UEFI target using them, we need to make
sure that the UEFI logic is aware that these memory regions are ACPI, so
that the loading kernel can mark them as reserved.

Since we'll never see alignment requirements more than a page, let's just
use efi_allocate_pages when we see high memory allocation requests in a
UEFI enabled environment. Even if we then boot using the native zImage
later, the memory allocation will still be valid.

Without this patch, Linux will refuse to consume the DSDT when passed from
qfw's ACPI framework. With this patch, it happily uses it.

Signed-off-by: Alexander Graf <agraf@csgraf.de>
---
 drivers/misc/qfw.c | 17 ++++++++++++++++-
 1 file changed, 16 insertions(+), 1 deletion(-)

Comments

Simon Glass March 12, 2022, 2:25 a.m. UTC | #1
Hi Alex,

On Sun, 27 Feb 2022 at 07:23, Alexander Graf <agraf@csgraf.de> wrote:
>
> When we allocate ACPI tables dynamically as part of the qfw ACPI loading
> code and then later want to boot a UEFI target using them, we need to make
> sure that the UEFI logic is aware that these memory regions are ACPI, so
> that the loading kernel can mark them as reserved.
>
> Since we'll never see alignment requirements more than a page, let's just
> use efi_allocate_pages when we see high memory allocation requests in a
> UEFI enabled environment. Even if we then boot using the native zImage
> later, the memory allocation will still be valid.
>
> Without this patch, Linux will refuse to consume the DSDT when passed from
> qfw's ACPI framework. With this patch, it happily uses it.
>
> Signed-off-by: Alexander Graf <agraf@csgraf.de>
> ---
>  drivers/misc/qfw.c | 17 ++++++++++++++++-
>  1 file changed, 16 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/misc/qfw.c b/drivers/misc/qfw.c
> index 754bc6a603..7c6ed41f48 100644
> --- a/drivers/misc/qfw.c
> +++ b/drivers/misc/qfw.c
> @@ -18,6 +18,9 @@
>  #if defined(CONFIG_GENERATE_ACPI_TABLE) && !defined(CONFIG_ARM)
>  #include <asm/tables.h>
>  #endif
> +#ifdef CONFIG_EFI_LOADER
> +#include <efi_loader.h>
> +#endif
>
>  #if defined(CONFIG_GENERATE_ACPI_TABLE) && !defined(CONFIG_SANDBOX)
>  /*
> @@ -35,7 +38,7 @@ static int bios_linker_allocate(struct udevice *dev,
>  {
>         uint32_t size, align;
>         struct fw_file *file;
> -       unsigned long aligned_addr;
> +       unsigned long aligned_addr = 0;
>
>         align = le32_to_cpu(entry->alloc.align);
>         /* align must be power of 2 */
> @@ -59,7 +62,19 @@ static int bios_linker_allocate(struct udevice *dev,
>          * in which is low memory
>          */
>         if (entry->alloc.zone == BIOS_LINKER_LOADER_ALLOC_ZONE_HIGH) {
> +#ifdef CONFIG_EFI_LOADER
> +               efi_status_t ret;
> +               u64 efi_addr = 1ULL << 32;
> +
> +               ret = efi_allocate_pages(EFI_ALLOCATE_MAX_ADDRESS,
> +                                        EFI_ACPI_RECLAIM_MEMORY,
> +                                        efi_size_in_pages(size),
> +                                        &efi_addr);
> +               if (ret == EFI_SUCCESS)
> +                       aligned_addr = efi_addr;
> +#else
>                 aligned_addr = (unsigned long)memalign(align, size);
> +#endif
>                 if (!aligned_addr) {
>                         printf("error: allocating resource\n");
>                         return -ENOMEM;
> --
> 2.32.0
>

The tables are normally created on start-up, before the command line
starts, so we can examine them in U-Boot.

It is a terrible idea fo call efi_allocate_pages() in code like this.
and the #ifdef as well. Ick!!

You can put ACPI tables in a bloblist so they are continguous and then
the EFI code can present the bloblist as reserved to Linux.

See coral, which does this.

Regards,
Simon
diff mbox series

Patch

diff --git a/drivers/misc/qfw.c b/drivers/misc/qfw.c
index 754bc6a603..7c6ed41f48 100644
--- a/drivers/misc/qfw.c
+++ b/drivers/misc/qfw.c
@@ -18,6 +18,9 @@ 
 #if defined(CONFIG_GENERATE_ACPI_TABLE) && !defined(CONFIG_ARM)
 #include <asm/tables.h>
 #endif
+#ifdef CONFIG_EFI_LOADER
+#include <efi_loader.h>
+#endif
 
 #if defined(CONFIG_GENERATE_ACPI_TABLE) && !defined(CONFIG_SANDBOX)
 /*
@@ -35,7 +38,7 @@  static int bios_linker_allocate(struct udevice *dev,
 {
 	uint32_t size, align;
 	struct fw_file *file;
-	unsigned long aligned_addr;
+	unsigned long aligned_addr = 0;
 
 	align = le32_to_cpu(entry->alloc.align);
 	/* align must be power of 2 */
@@ -59,7 +62,19 @@  static int bios_linker_allocate(struct udevice *dev,
 	 * in which is low memory
 	 */
 	if (entry->alloc.zone == BIOS_LINKER_LOADER_ALLOC_ZONE_HIGH) {
+#ifdef CONFIG_EFI_LOADER
+		efi_status_t ret;
+		u64 efi_addr = 1ULL << 32;
+
+		ret = efi_allocate_pages(EFI_ALLOCATE_MAX_ADDRESS,
+					 EFI_ACPI_RECLAIM_MEMORY,
+					 efi_size_in_pages(size),
+					 &efi_addr);
+		if (ret == EFI_SUCCESS)
+			aligned_addr = efi_addr;
+#else
 		aligned_addr = (unsigned long)memalign(align, size);
+#endif
 		if (!aligned_addr) {
 			printf("error: allocating resource\n");
 			return -ENOMEM;