OSDev.org

The Place to Start for Operating System Developers
It is currently Thu Mar 28, 2024 5:26 pm

All times are UTC - 6 hours




Post new topic Reply to topic  [ 5 posts ] 
Author Message
 Post subject: Call to UEFI AllocatePages fails with an EFI_NOT_FOUND
PostPosted: Sun Jun 05, 2022 11:03 am 
Offline

Joined: Sat Apr 30, 2022 5:57 am
Posts: 18
I am aware that this means that UEFI can't find the requested pages, (from page 203 of https://uefi.org/sites/default/files/re ... %202_6.pdf)
but the address I'm requesting it allocate pages from is well within my 32 GB of memory. (Specifically, address 0x1000)
The error only doesn't occur when I request it allocate address 0x0, which doesn't make any sense to me.

Here's the code:
Code:
    EFI_FILE_HANDLE kernelHandle; // Kernel file handle

    // Get a handle to the kernel file
    uefi_call_wrapper(volumeHandle->Open, 5, volumeHandle, &kernelHandle, L"kernel.elf", EFI_FILE_MODE_READ, EFI_FILE_READ_ONLY | EFI_FILE_HIDDEN | EFI_FILE_SYSTEM);
   
    // Read from the kernel file and load it into memory

    uint64_t kernelSize = FileSize(kernelHandle);

    #define PAGE_SIZE 4096
    #define PRE_ALLOC 5

    // Allocate (kernelSize / PAGE_SIZE) + PRE_ALLOC pages for the kernel. UEFI initilizes the VAS as identity mapped,
    // so I can't use AllocatePool, as the kernel address will be inconsistent otherwise.

    UINTN numPages = (kernelSize / PAGE_SIZE) + PRE_ALLOC;

    void* kernelAddress = (void*)0x1000;
    Status = uefi_call_wrapper(BS->AllocatePages, 4, AllocateAddress, EfiLoaderCode, numPages, (EFI_PHYSICAL_ADDRESS*)&kernelAddress);
    if (EFI_ERROR(Status) || kernelAddress == NULL)
    {
        Print(L"Could not allocate pages for the kernel! Stopping boot!\n");
        Print(L"Failure Reason: ");

        if (Status == EFI_OUT_OF_RESOURCES)
        {
            Print(L"EFI_OUT_OF_RESOURCES\n");
        }
        else if (Status == EFI_INVALID_PARAMETER)
        {
            Print(L"EFI_INVALID_PARAMETER\n");
        }
        else if (Status == EFI_NOT_FOUND)
        {
            Print(L"EFI_NOT_FOUND\n");
        }
        else if (Status == EFI_SUCCESS && kernelAddress == NULL)
        {
            Print(L"UNKNOWN_K_PTR_NULL\n");
        }

        Print(L"Please power off your machine. (I am too lazy to implement ACPI drivers)\n");

        while (true) { }

    }

    uint8_t *kernelBuf = kernelAddress;

    uefi_call_wrapper(kernelHandle->Read, 3, kernelHandle, &kernelSize, kernelBuf);
   

    Print(L"Loaded kernel at address %x\n", kernelBuf);

    while (true) { }


I've tested this in both QEMU and real hardware, both have the same result.

Here's the Github repo: https://github.com/ThatCodingGuy86/MimosaOS


Top
 Profile  
 
 Post subject: Re: Call to UEFI AllocatePages fails with an EFI_NOT_FOUND
PostPosted: Sun Jun 05, 2022 12:02 pm 
Offline
Member
Member

Joined: Sun Jun 23, 2019 5:36 pm
Posts: 618
Location: North Dakota, United States
First, you might want to use EDK II instead of GNU EFI, which is just a massive set of hacks to try to get EFI working with ELF that I'm pretty sure hardly anyone understands. Second, I'm pretty sure you want to use AllocatePool instead of AllocatePages. Maybe there's a particular reason you need AllocatePages for this, but if yoru trying to load your kernel, it should be relocatable so you can just use AllocatePool and relocate it to wherever UEFI wants it to be. The page your allocating could also just not be available, as your firmware indicates; its best practice to never assume anything about your memory map when UEFI is active.


Top
 Profile  
 
 Post subject: Re: Call to UEFI AllocatePages fails with an EFI_NOT_FOUND
PostPosted: Sun Jun 05, 2022 12:13 pm 
Offline
Member
Member

Joined: Mon Mar 25, 2013 7:01 pm
Posts: 5100
ThatCodingGuy89 wrote:
the address I'm requesting it allocate pages from is well within my 32 GB of memory. (Specifically, address 0x1000)

Have you tried dumping the memory map to see if that address is actually available? UEFI doesn't guarantee available memory at any specific address.

ThatCodingGuy89 wrote:
The error only doesn't occur when I request it allocate address 0x0, which doesn't make any sense to me.

That's the only address where you definitely should see an error in QEMU, since OVMF reserves the page at 0 to provide a compatibility hack for Windows 7.

Code:
uefi_call_wrapper

This is unrelated, but I really don't like gnu-efi. Personally, I'd rather use a compiler that can directly target UEFI so no wrapper is needed. (I think you can even use the gnu-efi headers if you do that, but I just write my own UEFI headers.)

Code:
AllocateAddress

You probably should use AllocateAnyPages. UEFI doesn't guarantee available memory at any specific address.


Top
 Profile  
 
 Post subject: Re: Call to UEFI AllocatePages fails with an EFI_NOT_FOUND
PostPosted: Sun Jun 05, 2022 12:58 pm 
Offline

Joined: Sat Apr 30, 2022 5:57 am
Posts: 18
Octocontrabass wrote:
Personally, I'd rather use a compiler that can directly target UEFI so no wrapper is needed.


Such as? I haven't heard of a compiler that directly supports UEFI without the hackery of gnu-efi.

Octocontrabass wrote:
Have you tried dumping the memory map to see if that address is actually available? UEFI doesn't guarantee available memory at any specific address.


I just did, I decided the reasonable first thing to check would be NumberOfPages, and it says 0. I'm not entirely sure how that make sense though, as for memory mapping to work at all in long mode (and I think in 32 bit mode as well), you have to have page tables. Or does it mean actual pages? Either way, it doesn't make any sense.

Ethin wrote:
I'm pretty sure you want to use AllocatePool instead of AllocatePages. Maybe there's a particular reason you need AllocatePages for this, but if yoru trying to load your kernel, it should be relocatable so you can just use AllocatePool and relocate it to wherever UEFI wants it to be.


The reason is in the comment above the AllocatePages call. I know you can make an ELF executable relocatable, but to my knowledge, this requires loader support,
which I honestly don't want to deal with, as it's been difficult enough parsing the ELF header.


Top
 Profile  
 
 Post subject: Re: Call to UEFI AllocatePages fails with an EFI_NOT_FOUND
PostPosted: Sun Jun 05, 2022 1:55 pm 
Offline
Member
Member

Joined: Mon Mar 25, 2013 7:01 pm
Posts: 5100
ThatCodingGuy89 wrote:
Octocontrabass wrote:
Personally, I'd rather use a compiler that can directly target UEFI so no wrapper is needed.

Such as?

Clang or MinGW-w64 GCC. They don't actually have a preset UEFI target, but the Windows target is close enough - you just need a few extra options to create an EFI binary. With GCC, I also use a custom linker script, although I'm pretty sure that's not actually necessary.

I use something like this:
Code:
clang --target=x86_64-windows -ffreestanding -nostdlib -mno-stack-arg-probe -mgeneral-regs-only -fuse-ld=lld-link -Wl,-entry:efi_main -Wl,-subsystem:efi_application -Wl,-largeaddressaware
x86_64-w64-mingw32-gcc -ffreestanding -nostdlib -mno-stack-arg-probe -mgeneral-regs-only -pie -s -Wl,--subsystem,10 -e efi_main -T uefi.ld


ThatCodingGuy89 wrote:
I just did, I decided the reasonable first thing to check would be NumberOfPages, and it says 0.

Does it say that in all of the memory map entries, or just one of them? In QEMU I see around 100 entries.

ThatCodingGuy89 wrote:
I know you can make an ELF executable relocatable, but to my knowledge, this requires loader support, which I honestly don't want to deal with, as it's been difficult enough parsing the ELF header.

Or you can use paging to map your ELF executable wherever it needs to be. Build your page tables, call ExitBootServices(), switch to your page tables, and jump to your kernel. This way, you're not depending on any particular physical address being available, but your kernel doesn't need to be relocatable.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 5 posts ] 

All times are UTC - 6 hours


Who is online

Users browsing this forum: No registered users and 74 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group