- 论坛徽章:
- 0
|
使用GRUB
翻译 : solo_lxy
E-mail : solo_lxy@126.com
QQ : 36727308
MSN : solo_lxy@hotmail.com
BOLG: http://osspace.blog.com.cn
(GRUB的英文主页可以在http://www.gnu.org/software/grub/grub.en.html 上找到)
本教程是由Chris Giese贡献的,可以到其网站(这个地址已经无效了 )参看英文版。
=========================================================
参考
=========================================================
这些都是我在使用GRUB时经验积累,可以在alt.os.development(我也没上去,郁闷拉)上找到相关帖子的原版:
Subject: Re: generic bootloader question
Newsgroups: alt.os.development
From: "Marv"
Date: Sat, 7 Apr 2001 23:35:20 +0100
References: <9antu8$glc$1@uni00nw.unity.ncsu.edu>
Message-ID: <986682856.680474@dionysos>
Subject: Re: Grub multiboot example
Newsgroups: alt.os.development
From: "Marv"
Date: Mon, 4 Jun 2001 17:21:17 +0100
References: <4a400d54.0106040458.5140872b@posting.google.com>
Message-ID:
Subject: Re: Grub multiboot example
Newsgroups: alt.os.development
From: "Mike Wimpy"
Date: Thu, 7 Jun 2001 22:17:51 -0700
References: <4a400d54.0106040458.5140872b@posting.google.com> <3B1CDA6D.154ADD9D@127.0.0.1> <3B1CDAF9.300ED5E6@127.0.0.1> <3B204A02.14A11876@cisco.com> <3b2053e5_2@news.pacifier.com> <3B205CC8.1685DD4C@cisco.com>
Message-ID: <3b205ff8_2@news.pacifier.com>
Subject: Re: grub coff (solved it!)
Newsgroups: alt.os.development
From: "Mark & Candice White"
Date: Sun, 16 Sep 2001 10:57:34 GMT
References:
Message-ID:
获取GRUB
原代码地址:ftp://alpha.gnu.org/gnu/grub/grub-0.90.tar.gz
可执行程序:ftp://alpha.gnu.org/gnu/grub/grub-0.90-i386-pc.tar.gz
DOS和Windows用户所需要的PARTCOPY和RAWRITE工具可以在以下网址下载:
http://www.execpc.com/~geezer/johnfine/index.htm#zero
http://uranus.it.swin.edu.au/~jn/linux/rawwrite.htm
http://www.tux.org/pub/dos/rawrite/
建立GRUB
类Unix环境可以在shell上执行以下命令:
> ./configure
> make
(…我想应该是这样的…)
(实在不行可以参看源代码中的Readme、FAQ或INSTALL文件)
DOS和Windows用户请参看源代码中的安装文档。(作者并没有给出相关方法,我也不想在这上面花时间,因为我不怎么喜欢在DO或Windows上做这样的事情)
在没有文件系统的软盘上安装GRUB
1. 获取GRUB的二进制文件(stage1和stage2)
2. 合并stage1、stage2到一个文件:
(DOS) > copy /b stage1 + stage2 boot
(UNIX) > cat stage1 stage2 > boot
3. 直接将boot文件写进软盘:
(DOS) > rewrite boot a:
或者 > partcopy boot 0 168000 –f0
(UNIX) > cat stage1 stage2 > boot
使用partcopy时它可能会报告说boot文件大小不到0x168000字节,不过不要紧。
在已经安装了文件系统的软盘上安装GRUB
1. 按照上面的介绍制作一个带有GRUB可以启动的软盘。
2. 将stage1和stage2拷贝到另外一张安装了文件系统的软盘上,注意该软盘的文件系统必须是GRUB可以识别的。为了使用GRUB的setup命令,stage1和stage2必须放在安装了文件系统的软盘的/boot/grub目录下,具体操作如下:
(DOS) > mkdir a:\boot
> mkdir a:\boot\grub
> copy stage1 a:\boot\grub
> copy stage2 a:\boot\grub
(UNIX) > mount /dev/fd0 /mnt
> mkdir /mnt/boot
> mkdir /mnt/boot/grub
> cp stage1 /mnt/boot/grub
> cp stage2 /mnt/boot/grub
3. 在第二个软盘上安装了GRUB后,就不要再修改、移动、删除或经过碎片整理了。一旦被修改,这个软盘就不能在用于启动了!为了防止修改,可以让这个文件变成只读的:
(DOS) attrib +r +s stage2
(UNIX) chmod a-w stage2
以上的DOS命令使得stage2变成一个只读的系统文件。这样可以防止碎片整理。
注意:stage1文件此时已经被拷贝至启动扇区。如果这个文件在GRUB安装后被删除,则该软盘还是可以启动的,这与stage2不同。
3. 用不带文件系统的软盘启动电脑。当GRUB提示符出现后,取出软盘,插入拷贝了stage1和stage2的带有文件系统的第二张软盘。
4. 如果stage1和stage2已经在/boot/grub目录中,那么可以简单的键入如下命令安装GRUB:
setup (fd0)
这条命令显然同下面的命令等效:
install /boot/grub/stage1 d (fd0) /boot/grub/stage2 p
/boot/grub/menu.lst
如果stage1和stage2在其他位置,如在子文件夹/foo中,那么按照如下的方式安装:
install = (fd0)/foo/stage1 (fd0) (fd0)/foo/stage2 0x800 p
(fd0)/foo/menu.lst
这样带有文件系统的这张软盘就可以作为启动了盘了。
xxx - 从第二张软盘上启动,拷贝一个新的stage2并修改其访问属性,然后重新执行setup或install,这样可行吗?(xxx – GRUB并不是一个shell -- 它不能拷贝文件或是列出文件夹 – 不是吗?)
xxx – 安装语法:
0x8000,这个值被写入软盘的驱动扇区,它指示stage2被加载到内存后的首地址。
P,修改stage2,告诉内核stage2所在的分区(我想是这样的)。
(fd0)/boot/grub/menu.lst,修改stage2,告诉GRUB到哪儿去加载menu.lst(启动
菜单)配置文件。
制作多启动内核
无论你的内核是什么样的文件格式,你的内核必须要有多启动头(multiboot header)。这个头必须是4字节对齐,并且必须在内核的前8k字节以前。
注意:一个.text段前8K的地址不必是某个开始文件的前8K.
ELF内核
GRUB可以直接识别ELF文件格式。如果你的内核是ELF内核,可以使用下面简单的多启动头:
MULTIBOOT_PAGE_ALIGN equ 1<<0
MULTIBOOT_MEMORY_INFO equ 1<<1
MULTIBOOT_HEADER_MAGIC equ 0x1BADB002
MULTIBOOT_HEADER_FLAGS equ MULTIBOOT_PAGE_ALIGN | MULTIBOOT_MEMORY_INFO
CHECKSUM equ -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)
; 多启动头( NASM 语法)
ALIGN 4
DD MULTIBOOT_HEADER_MAGIC
DD MULTIBOOT_HEADER_FLAGS
DD CHECKSUM
将上面的代码放在靠近内核启动代码的开始处,然后建立内核。在建立的内核以后,使用GRUB的mbchk功能函数测试内核是否能用于多启动
内核的加载地址
GRUB从ELF内核文件中读取物理地址(加载地址;LMA)。这个值必须大于或等于1M,并且小于真实的物理RAM的大小。
如果加载地址在1M以下,会发生#7号错误:
Loading below 1MB is not suppored
注意:这是GRUB的限制,并不是多启动机制的限制。
如果你使用了像0xC0000000这样的地址,显然是溢出了,同样会得到#7号错误。
注意:mbchk并不会检查这样的错误。
一般情况下,物理地址就是虚拟地址VMA,这可以在连接脚本或连接器的命令行中设置(“ld –Ttext=0x100000 …”)。如果你的连接器版本支持的话,物理地址和虚拟地址可以用“AT”在连接脚本里独立的指定:
OUTPUT_FORMAT("elf32-i386"
ENTRY(entry)
virt = 0xC0000000; /* 3 G */
phys = 0x100000; /* 1 M */
SECTIONS
{
.text virt : AT(phys)
{ code = .;
*(.text)
. = ALIGN(4096);
}
.data : AT(phys + (data - code))
{ data = .;
*(.data)
. = ALIGN(4096);
}
.bss : AT(phys + (bss - code))
{ bss = .;
*(.bss)
*(COMMON)
. = ALIGN(4096); }
end = .;
}
}
连接完成后,使用objdump –h查看地址是否正确。
DJGPP的COFF文件格式和其他文件格式
DJGPP用户可以使用下面这个工具制作ELF文件。
http://www.multimania.com/placr/binutils.html
(xxx – 这个服务器一般很难打开的,如果你愿意可以给它作个镜像。我无能为力,因为我的磁盘空间不够)
我推荐建立标准的COFF文件,然后这样做:
Objcopy-elf –O elf32-i386 krnl.cof kenl.elf
如果这样不行的话,你可以使用“AOUT KLUDGE”让GRUB加载COFF文件。这需要在多启动头的后面添加额外的域(field),像下面这样:
MULTIBOOT_PAGE_ALIGN equ 1<<0
MULTIBOOT_MEMORY_INFO equ 1<<1
MULTIBOOT_AOUT_KLUDGE equ 1<<16
MULTIBOOT_HEADER_MAGIC equ 0x1BADB002
MULTIBOOT_HEADER_FLAGS equ MULTIBOOT_PAGE_ALIGN| MULTIBOOT_MEMORY_INFO | MULTIBOOT_AOUT_KLUDGE
CHECKSUM equ -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)
; The Multiboot header
ALIGN 4
mboot:
DD MULTIBOOT_HEADER_MAGIC
DD MULTIBOOT_HEADER_FLAGS
DD CHECKSUM
;如果设置了在MULTIBOOT_HEADER_FLAGS
;中设置了MULTIBOOT_AOUT_KLUDGE
DD mboot ; these are PHYSICAL addresses
DD code ; start of kernel .text (code) section
DD edata ; end of kernel .data section
DD end ; end of kernel BSS
DD start ; kernel entry point (initial EIP)
注意:如果是二进制或其他文件格式,则同样需要“AOUT KLUDGE”。(xxx – 没有测试过,也许是正确的)。
启动内核
1. 确定你的内核在GRUB方便找到的位置。不必非得在软盘上(靠,这个真COOL)。
2. 从GRUB软盘上启动。
3. (可选的)告诉GRUB,它的根文件夹所使用的设备。
root (hd0,1)
这将挂载(mount)第一块硬盘的第二个主分区,以其作为做为根文件夹。
4. 告诉GRUB你的内核在哪儿:
kernel /krnl.elf
如果你没有指定根设备,就必须在路径名上显式指定:
kernel (hd0,1)/krnl.elf
5. 如果GRUB没有出现任何错误,那么就可以直接启动了:
boot
利用GRUB向你的内核传递信息
启动后,在32位内核进入点,机器状态如下:
1. CS指向基地址为0x00000000,限长为4G – 1的代码段描述符。
2. DS,SS,ES,FS和GS指向基地址为0x00000000,限长为4G – 1的数据段描述符。
3. A20地址线已经打开。
4. 页机制被禁止。
5. 中断被禁止。
6. EAX = 0x2BADB002
7. 系统信息和启动信息块的线性地址保存在 EBX中(相当于一个指针)。
/* 多启动信息结构 */
typedef struct multiboot_info
{
unsigned long flags;
unsigned long mem_lower;
unsigned long mem_upper;
unsigned long boot_device;
unsigned long cmdline;
unsigned long mods_count;
unsigned long mods_addr;
union
{
aout_symbol_table_t aout_sym;
elf_section_header_table_t elf_sec;
} u;
unsigned long mmap_length;
unsigned long mmap_addr;
} multiboot_info_t;
在调用main函数之前将EBX的值压入堆栈,就可以使用C代码来访问以上结构中的相关信息了,示例代码如下:
汇编启动代码:
…
push ebx
call main ; “call main” for Linux/ELF
…
C语言代码:
#include <…>
int main(multiboot_info_t* boot_info)
{
if( boot_info->flags & 2)
{
Kprintf(“the command line is:’%s’\n”,
(char*) boot_info->cmdline);
}
…
}
制作启动菜单
示例1:
# Entry 0:
title WildMagnolia
root (fd0)
kernel /boot/kernel.elf
module /boot/mod_a
module /boot/mod_b
示例2:
#
# Sample boot menu configuration file
#
# default - boot the first entry.
default 0
# if have problem - boot the second entry.
fallback 1
# after 30 sec boot default.
timeout 30
# GNU Hurd
title GNU/Hurd
root (hd0,0)
kernel /boot/gnumach.gz root=hd0s1
module /boot/serverboot.gz
# Linux - boot ot second HDD
title GNU/Linux
kernel (hd1,0)/vmlinuz root=/dev/hdb1
# booting Mach - get kernel from floppy
title Utah Mach4 multiboot
root (hd0,2)
pause Insert the diskette now!!
kernel (fd0)/boot/kernel root=hd0s3
module (fd0)/boot/bootstrap
# booting OS/2
title OS/2
root (hd0,1)
makeactive
# chainload OS/2 bootloader from the first sector
chainloader +1
# For booting Windows NT or Windows95
title Windows NT / Windows 95 boot menu
root (hd0,0)
makeactive
chainloader +1
# za boot na DOS ako Windows NT e instaliran
# chainload /bootsect.dos
# Colors change :0).
title Change the colors
color light-green/brown blink-red/blue
为内核加载模块(module)
======================================================================
xxx
============================================================================================================================================
Other
(看来作者并没有写全这些,真遗憾!
- gzip-compressed kernels?用gzip压缩的内核如何处理呢?
- does GRUB understand kernel file formats other than ELF?
- GRUB除了可以处理ELF内核以外还可以处理其他的吗?
by K.J.
Yes, you may also compile your kernel as a COFF file or an AOUT file.
K.J回答说你可以把你的内核编译成COFF或AOUT文件。(纯二进制文件一样是可以处理的,我正在写的一个内核就是使用纯二进制的,它可以让我更清楚的知道我的代码在内存的什么位置,这样对我来说更了然入胸。)
(在使用GRUB的过程中也出现了不少问题,有些到现在还没搞得太清楚,那位大虾在行的话不妨让我请教请教,谢谢了! 转贴请注明原文和翻译的文章,也不枉我敲了两个小时的中文,谢谢
[ 本帖最后由 solo_lxy 于 2006-4-24 03:30 编辑 ] |
|