👁 534

# Radxa Cubie A7Z UFS 启动修复:一个 devnum 引发的血案

手头这块 Radxa Cubie A7Z,全志 A733 八核,8GB 内存 + 256GB 海力士 UFS。刷了 HWRT(HardWareRoute),TF 卡启动一直正常,但拔掉 TF 卡就死活从 UFS 起不来。

折腾了一圈,根因竟然是 boot_package.fex 里一个数字写错了。

## 现象

TF 卡插着 → 正常启动,UFS 分区全部可见,读写正常。
拔掉 TF 卡 → U-Boot 卡在 `sunxi_flash_ufs_boot`,找不到启动设备,进不了内核。

UFS 本身没问题,分区表完好,根文件系统也在。就是 U-Boot 不认。

## UFS 的 LUN 布局

全志 A733 的 UFS 控制器暴露了 4 个 LUN(Logical Unit),Linux 下分别映射为:

| LUN | 设备 | 大小 | 内容 |
|—–|——|——|——|
| 0 | /dev/sda | 32MB | 空 |
| 1 | /dev/sdb | 32MB | 空 |
| 2 | /dev/sdc | 32MB | 空 |
| 3 | /dev/sdd | 238GB | GPT + 4个分区 |

关键点:真正的数据盘是 LUN3(sdd),前三个 LUN 都是空的。U-Boot 的隐藏分区也在 UFS 里,但不走 SCSI LUN 暴露。

## 根因定位

HWRT 的 `platform_install.sh` 里写 U-Boot 的逻辑:

“`bash
dd if=boot0_sdcard.bin of=$DEVICE bs=512 seek=256
dd if=boot0_ufs.bin of=$DEVICE bs=512 seek=2064
dd if=boot_package.fex of=$DEVICE bs=512 seek=24576
“`

boot_package.fex 被写到了 sdd 的 LBA 24576(12MB 偏移),这部分没问题。

问题出在 boot_package.fex 内部的环境变量:

“`
bootcmd_sunxi_flash_ufs0=setenv devnum 0; run sunxi_flash_ufs_boot
“`

`devnum 0` 意味着 U-Boot 去 LUN0(sda,32MB 空盘)找启动分区。当然找不到。

正确应该是 `devnum 3`,指向 LUN3(sdd,238GB 数据盘)。

## 修复过程

### 1. 备份原始 boot_package

“`bash
dd if=/dev/sdd of=/tmp/boot_package_backup.bin bs=512 skip=24576 count=2816
“`

### 2. 二进制 patch

boot_package.fex 是二进制文件,不能直接文本编辑。用 Python 精确定位并替换:

“`python

原始: “setenv devnum 0”

目标: “setenv devnum 3”

只改一个字节: 0x30 → 0x33

data = open(‘/tmp/boot_package_backup.bin’, ‘rb’).read()
idx = data.find(b’setenv devnum 0′)
data = data[:idx+14] + b’3′ + data[idx+15:]
open(‘/tmp/boot_package_patched.bin’, ‘wb’).write(data)
“`

### 3. 写回 sdd

“`bash
dd if=/tmp/boot_package_patched.bin of=/dev/sdd bs=512 seek=24576 conv=notrunc,fsync
“`

### 4. 验证

“`bash

读回来比对

dd if=/dev/sdd of=/tmp/verify.bin bs=512 skip=24576 count=2816
md5sum /tmp/boot_package_patched.bin /tmp/verify.bin

两者一致 ✅

# 确认内容
strings /tmp/verify.bin | grep devnum

输出: setenv devnum 3 ✅

“`

## GPT 4K 扇区对齐

顺带确认了一下 sdd 的 GPT 分区表,全志 UFS 使用 4096 字节物理扇区:

“`
Device Start End Sectors Size Type
/dev/sdd1 4096 69631 65536 256M Linux extended boot
/dev/sdd2 69632 43945312 43875681 167.4G Linux root (ARM-64)
/dev/sdd3 43945472 50236927 6291456 24G Linux filesystem
/dev/sdd4 50236928 62435071 12198144 46.5G Linux filesystem
“`

GPT 头的 AlternateLBA = 62435327,与磁盘总扇区数 62435328 匹配,说明 GPT 确实按 4K 扇区单位编写,没有对齐问题。

## 安全回滚

修改前已备份原始 boot_package.bin。如果 UFS 启动失败,插回 TF 卡即可恢复,TF 卡启动链完全不受影响。最坏情况用 TF 卡启动后把备份写回去:

“`bash
dd if=/tmp/boot_package_backup.bin of=/dev/sdd bs=512 seek=24576 conv=notrunc,fsync
“`

## 总结

全志 A733 UFS 的 LUN 布局不是常见的单 LUN,而是 4 LUN(3×32MB + 1×238GB)。HWRT 的 boot_package.fex 默认 `devnum=0` 指向了空 LUN,改成 `devnum=3` 就能正确从数据 LUN 启动。

一个字节的差异,让 UFS 启动完全瘫痪。嵌入式设备调试,有时候就是这么离谱。

—