前言
这篇写的较细,使用dd擦除emmc本来就是比较危险的事情,所以一定要细致。哪里没看明白的,赶紧留言问我,可不能存有侥幸心理。
思路大概就是:
1 先从emmc把数据读出来,放一个镜像文件里,使用hexdump -C查看该文件,主要是验证环境变量的位置对不对。最重要是还是一点一点熟悉命令。
2 先写镜像文件,验证一下能不能写成功
3 前面都验证好了,再写物理磁盘。
4 最后升级uboot。
一 使用fdisk -l查看磁盘状态
首先,找到磁盘挂载状态:已知,uboot位于第二sectors开始,fdisk位于第0x600开始,占用0x10个sectors,且每个sector是512字节,即占用8192字节,执行fdisk l
root@hehe:/dev# fdisk -l
Disk /dev/mmcblk1: 7.3 GiB, 7818182656 bytes, 15269888 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: 0x6a30ec95
Device Boot Start End Sectors Size Id Type
/dev/mmcblk1p1 20480 282623 262144 128M c W95 FAT32 (LBA)
/dev/mmcblk1p2 282624 15269887 14987264 7.2G 83 Linux
Disk /dev/mmcblk1boot1: 4 MiB, 4194304 bytes, 8192 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
Disk /dev/mmcblk1boot0: 4 MiB, 4194304 bytes, 8192 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
二 使用dd命令从1536扇区读数据
从命令结果可知,前10M空间是没有没挂载到系统中的。使用dd命令读取/dev/mmcblk1的前10M的空间,并输出到boot.img文件。
root@hehe:~# dd if=/dev/mmcblk1 of=uboot.img bs=512 count=20480
20480+0 records in
20480+0 records out
10485760 bytes (10 MB, 10 MiB) copied, 0.762808 s, 13.7 MB/s
root@hehe:~# ls -lsh boot.img
11M -rw-r--r-- 1 root root 10M Oct 15 17:30 boot.img
root@hehe:~#
使用hexdump查看uboot.img0x600 X 512地址,大小为8192字节的数据。
0x600X512 = 1536 X 512 =
hexdump -C -s 786432 -n 8192,效果如下:读到环境变量头了。
root@hehe:~# hexdump -C uboot.img -s 786432 -n 8192
000c0000 e5 9d 42 8b 55 55 49 44 5f 49 44 30 3d 35 64 34 |..B.UUID_ID0=5d4|
000c0010 38 30 30 63 34 00 55 55 49 44 5f 49 44 31 3d 32 |800c4.UUID_ID1=2|
000c0020 63 30 61 62 31 64 37 00 62 61 75 64 72 61 74 65 |c0ab1d7.baudrate|
000c0030 3d 31 31 35 32 30 30 00 62 6f 61 72 64 5f 6e 61 |=115200.board_na|
000c0040 6d 65 3d 45 56 4b 00 62 6f 61 72 64 5f 72 65 76 |me=EVK.board_rev|
##省略了很多很多
研究发现,可以直接使用dd的参数skip,跳过n个块来读,这样可以精准的读到8192字节的数据:
skip=N skip N ibs-sized blocks at start of input
dd skip=1536 if=/dev/mmcblk1 of=env.img bs=512 count=16
root@hehe:~# dd skip=1536 if=/dev/mmcblk1 of=env.img bs=512 count=16
16+0 records in
16+0 records out
8192 bytes (8.2 kB, 8.0 KiB) copied, 0.00125733 s, 6.5 MB/s
root@hehe:~#
使用hexdump -C查看新的env.img文件
root@host:/# hexdump -C env.img
00000000 d3 57 bd dc 55 55 49 44 5f 49 44 30 3d 35 64 34 |.W..UUID_ID0=5d4|
00000010 36 38 66 33 33 00 55 55 49 44 5f 49 44 31 3d 34 |68f33.UUID_ID1=4|
00000020 35 32 66 39 31 64 37 00 62 61 75 64 72 61 74 65 |52f91d7.baudrate|
00000030 3d 31 31 35 32 30 30 00 62 6f 6f 74 5f 66 64 74 |=115200.boot_fdt|
三 擦除读回来的uboot.img1536扇区开始的8192字节数据
下面就是擦除这块数据了,把他们全写成0吧;
这里又用到dd的另一参数,跳过N块的参数
seek=N Skip N output blocks
先尝试制作一个8192字节的zero.img镜像文件。
dd if=/dev/zero of=zero.img bs=512 count=16,执行效果如下所示:
root@host:/# dd if=/dev/zero \of=zero.img bs=512 count=16
16+0 records in
16+0 records out
root@host:/# ls -lsh zero.img
8 -rw-rw-rw- 1 root root 8.0K Jan 1 00:20 zero.img
root@host:/#
使用hexdump -C测试该文件:
root@host:/# hexdump -C zero.img
00000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00002000
root@host:/#
注意
我原来使用/dev/null作为0的输入源文件,结果显示dd: can't open '/dev/null of=zero.img': No such file or directory,然后就换成了/dev/zero作为输入源。
然后再将zero.img文件的内容写入到uboot.img的0x600(1536)块的地方:写16个块,就是16X512=8192字节。
执行dd if=zero.img seek=1536 of=uboot.img bs=512 count=16
root@host:/# dd if=zero.img seek=786432 of=uboot.img bs=512 count=16
16+0 records in
16+0 records out
root@host:/#
hexdump -C uboot.img -s 786432 -n 8192 验证是否写成功。
直接用/dev/zero作为输入源:
执行dd if=/dev/zero of=uboot.img seek=1536 bs=512 count=16
root@host:/# dd if=/dev/zero of=uboot.img seek=1536 bs=512 count=16
16+0 records in
16+0 records out
root@host:/#
执行hexdump -C uboot.img -s 786432 -n 8192:
root@host:/# hexdump -C uboot.img -s 786432 -n 8192
000c0000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
000c2000
root@host:/#
四 使用dd命令正式擦除指定扇区的数据
经过前面小心翼翼的试探,终于开始正式擦emmc了,这个时候,还是要保证所操作的设备,即便是擦坏了,也有办法能恢复,否则的暂时别试,先看我来一步一步怎么踩坑的。
首先,仔细填写命令,一定不能出错,这些参数都是用来在我自己的板子上测试的,如果是自己的板子,一定要搞清楚,这么参数啥意思
dd if=/dev/zero of=/dev/mmcblk1 seek=1536 bs=512 count=16
/dev/zero :0输入源
/dev/mmcblk1:要擦除的设备文件,我这里就是emmc
seek=1536 :跳过的bs数量
bs=512:块的大小
count=16 :一共要擦除16个bs,就是16Xbs = 16X512 = 8192字节。
root@host:/# dd if=/dev/zero of=/dev/mmcblk1 seek=1536 bs=512 count=16
16+0 records in
16+0 records out
root@host:/#
使用hexdump -C 看看,完整命令是:
hexdump -C /dev/mmcblk1 -s 786432 -n 8192,执行效果:
root@host:/# hexdump -C /dev/mmcblk1 -s 786432 -n 8192
000c0000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
000c2000
root@host:/#
重启,真的成功了。
五 使用dd升级uboot
先查看当前uboot的时间
查看升级之前uboot的编译时间:
准备升级文件 u-boot.imx
升级uboot,升级文件是u-boot.imx,不是u-boot.bin。如下所示,该文件大小是318464字节,换算成512字节的块就是318464/512 = 622块,使用科学计算器计算,如果计算得到的不是整数,说明文件错误,就不要升级了,先检查文件的来源。
root@hehe:~# ls -ls u-boot.imx
316 -rw-r--r-- 1 root root 318464 Oct 15 14:45 u-boot.imx
root@hehe:~#
编辑升级命令
dd if=/u-boot.imx of=/dev/mmcblk1 seek=2 bs=512 count=622
大部分前面都说过了,这里seek=2是为什么?
我的板子的u-boot是从第二的扇区开始存的,所以这里要偏移2个扇区,不是2个字节。
开始升级
root@hehe:~# dd if=/u-boot.imx of=/dev/mmcblk1 seek=2 bs=512 count=622
622+0 records in
622+0 records out
318464 bytes (318 kB, 311 KiB) copied, 0.008746 s, 36.4 MB/s
root@hehe:~#
重启,如果能正常启动,基本就是成功了。
重启后查看最新的u-boot时间:Dec 08 2022,2022年12月8号。没错,升级成功了。
小结
总结一下,两条命令,根据实际情况修改对应的参数,例如uboot的大小等等。
擦除使用
dd if=/dev/zero of=/dev/mmcblk1 seek=1536 bs=512 count=16
升级使用
dd if=/u-boot.imx of=/dev/mmcblk1 seek=2 bs=512 count=622