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 <ag...@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

Reply via email to