1. 程式人生 > >【uboot】mips架構uboot啟動分析

【uboot】mips架構uboot啟動分析

協處理器

協處理器一詞通常用來表示處理器的一個可選部件,負責處理指令集的某個擴充套件。
- CP1 是浮點協處理器,
- CP0 系統控制協處理器
- CP2 偶爾用來指定ISA擴充套件或者在幾個SoC應用中提供專用的暫存器;
- CP3 被MIPS32/64浮點指令佔用,很少用;

協處理器CP0

除了通常的運算功能,任何處理器都需要一些部件處理中斷,配置選項和監控片上快取記憶體(cache)和定時器功能。
CP0協處理器主要提供:
1)cpu的配置;
2)快取記憶體控制;
3)異常/中斷控制;
4)儲存管理單元控制;
5)雜項,如定時器,事件計數器,奇偶校驗,錯誤檢測;
在彙編中:
li t0, 0x10000004
mtc0 t0, $

12 #狀態暫存器,CPU的特權等級,能使用的中斷引腳等。
mtc0 zero, $13

\boot\uboot\board\atheros\common中的956x.S中
lowlevel_init: 在956x.S中定義,設定CPU,AHB,DDR,

uboot 作為bootloader的一種,用於引導作業系統順利啟動,本文記錄基於mips架構SDK中uboot的編譯過程和啟動流程

編譯過程

編譯過程可以分為三部分:

1.原始碼編譯

uboot編譯的方式是將各個目錄下的原始碼編譯成.o,然後通過mips-linux-uclibc-ar 命令建立成靜態庫,
./lib_bootstrap/libbootstrap.a
./cpu/mips/libmips.a
./board/atheros/board955x/libboard955x.a
./lib_mips/libmips.a
./lib_generic/libgeneric.a
./common/libcommon.a
./drivers/libdrivers.a
./rtc/librtc.a
./net/libnet.a
./post/libpost.a
./post/cpu/libcpu.a


到最後通過連線指令碼將這些靜態庫連結成u-boot,如下:
mips-linux-uclibc-ld -Bstatic -T /***/boot/u-boot/board/atheros/board955x/u-boot.lds -Ttext 0x80010000 $UNDEF_SYM cpu/mips/start.o /***/boot/u-boot/board/atheros/board955x/extra.o \
--start-group lib_generic/libgeneric.a common/libcommon.a board/atheros/board955x/libboard955x.a cpu/mips/libmips.a lib_mips/libmips.a drivers/libdrivers.a net/libnet.a rtc/librtc.a --end-group -L /***/toolchain/gcc-4.3.3/build_mips/staging_dir/usr/bin/../lib/gcc/mips-linux-uclibc/4.3.3 -lgcc \
-Map u-boot.map -o u-boot

注意 -Ttext 0x80010000,這裡是將初始地址重定向為0x80010000,如果不設定這個重定向地址,則為0;為什麼是這個地址,後面再說!

2. 新增libbootstrap.a

首先將u-boot拷貝成u-boot.bin
mips-linux-uclibc-objcopy –gap-fill=0xff -O binary u-boot u-boot.bin 各個section之間填充0xff
然後編譯目錄lib_bootstrap,並生成libbootstrap.a,如下:
/home/project/plc_platform/board/model_qca_qca95xx/sdk/board956x/boot/u-boot/board/atheros/board955x/u-boot-bootstrap.lds -Ttext 0x9f000000 $UNDEF_SYM cpu/mips/start_bootstrap.o \
--start-group lib_bootstrap/libbootstrap.a board/atheros/board955x/libboard955x.a cpu/mips/libmips.a --end-group -L /home/project/plc_platform/board/model_qca_qca95xx/toolchain/gcc-4.3.3/build_mips/staging_dir/usr/bin/../lib/gcc/mips-linux-uclibc/4.3.3 -lgcc \
-Map bootstrap.map -o bootstrap

然後copy:
mips-linux-uclibc-objcopy --gap-fill=0xff -O binary bootstrap bootstrap.bin
這個libbootstrap.a包含了lzma解壓縮的api,還有彙編檔案start_bootstrap.S,這個檔案十分重要,後面的uboot執行流程有介紹。注意-Ttext 0x9f000000,這個表明這部分程式碼是在flash中執行的,0x9f000000是flash地址的基地址。

lzma壓縮和製作映象

執行的makefile:
u-boot.lzimg: $(obj)u-boot.bin System.map
@$(LZMA) e $(obj)u-boot.bin u-boot.bin.lzma
@./tools/mkimage -A mips -T firmware -C lzma \
-a 0x$(shell grep "T _start" $(TOPDIR)/System.map | awk '{ printf "%s", $$1 }') \ -e 0x$(shell grep "T _start" $(TOPDIR)/System.map | awk '{ printf "%s", $$1 }') \
-n 'u-boot image' -d $(obj)u-boot.bin.lzma [email protected]

分為兩個過程,一個是呼叫lzma壓縮,一個呼叫mkimage製作映象。
LZMA 4.57 Copyright (c) 1999-2007 Igor Pavlov 2007-12-06
Image Name: u-boot image
Created: Mon Mar 28 16:01:07 2016
Image Type: MIPS Linux Firmware (lzma compressed)
Data Size: 40037 Bytes = 39.10 kB = 0.04 MB
Load Address: 0x80010000
Entry Point: 0x80010000
cp -f /home/project/plc_platform/board/model_qca_qca95xx/build/../sdk/board956x/boot/u-boot/tuboot.bin

mkimage主要是給壓縮後的映象新增一個頭,這個頭的結構如下:

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; /* DataLoad 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;

其中 uint32_t ih_load; /* DataLoad Address*/
uint32_t ih_ep; /* Entry Point Address
是兩個關鍵的地址,ih_load是解壓uboot到的目的地址,ih_ep是程式的入口地址。
到此,uboot編譯完成,最終的uboot.bin的結構如下:
++++++++++++++++++++++++++++++
|bootstrap.bin|image header|u-boot.lzimg |
++++++++++++++++++++++++++++++

上電初始化過程

彙編初始化

根據硬體特性程式從入口Entry(_start)開始執行,主要的操作在start_bootstrap.S中進行,主要的操作:
初始化時鐘,DDR,cache、禁止time中斷
CPU PLL CONFIG
SDRM或 DDR initialization
Initialize caches(bal mips_cache_reset),建立暫時棧空間
Initialize GOT pointer//為呼叫函式建立的符號表指標
進入第一個c函式bootstrap_board_init_f:
la t9, bootstrap_board_init_f
j t9

bootstrap_board_init_f

bootstrap_board_init_f先執行初始化函式指標陣列init_sequence,然後開闢一個臨時棧空間,在DDR的最高位置。然後計算臨時棧的起始位置
+++++++++++++++++++++++++++++++++++++++++++++++++
| |16B|128K uboot引數|gb_t|bd_t|malloc 128K|uboot的BSS&TEXT| 4K |
+++++++++++++++++++++++++++++++++++++++++++++++++
初始化一個臨時棧空間,然後呼叫bootstrap_relocate_code,最後要清cache,然後跳轉(不是很明白)
` bal mips_cache_flush
nop

/* Jump to where we’ve relocated ourselves.*/
addi t0, a2, in_ram - _start_bootstrap
j t0`
最後進入bootstrap_board_init_r

bootstrap_board_init_r

bootstrap_relocate_code在start_bootstrap.S中實現,將uboot的程式碼重定向到臨時棧空間棟執行,進入函式bootstrap_board_init_r,
bootstrap_board_init_r函式首先初始化128K的棧空間,然後將uboot的header取出來,檢查magic number和crc32校驗,通過後呼叫函式lzma_inflate解壓uboot:
i = lzma_inflate ((unsigned char )data, len, (unsigned char)ntohl(hdr->ih_load), &destLen);
解壓成功後,清除cache,跳入uboot的入口:fn = ntohl(hdr->ih_load),既是0x80010000地址:
80010000 T _start
80010030 T relocate_code
80010094 t in_ram
80010100 T ath_set_tuning_caps
800101a0 T do_go
800102c0 T print_image_hdr
800106c8 T do_bootd
80010718 T fake_image_header
800107f0 T do_bootm
800109c0 T flash_sect_erase
80010bc8 T do_flerase

_start函式在start.S中,,執行以下操作
清空cache
清空BSS段
正式進入C環境(la t9 board_init_r)

board_init_r

board_init_r 主要執行以下的操作:
將前面臨時棧一些資料(gd、bd等)copy到RAM中預留的對應位置
設定系統模式(Init_System_Mode),這裡可以設定CPU時鐘
env_relocate
devices_init //i2c、LCD、keyboard ……
main_loop迴圈監聽,無人為干預,啟動系統(do_bootm),有人為干預初始化乙太網其他相關操作。
main_loop中呼叫了parse_string_outer 通過執行命令bootm 0x9f010000 進入到函式do_bootm;

do_bootm

do_bootm:解壓縮kernel,呼叫do_bootm_linux

do_bootm_linux

do_bootm_linux:對kernel進行crc校驗,並和header中的crc欄位進行比較,設定環境變數,然後呼叫theKernel 進入kernel。

重要的巨集

CFG_PLL_720_600_200 cpu memory 和匯流排的頻率,對著這組配置,有一系列的巨集定義:
#define CPU_DDR_SYNC_MODE DDR_CTL_CONFIG_CPU_DDR_SYNC_SET(0)
\#define CPU_PLL_CONFIG_NINT_VAL CPU_PLL_CONFIG_NINT_SET(18)
\#define CPU_PLL_CONFIG_REF_DIV_VAL CPU_PLL_CONFIG_REFDIV_SET(1)
\#define CPU_PLL_CONFIG_RANGE_VAL CPU_PLL_CONFIG_RANGE_SET(1)
\#define CPU_PLL_CONFIG_OUT_DIV_VAL1 CPU_PLL_CONFIG_OUTDIV_SET(0)
\#define CPU_PLL_CONFIG_OUT_DIV_VAL2 CPU_PLL_CONFIG_OUTDIV_SET(0)
\#define CPU_PLL_DITHER_VAL CPU_PLL_DITHER_DITHER_EN_SET(0) | \
CPU_PLL_DITHER_NFRAC_MAX_SET(0x3f) | \
CPU_PLL_DITHER_NFRAC_MIN_SET(0) | \
CPU_PLL_DITHER_NFRAC_STEP_SET(1) | \
CPU_PLL_DITHER_UPDATE_COUNT_SET(0xf)

#define DDR_PLL_CONFIG_NINT_VAL DDR_PLL_CONFIG_NINT_SET(15)
#define DDR_PLL_CONFIG_REF_DIV_VAL DDR_PLL_CONFIG_REFDIV_SET(1)
#define DDR_PLL_CONFIG_RANGE_VAL DDR_PLL_CONFIG_RANGE_SET(1)
#define DDR_PLL_CONFIG_OUT_DIV_VAL1 DDR_PLL_CONFIG_OUTDIV_SET(0)
#define DDR_PLL_CONFIG_OUT_DIV_VAL2 DDR_PLL_CONFIG_OUTDIV_SET(0)
#define DDR_PLL_DITHER_VAL DDR_PLL_DITHER_DITHER_EN_SET(0) | \
DDR_PLL_DITHER_NFRAC_MAX_SET(0x3ff) | \
DDR_PLL_DITHER_NFRAC_MIN_SET(0) | \
DDR_PLL_DITHER_NFRAC_STEP_SET(1) | \
DDR_PLL_DITHER_UPDATE_COUNT_SET(0xf)

#define CPU_DDR_CLOCK_CONTROL_AHB_DIV_VAL CPU_DDR_CLOCK_CONTROL_AHB_POST_DIV_SET(2)
#define AHB_CLK_FROM_DDR CPU_DDR_CLOCK_CONTROL_AHBCLK_FROM_DDRPLL_SET(1)
#define CPU_AND_DDR_CLK_FROM_DDR CPU_DDR_CLOCK_CONTROL_CPU_DDR_CLK_FROM_DDRPLL_SET(0)
#define CPU_AND_DDR_CLK_FROM_CPU CPU_DDR_CLOCK_CONTROL_CPU_DDR_CLK_FROM_CPUPLL_SET(0)
#define CPU_DDR_CLOCK_CONTROL_DDR_POST_DIV CPU_DDR_CLOCK_CONTROL_DDR_POST_DIV_SET(0)
#define CPU_DDR_CLOCK_CONTROL_CPU_POST_DIV CPU_DDR_CLOCK_CONTROL_CPU_POST_DIV_SET(0)

問題分析

Setting 0x181162c0 to 0x60c02100
\## Booting image at 9f010000 ...
---- fileTag = 9f010000
text base = ffffffff
entry point = ffffffff
hdr->ih_load = 00000000
hdr->ih_ep = 00000000
Uncompressing Kernel Image at ffffffff ... Stream with EOS marker is not supportedLZMA ERROR 1 - must RESET board to recover

kernel的偏移位置錯了,應該是:export KERNEL_OFFSET=0x020000

嘗試更換新舊平臺的squashfs檔案系統,發現需要找lib下的zlib驅動,又嘗試整個kernel更換,發現編譯乙太網驅動失敗,標頭檔案找不到。
跟蹤出錯列印的函式呼叫棧,發現在unlzma出錯,研究make_flash原始碼:
[ 0.776000] Call Trace:
[ 0.776000] [<800f02c8>] unlzma+0xfb4/0x118c

終於知道問題所在,新平臺的檔案打包工具使用的壓縮方式是gzip,而不是lzma,在檔案buildFS_LZ中:
$SOURCE/util/mksquashfs4.0 $INSTALL_ROOT_FOR_BOARD $IMAGEPATH/$BOARD_TYPE-squashfs -noappend -always-use-fragments -all-root -b 1048576
關鍵是Z:\source\util目錄下的mksquashfs4是不支援lzma的,更換為舊的mksquashfs4.0就可以了。

相關推薦

ubootmips架構uboot啟動分析

協處理器 協處理器一詞通常用來表示處理器的一個可選部件,負責處理指令集的某個擴充套件。 - CP1 是浮點協處理器, - CP0 系統控制協處理器 - CP2 偶爾用來指定ISA擴充套件或者在幾個SoC應用中提供專用的暫存器; - CP3 被

1netty4服務端啟動原始碼分析-執行緒的建立

轉自 http://xw-z1985.iteye.com/blog/1925013 本文分析Netty中boss和worker的執行緒的建立過程: 以下程式碼是服務端的啟動程式碼,執行緒的建立就發生在其中。 EventLoopGroup bossGroup = new NioEv

快取快取架構分析

一、快取穿透預防及優化  快取穿透是指查詢一個根本不存在的資料,快取層和儲存層都不會命中,但是出於容錯的考慮,如果從儲存層查不到資料則不寫入快取層,如圖 11-3 所示整個過程分為如下 3 步: 快取層不命中 儲存層不命中,所以不將空結果寫回快取 返回空結果     

armarm架構64位入門基礎:架構分析、暫存器、呼叫規則、指令集、程式除錯以及參考手冊

Date: 2018.8.21 1、參考 2、ARM64位架構分析 ARM64位採用ARMv8架構,64位操作長度,對應處理器有Cortex-A53、Cortex-A57、Cortex-A73、iphones的A7和A8等。 AARCH64是全新32位固定長

jQuery結合accordion插件分析寫插件的方法及註意事項

als 參數 啟動 trigger 默認值 cto global efi each 1.jQuery插件的命名方式:jquery.[插件名].js 2.對象方法附加在jQuery.fn上,全局函數附加在jQuery對象本身上 3.插件內部this指向的是通過選擇器獲取的jQ

SCCM架構簡介

sccm架構 簡單來說,System Center Configuration Manager(SCCM/ConfigMgr)由SMS(Systems Management Server)發展而來,其作為一款針對企業級的客戶端,服務器管理平臺,提供迅速有效的配置管理、軟件分發、系統部署、軟硬件資產等完善

Jenkins怎麽啟動和停止服務

class jenkins配置 con 曾經 每次 一個 sta base dsm 筆者沒有把Jenkins配置到tomcat中,每次都是用命令行來啟動Jenkins。但是遇到一個問題:Jenkins一直是開著的,想關閉也關閉不了。百度了一些資料,均不靠譜(必須吐槽一下百

Hadoophiveserver2 不能啟動端口 10000 開啟服務的相關經驗總結

error: pro mon 進行 org multipl html pen exp 轉載來自http://blog.csdn.net/lsttoy/article/details/53490144。 這個問題困擾了我三天,各種查資料踩坑填坑的嘗試,終於搞定了這個

centos 服務開機啟動

我們 .html www onf 服務的啟動 version 服務 網絡 ast 轉自: http://blog.csdn.net/educast/article/details/49558945 http://www.cnblogs.com/panjun-Donet/ar

轉載FusionSphere架構詳解

computing ssis 修改 hyperv 適配器 drive 特殊 架構 avi FusionSphere底層使用Xen架構: 1.單臺物理機上建立hypervisor系統。 2.將所有單個hypervisor系統整合起來管理使用。 安裝C

轉載TCP粘包問題分析和解決(全)

刪除 而且 實例 報文 底層 nagle 存在 ngxin 想想 TCP通信粘包問題分析和解決(全) 在socket網絡程序中,TCP和UDP分別是面向連接和非面向連接的。因此TCP的socket編程,收發兩端(客戶端和服務器端)都要有成對的socket,因此,發送端為了將

評分軟件產品案例分析(團隊)

產品 gpo pos 提交 cnblogs 除了 har 一周 技術 【評分】軟件產品案例分析(團隊) 總結 按時交 - 有分 晚交 - 0分 遲交一周以上 - 倒扣本次作業分數 抄襲 - 倒扣本次作業分數 本次作業贊 日不落戰隊 ,做得相對詳細,大家可前往查看:

EclpiseEclipse中Tomcat啟動失敗或者是重啟失敗

lis 占用 listening xiang 進程 ref min dos get    經常在Eclipse中遇到這樣的問題,tomcat重啟之後失敗,而且也停止不了。最好的解決辦法就是用DOS命令殺死進程。 比如下面這種情況: 1.查看進程I

第一次個人作業(Linux性能分析

nal pprof 適合 right 比例 link 正常 and HA 工具選擇 這裏參考了http://gernotklingler.com/blog/gprof-valgrind-gperftools-evaluation-tools-application-leve

學習筆記:案例財政收入影響因素分析及預測模型

6.0 pearson end 4.5 pandas 問題 特征 ase max() 案例來源:《Python數據分析與挖掘實戰》第13章 案例背景與挖掘目標 輸入數據: 《某市統計年鑒》(1995-2014) 挖掘目標: 梳理影響地方財政收入的關鍵特征,分析、識別影響地

MaBatis學習---源碼分析MyBatis緩存原理

iso 負責 等待 全局 安全問題 cto suse 都去 pst 【原文】https://www.toutiao.com/i6594029178964673027/ 源碼分析MyBatis緩存原理 1.簡介 在 Web 應用中,緩存是必不可少的組件。通常我們都會用 Red

筆記Activity四種啟動模式區別

參考:https://blog.csdn.net/edisonchang/article/details/49981457 activity 啟動的四種模式 : AndroidManifest.xml :: android:launchMode="???" 1.standard:【不會

轉載軟體架構與框架

參考文章連結:https://blog.csdn.net/weixin_36317299/article/details/80558632 https://blog.csdn.net/qq_33559972/article/details/80559846 https://blog.csdn.net/Go

iOS詳解APP啟動過程

我們都知道,程式的入口是main函式,在用C寫程式碼的時候,都會有個mian函式,但是在OC中,在.m檔案中,我們最常看到的是viewDidLoad()。對於剛從C轉OC的人來說,剛開始有些蒙。其實,OC中也是有mian函式的,只是不實那麼明顯。     1、先執行m

iOS客戶端安全性問題分析及處理方式

目前,大部分的移動應用都是需要聯網,與伺服器進行通訊,獲取最新的資料。一提到網路,肯定就有大量和安全性相關的問題出來。所以,對於我們開發者而言,如何打造一個安全的App,是必須面對的問題。前段時間我專門對iOS移動應用安全性方面進行了研究,下面我們分析iOS應用中可能會存在的安全風險以及相對應的處理