SPLSecondary Program Loader的简称,第二阶段程序加载器,这里所谓的第二阶段是相对于SOC中的BROM来说的(BL0);

为什么需要SPL

主要原因是对于一些SOC来说,它的内部SRAM可能会比较小,小到无法装载下一个完整的u-boot镜像,那么就需要SPL,它主要负责初始化外部RAM和环境,并加载真正的u-boot镜像到外部RAM中来执行

REF:https://blog.csdn.net/rikeyone/article/details/51646200

SPL官方说明文档

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
Generic SPL framework
=====================

Overview
--------

To unify all existing implementations for a secondary program loader (SPL)
and to allow simply adding of new implementations this generic SPL framework
has been created. With this framework almost all source files for a board
can be reused. No code duplication or symlinking is necessary anymore.


How it works
------------

The object files for SPL are built separately and placed in the "spl" directory.
SPL项目相关的文件,单独存放在 spl目录

The final binaries which are generated are u-boot-spl, u-boot-spl.bin and
u-boot-spl.map.
最终编译生成的二进制文件为u-boot-spl, u-boot-spl.bin, u-boot-spl.map

A config option named CONFIG_SPL_BUILD is enabled by Kconfig for SPL.
Source files can therefore be compiled for SPL with different settings.
CONFIG_SPL_BUILD宏用来配置SPL


For example:

ifeq ($(CONFIG_SPL_BUILD),y)
obj-y += board_spl.o
else
obj-y += board.o
endif

obj-$(CONFIG_SPL_BUILD) += foo.o

#ifdef CONFIG_SPL_BUILD
foo();
#endif


The building of SPL images can be enabled by CONFIG_SPL option in Kconfig.
通过Kconfig中使能CONFIG_SPL来编译SPL固件

Because SPL images normally have a different text base, one has to be
configured by defining CONFIG_SPL_TEXT_BASE. The linker script has to be
defined with CONFIG_SPL_LDSCRIPT.
通常SPL固件有不同的入口地址,通过CONFIG_SPL_TEXT_BASE指定
链接地址使用CONFIG_SPL_LDSCRIPT指定

To support generic U-Boot libraries and drivers in the SPL binary one can
optionally define CONFIG_SPL_XXX_SUPPORT. Currently following options
are supported:
通过定义 CONFIG_SPL_XXX_SUPPORT来使能支持的功能&驱动

目前支持的有:
CONFIG_SPL_LIBCOMMON_SUPPORT (common/libcommon.o)
CONFIG_SPL_LIBDISK_SUPPORT (disk/libdisk.o)
CONFIG_SPL_I2C_SUPPORT (drivers/i2c/libi2c.o)
CONFIG_SPL_GPIO_SUPPORT (drivers/gpio/libgpio.o)
CONFIG_SPL_MMC_SUPPORT (drivers/mmc/libmmc.o)
CONFIG_SPL_SERIAL_SUPPORT (drivers/serial/libserial.o)
CONFIG_SPL_SPI_FLASH_SUPPORT (drivers/mtd/spi/libspi_flash.o)
CONFIG_SPL_SPI_SUPPORT (drivers/spi/libspi.o)
CONFIG_SPL_FAT_SUPPORT (fs/fat/libfat.o)
CONFIG_SPL_EXT_SUPPORT
CONFIG_SPL_LIBGENERIC_SUPPORT (lib/libgeneric.o)
CONFIG_SPL_POWER_SUPPORT (drivers/power/libpower.o)
CONFIG_SPL_NAND_SUPPORT (drivers/mtd/nand/libnand.o)
CONFIG_SPL_DRIVERS_MISC_SUPPORT (drivers/misc)
CONFIG_SPL_DMA_SUPPORT (drivers/dma/libdma.o)
CONFIG_SPL_POST_MEM_SUPPORT (post/drivers/memory.o)
CONFIG_SPL_NAND_LOAD (drivers/mtd/nand/nand_spl_load.o)
CONFIG_SPL_SPI_LOAD (drivers/mtd/spi/spi_spl_load.o)
CONFIG_SPL_RAM_DEVICE (common/spl/spl.c)
CONFIG_SPL_WATCHDOG_SUPPORT (drivers/watchdog/libwatchdog.o)


Debugging
---------

When building SPL with DEBUG set you may also need to set CONFIG_PANIC_HANG
as in most cases do_reset is not defined within SPL.


Estimating stack usage
----------------------

With gcc 4.6 (and later) and the use of GNU cflow it is possible to estimate
stack usage at various points in run sequence of SPL. The -fstack-usage option
to gcc will produce '.su' files (such as arch/arm/cpu/armv7/syslib.su) that
will give stack usage information and cflow can construct program flow.

Must have gcc 4.6 or later, which supports -fstack-usage

1) Build normally
2) Perform the following shell command to generate a list of C files used in
SPL:
$ find spl -name '*.su' | sed -e 's:^spl/::' -e 's:[.]su$:.c:' > used-spl.list
3) Execute cflow:
$ cflow --main=board_init_r `cat used-spl.list` 2>&1 | $PAGER

cflow will spit out a number of warnings as it does not parse
the config files and picks functions based on #ifdef. Parsing the '.i'
files instead introduces another set of headaches. These warnings are
not usually important to understanding the flow, however.

REF: https://github.com/ARM-software/u-boot/blob/master/doc/README.SPL

CONFIG_SUPPORT_SPL, CONFIG_SPL,CONFIG_SPL_BUILD的作用

  • CONFIG_SUPPORT_SPL: 表示是否支持SPL功能
  • CONFIG_SPL: 表示是否使能SPL
  • CONFIG_SPL_BUILD: 因为SPL和u-boot共用一个源码体系,他们之间通过这个宏来在源码中分开;

CONFIG_SUPPORT_SPL,CONFIG_SPL在common/spl/kconifg中定义
image-20220318125907718

CONFIG_SUPPORT_SPL配置

CONFIG_SUPPORT_SPL一般在具体的arch的Kconfig中配置,如:
image-20220318125927819

CONFIG_SPL配置

CONFIG_SPL依赖CONFIG_SUPPORT_SPL,只有使能CONFIG_SUPPORT_SPL,配置才有效,可以直接在arch的Kconfig中select SPL, 也可以写到xxx_defconfig文件中,如:
image-20220318125945991

CONFIG_SPL_BUILD在何处定义的?

找了很久的资料,看到wowotech的这篇,才明白是在script/Makefile.spl
image-20220318130005505

image-20220318130023173

REF:http://www.wowotech.net/forum/viewtopic.php?id=29

SPL Framework

CONFIG_SPL
Enable building of SPL globally.
全局使能SPL编译,定义后才会编译SPL,生成最终目标位于spl/u-boot-spl.bin

CONFIG_SPL_LDSCRIPT
LDSCRIPT for linking the SPL binary.
配置spl链接脚本路径

CONFIG_SPL_MAX_FOOTPRINT
Maximum size in memory allocated to the SPL, BSS included.
When defined, the linker checks that the actual memory
used by SPL from _start to __bss_end does not exceed it.
CONFIG_SPL_MAX_FOOTPRINT and CONFIG_SPL_BSS_MAX_SIZE
must not be both defined at the same time.
分配给SPL的最大堆内存空间,包括BSS段;定义后,链接器检查(__bss_end - _start)的大小,确保不超过CONFIG_SPL_MAX_FOOTPRINT; 不能和CONFIG_SPL_BSS_MAX_SIZE同时定义
image-20220319000241421

CONFIG_SPL_MAX_SIZE
Maximum size of the SPL image (text, data, rodata, and
linker lists sections), BSS excluded.
When defined, the linker checks that the actual size does
not exceed it.
SPL固件的最大大小,不包括BSS,定义后,链接器检查(__image_copy_end - __image_copy_start)的大小,确保不超过CONFIG_SPL_MAX_SIZE
image-20220319000934883

CONFIG_SPL_BSS_MAX_SIZE
Maximum size in memory allocated to the SPL BSS.
When defined, the linker checks that the actual memory used
by SPL from __bss_start to __bss_end does not exceed it.
CONFIG_SPL_MAX_FOOTPRINT and CONFIG_SPL_BSS_MAX_SIZE
must not be both defined at the same time.
SPL BSS段的最大大小,定义时,链接器将检查(__bss_end - __bss_start)的大小,确保不超过CONFIG_SPL_BSS_MAX_SIZE
image-20220319002447105

CONFIG_SPL_TEXT_BASE
TEXT_BASE for linking the SPL binary.
链接地址,SPL在内存中的运行入口地址

CONFIG_SPL_RELOC_TEXT_BASE
Address to relocate to. If unspecified, this is equal to
CONFIG_SPL_TEXT_BASE (i.e. no relocation is done).
CONFIG_SPL_BSS_START_ADDR
Link address for the BSS within the SPL binary.
SPL自己搬迁(relocate)的目的地址,如果不定义则和CONFIG_SPL_TEXT_BASE一样(这样将不会relocate)

CONFIG_SPL_STACK
Adress of the start of the stack SPL will use
SPL使用的栈的起始地址

CONFIG_SPL_PANIC_ON_RAW_IMAGE
When defined, SPL will panic() if the image it has
loaded does not have a signature.
Defining this is useful when code which loads images
in SPL cannot guarantee that absolutely all read errors
will be caught.
An example is the LPC32XX MLC NAND driver, which will
consider that a completely unreadable NAND block is bad,
and thus should be skipped silently.
定义时,SPL将执行panic()如果image没有签名。当不能完全保证所有的读取错误被捕获时,这个操作是很有用的。

CONFIG_SPL_RELOC_STACK
Adress of the start of the stack SPL will use after
relocation. If unspecified, this is equal to
CONFIG_SPL_STACK.
SPL迁移(relocate),<假如迁移的话>,迁移后的栈首地址,如果没有定义等于CONFIG_SPL_STACK

CONFIG_SYS_SPL_MALLOC_START
Starting address of the malloc pool used in SPL.
When this option is set the full malloc is used in SPL and
it is set up by spl_init() and before that, the simple malloc()
can be used if CONFIG_SYS_MALLOC_F is defined.
SPL使用的malloc内存池的起始地址。
当定义,SPL将使用在spl_init()中设置的full malloc(),在此之前,可以使用simple malloc(), 如果CONFIG_SYS_MALLOC_F被定义。

CONFIG_SYS_SPL_MALLOC_SIZE
The size of the malloc pool used in SPL.
SPL使用的malloc内存池大小。

CONFIG_SPL_OS_BOOT
Enable booting directly to an OS from SPL.
See also: doc/README.falcon
定义后,可以直接从SPL中启动系统

CONFIG_SPL_DISPLAY_PRINT
For ARM, enable an optional function to print more information
about the running system.
对于ARM架构,定义后,将使能打印更多系统信息

CONFIG_SPL_INIT_MINIMAL
Arch init code should be built for a very small image

CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION
Partition on the MMC to load U-Boot from when the MMC is being
used in raw mode
在raw模式下,使用MMC启动时,加载u-boot时的分区

CONFIG_SYS_MMCSD_RAW_MODE_KERNEL_SECTOR
Sector to load kernel uImage from when MMC is being
used in raw mode (for Falcon mode)
CONFIG_SYS_MMCSD_RAW_MODE_ARGS_SECTOR,
CONFIG_SYS_MMCSD_RAW_MODE_ARGS_SECTORS
Sector and number of sectors to load kernel argument
parameters from when MMC is being used in raw mode
(for falcon mode)

CONFIG_SYS_MMCSD_FS_BOOT_PARTITION
Partition on the MMC to load U-Boot from when the MMC is being
used in fs mode
在fs模式下,使用MMC启动时,加载u-boot时的分区

CONFIG_SPL_FS_LOAD_PAYLOAD_NAME
Filename to read to load U-Boot when reading from filesystem
在fs模式下,加载u-boot时,从文件系统中读取的文件名

CONFIG_SPL_FS_LOAD_KERNEL_NAME
Filename to read to load kernel uImage when reading
from filesystem (for Falcon mode)

CONFIG_SPL_FS_LOAD_ARGS_NAME
Filename to read to load kernel argument parameters
when reading from filesystem (for Falcon mode)

CONFIG_SPL_MPC83XX_WAIT_FOR_NAND
Set this for NAND SPL on PPC mpc83xx targets, so that
start.S waits for the rest of the SPL to load before
continuing (the hardware starts execution after just
loading the first page rather than the full 4K).

CONFIG_SPL_SKIP_RELOCATE
Avoid SPL relocation
定义后,SPL将不会被relocate

CONFIG_SPL_NAND_BASE
Include nand_base.c in the SPL. Requires
CONFIG_SPL_NAND_DRIVERS.
定义后,将包含nand_base.c,需要定义CONFIG_SPL_NAND_DRIVERS

CONFIG_SPL_NAND_DRIVERS
SPL uses normal NAND drivers, not minimal drivers.
定义后,SPL使用normal Nand驱动,而不是minimal驱动

CONFIG_SPL_NAND_IDENT
SPL uses the chip ID list to identify the NAND flash.
Requires CONFIG_SPL_NAND_BASE.
SPL使用芯片Id来识别nand flash型号,需要定义CONFIG_SPL_NAND_BASE

CONFIG_SPL_NAND_ECC
Include standard software ECC in the SPL
定义后,将包含标准的软件ECC实现

CONFIG_SPL_NAND_SIMPLE
Support for NAND boot using simple NAND drivers that
expose the cmd_ctrl() interface.
定义后,使用简单的nand驱动,暴露cmd_ctrl()接口

CONFIG_SPL_UBI
Support for a lightweight UBI (fastmap) scanner and loader
支持轻量级的UBI scanner 和loader.
(UBI相关介绍: http://velep.com/archives/909.html)

CONFIG_SPL_NAND_RAW_ONLY
Support to boot only raw u-boot.bin images. Use this only
if you need to save space.

CONFIG_SPL_COMMON_INIT_DDR
Set for common ddr init with serial presence detect in
SPL binary.
定义后,将使用通用的ddr初始化程序

CONFIG_SYS_NAND_5_ADDR_CYCLE, CONFIG_SYS_NAND_PAGE_COUNT,
CONFIG_SYS_NAND_PAGE_SIZE, CONFIG_SYS_NAND_OOBSIZE,
CONFIG_SYS_NAND_BLOCK_SIZE, CONFIG_SYS_NAND_BAD_BLOCK_POS,
CONFIG_SYS_NAND_ECCPOS, CONFIG_SYS_NAND_ECCSIZE,
CONFIG_SYS_NAND_ECCBYTES

Defines the size and behavior of the NAND that SPL uses
to read U-Boot
定义nand相关信息

CONFIG_SPL_NAND_BOOT
Add support NAND boot
支持从nand启动

CONFIG_SYS_NAND_U_BOOT_OFFS
Location in NAND to read U-Boot from
从Nand中读取u-boot的偏移地址

CONFIG_SYS_NAND_U_BOOT_DST
Location in memory to load U-Boot to
将u-boot加载到内存中的地址

CONFIG_SYS_NAND_U_BOOT_SIZE
Size of image to load
需要加载的u-boot的大小

CONFIG_SYS_NAND_U_BOOT_START
Entry point in loaded image to jump to
加载u-boot后,跳转到u-boot运行时,跳转的入口地址

CONFIG_SYS_NAND_HW_ECC_OOBFIRST
Define this if you need to first read the OOB and then the
data. This is used, for example, on davinci platforms.
定义后,将先读OOB,然后读data

CONFIG_SPL_RAM_DEVICE
Support for running image already present in ram, in SPL binary

CONFIG_SPL_PAD_TO
Image offset to which the SPL should be padded before appending
the SPL payload. By default, this is defined as
CONFIG_SPL_MAX_SIZE, or 0 if CONFIG_SPL_MAX_SIZE is undefined.
CONFIG_SPL_PAD_TO must be either 0, meaning to append the SPL
payload without any padding, or >= CONFIG_SPL_MAX_SIZE.

CONFIG_SPL_TARGET
Final target image containing SPL and payload. Some SPLs
use an arch-specific makefile fragment instead, for
example if more than one image needs to be produced.

CONFIG_SPL_FIT_PRINT
Printing information about a FIT image adds quite a bit of
code to SPL. So this is normally disabled in SPL. Use this
option to re-enable it. This will affect the output of the
bootm command when booting a FIT image.