数码之家

 找回密码
 立即注册
搜索
查看: 2035|回复: 1

[硬件] 转帖:IMX6UL eMMC加锁和解锁代码分析与实现

[复制链接]
发表于 2022-9-10 18:41:55 | 显示全部楼层 |阅读模式
背景

最近在使用eMMC作为外部存储设备过程中,出现eMMC两个分区数据全部被清空,文件系统数据和用户数据全部为0 ,在网上看到一篇文件说对eMMC加锁后强制解锁会清除用户数据,这样达到的效果与我遇到的类似,下面实现加锁和解锁代码进行测试。

环境

在uboot中添加对emmc命令加解锁测试比较方便,uboot版本2017.03

命令

对emmc加解锁主要是用CMD42命令进行操作,发送的命令和数据都是参考上面链接文章。

mmc现有命令



  • => mmc


  • mmc - MMC sub system





  • Usage:


  • mmc info - display info of the current MMC device


  • mmc read addr blk# cnt


  • mmc write addr blk# cnt


  • mmc erase blk# cnt


  • mmc rescan


  • mmc part - lists available partition on current mmc device


  • mmc dev [dev] [part] - show or set current mmc device [partition]


  • mmc list - lists available devices


  • mmc hwpartition [args...] - does hardware partitioning

添加lock/unlock/clear命令,cmd/mmc.c,cmd_mmc结构体中:



  •         U_BOOT_CMD_MKENT(lock, 1, 0, do_lock, "", ""),


  •         U_BOOT_CMD_MKENT(unlock, 1, 0, undo_lock, "", ""),


  •         U_BOOT_CMD_MKENT(clear, 1, 0, do_clear, "", ""),



  • static void lock_emmc(struct mmc *mmc)


  • {


  •         mmc_lock_emmc(mmc);


  • }


  • static int do_lock(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])


  • {


  •         struct mmc *mmc;





  •         if (curr_device < 0) {


  •                 if (get_mmc_num() > 0)


  •                         curr_device = 0;


  •                 else {


  •                         puts("No MMC device available\n");


  •                         return 1;


  •                 }


  •         }





  •         mmc = init_mmc_device(curr_device, false);


  •         if (!mmc)


  •                 return CMD_RET_FAILURE;





  •         lock_emmc(mmc);


  •         return CMD_RET_SUCCESS;


  • }

CMD42数据结构体

第0字节:设备锁/解锁模式

第1字节:密码长度,单位字节,这里设置1

第2字节:密码数据,这里设置简单的1



  • #define MMC_LOCK_UNLOCK                        42





  • struct mmc_pwd{


  •         u8 mode;


  •         u8 pwd_len;


  •         u8 pwd_data;


  • };

加锁

1. 若是没有选择设备,此时选择设备(CMD7),代码没实现,直接手动输入命令mmc dev 0。
           2. 设置block长度(CMD16),由8位设备锁/解锁模式,8位密码大小,总密码长度的大小决定。
           3. 发送CMD42命令,选择模式LOCK和SET_ PWD,另外加上PWD_LEN和PWD_DATA。



  • int mmc_lock_emmc(struct mmc *mmc)


  • {


  •         printf("mmc_lock_emmc\n");


  •         struct mmc_cmd cmd;


  •         struct mmc_data data;


  •         int timeout = 1000;





  •         printf("write_bl_len=%d\n",mmc->write_bl_len);//512





  •         if (mmc_set_blocklen(mmc, 3)){//设置block长度,总3个字节


  •                 printf("mmc_set_blocklen failed!\n");


  •                 return 0;


  •         }


  •         cmd.cmdidx = MMC_LOCK_UNLOCK;//CMD42


  •         cmd.cmdarg = 0;//


  •         cmd.resp_type = MMC_RSP_R1;





  •         struct mmc_pwd *src_pwd=(struct mmc_pwd *)malloc(3);


  •         if(NULL == src_pwd){


  •                 printf("malloc failed!\n");


  •                 return 0;


  •         }





  •         src_pwd->mode = 5;//lock and set pwd


  •         src_pwd->pwd_len = 1;


  •         src_pwd->pwd_data = 1;





  •         data.src = (char *)src_pwd;


  •         data.blocks = 1;


  •         data.blocksize = 3;


  •         data.flags = MMC_DATA_WRITE;





  •         if (mmc_send_cmd(mmc, &cmd, &data)) {


  •                 printf("mmc write failed\n");


  •                 return 0;


  •         }





  •         /* Waiting for the ready status */


  •         if (mmc_send_status(mmc, timeout)){


  •                 printf("mmc_send_status failed\n");


  •                 return 0;


  •         }





  •         return 0;


  • }


解锁

1. 若是没有选择设备,此时选择设备(CMD7),代码没实现,直接手动输入命令mmc dev 0。
           2. 设置block长度(CMD16),由8位设备锁/解锁模式,8位密码大小,总密码长度的大小决定。
           3. 发送CMD42命令,选择模式CLR_PWD,同样包括PWD_LEN和PWD,若是密码大小和内容正确,PWD内容会清除,且PWD_LEN设置为0。



  • int mmc_unlock_emmc(struct mmc *mmc)


  • {


  •         printf("mmc_unlock_emmc\n");


  •         struct mmc_cmd cmd;


  •         struct mmc_data data;


  •         int timeout = 1000;





  •         printf("write_bl_len=%d\n",mmc->write_bl_len);





  •         if (mmc_set_blocklen(mmc, 3)){


  •                 printf("mmc_set_blocklen failed!\n");


  •                 return 0;


  •         }


  •         cmd.cmdidx = MMC_LOCK_UNLOCK;


  •         cmd.cmdarg = 0;//


  •         cmd.resp_type = MMC_RSP_R1;





  •         struct mmc_pwd *src_pwd=(struct mmc_pwd *)malloc(3);


  •         if(NULL == src_pwd){


  •                 printf("malloc failed!\n");


  •                 return 0;


  •         }





  •         src_pwd->mode = 2;//unlock and clear pwd


  •         src_pwd->pwd_len = 1;


  •         src_pwd->pwd_data = 1;





  •         data.src = (char *)src_pwd;


  •         data.blocks = 1;


  •         data.blocksize = 3;


  •         data.flags = MMC_DATA_WRITE;





  •         if (mmc_send_cmd(mmc, &cmd, &data)) {


  •                 printf("mmc write failed\n");


  •                 return 0;


  •         }





  •         /* Waiting for the ready status */


  •         if (mmc_send_status(mmc, timeout)){


  •                 printf("mmc_send_status failed\n");


  •                 return 0;


  •         }





  •         return 0;


  • }

强制清除

用户忘了密码的情况,host可以清除所有PWD内容,这个过程叫做强行清除。
           1. 选择设备CMD7
           2. 设置block长度为1byte(CMD16)
           3. 发送CMD42,选择模式ERASE,data block表明模式ERASE。



  • struct mmc_pwd_clear{


  •         u8 mode;


  • };





  • int mmc_clear_emmc(struct mmc *mmc)


  • {


  •         printf("mmc_clear_emmc\n");


  •         struct mmc_cmd cmd;


  •         struct mmc_data data;


  •         int timeout = 1000;





  •         printf("write_bl_len=%d\n",mmc->write_bl_len);





  •         if (mmc_set_blocklen(mmc, 1)){


  •                 printf("mmc_set_blocklen failed!\n");


  •                 return 0;


  •         }


  •         cmd.cmdidx = MMC_LOCK_UNLOCK;


  •         cmd.cmdarg = 0;//


  •         cmd.resp_type = MMC_RSP_R1;





  •         struct mmc_pwd_clear *src_pwd_clear=(struct mmc_pwd *)malloc(1);


  •         if(NULL == src_pwd_clear){


  •                 printf("malloc failed!\n");


  •                 return 0;


  •         }





  •         src_pwd_clear->mode = 8;//q-clear





  •         data.src = (char *)src_pwd_clear;


  •         data.blocks = 1;


  •         data.blocksize = 1;


  •         data.flags = MMC_DATA_WRITE;





  •         if (mmc_send_cmd(mmc, &cmd, &data)) {


  •                 printf("mmc write failed\n");


  •                 return 0;


  •         }





  •         /* Waiting for the ready status */


  •         if (mmc_send_status(mmc, timeout)){


  •                 printf("mmc_send_status failed\n");


  •                 return 0;


  •         }





  •         return 0;


  • }

测试

选择设备

加锁前正常读

加锁

加锁后读失败

加锁后内核启动到文件系统读emmc失败打印



  • mmc1: new DDR MMC card at address 0001


  • mmcblk1: mmc1:0001 P1XXXX 7.20 GiB


  • mmcblk1boot0: mmc1:0001 P1XXXX partition 1 16.0 MiB


  • mmcblk1boot1: mmc1:0001 P1XXXX partition 2 16.0 MiB


  • mmcblk1rpmb: mmc1:0001 P1XXXX partition 3 128 KiB


  • hub 1-1:1.0: USB hub found


  • hub 1-1:1.0: 4 ports detected


  • usb 1-1.1: new high-speed USB device number 3 using ci_hdrc


  • usb 1-1.3: new full-speed USB device number 4 using ci_hdrc


  • EXT4-fs (ram0): mounted filesystem with ordered data mode. Opts: (null)


  • VFS: Mounted root (ext4 filesystem) readonly on device 1:0.


  • devtmpfs: mounted


  • Freeing unused kernel memory: 1024K (c0a00000 - c0b00000)


  • mmcblk1: error -110 sending stop command, original cmd response 0x2000900, card status 0x2400900


  • mmcblk1: error -110 transferring data, sector 0, nr 8, cmd response 0x2000900, card status 0x0


  • mmcblk1: error -110 sending stop command, original cmd response 0x2000900, card status 0x2400900


  • mmcblk1: error -110 transferring data, sector 0, nr 8, cmd response 0x2000900, card status 0x0


  • mmcblk1: retrying using single block read


  • mmcblk1: error -110 transferring data, sector 0, nr 8, cmd response 0x2000900, card status 0x0


  • blk_update_request: I/O error, dev mmcblk1, sector 0


  • mmcblk1: error -110 transferring data, sector 1, nr 7, cmd response 0x2000900, card status 0x0


  • blk_update_request: I/O error, dev mmcblk1, sector 1

解锁

解锁后读成功

加锁后强制清除

强制清除前分区存在

强制清除

强制清除后读成功,但数据全部为0

分区被删除

总结

加锁后强制清除会删除用户创建的分区和数据,EMMC出厂的数据会保留。与我遇到的情况有差异,我的是分区还在,但是分区里面的文件系统数据和用户数据全部被清空,原因待查中。。。


原帖地址:IMX6UL eMMC加锁和解锁代码分析与实现_王二车的博客-CSDN博客_emmc加密


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

APP|手机版|小黑屋|关于我们|联系我们|法律条款|技术知识分享平台

闽公网安备35020502000485号

闽ICP备2021002735号-2

GMT+8, 2025-5-22 05:56 , Processed in 0.156000 second(s), 10 queries , Redis On.

Powered by Discuz!

© 2006-2025 MyDigit.Net

快速回复 返回顶部 返回列表