无忧启动论坛

 找回密码
 注册
搜索
最纯净的「微PE装机优盘」UEPON大师作品系统gho:最纯净好用系统下载站广告联系 QQ:184822951 微信:wuyouceo
查看: 3990|回复: 12

[转贴] GRUB启动代码详解

  [复制链接]
发表于 2016-1-24 14:11:54 | 显示全部楼层 |阅读模式
本帖最后由 有阴也有阳 于 2016-1-24 18:31 编辑

                                                                                  GRUB2的介绍

         目前Grub1已经停止开发了,不再增加新的功能,所有的开发都转移到Grub2上了,Grub 2 是新一代的Grub,它实现了一些Grub中所没有的功能:

1.模块化设计   
不同于Grub的单一内核结构,Grub 2 的功能分布在很多的小模块中,并且能在运行时动态装载和卸除。
  
2.支持多体系结构   Grub 2可支持PC(i386), MAC(powerpc)等不同的体系结构,而且支持最新的EFI架构。
  
3.国际化的支持   Grub 2 可以支持非英语的语言。
  
4.内存管理   Grub 2 有真正的内存管理系统。
  
5.脚本语言   Grub 2 可以支持脚本语言,例如条件,循环,变量,函数等。   
当然,Grub 2正处在开发阶段,因此以上的某些功能可能现阶段还不是很完善。
如果你熟悉Grub2,应该可以看明白里面的内容。要注意的是:   
a、timeout, default等参数用变量来储存   
b、菜单项由menuentry定义   
c、第1个分区是(hd0,1)而不是(hd0,0)
        理论的东西说多了大家估计也晕,举个简单的例子:在grub1中,要改变启动背景的时候只能选择支持640X480分辨率并且格式也只能是.xpm的图片,分辨率稍微大点的图就显示不出来了,但grub2不存在这个问题,它有更绚丽的菜单界面,grub2默认.png  .tga  .jpeg等很多种格式的图片都支持,而且支持的图片分辨率也更大。


GRUB2启动代码分析
                                 
#
# DO NOT EDIT THIS FILE
#
# It is automatically generated by /usr/sbin/grub-mkconfig using templates
# from /etc/grub.d and settings from /etc/default/grub
#
### BEGIN /etc/grub.d/00_header ###
if [ -s $prefix/grubenv ]; then
#如果“$prefix/grubenv”目录不为空

  load_env
#从grubenv文件中加载环境变量
fi
set default="0"  
#启动第1项#

if [ ${prev_saved_entry} ]; then #如果prev_saved_entry的值不为空
  set saved_entry=${prev_saved_entry}  #将saved_entry的值设置成变量prev_saved_entry的值。

  save_env saved_entry #将变量saved_entry保存到grubenv文件中。

  set prev_saved_entry= #将prev_saved_entry的值设置为空

  save_env prev_saved_entry #将prev_saved_entry保存到grubenv文件中

  set boot_once=true #将boot_once的值设置为真(貌似是为了标志已经设置过启动的相关环境变量了)

fi
function savedefault {
  if [ -z ${boot_once} ]; then #如果已经设置过相关环境变量

saved_entry=${chosen} #用变量chosen的值给saved_entry赋值。

save_env saved_entry
#将saved_entry保存到grubenv文件中
  fi
}
function recordfail {   #存在启动失败记录时调用,设置变量recordfail。
  set recordfail=1
  if [ -n ${have_grubenv} ]; then if [ -z ${boot_once} ]; then save_env recordfail; fi; fi #如果grubenv文件存在,并已设置过相关变量,就将变量recordfail保存到grubenv文件。
}
insmod ext2        
#插入ext2文件系统支持的模块

set root='(hd0,9)'   
# 指定系统root分区,也就是 / 分区为第1个磁盘的第9个分区

search --no-floppy --fs-uuid --set d9985e84-7b54-4e5d-8ce9-c25cf88330aa #  指定uuid= d9985e84-7b54-4e5d-8ce9-c25cf88330aa的分区为root分区,如果前面的分区 #  号(hd0,9)的uuid与这里的uuid一致,这两句作用一样,如果不一致,则指定uuid的起 #  作用。

if loadfont /usr/share/grub/unicode.pf2 ; then #设置终端字体,unicode.pf2支持中文字符显示

  set gfxmode=640x480 #设置显示分辨率,默认为640×480

  insmod gfxterm #插入终端模块gfxterm,支持中文字符显示和支持24位图像。

  insmod vbe #插入vbe模块,GRUB2引入模块化机制,要使用它,需要在这里加入。

  if terminal_output gfxterm ; then true ; else
#检测grub2是否将终端设设定为gfxterm

    # For backward compatibility with versions of terminal.mod that don't
    # understand terminal_output
terminal gfxterm         
#设定grub2终端为gfxterm

  fi
fi
insmod ext2  
#插入ext2文件系统支持的模块  
set root='(hd0,9)'   
# 指定系统root分区,也就是 / 分区为第1个磁盘的第9个分区
search --no-floppy --fs-uuid --set d9985e84-7b54-4e5d-8ce9-c25cf88330aa #  指定uuid= d9985e84-7b54-4e5d-8ce9-c25cf88330aa的分区为root分区,如果前面的分区 #  号(hd0,9)的uuid与这里的uuid一致,这两句作用一样,如果不一致,则指定uuid的起 #  作用。

set locale_dir=($root)/boot/grub/locale
set lang=zh
insmod gettext
if [ ${recordfail} = 1 ]; then
  set timeout=-1    #若有启动失败的记录,则不再倒计时。
else
  set timeout=10   #如果停留在grub选择系统界面,停顿时间就设置成10秒,十秒后按默认启动项
#启动。
fi
### END /etc/grub.d/00_header ###
### BEGIN /etc/grub.d/05_debian_theme
###设置菜单颜色和背景颜色

set menu_color_normal=white/black   
#设定菜单字体及背景颜色

set menu_color_highlight=black/light-gray #设定选择项字体及背景颜色

### END /etc/grub.d/05_debian_theme ###
### BEGIN /etc/grub.d/10_linux ###
#10_linux为系统自动添加的当前root分区linux引导项


#菜单项,要包括 menuentry 双引号" " 和大括号 { }才完整,否则不显示菜单
menuentry ''Ubuntu,Linux 2.6.32-30-generic'' --class ubuntu --class gnu-linux --class gnu --class os {
        recordfail
#执行recordfail 函数
        insmod ext2
#插入ext2文件系统支持的模块
        set root='(hd0,9)'  
#指定系统root分区,也就是 / 分区为第1个磁盘的第9个分区

        search --no-floppy --fs-uuid --set d9985e84-7b54-4e5d-8ce9-c25cf88330aa #这句与set root=(hd0,9)效果一样,可删除其一,二者不一致以这句为准

        linux        /boot/vmlinuz-2.6.32-30-generic root=UUID=d9985e84-7b54-4e5d-8ce9-c25cf88330aa ro   quiet splash #加载内核
# ro:可读写,当启动分区是JFS等格式时需要使用此参数使得系统可以在启动是存放日志。
#quiet:安静模式,不显示启动详细信息。
#splash:显示徽标。

        initrd        /boot/initrd.img-2.6.32-30-generic #初始RAM磁盘,在系统引导过程中挂载的一个临时根文件系统。

}
menuentry ''Ubuntu,Linux 2.6.32-30-generic (恢复模式)'' --class ubuntu --class gnu-linux --class gnu --class os { #linux的恢复模式,与linux的启动项基本一样。

        recordfail #执行recordfail 函数

        insmod ext2
        set root='(hd0,9)'
        search --no-floppy --fs-uuid --set d9985e84-7b54-4e5d-8ce9-c25cf88330aa
        echo        '载入 Linux ...'
        linux        /boot/vmlinuz-2.6.32-30-generic root=UUID=d9985e84-7b54-4e5d-8ce9-c25cf88330aa ro single  #加载内核 貌似这个single参数就是指定的修复模式

        echo        '载入引导虚拟磁盘。'
        initrd        /boot/initrd.img-2.6.32-30-generic #初始RAM磁盘,在系统引导过程中挂载的一个临时根文件系统。

}
### END /etc/grub.d/10_linux ###

#20_memtest86+为系统自动添加的内存测试菜单项
menuentry "Memory test (memtest86+)" {
        insmod ext2
        set root='(hd0,9)'
        search --no-floppy --fs-uuid --set=root f8656ad4-390d-4a72-832a-1f4b313ac793
        linux16        /boot/memtest86+.bin
}
menuentry "Memory test (memtest86+, serial console 115200)" {
        insmod ext2
        set root='(hd0,9)'
        search --no-floppy --fs-uuid --set=root f8656ad4-390d-4a72-832a-1f4b313ac793
        linux16        /boot/memtest86+.bin console=ttyS0,115200n8
}
### END /etc/grub.d/20_memtest86+ ###


### BEGIN /etc/grub.d/30_os-prober ### #  30_os-prober或30_others为系统自动查找并添加其他系统菜单项,按windows、
#  linux、macos顺序查找并添加,支持windows 7识别。
if [ "x${timeout}" != "x-1" ]; then
  if keystatus; then
    if keystatus --shift; then
      set timeout=-1
    else
      set timeout=10
    fi
  else
    if sleep --interruptible 3 ; then
      set timeout=10
    fi
  fi
fi   
##直接启动默认的系统,需要选择引导不同的系统时才按几下shift键进入grub选择系统界面。##



menuentry "Windows 7 (loader) (on /dev/sda1)" {

        insmod ntfs
#插入NTFS文件系统支持的模块
        set root='(hd0,1)'
#指定系统root分区,也就是 / 分区为第1个磁盘的第1个分区

        search --no-floppy --fs-uuid --set 5802c4e402c4c7e8 #这句与set root=(hd0,1)效果一样,可删除其一,二者不一致以这句为准。

        chainloader +1
#指示GRUB读入分区的第一个扇区的引导记录。

}
### END /etc/grub.d/30_os-prober ###

### BEGIN /etc/grub.d/40_custom ###
#40_custom为自定义的启动项,如启动cdlinux

# This file provides an easy way to add custom menu entries.  Simply type the
# menu entries you want to add after this comment.  Be careful not to change
# the 'exec tail' line above.
### END /etc/grub.d/40_custom ###
### BEGIN /etc/grub.d/41_custom ###
if [ -f  $prefix/custom.cfg ]; then  
##如果$prefix/custom.cfg满足正规文件##
  source $prefix/custom.cfg;  ##重新加载此变量##
fi
### END /etc/grub.d/41_custom ###
发表于 2016-1-25 08:57:04 | 显示全部楼层
学习一下,谢谢分享
回复

使用道具 举报

发表于 2016-1-25 10:40:01 | 显示全部楼层
学习了,想问一下楼主有没有方法解决u盘版的grub2读取大文件的winpe时间超慢的问题?比如600M左右的pe,用grub2直接加载读取时间大约3到4分钟,太久了,我分析原因1,U盘本来的读取速度有限,2,grub2加载ISO文件机制是不是有问题(猜想理由是我用grub4dos快的多)。有没有方法加快读取时间?我参考各位前辈写的菜单:
menuentry 'win10pe'{
    set root='(hd0,msdos1)'
    linux16 /memdisk iso raw
    initrd16 /Win10.iso
}
回复

使用道具 举报

 楼主| 发表于 2016-1-25 12:24:43 | 显示全部楼层
liy 发表于 2016-1-25 10:40
学习了,想问一下楼主有没有方法解决u盘版的grub2读取大文件的winpe时间超慢的问题?比如600M左右的pe,用g ...

在BIOS启动部分我的用法是直接使用grub4dos,或者由grub2直接转grub4dos,等待时间为0......
回复

使用道具 举报

发表于 2016-2-20 14:01:57 | 显示全部楼层
捕获.PNG
新学习grub2,请教下  fi 是什么语句?

回复

使用道具 举报

发表于 2016-2-23 22:06:09 | 显示全部楼层
sskgaiqny 发表于 2016-2-20 14:01
新学习grub2,请教下  fi 是什么语句?

end if的意思
回复

使用道具 举报

发表于 2016-2-24 13:05:47 | 显示全部楼层

谢谢,原来如此
回复

使用道具 举报

发表于 2018-8-20 11:00:46 | 显示全部楼层
学习一下
回复

使用道具 举报

发表于 2018-8-22 11:33:19 | 显示全部楼层
有介绍源码的就好了
回复

使用道具 举报

发表于 2018-8-22 13:49:00 | 显示全部楼层
wintoflash 发表于 2018-8-22 12:24
如果你想查找GRUB2源码的相关问题,那我只能说你找错论坛了,论坛里还真没有研究过GRUB2源码的人。
你应 ...

只是最近遇到的grub2问题:grub没有加载usb keyboard相关的module(例如xhci ehci等),但是可以使用usb keyboard,这个原因还没有确认
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|Archiver|捐助支持|无忧启动 ( 闽ICP备05002490号-1 )

闽公网安备 35020302032614号

GMT+8, 2019-12-15 01:39

Powered by Discuz! X3.3

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表