首页 / 资讯中心 / 文章详情

MTK平台FDRAM分区新增与挂载到根目录的完整实践指南

MTK平台FDRAM分区新增与挂载到根目录的完整实践指南 ★ FEATURED ARTICLE
简介这是一份面向联发科平台安卓系统工程师的资源解决安卓九点零及以上版本、MT6761设备上新增FDRAM分区并挂载到根目录的配置问题。压缩包共二十一个文件体积约一百三十三KB内容涵盖构建脚本、安全策略、分区表、辅助脚本、配置文件等基本覆盖分区定义、文件系统格式化与挂载流程的各个实现环节。目前已有六百八十二人学习下载目录按照设备、构建、系统等模块组织方便按需查阅。资源将分区表文件修改、分区表固件调整、文件系统格式化、挂载配置编写以及安全权限设置整合在一起还考虑到了安卓九点零的双分区更新机制和卷守护进程框架适配适合需要实际验证的中高级开发人员对照落地能够有效降低自行探索的风险。1. FDRAM 分区是什么为什么 MTK 板卡要自己加一个分区Android 设备在出厂时分区表基本是写死的system、vendor、data、cache 各占一块用户能碰到的就是内置存储那部分。但做 MTK 平台定制的时候尤其是做行业平板、车机、工控设备这类项目经常遇到一个尴尬场景系统跑起来之后某些应用要写大量临时数据又不想占用 data 分区更不希望这些数据因为恢复出厂设置被清掉——这时候就需要一个“系统不主动管理、但能挂载使用”的独立分区。这个分区就是 FDRAM。“FDRAM”这个名字在 MTK 的 scatter 文件里并不默认存在它是后加进去的。它可以是 eMMC 上的一块独立区域专门用来放自定义数据。下载这份资源核心价值就是它把“新增一个 FDRAM 分区并挂载到根目录”的完整流程拆开了——从修改 scatter 声明分区、调整分区大小到配置挂载逻辑最后还要保证能开机自动挂载成功。适合正在做 MTK Android 系统定制、手里有源码级编译环境、却被分区方案卡住的朋友。这个操作排在系统移植里属于基础但极其容易翻车的活下面把每一步和踩过的坑一并说清楚。2. 修改 scatter 与分区表从声明分区到分配空间2.1 scatter 文件的结构与分区参数解读MTK 平台的烧录方案以 scatter 文件为核心上面记录了 eMMC 或者 UFS 的全部物理分区分配方式。常见的 scatter 文件名形如MT6768_Android_scatter.txt或者直接叫MTxxxx_Android_scatter.txt。你拿到这份资源之后第一步要做的就是打开 scatter找到现有分区列表看它的声明格式。我直接把一份实际能用到的 FDRAM 分区配置贴在下面便于对照。partition_index: SYS0 partition_name: FDRAM file_name: FDRAM.img type: EMMC_BOOT_IMG linear_start_addr: 0x0 partition_size: 0x2000000 region: EMMC_USER type: EMMC_USER这一段是 scatter 里新增分区的最小声明。partition_index是分区排序编号需要按 scatter 里现有分区的顺序接着编不能重复也不能跳号太多。partition_name是分区名这里叫 FDRAM名字可以自己定但不能带空格和特殊字符。file_name是烧录镜像名一般和分区名保持一致方便后续在编脚本里对应。partition_size是分区大小以十六进制表示0x2000000实际是 32MB。region: EMMC_USER表示这块区域放在用户区type: EMMC_BOOT_IMG表明该分区可被烧录工具识别为 boot 镜像类型。这里最容易被忽略的是linear_start_addr地址段。如果 scatter 里已经有分区新分区的起始地址必须紧接着上一个分区的结束地址不能留缝、不能重叠。常见的做法是打开 scatter 后先找到最后一个分区的结束地址把它作为新分区的 start。如果你是从别人手里拿到的 scatter没有地址计算工具可以直接用烧录工具读一遍整机分区布局看末地址再回填。2.2 分区大小分配十六进制换算与对齐规则分配分区大小是门玄学但有一点是硬性的MTK 的烧录工具要求分区起始地址和大小都按 4KB 对齐部分新平台还得 8KB 对齐。如果不对齐LLK 或者 SP Flash Tool 会直接报错提示分区重叠或者无法正常下载。换算方式很简单1MB 0x100000 字节32MB 就是0x200000064MB 就是0x4000000。如果你想留 48MB那就是0x3000000。我一般会建议多留一点余量。这个分区的用途是放系统扩展数据比如车机项目里要放导航地图增量包、离线语音包工控设备里可能要放日志文件。日志文件一旦写满整个分区满了会导致挂载异常最坏情况是开机卡在启动动画。所以分配的时候按最大可用空间的 1.2 倍去算宁愿留给系统不要留给万一。# 计算分区大小十六进制转十进制确认实际字节数 python3 -c print(hex(32 * 1024 * 1024)) python3 -c print(hex(48 * 1024 * 1024))这段命令把 32MB 和 48MB 直接转成十六进制得到0x2000000与0x3000000。实际操作里不要心算尤其数据量超过 128MB 之后十六进制的位数容易出错。确认好大小之后回填到 scatter 的partition_size字段里同时确认linear_start_addr是对齐的——简单判断方法地址值用十六进制看最后三位必须都是 0否则一定没对齐。2.3 把新增分区写进烧录脚本与代码库MTK 平台的烧录不是只靠 scatter还需要配套的代码库和 mk 脚本同步修改。以 Android 9 到 Android 13 的常见工程为例分区信息一般记录在device/mediatek/.../BoardConfig.mk或ProjectConfig.mk里需要把 FDRAM 加进TARGET_BOARD_AUTOTAG或者BOARD_MTK_BASIC_PARTITION列表中。# ProjectConfig.mk 或 BoardConfig.mk 中添加 FDRAM 分区声明 TARGET_BOARD_PLATFORM : mt6768 BOARD_MTK_FDRAM_PARTITION_SIZE : 33554432 BOARD_MTK_FDRAM_PARTITION_NAME : FDRAM这里的BOARD_MTK_FDRAM_PARTITION_SIZE用的是十进制字节数和 scatter 里的十六进制保持一一对应。33554432就是 32MB。加完之后进入代码工程目录确认vendor/mediatek/proprietary/bootable/bootloader/lk下的platform相关文件里有没有对应分区表定义。LK 是 MTK 平台早期的 bootloader它自己维护一套分区列表如果不加进去开机时 LK 会认为这个分区不存在Android 上层根本没有机会挂载它。总结这一章的做法先改 scatter 声明分区并算好地址与大小再改编译脚本让分区编入系统最后同步 LK 分区表。三步缺一不可顺序错乱会导致烧录工具能识别但 LK 起不来或者 LK 正常但 Android 侧没挂载节点。到这里分区本身的框架已经立住了下一步要解决的是怎么把它挂到根目录上。3. 挂载到根目录init 脚本与三处联动配置3.1 为什么挂载根目录不能只改 fstab很多人第一次做这个操作只改了fstab文件然后发现开机直接进不了系统或者挂在 vold 阶段报错。FDRAM 分区要挂到根目录不是一个简单的mount命令能解决的。Android 的根文件系统由 ramdisk 加载并切到 system 分区根目录下除了系统必要目录之外其他挂载点基本都是通过 init 脚本动态创建的。如果把 FDRAM 直接挂到/下面会跟根文件系统本身的挂载发生冲突。正确做法是挂到根目录下的一个新目录比如/f dram或者/FDRAM。这个目录不是分区而是挂载点。挂载点必须由 init 在开机阶段创建然后执行 mount。整个链路涉及fstab、init.rc和vold三处配置协同起来才算完整。很多人只动其中一个结果就是明明分区能识别但df -h里永远看不到它。# 查看当前分区是否被内核识别 adb shell ls /dev/block/platform/bootdevice/by-name/ adb shell cat /proc/partitions上面命令会在烧录完成后执行用于确认 FDRAM 节点是否存在。/proc/partitions会列出所有内核识别到的块设备如果这里能看到 FDRAM 对应的设备节点但 Android 上层没挂载问题就出在 init 或 vold 配置而不在内核层。3.2 配置 fstab 与 init.rc开机自动挂载以 Android 10 的 MTK 工程为例fstab文件一般位于vendor/etc/fstab.mtXXXX或者odm/etc/fstab.qcom。MTK 平台通常在vendor/etc/下。新增 FDRAM 挂载项时需要告诉系统分区类型、挂载点和文件系统格式。# 在 fstab 中新增 FDRAM 分区挂载项 /dev/block/by-name/FDRAM /FDRAM ext4 rw,noatime wait,check这一行的含义是把/dev/block/by-name/FDRAM这个设备挂到根目录下的/FDRAM目录文件系统为 ext4以可读写方式挂载挂载完成后执行文件系统检查。wait关键字表示必须等待该设备节点出现后才能继续check表示挂载前执行 fsck。注意/FDRAM目录在系统里要提前创建否则 mount 会失败。这个目录可以放在system/frameworks/base/data/etc/或者直接通过 init.rc 的mkdir命令在开机时创建。# init.rc 中创建挂载目录并执行挂载 on early-fs mkdir /FDRAM 0771 root root mount_all /vendor/etc/fstab.mt6768mkdir后面跟的权限 0771 表示 root 用户和 root 用户组可读写其他用户只读。mount_all是 Android init 的默认动作它会读取 fstab 文件并尝试挂载所有标记为wait的分区。如果你发现 FDRAM 没被挂载大概率是 fstab 路径不对或者挂载点目录没创建这俩是最高频的翻车原因。3.3 vold 与 SELinux 策略对挂载的影响MTK 平台 Android 8 之后默认开启了 SELinux enforcing 模式FDRAM 的挂载不只是文件系统的活还涉及进程权限。vold负责管理存储设备但如果你的 FDRAM 不是通过 vold 挂载的而是开机 init 阶段直接 mount那 vold 基本不参与。可问题在于 SELinux 策略会拦截 init 进程对/FDRAM目录的写入操作导致即使 mount 成功了应用层也无法读写文件。解决方案是在 sepolicy 里补充对应规则。常见的路径是device/mediatek/.../sepolicy/basic/property.te和file_contexts。file_contexts 里要为/FDRAM(/.*)?分配一个标签例如u:object_r:f dram_file:s0。同时在init.te或vold.te里允许对 f dram_file 的挂载和读写操作。# file_contexts 中为 FDRAM 挂载目录定义 SELinux 标签 /FDRAM(/.*)? u:object_r:f dram_file:s0# 允许 init 进程对 FDRAM 目录执行挂载和文件管理操作 allow init f dram_file:dir { create read write mounton search setattr }; allow init f dram_file:file { create read write open getattr setattr }; typeattribute f dram_file mlstrustedsubject;这里解释一下allow init这条规则的作用它允许 init 进程在 f dram_file 目录上执行创建、挂载、读写等操作。typeattribute是把该目录标记为受信任主体避免被更细粒度的规则卡住。实际工程里如果一直遇到 Permission denied 但明明文件系统是 rw 挂载的直接查 avc denied 日志然后对应补 sepolicy 规则即可。即便补完规则后还是不行不要怀疑代码第一时间检查dmesg和logcat里的 avc 拒绝信息这是在 MTK 平台排查挂载问题最直接的一条路。到这里FDRAM 的挂载链路已经讲通了。分区有声明能识别init 阶段创建目录、读取 fstab 完成挂载SELinux 放行访问权限应用层就能正常使用了。但实际操作中坑远不止这些下面把几个最容易让人折腾一夜的问题列出来。4. 避坑记录烧录、挂载、权限与对齐的五个典型问题4.1 烧录工具提示分区重叠或地址越界现象用 SP Flash Tool 或者官方烧录工具下载固件时进度条卡在ERROR: STATUS_BS_ERROR日志显示分区地址重叠或者提示partition size too large。原因绝大多数情况是 scatter 里linear_start_addr没有接着上一个分区末尾写或者partition_size超过了 eMMC 实际剩余空间。MTK 平台对分区布局检查很严格flash 工具会按顺序计算每个分区的 startsize一旦下一个 start 不等于上一个 startsize直接判定重叠。解决检查 scatter 中所有分区的地址连续性。用脚本或者 python 循环读出来逐个计算找到上一个分区的 end 地址把 FDRAM 的 start 改成该值同时确保 end 不超出设备总容量。这里注意 eMMC 的总容量不是cat /proc/partitions里的总和而是mmcblk0的完整块数乘以块大小通常会比分区总和大一些留有冗余给 PMT 等内部区域。4.2 开机卡在 init 阶段logcat 显示 mount 失败现象机器烧录完成后重新开机一直停在 Android 启动动画前串口日志里能看到mount: /dev/block/by-name/FDRAM - /FDRAM failed有时还会伴随invalid argument。原因挂载失败常见于两种——文件系统格式不对或者内核中没有开启对应文件系统的驱动支持。FDRAM 如果格式化为 ext4但内核裁剪时把 ext4 模块去掉了挂载必然失败。个别项目里有人拿 FAT32 格式的镜像直接填到 scatter 里也会报错。解决用mkfs.ext4重新制作镜像文件确保分区里是真的 ext4 文件系统。命令如下。mkfs.ext4 -L FDRAM -b 4096 FDRAM.img 32768这条命令中-L FDRAM是设置卷标-b 4096指定块大小最后的32768是块数量乘以块大小就是 128MB。制作完成后用烧录工具单独下载 FDRAM.img 到对应分区再开机验证。挂载失败还可能是 fstab 里的设备节点路径写错MTK 平台的 by-name 符号链接不是一定有需要先用ls -l /dev/block/platform/bootdevice/by-name/确认 FDRAM 链接存在。4.3 SELinux 拦截导致应用层无法写入现象分区挂载成功df -h能看到/FDRAM大小也对但adb shell进去用 root 写文件没问题应用层一写就报Permission denied。原因SELinux 策略只允许了 init 的挂载操作没有允许应用进程对f dram_file目录读写。Android 应用跑在untrusted_app域里除非显式加入允许规则否则对这个新标签的目录一律拒绝。解决在 sepolicy 文件里给untrusted_app补上对f dram_file的读写规则。注意不是直接照抄 init 的 allow 规则而是看目标应用运行在什么 domain再决定开放的粒度。行业设备上如果让应用直接写也可以把目录标签定为media_rw_data_file复用系统已有的 media 存储域省去自定义标签的麻烦。4.4 分区对齐错误导致 bootloader 无法引导现象烧录过程完全正常但重新开机后屏幕黑屏串口无任何输出或者 LK 阶段反复重启。原因分区 start 地址没有按平台要求的 4KB/8KB 对齐LK 在解析分区表时计算结果异常导致 bootimage 找不到。这种情况比前三类隐蔽因为它不会在烧录时报错问题在启动阶段才暴露。解决把 scatter 中所有地址用十六进制打印出来手动确认每个地址的后三位为 0。不方便目测的话用富表操作工具或脚本去除末三位判断是否为零。下面是 python 检查逻辑。def check_alignment(addr): return int(addr, 16) % 4096 0 # 假设起始地址为 0x1a00000检查是否 4KB 对齐 print(check_alignment(0x1a00000))如果结果为 False就必须把起始地址向下对齐。操作原则是不能往前挪避免覆盖前一个分区只能把 FDRAM 的 start 往后对齐对齐后的分区大小也要同步调整防止 end 越界。4.5 升级 OTA 时分区被擦除现象设备接收 OTA 升级包后/FDRAM里的数据全部丢失就像格式化了一样。原因MTK 的 OTA 脚本在升级时会根据partition_name的配置决定是否保留数据。如果 FDRAM 被写进了一般的format_all列表里升级过程就会把它一并格式化。解决找到 OTA 升级脚本通常为updater-script或者 MTK 的meta_init在格式化分区的列表里把 FDRAM 去掉或者将它的 flag 标记为keep。另外如果走的是msf差分升级还需要在partition_table的比较逻辑中忽略 FDRAM 的大小变化。这部分没有统一答案完全看工程里 OTA 流程怎么写但原则就是自定义分区不要出现在全量格式化的名单里。如果设备需要固件安全更新而清空该分区那就另说。5. 验证与进阶从 df 检查到 OTA 兼容性的最后一步整套配置改完之后验证不能只靠开机有没有挂载成功。有一个细节是/FDRAM挂载成功后你在文件管理器里看不到它这不一定说明有问题因为挂载点未必在存储服务的扫描范围内。验证挂载是否可用最直接的是跑一条完整的读写检查链路。# 检查挂载与文件系统 adb shell df -h | grep FDRAM # 写入测试文件并回读 adb shell echo FDRAM mount test /FDRAM/test.txt adb shell cat /FDRAM/test.txt # 重启后再次确认持久化 adb reboot adb shell cat /FDRAM/test.txt这条验证命令的价值在于确认三件事挂载是否为 rw、写入是否落盘、重启后是否保留。如果最后一步读不到文件说明分区虽然在但挂载动作没有在开机阶段稳定执行回到上面检查 init.rc 的mount_all顺序和 SELinux 的recovery域。进阶一点的做法是把 FDRAM 的挂载方式从 ext4 改为 f2fs因为 MTK 平台的 eMMC 随机读写性能对 f2fs 更友好日志型应用写入频繁的场景下f2fs 比 ext4 更能抗碎片化。改法很简单制作镜像时从mkfs.ext4换成mkfs.f2fs同时在 fstab 里把文件系统类型改为f2fs。注意 f2fs 对分区大小有最小要求低于 128MB 时部分平台不认如果分区分小了这个方案只能放弃老老实实用 ext4。最后一个容易忽略的是 OTA 兼容性。如果你的设备后续要走 FDRAM 分区独立升级比如单独推送 FDRAM.img 的差分包那么在文件的keymaster或者升级服务里需要按分区名字做白名单不能走系统分区的完整校验。否则系统更新服务会对 FDRAM.img 做签名校验而自定义分区又没有对应 key升级会被拒绝。这个坑我当初在做某跨平台系统的时候踩得很深。从那以后我每次做完分区改动都会强制走一遍三个检查scatter 地址连续性、fstab 的 mount 路径是否和 SELinux 标签匹配、updater-script里有没有误格式化。这套流程走完FDRAM 分区基本不会再出问题希望帮到你。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?
咨询建站