HOME 生活记录运维/编程
作者/来源:yixinu.com
栏目:运维/编程
日期:2016-12-05 12:45:14

做为对传统引导程序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压缩格式文件.

menuentry "Boot Hardware Detection Tool from iso" {

  linux16 /memdisk iso

  initrd16 /hdt.iso

  #append iso raw

}

menuentry "Boot DOS from floppy image (with 'raw' parameter)" {

  linux16 /memdisk raw

  initrd16 /dosboot.img

}



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同步的命令?


说明:  很多人反馈, 通过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)来访问。


===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

}


2, Tinycore Linux 4.4

menuentry "Tinycore" {

   set isofile="/boot/isos/tinycore.iso"

   loopback loop $isofile

   linux (loop)/boot/bzImage

   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

}

分享到:

Copyright © 2013-2014 yixinu.com 湘ICP备14004402号

QQ:316686606  Email: 316686606@qq.com