|
发表于 2006-6-2 10:29:37
|
显示全部楼层
还差这一块内容,*_stage1_5 and stage2 是怎么build出来的,以下来自于build过程,
写的相当清楚了。
Let's see how *_stage1_5 and stage2 are generated:
-------------------------------- BEGIN -----------------------------------
e2fs_stage1_5:
gcc -o e2fs_stage1_5.exec -nostdlib -Wl,-N -Wl,-Ttext -Wl,2000
e2fs_stage1_5_exec-start.o e2fs_stage1_5_exec-asm.o
e2fs_stage1_5_exec-common.o e2fs_stage1_5_exec-char_io.o
e2fs_stage1_5_exec-disk_io.o e2fs_stage1_5_exec-stage1_5.o
e2fs_stage1_5_exec-fsys_ext2fs.o e2fs_stage1_5_exec-bios.o
objcopy -O binary e2fs_stage1_5.exec e2fs_stage1_5
stage2:
gcc -o pre_stage2.exec -nostdlib -Wl,-N -Wl,-Ttext -Wl,8200
pre_stage2_exec-asm.o pre_stage2_exec-bios.o pre_stage2_exec-boot.o
pre_stage2_exec-builtins.o pre_stage2_exec-common.o
pre_stage2_exec-char_io.o pre_stage2_exec-cmdline.o
pre_stage2_exec-disk_io.o pre_stage2_exec-gunzip.o
pre_stage2_exec-fsys_ext2fs.o pre_stage2_exec-fsys_fat.o
pre_stage2_exec-fsys_ffs.o pre_stage2_exec-fsys_minix.o
pre_stage2_exec-fsys_reiserfs.o pre_stage2_exec-fsys_vstafs.o
pre_stage2_exec-hercules.o pre_stage2_exec-serial.o
pre_stage2_exec-smp-imps.o pre_stage2_exec-stage2.o
pre_stage2_exec-md5.o
objcopy -O binary pre_stage2.exec pre_stage2
cat start pre_stage2 > stage2
--------------------------------- END ------------------------------------
According to the output above, the layout should be:
e2fs_stage1_5:
[start.S] [asm.S] [common.c] [char_io.c] [disk_io.c] [stage1_5.c]
[fsys_ext2fs.c] [bios.c]
stage2:
[start.S] [asm.S] [bios.c] [boot.c] [builtins.c] [common.c] [char_io.c]
[cmdline.c] [disk_io.c] [gunzip.c] [fsys_ext2fs.c] [fsys_fat.c]
[fsys_ffs.c] [fsys_minix.c] [fsys_reiserfs.c] [fsys_vstafs.c]
[hercules.c] [serial.c] [smp-imps.c] [stage2.c] [md5.c]
We can see e2fs_stage1_5 and stage2 are similar. But e2fs_stage1_5 is
smaller, which contains basic modules(disk io, string handling, system
initialization, ext2/3 file system handling), while stage2 is all-in-one,
which contains all file system modules, display, encryption, etc.
start.S is very important for Grub. stage1 will load start.S to
0200:0000(if stage1_5 is configured) or 0800:0000(if not), then jump to
it. The task of start.S is simple(only 512Byte),it will load the rest parts
of stage1_5 or stage2 to memory. The question is, since the file-system
related code hasn't been loaded, how can grub know the location of the rest
sectors? start.S makes a trick:
-------------------------------- BEGIN -----------------------------------
blocklist_default_start:
.long 2 /* this is the sector start parameter, in logical
sectors from the start of the disk, sector 0 */
blocklist_default_len: /* this is the number of sectors to read */
#ifdef STAGE1_5
.word 0 /* the command "install" will fill this up */
#else
.word (STAGE2_SIZE + 511) >> 9
#endif
blocklist_default_seg:
#ifdef STAGE1_5
.word 0x220
#else
.word 0x820 /* this is the segment of the starting address
to load the data into */
#endif
firstlist: /* this label has to be after the list data!!! */
--------------------------------- END ------------------------------------
an example:
# hexdump -x -n 512 /boot/grub/stage2
...
00001d0 [ 0000 0000 0000 0000 ][ 0000 0000 0000 0000 ]
00001e0 [ 62c7 0026 0064 1600 ][ 62af 0026 0010 1400 ]
00001f0 [ 6287 0026 0020 1000 ][ 61d0 0026 003f 0820 ]
We should interpret(backwards) it as: load 0x3f sectors(start with No.
0x2661d0) to 0x0820:0000, load 0x20 sectors(start with No.0x266287) to
0x1000:0000, load 0x10 sectors(start with No.0x2662af) to 0x1400:00, load
0x64 sectors(start with No.0x2662c7) to 0x1600:0000.
In my distro, stage2 has 0xd4(1+0x3f+0x20+0x10+0x64) sectors, file size
is 108328 bytes, the two matches well(sector size is 512).
When start.S finishes running, stage1_5/stage2 is fully loaded. start.S
jumps to asm.S and continues to execute.
There still remains a problem, when is stage1.5 configured? In fact,
stage1.5 is not necessary. Its task is to load /boot/grub/stage2 to
memory. But pay attention, stage1.5 uses file system to load file stage2:
It analyzes the dentry, gets stage2's inode, then stage2's blocklists. So
if stage1.5 is configured, the stage2 is loaded via file system; if not,
stage2 is loaded via both stage2_sector in stage1 and sector lists in
start.S of stage2.
To make things clear, suppose the following scenario: (ext2/ext3)
# mv /boot/grub/stage2 /boot/grub/stage2.bak
If stage1.5 is configured, the boot fails, stage1.5 can't find
/boot/grub/stage2 in the file-system. But if stage1.5 is not configured,
the boot succeeds! That's because mv doesn't change stage2's physical
layout, so stage2_sector remains the same, also the sector lists in stage2.
Now, stage1 (-> stage1.5) -> stage2. Everything is in position. asm.S
will switch to protected mode, open /boot/grub/grub.conf(or menu.lst), get
configuration, display menus, and wait for user's interaction. After user
chooses the kernel, grub loads the specified kernel image(sometimes
ramdisk image also), then boots the kernel. |
|