日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

uboot分析之bootm_start

發布時間:2024/9/3 编程问答 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 uboot分析之bootm_start 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

bootm命令執行過程中調用了bootm_start函數,這個函數比較重要,所以先分析它。

1.common/cmd_bootm.c

?
  • static?int?bootm_start(cmd_tbl_t?*cmdtp,?int?flag,?int?argc,?char?*argv[])??
  • {??
  • ????void????????*os_hdr;??
  • ????int?????ret;??
  • ????memset?((void?*)&images,?0,?sizeof?(images));//images是一個bootm_headers_t類型的全局變量。見下面的分析。???
  • ????images.verify?=?getenv_yesno?("verify");//從環境變量中檢查是否要對鏡像的數據(不是鏡像頭)進行校驗。???
  • ????bootm_start_lmb();//不做任何有意義的工作,除了定義#?define?lmb_reserve(lmb,?base,?size)???
  • ????/*?get?kernel?image?header,?start?address?and?length?*/尋找可用的內核鏡像,見下面的分析。主要根據傳入的參數檢查鏡像的合法性并獲取信息。??
  • ????os_hdr?=?boot_get_kernel?(cmdtp,?flag,?argc,?argv,??
  • ????????????&images,?&images.os.image_start,?&images.os.image_len);//返回指向內存中鏡像頭的指針???
  • ????if?(images.os.image_len?==?0)?{??
  • ????????puts?("ERROR:?can't?get?kernel?image!/n");??
  • ????????return?1;??
  • ????}??
  • ????/*?get?image?parameters?*/??
  • ????switch?(genimg_get_format?(os_hdr))?{//根據鏡像魔數獲取鏡像類型???
  • ????case?IMAGE_FORMAT_LEGACY:??
  • ????????images.os.type?=?image_get_type?(os_hdr);//鏡像類型???
  • ????????images.os.comp?=?image_get_comp?(os_hdr);//壓縮類型???
  • ????????images.os.os?=?image_get_os?(os_hdr);//操作系統類型???
  • ????????images.os.end?=?image_get_image_end?(os_hdr);//當前鏡像的尾地址???
  • ????????images.os.load?=?image_get_load?(os_hdr);//鏡像數據的載入地址???
  • ????????break;??
  • ????default:??
  • ????????puts?("ERROR:?unknown?image?format?type!/n");??
  • ????????return?1;??
  • ????}??
  • ????/*?find?kernel?entry?point?*/??
  • ????if?(images.legacy_hdr_valid)?{//如果鏡像已經通過驗證???
  • ????????images.ep?=?image_get_ep?(&images.legacy_hdr_os_copy);//獲取入口地址,填充images.ep?。???
  • ????}?else?{??
  • ????????puts?("Could?not?find?kernel?entry?point!/n");??
  • ????????return?1;??
  • ????}??
  • ????if?(((images.os.type?==?IH_TYPE_KERNEL)?||??
  • ?????????(images.os.type?==?IH_TYPE_MULTI))?&&??
  • ????????(images.os.os?==?IH_OS_LINUX))?{??
  • ????????/*?find?ramdisk?*/3250的配置中這個函數不做任何工作??
  • ????????ret?=?boot_get_ramdisk?(argc,?argv,?&images,?IH_INITRD_ARCH,??
  • ????????????????&images.rd_start,?&images.rd_end);??
  • ????????if?(ret)?{??
  • ????????????puts?("Ramdisk?image?is?corrupt?or?invalid/n");??
  • ????????????return?1;??
  • ????????}??
  • ????}??
  • ????images.os.start?=?(ulong)os_hdr;//指向內存中鏡像的頭地址???
  • ????images.state?=?BOOTM_STATE_START;//標記引導狀態???
  • ????return?0;??
  • }??
  • ?

    總結一下這個函數的主要工作:第一步校驗鏡像的正確性,獲取鏡像的信息(根據鏡像頭),第二部將第一步獲取的信息存入images(主要是填充image_info_t類型的os成員)

    2. bootm_headers_t

    ?
  • typedef?struct?bootm_headers?{??
  • ????/*?
  • ?????*?Legacy?os?image?header,?if?it?is?a?multi?component?image?
  • ?????*?then?boot_get_ramdisk()?and?get_fdt()?will?attempt?to?get?
  • ?????*?data?from?second?and?third?component?accordingly.?
  • ?????*/??
  • ????image_header_t????*legacy_hdr_os;????????/*?image?header?pointer?*/??
  • ????image_header_t????legacy_hdr_os_copy;????/*?header?copy?*/??
  • ????ulong????????legacy_hdr_valid;??
  • #ifndef?USE_HOSTCC???
  • ????image_info_t????os;????????/*?os?image?info?*/??
  • ????ulong????????ep;????????/*?entry?point?of?OS?*/??
  • ????ulong????????rd_start,?rd_end;/*?ramdisk?start/end?*/??
  • ????ulong????????ft_len;????????/*?length?of?flat?device?tree?*/??
  • ????ulong????????initrd_start;??
  • ????ulong????????initrd_end;??
  • ????ulong????????cmdline_start;??
  • ????ulong????????cmdline_end;??
  • ????bd_t????????*kbd;??
  • #endif???
  • ????int????????verify;????????/*?getenv("verify")[0]?!=?'n'?*/??
  • #define????BOOTM_STATE_START????????(0x00000001)???
  • #define????BOOTM_STATE_LOADOS????????(0x00000002)???
  • #define????BOOTM_STATE_RAMDISK????(0x00000004)???
  • #define????BOOTM_STATE_FDT????????(0x00000008)???
  • #define????BOOTM_STATE_OS_CMDLINE????(0x00000010)???
  • #define????BOOTM_STATE_OS_BD_T????(0x00000020)???
  • #define????BOOTM_STATE_OS_PREP????(0x00000040)???
  • #define????BOOTM_STATE_OS_GO????????(0x00000080)???
  • ????int????????state;??
  • }?bootm_headers_t;??
  • /*?
  • ?*?Legacy?format?image?header,?
  • ?*?all?data?in?network?byte?order?(aka?natural?aka?bigendian).?
  • ?*/內核鏡像頭??include/image.h??
  • typedef?struct?image_header?{??
  • ????uint32_t????ih_magic;????????/*?Image?Header?Magic?Number????*/鏡像頭部幻數,為#define?IH_MAGIC????0x27051956??
  • ????uint32_t????ih_hcrc;????????????/*?Image?Header?CRC?Checksum????*/鏡像頭部crc校驗碼??
  • ????uint32_t????ih_time;????????????/*?Image?Creation?Timestamp????*/鏡像創建時間戳??
  • ????uint32_t????ih_size;????????????/*?Image?Data?Size????????*/鏡像數據大小(不算頭部)1828536??
  • ????uint32_t????ih_load;????????????/*?Data?????Load??Address????????*/數據將要載入的內存地址???80008000??
  • ????uint32_t????ih_ep;????????????/*?Entry?Point?Address????????*/鏡像入口地址????????80008000?????????????
  • ????uint32_t????ih_dcrc;????????????/*?Image?Data?CRC?Checksum????*/鏡像數據校驗碼??
  • ????uint8_t????????ih_os;????????/*?Operating?System????????*/操作系統類型????#define?IH_OS_LINUX????????5??
  • ????uint8_t????????ih_arch;????????/*?CPU?architecture????????*/CPU架構類型????#define?IH_ARCH_ARM????????2??
  • ????uint8_t????????ih_type;????????/*?Image?Type????????????*/鏡像類型????????IH_TYPE_KERNEL??
  • ????uint8_t????????ih_comp;????/*?Compression?Type????????*/壓縮類型????????IH_COMP_NONE??
  • ????uint8_t????????ih_name[IH_NMLEN];????/*?Image?Name????????*/鏡像名字Linux-2.6.27.8,#define?IH_NMLEN????????32??
  • }?image_header_t;??
  • 鏡像信息??????include/image.h??
  • typedef?struct?image_info?{??
  • ????ulong????????start,?end;????????????/*?start/end?of?blob?*/鏡像的起始地址和尾地址??
  • ????ulong????????image_start,?image_len;?????????/*?start?of?image?within?blob,?len?of?image?*/鏡像數據的開始地址和長度??
  • ????ulong????????load;????????????????/*?load?addr?for?the?image?*/鏡像數據的裝載地址??
  • ????uint8_t????????comp,?type,?os;????????????/*?compression,?type?of?image,?os?type?*/壓縮類型,鏡像類型和操作系統類型??
  • }?image_info_t;??
  • ?

    3。boot_get_kernel

    ?
  • /**?
  • ?*?boot_get_kernel?-?find?kernel?image?
  • ?*?@os_data:?pointer?to?a?ulong?variable,?will?hold?os?data?start?address?
  • ?*?@os_len:?pointer?to?a?ulong?variable,?will?hold?os?data?length?
  • ?*?
  • ?*?boot_get_kernel()?tries?to?find?a?kernel?image,?verifies?its?integrity?
  • ?*?and?locates?kernel?data.?
  • ?*?
  • ?*?returns:?
  • ?*?????pointer?to?image?header?if?valid?image?was?found,?plus?kernel?start?
  • ?*?????address?and?length,?otherwise?NULL?
  • ?*/??
  • 尋找可用的內核鏡像??
  • static?void?*boot_get_kernel?(cmd_tbl_t?*cmdtp,?int?flag,?int?argc,?char?*argv[],??
  • ????????bootm_headers_t?*images,?ulong?*os_data,?ulong?*os_len)??
  • {??
  • ????image_header_t????*hdr;??
  • ????ulong????????img_addr;??
  • ????/*?find?out?kernel?image?address?*/??
  • ????if?(argc?<?2)?{//如果參數太少???
  • ????????img_addr?=?load_addr;????//使用默認的鏡像載入地址,這個地址是在配置頭文件中定義的?ulong?load_addr?=?CONFIG_SYS_LOAD_ADDR;???
  • ????????debug?("*??kernel:?default?image?load?address?=?0x%08lx/n",??
  • ????????????????load_addr);??
  • ????}?else?{??
  • ????????img_addr?=?simple_strtoul(argv[1],?NULL,?16);//參數足夠的話,把第二個參數轉化為16進制作為地址???
  • ????????debug?("*??kernel:?cmdline?image?address?=?0x%08lx/n",?img_addr);??
  • ????}??
  • ????show_boot_progress?(1);??
  • ????/*?copy?from?dataflash?if?needed?*/??
  • ????img_addr?=?genimg_get_image?(img_addr);//對于3250,這個函數什么都沒做。因為沒有dataflash.???
  • ????/*?check?image?type,?for?FIT?images?get?FIT?kernel?node?*/??
  • ????*os_data?=?*os_len?=?0;??
  • ????switch?(genimg_get_format?((void?*)img_addr))?{//根據上面得到的鏡像的地址,獲取鏡像的類型。這個函數根據鏡像頭部的魔數返回類型。???
  • ????case?IMAGE_FORMAT_LEGACY:??
  • ????????printf?("##?Booting?kernel?from?Legacy?Image?at?%08lx?.../n",???//打印引導消息???
  • ????????????????img_addr);??
  • ????????hdr?=?image_get_kernel?(img_addr,?images->verify);//檢驗鏡像的合法性(校驗碼、魔數、架構類型等),并打印信息。見下面的分析。???
  • ????????if?(!hdr)??
  • ????????????return?NULL;??
  • ????????show_boot_progress?(5);??
  • ????????/*?get?os_data?and?os_len?*/??
  • ????????switch?(image_get_type?(hdr))?{??
  • ????????case?IH_TYPE_KERNEL:??
  • ????????????*os_data?=?image_get_data?(hdr);//鏡像數據的地址,也就是緊挨著鏡像頭的地址。???
  • ????????????*os_len?=?image_get_data_size?(hdr);//鏡像數據部分大小???
  • ????????????break;??
  • ????????case?IH_TYPE_MULTI:??
  • ????????????image_multi_getimg?(hdr,?0,?os_data,?os_len);??
  • ????????????break;??
  • ????????case?IH_TYPE_STANDALONE:??
  • ????????????*os_data?=?image_get_data?(hdr);??
  • ????????????*os_len?=?image_get_data_size?(hdr);??
  • ????????????break;??
  • ????????default:??
  • ????????????printf?("Wrong?Image?Type?for?%s?command/n",?cmdtp->name);??
  • ????????????show_boot_progress?(-5);??
  • ????????????return?NULL;??
  • ????????}??
  • ????????/*?
  • ?????????*?copy?image?header?to?allow?for?image?overwrites?during?kernel?
  • ?????????*?decompression.?
  • ?????????*/拷貝一份鏡像的頭部到images中。??
  • ????????memmove?(&images->legacy_hdr_os_copy,?hdr,?sizeof(image_header_t));??
  • ????????/*?save?pointer?to?image?header?*/??
  • ????????images->legacy_hdr_os?=?hdr;//images中指針指向鏡像的頭部???
  • ????????images->legacy_hdr_valid?=?1;//鏡像已經檢驗合格,置標志量???
  • ????????show_boot_progress?(6);??
  • ????????break;??
  • ????default:??
  • ????????printf?("Wrong?Image?Format?for?%s?command/n",?cmdtp->name);??
  • ????????show_boot_progress?(-108);??
  • ????????return?NULL;??
  • ????}??
  • ????debug?("???kernel?data?at?0x%08lx,?len?=?0x%08lx?(%ld)/n",??
  • ????????????*os_data,?*os_len,?*os_len);??
  • ????return?(void?*)img_addr;??
  • }??
  • ?

    4。image_get_kernel

    ?
  • common/cmd_bootm.c??
  • static?image_header_t?*image_get_kernel?(ulong?img_addr,?int?verify)??
  • {??
  • ????image_header_t?*hdr?=?(image_header_t?*)img_addr;??
  • ????if?(!image_check_magic(hdr))?{????//檢查鏡像頭部的魔數是否等于?IH_MAGIC???
  • ????????puts?("Bad?Magic?Number/n");??
  • ????????show_boot_progress?(-1);??
  • ????????return?NULL;??
  • ????}??
  • ????show_boot_progress?(2);??
  • ????if?(!image_check_hcrc?(hdr))?{//檢查鏡像頭部的校驗碼(hcrc為0時鏡像頭的校驗碼)???
  • ????????puts?("Bad?Header?Checksum/n");??
  • ????????show_boot_progress?(-2);??
  • ????????return?NULL;??
  • ????}??
  • ????show_boot_progress?(3);??
  • ????image_print_contents?(hdr);//根據傳入的鏡像頭地址,打印鏡像的信息,見下面的分析。???
  • /*?
  • ???Image?Name:???Linux-2.6.27.8?
  • ???Image?Type:???ARM?Linux?Kernel?Image?(uncompressed)?
  • ???Data?Size:????1828536?Bytes?=?1.7?MiB?
  • ???Load?Address:?80008000?
  • ???Entry?Point:??80008000?
  • */??
  • ????if?(verify)?{//是否要對鏡像的數據部分進行校驗???
  • ????????puts?("???Verifying?Checksum?...?");??
  • ????????if?(!image_check_dcrc?(hdr))?{??
  • ????????????printf?("Bad?Data?CRC/n");??
  • ????????????show_boot_progress?(-3);??
  • ????????????return?NULL;??
  • ????????}??
  • ????????puts?("OK/n");??
  • ????}??
  • ????show_boot_progress?(4);??
  • ????if?(!image_check_target_arch?(hdr))?{//檢查是否是IH_ARCH_ARM架構???
  • ????????printf?("Unsupported?Architecture?0x%x/n",?image_get_arch?(hdr));??
  • ????????show_boot_progress?(-4);??
  • ????????return?NULL;??
  • ????}??
  • ????return?hdr;??
  • } ?
  • 總結

    以上是生活随笔為你收集整理的uboot分析之bootm_start的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。