`
Michaelmatrix
  • 浏览: 210742 次
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

Linux bootloader 编写方法

 
阅读更多
对于移植linux到其它开发板的人来说,编写bootloader是一个不可避免的过程。对于学习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后半部得到,详细地址可以参阅linuxbootprotocol。





回页首


3.引导过程概述

第一步,打开冰箱门;第二步把大象放到冰箱里……不要笑,过程就是这么简单。首先需要把linux内核的setup部分拷贝到9020H:0开始的地址,然后把保护模式内核拷贝到1MB开始的地址,然后根据LinuxBootProtocol2.03的内容设定参数区的内容,基地址就是9000H:0,最后使用一条ljmp$0x9020,$0跳转到setup段,剩下的事情就是linux自己的了^_^,果然简单吧!





回页首


4.THELINUX/I386BOOTPROTOCOL

这个就是我们引导linux所使用的协议,它的位置在:Documetation/i386/boot.txt中。里面详细的写了引导linux所需要知道的一切知识,对于其它体系结构的CPU,也一定存在着类似的东东,仿照本文的方法就可以了。





回页首


5.细节一:基本引导参数

当然我们不指定任何参数linux内核也可以启动,但是这样有可能启动进入一个我们不支持的framebuffer模式,导致没有任何屏幕显示;也可能mount了错误的根分区失败,导致NoInitFound的kernelpanic。所以我们必须要指定一些东西。

如果你像我一样是一个懒人,那么可以直接把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,这表示未知的bootloader,如果你的bootloader已经得到了一个官方分配的typeid,那就写上自己的数值。





回页首


6.细节二:如何加载内核

如果你现在的环境是一无所有,那么必须使用bios中断或者ATA指令去读硬盘了,不过如果你手中如果有基本的DOS系统,那么就可以使用DOS的程序了。为了能够操作整个4GB的地址空间,我使用了WATCOMC写了个小程序读内核,不过你可以仿照bootsect里面的做法,在实模式中读一部分,然后进入到保护模式拷贝到1MB以上,然后再从实模式读一部分……需要注意1:9000H:0也是DOS占用的地址空间,所以读完内核后就不要返回DOS了,否则会有问题;

注意2:一定保证是纯DOS,不要加载HIMEM或者EMM386这样的东西,它们会使上面的引导过程失败。loadlin倒是可以来者通吃几乎所有的DOS,不过它的作者也是这方面的大牛,对DOS下的内存管理非常的熟悉。我们现在研究这些古老的东西很难找资料了,况且我们是在写bootloader,不是DOSkiller^_^。





回页首


7.引导时的高级功能

1)initrd

initrd是启动时的一个小虚拟盘,一般用它来实现模块化的内核。引导initrd的方法主要有两个要点:
第一,把initrd读入内存,我们可以仿照大多数bootloader的方法把它放在内存的最高端;
第二,设定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,使用WATCOMC和TASM,WATCOMC是一个可以在DOS下生成能访问4GB物理地址程序的C编译器,里面也有详细的注释和文档说明。可以从下面的地址下载:loaderx.tar.gz

分享到:
评论

相关推荐

    Linux bootloader编写方法

    Linux bootloader的编写方法详细描述,对于要完成bootloader项目的比较有用

    移植Linux时Linux Bootloader编写方法

    移植Linux时Linux Bootloader编写方法 linux运行在保护模式下,但是当机器启动复位的时候却处于实模式下。所以写bootloader做的工作也是在实模式之下的。

    嵌入式Linux开发详细文档

    嵌入式Linux开发详细文档,...Linux bootloader 编写方法.pdf S3C2410完全开发流程.pdf 超级菜鸟快速上手(44B0).pdf 嵌入式linux开发入门.pdf 嵌入式linux开发手册.pdf YC2440开发指南-utuLinux2.6.24篇-20081106.pdf

    bootloader vivi.tgz

    移植Linux需要很大的工作量,其中之一就是HAL层的编写。在具体实现上,HAL层以arch目录的形式存在。显然,该层需要与bootloader 有一定的约定,否则就不能很好的支持。其实,这个地方应该思考一个问题,就是说,boot...

    最简bootloader只能加载系统内核

    史上最简单的嵌入式Linux bootloader,代码量非常小,只具有加载系统内核功能。非常适合用来理解bootloader的功能以及进程。根据uboot编写。在mini2440 w35测试成功。nandflash是k9f2g08。记得使用mkimage后的linux...

    构建嵌入式Linux系统的详细文档,系统启动bootloader的编写,GNU交叉工具链的构建,u-boot的移植,linux2.6内核.rar

    构建嵌入式Linux系统的详细文档,系统启动bootloader的编写,GNU交叉工具链的构建,u-boot的移植,linux2.6内核 http://www.59186618.com

    bootloader

    自己编写的bootloader,适合TQ210,可以初始化硬件并引导Linux内核启动。

    对AT91RM9200Bootloader的移植,Linux内核的建立,串口、液晶、网络驱动程序的编写,以及文件系统的建立

    对AT91RM9200Bootloader的移植,Linux内核的建立,串口、液晶、网络驱动程序的编写,以及文件系统的建立

    Linux移植及驱动应用程序课程设计任务书.docx

    具体任务有搭建嵌入式Linux开发环境、编译Bootloader、裁剪和编译Linux内核、制作和挂载NFS文件系统。 (2) 开发Linux按键驱动程序,驱动开发板上三个按键。 (3) 开发LED驱动程序或者PWM驱动程序。要求LED驱动程序能...

    基于嵌入式S3C2440系统Bootloader设计与实现.pdf

    基于嵌入式S3C2440系统Bootloader设计与实现.pdf

    linux驱动程序设计入门

    (2)Linux 固件工程师(Firmware Engineer):主要进行 Bootloader、Linux 的移植及 Linux 设备驱动程序的设计。 一般而言,固件工程师的要求要高于应用软件工程师的层次,而其中的 Linux 设备驱动 编程又是 ...

    嵌入式Linux应用程序开发标准教程(第2版全)

    《嵌入式Linux应用程序开发标准教程(第2版)》主要分为3个部分,包括Linux基础、搭建嵌入式Linux环境和嵌入式Linux的应用开发。Linux基础部分从Linux基础、基本操作命令讲起,为Linux初学者能快速入门提供了保证。...

    嵌入式Linux C编程入门(第2版) PPT

    第8章 嵌入式linux c语言基础——arm linux内核常见数据结构 225 8.1 链表 226 8.1.1 链表概述 226 8.1.2 单向链表 226 8.1.3 双向链表 233 8.1.4 循环链表 234 8.1.5 arm linux中链表使用实例 ...

    深入浅出Linux驱动编程

     (2)Linux固件工程师(Firmware Engineer):主要进行Bootloader、Linux的移植及Linux设备驱动程序的设计。  一般而言,固件工程师的要求要高于应用软件工程师的层次,而其中的Linux设备驱动编程又是Linux程序...

    linux移植、驱动编写最详细教程

    linux移植、驱动编写最详细教程,Linux 操作系统的安装以及配置............................................................................................3 1 如何安装RedHat9.0 ..............................

    ARM嵌入式Linux系统开发详解

    linux系统内核结构和移植方法、bootloader功能和移植;linux应用程序开发,包括如何操作文件、管理内存、访问串口、多线程和多进程技术,并且剖析了应用程序的结构和工作流程;linux系统设备驱动程序开发,包括如何...

    Linux驱动开发入门.pdf

    目前,Linux软件工程师大致可分为两个层次: – (1)Linux应用软件工程师(Application Software Engineer):主要利用C库函数和Linux API进行应用...要进行Bootloader、Linux的移植及Linux设备驱动程序的 设计。

    深入理解LINUX内存管理学习笔记

    护模式的称不上OS的OS,已经做完了bootloader,构思kernel的实现的时 候,困惑在内存管理的实现上,阅读这本书,希望能有利于自己的OS的编写。 4,克服惰性,多读书,希望一天能阅读5页,争取半年内阅读完这本原版...

Global site tag (gtag.js) - Google Analytics