Skip site navigation (1)Skip section navigation (2)

  
 
  

home | help
LOADER.EFI(8)		     System Manager's Manual		   LOADER.EFI(8)

NAME
     loader.efi -- UEFI kernel loader

DESCRIPTION
     On UEFI systems, loader.efi loads the kernel.

     boot1.efi(8)  is  used to load loader.efi when it is placed within a UFS or
     ZFS file system.  Alternatively, loader.efi is used directly  when  config-
     ured  with  efibootmgr(8), or when placed directly as the default boot pro-
     gram as described in uefi(8).  When a system is built using  bsdinstall(8),
     loader.efi will be used directly.

   Console Considerations
     The EFI BIOS provides a generic console.  In loader.efi this is selected by
     specifying  "efi"	using  the  console  variable.	 loader.efi examines the
     8be4df61-93ca-11d2-aa0d-00e098032b8c-ConOut UEFI  environment  variable  to
     guess what the "efi" console points to.  loader.efi will output its prompts
     and menus to all the places specified by ConOut.  However, the FreeBSD ker-
     nel  has  a  limitation  when more than one console is present.  The kernel
     outputs to all configured consoles.  Only the primary console will get  the
     log  messages  from  the  rc(8) system, and prompts for things like geli(8)
     passwords.  If loader.efi finds a video device first, then loader.efi tells
     the kernel to use the video console as primary.  Likewise, if a serial  de-
     vice  is first in the ConOut list, the serial port will be the primary con-
     sole.

     If there is no ConOut  variable,  both  serial  and  video  are  attempted.
     loader.efi uses the "efi" console for the video (which may or may not work)
     and "comconsole" for the serial on COM1 at the default baud rate.	The ker-
     nel  will	use  a	dual  console,	with the video console primary if a UEFI
     graphics device is detected, or the serial console as primary if not.

     On x86 platforms, if you wish to redirect the loader's output to  a  serial
     port  when  the EFI BIOS doesn't support it, or to a serial port that isn't
     the one the EFI BIOS redirects its output to, set console to  "comconsole".
     The  default port is COM1 with an I/O address of 0x3f8.  comconsole_port is
     used to set this to a different port address.  comconsole_speed is used  to
     set  the of the serial port (the default is 9600).  If you have console set
     to "efi,comconsole" you will get output on both the EFI console and the se-
     rial port.  If this causes a doubling of characters, set console to  "efi",
     since your EFI BIOS is redirecting to the serial port already.

     If your EFI BIOS redirects the serial port, you may need to tell the kernel
     which address to use.  EFI uses ACPI's UID to identify the serial port, but
     loader.efi  does  not  have an ACPI parser, so it cannot convert that to an
     I/O port.	The FreeBSD kernel initializes its consoles before it can decode
     ACPI resources.  The FreeBSD kernel will look at the hw.uart.console  vari-
     able  to set its serial console.  Its format should be described in uart(4)
     but is not.  Set it to "io:0x3f8,br:115200" with the proper  port	address.
     PCI or memory mapped ports are beyond the scope of this man page.

     The serial ports are assigned as follows on IBM PC compatible systems:

	   Windows Name    I/O Port Address    Typical FreeBSD device
	   COM1 	   0x3f8	       /dev/uart0
	   COM2 	   0x2f8	       /dev/uart1
	   COM3 	   0x3e8	       /dev/uart2
	   COM4 	   0x2e8	       /dev/uart3
     Though COM3 and COM4 can vary.

   Primary Console
     The  primary console is set using the boot flags.	These command line argu-
     ments set corresponding flags for the kernel.   These  flags  can	be  con-
     trolled  by  setting  loader  environment variables to "yes" or "no".  Boot
     flags may be set on the command line to the boot command.	Inside the  ker-
     nel,  the	RB_  flags  are used to control behavior, sometimes in architec-
     turally specific ways and are included to aid in discovery of any	behavior
     not covered in this document.

	   boot flag	loader variable    Kernel RB_ flag
	   -a		boot_askme	   RB_ASKNAME
	   -c		boot_cdrom	   RB_CDROM
	   -d		boot_ddb	   RB_KDB
	   -r		boot_dfltroot	   RB_DFLTROOT
	   -D		boot_multiple	   RB_MULTIPLE
	   -m		boot_mute	   RB_MUTE
	   -g		boot_gdb	   RB_GDB
	   -h		boot_serial	   RB_SERIAL
	   -p		boot_pause	   RB_PAUSE
	   -P		boot_probe	   RB_PROBE
	   -s		boot_single	   RB_SINGLE
	   -v		boot_verbose	   RB_VERBOSE
     And the following flags determine the primary console:

	   Flags    Kernel Flags    Kernel Consoles    Primary Console
	   none     0		    Video	       Video
	   -h	    RB_SERIAL	    Serial	       Serial
	   -D	    RB_MULTIPLE     Serial, Video      Video
	   -Dh	    RB_SERIAL | RB_MULTIPLE	       Serial, Video	  Serial

     loader.efi  does  not implement the probe -P functionality where we use the
     video console if a keyboard is connected and a serial console otherwise.

   Additional Environment Variables
     loader.efi   loads   some	 extra	 variables   early   in   startup   from
     /efi/freebsd/loader.env  from the EFI partition.  Only simple variables can
     be set here.  It can be useful to specify the root filesystem:

	   rootdev=disk0s1a

   Staging Slop
     The kernel must parse the firmware memory map tables to know what memory it
     can use.  Since it must allocate memory  to  do  this,  loader.efi  ensures
     there's  extra  memory  available, called "slop", after everything it loads
     (the kernel, modules and metadata) for the kernel to bootstrap  the  memory
     allocator.

     By default, amd64 reserves 8MB.  The staging_slop command allows for tuning
     the slop size.  It takes a single argument, the size of the slop in bytes.

   amd64 Nocopy
     loader.efi  will load the kernel into memory that is 2MB aligned below 4GB.
     It cannot load to a fixed address because the UEFI firmware may reserve ar-
     bitrary memory for its use at runtime.  Prior to FreeBSD 13.1, kernels  re-
     tained  the old BIOS-boot protocol of loading at exactly 2MB.  Such kernels
     must be copied from their loaded location to 2MB prior  starting  them  up.
     The  copy_staging command is used to enable this copying for older kernels.
     It takes a single argument which can be one of

     disable  Force-disable copying staging area to 2M.

     enable   Force-enable copying staging area to 2M.

     auto     Selects the behaviour based on the kernel's capability  of  boost-
	      raping  from  non-2M physical base.  The kernel reports this capa-
	      bility by exporting the symbol kernphys.

     Arm64 loaders have operated in the `nocopy' mode from their  inception,  so
     there  is	no copy_staging command on that platform.  Riscv, 32-bit arm and
     arm64 have always loaded at any 2MB aligned location,  so	do  not  provide
     copy_staging.

	   Note. BIOS loaders on i386 and amd64 put the staging area starting at
	   the physical address 2M, then enable paging with identical mapping
	   for the low 1G.  The initial port of loader.efi followed the same
	   scheme for handing control to the kernel, since it avoided modifica-
	   tions for the loader/kernel hand-off protocol, and for the kernel
	   page table bootstrap.

	   This approach is incompatible with the UEFI specification, and as a
	   practical matter, caused troubles on many boards, because UEFI
	   firmware is free to use any memory for its own needs.  Applications
	   like loader.efi must only use memory explicitly allocated using boot
	   interfaces.	The original way also potentially destroyed UEFI runtime
	   interfaces data.

	   Eventually, loader.efi and the kernel were improved to avoid this
	   problem.

   amd64 Faults
     Because  it executes in x86 protected mode, the amd64 version of loader.efi
     is susceptible to CPU faults due to programmer mistakes and memory  corrup-
     tion.   To  make debugging such faults easier, amd64 loader.efi can provide
     detailed reporting of the CPU state at the time of the fault.

     The grab_faults command installs a handler for faults directly in the  IDT,
     avoiding  the  use of the UEFI debugging interface EFI_DEBUG_SUPPORT_PROTO-
     COL.RegisterExceptionCallback().  That interface is left available for  ad-
     vanced  debuggers in the UEFI environment.  The ungrab_faults command tries
     to deinstall the fault handler, returning TSS and IDT CPU tables  to  their
     pre-installation  state.	The  fault  command  produces  a  fault  in  the
     loader.efi environment for testing purposes, by executing the ud2 processor
     instruction.

FILES
     /boot/loader.efi  The location of the UEFI kernel loader within the system.

   EFI System Partition
     loader.efi is installed on the ESP (EFI System Partition)	in  one  of  the
     following locations:

     efi/boot/bootXXX.efi    The  default  location  for  any  EFI  loader  (see
			     uefi(8) for values to replace `XXX' with).

     efi/freebsd/loader.efi  The location reserved specifically for the  FreeBSD
			     EFI loader.

     The default location for the ESP mount point is documented in hier(7).

EXAMPLES
   Updating loader.efi on the ESP
     The  following  example  shows  how to install a new loader.efi on the ESP.
     The exact placement is complicated due to the diversity  of  installations,
     setups  and situations.  In this section, paths that are all lower case are
     Unix paths.  Paths that are all upper case are relative to  the  ESP  mount
     point,  though they may appear as lower case on your system because the FAT
     filesystem of the ESP is case insensitive.

     Locate the ESP, which has its own partition type of "efi":

	   # gpart show nda0
	   =>	     40  7501476448  nda0  GPT	(3.5T)
		     40      614400	1  efi	(300M)
		 614440  7500862048	2  freebsd-zfs	(3.5T)

     The name of the ESP on this system is nda0p1.  By	default,  this	will  be
     mounted on /boot/efi.  To check:

	   # mount | grep nda0p1
	   /dev/nda0p1 on /boot/efi (msdosfs, local)
     If it's not mounted, you will need to mount it:

	   # mount -t msdosfs /dev/nda0p1 /boot/efi

     efibootmgr(8) reports what we booted from.

	   # efibootmgr -v
	   Boot to FW : false
	   BootCurrent: 0001
	   Timeout    : 2 seconds
	   BootOrder  : 0000, 0001, 0003, 0004, 0005, 0006, 0001, 0008, 000A, 000B, 000C, 000E, 0007
	   ...
	   +Boot0001* FreeBSD ZPOOL HD(1,GPT,b5d0f86b-265d-1e1b-18aa-0ed55e1e73bd,0x28,0x96000)/File(EEBSDDER.EFI)
				       nda0p1:/EFI/FREEBSD/LOADER.EFI /boot/efi//EFI/FREEBSD/LOADER.EFI
	   ...
     Often  there are several options, depending on the BIOS.  The entry that we
     booted with is marked with a `+' at the start of the line, as shown  above.
     So  in  this  case, this firmware is using /EFI/FREEBSD/LOADER.EFI from the
     ESP.  Often times it will be the UEFI "default" loader, which varies by ar-
     chitecture.

	   Architecture    Default Path
	   amd64	   /EFI/BOOT/BOOTX64.EFI
	   arm		   /EFI/BOOT/BOOTARM.EFI
	   arm64	   /EFI/BOOT/BOOTAA64.EFI
	   i386 	   /EFI/BOOT/BOOTIA32.EFI
	   riscv	   /EFI/BOOT/BOOTRISCV64.EFI
     However, care must be taken: some multiple-boot environments rely on a spe-
     cial bootXXX.efi to function.  Before updating  a	bootXXX.efi  file,  make
     sure it is the FreeBSD boot loader before updating it:

	   # strings /boot/efi/EFI/BOOT/BOOTX64.EFI | grep FreeBSD | grep EFI
	   FreeBSD/amd64 EFI loader, Revision 3.0

     bsdinstall(8)  copies  loader.efi	to  the default name if there wasn't one
     there before.  Check to see if they are copies before  updating  (with  X64
     substituted using the above table):

	   # cmp /boot/efi/EFI/FREEBSD/LOADER.EFI /boot/efi/EFI/BOOT/BOOOTX64.EFI
     Copy the loader:

	   # cp /boot/loader.efi /boot/efi/EFI/FREEBSD/LOADER.EFI
     replacing the all caps part of the example with the proper path.

     If  ESP  path  was  /FREEBSD/LOADER.EFI and LOADER.EFI and BOOTX64.EFI were
     identical in the cmp step, copy the loader to the default location:

	   # cp /boot/loader.efi /boot/efi/EFI/BOOT/BOOTX64.EFI

     Finally, if you mounted the ESP, you may wish to unmount it.

	   # umount /boot/efi

SEE ALSO
     loader(8), uefi(8)

BUGS
     Non-x86 serial console handling is even more confusing and less well  docu-
     mented.

     Sometimes	when the serial port speed isn't set, 9600 is used.  Other times
     the result is typically 115200 since the speed remains unchanged  from  the
     default.

     U-Boot implements a subset of the UEFI standard.  Some versions do not sup-
     port  fetching  loader variables, so efibootmgr may not work.  In addition,
     efibootmgr is not supported on armv7 or riscv.   In  these  instances,  the
     user  has	to understand what was booted to update it properly (and in most
     cases, it will be the FreeBSD path  and  the  UEFI  default  so  just  copy
     loader.efi  there if there are loaders there).  Typically in these embedded
     situations,  there  is  only  one	.efi  file  (loader.efi  or  a	copy  of
     loader.efi).  The path to this file is typically the default removable path
     above.

     Managing  booting	multiple  OSes	on UEFI varies greatly, so extra caution
     when updating the UEFI default loader.

     The old, now obsolete, boot1.efi was installed as bootx64.efi in FreeBSD 10
     and earlier.  Since it was quite limited in functionality, we created  very
     small  ESPs by default.  A modern loader.efi will not fit.  However, if the
     old boot1.efi still works, there's no need to update it since it will chain
     boot /boot/loader.efi from a copy that make installworld updates.

FreeBSD 14.3			September 3, 2024		   LOADER.EFI(8)

Want to link to this manual page? Use this URL:
<https://man.freebsd.org/cgi/man.cgi?query=loader.efi&sektion=8&manpath=FreeBSD+14.3-RELEASE>

home | help