# MtkPt **Repository Path**: geekflashtool/mtk-pt ## Basic Information - **Project Name**: MtkPt - **Description**: 一篇文档用于解析Mtk 部分Legacy设备中 存在MBR分区的设备的分区表解析,一种特殊的Mtk分区表格式 - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 0 - **Created**: 2026-08-11 - **Last Updated**: 2026-08-11 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # MediaTek Legacy PMT / PT Partition Table 解析 > 本文档描述旧式 MediaTek 设备中 PMT (Partition Table) 与 MPT (Mirror) 在 eMMC USER 区的布局、结构及校验规则。 --- ### 位置与布局 - 固件在 USER 区末尾保留 **1 MiB** 空间。 - 主 PT 位于末尾偏移 `user_size - 0x100000`,镜像 MPT 位于主 PT 偏移 `+0x1000`(4 KiB)。 - 扇区大小固定 512 字节,每次读取一个 4 KiB 块(8 扇区)。 | 区域 | 字节偏移 | Magic | |------|----------|-------| | 主 PT | `user_size - 0x100000` | `0x50547631`(磁盘字节 `31 76 54 50`) | | 镜像 MPT | `user_size - 0x0FF000` | `0x4D505431`(磁盘字节 `31 54 50 4D`) | ### 磁盘块结构 `PmtDiskBlock`(4 KiB) | 偏移 | 大小 | 字段 | 说明 | |------|------|------|------| | `0x000` | 4 B | `head_magic` | 主 PT: `0x50547631`,镜像: `0x4D505431` | | `0x004` | 4 B | `version` | 固定 `"1.0\0"`(字节 `31 2E 30 00`) | | `0x008` | 40 × 0x58 | `entries[40]` | 分区条目数组 | | `0xDC8` | 0x230 | reserved | 保留填充 | | `0xFF8` | 4 B | `sequence` | 序号(仅低 8 位有效) | | `0xFFC` | 4 B | `tail_magic` | 必须等于 `head_magic` | ### 分区条目 `PmtDiskEntry`(0x58 字节) | 偏移 | 大小 | 字段 | 说明 | |------|------|------|------| | `+0x00` | 64 B | `name[64]` | NUL 结尾名称 | | `+0x40` | 8 B | `size` | 分区大小(字节) | | `+0x48` | 8 B | `offset` | 起始偏移(字节) | | `+0x50` | 8 B | `mask_flags` | 属性掩码 | ## ⚠️注意:如果是提取的ROM,也就是全字库,对于此偏移还需要减去0xC00000才可以得到正确的文件偏移 ### 运行时结构 `PmtRuntimeEntry`(0x60 字节) 固件读入内存后展开,相比磁盘结构增加 `part_id` 字段(固定 `0xFF`),其余字段复制自磁盘条目。 ### 校验规则 - 仅校验头部 Magic、版本 `"1.0\0"` 和尾部 Magic,**无 CRC/校验和**。 - **回退策略**:仅当主 PT 读取成功但 Magic/版本校验失败时,才尝试镜像 MPT;若主 PT 读取 I/O 错误,则直接返回失败。 ### 常量汇总 | 常量 | 值 | 说明 | |------|----|------| | `PMT_BLOCK_SIZE` | `0x1000` | 4 KiB | | `PMT_DISK_ENTRY_SIZE` | `0x58` | 88 字节 | | `PMT_RUNTIME_ENTRY_SIZE` | `0x60` | 96 字节 | | `PMT_ENTRY_COUNT` | `40` | 最大分区数 | | `PMT_RESERVED_FROM_END` | `0x100000` | 保留区 1 MiB | | `PMT_MIRROR_DELTA` | `0x1000` | 镜像偏移 | | `PMT_PT_MAGIC` | `0x50547631` | 主 PT Magic | | `PMT_MPT_MAGIC` | `0x4D505431` | 镜像 MPT Magic | | `PMT_VERSION` | `"1.0\0"` | 版本字符串 | ### 从 USER 区镜像定位 若 `user.bin` 长度为 `N`,则: - 主 PT 文件偏移 = `N - 0x100000` - 镜像 MPT 文件偏移 = `N - 0x0FF000` 在该偏移处应分别看到字节序列 `31 76 54 50 31 2E 30 00` 和 `31 54 50 4D 31 2E 30 00`。 ### 伪代码示例 ```c // 计算偏移 main_pt = user_size - 0x100000; mirror_pt = main_pt + 0x1000; // 读取并校验主 PT block = read(main_pt, 0x1000); if (block.head_magic == 0x50547631 && block.version == "1.0\0" && block.tail_magic == 0x50547631) valid = true; else { block = read(mirror_pt, 0x1000); if (block.head_magic == 0x4D505431 && block.version == "1.0\0" && block.tail_magic == 0x4D505431) valid = true; else error("无效 PT/MPT"); } // 解析 40 条记录 for (i = 0; i < 40; i++) { entry = block.entries[i]; name = entry.name; size = entry.size; offset = entry.offset; flags = entry.mask_flags; }