bootloader 的两个作用:
1、初始化硬件; 2、启动OS。
bootm命令就是用来启动操作系统的。
内核文件分为 zImage 和 uImage, uImage 是 zImage 的基础上增加了信息头,bootm 命令只能使用 uImage 文件。
bootm命令工作流程:
1、检查信息头(是否压缩/os种类/幻数等信息)
2、根据os的类型调用相关函数
2.1、获取内核地址
2.2、获取CPU型号
2.3、设置启动参数(内存大小、串口号)等
3、启动 Linux 内核
在本次编写的bootloader中省去了第一个步骤,没有检查信息头。
内核本身有处理器参数,bootm命令中传入的CPU参数需要与之相同。
代码编写:
boot.c
#include "atag.h"
#include "string.h"
#define SDRAM_KERNEL_START 0x31000000 //内核的下载的位置
#define SDRAM_TAGS_START 0x30000100
#define SDRAM_ADDR_START 0x30000000
#define SDRAM_TOTAL_SIZE 0x04000000
void (*theKernel)(int , int , unsigned int );
struct tag *pCurTag;
const char *cmdline = "console=ttySAC0,115200 init=/init";
void setup_core_tag()
{
pCurTag = (struct tag *)SDRAM_TAGS_START;
pCurTag->hdr.tag = ATAG_CORE;
pCurTag->hdr.size = tag_size(tag_core);
pCurTag->u.core.flags = 0;
pCurTag->u.core.pagesize = 4096;
pCurTag->u.core.rootdev = 0;
pCurTag = tag_next(pCurTag);
}
void setup_mem_tag()
{
pCurTag->hdr.tag = ATAG_MEM;
pCurTag->hdr.size = tag_size(tag_mem32);
pCurTag->u.mem.start = SDRAM_ADDR_START;
pCurTag->u.mem.size = SDRAM_TOTAL_SIZE;
pCurTag = tag_next(pCurTag);
}
void setup_cmdline_tag()
{
int linelen = strlen(cmdline);
pCurTag->hdr.tag = ATAG_CMDLINE;
pCurTag->hdr.size = (sizeof(struct tag_header)+linelen+1+4)>>2;
strcpy(pCurTag->u.cmdline.cmdline,cmdline);
pCurTag = tag_next(pCurTag);
}
void setup_end_tag()
{
pCurTag->hdr.tag = ATAG_NONE;
pCurTag->hdr.size = 0;
}
void boot_linux()
{
//1. 获取Linux启动地址
theKernel = (void (*)(int , int , unsigned int ))SDRAM_KERNEL_START;
//2. 设置启动参数
//2.1 设置核心启动参数
setup_core_tag();
//2.2 设置内存参数
setup_mem_tag();
//2.3 设置命令行参数
setup_cmdline_tag();
//2.4 设置参数结束标志
setup_end_tag();
//3. 启动Linux系统
theKernel(0,168,SDRAM_TAGS_START);//168是处理器编号,第三个是启动地址
}
atag.h
//参数区的数据结构就是tag结构
#define ATAG_CORE 0x54410001
#define ATAG_MEM 0x54410002
#define ATAG_CMDLINE 0x54410009
#define ATAG_NONE 0x00000000
struct tag_header {
unsigned int size;
unsigned int tag;
};
struct tag_core {
unsigned int flags;
unsigned int pagesize;
unsigned int rootdev;
};
struct tag_mem32 {
unsigned int size;
unsigned int start;
};
struct tag_cmdline {
char cmdline[1];
};
struct tag {
struct tag_header hdr;
union {
struct tag_core core;
struct tag_mem32 mem;
struct tag_cmdline cmdline;
} u;
};
#define tag_size(type) ((sizeof(struct tag_header) + sizeof(struct type)) >> 2)
#define tag_next(t) ((struct tag *)((unsigned int *)(t) + (t)->hdr.size))