do_bootm()函数个人注释

来源:互联网 发布:淘宝我的发票灰色的 编辑:程序博客网 时间:2024/06/06 23:51
int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]){ulongiflag;ulongaddr;ulongdata, len, checksum;ulong  *len_ptr;uintunc_len = CFG_BOOTM_LEN;inti, verify;char*name, *s;int(*appl)(int, char *[]);image_header_t *hdr = &header;/*为是否对镜像头做校验做准备,读取uboot的环境变量verify,如果环境变量verify等于’n’,则局部变量verify赋值成为0;如果环境变量verify为空(即没有定义环境变量verify)或者环境变量verify不等于’n’,则局部变量verify赋值成为1*/s = getenv ("verify");verify = (s && (*s == 'n')) ? 0 : 1;if (argc < 2) //获取镜像存放的内存首地址,如果参数个数小于2(即只是输入了bootm),使用缺省加载地址CFG_LOAD_ADDR。{addr = load_addr;} else  //否则使用第二个参数作为加载地址{addr = simple_strtoul(argv[1], NULL, 16);}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_DATAFLASHif (addr_dataflash(addr)){read_dataflash(addr, sizeof(image_header_t), (char *)&header);} else#endif//从镜像内存首地址读取镜像头部,为下面的分析校验做准备memmove (&header, (char *)addr, sizeof(image_header_t));//判断内核头部编号属性是否为IH_MAGIC,如果不是u-boot镜像识别的内核镜像格式,会输出提示信息”Bad Magic Number”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__ */  {puts ("Bad Magic Number\n");SHOW_BOOT_PROGRESS (-1);return 1;  }}SHOW_BOOT_PROGRESS (2);data = (ulong)&header;len  = sizeof(image_header_t);//对内核的镜像头部做CRC检验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_DATAFLASHif (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) //对镜像头部的数据做CRC校验{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;//检验CPU的类型#if defined(__PPC__)if (hdr->ih_arch != IH_CPU_PPC)#elif defined(__ARM__)if (hdr->ih_arch != IH_CPU_ARM)#elif defined(__I386__)if (hdr->ih_arch != IH_CPU_I386)#elif defined(__mips__)if (hdr->ih_arch != IH_CPU_MIPS)#elif defined(__nios__)if (hdr->ih_arch != IH_CPU_NIOS)#elif defined(__M68K__)if (hdr->ih_arch != IH_CPU_M68K)#elif defined(__microblaze__)if (hdr->ih_arch != IH_CPU_MICROBLAZE)#elif defined(__nios2__)if (hdr->ih_arch != IH_CPU_NIOS2)#elif defined(__blackfin__)if (hdr->ih_arch != IH_CPU_BLACKFIN)#elif defined(__avr32__)if (hdr->ih_arch != IH_CPU_AVR32)#else# error Unknown CPU type#endif{printf ("Unsupported Architecture 0x%x\n", hdr->ih_arch);SHOW_BOOT_PROGRESS (-4);return 1;}SHOW_BOOT_PROGRESS (5);switch (hdr->ih_type) {case IH_TYPE_STANDALONE:name = "Standalone Application";/* A second argument overwrites the load address */if (argc > 2) {hdr->ih_load = htonl(simple_strtoul(argv[2], NULL, 16));}break;case IH_TYPE_KERNEL:name = "Kernel Image";break;case IH_TYPE_MULTI:name = "Multi-File Image";len  = ntohl(len_ptr[0]);/* OS kernel is always the first image */data += 8; /* kernel_len + terminator */for (i=1; len_ptr[i]; ++i)data += 4;break;default: printf ("Wrong Image Type for %s command\n", cmdtp->name);SHOW_BOOT_PROGRESS (-5);return 1;}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();#endifswitch (hdr->ih_comp) //开始判断是否对内核进行了压缩{//首先清楚这几个地址的定义addr = CFG_LOAD_ADDR;  data = addr + sizeof(image_header_t);case IH_COMP_NONE:  //如果没有被压缩,只是在内核的前面加了一个头部信息//在利用mkimage时指定-a选项后面就是指定的内核加载的地址,这个地址会被存放到镜像头结构的ih_load成员变量中,如在smdk2410中ih_load为0x30008000//如果加载地址等于addr(即:bootm后面接的地址)就不移动内核,可以在这个addr上开始加载,此时的内核入口地址就是addr后的64字节,即dataif(ntohl(hdr->ih_load) == addr){ printf ("   XIP %s ... ", name);}/*ih_load不等于addr,此时:data=addr+64还是指向真正的内核部分,这时候就要将内核拷贝到ih_load指定的地方才能执行,这种情况ih_load==ih_ep加载地址等于内核的入口地址*/else {#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)size_t l = len;void *to = (void *)ntohl(hdr->ih_load);void *from = (void *)data;printf ("   Loading %s ... ", name);while (l > 0) {size_t tail = (l > CHUNKSZ) ? CHUNKSZ : l;WATCHDOG_RESET();memmove (to, from, tail);to += tail;from += tail;l -= tail;}#else/* !(CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG) */memmove ((void *) ntohl(hdr->ih_load), (uchar *)data, len);//内核移动函数:将data地址处的真正内核复制到指定的ih_load处#endif/* CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG */}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;#ifdef CONFIG_BZIP2//内核文件有压缩成bzip2格式情况:需要解压缩case IH_COMP_BZIP2:printf ("   Uncompressing %s ... ", name);/* * If we've got less than 4 MB of malloc() space, * use slower decompression algorithm which requires * at most 2300 KB of memory. */i = BZ2_bzBuffToBuffDecompress ((char*)ntohl(hdr->ih_load),&unc_len, (char *)data, len,CFG_MALLOC_LEN < (4096 * 1024), 0);if (i != BZ_OK) {printf ("BUNZIP2 ERROR %d - must RESET board to recover\n", i);SHOW_BOOT_PROGRESS (-6);udelay(100000);do_reset (cmdtp, flag, argc, argv);}break;#endif /* CONFIG_BZIP2 */default:if (iflag)enable_interrupts();printf ("Unimplemented compression type %d\n", hdr->ih_comp);SHOW_BOOT_PROGRESS (-7);return 1;}puts ("OK\n");SHOW_BOOT_PROGRESS (7);switch (hdr->ih_type) {case IH_TYPE_STANDALONE:if (iflag)enable_interrupts();/* load (and uncompress), but don't start if "autostart" * is set to "no" */if (((s = getenv("autostart")) != NULL) && (strcmp(s,"no") == 0)) {char buf[32];sprintf(buf, "%lX", len);setenv("filesize", buf);return 0;}appl = (int (*)(int, char *[]))ntohl(hdr->ih_ep);(*appl)(argc-1, &argv[1]);return 0;case IH_TYPE_KERNEL:case IH_TYPE_MULTI:/* handled below */break;default:if (iflag)enable_interrupts();printf ("Can't boot image type %d\n", hdr->ih_type);SHOW_BOOT_PROGRESS (-8);return 1;}SHOW_BOOT_PROGRESS (8);switch (hdr->ih_os) //确定内核的操作系统{default:/* handled by (original) Linux case */case IH_OS_LINUX: //选定为Linux操作系统#ifdef CONFIG_SILENT_CONSOLE    fixup_silent_linux();#endif//调用do_bootm_linux函数启动内核,接着分析armlinux.c文件下的这个函数,从这里传入的参数有:    do_bootm_linux  (cmdtp, flag, argc, argv,     addr, len_ptr, verify);    break;case IH_OS_NETBSD:    do_bootm_netbsd (cmdtp, flag, argc, argv,     addr, len_ptr, verify);    break;#ifdef CONFIG_LYNXKDIcase IH_OS_LYNXOS:    do_bootm_lynxkdi (cmdtp, flag, argc, argv,     addr, len_ptr, verify);    break;#endifcase IH_OS_RTEMS:    do_bootm_rtems (cmdtp, flag, argc, argv,     addr, len_ptr, verify);    break;#if (CONFIG_COMMANDS & CFG_CMD_ELF)case IH_OS_VXWORKS:    do_bootm_vxworks (cmdtp, flag, argc, argv,      addr, len_ptr, verify);    break;case IH_OS_QNX:    do_bootm_qnxelf (cmdtp, flag, argc, argv,      addr, len_ptr, verify);    break;#endif /* CFG_CMD_ELF */#ifdef CONFIG_ARTOScase IH_OS_ARTOS:    do_bootm_artos  (cmdtp, flag, argc, argv,     addr, len_ptr, verify);    break;#endif}SHOW_BOOT_PROGRESS (-9);#ifdef DEBUGputs ("\n## Control returned to monitor - resetting...\n");do_reset (cmdtp, flag, argc, argv);#endifreturn 1;}


0 0
原创粉丝点击