如何通过dd找到/boot/Image

目标: 找到/boot/Image文件的数据块

0.ext4文件系统布局

sudo dumpe2fs /dev/mmcblk0p1

输出

sudo dumpe2fs /dev/mmcblk0p1
dumpe2fs 1.44.1 (24-Mar-2018)
Filesystem volume name:   <none>
Last mounted on:          /
Filesystem UUID:          0091ad72-a6a0-4cd7-9f64-75b0c06f4583
Filesystem magic number:  0xEF53
Filesystem revision #:    1 (dynamic)
Filesystem features:      has_journal ext_attr resize_inode dir_index filetype needs_recovery extent 64bit flex_bg sparse_super large_file huge_file dir_nlink extra_isize metadata_csum
Filesystem flags:         signed_directory_hash 
Default mount options:    user_xattr acl
Filesystem state:         clean
Errors behavior:          Continue
Filesystem OS type:       Linux
Inode count:              524288
Block count:              2097152
Reserved block count:     104857
Free blocks:              708331
Free inodes:              356662
First block:              0
Block size:               4096
Fragment size:            4096
Group descriptor size:    64
Reserved GDT blocks:      1023
Blocks per group:         32768
Fragments per group:      32768
Inodes per group:         8192
Inode blocks per group:   512
Flex block group size:    16
Filesystem created:       Fri Oct 10 16:01:29 2025
Last mount time:          Sat Jan  1 09:00:17 2000
Last write time:          Sat Jan  1 09:00:17 2000
Mount count:              2
Maximum mount count:      -1
Last checked:             Tue Oct 14 18:35:14 2025
Check interval:           0 (<none>)
Lifetime writes:          107 MB
Reserved blocks uid:      0 (user root)
Reserved blocks gid:      0 (group root)
First inode:              11
Inode size:	          256
Required extra isize:     32
Desired extra isize:      32
Journal inode:            8
First orphan inode:       271049
Default directory hash:   half_md4
Directory Hash Seed:      9a23ae96-0c0d-4279-8d95-4bc605292e1c
Journal backup:           inode blocks
Checksum type:            crc32c
Checksum:                 0x5a001698
Journal features:         journal_incompat_revoke journal_64bit journal_checksum_v3
Journal size:             64M
Journal length:           16384
Journal sequence:         0x00001121
Journal start:            8197
Journal checksum type:    crc32c
Journal checksum:         0xd573dcb6


Group 0: (Blocks 0-32767) csum 0x8e29 [ITABLE_ZEROED]
  Primary superblock at 0, Group descriptors at 1-1
  Reserved GDT blocks at 2-1024
  Block bitmap at 1025 (+1025), csum 0x56053078
  Inode bitmap at 1041 (+1041), csum 0x64306ca9
  Inode table at 1057-1568 (+1057)
  0 free blocks, 7 free inodes, 727 directories
  Free blocks: 
  Free inodes: 396, 2276, 2280, 2470-2471, 2716, 2804
Group 1: (Blocks 32768-65535) csum 0x9dfa [ITABLE_ZEROED]
  Backup superblock at 32768, Group descriptors at 32769-32769
  Reserved GDT blocks at 32770-33792
  Block bitmap at 1026 (bg #0 + 1026), csum 0xf93b5b4a
  Inode bitmap at 1042 (bg #0 + 1042), csum 0x099df3c4
  Inode table at 1569-2080 (bg #0 + 1569)
  33 free blocks, 0 free inodes, 558 directories
  Free blocks: 33800-33815, 33960-33975, 42671
  Free inodes: 

其中的关键信息
首先是超级块中存储的

Group descriptor size:    64

Block size:               4096
Blocks per group:         32768
Inode size:	          256
Inodes per group:         8192
Inode blocks per group:   512

第一个说明group descriptor table(GDT, 块组描述表)的大小是64个, 总共有64个group
这里简单说明一下ext4各级单位之间的关系
最顶层的为group
再下一层的为block
再下一层为bytes

数据块的块号指的是block的号,所以想找到数据块就是 数据块号x block size
inode号则稍微是有点不一样的, 应该这样理解, 即对inode来说
底部好像是一个连续的数组, 然后每个8192个(inodes per group) 算一个group
它的大小是inode size (Bytes)
因此总共是占了 8192 x 256 / 4096 = 512个block (即Inode blocks per group)

但其实每个group inode所在的位置是不确定的, 这个是需要查询GDT来获取的
比如说

Group 0: (Blocks 0-32767) csum 0x8e29 [ITABLE_ZEROED]
  Primary superblock at 0, Group descriptors at 1-1
  Reserved GDT blocks at 2-1024
  Block bitmap at 1025 (+1025), csum 0x56053078
  Inode bitmap at 1041 (+1041), csum 0x64306ca9
  Inode table at 1057-1568 (+1057)
  0 free blocks, 7 free inodes, 727 directories
  Free blocks: 
  Free inodes: 396, 2276, 2280, 2470-2471, 2716, 2804

这个就说明, 它的Inode table在1057-1568块的位置
然后整个组在0-32767的位置
然后0号group默认是用来放主超级块的
所以它这里会告诉你主超级块在0号块, GDT在1-1号块(因为只有64个group,每个descriptor 64字节,所以64×64=4096字节=1块)

  • Reserved GDT blocks at 2-1024 是系统预留给将来扩展的GDT空间
    我自己电脑上的输出是这样的
Group 0: (Blocks 0-32767) csum 0xb0fe [ITABLE_ZEROED]
  Primary superblock at 0, Group descriptors at 1-120
  Reserved GDT blocks at 121-1144
  Block bitmap at 1145 (+1145), csum 0x1f55a79e
  Inode bitmap at 1161 (+1161), csum 0x61a30a41
  Inode table at 1177-1688 (+1177)
  276 free blocks, 8172 free inodes, 2 directories, 8171 unused inodes
  Free blocks: 9645-9648, 9750-9751, 9881-9882, 9900-9913, 10112-10239, 10358-10361, 10495-10508, 10576-10579, 10867-10869, 10888-10911, 10986-10990, 11085-11100, 11281, 32376-32387, 32438-32464, 32521-32534, 32766-32767
  Free inodes: 21-8192

可以看到其实是在1-120的, 然后后面的121-1144是保留用的,默认应该是0, 注意这里提到的都是块号

所以假如我需要找inode table, 则要从1177-1688这里找

然后group 0的布局如下所示

Group 0: (Blocks 0-32767)
┌─────────────────────────────────────────────────────┐
│ 块 0:      主超级块 (在块0的1024-2047字节位置)      │
├─────────────────────────────────────────────────────┤
│ 块 1:      块组描述符表                             │
├─────────────────────────────────────────────────────┤
│ 块 2-1024: 保留的GDT块 (未来扩展用)                │
├─────────────────────────────────────────────────────┤
│ 块 1025:   Block bitmap (4096字节,标记32768个块)  │
├─────────────────────────────────────────────────────┤
│ 块 1026-1040: 未使用 (间隙)                        │
├─────────────────────────────────────────────────────┤
│ 块 1041:   Inode bitmap (1024字节,标记8192个inode)│
├─────────────────────────────────────────────────────┤
│ 块 1042-1056: 未使用 (间隙)                        │
├─────────────────────────────────────────────────────┤
│ 块 1057-1568: Inode表 (512个块,存储8192个inode)  │
├─────────────────────────────────────────────────────┤
│ 块 1569-32767: 实际数据块                          │
└─────────────────────────────────────────────────────┘

然后如果你选择了稀疏超级块存储这一特性, 备份超级块只会被存储特定的group上. 即前面还是会有几块用是用来充当超级块的备份的,

1.查找/boot/Image

启动用文件
一定存在, 所以拿这个作为查找用的例子

首先 / 的inode 号被固定为2
因此它在

2/8192 = 0
2%8192 = 2

第0块的第2个inode

查上面的表可知
第0个的inode table在1057x4096
第2个inode在偏移 256x(2-1)的位置

然后用dd去读对应大小的内容
这里是我知道它使用的ext4引入的extent格式 这个会在前面的flag中说明

ext2/3用的是12个直接块+间接块的形式, 但是这样是比较低效率的, 所以引入了extent格式.
但是它们用的这个位置是没有变化的 即40开始的位置
然后extent格式下, 头占12B

struct ext4_extent_header {
    __le16  eh_magic;    // 0xF30A
    __le16  eh_entries;  // 当前 extent 条目数
    __le16  eh_max;      // 最大可容纳 extent 数
    __le16  eh_depth;    // 树深度(0 表示叶子节点)
    __le32  eh_generation; // 通常为 0
};

然后每个条目内容是

struct ext4_extent {
    __le32  ee_block;    // 逻辑块号(文件内的偏移,以块为单位)
    __le16  ee_len;      // 范围长度(块数)
    __le16  ee_start_hi; // 物理块号高16位(用于 >32位地址)
    __le32  ee_start_lo; // 物理块号低32位
};

我们关心的是后面这16+32位
但可以看到16位是00, 所以我们直接看最后的32位, 即再跳过8B

neu@neu-desktop:~$ sudo dd if=/dev/mmcblk0p1 bs=1 count=12 skip=$((1057*4096+256+40+12)) 2>/dev/null | hexdump -C
00000000  00 00 00 00 01 00 00 00  21 24 00 00              |........!$..|
0000000c
neu@neu-desktop:~$ sudo dd if=/dev/mmcblk0p1 bs=1 count=4 skip=$((1057*4096+256+40+12+8)) 2>/dev/null | hexdump -C
00000000  21 24 00 00                                       |!$..|
00000004

所以数据块在
0x2421 = 9249

然后读数据块的内容

9249x4096B

neu@neu-desktop:~$ sudo dd if=/dev/mmcblk0p1 bs=4096 skip=9249 count=1 | hexdump -C
1+0 records in
1+0 records out
00000000  02 00 00 00 0c 00 01 02  2e 00 00 00 02 00 00 00  |................|
4096 bytes (4.1 kB, 4.0 KiB) copied, 0.000179881 s, 22.8 MB/s
00000010  0c 00 02 02 2e 2e 00 00  0b 00 00 00 14 00 0a 02  |................|
00000020  6c 6f 73 74 2b 66 6f 75  6e 64 00 00 01 00 06 00  |lost+found......|
00000030  0c 00 04 02 62 6f 6f 74  01 00 02 00 0c 00 03 02  |....boot........|
00000040  62 69 6e 00 0c 00 00 00  0c 00 03 02 64 65 76 00  |bin.........dev.|
00000050  0e 00 00 00 0c 00 03 02  65 74 63 00 c5 00 02 00  |........etc.....|
00000060  0c 00 04 02 68 6f 6d 65  c6 00 02 00 0c 00 03 02  |....home........|
00000070  6c 69 62 00 4b 00 06 00  10 00 05 02 6d 65 64 69  |lib.K.......medi|
00000080  61 00 00 00 4c 00 06 00  0c 00 03 02 6d 6e 74 00  |a...L.......mnt.|
00000090  4d 00 06 00 0c 00 03 02  6f 70 74 00 01 00 04 00  |M.......opt.....|
000000a0  0c 00 04 02 70 72 6f 63  ff 0a 00 00 14 00 0a 01  |....proc........|
000000b0  52 45 41 44 4d 45 2e 74  78 74 00 00 02 00 04 00  |README.txt......|
000000c0  0c 00 04 02 72 6f 6f 74  06 00 04 00 0c 00 03 02  |....root........|
000000d0  72 75 6e 00 2e 00 04 00  0c 00 04 02 73 62 69 6e  |run.........sbin|
000000e0  eb 00 04 00 0c 00 04 02  73 6e 61 70 ec 00 04 00  |........snap....|
000000f0  0c 00 03 02 73 72 76 00  ed 00 04 00 0c 00 03 02  |....srv.........|
00000100  73 79 73 00 ee 00 04 00  0c 00 03 02 74 6d 70 00  |sys.........tmp.|
00000110  ef 00 04 00 0c 00 03 02  75 73 72 00 67 12 02 00  |........usr.g...|
00000120  0c 00 03 02 76 61 72 00  82 bd 00 00 cc 0e 32 01  |....var.......2.|
00000130  74 65 67 72 61 31 39 34  2d 6d 62 31 2d 62 63 74  |tegra194-mb1-bct|
00000140  2d 72 61 74 63 68 65 74  2d 70 32 38 38 38 2d 30  |-ratchet-p2888-0|
00000150  30 30 30 2d 70 32 38 32  32 2d 30 30 30 30 2e 63  |000-p2822-0000.c|
00000160  66 67 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |fg..............|
00000170  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00000ff0  00 00 00 00 00 00 00 00  0c 00 00 de f3 4c 5b 21  |.............L[!|
00001000

存储的目录项的逻辑是这样的

struct ext4_dir_entry_2 {
    __le32 inode;          // 对应的 inode 编号
    __le16 rec_len;        // 本记录总长度(用于链表)
    __u8   name_len;       // 文件名长度
    __u8   file_type;      // 文件类型(如 DIR, REG, SYMLINK 等)
    char   name[];         // 文件名(不以 \0 结尾)
};

我们要找的是inode, 所以从name向前去掉32位, 共4B就是我们要的
所以inode号是0x060001 = 393217

393217/8192=48
393217%8192=1

48块的inode table起始在1572896
256x(1-1) = 0
然后按照和之前一样的方法我们就可以找到boot的数据块在

neu@neu-desktop:~$ sudo dd if=/dev/mmcblk0p1 bs=1 skip=$((1572896*4096+40)) count=$((256-40)) | hexdump -C
00000000  0a f3 01 00 04 00 00 00  00 00 00 00 00 00 00 00  |................|
00000010  01 00 00 00 20 20 18 00  00 00 00 00 00 00 00 00  |....  ..........|
00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000030  00 00 00 00 00 00 00 00  00 00 00 00 88 68 69 f3  |.............hi.|
00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000050  00 00 00 00 ce 47 00 00  20 00 14 ac 00 9c d2 2c  |.....G.. ......,|
00000060  00 9c d2 2c 80 3c ca 8f  59 bd e8 68 54 fe 34 b3  |...,.<..Y..hT.4.|
00000070  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
216+0 records in
216+0 records out
216 bytes copied, 0.0038682 s, 55.8 kB/s
000000d8

0x182020 = 1581088

然后就能发现Image

neu@neu-desktop:~$ sudo dd if=/dev/mmcblk0p1 bs=4096 skip=1581088 count=1 | hexdump -C
1+0 records in
1+0 records out
00000000  01 00 06 00 0c 00 01 02  2e 00 00 00 02 00 00 00  |................|
4096 bytes (4.1 kB, 4.0 KiB) copied, 0.000166152 s, 24.7 MB/s
00000010  0c 00 02 02 2e 2e 00 00  02 00 06 00 0c 00 03 02  |................|
00000020  64 74 62 00 03 00 06 00  10 00 05 01 49 6d 61 67  |dtb.........Imag|
00000030  65 00 00 00 05 00 06 00  38 00 2e 01 74 65 67 72  |e.......8...tegr|

可以观察到, Image放在了 0x060003 即目录后两个inode处

echo [[cis_nofsimage]] cp -vf /home/issac.lin/SSR931G/project/board/m6p/boot/spinand/partition/* /home/issac.lin/SSR931G/project/image/output/images/boot/ /home/issac.lin/SSR931G/project/image/makefiletools/bin/pnigenerator -c 1024 -s 0x20000 -a "0x140000(CIS),0x60000(IPL),0x60000(IPL_CUST),0x100000(UBOOT)" -b "0x60000(IPL),0x60000(IPL_CUST),0x100000(UBOOT)" -t "0x40000(ENV),0x500000(KERNEL),0x500000(RECOVERY),0x600000(rootfs),0x100000(MISC),-(ubia)" -o /home/issac.lin/SSR931G/project/image/output/images/boot/partinfo.pni \ > /home/issac.lin/SSR931G/project/image/output/images/partition_layout.txt cat /home/issac.lin/SSR931G/project/image/output/images/partition_layout.txt if [ "spinand" = "spinand" ]; then \ /home/issac.lin/SSR931G/project/image/makefiletools/bin/snigenerator -a 10 -b 24 -i /home/issac.lin/SSR931G/project/board/m6p/boot/spinand/partition/flash.sni -o /home/issac.lin/SSR931G/project/image/output/images/boot/flash.sni; \ /home/issac.lin/SSR931G/project/image/makefiletools/bin/snigenerator -a 10 -b 24 -i /home/issac.lin/SSR931G/project/board/m6p/boot/spinand/partition/flash_list.sni -o /home/issac.lin/SSR931G/project/image/output/images/boot/flash_list.sni; \ fi; dd if=/dev/zero bs=2048 count=2 | tr '\000' '\377' > /home/issac.lin/SSR931G/project/image/output/images/cis.bin dd if=/home/issac.lin/SSR931G/project/image/output/images/boot/flash.sni of=/home/issac.lin/SSR931G/project/image/output/images/cis.bin bs=2048 count=1 conv=notrunc seek=0 dd if=/home/issac.lin/SSR931G/project/image/output/images/boot/partinfo.pni of=/home/issac.lin/SSR931G/project/image/output/images/cis.bin bs=2048 count=1 conv=notrunc seek=1 cat /home/issac.lin/SSR931G/project/image/output/images/boot/flash_list.sni >> /home/issac.lin/SSR931G/project/image/output/images/cis.bin这是makefile吗
07-22
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值