You are on page 1of 7

UEFI Booting Fedora 17

UEFI Booting Fedora 17


Finnbarr P. Murphy
(fpm@fpmurphy.com) 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:

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 #cd ../grub2; ls -R .: themes ./themes: system

Fo r

07-13-2012

pe rs o

< -- used by GRUB 0.97 EFI,

Copyright 2004-2012 Finnbarr P. Murphy. All rights reserved.

nn a

lu

$ df -h Filesystem rootfs devtmpfs tmpfs tmpfs /dev/sda3 tmpfs tmpfs /dev/sda5 /dev/sda2 /dev/sda1

Size 50G 7.8G 7.8G 7.8G 50G 7.8G 7.8G 398G 497M 200M

Used Avail Use% Mounted on 5.6G 42G 12% / 0 7.8G 0% /dev 96K 7.8G 1% /dev/shm 1.3M 7.8G 1% /run 5.6G 42G 12% / 0 7.8G 0% /sys/fs/cgroup 0 7.8G 0% /media 6.2G 372G 2% /home 74M 399M 16% /boot 27M 173M 14% /boot/efi

se
1/7

on

ly

UEFI Booting Fedora 17 ./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

CONFIG_EFI=y CONFIG_EFI_VARS=y

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.

Fo r

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.

07-13-2012

pe rs o

The EFI Boot Stub ---------------------------

Copyright 2004-2012 Finnbarr P. Murphy. All rights reserved.

nn a

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.

lu

se

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:

on

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.

ly

2/7

UEFI Booting Fedora 17 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,

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:

Fo r

q q q q

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 drwx------ 3 root -rwx------ 1 root -rwx------ 1 root -rwx------ 1 root -rwx------ 1 root

pe rs o

-l root 4096 May 20 01:36 root 17432458 May 23 21:49 root 214 May 26 12:14 root 1240192 May 26 22:53 root 4664080 May 23 21:49

07-13-2012

Copyright 2004-2012 Finnbarr P. Murphy. All rights reserved.

nn a

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.

lu

fs0:\Kernels> bzImage.efi initrd=\Kernels\initrd-large.img

EFI initramfs-3.3.6-3.fc17.x86_64.img f17.nsh Shell.efi vmlinuz-3.3.6-3.fc17.x86_64.efi

se
3/7

on

ly

UEFI Booting Fedora 17

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:

Fo r

# 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\g rub.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-lin ux.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.

07-13-2012

pe rs o

Copyright 2004-2012 Finnbarr P. Murphy. All rights reserved.

nn a

lu

The efibootmgr utility can be used to change the UEFI boot variables, i.e. Timeout,BootOrder, and the BootXXXX variables.

se

Turning now to related UEFI topic, let us examine what UEFI-related information is available or modifiable from within F17.

on

EFI shell scripts have to have an extension of .nsh, i.e new shell script. To boot F17, I then simply type f17.

ly

# 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=.\in itramfs-3.3.6-3.fc17.x86_64.img

4/7

UEFI Booting Fedora 17 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.

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 :

Fo r

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. #include <efi.h> #include <efilib.h> #define LINUX_EFI_CRASH_GUID \ (EFI_GUID) { 0xcfc8fc79, 0xbe2e, 0x4ddc, { 0x97, 0xf0, 0x9f, 0x98, 0xbf, 0xe2, 0x98, 0x a0 } } #define PSTORE_EFI_ATTRIBUTES \ (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACC

07-13-2012

pe rs o

Copyright 2004-2012 Finnbarr P. Murphy. All rights reserved.

nn a

# 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.869252] [ 0.871917] Pid: 1, comm: swapper/0 Not tainted 3.3.6-3.fc17.x86_64 #1 [ 0.872804] Call Trace: [ 0.873678] [] panic+0xba/0x1c6 [ 0.874551] [] ? printk_all_partitions+0x259/0x26b [ 0.875430] [] __stack_chk_fail+0x1b/0x20 [ 0.876306] [] printk_all_partitions+0x259/0x26b [ 0.877170] [] mount_block_root+0x1bc/0x27f [ 0.878015] [] mount_root+0x57/0x5b [ 0.878843] [] prepare_namespace+0x13d/0x176 [ 0.879660] [] kernel_init+0x155/0x15a [ 0.880477] [] ? schedule_tail+0x27/0xb0 [ 0.881286] [] kernel_thread_helper+0x4/0x10 [ 0.882082] [] ? start_kernel+0x3c5/0x3c5 [ 0.882868] [] ? gs_change+0x13/0x13

lu

se

on

ly
5/7

UEFI Booting Fedora 17 ESS) 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, &amp;size, name, &amp;curGuid); if (status != EFI_SUCCESS) break; val = LibGetVariable(name, &amp;curGuid); if (!CompareGuid( &amp;curGuid, &amp;CrashGuid)) { status = uefi_call_wrapper(RT->SetVariable, 5, &amp;name, &amp;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-mergeconstants --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)

Fo r

07-13-2012

pe rs o

Copyright 2004-2012 Finnbarr P. Murphy. All rights reserved.

nn a

lu

se

on

ly

6/7

UEFI Booting Fedora 17 LDFLAGS = -nostdlib -T $(LIBDIR)/gnuefi/elf_$(HOSTARCH)_efi.lds -shared -Bsymbolic $(LIBDI R)/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-r ed-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 $@

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.

Fo r

07-13-2012

pe rs o

Copyright 2004-2012 Finnbarr P. Murphy. All rights reserved.

nn a

lu

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.

se

on

ly

7/7