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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

uboot启动内核

發布時間:2025/3/15 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 uboot启动内核 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1、操作系統運行起來后分為兩內核層和應用層。兩層的權限不同,內核可以直接訪問硬件,而應用層對硬件的訪問遭到了限制。

(uboot的鏡像是u-boot.bin,Linux的鏡像是zImage)

2、SD卡中的特定分區

在沒有上電時,bootloader(引導區)、kernel(內核)、rootfs(文件系統)等必要的軟件都以鏡像的形式存儲在SD中(存儲介質),運行時都是在DDR中,與其他外存介質無關。以上兩種狀態可以認為穩定狀態。而從靜止狀態到運行狀態的過程(啟動過程),可認為是動態過程。啟動過程就是從SD卡中把代碼搬移到DDR內存中運行,這些代碼就是進行相關硬件的初始化和軟件架構的建立,最終達到運行時的穩定狀態。未上電時,uboot.bin、ZImage、rootfs必須在SD中的特定位置存放,也就是說需要對SD卡進行分區,然后將各種鏡像存放在各自的分區中。uboot在啟動內核過程中傳參給內核時,這些分區參數不能傳錯。

3、運行時必須先加載到DDR的連接地址處

uboot在第一階段中進行重定位時將第二階段(整個uboot的鏡像)加載到DDR的0xC3E00000地址處,這個地址就是uboot的連接地址。一樣的,uboot在啟動內核時將內核鏡像從SD卡讀取存到DDR中,此時也必須存放到內核的鏈接地址處,否則啟動不起來。(內核鏈接地址0x30008000)

?

4、內核啟動需要必要的參數

uboot是無條件啟動的,而內核不能,內核需要uboot來幫助啟動。uboot要幫助內核實現重定位、給內核提供啟動參數。

5、啟動內核的第一步:加載內核到DDR中

Uboot如何啟動內核? 1)先將內核鏡像從啟動介質(SD卡)加載到DDR中。 2)到DDR中啟動內核鏡像(uboot的第二階段就是在DDR中運行的)。 內核的代碼不需要考慮重定位,因為這些uboot已經幫做好了,內核只需要從鏈接地址處開始運行就可以了。

6、如何獲取內核鏡像?

1)在SD卡/iNand/Nand/NorFlash等存儲介質。

如SD卡:uboot只需到SD卡kernel分區中讀取內核鏡像到DDR即可。讀取需要用uboot的命令來讀取。(x210的iNand版本是movi命令,Nand版本就是Nand命令)

movi read kernel 30008000

kernel 是SD卡的內核分區,30008000 是內核的鏈接地址。

2)tftp、nfs等網絡下載方式從服務器遠端獲取鏡像。

uboot還支持遠程啟動,也就是內核鏡像不燒錄到開發板的SD卡中等其他介質,而是放在主機的服務器中,然后啟動時uboot通過網絡從服務器中下載鏡像到開發板的DDR中。

tftp 30008000 zImage

7、如何知道內核的鏈接地址?

鏈接地址在內核源代碼的連接腳本或者Makefile中查找。

?

8、zImage和uImage的區別

bootm命令對應do_bootm函數,命令前加do_即可構成這個命令對應的函數,因此執行boot命令時,uboot實際執行的函數叫做do_bootm函數,在cmd_bootm.c文件內。

#if defined(CONFIG_SECURE_BOOT) 這個宏主要用來編譯一些簽名認證的代碼。

#ifdef CONFIG_ZIMAGE_BOOT ?這個條件用來支持zImage格式內核啟動的。

?

9、vmlinuz、zImage和uImage

1)uboot經過編譯生成的elf格式可執行文件為u-boot,類似于windows的exe格式,在操作系統下是可以直接運行的。但不能用來燒錄下載,燒錄時用u-boot.bin(也叫鏡像文件,用來燒錄到iNand中執行的)。U-boot.bin的來源:是由u-boot使用arm-linux-objcopy進行加工得到。

2)linux內核經過編譯后也會生成elf格式的可執行程序,叫vmlinux或vmlinuz。這個是原始未加工的原版內核elf格式文件。vmlinuz和zImage所在的目錄: ?~/x210v3_bsp/kernel/arch/arm/boot ?

在實際燒錄時不是vmlinuz/vmlinux,而是要用objcopy工具去制作成燒錄鏡像格式,Image格式(內核沒有.bin后綴)。Vmlinuz大概有78M而Image只有7.5M。但還是覺得Image太大了,所以實際使用時要對其壓縮,所以就有了zImage壓縮鏡像文件。

uImage和zImage是什么關系?uImage是由uboot對zImage加工得到的,加工的過程就是在zImage前面加上64k字節的頭信息。

uImage不關linux內核的事,linux內核只管生成zImage即可,然后uboot中的mkimage工具再去由zImage加工生成uImage來給uboot啟動。uboot中也可以支持zImage,是否支持就看x210_sd.h中是否定義了LINUX_ZIMAGE_MAGIC這個宏。

?

10、編譯內核得到uImage然后啟動

如果直接在kernel底下去make uImage會出現mkimage command not found。解決方案:去uboot/tools下cp mkimage /usr/local/bin/,復制mkimage工具到系統目錄下。再去make uImage即可。

#if defined(CONFIG_ZIMAGE_BOOT)

after_header_check:

396-397行后,才是真正的zImage啟動,之前都是進行鏡像的頭部信息校驗(判斷是哪種格式等)。

?

11、LINUX_ZIMAGE_MAGIC ?宏定義

#ifdef CONFIG_ZIMAGE_BOOT

#define LINUX_ZIMAGE_MAGIC ?0x016f2818

LINUX_ZIMAGE_MAGIC在這里稱作一個魔數,這個數等于0x016f2818表示這個鏡像是一個zImage。也就是說zImage格式的鏡像中在頭部的一個固定位置存放了這個數作為格式標記。

do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])函數。當執行bootm 0x30008000時,就是執行zImage啟動內核,此時do_bootm的argc=2,argv[0]=bootm ?argv[1]=0x30008000。也可以不帶參進行默認執行,默認執行的連接地址為CFG_LOAD_ADDR,此宏定義在x210_sd.h。如何判斷是zImage文件?zImage頭部開始的第37-40字節處存放著zImage標志魔數,從這個位置取出然后對比LINUX_ZIMAGE_MAGIC。

?

12、image_header_t 結構體

image_header_t *hdr;

typedef struct image_header {

uint32_t ih_magic; /* Image Header Magic Number */

uint32_t ih_hcrc; /* Image Header CRC Checksum */

uint32_t ih_time; /* Image Creation Timestamp */

uint32_t ih_size; /* Image Data Size */

uint32_t ih_load; /* Data ?Load ?Address */

uint32_t ih_ep; /* Entry Point Address */

uint32_t ih_dcrc; /* Image Data CRC Checksum */

uint8_t ih_os; /* Operating System */

uint8_t ih_arch; /* CPU architecture */

uint8_t ih_type; /* Image Type */

uint8_t ih_comp; /* Compression Type */

uint8_t ih_name[IH_NMLEN]; /* Image Name */

} image_header_t;

這個數據結構是uboot啟動內核時使用的一個標準啟動數據結構。zImage頭信息也是一個image_header_t,但是在實際啟動之前需要進行一些改造。hdr->ih_os = IH_OS_LINUX;

hdr->ih_ep = ntohl(addr);這兩句就是在進行改造。

static bootm_headers_t images; /*pointers to os/initrd/fdt images */

images全局變量是do_bootm函數中使用,用來完成啟動過程的。zImage的校驗過程其實就是先確認是不是zImage,確認后再修改zImage的頭信息到合適,修改后用頭信息去初始化images這個全局變量,然后就完成了校驗。

?

13、uImage啟動

case IMAGE_FORMAT_LEGACY:

type = image_get_type (os_hdr);

comp = image_get_comp (os_hdr);

os = image_get_os (os_hdr);

image_end = image_get_image_end (os_hdr);

load_start = image_get_load (os_hdr);

break;

以上代碼就是用來啟動uImage格式的。uImage方式是uboot本身發明的支持linux啟動的鏡像格式,但是后來這種方式被設備樹方式所取代了(在do_bootm方式中叫FIT)。uImage的啟動校驗主要在boot_get_kernel函數中,主要任務就是校驗uImage的頭信息,并且得到真正的kernel的起始位置去啟動。

uboot設計時只支持uImage啟動,后來有了fdt方式之后,就把uImage方式命令為LEGACY方式,fdt方式命令為FIT方式。第二階段校驗頭信息結束,然后進入第三階段,第三階段主要任務是調用do_bootm_linux函數啟動linux內核。

?

14、do_bootm_linux函數 和 鏡像的入口處entrypoint

此函數在uboot/lib_arm/bootm.c目錄下。ep就是entrypoint的縮寫,就是程序入口。一個鏡像文件的起始執行部分不是在鏡像的開頭(鏡像開頭有n個字節的頭信息),真正的鏡像文件執行時第一句代碼在鏡像的中部某個字節處,相當于頭是有一定的偏移量。一般執行一個鏡像都是:第一步先讀取頭信息,然后在頭信息的特定地址找MAGIC_NUM,由此來確定鏡像種類;第二步對鏡像進行校驗;第三步再次讀取頭信息,由特定地址知道這個鏡像的各種信息(鏡像長度、鏡像種類、入口地址);第四步就去entrypoint處開始執行鏡像。

theKernel = (void (*)(int, int, uint))ep;將ep賦值給theKernel,則這個函數指向就指向了內存中加載的OS鏡像的真正入口地址(就是操作系統的第一句執行的代碼)。

?

#if defined (CONFIG_SETUP_MEMORY_TAGS) || \

????defined (CONFIG_CMDLINE_TAG) || \

????defined (CONFIG_INITRD_TAG) || \

????defined (CONFIG_SERIAL_TAG) || \

????defined (CONFIG_REVISION_TAG) || \

????defined (CONFIG_LCD) || \

????defined (CONFIG_VFD) || \

????defined (CONFIG_MTDPARTITION)

setup_start_tag (bd);

給linux內核準備傳遞的參數處理。

?

?

15、傳參詳解

tag方式傳參

(1)struct tag,tag是一個數據結構,在uboot和linux kernel中都有定義tag數據機構,而且定義是一樣的。

(2)tag_header和tag_xxx。tag_header中有這個tag的size和類型編碼,kernel拿到一個tag后先分析tag_header得到tag的類型和大小,然后將tag中剩余部分當作一個tag_xxx來處理。

(3)tag_start與tag_end。kernel接收到的傳參是若干個tag構成的,這些tag由tag_start起始,到tag_end結束。

(4)tag傳參的方式是由linux kernel發明的,kernel定義了這種向我傳參的方式,uboot只是實現了這種傳參方式從而可以支持給kernel傳參。

16、x210_sd.h中配置傳參宏

(1)CONFIG_SETUP_MEMORY_TAGS,tag_mem,傳參內容是內存配置信息。

(2)CONFIG_CMDLINE_TAG,tag_cmdline,傳參內容是啟動命令行參數,也就是uboot環境變量的bootargs.

(3)CONFIG_INITRD_TAG

(4)CONFIG_MTDPARTITION,傳參內容是iNand/SD卡的分區表。

(5)起始tag是ATAG_CORE、結束tag是ATAG_NONE,其他的ATAG_XXX都是有效信息tag。

思考:內核如何拿到這些tag?

uboot最終是調用theKernel函數來執行linux內核的,uboot調用這個函數(其實就是linux內核)時傳遞了3個參數。這3個參數就是uboot直接傳遞給linux內核的3個參數,通過寄存器來實現傳參的。(第1個參數就放在r0中,第二個參數放在r1中,第3個參數放在r2中)第1個參數固定為0,第2個參數是機器碼,第3個參數傳遞的就是大片傳參tag的首地址。

2.7.7.3、移植時注意事項

(1)uboot移植時一般只需要配置相應的宏即可

(2)kernel啟動不成功,注意傳參是否成功。傳參不成功首先看uboot中bootargs設置是否正確,其次看uboot是否開啟了相應宏以支持傳參。

總結

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

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