您好,  [请登录] [QQ登录]  [支付宝登录[免费注册]

商品分类

分享到: 百度搜藏 搜狐微博 新浪微博 腾讯微博 QQ收藏 人人网 Facebook Twitter

Linux bootloader编写要领

发布日期:2011-05-19

敷衍移植 linux 到别的开辟板的人来说,编写 boot loader 是一个不可克制的进程。敷衍学习linux的人来讲,编写 bootloader 也是一个很有寻衅性的变乱。本文通过对 linux引导协议举行阐发,过细叙述了怎样编写一个可以在 i386 呆板上引导 2.4.20内核的底子的bootloader。

    1.概述

    linux运行在掩护模式下,但是当呆板启动复位的时间却处于实模式下。以是写bootloader做的变乱也是在实模式之下的。

    linux的内核有多种格局,老式的zImage和新型的bzImage。它们之间最大的差别是敷衍内核体积大小的限定。由于zImage内核须要放在实模式1MB的内存之内,以是其体积受到了限定。如今采取的内核格局大多为bzImage,这种格局没有1MB内存限定。本文以下部分紧张以bzImage为例举行阐发。

    2.bzImage格局内核的布局

    bzImage内核从前向后分为3个部分,前512字节被称为bootsect,这便是软盘引导linux时用到的bootloader,要是不从软盘引导,这部分就没有效,此中存储了一些编译时天生的内核启动选项的默认值。从512个字节开始的512*n个字节称为setup部分,这是linux内核的实模式部分,这部分在实模式下运行,紧张结果是为掩护模式的linux内核启动准备环境。这个部分着末会切换进入掩护模式,跳转到掩护模式的内核实行。着末的部分便是掩护模式的内核,也便是真正意义上的linux内核。此中n的大小可以从bootsect后半部得到,过细地点可以参阅linux boot protocol。

    3.引导进程概述

    第一步,打开冰箱门;第二步把大象放到冰箱里……不要笑,进程便是这么大抵。起首须要把linux内核的setup部分拷贝到9020H:0开始的地点,然后把掩护模式内核拷贝到1MB开始的地点,然后根据Linux Boot Protocol 2.03的内容设置参数区的内容,基地点便是9000H:0,着末利用一条ljmp $0x9020,$0跳转到setup段,剩下的变乱便是linux本身的了^_^,公然大抵吧!

    4.THE LINUX/I386 BOOT PROTOCOL

    这个便是我们引导linux所利用的协议,它的位置在:Documetation/i386/boot.txt中。内里过细的写了引导linux所须要知道的齐备知识,敷衍别的体系布局的CPU,也肯定存在着雷同的东东,仿照本文的要领就可以了。

    5.细节一:底子引导参数

    固然我们不指定恣意参数linux内核也可以启动,但是如许有大概启动进入一个我们不支持的framebuffer模式,导致没有恣意屏幕表现;也大概mount了错误的根分区失败,导致No Init Found的kernel panic。以是我们必须要指定一些东西。

    要是你像我一样是一个懒人,那么可以直接把bootsect拷到9000H:0的位置,利用软盘引导时它会把本身复制到这个地方的,这内里有些默认的设置,详情请见boot.txt。

    起首是root的位置,这里bootsect_pos指向的是9000H:0的地点。

 bootsect_pos[0x1fc] = root_minor; bootsect_pos[0x1fd] = root_major;  

    此中root_minor和root_major分别是root的主配置号和次配置号。

    当前表现模式:

 bootsect_pos[0x1fa] = 0xff; bootsect_pos[0x1fb] = 0xff;  

    这两个数值相称于引导参数vga=0xHHH的值,两个0xff代表文本模式。

 bootsect_pos[0x210] = 0xff;  

    这是在设置你的bootloader的典范,着实只要不是0就行,由于0代表的loader太旧无法引导新的内核,setup发明这个后就会停下来。根据典范你应该写成0xff,这表现未知的boot loader,要是你的bootloader已经得到了一个官方分派的type id,那就写上本身的数值。

    6.细节二:怎样加载内核

    要是你如今的环境是一无全部,那么必须利用bios克制大概ATA指令去读硬盘了,不过要是你手中要是有底子的DOS体系,那么就可以利用DOS的步调了。为了可以大概利用整个4GB的地点空间,我利用了WATCOM C写了个小步调读内核,不过你可以仿照bootsect内里的做法,在实模式中读一部分,然失队入到掩护模式拷贝到1MB以上,然后再从实模式读一部分……须要过细1:9000H:0也是DOS占用的地点空间,以是读完内核后就不要返回DOS了,不然会有标题;

    过细2:肯定包管是纯DOS,不要加载HIMEM大概EMM386如许的东西,它们会使上面的引导进程失败。loadlin倒是可以来者通吃险些全部的DOS,不过它的作者也是这方面的大牛,对DOS下的内存办理非常的熟习。我们如今研究这些陈腐的东西很难找数据了,何况我们是在写bootloader,不是DOS killer^_^。

    7.引导时的高级结果

    1)initrd

    initrd是启动时的一个小假造盘,一样通常用它来实现模块化的内核。引导initrd的要领紧张有两个要点:
第一,把initrd读入内存,我们可以仿照大多数boot loader的要领把它放在内存的最高端;
第二,设置initrd的肇始位置和长度

    bootsect_pos[0x218]开始的4个字节放的是肇始物理地点,bootsect_pos[0x21c]开始的4个字节放的是initrd的长度。

    2)command_line支持

    用command_line你可以给内核传一些参数,本身定制内核的活动。我是如许做的,起首把command_line放在9900H:0的地点里,然后把9900H:0的物理地点存放在bootsect_pos[0x228]开始的4个字节内里。过细肯定是物理地点,以是你应该放99000H这个数,然后内核就会辨认你的command_line了。

    8.结束语

    写本文的目标紧张是为了用最少的语言和最短的时间阐发bootloader的原理,真正的权势巨头数据还是要看linux内核源码和boot.txt文件。我曾经写过一个例子loaderx,利用WATCOM C和TASM,WATCOM C是一个可以在DOS下天生能访问4GB物理地点步调的C编译器,内里也有过细的表明和文档阐发。可以从下面的地点下载:loaderx.tar.gz