说明:第一阶段和第二阶段具体细节未做说明,旨在整个启动流程,即如何自己实现bootloader的整体思维。代码附带贴出,可以参考。
在第一阶段start.s中未完成的工作只剩下main函数。main函数的工作如下:
1、从NandFlash中把内核读入内存
2、设置需要传递的参数
3、跳转执行
第一阶段代码与下面代码一起便可启动内核,具体不在此分析,如不理解,可以参看uboot源码
boot.c(串口的初始化在第一阶段的init.c中)
- #include "setup.h"
-
- extern void uart0_init(void);
- extern void nand_read(unsigned int addr, unsigned charchar *buf, unsigned int len);
- extern void puts(charchar *str);
- extern void puthex(unsigned int val);
-
-
- static struct tag *params;
-
- void setup_start_tag(void)
- {
- params = (struct tag *)0x30000100;
-
- 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);
- }
-
- void setup_memory_tags(void)
- {
- params->hdr.tag = ATAG_MEM;
- params->hdr.size = tag_size (tag_mem32);
-
- params->u.mem.start = 0x30000000;
- params->u.mem.size = 64*1024*1024;
-
- params = tag_next (params);
- }
-
- int strlen(charchar *str)
- {
- int i = 0;
- while (str[i])
- {
- i++;
- }
- return i;
- }
-
- void strcpy(charchar *dest, charchar *src)
- {
- while ((*dest++ = *src++) != '\0');
- }
-
- void setup_commandline_tag(charchar *cmdline)
- {
- int len = strlen(cmdline) + 1;
-
- params->hdr.tag = ATAG_CMDLINE;
- params->hdr.size = (sizeof (struct tag_header) + len + 3) >> 2;
-
- strcpy (params->u.cmdline.cmdline, cmdline);
-
- params = tag_next (params);
- }
-
- void setup_end_tag(void)
- {
- params->hdr.tag = ATAG_NONE;
- params->hdr.size = 0;
- }
-
-
- int main(void)
- {
- void (*theKernel)(int zero, int arch, unsigned int params);
- volatile unsigned intint *p = (volatile unsigned intint *)0x30008000;
-
-
- uart0_init();
-
-
- puts("Copy kernel from nand\n\r");
- nand_read(0x60000+64, (unsigned charchar *)0x30008000, 0x200000);
- puthex(0x1234ABCD);
- puts("\n\r");
- puthex(*p);
- puts("\n\r");
-
-
- puts("Set boot params\n\r");
- setup_start_tag();
- setup_memory_tags();
- setup_commandline_tag("noinitrd root=/dev/mtdblock3 init=/linuxrc console=ttySAC0");
- setup_end_tag();
-
-
- puts("Boot kernel\n\r");
- theKernel = (void (*)(int, int, unsigned int))0x30008000;
- theKernel(0, 362, 0x30000100);
-
-
-
-
-
-
-
- puts("Error!\n\r");
-
-
- return -1;
- }
Makefile
- CC = arm-linux-gcc
- LD = arm-linux-ld
- AR = arm-linux-ar
- OBJCOPY = arm-linux-objcopy
- OBJDUMP = arm-linux-objdump
-
- CFLAGS := -Wall -O2
- CPPFLAGS := -nostdinc -nostdlib -fno-builtin
-
- objs := start.o init.o boot.o
-
- boot.bin: $(objs)
- ${LD} -Tboot.lds -o boot.elf $^
- ${OBJCOPY} -O binary -S boot.elf $@
- ${OBJDUMP} -D -m arm boot.elf > boot.dis
-
- %.o:%.c
- ${CC} $(CPPFLAGS) $(CFLAGS) -c -o $@ $<
-
- %.o:%.S
- ${CC} $(CPPFLAGS) $(CFLAGS) -c -o $@ $<
-
- clean:
- rm -f *.o *.bin *.elf *.dis