美文网首页
树莓派(Raspberry Pi)修改系统镜像(img)

树莓派(Raspberry Pi)修改系统镜像(img)

作者: 绿箭ML | 来源:发表于2020-08-15 11:28 被阅读0次

    树莓派修改系统镜像

    讨论如何使用通过loop设备映射文件,挂载树莓派img中的分区,然后像普通的文件系统那样修改镜像分区中的文件。

    有2个关键点

    • 如何确认分区的起始位置,以及分区的范围。
    • 不同版本的losetup支持的参数不一样,如果支持-P参数特性,则可以直接加载分区,无需再手动计算偏移量,可以像挂载普通硬盘一样直接生成分区块设备

    准备工作

    • 需要一个支持linux设备,已经root了的termux,或者,一个普通的linux发行版均可。
    • 需要用到的关键命令losetup,fdisk,tun2fs,mount,请检查是否都有。
    • 大部分操作均需要root权限。
    • 去源内下载一份镜像文件。

    第一步:下载镜像

    首先,下载一个可以用于写入树莓派的img镜像,国内可以在清华的镜像站中下载。

    清华源的地址:https://mirrors.tuna.tsinghua.edu.cn/raspberry-pi-os-images/raspbian/images/raspbian-2020-02-14/

    我下载的是2020-02-13-raspbian-buster.zip,解压后得到2020-02-13-raspbian-buster.img,img文件可以直接烧录到内存卡,它实际上是个包含了mbr分区表的磁盘映像。

    第二步:使用losetup命令把img文件映射成块设备

    首先我们先确认losetup支持的选项,有没有-P选项:

    #这是我手机版本的losetup
    $losetup --help
    usage: losetup [-cdrs] [-o OFFSET] [-S SIZE] {-d DEVICE...|-j FILE|-af|{DEVICE FILE}}
    
    Associate a loopback device with a file, or show current file (if any)
    associated with a loop device.
    
    Instead of a device:
    -a      Iterate through all loopback devices
    -f      Find first unused loop device (may create one)
    -j      Iterate through all loopback devices associated with FILE
    
    existing:
    -c      Check capacity (file size changed)
    -d      Detach loopback device
    
    new:
    -s      Show device name (alias --show)
    -o      Start assocation at OFFSET into FILE
    -r      Read only
    -S      Limit SIZE of loopback association (alias --sizelimit)
    
    

    看帮助信息,它不支持-P参数,直接加载一个多分区的img文件,它不会生成/dev/loop0p1这样的分区块设备。

    如果losetup支持-P参数,那么,可以这样让他/dev生成分区的块设备loop0p1

    #losetup -f -P ./2020-02-13-raspbian-buster.img
    

    再查看/dev下loop有没有生成对应分区的块设备,如果额外生成/dev/loop0p2这样的文件,则直接挂载这个设备。如果没有,继续以下步骤,手动计算分区的起始位置和大小。

    注意,linux发行版的losetup如果没有-S参数,请看看是否是--sizelimit参数,没有-o的话,则看看--offset,先通过losetup --help查看

    第三步:确认分区数量和分区的位置

    上面的losetup有两个很重要的参数

    • -S Limit SIZE of loopback association

      • 指定映射的文件部分内容(可以用来设定分区的大小)
    • -o Start assocation at OFFSET into FILE

      • 跳过多少个字节(用这个参数可以指定分区的起始位置)

    不同版本的可能losetup相关的参数有细微的不同,要以实际为准。

    那么需要确定分区的起始和结束位置。先尝试把整个img映射,注意,这需要root权限

    加载当前文件夹的2020-02-13-raspbian-buster.img

    #losetup -f ./2020-02-13-raspbian-buster.img
    

    映射后通过losetup命令(不带参数)得知,文件映射到了/dev/loop0这个设备

    因为img包含了mbr分区表信息,我可以使用fdisk来读取分区表,获取分区信息。

    #fdisk -l  /dev/loop0
    Disk /dev/loop0:3.5 GiB,3787456512 字节,7397376 个扇区
    单元:扇区 / 1 * 512 = 512 字节
    扇区大小(逻辑/物理):512 字节 / 512 字节
    I/O 大小(最小/最佳):512 字节 / 512 字节
    磁盘标签类型:dos
    磁盘标识符:0xea7d04d6
    
    设备         启动   起点    末尾    扇区  大小 Id 类型
    /dev/loop0p1        8192  532479  524288  256M  c W95 FAT32 (LBA)
    /dev/loop0p2      532480 7397375 6864896  3.3G 83 Linux
    

    通过分区表,我获得了一些信息。

    • 这个是个3.5G的映像。
    • 这个img有2个分区,一个是fat32分区(/dev/loop0p1),一个是linux的ext分区。(/dev/loop0p2)
    • 分区的具体物理位置(起点、末尾),分区大小(扇区)
    • 这个磁盘镜像每个扇区是512字节

    他虽然写了/dev/loop0p2这样的设备,但是实际上,可能/dev下根本没有loop0p1 loop0p2这两个块设备文件。

    此时需要换一种方式,根据分区在文件内的位置,直接映射分区到loop设备,然后再挂载。

    第3.5步:计算分区位置及大小

    因为img文件包含一个mbr分区表,可以通过查看分区表确认分区数量和位置,通过以上fdisk读取的分区表信息可以得知,该img有2个分区。

    fat32类型那个分区应该存放内核,config.txt之类的分区,也就是我们烧录后看到内存卡只有256m的原因。

    linux类型分区是树莓派的根分区,也就是进系统后,挂载在/的根分区

    此时我需要计算根分区的起始位置,如果我需要改动config.txt,则计算fat32分区的位置,以下以计算根分区为例。

    逻辑扇区大小为512字节,分区大小为扇区数量的512倍字节,需要乘以扇区大小(下面换算分区大小同理),根分区的起始位置则换算为

    512 * 532480 = 272629760
    

    它偏离文件起始的272629760字节,即用-o参数指定偏移的值。

    分区的大小为

    512  * 6864896 = 3514826752
    

    使用-S参数限制映像文件的内容范围,记录下来以上信息后,卸载loop设备(此处为/dev/loop0),然后再重新进行映射。

    卸载设备

    #losetup -d /dev/loop0
    

    再次映射

    #losetup -f -o 272629760 -S 3514826752 ./2020-02-13-raspbian-buster.img
    

    此时,我们再次losetup看看映射的loop设备

    #losetup
    NAME        SIZELIMIT    OFFSET AUTOCLEAR RO BACK-FILE                                                      DIO LOG-SEC
    /dev/loop0 3514826752 272629760         0  0 /home/xxx/raspbian/2020-02-13-raspbian-buster.img   0     512                                                                           0     512
    

    可以看到sizelimit字段和offset字段都有了具体的值,和我们设置的一致。/dev/loop0映射到了映像文件的根分区范围内

    这是一个ext分区,我们可以通过tun2fs来读取文件系统的超级块

    #tun2fs -l /dev/loop0
    

    可以看到以下内容

    tune2fs 1.44.5 (15-Dec-2018)
    Filesystem volume name:   rootfs
    Last mounted on:          /mnt/raspbian
    Filesystem UUID:          80571af6-21c9-48a0-9df5-cffb60cf79af
    Filesystem magic number:  0xEF53
    Filesystem revision #:    1 (dynamic)
    Filesystem features:      has_journal ext_attr resize_inode dir_index filetype extent flex_bg sparse_super large_file dir_nlink extra_isize
    Filesystem flags:         unsigned_directory_hash 
    Default mount options:    user_xattr acl
    Filesystem state:         clean
    Errors behavior:          Continue
    Filesystem OS type:       Linux
    Inode count:              214704
    Block count:              858112
    Reserved block count:     42905
    Free blocks:              133541
    Free inodes:              108390
    First block:              0
    Block size:               4096
    Fragment size:            4096
    Reserved GDT blocks:      209
    Blocks per group:         32768
    Fragments per group:      32768
    Inodes per group:         7952
    Inode blocks per group:   497
    Flex block group size:    16
    Filesystem created:       Fri Feb 14 00:15:48 2020
    Last mount time:          Sat Aug 15 04:54:28 2020
    Last write time:          Sat Aug 15 05:22:08 2020
    Mount count:              3
    Maximum mount count:      -1
    Last checked:             Fri Feb 14 00:15:48 2020
    Check interval:           0 (<none>)
    Lifetime writes:          3052 MB
    Reserved blocks uid:      0 (user root)
    Reserved blocks gid:      0 (group root)
    First inode:              11
    Inode size:           256
    Required extra isize:     32
    Desired extra isize:      32
    Journal inode:            8
    Default directory hash:   half_md4
    Directory Hash Seed:      6006b686-6f27-4ca7-b7ea-d1d803c3da46
    Journal backup:           inode blocks
    

    说明正确读出了该分区下文件系统的超级快。可以挂载。

    第4步:挂载文件系统

    在当前文件夹下新建一个root文件夹作为分区的挂载点。

    #mkdir root
    

    挂载

    #mount -t ext4 -o rw /dev/loop0 root
    

    挂载成功后,通过当前目录下root挂载点访问img中根分区的内容。需要修改什么内容就尽情修改吧!

    修改完成后使用sync命令同步写入磁盘。

    #sync
    #sync
    #sync
    

    退出root文件夹后,卸载当前目录下root挂载点

    #umount root
    

    取消映射关系,分离

    #losetup -d /dev/loop0
    

    插入tf卡后,用dd指令把img文件写入,假设内存卡设备为/dev/sdc

    dd if=./2020-02-13-raspbian-buster.img of=/dev/sdc
    

    镜像比较大,而且tf卡性能较差的情况下,写入的速度比较慢,需要耐心等待。

    写入成功后,sync同步,即可取出tf卡。树莓派系统刷写完毕。

    相关文章

      网友评论

          本文标题:树莓派(Raspberry Pi)修改系统镜像(img)

          本文链接:https://www.haomeiwen.com/subject/nlxadktx.html