为什么使用 dd 复制 micro SD 卡无法生成可启动卡?

逆向工程 嵌入式
2021-06-17 09:47:02

我有一个基于Olinixino iMX233设计的嵌入式设备它有一个飞思卡尔 iMX233 微处理器,并从一个带插槽的 2GB microSD 卡启动。

我希望更改文件系统,但也要在更改文件系统之前备份文件系统,以免设备变砖。

为此,我获得了一个类似的 2GB micro SD 卡,并在 USB 读卡器中使用dd克隆了当前的 SD 卡

dd if=/dev/sdc of=HeatmiserSDC.img

然后在交换卡后:

dd if=HeatmiserSDC.img of=/dev/sdc

当这张新卡放入设备时,它无法启动。

我现在还尝试了 sg3_utils 实用程序sg_dd,它的运行级别稍低。这产生了一个略有不同的图像文件,但仍然无法启动。

我现在还在 Thinkpad x220 的直接 SD 卡接口 (/dev/mmcblk0) 中使用了 SD 到 micro SD 适配器。这也无法启动。

串行控制台在启动失败时会产生一个错误代码0x8020a007,这在 Google 搜索期间没有多大用处。

我尝试了多张卡,包括一些 4GB 的卡。这似乎不是空间问题 - 有时一个 2GB SD 卡比另一个稍小。该板似乎也在使用 SD 协议而不是 SPI 协议。SPI 协议有时在较新的卡上不是很可靠。

fsutil -l产生以下输出:

Disk /dev/sdc: 1996 MB, 1996488704 bytes
8 heads, 7 sectors/track, 69632 cylinders, total 3899392 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 identifier: 0x0f6c2d46

   Device Boot      Start         End      Blocks   Id  System
/dev/sdc1            2048       32000       14976+  53  OnTrack DM6 Aux3
/dev/sdc2           32001      200000       84000   83  Linux
/dev/sdc3          200001      400000      100000   83  Linux
/dev/sdc4          400001     3899391     1749695+  83  Linux

有什么我在这里想念的吗?一些未作为dd一部分复制的数据

2个回答

经过一番搜索,似乎 iMX233 上的启动过程相当不规范。默认情况下,它会在 SD 卡的最后一个块中查找“引导控制块”(BCB)。

检查原始 SD 卡,使用fdisk -l找到最后一个块

Disk /dev/mmcblk0: 1996 MB, 1996488704 bytes
4 heads, 16 sectors/track, 60928 cylinders, total 3899392 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 identifier: 0x0f6c2d46

        Device Boot      Start         End      Blocks   Id  System
/dev/mmcblk0p1            2048       32000       14976+  53  OnTrack DM6 Aux3
/dev/mmcblk0p2           32001      200000       84000   83  Linux
/dev/mmcblk0p3          200001      400000      100000   83  Linux
/dev/mmcblk0p4          400001     3899391     1749695+  83  Linux

有3899392个扇区。

使用dd检查 SD 卡的最后一个扇区

root@kali:~# dd if=/dev/mmcblk0 bs=512 count=1 skip=3899391 2> /dev/null | hexdump -C
00000000  33 22 11 00 01 00 00 00  04 00 00 00 04 00 00 00  |3"..............|
00000010  04 00 00 00 04 08 00 00  50 00 00 00 50 00 00 00  |........P...P...|
00000020  50 00 00 00 50 00 00 00  ef be ad de 00 00 00 00  |P...P...........|
00000030  01 00 00 00 02 00 00 00  03 00 00 00 04 00 00 00  |................|
00000040  05 00 00 00 06 00 00 00  07 00 00 00 08 00 00 00  |................|
00000050  09 00 00 00 0d 0a 00 00  00 0b 00 00 00 0c 00 00  |................|
00000060  00 0d 00 00 00 0e 00 00  00 0f 00 00 00 10 00 00  |................|
00000070  00 11 00 00 00 12 00 00  00 13 00 00 00 14 00 00  |................|
00000080  00 15 00 00 00 16 00 00  00 17 00 00 00 18 00 00  |................|
00000090  00 19 00 00 00 1a 00 00  00 1b 00 00 00 1c 00 00  |................|
000000a0  00 1d 00 00 00 1e 00 00  00 1f 00 00 00 20 00 00  |............. ..|
000000b0  00 21 00 00 00 22 00 00  00 23 00 00 00 24 00 00  |.!..."...#...$..|
000000c0  00 25 00 00 00 26 00 00  00 27 00 00 00 28 00 00  |.%...&...'...(..|
000000d0  00 29 00 00 00 2a 00 00  00 2b 00 00 00 2c 00 00  |.)...*...+...,..|
000000e0  00 2d 00 00 00 2e 00 00  00 2f 00 00 00 30 00 00  |.-......./...0..|
000000f0  00 31 00 00 00 32 00 00  00 33 00 00 00 34 00 00  |.1...2...3...4..|
00000100  00 35 00 00 00 36 00 00  00 37 00 00 00 38 00 00  |.5...6...7...8..|
00000110  00 39 00 00 00 3a 00 00  00 3b 00 00 00 3c 00 00  |.9...:...;...<..|
00000120  00 3d 00 00 00 3e 00 00  00 3f 00 00 00 40 00 00  |.=...>...?...@..|
00000130  00 41 00 00 00 42 00 00  00 43 00 00 00 44 00 00  |.A...B...C...D..|
00000140  00 45 00 00 00 46 00 00  00 47 00 00 00 48 00 00  |.E...F...G...H..|
00000150  00 49 00 00 00 4a 00 00  00 4b 00 00 00 4c 00 00  |.I...J...K...L..|
00000160  00 4d 00 00 00 4e 00 00  00 4f 00 00 00 50 00 00  |.M...N...O...P..|
00000170  00 51 00 00 00 52 00 00  00 53 00 00 00 54 00 00  |.Q...R...S...T..|
00000180  00 55 00 00 00 56 00 00  00 57 00 00 00 58 00 00  |.U...V...W...X..|
00000190  00 59 00 00 00 5a 00 00  00 5b 00 00 00 5c 00 00  |.Y...Z...[...\..|
000001a0  00 5d 00 00 00 5e 00 00  00 5f 00 00 00 60 00 00  |.]...^..._...`..|
000001b0  00 61 00 00 00 62 00 00  00 63 00 00 00 64 00 00  |.a...b...c...d..|
000001c0  00 65 00 00 00 66 00 00  00 67 00 00 00 68 00 00  |.e...f...g...h..|
000001d0  00 69 00 00 00 6a 00 00  00 6b 00 00 00 6c 00 00  |.i...j...k...l..|
000001e0  00 6d 00 00 00 6e 00 00  00 6f 00 00 00 70 00 00  |.m...n...o...p..|
000001f0  00 71 00 00 00 72 00 00  00 73 00 00 00 74 00 00  |.q...r...s...t..|
00000200

一些飞思卡尔文档中提到了 0x33221100 的神奇数字,尽管我希望看到它具有相反的字节序。

因此,要成功进行克隆,请选择更大容量的 SD 卡以确保不会覆盖任何内容(或者您可以调整分区大小)。

拍摄原卡的图像:

root@kali:~# dd if=/dev/mmcblk0 of=wholeSD.img
3899392+0 records in
3899392+0 records out
1996488704 bytes (2.0 GB) copied, 98.3687 s, 20.3 MB/s

然后拍摄 BCB 最后一个扇区的图像:

root@kali:~# dd if=/dev/mmcblk0 bs=512 count=1 skip=3899391 of=BCB.img
1+0 records in
1+0 records out
512 bytes (512 B) copied, 0.000220203 s, 2.3 MB/s

了解新的 SD 卡有多大:

Disk /dev/mmcblk0: 2002 MB, 2002780160 bytes
4 heads, 16 sectors/track, 61120 cylinders, total 3911680 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 identifier: 0x0f6c2d46

        Device Boot      Start         End      Blocks   Id  System
/dev/mmcblk0p1            2048       32000       14976+  53  OnTrack DM6 Aux3
/dev/mmcblk0p2           32001      200000       84000   83  Linux
/dev/mmcblk0p3          200001      400000      100000   83  Linux
/dev/mmcblk0p4          400001     3899391     1749695+  83  Linux

这个更大,有 3911680 个扇区。

将整个卡片图像移动到新卡片上:

root@kali:~# dd if=wholeSD.img of=/dev/mmcblk0
13899392+0 records in
3899392+0 records out
1996488704 bytes (2.0 GB) copied, 1545.45 s, 1.3 MB/s

然后将 BCB 图像移动到卡片的最后一个扇区:

root@kali:~# dd if=BCB.img bs=512 count=1 seek=3911679 of=/dev/mmcblk0
1+0 records in
1+0 records out
512 bytes (512 B) copied, 8.4684e-05 s, 6.0 MB/s

注意使用seek(输出端)而不是skip(输入端)。

值得仔细检查最后一个块是否已写入。几个便宜的 SD 卡似乎在最后一个扇区中不起作用,可能是因为它们误报了大小。

现在你有一张启动卡。

Micro SD 卡具有可从卡中读取的卡识别寄存器 (CID)。CID 包含产品序列号和制造日期等,这些信息因卡而异。

您的固件可能特定于某个 CID,作为一种复制保护形式。

这篇博文是关于在运行 Linux 的 iMX233 上读取 CID 并将其用作复制保护机制。