UEFI drivers
A UEFI driver is an EDK II module built as a .efi image. It runs in boot services and can publish protocols, bind devices and prepare hardware for the next stage.
Module layout
MyDriver/
MyDriver.c
MyDriver.inf
MyProtocol.hMyDriver.inf:
[Defines]
INF_VERSION = 0x00010019
BASE_NAME = MyDriver
FILE_GUID = 00000000-0000-0000-0000-000000000000
MODULE_TYPE = UEFI_DRIVER
VERSION_STRING = 0.1
ENTRY_POINT = MyDriverEntry
[Sources]
MyDriver.c
[Packages]
MdePkg/MdePkg.dec
UniXNUPkg/UniXNUPkg.dec
[LibraryClasses]
MemoryAllocationLib
UefiBootServicesTableLib
UefiDriverEntryPoint
[Protocols]
gMyProtocolGuid ## PRODUCES
gEfiLoadedImageProtocolGuid ## CONSUMESMyDriver.c:
#include <Uefi.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Protocol/LoadedImage.h>
#include <Protocol/MyProtocol.h>
STATIC MY_PROTOCOL mProtocol = { MY_SIGNATURE, NULL };
EFI_STATUS
EFIAPI
MyDriverEntry (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_LOADED_IMAGE_PROTOCOL *Loaded;
EFI_HANDLE Handle = NULL;
if (!EFI_ERROR (gBS->HandleProtocol (
ImageHandle, &gEfiLoadedImageProtocolGuid, (VOID **)&Loaded)) &&
(Loaded->LoadOptions != NULL))
{
mProtocol.Options = AllocateCopyPool (
Loaded->LoadOptionsSize, Loaded->LoadOptions);
}
return gBS->InstallMultipleProtocolInterfaces (
&Handle, &gMyProtocolGuid, &mProtocol, NULL);
}The driver receives its LoadOptions from the UniXNU args field.
Build
Add the INF to a DSC:
[Components]
MyPkg/MyDriver/MyDriver.infBuild with EDK II:
build -p MyPkg/MyPkg.dsc -a AARCH64 -b DEBUG -t CLANGPDB -n 8The result is Build/MyPkg/DEBUG_CLANGPDB/AARCH64/MyDriver.efi.
The UniXNU package DSC contains the standalone build:
package/UniXNUPkg/UniXNUPkg.dscpackage/build.sh copies the EFI binaries to Build/Out/AARCH64-DEBUG.
Load from UniXNU
Copy the driver to the payload volume and add an entry to unixnu.toml:
[[driver]]
path = "Drivers/MyDriver.efi"
args = "board=1"
connect = true
enabled = true| Key | Meaning |
|---|---|
path | Path relative to \EFI\UniXNU, or fv:<GUID> |
args | Load options string |
connect | Run ConnectController on every handle after the driver starts |
enabled | false skips the entry |
A kit can add the driver:
[[driver]]
file = "MyDriver.efi"
args = "from-kit"The kit path resolves relative to the kit directory.
Firmware volume path
fv:<GUID> loads a file from any firmware volume by file GUID:
[[driver]]
path = "fv:00000000-0000-0000-0000-000000000000"This loads a driver already embedded in the firmware without copying it to the payload.
Firmware volume inclusion
To embed a driver in the firmware:
- Add the INF to the platform DSC under
[Components]. - Add the INF to the FDF under
[FV.<name>] INF. - Rebuild the firmware.
The firmware dispatcher starts DXE drivers during dispatch. A UEFI application in the FV is started by UniXNUDxe or by a Boot#### option.
Driver model
A UEFI driver that follows the driver model implements EFI_DRIVER_BINDING_PROTOCOL:
| Function | Role |
|---|---|
Supported | Reports whether the driver can handle a controller |
Start | Installs child handles or protocols |
Stop | Removes them |
UniXNU calls ConnectController on every handle when connect = true and [boot] connect_all is true. This binds driver-model drivers to new devices.
Protocols
A protocol is a GUID and a function table:
typedef struct {
UINT64 Signature;
EFI_STATUS (EFIAPI *DoWork)(IN struct _MY_PROTOCOL *This);
} MY_PROTOCOL;
extern EFI_GUID gMyProtocolGuid;The producer installs it with InstallMultipleProtocolInterfaces. A consumer locates it with LocateProtocol or HandleProtocol.
Example modules
| Module | Purpose |
|---|---|
UniXNUPkg/Test/SampleDriver | Installs UNIXNU_SAMPLE_PROTOCOL and records its load options |
UniXNUPkg/Test/HelloPayload | Test application for injection |
UniXNUPkg/Driver/UniXNUDxe | Registers the UniXNU application as a boot option |
drivers/DarwinBoot | Installs UNIXNU_LOADER_PROTOCOL |
Logging
UniXNU logs every driver result:
UNIXNU: driver <path> (<origin>): started
UNIXNU: driver <path> (<origin>): load failed: <status>
UNIXNU: driver <path> (<origin>): start failed: <status>The menu shows the loaded and failed counts and the first failure reason.