flat assembler
Message board for the users of flat assembler.

Index > OS Construction > Format options for UEFI OS bootloader

Goto page 1, 2  Next
Author
Thread Post new topic Reply to topic
pfranz



Joined: 13 Jan 2007
Posts: 116
Location: Italy
pfranz 23 Oct 2023, 17:47
I am writing an OS bootloader for UEFI 2.3.1 64bit.
If I use "format pe64 efi" it goes fine; if I use "efiboot" instead of "efi", it crashes.
What is the difference between "efi" and "efiboot"?
Also, should I add "dll"?
Post 23 Oct 2023, 17:47
View user's profile Send private message Reply with quote
Feryno



Joined: 23 Mar 2005
Posts: 514
Location: Czech republic, Slovak republic
Feryno 23 Oct 2023, 18:48
efi = application, you can run it e.g. from uefi shell
efiboot = loaded by UEFI at boot stage (exists in Boot#### and in BootOrder variables) or loaded from efi system partition \EFI\BOOT\bootx64.efi), you should use efi boot services
efidriver = loaded as a driver (exists in Driver#### and in DriverOrder variables), you should use efi runtime services (drivers are loaded at early stage when bootservices does not yet exist and are running later together with OS when some services does not exist anymore)

older uefi (like 10 years old) did not care and allowed efi application be started at boot stage and also allowed efiboot be loaded from uefi shell
newer uefi (like 1-2 years old) refuse to start them if compiled as different type (efiboot cannot be started from uefi shell, efi application cannot be loaded at boot), in newer uefis also memory allocations fail if used incorrect memory types (you should use memory types EfiRuntimeServicesCode or EfiRuntimeServicesData when allocating memory in efidriver but such allocation fails in efiboot)

so you should use efiboot as you correctly wrote, because you are writing OS bootloader

post here what you already have done (source + compiled binary), but reproducing your crash could be difficult for other members of the forum as everyone has different uefi firmware
you can also try the simplest binary like this:

Code:
format PE64 dll efiboot at 0 on 'nul'

section '.text' code readable executable

entry $
; in: rcx = ImageHandle
;     rdx = SystemTable

        xor     eax,eax         ; = EFI_SUCCESS
        ret    


also the behavior may depend on the value returned when exiting your program, for efiboot returning an error (or rax,-1 instead of xor eax,eax) causes the uefi to load next Boot#### from BootOrder
Post 23 Oct 2023, 18:48
View user's profile Send private message Visit poster's website ICQ Number Reply with quote
pfranz



Joined: 13 Jan 2007
Posts: 116
Location: Italy
pfranz 23 Oct 2023, 19:30
Mine doesn't even reach the first print before crashing, I should be able to slim it down to a simple example.
But actually it crashes because I try to launch it from the Shell, after UEFI refuses to boot from my program. You said it cannot be launched, so this may be the reason for the crash. But why doesn't it get accepted? I tried your format options to no avail.
As to the UEFI firmware, I am using VirtualBox 5 on linux which simulates v. 2.3.1
Post 23 Oct 2023, 19:30
View user's profile Send private message Reply with quote
pfranz



Joined: 13 Jan 2007
Posts: 116
Location: Italy
pfranz 24 Oct 2023, 05:37
Tried a more recent VirtualBox 6.1.22 from 2021, got same problem.
Post 24 Oct 2023, 05:37
View user's profile Send private message Reply with quote
sinsi



Joined: 10 Aug 2007
Posts: 794
Location: Adelaide
sinsi 24 Oct 2023, 10:23
Have you disabled Secure Boot?
Post 24 Oct 2023, 10:23
View user's profile Send private message Reply with quote
pfranz



Joined: 13 Jan 2007
Posts: 116
Location: Italy
pfranz 24 Oct 2023, 13:12
sinsi wrote:
Have you disabled Secure Boot?
I don't think there is such an option in VirtualBox 6, only in VirtualBox 7.
Post 24 Oct 2023, 13:12
View user's profile Send private message Reply with quote
Feryno



Joined: 23 Mar 2005
Posts: 514
Location: Czech republic, Slovak republic
Feryno 24 Oct 2023, 16:39
Can you create an image of a floppy drive, format it as FAT16, create the above path and copy your file there?
Post 24 Oct 2023, 16:39
View user's profile Send private message Visit poster's website ICQ Number Reply with quote
pfranz



Joined: 13 Jan 2007
Posts: 116
Location: Italy
pfranz 26 Oct 2023, 04:30
Feryno wrote:
Can you create an image of a floppy drive, format it as FAT16, create the above path and copy your file there?
I did it with FAT12 (it is supported by UEFI, FAT16 may create problems), didn't work.

Given that uefi may not support ISO, and VirtualBox 6 dropped its support since 6.1.34, I created ISO/UDF hybrid, and pure UDF: same behavior, pe64 efi works, efiboot doesn't.
The only difference using the most recent 6.1.48 instead of older versions, is that uefi doesn't automatically boot my loader, it boots into the shell. I have to exit and load it with "Load from file" in the boot maintainance menu.

Attached is an example with source and executable.
No way I can launch it.


Description:
Download
Filename: t.zip
Filesize: 1007 Bytes
Downloaded: 222 Time(s)

Post 26 Oct 2023, 04:30
View user's profile Send private message Reply with quote
sinsi



Joined: 10 Aug 2007
Posts: 794
Location: Adelaide
sinsi 26 Oct 2023, 14:54
Possibly EFIBOOT is for drivers whereas a loader is just an EFI application.
Not sure if you need a GPT disk and/or an EFI System partition (type 0xEF) for booting
The following code will boot in Virtual Box 7 (from a VHD with GPT and EFI System partition)
Code:
format pe64 efi
section '.text' code executable readable

entry $
                sub     rsp,28h
                mov     rcx,[rdx + 64]
                mov     rax,[rcx + 8]
                mov     rdx,string
                call    rax
                jmp     $

string du 'Hello, World!',13,10,0
    
Post 26 Oct 2023, 14:54
View user's profile Send private message Reply with quote
pfranz



Joined: 13 Jan 2007
Posts: 116
Location: Italy
pfranz 26 Oct 2023, 16:34
sinsi wrote:
Possibly EFIBOOT is for drivers whereas a loader is just an EFI application.
Not sure if you need a GPT disk and/or an EFI System partition (type 0xEF) for booting
The following code will boot in Virtual Box 7 (from a VHD with GPT and EFI System partition)
Code:
format pe64 efi
section '.text' code executable readable

entry $
                sub     rsp,28h
                mov     rcx,[rdx + 64]
                mov     rax,[rcx + 8]
                mov     rdx,string
                call    rax
                jmp     $

string du 'Hello, World!',13,10,0
    
Yes, I had read about the need of a partition for both hard disk and cd/dvd. But this is secondary: I would like to know about efiboot. I don't see anywhere in efi specification that the pe format for certain categories (driver, os loaders) must be different: why the need of efiboot? In which way is it different?
Post 26 Oct 2023, 16:34
View user's profile Send private message Reply with quote
sinsi



Joined: 10 Aug 2007
Posts: 794
Location: Adelaide
sinsi 26 Oct 2023, 19:33
From the UEFI spec
Quote:
// PE32+ Subsystem type for EFI images
#define EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION 10
#define EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER 11
#define EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER 12

From the FASM documentation
Quote:
To select the Portable Executable output format, use format PE directive, it can be followed by additional format settings: first the target subsystem setting, which can be console or GUI for Windows applications, native for Windows drivers, EFI, EFIboot or EFIruntime for the UEFI


An OS loader is just an application, not a driver, so we use FORMAT PE64 EFI
Post 26 Oct 2023, 19:33
View user's profile Send private message Reply with quote
pfranz



Joined: 13 Jan 2007
Posts: 116
Location: Italy
pfranz 26 Oct 2023, 19:48
sinsi wrote:
Code:
sub     rsp,28h    
This looks incorrect.When you make an efi call, the stack must be 16 byte aligned. You get it by subtracting 28h only if the stack is not aligned on entry, what I have always seen. But we cannot assume that the stack is NEVER aligned on entry, so the correct way would be:
Code:
and spl, 15
sub rsp, 20h    
Post 26 Oct 2023, 19:48
View user's profile Send private message Reply with quote
pfranz



Joined: 13 Jan 2007
Posts: 116
Location: Italy
pfranz 26 Oct 2023, 19:53
sinsi wrote:
From the UEFI spec

An OS loader is just an application, not a driver, so we use FORMAT PE64 EFI
Thanks for the uefi quote, I hadn't seen it but looks more like a piece of code than specification text.
I had seen the fasm documentation from where I took the efiboot option.
Probably it is intended for drivers, as you say.
Post 26 Oct 2023, 19:53
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20447
Location: In your JS exploiting you and your system
revolution 26 Oct 2023, 19:55
pfranz wrote:
sinsi wrote:
Code:
sub     rsp,28h    
This looks incorrect.When you make an efi call, the stack must be 16 byte aligned. You get it by subtracting 28h only if the stack is not aligned on entry, what I have always seen. But we cannot assume that the stack is NEVER aligned on entry, so the correct way would be:
Code:
and spl, 15
sub rsp, 20h    
I think you meant
Code:
and rsp,not 0xf ; or and spl,not 0xf    
The not is vital. But the code from sini was correct.

I also like the double negative "cannot assume that the stack is NEVER aligned". And I think you are correct actually, the EFI system does ensure the stack has the correct alignment.
Post 26 Oct 2023, 19:55
View user's profile Send private message Visit poster's website Reply with quote
pfranz



Joined: 13 Jan 2007
Posts: 116
Location: Italy
pfranz 26 Oct 2023, 20:34
revolution wrote:
I also like the double negative "cannot assume that the stack is NEVER aligned". And I think you are correct actually, the EFI system does ensure the stack has the correct alignment.
I meant "and spl, 11110000b" which for some obscure reason translated in my mind to "and spl, 15" instead of "and spl, 240" as you correctly wrote.

I am not sure what you got from my phrase. I mean that for some strange reason in the few EFI environments I tested, I have always found rsp 8-byte aligned but 16-byte misaligned; in other words its hex representation always ends with 8. In this case, sub rsp, 28h happens to work, but only because of this 8-byte alignment / 16-byte misalignment which looks very frequent but cannot be assumed. Put it simply, we cannot assume that the EFI firmware will always serve us an rsp that ends with "8". It may end with "0", in which case sub rsp, 28h would produce a 16- byte misaligned stack when doing the uefi call.


Last edited by pfranz on 26 Oct 2023, 23:16; edited 1 time in total
Post 26 Oct 2023, 20:34
View user's profile Send private message Reply with quote
sinsi



Joined: 10 Aug 2007
Posts: 794
Location: Adelaide
sinsi 26 Oct 2023, 20:42
The way the calling convention works, on entry to your program the stack will always be misaligned by 8
because the EFI code uses "call" to start your program, which pushes the return address on to the stack.

Not sure what you mean by 16-byte misaligned?
Post 26 Oct 2023, 20:42
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20447
Location: In your JS exploiting you and your system
revolution 26 Oct 2023, 20:58
pfranz wrote:
I mean that for some strange reason in the few EFI environments I tested, I have always found rsp 8-byte aligned but 16-byte misaligned; in other words its hex representation always ends with 8.
This is the spec, all is normal. That is the exact expected behaviour. So "sub rsp, 0x...8" is the correct code and will align the stack as expected.
Post 26 Oct 2023, 20:58
View user's profile Send private message Visit poster's website Reply with quote
pfranz



Joined: 13 Jan 2007
Posts: 116
Location: Italy
pfranz 26 Oct 2023, 23:11
sinsi wrote:
The way the calling convention works, on entry to your program the stack will always be misaligned by 8
because the EFI code uses "call" to start your program, which pushes the return address on to the stack.

Not sure what you mean by 16-byte misaligned?
Aaahh ... now I understand. Thanks for the explanation.
So our EFI loader is considered a "routine call" and follows the same rules of the calling convention? That is, the stack is 16 byte aligned and then the call itself subtracts 8 bytes?
I didn't see it as a "called routine" because even if the os loading fails, there is no "ret", just an exit call to uefi.

For me "16-byte misaligned" is the opposite of "16-byte aligned": not all the least significant 4 bits of the address are 0.
Post 26 Oct 2023, 23:11
View user's profile Send private message Reply with quote
pfranz



Joined: 13 Jan 2007
Posts: 116
Location: Italy
pfranz 26 Oct 2023, 23:14
revolution wrote:
This is the spec, all is normal.
Can you please tell me where in the specification is said so? Thanks.
Post 26 Oct 2023, 23:14
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20447
Location: In your JS exploiting you and your system
revolution 26 Oct 2023, 23:17
It is the Microsoft FASTCALL convention for 64-bit code.

And the alignment is also a common feature for other calling conventions like SYS-V.
Post 26 Oct 2023, 23:17
View user's profile Send private message Visit poster's website Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  
Goto page 1, 2  Next

< Last Thread | Next Thread >
Forum Rules:
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 vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2025, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.