在U-Boot源码阅读(六)大佬的命令这篇文章中,知道了内核的启动是通过命令nand read.i c0008000 80000 500000;bootm c0008000,先把flash的数据读到内存中,然后执行这段内存的命令。看上去bootm和go还是很相近的嘛。但是go仅仅是开始执行而已,并没做任何的操作。而内核的启动需要满足下列条件:
(1)CPU 寄存器的设置。
? R0=0。
? R1=机器类型ID;对于ARM 结构的CPU,其机器类型ID 可以参见linux/arch/arm/tools/mach-types。
? R2=启动参数标记列表在RAM 中起始基地址。
(2)CPU 工作模式。
? 必须禁止中断(IRQs 和FIQs)。
? CPU 必须为SVC 模式。
(3)Cache 和MMU 的设置。
? MMU 必须关闭。
? 指令Cache 可以打开也可以关闭。
? 数据Cache 必须关闭。
bootm命令:
- int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
- {
- ulong iflag;
- ulong addr;
- ulong data, len, checksum;
- ulong *len_ptr = NULL; /* not to make warning. by scsuh */
- uint unc_len = CFG_BOOTM_LEN;
- int i, verify;
- char *name, *s;
- int (*appl)(int, char *[]);
- image_header_t *hdr = &header;
- s = getenv ("verify");
- verify = (s && (*s == 'n')) ? 0 : 1;
- if (argc < 2) {
- addr = load_addr;
- } else {
- addr = simple_strtoul(argv[1], NULL, 16);
- }
- #ifdef CONFIG_ZIMAGE_BOOT
- #define LINUX_ZIMAGE_MAGIC 0x016f2818
- if (*(ulong *)(addr + 9*4) == LINUX_ZIMAGE_MAGIC) {
- printf("Boot with zImage\n");
- addr = virt_to_phys(addr);
- hdr->ih_os = IH_OS_LINUX;
- hdr->ih_ep = ntohl(addr);
- goto after_header_check;
- }
- #endif
- SHOW_BOOT_PROGRESS (1);
- printf ("## Booting image at %08lx ...\n", addr);
- /* Copy header so we can blank CRC field for re-calculation */
- #ifdef CONFIG_HAS_DATAFLASH
- if (addr_dataflash(addr)){
- read_dataflash(addr, sizeof(image_header_t), (char *)&header);
- } else
- #endif
- memmove (&header, (char *)addr, sizeof(image_header_t));
- if (ntohl(hdr->ih_magic) != IH_MAGIC) {
- #ifdef __I386__ /* correct image format not implemented yet - fake it */
- if (fake_header(hdr, (void*)addr, -1) != NULL) {
- /* to compensate for the addition below */
- addr -= sizeof(image_header_t);
- /* turnof verify,
- * fake_header() does not fake the data crc
- */
- verify = 0;
- } else
- #endif /* __I386__ */
- {
- #ifdef CONFIG_IMAGE_BOOT
- printf("Boot with Image\n");
- addr = virt_to_phys(addr);
- hdr->ih_os = IH_OS_LINUX;
- hdr->ih_ep = ntohl(addr);
- hdr->ih_comp = IH_COMP_NONE;
- goto after_header_check;
- #endif
- puts ("Bad Magic Number\n");
- SHOW_BOOT_PROGRESS (-1);
- return 1;
- }
- }
- SHOW_BOOT_PROGRESS (2);
- data = (ulong)&header;
- len = sizeof(image_header_t);
- checksum = ntohl(hdr->ih_hcrc);
- hdr->ih_hcrc = 0;
- if (crc32 (0, (uchar *)data, len) != checksum) {
- puts ("Bad Header Checksum\n");
- SHOW_BOOT_PROGRESS (-2);
- return 1;
- }
- SHOW_BOOT_PROGRESS (3);
- #ifdef CONFIG_HAS_DATAFLASH
- if (addr_dataflash(addr)){
- len = ntohl(hdr->ih_size) + sizeof(image_header_t);
- read_dataflash(addr, len, (char *)CFG_LOAD_ADDR);
- addr = CFG_LOAD_ADDR;
- }
- #endif
- /* for multi-file images we need the data part, too */
- print_image_hdr ((image_header_t *)addr);
- data = addr + sizeof(image_header_t);
- len = ntohl(hdr->ih_size);
- if (verify) {
- puts (" Verifying Checksum ... ");
- if (crc32 (0, (uchar *)data, len) != ntohl(hdr->ih_dcrc)) {
- printf ("Bad Data CRC\n");
- SHOW_BOOT_PROGRESS (-3);
- return 1;
- }
- puts ("OK\n");
- }
- SHOW_BOOT_PROGRESS (4);
- len_ptr = (ulong *)data;
- SHOW_BOOT_PROGRESS (5);
- switch (hdr->ih_type) {
- case IH_TYPE_STANDALONE:
- break;
- case IH_TYPE_KERNEL:
- name = "Kernel Image";
- break;
- case IH_TYPE_MULTI:
- break;
- }
- SHOW_BOOT_PROGRESS (6);
- /*
- * We have reached the point of no return: we are going to
- * overwrite all exception vector code, so we cannot easily
- * recover from any failures any more...
- */
- iflag = disable_interrupts();
- #ifdef CONFIG_AMIGAONEG3SE
- /*
- * We've possible left the caches enabled during
- * bios emulation, so turn them off again
- */
- icache_disable();
- invalidate_l1_instruction_cache();
- flush_data_cache();
- dcache_disable();
- #endif
- switch (hdr->ih_comp) {
- case IH_COMP_NONE:
- break;
- case IH_COMP_GZIP: //这里使用gzip对内核进行压缩
- printf (" Uncompressing %s ... ", name);
- if (gunzip ((void *)ntohl(hdr->ih_load), unc_len,
- (uchar *)data, &len) != 0) {
- puts ("GUNZIP ERROR - must RESET board to recover\n");
- SHOW_BOOT_PROGRESS (-6);
- do_reset (cmdtp, flag, argc, argv);
- }
- break;
- }
- puts ("OK\n");
- SHOW_BOOT_PROGRESS (7);
- switch (hdr->ih_type) {
- case IH_TYPE_STANDALONE:
- return 0;
- case IH_TYPE_KERNEL:
- case IH_TYPE_MULTI:
- /* handled below */
- break;
- default:
- return 1;
- }
- SHOW_BOOT_PROGRESS (8);
- #if defined(CONFIG_ZIMAGE_BOOT) || defined(CONFIG_IMAGE_BOOT)
- after_header_check:
- #endif
- switch (hdr->ih_os) {
- default: /* handled by (original) Linux case */
- case IH_OS_LINUX:
- #ifdef CONFIG_SILENT_CONSOLE
- fixup_silent_linux();
- #endif
- do_bootm_linux (cmdtp, flag, argc, argv,
- addr, len_ptr, verify);
- break;
- }
- SHOW_BOOT_PROGRESS (-9);
- return 1;
- }