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

树莓派修改系统镜像

讨论如何使用通过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卡。树莓派系统刷写完毕。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,290评论 6 491
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,107评论 2 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,872评论 0 347
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,415评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,453评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,784评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,927评论 3 406
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,691评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,137评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,472评论 2 326
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,622评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,289评论 4 329
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,887评论 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,741评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,977评论 1 265
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,316评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,490评论 2 348