Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create a UEFI kernel in NASM on Linux

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.

like image 470
Jonathan Dewein Avatar asked Mar 28 '19 23:03

Jonathan Dewein


1 Answers

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.

like image 89
Michael Petch Avatar answered Nov 15 '22 09:11

Michael Petch