Grub-Install Ubuntu | How to Install GRUB2 with EFI Support


Purpose

This document outlines a reference procedure for installing the GRUB2 bootloader with UEFI support built by the Desktop factory to a boot device for the target board.

Prerequisitesubuntu 14.04

  • x86 Host Machine
    • Note: For 64-bit targets, you must have a 64-bit host OS.
  • x86 Target Machine
  • Desktop Factory with the following options enabled:
    • bash (needed for chroot)
    • grep (needed for grub-install)
    • ncurses
    • Target Software->Kernel->Include kernel image within the RFS

Procedure

Build GRUB2 with EFI Support

  1. Open your Desktop Factory configuration interface:
    $ make menuconfig
  2. Navigate to "Target Software->Bootloaders->GRUB2..."
  3. Set "grub2 Platform String" to efi.
  4. Save your configuration.
  5. Remove your existing grub2 build:
    $ make grub2-distclean
  6. Rebuild the Factory:
    $ make

Attach volume to host machine

If you are using USB stick, Compact Flash, SD, or hard drive, connect it to the host. Determine the device node using dmesg, and unmount any volumes that auto-mount. For the purposes of this document, we assume /dev/sdX is the name of the disk.

Create a Linux partition on the device for the RFS.

  1. Create a Linux partition for the RFS using fdisk.
    $ sudo fdisk /dev/sdX
    • Type o to create a new partition table.
    • Create the EFI Partition.
      • Type n to create a new partition.
      • Type p to select a primary partition type.
      • Set Partition Number to 1.
      • Accept the default value for First Sector.
      • Set the Last Sector to +50M.
      • Type t to set the partition type.
      • Type c to set the partition type to W95 FAT32 (LBA).
    • Create the RFS Partition.
      • Type n to create a new partition.
      • Type p to select a primary partition type.
      • Set Partition Number to 2.
      • Accept the defaults for First Sector and Last Sector.
    • Type w to write the new partition table.
  2. Format the EFI partition using mkfs.vfat:
    $ sudo mkfs.vfat -n "efi" /dev/sdX1
  3. Format the RFS partition using mkfs.ext4:
    $ sudo mkfs.ext4 -L "rfs" /dev/sdX2

Initialize the RFS contents

  1. Mount the volume:
    $ sudo mount -t ext4 /dev/sdX2 /rfs
  2. Change to the mounted directory:
    $ cd /rfs
  3. As root, extract the RFS output tarball into the mount point:
    $ sudo tar -xf /path/to/factory/build_*/images/rfs/rootfs.tar.gz
  4. Copy the kernel to the volume and rename it to vmlinuz for autodetection:
    $ sudo mkdir -p boot/
    $ sudo cp /path/to/factory/build_*/images/bzImage-<version> boot/vmlinuz-<version>
    

Set up the EFI Partition

We will be doing most of the EFI setup from within our chroot. However, we still need to mount the volume:

$ sudo mount /dev/sdX1 /efi

Use chroot to install grub to the device

  1. Enter the RFS directory:
    $ cd /rfs
  2. Create the EFI directory under boot:
    $ sudo mkdir -p boot/efi
  3. Bind mount the /dev, /sys, and /proc directories. This allows you to access your system from the chroot jail.
    $ sudo mount --bind /dev ./dev
    $ sudo mount --bind /sys ./sys
    $ sudo mount --bind /proc ./proc
    
  4. Bind mount the your EFI mount point directory:
    $ sudo mount --bind /efi ./boot/efi
  5. Enter the chroot jail:
    32-bit Target
    $ sudo linux32 chroot .

    64-bit Target
    $ sudo linux64 chroot .
  6. Install grub to your Linux partition
    32-bit Target
    # grub-install --target=i386-efi --efi-directory=/boot/efi --removable --boot-directory=
    /boot/efi/EFI --bootloader-id=grub /dev/sdX

    64-bit Target
    # grub-install --target=x86_64-efi --efi-directory=/boot/efi --removable --boot-directory
    =/boot/efi/EFI --bootloader-id=grub /dev/sdX

The --removable flag prevents the efibootmgr application from running on your host machine if it is present in your filesystem. Otherwise, it would modify your host's EFI partition, which is undesirable.

Create a grub.cfg file under /boot/grub

Note: In order for grub-mkconfig to automatically detect the kernel image, it must be named renamed vmlinuz-<version>. Otherwise you can manually add the menuentry pointing to bzImage.

# grub-mkconfig -o /boot/efi/EFI/grub/grub.cfg

Exit chroot and unmount dev, sys, and proc

# exit
$ sudo umount ./dev
$ sudo umount ./sys
$ sudo umount ./proc
$ sudo umount ./boot/efi

Cleanup grub.cfg

At this point you should edit the grub.cfg to set the root device correctly. Due to the bind mounted device tree, the generated grub.cfg will specify the wrong root.

  1. Open the grub.cfg file, found at /efi/EFI/grub/grub.cfg.
  2. Find the line that sets the root device, typically in the menuentry option:
    set root='hd1,msdos2'
  3. Edit the line to correspond with the second partition of the first hard drive:
    set root='hd0,msdos2'
  4. If you are not using an initrd, you should modify your kernel command line options to boot from the proper device. You may also add additional boot arguments to your kernel command line.
    linux   /boot/vmlinuz-3.4-ts-i686 root=/dev/sda2 rw video=vesafb vga=0x318 vmalloc=256MB 
    console=ttyS0,115200

(OPTIONAL) Add a manual menu-entry to grub.cfg

If your kernel was not autodetected, or if you simply want to add an additional boot entry, you can manually edit the grub.cfg.

  1. Enter an entry like this between the 10_linux lines:
    ### BEGIN /etc/grub.d/10_linux ###
    menuentry 'Timesys' --class gnu-linux --class gnu --class os {
       linux /bzImage <kernel-arguments>
    }
    ### END /etc/grub.d/10_linux ###
    

Create startup.nsh script

The EFI shell runs a script at boot time called startup.nsh. We should create this file in the root of the /efi partition

  1. Create the file startup.nsh and open it in your editor of choice.
  2. Add the following contents to it:
    For 32-bit targets
    FS0:
    cd \efi\grub
    boot.efi
    

    For 64-bit targets
    FS0:
    cd \efi\grub\x86_64-efi
    grub.efi
    
  3. Copy the file to the root of your /efi partition:
    $ sudo cp startup.nsh /efi/

Clean up

  1. Leave the RFS partition:
    $ cd /
  2. Unmount the RFS partition:
    $ sudo umount /rfs
  3. Unmount the EFI partition:
    $ sudo umount /efi
  4. Remove the hard drive from your system, and attach it to the target system.
  5. 4.1 Installing GRUB using grub-install

    For information on where GRUB should be installed on PC BIOS platforms, see BIOS installation.

    In order to install GRUB under a UNIX-like OS (such as GNU), invoke the program grub-install (see Invoking grub-install) as the superuser (root).

    The usage is basically very simple. You only need to specify one argument to the program, namely, where to install the boot loader. The argument has to be either a device file (like ‘/dev/hda’). For example, under Linux the following will install GRUB into the MBR of the first IDE disk:

    # grub-install /dev/sda
    

    Likewise, under GNU/Hurd, this has the same effect:

    # grub-install /dev/hd0
    

    But all the above examples assume that GRUB should put images under the /boot directory. If you want GRUB to put images under a directory other than /boot, you need to specify the option --boot-directory. The typical usage is that you create a GRUB boot floppy with a filesystem. Here is an example:

    # mke2fs /dev/fd0
    # mount -t ext2 /dev/fd0 /mnt
    # mkdir /mnt/boot
    # grub-install --boot-directory=/mnt/boot /dev/fd0
    # umount /mnt
    

    Some BIOSes have a bug of exposing the first partition of a USB drive as a floppy instead of exposing the USB drive as a hard disk (they call it “USB-FDD” boot). In such cases, you need to install like this:

    # losetup /dev/loop0 /dev/sdb1
    # mount /dev/loop0 /mnt/usb
    # grub-install --boot-directory=/mnt/usb/bugbios --force --allow-floppy /dev/loop0
    

    This install doesn’t conflict with standard install as long as they are in separate directories.

    On EFI systems for fixed disk install you have to mount EFI System Partition. If you mount it at /boot/efi then you don’t need any special arguments:

    # grub-install
    

    Otherwise you need to specify where your EFI System partition is mounted:

    # grub-install --efi-directory=/mnt/efi
    

    For removable installs you have to use --removable and specify both --boot-directory and --efi-directory:

    # grub-install --efi-directory=/mnt/usb --boot-directory=/mnt/usb/boot --removable
    
     
Next Post Previous Post
No Comment
Add Comment
comment url