How to create a UEFI kernel in NASM on Linux
Asked Answered
P

1

5

I have been following this guide for OS development OS Development on Windows

However, I do not like the windows development environment, and so I am trying to transfer these instructions over to my preferred Linux environment.

I have tried the tutorial from Rod's Books, and everything compiles correctly, and I receive the hello.efi file... but how do I boot from it? I use the command qemu-system-x86_64 -bios OVMF.fd -kernel hello.efi -net none, but I just get the typical EFI shell.

What I would really like is to have a Linux version of the Hacker Pulp guide.

I have also tried this guide from kalzlauskas, and this instructions from the osdev UEFI Bare Bones.

Polacca answered 28/3, 2019 at 23:35 Comment(0)
L
7

TL;DR: The main problem is that you can't run an EFI application directly with QEMU's -kernel option. -kernel is meant for starting Multiboot compliant executables or loading Linux bzImage files.


Since your question suggests you have managed to compile and link an EFI application with one of the tutorials, this answer will strictly focus on methods of running it with QEMU. Which tutorial or method you followed to build the EFI application itself doesn't matter.

Use this command in your project directory to create a series of subdirectories for use as an EFI boot drive:

mkdir -p bootdrv/EFI/BOOT/

You only have to create the directories once. Once they have been created, copy your hello.efi file to the file named bootdrv/EFI/BOOT/BOOTX64.EFI. EFI/BOOT/BOOTX64.EFI is the default boot file for 64-bit UEFI. On 32-bit UEFI the default boot file is EFI/BOOT/BOOTIA32.EFI. Run the following command to launch your EFI program:

qemu-system-x86_64 -bios OVMF.fd -net none -drive file=fat:rw:bootdrv,format=raw

This mounts the bootdrv directory as a FAT file system in the emulator as the first hard drive. 64-bit EFI should automatically run the file EFI/BOOT/BOOTX64.EFI


As an alternative you can copy your hello.efi file to the directory bootdrv/EFI/BOOT/, and create a startup script with the name bootdrv/EFI/BOOT/startup.nsh containing the following commands:

\EFI\BOOT\hello.efi
pause

EFI/BOOT/startup.nsh is the default startup script that will be run in the absence of a default EFI application. The file should contain a blank line after the last command. The command \EFI\BOOT\hello.efi runs hello.efi and pause prompts to press a key. You don't have to specify pause, it's just convenient if the program you run exits back to the shell. You can run it with same command as before:

qemu-system-x86_64 -bios OVMF.fd -net none -drive file=fat:rw:bootdrv,format=raw

This mounts the bootdrv directory as a FAT file system in the emulator as the first hard drive. EFI will load EFI/BOOT/startup.nsh as a startup script and execute the commands contained in it. That should automatically run hello.efi.

Latinism answered 29/3, 2019 at 1:18 Comment(4)
Is this for the "Rod's Books" tutorial?Polacca
@JonathanDewein : It doesn't depend on a particular tutorial. Since you said you were able to build an EFI application called hello.efi I focused on your real problem of running it. Once you have your EFI file built (no matter how you built it or what tutorial) - the method above wold allow you to run it on Linux. You can't use the QEMU -kernel option to directly run an EFI application.Latinism
Awesome! Thank you, so much, for your help. I was confused at first because I was led to a "boot manager" of sorts. Once I booted into the EFI Shell and ran 'fs0:', 'hello.efi', it ran my EFI hello world application. Next step...kernel development with UEFI. Do you happen to have any suggestions? I am reading the specs and some interesting white papers at uefi.org currently.Polacca
@JonathanDewein I have no real recommendations regarding actual tutorials for OS development using EFI. Probably finding existing code on Github that does it would be a starting point.Latinism

© 2022 - 2024 — McMap. All rights reserved.