免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1191 | 回复: 0
打印 上一主题 下一主题

编写操作系统之使用GRUB [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2006-04-24 03:09 |只看该作者 |倒序浏览
使用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 编辑 ]

使用GRUB.rar

18.26 KB, 下载次数: 48

WORD文档

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

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP