引言
最近遇到调用Nvram服务写SN号失败的问题,
抓取了日志,没有看到明显的异常
Line 372: 04-20 12:57:20.187 411 411 D NVRAM : NVM_GetLIDByName /mnt/vendor/nvdata/APCFG/APRDEB/PRODUCT_INFO
Line 373: 04-20 12:57:20.188 411 411 D NVRAM : NVRAM: NVM_GetLIDByName Lid =61
Line 376: 04-20 12:57:20.188 411 411 D NVRAM : 61 is in new nvram partition!!!
Line 377: 04-20 12:57:20.188 411 411 D NVRAM : New NVRAM partition name is /dev/block/platform/bootdevice/by-name/proinfo.
Line 390: 04-20 12:57:20.194 411 411 D NVRAM : 61 is in new nvram partition!!!
Line 391: 04-20 12:57:20.195 411 411 D NVRAM : Read Done!Size is 64
Line 392: 04-20 12:57:20.195 411 411 D NVRAM : nvramstr buff[0]0, buff[1]0, buff[2]0, buff[3]0, buff[4]0, buff[5]0, buff[6]0, buff[7]0, buff[8]0
Line 393: 04-20 12:57:20.195 411 411 D NVRAM : nvramstr 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
Line 394: 04-20 12:57:20.195 411 411 D NVRAM :
Line 397: 04-20 12:57:20.198 411 411 D NVRAM : NVM_GetLIDByName /mnt/vendor/nvdata/APCFG/APRDEB/PRODUCT_INFO
Line 398: 04-20 12:57:20.198 411 411 D NVRAM : NVRAM: NVM_GetLIDByName Lid =61
Line 399: 04-20 12:57:20.198 411 411 D NVRAM : 61 is in new nvram partition!!!
Line 400: 04-20 12:57:20.198 411 411 D NVRAM : New NVRAM partition name is /dev/block/platform/bootdevice/by-name/proinfo.
Line 402: 04-20 12:57:20.199 411 411 D NVRAM : 61 is in new nvram partition!!!
Line 403: 04-20 12:57:20.199 411 411 D NVRAM : Read Done!Size is 64
Line 404: 04-20 12:57:20.199 411 411 D NVRAM : nvramstr buff[0]0, buff[1]0, buff[2]0, buff[3]0, buff[4]0, buff[5]0, buff[6]0, buff[7]0, buff[8]0
Line 405: 04-20 12:57:20.199 411 411 D NVRAM : nvramstr 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
Line 406: 04-20 12:57:20.199 411 411 D NVRAM :
Line 468: 04-20 12:57:21.651 411 411 D NVRAM : NVM_GetLIDByName /mnt/vendor/nvdata/APCFG/APRDEB/PRODUCT_INFO
Line 469: 04-20 12:57:21.651 411 411 D NVRAM : NVRAM: NVM_GetLIDByName Lid =61
Line 470: 04-20 12:57:21.652 411 411 D NVRAM : 61 is in new nvram partition!!!
Line 471: 04-20 12:57:21.652 411 411 D NVRAM : New NVRAM partition name is /dev/block/platform/bootdevice/by-name/proinfo.
Line 472: 04-20 12:57:21.652 411 411 D NVRAM : RecNum is :1
解决方案
对这一块完全不懂,只能先去网上查查相关资料,这里要感谢大佬的分享资料,对我帮助很大
Android10.0 压力测试–恢复出厂自动测试工具
android10.0(Q) Nvram 新增节点
Nvram新增节点,遇到可读不可写的问题
问题根本原因是正常开机情况下, product info 会被 EMMC 写保护挡下 power on write protect权限问题
解决办法,注释里面的 set_write_protect()调用
vendor\mediatek\proprietary\bootable\bootloader\lk\platform\mt6771\write_protect_ab.c
diff --git a/vendor/mediatek/proprietary/bootable/bootloader/lk/platform/mt6771/write_protect_ab.c b/vendor/mediatek/proprietary/bootable/bootloader/lk/platform/mt6771/write_protect_ab.c
index 16f39ed8a9..d280ed1445 100755
--- a/vendor/mediatek/proprietary/bootable/bootloader/lk/platform/mt6771/write_protect_ab.c
+++ b/vendor/mediatek/proprietary/bootable/bootloader/lk/platform/mt6771/write_protect_ab.c
@@ -160,9 +160,9 @@ void write_protect_flow(void)
#endif
if (!bypass_wp) {
- ret = set_write_protect();
+ /*ret = set_write_protect();
if (ret != 0)
- pal_log_err("write protect fail! \n");
+ pal_log_err("write protect fail! \n");*/
pal_log_err("write protect Done! \n");
} else
pal_log_err("Bypass write protect! \n");
编译,刷机,可以读到sn号。
备用丶解决方案
问题到这里还没有完全结束,这种解决方案不是最完美的
int set_write_protect(void)
{
int err = 0;
const char *ab_suffix = NULL;
char wp_start[WRITE_PROTECT_PARTITION_NAME_SZ] = {0};
char wp_end[WRITE_PROTECT_PARTITION_NAME_SZ] = {0};
ab_suffix = get_suffix();
if (ab_suffix == NULL) {
dprintf(CRITICAL, "[%s] invalid address.\n", __func__);
return ERR_INVALID_ADDR;
}
#ifdef MTK_UFS_OTP
/*
UFS OTP分区
*所有启动模式均应考虑OTP分区是否需要锁定
*注意:请确保在执行OTP分区锁定之前先执行其他分区。 因为我们不允许以下情况:
*-如果当前的安全写保护配置块中已经存在OTP条目,并且OTP分区锁定请求不是第一个请求。 对于这种情况,将返回UFS_OTP_ALREADY_LOCKED
并跳过后面的所有其他分区锁定。
* /
/* 检查是否需要立即锁定OTP分区 */
if (ufs_lk_otp_lock_req("otp") == 1) {
pal_log_info("[%s] Lock OTP partition ... \n", __func__);
err = partition_write_prot_set("otp", "otp", WP_PERMANENT);
if (err != 0) {
pal_log_err("[%s] Lock otp failed: %d\n", __func__, err);
return err;
}
} else
pal_log_info("[%s] Lock OTP is not required\n", __func__);
#endif /* MTK_UFS_OTP */
#if defined(MTK_POWER_ON_WRITE_PROTECT)
if (g_boot_mode == NORMAL_BOOT) {
pal_log_info("[%s] Lock boot region \n", __func__);
err = partition_write_prot_set("preloader", "preloader", WP_POWER_ON);
if (err != 0) {
pal_log_err("[%s] Lock boot region failed: %d\n", __func__, err);
return err;
}
snprintf(wp_start, WRITE_PROTECT_PARTITION_NAME_SZ, "sec1");
snprintf(wp_end, WRITE_PROTECT_PARTITION_NAME_SZ, "logo");
pal_log_info("[%s]: Lock %s->%s \n", __func__, wp_start, wp_end);
err = partition_write_prot_set(wp_start, wp_end, WP_POWER_ON);
if (err != 0) {
pal_log_err("[%s]: Lock %s->%s failed:%d\n",
__func__, wp_start, wp_end, err);
return err;
}
memset(wp_start, 0, sizeof(char) * WRITE_PROTECT_PARTITION_NAME_SZ);
memset(wp_end, 0, sizeof(char) * WRITE_PROTECT_PARTITION_NAME_SZ);
snprintf(wp_start, WRITE_PROTECT_PARTITION_NAME_SZ, "md1img%s", ab_suffix);
#ifdef MTK_SECURITY_SW_SUPPORT
if (TRUE == seclib_sec_boot_enabled(TRUE))
snprintf(wp_end, WRITE_PROTECT_PARTITION_NAME_SZ, "system%s", ab_suffix);
else
snprintf(wp_end, WRITE_PROTECT_PARTITION_NAME_SZ, "tee%s", ab_suffix);
#else
snprintf(wp_end, WRITE_PROTECT_PARTITION_NAME_SZ, "tee%s", ab_suffix);
#endif
pal_log_info("[%s]: Lock %s->%s\n", __func__, wp_start, wp_end);
err = partition_write_prot_set(wp_start, wp_end, WP_POWER_ON);
if (err != 0) {
pal_log_err("[%s]: Lock %s->%s failed:%d\n",
__func__, wp_start, wp_end, err);
return err;
}
}
pal_log_info("[%s] Lock seccfg\n", __func__);
err = partition_write_prot_set("seccfg", "seccfg", WP_POWER_ON);
if (err != 0) {
pal_log_err("[%s]: Lock seccfg failed:%d\n", __func__, err);
return err;
}
#endif
return 0;
}
阅读源码,分析一下set_write_protect()方法的逻辑,partition_write_prot_set(wp_start, wp_end, WP_POWER_ON)方法去设置分区的写保护,从wp_start分区到wp_end分区,代码中设置了sec1分区到logo分区的写保护
找到分区的表格,proinfo和nvram都在写保护的区间中
\device\mediatek\build\build\tools\ptgen\MT6771\partition_table_MT6771_emmc.csv
根据代码逻辑,我们缩小写保护分区的大小
diff --git a/vendor/mediatek/proprietary/bootable/bootloader/lk/platform/mt6771/write_protect_ab.c b/vendor/mediatek/proprietary/bootable/bootloader/lk/platform/mt6771/write_protect_ab.c
index 23ff5f93e7..16f39ed8a9 100755
--- a/vendor/mediatek/proprietary/bootable/bootloader/lk/platform/mt6771/write_protect_ab.c
+++ b/vendor/mediatek/proprietary/bootable/bootloader/lk/platform/mt6771/write_protect_ab.c
@@ -102,9 +102,10 @@ int set_write_protect(void)
pal_log_err("[%s] Lock boot region failed: %d\n", __func__, err);
return err;
}
- snprintf(wp_start, WRITE_PROTECT_PARTITION_NAME_SZ, "sec1");
- snprintf(wp_end, WRITE_PROTECT_PARTITION_NAME_SZ, "logo");
+ snprintf(wp_start, WRITE_PROTECT_PARTITION_NAME_SZ, "efuse");
+ snprintf(wp_end, WRITE_PROTECT_PARTITION_NAME_SZ, "nvram");
pal_log_info("[%s]: Lock %s->%s \n", __func__, wp_start, wp_end);
err = partition_write_prot_set(wp_start, wp_end, WP_POWER_ON);
编译,刷机,写sn号成功。
在已有解决方案的基础上,进一步分析源码,理清代码逻辑,寻找其他解决方案,能加快能力的提升。
注:我修改的是write_protect_ab.c文件,而不是write_protect.c文件,是因为该项目开启了a/b分区。
没有开启a/b分区的,还是应该修改write_protect.c文件。