我有一个非常具体的需求:
部分替换Flash 的内容以移动MTD分区边界。

当前 map 是:

  • 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

  • 这意味着将initrdscriptsfilesystem折叠到一个区域中,而其他区域则保持独立。

    问题是这应该从正在运行的系统(使用“旧”配置启动)开始实现。我应该在重新启动之前重写内核和"new"文件系统。

    该系统是嵌入式系统,因此我的操作空间很小(不过,我有SD卡)。

    当然,重写后的内核将在其DTB中写入"new"配置。

    问题是过渡。

    注意:我见过this Question,但是它很老,并且有需要内核补丁的缺点,我想避免这种情况。

    注意2:该问题已被标记为删除,因为“与编程无关”。我不同意:我需要在大约14k的设备上执行上述操作,其中大多数设备已经出售给客户,因此任何可行的解决方案至少都应包含脚本。

    注意3:如果绝对必要,我什至可以考虑(小的)内核修改(是的,我有办法远程更新内核)。

    最佳答案

    我有三个想法/建议:

  • 除了移动分区,您是否可以将"new"文件系统镜像拆分为多个块并将它们写入相应的“旧” 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
    
  • concatenating MTD devices支持内核(这正是您要尝试的功能)。我看不到使用它的简单方法,但是您可以创建一个内核模块,该模块将所需的分区连接到一个连续的MTD设备中。
  • 为了将3个MTD分区合并为一个以写入新的文件系统,您可以在3个mtdblock上创建dm-linear映射,然后使用block2mtd将其转换回MTD设备。 (即mtdblock +设备映射器线性+ block2mtd),但是看起来很尴尬,我不知道它是否能很好地工作(例如,OOB数据)。

  • EDIT1:添加了一条注释,解释了$(( bs ))的使用-从十六进制转换,因为dd不能直接处理十六进制数字(既不是coreutils,也不是busybox dd)。

    关于linux - 是否可以在运行时调整MTD分区的大小?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/57613365/

    10-12 05:30