linux - 是否可以在运行时调整 MTD 分区的大小?
问题描述
我有一个非常具体的需求:部分替换闪存的内容并移动 MTD 分区边界。
目前的地图是:
u-boot 0x000000 0x040000
u-boot-env 0x040000 0x010000
kernel 0x050000 0x230000
initrd 0x280000 0x170000
scripts 0x3f0000 0x010000
filesystem 0x400000 0xbf0000
firmware 0xff0000 0x010000
虽然所需的输出是:
u-boot 0x000000 0x040000
u-boot-env 0x040000 0x010000
kernel 0x050000 0x230000
filesystem 0x280000 0xd70000
firmware 0xff0000 0x010000
这意味着要崩溃initrd
,scripts
并filesystem
进入一个单独的区域,而让其他区域独自一人。
问题是这应该从正在运行的系统中实现(使用“旧”配置启动),我应该在重新启动之前重写内核和“新”文件系统。
该系统是嵌入式的,所以我没有多少空间进行操作(不过我有一张 SD 卡)。
当然,重写的内核将在其 DTB 中写入“新”配置。
问题是过渡。
注意:我看过这个问题,但它很老,并且需要内核补丁,我想避免它的缺点。
注意2:这个问题已被标记为删除,因为“与编程无关”。我不同意:我需要在大约 14k 设备上执行上述操作,其中大多数已经卖给了客户,所以任何可行的解决方案至少应该包括脚本。
NOTE3:如果绝对必要,我什至可以考虑(小)内核修改(是的,我有办法远程更新内核)。
解决方案
我有三个想法/建议:
- 您可以将“新”文件系统映像拆分为块并将它们写入相应的“旧”MTD 分区,而不是移动分区吗?这样您就不需要更改 MTD 分区图。启动到新内核后,它将看到新的连续根文件系统。对于 JFFS2 文件系统,使用 split 或 dd、flash_erase 和 nandwrite 应该相当简单。就像是:
# WARNING: this script assumes that it runs from tmpfs and the old root filesystem is already unmounted.
# Also, it assumes that your shell has arithmetic evaluation, which handles hex (my busybox 1.29 ash does this).
# assuming newrootfs.img is the image of new rootfs
new_rootfs_img="newrootfs.img"
mtd_initrd="/dev/mtd3"
mtd_initrd_size=0x170000
mtd_scripts="/dev/mtd4"
mtd_scripts_size=0x010000
mtd_filesystem="/dev/mtd5"
mtd_filesystem_size=0xbf0000
# prepare chunks of new filesystem image
bs="0x1000"
# note: using arithmetic evaluation $(()) to convert from hex and do the math.
# dd doesn't handle hex numbers ("dd: invalid number '0x1000'") -- $(()) works this around
dd if="${new_rootfs_img}" of="rootfs_initrd" bs=$(( bs )) count=$(( mtd_initrd_size / bs ))
dd if="${new_rootfs_img}" of="rootfs_scripts" bs=$(( bs )) count=$(( mtd_scripts_size / bs )) skip=$(( mtd_initrd_size / bs ))
dd if="${new_rootfs_img}" of="rootfs_filesystem" bs=$(( bs )) count=$(( mtd_filesystem_size / bs )) skip=$(( ( mtd_initrd_size + mtd_scripts_size ) / bs ))
# there's no going back after this point
flash_eraseall -j "${mtd_initrd}"
flash_eraseall -j "${mtd_scripts}"
flash_eraseall -j "${mtd_filesystem}"
nandwrite -p "${mtd_initrd}" rootfs_initrd
nandwrite -p "${mtd_scripts}" rootfs_scripts
nandwrite -p "${mtd_filesystem}" rootfs_filesystem
# don't forget to update the kernel too
有对连接 MTD 设备的内核支持(这正是您想要做的)。我看不到使用它的简单方法,但您可以创建一个内核模块,它将您所需的分区连接到一个连续的 MTD 设备中。
为了将 3 个 MTD 分区合并为一个以写入新文件系统,您可以在 3 个 mtdblocks 上创建一个 dm 线性映射,然后使用 block2mtd 将其转回 MTD 设备。(即mtdblock + 设备映射器线性+ block2mtd) 但它看起来很尴尬,我不知道它是否能正常工作(例如,OOB 数据)。
EDIT1:添加了一条注释,解释使用$(( bs ))
-- 从十六进制转换为dd
不直接处理十六进制数字(coreutils 和busybox dd 都不是)。
推荐阅读
- docker - TensorFlow 模型服务器 - 无法解析主机 POST
- ios - 带有 ScrollView 的 NavigationView 具有意外的速度(或没有动画) - 大标题 + ScrollView - SwiftUI - iOS 14
- xamarin.android - Xamarin Android - 自定义地图图像异步
- javascript - 如果每个字符串中的第一个字符相同,则从数组中的每个字符串中删除第一个字符
- javascript - 为什么在javascript中未定义console.log(XHR.responceText)日志记录
- cookies - 将 localhost 连接到远程开发服务器(CORS、同站点、安全和其他令人头疼的问题)
- visual-studio - Azure 函数在 function.json 的本地缺少绑定
- ldap - 在 LDAP 中一次更改多个 UID 的单个属性的值
- java - 用于显示 ProgressBar 的弹出窗口未在 JavaFX 中显示
- swift - 有没有办法为 Xcode 游乐场设置部署目标