MTK平台scatter.txt生成全解析:从分区表原理到自定义实践

MTK平台scatter.txt生成全解析:从分区表原理到自定义实践
1. 项目概述从芯片到镜像理解MTK分区表的枢纽在MTK联发科平台的Android设备开发中无论是进行系统定制、固件升级还是深度调试有一个文件你绝对绕不开那就是scatter.txt。这个看似普通的文本文件却是连接芯片物理内存布局与软件镜像烧录的“地图”。很多刚接触MTK平台的朋友拿到一个项目源码包看到里面预置的scatter.txt可能会直接拿来就用或者仅仅修改一下分区大小。但你是否想过这个文件是如何生成的它背后的数据来源是什么修改一个分区参数会如何影响整个系统的启动和运行这就是我们今天要深入探讨的核心MTK scatter.txt的生成过程。这个过程远不止是运行一个脚本那么简单它贯穿了从芯片设计、硬件选型到软件系统规划的整个产品定义阶段。理解这个过程不仅能让你在遇到“分区表错误”、“刷机失败”时快速定位问题更能让你在自定义分区、适配新硬件或进行系统裁剪时做到心中有数游刃有余。简单来说scatter.txt是ptgen分区表生成器工具根据硬件和软件需求“编译”出来的最终产物而我们要拆解的正是这个“编译”过程的输入、处理和输出。2. 核心概念解析分区表、scatter.txt与ptgen在深入生成过程之前我们必须厘清几个核心概念以及它们之间的关系。这就像盖房子前要先看懂建筑图纸一样。2.1 什么是分区表Partition Table在存储设备如eMMC、UFS上分区表定义了如何将一块连续的物理存储空间划分成多个逻辑上独立的部分每个部分就是一个分区。例如boot分区存放内核和ramdisksystem分区存放Android系统userdata分区存放用户数据。在MTK平台分区表的核心信息通常来源于两个地方硬件定义芯片本身有默认的存储器映射和预定义的分区建议这通常在芯片的参考设计文档中。软件需求具体的项目Project根据要搭载的Android版本、功能特性如双系统、安全启动、预装应用大小等对分区的大小、类型和顺序提出具体要求。2.2 scatter.txt的角色与结构scatter.txt是MTK专属的、面向SP Flash Tool烧录工具和LKLittle KernelMTK平台的bootloader之一的分区表描述文件。它不是一个简单的列表而是一个结构化的脚本告诉工具每个分区的名称如PRELOADER,PGPT,PRO_INFO,NVRAM,PROTECT_F,PROTECT_S,SECCFG,UBOOT,BOOTIMG,RECOVERY,SEC_RO,MISC,LOGO,EXPDB,FRP,NVDATA,METADATA,SYSTEM,CACHE,USERDATA,FAT等。该分区在物理存储上的起始地址physical_start_addr这是绝对地址从存储器的0x0开始计算。分区的大小partition_size以字节为单位。该分区对应的镜像文件file_name烧录时使用的实际文件如boot.img,system.img。分区的操作属性如是否可擦除is_download是否在烧录时进行校验等。一个典型的scatter.txt片段如下- partition_index: SYS0 partition_name: PRELOADER file_name: preloader_k62v1_64_bsp.bin is_download: true type: SV5_BL_BIN linear_start_addr: 0x0 physical_start_addr: 0x0 partition_size: 0x40000 region: EMMC_USER storage: HW_STORAGE_EMMC boundary_check: true is_reserved: false operation_type: BOOTLOADERS reserve: 0x002.3 ptgen分区表的“编译器”ptgenPartition Table Generator是MTK平台用于生成分区表相关文件主要是scatter.txt的核心工具或脚本集合。它通常位于MTK发布的源码包中路径类似于vendor/mediatek/proprietary/scripts/ptgen/。你可以把它理解为一个“编译器”它读取“源代码”硬件配置和软件需求经过处理输出“目标文件”scatter.txt等。ptgen的主要输入Memory Device List一个定义了项目所用存储器件如eMMC 64GB基本信息的文件包括总容量、块大小、预留区域等。Partition Configuration File一个详细定义每个分区属性、大小规则和依赖关系的配置文件。这是工程师进行自定义的主要战场。Project Configuration具体项目的Makefile或配置文件中定义的变量如MTK_EMMC_SIZE,MTK_NAND_PAGE_SIZE,MTK_FAT_ON_NAND等。ptgen的主要输出scatter.txt用于烧录。partition_table.mk(或ptgen.mk)用于Android编译系统指导images的生成和打包。有时还会输出用于LK或Preloader内部使用的头文件。理解了这三者的关系我们就可以进入正题看看ptgen是如何工作的。3. scatter.txt生成流程全解析生成一个可用的scatter.txt是一个多阶段、有严格顺序的过程。下面我们以一个虚拟的MTK 6789平台项目为例拆解其完整流程。3.1 第一阶段硬件与项目配置收集这是生成过程的基石所有后续计算都依赖于本阶段的输入。3.1.1 确定存储设备类型和容量这是第一步也是决定性的一步。项目硬件工程师会选定具体的eMMC或UFS芯片例如“SK海力士 128GB eMMC 5.1”。这个信息会通过项目的配置文件如ProjectConfig.mk传递给编译系统通常以变量形式存在例如MTK_EMMC_SUPPORTyes EMMC_CHIPKLUBG4U1EA-B0C1 # 这是海力士某型号的Part Number MTK_EMMC_SIZE0x1D0000000 # 以字节表示的128GB容量即116GB左右厂商进制和系统进制的差异ptgen会首先读取这些变量确定它是在为哪种存储设备、多大容量生成分区表。这里有一个关键坑点eMMC的总容量并非全部可用开头一部分通常是前几个MB被用于硬件级的坏块管理、固件等这部分是ptgen必须避开的。因此在Memory Device List文件中会明确定义USER_AREA_START_ADDRESS用户可用区域起始地址。3.1.2 解析分区配置文件这是工程师干预最多的文件。在MTK代码中通常位于device/mediatek/build/build/tools/ptgen/或类似路径下文件名可能是[platform]_partition_table.conf如mt6789_partition_table.conf。 这个文件定义了所有可能的分区以及它们的大小计算规则。规则非常灵活固定大小partition_size: 0x800000固定8MB。比例大小partition_size: 2%占用户可用空间的2%。剩余空间对于最后一个分区如USERDATA通常会定义为partition_size: -1表示占用所有剩余空间。对齐要求alignment: 0x1000001MB对齐。这对Flash存储器的性能至关重要未对齐的读写会极大降低速度。依赖关系例如SECCFG分区必须在PROTECT_F之后NVRAM必须有一个固定的备份分区等。实操心得修改这个配置文件是自定义分区的标准方法。但切记不要只改一个分区的大小就了事。比如你把SYSTEM分区从3GB扩大到4GB那么它后面的所有分区CACHE,USERDATA等的起始地址都会后移1GB。你必须确保最后一个分区如USERDATA的“剩余空间”定义仍然有效且总容量没有超出存储设备极限。一个实用的方法是在修改后用ptgen的调试模式先跑一遍输出计算过程中的中间变量检查是否有分区溢出或地址冲突。3.2 第二阶段ptgen核心计算与决策收集完所有配置后ptgen脚本通常是Perl或Python编写开始进行核心的逻辑计算。3.2.1 建立分区顺序链表ptgen首先会根据配置文件建立一个有顺序的分区链表。这个顺序不是随意的它遵循MTK平台的内在要求Preloader区域最开始的区域存放PRELOADER和PGPTPrimary GPT表等这些分区在USER_AREA之外地址非常靠前。保护性分区如PRO_INFO,NVRAM,PROTECT_F/S。这些分区存放IMEI、NVRAM参数、安全密钥等关键数据需要被保护防止被意外擦除。Bootloader相关SECCFG,UBOOT,BOOTIMG,RECOVERY,SEC_RO。这是启动链的核心。系统与数据分区MISC,LOGO,SYSTEM,VENDOR,PRODUCT,CACHE,USERDATA等。GPT备份SGPTSecondary GPT表位于磁盘末尾。ptgen会按照这个逻辑顺序依次处理每个分区节点。3.2.2 动态计算分区大小与地址这是最核心的算法部分。ptgen会遍历分区链表计算当前分区大小根据配置规则固定值、百分比、剩余值结合已知的总用户空间大小计算出该分区的字节数。地址对齐将计算出的分区起始地址根据该分区的alignment要求进行向上对齐。例如当前地址是0x12345678对齐要求是0x1000001MB那么对齐后的地址将是0x12400000。更新下一个分区的起始地址将当前分区的起始地址加上其对齐后的大小作为下一个分区的起始地址。循环与校验重复以上步骤直到处理完所有分区。在这个过程中ptgen会持续进行边界检查检查每个分区的结束地址是否超过了存储设备的总物理地址。检查是否有分区地址重叠。对于定义为“剩余空间”的分区如USERDATA会用一个标志位标记在最后计算时用总空间减去已分配空间得出其实际大小。3.2.3 处理特殊分区与依赖一些分区有特殊逻辑GPT表PGPT和SGPT的大小和位置是固定的由eMMC规范决定ptgen会直接写入固定值。备份分区如NVRAM和NVDATA通常有主备两份ptgen会自动计算备份分区的地址。FAT分区如果项目配置了MTK_FAT_ON_NAND旧式设计ptgen会在最后预留一个FAT分区。3.3 第三阶段文件生成与输出计算完成后ptgen会将结果输出到不同的文件中以适应不同的下游工具。3.3.1 生成scatter.txtptgen将遍历最终确定的分区链表按照SP Flash Tool要求的格式为每个分区生成一个条目。关键步骤包括将计算出的十六进制地址和大小填入physical_start_addr和partition_size。根据分区类型关联默认的镜像文件名。例如BOOTIMG关联boot.imgRECOVERY关联recovery.img。设置分区属性is_download: true表示该分区需要被烧录对于PRO_INFO、NVRAM等存放设备唯一数据的分区可能会设置为is_download: false因为它们在量产时通过专用工具写入日常刷机不应被覆盖。最终生成一个完整的、语法正确的scatter.txt文件。3.3.2 生成编译系统文件同时ptgen会生成一个partition_table.mk文件。这个文件被Android的编译系统通过BoardConfig.mk引入使用。它主要做两件事定义BOARD_xxxIMAGE_PARTITION_SIZE例如BOARD_SYSTEMIMAGE_PARTITION_SIZE : 3221225472。当执行make systemimage时编译系统会读取这个值来创建指定大小的system.img文件。如果system.img的实际内容超过了这个大小编译就会报错。定义分区列表提供一个所有分区名称的列表用于一些需要遍历分区的脚本。3.3.3 集成到编译流程在完整的Android源码编译中例如执行source build/envsetup.sh lunch project然后makeptgen的调用通常被集成在device/mediatek/project/device.mk或类似的Makefile中。它会在编译早期被自动执行确保生成的scatter.txt和partition_table.mk与当前代码版本和项目配置同步。4. 自定义分区与高级调试技巧理解了自动生成过程我们就能进行有效的手动干预和问题排查。4.1 如何安全地自定义分区假设你需要为项目增加一个OEM分区来存放客制化应用或者扩大VENDOR分区以容纳新的HAL库。标准操作流程如下定位配置文件找到你项目对应的[platform]_partition_table.conf文件。插入新分区定义在合适的位置例如在SYSTEM分区之后USERDATA分区之前添加你的新分区。必须明确指定其partition_size固定值或百分比和alignment。partition_name: OEM file_name: oem.img partition_size: 0x20000000 # 512MB alignment: 0x100000 # 1MB对齐调整受影响分区由于你插入了一个新分区后面所有分区的起始地址都会后移。你必须手动调整最后一个使用“剩余空间”定义的分区通常是USERDATA的规则确保它仍然能正确计算大小。或者你可以选择缩小某个现有分区如CACHE来腾出空间。重新生成并验证执行ptgen脚本或重新编译整个Android源码make会触发ptgen。检查新生成的scatter.txt确认新分区的地址、大小正确且没有地址重叠或溢出。检查生成的partition_table.mk确认有BOARD_OEMIMAGE_PARTITION_SIZE的定义。更新编译配置在设备的BoardConfig.mk中可能需要添加BOARD_OEMIMAGE_FILE_SYSTEM_TYPE : ext4等定义以便编译系统知道如何打包oem.img。避坑指南绝对不要直接修改自动生成的scatter.txt文件因为这个文件是ptgen的输出结果。下次编译或执行ptgen时你的修改会被覆盖。所有自定义都必须在输入文件*.conf配置文件中进行。4.2 scatter.txt相关问题的排查思路当刷机失败SP Flash Tool报错如ERROR: S_UNDEFINED_ERROR(0xCDCD0501)或ERROR: S_PART_MAUI_SPACE_NOT_ENOUGH(0xFD010002)时很可能与scatter.txt有关。排查步骤核对版本首先确认你使用的scatter.txt是否与你的设备型号、硬件版本尤其是eMMC容量完全匹配。用64GB版本的scatter.txt去刷32GB的设备百分之百会失败。检查分区大小使用文本编辑器打开scatter.txt计算所有分区的partition_size之和。这个总和加上PGPT/SGPT等开销必须小于等于eMMC芯片的USER_AREA总大小。如果超出就会触发空间不足错误。检查镜像文件确认scatter.txt中列出的file_name如system.img是否真实存在于刷机包中并且其实际文件大小是否超过了对应分区的partition_size。system.img过大是导致刷机失败的常见原因。使用ptgen调试如果怀疑是生成过程有问题可以尝试手动运行ptgen脚本并打开调试输出。通常可以通过添加-v或--verbose参数来实现。这会打印出每一步的计算过程和中间变量帮助你定位是哪个分区的计算出了错。对比法找一个已知正常的、同型号设备的scatter.txt与你出问题的文件进行逐行对比。重点关注PRELOADER,PGPT,BOOTIMG,SYSTEM,USERDATA这几个关键分区的地址和大小。一个典型错误案例工程师A为了放入更大的GMS包将SYSTEM分区从0xC0000000(3GB) 改为0x100000000(4GB)但没有相应缩小USERDATA或确认总容量。ptgen在计算时USERDATA的起始地址后移了1GB但其“占用剩余空间”的规则导致其结束地址超出了eMMC的物理末尾地址。由于ptgen的边界检查这个错误的配置在生成时就可能报错。如果检查被绕过生成的scatter.txt中USERDATA分区将有一个非法的结束地址用这个文件刷机在写入USERDATA分区时就会发生失败。5. 深入原理从scatter.txt到设备启动理解了生成过程我们还能更深入地看scatter.txt如何影响设备的生死。5.1 scatter.txt与Preloader/LK的交互scatter.txt不仅是烧录工具的指南其信息也被编译进了Preloader和LK中。在编译Preloader时会提取scatter.txt中关于分区布局的信息生成一个头文件如partition_define.h。Preloader依靠这个信息来定位LK或UBOOT所在的分区从而加载并跳转。LK同样需要知道分区布局才能挂载boot或recovery分区来加载Linux内核。如果scatter.txt中的分区地址与Preloader/LK中硬编码或编译时写入的地址不匹配设备将无法启动卡在最早期的引导阶段。5.2 GPT与MBR现代分区表的基石虽然MTK使用自定义的scatter.txt格式但其描述的分区布局最终会体现在存储设备的GPTGUID Partition Table上。PGPT和SGPT分区就是存放GPT数据的地方。SP Flash Tool在烧录时除了写入各个镜像文件还会根据scatter.txt的信息在PGPT和SGPT位置写入标准的GPT表。操作系统包括Android是通过读取GPT来识别分区的。因此scatter.txt的准确性直接决定了设备上GPT表的正确性。5.3 动态分区Dynamic Partition带来的变化从Android 10/Q开始Google引入了动态分区Dynamic Partition机制用于system、vendor、product等只读分区。这对于scatter.txt的生成有重大影响。布局简化在scatter.txt中不再为system、vendor等定义固定大小的独立分区而是定义一个大的super分区。生成逻辑变化ptgen的配置和计算逻辑需要适配动态分区。分区大小可能在刷机时由lpmake工具动态决定而不是在scatter.txt中写死。scatter.txt中super分区的大小需要足够容纳所有动态子分区的总和。工具链更新SP Flash Tool也需要更新以支持烧录super分区镜像。理解动态分区下的scatter.txt生成需要同时理解super.img的构建过程。这个过程虽然底层但却是MTK Android设备开发的基石之一。它不像写应用逻辑那样有直接的界面反馈但一旦出错影响是根本性的——设备变砖。掌握它意味着你拥有了从系统层面定义和改造设备存储布局的能力。下次当你打开一个scatter.txt文件时希望你能看到的不仅仅是一行行地址和数字而是一张由芯片规格、项目需求和工具脚本共同绘制的精密地图。