Re: efi_random_alloc() returning EFI_NOT_FOUND

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Ben

On Sun, 9 Mar 2025 at 20:12, Ben Schneider <ben@xxxxxxxxx> wrote:
>
> Hi Ilias, thank you for connecting the threads. I'm clearly
> struggling a bit and appreciate how patient and helpful
> everyone has been.

No worries, I'd rather help than leave a bug lingering around. They
tend to come back biting

>
> On Saturday, March 8th, 2025 at 5:43 PM, Ilias Apalodimas <ilias.apalodimas@xxxxxxxxxx> wrote:
> > The 'efidebug' command will dump the EFI memory map. Can you send that?
>
> This is what U-Boot reports:
>
> Type             Start            End              Attributes
> ================ ================ ================ ==========
> CONVENTIONAL     0000000000000000-0000000004000000 WB
> BOOT DATA        0000000004000000-0000000004200000 WB
> CONVENTIONAL     0000000004200000-0000000004400000 WB
> BOOT DATA        0000000004400000-0000000005400000 WB
> CONVENTIONAL     0000000005400000-000000003eabc000 WB
> BOOT DATA        000000003eabc000-000000003eac1000 WB
> RUNTIME DATA     000000003eac1000-000000003eac2000 WB|RT
> BOOT DATA        000000003eac2000-000000003eac3000 WB
> RUNTIME DATA     000000003eac3000-000000003eae5000 WB|RT
> BOOT DATA        000000003eae5000-000000003eaee000 WB
> BOOT CODE        000000003eaee000-000000003fb8a000 WB
> RUNTIME DATA     000000003fb8a000-000000003fb8b000 WB|RT
> BOOT CODE        000000003fb8b000-000000003ff00000 WB
> RUNTIME CODE     000000003ff00000-000000003ff10000 WB|RT
> BOOT CODE        000000003ff10000-0000000040000000 WB
>
> > Any idea if we can reproduce this on QEMU?
>
> I have not attempted to reproduce with QEMU.
>
> From what I can tell on my device, total_slots is 467 and
> target_slot seems to always start with a value of 0 despite the
> comment that it should be a random value in [0, total_slots).
>
> In the first iteration through the second for loop,
> MD_NUM_SLOTS(md) appears to have a value of 24 and since
> target_slot is always 0, it never reaches the 'continue'
> statement. With current builds, &target appears to have a value of
> 3faee138.

&target is the stack-allocated address -- it makes sense to be
identical. What we really want to print is 'target,' which is the
requested address.
Can you print 'target' in both of your success/fail cases and also
apply the patch below to u-boot:

diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c
index 6d00b1862505..421206d3c4a9 100644
--- a/lib/efi_loader/efi_memory.c
+++ b/lib/efi_loader/efi_memory.c
@@ -456,6 +456,9 @@ efi_status_t efi_allocate_pages(enum efi_allocate_type type,
        uint flags;
        efi_status_t ret;
        phys_addr_t addr;
+        efi_uintn_t map_size;
+       struct efi_mem_desc *memmap, *map;
+        int i;

        /* Check import parameters */
        if (memory_type >= EFI_PERSISTENT_MEMORY_TYPE &&
@@ -490,6 +493,18 @@ efi_status_t efi_allocate_pages(enum
efi_allocate_type type,
                if (*memory & EFI_PAGE_MASK)
                        return EFI_NOT_FOUND;

+               efi_get_memory_map_alloc(&map_size, &memmap);
+
+#define EFI_PHYS_ADDR_WIDTH (int)(sizeof(efi_physical_addr_t) * 2)
+               for (i = 0, map = memmap; i < map_size / sizeof(*map);
map++, i++) {
+                       printf("%-x %.*llx-%.*llx\n", map->type,
EFI_PHYS_ADDR_WIDTH,
+                              (u64)map_to_sysmem((void *)(uintptr_t)
map->physical_start),
+                              EFI_PHYS_ADDR_WIDTH,
+                              (u64)map_to_sysmem((void *)(uintptr_t)
(map->physical_start + map->num_pages * EFI_PAGE_SIZE)));
+               }
+
+               efi_free_pool(memmap);
+
                addr = map_to_sysmem((void *)(uintptr_t)*memory);
                addr = (u64)lmb_alloc_addr(addr, len, flags);
                if (!addr)

That will print the memory map, right before the efi_allocate_pages() request.

>  U-Boot appears to send this address to map_to_sysmem()
> [1] which seems to return 0, which is then what results in the
> EFI_NOT_FOUND.

map_to_sysmem() does nothing in actual hardware, it's there for an
internal platform called 'sandbox'. What fails is the call to
efi_allocate_pages().

>
> I went back to try figure out why it is somehow working when I
> block the 'break' statement with the condition status ==
> EFI_SUCCESS. Doing so causes the loop to start its second
> iteration when EFI_NOT_FOUND comes back. In the second iteration,
> MD_NUM_SLOTS(md) is 0 so we reach the 'continue' statement. This
> happens for the third and fourth iteration too. On the fifth
> iteration, MD_NUM_SLOTS(md) is 443 so it makes its second call to
> efi_allocate_pages(). On all iterations, target_slot remains 0.
>
> What is confusing is this second call to efi_allocate_pages()
> seems to have the same value for &target of 3faee138, but this
> time when U-Boot calls map_to_sysmem() it returns a value of
> 88080384 instead of 0. As a result, we get EFI_SUCCESS and the
> kernel boots.

Look above, what changes is the physical address not the pointer itself.
What I assume is happening here, is that the first call requests an
address which U-Boot somehow has already allocated, or the requested
length exceeds what we have available. Then you move to the next slot
and the new address happens to be ok.

>
> U-Boot also reports a new reservation in its lmb map between the
> first and second calls to efi_allocate_pages().
>

Yes internally efi_allocate_pages() uses the lmb APIs to allocate and
manage memory so that's normal.

> During first call to efi_allocate_pages():
>
> lmb_dump_all:
>  memory.count = 0x1
>  memory[0]      [0x0-0x3fffffff], 0x40000000 bytes, flags: none
>  reserved.count = 0x5
>  reserved[0]    [0x4000000-0x41fffff], 0x200000 bytes, flags: none
>  reserved[1]    [0x4400000-0x53fffff], 0x1000000 bytes, flags: none
>  reserved[2]    [0x3dae3000-0x3e2c8fff], 0x7e6000 bytes, flags: no-overwrite, no-map
>  reserved[3]    [0x3ea6c000-0x3eaedfff], 0x82000 bytes, flags: no-overwrite, no-map
>  reserved[4]    [0x3eaee960-0x3fffffff], 0x15116a0 bytes, flags: no-map
>
> During second call to efi_allocate_pages():
>
> lmb_dump_all:
>  memory.count = 0x1
>  memory[0]      [0x0-0x3fffffff], 0x40000000 bytes, flags: none
>  reserved.count = 0x6
>  reserved[0]    [0x0-0x113ffff], 0x1140000 bytes, flags: no-overwrite, no-map
>  reserved[1]    [0x4000000-0x41fffff], 0x200000 bytes, flags: none
>  reserved[2]    [0x4400000-0x53fffff], 0x1000000 bytes, flags: none
>  reserved[3]    [0x3dae3000-0x3e2c8fff], 0x7e6000 bytes, flags: no-overwrite, no-map
>  reserved[4]    [0x3ea6c000-0x3eaedfff], 0x82000 bytes, flags: no-overwrite, no-map
>  reserved[5]    [0x3eaee960-0x3fffffff], 0x15116a0 bytes, flags: no-map
>
> [1] https://github.com/u-boot/u-boot/blob/master/lib/efi_loader/efi_memory.c#L493
>

Cheers
/Ilias




[Index of Archives]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux OMAP]     [Linux MIPS]     [ECOS]     [Asterisk Internet PBX]     [Linux API]

  Powered by Linux