Bootm的流程分析.docx

上传人:b****5 文档编号:6187546 上传时间:2023-01-04 格式:DOCX 页数:18 大小:53.34KB
下载 相关 举报
Bootm的流程分析.docx_第1页
第1页 / 共18页
Bootm的流程分析.docx_第2页
第2页 / 共18页
Bootm的流程分析.docx_第3页
第3页 / 共18页
Bootm的流程分析.docx_第4页
第4页 / 共18页
Bootm的流程分析.docx_第5页
第5页 / 共18页
点击查看更多>>
下载资源
资源描述

Bootm的流程分析.docx

《Bootm的流程分析.docx》由会员分享,可在线阅读,更多相关《Bootm的流程分析.docx(18页珍藏版)》请在冰豆网上搜索。

Bootm的流程分析.docx

Bootm的流程分析

Bootm的流程分析

Bootm的流程分析

一、在开始之前先说明一下bootm相关的东西。

1、首先说明一下,S3C2410架构下的bootm只对sdram中的内核镜像文件进行操作(好像AT91架构提供了一段从flash复制内核镜像的代码,不过针对s3c2410架构就没有这段代码,虽然可以在u-boot下添加这段代码,不过好像这个用处不大),所以请确保你的内核镜像下载到sdram中,或者在bootcmd下把flash中的内核镜像复制到sdram中。

2、-a参数后是内核的运行地址,-e参数后是入口地址。

3、

1)如果我们没用mkimage对内核进行处理的话,那直接把内核下载到0x30008000再运行就行,内核会自解压运行(不过内核运行需要一个tag来传递参数,而这个tag建议是由bootloader提供的,在u-boot下默认是由bootm命令建立的)。

2)如果使用mkimage生成内核镜像文件的话,会在内核的前头加上了64byte的信息,供建立tag之用。

bootm命令会首先判断bootmxxxx这个指定的地址xxxx是否与-a指定的加载地址相同。

(1)如果不同的话会从这个地址开始提取出这个64byte的头部,对其进行分析,然后把去掉头部的内核复制到-a指定的load地址中去运行之

(2)如果相同的话那就让其原封不同的放在那,但-e指定的入口地址会推后64byte,以跳过这64byte的头部。

bootm用于加载并启动U-Boot能辨识的操作系统映像,即bootm加载的映像必须是用mkimage工具打过包的映像,bootm不能启动直接的内核映像,因为bootm必须从映像的头获取映像的一些信息,比如操作系统的类型,映像是否压缩,映像的加载地址和压缩地址等。

更详细的映像头信息可以查看mkimage工具的说明。

而bootm的详细用法可通过helpbootm

获得。

=>helpbootm

bootm[addr[arg...]]

-bootapplicationimagestoredinmemorypassingarguments'arg...';whenbootingaLinux

kernel,'arg'canbetheaddressofaninitrdimage

Bootm用于将内核映像加载到指定的地址,如果需要还要进行解压映像。

然后根据操作系统和体系结构的不同给内核传递不同的内核参数,最后启动内核。

bootm可以有两个参数,第一个参数为内核映像的地址,它可以是RAM地址或者Flash地址。

第二个参数是可选参数,即initrd映像的地址,当采用Ramdisk作为根文件系统时需要使用bootm的第二个参数。

当需要加载initrd映像时,首先U-Boot把内核映像加载到指定地址,然后再把Ramdisk映像加载到指定地址,同时把Ramdisk映像的大小和地址告知内核。

Bootm命令后U-Boot会将控制权交给Kernel。

common/cmd_bootm.c是bootm的命令实现代码,下面结合U-Boob引导内核启动信息来分析bootm代码,下面是我的开发板的启动信息:

U-Boot2009.11(Jun252010-08:

28:

06)

DRAM:

64MB

Flash:

2MB

NAND:

64MiB

In:

serial

Out:

serial

Err:

serial

Net:

dm9000

Hitanykeytostopautoboot:

0

NANDread:

device0offset0x80000,size0x500000

5242880bytesread:

OK

##BootingkernelfromLegacyImageat30008000...

ImageName:

mark

Created:

2010-07-0215:

37:

07UTC

ImageType:

ARMLinuxKernelImage(uncompressed)

DataSize:

1800624Bytes=1.7MB

LoadAddress:

30008000

EntryPoint:

30008040

VerifyingChecksum...OK

XIPKernelImage...OK

OK

Startingkernel...

UncompressingLinux..................................................................................................................done,bootingthekernel.

Linuxversion2.6.29.1(root@ubuntu)(gccversion4.3.2(SourceryG++Lite2008q3-72))#64FriJul208:

30:

03PDT2010

CPU:

ARM920T[41129200]revision0(ARMv4T),cr=c0007177

CPU:

VIVTdatacache,VIVTinstructioncache

Machine:

Study-S3C2440

Memorypolicy:

ECCdisabled,Datacachewriteback

cmd_bootm.c

先分析bootm命令在U-Boot中是如何添加的:

U_BOOT_CMD(

bootm,CONFIG_SYS_MAXARGS,1,do_bootm,

"bootapplicationimagefrommemory",

"[addr[arg...]]\n-bootapplicationimagestoredinmemory\n"

"\tpassingarguments'arg...';whenbootingaLinuxkernel,\n"

"\t'arg'canbetheaddressofaninitrdimage\n"

#ifdefined(CONFIG_OF_LIBFDT)

"\tWhenbootingaLinuxkernelwhichrequiresaflatdevice-tree\n"

"\tathirdargumentisrequiredwhichistheaddressofthe\n"

"\tdevice-treeblob.Tobootthatkernelwithoutaninitrdimage,\n"

"\tusea'-'forthesecondargument.Ifyoudonotpassathird\n"

"\tabd_infostructwillbepassedinstead\n"

#endif

#ifdefined(CONFIG_FIT)

"\t\nForthenewmulticomponentuImageformat(FIT)addresses\n"

"\tmustbeextenedtoincludecomponentorconfigurationunitname:

\n"

"\taddr:

-directcomponentimagespecification\n"

"\taddr#-configurationspecification\n"

"\tUseiminfocommandtogetthelistofexistingcomponent\n"

"\timagesandconfigurations.\n"

#endif

"\nSub-commandstodopartofthebootmsequence.Thesub-commands"

"mustbe\n"

"issuedintheorderbelow(it'soktonotissueallsub-commands):

\n"

"\tstart[addr[arg...]]\n"

"\tloados-loadOSimage\n"

#ifdefined(CONFIG_PPC)||defined(CONFIG_M68K)||defined(CONFIG_SPARC)

"\tramdisk-relocateinitrd,setenvinitrd_start/initrd_end\n"

#endif

#ifdefined(CONFIG_OF_LIBFDT)

"\tfdt-relocateflatdevicetree\n"

#endif

"\tcmdline-OSspecificcommandlineprocessing/setup\n"

"\tbdt-OSspecificbd_tprocessing\n"

"\tprep-OSspecificprepbeforerelocationorgo\n"

"\tgo-startOS"

);

宏U_BOOT_CMD用于定义U-Boot命令,它的定义如下:

#defineU_BOOT_CMD(name,maxargs,rep,cmd,usage,help)\

cmd_btl_t__u_boot_cmd##nameStruct_Section={#name,maxargs,rep,cmd,usage,help|

#defineStructSection__attribute__((unused,section(".u_boot_cmd")))

宏U_BOOT_CMD展开后如下所示:

cmd_tlb_t__u_boot_cmd_bootm__a

见—嵌入式liinux应用开发完全手册

do_bootm函数分析

staticboot_os_fn*boot_os[]={

#ifdefCONFIG_BOOTM_LINUX

[IH_OS_LINUX]=do_bootm_linux,//由于我使用的是linux内核,编译时将会选择该函数

#endif

intdo_bootm(cmd_tbl_t*cmdtp,intflag,intargc,char*argv[])//这里的argc和argv就是bootm命令行参数

{

boot_os_fn*boot_fn;//定义跳转到操作系统执行的指针

if(bootm_start(cmdtp,flag,argc,argv))//调用bootm_start函数

return1;

iflag=disable_interrupts();//禁止中断

ret=bootm_load_os(images.os,&load_end,1);//调用bootm_load_os函数

boot_fn=boot_os[images.os.os];//根据OS类型去选择启动操作系统的函数

boot_fn(0,argc,argv,&images);//执行do_bootm_linux函数

}

do_bootm函数中调用的几个重要的函数是bootm_start、bootm_load_os、do_bootm_linux,下面一一分析。

bootm_start

staticbootm_headers_timages;/*pointerstoos/initrd/fdtimages*/

staticintbootm_start(cmd_tbl_t*cmdtp,intflag,intargc,char*argv[])

{

void*os_hdr;

/*getkernelimageheader,startaddressandlength*/

os_hdr=boot_get_kernel(cmdtp,flag,argc,argv,

&images,&images.os.image_start,&images.os.image_len);

….

/*getimageparameters*/

switch(genimg_get_format(os_hdr)){//获取image头格式类型

caseIMAGE_FORMAT_LEGACY:

//老的image头格式

images.os.type=image_get_type(os_hdr);//获取image的类型

p=image_get_comp(os_hdr);//获取image的压缩类型

images.os.os=image_get_os(os_hdr);//获取image的OS类型

images.os.end=image_get_image_end(os_hdr);//获取image开始地址

images.os.load=image_get_load(os_hdr);//获取image结束地址

break;

/*findkernelentrypoint*/

if(images.legacy_hdr_valid){

images.ep=image_get_ep(&images.legacy_hdr_os_copy);//获取image入口指针

}

ulongload_addr=CONFIG_SYS_LOAD_ADDR;/*DefaultLoadAddress*/

//寻找内核映像、校验它的完整性和定位内核数据位置

staticvoid*boot_get_kernel(cmd_tbl_t*cmdtp,intflag,intargc,char*argv[],

bootm_headers_t*images,ulong*os_data,ulong*os_len)

{

image_header_t*hdr;

/*findoutkernelimageaddress*/

if(argc<2){//bootm命令后面不带参数时

img_addr=load_addr;//使用默认加载地址

debug("*kernel:

defaultimageloadaddress=0x%08lx\n",

load_addr);

switch(genimg_get_format((void*)img_addr)){//获取image头类型

caseIMAGE_FORMAT_LEGACY:

//早期的image头类型

printf("##BootingkernelfromLegacyImageat%08lx...\n",img_addr);//该打印信息出现在U-Boot启动信息里

hdr=image_get_kernel(img_addr,images->verify);//获取image头

}

//校验早期格式内核映像

staticimage_header_t*image_get_kernel(ulongimg_addr,intverify)

{

image_header_t*hdr=(image_header_t*)img_addr;

if(!

image_check_magic(hdr)){//校验MAGICnumber

puts("BadMagicNumber\n");

show_boot_progress(-1);

returnNULL;

}

show_boot_progress

(2);

if(!

image_check_hcrc(hdr)){//image头校验

puts("BadHeaderChecksum\n");

show_boot_progress(-2);

returnNULL;

}

show_boot_progress(3);

image_print_contents(hdr);//该函数内将打印imag头信息“

ImageName:

mark

Created:

2010-07-0215:

37:

07UTC

ImageType:

ARMLinuxKernelImage(uncompressed)

DataSize:

1800624Bytes=1.7MB

LoadAddress:

30008000

EntryPoint:

30008040

if(verify){

puts("VerifyingChecksum...");//出现在U-Boot启动信息中

if(!

image_check_dcrc(hdr)){//校验image数据

printf("BadDataCRC\n");

show_boot_progress(-3);

returnNULL;

}

puts("OK\n");//出现在U-Boot启动信息中

}

show_boot_progress(4);

if(!

image_check_target_arch(hdr)){//ARM、i386、MIPS等架构检查

printf("UnsupportedArchitecture0x%x\n",image_get_arch(hdr));

show_boot_progress(-4);

returnNULL;

}

returnhdr;

}

//打印image头信息

voidimage_print_contents(constvoid*ptr)

{

constimage_header_t*hdr=(constimage_header_t*)ptr;

constchar*p;

#ifdefUSE_HOSTCC

p="";

#else

p="";//打印空格

#endif

//打印image名字

printf("%sImageName:

%.*s\n",p,IH_NMLEN,image_get_name(hdr));

#ifdefined(CONFIG_TIMESTAMP)||defined(CONFIG_CMD_DATE)||defined(USE_HOSTCC)

printf("%sCreated:

",p);//打印image创建日期

genimg_print_time((time_t)image_get_time(hdr));

#endif

printf("%sImageType:

",p);//打印image类型

image_print_type(hdr);

printf("%sDataSize:

",p);//打印image大小

genimg_print_size(image_get_data_size(hdr));

printf("%sLoadAddress:

%08x\n",p,image_get_load(hdr));//打印image加载地址

printf("%sEntryPoint:

%08x\n",p,image_get_ep(hdr));//打印image入口指针

}

typedefstructbootm_headers{

/*

*Legacyosimageheader,ifitisamulticomponentimage

*thenboot_get_ramdisk()andget_fdt()willattempttoget

*datafromsecondandthirdcomponentaccordingly.

*/

image_header_t*legacy_hdr_os;/*imageheaderpointer*/

image_header_tlegacy_hdr_os_copy;/*headercopy*/

ulonglegacy_hdr_valid;

#ifndefUSE_HOSTCC

image_info_tos;/*osimageinfo*/

ulongep;/*entrypointofOS*/

ulongrd_start,rd_end;/*ramdiskstart/end*/

ulongft_len;/*lengthofflatdevicetree*/

ulonginitrd_start;

ulonginitrd_end;

ulongcmdline_start;

ulongcmdline_end;

bd_t*kbd;

#endif

intverify;/*getenv("verify")[0]!

='n'*/

#defineBOOTM_STATE_START(0x00000001)

#defineBOOTM_STATE_LOADOS(0x00000002)

#defineBOOTM_STATE_RAMDISK(0x00000004)

#defineBOOTM_STATE_FDT(0x00000008)

#defineBOOTM_STATE_OS_CMDLINE(0x00000010)

#defineBOOTM_STATE_OS_BD_T(0x00000020)

#defineBOOTM_STATE_OS_PREP(0x00000040)

#defineBOOTM_STATE_OS_GO(0x00000080)

intstate;

#ifndefUSE_HOSTCC

structlmblmb;/*formemorymgmt*/

#endif

}bootm_headers_t;

 

bootm_load_os

staticintbootm_load_os(image_info_tos,ulong*load_end,intbo

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 经管营销 > 人力资源管理

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1