我们知道,在u-boot中可以使用bootm这个命令来引导uclinux内核,那么其具体的过程是怎样的呢?1.1.1bootm的命令参数通过helpbootm命令可以知道bootm所带的参数,以下内容来自于u-boot/common/cmd-bootm.c:U_BOOT_CMD(bootm,CFG_MAXARGS,1,do_bootm,"bootm-bootapplicationimagefrommemory\n","[addr[arg...]]\n-bootapplicationimagestoredinmemory\n""\tpassingarguments'arg...';whenbootingaLinuxkernel,\n""\t'arg'canbetheaddressofaninitrdimage\n");从这里可以知道,bootm后面可以带两个参数,一个是内核所在的地址,这个地址就是通过tftp或者loadx指令下载内核时的存放地址,另一个可以指明initrd所处的位置。1.1.2do_bootm在u-boot检测到bootm命令后,它将调用do_bootm这个函数进行内核引导:intdo_bootm(cmd_tbl_t*cmdtp,intflag,intargc,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;/*1、提取命令行中的地址参数。*/s=getenv("verify");verify=(s&&(*s=='n'))?0:1;if(argc<2){addr=load_addr;}else{addr=simple_strtoul(argv[1],NULL,16);}SHOW_BOOT_PROGRESS(1);printf("##Bootingimageat%08lx...\n",addr);/*CopyheadersowecanblankCRCfieldforre-calculation*/memmove(&header,(char*)addr,sizeof(image_header_t));/*2、检测内核文件头的签名是否有效。*/if(ntohl(hdr->ih_magic)!=IH_MAGIC){{puts("BadMagicNumber\n");SHOW_BOOT_PROGRESS(-1);return1;}}SHOW_BOOT_PROGRESS(2);/*3、通过CRC校验确定文件是否损坏。*/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("BadHeaderChecksum\n");SHOW_BOOT_PROGRESS(-2);return1;}SHOW_BOOT_PROGRESS(3);/*4、输出内核文件头的信息。*//*formulti-fileimagesweneedthedatapart,too*/print_image_hdr((image_header_t*)addr);data=addr+sizeof(image_header_t);len=ntohl(hdr->ih_size);if(verify){puts("VerifyingChecksum...");if(crc32(0,(uchar*)data,len)!=ntohl(hdr->ih_dcrc)){printf("BadDataCRC\n");SHOW_BOOT_PROGRESS(-3);return1;}puts("OK\n");}SHOW_BOOT_PROGRESS(4);/*5、检验内核是否为此ARCH编译的。*/len_ptr=(ulong*)data;if(hdr->ih_arch!=IH_CPU_BLACKFIN){printf("UnsupportedArchitecture0x%x\n",hdr->ih_arch);SHOW_BOOT_PROGRESS(-4);return1;}SHOW_BOOT_PROGRESS(5);/*6、判断文件类型,对于uclinux内核,其值为IH_TYPE_KERNEL。*/switch(hdr->ih_type){caseIH_TYPE_STANDALONE:name="StandaloneApplication";/*Asecondargumentoverwritestheloadaddress*/if(argc>2){hdr->ih_load=htonl(simple_strtoul(argv[2],NULL,16));}break;caseIH_TYPE_KERNEL:name="KernelImage";break;caseIH_TYPE_MULTI:name="Multi-FileImage";len=ntohl(len_ptr[0]);/*OSkernelisalwaysthefirstimage*/data+=8;/*kernel_len+terminator*/for(i=1;len_ptr[i];++i)data+=4;break;default:printf("WrongImageTypefor%scommand\n",cmdtp->name);SHOW_BOOT_PROGRESS(-5);return1;}SHOW_BOOT_PROGRESS(6);/**Wehavereachedthepointofnoreturn:wearegoingto*overwriteallexceptionvectorcode,sowecannoteasily*recoverfromanyfailuresanymore...*//*7、将内核解压缩到文件头中指定的LoadAddress,从这里也可以知道,下载地址和文件头中的LoadAddress之间应该有足够的空间,否则将造成解压缩的失败。*/iflag=disable_interrupts();switch(hdr->ih_comp){caseIH_COMP_NONE:if(ntohl(hdr->ih_load)==addr){printf("XIP%s...",name);}else{memmove((void*)ntohl(hdr->ih_load),(uchar*)data,len);}break;caseIH_COMP_GZIP:printf("Uncompressing%s...",name);if(gunzip((void*)ntohl(hdr->ih_load),unc_len,(uchar*)data,&len)!=0){puts("GUNZIPERROR-mu...