WhyCan Forum

人过留名,雁过留声,感谢各位朋友不离不弃地支持。 QQ: 516333132, 微信: whycan_cn (哇酷网/挖坑网/填坑网) admin@whycan.cn

您尚未登录。

#1 2019-10-11 16:22:55

Rikka0w0
会员
注册时间: 2019-10-08
累计积分: 4

为F1C100S的SPI Flash制作SquashFS+JFFS2+OverlayFS的rootfs来增大可读写空间

荔枝派标配的是16MB的W25Q128 SPI Flash,在放入荔枝派官方的uboot 内核 rootfs的情况下,可用空间一般不超过1MB。
其实仔细观察一下还是有很多可以调整的空间的。

SquashFS可以对rootfs进行压缩,但是rootfs会变成只读的。可以使用OverlayFS将只读分区和可写分区合并,这样的rootfs优先使用SquashFS里的数据并且会把更改储存到JFFS2分区里面。只要运行时没有过多修改SquashFS里的数据,那这种方案节省的空间还是很多的。大名鼎鼎的OpenWRT既是采用了这种解决方案从而能在8MB Flash的路由器上运行的。这种方案运行时修改来自SquashFS的文件时,那个文件并不会动,而是会在JFFS2里储存修改后的文件,这样会有一个文件的两个版本,OverlayFS优先使用JFFS2里的版本,但是这样会造成两个版本同时存在,反而浪费空间,但是这也没办法。有得有失嘛。

这个是我的SPI Flash的结构:

Partition	Content		Offset		Size (byte)
mtd0		uboot-bin		0			0x58000 (360448 Byte)
		uboot-env		0x58000		0x8000
mtd1		dtb			0x60000		0x4000  (16kB)
mtd2		kernel		0x64000		0x400000 (4MB)
mtd3		rootfs		0x464000		0x4FC000 (4.98MB)
mtd4		overlay		0x960000		0x500000 (5MB)

相比官方的镜像,多了一个mtd4分区,就是用于储存运行时对rootfs修改的地方。注意这个mtd4的起始地址和大小必须是擦除区块大小的整数倍,不然无法写!我用的W25Q128这个数字是0x10000(64kB)。

首先是降低uboot的空间占用, https://whycan.cn/t_2179.html 里提到了uboot本体只有270kb,我看了下,确实是这样,我的u-boot.bin是268kb。
于是激进一点,把Environment Offset从0x100000调成了0x58000,这样Uboot部分分400kB就可以了,比原版的1MB小太多了。
话说回来Uboot一般也不会在之后加太多东西了,最多变变启动参数什么的,本体大小变化不大,这个应该是安全的。
具体的Uboot配置需要在`make ARCH=arm menuconfig`里修改,一共有三处:

# [ *] Enable boot arguments
   = console=ttyS0,115200 panic=5 rootwait root=/dev/mtdblock3 rw rootfstype=squashfs init=/etc/preinit
# [ *] Enable a default value for bootcmd
   = sf probe 0 50000000; sf read 0x80C00000 0x60000 0x4000; sf read 0x80008000 0x64000 0x400000; bootz 0x80008000 - 0x80C00000
# Environment -> Environment Offset = 0x58000

分别是:

1. 指定Linux的启动参数,要点是rootfstype=squashfs init=/etc/preinit这部分,之后会说。
2. 告诉UBoot如何把dtb和内核zImage从SPI Flash装载到内存里,这部分的SPI Flash地址要和上面的表对应。
3. 修改UBoot环境变量储存区的开始位置,减小空间浪费。

UBoot不需要修改c或者h文件。




然后是修改Linux内核的配置,同样还是`make ARCH=arm menuconfig`:

<*> Overlay filesystem support
[ *] Miscellaneous filesystems  --->
--><*>   Journalling Flash File System v2 (JFFS2) support
--><*>   SquashFS 4.0 - Squashed file system support

Device Drivers:

<*> Memory Technology Device (MTD) support  --->
--><*>   Caching block device access to MTD devices

[ *] SPI support  --->
-->< >   Allwinner A10 SoCs SPI controller
--><*>   Allwinner A31 SPI controller

分别是启用了OverlayFS、JFFS2、SquashFS文件系统的支持,
启动MTD设备的缓存(这样才能用SPI Flash上启动)
然后就是修正原版.config里SPI控制器选错了的问题。

还有需要修改dts文件(arch/arm/boot/dts/suniv-f1c100s-licheepi-nano.dts):

    flash: w25q128@0 {
        #address-cells = <1>;
        #size-cells = <1>;
        compatible = "winbond,w25q128", "jedec,spi-nor";
        reg = <0>;
        spi-max-frequency = <50000000>;
        partitions {
            compatible = "fixed-partitions";
            #address-cells = <1>;
            #size-cells = <1>;

            partition@0 {
                label = "u-boot";
                reg = <0x000000 0x58000>;
                read-only;
            };

            partition@60000 {
                label = "dtb";
                reg = <0x60000 0x4000>;
                read-only;
            };

            partition@64000 {
                label = "kernel";
                reg = <0x64000 0x400000>;
                read-only;
            };

            partition@464000 {
                label = "rootfs";
                reg = <0x464000 0x4FC000>;
                read-only;
            };

            partition@960000 {
                label = "overlayfs";
                reg = <0x960000 0x500000>;
            };

        };
    };

   

这里面的分区开始位置和大小要和uboot启动参数还有最上面的表对应才行。
到此为止uboot和Linux内核就修改好了。现在可以对u-boot和linux分别使用:
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- -j4

然后是编译linux的内核模块:

make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- -j4 INSTALL_MOD_PATH=out modules
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- -j4 INSTALL_MOD_PATH=out modules_install

现在可以开始制作rootfs了。首先是制作SquashFS部分,这部分是基于原版的Rootfs的。
1. 释放原来的rootfs到一个文件夹:

mkdir rootfs_new
cd rootfs_new
tar xvpzf ../rootfs.tar.gz

2. 把新编译的内核模块放进去
3. 创建映射文件夹

mkdir rootfs_new/overlay
mkdir rootfs_new/chroot
mkdir rootfs_new/rom

4. 建立一个启动脚本`rootfs_new/etc/preinit`:

#!/bin/sh

# export PATH="/usr/sbin:/usr/bin:/sbin:/bin"

# mount the new rootfs
mount -t squashfs /dev/mtdblock3 /rom
mount -t jffs2 /dev/mtdblock4 /overlay
mount -n -t overlay overlayfs:/overlay -o lowerdir=/rom,upperdir=/overlay/rw,workdir=/overlay/work /chroot

# mount /dev and /sys for chroot environment
# /dev/pts, /dev/shm, /proc, /tmp and /run will be mounted by inittab from fstab
mount -t sysfs sysfs /sys
mount --rbind /sys /chroot/sys/
mount --rbind /dev /chroot/dev/


exec chroot /chroot /sbin/init

启动参数里的init=/etc/preinit就是指这个脚本。根据Linux文档,init=这个参数会替换原本的/sbin/init被执行。
咱们的preinit首先会挂载只读分区SquashFS和可写分区JFFS2,再在/chroot文件夹中创建overlay,
然后在新的rootfs里挂在/dev和/sys,最后执行chroot并在新的root环境下执行/sbin/init,
回归系统正常的启动程序,只不过是在新的rootfs下。这样之后的程序都不会察觉rootfs发生了变化。使用如下命令打包SquashFS:
mksquashfs rootfs_new/ rootfs_new.img -no-exports -no-xattrs -all-root

最后一步是制作JFFS2的镜像:

mkdir -p overlay/work
mkdir -p overlay/rw
mkfs.jffs2 -s 0x100 -e 0x10000 --pad=0x500000 -o jffs2.img -d overlay/

work文件夹是OverlayFS需要的一个空文件夹,rw是储存增量修改的地方。



烧写入SPI Flash, 注意地址别写错:

# uboot
sudo sunxi-fel -p spiflash-write 0 u-boot/u-boot-sunxi-with-spl.bin
# dtb
sudo sunxi-fel -p spiflash-write 0x60000 linux/arch/arm/boot/dts/suniv-f1c100s-licheepi-nano.dtb
# kernel
sudo sunxi-fel -p spiflash-write 0x64000 linux/arch/arm/boot/zImage
# squashfs
sudo sunxi-fel -p spiflash-write 0x464000 rootfs_new.img
# jffs2
sudo sunxi-fel -p spiflash-write 0x960000 jffs2.img

推荐阅读:
https://gist.github.com/rikka0w0/f56977f81d1228fc503b00ad7b526aa7
https://gist.github.com/rikka0w0/e04eee5fa623b37866ded805c855f287
https://whycan.cn/t_2179_2.html
https://www.kernel.org/doc/Documentation/filesystems/overlayfs.txt

离线

#2 2019-10-11 16:48:05

晕哥
Administrator
注册时间: 2017-09-06
累计积分: 8,551

Re: 为F1C100S的SPI Flash制作SquashFS+JFFS2+OverlayFS的rootfs来增大可读写空间

感谢楼主分享,前排围观学习!

离线

#3 2019-10-11 18:35:18

msr06rr
会员
所在地: 苏州
注册时间: 2018-01-11
累计积分: 149

Re: 为F1C100S的SPI Flash制作SquashFS+JFFS2+OverlayFS的rootfs来增大可读写空间

这个很干货

离线

#4 2019-10-11 18:52:56

jiangming1399
会员
注册时间: 2018-06-14
累计积分: 63

Re: 为F1C100S的SPI Flash制作SquashFS+JFFS2+OverlayFS的rootfs来增大可读写空间

是rikka!

之前卡在了preinit的脚本的编写上,感谢分享

离线

#5 2019-10-11 19:01:35

pythinker
会员
注册时间: 2019-02-12
累计积分: 36

Re: 为F1C100S的SPI Flash制作SquashFS+JFFS2+OverlayFS的rootfs来增大可读写空间

干货, 打卡学习

离线

#6 2019-10-11 23:05:50

zzm24
会员
注册时间: 2018-05-07
累计积分: 16

Re: 为F1C100S的SPI Flash制作SquashFS+JFFS2+OverlayFS的rootfs来增大可读写空间

打卡学习

离线

#7 2019-10-22 11:23:22

pans203
会员
注册时间: 2019-09-19
累计积分: 1

Re: 为F1C100S的SPI Flash制作SquashFS+JFFS2+OverlayFS的rootfs来增大可读写空间

请问下
做overlayfs的时候加载的时候提示

[    1.532950] random: crng init done
[    1.968507] overlayfs: upper fs does not support tmpfile.
[    1.974024] overlayfs: upper fs does not support xattr, falling back to index=off and metacopy=off.
Starting syslogd: OK
Starting klogd: OK
Running sysctl: OK
read-only file system detected...done
Starting nginx...
Starting redis: OK
ssh-keygen: generating new host keys: RSA Could not save your public key in /etc/ssh/ssh_host_rsa_key.WUUwzuCq4Z: Read-only file system
ssh-keygen: generating new host keys: DSA Could not save your public key in /etc/ssh/ssh_host_dsa_key.gzfYBUwEuO: Read-only file system
ssh-keygen: generating new host keys: ECDSA Could not save your public key in /etc/ssh/ssh_host_ecdsa_key.NhHCDssYbw: Read-only file system
ssh-keygen: generating new host keys: ED25519 Could not save your public key in /etc/ssh/ssh_host_ed25519_key.3gaphbfyLB: Read-only file system
Starting sshd: Unable to load host key: /overlay/ssh/ssh_host_rsa_key
Unable to load host key: /overlay/ssh/ssh_host_ecdsa_key
Unable to load host key: /overlay/ssh/ssh_host_ed25519_key
sshd: no hostkeys available -- exiting.
OK

mount指令我加到/etc/inittab中了

# Startup the system
::sysinit:/bin/mount -t proc proc /proc
::sysinit:/bin/mount -o remount,rw /
::sysinit:/bin/mkdir -p /dev/pts /dev/shm
::sysinit:/bin/mount -a
::sysinit:/sbin/swapon -a
null::sysinit:/bin/ln -sf /proc/self/fd /dev/fd
null::sysinit:/bin/ln -sf /proc/self/fd/0 /dev/stdin
null::sysinit:/bin/ln -sf /proc/self/fd/1 /dev/stdout
null::sysinit:/bin/ln -sf /proc/self/fd/2 /dev/stderr
::sysinit:/bin/hostname -F /etc/hostname

::sysinit:mount -n -t jffs2 /dev/mtdblock4  /overlay
::sysinit:mount -n -t overlay overlayfs:/overlay -o lowerdir=/,upperdir=/overlay/upperdir,workdir=/overlay/workdir /merged/
#::sysinit:pivot_root /merged /merged/rom


# now run any rc scripts
::sysinit:/etc/init.d/rcS

ssh报错readonly问下有什么解决方法么

离线

#8 2019-11-18 17:20:28

qianhao
会员
注册时间: 2017-12-14
累计积分: 124

Re: 为F1C100S的SPI Flash制作SquashFS+JFFS2+OverlayFS的rootfs来增大可读写空间

干货 需要收藏

离线

#9 2019-11-19 08:13:51

qter
会员
注册时间: 2017-09-14
累计积分: 25

Re: 为F1C100S的SPI Flash制作SquashFS+JFFS2+OverlayFS的rootfs来增大可读写空间

好贴, 赶脚相见恨晚。

离线

页脚