嵌入式linux启动信息注释之bootloader
作为一名嵌入系统开发者,你一定遇到过下面的情景:
在某论坛上看到一篇帖子,上面贴着嵌入式linux开发板启动时的有关信息,然后大家在帖子里讨论着这个启动过程中出现的问题,随机举例如下:
- Linux version 2.4.20-uc0 (root@Local) (gcc version 2.95.3 20010315 (release) (ColdFire patches - 20010318 from http://f
- (uClinux XIP and shared lib patches from http://www.snapgear.com/)) #20 三 6月 1
- 8 00:58:31 CST 2003
- Processor: Samsung S3C4510B revision 6
- Architecture: SNDS100
- On node 0 totalpages: 4096
- zone(0): 0 pages.
- zone(1): 4096
- pages. zone(2): 0 pages.
- Kernel command line: root=/dev/rom0
- Calibrating delay loop... 49.76 BogoMIPS
- Memory: 16MB = 16MB total
- Memory: 14348KB available (1615K code, 156K data, 40K init)
- Dentry cache hash table entries: 2048 (order: 2, 16384 bytes)
- Inode cache hash table entries: 1024 (order: 1,
- Mount-cache hash table entries: 512 (order: 0, 4096 bytes)
- Buffer-cache hash table entries: 1024 (order: 0, 4096 bytes)
- Page-cache hash table entries: 4096 (order: 2, 16384 bytes)
- POSIX conformance testing by UNIFIX Linux NET4.0 for Linux 2.4
- Based upon Swansea University Computer Society NET3.039
- Initializing RT netlink socket
- Starting kswapd
- Samsung S3C4510 Serial driver version 0.9 (2001-12-27) with no serial options en abled
- ttyS00 at 0x3ffd000 (irq = 5) is a S3C4510B
- ttyS01 at 0x3ffe000 (irq = 7) is a S3C451
- Blkmem copyright 1998,1999 D. Jeff Dionne
- Blkmem copyright 1998 Kenneth Albanowski
- Blkmem 1 disk images:
- 0: BE558-1A5D57 [VIRTUAL BE558-1A5D57] (RO)
- RAMDISK driver initialized: 16 RAM disks of 1024K size 1024 blocksize
- Samsung S3C4510 Ethernet driver version 0.1 (2002-02-20)
- eth0: 00:40:95:36:35:34
- NET4: Linux TCP/IP 1.0 for NET4.0
- IP Protocols: ICMP, UDP, TCP
- IP: routing cache hash table of 512 buckets, 4Kbytes
- TCP: Hash tables configured (established 1024 bind 1024)
- VFS: Mounted root (romfs Freeing init memory: 40K
复制代码
上面的这些输出信息,也可能包括你自己正在做的嵌入式linux开发板的输出信息,其中的每一行,每一个字的含义,你是否深究过,或者说大部分的含义你能确切地知道的?本人想在这里结合本人在实践中一些体会来和广大嵌入式linux的开发者一起读懂这些信息。
我们在这里将以一个真实的嵌入式linux系统的启动过程为例,来分析这些输出信息。启动信息的原始内容将用标记标出,以区别与注释。
嵌入式linux的启动主要分为两个阶段:
① 第一部分bootloader启动阶段
② 第二部分linux 内核初始化和启动阶段
第一部分 : bootloader启动
- Boot loader v0.12
- NOTE: this boot loader is designed to boot kernels made with the
- 2.4.xx releases
- bootloader for XV
- Built at Nov 20 2005 10:12:35
复制代码
Bootloader头信息,版本,编译时间等,这个因不同的bootloader的设计而有所不同,由此你能看出bootloader的版本信息,有很多使用的是通用的bootloader,如u-boot,redboot等。
- Loaded to 0x90060000
复制代码
将bootloader加载到内存ram中的0x90060000处,即将bootloader加载到内存的高端地址处。
Linux内核将被bootloader加载到0x90090000处。
- Found boot configuration
复制代码
查找到了启动boot的配置信息
- Booted from parallel flash
复制代码
从flash中启动代码,此处的flash为并行闪存。Flash的分类列举如下:
闪存分三类:并行,串行,不可擦除。
①并行Parallel flash
NOR Flash,Intel于1988年发明.随机读取的速度比较快,随机按字节写,每次可以传输8Bit。一般适合应用于数据/程序的存贮应用中.NOR还可以片内执行(execute-in-place)XIP.写入和擦除速度很低。
NAND Flash,1989年,东芝公司发明.是以块和页为单位来读写的,不能随机访问某个指定的点.因而相对来说读取速度较慢,而擦除和写入的速度则比较快,每次可以传输16Bit,一般适用在大容量的多媒体应用中,容量大。如:CF,SM.
②串行Serial Flash 是以字节进行传输的,每次可以传输1-2Bit.如:MMC,SD,MS卡.串行闪存器件体积小,引脚也少,成本相对也更低廉。
③不可擦除Mask Rom Flash的特点是一次性录入数据,具有不可更改性,经常运用于游戏和需版权保护文件等的录入。其显著特点是成本低。
注意:任何flash器件的写入操作只能在空或已擦除的单元内进行,所以大多数情况下,在进行写入操作之前必须先执行擦除。NAND器件执行擦除操作是十分简单的,而NOR则要求在进行擦除前先要将目标块内所有的位都写为0。
从上面的信息,我们可以对flash类型特点有个比较明确的了解。
- CPU clock rate: 200 MHz
复制代码
开发板上所使用的CPU的主频为200MHZ.
- DRAM size is 128MB (128MB/0MB)
复制代码
动态内存ram大小为128M。这里我们列举一下内存的类型及工作原理。
根据内存的工作原理可以划分出两种内存:DRAM和SRAM
①DRAM表示动态随机存取存储器。这是一种以电荷形式进行存储的半导体存储器。DRAM中的每个存储单元由一个晶体管和一个电容器组成。数据存储在电容器中。电容器会由于漏电而导致电荷丢失,因而DRAM器件是不稳定的。为了将数据保存在存储器中,DRAM器件必须有规律地进行刷新。
②SRAM是静态的,因此只要供电它就会保持一个值。一般而言,SRAM 比DRAM要快,这是因为SRAM没有刷新周期。每个SRAM存储单元由6个晶体管组成,而DRAM存储单元由一个晶体管和一个电容器组成。相比而言,DRAM比SRAM每个存储单元的成本要高。照此推理,可以断定在给定的固定区域内DRAM的密度比SRAM 的密度要大。
SRAM常常用于高速缓冲存储器,因为它有更高的速率;而DRAM常常用于PC中的主存储器,因为其拥有更高的密度。
在嵌入式系统中使用DRAM内存的设计比较广泛。
地址辅助说明:
先说明一下内存地址数字情况,主要是为了方便记忆。
可以访问的内存为4G。
0x40000000是1GB处;
0x00040000是256K处,0x00020000是128K处,0x90000000是2GB多的地方。
- 1M->0x00100000,
- 2M->0x00200000,
- 8M->0x00800000
- 16M->0x01000000,
- 32M->0x02000000
- 256M->0x10000000
- 64K->0x00010000
- 4K->0x00001000
复制代码
这个是个快速记忆的方法,你可以根据地址中1的位置和其后0的个数来快速知道换算后的地址是在多少兆的地方。比如,1的后面5个0,代表1M的大小,6个0,代表16M,以此类推。
- ROMFS found at 0x46040000, Volume name = rom 43f291aa
复制代码
romfs,只读文件系统所在的地址为:0x46040000 (flash映射后的第3分区)。
卷名为rom。
romfs和rootfs概念上有所区别。
flash在内存中的的起始地址为0x46000000,而ROMFS在flash分区上的起始位置为0x00040000,所以ROMFS在内存地址中的位置就为0x46040000。这个细节的部分可以参考flash分区时的地方,Creating 3 MTD partitions。
romfs中包括kernel和app应用,不包括bootloader和firmware信息头。romfs只读文件系统里的内容有很多种分类方法,我们可以将kernel和app同时放里面,作为根文件系统下的一个文件,也可以在flash上另外划分区域来分别存放。
VFS虚拟文件系统交换器
在linux系统中,目前已经开发出多种文件系统,那么如何让这些文件系统能共存在一个系统中呢,从linux 2.0开始,引入了虚拟文件系统管理器 VFS的概念。
Linux 下的文件系统主要可分为三大块:
① 一是上层的文件系统的系统调用,
② 二是虚拟文件系统交换器 VFS(Virtual Filesystem Switch),
③ 三是挂载到 VFS 中的各实际文件系统,例如 ext2,jffs 等。
VFS的确切叫法是Virtual Filesystem Switch虚拟文件系统交换器,这里的VFS中的"S"是指的switch,这个需要强调一下的,它很容易被混淆成"system",如果理解成"system"将是不正确的,请多加注意。
VFS是具体文件系统filesystem的一个管理器。
VFS是Linux内核中的一个软件层,一种软件机制,它也提供了内核中的一个抽象功能,允许不同的文件系统共存,可以称它为 Linux 的文件系统管理者,与它相关的数据结构只存在于物理内存当中。所以在每次系统初始化期间,Linux 都首先要在内存当中构造一棵 VFS 的目录树。VFS 中的各目录其主要用途是用来提供实际文件系统的挂载点。而rootfs将是这个目录树的根结点的(root),即 "/"目录,VFS的结构就是从这个rootfs开始的。有了VFS,那么对文件的操作将使用统一的接口,将来通过文件系统调用对 VFS 发起的文件操作等指令将被 rootfs 文件系统中相应的函数接口所接管。
注意:rootfs并不是一个具体的文件系统类型,如jffs。它只是一个理论上的概念。在具体的嵌入系统实例中,可以将某种具体的文件系统设置为根文件系统rootfs,如我们可以设置romfs为根文件系统,也可以设置jffs为根文件系统。
这里的ROMFS只读文件系统只是一种具体的文件系统类型,也是在嵌入系统中经常使用到的类型。
看完了上面的内容,以后你对出现的类似"kernel Panic:VFS:Unable to mount root fs on 0:00"的含义应该已经了解了。其中"VFS:"就是虚拟文件系统管理器操作时的输出信息了。
- File linux.bin.gz found
复制代码
linux kernel内核文件名,它是在只读文件系统romfs上的一个组成部分。
- Unzipping image from 0x4639DE60 to 0x90090000, size = 1316021
复制代码
将romfs中的linux kernel解压缩到0x90090000,之后会从这个内存地址启动内核。romfs为压缩格式文件,使用压缩的只读文件系统,是为了保持制作出来的整个系统所占用的flash空间减小。这个内核的大小为1.3M左右,这也是目前大多数嵌入系统所使用的方法。
- Inptr = 0x00000014(20)Inflating....
复制代码
释放,解压中。。。(变大,充气, 膨胀)
- Outcnt = 0x0030e7c8(3205064)Final Inptr = 0x001414ad(1316013)Original CRC = 0xcbd73adbComputed CRC = 0xcbd73adb
复制代码
做释放后的CRC检查
- Boot kernel at 0x90090000 with ROMFS at 0x46040000
复制代码
kernel已经被从romfs中释放到内存地址0x90090000处,可以跳转到此处启动kernel了,这里是指定的kernel的起始地址
- Press 'enter' to boot
复制代码
系统等待启动,后面将看到linux kernel的启动过程。