TongXu-Server

Grub

GRUB

  • GRUB(Grand Unified Bootloader)大统一加载器,是一个引导加载程序,当前为GRUB2。原始的GRUB被称为GRUB Legacy。

    • grub捆绑了由自己支持的多种文件系统,btrfs、ext4、FAT32、XFS。
    • 使用一个单独的/boot分区,可以规避大部分不兼容问题。
  • UEFI

    • 使用UEFI安装时,一定要让安装介质以UEFI启动,否则efibootmgr无法添加GRUB UEFI启动项。

      • 要从一个磁盘上使用UEFI启动,必须有一个efi分区。
      • GRUB能够通过insmod加载额外模块,这时候UEFI无法使用安全启动Secure Boot。
      • 使用了安全启动,要使用grub额外模块,必须通过grub-mkstandalone、grub-install重新安装GRUB,以生成包含所需模块的grubx64.efi
    • 安装

      • 安装grub 、efibootmgr包,efibootmgr用于grub脚本用来将启动项写入NVROM。

      • 挂载efi系统分区:选择一个启动引导器标识例如ARCH、GRUB等,将在esp/EFI/中创建一个与标识同名的目录来存储EFI二进制文件。而且这个名字还会用于UEFI启动菜单中区分GRUB启动项。

      • 执行下面命令将GRUB EFI应用grubx64.efi安装到esp/EFI/GRUB/,并将其模块安装到/boot/grub/x86_64-efi/

        #需要在chroot之后再运行grub-install
        #否则需要使用--boot-directory=选项来制定挂载/boot目录的路径,如--boot-directory=/mnt/boot
        
        grub-install --target=x86_64-efi --efi-directory=esp --bootloader-id=GRUB
        
        #如果固件启动器数量已满,这个命令会失败,需要使用efibootmgr删除不必要的条目
        
      • 如果使用–removable选项,那GRUB将会被安装到esp/EFI/BOOT/BOOTX64.EFI,此时即使EFI变量被重设或这你把这个驱动器连接到其他电脑上,你仍可以从这个驱动器上启动。

    • 启用安全启动

      • GRUB支持CA密钥或者shim进行安全启动。

      • CA

        grub-intall --target=x86_64-efi --efi-directory=sep --bootloader-id=GRUB --modules="tpm" --disabel-shim-lock
        
      • Shim-lock

        • 当使用shim-lock时,只有GRUB二进制文件包含了全部用于读取含有vmlinuxz和initramfs镜像的文件系统的必要模块时,才可以成功进入安全启动模式。

        • 安全启动模式下,不允许使用insmod加载模块。

        • 根据ubuntu的官方构建脚本,整合下列模块

          1. 基础模块

            all_video,boot,btrfs,cat,chain,configfile,echo,efifwsetup,efinet,ext2,fat,font,gettext,gfxmenu,gfxterm,gfxterm_background,gzio,halt,help,hfsplus,iso9660,jpeg,keystatus,loadenv,loopback,linux,ls,lsefi,lsefimmap,lsefisystab,lssal,memdisk,mincmd,normal,ntfs,part_apple,part_msdos,part_gpt,password_pbkdf2,png,probe,reboot,regexp,search,search_fs_uuid,search_fs_file,search_label,sleep,smbios,squash4,test,true,video,xfs,zfs,zfscrypt,zfsinfo
            
          2. 平台特定模块

            play 启动时播放声音
            cpuid 启动时检查cpu功能
            tpm 提供可度量启动,可信平台模块支持
            
          3. 高级模块

            cryptodisk 从dm-crypt加密磁盘启动
            gcry_algorithm 支持特定散列和加密算法
            luks 从LUKS加密的磁盘启动
            ic|lvm 从LVM逻辑卷启动
            mdraid09\mdraid1x,raid5rec,raid6rec 从raid虚拟磁盘启动
            
        • grub从UEFI shim加载器启动,还需要一个secure boot advanced targeting SBAT文件/部分包含在efi二进制文件中。在/usr/share/grub/sbat.csv提供了一个简单的SBAT.csv文件。

          grub-install --target=x86_64-efi --efi-directory=sep --modules=${GRUB_MODULES} --sbat /usr/share/grub/sbat.csv 
          
          sbsign --key MOK.key --cert MOK.cert --output esp/EFI/GRUB/grubx64.efi esp/EFI/grubx64.efi
          
          cp esp/EFI/GRUB/grubx64.efi esp/EFI/BOOT/grubx64.efi
          
  • 配置

    • GRUB每次启动的时候加载配置文件/boot/grub/grub.cfg

      • 每当修改/etc/default/grub 或者 /etc/grub.d/中的文件后,都需要再次生成主配置文件

        grub-mkconfig -o /boot/grub/grub.cfg
        
      • 自动生成脚本默认将在生成的配置文件中为所有已安装的arch linux 内核添加条目。每次安装内核后都需要重新运行一次grub-mkconfig

    • 探测其他操作系统

      • 安装os-prober并挂载包含其他系统引导程序的磁盘分区,然后重新运行grub-mkconfig
        • 输出Warning: os-prober will not be executed to detect other bootable partitions
        • 需要编辑/etc/default/grub取消 GRUB_DISABLE_OS_PROBER=false注释
      • windows
        • 以UEFI安装的windows需要确保含有windows boot manager(bootmgfw.eft)的分区被挂载,以root身份运行os-prober来检测并为其生成启动菜单。
        • 可能需要安装fuse3,并使用ntfs-3g挂载分区
    • 额外参数

      • /etc/default/grub中摄这GRUB_CMDLINE_LINUX和GRUB_CMDLINE_LINXU_DEFAULT变量,生成普通启动项时,这两个参数的值会合并在一起传给内核。生成recovery启动项时,仅使用GRUB_CMDLINE_LINUX参数。
      • 支持系统休眠后恢复
        • GRUB_CMDLINE_LINUX_DEFAULT=“resume=UUID=uuid-of-swap-partition quiet”
    • 设置启动菜单的顶层启动项

      • /etc/default/grub中指定GRUB_TOP_LEVEL=内核路径
    • LVM

      • 如果你的/boot或者/使用了LVM确保lvm模块已经预先加载好

        /etc/default/grub
        GRUB_PRELOAD_MODULES="... lvm"
        
    • RAID

      • 需要加载GRUB模块mdraid09 或者 mdraid1x

        /etc/default/grub
        GRUB_PRELOAD_MODULES="... mdraid09 mdraid1x"
        #/dev/md0写成
        set root=(md/0)
        #/dev/md0p1写成
        set root=(md/0,1)
        
      • 如果在/boot分区使用raid1时安装grub

        grub-install --target=i386-pc --debug /dev/sda
        grub-install --target=i386-pc --debug /dev/sdb
        
    • 定制grub.cfg

      • 基础的GRUB配置如下的设置

        • (hdX,Y) 为磁盘x上的y分区,分区编号从1开始,磁盘编号从0开始
        • set default=N 用户没有进行选择时的默认启动项
        • set timeout=M 使用默认启动项之前等待用户自动选择的时间
        • menuentry “title” {entry options} 为一个标题为title的启动条目
        • set root=(hdX,Y) 设置/boot分区,即内核和GRUB模块存储的位置
      • LoaderDevicePartUUID

        • gpt分区自动挂载使用的systemd-gpt-auto-generator需要LoaderDevicePartUUID UEFI变量以正常工作

          #/boot/grub/grub.cfg
          if [ "$grub_platform" = "efi"];then
          	insmod bli
          fi
          
      • grub启动菜单条目示例

        menuentry "System shutdown" {
        	echo "System shutting down..."
        	halt
        }
        
        menuentry "System restart" {
        	echo "System rebooting..."
        	reboot
        }
        
        if [ ${grub_platform} == "efi" ];then
        	#放入仅grub处于uefi模式的时候显示的条目
        	menuentry "UEFI Firmware Settings" --id 'uefi-firmware'{
        		fwsetup
        	}
        fi
        
        menuentry "UEFI Shell" {
        	insmod fat
        	insmod chain
        	search --no-floppy --set=root --file /shellx64.efi
        	chainloader /shellx64.efi
        }
        
        menuentry "Arch Linux"{
        	insmod fat
        	insmod chain
        	search --no-floppy --set=root --fs-uuid FILESYSTEM_UUID
        	chainloader /EFI/Linux/arch-linux.efi
        }
        menuentry "Other Linux"{
        	set root=(hd0,2)
        	linux /boot/vmlinuz
        	initrd /boot/initrd.img
        }
        menuentry "Other Linux" {
        	search --no-floppy --set=root --fs-uuid uuid
        	#search -no-floppy --set=root --label OTHER_LINUX
        	linux /boot/vmlinuz
        	initrd /boot/initrd.img
        }
        
        menuentry "configfile hd0,gpt4" {
        	insmod part_gpt
        	insmod btrfs
        	insmod ext2
        	set root='hd0,gpt4'
        	configfile /boot/grub/grub.cfg
        }
        
        #uefi/gpt模式下安装windows
        if [ '${grub_platfome}' == "efi" ];then
        	menuentry "MS Windows UEFI/GPT" {
        		insmod part_gpt
        		insmod fat
        		insmod chain
        		#grub-probe --target=fs_uuid esp/EFI/Microsoft/Boot/bootmgfw.efi得到 $fs_uuid
        		#grub-probe --target=hints_string eps/EFI/Microsoft/Boot/bootmgfw.efi
        		#--hint-bios=hd0,gpt1 --hint-efi=hd0,gpt1 --hin-baremetal=ahci0,gpt1
        		search --no-floppy --fs-uuid --set=root $hints_string $fs_uuid
        		chainloader /EFI/Microsoft/Boot/bootmgfw.efi
        	}
        fi
        
    • grub命令行

      • GRUB的主要功能通过/boot/grub里的模块实现,按需加载。GRUB提供了gurb>正常的shell以及grub rescue>救急shell。
      grub rescue> set prefix=(hdx,y)/boot/grub
      grub rescue> insmod (hdx,y)/boot/grub/i386-pc/normal.mod
      rescue:grub>normal
      
      • 支持对长输出进行分页

        grub> set pager 1
        
      • 使用命令行引导操作系统

        • 使用chainloading来引导存储在一个驱动器或者分区中的windows或者linux系统
        • chainloading的意思是用当前的启动加载器去加载另一个启动加载器,也叫做链式加载
        • 要被加载的另一个启动加载器可能在一个有分区表的磁盘的头部MBR,或者在一个未分区磁盘或者一个分区的头部VBR,也可能在使用UEFI得情况下是一个EFI可执行文件
      #分区的VBR
      set root=(hdx,y)
      chainloader +1
      boot
      #MBR或者未分区的VBR
      set root=hdX
      chainloader +1
      boot
      #uefi
      insmod fat
      set root=(hdx,gpty)
      chainloader (${root}/EFI/Microsoft/Boot/bootmgfw.efi)
      boot
      
      • 急救模式
      #grub rescue>
      set prefix=(hdx,y)/boot/grub
      insmod linux  #启动熟悉的linux和initrd命令的支持
      set root=(hdx,y)
      linux /boot/vmlinuz-linux root=/dev/sdaz
      initrd /boot/initramfs-linux.img
      boot
      
    • 移除GRUB

    #运行efibootmgr确保安装了其他启动加载器并配置其接管启动引导工作
    efibootmgr
    #BootOrder: 0003, 0001, 0000, 0002
    #Boot0000* Windows Boot Manager HD(2,GPT,uuid)/File(\EFI\Microsoft\Boot\bootmgfw.efi)
    #Boot0001* GRUB HD(2,GPT,uuid)/File(/EFI/GRUB/grubx64.efi)
    ...
    efibootmgr --delete-bootnum -b 1
    
    #再删除esp/EFI/grub和/boot/grub目录