从零写bootloader--第二阶段启动的实现

说明:第一阶段和第二阶段具体细节未做说明,旨在整个启动流程,即如何自己实现bootloader的整体思维。代码附带贴出,可以参考。

在第一阶段start.s中未完成的工作只剩下main函数。main函数的工作如下:

1、从NandFlash中把内核读入内存

2、设置需要传递的参数

3、跳转执行

第一阶段代码与下面代码一起便可启动内核,具体不在此分析,如不理解,可以参看uboot源码

boot.c(串口的初始化在第一阶段的init.c中)

[objc] view plain copy
  1. #include "setup.h"  
  2.   
  3. extern void uart0_init(void);  
  4. extern void nand_read(unsigned int addr, unsigned charchar *buf, unsigned int len);  
  5. extern void puts(charchar *str);  
  6. extern void puthex(unsigned int val);  
  7.   
  8.   
  9. static struct tag *params;  
  10.   
  11. void setup_start_tag(void)  
  12. {  
  13.     params = (struct tag *)0x30000100;  
  14.   
  15.     params->hdr.tag = ATAG_CORE;  
  16.     params->hdr.size = tag_size (tag_core);  
  17.   
  18.     params->u.core.flags = 0;  
  19.     params->u.core.pagesize = 0;  
  20.     params->u.core.rootdev = 0;  
  21.   
  22.     params = tag_next (params);  
  23. }  
  24.   
  25. void setup_memory_tags(void)  
  26. {  
  27.     params->hdr.tag = ATAG_MEM;  
  28.     params->hdr.size = tag_size (tag_mem32);  
  29.       
  30.     params->u.mem.start = 0x30000000;  
  31.     params->u.mem.size  = 64*1024*1024;  
  32.       
  33.     params = tag_next (params);  
  34. }  
  35.   
  36. int strlen(charchar *str)  
  37. {  
  38.     int i = 0;  
  39.     while (str[i])  
  40.     {  
  41.         i++;  
  42.     }  
  43.     return i;  
  44. }  
  45.   
  46. void strcpy(charchar *dest, charchar *src)  
  47. {  
  48.     while ((*dest++ = *src++) != '\0');  
  49. }  
  50.   
  51. void setup_commandline_tag(charchar *cmdline)  
  52. {  
  53.     int len = strlen(cmdline) + 1;  
  54.       
  55.     params->hdr.tag  = ATAG_CMDLINE;  
  56.     params->hdr.size = (sizeof (struct tag_header) + len + 3) >> 2;  
  57.   
  58.     strcpy (params->u.cmdline.cmdline, cmdline);  
  59.   
  60.     params = tag_next (params);  
  61. }  
  62.   
  63. void setup_end_tag(void)  
  64. {  
  65.     params->hdr.tag = ATAG_NONE;  
  66.     params->hdr.size = 0;  
  67. }  
  68.   
  69.   
  70. int main(void)  
  71. {  
  72.     void (*theKernel)(int zero, int arch, unsigned int params);  
  73.     volatile unsigned intint *p = (volatile unsigned intint *)0x30008000;  
  74.   
  75.     /* 0. 帮内核设置串口: 内核启动的开始部分会从串口打印一些信息,但是内核一开始没有初始化串口 */  
  76.     uart0_init();  
  77.       
  78.     /* 1. 从NAND FLASH里把内核读入内存 */  
  79.     puts("Copy kernel from nand\n\r");  
  80.     nand_read(0x60000+64, (unsigned charchar *)0x300080000x200000);  //uImage = 64字节头部 + zImage,内核存放在0x60000的位置  
  81.     puthex(0x1234ABCD);                                            //用作测试       
  82.     puts("\n\r");  
  83.     puthex(*p);                                                    //打印出zImage前4字节  
  84.     puts("\n\r");  
  85.   
  86.     /* 2. 设置参数 */  
  87.     puts("Set boot params\n\r");  
  88.     setup_start_tag();  
  89.     setup_memory_tags();  
  90.     setup_commandline_tag("noinitrd root=/dev/mtdblock3 init=/linuxrc console=ttySAC0");  
  91.     setup_end_tag();  
  92.   
  93.     /* 3. 跳转执行 */  
  94.     puts("Boot kernel\n\r");  
  95.     theKernel = (void (*)(intint, unsigned int))0x30008000;  
  96.     theKernel(03620x30000100);           //要传递的参数约定放在0x30000100的位置,内核放在0x30008000的位置。中间放参数                     
  97.     /*  
  98.      *  mov r0, #0 
  99.      *  ldr r1, =362 
  100.      *  ldr r2, =0x30000100 
  101.      *  mov pc, #0x30008000  
  102.      */  
  103.   
  104.     puts("Error!\n\r");  
  105.     /* 如果一切正常, 不会执行到这里 */  
  106.   
  107.     return -1;  
  108. }  

Makefile

[objc] view plain copy
  1. CC      = arm-linux-gcc  
  2. LD      = arm-linux-ld  
  3. AR      = arm-linux-ar  
  4. OBJCOPY = arm-linux-objcopy  
  5. OBJDUMP = arm-linux-objdump  
  6.   
  7. CFLAGS      := -Wall -O2  
  8. CPPFLAGS    := -nostdinc -nostdlib -fno-builtin  
  9.   
  10. objs := start.o init.o boot.o  
  11.   
  12. boot.bin: $(objs)  
  13.     ${LD} -Tboot.lds -o boot.elf $^  
  14.     ${OBJCOPY} -O binary -S boot.elf $@  
  15.     ${OBJDUMP} -D -m arm boot.elf > boot.dis  
  16.       
  17. %.o:%.c  
  18.     ${CC} $(CPPFLAGS) $(CFLAGS) -c -o $@ $<  
  19.   
  20. %.o:%.S  
  21.     ${CC} $(CPPFLAGS) $(CFLAGS) -c -o $@ $<  
  22.   
  23. clean:  
  24.     rm -f *.o *.bin *.elf *.dis 

你可能感兴趣的:(armos)