This script automates the process of building EFI application using the EDK II development environment and sending them to the virtual disk of an OVMF based virtual machine.
- Build and copy EFI applications
- Manage individual application profiles
- Dynamic configuration of paths and parameters
- Build and replace the OVMF firmware image
- The script assumes you use EDK II and libvrt (qemu) running OVMF firmware
- You need to have root access permissions in order to mount the virtual disk
- The virtual disk must be a FAT32 raw image file named
OVMF_DISK.img
- Control more parameters of the EDK II build
- Support other virtual disks formats and paths
- Add an automatically generated UEFI startup script
After installing qemu, libvirt, OVMF, and virt-manager, add the path to
your OVMF firmware image and runtime variables template to your libvirt config
so virt-install
or virt-manager
can find those later on. Add the following
line to /etc/libvirt/qemu.conf
:
nvram = [ "<PATH_TO_OVMF>/OVMF_CODE.fd:<PATH_TO_OVMF>/OVMF_VARS.fd" ]
- Create a file filled with zeros:
$ dd if=/dev/zero of=OVMF_DISK.img bs=1M count=100
- Use
fdisk OVMF_DISK.img
to create primary partition of type W95 FAT32 (LBA). - Create the FAT32 file system in the image:
$ mkfs.vfat OVMF_DISK.img
- Press on File -> New Virtual Machine and select Import existing disk image.
- Browse for the FAT32 raw image file you created.
- On the final step of the wizard, select Customize configuration before install.
- Change the Firmware to the UEFI x86_64 option.
- [Optional] Change Chipset to Q35.
- [Optional] Go to the CPUs screen, uncheck Copy host CPU configutaion and
on the Model field write host-passthrough. - [Optional] Go to Disk 1 screen, change Disk Bus to SATA and Cache mode to writethrough.
- Click on Begin Installation.
The script should be placed in a working directory where it will be able to save its profile and configurations files.
Before running the script, EDK II BaseTools should be compiled.
The build configurations file edk2/Conf/target.txt
should be edited with the
following values: TOOL_CHAIN_TAG = GCC5
and TARGET_ARCH = X64
. Currently,
the script does not support other build configurations without editing it.
Run command ./efiappbnc --help
for more information.
The script needs to be configured with some paths and parameters in order to
work. The configurations are saved to a .config
file in the working directory.
If the file does not exist, the script will ask to set configurations. The script
will check for missing configurations when needed.
Run command ./efiappbnc configure
to edit existing configurations.
leyaniv@leyaniv-Airtop2 /work/TianoCore/efiappbnc $ ./efiappbnc ===Edit configurations=== 1) OVMF virtual image file path: Not set 2) Number of threads to build: Not set 3) EDK2 repository path: Not set Select a number to edit (Press enter to save and continue): 1 Edit "OVMF virtual image file path": /work/TianoCore/OVMF 1) OVMF virtual image file path: /work/TianoCore/OVMF 2) Number of threads to build: Not set 3) EDK2 repository path: Not set Select a number to edit (Press enter to save and continue): 2 Edit "Number of threads to build": 14 1) OVMF virtual image file path: /work/TianoCore/OVMF 2) Number of threads to build: 14 3) EDK2 repository path: Not set Select a number to edit (Press enter to save and continue): 3 Edit "EDK2 repository path": /work/TianoCore/edk2 1) OVMF virtual image file path: /work/TianoCore/OVMF 2) Number of threads to build: 14 3) EDK2 repository path: /work/TianoCore/edk2 Select a number to edit (Press enter to save and continue): >> Saving configurations >> Looking for available app profiles >> No profiles found, create a new one Input application name: CLHello ===EDK2 build=== >> Building shell environment Loading previous configuration from /work/TianoCore/edk2/Conf/BuildEnv.sh WORKSPACE: /work/TianoCore/edk2 EDK_TOOLS_PATH: /work/TianoCore/edk2/BaseTools CONF_PATH: /work/TianoCore/edk2/Conf Input platform name: Compulab Input package name: CompulabPkg Input package DSC file name: CompulabPkg.dsc >> Building package Build environment: Linux-4.13.0-45-generic-x86_64-with-LinuxMint-18.3-sylvia Build start time: 17:50:09, Sep.06 2018 WORKSPACE = /work/TianoCore/edk2 ECP_SOURCE = /work/TianoCore/edk2/EdkCompatibilityPkg EDK_SOURCE = /work/TianoCore/edk2/EdkCompatibilityPkg EFI_SOURCE = /work/TianoCore/edk2/EdkCompatibilityPkg EDK_TOOLS_PATH = /work/TianoCore/edk2/BaseTools CONF_PATH = /work/TianoCore/edk2/Conf Processing meta-data . done! Building ... /work/TianoCore/edk2/ShellPkg/Library/UefiShellLib/UefiShellLib.inf [X64] Building ... /work/TianoCore/edk2/ShellPkg/Library/UefiShellCEntryLib/UefiShellCEntryLib.inf [X64] Building ... /work/TianoCore/edk2/MdePkg/Library/UefiFileHandleLib/UefiFileHandleLib.inf [X64] Building ... /work/TianoCore/edk2/MdeModulePkg/Library/UefiHiiLib/UefiHiiLib.inf [X64] Building ... /work/TianoCore/edk2/MdeModulePkg/Library/UefiSortLib/UefiSortLib.inf [X64] Building ... /work/TianoCore/edk2/MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf [X64] Building ... /work/TianoCore/edk2/MdePkg/Library/UefiLib/UefiLib.inf [X64] Building ... /work/TianoCore/edk2/MdeModulePkg/Library/UefiHiiServicesLib/UefiHiiServicesLib.inf [X64] Building ... /work/TianoCore/edk2/MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf [X64] Building ... /work/TianoCore/edk2/MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf [X64] Building ... /work/TianoCore/edk2/MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf [X64] Building ... /work/TianoCore/edk2/MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf [X64] Building ... /work/TianoCore/edk2/MdePkg/Library/BaseLib/BaseLib.inf [X64] Building ... /work/TianoCore/edk2/MdePkg/Library/BasePrintLib/BasePrintLib.inf [X64] Building ... /work/TianoCore/edk2/MdePkg/Library/UefiDebugLibConOut/UefiDebugLibConOut.inf [X64] Building ... /work/TianoCore/edk2/MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf [X64] Building ... /work/TianoCore/edk2/MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf [X64] Building ... /work/TianoCore/edk2/MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf [X64] Building ... /work/TianoCore/edk2/CompulabPkg/CLHello/CLHello.inf [X64] - Done - Build end time: 17:50:10, Sep.06 2018 Build total time: 00:00:01 ===Copy application to OVMF drive=== Input application file name: CLHello.efi >> Mounting OVMF drive image >> Copying application to mounted image >> Unmounting OVMF drive image >> Resseting OVMF qemu session Domain OVMF-RAW was reset Do you want to save a app profile? (Press y/n): y >> Saving a profile for CLHello app >> Done!
- Type
exit
on the EFI shell to get to the setup menu. - To change the screen resolution, enter the setup menu, go to Device Manager,
then OVMF Platform Configuration. Change the preferred resolution and exit.
The console output text mode (number of rows and columns) can be changed using
the mode
shell command. You might find the original selection of available
modes to be very limited on your OVMF firmware. To add additional modes to your
firmware, you need to edit the array mTerminalConsoleModeData
with your desired
selection of modes.
The array is located in MdeModulePkg/Universal/Console/TerminalDxe/Terminal.c
For example (based on this patch):
TERMINAL_CONSOLE_MODE_DATA mTerminalConsoleModeData[] = {
{ 80, 25 }, // from graphics resolution 640 x 480
{ 80, 50 }, // from graphics resolution 640 x 960
{ 100, 25 }, // from graphics resolution 800 x 480
{ 100, 31 }, // from graphics resolution 800 x 600
{ 104, 32 }, // from graphics resolution 832 x 624
{ 120, 33 }, // from graphics resolution 960 x 640
{ 128, 31 }, // from graphics resolution 1024 x 600
{ 128, 40 }, // from graphics resolution 1024 x 768
{ 144, 45 }, // from graphics resolution 1152 x 864
{ 144, 45 }, // from graphics resolution 1152 x 870
{ 160, 37 }, // from graphics resolution 1280 x 720
{ 160, 40 }, // from graphics resolution 1280 x 760
{ 160, 40 }, // from graphics resolution 1280 x 768
{ 160, 42 }, // from graphics resolution 1280 x 800
{ 160, 50 }, // from graphics resolution 1280 x 960
{ 160, 53 }, // from graphics resolution 1280 x 1024
{ 170, 40 }, // from graphics resolution 1360 x 768
{ 170, 40 }, // from graphics resolution 1366 x 768
{ 175, 55 }, // from graphics resolution 1400 x 1050
{ 180, 47 }, // from graphics resolution 1440 x 900
{ 200, 47 }, // from graphics resolution 1600 x 900
{ 200, 63 }, // from graphics resolution 1600 x 1200
{ 210, 55 }, // from graphics resolution 1680 x 1050
{ 240, 56 }, // from graphics resolution 1920 x 1080
{ 240, 63 }, // from graphics resolution 1920 x 1200
{ 240, 75 }, // from graphics resolution 1920 x 1440
{ 250, 105 }, // from graphics resolution 2000 x 2000
{ 256, 80 }, // from graphics resolution 2048 x 1536
{ 256, 107 }, // from graphics resolution 2048 x 2048
{ 320, 75 }, // from graphics resolution 2560 x 1440
{ 320, 84 }, // from graphics resolution 2560 x 1600
{ 320, 107 }, // from graphics resolution 2560 x 2048
{ 350, 110 }, // from graphics resolution 2800 x 2100
{ 400, 126 }, // from graphics resolution 3200 x 2400
{ 480, 113 }, // from graphics resolution 3840 x 2160
{ 512, 113 }, // from graphics resolution 4096 x 2160
{ 960, 227 }, // from graphics resolution 7680 x 4320
{ 1024, 227 }, // from graphics resolution 8192 x 4320
//
// New modes can be added here.
//
};
After copying the application binary to the virtual disk, the script will reset
the qemu session. A startup script can be useful to avoid typing the same
commands after each reset. The startup script is a file named startup.nsh
that
is located at the root of the virtual disk. The following script is an example
echo -off
mode 128 40 # Change console output mode (suits 1024 x 768 resolution)
fs0: # Go to the virtual drive
ls # List files
echo -on