u-boot中SPL源代碼分析
[Author: Bo Shen <voice.shen@gmail.com>
[u-boot: 2014.01-rc1]
本文將使用sama5d3xek SPL實現做為例子,具體代碼可查看:https://github.com/voiceshen/u-boot/tree/sama5d3xek_spl_spi_nand
u-boot SPL (second program loader), 對許多人來說也說很陌生。下面對此進行一個簡單介紹。
1. ARM SoC的啟動過程:
RomBoot --> SPL --> u-boot --> Linux kernel --> file system --> start application
(RomBoot是固化在SoC內部的。)
u-boot實現了一個新功能,能在編譯u-boot的同時生成SPL二進制文件。
2. SPL運行代碼go through
從u-boot-spl.lds鏈接文件可知,啟動代碼也是start.S。
(reset) <arch/arm/cpu/armv7/start.S> (b lowlevel_init: arch/arm/cpu/armv7/lowlevel_init.S) (b _main) --> <arch/arm/lib/crt0.S> (bl board_init_f) --> <arch/arm/lib/spl.c> (board_init_r) --> <common/spl/spl.c> (jump_to_image_no_args去啟動u-boot) 到此SPL的生命周期結束。
簡單來講:SPL所做工作,一些硬體的初始化,然後讀取u-boot,最後調轉至u-boot。
3. 下面具體分析SPL的相關代碼。
<arch/arm/cpu/armv7/start.S>
110 reset:
111 bl save_boot_params
112/*
113 * disable interrupts (FIQ and IRQ), also set the cpu to SVC32 mode,
114 * except if in HYP mode already
115 */
116 mrs r0, cpsr
117and r1, r0,#0x1f @ mask mode bits
118 teq r1,#0x1a @ test for HYP mode
119 bicne r0, r0,#0x1f @ clear all mode bits
120 orrne r0, r0,#0x13 @ set SVC mode
121 orr r0, r0,#0xc0 @ disable FIQ and IRQ
122 msr cpsr,r0
123
124/*
125 * Setup vector:
126 * (OMAP4 spl TEXT_BASE is not 32 byte aligned.
127 * Continue to use ROM code vector only in OMAP4 spl)
128 */
129#if !(defined(CONFIG_OMAP44XX) && defined(CONFIG_SPL_BUILD))
130/* Set V=0 in CP15 SCTRL register - for VBAR to point to vector */
131 mrc p15,0, r0, c1, c0,0@Read CP15 SCTRL Register
132 bic r0,#CR_V @ V = 0
133 mcr p15,0, r0, c1, c0,0@Write CP15 SCTRL Register
134
135/* Set vector address in CP15 VBAR register */
136 ldr r0,=_start
137 mcr p15,0, r0, c12, c0,0@Set VBAR
138#endif
139
140/* the mask ROM code should have PLL and others stable */
141#ifndef CONFIG_SKIP_LOWLEVEL_INIT
142 bl cpu_init_cp15
143 bl cpu_init_crit
144#endif
145
146 bl _main
111:如果沒有重新定義save_boot_params,則使用<arch/arm/cpu/armv7/start.S>中的save_boot_params。其不做任何事情,直接返回。
116~138: 看注釋即可明白。
141: 因為SPL主要是對SoC進行初始化,所以不會定義CONFIG_SKIP_LOWLEVE_INIT, 即142,143行得以執行。
142: cpu_init_cpu15, 主要作用invalidate L1 I/D cache, disable MMU. 檢查是否需要workaround。
143: cpu_init_crit直接跳轉到lowlevel_init
下面看看lowlevel_init的實現:
<arch/arm/cpu/armv7/lowlevel_init.S>
18 ENTRY(lowlevel_init)
19/*
20 * Setup a temporary stack
21 */
22 ldr sp,=CONFIG_SYS_INIT_SP_ADDR
23 bic sp, sp,#7 /* 8-byte alignment for ABI compliance */
24#ifdef CONFIG_SPL_BUILD
25 ldr r9,=gdata
26#else
27sub sp,#GD_SIZE
28 bic sp, sp,#7
29 mov r9, sp
30#endif
31/*
32 * Save the old lr(passed in ip) and the current lr to stack
33 */
34 push {ip, lr}
35
36/*
37 * go setup pll, mux, memory
38 */
39 bl s_init
40 pop {ip, pc}
41 ENDPROC(lowlevel_init)
22: 對stack pointer賦值成CONFIG_SYS_INIT_SP_ADDR
23: 確保sp是8位元組對齊。
25:將gdata的地址存入到r9寄存器中。
39:跳轉到s_init。對Atmel sama5d3xek board, s_init定義在:<arch/arm/cpu/at91-common/spl.c> 此處暫時不分析。
然後返回到start.S處,接下來調用:bl _main到<arch/arm/lib/crt0.S>
58 ENTRY(_main)
59
60/*
61 * Set up initial C runtime environment and call board_init_f(0).
62 */
63
64#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK)
65 ldr sp,=(CONFIG_SPL_STACK)
66#else
67 ldr sp,=(CONFIG_SYS_INIT_SP_ADDR)
68#endif
69 bic sp, sp,#7 /* 8-byte alignment for ABI compliance */
70sub sp,#GD_SIZE /* allocate one GD above SP */
71 bic sp, sp,#7 /* 8-byte alignment for ABI compliance */
72 mov r9, sp /* GD is above SP */
73 mov r0,#0
74 bl board_init_f
65: 重新對SP賦值
69: 確認sp是8字對齊
70:相當於保留一個global_data的大小。
71: 確認更新後的sp是8字對齊
72:r9指向global_data
73:r0賦值0
74:跳轉到board_init_f中運行。
board_init_f在<arch/arm/lib/spl.c>定義:
20/*
21 * In the context of SPL, board_init_f must ensure that any clocks/etc for
22 * DDR are enabled, ensure that the stack pointer is valid, clear the BSS
23 * and call board_init_f. We provide this version by default but mark it
24 * as __weak to allow for platforms to do this in their own way if needed.
25 */
26void __weak board_init_f(ulong dummy)
27{
28/* Clear the BSS. */
29 memset(__bss_start,0, __bss_end - __bss_start);
30
31/* Set global data pointer. */
32 gd =&gdata;
33
34 board_init_r(NULL,0);
35}
26: board_init_f是一個弱函數,是可以被重新定義的。
29:對BSS段進行清零操作。
34: 跳轉到board_init_r
board_init_r在<common/spl/spl.c>中定義:
132void board_init_r(gd_t*dummy1,ulong dummy2)
133{
134 u32 boot_device;
135 debug(">>spl:board_init_r()\n");
136
137#ifdef CONFIG_SYS_SPL_MALLOC_START
138 mem_malloc_init(CONFIG_SYS_SPL_MALLOC_START,
139 CONFIG_SYS_SPL_MALLOC_SIZE);
140#endif
141
142#ifndef CONFIG_PPC
143/*
144 * timer_init() does not exist on PPC systems. The timer is initialized
145 * and enabled (decrementer) in interrupt_init() here.
146 */
147 timer_init();
148#endif
149
150#ifdef CONFIG_SPL_BOARD_INIT
151 spl_board_init();
152#endif
135: 輸出debug信息:>>spl:board_init_r();
137~140: 如果定義了:CONFIG_SYS_SPL_MALLOC_START, 則進行memory的malloc池初始化。以後調用malloc就在這個池子裡面分配內存。
142~148: 如果沒有定義:CONFIG_PPC, 則進行timer的初始化:timer_init() <arm/arm/cpu/armv7/at91/time.c>
150~150: CONFIG_SPL_BOARD_INIT, 則調用spl_board_init(). 這是board相關的定義,<board/atmel/sama5d3xek/sama5d3xek.c>
一切就緒後,就要檢查從什麼設備來啟動了。這裡就貼出RAM,MMC, NAND相關代碼
154 boot_device = spl_boot_device();
155 debug("boot device - %d\n", boot_device);
156switch(boot_device){
157#ifdef CONFIG_SPL_RAM_DEVICE
158case BOOT_DEVICE_RAM:
159 spl_ram_load_image();
160break;
161#endif
162#ifdef CONFIG_SPL_MMC_SUPPORT
163case BOOT_DEVICE_MMC1:
164case BOOT_DEVICE_MMC2:
165case BOOT_DEVICE_MMC2_2:
166 spl_mmc_load_image();
167break;
168#endif
169#ifdef CONFIG_SPL_NAND_SUPPORT
170case BOOT_DEVICE_NAND:
171 spl_nand_load_image();
172break;
173#endif
154: 獲取spl_boot_device,即從什麼設備啟動。
157~161:如果定義了CONFIG_SPL_RAM_DEVICE, 則執行spl_ram_load_image(),其就是將image下載到ram中。
162~168:如果定義了CONFIG_SPL_MMC_SUPPORT, 則執行spl_mmc_load_image(),其就是將image從mmc/sd裡面讀取到ram中。
169~173:如果定義了CONFIG_SPL_NAND_SUPPORT, 則執行spl_nand_load_image(), 其就是將image從nand flash中讀取到ram中。
當要啟動的image位於RAM中後,我們就可以啟動之。
213switch(spl_image.os){
214case IH_OS_U_BOOT:
215 debug("Jumping to U-Boot\n");
216break;
217#ifdef CONFIG_SPL_OS_BOOT
218case IH_OS_LINUX:
219 debug("Jumping to Linux\n");
220 spl_board_prepare_for_linux();
221 jump_to_image_linux((void*)CONFIG_SYS_SPL_ARGS_ADDR);
222#endif
223default:
224 debug("Unsupported OS image.. Jumping nevertheless..\n");
225}
226 jump_to_image_no_args(&spl_image);
227}
213: 判斷image的類型。
214:如果是u-boot,則直接到227去運行u-boot。
218:如果是Linux,則到221去啟動Linux.
至此,SPL結束它的生命,控制權交於u-boot或Linux。
類似問題
解壓縮tar.gz文件用wget命令行使用我的tar gz文件。我下載了它的根@ raspberrypi。有什麼辦法可以解壓縮在/usr/src目錄? 使用 C選擇焦油: tar zxvf lt;yourfile gt; tar gz C /usr/src/ 然後,焦油的含量應在: /us...
我可以告訴如果一個過程或被殺了自己的堆棧轉儲?我有一個卸垛時被殺。 gdb Thread 2 Thread 0xf6ec6b90 LWP 10941 : 0 0xffffe410 in __kernel_vsyscall 1 0xf7a47525 in __GI___poll fds=0xf7fb1558 nfd...
自動背景Perl執行Ubuntu我已經解決這個問題了大約一個星期 我沒有 所以我想接觸一些幫助。我有一個perl腳本 通過命令 執行通常的方式 nohup /script pl param arg param2 arg2 amp; 我通常有大約十這些運行一次處理相同類型的數據從不同的來源 即通過參數指...
試圖建立在RedHat機應用和連接得到未定義的引用誤差我在這個新領域和經驗的人需要幫助。 我試圖建立產品與gcc 4 7 2 RedHat機。我聯繫lstdc 靜。結果我得到未定義的引用問題。 更具體的說,讓我告訴一些細節。 建築標準,——verbose選項顯示:rhel5 5 / gcc 4 7 2 / lib / l...
開機調試Linux內核我已經編譯的Linux內核配置選項ROOT_NFS。我現在的問題是屏幕列印快速我看到錯誤,我無法解決這一問題的最佳途徑找到任何文件。我的表演,這在VirtualBox。 有Documentation/serial console txt你可以看看。串列控制枱曆來被用於...
部署Web應用程序使用cron部署Web應用程序依賴於cron工作最好的方法是什麼(高速緩存的維護,資料庫的更新,……)?像資料庫架構的更改,有工具,如用於管理不同版本之間的變化dbdeploy,但你如何自動更新crontab? 我知道實際的cron文件存儲在/ var /軸/但我聽說它是編輯這些...
你能知道你的最大堆棧深度在你編譯?有一種方法能夠輕鬆監控你的堆棧深度在Linux環境?考慮在C的基本應用情況,用gcc編譯後,在Ubuntu。如果你不允許動態內存分配(沒有分配/釋放的)? 你能知道你的最大堆棧深度在你編譯?號考慮一個遞歸函數會調用本身的次數,取決於輸入。你不知道多少次函數可以被調用,一...
開放的gnome終端沒有採購. bashrc自從我 bashrc包含很多別名 變數和許多其他的東西 bash的行為變化 不時我想運行gnome terminal沒有採購。我想知道有一些簡單的方法如何做到這一點 而不需要暫時重命名 bashrc或刪除其內容。 您可以運行bash沒有採購 bashrc : bash...
Linux取代柱與父目錄名文件名我有一個文件結構看起來像這樣: 000000 / 000_extracted csv浪涌/ track_ 在零點可由任何數值取代 文件000_extracted csv看起來像: Timestep ElementID SE 1 100 5 2 100 1 3 3 10...
在bash egrep,包含Egrep通常期望的圖案和文件。然後egrep搜索裡面文件的圖案和印刷品包含指定模式的線。 現在如果我想找到一個字元串,是在一個變數的一個模式?我們為什麼要使用 lt; lt; lt;?我知道 lt;重定向什麼文件中包含的命令的輸入。 其次,本 ~符號的使用,例如,如...
我怎麼rtld_lazy行為以一個函數的地址嗎?我們有一個嚴重依賴於載入模塊使用的系統dlopen 。我們的模塊是自描述的,一個符號,指出一些元數據載入模塊相關(描述,載入順序載入,旗幟,等)。 我們首先載入模塊指定RTLD_LAZY國旗dlopen ,得到我們需要的元數據,然後載入模塊,房後(在我們知道的載入順序...
需要timespec結構清晰的想法在我的項目我使用struct timespec如下 struct timespec start end; clock_gettime CLOCK_REALTIME amp;start ; / Do something / clock_gettime CLOCK_REA...
無法安裝git我跑以下命令在linux mint 12日麗莎: 1 sudo rm rf /var/lib/apt/lists/ vf 2 sudo apt get update 3 sudo apt get install git 我得到以下錯誤運行3。也就是說 安裝git: R...
將命令輸出分配給變數我克隆的虛擬機 我需要編輯/etc/hostname和用一個新的替換舊的主機名。 然後我就會運行 hostname new server name ssd會話和註銷並再次登錄。 我想通過這樣做使我的工作更容易 echo new server name gt; /etc...
如何去除SHELL BASH Linux連續的空間?我有字元串包含的單詞。 詞與詞之間有一個隨機數的空間 str= toto1 toto2 toto3 toto4 toto5 toto6 我如何刪除重複的詞與詞之間的空間,只保留一個空間? 使用tr與 s把重複的字元: echo str | tr s toto1 tot...
未知的414 GB /設備/分區卷在EC2 Linux實例3我的Amazon EC2實例我注意到每個分區包含兩個414 gb /設備。 cat /proc/partitions 主要的小 塊的名字 202 65 65 xvde1 202 144 144 xvdj 202 160 160 xvdk df h 文件系統大小效果使...
如何在Ubuntu 12.04安裝的網路文件夾我有我的地方Ubuntu 12 04箱和一盒我使用Ubuntu作為一個文件夾。 我只希望我的/家/用戶/文件指smb://192 168 0 15/myfiles文件夾。 這樣,如果我去/家/用戶/文件,我看到smb://192 168 0 15/myfiles內容。...
跨平台的浮點Consistancy我開發一個跨平台的遊戲 扮演通過網路使用同步模型。作為一個簡單的概述 這意味著只有輸入交流 所有遊戲邏輯是每個客戶端電腦上的模擬。因此 consistancy和決定論是非常重要的。 我編譯MinGW32 Windows版本 它使用GCC 4 8 1 在Linux上使用...
如何更改安裝調試信息庫[主持人]:新根~ GDB Q hello1 閱讀符號/根/ hello1……做。(GDB)R 啟動程序:/根/ hello1 程序退出代碼0244。單獨使用:debuginfos 失蹤,調試信息安裝i686 glibc 2 12 1 107。決定。 我想在我的Cen...
定義與杜步行目錄陣列我寫的測試一個遞歸杜輸出與目錄或文件系統,選擇最大的目錄和重複基本的腳本,然後將結果輸出整齊。有沒有一種方法可以結合我的陣列和一些if/then語句使這更優雅,繼續遞歸直到沒有更多的目錄進行匹配,然後列印輸出數組? /bin/bash dir1= 1 du1= du ...
如何計算數字的字元串在Bash中嗎我有下面的字元串包含詞用空格分開 str= word1 word2 word3 如何計算詞語的數量? 我不想使用一個for循環計數器。我想做一個命令。 您可以使用wc : wc w lt; lt; lt; str 3 試試這個: str= word1 word2 wo...
如何使用一個屬性文件包含在外殼的數的性質這是我的第一個問題對計算器。我確信它將已回答了(這是一個非常愚蠢的問題,我想,當我剛開始學習Linux腳本),但我才成功找到一個答案。 對不起。 這是我的問題:我嘗試使用一個殼體內的數量在屬性文件了,我有一個錯誤,因為數量不採取「如是」。 我有一個prop prope...
如何在節點上啟動ChildProcess MacOSX和Linux我有一個Express伺服器 Linux機器上運行下面的腳本好。現在 想改變python文件位置參考Mac OSX上的一個目錄結構。我需要引用節點的當前工作目錄 但工作相對位置。這是一個路徑的問題。類似的代碼 這在Linux上運行很好。 app put /route ...
如何在Linux讀取INI文件你會如何使用Linux命令讀取INI文件?我知道在Windows可以使用API調用getprivateprofilestring 例如;如何在系統獲得版本: [system1] version=XYZ date=123 [system2] version=ABC da...
在bash使用mkvmerge環我與它的相應的有幾個視頻SRT文件。我試圖將它們合并使用一個循環,但我堅持。這段代碼不工作:for i in avi do mkvmerge o i mkv \ i avi \ i esp srt done 相反,如果我使用這段代碼:for i in avi do mk...
編製Fortran程序在Linux和移動到另一個Linux機器可執行我有一個代碼,我已經寫在FORTRAN語言在我的博士,我現在有一些研究者使用Linux的合作,他們需要我的模型,那基本上是一個單一的可執行文件。在未來我可能會使開放源代碼,但知道他們只是想執行,也因為他們不是程序員,他們從來沒有在他們的生活中,編譯程序。所以問題是:是...
你是怎麼逃脫的連接字元串中的用戶名:密碼對嗎?我們有一個是建立這樣的連接字元串: http:// {i user}: {i pass}@ {i host}:22 然而,如果用戶的密碼包含「@」,然後我們結束了一個字元串,像這樣: http://user:p@ss@1 2 3 4:22 這顯然將劇本了。有沒有辦法逃...
Linux的bash腳本計算平均IO等待時間我需要一些幫助來計算平均IO等待時間為一個bash腳本。 我將要運行的腳本是非常簡單的。排序2個文件,然後加入。因為我是測試將巨大的文件,我需要知道有多少的IO瓶頸我為了做一些決定(文件加入 。 我發現把IO等待時間一般在許多不同的答案,但沒有方法來計算一個項目的平均...
命令Bash函數引用在試圖創建一個Bash函數接受參數並把它們傳送到我在引用參數的正確遇到問題的另一個命令。 我確定以下功能: function cluster { dsh acM \ @ \ ; } 這個命令是將類似的用法cluster ls l對dsh acM ls l 。 謝謝你的...
安裝後無法訪問phpmyadmin嗎我想我的新伺服器上安裝phpmyadmin 本指南:https://www digitalocean com/community/articles/how to install and secure phpmyadmin on ubuntu 12 04 本質上是: a...
timeval結構的使用我需要計算出它需要運行某一功能時撞到下面的代碼,記錄輸出一段代碼的執行時間在納秒 也有區別 struct timeval timer_spent與timeval timer_spent / Put this line at the top of the file: /...
學習UNIX和C -觀看的過程,文件和v-node表我正在閱讀有關流程表,在本文件表和v node表在UNIX環境高級編程。 幫助我的理解,這將是能夠查看進程表文件表和有用的,v node表和它們之間的關係。我怎樣才能把這些內部結構,當我編寫和調試C代碼? 我試件內部結構信息一起使用的輸出ps和ls與寫生的關係在紙上以...
如何複製一個文件上傳在活動框架?我想玩2 0 4做一個基本的文件上傳。文件上傳自己的作品,我能得到一File對象。然而,我想將此文件複製到/public/images/目錄我該如何做?下面的代碼不產生結果或錯誤: FilePart picture = body getFile file ; File...
如何從Windows桌面Linux終端複製文件我用膩子連接到Linux伺服器。我想複製一些文件從終端到我的桌面。我可以通過執行PSCP(HTTP:/ /。地球。李/ ~ sgtatham /泥/ 0 60/htmldoc/chapter5 html在我的Windows CMD命令。我怎麼能做同樣的任務,通過我的膩子...
如何運行命令時重新啟動CentOS伺服器我將在我的伺服器重新啟動一次運行一個命令 我有我的聊天應用程序伺服器Node js 這是我寫的命令行運行我的聊天應用膩子 登錄到伺服器 [root@name ~] cd / [root@name /] cd /home/admin/domains/mydomain c...
如何知道crontab任務實際上是執行我有一個腳本,應該執行的計劃任務。我怎麼能驗證此此刻如果任務程序被執行前幾個小時? 你應該加入一個修改crontab文件MAILTO= lt;your email here gt;在你的計劃,你將通過電子郵件發送的執行結果。這不會解決你知道在過去執行的腳本的問題,但它...
使用從另一台計算機上運行Linux程序數據我對電腦A 一些大的數據有可能在另一台計算機上運行一個程序B利用這些數據(使用SSH或什麼的?)。 這當然是可能的。有與遠程計算機上的數據工作的無盡的可能性。假設NFS和桑巴是不可用的幾個方法,你可以使用SSH:魚 SCP SSHFS或SFTP。 例如: scp us...
PHP發送郵件的隊列優先順序我怎麼能在Sendmail隊列設置消息優先順序? 我希望所有的消息從PHP要先當我發送大消息列表,用戶的「背景」。無優先權定義緊急信息卡在長時間的排隊。 你可以使用特殊的「優先順序」的郵件標題。 有幾個預定義的類信息:一流,快遞,列表,散裝,垃圾。第一類具有最高的優先...
如何去主棧我使用的備用堆棧處理在Linux C程序的信號。當棧溢出時,我的信號被傳遞到我的備用信號堆棧不在主。 所以在這種情況下我想丟掉主要的棧的…我怎麼能? 記得在主棧頂地址(和一些局部變數在堆棧幀),並把從異常地址。要知道,有一些可移植性問題(堆棧向上生長在惠普的PA RI...
我如何能用重定向和管道命令bash字元串?我想做一個與重定向和/或管道命令bash的字元串,並用它來顯示命令的字元串或執行命令的字元串。一個沒有重定向或管道工程簡單的命令,而是一系列與重定向或管道命令不。例如, command= echo 1 command echo command 將顯示 1 echo 1...
WRT54G路由表/ IP表我是一個發展的關注其路由表WRT54GL無線路由器固件升級本科學生。實施的目的是提高IPv4和IPv6路由。 問題是,我要看看我能改變路由表的源/配置我的要求的模塊是什麼? 我已經設置開發環境在NetBeans工具Ubuntu鏡像系統。 我是新來這個的任何建議或閱讀材...
合并對Linux只保留在文件中出現的線的兩個文件在Linux,我如何合并兩個文件和保存在文件中有一場比賽? 每一行由換行符分隔(\n)。 到目前為止,我發現sort它,然後使用comm 12。這是最好的方法(假設它是正確的)? 向包含 aaa bbb ccc ddd fileb包含 aaa ddd eee 我想要一...
安裝32位Java 64位CentOS:錯誤Java /郎/對象我有一個CentOS箱 釋放6 5最終 Linux內核2 6 32 431。決定。x86_64 GNOME 2 28 2 處理器英特爾至強×64位 Java的64位版本是包含在安裝,就像Firefox。 我想運行一個32位的Java應用程序是我寫的,我測試了Windo...
輸入列和awk我試圖讓用戶輸入一個值,看在一個文件中特定的列。有沒有辦法打開柱awk沒有在所有的開關的情況下重複我自己? Code: read p Enter a column: input for i in file_name ; do cat i | awk v column=...