Linux is only one of the Operating Systems that our chips need to support. While some features need a complete OS for testing, we want to make sure that features are as tested as possible before we try to debug them through Linux.
My current code implements has to talk to the firmware. Thus we need to have a responder in the firmware. Testing this from Linux has to go through the entire Linux networking stack.
The developers of the firmware already have to deal with UEFI. UEFI is installed with the firmware. Since writing UEFI apps is basically like writing DOS apps (according to Ron Minnich) it is not a huge demand on our Firmware team to have them use UEFI as the basis for writing thei test code. Thus, they produced a simple app called RespTest.efi That checks that their code does what they expect it to do.
The normal process is that they boot the UEFI shell, switch to the file system, and copy up the Executable via tftp, Once it is on the system, they run it manually. After the first time the executable is leaded, the executable is persisted on the system. Thus, to run it a second or third time, after, say, a change to the firmware, can be automated from the operating system.
ls /boot/efi/
EFI ResponderTest.efi spinor.img
The above was executed from a Linux system running that has the efi partition mounted in /boot/efi. The RespTest.efi binary was copied up using tftp.
To see the set of UEFI boot options, we can use efibootmgr. These are mostly various flavors of PXE
efibootmgr BootCurrent: 0001 Timeout: 10 seconds BootOrder: 0000,0001,0002,0003,0004,0005,0006,0007,0008,0009,000A Boot0000* UiApp FvVol(5c60f367-a505-419a-859e-2a4ff6ca6fe5)/FvFile(462caa21-7614-4503-836e-8ab6f4662331) Boot0001* Fedora (Samsung SSD 970 EVO Plus 250GB) PcieRoot(0x60000)/Pci(0x1,0x0)/Pci(0x0,0x0)/NVMe(0x1,00-25-38-5A-91-51-38-0A)/HD(1,GPT,4c1510a2-110f-492f-8c64-50127bc2e552,0x800,0x200000)/File(\EFI\fedora\shimaa64.efi) File(.????????) Boot0002* UEFI PXEv4 (MAC:0C42A15A9B28) PcieRoot(0x0)/Pci(0x1,0x0)/Pci(0x0,0x0)/MAC(0c42a15a9b28,1)/IPv4(0.0.0.00.0.0.0,0,0){auto_created_boot_option} ... Boot0009* UEFI HTTPv6 (MAC:0C42A15A9B29) PcieRoot(0x0)/Pci(0x1,0x0)/Pci(0x0,0x1)/MAC(0c42a15a9b29,1)/IPv6([::]:<->[::]:,0,0)/Uri(){auto_created_boot_option} Boot000A* UEFI Shell FvVol(5c60f367-a505-419a-859e-2a4ff6ca6fe5)/FvFile(7c04a583-9e3e-4f1c-ad65-e05268d0b4d1) |
Lets say I want to boot to the UEFI shell next time. Since that has an index of 000A, I can run the following command to tell UEFI to boot to the shell once and only once. After that it will return to the default order:
efibootmgr –bootnext 000A
Here are the first few lines of output from that command;
# efibootmgr --bootnext 000A BootNext: 000A BootCurrent: 0001 Timeout: 10 seconds |
If I want to add an addition boot option, I can use the –create option. To tell it to boot the ResponderTest,efi executable:
efibootmgr efibootmgr --create -d /dev/nvme0n1p1 --label RespTest -l RespTest.efi
The last line of output from that command is:
Boot000B* RespTest HD(1,GPT,4c1510a2-110f-492f-8c64-50127bc2e552,0x800,0x200000)/File(RespTest.efi)efibootmgr
If I then want to make UEFI select this option upon next boot…
# efibootmgr --bootnext 000B
BootNext: 000B
BootCurrent: 0001
Timeout: 10 seconds
Note that the executable is in /boot/efi mounted on the Linux filesystem, but that will be the EF0: in UEFI. If you wish to put something further down the tree, you can, but remember that UEFI uses reverse slashes. I think it would look something like this…but I have not tried it yet:
efibootmgr efibootmgr –create -d /dev/nvme0n1p1 –label RespTest -l EFI\\RespTest.efi
Note the double slash to avoid Linux escaping….I think this is necessary.