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纯净版
相关文章
- 纯净版 Win10 直接硬盘安装方法
- 微软为 Win10 推送 4 月扩展安全更新 KB5082200
- 微软宣布 2026 年全面重构 Win11 系统
- Win11 26H1 四月更新 KB5083768 发布,提升传输稳定性
- 微软 Win11 24H2 / 25H2 发布 4 月累积更新补丁 KB5083769
- 如何使用U盘重装Windows7系统-U盘重装Win7最简单的方法
- 如何使用U盘重装Windows11系统-U盘重装Win11最简单的方法
- 如何使用U盘重装Windows10系统-U盘重装Win10最简单的方法
- 微软推送 Win11 26H1 预览版更新 KB5079466
- 微软推送 Win11 26H1 预览版!版本号升至 28000.1643
系统下载排行榜71011xp
【番茄花园】Win7 64位 快速稳定版
2【纯净之家】Windows7 32位 全新纯净版
3【纯净之家】Win7 64位 Office2007 办公旗舰版
4【雨林木风】Windows7 64位 装机旗舰版
5JUJUMAO Win7 64位旗舰纯净版
6【电脑公司】Windows7 64位 免费旗舰版
7【游戏专用】Windows7 64位 装机旗舰版
8【深度技术】Windows7 64位 官方旗舰版
9【纯净之家】Windows7 SP1 32位 全补丁旗舰版
10【番茄花园】Windows7 64位 旗舰装机版
【纯净之家】Windows10 22H2 64位 企业版
2【纯净之家】Windows10 32位 官方正式版
3【雨林木风】Windows10 64位稳定版系统
4【技术员】Windows10 64位 系统纯净版
5【技术员】Windows10 64位 纯净版iso镜像
6JUJUMAO Win10 64位 纯净版镜像
7【番茄花园】Windows10 64位 专业版镜像
8【雨林木风】Windows10 64位 官方专业版
9【技术员】Windows10 64位 LTSC 纯净版
10【技术员】Windows10 64位 纯净装机版
【纯净之家】Windows11 23H2 64位 纯净专业版
2【纯净之家】Windows11 23H2 64位 游戏优化版
3【纯净之家】Windows11 23H2 64位 企业版系统
4【纯净之家】Windows11 23H2 64位 中文家庭版
5风林火山Windows11下载中文版(24H2)
6雨林木风 Win11 25H2 超级纯净版系统
7JUJUMAO Win11 24H2 64位 精简版镜像
8萝卜家园 Win11 25H2 专业版镜像
9JUJUMAO Win11 24H2 64位 专业版镜像
10【纯净之家】Windows11 23H2 64位 纯净家庭版
深度技术 GHOST XP SP3 电脑专用版 V2017.03
2深度技术 GGHOST XP SP3 电脑专用版 V2017.02
3萝卜家园 GHOST XP SP3 万能装机版 V2017.03
4番茄花园 GHOST XP SP3 极速体验版 V2017.03
5雨林木风 GHOST XP SP3 官方旗舰版 V2017.03
6Win7系统下载 PCOS技术Ghost WinXP SP3 2017 夏季装机版
7萝卜家园 GHOST XP SP3 完美装机版 V2016.10
8电脑公司 GHOST XP SP3 经典旗舰版 V2017.03
9雨林木风GHOST XP SP3完美纯净版【V201710】已激活
10雨林木风 GHOST XP SP3 精英装机版 V2017.04
热门教程
装机必备 更多+
重装工具


