bootloader :将内核和文件系统载入内存
Linux 内核:Linux 内核由内存管理、进程管理、设备驱动程序、网络管理等组成,它是操作系统的核心,具有很多最基本的功能,决定了系统的性能和稳定性。用户空间的文件系统用来提供管理系统的各种配置,提供相应的应用程序、服务、数据交换等。
文件系统: 文件系统作为一种载体,它是用来实现用户与操作系统内核的交互
nandflash存放地址
#define IMG_BOOTLOADER 0x00000000
#define IMG_KERNEL 0x00300000
#define IMG_ROOTFS 0x00700000
int main(void)
{
FATFS fs;
int FileSize;
RTC_Time Time = {
2015, 1, 1, 22, 00, 0, 5
};
Uart_Init();
printf("CPU: S3C2416@%dMHz\n", get_ARMCLK()/1000000);
printf(" Fclk = %dMHz, Hclk = %dMHz, Pclk = %dMHz\n",
get_FCLK()/1000000, get_HCLK()/1000000, get_PCLK()/1000000);
NandBoot_Init();
RTC_Init(&Time);
f_mount(&fs, "" , 0);
if (DownloadSelect == 3) { -- 将bootload\内核\文件系统写入nandflash
// 下载选择了从sd卡自更新bootloader, kernel, rootfs
printf("Trying to update bootloader...\n");
FileSize = Sd_ReadFileToRam("/image/bootloader.bin", (uint8_t *)DRAM_BASE);
if (FileSize > 0) {
NandBoot_WriteSkipBad(0, (uint8_t *)DRAM_BASE, FileSize);
printf("Bootloader has been updated, file size %d\n", FileSize);
}
printf("Trying to update kernel...\n");
FileSize = Sd_ReadFileToRam("/image/kernel.bin", (uint8_t *)DRAM_BASE);
if (FileSize > 0) {
Nand_DownloadKernel((uint8_t *)DRAM_BASE, FileSize);
printf("Kernel has been updated, file size %d\n", FileSize);
}
printf("Trying to update rootfs...\n");
FileSize = Nand_DownloadRootfs("/image/rootfs.bin");
if (FileSize > 0) {
printf("Rootfs has been updated, file size %d\n", FileSize);
} else {
printf("Update rootfs error\n");
}
printf("Update is complete, you need to restart the system...\n");
while (1);
} else if (DownloadSelect == 4) {
// 擦除整个nand flash
Debug("Nand flash is erasing...\n");
Nand_EraseFlash();
printf("Erase is complete, you need to restart the system...\n");
while (1);
}
//在这里开始启动内核
Board_Init();
Kernel_Boot();
printf("Linux boot failed\n");
while (1) {
}
}
//设置启动参数
void Kernel_SetupParam(struct tag *params)
{
// start_tag
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);
设置内存标记 ATAG_MEM,标记内存的位置及大小
params->hdr.tag = ATAG_MEM;
params->hdr.size = tag_size (tag_mem32);
params->u.mem.start = DRAM_BASE;
params->u.mem.size = DRAM_SIZE; // 64M
params = tag_next (params);
//设置命令行标记 ATAG_CMDLINE,这是一个字符串,用来控制内核的行为。如
//"noinitrd root=/dev/mtdblock3 rootfstype=yaffs2 init=/linuxrc console=ttySAC0",表示
//根文件系统在 MTD3 分区上,文件系统为 yaffs2,系统启动后执行的第一个程序为
linuxrc,控制台为 ttySAC0。
params->hdr.tag = ATAG_CMDLINE;
params->hdr.size = (sizeof(struct tag_header)+strlen(NandBootArgs)+1+4) >> 2;
strcpy(params->u.cmdline.cmdline, NandBootArgs); //根文件路径
params = tag_next (params);
// end tag
params->hdr.tag = ATAG_NONE;
params->hdr.size = 0;
}
int Kernel_Boot(void)
{
int Ret;
int FileSize;
uint32_t KernelBase;
struct tag *params;
void (*Kernel)(uint32_t, uint32_t, uint32_t);
KernelBase = DRAM_BASE+LINUX_KERNEL_OFFSET;
// Setup linux parameters and linux command line
params = (struct tag *)(DRAM_BASE+LINUX_PARAM_OFFSET);
FileSize = Nand_ReadKernelSize();
if (FileSize > 0) {
Ret = Nand_ReadKernel((uint8_t *)KernelBase, FileSize);
if (Ret == -1) {
printf("failed to read linux kernel from nand flash\n");
return -1;
}
} else {
printf("can not find kernel image in nand flash\n");
return -1;
}
if ((*(uint32_t *)(KernelBase+4*9)) != LINUX_ZIMAGE_MAGIC) {
printf("This binary is not compressed linux kernel image\n");
} else {
printf("Boot with zImage magic\n");
}
Kernel_SetupParam(params); //载入参数
//在交出 CPU 控制权之前,bootloader 需要把 CPU 恢复成初始的环境,CPU 必须禁止
//IRQ 以及 FIQ 中断,处于特权模式,关闭 MMU,使无效并且写回 DCache 数据到主存,
//禁止 DCache,推荐 ICache 打开。
IRQ_Disable(); //禁止中断
Kernel_CleanUpBeforeBoot();
Kernel = (void (*)(uint32_t, uint32_t, uint32_t))KernelBase; //跳到内核载入的地址区别执行
//bootloader 跳转到内核时,将传递三个参数给内核,对于 ARM 为 R0、R1、R2 这三
//个寄存器。第一个参数 R0 必须为 0,第二个参数 R1 为机器码,必须与 linux 内核一致才
//能启动,第三个参数为先前设置的内核启动参数地址位置。跳转到内核后,bootloader 完
//全退出,由 linux 内核全权处理。
Kernel(0, MACH_TYPE, (uint32_t)params); // n开始启动内核
return -1;
}