帶EFI支持的GRUB2安裝全記錄


版權歸作者所有,任何形式轉載請聯系作者。
作者:keenshoes(來自豆瓣)
來源:https://www.douban.com/note/210077866/
 
關鍵詞:
EFI
GRUB2
efibootmgr
Gentoo LINUX
Windows 7
Mac OS X
multiboot

    做為對傳統引導程序grub的升級版本, Grub2的功能非凡, 他的不俗表現, 至少有兩方面, 1, Grub2可以識別當前使用的大多數文件系統, 無論在GPT還是MBR格式的.2, Grub2可以采用更靈活的模塊和腳本來引導大部分操作系統和ISO. 不過Grub2在提供更大的便利的同時, 也失去了自己編輯啟動文件的可能, 任何變動都需要通過grub2來更新.
     本文將對grub2從編譯到安裝,配置更方面進行詳細描述.  平台為Gentoo Linux.

1,   編譯帶EFI支持的Grub2
      echo 'sys-boot/grub:2' >> /etc/portage/package.unmask     #unmask grub:2
      export GRUB_PLATFORMS="emu efi-32 efi-64 pc coreboot multiboot qemu"
      USE="x86_64-efi-64" emerge -v grub:2      #采用帶64位EFI支持的USE進行編譯.

2,   安裝Grub2
      首先需要准備EFI分區.  在這里, Windows 7安裝的EFI分區, 可以直接使用, 有關Windows7的信息不會被復寫.
      啟動Gentoo Linux或者其他Linux Live CD並chroot到本地硬盤
       mkdir -p /boot    # 創建mount點
       mount /dev/sda2   /mnt/efi # 假設EFI分區為sda2, 將它掛在/mnt/efi目錄下.

      執行Grub2安裝命令, 為了文件管理方便, 直接將文件安裝在EFI分區的/grub2目錄下.
     # grub2-install --directory=/usr/lib64/grub/x86_64-efi --target=x86_64-efi --root-directory=/mnt/efi --boot-directory=/mnt/efi --bootloader-id=GRUB2 --removable  sda1
       --directory     #定義了grub2安裝的源文件位置, 缺省為/usr/lib64/grub/x86_64-efi
       --target         #定義了目標文件格式, 比如是64或32位EFI模式, 還是GRUB2-BIOS模式.
       --root-directory  #定義文件復制目標位置.  復制到哪里去?
       -- boot-directory  #定義啟動目錄, 缺省帶/boot/grub2的prefix, 所以我們直接定義/就可以.
                     但是,如果安裝到EFI的系統上, 直接把EFI的mount點寫上去。

=====2016-02-26========
新版的grub2已經找不到boot-directory這個參數了,特別時EFI安裝時,需要變更為--efi-directory,不然會cannot find EFI directory的錯誤。
grub2-install --directory=/usr/lib64/grub/x86_64-efi --target=x86_64-efi --efi-directory=/mnt/efi --boot-directory=/mnt/efi --bootloader-id=GRUB2 --removable sda1
======================

       該操作將復制所需要各種的mod, pf2字體, theme主題到指定位置, 因此不再需要手工安裝復制.

       將grub2安裝到EFI分區時, 同時會自動創建一個grub.efi的文件。理論上要求root/boot-directory都直接寫這個mount點, 重新啟動時就能自動掛起來。如果想先安裝在系統的根或其他目錄,然后再復制到EFI分區,就會出現grub rescue, prefix not set,unknown filesystem或者沒菜單等各種蛋疼的問題,這是因為前面生成的EFI只把相關linux分區格式加起來了,而且指定去那個目錄查找grub.cfg文件。 太智能了,但是手冊也不寫明白,讓人惡心。

3,    創建啟動映像或bootloader.
       對於EFI分區, 這個東西可以做,也可以不做。但是如果做不好的話,生成的EFI文件會一直報prefix not set, 然后卡死在那里。 還不如直接用系統生成的呢。
       #grub2-mkimage -d /usr/lib64/grub/x86_64-efi -O x86_64-efi -p /grub2 -o /boot/grub/grub2-x86_64-efi.efi part_gpt part_msdos gpt hfs hfsplus btrfs fat ext2 iso9660 reiserfs scsi normal configfile chain appleldr configfile linux multiboot boot efi_gop apple linux echo cpio sh cat cpio hexdump ls date minicmd
        -d  定義源文件位置.  缺省為/usr/lib64/grub/{ARCH}
        -O 定義輸出格式, 也就是所謂的Target, 可以通過{TARGET}來定義調用
        -p  定義配置文件和mod文件的位置(在EFI分區的相對位置),  -p是個很蛋疼的參數。在grub.cfg里一定要設置。不然麻煩的很。
        -o  定義本次編譯的文件名字和位置.
        后面附加的是將要編譯進bootloader的模塊, 將一些常用的模塊編譯進就可以了, 不常用的模塊, 在使用時可以通過insmod直接調用.  boot halt reboot help fshelp minicmd echo等常用功能建議編譯進去. 這樣在EFI啟動模式可以方便的關機重啟.
      想編譯MBR格式的將輸出定義為  -O gr2ldr 就可以了. gr2ldr可以被其他bootloader調用.

      注意: 因為編譯的EFI/gr2ldr對地址都是硬編碼的, 所以關聯文件的位置就比較重要, 不然啟動的時候會出現加載不上模塊, 或者顯示不出菜單等問題.

4,  創建啟動配置文件
     #grub2-mkconfig -o /boot/grub2/grub.cfg
     將啟動文件復制到EFI分區的/grub2目錄下. GRUB 2 配置文件默認位置是 /boot/grub/grub.cfg。也有些 Linux 軟件包使用 /boot/grub2/grub.cfg,同時啟用 GRUB Legacy 和 GRUB 2 安裝程序。這里需要自己了解, 到底哪個文件是grub2使用的.
      在gentoo下, grub:2只使用grub2下的grub.cfg
     
5,  創建自定義啟動配置文件
     自定義啟動文件需要在/etc/grub.d/之下, 進行編輯, 復制一個模版, 修改完成后, 再調用grub2-mkconfig就可以將文件加進去了.
     因為grub.cfg對格式有一定要求, 因此自行修改grub.cfg文件, 可能會出現菜單不顯示, grub引導不成功等問題. 另外直接修改的grub.cfg, 在下次調用mkconfig后就會被自動覆蓋掉, 所以一定要及時備份.
     自定義的cfg文件, 行尾一定不能有空格等空字符.
      grub2對格式檢查很嚴格, 所有的custom文件, 必須以有exec tail的內容在首.
     所有的grub2配置命令 ,都可以在grub>模式下調試

例子:
通過GRUB2調用EFI啟動Windows 7
# grub2-probe --target=fs_uuid /boot/efi/efi/Microsoft/Boot/bootmgfw.efi
E1A8-BA25
# grub2-probe --target=hints_string /boot/efi/efi/Microsoft/Boot/bootmgfw.efi
--hint-bios=hd0,gpt2 --hint-efi=hd0,gpt2 --hint-baremetal=ahci0,gpt2
#這個參數hints_string在新版本的Grub2-probe中已經廢棄.

在獲得Windows 7的UUID和hints_string后, 可以直接編寫cfg.
menuentry "Microsoft Windows x86_64 UEFI-GPT" {
    insmod part_gpt
    insmod fat
    insmod search_fs_uuid
    insmod chain
    search --fs-uuid --no-floppy --set=root --hint-bios=hd0,gpt2 --hint-efi=hd0,gpt2 --hint-baremetal=ahci0,gpt2 E1A8-BA25
    chainloader /efi/Microsoft/Boot/bootmgfw.efi
}

另Windows 7帶EFI有更簡單的啟動模式,  可以啟動. 但chainloader +1的模式需要MBR的boot code配合, 在GPT的系統里不工作.
menuentry "Windows 7" {
        set root='(hd0,gpt2)'
        chainloader /EFI/microsoft/BOOT/bootmgfw.efi
}

通過grub2引導Gentoo Linux
menuentry 'Gentoo GNU/Linux' {
    load_video
    insmod gzio
    insmod part_gpt
    insmod fat
    set root='hd0,gpt7'
    linux    /root/kernel-3.1.12-gentoo root=/dev/sda7 ro  
}

通過Grub2生成的代碼也可以引導Mac OSX, 但這也許還是和磁盤格式, 或者機器類型有關. 也許只有純種的Mac機器才支持這代碼. 否則大部分生成的代碼都不運行的.

=====以下命令,未曾在gentoo下測試====
引導ISO文件是非常容易了, 但也並不是想象的那么方便. 因為ISO文件本身千變萬化, 千差萬別. 無論你通過什么方式引導ISO,都要包含一定的邏輯, 將系統的控制權轉交出去. 引導ISO是個技術貨, 每個ISO都有自己不同的引導參數和機制.
引導基於Linux的系統, 至少要有兩個方面的工作要處理. 1), 定義iso文件的位置, 並傳遞給被引導系統, 以便在系統引導起來后, 可以把這個iso做為cdrom看待. 這個定義通常是在initrd中進行定義(/proc/cmdline). 每種系統定義的方法和方式都有所不同 2),  需要傳遞給內核系統的啟動參數, 這可以通過查看光盤的啟動文件比如grub.cfg, syslinux.cfg來確認.
menuentry "Rescure Linux ISO" {
  insmod loopback
  insmod part_gpt
  loopback loop (hd0,1)/rescure/rescure-linux.iso
  linux    (loop)/boot/rescure/linux26 isofrom=/dev/sda1/rescure/rescure-linux.iso boot=live quiet vga=791 noeject noprompt
  initrd   (loop)/boot/grmlsmall/initrd.gz
}

沒有核心的類DOS盤直接用chainloader去掛.  
menuentry "Ghost for Dos" {
        loopback loop (hd0,0)/images/ghost.iso
        chainloader (loop)
}

還有一種格式的叫MEMDISK (仿真磁盤),就是把映像直接讀到內存去, 然后在啟動一些傳統的系統. 這類磁盤包括軟盤映像img , iso映像, 還有一些是硬盤分區映像等. 都通過linux16創建memdisk, 然后傳遞給initrd16來處理用. 適用於通過INT 13進行調用的實模式系統, 如DOS和大部分bootloader. 這里調用的磁盤映像文件可以是zip或gzip壓縮格式文件, 諸如WinPE盤等。

menuentry "Boot Hardware Detection Tool from iso" {
   linux16 /memdisk iso
   initrd16 /hdt.iso
   #append iso raw
 }

menuentry 'WinPE boot system ISO' {
  set root='(hd1,gpt3)'
  echo 'Loading Memdisk...'
  insmod memdisk
  linux16 /images/memdisk iso raw
  echo 'Loading ISO...'
  initrd16 /os-set/winpe/Win10PE.iso
}
====Win10PE引導,經過驗證,是成功的======



6,  將編譯好的EFI添加到EFI的啟動列表中, 讓efi自動執行.
      efibootmgr --create --gpt --disk /dev/sda --part 1 --write-signature --label "GRUB2" --loader "\\efi\\grub2\\grub.efi"
      當然, 不修改,問題也不大, 現在大部分機器都有Boot from efi file功能, 直接選文件啟動就可以了.

7,   常見問題
      a, 啟動時, 看不到菜單. 有兩種可能
      .系統只有一個menuentry, 系統不顯示菜單, 直接引導進入, 按shift可以調出菜單.
      .配置文件位置不對, grub2找不到菜單, 會直接停在grub>的窗口.
       b, insmod提示找不到文件
        模塊文件不在指定位置. 需要手工或按說明操作, 把模塊文件放在EFI編碼的特定位置.
       c,執行EFI文件, 沒任何反應, 直接退出.
         連字體文件都沒有了,  環境變量沒了, 什么都跑不下去了.
       d, 編輯了grub.cfg文件, 但在菜單里看不到變化.
          編輯錯了文件位置, 檢查一下系統調用的是grub還是grub2下的配置文件.
       e,  通過chain0, tboot等方式引導, 進不了Mac OS X
           在GPT模式下, 所有基於MBR的東西都跑不起來, 這個系統里沒有他們需要的MBR分區表, 給不了他們文件位置.
       f, 執行gptsync后, 系統分區表不見了, 數據丟失.
          活該, 在純粹的GPT表上, 執行什么和MBR同步的命令?

8, grub rescue>的恢復
       如果grub.cfg里的配置有問題,會在啟動時進入rescue模式,此時可以通過重新設置變量的方式調出grub的啟動菜單。

在grub的菜單出來后,依然會有root定義錯誤導致系統無法啟動。可以選擇c或者e,對啟動表項修改后進行啟動。。。

9,  grub啟動時,無法加載themes和background圖片,進去后提示:error:no video mode activated.
      進入grub命令行
grub> videoinfo
List of supported video modes:
Legend: mask/position=red/green/blue/reserved
Adapter 'EFI GOP driver':
 0x00 1280 x 1024 x 32 (5120) Direct color ......
EDID version: 1.4
     preferred mode: 1920x1080
grub> gfxmode=1280x1024x32
grub> videotest
順利調出圖像。
由此可知,因為gfxmode設置不對,導致grub進入text模式,導致themes之類的都不正確。修改grub.cfg中的gfxmode即可。

說明:  很多人反饋, 通過grub2-mkconfig生成的Mac OSX配置, 可以直接啟動機器. 估計這和機器的配置等有關系,比如MBR內容, Mac的版本等.並不是100%成功的. 猜測成功的模式和磁盤的分區格式有關, 大凡用MBR或混合磁盤格式的, 因為都含有boot123代碼, 基本上都能成功.
      grub2可以引導ISO文件, 但都是帶kernel的非仿真光盤. 帶有特定引導扇區的實模式iso文件如何引導, 在研究中.
       對於Mac OSX在GPT盤上的引導, 有人通過打33185 patch的方式, 可以實現appleloader直接啟動.  patch名字為appleloader_macbook_7_1.patch
       http://savannah.gnu.org/bugs/index.php?33185
 
        grub2里還有一個高級功能,可以把所有需要的模塊,文件等放到一個文件系統映像里,然后加到core.img里。比如說,你可以把command.lst,fs.lst,grub.cfg, normal.mod和其他需要的mod文件打包到一個cpio文檔里,然后用以下的命令生成core.img:
grub-mkimage -d . -o core.img -p (memdisk)/ -m cpio_image memdisk cpio
啟動后,文檔里的內容可以用(memdisk)來訪問。

 注: 通過GRUB2引導操作系統,與硬件本身還有很大的關系。比如Pmagic,  WinPE等iso, 在新的機器上引導成功的指令,換到舊的電腦上就不成功。可能與主板本身有關系,也可能和系統啟動時的內存大小有關。總會有一款適合自己,不再深究了。
===OVER====

經測試可以執行啟動操作的 Linux or LiveCD,  就是有這樣那樣的問題, 都是細節了, 可以以后慢慢調整.
1, pmagic livecd
復制livecd里pmagic目錄到/boot下, 包括bzImage, initrd.img, pmagic-VERSION.sqfs文件.
root=/dev/sda7  定義了iso文件所在分區
directory=/boot   定義pmagic-VERSION.sqfs所在位置 (具體為/boot/pmagic/pmodules/pmagic-VERSION.sqfs)
menuentry "loopback-pmagic from harddisk (ISO = pmagic-4.4.iso)" {
  loopback loop (hd0,gpt7)/images/pmagic-4.4.iso
  linux (loop)/pmagic/bzImage isofrom=/dev/sda5/pmagic-4.4.iso root=/dev/sda7 directory=boot edd=off noapic load_ramdisk=1 prompt_ramdisk=0 rw loglevel=9 max_loop=256
  initrd (loop)/pmagic/initrd.img
}

for i in $(cat /proc/cmdline); do
   case $i in
      directory=*)     directory=$(get_opt $i) ;;
      iso_location=*)  iso_location=$(get_opt $i)  ;;
      iso_filename=*)  ISO_VERSION=$(get_opt $i) ;;
      root=*)          root=$(get_opt $i)  ;;
      label=*)         label=$(get_opt $i)  ;;
      uuid=*)          uuid=$(get_opt $i) ;;
   esac
done
仔細研究pmagic文件查找邏輯, 就會發現除了directory, 還有一個iso_location的方式可以用來做為sqfs文件查找的替代方法. 這個iso_location就是在pmagic里定義查找ISO的一種方法, 和其他的grml的findiso, ubuntu的iso-scan/filename一樣, 都是在initrd自行定義的.
menuentry "Parted Magic" {
    set isofile="/boot/isos/pmagic.iso"
    loopback loop $isofile
    linux (loop)/pmagic/bzImage iso_filename=$isofile edd=off noapic load_ramdisk=1 prompt_ramdisk=0 rwnomce sleep=10 loglevel=0
    initrd (loop)/pmagic/initramfs
}

pmagic的directory定義是這樣的  $directory/pmagic/pmodules/PMAGIC-$VERSION.SQFS,因此定義directory時,直接定義上級目錄就可以了。不過這里還有一個超級大坑,就是搜索的文件都是大寫。而windows下復制文件又無法區分大小,因此經常會引起PMAGIC-$VERSION.SQFS not found的問題。只能引導到linux下重新改下文件名。

======20190401=引導Pmagic的三種模式===========
模式一: 2019版,將pmagic.sqfs打包到files.cgz模式
menuentry "Pmagic-2019-01-03-pxe from sda5)" {
  insmod ntfs
  insmod loopback
  set root=(hd1,gpt3)
  linux  /images/pmagic/bzImage64  edd=on vga=normal
  initrd /images/pmagic/initrd.img /images/pmagic/fu.img /images/pmagic/m64.img /images/pmagic/files.cgz
}
pmagic20190103版本通過加載files.cgz實現sqfs文件的加載。file.cgz為cpio格式的gz壓縮包,這樣可以直接引導,方便了很多很多。
解包:
#gunzip files.cgz
#cpio -idmv < files.cpio
#ls
pmagic/pmodules/PMAGIC-$VERSION.sqfs
壓縮:
 find ./* | cpio -H newc -o > files.cpio (或者 find ./* | cpio -H tar -o > files.cpio)

模式二: 將pmagic解包到本地文件方式
menuentry "Pmagic-2016-10-18.iso from sda5)" {
  insmod ntfs
  insmod loopback
  set root=(hd1,gpt3)
  linux  /images/pmagic2016/pmagic/bzImage64 root=/dev/ram0 directory=images/pmagic2016 edd=on vga=normal boot=live eject=no noapic load_ramdisk=1 prompt_ramdisk=0 rw loglevel=9 max_loop=256
  initrd /images/pmagic2016/pmagic/initrd.img /images/pmagic2016/pmagic/fu.img /images/pmagic2016/pmagic/m64.img
}
回頭來看pmagic2016, 就會發現在initrd啟動時,會自動在directory目錄下搜索pmagic/pmodules/PMAGIC-$VERSION的版本,因此在早期格式里定義的loopfile根本就是個多余的東西,直接刪除。

模式三: 直接引導Pmagic LiveCD模式
menuentry "Pmagic-2016-10-18-LiveCD from sda5)" {
  insmod ntfs
  insmod loopback
  insmod png
  set root=(hd1,gpt3)
  background_image /images/pmagic/pmagic.png
  loopback loop (hd1,gpt3)/images/pmagic_2016_10_18.iso
  linux  (loop)/pmagic/bzImage64  edd=on vga=normal
  initrd (loop)/pmagic/initrd.img (loop)/pmagic/fu.img (loop)/pmagic/m64.img
}
==============================

2, Tinycore Linux
menuentry "Tinycore" {
    set isofile="/boot/isos/tinycore.iso"
    loopback loop $isofile
    linux (loop)/boot/vmlinuz loglevel=3 cde waitusb=10 linux repo=hd:/dev/disk/by-uuid/${USBUUID}:/
    initrd (loop)/boot/tinycore.gz
}
這個版本的tinycore在我機器上黑屏, 什么都看不到, 不認識我的gpt盤?

3, CDLinux 0.9.7.1
loopback loop (hd0,gpt7)/images/cdlinux/cdlinux-0.9.7.1.iso
linux (loop)/CDlinux/bzImage root=/dev/ram0 livecd quiet vga=773 noeject noprompt sleep=0 load_ramdisk=1 prompt_ramdisk=0
initrd (loop)/CDlinux/initrd
圖象出來就掛了.

4, Gentoo
menuentry "...   2 - Gentoo 11 Live DVD" {
    set isofile="/livedvd-x86-amd64-32ul-2012.iso"
    search --set -f $isofile
    loopback loop $isofile
    echo    'Chargement du noyau Linux ...'
    linux (loop)/boot/gentoo64 root=/dev/ram0 looptype=squashfs loop=/image.squashfs cdroot isoboot=$isofile splash=silent,theme:livecd-10
    echo    'Chargement du disque mémoire initial ...'
    initrd (loop)/boot/gentoo64.igz
}

5, CloneZilla
menuentry "CloneZilla amd64 (800x600)" {
set isofile="/boot/clonezilla-live-1.2.6-24-amd64.iso"
loopback loop $isofile
linux (loop)/live/vmlinuz boot=live live-config noswap nolocales edd=on nomodeset ocs_live_run="ocs-live-general" ocs_live_extra_param="" ocs_live_keymap="" ocs_live_batch="no" ocs_lang="" gfxpayload=800x600x16,800x600 ip=frommedia nosplash toram=filesystem.squashfs findiso=$isofile
initrd (loop)/live/initrd.img
}

6,  Fedora
menuentry ".. Fedora 15 Desktop AMD64 (extracted)" {
    linux /boot/iso/LiveCD-FC15/isolinux/vmlinuz0 root=UUID=8816-2C13 live_dir=/boot/iso/LiveCD-FC15/LiveOS/ rootfstype=auto ro liveimg quiet  rhgb rd.luks=0 rd.md=0 rd.dm=0 locale=fr_FR bootkbd=fr console-setup/layoutcode=fr
    initrd /boot/iso/LiveCD-FC15/isolinux/initrd0.img
}

 在grub2引導硬盤iso文件后,進入操作系統后,需要卸載它,不然會出現分區表問題。
代碼: sudo umount -l /isodevice

a,   使用GRUB2引導(硬盤安裝) Gentoo LiveCD 的ISO文件?

以"install-amd64-minimal-*.iso"為例。
第一步,將ISO中的'/isolinux/{gentoo,gentoo.igz}'、'/image.squashfs'三個文件放到'(hd0,gpt3)/os/gentoo/'目錄中;
第二步,將ISO中的'/livecd'放到相同分區(hd0,gpt3)的根目錄下;
最后,在'grub.cfg'中加入如下菜單項:
menuentry "Gentoo Minimal Install LiveCD" --unrestricted {
    linux  (hd0,gpt3)/os/gentoo/gentoo cdroot looptype=squashfs loop=/os/gentoo/image.squashfs
    initrd (hd0,gpt3)/os/gentoo/gentoo.igz
}
[提示]'livecd'是尋找'image.squashfs'所在磁盤分區的關鍵。
[提示] Gentoo LiveCD 亦可使用與其他Linux發行版的LiveCD類似的方法啟動(也就是使用"isoboot="參數)。

b,  使用GRUB2引導(硬盤安裝)各種 Linux LiveCD 的ISO文件?
這里給出的方法,只適用於提供了"img_loop="或"iso-scan/filename="或"fromiso="或"isoboot="或"isoloop="之類參數的LiveCD。
下面以 Ubuntu 的 LiveCD 為例說明。首先,假定你將ISO文件放在'(hd0,gpt3)/ISO/Ubuntu.iso';然后,在'grub.cfg'中加入如下菜單項:
menuentry "Ubuntu LiveCD" --unrestricted {
    loopback loop0 (hd0,gpt3)/ISO/Ubuntu.iso
    linux  (loop0)/casper/vmlinuz boot=casper iso-scan/filename=/ISO/Ubuntu.iso
    initrd (loop0)/casper/initrd.lz
}
[說明]這里給出的方法,其實就是各種"硬盤安裝 XX Linux"的翻版,只不過不再需要將"vmlinuz"與"initrd"從ISO中解壓出來而已。

c, bionicpup64, xenialpup64, slacko,   
缺少讀iso的函數,無法直接通過iso文件引導。

Reference:
http://doc.ubuntu-fr.org/tutoriel/grub2_lancer_des_images_iso
 https://www.gnu.org/software/grub/manual/html_node/Images.html#Images
https://www.cnblogs.com/f-ck-need-u/archive/2017/06/29/7094693.html



免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM