Cấu hình U-Boot để nhận diện HackberryPi CM5
Bước đầu tiên là tạo cấu hình U-Boot đặc thù cho board HackberryPi CM5 dựa trên cấu hình gốc của Allwinner H6.
Tại sao: U-Boot cần biết chính xác kích thước RAM, địa chỉ DDR, và cấu hình GPIO của board để khởi động đúng cách.
Kết quả mong đợi: Một file cấu hình C mới trong thư mục config của U-Boot.
Trước tiên, sao chép file cấu hình mẫu H6 để tạo cấu hình mới cho CM5.
cd u-boot-allwinner
cp configs/sun50i-h6-nanopi-r2s_defconfig configs/sun50i-h6-hackberrypi-cm5_defconfig
Sau lệnh này, file defconfig mới được tạo ra, bạn cần chỉnh sửa các tham số bên trong.
Sửa file defconfig để tắt các driver không dùng đến và bật driver cần thiết cho CM5.
vim configs/sun50i-h6-hackberrypi-cm5_defconfig
Nội dung cần chỉnh sửa trong file: Thêm dòng định nghĩa board và tắt console UART không cần thiết nếu dùng HDMI.
CONFIG_DEFAULT_DEVICE_TREE="sun50i-h6-hackberrypi-cm5"
CONFIG_CMD_FAT=y
CONFIG_CMD_MMC=y
CONFIG_CMD_USB=y
CONFIG_CMD_EXT4=y
CONFIG_MMC_SUNXI=y
CONFIG_SPL_MMC_SUPPORT=y
CONFIG_SPL_MMC_SUNXI_SUPPORT=y
CONFIG_SPL_FIT_IMAGE_SUPPORT=y
CONFIG_SPL_OF_CONTROL=y
CONFIG_SPL_LIBCOMMON_SUPPORT=y
CONFIG_SPL_LIBGENERIC_SUPPORT=y
CONFIG_SPL_STACK_R=y
CONFIG_SPL_TEXT_BASE=0x00000000
File defconfig đã cập nhật các driver cần thiết cho boot từ SD card hoặc eMMC.
Chỉnh sửa file header C cho board
Tạo file cấu hình C riêng cho board để định nghĩa các tham số phần cứng cụ thể.
Tại sao: U-Boot cần file C để xác định vùng nhớ và tên board trong source code.
Kết quả mong đợi: File C mới trong thư mục board.
Tạo thư mục và file cấu hình cho board HackberryPi CM5.
mkdir -p board/allwinner/hackberrypi-cm5
touch board/allwinner/hackberrypi-cm5/hackberrypi-cm5.c
Nội dung hoàn chỉnh của file hackberrypi-cm5.c:
#include <common.h>
#include <malloc.h>
#include <asm/arch/cpu.h>
#include <asm/arch/sys_proto.h>
int checkboard(void)
{
printf("Board: HackberryPi CM5 (Allwinner H6)\n");
return 0;
}
int dram_init(void)
{
/* HackberryPi CM5 có 1GB DDR3L */
gd->ram_size = 1024 * 1024 * 1024;
return 0;
}
File này đã khai báo tên board và kích thước RAM 1GB cho U-Boot.
Chỉnh sửa Makefile của thư mục board
Cập nhật Makefile của thư mục board/allwinner để biên dịch file mới.
Tại sao: Makefile là file điều khiển quy trình biên dịch, nếu không thêm tên board vào, nó sẽ bỏ qua file C vừa tạo.
Kết quả mong đợi: Makefile đã cập nhật, sẵn sàng biên dịch board mới.
Sửa file Makefile để thêm tên board vào danh sách biên dịch.
vim board/allwinner/Makefile
Nội dung cần thêm vào cuối file Makefile (dòng BOARD_LIST):
BOARD_LIST += hackberrypi-cm5
Makefile đã nhận diện board HackberryPi CM5 trong danh sách các board hỗ trợ.
Viết script boot để nạp kernel và rootfs vào RAM
Tạo file boot.scr cho U-Boot
Viết kịch bản boot (boot script) để chỉ dẫn U-Boot tải kernel và device tree từ thẻ nhớ vào RAM và khởi động.
Tại sao: U-Boot không tự động biết cách tải kernel, cần một script để chỉ định địa chỉ, tên file và tham số khởi động.
Kết quả mong đợi: File boot.scr nhị phân đã được tạo sẵn.
Tạo file văn bản chứa các lệnh boot script.
cd u-boot-allwinner
mkdir -p scripts/boot
cat > scripts/boot/boot-script.txt
File boot-script.txt đã chứa các lệnh định nghĩa địa chỉ và tải file hệ thống.
Chuyển đổi file văn bản sang định dạng nhị phân boot.scr dùng được cho U-Boot.
mkimage -A arm -T script -C none -a 0 -n "HackberryPi Boot" -d scripts/boot/boot-script.txt scripts/boot/boot.scr
File boot.scr đã được tạo, sẵn sàng để flash vào thẻ nhớ.
Cấu hình môi trường U-Boot (Environment)
Định nghĩa các biến môi trường mặc định trong U-Boot để hỗ trợ boot script.
Tại sao: Giúp boot script ngắn gọn hơn bằng cách sử dụng các biến đã được định nghĩa sẵn.
Kết quả mong đợi: Các biến môi trường được lưu vào phần environment của U-Boot.
Chỉnh sửa file C để thêm các biến mặc định vào môi trường U-Boot.
vim board/allwinner/hackberrypi-cm5/hackberrypi-cm5.c
Nội dung cần thêm vào file hackberrypi-cm5.c (sau hàm dram_init):
#include <environment.h>
char * const default_env[] = {
"loadaddr=0x46000000\0",
"fdt_addr=0x48000000\0",
"kernel_addr=0x42000000\0",
"bootargs=console=ttyS0,115200 root=PARTUUID=12345678-02 rw rootwait\0",
"bootcmd=mmc dev 0; fatload mmc 0 \${kernel_addr} uImage; fatload mmc 0 \${fdt_addr} sun50i-h6-hackberrypi-cm5.dtb; bootm \${kernel_addr} \${fdt_addr}\0",
NULL
};
int env_init(void)
{
return 0;
}
U-Boot giờ đã có các biến môi trường mặc định để chạy boot script.
Cấu hình tham số bootargs cho device tree
Chỉnh sửa Device Tree Source (DTS)
Cập nhật file DTS của kernel để khớp với phần cứng HackberryPi CM5.
Tại sao: Device tree mô tả phần cứng cho Kernel, nếu không khớp với bootargs, kernel sẽ không nhận diện được thiết bị ngoại vi.
Kết quả mong đợi: File .dtb đã biên dịch khớp với cấu hình boot.
Tạo file DTS dựa trên file gốc của H6.
cd linux-sunxi/arch/arm/boot/dts
cp sun50i-h6-nanopi-r2s.dts sun50i-h6-hackberrypi-cm5.dts
Nội dung cần chỉnh sửa trong file sun50i-h6-hackberrypi-cm5.dts (thêm node cho board):
/dts-v1/;
#include "sun50i-h6.dtsi"
/ {
model = "HackberryPi CM5";
compatible = "hackberrypi,cm5", "allwinner,sun50i-h6";
chosen {
bootargs = "console=ttyS0,115200";
};
memory {
device_type = "memory";
reg = ; /* 1GB RAM */
};
};
File DTS đã cập nhật tên model và kích thước bộ nhớ cho HackberryPi CM5.
Chỉnh sửa bootargs trong U-Boot để truyền tham số
Đảm bảo bootargs trong U-Boot truyền đúng tham số cho Kernel.
Tại sao: Kernel cần biết đường dẫn root filesystem và cấu hình console để khởi động.
Kết quả mong đợi: Kernel nhận đúng tham số khi boot.
Sửa lại bootargs trong file boot-script.txt để khớp với partition của rootfs.
sed -i 's/12345678-02/your-root-partition-uuid/g' scripts/boot/boot-script.txt
Tham số bootargs đã được cập nhật để trỏ đúng partition root.
Biên dịch và xuất file image U-Boot (.bin)
Biên dịch U-Boot cho board mới
Chạy lệnh biên dịch U-Boot sử dụng file defconfig đã tạo.
Tại sao: Quy trình biên dịch sẽ tạo ra file nhị phân U-Boot cuối cùng (.bin) chứa code boot và script đã cấu hình.
Kết quả mong đợi: File sun50i-h6-hackberrypi-cm5.bin hoặc u-boot-sunxi-with-spl.bin được tạo ra.
Chạy lệnh make để biên dịch U-Boot.
cd u-boot-allwinner
make sun50i-h6-hackberrypi-cm5_defconfig
make -j$(nproc)
Quá trình biên dịch hoàn tất, tạo ra file nhị phân trong thư mục build.
Gói hóa U-Boot với SPL và FIP
Sử dụng script sunxi-fel hoặc sunxi-tools để đóng gói SPL và U-Boot thành file .bin duy nhất.
Tại sao: Allwinner H6 yêu cầu file boot kép (SPL + U-Boot) được đóng gói theo định dạng cụ thể để load từ ROM boot.
Kết quả mong đợi: File u-boot-sunxi-with-spl.bin sẵn sàng để flash vào thẻ nhớ.
Chạy script đóng gói U-Boot.
cd u-boot-allwinner
./tools/mkimage -A arm -T script -C none -a 0 -n "HackberryPi Boot" -d scripts/boot/boot.scr boot.scr
./tools/mkimage -A arm -T standalone -C none -a 0x00000000 -e 0x00000000 -n "SPL" -d u-boot-sunxi-with-spl.bin u-boot-sunxi-with-spl.bin
File u-boot-sunxi-with-spl.bin đã được tạo, chứa SPL và U-Boot.
Verify kết quả biên dịch
Kiểm tra file U-Boot đã tạo để đảm bảo không có lỗi.
Tại sao: Xác nhận file nhị phân có kích thước hợp lệ và chứa các thành phần cần thiết.
Kết quả mong đợi: Thông tin file hiển thị kích thước và định dạng đúng.
Chạy lệnh kiểm tra file nhị phân.
ls -lh u-boot-sunxi-with-spl.bin
file u-boot-sunxi-with-spl.bin
File có kích thước khoảng vài MB và được nhận diện là ARM executable.
Chạy lệnh kiểm tra nội dung boot script.
mkimage -l boot.scr
Hiển thị thông tin metadata của boot script, xác nhận script đã được đóng gói đúng.
Điều hướng series:
Mục lục: Series: Xây dựng hệ điều hành Linux từ source cho HackberryPi CM5
« Phần 4: Xây dựng môi trường người dùng (Rootfs) từ nguồn
Phần 6: Gói hóa hệ thống và tạo file bootable image »