为V831制作dd镜像及扩容脚本的记录

需求

  1. 制作一个全平台通用的烧录镜像

  2. 用户可自行调整root空间大小

  3. 存在一个分区,可以全平台读写

解压镜像

tina系统一键打包后为Phoenix img, 不是常规的分区镜像,因此需要PhoenixCard解压镜像到sd卡中。

完成后分区情况如下

Device      Start    End Sectors   Size Type
/dev/sdb1   49152  49663     512   256K Microsoft basic data
/dev/sdb2   49664  61951   12288     6M Microsoft basic data
/dev/sdb3   61952 225791  163840    80M Microsoft basic data
/dev/sdb4  225792 553471  327680   160M Microsoft basic data
/dev/sdb5  553472 980991  427520 208.8M Microsoft basic data

最后一个是phoenix烧录后自动拓展的UDISK分区,不管它。

由于gpt分区表存在于头部和尾部,所以gpt分区的克隆实际上十分麻烦,先慢慢尝试下吧,也许最后可以修复。

这里实际上需要的数据只有sda1到sda4,所以需要计算下复制的数据大小。

计算数据大小

可以看到sectors大小为bytes

Disk /dev/sdb: 480 MiB, 503316480 bytes, 983040 sectors
Disk model: SD Card Reader  
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes

扇区大小和磁盘大小换算:983040*512(Bytes)=503316480(Bytes)/1024(KiB)/1024(MiB)=480(MiB)

所以复制到sdb4末尾,所需的字节数为

553472*512=283377664bytes。并且还需要1024k大小储存gpt分区信息。

bs=bytes:同时设置读入/输出的块大小为bytes个字节。

count=blocks:仅拷贝blocks个块,块大小等于ibs指定的字节数。

块和字节数后可能带有以下的一个或多个后缀:

c =1, w =2, b =512, kB =1000, K =1024, MB =1000x1000, M =1024x1024, xM =M

GB =1000x1000x1000, G =1024x1024x1024, and so on for T, P, E, Z, Y.

如果将bs设置为1M,则count=283377664/1024/1024+1024K/1M=271.25,显然是不允许小数的,但是sdb5扇区上的数据是我们不需要的,多出一些扇区无关紧要,最后设置count为272。

克隆dd镜像

dd if=/dev/sdb bs=1M count=272 of=./image.img status=progress

克隆完毕后查看分区情况

fdisk -l image.img

Disk image.img: 272 MiB, 285212672 bytes, 557056 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x00000000

Device     Boot Start        End    Sectors Size Id Type
image.img1          1 4294967295 4294967295   2T ee GPT

可以看到分区表已经损坏,需要重建分区表。

修复分区

新建gpt分区表

parted /dev/sdb
mklabel gpt
yes
quit

恢复分区

/home/lithromantic/Desktop]$ fdisk image.img 

Command (m for help): n
Partition number (1-128, default 1): 
First sector (34-557022, default 2048): 49152
Last sector, +/-sectors or +/-size{K,M,G,T,P} (49152-557022, default 557022): 49663

Created a new partition 1 of type 'Linux filesystem' and of size 256 KiB.

Command (m for help): n
Partition number (2-128, default 2): 
First sector (34-557022, default 51200): 49664
Last sector, +/-sectors or +/-size{K,M,G,T,P} (49664-557022, default 557022): 61951

Created a new partition 2 of type 'Linux filesystem' and of size 6 MiB.

Command (m for help): n
Partition number (3-128, default 3): 
First sector (34-557022, default 63488): 61952
Last sector, +/-sectors or +/-size{K,M,G,T,P} (61952-557022, default 557022): 225791

Created a new partition 3 of type 'Linux filesystem' and of size 80 MiB.

Command (m for help): n
Partition number (4-128, default 4): 
First sector (34-557022, default 227328): 225792
Last sector, +/-sectors or +/-size{K,M,G,T,P} (225792-557022, default 557022): 553471

Created a new partition 4 of type 'Linux filesystem' and of size 160 MiB.
Partition #4 contains a ext4 signature.

Do you want to remove the signature? [Y]es/[N]o: n

Command (m for help): p

Disk image.img: 272 MiB, 285212672 bytes, 557056 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: gpt
Disk identifier: 6024F1DE-D798-471C-AC53-16FD356C178C

Device      Start    End Sectors  Size Type
image.img1  49152  49663     512  256K Linux filesystem
image.img2  49664  61951   12288    6M Linux filesystem
image.img3  61952 225791  163840   80M Linux filesystem
image.img4 225792 553471  327680  160M Linux filesystem

Command (m for help): w
The partition table has been altered.
Syncing disks.

然后挂载到loop下

losetup -P /dev/loop404 image.img

挂载分区查看信息是否一致

mkdir /tmp/test && mount /dev/loop404p4 /tmp/test

可见文件系统都在

[/home/lithromantic/Desktop]$ cd /tmp/test              
[/tmp/test]$ ls                               
bin  dev  etc  home  lib  lost+found  mnt  overlay  proc  pseudo_init  rdinit  rom  root  run  sbin  sys  tmp  usr  var

卸载分区,卸载镜像

umount /tmp/test && losetup -D /dev/loop404

现在我们有了一个可用的dd镜像,在进行其他步骤前,需要先测试下镜像是否可用。

结果令人失望,V831没有任何反应。

猜测是重建gpt分区时破坏了启动文件。

为了防止设备不兼容gpt分区,通常gpt分区表会内嵌一个mbr分区表,尝试重构分区。

重构mbr分区

重新dd镜像,这次直接使用fdisk编辑分区

/home/lithromantic/Desktop]$ fdisk image.img 

Welcome to fdisk (util-linux 2.36.1).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.


Command (m for help): p
Disk image.img: 272 MiB, 285212672 bytes, 557056 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: gpt
Disk identifier: 6024F1DE-D798-471C-AC53-16FD356C178C

Command (m for help): n
Partition number (1-128, default 1): 
First sector (34-557022, default 2048): 49152
Last sector, +/-sectors or +/-size{K,M,G,T,P} (49152-557022, default 557022): 49663

Created a new partition 1 of type 'Linux filesystem' and of size 256 KiB.

Command (m for help): n
Partition number (2-128, default 2): 
First sector (34-557022, default 51200): 49664
Last sector, +/-sectors or +/-size{K,M,G,T,P} (49664-557022, default 557022): 61951

Created a new partition 2 of type 'Linux filesystem' and of size 6 MiB.

Command (m for help): n
Partition number (3-128, default 3): 
First sector (34-557022, default 63488): 61952
Last sector, +/-sectors or +/-size{K,M,G,T,P} (61952-557022, default 557022): 225791

Created a new partition 3 of type 'Linux filesystem' and of size 80 MiB.

Command (m for help): n
Partition number (4-128, default 4): 
First sector (34-557022, default 227328): 225792
Last sector, +/-sectors or +/-size{K,M,G,T,P} (225792-557022, default 557022): 553471

Created a new partition 4 of type 'Linux filesystem' and of size 160 MiB.
Partition #4 contains a ext4 signature.

Do you want to remove the signature? [Y]es/[N]o: n

Command (m for help): w
The partition table has been altered.
Syncing disks.

上电,正常启动

   __  ___     _        __   _                 /  |/  /__ _(_)_ __  / /  (_)__  __ ____ __ / /|_/ / _ `/ /\ \ / / /__/ / _ \/ // /\ \ //_/  /_/\_,_/_//_\_\ /____/_/_//_/\_,_//_\_\  ----------------------------------------------root@sipeed:/# 

查看分区表:

root@sipeed:/# fdisk -l

Disk /dev/mmcblk0: 29.4 GiB, 31609323520 bytes, 61736960 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x4139124f

Device         Boot  Start    End Sectors  Size Id Type
/dev/mmcblk0p1       49152  49663     512  256K 83 Linux
/dev/mmcblk0p2       49664  61951   12288    6M 83 Linux
/dev/mmcblk0p3       61952 225791  163840   80M 83 Linux
/dev/mmcblk0p4      225792 553471  327680  160M 83 Linux

可见分区为dos能正常引导。

但是对该分区表修改没什么用,实际上还是没法修改任何信息。

重新dd镜像

这次尝试克隆完整镜像。dd if=/dev/sdb of=./img.img status=progress

创建一个大小为1G的镜像

dd if=/dev/zero bs=4M count=256 of=test.img status=progress

挂载,并克隆v831镜像

losetup -P /dev/loop404 test.img
dd if=img.img of=/dev/loop404 status=progress

检查镜像,会有错误提示

fdisk -l /dev/loop404GPT PMBR size mismatch (983039 != 2097151) will be corrected by write.The backup GPT table is not on the end of the device.Disk /dev/loop404: 1 GiB, 1073741824 bytes, 2097152 sectors

不管,烧录到镜像中查看结果

正常启动,但是会报GPT错误,也不管

root@sipeed:/# fdisk -lGPT PMBR size mismatch (983039 != 61736959) will be corrected by w(rite).Disk /dev/mmcblk0: 29.4 GiB, 31609323520 bytes, 61736960 sectorsUnits: sectors of 1 * 512 = 512 bytesSector size (logical/physical): 512 bytes / 512 bytesI/O size (minimum/optimal): 512 bytes / 512 bytesDisklabel type: gptDisk identifier: AB6F3888-569A-4926-9668-80941DCB40BC

新建分区后,磁盘恢复正常

root@sipeed:/# fdisk -l

Disk /dev/mmcblk0: 29.4 GiB, 31609323520 bytes, 61736960 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: gpt
Disk identifier: AB6F3888-569A-4926-9668-80941DCB40BC

Device          Start      End  Sectors  Size Type
/dev/mmcblk0p1  49152    49663      512  256K Microsoft basic data
/dev/mmcblk0p2  49664    61951    12288    6M Microsoft basic data
/dev/mmcblk0p3  61952   225791   163840   80M Microsoft basic data
/dev/mmcblk0p4 225792   553471   327680  160M Microsoft basic data
/dev/mmcblk0p5 553472 61736956 61183485 29.2G Linux filesystem

尝试制作更小的镜像

497 /home/lithromantic  » `dd if=img.img bs=1M count=272 of=/dev/loop404 status=progress`

498 /home/lithromantic  » fdisk -l /dev/loop404
GPT PMBR size mismatch (983039 != 573439) will be corrected by write.
Disk /dev/loop404: 280 MiB, 293601280 bytes, 573440 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x00000000

果然,分区表错误,并且由于丢失了磁盘末尾的数据,分区也无法查看

Device         Boot Start    End Sectors  Size Id Type/dev/loop404p1          1 573439  573439  280M ee GPT

既然知道数据存在于最后1M字节中,那也dd过来会如何?

515 /home/lithromantic  » dd if=img.img skip=980992 of=/dev/loop404  seek=571392  status=progress

516 /home/lithromantic  » fdisk /dev/loop404

Welcome to fdisk (util-linux 2.36.1).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.


Command (m for help): p
Disk /dev/loop404: 280 MiB, 293601280 bytes, 573440 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x00000000

没任何用。

看来gpt分区情况下,小的可以往大的克隆,大的不能往小的克隆。所以制作镜像时,切记使用小磁盘制作。

拓展root分区大小

文件系统存在于/dev/mmcblk0p4中,需要调整大小就需要修改此分区大小。

在此之前需要先删除/dev/mmcblk0p4和以后的分区

假设需要增加到1G,则end扇区为2048*1024+225792=2322944

或者直接+1G

root@sipeed:~# fdisk /dev/mmcblk0

Welcome to fdisk (util-linux 2.25.2).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.


Command (m for help): d
Partition number (1-4, default 4): 

Partition 4 has been deleted.

Command (m for help): n
Partition number (4-8, default 4): 
First sector (225792-61736956, default 227328): 225792
Last sector, +sectors or +size{K,M,G,T,P} (225792-61736956, default 61736956): +1G

Created a new partition 4 of type 'Linux filesystem' and of size 1023.8 MiB.

Command (m for help): W
W: unknown command

Command (m for help): w

The partition table has been altered.
Calling ioctl() to re-read partition table.

重启后发现进不去系统了。

在电脑上查看,文件系统没问题。

重新烧录一张卡,然后用电脑扩容,启动

root@sipeed:/# df -h
Filesystem                Size      Used Available Use% Mounted on
/dev/root              1014.0M    109.4M    888.7M  11% /
tmpfs                    29.4M     12.0K     29.4M   0% /tmp
none                     29.3M         0     29.3M   0% /dev
/dev/root              1014.0M    109.4M    888.7M  11% /root

基本没问题。

对比后发现fdisk删除分区时把Name也删掉了。

试试加上Name

root@sipeed:/# fdisk /dev/mmcblk0

Command (m for help): x

Expert command (m for help): n
Partition number (1-4, default 4): 

New name: rootfs

Partition name changed from '' to 'rootfs'.

Expert command (m for help): r

Command (m for help): w

The partition table has been altered.
Calling ioctl() to re-read partition table.

重启后,正常启动。

查看分区大小

root@sipeed:/# fdisk -l

Disk /dev/mmcblk0: 29.4 GiB, 31609323520 bytes, 61736960 sectors
Device          Start     End Sectors  Size Type
/dev/mmcblk0p1  49152   49663     512  256K Microsoft basic data
/dev/mmcblk0p2  49664   61951   12288    6M Microsoft basic data
/dev/mmcblk0p3  61952  225791  163840   80M Microsoft basic data
/dev/mmcblk0p4 225792 4419583 4193792    2G Linux filesystem

查看挂载情况

root@sipeed:/# df
Filesystem           1K-blocks      Used Available Use% Mounted on
/dev/root              1038360    111984    909992  11% /
tmpfs                    30100        12     30088   0% /tmp
none                     30028         0     30028   0% /dev
/dev/root              1038360    111984    909992  11% /root

可以看到大小对不上。

resize一下

root@sipeed:/# resize2fs /dev/root
resize2fs 1.42.12 (29-Aug-2014)
Filesystem at /dev/root is mounted on /; on-line resizing required
old_desc_blocks = 1, new_desc_blocks = 1
resize2fs: Read-only file system While checking for on-line resizing support

有问题,失败。

实际上,这里提示Read-only file system是因为之前umount过,分区变成了只读分区,重新挂载下即可。

试试修复下磁盘

root@sipeed:/# e2fsck -f /dev/mmcblk0p4
e2fsck 1.42.12 (29-Aug-2014)
Pass 1: Checking inodes, blocks, and sizes
Inode 7, i_size is 62963712, should be 67174400.  Fix<y>? yes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information

/dev/mmcblk0p4: ***** FILE SYSTEM WAS MODIFIED *****
/dev/mmcblk0p4: ***** REBOOT LINUX *****
/dev/mmcblk0p4: 4005/24064 files (0.0% non-contiguous), 30550/262144 blocks

修复完成,重启测试下。

root@sipeed:/# resize2fs /dev/root
resize2fs 1.42.12 (29-Aug-2014)
Filesystem at /dev/root is mounted on /; on-line resizing required
old_desc_blocks = 1, new_desc_blocks = 1
The filesystem on /dev/root is now 524224 (4k) blocks long.

root@sipeed:/# df -h
Filesystem                Size      Used Available Use% Mounted on
/dev/root                 2.0G    109.4M      1.9G   5% /
tmpfs                    29.4M     12.0K     29.4M   0% /tmp
none                     29.3M         0     29.3M   0% /dev
/dev/root                 2.0G    109.4M      1.9G   5% /root

正常使用了。

警告!扩大root分区后不要直接减小分区,否则会导致块异常而导致无法启动!并且无法修复!

制作全平台通用分区

实际上就是新建一个Fat格式的分区。

新建分区,直接拉满。

root@sipeed:/# fdisk /dev/mmcblk0

Command (m for help): n
Partition number (5-8, default 5): 
First sector (4419584-61736956, default 4419584): 
Last sector, +sectors or +size{K,M,G,T,P} (4419584-61736956, default 61736956): 

Created a new partition 5 of type 'Linux filesystem' and of size 27.3 GiB.

Command (m for help): w
The partition table has been altered.
Calling ioctl() to re-read partition table.

格式化分区

root@sipeed:/# mkfs.vfat /dev/mmcblk0p5
mkfs.vfat: can't open '/dev/mmcblk0p5': No such file or directory

看样子需要重启生效下,reboot。

验证分区

插电脑上,可以看到windows成功读取了一个27.3G大小的U盘(H:),

image-20210830093720388

但是同时会多出一个需要格式化的U盘 (G:),这是我们不想看到的。

插上设备,看看是哪里出了问题。

Device           Start      End  Sectors  Size Type
/dev/mmcblk0p1   49152    49663      512  256K Microsoft basic data
/dev/mmcblk0p2   49664    61951    12288    6M Microsoft basic data
/dev/mmcblk0p3   61952   225791   163840   80M Microsoft basic data
/dev/mmcblk0p4  225792  4419583  4193792    2G Linux filesystem
/dev/mmcblk0p5 4419584 61736956 57317373 27.3G Linux filesystem

很明显,4和5分别是G和H磁盘,唯一不一样的就是文件系统格式,一个是ext4,一个是fat。可以注意到,前三个磁盘并不会被电脑读取,后两个和前两个的type不同,修改下试试。

root@sipeed:/# fdisk /dev/mmcblk0

Welcome to fdisk (util-linux 2.25.2).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.


Command (m for help): t
Partition number (1-5, default 5): 
Partition type (type L to list all types): l

  6 Microsoft basic data           EBD0A0A2-B9E5-4433-87C0-68B6B72699C7

Partition type (type L to list all types): 6

Changed type of partition 'Linux filesystem' to 'Microsoft basic data'.

Command (m for help): w
The partition table has been altered.
Calling ioctl() to re-read partition table.

不能用。

同时注意到新烧录的镜像不会出现此问题,上电脑对比下。

image-20210830100139117

image-20210830100100904

可以注意到修改大小后,rootfs的Flags丢失了,添加回来先。

上电后依然无法使用,原因在于Windows已经给此分区分配盘符,手动删除即可,

但并不是我们所期望的,我们希望用户拿到镜像后什么都不干就能用。

找一张新卡复现下。

发现在使用fdisk只修改了分区/dev/mmcblk0p4后,没问题。

使用fdisk只修改了分区/dev/mmcblk0p5后,没问题。

在修改了GUID后,两者都不在分配盘符。

root@sipeed:/# fdisk /dev/mmcblk0

Welcome to fdisk (util-linux 2.25.2).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.

Expert command (m for help): u
Partition number (1-5, default 5): 4

New UUID (in 8-4-4-4-12 format): A0085546-4166-744A-A353-FCA9272B8E48

Partition UUID changed from 3A22EC04-4B57-4945-A295-773995BDA2B0 to A0085546-4166-744A-A353-FCA9272B8E48.

Expert command (m for help): u
Partition number (1-5, default 5): 5

New UUID (in 8-4-4-4-12 format): A0085546-4166-744A-A353-FCA9272B8E49

Partition UUID changed from 742380B9-389D-4908-91F7-2FA2CB6E7195 to A0085546-4166-744A-A353-FCA9272B8E49.

Expert command (m for help): r

Command (m for help): w

把分区5的UUID修改后,就可以正常读取了。

注意到使用Phoenix card烧录的UDISK也无法读取,尝试修改UUID,发现没用,同时手动分配盘符时,会提示系统找不到指定的文件,应该是多种参数共同作用的结果,以后再探讨。

挂载分区

分区5在电脑上可读后,还需要再Linux下可读。

root@sipeed:/# df -h
Filesystem                Size      Used Available Use% Mounted on
/dev/root                 2.0G    109.4M      1.9G   5% /
tmpfs                    29.4M     12.0K     29.4M   0% /tmp
none                     29.3M         0     29.3M   0% /dev
/dev/root                 2.0G    109.4M      1.9G   5% /root

可以看到,现在磁盘还没挂载。

root@sipeed:/# mount /dev/mmcblk0p5 /mnt
root@sipeed:/# df -h
Filesystem                Size      Used Available Use% Mounted on
/dev/root                 2.0G    109.4M      1.9G   5% /
tmpfs                    29.4M     12.0K     29.4M   0% /tmp
none                     29.3M         0     29.3M   0% /dev
/dev/root                 2.0G    109.4M      1.9G   5% /root
/dev/mmcblk0p5           27.3G     64.0K     27.3G   0% /mnt

挂载后即可使用。

但是手动挂载不是我们想要的,我们期望系统启动后自动挂载。

实际上,在/etc/init.d/rcS中,存在by-name挂载磁盘的代码。

if [ x"$src" == x/dev/by-name/UDISK ]; then             
mount -t vfat "$fs_src" "$fs_mntpt" 2>/dev/null 
if [ "$?" -ne "0" ]; then                       
    mkfs.vfat "$fs_src" > /dev/null         
    mount -t vfat "$fs_src" "$fs_mntpt" 2>/dev/null
fi                                                     

所以我们只需要修改分区5的name即可。

root@sipeed:/# fdisk /dev/mmcblk0

Welcome to fdisk (util-linux 2.25.2).

Command (m for help): x

Expert command (m for help): n
Partition number (1-5, default 5): 

New name: UDISK

Partition name changed from '' to 'UDISK'.

Expert command (m for help): r

Command (m for help): w
The partition table has been altered.
Calling ioctl() to re-read partition table.

重启,成功挂载。

Filesystem                Size      Used Available Use% Mounted on
/dev/root                 2.0G    109.4M      1.9G   5% /
tmpfs                    29.4M     12.0K     29.4M   0% /tmp
none                     29.3M         0     29.3M   0% /dev
/dev/mmcblk0p5           27.3G     64.0K     27.3G   0% /mnt/UDISK
/dev/mmcblk0p5           27.3G     64.0K     27.3G   0% /root

制作脚本

用户可选的参数应该有

Filesystem size 备注
/dev/root 用户指定 在没有/dev/mmcblk0p5的情况下才能调节
/dev/mmcblk0p5 磁盘剩余所有空间

首先要有个选择菜单

#!/bin/sh
menu()
{
echo "choose you want do:
1):UDISK
2):root
"
read -p "defult 1):" task
task=${task:-1}
if [ "$task" = "2" ];then
	read -p "+size{K,M,G,T,P} , such as: +1G
default all size:" size
else
fi
}

引导用户选择UDISK后,就要创建UDISK分区了。

创建分区手动方法如下

root@sipeed:/# fdisk /dev/mmcblk0 #打开fdisk
Command (m for help): n #新建分区
Partition number (5-8, default 5):  #分区5
First sector (4419584-61736956, default 4419584): #默认大小

Last sector, +sectors or +size{K,M,G,T,P} (4419584-61736956, default 61736956):

Command (m for help): x #扩展功能

Expert command (m for help): n #修改名字
Partition number (1-5, default 5): #分区5

New name: UDISK #新名字

Expert command (m for help): r #退出

Command (m for help): w #保存

显然不可能引导用户手动完成这部分,这里可以借助linux管道

echo "n
5


x
n
5
UDISK
r
w

" | fdisk /dev/mmcblk0

显然这样写脚本太不美观了,我们可以使用 -e来转译特殊符号,每个\n即是一个换行符。

echo -e "n\n5\n\n\nx\nn\n5\nUDISK\nr\nw\n" | fdisk /dev/mmcblk0

下一步需要的就是格式化分区为fat,这里牵扯到重启系统。

我们希望重启后脚本自动执行,并且下次重启后脚本不在自动执行。

我们需要先备份一个开机脚本,移除执行权限

cd /etc/init.d
cp rc.final rc.final.bak
chmod -x rc.final.bak

然后rc.final 末尾添加执行我们这个脚本的命令

echo "sh /resize.sh mkfs" >> /etc/init.d/rc.final

其中mkfs是向脚本传递参数,可以通过传入的参数来判断运行情况。

这时候在我们的菜单外面套一层if [ "$1" != "mkfs" ];then fi即可确保下次不执行。

重启后,脚本执行格式化UDISK,并且移除开机自启动。

mkfs_udisk()
{
mkfs.vfat /dev/mmcblk0p5
cd /etc/init.d
rm rc.final
mv rc.final.bak rc.final
chmod +x rc.final
echo "all ok"
}

然后在我们的菜单中添加该分支

elif [ "$1" = "mkfs" ];then
	mkfs_udisk

放入根目录,执行即可。

在内部调试时,我们可能需要更大的根目录分区,这时候就要扩大根目录分区。

在扩容根目录前,要先删除UDISK,并且提示用户,防止文件丢失

detele_udisk()
{
if [ -e /dev/by-name/UDISK  ]; then
	echo "Warning, UDISK already exists, do you want to delete it?"
	read -p "Y(es) or N(o),defult: Y"del_yn
	del_yn=${del_yn:-y}
	if [ $del_yn = "Y" -o $del_yn = "y" ];then
		echo -e "d\n5\nw\n"|fdisk /dev/mmbclk0
	else
		echo "now stop task"
		exit 0
}

然后编写扩容根目录的脚本

resize_root()
{
echo -e "d\n4\nn\n4\n225792\n$size\nx\nn\n4\nrootfs\nu\n4\nA0085546-4166-744A-A353-FCA9272B8E49\nr\nw\n"|fdisk /dev/mmbclk0
cd /etc/init.d
cp rc.final rc.final.bak
chmod -x rc.final.bak
echo "sh /resize.sh resize" >> /etc/init.d/rc.final
reboot
}

然后使扩容空间生效

resize2fs_root()
{
resize2fs /dev/root
cd /etc/init.d
rm rc.final
mv rc.final.bak rc.final
chmod +x rc.local
echo "change root size ok"
}

添加函数进菜单选项

elif [ "$select" = "resize" ];then
	resize2fs_root

完整脚本如下:

#!/bin/sh
select=$1                                                                                                  
select=${select:-begin}

detele_udisk()
{
if [ -e /dev/by-name/UDISK  ]; then
	echo "Warning, UDISK already exists, do you want to delete it?"
	read -p "Y(es) or N(o),defult: Y" del_yn
	del_yn=${del_yn:-y}
	if [ $del_yn = "Y" -o $del_yn = "y" ];then
		echo -e "d\n5\nw\n"|fdisk /dev/mmcblk0
	else
		echo "now stop task"
		exit 0
	fi
fi
}

create_UDISK()
{
echo -e "n\n5\n\n\nx\nn\n5\nUDISK\nr\nw\n" | fdisk /dev/mmcblk0
cd /etc/init.d
cp rc.final rc.final.bak
chmod -x rc.final.bak
echo "sh /resize.sh mkfs" >> /etc/init.d/rc.final
reboot
}

mkfs_udisk()
{
mkfs.vfat /dev/mmcblk0p5
cd /etc/init.d
rm rc.final
mv rc.final.bak rc.final
chmod +x rc.final
echo "all ok"
}

resize_root()
{
echo -e "d\n4\nn\n4\n225792\n$size\nx\nn\n4\nrootfs\nu\n4\nA0085546-4166-744A-A353-FCA9272B8E49\nr\nw\n"|fdisk /dev/mmcblk0
cd /etc/init.d
cp rc.final rc.final.bak
chmod -x rc.final.bak
echo "sh /resize.sh resize" >> /etc/init.d/rc.final
reboot
}
resize2fs_root()
{
resize2fs /dev/root
cd /etc/init.d
rm rc.final
mv rc.final.bak rc.final
chmod +x rc.final
echo "change root size ok"
}
menu()
{
echo "your input $select"
if [ "$select" = "begin" ];then
	echo "choose you want do:
	1):UDISK
	2):root
	If you want to view your disks on different platforms,you should do 1
	IF you just want expand your root filesystem,do 2
	maybe you all want,then do 2 before do 1
	You will can't change the size of your root filesystem after you get UDISK
	"
	read -p "defult 1):" task
	task=${task:-1}
	echo "You choose $task;"
	if [ "$task" = "2" ];then
		read -p "+size{K,M,G,T,P} , such as: +1G
	default all size:" size
		detele_udisk
		resize_root
	else
		create_UDISK
	fi
elif [ "$select" = "mkfs" ];then
	mkfs_udisk
elif [ "$select" = "resize" ];then
	resize2fs_root
fi
}

menu

后续补充

在后续使用时发现,完全扩展root分区后,resize会报

resize2fs: Operation not permitted While trying to add group #3

这是由于文件系统中的journal 限制了块数量

此时需要重新创建journal

umount /dev/sdb4
tune2fs -O ^has_journal /dev/sdb4
tune2fs -j /dev/sdb4
e2fsck -fy /dev/sdb4
resize /dev/sdb4

此时插上板子后root分区才会正常,并且可以继续增加大小。

但是需要注意的是,以上操作是在电脑端进行的,在831上执行会出问题,暂且不谈。

尝试在dd镜像时就修改特性。

losetup -P /dev/loop404 test.img 
Desktop losetup -P /dev/loop404 test.img             
 Desktop fdisk /dev/loop404                   

Welcome to fdisk (util-linux 2.36.1).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.

Command (m for help): d
Partition number (1-5, default 5): 

Partition 5 has been deleted.

Command (m for help): w
The partition table has been altered.
Calling ioctl() to re-read partition table.
Syncing disks.

 Desktop e2fsck -fyC 0 /dev/loop404p4
e2fsck 1.45.7 (28-Jan-2021)
/dev/loop404p4: recovering journal
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure                                           
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
Padding at end of inode bitmap is not set. Fix? yes                            
/dev/loop404p4: ***** FILE SYSTEM WAS MODIFIED *****
/dev/loop404p4: 4009/6016 files (0.0% non-contiguous), 29384/51200 blocks
 Desktop resize2fs -p /dev/loop404p4 
resize2fs 1.45.7 (28-Jan-2021)
The filesystem is already 51200 (4k) blocks long.  Nothing to do!

失败

考虑给root扩容下试试

 Desktop losetup -P /dev/loop404 test.img             
 Desktop fdisk /dev/loop404         

Welcome to fdisk (util-linux 2.36.1).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.


Command (m for help): d
Partition number (1-4, default 4): 

Partition 4 has been deleted.

Command (m for help): n
Partition number (4-8, default 4): 
First sector (225792-983036, default 227328): 225792
Last sector, +/-sectors or +/-size{K,M,G,T,P} (225792-983036, default 983036): +300M

Created a new partition 4 of type 'Linux filesystem' and of size 299.8 MiB.
Partition #4 contains a ext4 signature.

Do you want to remove the signature? [Y]es/[N]o: y

The signature will be removed by a write command.

Command (m for help): x

Expert command (m for help): n
Partition number (1-4, default 4): 

New name: rootfs

Partition name changed from '' to 'rootfs'.

Expert command (m for help): r

Command (m for help): w

The partition table has been altered.
Calling ioctl() to re-read partition table.
Syncing disks.

 Desktop e2fsck -fyC 0 /dev/loop404p4    
e2fsck 1.45.7 (28-Jan-2021)
ext2fs_open2: Bad magic number in super-block
e2fsck: Superblock invalid, trying backup blocks...
Backing up journal inode block information.

Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure                                           
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
Free blocks count wrong (0, counted=21816).
Fix? yes

Free inodes count wrong (0, counted=2007).                                     
Fix? yes


/dev/loop404p4: ***** FILE SYSTEM WAS MODIFIED *****
/dev/loop404p4: 4009/6016 files (0.0% non-contiguous), 29384/51200 blocks
 Desktop resize2fs -p /dev/loop404p4     
resize2fs 1.45.7 (28-Jan-2021)
Resizing the filesystem on /dev/loop404p4 to 76736 (4k) blocks.
The filesystem on /dev/loop404p4 is now 76736 (4k) blocks long.

 Desktop losetup -d /dev/loop404  

可以使用了

需要注意的是,Last sector, +/-sectors or +/-size{K,M,G,T,P} (225792-983036, default 983036): +300M这里,如果使用default,会导致windows下烧录镜像异常。

制作dd脚本

由于牵扯到电脑端预处理,所以写个脚本批处理下。

脚本期望功能如下

输入参数 输出 备注
源镜像位置 压缩包镜像 可以指定任意位置
输出镜像位置 烧录信息 可以指定任意名称

创建接口,存储输入参数,同时提醒用户检查路径是否正确

#!/bin/sh
input_addr=$1
output_addr=$2
name=$3
input_addr=${input_addr:-/dev/sdb}
output_addr=${output_addr:-./}
name=${name:-sipeed.img}
read -p "Please confirm the path and image size,must be 512MiB! 
Y(es) or other,defult<n>" sure_path
if [ "$sure_path" != "y" -a "$sure_path" != "Y" ];then
	echo "exit"
	exit 0
fi

然后dd镜像,并挂载到loop设备中修改并压缩

sudo dd if=$input_addr status=progress of=/tmp/$name &&\
sudo losetup -d /dev/loop404 
sudo losetup -P /dev/loop404 /tmp/$name &&\
sleep 2 
echo -e "\n\nd\n5\nd\n4\nn\n4\n225792\n+300M\nx\nn\n4\nrootfs\nr\nw\n"|sudo fdisk /dev/loop404 &&\
sudo e2fsck -fyC 0 /dev/loop404p4 &&\
sleep 2
sudo resize2fs -p /dev/loop404p4
sudo losetup -d /dev/loop404 

addr=$(pwd) &&\
cd /tmp &&\
echo "Compressing the mirror takes some time, and you can use <progress -m> at other terminals to see progress" &&\
sudo xz -z -k $name --threads=0 &&\
cd $addr &&\
sudo mv /tmp/$name.xz $output_addr &&\
sudo rm /tmp/$name

实际上,fdisk无法以脚本方式删除signature,所以分区部分还需要手动执行。

Do you want to remove the signature? [Y]es/[N]o: y
Partition #4 contains a ext4 signature.

简化脚本,只保留修改分区大小部分。

#!/bin/sh
input_addr=$1
output_addr=$2
name=$3
input_addr=${input_addr:-dd.img}
output_addr=${output_addr:-./}
name=${name:-sipeed.img}
echo "input_addr=$input_addr,output_addr=$output_addr, name is $name

you can run xx.sh <intputaddr> <outputaddr> <name> to specify them or use defult
Such as 
dd.sh ./dd.img /root test.img 
or
dd.sh ./dd.img"
sudo cp $input_addr /tmp/$name
sudo losetup -d /dev/loop404 
sudo losetup -P /dev/loop404 /tmp/$name &&\
sudo e2fsck -fyC 0 /dev/loop404p4 &&\
sleep 2
sudo resize2fs -p /dev/loop404p4
echo -e "\nx\nn\n4\nrootfs\nu\n4\nA0085546-4166-744A-A353-FCA9272B8E48\nr\nw\n"|sudo fdisk /dev/loop404p4
sudo losetup -d /dev/loop404 

addr=$(pwd) &&\
cd /tmp &&\
echo "Compressing the mirror takes some time, and you can use <progress -m> at other terminals to see progress" &&\
sudo xz -z -k $name --threads=0 &&\
cd $addr &&\
sudo mv /tmp/$name.xz $output_addr &&\
sudo rm /tmp/$name
echo "all ok,use xz -dc $name.xz |sudo dd of=/dev/sdb bs=1M status=progress oflag=direct to create a tf Startup Disk"

同时人工需要执行的命令如下:

~sudo dd if=/dev/sdb of=dd.img status=progress
~ fdisk dd.img    

Welcome to fdisk (util-linux 2.36.1).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.

Command (m for help): d
Partition number (1-5, default 5): 

Partition 5 has been deleted.

Command (m for help): d
Partition number (1-4, default 4): 4

Partition 4 has been deleted.

Command (m for help): n
Partition number (4-8, default 4): 
First sector (225792-983036, default 227328): 225792
Last sector, +/-sectors or +/-size{K,M,G,T,P} (225792-983036, default 983036): +300M

Created a new partition 4 of type 'Linux filesystem' and of size 299.8 MiB.
Partition #4 contains a ext4 signature.

Do you want to remove the signature? [Y]es/[N]o: y

The signature will be removed by a write command.

Command (m for help): w
The partition table has been altered.
Syncing disks.

解决。

posted @ 2021-08-30 18:49  USTHzhanglu  阅读(569)  评论(0编辑  收藏  举报