mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-10 15:14:43 +00:00
Merge git://git.denx.de/u-boot-sunxi
trini: Make Kconfig SPL_xxx entires only show if SPL, so that we don't get Kconfig errors on platforms without SPL, ie sandbox (without SPL). Signed-off-by: Tom Rini <trini@konsulko.com>
This commit is contained in:
commit
711391131c
18 changed files with 719 additions and 230 deletions
26
Kconfig
26
Kconfig
|
@ -220,18 +220,22 @@ config FIT_IMAGE_POST_PROCESS
|
|||
injected into the FIT creation (i.e. the blobs would have been pre-
|
||||
processed before being added to the FIT image).
|
||||
|
||||
if SPL
|
||||
|
||||
config SPL_FIT
|
||||
bool "Support Flattened Image Tree within SPL"
|
||||
depends on SPL
|
||||
select SPL_OF_LIBFDT
|
||||
|
||||
config SPL_FIT_SIGNATURE
|
||||
bool "Enable signature verification of FIT firmware within SPL"
|
||||
depends on SPL_FIT
|
||||
depends on SPL_DM
|
||||
select SPL_FIT
|
||||
select SPL_RSA
|
||||
|
||||
config SPL_LOAD_FIT
|
||||
bool "Enable SPL loading U-Boot as a FIT"
|
||||
select SPL_FIT
|
||||
help
|
||||
Normally with the SPL framework a legacy image is generated as part
|
||||
of the build. This contains U-Boot along with information as to
|
||||
|
@ -254,6 +258,26 @@ config SPL_FIT_IMAGE_POST_PROCESS
|
|||
injected into the FIT creation (i.e. the blobs would have been pre-
|
||||
processed before being added to the FIT image).
|
||||
|
||||
config SPL_FIT_SOURCE
|
||||
string ".its source file for U-Boot FIT image"
|
||||
depends on SPL_FIT
|
||||
help
|
||||
Specifies a (platform specific) FIT source file to generate the
|
||||
U-Boot FIT image. This could specify further image to load and/or
|
||||
execute.
|
||||
|
||||
config SPL_FIT_GENERATOR
|
||||
string ".its file generator script for U-Boot FIT image"
|
||||
depends on SPL_FIT
|
||||
default "board/sunxi/mksunxi_fit_atf.sh" if SPL_LOAD_FIT && ARCH_SUNXI
|
||||
help
|
||||
Specifies a (platform specific) script file to generate the FIT
|
||||
source file used to build the U-Boot FIT image file. This gets
|
||||
passed a list of supported device tree file stub names to
|
||||
include in the generated image.
|
||||
|
||||
endif # SPL
|
||||
|
||||
endif # FIT
|
||||
|
||||
config OF_BOARD_SETUP
|
||||
|
|
20
Makefile
20
Makefile
|
@ -833,6 +833,10 @@ quiet_cmd_mkimage = MKIMAGE $@
|
|||
cmd_mkimage = $(objtree)/tools/mkimage $(MKIMAGEFLAGS_$(@F)) -d $< $@ \
|
||||
$(if $(KBUILD_VERBOSE:1=), >$(MKIMAGEOUTPUT))
|
||||
|
||||
quiet_cmd_mkfitimage = MKIMAGE $@
|
||||
cmd_mkfitimage = $(objtree)/tools/mkimage $(MKIMAGEFLAGS_$(@F)) -f $(U_BOOT_ITS) -E $@ \
|
||||
$(if $(KBUILD_VERBOSE:1=), >$(MKIMAGEOUTPUT))
|
||||
|
||||
quiet_cmd_cat = CAT $@
|
||||
cmd_cat = cat $(filter-out $(PHONY), $^) > $@
|
||||
|
||||
|
@ -952,6 +956,19 @@ quiet_cmd_cpp_cfg = CFG $@
|
|||
cmd_cpp_cfg = $(CPP) -Wp,-MD,$(depfile) $(cpp_flags) $(LDPPFLAGS) -ansi \
|
||||
-DDO_DEPS_ONLY -D__ASSEMBLY__ -x assembler-with-cpp -P -dM -E -o $@ $<
|
||||
|
||||
# Boards with more complex image requirments can provide an .its source file
|
||||
# or a generator script
|
||||
ifneq ($(CONFIG_SPL_FIT_SOURCE),"")
|
||||
U_BOOT_ITS = $(subst ",,$(CONFIG_SPL_FIT_SOURCE))
|
||||
else
|
||||
ifneq ($(CONFIG_SPL_FIT_GENERATOR),"")
|
||||
U_BOOT_ITS := u-boot.its
|
||||
$(U_BOOT_ITS): FORCE
|
||||
$(srctree)/$(CONFIG_SPL_FIT_GENERATOR) \
|
||||
$(patsubst %,arch/$(ARCH)/dts/%.dtb,$(subst ",,$(CONFIG_OF_LIST))) > $@
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef CONFIG_SPL_LOAD_FIT
|
||||
MKIMAGEFLAGS_u-boot.img = -f auto -A $(ARCH) -T firmware -C none -O u-boot \
|
||||
-a $(CONFIG_SYS_TEXT_BASE) -e $(CONFIG_SYS_UBOOT_START) \
|
||||
|
@ -984,6 +1001,9 @@ u-boot-dtb.img u-boot.img u-boot.kwb u-boot.pbl u-boot-ivt.img: \
|
|||
$(if $(CONFIG_SPL_LOAD_FIT),u-boot-nodtb.bin dts/dt.dtb,u-boot.bin) FORCE
|
||||
$(call if_changed,mkimage)
|
||||
|
||||
u-boot.itb: u-boot-nodtb.bin dts/dt.dtb $(U_BOOT_ITS) FORCE
|
||||
$(call if_changed,mkfitimage)
|
||||
|
||||
u-boot-spl.kwb: u-boot.img spl/u-boot-spl.bin FORCE
|
||||
$(call if_changed,mkimage)
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
#define BOOT0_MAGIC "eGON.BT0"
|
||||
#define SPL_SIGNATURE "SPL" /* marks "sunxi" SPL header */
|
||||
#define SPL_HEADER_VERSION 1
|
||||
#define SPL_HEADER_VERSION 2
|
||||
|
||||
#ifdef CONFIG_SUNXI_HIGH_SRAM
|
||||
#define SPL_ADDR 0x10000
|
||||
|
@ -58,11 +58,24 @@ struct boot_file_head {
|
|||
* compatible format, ready to be imported via "env import -t".
|
||||
*/
|
||||
uint32_t fel_uEnv_length;
|
||||
uint32_t reserved1[2];
|
||||
/*
|
||||
* Offset of an ASCIIZ string (relative to the SPL header), which
|
||||
* contains the default device tree name (CONFIG_DEFAULT_DEVICE_TREE).
|
||||
* This is optional and may be set to NULL. Is intended to be used
|
||||
* by flash programming tools for providing nice informative messages
|
||||
* to the users.
|
||||
*/
|
||||
uint32_t dt_name_offset;
|
||||
uint32_t reserved1;
|
||||
uint32_t boot_media; /* written here by the boot ROM */
|
||||
uint32_t reserved2[5]; /* padding, align to 64 bytes */
|
||||
/* A padding area (may be used for storing text strings) */
|
||||
uint32_t string_pool[13];
|
||||
/* The header must be a multiple of 32 bytes (for VBAR alignment) */
|
||||
};
|
||||
|
||||
/* Compile time check to assure proper alignment of structure */
|
||||
typedef char boot_file_head_not_multiple_of_32[1 - 2*(sizeof(struct boot_file_head) % 32)];
|
||||
|
||||
#define is_boot0_magic(addr) (memcmp((void *)addr, BOOT0_MAGIC, 8) == 0)
|
||||
|
||||
#endif
|
||||
|
|
|
@ -44,8 +44,10 @@ obj-y += stack.o
|
|||
ifdef CONFIG_CPU_V7M
|
||||
obj-y += interrupts_m.o
|
||||
else ifdef CONFIG_ARM64
|
||||
obj-y += ccn504.o
|
||||
obj-$(CONFIG_FSL_LAYERSCAPE) += ccn504.o
|
||||
ifneq ($(CONFIG_GICV2)$(CONFIG_GICV3),)
|
||||
obj-y += gic_64.o
|
||||
endif
|
||||
obj-y += interrupts_64.o
|
||||
else
|
||||
obj-y += interrupts.o
|
||||
|
|
|
@ -143,12 +143,16 @@ config MACH_SUN50I
|
|||
select SUNXI_GEN_SUN6I
|
||||
select SUNXI_HIGH_SRAM
|
||||
select SUPPORT_SPL
|
||||
select FIT
|
||||
select SPL_LOAD_FIT
|
||||
|
||||
config MACH_SUN50I_H5
|
||||
bool "sun50i (Allwinner H5)"
|
||||
select ARM64
|
||||
select MACH_SUNXI_H3_H5
|
||||
select SUNXI_HIGH_SRAM
|
||||
select FIT
|
||||
select SPL_LOAD_FIT
|
||||
|
||||
endchoice
|
||||
|
||||
|
|
|
@ -72,7 +72,6 @@ F: configs/q8_a33_tablet_1024x600_defconfig
|
|||
F: include/configs/sun9i.h
|
||||
F: configs/Merrii_A80_Optimus_defconfig
|
||||
F: include/configs/sun50i.h
|
||||
F: configs/pine64_plus_defconfig
|
||||
|
||||
A20-OLIMEX-SOM-EVB BOARD
|
||||
M: Marcus Cooper <codekipper@gmail.com>
|
||||
|
@ -263,6 +262,11 @@ M: Andre Przywara <andre.przywara@arm.com>
|
|||
S: Maintained
|
||||
F: configs/orangepi_pc2_defconfig
|
||||
|
||||
PINE64 BOARDS
|
||||
M: Andre Przywara <andre.przywara@arm.com>
|
||||
S: Maintained
|
||||
F: configs/pine64_plus_defconfig
|
||||
|
||||
R16 EVB PARROT BOARD
|
||||
M: Quentin Schulz <quentin.schulz@free-electrons.com>
|
||||
S: Maintained
|
||||
|
|
|
@ -1,98 +0,0 @@
|
|||
Pine64 board README
|
||||
====================
|
||||
|
||||
The Pine64(+) is a single board computer equipped with an AArch64 capable ARMv8
|
||||
compliant Allwinner A64 SoC.
|
||||
This chip has ARM Cortex A-53 cores and thus can run both in AArch32
|
||||
(compatible to 32-bit ARMv7) and AArch64 modes. Upon reset the SoC starts
|
||||
in AArch32 mode and executes 32-bit code from the Boot ROM (BROM).
|
||||
This has some implications on U-Boot.
|
||||
|
||||
Quick start
|
||||
============
|
||||
- Get hold of a boot0.img file (see below for more details).
|
||||
- Get the boot0img tool source from the tools directory in [1] and compile
|
||||
that on your host.
|
||||
- Build U-Boot:
|
||||
$ export CROSS_COMPILE=aarch64-linux-gnu-
|
||||
$ make pine64_plus_defconfig
|
||||
$ make
|
||||
- You also need a compiled ARM Trusted Firmware (ATF) binary. Checkout the
|
||||
"allwinner" branch from the github repository [2] and build it:
|
||||
$ export CROSS_COMPILE=aarch64-linux-gnu-
|
||||
$ make PLAT=sun50iw1p1 DEBUG=1 bl31
|
||||
The resulting binary is build/sun50iw1p1/debug/bl31.bin.
|
||||
|
||||
Now put an empty (or disposable) micro SD card in your card reader and learn
|
||||
its device file name, replacing /dev/sd<x> below with the result (that could
|
||||
be /dev/mmcblk<x> as well):
|
||||
|
||||
$ ./boot0img --device /dev/sd<x> -e -u u-boot.bin -B boot0.img \
|
||||
-d trampoline64:0x44000 -s bl31.bin -a 0x44008 -p 100
|
||||
(either copying the respective files to the working directory or specifying
|
||||
the paths directly)
|
||||
|
||||
This will create a new partition table (with a 100 MB FAT boot partition),
|
||||
copies boot0.img, ATF and U-Boot to the proper locations on the SD card and
|
||||
will fill in the magic Allwinner header to be recognized by boot0.
|
||||
Prefix the above call with "sudo" if you don't have write access to the
|
||||
uSD card. You can also use "-o output.img" instead of "--device /dev/sd<x>"
|
||||
to create an image file and "dd" that to the uSD card.
|
||||
Omitting the "-p" option will skip the partition table.
|
||||
|
||||
Now put this uSD card in the board and power it on. You should be greeted by
|
||||
the U-Boot prompt.
|
||||
|
||||
|
||||
Main U-Boot
|
||||
============
|
||||
The main U-Boot proper is a real 64-bit ARMv8 port and runs entirely in the
|
||||
64-bit AArch64 mode. It can load any AArch64 code, EFI applications or arm64
|
||||
Linux kernel images (often named "Image") using the booti command.
|
||||
Launching 32-bit code and kernels is technically possible, though not without
|
||||
drawbacks (or hacks to avoid them) and currently not implemented.
|
||||
|
||||
SPL support
|
||||
============
|
||||
The main task of the SPL support is to bring up the DRAM controller and make
|
||||
DRAM actually accessible. At the moment there is no documentation or source
|
||||
code available which would do this.
|
||||
There are currently two ways to overcome this situation: using a tainted 32-bit
|
||||
SPL (involving some hacks and resulting in a non-redistributable binary, thus
|
||||
not described here) or using the Allwinner boot0 blob.
|
||||
|
||||
boot0 method
|
||||
-------------
|
||||
boot0 is Allwiner's secondary program loader and it can be used as some kind
|
||||
of SPL replacement to get U-Boot up and running.
|
||||
The binary is a 32 KByte blob and contained on every Pine64 image distributed
|
||||
so far. It can be easily extracted from a micro SD card or an image file:
|
||||
# dd if=/dev/sd<x> of=boot0.bin bs=8k skip=1 count=4
|
||||
where /dev/sd<x> is the device name of the uSD card or the name of the image
|
||||
file. Apparently Allwinner allows re-distribution of this proprietary code
|
||||
as-is.
|
||||
For the time being this boot0 blob is the only redistributable way of making
|
||||
U-Boot work on the Pine64. Beside loading the various parts of the (original)
|
||||
firmware it also switches the core into AArch64 mode.
|
||||
The original boot0 code looks for U-Boot at a certain place on an uSD card
|
||||
(at 19096 KB), also it expects a header with magic bytes and a checksum.
|
||||
There is a tool called boot0img[1] which takes a boot0.bin image and a compiled
|
||||
U-Boot binary (plus other binaries) and will populate that header accordingly.
|
||||
To make space for the magic header, the pine64_plus_defconfig will make sure
|
||||
there is sufficient space at the beginning of the U-Boot binary.
|
||||
boot0img will also take care of putting the different binaries at the right
|
||||
places on the uSD card and works around unused, but mandatory parts by using
|
||||
trampoline code. See the output of "boot0img -h" for more information.
|
||||
boot0img can also patch boot0 to avoid loading U-Boot from 19MB, instead
|
||||
fetching it from just behind the boot0 binary (-B option).
|
||||
|
||||
FEL boot
|
||||
=========
|
||||
FEL is the name of the Allwinner defined USB boot protocol built-in the
|
||||
mask ROM of most Allwinner SoCs. It allows to bootstrap a board solely
|
||||
by using the USB-OTG interface and a host port on another computer.
|
||||
Since FEL boot does not work with boot0, it requires the libdram hack, which
|
||||
is not described here.
|
||||
|
||||
[1] https://github.com/apritzel/pine64/
|
||||
[2] https://github.com/apritzel/arm-trusted-firmware.git
|
165
board/sunxi/README.sunxi64
Normal file
165
board/sunxi/README.sunxi64
Normal file
|
@ -0,0 +1,165 @@
|
|||
Allwinner 64-bit boards README
|
||||
==============================
|
||||
|
||||
Newer Allwinner SoCs feature ARMv8 cores (ARM Cortex-A53) with support for
|
||||
both the 64-bit AArch64 mode and the ARMv7 compatible 32-bit AArch32 mode.
|
||||
Examples are the Allwinner A64 (used for instance on the Pine64 board) or
|
||||
the Allwinner H5 SoC (as used on the OrangePi PC 2).
|
||||
These SoCs are wired to start in AArch32 mode on reset and execute 32-bit
|
||||
code from the Boot ROM (BROM). As this has some implications on U-Boot, this
|
||||
file describes how to make full use of the 64-bit capabilities.
|
||||
|
||||
Quick Start / Overview
|
||||
======================
|
||||
- Build the ARM Trusted Firmware binary (see "ARM Trusted Firmware (ATF)" below)
|
||||
- Build U-Boot (see "SPL/U-Boot" below)
|
||||
- Transfer to an uSD card (see "microSD card" below)
|
||||
- Boot and enjoy!
|
||||
|
||||
Building the firmware
|
||||
=====================
|
||||
|
||||
The Allwinner A64/H5 firmware consists of three parts: U-Boot's SPL, an
|
||||
ARM Trusted Firmware (ATF) build and the U-Boot proper.
|
||||
The SPL will load both ATF and U-Boot proper along with the right device
|
||||
tree blob (.dtb) and will pass execution to ATF (in EL3), which in turn will
|
||||
drop into the U-Boot proper (in EL2).
|
||||
As the ATF binary will become part of the U-Boot image file, you will need
|
||||
to build it first.
|
||||
|
||||
ARM Trusted Firmware (ATF)
|
||||
----------------------------
|
||||
Checkout the "allwinner" branch from the github repository [1] and build it:
|
||||
$ export CROSS_COMPILE=aarch64-linux-gnu-
|
||||
$ make PLAT=sun50iw1p1 DEBUG=1 bl31
|
||||
The resulting binary is build/sun50iw1p1/debug/bl31.bin. Either put the
|
||||
location of this file into the BL31 environment variable or copy this to
|
||||
the root of your U-Boot build directory (or create a symbolic link).
|
||||
$ export BL31=/src/arm-trusted-firmware/build/sun50iw1p1/debug/bl31.bin
|
||||
(adjust the actual path accordingly)
|
||||
|
||||
SPL/U-Boot
|
||||
------------
|
||||
Both U-Boot proper and the SPL are using the 64-bit mode. As the boot ROM
|
||||
enters the SPL still in AArch32 secure SVC mode, there is some shim code to
|
||||
enter AArch64 very early. The rest of the SPL runs in AArch64 EL3.
|
||||
U-Boot proper runs in EL2 and can load any AArch64 code (using the "go"
|
||||
command), EFI applications (with "bootefi") or arm64 Linux kernel images
|
||||
(often named "Image"), using the "booti" command.
|
||||
|
||||
$ make clean
|
||||
$ export CROSS_COMPILE=aarch64-linux-gnu-
|
||||
$ make pine64_plus_defconfig
|
||||
$ make
|
||||
|
||||
This will build the SPL in spl/sunxi-spl.bin and a FIT image called u-boot.itb,
|
||||
which contains the rest of the firmware.
|
||||
|
||||
|
||||
Boot process
|
||||
============
|
||||
The on-die BROM code will try several methods to load and execute the firmware.
|
||||
On a typical board like the Pine64 this will result in the following boot order:
|
||||
|
||||
1) Reading 32KB from sector 16 (@8K) of the microSD card to SRAM A1. If the
|
||||
BROM finds the magic "eGON" header in the first bytes, it will execute that
|
||||
code. If not (no SD card at all or invalid magic), it will:
|
||||
2) Try to read 32KB from sector 16 (@8K) of memory connected to the MMC2
|
||||
controller, typically an on-board eMMC chip. If there is no eMMC or it does
|
||||
not contain a valid boot header, it will:
|
||||
3) Initialize the SPI0 controller and try to access a NOR flash connected to
|
||||
it (using the CS0 pin). If a flash chip is found, the BROM will load the
|
||||
first 32KB (from offset 0) into SRAM A1. Now it checks for the magic eGON
|
||||
header and checksum and will execute the code upon finding it. If not, it will:
|
||||
4) Initialize the USB OTG controller and will wait for a host to connect to
|
||||
it, speaking the Allwinner proprietary (but deciphered) "FEL" USB protocol.
|
||||
|
||||
|
||||
To boot the Pine64 board, you can use U-Boot and any of the described methods.
|
||||
|
||||
FEL boot (USB OTG)
|
||||
------------------
|
||||
FEL is the name of the Allwinner defined USB boot protocol built in the
|
||||
mask ROM of most Allwinner SoCs. It allows to bootstrap a board solely
|
||||
by using the USB-OTG interface and a host port on another computer.
|
||||
As the FEL mode is controlled by the boot ROM, it expects to be running in
|
||||
AArch32. For now the AArch64 SPL cannot properly return into FEL mode, so the
|
||||
feature is disabled in the configuration at the moment.
|
||||
|
||||
microSD card
|
||||
------------
|
||||
Transfer the SPL and the U-Boot FIT image directly to an uSD card:
|
||||
# dd if=spl/sunxi-spl.bin of=/dev/sdx bs=8k seek=1
|
||||
# dd if=u-boot.itb of=/dev/sdx bs=8k seek=5
|
||||
# sync
|
||||
(replace /dev/sdx with you SD card device file name, which could be
|
||||
/dev/mmcblk[x] as well).
|
||||
|
||||
Alternatively you can concatenate the SPL and the U-Boot FIT image into a
|
||||
single file and transfer that instead:
|
||||
$ cat spl/sunxi-spl.bin u-boot.itb > u-boot-sunxi-with-spl.bin
|
||||
# dd if=u-boot-sunxi-with-spl.bin of=/dev/sdx bs=8k seek=1
|
||||
|
||||
You can partition the microSD card, but leave the first MB unallocated (most
|
||||
partitioning tools will do this anyway).
|
||||
|
||||
NOR flash
|
||||
---------
|
||||
Some boards (like the SoPine, Pinebook or the OrangePi PC2) come with a
|
||||
soldered SPI NOR flash chip. On other boards like the Pine64 such a chip
|
||||
can be connected to the SPI0/CS0 pins on the PI-2 headers.
|
||||
Create the SPL and FIT image like described above for the SD card.
|
||||
Now connect either an "A to A" USB cable to the upper USB port on the Pine64
|
||||
or get an adaptor and use a regular A-microB cable connected to it. Other
|
||||
boards often have a proper micro-B USB socket connected to the USB OTB port.
|
||||
Remove a microSD card from the slot and power on the board.
|
||||
On your host computer download and build the sunxi-tools package[2], then
|
||||
use "sunxi-fel" to access the board:
|
||||
$ ./sunxi-fel ver -v -p
|
||||
This should give you an output starting with: AWUSBFEX soc=00001689(A64) ...
|
||||
Now use the sunxi-fel tool to write to the NOR flash:
|
||||
$ ./sunxi-fel spiflash-write 0 spl/sunxi-spl.bin
|
||||
$ ./sunxi-fel spiflash-write 32768 u-boot.itb
|
||||
Now boot the board without an SD card inserted and you should see the
|
||||
U-Boot prompt on the serial console.
|
||||
|
||||
(Legacy) boot0 method
|
||||
---------------------
|
||||
boot0 is Allwiner's secondary program loader and it can be used as some kind
|
||||
of SPL replacement to get U-Boot up and running from an microSD card.
|
||||
For some time using boot0 was the only option to get the Pine64 booted.
|
||||
With working DRAM init code in U-Boot's SPL this is no longer necessary,
|
||||
but this method is described here for the sake of completeness.
|
||||
Please note that this method works only with the boot0 files shipped with
|
||||
A64 based boards, the H5 uses an incompatible layout which is not supported
|
||||
by this method.
|
||||
|
||||
The boot0 binary is a 32 KByte blob and contained in the official Pine64 images
|
||||
distributed by Pine64 or Allwinner. It can be easily extracted from a micro
|
||||
SD card or an image file:
|
||||
# dd if=/dev/sd<x> of=boot0.bin bs=8k skip=1 count=4
|
||||
where /dev/sd<x> is the device name of the uSD card or the name of the image
|
||||
file. Apparently Allwinner allows re-distribution of this proprietary code
|
||||
"as-is".
|
||||
This boot0 blob takes care of DRAM initialisation and loads the remaining
|
||||
firmware parts, then switches the core into AArch64 mode.
|
||||
The original boot0 code looks for U-Boot at a certain place on an uSD card
|
||||
(at 19096 KB), also it expects a header with magic bytes and a checksum.
|
||||
There is a tool called boot0img[3] which takes a boot0.bin image and a compiled
|
||||
U-Boot binary (plus other binaries) and will populate that header accordingly.
|
||||
To make space for the magic header, the pine64_plus_defconfig will make sure
|
||||
there is sufficient space at the beginning of the U-Boot binary.
|
||||
boot0img will also take care of putting the different binaries at the right
|
||||
places on the uSD card and works around unused, but mandatory parts by using
|
||||
trampoline code. See the output of "boot0img -h" for more information.
|
||||
boot0img can also patch boot0 to avoid loading U-Boot from 19MB, instead
|
||||
fetching it from just behind the boot0 binary (-B option).
|
||||
$ ./boot0img -o firmware.img -B boot0.img -u u-boot-dtb.bin -e -s bl31.bin \
|
||||
-a 0x44008 -d trampoline64:0x44000
|
||||
Then write this image to a microSD card, replacing /dev/sdx with the right
|
||||
device file (see above):
|
||||
$ dd if=firmware.img of=/dev/sdx bs=8k seek=1
|
||||
|
||||
[1] https://github.com/apritzel/arm-trusted-firmware.git
|
||||
[2] git://github.com/linux-sunxi/sunxi-tools.git
|
||||
[3] https://github.com/apritzel/pine64/
|
|
@ -512,7 +512,6 @@ int board_mmc_init(bd_t *bis)
|
|||
void sunxi_board_init(void)
|
||||
{
|
||||
int power_failed = 0;
|
||||
unsigned long ramsize;
|
||||
|
||||
#ifdef CONFIG_SY8106A_POWER
|
||||
power_failed = sy8106a_set_vout1(CONFIG_SY8106A_VOUT1_VOLT);
|
||||
|
@ -573,9 +572,9 @@ void sunxi_board_init(void)
|
|||
#endif
|
||||
#endif
|
||||
printf("DRAM:");
|
||||
ramsize = sunxi_dram_init();
|
||||
printf(" %d MiB\n", (int)(ramsize >> 20));
|
||||
if (!ramsize)
|
||||
gd->ram_size = sunxi_dram_init();
|
||||
printf(" %d MiB\n", (int)(gd->ram_size >> 20));
|
||||
if (!gd->ram_size)
|
||||
hang();
|
||||
|
||||
/*
|
||||
|
@ -758,3 +757,32 @@ int ft_board_setup(void *blob, bd_t *bd)
|
|||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SPL_LOAD_FIT
|
||||
int board_fit_config_name_match(const char *name)
|
||||
{
|
||||
struct boot_file_head *spl = (void *)(ulong)SPL_ADDR;
|
||||
const char *cmp_str = (void *)(ulong)SPL_ADDR;
|
||||
|
||||
/* Check if there is a DT name stored in the SPL header and use that. */
|
||||
if (spl->dt_name_offset) {
|
||||
cmp_str += spl->dt_name_offset;
|
||||
} else {
|
||||
#ifdef CONFIG_DEFAULT_DEVICE_TREE
|
||||
cmp_str = CONFIG_DEFAULT_DEVICE_TREE;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
};
|
||||
|
||||
/* Differentiate the two Pine64 board DTs by their DRAM size. */
|
||||
if (strstr(name, "-pine64") && strstr(cmp_str, "-pine64")) {
|
||||
if ((gd->ram_size > 512 * 1024 * 1024))
|
||||
return !strstr(name, "plus");
|
||||
else
|
||||
return !!strstr(name, "plus");
|
||||
} else {
|
||||
return strcmp(name, cmp_str);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
75
board/sunxi/mksunxi_fit_atf.sh
Executable file
75
board/sunxi/mksunxi_fit_atf.sh
Executable file
|
@ -0,0 +1,75 @@
|
|||
#!/bin/sh
|
||||
#
|
||||
# script to generate FIT image source for 64-bit sunxi boards with
|
||||
# ARM Trusted Firmware and multiple device trees (given on the command line)
|
||||
#
|
||||
# usage: $0 <dt_name> [<dt_name> [<dt_name] ...]
|
||||
|
||||
[ -z "$BL31" ] && BL31="bl31.bin"
|
||||
|
||||
cat << __HEADER_EOF
|
||||
/dts-v1/;
|
||||
|
||||
/ {
|
||||
description = "Configuration to load ATF before U-Boot";
|
||||
#address-cells = <1>;
|
||||
|
||||
images {
|
||||
uboot@1 {
|
||||
description = "U-Boot (64-bit)";
|
||||
data = /incbin/("u-boot-nodtb.bin");
|
||||
type = "standalone";
|
||||
arch = "arm64";
|
||||
compression = "none";
|
||||
load = <0x4a000000>;
|
||||
};
|
||||
atf@1 {
|
||||
description = "ARM Trusted Firmware";
|
||||
data = /incbin/("$BL31");
|
||||
type = "firmware";
|
||||
arch = "arm64";
|
||||
compression = "none";
|
||||
load = <0x44000>;
|
||||
entry = <0x44000>;
|
||||
};
|
||||
__HEADER_EOF
|
||||
|
||||
cnt=1
|
||||
for dtname in $*
|
||||
do
|
||||
cat << __FDT_IMAGE_EOF
|
||||
fdt@$cnt {
|
||||
description = "$(basename $dtname .dtb)";
|
||||
data = /incbin/("$dtname");
|
||||
type = "flat_dt";
|
||||
compression = "none";
|
||||
};
|
||||
__FDT_IMAGE_EOF
|
||||
cnt=$((cnt+1))
|
||||
done
|
||||
|
||||
cat << __CONF_HEADER_EOF
|
||||
};
|
||||
configurations {
|
||||
default = "config@1";
|
||||
|
||||
__CONF_HEADER_EOF
|
||||
|
||||
cnt=1
|
||||
for dtname in $*
|
||||
do
|
||||
cat << __CONF_SECTION_EOF
|
||||
config@$cnt {
|
||||
description = "$(basename $dtname .dtb)";
|
||||
firmware = "uboot@1";
|
||||
loadables = "atf@1";
|
||||
fdt = "fdt@$cnt";
|
||||
};
|
||||
__CONF_SECTION_EOF
|
||||
cnt=$((cnt+1))
|
||||
done
|
||||
|
||||
cat << __ITS_EOF
|
||||
};
|
||||
};
|
||||
__ITS_EOF
|
|
@ -11,24 +11,30 @@
|
|||
#include <libfdt.h>
|
||||
#include <spl.h>
|
||||
|
||||
#define FDT_ERROR ((ulong)(-1))
|
||||
|
||||
static ulong fdt_getprop_u32(const void *fdt, int node, const char *prop)
|
||||
{
|
||||
const u32 *cell;
|
||||
int len;
|
||||
|
||||
cell = fdt_getprop(fdt, node, prop, &len);
|
||||
if (len != sizeof(*cell))
|
||||
return -1U;
|
||||
if (!cell || len != sizeof(*cell))
|
||||
return FDT_ERROR;
|
||||
|
||||
return fdt32_to_cpu(*cell);
|
||||
}
|
||||
|
||||
static int spl_fit_select_fdt(const void *fdt, int images, int *fdt_offsetp)
|
||||
/*
|
||||
* Iterate over all /configurations subnodes and call a platform specific
|
||||
* function to find the matching configuration.
|
||||
* Returns the node offset or a negative error number.
|
||||
*/
|
||||
static int spl_fit_find_config_node(const void *fdt)
|
||||
{
|
||||
const char *name, *fdt_name;
|
||||
int conf, node, fdt_node;
|
||||
int len;
|
||||
const char *name;
|
||||
int conf, node, len;
|
||||
|
||||
*fdt_offsetp = 0;
|
||||
conf = fdt_path_offset(fdt, FIT_CONFS_PATH);
|
||||
if (conf < 0) {
|
||||
debug("%s: Cannot find /configurations node: %d\n", __func__,
|
||||
|
@ -50,41 +56,71 @@ static int spl_fit_select_fdt(const void *fdt, int images, int *fdt_offsetp)
|
|||
continue;
|
||||
|
||||
debug("Selecting config '%s'", name);
|
||||
fdt_name = fdt_getprop(fdt, node, FIT_FDT_PROP, &len);
|
||||
if (!fdt_name) {
|
||||
debug("%s: Cannot find fdt name property: %d\n",
|
||||
__func__, len);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
debug(", fdt '%s'\n", fdt_name);
|
||||
fdt_node = fdt_subnode_offset(fdt, images, fdt_name);
|
||||
if (fdt_node < 0) {
|
||||
debug("%s: Cannot find fdt node '%s': %d\n",
|
||||
__func__, fdt_name, fdt_node);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
*fdt_offsetp = fdt_getprop_u32(fdt, fdt_node, "data-offset");
|
||||
len = fdt_getprop_u32(fdt, fdt_node, "data-size");
|
||||
debug("FIT: Selected '%s'\n", name);
|
||||
|
||||
return len;
|
||||
return node;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
|
||||
printf("No matching DT out of these options:\n");
|
||||
for (node = fdt_first_subnode(fdt, conf);
|
||||
node >= 0;
|
||||
node = fdt_next_subnode(fdt, node)) {
|
||||
name = fdt_getprop(fdt, node, "description", &len);
|
||||
printf(" %s\n", name);
|
||||
}
|
||||
#endif
|
||||
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
/**
|
||||
* spl_fit_get_image_node(): By using the matching configuration subnode,
|
||||
* retrieve the name of an image, specified by a property name and an index
|
||||
* into that.
|
||||
* @fit: Pointer to the FDT blob.
|
||||
* @images: Offset of the /images subnode.
|
||||
* @type: Name of the property within the configuration subnode.
|
||||
* @index: Index into the list of strings in this property.
|
||||
*
|
||||
* Return: the node offset of the respective image node or a negative
|
||||
* error number.
|
||||
*/
|
||||
static int spl_fit_get_image_node(const void *fit, int images,
|
||||
const char *type, int index)
|
||||
{
|
||||
const char *name, *str;
|
||||
int node, conf_node;
|
||||
int len, i;
|
||||
|
||||
conf_node = spl_fit_find_config_node(fit);
|
||||
if (conf_node < 0) {
|
||||
#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
|
||||
printf("No matching DT out of these options:\n");
|
||||
for (node = fdt_first_subnode(fit, conf_node);
|
||||
node >= 0;
|
||||
node = fdt_next_subnode(fit, node)) {
|
||||
name = fdt_getprop(fit, node, "description", &len);
|
||||
printf(" %s\n", name);
|
||||
}
|
||||
#endif
|
||||
return conf_node;
|
||||
}
|
||||
|
||||
name = fdt_getprop(fit, conf_node, type, &len);
|
||||
if (!name) {
|
||||
debug("cannot find property '%s': %d\n", type, len);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
str = name;
|
||||
for (i = 0; i < index; i++) {
|
||||
str = strchr(str, '\0') + 1;
|
||||
if (!str || (str - name >= len)) {
|
||||
debug("no string for index %d\n", index);
|
||||
return -E2BIG;
|
||||
}
|
||||
}
|
||||
|
||||
debug("%s: '%s'\n", type, str);
|
||||
node = fdt_subnode_offset(fit, images, str);
|
||||
if (node < 0) {
|
||||
debug("cannot find image node '%s': %d\n", str, node);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
static int get_aligned_image_offset(struct spl_load_info *info, int offset)
|
||||
{
|
||||
/*
|
||||
|
@ -123,19 +159,82 @@ static int get_aligned_image_size(struct spl_load_info *info, int data_size,
|
|||
return (data_size + info->bl_len - 1) / info->bl_len;
|
||||
}
|
||||
|
||||
/**
|
||||
* spl_load_fit_image(): load the image described in a certain FIT node
|
||||
* @info: points to information about the device to load data from
|
||||
* @sector: the start sector of the FIT image on the device
|
||||
* @fit: points to the flattened device tree blob describing the FIT
|
||||
* image
|
||||
* @base_offset: the beginning of the data area containing the actual
|
||||
* image data, relative to the beginning of the FIT
|
||||
* @node: offset of the DT node describing the image to load (relative
|
||||
* to @fit)
|
||||
* @image_info: will be filled with information about the loaded image
|
||||
* If the FIT node does not contain a "load" (address) property,
|
||||
* the image gets loaded to the address pointed to by the
|
||||
* load_addr member in this struct.
|
||||
*
|
||||
* Return: 0 on success or a negative error number.
|
||||
*/
|
||||
static int spl_load_fit_image(struct spl_load_info *info, ulong sector,
|
||||
void *fit, ulong base_offset, int node,
|
||||
struct spl_image_info *image_info)
|
||||
{
|
||||
ulong offset;
|
||||
size_t length;
|
||||
ulong load_addr, load_ptr;
|
||||
void *src;
|
||||
ulong overhead;
|
||||
int nr_sectors;
|
||||
int align_len = ARCH_DMA_MINALIGN - 1;
|
||||
|
||||
offset = fdt_getprop_u32(fit, node, "data-offset");
|
||||
if (offset == FDT_ERROR)
|
||||
return -ENOENT;
|
||||
offset += base_offset;
|
||||
length = fdt_getprop_u32(fit, node, "data-size");
|
||||
if (length == FDT_ERROR)
|
||||
return -ENOENT;
|
||||
load_addr = fdt_getprop_u32(fit, node, "load");
|
||||
if (load_addr == FDT_ERROR && image_info)
|
||||
load_addr = image_info->load_addr;
|
||||
load_ptr = (load_addr + align_len) & ~align_len;
|
||||
|
||||
overhead = get_aligned_image_overhead(info, offset);
|
||||
nr_sectors = get_aligned_image_size(info, length, offset);
|
||||
|
||||
if (info->read(info, sector + get_aligned_image_offset(info, offset),
|
||||
nr_sectors, (void*)load_ptr) != nr_sectors)
|
||||
return -EIO;
|
||||
debug("image: dst=%lx, offset=%lx, size=%lx\n", load_ptr, offset,
|
||||
(unsigned long)length);
|
||||
|
||||
src = (void *)load_ptr + overhead;
|
||||
#ifdef CONFIG_SPL_FIT_IMAGE_POST_PROCESS
|
||||
board_fit_image_post_process(&src, &length);
|
||||
#endif
|
||||
|
||||
memcpy((void*)load_addr, src, length);
|
||||
|
||||
if (image_info) {
|
||||
image_info->load_addr = load_addr;
|
||||
image_info->size = length;
|
||||
image_info->entry_point = fdt_getprop_u32(fit, node, "entry");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int spl_load_simple_fit(struct spl_image_info *spl_image,
|
||||
struct spl_load_info *info, ulong sector, void *fit)
|
||||
{
|
||||
int sectors;
|
||||
ulong size, load;
|
||||
ulong size;
|
||||
unsigned long count;
|
||||
int node, images;
|
||||
void *load_ptr;
|
||||
int fdt_offset, fdt_len;
|
||||
int data_offset, data_size;
|
||||
struct spl_image_info image_info;
|
||||
int node, images, ret;
|
||||
int base_offset, align_len = ARCH_DMA_MINALIGN - 1;
|
||||
int src_sector;
|
||||
void *dst, *src;
|
||||
int index = 0;
|
||||
|
||||
/*
|
||||
* Figure out where the external images start. This is the base for the
|
||||
|
@ -168,90 +267,82 @@ int spl_load_simple_fit(struct spl_image_info *spl_image,
|
|||
if (count == 0)
|
||||
return -EIO;
|
||||
|
||||
/* find the firmware image to load */
|
||||
/* find the node holding the images information */
|
||||
images = fdt_path_offset(fit, FIT_IMAGES_PATH);
|
||||
if (images < 0) {
|
||||
debug("%s: Cannot find /images node: %d\n", __func__, images);
|
||||
return -1;
|
||||
}
|
||||
node = fdt_first_subnode(fit, images);
|
||||
|
||||
/* find the U-Boot image */
|
||||
node = spl_fit_get_image_node(fit, images, "firmware", 0);
|
||||
if (node < 0) {
|
||||
debug("%s: Cannot find first image node: %d\n", __func__, node);
|
||||
debug("could not find firmware image, trying loadables...\n");
|
||||
node = spl_fit_get_image_node(fit, images, "loadables", 0);
|
||||
/*
|
||||
* If we pick the U-Boot image from "loadables", start at
|
||||
* the second image when later loading additional images.
|
||||
*/
|
||||
index = 1;
|
||||
}
|
||||
if (node < 0) {
|
||||
debug("%s: Cannot find u-boot image node: %d\n",
|
||||
__func__, node);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Get its information and set up the spl_image structure */
|
||||
data_offset = fdt_getprop_u32(fit, node, "data-offset");
|
||||
data_size = fdt_getprop_u32(fit, node, "data-size");
|
||||
load = fdt_getprop_u32(fit, node, "load");
|
||||
debug("data_offset=%x, data_size=%x\n", data_offset, data_size);
|
||||
spl_image->load_addr = load;
|
||||
spl_image->entry_point = load;
|
||||
/* Load the image and set up the spl_image structure */
|
||||
ret = spl_load_fit_image(info, sector, fit, base_offset, node,
|
||||
spl_image);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
spl_image->os = IH_OS_U_BOOT;
|
||||
|
||||
/*
|
||||
* Work out where to place the image. We read it so that the first
|
||||
* byte will be at 'load'. This may mean we need to load it starting
|
||||
* before then, since we can only read whole blocks.
|
||||
*/
|
||||
data_offset += base_offset;
|
||||
sectors = get_aligned_image_size(info, data_size, data_offset);
|
||||
load_ptr = (void *)load;
|
||||
debug("U-Boot size %x, data %p\n", data_size, load_ptr);
|
||||
dst = load_ptr;
|
||||
|
||||
/* Read the image */
|
||||
src_sector = sector + get_aligned_image_offset(info, data_offset);
|
||||
debug("Aligned image read: dst=%p, src_sector=%x, sectors=%x\n",
|
||||
dst, src_sector, sectors);
|
||||
count = info->read(info, src_sector, sectors, dst);
|
||||
if (count != sectors)
|
||||
return -EIO;
|
||||
debug("image: dst=%p, data_offset=%x, size=%x\n", dst, data_offset,
|
||||
data_size);
|
||||
src = dst + get_aligned_image_overhead(info, data_offset);
|
||||
|
||||
#ifdef CONFIG_SPL_FIT_IMAGE_POST_PROCESS
|
||||
board_fit_image_post_process((void **)&src, (size_t *)&data_size);
|
||||
#endif
|
||||
|
||||
memcpy(dst, src, data_size);
|
||||
|
||||
/* Figure out which device tree the board wants to use */
|
||||
fdt_len = spl_fit_select_fdt(fit, images, &fdt_offset);
|
||||
if (fdt_len < 0)
|
||||
return fdt_len;
|
||||
node = spl_fit_get_image_node(fit, images, FIT_FDT_PROP, 0);
|
||||
if (node < 0) {
|
||||
debug("%s: cannot find FDT node\n", __func__);
|
||||
return node;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the device tree and place it after the image. There may be
|
||||
* some extra data before it since we can only read entire blocks.
|
||||
* And also align the destination address to ARCH_DMA_MINALIGN.
|
||||
* Read the device tree and place it after the image.
|
||||
* Align the destination address to ARCH_DMA_MINALIGN.
|
||||
*/
|
||||
dst = (void *)((load + data_size + align_len) & ~align_len);
|
||||
fdt_offset += base_offset;
|
||||
sectors = get_aligned_image_size(info, fdt_len, fdt_offset);
|
||||
src_sector = sector + get_aligned_image_offset(info, fdt_offset);
|
||||
count = info->read(info, src_sector, sectors, dst);
|
||||
debug("Aligned fdt read: dst %p, src_sector = %x, sectors %x\n",
|
||||
dst, src_sector, sectors);
|
||||
if (count != sectors)
|
||||
return -EIO;
|
||||
image_info.load_addr = spl_image->load_addr + spl_image->size;
|
||||
ret = spl_load_fit_image(info, sector, fit, base_offset, node,
|
||||
&image_info);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Now check if there are more images for us to load */
|
||||
for (; ; index++) {
|
||||
node = spl_fit_get_image_node(fit, images, "loadables", index);
|
||||
if (node < 0)
|
||||
break;
|
||||
|
||||
ret = spl_load_fit_image(info, sector, fit, base_offset, node,
|
||||
&image_info);
|
||||
if (ret < 0)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* If the "firmware" image did not provide an entry point,
|
||||
* use the first valid entry point from the loadables.
|
||||
*/
|
||||
if (spl_image->entry_point == FDT_ERROR &&
|
||||
image_info.entry_point != FDT_ERROR)
|
||||
spl_image->entry_point = image_info.entry_point;
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy the device tree so that it starts immediately after the image.
|
||||
* After this we will have the U-Boot image and its device tree ready
|
||||
* for us to start.
|
||||
* If a platform does not provide CONFIG_SYS_UBOOT_START, U-Boot's
|
||||
* Makefile will set it to 0 and it will end up as the entry point
|
||||
* here. What it actually means is: use the load address.
|
||||
*/
|
||||
debug("fdt: dst=%p, data_offset=%x, size=%x\n", dst, fdt_offset,
|
||||
fdt_len);
|
||||
src = dst + get_aligned_image_overhead(info, fdt_offset);
|
||||
dst = load_ptr + data_size;
|
||||
|
||||
#ifdef CONFIG_SPL_FIT_IMAGE_POST_PROCESS
|
||||
board_fit_image_post_process((void **)&src, (size_t *)&fdt_len);
|
||||
#endif
|
||||
|
||||
memcpy(dst, src, fdt_len);
|
||||
if (spl_image->entry_point == FDT_ERROR || spl_image->entry_point == 0)
|
||||
spl_image->entry_point = spl_image->load_addr;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -48,4 +48,3 @@ CONFIG_G_DNL_MANUFACTURER="Texas Instruments"
|
|||
CONFIG_G_DNL_VENDOR_NUM=0x0451
|
||||
CONFIG_G_DNL_PRODUCT_NUM=0xd022
|
||||
CONFIG_RSA=y
|
||||
CONFIG_SPL_OF_LIBFDT=y
|
||||
|
|
|
@ -3,6 +3,7 @@ CONFIG_ARCH_SUNXI=y
|
|||
CONFIG_MACH_SUN50I=y
|
||||
CONFIG_RESERVE_ALLWINNER_BOOT0_HEADER=y
|
||||
CONFIG_DEFAULT_DEVICE_TREE="sun50i-a64-pine64-plus"
|
||||
CONFIG_OF_LIST="sun50i-a64-pine64 sun50i-a64-pine64-plus"
|
||||
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
|
||||
CONFIG_CONSOLE_MUX=y
|
||||
CONFIG_SPL=y
|
||||
|
|
|
@ -44,6 +44,27 @@ image source file mkimage + dtc transfer to target
|
|||
+ ---------------> image file --------------------> bootm
|
||||
image data file(s)
|
||||
|
||||
SPL usage
|
||||
---------
|
||||
|
||||
The SPL can make use of the new image format as well, this traditionally
|
||||
is used to ship multiple device tree files within one image. Code in the SPL
|
||||
will choose the one matching the current board and append this to the
|
||||
U-Boot proper binary to be automatically used up by it.
|
||||
Aside from U-Boot proper and one device tree blob the SPL can load multiple,
|
||||
arbitrary image files as well. These binaries should be specified in their
|
||||
own subnode under the /images node, which should then be referenced from one or
|
||||
multiple /configurations subnodes. The required images must be enumerated in
|
||||
the "loadables" property as a list of strings.
|
||||
|
||||
If a platform specific image source file (.its) is shipped with the U-Boot
|
||||
source, it can be specified using the CONFIG_SPL_FIT_SOURCE Kconfig symbol.
|
||||
In this case it will be automatically used by U-Boot's Makefile to generate
|
||||
the image.
|
||||
If a static source file is not flexible enough, CONFIG_SPL_FIT_GENERATOR
|
||||
can point to a script which generates this image source file during
|
||||
the build process. It gets passed a list of device tree files (taken from the
|
||||
CONFIG_OF_LIST symbol).
|
||||
|
||||
Example 1 -- old-style (non-FDT) kernel booting
|
||||
-----------------------------------------------
|
||||
|
|
89
doc/uImage.FIT/multi_spl.its
Normal file
89
doc/uImage.FIT/multi_spl.its
Normal file
|
@ -0,0 +1,89 @@
|
|||
/dts-v1/;
|
||||
|
||||
/*
|
||||
* (Bogus) example FIT image description file demonstrating the usage
|
||||
* of multiple images loaded by the SPL.
|
||||
* Several binaries will be loaded at their respective load addresses.
|
||||
* Finally the one image specifying an entry point will be entered by the SPL.
|
||||
*/
|
||||
|
||||
/ {
|
||||
description = "multiple firmware blobs and U-Boot, loaded by SPL";
|
||||
#address-cells = <0x1>;
|
||||
|
||||
images {
|
||||
|
||||
uboot {
|
||||
description = "U-Boot (64-bit)";
|
||||
type = "standalone";
|
||||
arch = "arm64";
|
||||
compression = "none";
|
||||
load = <0x4a000000>;
|
||||
};
|
||||
|
||||
atf {
|
||||
description = "ARM Trusted Firmware";
|
||||
type = "firmware";
|
||||
arch = "arm64";
|
||||
compression = "none";
|
||||
load = <0x18000>;
|
||||
entry = <0x18000>;
|
||||
};
|
||||
|
||||
mgmt-firmware {
|
||||
description = "arisc management processor firmware";
|
||||
type = "firmware";
|
||||
arch = "or1k";
|
||||
compression = "none";
|
||||
load = <0x40000>;
|
||||
};
|
||||
|
||||
fdt@1 {
|
||||
description = "Pine64+ DT";
|
||||
type = "flat_dt";
|
||||
compression = "none";
|
||||
load = <0x4fa00000>;
|
||||
arch = "arm64";
|
||||
};
|
||||
|
||||
fdt@2 {
|
||||
description = "Pine64 DT";
|
||||
type = "flat_dt";
|
||||
compression = "none";
|
||||
load = <0x4fa00000>;
|
||||
arch = "arm64";
|
||||
};
|
||||
|
||||
kernel {
|
||||
description = "4.7-rc5 kernel";
|
||||
type = "kernel";
|
||||
compression = "none";
|
||||
load = <0x40080000>;
|
||||
arch = "arm64";
|
||||
};
|
||||
|
||||
initrd {
|
||||
description = "Debian installer initrd";
|
||||
type = "ramdisk";
|
||||
compression = "none";
|
||||
load = <0x4fe00000>;
|
||||
arch = "arm64";
|
||||
};
|
||||
};
|
||||
|
||||
configurations {
|
||||
default = "config@1";
|
||||
|
||||
config@1 {
|
||||
description = "sun50i-a64-pine64-plus";
|
||||
loadables = "uboot", "atf", "kernel", "initrd";
|
||||
fdt = "fdt@1";
|
||||
};
|
||||
|
||||
config@2 {
|
||||
description = "sun50i-a64-pine64";
|
||||
loadables = "uboot", "atf", "mgmt-firmware";
|
||||
fdt = "fdt@2";
|
||||
};
|
||||
};
|
||||
};
|
|
@ -32,6 +32,10 @@
|
|||
# define CONFIG_MACH_TYPE_COMPAT_REV 1
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ARM64
|
||||
#define CONFIG_BUILD_TARGET "u-boot.itb"
|
||||
#endif
|
||||
|
||||
/* Serial & console */
|
||||
#define CONFIG_SYS_NS16550_SERIAL
|
||||
/* ns16550 reg in the low bits of cpu reg */
|
||||
|
@ -185,12 +189,17 @@
|
|||
#endif
|
||||
|
||||
#ifdef CONFIG_SUNXI_HIGH_SRAM
|
||||
#define CONFIG_SPL_TEXT_BASE 0x10040 /* sram start+header */
|
||||
#define CONFIG_SPL_MAX_SIZE 0x7fc0 /* 32 KiB */
|
||||
#define LOW_LEVEL_SRAM_STACK 0x00018000
|
||||
#define CONFIG_SPL_TEXT_BASE 0x10060 /* sram start+header */
|
||||
#define CONFIG_SPL_MAX_SIZE 0x7fa0 /* 32 KiB */
|
||||
#ifdef CONFIG_ARM64
|
||||
/* end of SRAM A2 for now, as SRAM A1 is pretty tight for an ARM64 build */
|
||||
#define LOW_LEVEL_SRAM_STACK 0x00054000
|
||||
#else
|
||||
#define CONFIG_SPL_TEXT_BASE 0x40 /* sram start+header */
|
||||
#define CONFIG_SPL_MAX_SIZE 0x5fc0 /* 24KB on sun4i/sun7i */
|
||||
#define LOW_LEVEL_SRAM_STACK 0x00018000
|
||||
#endif /* !CONFIG_ARM64 */
|
||||
#else
|
||||
#define CONFIG_SPL_TEXT_BASE 0x60 /* sram start+header */
|
||||
#define CONFIG_SPL_MAX_SIZE 0x5fa0 /* 24KB on sun4i/sun7i */
|
||||
#define LOW_LEVEL_SRAM_STACK 0x00008000 /* End of sram */
|
||||
#endif
|
||||
|
||||
|
|
|
@ -304,7 +304,8 @@ $(obj)/$(SPL_BIN).sfp: $(obj)/$(SPL_BIN).bin FORCE
|
|||
$(call if_changed,mkimage)
|
||||
|
||||
quiet_cmd_mksunxiboot = MKSUNXI $@
|
||||
cmd_mksunxiboot = $(objtree)/tools/mksunxiboot $< $@
|
||||
cmd_mksunxiboot = $(objtree)/tools/mksunxiboot \
|
||||
--default-dt $(CONFIG_DEFAULT_DEVICE_TREE) $< $@
|
||||
$(obj)/sunxi-spl.bin: $(obj)/$(SPL_BIN).bin FORCE
|
||||
$(call if_changed,mksunxiboot)
|
||||
|
||||
|
|
|
@ -48,8 +48,8 @@ int gen_check_sum(struct boot_file_head *head_p)
|
|||
#define ALIGN(x, a) __ALIGN_MASK((x), (typeof(x))(a)-1)
|
||||
#define __ALIGN_MASK(x, mask) (((x)+(mask))&~(mask))
|
||||
|
||||
#define SUN4I_SRAM_SIZE 0x7600 /* 0x7748+ is used by BROM */
|
||||
#define SRAM_LOAD_MAX_SIZE (SUN4I_SRAM_SIZE - sizeof(struct boot_file_head))
|
||||
#define SUNXI_SRAM_SIZE 0x8000 /* SoC with smaller size are limited before */
|
||||
#define SRAM_LOAD_MAX_SIZE (SUNXI_SRAM_SIZE - sizeof(struct boot_file_head))
|
||||
|
||||
/*
|
||||
* BROM (at least on A10 and A20) requires NAND-images to be explicitly aligned
|
||||
|
@ -70,11 +70,40 @@ int main(int argc, char *argv[])
|
|||
struct boot_img img;
|
||||
unsigned file_size;
|
||||
int count;
|
||||
char *tool_name = argv[0];
|
||||
char *default_dt = NULL;
|
||||
|
||||
if (argc < 2) {
|
||||
printf("\tThis program makes an input bin file to sun4i " \
|
||||
"bootable image.\n" \
|
||||
"\tUsage: %s input_file out_putfile\n", argv[0]);
|
||||
/* a sanity check */
|
||||
if ((sizeof(img.header) % 32) != 0) {
|
||||
fprintf(stderr, "ERROR: the SPL header must be a multiple ");
|
||||
fprintf(stderr, "of 32 bytes.\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
/* process optional command line switches */
|
||||
while (argc >= 2 && argv[1][0] == '-') {
|
||||
if (strcmp(argv[1], "--default-dt") == 0) {
|
||||
if (argc >= 3) {
|
||||
default_dt = argv[2];
|
||||
argv += 2;
|
||||
argc -= 2;
|
||||
continue;
|
||||
}
|
||||
fprintf(stderr, "ERROR: no --default-dt arg\n");
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
fprintf(stderr, "ERROR: bad option '%s'\n", argv[1]);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
if (argc < 3) {
|
||||
printf("This program converts an input binary file to a sunxi bootable image.\n");
|
||||
printf("\nUsage: %s [options] input_file output_file\n",
|
||||
tool_name);
|
||||
printf("Where [options] may be:\n");
|
||||
printf(" --default-dt arg - 'arg' is the default device tree name\n");
|
||||
printf(" (CONFIG_DEFAULT_DEVICE_TREE).\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
|
@ -122,6 +151,18 @@ int main(int argc, char *argv[])
|
|||
memcpy(img.header.spl_signature, SPL_SIGNATURE, 3); /* "sunxi" marker */
|
||||
img.header.spl_signature[3] = SPL_HEADER_VERSION;
|
||||
|
||||
if (default_dt) {
|
||||
if (strlen(default_dt) + 1 <= sizeof(img.header.string_pool)) {
|
||||
strcpy((char *)img.header.string_pool, default_dt);
|
||||
img.header.dt_name_offset =
|
||||
cpu_to_le32(offsetof(struct boot_file_head,
|
||||
string_pool));
|
||||
} else {
|
||||
printf("WARNING: The SPL header is too small\n");
|
||||
printf(" and has no space to store the dt name.\n");
|
||||
}
|
||||
}
|
||||
|
||||
gen_check_sum(&img.header);
|
||||
|
||||
count = write(fd_out, &img, le32_to_cpu(img.header.length));
|
||||
|
|
Loading…
Reference in a new issue