今天早上看了一上午的bootloader簡單源碼,終於捋順了bootloader的執行過程,之前只是知道bootloader代碼會先被irom中的代碼拷貝到iram中一部分,然后執行這部分代碼,會把整個bootloader代碼拷貝到sdram中,最終在sdram執行剩下的代碼,而這段代碼會把kernel拷貝到sdram的某個地址,最終引導起來整個內核。但是我今天早上看代碼的時候看到一個問題,我所有的代碼都是自己動手實現的,只要一步一步按照順序來,不就可以實現么?為什么還要拷貝來拷貝去的。感覺直接按照跳轉的方式,跳轉值進行指令的跳轉就行,但是想過之后,我意識到自己真是無知了。比如說在irom中執行的時候,會有一次跳轉到iram中某一個地址,當然pc是肯定可以直接跳轉到指定的任何一個地址,但是在這個地址中沒有存放指令碼,這時候,肯定是一個有去無回的過程,不僅這樣,這個pc跳到這里后,就會很迷茫,前不着村,后不着店的,不知道自己的所去所從,就會死到這里。只有先把代碼拷貝到將要跳轉的地址中,pc指針才會順着跳轉后的指令繼續執行,也就是說每一個指令都要負責人,確保執行完這個指令后,一定要有另一個指令去接納pc。這樣pc才會一直活在我的代碼中。
下邊我就再把我更進一步了解到的bootloader執行過程再重新敘述一下:
我使用的是s5pv210芯片、K9K8G08U0A型號的nand flash
第一步:cpu啟動起來后,先來到0x00000000這個地址處(也就是irom的地址),此時會看到有一段代碼(這是irom中固定的代碼)在這里,這段代碼會找到bootloader的第一段代碼(以下就稱為BL1)存放的地址,由於BL1存放在nand flash中,不支持片上執行,所以irom會把這段代碼拷貝到iram中,
但是在拷貝之前,irom會先把iram的起始4個地址分別寫上一定的內容(不過通常只寫0x00地址為BL1所占空間的大小(一般是8k),而其他三個地址全寫為0),把BL1這段代碼拷貝到iram后,irom的使命就快要完成了,irom的最后一個任務就是把pc指針指向放BL1的那塊地址的起始位置,然后就按照這個地址的指令開始執行。
第二步:這個時候開始執行BL1的代碼。這段代碼的功能是初始化硬件,比如串口,內存,顯示器,按鍵等等。
在初始化所有需要初始化的硬件后,BL1還會有一個拷貝指令,就是要把bootloader拷貝到sdram中一般會把bootloader的代碼放到BLADD(表示為bootloader在sdram中存放的地址。
這時候BL1的使命也將要完成,於是,BL1會把pc指針跳轉到BL2的地址,此時所有要運行的代碼都在sdram中,這次的跳轉不會直接從這次拷貝的開始地址執行,而是跳過BL1代碼所占的地址,從BL2開始執行。
第三步:執行BL2中的代碼。此時BL2代碼的功能主要是實現MTD設備驅動初始化,電源、時鍾初始化,堆棧空間,以及各種必要的初始化,並且會提供一個命令行,可以進行交互。在這之后會有一個設置內核參數的過程,這些參數在內存中的存在方式也是以結構體存儲,以鏈表進行關聯的,而這個 鏈表有一個固定的起始地址-0x3000_0100;每一個結構體代表一個信息,並首尾相連,內核在需要這些參數時,就可以再對應的地址上取數據。這一步執行完畢后,就要把kernel的代碼拷貝到sdram中的一個指定地址,並且會把這個地址強制轉換成一個函數指針,並且向這個函數中傳遞一些參數,最終會到內核中執行內核代碼。這個時候,內核就會被引導到執行狀態。
這就是我今天大半天的心得,寫出來,看到這篇文章的你,肯定也是對這方面感興趣的,希望可以互相交流,盡情來吐槽我的這篇文章吧,把你所認為不對或者我沒有想到的內容告訴我,大家共同進步!