For example, here is some source code to create a simple Hello World app. The system will boot
and simply display "Hello, World!" to the screen. This is a modified version of the source
that will be in the next edition of FYSOS: The System Core, which will include detailed instructions on how to create a boot loader using the UEFI system.
boot.c
#pragma proc(486)
#pragma proc(long)
#pragma ptype(pmode)
#include "ctype.h"
#include "efi_32.h"
#include "efi_32.c"
#include "conout.c"
EFI_STATUS efi_main(EFI_HANDLE ImageHandle, struct EFI_SYSTEM_TABLE *SystemTable) {
if (!InitializeLib(ImageHandle, SystemTable))
return 1;
cls();
puts(L"Hello, World!");
while (1)
_asm ("hlt \n");
return EFI_SUCCESS;
}
conout.c
void cls(void) {
gSystemTable->ConOut->ClearScreen(gSystemTable->ConOut);
}
void puts(const wchar_t *text) {
gSystemTable->ConOut->OutputString(gSystemTable->ConOut, text);
}
efi_32.c
EFI_HANDLE gImageHandle;
struct EFI_SYSTEM_TABLE *gSystemTable;
bool InitializeLib(EFI_HANDLE ImageHandle, struct EFI_SYSTEM_TABLE *SystemTable) {
if ((SystemTable->Hdr.Signature[0] != EFI_SYSTEM_TABLE_SIGNATURE) ||
(SystemTable->Hdr.Signature[1] != EFI_SYSTEM_TABLE_SIGNATURE2))
return FALSE;
gImageHandle = ImageHandle;
gSystemTable = SystemTable;
return TRUE;
}
efi_32.h
#pragma pack(push, 1)
typedef unsigned int EFI_STATUS;
typedef void *EFI_HANDLE;
#define EFI_SUCCESS 0
#define EFI_SYSTEM_TABLE_SIGNATURE 0x20494249
#define EFI_SYSTEM_TABLE_SIGNATURE2 0x54535953
#define EFI_RUNTIME_SERVICES_SIGNATURE 0x544E5552
#define EFI_RUNTIME_SERVICES_SIGNATURE2 0x56524553
struct EFI_TABLE_HEADER {
bit32u Signature[2];
bit32u Revision;
bit32u HeaderSize;
bit32u CRC32;
bit32u Reserved;
};
struct EFI_GUID {
bit32u Data1;
bit16u Data2;
bit16u Data3;
bit8u Data4[8];
};
struct EFI_CONFIGURATION_TABLE {
struct EFI_GUID VendorGuid;
void *VendorTable;
};
struct EFI_SYSTEM_TABLE {
struct EFI_TABLE_HEADER Hdr;
bit16u *FirmwareVendor;
bit32u FirmwareRevision;
EFI_HANDLE ConsoleInHandle;
struct EFI_SIMPLE_TEXT_INPUT_PROTOCOL *ConIn;
EFI_HANDLE ConsoleOutHandle;
struct SIMPLE_TEXT_OUTPUT_INTERFACE *ConOut;
EFI_HANDLE StandardErrorHandle;
struct SIMPLE_TEXT_OUTPUT_INTERFACE *StdErr;
struct EFI_RUNTIME_SERVICES *RuntimeServices;
void *BootServices;
bit32u NumberOfTableEntries;
struct EFI_CONFIGURATION_TABLE *ConfigurationTable;
};
struct SIMPLE_TEXT_OUTPUT_INTERFACE {
void *Reset;
void (*OutputString)(bit16u *text, struct SIMPLE_TEXT_OUTPUT_INTERFACE *ConOut);
void *TestString;
void *QueryMode;
void *SetMode;
void *SetAttribute;
void (*ClearScreen)(struct SIMPLE_TEXT_OUTPUT_INTERFACE *ConOut);
void *SetCursorPosition;
void *EnableCursor;
void *Mode;
};
struct EFI_SIMPLE_TEXT_INPUT_PROTOCOL {
void *Reset;
void *ReadKeyStroke;
void *WaitForKey;
};
struct EFI_RUNTIME_SERVICES {
struct EFI_TABLE_HEADER Hdr;
void *GetTime;
void *SetTime;
void *GetWakeUpTime;
void *SetWakeUpTime;
void *SetVirtualAddressMap;
void *ConvertPointer;
void *GetVariable;
void *GetNextVariableName;
void *SetVariable;
void *GetNextHighMonotonicCount;
void *ResetSystem;
};
#pragma pack(pop)
bool InitializeLib(EFI_HANDLE ImageHandle, struct EFI_SYSTEM_TABLE *SystemTable);
void cls(void);
void puts(wchar_t *);
ctype.h
#define TRUE 1
#define FALSE 0
#define NULL ((void *) 0)
typedef unsigned char bool;
typedef signed char bit8s;
typedef unsigned char bit8u;
typedef signed short bit16s;
typedef unsigned short bit16u;
typedef signed long bit32s;
typedef unsigned long bit32u;
startup.nsh
fs0:
boot.efi
Please note that the modifications I made to NBC are just enough to compile the code I needed to show how to create an EFI bootable image, as well as the source listed above. If I didn't need a function call, I simply declared it as a "void *FunctionName". Further modifications to NBC and a more detailed source code will be available when the next edition of this book is released. Thanks.