This post looks at the state of UEFI booting in Fedora 17(codename Beefy Miracle). By UEFI booting, I mean the ability to boot a Linux operating system without the next for GRUB, efililo or any other boot loader.
Here is how Fedora 17 (F17) sets up a 500G disk if you do an F17 default UEFI install:
$ df -h Filesystem Size Used Avail Use% Mounted on rootfs 50G 5.6G 42G 12% / devtmpfs 7.8G 0 7.8G 0% /dev tmpfs 7.8G 96K 7.8G 1% /dev/shm tmpfs 7.8G 1.3M 7.8G 1% /run /dev/sda3 50G 5.6G 42G 12% / tmpfs 7.8G 0 7.8G 0% /sys/fs/cgroup tmpfs 7.8G 0 7.8G 0% /media /dev/sda5 398G 6.2G 372G 2% /home /dev/sda2 497M 74M 399M 16% /boot /dev/sda1 200M 27M 173M 14% /boot/efi
I am not going to explain how to do a UEFI install. I assume that you know how to do so if you are reading this blog. If not, read the F17 Release Notes.
Looking more closely at the contents of /boot, you will see that it contains three sub-directores of interest, i.e. efi, grub and grub2:
# cd /boot; ls -al total 47406 dr-xr-xr-x. 6 root root 1024 May 24 12:02 . dr-xr-xr-x. 18 root root 4096 May 26 19:15 .. -rw-r--r--. 1 root root 114861 Mar 18 23:09 config-3.3.0-1.fc17.x86_64 -rw-r--r-- 1 root root 115168 May 16 17:27 config-3.3.6-3.fc17.x86_64 drwx------ 4 root root 16384 Dec 31 1969 efi drwxr-xr-x. 2 root root 1024 May 24 12:02 grub drwxr-xr-x 3 root root 1024 May 24 12:02 grub2 -rw-r--r--. 1 root root 16683967 May 19 18:58 initramfs-3.3.0-1.fc17.x86_64.img -rw-r--r-- 1 root root 17432458 May 21 19:38 initramfs-3.3.6-3.fc17.x86_64.img drwx------. 2 root root 12288 May 19 18:44 lost+found -rw-------. 1 root root 2411498 Mar 18 23:09 System.map-3.3.0-1.fc17.x86_64 -rw------- 1 root root 2412800 May 16 17:27 System.map-3.3.6-3.fc17.x86_64 -rwxr-xr-x. 1 root root 4661840 Mar 18 23:09 vmlinuz-3.3.0-1.fc17.x86_64 -rwxr-xr-x 1 root root 4664080 May 16 17:27 vmlinuz-3.3.6-3.fc17.x86_64 -rw-r--r-- 1 root root 164 May 16 17:27 .vmlinuz-3.3.6-3.fc17.x86_64.hmac # cd grub; ls splash.xpm.gz < -- used by GRUB 0.97 EFI, #cd ../grub2; ls -R .: themes ./themes: system ./themes/system: background.png # cd /boot/efi/EFI/redhat; ls -l -rwx------ 1 root root 64 May 19 15:02 device.map -rwx------ 1 root root 1050 May 21 19:38 grub.conf -rwx------ 1 root root 246697 Apr 27 11:45 grub.efi
The hardware platoform that I UEFI-installed F17 on was a Biostar TZ77MXE which has AMI Aptio (UEFI 2.3) firmware. The UEFI install completed without incident or failure but the system would not boot after installation was completed. I traced the problem to a boot flag on the protective MBR. Once I removed the boot flag, the firmware had no difficulty UEFI-booting F17. Intel UEFI firmware seems to want the boot flag, other firmware such as the AMI Aptio appear to require the boot flag not to be set. The firmware boots a modified version of Legacy GRUB v0.97 (grub.efi) which in turn boots F17. Note that the GRUB Legacy upstream source does not have UEFI support. Redhat’s fork of GRUB Legacy, which is maintained by Peter Jones, contains a number of UEFI patches provided by Intel. See here for the gory details.
EFI runtime services support was recently added to the Linux Kernel (3.3.1 and later) to enable booting the kernel directly from a UEFI shell or a UEFI boot manager. To build the kernel with EFISTUB (EFI runtime services) support, the following kernel configuration is necessary:
CONFIG_EFI=y CONFIG_EFI_VARS=y
Rather than trying to write my own explanation of how to do this, read the the following text, written by Matt Fleming, that was added to the Linux Kernel codebase by H. Peter Anvin on June 1st 2012.
The EFI Boot Stub --------------------------- On the x86 platform, a bzImage can masquerade as a PE/COFF image, thereby convincing EFI firmware loaders to load it as an EFI executable. The code that modifies the bzImage header, along with the EFI-specific entry point that the firmware loader jumps to are collectively known as the "EFI boot stub", and live in arch/x86/boot/header.S and arch/x86/boot/compressed/eboot.c, respectively. By using the EFI boot stub it's possible to boot a Linux kernel without the use of a conventional EFI boot loader, such as grub or elilo. Since the EFI boot stub performs the jobs of a boot loader, in a certain sense it *IS* the boot loader. The EFI boot stub is enabled with the CONFIG_EFI_STUB kernel option. **** How to install bzImage.efi The bzImage located in arch/x86/boot/bzImage must be copied to the EFI System Partiion (ESP) and renamed with the extension ".efi". Without the extension the EFI firmware loader will refuse to execute it. It's not possible to execute bzImage.efi from the usual Linux file systems because EFI firmware doesn't have support for them. **** Passing kernel parameters from the EFI shell Arguments to the kernel can be passed after bzImage.efi, e.g. fs0:> bzImage.efi console=ttyS0 root=/dev/sda4 **** The "initrd=" option Like most boot loaders, the EFI stub allows the user to specify multiple initrd files using the "initrd=" option. This is the only EFI stub-specific command line parameter, everything else is passed to the kernel when it boots. The path to the initrd file must be an absolute path from the beginning of the ESP, relative path names do not work. Also, the path is an EFI-style path and directory elements must be separated with backslashes (\). For example, given the following directory layout, fs0:> Kernels\ bzImage.efi initrd-large.img Ramdisks\ initrd-small.img initrd-medium.img to boot with the initrd-large.img file if the current working directory is fs0:\Kernels, the following command must be used, fs0:\Kernels> bzImage.efi initrd=\Kernels\initrd-large.img Notice how bzImage.efi can be specified with a relative path. That's because the image we're executing is interpreted by the EFI shell, which understands relative paths, whereas the rest of the command line is passed to bzImage.efi.
Usually there is an option on your firmware configuration screen, to boot to an EFI shell. An EFI shell is simply another EFI application (executable image) as far as the firmware is concerned.
If your firmware does not come with a built-in EFI shell, you need to install a X64 EFI shell at (typically) /boot/efi and name it either shell.efi or shellx64.efi. If you need an X64 EFI shell, you can download one from my website.
All EFI executable images contain a PE/COFF header defining the format of the executable code. The code may be one of the following:
- IA-32
- X64
- IA-64 (Itaninum)
- EFI byte code (Processor agnostic)
Once you get to the EFI shell prompt, you need to copy your kernel and initramfs images to your ESP (EFI System Partition) and give the kernel an .EFI extension. It does not matter whether it is lowercase or uppercase as the ESP is a FAT filesystem and thus case agnostic. You should then be able to boot F17 from the EFI shell command line.
# cd /boot/efi; ls -l drwx------ 3 root root 4096 May 20 01:36 EFI -rwx------ 1 root root 17432458 May 23 21:49 initramfs-3.3.6-3.fc17.x86_64.img -rwx------ 1 root root 214 May 26 12:14 f17.nsh -rwx------ 1 root root 1240192 May 26 22:53 Shell.efi -rwx------ 1 root root 4664080 May 23 21:49 vmlinuz-3.3.6-3.fc17.x86_64.efi
In older versions of Fedora, you had to boot the kernel using a UEFI-enabled verion of GRUB Legacy which came with the release or you could download and build a UEFI-enabled version of GRUB2. With EFI runtime services availbale in the Linux kernel, you can boot the kernel directly from an EFI Shell without the need to use GRUB,
Here is a copy of the EFI shell script which I created to simplify booting Fedora 17 with the 3.3.6-3 kernel:
# cat f17.nsh vmlinuz-3.3.6-3.fc17.x86_64.efi root=UUID=1d3092fc-265e-4860-a609-d6a16c1a6458 rd.lvm=0 rd.dm=0 KEYTABLE=us SYSFONT=True rd.md=0 rd.luks=0 ro LANG=en_US.UTF-8 rhgb quiet initrd=.\initramfs-3.3.6-3.fc17.x86_64.img
EFI shell scripts have to have an extension of .nsh, i.e new shell script. To boot F17, I then simply type f17.
Turning now to related UEFI topic, let us examine what UEFI-related information is available or modifiable from within F17.
The efibootmgr utility can be used to change the UEFI boot variables, i.e. Timeout,BootOrder, and the BootXXXX variables.
# efibootmgr Timeout: 2 seconds BootOrder: 0000,0001,0002 Boot0000* Fedora Boot0001 CD/DVD Drive Boot0002 Hard Drive [root@ultra vars]# efibootmgr -v Timeout: 2 seconds BootOrder: 0000,0001,0002 Boot0000* Fedora HD(1,800,64000,a2b4a2ac-5677-43cf-a820-b97975015f20)File(\EFI\redhat\grub.efi) Boot0001 CD/DVD Drive BIOS(3,0,00)AMGOAMNO........o.H.P. .D.V.D. .W.r.i.t.e.r. .1.0.7.0.d....................A...........................>..Gd-.;.A..MQ..L. . . . . . . . . . . . . . . . . . . . ......AMBO Boot0002 Hard Drive BIOS(2,0,00)AMGOAMNO........o.S.T.3.5.0.0.4.1.3.A.S....................A...........................>..Gd-.;.A..MQ..L. . . . . . . . . . . . .2.Z.8.A.Q.J.8.N......AMBOAMNO........o.S.T.3.5.0.0.4.1.8.A.S....................A...........................>..Gd-.;.A..MQ..L. . . . . . . . . . . . .V.9.J.M.P.4.7.7......AMBOAMNO........o.S.T.3.5.0.0.3.2.0.A.S....................A...........................>..Gd-.;.A..MQ..L. . . . . . . . . . . . .Q.9.4.M.N.9.Q.M......AMBO
By the way, it is possible to directly embed the kernel parameters within the boot entry created by efibootmgr. For example,
# echo "root=/dev/sdaX ro rootfstype=ext4 add_efi_memmap initrd=\\EFI\\arch\\initramfs-linux.img" | iconv -f asc
FPM >>>>>> https://wiki.archlinux.org/index.php/UEFI_Bootloaders
While examining the contents of the /sys/firmware/efi/vars sub-directory, I noticed the following directories which I had never seen before.
dump-type0-10-1337811289-cfc8fc79-be2e-4ddc-97f0-9f98bfe298a0 dump-type0-11-1337811290-cfc8fc79-be2e-4ddc-97f0-9f98bfe298a0 dump-type0-1-1337864078-cfc8fc79-be2e-4ddc-97f0-9f98bfe298a0 dump-type0-2-1337864079-cfc8fc79-be2e-4ddc-97f0-9f98bfe298a0 dump-type0-3-1337864080-cfc8fc79-be2e-4ddc-97f0-9f98bfe298a0 dump-type0-4-1337864081-cfc8fc79-be2e-4ddc-97f0-9f98bfe298a0 dump-type0-5-1337864082-cfc8fc79-be2e-4ddc-97f0-9f98bfe298a0 dump-type0-6-1337864083-cfc8fc79-be2e-4ddc-97f0-9f98bfe298a0 dump-type0-7-1337864084-cfc8fc79-be2e-4ddc-97f0-9f98bfe298a0 dump-type0-8-1337864085-cfc8fc79-be2e-4ddc-97f0-9f98bfe298a0 dump-type0-9-1337864086-cfc8fc79-be2e-4ddc-97f0-9f98bfe298a0
Examining the first sub-directory revealed that the data file contained therein is some sort of a kernel dump facility.
# cd dump-type0-1-1337864078-cfc8fc79-be2e-4ddc-97f0-9f98bfe298a0] # cat data Oops#1 Part1 ic - not syncing: stack-protector: Kernel stack is corrupted in: ffffffff81b14c64 <0>[ 0.869252] <4>[ 0.871917] Pid: 1, comm: swapper/0 Not tainted 3.3.6-3.fc17.x86_64 #1 <4>[ 0.872804] Call Trace: <4>[ 0.873678] [<ffffffff815e27dd>] panic+0xba/0x1c6 <4>[ 0.874551] [<ffffffff81b14c64>] ? printk_all_partitions+0x259/0x26b <4>[ 0.875430] [<ffffffff810566bb>] __stack_chk_fail+0x1b/0x20 <4>[ 0.876306] [<ffffffff81b14c64>] printk_all_partitions+0x259/0x26b <4>[ 0.877170] [<ffffffff81aedfe0>] mount_block_root+0x1bc/0x27f <4>[ 0.878015] [<ffffffff81aee0fa>] mount_root+0x57/0x5b <4>[ 0.878843] [<ffffffff81aee23b>] prepare_namespace+0x13d/0x176 <4>[ 0.879660] [<ffffffff81aedd60>] kernel_init+0x155/0x15a <4>[ 0.880477] [<ffffffff81087b77>] ? schedule_tail+0x27/0xb0 <4>[ 0.881286] [<ffffffff815f52a4>] kernel_thread_helper+0x4/0x10 <4>[ 0.882082] [<ffffffff81aedc0b>] ? start_kernel+0x3c5/0x3c5 <4>[ 0.882868] [<ffffffff815f52a0>] ? gs_change+0x13/0x13 </ffffffff815f52a0></ffffffff81aedc0b></ffffffff815f52a4></ffffffff81087b77> </ffffffff81aedd60></ffffffff81aee23b></ffffffff81aee0fa></ffffffff81aedfe0> </ffffffff81b14c64></ffffffff810566bb></ffffffff81b14c64></ffffffff815e27dd>
Looking at the firmware NVRAM using the EFI dmpstore utility showed that the contents of these files are stored as NVRAM variables. For example, here is the contents of dump-type0-10-1337811289:
Variable NV+RT+BS 'CFC8FC79-BE2E-4DDC-97F0-9F98BFE298A0:dump-type0-10-1337811289' DataSize = 400 00000000: 4F 6F 70 73 23 31 20 50-61 72 74 31 30 0A 30 3A *Oops#1 Part10.0:* 00000010: 20 55 53 42 20 68 75 62-20 66 6F 75 6E 64 0A 3C * USB hub found.< * 00000020: 36 3E 5B 20 20 20 20 30-2E 35 30 30 36 39 34 5D *6>[ 0.500694]* 00000030: 20 68 75 62 20 32 2D 30-3A 31 2E 30 3A 20 32 20 * hub 2-0:1.0: 2 * 00000040: 70 6F 72 74 73 20 64 65-74 65 63 74 65 64 0A 3C *ports detected.< * 00000050: 36 3E 5B 20 20 20 20 30-2E 35 30 31 30 35 38 5D *6>[ 0.501058]* 00000060: 20 6F 68 63 69 5F 68 63-64 3A 20 55 53 42 20 31 * ohci_hcd: USB 1* 00000070: 2E 31 20 27 4F 70 65 6E-27 20 48 6F 73 74 20 43 *.1 'Open' Host C* 00000080: 6F 6E 74 72 6F 6C 6C 65-72 20 28 4F 48 43 49 29 *ontroller (OHCI)* 00000090: 20 44 72 69 76 65 72 0A-3C 36 3E 5B 20 20 20 20 * Driver.<6>[ * 000000A0: 30 2E 35 30 31 34 31 35-5D 20 75 68 63 69 5F 68 *0.501415] uhci_h* 000000B0: 63 64 3A 20 55 53 42 20-55 6E 69 76 65 72 73 61 *cd: USB Universa* 000000C0: 6C 20 48 6F 73 74 20 43-6F 6E 74 72 6F 6C 6C 65 *l Host Controlle* 000000D0: 72 20 49 6E 74 65 72 66-61 63 65 20 64 72 69 76 *r Interface driv* 000000E0: 65 72 0A 3C 37 3E 5B 20-20 20 20 30 2E 35 30 31 *er.<7>[ 0.501* 000000F0: 38 30 33 5D 20 78 68 63-69 5F 68 63 64 20 30 30 *803] xhci_hcd 00* 00000100: 30 30 3A 30 30 3A 31 34-2E 30 3A 20 73 65 74 74 *00:00:14.0: sett* 00000110: 69 6E 67 20 6C 61 74 65-6E 63 79 20 74 69 6D 65 *ing latency time* 00000120: 72 20 74 6F 20 36 34 0A-3C 36 3E 5B 20 20 20 20 *r to 64.<6>[ * 00000130: 30 2E 35 30 31 38 30 36-5D 20 78 68 63 69 5F 68 *0.501806] xhci_h* 00000140: 63 64 20 30 30 30 30 3A-30 30 3A 31 34 2E 30 3A *cd 0000:00:14.0:* 00000150: 20 78 48 43 49 20 48 6F-73 74 20 43 6F 6E 74 72 * xHCI Host Contr* 00000160: 6F 6C 6C 65 72 0A 3C 36-3E 5B 20 20 20 20 30 2E *oller.<6>[ 0.* 00000170: 35 30 32 31 38 38 5D 20-78 68 63 69 5F 68 63 64 *502188] xhci_hcd* 00000180: 20 30 30 30 30 3A 30 30-3A 31 34 2E 30 3A 20 6E * 0000:00:14.0: n* 00000190: 65 77 20 55 53 42 20 62-75 73 20 72 65 67 69 73 *ew USB bus regis* 000001A0: 74 65 72 65 64 2C 20 61-73 73 69 67 6E 65 64 20 *tered, assigned * 000001B0: 62 75 73 20 6E 75 6D 62-65 72 20 33 0A 3C 37 3E *bus number 3.<7>* 000001C0: 5B 20 20 20 20 30 2E 35-30 32 36 34 30 5D 20 78 *[ 0.502640] x* 000001D0: 68 63 69 5F 68 63 64 20-30 30 30 30 3A 30 30 3A *hci_hcd 0000:00:* 000001E0: 31 34 2E 30 3A 20 63 61-63 68 65 20 6C 69 6E 65 *14.0: cache line* 000001F0: 20 73 69 7A 65 20 6F 66-20 36 34 20 69 73 20 6E * size of 64 is n* 00000200: 6F 74 20 73 75 70 70 6F-72 74 65 64 0A 3C 36 3E *ot supported.<6>* 00000210: 5B 20 20 20 20 30 2E 35-30 32 36 34 33 5D 20 78 *[ 0.502643] x* 00000220: 68 63 69 5F 68 63 64 20-30 30 30 30 3A 30 30 3A *hci_hcd 0000:00:* 00000230: 31 34 2E 30 3A 20 69 72-71 20 31 36 2C 20 69 6F *14.0: irq 16, io* 00000240: 20 6D 65 6D 20 30 78 66-37 63 30 30 30 30 30 0A * mem 0xf7c00000.* 00000250: 3C 37 3E 5B 20 20 20 20-30 2E 35 30 33 30 35 37 *<7>[ 0.503057* 00000260: 5D 20 78 68 63 69 5F 68-63 64 20 30 30 30 30 3A *] xhci_hcd 0000:* 00000270: 30 30 3A 31 34 2E 30 3A-20 69 72 71 20 34 31 20 *00:14.0: irq 41 * 00000280: 66 6F 72 20 4D 53 49 2F-4D 53 49 2D 58 0A 3C 36 *for MSI/MSI-X.<6* 00000290: 3E 5B 20 20 20 20 30 2E-35 30 33 30 39 33 5D 20 *>[ 0.503093] * 000002A0: 75 73 62 20 75 73 62 33-3A 20 4E 65 77 20 55 53 *usb usb3: New US* 000002B0: 42 20 64 65 76 69 63 65-20 66 6F 75 6E 64 2C 20 *B device found, * 000002C0: 69 64 56 65 6E 64 6F 72-3D 31 64 36 62 2C 20 69 *idVendor=1d6b, i* 000002D0: 64 50 72 6F 64 75 63 74-3D 30 30 30 32 0A 3C 36 *dProduct=0002.<6* 000002E0: 3E 5B 20 20 20 20 30 2E-35 30 33 34 37 32 5D 20 *>[ 0.503472] * 000002F0: 75 73 62 20 75 73 62 33-3A 20 4E 65 77 20 55 53 *usb usb3: New US* 00000300: 42 20 64 65 76 69 63 65-20 73 74 72 69 6E 67 73 *B device strings* 00000310: 3A 20 4D 66 72 3D 33 2C-20 50 72 6F 64 75 63 74 *: Mfr=3, Product* 00000320: 3D 32 2C 20 53 65 72 69-61 6C 4E 75 6D 62 65 72 *=2, SerialNumber* 00000330: 3D 31 0A 3C 36 3E 5B 20-20 20 20 30 2E 35 30 33 *=1.<6>[ 0.503* 00000340: 38 34 34 5D 20 75 73 62-20 75 73 62 33 3A 20 50 *844] usb usb3: P* 00000350: 72 6F 64 75 63 74 3A 20-78 48 43 49 20 48 6F 73 *roduct: xHCI Hos* 00000360: 74 20 43 6F 6E 74 72 6F-6C 6C 65 72 0A 3C 36 3E *t Controller.<6>* 00000370: 5B 20 20 20 20 30 2E 35-30 34 32 30 39 5D 20 75 *[ 0.504209] u* 00000380: 73 62 20 75 73 62 33 3A-20 4D 61 6E 75 66 61 63 *sb usb3: Manufac* 00000390: 74 75 72 65 72 3A 20 4C-69 6E 75 78 20 33 2E 33 *turer: Linux 3.3* 000003A0: 2E 36 2D 33 2E 66 63 31-37 2E 78 38 36 5F 36 34 *.6-3.fc17.x86_64* 000003B0: 20 78 68 63 69 5F 68 63-64 0A 3C 36 3E 5B 20 20 * xhci_hcd.<6>[ * 000003C0: 20 20 30 2E 35 30 34 35-38 31 5D 20 75 73 62 20 * 0.504581] usb * 000003D0: 75 73 62 33 3A 20 53 65-72 69 61 6C 4E 75 6D 62 *usb3: SerialNumb* 000003E0: 65 72 3A 20 30 30 30 30-3A 30 30 3A 31 34 2E 30 *er: 0000:00:14.0* 000003F0: 0A 3C 37 3E 5B 20 20 20-20 30 2E 35 30 34 39 38 *.<7>[ 0.50498*
We have to look inside the Linux kernel, specifically …/drivers/firmware/efivars.c, to understand where these UEFI NV (non volatile) variables are being created. The appropriate code is compiled into the Linux kernel, if the kernel is build with CONFIG_PSTORE. The first component of the variable name is always CFC8FC79-BE2E-4DDC-97F0-9F98BFE298A0 which is a GUID defined as LINUX_EFI_CRASH_GUID. The second component is a type designation:
enum pstore_type_id { PSTORE_TYPE_DMESG = 0, PSTORE_TYPE_MCE = 1, PSTORE_TYPE_UNKNOWN = 255 };
The third component is just a sequential number and the final component is the current time in seconds returned from the kernel’s get_secondsfunction.
Tony Luck, author of pstore, writes about pstore in this LWN article.
Some platforms have a small amount of non-volatile storage that can be used to store information useful to diagnose the cause of a system crash. This is the generic part of a file system interface that presents information from the crash as a series of files in
/dev/pstore. Once the information has been seen, the underlying storage is freed by deleting the files.
You can also delete these NV variables when in the EFI shell because the NV variable attributes are set to
(EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS)
Here is a simple EFI application which will erase all the pstore-created NV variables:
#include <efi.h> #include <efilib.h> #define LINUX_EFI_CRASH_GUID \ (EFI_GUID) { 0xcfc8fc79, 0xbe2e, 0x4ddc, { 0x97, 0xf0, 0x9f, 0x98, 0xbf, 0xe2, 0x98, 0xa0 } } #define PSTORE_EFI_ATTRIBUTES \ (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS) EFI_STATUS efi_main (EFI_HANDLE image, EFI_SYSTEM_TABLE *systab) { EFI_STATUS status = EFI_SUCCESS; CHAR16 name[256], *val; EFI_GUID curGuid= NullGuid; UINTN size; UINTN valsize = 100; EFI_GUID CrashGuid = LINUX_EFI_CRASH_GUID ; InitializeLib(image, systab); name[0] = 0; while (1) { size = sizeof(name); status = uefi_call_wrapper(RT->GetNextVariableName, 3, &size, name, &curGuid); if (status != EFI_SUCCESS) break; val = LibGetVariable(name, &curGuid); if (!CompareGuid( &curGuid, &CrashGuid)) { status = uefi_call_wrapper(RT->SetVariable, 5, &name, &curGuid, PSTORE_EFI_ATTRIBUTES, 0, NULL); if (status != EFI_SUCCESS) { Print(L"ERROR: SetVariable failed: %d\n", status); } } FreePool(val); } return status; }
and here is a suitable Makefile for compiling it on Fedora 17:
SRCDIR = . PREFIX := /usr HOSTARCH = $(shell uname -m | sed s,i[3456789]86,ia32,) ARCH := $(shell uname -m | sed s,i[3456789]86,ia32,) INCDIR = -I. CPPFLAGS = -DCONFIG_$(ARCH) CFLAGS = $(ARCH3264) -g -O0 -fpic -Wall -fshort-wchar -fno-strict-aliasing -fno-merge-constants --std=gnu99 -D_GNU_SOURCE ASFLAGS = $(ARCH3264) LDFLAGS = -nostdlib INSTALL = install CC = gcc AS = as LD = ld.bfd AR = ar RANLIB = ranlib OBJCOPY = objcopy ifeq ($(ARCH), ia32) LIBDIR := $(PREFIX)/lib ifeq ($(HOSTARCH), x86_64) ARCH3264 := -m32 endif endif ifeq ($(ARCH), x86_64) CFLAGS += -mno-red-zone LIBDIR := $(PREFIX)/lib64 ifeq ($(HOSTARCH), ia32) ARCH3264 := -m64 endif endif FORMAT=efi-app-$(HOSTARCH) LDFLAGS = -nostdlib -T $(LIBDIR)/gnuefi/elf_$(HOSTARCH)_efi.lds -shared -Bsymbolic $(LIBDIR)/gnuefi/crt0-efi-$(HOSTARCH).o -L$(LIBDIR) LIBS=-lefi -lgnuefi $(shell $(CC) -print-libgcc-file-name) CCLDFLAGS = CFLAGS = -I/usr/include/efi/ -I/usr/include/efi/$(HOSTARCH)/ -I/usr/include/efi/protocol -fpic -fshort-wchar -fno-reorder-functions -fno-strict-aliasing -fno-merge-constants -mno-red-zone -Wimplicit-function-declaration TARGETS = cer.efi all : $(TARGETS) clean : @rm -rf *.o *.a *.so $(TARGETS) .PHONY: all clean install %.efi : %.so $(OBJCOPY) -j .text -j .sdata -j .data -j .dynamic -j .dynsym -j .rel \ -j .rela -j .reloc --target=$(FORMAT) $*.so $@ %.so: %.o $(LD) $(LDFLAGS) -o $@ $^ $(LIBS) %.o: %.c $(CC) $(INCDIR) $(CFLAGS) $(CPPFLAGS) -D__UEFI__ -c $< -o $@ %.S: %.c $(CC) $(INCDIR) $(CFLAGS) $(CPPFLAGS) -D__UEFI__ -S $< -o $@ %.E: %.c $(CC) $(INCDIR) $(CFLAGS) $(CPPFLAGS) -D__UEFI__ -E $< -o $@
This is not the same as the mechanism detailed in Appendix P of the latest UEFI Specification for dealing with Hardware Error Records. These NV variables are named HwErrRec0001, HwErrRec0002, and so on. Such records are not generated unless the NV variable HwErrRecSupport is defined. By the way, hardware error records support is optional.
The next release or two of Fedora are going to be very interesting as far as UEFI support is concerned. To a certain extent, UEFI support in forthcoming versions of Fedora will be dictated by the actions of Microsoft. For example, it is planned to add support for SecureBoot to Fedora 18 because Microsoft Windows 8 will require it.