Linux系统引导过程(BIOS和Bootloader部分)
KEY:x86体系 CPU 系统引导 启动过程 Linux LILO bootstrapping
BIOS(0xfffffff0)
X86体系计算机系统的自举(bootstrapping)过程起始于对CPU的RESET引脚的触发。这个操作会把CPU的一些寄存器置为默认值,比如代码段寄存器CS(code segment)被置为0xf000、指令指针寄存器(EIP)被置为0x0000fff0等,其它寄存器的初始值如下表(下表未列的其它寄存器值均为未定义):
32位还是16位?
细心注意开机时有部分寄存器的值是32位的。其实在386以后的32位处理器在实模式下产生的地址也是32位的,只不过16位程序只使用固定的16位兼容的一个地址空间罢了(KEMIN:这个结论有待进一步的验证)。举例如开机第一指令8086上应该是0xffff0,但是在80368却是0xfffffff0。这个地址在保护模式是通过EIP加上
保存在由段选择子指向的段描述符里的[基址
]得到的,但是在实模式下[段描述
]符尚没有初始化,那么基地址从哪来的呢?INTEL解释说为了提高访问的速度,每个段寄存器都有隐藏部分用作缓存,看下面:
The CS register has two parts: the visible segment selector part and the hidden base address part. In real-address mode, the base address is normally formed by shifting the 16-bit segment selector value
4 bits to the left to produce a 20-bit base address. However, during a hardware reset, the segment
selector in the CS register is loaded with F000H and the base address is loaded with FFFF0000H. The starting address is thus formed by adding the base address to the value in the EIP register (that is, FFFF0000 + FFF0H = FFFFFFF0H).
Every segment register has a “visible” part and a “hidden” part. (The hidden part is sometimes
referred to as a “descriptor cache” or a “shadow register.”) When a segment selector is loaded
into the visible part of a segment register, the processor also loads the hidden part of the segment register with the base address, segment limit, and access control information from the segment
descriptor pointed to by the segment selector. The information cached in the segment register
(visible and hidden) allows the processor to translate addresses without taking extra bus cycles
to read the base address and limit from the segment descriptor. In systems in which multiple
processors have access to the same descriptor tables, it is the responsibility of software to reload
the segment registers when the descriptor tables are modified. If this is not done, an old segment
descriptor cached in a segment register might be used after its memory-resident version has been
modified.
因此电脑一开启,工作在实模式下的16位BIOS程序便开始工作,包括系统自检(POST)和硬件初始化工作;BIOS还提供了基本的设备驱动程序,以便进行输入输出,比如磁盘驱动、显示驱动。一些早期的基于实模式的OS还依赖BIOS提供的驱动程序,比如DOS,比如WINDOWS3.1。由于 Linux内核是工作在保护模式下的,所以内核重新实现了所有设备驱动,用以替换实模式BIOS驱动。但在内核正式接管计算机之前,引导加载程序还是利 BIOS的磁盘驱动把内核映像和其它数据从磁盘读出。
在这一阶段BIOS的大概工作为四部分:
1. 第一个部分是对系统硬件进行故障检测,也叫做加电自检(Power On Self Test,简称POST),功能是检查计算机系统是否良好;通常完整的POST自检将包括对CPU,640K基本内存,1M以上的扩展内存,ROM,主板, CMOS存储器,串并口,显示卡,软硬盘子系统及键盘进行测试,一旦在自检中发现问题,系统将给出提示信息或鸣笛警告。自检中如发现有错误,将按两种情况处理:对于严重故障(致命性故障)则停机,此时由于各种初始化操作还没完成,不能给出任何提示或信号;对于非严重故障则给出提示或声音报警信号,等待用户处理。 Recent 80 x 86, AMD64, and Itanium computers make use of the Advanced Configuration and Power Interface(ACPI ) standard. The bootstrap code in an ACPI-compliant BIOS builds several tables that describe the hardware devices present in the system. These tables have a vendor-independent format and can be read by the operating system kernel to learn how to handle the devices.
2. 第二个部分是初始化,包括创建中断向量、设置寄存器、对一些外部设备进行初始化和检测等,其中很重要的一部分是读取BIOS配置,对系统硬件进行状态配置和检查。 This phase is crucial in modern PCI-based architectures, because it guarantees that all hardware devices operate without conflicts on the IRQ lines and I/O ports. At the end of this phase, a table of installed PCI devices is displayed.
3. 最后一个部分是查找引导程序,用来引导DOS或其他操作系统。查找顺序取决于BIOS设置depending on the BIOS setting, the procedure may try to access (in a predefined, customizable order) the first sector (boot sector) of every floppy disk, hard disk, and CD-ROM in the system.
4. As soon as a valid device is found, it copies the contents of its first sector into RAM, starting from physical address 0x00007c00, and then jumps into that address and executes the code just loaded.
KEMIN:把引导自举划分为几个阶段,并明确各个阶段的[逻辑任务
]对把握引导过程很有裨益。这些[逻辑任务
]除硬件状态检测,最主要是逻辑环境的构建。因为这些阶段前后有明显的[逻辑层级
]关系,后一阶段的操作环境由前一阶段来构建和初始化。
16位程序的操作环境?
KEMIN:其实Bootloaders和BIOS一样,都是16位程序(所有DOS程序不管没有界面都是16位程序)。与32位程序运行需要一个操作环境类似,16位程序需不要操作环境?
Boot loaders are programs that reside on the boot device of a computer. A boot loader is called by BIOS after enough system initialization has occurred to support the memory, interrupts, and I/O required to load the kernel.
从上面这段话可知应该是需要的,那么在开机的一刻这样的操作环境建立起来没有?请想想上BIOS的初始化工作一步,并看以下的实模式下的内存布局,非ROM内存类型(比如实模式中断向量表)的数据都是16位程序的操作环境数据。
Physical memory layout of the PC
线性地址范围
实模式地址范围
内存类型
用途
0- 3FF |
0000:0000-0000:03FF |
RAM |
real-mode interrupt vector table (IVT)
|
400- 4FF |
0040:0000-0040:00FF |
BIOS data area (BDA)
|
500- 9FBFF |
0050:0000-9000:FBFF |
free conventional memory
(below 1 meg)
|
9FC00- 9FFFF |
9000:FC00-9000:FFFF |
extended BIOS data area (EBDA)
|
A0000- BFFFF |
A000:0000-B000:FFFF |
video RAM |
VGA framebuffers
|
C0000- C7FFF |
C000:0000-C000:7FFF |
ROM |
video BIOS (32K is typical size)
|
C8000- EFFFF |
C800:0000-E000:FFFF |
NOTHING |
|
F0000- FFFFF |
F000:0000-F000:FFFF |
ROM |
motherboard BIOS (64K is typical size)
|
100000- FEBFFFFF |
|
RAM |
free extended memory
(1 meg and above)
|
FEC00000- FFFFFFFF |
|
various |
motherboard BIOS, PnP NVRAM, ACPI, etc.
|
Boot Loader(0x00007c00)
接上一阶段,这一阶段一开始已经有一段引导程序代码驻留在始于0x00007c00
处,大小为一个扇区512字节,并且处理器下一条指令的地址是 0x00007c00。由于引导的功能需求多种多样(例如有不同的引导介质或多操作系统共存),会有多种不同的引导程序。引导过程细节不尽相同,比如不同的引导介质调用不同的驱动(调用软盘驱动或IDE磁盘驱动),而引导过程本身也有分两个(比如LILO)甚至三个(比如GRUB)前后相继“接力”的16 位程序完成。不管引导的策略如何,引导程序主要任务
还是把操作系统从引导介质加载入内存。下面是利用LILO从硬盘加Linux的一个过程(假设LILO 分两步完成引导,前一步由16位程序LA完成,后一步由16位程序LB完成):
- BIOS将硬盘主引导扇区(其中有LA代码)读入至内存中的0x00007c00处,控制权转给该地址程序LA;
- LA把自身移动至0x9A000处,并建立堆栈(从0x9B000处向0x9A200增长);
- LA将LB读入至内存的0x9B000处,把控制权交给LB(KEMIN:LB在什么地方?目前所知它可以在LA或BIOS能访问到的任何地方);
- LB将把[描述符表
](descriptor table)读入0x9D200处,并把保存[默认命令行
](default command line)数据的扇区读入0x9D600处;
- 接着LB检查用户输入,不管用户输入了一个新的内核镜像还是使用缺省内核镜像信息,[选项扇区
](options sector)的数据都会被LB读入0x9D600处,而最终生成的[参数行
](parameter line)会保存在0x9D800处(如果这个参数行中有lock选项,那新参数行会被保存作为默认的参数行);
- 如果用户配置了初始化RAMDISK镜像的话,这个镜像文件将被读入到物理内存(或16MB)末尾以下(KEMIN:也就是以内)的空间里,并且文件的起始地址必须[低于]下一[内存页
] 的边界,以便于启动后系统把它所占的内存回收到[空闲内存池]。这里有一个16MB的限制,这是因为BIOS程序不支持对16MB(24位内存空间)以上内存的访问。(KEMIN:实模式下怎么又会是24位的呢?貌似在开机与正式进入保护模式之前的代码都能够使用CPU所有指令,改变CPU的操作模式。)(KEMIN:为什么需要初始化RAMDISK:initrd?看这里
。)
- 下一步,内核镜像的软盘启动扇区(floppy boot sector)被读入0x90000处;操作系统的初始化代码扇区(setup()函数)则被读入0x90200处。内核镜像余下部分被读入 0x00010000处(称为低地址,专为存放用"make zImage"编译的小内核)或0x00100000处(称为高地址,专为存放用"make bzImage"编译的大内核);在读入的过程中,存放map文件的扇区被读入0x9D000处。
- 如果读入的image是Linux的内核,控制权将交给处于0x90200的Setup.S。如果读入的是另外的操作系统,过程要稍微麻烦一点:chain loader被读入到内存的0x90200处。该操作系统用于启动的扇区被读入到0x90400。chain loader将把它所包含的分区表移到0x00600处,把引导扇区读入到0x07c00。做完这一切,它把控制权交给引导扇区代码。
图LILO运行后的计算机内存布局
KEMIN:这个过程远没详尽LILO的引导过程。过程中出现很多神秘的信息,比如描述表、参数行数据、软盘启动扇区、setup()函数所在扇区,这里没有讲LILO是怎么知道这些数据的位置的。
LILO怎么找到内核的?
When Lilo boots the system, it uses BIOS calls to load the Linux kernel off the disk (IDE drive, floppy or
whatever). Therefore, the kernel must live in some place that can be accessed by the bios.
At boot time, Lilo is not able to read filesystem data, and any pathname you put in /etc/lilo.conf is
resolved at installation time (when you invoke /sbin/lilo). Installation time is when the program builds the tables that list which sectors are used by the files used to load the operating system. As a consequence, all of these files must live in a partition that can be accessed by the BIOS (the files are usually located in the /boot directory, this means that only the root partition of your Linux system needs to be accessed via the BIOS).
Another consequence of being BIOS-based is that you must reinstall the loader (i.e., you must reinvoke
/sbin/lilo) any time you modify the Lilo setup. Whenever you recompile your kernel and overwrite your old image you must reinstall Lilo.
由此可见,LILO是事先生成启动所需的所有数据,并生成一个元数据文件(map file);并且可看出来,lilo与操作系统的亲缘性强度胜于与BIOS的强度。当然,也别忘记操作系统本身就与硬件是相关的。
LINUX引导磁盘制作
Linux内核经裁减(通过重新配置内核组成的模块并编译)后可被装进一张1.44M的软盘。这张可引导的磁盘布局很简单,引导扇区(也就是第一个扇区)存放[引导程序](源码是/arch/i386/boot/bootsect.S),接着就是内核镜像。当我们编译一个新内核的时候,引导代码只是简单地放在内核镜像的前面,这样只需要把内核镜像从磁盘的第一个扇区开始整个拷进去就可以制作出一张可引导的磁盘了。
参考
分享到:
相关推荐
总结来说,Linux启动过程包括CPU上电初始化、BIOS加载引导程序、第一阶段引导程序加载第二阶段引导程序、第二阶段引导程序加载内核,以及内核启动并接管系统。这个复杂的过程确保了操作系统能够正确、高效地运行。
总结来说,"bootloader BIOS"是计算机启动过程中的一个重要组成部分,负责从硬件层面引导操作系统启动。理解其工作原理对于系统管理员和硬件爱好者来说至关重要,因为他们可以通过调整BIOS设置和选择合适的引导加载...
通过详细介绍启动过程中涉及的关键文件和技术细节,帮助读者更好地理解 Linux 系统的引导机制及其相关组件。 #### 关键词 - POST (Power-On Self Test) - BIOS (Basic Input/Output System) - LILO (Linux Loader)...
Linux系统引导过程是一个复杂但有序的序列,涉及多个步骤,从最基本的硬件初始化到最终的用户登录。以下是Linux系统引导过程的详细解释: 1. **BIOS自检**:当计算机开机,首先执行的是BIOS(基本输入/输出系统),...
总的来说,Linux引导装载程序的分析涵盖了硬件初始化、内核加载和系统启动过程的关键环节。了解这些知识对于嵌入式Linux开发至关重要,因为它可以帮助开发者选择合适的引导装载程序,优化内存管理,并确保系统的稳定...
Linux Bootloader是操作系统启动的关键部分,它负责将Linux内核加载到内存中并初始化必要的硬件环境,以便内核能够接管系统的控制权。在移植Linux到一个新的硬件平台时,编写或适配Bootloader是一项重要的任务。本文...
在引导过程中,首先需要把 Linux 内核的 setup 部分拷贝到 9020H:0 开始的地址,然后把保护模式内核拷贝到 1MB 开始的地址,然后根据 Linux Boot Protocol 2.03 的内容设定参数区的内容,基地址就是 9000H:0,最后...
Linux操作系统是全球最广泛使用的开源操作系统之一,其内核引导程序是系统启动过程中的关键环节。这篇文章将深入探讨Linux内核引导程序的工作原理、流程以及它在系统启动中扮演的角色。 首先,我们要明白Linux内核...
Linux系统引导流程是学习和理解Linux系统的基础,特别是对于系统开发人员而言,掌握这一过程至关重要。Linux启动的复杂性在于它涉及到多个阶段和众多的组件,下面我们将逐一解析。 首先,启动流程的第一阶段是从...
### Linux系统加载过程详解 #### 一、Power On与BIOS初始化 - **步骤一:** 计算机开机后,首先经历的是电源开启(power on)的过程,这标志着计算机硬件开始通电工作。 - **步骤二:** 通电之后,计算机开始执行...
ARM Linux 启动过程可以分为四个部分:引导加载程序(bootloader),Linux 内核,文件系统,应用程序。其中 bootloader 是系统启动或复位以后执行的第一段代码,它主要用来初始化处理器及外设,然后调用 Linux 内核...
标题中的“无BIOS的X86模型及其Linux引导机制设计”是指在X86架构的计算机系统中,不依赖传统的基本输入输出系统(BIOS)来启动和加载操作系统,特别是Linux内核。BIOS作为Intel X86体系的重要组成部分,长久以来在...
本文将深入解析如何使用GRUB(Grand Unified Bootloader)来修复Linux系统的引导问题,确保即使在遭遇引导故障时,也无需重装整个操作系统。 ### GRUB:Linux系统中的守护者 GRUB是Linux中最广泛使用的引导加载...
ARM Linux 启动过程可以分为三个部分:启动准备、内核启动和系统初始化。在启动准备阶段,bootloader 会将非易失性存储器中的 Linux 内核拷贝到 RAM 中去,然后跳转到内核的第一条指令处继续执行。在内核启动阶段,...
LILO是早期的Linux引导程序,而GRUB是GNU项目的一部分,提供了更灵活的配置和更高的兼容性。了解这两种BootLoader的配置和工作原理对于管理多系统引导至关重要。 总结: 嵌入式Linux系统的启动涉及BootLoader的选择...
这个区域通常包含一个小的引导程序,称为GRUB(Grand Unified Bootloader)或者LILO(LInux LOader),它们是多系统启动管理器,可以引导不同的操作系统。 2. **GRUB或LILO**:GRUB是红旗Linux常用的引导装载程序,...
### Linux引导过程详解 Linux操作系统启动过程是计算机科学领域中一个复杂的主题,涉及到硬件初始化、内核加载、系统服务启动等多个阶段。以下是对Linux引导过程的深入解析,旨在揭示从开机到用户界面呈现的全过程...