u-boot中SPL源代码分析
系统大全为您提供
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/armu/armv7/start.S> (b lowlevel_init: arch/armu/armv7/lowlevel_init.S) (b _main) --> <arch/armb/crt0.S> (bl board_init_f) --> <arch/armb/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/armu/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
117 and 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/armu/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/armu/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
27 sub 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/armu/at91-common/spl.c> 此处暂时不分析。
然后返回到start.S处,接下来调用:bl _main到<arch/armb/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
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/armb/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 */
26 void __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>中定义:
132 void board_init_r(gd_t *dummy1, ulong dummy2)
133 {
134 u32 boot_device;
135 debug("》spl:board_init_r() ");
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/armu/armv7/at91/time.c>
150~150: CONFIG_SPL_BOARD_INIT, 则调用spl_board_init()。 这是board相关的定义,<board/atmelma5d3xekma5d3xek.c>
一切就绪后,就要检查从什么设备来启动了。这里就贴出RAM,MMC, NAND相关代码
154 boot_device = spl_boot_device();
155 debug("boot device - %d ", boot_device);
156 switch (boot_device) {
157 #ifdef CONFIG_SPL_RAM_DEVICE
158 case BOOT_DEVICE_RAM:
159 spl_ram_load_image();
160 break;
161 #endif
162 #ifdef CONFIG_SPL_MMC_SUPPORT
163 case BOOT_DEVICE_MMC1:
164 case BOOT_DEVICE_MMC2:
165 case BOOT_DEVICE_MMC2_2:
166 spl_mmc_load_image();
167 break;
168 #endif
169 #ifdef CONFIG_SPL_NAND_SUPPORT
170 case BOOT_DEVICE_NAND:
171 spl_nand_load_image();
172 break;
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中后,我们就可以启动之。
213 switch (spl_image.os) {
214 case IH_OS_U_BOOT:
215 debug("Jumping to U-Boot ");
216 break;
217 #ifdef CONFIG_SPL_OS_BOOT
218 case IH_OS_LINUX:
219 debug("Jumping to Linux ");
220 spl_board_prepare_for_linux();
221 jump_to_image_linux((void *)CONFIG_SYS_SPL_ARGS_ADDR);
222 #endif
223 default:
224 debug("Unsupported OS image Jumping nevertheless ");
225 }
226 jump_to_image_no_args(&spl_image);
227 }
213: 判断image的类型。
至此,SPL结束它的生命,控制权交于u-boot或Linux.
以上就是系统大全给大家介绍的如何使的方法都有一定的了解了吧,好了,如果大家还想了解更多的资讯,那就赶紧点击系统大全官网吧。
本文来自系统大全http://www.win7cn.com/如需转载请注明!推荐:win7纯净版
系统下载排行榜71011xp
番茄花园 GHOST WIN7 SP1 X64 快速稳定版 V2017.03 (64位
2深度技术 GHOST WIN7 SP1 X64 稳定安全版 V2017.02(64位
3雨林木风 GHOST WIN7 SP1(32位)装机版 V2017.03
4深度技术 GHOST WIN7 SP1 X86 专业装机版 V2017.03(32位
5电脑公司 GHOST WIN7 SP1 X86 经典旗舰版 V2017.03(32位
6深度技术 GHOST WIN7 SP1 X86 稳定安全版 V2017.02
7深度技术 GHOST WIN7 SP1 X64 专业装机版 V2017.03(64位
8电脑公司 GHOST WIN7 SP1 X64 经典旗舰版 V2017.03(64位
9电脑公司 GHOST WIN7 SP1 X64 新春贺岁版 V2017.02(64位
10电脑公司 GHOST WIN7 SP1 X86 新春贺岁版 V2017.02(32位
win10系统下载 Win10 1607 精简安装版 LTSB长期服务版
2Win10专业工作站版最新镜像 V2022.06
3微软原版Win10 ISO镜像64位(win10纯净版)
4深度技术 Ghost Win10 64位 国庆特别版 V2021.10
5电脑公司Ghost Win10 64位装机版V2017.03
6雨晨 Win10 1703 15063.250 64位 极速精简版
7JUJUMAO Win8.1 Up3 X64 极速精简版v2019.11
8win10系统下载 稳安快 Win10 x64 极速精简版 V1.0
9lopatkin Win10专业精简版 V2022.05
10Win10 21H2 纯净版镜像 V2021
Win11PE网络纯净版 V2021
2风林火山 Ghost Win11 64位 专业正式版 V2021.10
3Win11官方纯净版 V2021
4Win11 23H2 25115 官方原版镜像 V2022.05
5新一代系统 JUJUMAO Win11专业版 64位 v2021.08
6雨林木风 Ghost Win11 64位 正式版 V2021.10
7微软MSDN原版Win11系统 V2021
8Win11 22000.282正式版镜像 V2021.10
9深度技术 Ghost Win11 64位 专业版 V2021.10
10微软Win11游戏系统 V2021.10
深度技术 GHOST XP SP3 电脑专用版 V2017.03
2深度技术 GGHOST XP SP3 电脑专用版 V2017.02
3Win7系统下载 PCOS技术Ghost WinXP SP3 2017 夏季装机版
4萝卜家园 GHOST XP SP3 万能装机版 V2017.03
5番茄花园 GHOST XP SP3 极速体验版 V2017.03
6雨林木风 GHOST XP SP3 官方旗舰版 V2017.03
7电脑公司 GHOST XP SP3 经典旗舰版 V2017.03
8雨林木风GHOST XP SP3完美纯净版【V201710】已激活
9萝卜家园 GHOST XP SP3 完美装机版 V2016.10
10雨林木风 GHOST XP SP3 精英装机版 V2017.04
热门教程
装机必备 更多+
重装工具