USB移动存储启动和运行树莓派3

注解

本文实践是在 树莓派Raspberry Pi 3 结合USB转接卡,使用 2.5寸 笔记本硬盘构建的。后续我准备再使用 树莓派Raspberry Pi 4 结合USB SSD移动硬盘来构建 Raspberry Pi Cluster

注意,最初我的实践是在树莓派官方32位raspbian系统上实践的,最近为了构建 Raspberry Pi Cluster 运行 Kubernetes Atlas ,我改为使用64位Ubuntu系统。Ubuntu for Raspberry Pi和官方Raspbian在bootloader上有点差异,详见文章最后部分。

设置USB启动模式

在设置树莓派3能够从磁盘启动之前,它首先需要从SD卡启动并配置激活USB启动模式。这个过程是通过在树莓派SoC的OTP(One Time Programmable)内存设置一个激活从USB存储设备启动的。

注解

一旦这个位设置,就不再需要SD卡。但是要注意:任何修改OTP都是永久的,不能撤销。

激活USB存储启动

  • 通过更新准备 /boot 目录:

    sudo apt update && sudo apt upgrade
    
  • 使用以下命令激活USB启动模式:

    echo program_usb_boot_mode=1 | sudo tee -a /boot/config.txt
    

以上命令在 /boot/config.txt 中添加了 program_usb_boot_mode=1

使用 sudo reboot 命令重启树莓派,然后检查OTP是否已经设置成可编程:

vcgencmd otp_dump | grep 17:

确保输出是 17:3020000a 。如果不是这个输出值,责表示OTP还没有成功设置为可编程。

  • 然后就可以从 config.txt 最后删除掉 program_usb_boot_mode ,这样你把这个SD卡插到其他树莓派上不会导致其进入USB启动模式。

注解

确保 config.txt 配置文件最后没有空白行。

USB存储设备

2017-04-10 版本开始,可以通过复制方式将操作系统镜像直接安装到USB存储器。这种方式也可以针对一个SD卡。

由于我们已经在[树莓派快速起步](raspberry_pi_quick_start)过程中在SD卡上安装了Raspbian,现在我们可以从已经安装了系统的SD卡中直接复制到磁盘中,就可以保留原先所有做过的更改。

这个过程和从Raspbian镜像复制到SD卡相似,只是需要注意磁盘的命令,一定要确保是从SD卡复制到磁盘。

  • /dev/mmcblk0 SD卡

  • /dev/sda USB接口的磁盘

注解

目前我部署 Raspberry Pi Cluster 采用64位操作系统,设备是 树莓派Raspberry Pi 4树莓派Raspberry Pi 3 。实际上Ubuntu提供的64位ARM操作系统是一个版本,可以同时用于树莓派3和4。

我首次安装64位操作系统是在树莓派4上,完成后,我将采用本方案clone到树莓派3上组建集群。

  • Raspberry Pi 4安装的64位Ubuntu分区如下:

    Disk /dev/mmcblk0: 119.9 GiB, 127865454592 bytes, 249737216 sectors
    Units: sectors of 1 * 512 = 512 bytes
    Sector size (logical/physical): 512 bytes / 512 bytes
    I/O size (minimum/optimal): 512 bytes / 512 bytes
    Disklabel type: dos
    Disk identifier: 0xab86aefd
    
    Device         Boot  Start       End   Sectors   Size Id Type
    /dev/mmcblk0p1 *      2048    526335    524288   256M  c W95 FAT32 (LBA)
    /dev/mmcblk0p2      526336 249737182 249210847 118.9G 83 Linux
    
  • 划分USB磁盘分区

对照TF卡上的当前树莓派操作系统分区,可以看到有2个分区,一个是FAT32分区,另一个是Linux分区,我们也需要对应在USB磁盘上完成这个划分。

使用 parted 划分分区

 1# parted -a optimal /dev/sda
 2GNU Parted 3.3
 3Using /dev/sda
 4Welcome to GNU Parted! Type 'help' to view a list of commands.
 5(parted) mklabel msdos
 6Warning: The existing disk label on /dev/sda will be destroyed and all data on
 7this disk will be lost. Do you want to continue?
 8Yes/No? y
 9(parted) print
10Model: WD My Passport 25F3 (scsi)
11Disk /dev/sda: 1024GB
12Sector size (logical/physical): 512B/4096B
13Partition Table: msdos
14Disk Flags:
15
16Number  Start  End  Size  Type  File system  Flags
17
18(parted) mkpart primary fat32 2048s 256M
19(parted) align-check optimal 1
201 aligned
21(parted) unit s
22(parted) print
23Model: WD My Passport 25F3 (scsi)
24Disk /dev/sda: 2000343040s
25Sector size (logical/physical): 512B/4096B
26Partition Table: msdos
27Disk Flags:
28
29Number  Start  End      Size     Type     File system  Flags
30 1      2048s  499711s  497664s  primary  fat32        lba
31
32(parted) mkpart primary ext4 499712 30G
33(parted) print
34Model: WD My Passport 25F3 (scsi)
35Disk /dev/sda: 2000343040s
36Sector size (logical/physical): 512B/4096B
37Partition Table: msdos
38Disk Flags:
39
40Number  Start    End        Size       Type     File system  Flags
41 1      2048s    499711s    497664s    primary  fat32        lba
42 2      499712s  58593279s  58093568s  primary  ext4         lba
43
44(parted) align-check optimal 2
452 aligned
46(parted) unit MB
47(parted) set 1 boot on
48(parted) print
49Model: WD My Passport 25F3 (scsi)
50Disk /dev/sda: 1024176MB
51Sector size (logical/physical): 512B/4096B
52Partition Table: msdos
53Disk Flags:
54
55Number  Start   End      Size     Type     File system  Flags
56 1      1.05MB  256MB    255MB    primary  fat32        boot, lba
57 2      256MB   30000MB  29744MB  primary  ext4         lba
58
59(parted) q
60Information: You may need to update /etc/fstab.

注解

4k对齐参考 How to align partitions for best performance using parted ,其中参数查看 /dev/sda ,所以第一个分区起始扇区选择 2048s

# cat /sys/block/sda/queue/optimal_io_size
0
# cat /sys/block/sda/queue/minimum_io_size
512
# cat /sys/block/sda/alignment_offset
0
# cat /sys/block/sda/queue/physical_block_size
512

注意:这里划分 /dev/sda2 只分配30G给操作系统使用,因为我准备把剩余的空间作为存储空间,将在后续使用卷管理来维护,并构建Ceph和GlusterFS存储。

  • 退出 parted 检查存储的 PARTUUID

    # blkid /dev/sda
    /dev/sda: PTUUID="5e878358" PTTYPE="dos"
    # blkid /dev/sda1
    /dev/sda1: SEC_TYPE="msdos" UUID="1E2C-FFAE" TYPE="vfat" PARTUUID="5e878358-01"
    # blkid /dev/sda2
    /dev/sda2: PARTUUID="5e878358-02"
    

注意,此时看不到 UUIDUUIDmkfs.ext4 /dev/sda2 之后就会标记上。

和普通的PC不同,树莓派会默认尝试搜索可以启动的分区(默认会从SD卡启动,15秒之后将尝试从USB存储启动,即前面修改的配置)。

注解

一定要有一个fat分区用于存放 /boot 分区内容,因为UEFI启动默认会寻找vfat分区内容来启动。

注解

  • 如果使用 dd 命令复制磁盘分区,所以要确保 /dev/sda2 磁盘分区大于源SD卡分区 /dev/mmcblk0p2

  • 如果使用 tar 方式复制磁盘文件系统,则目标分区只要能够容纳源 /dev/mmcblk0p2 文件就可以 - 我采用的是这个方法

通过 dd 复制磁盘(我没有采用这个方法)

如果使用 dd 复制磁盘,责执行操作系统复制命令如下(不需要区分磁盘分区):

dd if=/dev/mmcblk0 of=/dev/sda conv=fsync

注解

dd 复制命令参考了在Linux中制作镜像到SD卡的命令 INSTALLING OPERATING SYSTEM IMAGES ON LINUX

通过 tar 复制磁盘

  • 使用 tar 方式复制磁盘文件:

    cd /
    tar -cpzf pi.tar.gz --exclude=/pi.tar.gz --one-file-system /
    
    mkfs.ext4 /dev/sda2
    mount /dev/sda2 /mnt
    
    sudo tar -xpzf /pi.tar.gz -C /mnt --numeric-owner
    

注解

上述备份的 /pi.tar.gz 没有包含 /boot 分区内容,所以后面我们还有一步单独复制 /boot 分区的操作。

注解

在执行了 mkfs.ext4 /dev/sda2 之后,再使用 blkid /dev/sda2 就能够看到 UUID ,这个 UUID 是文件系统UUID:

blkid /dev/sda2

显示输出:

/dev/sda2: UUID="b2e461e7-5a68-434d-bda1-c7c137e8c38e" TYPE="ext4" PARTUUID="1a99ca08-02"
  • 格式化 /dev/sda1 作为vfat32 分区:

    # mkfs.vfat /dev/sda1  <= 这里没有指定FAT32文件系统,默认格式化是FAT16
    # 检查发现`fdisk`虽然可以通过`c`这个type来标记分区为FAT32,但是如果`mkfs.fat`不指定`-F32`参数
    # 会导致文件系统还是`fat16`文件系统,虽然用`fdisk -l`看不出,但是`parted`则能够看到是`fat16`
    mkfs.fat -F32 /dev/sda1
    
  • 早期的32位系统可以通过以下命令复制 /boot 分区:

    mount /dev/sda1 /mnt/boot
    (cd /boot && tar cf - .)|(cd /mnt/boot && tar xf -)
    
  • 但是现在64位操作系统 /dev/sda1 已经不是直接挂载为 /boot 目录,检查对比TF卡中操作系统可以看到:

    # df -h
    Filesystem      Size  Used Avail Use% Mounted on
    ...
    /dev/mmcblk0p2  117G  3.5G  109G   4% /
    ...
    /dev/mmcblk0p1  253M   97M  156M  39% /boot/firmware
    

所以对应挂载目录不同,我们采用以下命令:

mount /dev/sda1 /mnt/boot/firmware
(cd /boot/firmware && tar cf - .)|(cd /mnt/boot/firmware && tar xf -)

注解

要避免包含目录,使用 --exclude 参数。参考 Exclude Multiple Directories When Creating A tar Archive 。但是我使用如下命令依然包含了不需要的目录( 失败 ),最后还是采用 通过tar备份和恢复Linux系统 来完成:

(cd / && tar cf - --exclude "/mnt" --exclude "/sys" --exclude "/proc" --exclude "/lost+found" --exclude "/tmp" .)|(cd /mnt && tar xf -)

配置修改

注解

注意:除非使用 dd 来复制SD卡到HDD才能保持原有的 PARTUUID ,否则使用 parted 划分分区以及使用 mkfs 创建文件系统,都会使得目标磁盘的 UUIDPARTUUID 变化。则需要修改启动配置文件反映分区标识的变化。

  • 检查当前SD卡的分区UUID,例如如下:

    $ sudo blkid /dev/mmcblk0p1
    /dev/mmcblk0p1: LABEL="boot" UUID="CDD4-B453" TYPE="vfat" PARTUUID="5e878358-01"
    
    $ sudo blkid /dev/mmcblk0p2
    /dev/mmcblk0p2: LABEL="rootfs" UUID="72bfc10d-73ec-4d9e-a54a-1cc507ee7ed2" TYPE="ext4" PARTUUID="5e878358-02"
    
    $ sudo blkid /dev/mmcblk0
    /dev/mmcblk0: PTUUID="5e878358" PTTYPE="dos"
    

note:

``/dev/mmcblk0`` 使用 ``parted`` 检查显示是 ``msdos`` 分区表,但是使用 ``blkid`` 检查可以看到具有 ``PARTUUID`` 。参考 `Persistent block device naming <https://wiki.archlinux.org/index.php/persistent_block_device_naming>`_ ,原文介绍 ``GPT`` 分区表支持 ``PARTUUID`` 。不过,我实践发现树莓派默认安装的系统使用的是 ``msdos`` 分区表,但是也具有 ``PARTUUID`` 。测试验证发现,通过使用 ``parted`` 划分磁盘分区就会有 ``PARTUUID`` 。

以下是 /dev/mmcblk0partedprint 输出:

GNU Parted 3.3
Using /dev/mmcblk0
Welcome to GNU Parted! Type 'help' to view a list of commands.
(parted) print
Model: SD SN128 (sd/mmc)
Disk /dev/mmcblk0: 128GB
Sector size (logical/physical): 512B/512B
Partition Table: msdos
Disk Flags:

Number  Start   End    Size   Type     File system  Flags
 1      1049kB  269MB  268MB  primary  fat32        boot, lba
 2      269MB   128GB  128GB  primary  ext4

上述可以看到

分区 | PARTUUID |
/dev/mmcblk0p1 | 5e878358-01 |
/dev/mmcblk0p2 | 5e878358-02 |

如果使用 dd 命令来复制磁盘分区,则HDD磁盘的 /dev/sda1/dev/sda2PARTUUID 会和原先的TF卡完全相同,即依然保持 5e878358-015e878358-02 。这样就不用修改HDD文件系统中的配置。

但是通过磁盘 partedmkfs.ext4 创建的HDD文件系统,然后再通过 tar 恢复操作系统。此时磁盘 PARTUUIDUUID 不同,则要修改对应配置 /boot/cmdline.txt/etc/fstab

# blkid /dev/sda1
/dev/sda1: UUID="CB15-2042" TYPE="vfat" PARTUUID="5e878358-01"
# blkid /dev/sda2
/dev/sda2: UUID="d11f9da5-aeee-477f-9d95-d290c6f56267" TYPE="ext4" PARTUUID="5e878358-02"

32位操作系统启动配置

注解

以下32位操作系统配置方法是我之前的记录整理,当前实践是64位操作系统,方法不同。

  • 检查 /boot/cmdline.txt 配置文件,可以看到原先配置内容如下:

    $ cat cmdline.txt
    dwc_otg.lpm_enable=0 console=serial0,115200 console=tty1 root=PARTUUID=5e878358-02 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait
    

这里可以看到 root=PARTUUID=5e878358-02 就是SD卡的分区 /dev/mmcblk0p2 对应的 PARTUUID="5e878358-02"

  • 根据前述检查USB磁盘的分区 UUID ,即 e3f5b3fb-297c-44fe-b763-566b51b87524 ,注意,我们要将启动指向分区 /dev/sda2 ,因为这个分区就是从 /dev/mmcblk0p2 通过 tar 方式复制出来的。修改 /mnt/boot/cmdline.txt (该文件位于 /dev/sda2 这个HDD分区文件系统中):

    dwc_otg.lpm_enable=0 console=serial0,115200 console=tty1 root=PARTUUID=1a99ca08-02 rootfstype=ext4 elevator=cfq fsck.repair=yes rootwait
    

注解

这里修改了2个地方:

  • root=PARTUUID=e3f5b3fb-297c-44fe-b763-566b51b87524 指向HDD磁盘分区 /dev/sda2 表示从USB外接的硬盘启动

  • evevator=cfq 是修改原先针对SSD/SDCARD/TFCARD这类固态硬盘优化参数 deadline ,由于使用机械硬盘针对HDD硬盘优化参数修改成 cfq

  • 修改 /mnt/etc/fstab 配置文件,修改 / 行中 PARTUUID 内容:

    proc            /proc           proc    defaults          0       0
    PARTUUID=5e878358-01  /boot           vfat    defaults          0       2
    PARTUUID=5e878358-02  /               ext4    defaults,noatime  0       1
    
  • 关机,然后取出TF卡,再次加电,此时树莓派将从外接USB的HDD磁盘启动

注解

测试下来,如果再次使用TF卡,依然能够优先从TF卡启动树莓派。只有TF卡不可用时候,才会从USB HDD启动。

64位Ubuntu启动修改

Ubuntu镜像使用 u-boot 作为bootloader,而树莓派内建的bootloader可以使用在 system-boot 分区的config.txt文件的一些修改。

64位Ubuntu操作系统 /boot 目录并没有独立建立分区,而是在 /boot/firmware 目录单独建立vfat32分区,并且这个分区是可启动分区。

对于2017年4月以后的系统,必须具备bootloader文件,所以需要获得最新的 bootcode.bin, fixup.dat 和 start.elf 并复制到 system-boot 分区。另外,Ubuntu的u-boot脚本硬编码了使用SD卡启动,所以需要修改bootloader,采用树莓派的bootloader才能够从USB磁盘启动。

解压缩内核

警告

每次Ubuntu升级内核都需要重复这个步骤。

首先我们需要把 vmlinuz 解压缩成 vmlinux ,这是因为当前还不支持从压缩的 64位 arm 内核启动

  • 找出内核镜像的gziped内容位置:

    od -A d -t x1 vmlinuz | grep '1f 8b 08 00'
    

输出内容:

0000000 1f 8b 08 00 00 00 00 00 02 03 ec 5c 0f 74 54 e

这里第一个 0000000 数字就是我们查找的位置,在这个位置右边就是镜像起点。

  • 使用 dd 命令输出数据并使用 zcat 解压缩。如果你看到的数字不是 0000000 ,就用你看到的数字作为 skip= 参数:

    dd if=vmlinuz bs=1 skip=0000000 | zcat > vmlinux
    

修改bootloader

  • 查看 /mnt/boot/firmware/config.txt (也就是USB硬盘分区 /dev/sda1 挂载后的配置文件) ,默认内容是针对不同树莓派的启动配置。注意,在配置文件开头说明建议不要直接修改 config.txt ,而是应该修改 usercfg.txt 来包含用户修改:

    [pi4]
    kernel=uboot_rpi_4.bin
    max_framebuffers=2
    
    [pi2]
    kernel=uboot_rpi_2.bin
    
    [pi3]
    kernel=uboot_rpi_3.bin
    
    [all]
    arm_64bit=1
    device_tree_address=0x03000000
    
    enable_uart=1
    cmdline=cmdline.txt
    
    include syscfg.txt
    include usercfg.txt
    

按照Ubuntu文档,需要将修改成:

kernel=vmlinuz
initramfs initrd.img followkernel
#device_tree_address=0x03000000

所以我实际修改 config.txt 内容如下:

[pi4]
#kernel=uboot_rpi_4.bin
#max_framebuffers=2

[pi2]
#kernel=uboot_rpi_2.bin

[pi3]
#kernel=uboot_rpi_3.bin

[all]
arm_64bit=1
device_tree_address=0x03000000
kernel=vmlinux
initramfs initrd.img followkernel

更新.dat和.elf文件

  • 检查 /mnt/boot 目录下内容,可以看到 dtbs 目录因为我最初是安装的树莓派4系统,所以 dtb 软链接都是只想树莓派4,这部分需要手工修改。

不过我发现使用树莓派4的TF卡插入到树莓派3上能够正常启动

以下是当前 /mnt/boot 下内容,如果有必要我准备手工修改 dtb 软链接:

# ls -lh
total 81M
-rw------- 1 root root 4.0M Jul 10 05:18 System.map-5.4.0-1015-raspi
-rw------- 1 root root 4.0M Sep  5 01:03 System.map-5.4.0-1018-raspi
-rw-r--r-- 1 root root 216K Jul 10 05:18 config-5.4.0-1015-raspi
-rw-r--r-- 1 root root 216K Sep  5 01:03 config-5.4.0-1018-raspi
lrwxrwxrwx 1 root root   43 Sep 18 12:53 dtb -> dtbs/5.4.0-1018-raspi/./bcm2711-rpi-4-b.dtb
lrwxrwxrwx 1 root root   43 Sep 12 06:07 dtb-5.4.0-1015-raspi -> dtbs/5.4.0-1015-raspi/./bcm2711-rpi-4-b.dtb
lrwxrwxrwx 1 root root   43 Sep 18 12:53 dtb-5.4.0-1018-raspi -> dtbs/5.4.0-1018-raspi/./bcm2711-rpi-4-b.dtb
drwxr-xr-x 4 root root 4.0K Sep 12 06:08 dtbs
drwxr-xr-x 5 root root 5.0K Jan  1  1970 firmware
lrwxrwxrwx 1 root root   27 Sep 12 06:06 initrd.img -> initrd.img-5.4.0-1018-raspi
-rw-r--r-- 1 root root  29M Sep 12 06:07 initrd.img-5.4.0-1015-raspi
-rw-r--r-- 1 root root  29M Sep 18 12:53 initrd.img-5.4.0-1018-raspi
lrwxrwxrwx 1 root root   27 Jul 31 16:44 initrd.img.old -> initrd.img-5.4.0-1015-raspi
lrwxrwxrwx 1 root root   24 Sep 12 06:06 vmlinuz -> vmlinuz-5.4.0-1018-raspi
-rw------- 1 root root 8.1M Jul 10 05:18 vmlinuz-5.4.0-1015-raspi
-rw------- 1 root root 8.1M Sep  5 01:03 vmlinuz-5.4.0-1018-raspi
lrwxrwxrwx 1 root root   24 Jul 31 16:44 vmlinuz.old -> vmlinuz-5.4.0-1015-raspi

以下是复制树莓派3的dtb文件并建立软链接步骤:

cd /mnt/boot/dtbs/5.4.0-1018-raspi
cp /lib/firmware/5.4.0-1018-raspi/device-tree/broadcom/bcm2837-rpi-3-b.dtb ./
cd /mnt/boot/dtbs/5.4.0-1015-raspi
cp /lib/firmware/5.4.0-1015-raspi/device-tree/broadcom/bcm2837-rpi-3-b.dtb ./

cd /mnt/boot
unlink dtb
ln -s dtbs/5.4.0-1018-raspi/./bcm2837-rpi-3-b.dtb ./dtb
unlink dtb-5.4.0-1015-raspi
ln -s dtbs/5.4.0-1015-raspi/./bcm2837-rpi-3-b.dtb ./dtb-5.4.0-1015-raspi
unlink dtb-5.4.0-1018-raspi
ln -s dtbs/5.4.0-1018-raspi/./bcm2837-rpi-3-b.dtb ./dtb-5.4.0-1018-raspi

注解

不过我执行了上述软链接修正,在树莓派3上依然不能从USB磁盘启动。从 USB Boot Ubuntu Server 20.04 on Raspberry Pi 4 来看,可能需要更新最新的 raspberrypi/firmware

然后复制到 /mnt/boot/firmware 目录下覆盖原文件:

cd /mnt/boot/firmware
cp ~/Downloads/firmware-/boot/*.dat ./
cp ~/Downloads/firmware-/boot/*.elf .

注解

这步待验证

修改bootloader

  • 修改 /mnt/boot/firmware/cmdline.txt

cmdline.txt

net.ifnames=0 dwc_otg.lpm_enable=0 console=serial0,115200 console=tty1 root=LABEL=writable rootfstype=ext4 elevator=deadline rootwait fixrtc

原先记录是 root=LABEL=writable 实际上就是SD卡的原先的 /dev/mmcblk0p2 (分区2) 的文件系统LABEL名字(我觉得其实格式化移动硬盘也加上这个标签,或许不需要再修订 cmdline.txt 配置) 。我现在修改成USB移动硬盘分区的PARTUUID。

另外还修改一个针对机械硬盘优化参数 elevator=cfq

完整修订如下:

net.ifnames=0 dwc_otg.lpm_enable=0 console=serial0,115200 console=tty1 root=PARTUUID=5e878358-02 rootfstype=ext4 elevator=cfq rootwait fixrtc

分区

参考原先SD卡的分区标记,在 /dev/sda1 上加上启动标记:

# parted /dev/sda
GNU Parted 3.3
Using /dev/sda
Welcome to GNU Parted! Type 'help' to view a list of commands.
(parted) print
Model: External USB3.0 (scsi)
Disk /dev/sda: 500GB
Sector size (logical/physical): 512B/4096B
Partition Table: msdos
Disk Flags:

Number  Start   End     Size    Type     File system  Flags
 1      1049kB  256MB   255MB   primary  fat32        lba
 2      256MB   30.0GB  29.7GB  primary  ext4

(parted) set 1 boot on
(parted) print
Model: External USB3.0 (scsi)
Disk /dev/sda: 500GB
Sector size (logical/physical): 512B/4096B
Partition Table: msdos
Disk Flags:

Number  Start   End     Size    Type     File system  Flags
 1      1049kB  256MB   255MB   primary  fat32        boot, lba
 2      256MB   30.0GB  29.7GB  primary  ext4

(parted) quit
Information: You may need to update /etc/fstab.
  • 修改 /mnt/etc/fstab 配置,对应磁盘分区的PARTID:

    PARTUUID="5e878358-02"  /        ext4   defaults        0 0
    PARTUUID="5e878358-01"  /boot/firmware  vfat    defaults        0       1
    

注解

我现在暂时还没有解决Raspberry Pi 3从USB存储启动Ubuntu Server 64bit for Raspberry Pi系统,似乎是需要更新firmware来解决。

不过这两天感觉有点瓶颈(疲倦),先放下,等过两天解决 树莓派4 USB存储启动Ubuntu Server 20.04 之后再会过来处理。

参考