亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频

蟲蟲首頁| 資源下載| 資源專輯| 精品軟件
登錄| 注冊

您現(xiàn)在的位置是:首頁 > 技術(shù)閱讀 >  u-boot2020.04移植(5、u-boot重定位)

u-boot2020.04移植(5、u-boot重定位)

時(shí)間:2024-05-31

點(diǎn)擊下方閱讀原文可訪問文中超鏈接

如果想了解重定位是怎么一回事,可以參考這位老哥的博客:https://blog.csdn.net/skyflying2012/article/details/37660265

第一階段結(jié)束,便開始u-boot的重定位(這里有點(diǎn)小疑惑,在前面將u-boot從SD卡拷貝到DDR中時(shí),我就是拷貝到鏈接地址的,也就是說那個(gè)時(shí)候u-boot的運(yùn)行地址就和鏈接地址一致了,可以正常運(yùn)行完整個(gè)u-boot,這里又再次重定位,只不過是將u-boot搬到內(nèi)存的高地址去運(yùn)行,網(wǎng)上搜了一下,有說是因?yàn)榉乐箖?nèi)核解壓的時(shí)候覆蓋了u-boot本身,那也就是說只要解壓內(nèi)核不會(huì)覆蓋u-boot這部分內(nèi)存,理論上就不需要再次重定位了,等之后有時(shí)間我測試一下,去掉這部分重定位代碼,看u-boot是否還能正常運(yùn)行,以驗(yàn)證自己的想法),關(guān)于這部分新版u-boot和以前的不太一樣,個(gè)人感覺新版的設(shè)計(jì)更加簡單便于理解。

現(xiàn)在回到arch/arm/lib/crt0.S文件:

重定位前的準(zhǔn)備工作

/*arch/arm/lib/crt0.S*/

/*GD_START_ADDR_SP定義在include/generated/generic-asm-offsets.h文件(這個(gè)文件是u-boot自動(dòng)生成的,而且過程也是有點(diǎn)高端,
感興趣的可以網(wǎng)上了解一下,貼一個(gè)我看過的鏈接:http://blog.chinaunix.net/uid-25000873-id-4134037.html),
在這里表示在gd這個(gè)數(shù)據(jù)結(jié)構(gòu)中start_addr_sp的偏移值,前面我們也知道r9這個(gè)寄存器綁定的就是gd全局變量這個(gè)指針,
所以相當(dāng)于將gd->start_addr_sp里面的值加載到r0中*/

ldr r0, [r9, #GD_START_ADDR_SP] /* sp = gd->start_addr_sp */
bic r0, r0, #7 /* 8-byte alignment for ABI compliance */
/*設(shè)置棧指針*/
mov sp, r0
/*獲取gd->bd的位置*/
ldr r9, [r9, #GD_BD] /* r9 = gd->bd */
/*在內(nèi)存圖上可以看出,新的gd結(jié)構(gòu)在bd結(jié)構(gòu)的下面緊挨著,所以減去gd的大小就是新的gd起始地址*/
sub r9, r9, #GD_SIZE /* new GD is below bd */

/*這里將here標(biāo)號(hào)的地址值讀取到lr中,注意這里是adr,關(guān)于adr與ldr的區(qū)別可自行網(wǎng)上搜索*/
adr lr, here
/*將重定位偏移值加載到r0寄存器中*/
ldr r0, [r9, #GD_RELOC_OFF] /* r0 = gd->reloc_off */
/*鏈接寄存器加上偏移值后,lr的地址就變成重定位后的地址了*/
add lr, lr, r0
/*未定義*/
#if defined(CONFIG_CPU_V7M)
orr lr, #1 /* As required by Thumb-only */
#endif
/*將重定位地址加載到r0中,作為參數(shù)傳給relocate_code*/
ldr r0, [r9, #GD_RELOCADDR] /* r0 = gd->relocaddr */
/*執(zhí)行重定位*/
b relocate_code
/*從relocate_code回來后,就直接運(yùn)行在重定位后的u-boot中了,here標(biāo)號(hào)已經(jīng)是重定位后那個(gè)here標(biāo)號(hào)了*/
here:

/*
省略
*/

上面的步驟結(jié)束后,sp棧指針就設(shè)置成gd->start_addr_sp指向的地方了,而r9之前綁定的那個(gè)gd也變成重定位后的新地址的gd結(jié)構(gòu)了,內(nèi)存圖如下:

圖1

執(zhí)行重定位

/*arch/arm/lib/relocate.S*/

ENTRY(relocate_code)
/*從鏈接腳本可知,主要是將代碼段和數(shù)據(jù)段拷貝到新的地址*/
ldr r1, =__image_copy_start /* r1 <- SRC &__image_copy_start */
/*r0是重定位地址,r1是目前u-boot運(yùn)行地址,這里也有個(gè)疑問,要是u-boot運(yùn)行地址現(xiàn)在和鏈接地址不一樣,
它要拷貝的地方可能根本就是空的或者是錯(cuò)的,那這里不就有問題嗎?這個(gè)我之后得驗(yàn)證一下*/

subs r4, r0, r1 /* r4 <- relocation offset */
/*上一句subs指令會(huì)影響CPSR的狀態(tài),這里如果r4的值為0,表示r0和r1是一樣的,不需要再重定位*/
beq relocate_done /* skip relocation */
/*將拷貝結(jié)束地址放到r2中*/
ldr r2, =__image_copy_end /* r2 <- SRC &__image_copy_end */

copy_loop:
/*以r1為起始地址(也就是目前u-boot的起始地址),加載兩個(gè)字到r10,r11中*/
ldmia r1!, {r10-r11} /* copy from source address [r1] */
/*以r0為起始地址(也就是重定位的新地址),加載r10,r11的值到r0,r0+4中*/
stmia r0!, {r10-r11} /* copy to target address [r0] */
/*比較是否讀取到結(jié)束地址*/
cmp r1, r2 /* until source end address [r2] */
/*一直循環(huán),直到拷貝結(jié)束*/
blo copy_loop

/*
* fix .rel.dyn relocations
*/

/*下面這些才是重定位最重要的,上面雖然將u-boot拷貝到新地址了,但是我們要使用的變量,
和一些數(shù)據(jù)這些的地址(這里說地址可能有些不太準(zhǔn)確)還是沒變的,重定位后的u-boot應(yīng)該訪問的是新地址的變量和數(shù)據(jù)等,
下面這段代碼就是干這個(gè)事的,我們給新地址的u-boot每一個(gè)要訪問的變量地址等加上一個(gè)偏移,這樣就能正確訪問了*/

ldr r2, =__rel_dyn_start /* r2 <- SRC &__rel_dyn_start */
ldr r3, =__rel_dyn_end /* r3 <- SRC &__rel_dyn_end */
fixloop:
/*以r2為起始地址(也就是動(dòng)態(tài)符號(hào)表的起始地址),加載兩個(gè)字到r0,r1中*/
ldmia r2!, {r0-r1} /* (r0,r1) <- (SRC location,fixup) */
/*取出r1中數(shù)據(jù)的低8位*/
and r1, r1, #0xff
/*R_ARM_RELATIVE用來檢查這個(gè)符號(hào)是不是需要被重定位*/
cmp r1, #R_ARM_RELATIVE
/*不需要的話就跳過*/
bne fixnext

/* relative fix: increase location by offset */
/*r4是重定位偏移,這里就是要加上這個(gè)偏移*/
add r0, r0, r4
/*取出加上偏移后的以r0為地址內(nèi)的數(shù)據(jù)存到r1中,這里取出的也就是新的u-boot里面存放變量的那個(gè)地址*/
ldr r1, [r0]
/*給新的u-boot存放變量的那個(gè)地址加上偏移*/
add r1, r1, r4
/*將加了偏移后的值(變量的地址)寫回,這樣新的u-boot就能正確訪問了*/
str r1, [r0]
fixnext:
cmp r2, r3
blo fixloop

relocate_done:

/*未定義*/
#ifdef __XSCALE__
/*
* On xscale, icache must be invalidated and write buffers drained,
* even with cache disabled - 4.2.7 of xscale core developer's manual
*/

mcr p15, 0, r0, c7, c7, 0 /* invalidate icache */
mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */
#endif

/* ARMv4- don't know bx lr but the assembler fails to see that */

#ifdef __ARM_ARCH_4__
mov pc, lr
#else
/*重定位結(jié)束*/
bx lr
#endif

ENDPROC(relocate_code)

接下來重定位向量表,這個(gè)很簡單,就是操作協(xié)處理器

/*arch/arm/lib/relocate.S*/

.section .text.relocate_vectors,"ax",%progbits
.weak relocate_vectors

ENTRY(relocate_vectors)

/*未定義*/
#ifdef CONFIG_CPU_V7M
/*
省略
*/

#else
/*定義了,前面也講過,這個(gè)就是向量表基地址寄存器*/
#ifdef CONFIG_HAS_VBAR
/*
* If the ARM processor has the security extensions,
* use VBAR to relocate the exception vectors.
*/

/*這個(gè)還是操作協(xié)處理器,和start.S里面設(shè)置重設(shè)向量表是一樣的*/
ldr r0, [r9, #GD_RELOCADDR] /* r0 = gd->relocaddr */
mcr p15, 0, r0, c12, c0, 0 /* Set VBAR */
#else
/*
省略
*/

#endif
#endif
bx lr

ENDPROC(relocate_vectors)
/*arch/arm/cpu/armv7/start.S*/

ENTRY(c_runtime_cpu_setup)
/*
* If I-cache is enabled invalidate it
*/

/*因?yàn)閡-boot又已經(jīng)重定位了,現(xiàn)在流水線和緩存里面的內(nèi)容都是舊的,需要清掉重新填充*/
#if !CONFIG_IS_ENABLED(SYS_ICACHE_OFF)
mcr p15, 0, r0, c7, c5, 0 @ invalidate icache
mcr p15, 0, r0, c7, c10, 4 @ DSB
mcr p15, 0, r0, c7, c5, 4 @ ISB
#endif

bx lr

ENDPROC(c_runtime_cpu_setup)

然后是清bss段,這是C語言運(yùn)行環(huán)境需要的,然后執(zhí)行board_init_r

/*arch/arm/lib/crt0.S*/

/* Set up final (full) environment */

bl c_runtime_cpu_setup /* we still call old routine here */
#endif
/*CONFIG_SPL_BUILD未定義,要執(zhí)行*/
#if !defined(CONFIG_SPL_BUILD) || CONFIG_IS_ENABLED(FRAMEWORK)

/*CONFIG_SPL_EARLY_BSS未定義,要執(zhí)行*/
#if !defined(CONFIG_SPL_EARLY_BSS)
/*清BSS段,這是一個(gè)宏定義,執(zhí)行了一個(gè)memset,就不追進(jìn)去了*/
SPL_CLEAR_BSS
#endif

/*未定義*/
# ifdef CONFIG_SPL_BUILD
/* Use a DRAM stack for the rest of SPL, if requested */
bl spl_relocate_stack_gd
cmp r0, #0
movne sp, r0
movne r9, r0
# endif

/*未定義,要執(zhí)行,就是點(diǎn)亮一顆led燈,執(zhí)不執(zhí)行都無所謂*/
#if ! defined(CONFIG_SPL_BUILD)
bl coloured_LED_init
bl red_led_on
#endif
/*將gd_t這個(gè)數(shù)據(jù)結(jié)構(gòu)放到r0中,將重定位地址放到r1中,作為參數(shù)傳給board_init_r*/
/* call board_init_r(gd_t *id, ulong dest_addr) */
mov r0, r9 /* gd_t */
ldr r1, [r9, #GD_RELOCADDR] /* dest_addr */
/* call board_init_r */
#if CONFIG_IS_ENABLED(SYS_THUMB_BUILD)
ldr lr, =board_init_r /* this is auto-relocated! */
bx lr
#else
/*調(diào)用board_init_r,進(jìn)入u-boot第二階段*/
ldr pc, =board_init_r /* this is auto-relocated! */
#endif
/* we should not return here. */
#endif

到了這里,u-boot重定位就結(jié)束了,其實(shí)u-boot重定位的知識(shí)遠(yuǎn)不止代碼中的這點(diǎn)兒,有很多的細(xì)節(jié),建議讀者有時(shí)間的話,多去網(wǎng)上查閱一下相關(guān)的資料,比如位置無關(guān)代碼與位置有關(guān)代碼,為什么需要重定位等問題,這樣對重定位才有更加深入和深刻的理解。

歡迎掃碼關(guān)注我的微信公眾號(hào)

主站蜘蛛池模板: 临城县| 民勤县| 三明市| 景谷| 遂平县| 汶川县| 宜黄县| 天气| 永康市| 永州市| 东平县| 旬邑县| 岳普湖县| 东平县| 汾阳市| 卓尼县| 乌鲁木齐县| 大冶市| 辽源市| 二手房| 汪清县| 富锦市| 南开区| 内黄县| 长治县| 绥江县| 徐汇区| 沾益县| 灌阳县| 景泰县| 咸宁市| 光泽县| 陕西省| 弥渡县| 介休市| 兴宁市| 轮台县| 安西县| 汝南县| 新竹县| 拜城县|