一个最简单的arm linux bootloader
2008-04-02 15:37
375 查看
Boot Loader 就是在linux操作系统内核运行之前运行的一段小程序。
可以分为以下几个步骤:初始化硬件设备、读取内核影像,设置启动参数,启动内核。
你可以通过一直U-boot来得到一个功能强大的boot loader,但是对于实际情况来说,
我们启动linux kernel只需要几个步骤就可以完成,写一个最简单的linux bootloader也是一件很轻松的事情。
这里介绍一个最简单的bootloader。
一、初始化硬件:
1、初始化CPU时钟频率,禁止中断。
2、关闭看门狗。
3、初始化存储控制器。
4、初始化linux需要用到的串口。
5、设置堆栈,CPU 必须 SVC 模式, 禁止mmu和cache,进入C程序入口。
二、读取内核影像:
1、由于内核影像存储在Nand Flash中,所以初始化NAND控制器。
2、读出内核影像数据到(rambase + 0x8000)。
3、因为我们的根文件系统直接在mtd中存在,没有用到ramdisk作为根文件系统,所以不需要加载initrd作为根文件系统。
三、设置linux内核启动参数。
设置启动参数为 cmdline = "console=ttyS0 root=mtdblock0"
1、设置param_struct来传递参数。
void linux_arg(char *cmdline)
...{
int i;
struct param_struct *params = (struct param_struct *)(rambase+0x100);
params->u1.s.page_size = 4096;
params->u1.s.nr_pages = (RAM_SIZE) >> 12;
for(i = 0; i < 24; i++)
params->commandline[i] = cmdline[i];
}
其中 param_struct 结构在arch/arm/kernel/compat.c中声明,
/*This is the old deprecated way to pass parameters to the kernel*/
在新的内核中启动参数以标记语言的形式来传递。 不过用以上的方法仍然可以启动现在最新的内核。
2、以标记列表的形式来传递启动参数。
启动参数标记列表以标记 ATAG_CORE 开始,以标记 ATAG_NONE 结束。
每个标记由标识被传递参数的 tag_header 结构以及随后的参数值数据结构来组成。具体可以参考
arch/arm/kernel/compat.c arch/arm/kernel/setup.c等。
这里简单起见,只设置了 ATAG_CORE ATAG_CMDLINE。
#define tag_next(t) ((struct tag *)((__u32 *)(t) + (t)->hdr.size))
params = (struct tag *)BOOT_PARAMS;
params->hdr.tag = ATAG_CORE;
params->hdr.size = tag_size(tag_core);
params->u.core.flags = 0;
params->u.core.pagesize = 0;
params->u.core.rootdev = 0;
params = tag_next(params);
params->hdr.tag = ATAG_CMDLINE;
params->hdr.size = (sizeof(struct tag_header) + strlen(p) + 1 + 4) >> 2;
strcpy(params->u.cmdline.cmdline, p);
params = tag_next(params);
params->hdr.tag = ATAG_NONE;
params->hdr.size = 0;
四、传递参数,运行内核。
内核调用需要三个参数分别在三个寄存器中 R0, R1, R2。
R0=0;
R1=机器类型 ID;关于 Machine Type Number,可以参见 linux/arch/arm/tools/mach-types。
R2=启动参数标记列表在 RAM 中起始基地址。
可以用以下行数调用来传递参数和执行内核:
void (*theKernel)(int zero, int arch, u32 addr) = (void (*)(int, int, u32))(rambase + 0x8000);
theKernel(0, ARCH, rambase);
五、启动信息:
串口收到"uncompressing linux.................. done, booting the kernel……"
boot loader 已经成功地转起来了。
整个启动程序代码只有3k左右, 可以用ads 或realview编译成功,可以正常启动linux, 在板子上可以很好的运行。
可以分为以下几个步骤:初始化硬件设备、读取内核影像,设置启动参数,启动内核。
你可以通过一直U-boot来得到一个功能强大的boot loader,但是对于实际情况来说,
我们启动linux kernel只需要几个步骤就可以完成,写一个最简单的linux bootloader也是一件很轻松的事情。
这里介绍一个最简单的bootloader。
一、初始化硬件:
1、初始化CPU时钟频率,禁止中断。
2、关闭看门狗。
3、初始化存储控制器。
4、初始化linux需要用到的串口。
5、设置堆栈,CPU 必须 SVC 模式, 禁止mmu和cache,进入C程序入口。
二、读取内核影像:
1、由于内核影像存储在Nand Flash中,所以初始化NAND控制器。
2、读出内核影像数据到(rambase + 0x8000)。
3、因为我们的根文件系统直接在mtd中存在,没有用到ramdisk作为根文件系统,所以不需要加载initrd作为根文件系统。
三、设置linux内核启动参数。
设置启动参数为 cmdline = "console=ttyS0 root=mtdblock0"
1、设置param_struct来传递参数。
void linux_arg(char *cmdline)
...{
int i;
struct param_struct *params = (struct param_struct *)(rambase+0x100);
params->u1.s.page_size = 4096;
params->u1.s.nr_pages = (RAM_SIZE) >> 12;
for(i = 0; i < 24; i++)
params->commandline[i] = cmdline[i];
}
其中 param_struct 结构在arch/arm/kernel/compat.c中声明,
/*This is the old deprecated way to pass parameters to the kernel*/
在新的内核中启动参数以标记语言的形式来传递。 不过用以上的方法仍然可以启动现在最新的内核。
2、以标记列表的形式来传递启动参数。
启动参数标记列表以标记 ATAG_CORE 开始,以标记 ATAG_NONE 结束。
每个标记由标识被传递参数的 tag_header 结构以及随后的参数值数据结构来组成。具体可以参考
arch/arm/kernel/compat.c arch/arm/kernel/setup.c等。
这里简单起见,只设置了 ATAG_CORE ATAG_CMDLINE。
#define tag_next(t) ((struct tag *)((__u32 *)(t) + (t)->hdr.size))
params = (struct tag *)BOOT_PARAMS;
params->hdr.tag = ATAG_CORE;
params->hdr.size = tag_size(tag_core);
params->u.core.flags = 0;
params->u.core.pagesize = 0;
params->u.core.rootdev = 0;
params = tag_next(params);
params->hdr.tag = ATAG_CMDLINE;
params->hdr.size = (sizeof(struct tag_header) + strlen(p) + 1 + 4) >> 2;
strcpy(params->u.cmdline.cmdline, p);
params = tag_next(params);
params->hdr.tag = ATAG_NONE;
params->hdr.size = 0;
四、传递参数,运行内核。
内核调用需要三个参数分别在三个寄存器中 R0, R1, R2。
R0=0;
R1=机器类型 ID;关于 Machine Type Number,可以参见 linux/arch/arm/tools/mach-types。
R2=启动参数标记列表在 RAM 中起始基地址。
可以用以下行数调用来传递参数和执行内核:
void (*theKernel)(int zero, int arch, u32 addr) = (void (*)(int, int, u32))(rambase + 0x8000);
theKernel(0, ARCH, rambase);
五、启动信息:
串口收到"uncompressing linux.................. done, booting the kernel……"
boot loader 已经成功地转起来了。
整个启动程序代码只有3k左右, 可以用ads 或realview编译成功,可以正常启动linux, 在板子上可以很好的运行。
相关文章推荐
- linux0.11学习笔记-技术铺垫-简单AB任务切换程序(1)-实现一个简单的bootloader
- linux0.11学习笔记-技术铺垫-简单AB任务切换程序(1)-实现一个简单的bootloader
- Linux下计算程序运行时间的一个简单方法
- linux下c++使用ncurses库的一个简单实例
- 一个简单的linux守护进程
- Atmel at91rm9200的armlinux的bootloader启动代码分析
- linux下编写的一个最简单的Makefile文件
- Linux C++ 一个线程池的简单实现(附代码)
- linux组播编程一个简单的例子
- 一个简单的Linux内核代码整合到一个文件的Java程序
- linux入门:编写一个简单的shell(仅支持部分ls,ps命令)
- 关于(在2410+linux平台上,关于led 的一个简单应用程序)的驱动程序
- 一个简单的linux下原生socket的tcp程序及其修改
- Linux +C+sqlite3 一个简单的学生管理系统
- 为LINUX 设计一个简单的二级文件系统。
- Linux平台自动部署脚本的一个简单例子
- 一个简单的linux用户操作记录监控
- ps_mem:一个用于精确报告 Linux 核心内存用量的简单 Python 脚本
- linux u盘启动盘制作如此简单,一个dd命令搞定
- 【Linux】写一个简单的进度条