Bootloader(s)
There are two bootloaders:
- SPL: always reside in the first partition, loaded by the ROM on the board in SRAM. SPL load U-Boot (This partition is small), the file to write in the partition is "work/u-boot-spl.bin.normal.out"
- U-Boot: always reside in the second partition, "real" bootloader that loads the kernel etc. (This partition is bigger), OpenSBI is embedded in the same partition with U-Boot and is loaded by SPL. The file to write in the partition is "work/starfive_fw_payload.img"
Edit boot logo
cd u-boot/tools/
vim Makefile
The loaded logo is usually the BOARD name logo (so logos/starfive.bmp) or the VENDOR logo if the first one is missing.
# Use board logo and fallback to vendor
ifneq ($(wildcard $(srctree)/$(src)/logos/$(BOARD).bmp),)
LOGO_BMP= $(srctree)/$(src)/logos/$(BOARD).bmp
else
ifneq ($(wildcard $(srctree)/$(src)/logos/$(VENDOR).bmp),)
LOGO_BMP= $(srctree)/$(src)/logos/$(VENDOR).bmp
endif
endif
Just replace $(BOARD).bmp (so starfive.bmp) or add a new line to the Makefile like
LOGO_BMP = $(srctree)/$(src)/logos/your_cool_logo.bmp
Third partition (VFAT Image)
The third partition contains the fit file (Flat Image Tree). Basically it's a compressed archive containing the kernel binary, the dtb (device tree blob) files and other stuff needed to boot with this specific hardware.
There are also files like something_uEnv.txt, those are files used by U-Boot to determine what to do.
$(vfat_image): $(fit) $(confdir)/jh7110_uEnv.txt $(confdir)/vf2_uEnv.txt $(confdir)/vf2_nvme_uEnv.txt
@if [ `du --apparent-size --block-size=512 $(uboot) | cut -f 1` -ge $(UBOOT_SIZE) ]; then \
echo "Uboot is too large for partition!!\nReduce uboot or increase partition size"; \
exit 1; fi
dd if=/dev/zero of=$(vfat_image) bs=512 count=$(VFAT_SIZE)
/sbin/mkfs.vfat $(vfat_image)
PATH=$(RVPATH) MTOOLS_SKIP_CHECK=1 mcopy -i $(vfat_image) $(fit) ::starfiveu.fit
PATH=$(RVPATH) MTOOLS_SKIP_CHECK=1 mcopy -i $(vfat_image) $(confdir)/jh7110_uEnv.txt ::jh7110_uEnv.txt
PATH=$(RVPATH) MTOOLS_SKIP_CHECK=1 mcopy -i $(vfat_image) $(confdir)/vf2_uEnv.txt ::vf2_uEnv.txt
PATH=$(RVPATH) MTOOLS_SKIP_CHECK=1 mcopy -i $(vfat_image) $(confdir)/vf2_nvme_uEnv.txt ::vf2_nvme_uEnv.txt
The Makefile command, just create the partition, format it and copies everything (fit file and uEnv file) inside it.
Also the beginning and end of this partition cannot be random, must respect those constrainst (specified in the Makefile):
VFAT_START = 16384
VFAT_END = 614399
VFAT_SIZE = $(shell expr $(VFAT_END) - $(VFAT_START) + 1)
In other contexts could theoretically be a normal /boot partition containing a classic kernel, but only if we install grub here. (Not tested but they make it working somehow).
Use the menuconfig(s)
To run the different menuconfigs from the root folder:
- Linux
make linux-menuconfig - U-Boot
make uboot-menuconfig - initramfs (Buildroot)
make buildroot-initramfs-menuconfig - rootfs (Buildroot)
make buildroot-rootfs-menuconfig
Partitions
Generic informations about the partitions creation, if using the makefile those things are done automatically. Otherwise you need to follow those constrainsts to hope to have something working.
Partitions types
When we create the partitions in the img file, we always need to set those specific GUID codes:
# Relevant partition type codes with GUID
SPL = 2E54B353-1271-4842-806F-E436D6AF6985
VFAT = EBD0A0A2-B9E5-4433-87C0-68B6B72699C7
LINUX = 0FC63DAF-8483-4772-8E79-3D69D8477DE4
UBOOT = 5B193300-FC78-40CD-8002-E86C45580B47
UBOOTENV = a09354ac-cd63-11e8-9aff-70b3d592f0fa
UBOOTDTB = 070dd1a8-cd64-11e8-aa3d-70b3d592f0fa
UBOOTFIT = 04ffcafa-cd65-11e8-b974-70b3d592f0fa
Partitions beginning and size
Each partition must respect the following sizes and starts:
SPL_START = 4096
SPL_END = 8191
UBOOT_START = 8192
UBOOT_END = 16383
UBOOT_SIZE = $(shell expr $(UBOOT_END) - $(UBOOT_START) + 1)
VFAT_START = 16384
VFAT_END = 614399
VFAT_SIZE = $(shell expr $(VFAT_END) - $(VFAT_START) + 1)
ROOT_START = 614400
Creating the partitions
The partitions can be created with the tool you prefer. Here is how you can make it with sgdisk:
sudo /sbin/sgdisk --clear \
--new=1:$(SPL_START):$(SPL_END) --change-name=1:"spl" --typecode=1:$(SPL) \
--new=2:$(UBOOT_START):$(UBOOT_END) --change-name=2:"uboot" --typecode=2:$(UBOOT) \
--new=3:$(VFAT_START):$(VFAT_END) --change-name=3:"image" --typecode=3:$(VFAT) \
--new=4:$(ROOT_START):0 --change-name=4:"root" --typecode=4:$(LINUX) \
$(DISK)
-/sbin/partprobe
@sleep 1
The START(s) and END(s) are the values mentioned above. The DISK variable is the img file. $(SPL), $(UBOOT), $(VFAT) and $(LINUX) are the GUID codes mentioned above.
Writing the partitions
We write the first three partitions with DD, the ROOT partition will instead be mounted and the rootfs data copied inside.
sudo dd if=$(spl_bin_normal_out) of=$(PART1) bs=4096
sudo dd if=$(uboot_fit) of=$(PART2) bs=4096
sudo dd if=$(vfat_image) of=$(PART3) bs=4096
sync; sleep 1;
$(PART1), $(PART2) and $(PART3) are the partitions of the img you mounted. You can mount them under /dev/loop0 with losetup /dev/loop0 image.img.
All this stuff, in the Makefile is done by make format-boot-loader.
Writing the rootfs
This can be done in different ways but usually, we first format the fourth partition:
sudo /sbin/mke2fs -t ext4 $(PART4)
And then we mount it and copy the file inside, do it as you want but here is how is done in the Makefile:
-mkdir -p tmp-mnt
-mkdir -p tmp-rootfs
-sudo mount $(PART4) tmp-mnt && \
sudo mount -o loop $(buildroot_rootfs_ext) tmp-rootfs&& \
sudo cp -fr tmp-rootfs/* tmp-mnt/
sync; sleep 1;
sudo umount tmp-mnt
sudo umount tmp-rootfs
rmdir tmp-mnt
rmdir tmp-rootfs
All this stuff, in the Makefile is done by make format-rootfs-image (will run also format-boot-loader).