UEFI ISO Bare Bones: Difference between revisions

From OSDev.wiki
Jump to navigation Jump to search
[unchecked revision][unchecked revision]
Content added Content deleted
(Added section on creating a FAT image within the ISO image)
No edit summary
Line 1: Line 1:
{{BeginnersWarning}}
{{Rating|2}}
{{Rating|2}}



Revision as of 03:45, 10 September 2018

WAIT! Have you read Getting Started, Beginner Mistakes, and some of the related OS theory?
Difficulty level

Medium

In this tutorial we will create an ISO image containing a bare bones UEFI application for the 32-bit x86 platform.

You are recommended to have read and fully understood the Bare Bones tutorial first. The UEFI page provides some background to the UEFI boot process and should also be consulted first.

Prerequisites

You will need a GCC Cross-Compiler targeting the i686-pc-mingw32 target, and the gnu-efi package. Extract gnu-efi somewhere on your system (you will need to access its 'inc' directory). We use xorriso to create the iso image. You will also need an emulator to test on (this tutorial was tested with VirtualBox - ensure the EFI option is selected in the VM options).

You will also need some way of creating a FAT filesystem image (e.g. with the Loopback Device or MTools)

hello.c

Create a file with the following:

#include <efi.h>
#include <efilib.h>

EFI_SYSTEM_TABLE *gST;

EFI_STATUS efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
{
    EFI_STATUS Status;
    EFI_INPUT_KEY Key;

    /* Store the system table for future use in other functions */
    gST = SystemTable;

    /* Say hi */
    Status = gST->ConOut->OutputString(gST->ConOut, L"Hello World\n\r");
    if (EFI_ERROR(Status))
        return Status;

    /* Now wait for a keystroke before continuing, otherwise your
       message will flash off the screen before you see it.

       First, we need to empty the console input buffer to flush
       out any keystrokes entered before this point */
    Status = gST->ConIn->Reset(gST->ConIn, FALSE);
    if (EFI_ERROR(Status))
        return Status;

    /* Now wait until a key becomes available.  This is a simple
       polling implementation.  You could try and use the WaitForKey
       event instead if you like */
    while ((Status = gST->ConIn->ReadKeyStroke(gST->ConIn, &Key)) == EFI_NOT_READY) ;

    return Status;
}

Building

To build, we use our cross-compiler:

i686-pc-mingw32-gcc -c -o hello.o -Ipath/to/gnu-efi/inc -Ipath/to/gnu-efi/inc/ia32 hello.c
i686-pc-mingw32-ld -b pei-i386 -shared -dll --subsystem 10 -nostdlib -o hello.efi -e _efi_main hello.o

Note here that '--subsystem 10' specifies an EFI application.

Creating the FAT image

Next, you will need to create a FAT filesystem image. How to do this is beyond the scope of this tutorial (as it greatly depends on the tools you are using) but it needs to contain your hello.efi file located at /EFI/BOOT/BOOTIA32.EFI

We will assume your FAT image is called hello.img

Creating the ISO

The iso image is a standard ISO9660 image which contains our FAT image as a file. A special El Torito option then points EFI aware systems to this image to be loaded.

mkdir iso
cp hello.img iso
xorriso -as mkisofs -R -f -e hello.img -no-emul-boot -o efi.iso iso

The efi.iso file should now be directly bootable in VirtualBox (assuming you have ticked the EFI option in the settings for your VM).

What to do next?

You may want to try using some more of the EFI boot services, e.g. to read more files from your iso image, manage memory etc (see the UEFI Specifications page for further documentation of this). You may also want to look at creating a 64-bit UEFI application instead. Finally, you could consider trying to create a CD that boots under normal PC BIOS and UEFI (possibly both 32- and 64-bit).

See also

UEFI