Customer requirements:
Encrypted SD cards can only be used in fixed machines, and the machine can not read cards other than encryption cards.
Solutions:
1. How to identify the encryption card:
There are CSR registers in the SD card protocol, where bit25 is the card_is_lock flag
If it's 1, it's locked.
Decision Card Encryption Code:
@@ -993,15 +1033,33 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr, * Select card, as all following commands rely on that. */ if (!mmc_host_is_spi(host)) { - err = mmc_select_card(card); + err = mmc_select_card_with_resp(card,resp);//When sending the pick-up card, the response data is retrieved, and the response data format is R1. + printk("zztest---mmc_host_is_spi ok\n"); if (err) goto free_card; + printk("---respis %x\n",resp[0]); + if(resp[0]&0x02000000){ //If lock's flag bit is 1, the password is passed in and decrypted + printk("---sdcard is locked, clear lock---\n"); + err = mmc_unlock_card(card,host); + if(err) + goto free_card; + }else{ + //Normally, the next step is to set up the card, where the customer needs to report the error back directly. + printk("---sdcard is normal,dont setup it---\n"); + err = -110; + goto free_card; + } + printk("zztest---mmc_clear_card ok\n"); }
2. How to decrypt:
SD card protocol refers to the lock and unlock command of SD card:
Bit3 is the erase mark
Bit2 is unlock, lock flag, 0unlock, 1lock
Bit1 is a password clearance flag and 1 is a password clearance flag.
Bit0 sets a password flag and a password for 1
PWDS_LEN is the password length
Password data is password data
3. Decrypt code:
int mmc_unlock_card(struct mmc_card *mmc,struct mmc_host *host) +{ + + struct mmc_request mrq = {NULL}; + struct mmc_command cmd = {0}; + struct mmc_data data = {0}; + struct scatterlist sg; + int i ; + u8 *data_buf; + int err = 0; + + printk("mmc_unlock_emmc\n"); + data_buf = kmalloc(512, GFP_KERNEL); + if (!data_buf) + return -ENOMEM; + //Pass in decryption Command + password + data_buf[0] = 0x00; + data_buf[1] = 0x08; + data_buf[2] = 'C'; + data_buf[3] = 'h'; + data_buf[4] = 'a'; + data_buf[5] = 'n'; + data_buf[6] = 'g'; + data_buf[7] = 'h'; + data_buf[8] = 'u'; + data_buf[9] = 'a'; + + if (mmc_set_blocklen(mmc, 512)){ + printk("mmc_set_blocklen failed!\n"); + return 0; + } + + mrq.cmd = &cmd; + mrq.data = &data; + + cmd.opcode = MMC_LOCK_UNLOCK; + cmd.arg = 0;// + cmd.flags = MMC_RSP_R1B | MMC_CMD_ADTC;; + cmd.retries = 3; + + data.blocks = 1; + data.blksz = 512; + data.flags = MMC_DATA_WRITE; + + data.sg = &sg; + data.sg_len = 1; + sg_init_one(&sg, data_buf, 512); + + mmc_set_data_timeout(&data,mmc); + mmc_wait_for_req(host, &mrq); + printk("zztest---mmc_set_data_timeout is OK\n"); + kfree(data_buf); + + for(i=0;i<4;i++){ + printk("--rep_data is %d\n",cmd.resp[i]); + } + if (cmd.error) + return cmd.error; + if (data.error) + return data.error; + return err; + +}
Complete code modification:
diff --git a/drivers/mmc/core/bus.h b/drivers/mmc/core/bus.h old mode 100644 new mode 100755 diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c old mode 100644 new mode 100755 index 5f46756..fc138f5 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -620,6 +620,7 @@ out: return err; } + MMC_DEV_ATTR(cid, "%08x%08x%08x%08x\n", card->raw_cid[0], card->raw_cid[1], card->raw_cid[2], card->raw_cid[3]); MMC_DEV_ATTR(csd, "%08x%08x%08x%08x\n", card->raw_csd[0], card->raw_csd[1], diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c old mode 100644 new mode 100755 index 07fb48d..b6aff49 --- a/drivers/mmc/core/mmc_ops.c +++ b/drivers/mmc/core/mmc_ops.c @@ -93,6 +93,40 @@ int mmc_deselect_cards(struct mmc_host *host) return _mmc_select_card(host, NULL); } +static int _mmc_select_card_with_resp(struct mmc_host *host, struct mmc_card *card,u32 *buf) +{ + int err; + struct mmc_command cmd = {0}; + + BUG_ON(!host); + + cmd.opcode = MMC_SELECT_CARD; + + if (card) { + cmd.arg = card->rca << 16; + cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; + } else { + cmd.arg = 0; + cmd.flags = MMC_RSP_NONE | MMC_CMD_AC; + } + + err = mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES); + if (err) + return err; + + memcpy(buf, cmd.resp, sizeof(u32) * 4); + return 0; +} + + +int mmc_select_card_with_resp(struct mmc_card *card,u32 *buf) +{ + BUG_ON(!card); + + return _mmc_select_card_with_resp(card->host, card,buf); +} + + int mmc_go_idle(struct mmc_host *host) { int err; @@ -305,6 +339,197 @@ mmc_send_cxd_data(struct mmc_card *card, struct mmc_host *host, return 0; } +struct mmc_pwd{ + u8 mode; + u8 pwd_len; + u8 pwd_data; +}; + + +int mmc_lock_card(struct mmc_card* mmc ,struct mmc_host *host) +{ + + struct mmc_request mrq = {NULL}; + struct mmc_command cmd = {0}; + struct mmc_data data = {0}; + struct scatterlist sg; + u8 *data_buf; + int err = 0; + + printk("mmc_lock_emmc\n"); + data_buf = kmalloc(512, GFP_KERNEL); + if (!data_buf) + return -ENOMEM; + + data_buf[0] = 0x01; + data_buf[1] = 0x08; + data_buf[2] = 'C'; + data_buf[3] = 'h'; + data_buf[4] = 'a'; + data_buf[5] = 'n'; + data_buf[6] = 'g'; + data_buf[7] = 'h'; + data_buf[8] = 'u'; + data_buf[9] = 'a'; + + if (mmc_set_blocklen(mmc, 512)){ + printk("mmc_set_blocklen failed!\n"); + return 0; + } + printk("zztest---mmc_set_blocklen OK\n"); + + mrq.cmd = &cmd; + mrq.data = &data; + + cmd.opcode = MMC_LOCK_UNLOCK; + cmd.arg = 0;// + cmd.flags = MMC_RSP_R1B | MMC_CMD_ADTC;; + cmd.retries = 3; + + data.blocks = 1; + data.blksz = 512; + data.flags = MMC_DATA_WRITE; + + data.sg = &sg; + data.sg_len = 1; + sg_init_one(&sg, data_buf, 512); + + mmc_set_data_timeout(&data,mmc); + mmc_wait_for_req(host, &mrq); + + kfree(data_buf); + + if (cmd.error) + return cmd.error; + if (data.error) + return data.error; + return err; +} +EXPORT_SYMBOL_GPL(mmc_lock_card); + + +int mmc_unlock_card(struct mmc_card *mmc,struct mmc_host *host) +{ + + struct mmc_request mrq = {NULL}; + struct mmc_command cmd = {0}; + struct mmc_data data = {0}; + struct scatterlist sg; + //u32 rep_data[4]={0}; + int i ; + u8 *data_buf; + int err = 0; + + printk("mmc_unlock_emmc\n"); + data_buf = kmalloc(512, GFP_KERNEL); + if (!data_buf) + return -ENOMEM; + + data_buf[0] = 0x00; + data_buf[1] = 0x08; + data_buf[2] = 'C'; + data_buf[3] = 'h'; + data_buf[4] = 'a'; + data_buf[5] = 'n'; + data_buf[6] = 'g'; + data_buf[7] = 'h'; + data_buf[8] = 'u'; + data_buf[9] = 'a'; + + if (mmc_set_blocklen(mmc, 512)){ + printk("mmc_set_blocklen failed!\n"); + return 0; + } + printk("zztest---mmc_set_blocklen OK\n"); + + mrq.cmd = &cmd; + mrq.data = &data; + + cmd.opcode = MMC_LOCK_UNLOCK; + cmd.arg = 0;// + cmd.flags = MMC_RSP_R1B | MMC_CMD_ADTC;; + cmd.retries = 3; + + data.blocks = 1; + data.blksz = 512; + data.flags = MMC_DATA_WRITE; + + data.sg = &sg; + data.sg_len = 1; + sg_init_one(&sg, data_buf, 512); + + mmc_set_data_timeout(&data,mmc); + mmc_wait_for_req(host, &mrq); + printk("zztest---mmc_set_data_timeout is OK\n"); + kfree(data_buf); + + for(i=0;i<4;i++){ + printk("--rep_data is %d\n",cmd.resp[i]); + } + if (cmd.error) + return cmd.error; + if (data.error) + return data.error; + return err; + +} +EXPORT_SYMBOL_GPL(mmc_unlock_card); + +struct mmc_pwd_clear{ + u8 mode; +}; + +int mmc_clear_card(struct mmc_card *mmc,struct mmc_host *host) +{ + + struct mmc_request mrq = {NULL}; + struct mmc_command cmd = {0}; + struct mmc_data data = {0}; + struct scatterlist sg; + u8 *data_buf; + int err = 0; + + printk("mmc_clear_emmc\n"); + + data_buf = kmalloc(512, GFP_KERNEL); + if (!data_buf) + return -ENOMEM; + + data_buf[0] = 0x08; + if (mmc_set_blocklen(mmc, 512)){ + printk("mmc_set_blocklen failed!\n"); + return 0; + } + printk("zztest---mmc_set_blocklen OK\n"); + + mrq.cmd = &cmd; + mrq.data = &data; + cmd.opcode = MMC_LOCK_UNLOCK; + cmd.arg = 0;// + cmd.flags = MMC_RSP_R1| MMC_CMD_ADTC; + cmd.retries = 3; + + data.blocks = 1; + data.blksz = 512; + data.flags = MMC_DATA_WRITE; + + data.sg = &sg; + data.sg_len = 1; + + mmc_set_data_timeout(&data,mmc); + printk("zztest---mmc_set_data_timeout is OK\n"); + sg_init_one(&sg, data_buf, 512); + mmc_wait_for_req(host, &mrq); + + kfree(data_buf); + if (cmd.error) + return cmd.error; + if (data.error) + return data.error; + return err; +} + + int mmc_send_csd(struct mmc_card *card, u32 *csd) { int ret, i; diff --git a/drivers/mmc/core/mmc_ops.h b/drivers/mmc/core/mmc_ops.h old mode 100644 new mode 100755 index 40f6648..ce78697 --- a/drivers/mmc/core/mmc_ops.h +++ b/drivers/mmc/core/mmc_ops.h @@ -27,5 +27,9 @@ int mmc_spi_set_crc(struct mmc_host *host, int use_crc); int mmc_bus_test(struct mmc_card *card, u8 bus_width); int mmc_send_hpi_cmd(struct mmc_card *card, u32 *status); int mmc_switch_status_error(struct mmc_host *host, u32 status); +int mmc_lock_card(struct mmc_card* mmc ,struct mmc_host *host); +int mmc_unlock_card(struct mmc_card* mmc ,struct mmc_host *host); +int mmc_clear_card(struct mmc_card *mmc,struct mmc_host *host); +int mmc_select_card_with_resp(struct mmc_card *card,u32 *buf); #endif diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c old mode 100644 new mode 100755 index b03fbd8..7cb29e7 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c @@ -676,6 +676,41 @@ out: return err; } + +static ssize_t name_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct mmc_card *card = mmc_dev_to_card(dev); + struct mmc_host *host = card->host; + int ret ; + if((card != NULL)&&(host != NULL)){ + ret = mmc_lock_card(card,host); + } + if(ret) + printk("zztest--mmc_lock_card error\n"); + return sprintf(buf, "%s\n", card->cid.prod_name); +} + +static ssize_t oemid_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct mmc_card *card = mmc_dev_to_card(dev); + struct mmc_host *host = card->host; + int ret ; + if((card != NULL)&&(host != NULL)){ + ret = mmc_unlock_card(card,host); + } + //mmc_select_card(card,host); + if(ret) + printk("zztest--mmc_bus_test error\n"); + return sprintf(buf, "%d\n", card->cid.oemid); +} + +static DEVICE_ATTR(oemid, S_IRUGO, oemid_show, NULL); +static DEVICE_ATTR(name, S_IRUGO, name_show, NULL); + MMC_DEV_ATTR(cid, "%08x%08x%08x%08x\n", card->raw_cid[0], card->raw_cid[1], card->raw_cid[2], card->raw_cid[3]); MMC_DEV_ATTR(csd, "%08x%08x%08x%08x\n", card->raw_csd[0], card->raw_csd[1], @@ -687,8 +722,8 @@ MMC_DEV_ATTR(preferred_erase_size, "%u\n", card->pref_erase << 9); MMC_DEV_ATTR(fwrev, "0x%x\n", card->cid.fwrev); MMC_DEV_ATTR(hwrev, "0x%x\n", card->cid.hwrev); MMC_DEV_ATTR(manfid, "0x%06x\n", card->cid.manfid); -MMC_DEV_ATTR(name, "%s\n", card->cid.prod_name); -MMC_DEV_ATTR(oemid, "0x%04x\n", card->cid.oemid); +//MMC_DEV_ATTR(name, "%s\n", card->cid.prod_name); +//MMC_DEV_ATTR(oemid, "0x%04x\n", card->cid.oemid); MMC_DEV_ATTR(serial, "0x%08x\n", card->cid.serial); @@ -939,10 +974,12 @@ void mmc_sd_go_highspeed(struct mmc_card *card) * In the case of a resume, "oldcard" will contain the card * we're trying to reinitialise. */ + static int mmc_sd_init_card(struct mmc_host *host, u32 ocr, struct mmc_card *oldcard) { struct mmc_card *card; + u32 resp[4]={0}; int err; u32 cid[4]; u32 rocr = 0; @@ -954,6 +991,7 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr, if (err) return err; + printk("zztest---mmc_sd_get_cid ok\n"); if (oldcard) { if (memcmp(cid, oldcard->raw_cid, sizeof(cid)) != 0) return -ENOENT; @@ -977,12 +1015,14 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr, */ if (!mmc_host_is_spi(host)) { err = mmc_send_relative_addr(host, &card->rca); + printk("zztest--mmc_send_relative_addr\n"); if (err) goto free_card; } if (!oldcard) { err = mmc_sd_get_csd(host, card); + printk("zztest--mmc_sd_get_csd\n"); if (err) goto free_card; @@ -993,15 +1033,33 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr, * Select card, as all following commands rely on that. */ if (!mmc_host_is_spi(host)) { - err = mmc_select_card(card); + err = mmc_select_card_with_resp(card,resp); + printk("zztest---mmc_host_is_spi ok\n"); if (err) goto free_card; + printk("zztest---mmc_clear_card ok\n"); + printk("---respis %x\n",resp[0]); + if(resp[0]&0x02000000){ + printk("---sdcard is locked, clear lock---\n"); + err = mmc_unlock_card(card,host); + if(err) + goto free_card; + }else{ + //Customer requirements, unconventional operations + printk("---sdcard is normal,dont setup it---\n"); + err = -110; + goto free_card; + } + printk("zztest---mmc_clear_card ok\n"); } + err = mmc_sd_setup_card(host, card, oldcard != NULL); - if (err) + if (err) goto free_card; + + printk("zztest---mmc_sd_setup_card ok\n"); /* Initialization sequence for UHS-I cards */ if (rocr & SD_ROCR_S18A) { err = mmc_sd_init_uhs_card(card); @@ -1295,6 +1353,7 @@ int mmc_attach_sd(struct mmc_host *host) err = mmc_spi_read_ocr(host, 0, &ocr); if (err) goto err; + printk("zztest----mmc_spi_read_ocr ok\n"); } rocr = mmc_select_voltage(host, ocr); @@ -1306,7 +1365,7 @@ int mmc_attach_sd(struct mmc_host *host) err = -EINVAL; goto err; } - + printk("zztest----mmc_select_voltage ok\n"); /* * Detect and init the card. */ @@ -1314,6 +1373,7 @@ int mmc_attach_sd(struct mmc_host *host) if (err) goto err; + printk("zztest----mmc_sd_init_card ok\n"); mmc_release_host(host); err = mmc_add_card(host->card); mmc_claim_host(host);
Reference blog:
https://blog.csdn.net/g_salamander/article/details/14167055
https://blog.csdn.net/Code_DZhangTeng/article/details/79504643