荔枝派4A,从SPL到kernel,SD卡启动踩坑

更新 添加kernel不识别sd卡的修正过程

最近RISC-V开发板降价,芯片是阿里的TH15204*C910 +16GB RAM+128GB ROM的板子卖480元,附带两个协处理器C906E902实时核,附带NPU,可玩性超高。开发板标配的固件和各种第三方系统默认从eMMC启动,且没有给SDBoot的信息。我想从SD卡启动U-Boot并引导Linux,可是没有找到th1520BootROM文档。

经过摸索,th1520的启动管脚配置为SD卡,芯片上电后BootROM会尝试从0扇区读取SPL,并用串口输出内容

如此一来,只需把SPL写入0扇区,BootROM->SPL->U-Boot的启动链便完成了

SPLU-BootopenSBI打包写入SD卡扇区:dd if=u-boot-with-spl.bin of=/dev/mmcblk1 conv=fsy nc

GPT分区类型的SD卡,前34个分区有特殊用途,0扇区是保护性MBRPMBR),1~33扇区是分区表,把SPL写入0扇区会覆盖GPT 分区 表

第一步 修改uboot代码, 开启 日志

1.修改GPT解析驱动(disk/part_ ef i.c)

打开源码目录下的disk/part_efi.c。在文件的第1行(必须在所有的#include之前),加 上这 句代码:

#defi ne DEBUG

2.修改块设备/分区核心接口(dis k/ part.c)

同样地,打开disk/part.c, 在第 1行加上:

#d ef ine DEBUG

3. 修改MMC核心驱动(driver s/ mmc/mmc.c)

第二步:通过menuco nfi g提高全局日志级别

make -j 15 CROSS_COMPILE=riscv64-linux-gnu- O=/dev/shm light_lpi4 a_1 6g_defconfig

make -j 15 CROSS_COMPILE=riscv64-linux-gnu- O=/de v/s hm menuconfig

make -j 15 CROSS_COMPILE=riscv64-linu x-g nu- O=/dev/shm

rm -r build && mkdir -p build && cp /dev /sh m/u-boot* build

include/common.h中 打 开调试开关#define DEBU G

调整menuc onf ig

Plaintext

Device Drivers —>

Logging —>

[*] Enable logging f or U-Boot (CONFIG_LOG=y)

(7) Maximum log level to recor d ( CONFIG_LOGLEVEL=78)

Level 7LOGL_DEBUGLe vel 8LOGL_DEBUG_CON T ENT

编 译完成后写入eMMC开机测试

获得日志

Lig ht LPI4A 16G# part list mmc 1

blk_get_devnum_by_typename: if_type=6, devnum =1: sdhci@ffe7080000.blk, 6, 0

blk_get_devnum_by_typename: if_type=6, de vnu m=1: sd@ffe7090000.blk, 6, 1

blk_get_devnum_by_typena me: Device desc 00000000ffa27 9a0

miss: start 0, count 1

blk_find_device: if_type=6, de vnu m=1: sdhci@ffe7080000.blk, 6, 0

blk_find_device: if_type=6 , d evnum=1: sd@ffe7090000.blk, 6 , 1

fill: s tart 0, count 1

part_init: try ‘EFI’: ret=- 1 ← EFI (GPT)驱动尝试解析,直 接返回 -1 (失败)

hit: start 0, count 1

## Unknown partition table type 0

在这整个过程中,U-Boot的底层驱动自始至终只读取了LBA 0(第0扇区),它根本就没有去读LBA 1( 主G PT所在位置),更别提去读SD卡尾部的Backup GPT了!

为什么会这样?这就涉及到了U-Boot EFI驱动的“前置防御机制”。

U-Boot的源码 disk/ part_efi.c中,test_part_efi()函数是这样写的:

/* Read legacy MBR from block 0 and check it */

if ((blk_drea d(dev_ desc, 0, 1, (ulong *)legacymbr) != 1) ||

(is_ pmbr _v alid (leg acy mbr) != 1)) {

return -1;

}

真相大白:

标准的GPT规范要求在0扇区必须有一个“保护性MBRPro tectiv e MBR)”,它的特征是结尾有55 AA,且包含一个类型为0xEE的假分 区。

0扇区早就被uboot-with-spl.binRISC-V机器码填满了!

因此,当EFI驱动读取LBA 0后,is_pmbr_valid(legacymbr)返回了FalseE FI 驱动一看0扇区连保护性MBR都没有,直接当场宣判“这不是GPT磁盘”,返回了-1

它根本懒得去管 你LBA 1有没有数据,也根本 不会 触发后续去SD卡尾部寻找Backup GPT的容错回退逻辑!

修改U-Boot源码

打开disk/part_efi.c

第一步: 找到检测函数

在文件中搜索i n t test_part_efi或者is_pmbr_valid

第二步:注 释掉PMBR校验逻辑

将那段严格的检测逻辑修改掉,让它即使发现0扇区被破坏,也强制继 续往下走 。

static int part_test_efi(struct blk_desc *dev_desc)

{

ALLOC_CAC HE_A LIGN_BUFFER_PAD(legacy_mbr, legacymbr, 1, dev_desc->blk sz );

/* Read legacy MBR from block 0 and validate it * /

if ((blk_dread(dev_desc, 0, 1, (ulong * )legacy mbr) != 1)

|| (i s_pmbr_vali d(le g acym br) != 1)) {

return -1;

}

re tu r n 0;

}

static int part_test_efi(struct blk_desc *dev_desc)

{

ALL OC_CACHE_ALIGN_BUFFER_PAD(legacy_mbr, legacymbr, 1, dev_desc- >b lksz);

/* Read legacy MBR from block 0 and don’t valida te it */

if (( blk_drea d(dev_de sc, 0, 1 , (u lo ng * )legac ymb r) ! = 1)) {

return -1;

}

return 0;

}

重新编译后烧录

日 志

Light LPI4A 16G# part list mmc 1

## Testing fo r valid EFI partition ##

Partition Map for MMC device 1 – Partition Type: EFI

GUID Partition Table Header signature is wrong: 0x 2529730529073 != 0x5452415020494645

fi nd_valid_g pt: *** ERROR: Invalid GPT * **

find _valid_gpt : *** Using Backup GP T ***

Part S tart LBA End LBA Name

Attribu tes

Type GUID

Partit ion GUID

1 0x00001000 0x00032fff “”

attrs: 0x00 00000000000 000

type: 0fc63daf-8483-4772-8 e79-3d69d84 77de4

type: linux

guid: 63f6d427-7e5 e-417f-98c6 -ad6e83bb84fd

2 0x00033000 0x03a527ff “”

attrs: 0x00000000 00000000

type: 0fc63daf-8483-4 772-8e79-3 d69d8477d e4

type: linux

guid: e6a7b680-8df5-4c52-9931-65063190a2fc

uboot可以正常识别sd卡了

上面内容只是实现th1520芯片从sd卡启动ubootkernel,进入userland时可能出现挂载分区失败的问题

所以,还需要修改以下内容

Uboot代码,修改后重新编译,用dd写入sd0扇区

include/configs/light-c910.h中的uboot环境变量信息,编译时会把变量写入binuboot启动时根据变量启动kernel,这些变量包括加载协处理器固件、设置kernel内存地址、启动分区uuidkernel参数等信 息

/boot分区内核启动参数,分区UUID,需要和sd卡分区uuid 匹配

/etc/fstab挂载分区需要和sd卡分区uuid 匹配

重启,kenel不认识gpt分区表损坏的SD卡,panic

[ 4.696074] Waiting for root device /dev/mmcblk 1p2…

[ 4.698327] mmc1: new ultra high speed SDR104 SDHC card at addre ss 0001

[ 4.708489] mmcblk1: mmc1:0001 SD 29.2 GiB

[ 4.730525] /dev/root: Can’t open blockdev

[ 4.734672] VFS: Cannot open root device “/dev/mmcblk1p2” or unknown-block(179,770) : error -6

[ 4.743208] Please append a correct “root=” boot option; here are the available partitions:

[ 4.751572] b300 12213 8624 mmcblk0

[ 4.751579] d river: mmcblk

[ 4.758391] b301 2031 mmcblk0p1 13bff422-9836-4617-929 c-bef34845ad26

[ 4.758397]

[ 4.767371] b302 512000 mmcblk0p2 363dfde9-7b99-4085-b cfd-f9573f728f60

[ 4.767376]

[ 4.776346] b303 4194304 mmcblk0p3 5ebcaaf0-e098-43b9 -beef-1f8deedd135 e

[ 4.776351]

[ 4.785323] b304 117430255 mmcblk0p4 80a5a8e9-c744-49 1a-93c1-4f4194fd6 90a

[ 4.785328]

[ 4.794308] 0b3:00100 4096 mmcblk0boot0

[ 4.794313] (driver?)

[ 4.801116] 0b3:00200 4096 mmcblk0boot1

[ 4.801120] (driver?)

[ 4.807930] 0b 3:00300 30578688 mmcblk1

[ 4.807935] driver: mmcblk

[ 4.814743] L ist of all bdev filesys tems:

[ 4.818758] ext3

[ 4.818762 ] ext2

[ 4 .820685] ext4

[ 4.822613]

[ 4.826039] th1520-event soc: th1520-event: set rebootmode:0x22

[ 4.831878] Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(179,770)

[ 4.840489] CPU: 1 PID: 1 Comm: swapper/0 Not tainted 6.6.119 -th1520 #2025.12.24.18.43+2a44b04d6

[ 4.849274] Hardwar e name: Sipeed Lichee Pi 4A 1 6G (DT)

[ 4.854497] Call Trace:

[ 4.856944] [] dump_backtrace+0x28/0x30

[ 4.862354] [< ffffffff80a36a3c>] show_stack+0x38/0x44

[ 4.867408] [] dump_stack_lvl+0x44/0x5c

[ 4.872810] [] dump_stack+0x18/0x20

[ 4.8778 62] [] panic+0x13a/0x322

[ 4.882654] [] mount_root_generic+0x210/0x2be

[ 4.888576] [] mount_root+0x16e/0x186

[ 4.893802] [] prepare_namespace+0x20c/0x262

[ 4.899635] [] kernel_init_freeable+0x2fa/0x326

[ 4.9057 31] [] kernel_init+0x2a/0x158

[ 4.910 957] [] ret_from_fork+0xe/0x 1c

[ 4.916185] SMP: stopping secondary CPUs

[ 4.920112] [panic_cpufreq_notifier_ call]Match the clock sw status to the hw after rst

[ 4.928188] —[ end Kernel panic - not syncing: VFS: Una ble to mount root fs on unknown-block(179,770) ]—

继续修改,内核参数添加init=/bin/bash gpt

setenv bootargs “root=/dev/mmcblk1p2 rw console=ttyS0,115200 rootwait rw earlycon clk_ignore_unused loglevel=7 eth= rootrwo ptions=rw,noatime rootrwreset=yes init=/bin/bash gpt”

再次启动,截取日志片 段,kernel使用备份的GPT识别到两个分区并成功启动,可以看到sd卡中的archlinux

[ 5.4853 15] Freeing unused kernel image (initmem) m emory: 2752K

[ 5.491 327] Run /init as init process

Loading, please wait…

[ 5.528013] m mc1: new ultra high speed SDR104 SDHC card at ad dress 0001

[ 5.535636] mmcblk1: mmc1:0001 SD 29.2 GiB

[ 5.548432] Primary GPT is in valid , using alternate GPT.

[ 5.553961] mmcblk1: p1 p2

1 个赞