mmc_rpmb.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741
  1. /* Copyright Statement:
  2. *
  3. * This software/firmware and related documentation ("MediaTek Software") are
  4. * protected under relevant copyright laws. The information contained herein
  5. * is confidential and proprietary to MediaTek Inc. and/or its licensors.
  6. * Without the prior written permission of MediaTek inc. and/or its licensors,
  7. * any reproduction, modification, use or disclosure of MediaTek Software,
  8. * and information contained herein, in whole or in part, shall be strictly prohibited.
  9. */
  10. /* MediaTek Inc. (C) 2018. All rights reserved.
  11. *
  12. * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
  13. * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
  14. * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON
  15. * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
  16. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
  17. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
  18. * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
  19. * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
  20. * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH
  21. * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES
  22. * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES
  23. * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK
  24. * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
  25. * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND
  26. * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
  27. * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
  28. * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO
  29. * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
  30. *
  31. * The following software/firmware and/or related documentation ("MediaTek Software")
  32. * have been modified by MediaTek Inc. All revisions are subject to any receiver\'s
  33. * applicable license agreements with MediaTek Inc.
  34. */
  35. #include "msdc.h"
  36. #include "mmc_rpmb.h"
  37. #include "memory_layout.h"
  38. #define RPMB_KEY_DUMP 0
  39. #if defined(MMC_MSDC_DRV_LK)
  40. extern int32_t rpmb_hmac(uint32_t pattern, uint32_t size);
  41. extern int32_t rpmb_init(void);
  42. u32 *shared_msg_addr =(u32 *)(LK_HMAC_BASE+0x40);
  43. u32 *shared_hmac_addr = (u32 *)(LK_HMAC_BASE+0xCE0);
  44. #include <stdlib.h>
  45. #include <arch/arm/mmu.h>
  46. #include <arch/ops.h>
  47. //For arch_clean_invalidate_cache_range() is defined in bootable/bootloader/include/arch/ops.h
  48. #endif
  49. #ifndef swab16
  50. #define swab16(x) \
  51. ((u16)( \
  52. (((u16)(x) & (u16)0x00ffU) << 8) | \
  53. (((u16)(x) & (u16)0xff00U) >> 8) ))
  54. #endif
  55. #ifndef swab32
  56. #define swab32(x) \
  57. ((u32)( \
  58. (((u32)(x) & (u32)0x000000ffUL) << 24) | \
  59. (((u32)(x) & (u32)0x0000ff00UL) << 8) | \
  60. (((u32)(x) & (u32)0x00ff0000UL) >> 8) | \
  61. (((u32)(x) & (u32)0xff000000UL) >> 24) ))
  62. #endif
  63. #ifndef cpu_to_be16
  64. #define cpu_to_be16(x) ({ u16 _x = x; swab16(_x); })
  65. #endif
  66. #ifndef cpu_to_be32
  67. #define cpu_to_be32(x) ({ u32 _x = x; swab32(_x); })
  68. #endif
  69. #ifndef be16_to_cpu
  70. #define be16_to_cpu(x) cpu_to_be16(x)
  71. #endif
  72. #ifndef be32_to_cpu
  73. #define be32_to_cpu(x) cpu_to_be32(x)
  74. #endif
  75. static const char * const rpmb_err_msg[] = {
  76. "",
  77. "General failure",
  78. "Authentication failure",
  79. "Counter failure",
  80. "Address failure",
  81. "Write failure",
  82. "Read failure",
  83. "Authentication key not yet programmed",
  84. };
  85. #if defined(MMC_MSDC_DRV_LK) && !defined(MTK_UFS_SUPPORT)
  86. int init_rpmb_sharemem(void)
  87. {
  88. uint32_t start, size;
  89. int ret = 0;
  90. /* map shared memory for rpmb */
  91. start = ROUNDDOWN((uint32_t)LK_HMAC_BASE, PAGE_SIZE);
  92. size = PAGE_SIZE;
  93. arch_mmu_map((uint64_t)start, (uint32_t)start,
  94. MMU_MEMORY_TYPE_NORMAL_WRITE_BACK | MMU_MEMORY_AP_P_RW_U_NA,
  95. ROUNDUP(size, PAGE_SIZE));
  96. ret = rpmb_init();
  97. if (ret) {
  98. msdc_pr_err("[%s]: RPMB rpmb_init error, ret = %d \n", __func__, ret);
  99. return ret;
  100. }
  101. return 0;
  102. }
  103. #endif
  104. static int mmc_rpmb_pre_frame(struct mmc_rpmb_req *rpmb_req)
  105. {
  106. struct mmc_rpmb_cfg *rpmb_cfg = rpmb_req->rpmb_cfg;
  107. u8 *data_frame = rpmb_req->data_frame;
  108. #if defined(MMC_MSDC_DRV_LK)
  109. u32 wc;
  110. #endif
  111. u16 blks = rpmb_cfg->blk_cnt;
  112. u16 addr;
  113. u16 type;
  114. u8 *nonce = rpmb_cfg->nonce;
  115. memset(data_frame, 0, 512 * blks);
  116. type = cpu_to_be16(rpmb_cfg->type);
  117. memcpy(data_frame + RPMB_TYPE_BEG, &type, 2);
  118. if (rpmb_cfg->type == RPMB_PROGRAM_KEY) {
  119. memcpy(data_frame + RPMB_MAC_BEG, rpmb_cfg->mac, RPMB_SZ_MAC);
  120. } else if (rpmb_cfg->type == RPMB_GET_WRITE_COUNTER ||
  121. rpmb_cfg->type == RPMB_READ_DATA) {
  122. /*
  123. * One package prepared
  124. * This request needs Nonce and type
  125. * If is data read, then also need addr
  126. */
  127. if (rpmb_cfg->type == RPMB_READ_DATA) {
  128. addr = cpu_to_be16(rpmb_cfg->addr);
  129. memcpy(data_frame + RPMB_ADDR_BEG, &addr, 2);
  130. }
  131. /* convert Nonce code */
  132. memcpy(data_frame + RPMB_NONCE_BEG, nonce, RPMB_SZ_NONCE);
  133. #if defined(MMC_MSDC_DRV_LK)
  134. } else if (rpmb_cfg->type == RPMB_WRITE_DATA) {
  135. addr = cpu_to_be16(rpmb_cfg->addr);
  136. memcpy(data_frame + RPMB_ADDR_BEG, &addr, 2);
  137. wc = cpu_to_be32(rpmb_cfg->wc);
  138. memcpy(data_frame + RPMB_WCOUNTER_BEG, &wc, 4);
  139. blks = cpu_to_be16(rpmb_cfg->blk_cnt);
  140. memcpy(data_frame + RPMB_BLKS_BEG, &blks, 2);
  141. #endif
  142. }
  143. return 0;
  144. }
  145. static int mmc_rpmb_post_frame(struct mmc_rpmb_req *rpmb_req)
  146. {
  147. struct mmc_rpmb_cfg *rpmb_cfg = rpmb_req->rpmb_cfg;
  148. u8 *data_frame = rpmb_req->data_frame;
  149. u16 result;
  150. memcpy(&result, data_frame + RPMB_RES_BEG, 2);
  151. rpmb_cfg->result = cpu_to_be16(result);
  152. if (rpmb_cfg->type == RPMB_GET_WRITE_COUNTER ||
  153. rpmb_cfg->type == RPMB_WRITE_DATA) {
  154. rpmb_cfg->wc = cpu_to_be32(*(u32 *)&data_frame[RPMB_WCOUNTER_BEG]);
  155. msdc_pr_info("%s, rpmb_cfg->wc = %x\n", __func__, rpmb_cfg->wc);
  156. }
  157. if (rpmb_cfg->type == RPMB_GET_WRITE_COUNTER ||
  158. rpmb_cfg->type == RPMB_READ_DATA) {
  159. /* nonce copy */
  160. memcpy(rpmb_cfg->nonce, data_frame + RPMB_NONCE_BEG, RPMB_SZ_NONCE);
  161. }
  162. if (rpmb_cfg->mac) {
  163. /*
  164. * To do. compute if mac is legal or not. Current we don't do this since we just perform get wc to check if we need set key.
  165. */
  166. #if defined(MMC_MSDC_DRV_LK)
  167. memcpy(rpmb_cfg->mac, data_frame + RPMB_MAC_BEG, RPMB_SZ_MAC);
  168. #endif
  169. }
  170. return 0;
  171. }
  172. static int mmc_rpmb_send_command(struct mmc_card *card, u8 *data_frame, u16 blks, u16 type, u8 req_type)
  173. {
  174. struct mmc_host *host = card->host;
  175. int err;
  176. /*
  177. * Auto CMD23 and CMD25 or CMD18
  178. */
  179. if ((req_type == RPMB_REQ && type == RPMB_WRITE_DATA) ||
  180. (req_type == RPMB_REQ && type == RPMB_PROGRAM_KEY))
  181. msdc_set_reliable_write(host, 1);
  182. else
  183. msdc_set_reliable_write(host, 0);
  184. msdc_set_autocmd(host, MSDC_AUTOCMD23, 1);
  185. if (req_type == RPMB_REQ)
  186. err = mmc_block_write(0, 0, blks, (unsigned long *) data_frame);
  187. else
  188. err = mmc_block_read(0, 0, blks, (unsigned long *) data_frame);
  189. msdc_set_autocmd(host, MSDC_AUTOCMD23, 0);
  190. if (err)
  191. msdc_pr_err("%s: CMD%s failed. (%d)\n", __func__, ((req_type==RPMB_REQ) ? "25":"18"), err);
  192. return err;
  193. }
  194. static int mmc_rpmb_start_req(struct mmc_card *card, struct mmc_rpmb_req *rpmb_req)
  195. {
  196. int err = 0;
  197. u16 blks = rpmb_req->rpmb_cfg->blk_cnt;
  198. u16 type = rpmb_req->rpmb_cfg->type;
  199. u8 *data_frame = rpmb_req->data_frame;
  200. /*
  201. * STEP 1: send request to RPMB partition
  202. */
  203. if (type == RPMB_WRITE_DATA)
  204. err = mmc_rpmb_send_command(card, data_frame, blks, type, RPMB_REQ);
  205. else
  206. err = mmc_rpmb_send_command(card, data_frame, 1, type, RPMB_REQ);
  207. if (err) {
  208. msdc_pr_err("%s step 1, request failed (%d)\n", __func__, err);
  209. goto out;
  210. }
  211. /*
  212. * STEP 2: check write result
  213. * Only for WRITE_DATA or Program key
  214. */
  215. memset(data_frame, 0, 512 * blks);
  216. if (type == RPMB_WRITE_DATA || type == RPMB_PROGRAM_KEY) {
  217. data_frame[RPMB_TYPE_BEG + 1] = RPMB_RESULT_READ;
  218. err = mmc_rpmb_send_command(card, data_frame, 1, RPMB_RESULT_READ, RPMB_REQ);
  219. if (err) {
  220. msdc_pr_err("%s step 2, request result failed (%d)\n", __func__, err);
  221. goto out;
  222. }
  223. }
  224. /*
  225. * STEP 3: get response from RPMB partition
  226. */
  227. data_frame[RPMB_TYPE_BEG] = 0;
  228. data_frame[RPMB_TYPE_BEG + 1] = type;
  229. if (type == RPMB_READ_DATA)
  230. err = mmc_rpmb_send_command(card, data_frame, blks, type, RPMB_RESP);
  231. else
  232. err = mmc_rpmb_send_command(card, data_frame, 1, type, RPMB_RESP);
  233. if (err) {
  234. msdc_pr_err("%s step 3, response failed (%d)\n", __func__, err);
  235. }
  236. out:
  237. return err;
  238. }
  239. int mmc_rpmb_check_result(u16 result)
  240. {
  241. if (result) {
  242. msdc_pr_err("%s %s %s\n", __func__, rpmb_err_msg[result & 0x7],
  243. (result & 0x80) ? "Write counter has expired" : "");
  244. }
  245. return result;
  246. }
  247. int mmc_rpmb_get_wc(u32 *wc, int *rpmb_result)
  248. {
  249. struct mmc_card *card = mmc_get_card(0);
  250. struct mmc_rpmb_cfg rpmb_cfg;
  251. struct mmc_rpmb_req rpmb_req;
  252. u8 *ext_csd = &card->raw_ext_csd[0];
  253. u8 rpmb_frame[512];
  254. u8 nonce[16];
  255. u8 val;
  256. int ret = 0;
  257. memset(&rpmb_cfg, 0, sizeof(struct mmc_rpmb_cfg));
  258. memset(nonce, 0, 16);
  259. rpmb_cfg.type = RPMB_GET_WRITE_COUNTER;
  260. rpmb_cfg.result = 0;
  261. rpmb_cfg.blk_cnt = 1;
  262. rpmb_cfg.addr = 0;
  263. rpmb_cfg.wc = 0;
  264. rpmb_cfg.nonce = nonce;
  265. rpmb_cfg.data = NULL;
  266. rpmb_cfg.mac = NULL;
  267. /*
  268. * 1. Switch to RPMB partition.
  269. */
  270. val = (ext_csd[EXT_CSD_PART_CFG] & ~0x7) | (EXT_CSD_PART_CFG_RPMB_PART & 0x7);
  271. ret = mmc_set_part_config(card, val);
  272. if (ret) {
  273. msdc_pr_err("%s, mmc_set_part_config failed!! (%x)\n", __func__, ret);
  274. return ret;
  275. }
  276. msdc_pr_info("%s, mmc_set_part_config done!!\n", __func__);
  277. rpmb_req.rpmb_cfg = &rpmb_cfg;
  278. rpmb_req.data_frame = rpmb_frame;
  279. /*
  280. * 2. Prepare get wc data frame.
  281. */
  282. ret = mmc_rpmb_pre_frame(&rpmb_req);
  283. /*
  284. * 3. CMD 23 and followed CMD25/18 procedure.
  285. */
  286. ret = mmc_rpmb_start_req(card, &rpmb_req);
  287. if (ret) {
  288. msdc_pr_err("%s, mmc_rpmb_part_ops failed!! (%x)\n", __func__, ret);
  289. return ret;
  290. }
  291. ret = mmc_rpmb_post_frame(&rpmb_req);
  292. msdc_pr_info("%s, rpmb_req.result=%x\n", __func__, rpmb_cfg.result);
  293. #if defined(MMC_MSDC_DRV_LK)
  294. memcpy(shared_msg_addr, rpmb_frame + RPMB_DATA_BEG, 284);
  295. arch_clean_invalidate_cache_range((addr_t) LK_HMAC_BASE, 4096);
  296. ret = rpmb_hmac(0, 284);
  297. if (ret) {
  298. msdc_pr_err("%s, rpmb_hmac error.\n", __func__);
  299. }
  300. if (memcmp(rpmb_frame + RPMB_MAC_BEG, shared_hmac_addr, 32) != 0) {
  301. msdc_pr_err("%s, compare hmac error!!\n", __func__);
  302. return ret;
  303. }
  304. #endif
  305. //ret = be16_to_cpu(rpmb_req.result);
  306. /*
  307. * 4. Check result.
  308. */
  309. *rpmb_result = mmc_rpmb_check_result(rpmb_cfg.result);
  310. *wc = rpmb_cfg.wc;
  311. return ret;
  312. }
  313. #if CFG_RPMB_KEY_PROGRAMED_IN_KERNEL
  314. int mmc_rpmb_set_key(u8 *key, int *rpmb_result)
  315. {
  316. struct mmc_host *host = mmc_get_host(0);
  317. struct mmc_card *card = mmc_get_card(0);
  318. struct mmc_rpmb_cfg rpmb_cfg;
  319. struct mmc_rpmb_req rpmb_req;
  320. u8 *ext_csd = &card->raw_ext_csd[0];
  321. u16 result = 0;
  322. u8 rpmb_frame[512];
  323. u8 val;
  324. int ret;
  325. u32 wc;
  326. int i;
  327. *rpmb_result = 0;
  328. ret = mmc_rpmb_get_wc(&wc, rpmb_result);
  329. #if RPMB_KEY_DUMP
  330. printf("rpmb key=\n");
  331. for (i=0;i<32;i++)
  332. printf("0x%x, ", key[i]);
  333. printf("\n");
  334. #endif
  335. /* if any errors, return it */
  336. if (ret) {
  337. printf("%s, get wc failed!! (%d)\n", __func__, ret);
  338. return ret;
  339. }
  340. if (*rpmb_result != 7) {
  341. print("mmc rpmb key already programmed!!\n");
  342. return ret;
  343. }
  344. print("mmc rpmb key will be programmed in kernel, skip now!\n" );
  345. return ret;
  346. }
  347. #else
  348. int mmc_rpmb_set_key(u8 *key)
  349. {
  350. struct mmc_card *card = mmc_get_card(0);
  351. struct mmc_rpmb_cfg rpmb_cfg;
  352. struct mmc_rpmb_req rpmb_req;
  353. u8 *ext_csd = &card->raw_ext_csd[0];
  354. u8 rpmb_frame[512];
  355. u8 val;
  356. int ret, rpmb_result = 0;
  357. u32 wc;
  358. #if RPMB_KEY_DUMP
  359. int i;
  360. #endif
  361. ret = mmc_rpmb_get_wc(&wc, &rpmb_result);
  362. #if RPMB_KEY_DUMP
  363. msdc_pr_info("rpmb key=\n");
  364. for (i = 0; i < 32; i++)
  365. msdc_pr_info("0x%x, ", key[i]);
  366. #endif
  367. /* if any errors, return it */
  368. if (ret) {
  369. msdc_pr_err("%s, get wc failed!! (%d)\n", __func__, ret);
  370. return ret;
  371. }
  372. if (rpmb_result != 7) {
  373. msdc_pr_err("mmc rpmb key is already programmed!!\n");
  374. return ret;
  375. }
  376. memset(&rpmb_cfg, 0, sizeof(struct mmc_rpmb_cfg));
  377. rpmb_cfg.type = RPMB_PROGRAM_KEY;
  378. rpmb_cfg.result = 0;
  379. rpmb_cfg.blk_cnt = 1;
  380. rpmb_cfg.addr = 0;
  381. rpmb_cfg.wc = 0;
  382. rpmb_cfg.nonce = NULL;
  383. rpmb_cfg.data = NULL;
  384. rpmb_cfg.mac = key;
  385. /*
  386. * 1. Switch to RPMB partition.
  387. */
  388. val = (ext_csd[EXT_CSD_PART_CFG] & ~0x7) | (EXT_CSD_PART_CFG_RPMB_PART & 0x7);
  389. ret = mmc_set_part_config(card, val);
  390. if (ret) {
  391. msdc_pr_err("%s, mmc_set_part_config failed!! (%x)\n", __func__, ret);
  392. return ret;
  393. }
  394. rpmb_req.rpmb_cfg = &rpmb_cfg;
  395. rpmb_req.data_frame = rpmb_frame;
  396. /*
  397. * 2. Prepare program key data frame.
  398. */
  399. ret = mmc_rpmb_pre_frame(&rpmb_req);
  400. /*
  401. * 3. CMD 23 and followed CMD25/18 procedure.
  402. */
  403. ret = mmc_rpmb_start_req(card, &rpmb_req);
  404. if (ret) {
  405. msdc_pr_err("%s, mmc_rpmb_part_ops failed!! (%x)\n", __func__, ret);
  406. return ret;
  407. }
  408. ret = mmc_rpmb_post_frame(&rpmb_req);
  409. msdc_pr_info("%s, rpmb_req.result=%x\n", __func__, rpmb_cfg.result);
  410. //ret = be16_to_cpu(rpmb_req.result);
  411. /*
  412. * 4. Check result.
  413. */
  414. ret = mmc_rpmb_check_result(rpmb_cfg.result);
  415. if (ret == 0)
  416. msdc_pr_info("RPMB key is successfully programmed!!\n");
  417. return ret;
  418. }
  419. #endif
  420. u32 mmc_rpmb_get_size(void)
  421. {
  422. struct mmc_card *card = mmc_get_card(0);
  423. u8 *ext_csd = &card->raw_ext_csd[0];
  424. return ext_csd[EXT_CSD_RPMB_SIZE_MULT] * 128 * 1024;
  425. }
  426. //get ext_csd[222]
  427. u32 mmc_rpmb_get_rel_wr_sec_c(void)
  428. {
  429. struct mmc_card *card = mmc_get_card(0);
  430. u8 *ext_csd = &card->raw_ext_csd[0];
  431. printf("RPMB rel_wr_sec=%d\n", ext_csd[EXT_CSD_REL_WR_SEC_C]);
  432. return ext_csd[EXT_CSD_REL_WR_SEC_C];
  433. }
  434. #if defined(MMC_MSDC_DRV_LK)
  435. int mmc_rpmb_read_data(u32 blkAddr, u32 *buf, u32 bufLen)
  436. {
  437. struct mmc_card *card = mmc_get_card(0);
  438. struct mmc_rpmb_cfg rpmb_cfg;
  439. struct mmc_rpmb_req rpmb_req;
  440. u32 blkLen;
  441. u32 left_size = bufLen;
  442. u32 tran_size;
  443. u8 *ext_csd = &card->raw_ext_csd[0];
  444. u8 rpmb_frame[512];
  445. u8 nonce[16];
  446. u8 val;
  447. u32 ret = 0, i;
  448. /*
  449. * 1. Switch to RPMB partition.
  450. */
  451. val = (ext_csd[EXT_CSD_PART_CFG] & ~0x7) | (EXT_CSD_PART_CFG_RPMB_PART & 0x7);
  452. ret = mmc_set_part_config(card, val);
  453. if (ret) {
  454. msdc_pr_err("%s, mmc_set_part_config failed!! (%x)\n", __func__, ret);
  455. return ret;
  456. }
  457. msdc_pr_info("%s, mmc_set_part_config done!!\n", __func__);
  458. blkLen = (bufLen % RPMB_SZ_DATA) ? (bufLen / RPMB_SZ_DATA + 1) : (bufLen / RPMB_SZ_DATA);
  459. for (i = 0; i < blkLen; i++) {
  460. memset(&rpmb_cfg, 0, sizeof(struct mmc_rpmb_cfg));
  461. memset(nonce, 0, 16);
  462. rpmb_cfg.type = RPMB_READ_DATA;
  463. rpmb_cfg.result = 0;
  464. rpmb_cfg.blk_cnt = 1;
  465. rpmb_cfg.addr = blkAddr + i;
  466. rpmb_cfg.wc = 0;
  467. rpmb_cfg.nonce = nonce;
  468. rpmb_cfg.data = NULL;
  469. rpmb_cfg.mac = NULL;
  470. rpmb_req.rpmb_cfg = &rpmb_cfg;
  471. rpmb_req.data_frame = rpmb_frame;
  472. /*
  473. * 2. Prepare read data frame.
  474. */
  475. ret = mmc_rpmb_pre_frame(&rpmb_req);
  476. /*
  477. * 3. CMD 23 and followed CMD25/18 procedure.
  478. */
  479. ret = mmc_rpmb_start_req(card, &rpmb_req);
  480. if (ret) {
  481. msdc_pr_err("%s, mmc_rpmb_start_req failed!! (%x)\n", __func__, ret);
  482. return ret;
  483. }
  484. ret = mmc_rpmb_post_frame(&rpmb_req);
  485. msdc_pr_info("%s, rpmb_req.result=%x\n", __func__, rpmb_cfg.result);
  486. //ret = be16_to_cpu(rpmb_req.result);
  487. /*
  488. * 4. Authenticate hmac.
  489. */
  490. memcpy(shared_msg_addr, rpmb_frame + RPMB_DATA_BEG, 284);
  491. arch_clean_invalidate_cache_range((addr_t) LK_HMAC_BASE, 4096);
  492. ret = rpmb_hmac(0, 284);
  493. if (ret) {
  494. msdc_pr_err("%s, rpmb_hmac error.\n", __func__);
  495. }
  496. if (memcmp(rpmb_frame + RPMB_MAC_BEG, shared_hmac_addr, 32) != 0) {
  497. msdc_pr_err("%s, compare hmac error!!\n", __func__);
  498. return ret;
  499. }
  500. /*
  501. * 5. Authenticate nonce.
  502. */
  503. if (memcmp(nonce, rpmb_cfg.nonce, RPMB_SZ_NONCE) != 0) {
  504. msdc_pr_err("%s, compare nonce error!!\n", __func__);
  505. return ret;
  506. }
  507. /*
  508. * 6. Check result.
  509. */
  510. if (mmc_rpmb_check_result(rpmb_cfg.result))
  511. return ret;
  512. if (left_size >= RPMB_SZ_DATA)
  513. tran_size = RPMB_SZ_DATA;
  514. else
  515. tran_size = left_size;
  516. memcpy((u8 *)buf + i * RPMB_SZ_DATA, rpmb_frame + RPMB_DATA_BEG, tran_size);
  517. left_size -= tran_size;
  518. }
  519. return ret;
  520. }
  521. int mmc_rpmb_write_data(u32 blkAddr, u32 *buf, u32 bufLen)
  522. {
  523. struct mmc_card *card = mmc_get_card(0);
  524. struct mmc_rpmb_cfg rpmb_cfg;
  525. struct mmc_rpmb_req rpmb_req;
  526. u32 blkLen;
  527. u32 left_size = bufLen;
  528. u32 tran_size;
  529. u8 rpmb_frame[512];
  530. int ret = 0, rpmb_result = 0;
  531. u32 wc;
  532. u32 i;
  533. blkLen = (bufLen % RPMB_SZ_DATA) ? (bufLen / RPMB_SZ_DATA + 1) : (bufLen / RPMB_SZ_DATA);
  534. for (i = 0; i < blkLen; i++) {
  535. ret = mmc_rpmb_get_wc(&wc, &rpmb_result);
  536. /* if any errors, return it */
  537. if (ret) {
  538. msdc_pr_err("%s, get wc failed!! (%d)\n", __func__, ret);
  539. return ret;
  540. }
  541. memset(&rpmb_cfg, 0, sizeof(struct mmc_rpmb_cfg));
  542. rpmb_cfg.type = RPMB_WRITE_DATA;
  543. rpmb_cfg.result = 0;
  544. rpmb_cfg.blk_cnt = 1;
  545. rpmb_cfg.addr = blkAddr + i;
  546. rpmb_cfg.wc = wc;
  547. rpmb_cfg.nonce = NULL;
  548. rpmb_cfg.data = (u8 *)buf;
  549. rpmb_cfg.mac = NULL;
  550. rpmb_req.rpmb_cfg = &rpmb_cfg;
  551. rpmb_req.data_frame = rpmb_frame;
  552. /*
  553. * 1. Prepare write data frame.
  554. */
  555. ret = mmc_rpmb_pre_frame(&rpmb_req);
  556. if (left_size >= RPMB_SZ_DATA)
  557. tran_size = RPMB_SZ_DATA;
  558. else
  559. tran_size = left_size;
  560. memcpy(rpmb_frame + RPMB_DATA_BEG, (u8 *)buf + i * RPMB_SZ_DATA, tran_size);
  561. /*
  562. * 2. Compute hmac.
  563. */
  564. memcpy(shared_msg_addr, rpmb_frame + RPMB_DATA_BEG, 284);
  565. arch_clean_invalidate_cache_range((addr_t) LK_HMAC_BASE, 4096);
  566. ret = rpmb_hmac(0, 284);
  567. if (ret)
  568. msdc_pr_err("%s, rpmb_hmac error!!\n", __func__);
  569. memcpy(rpmb_frame + RPMB_MAC_BEG, shared_hmac_addr, 32);
  570. /*
  571. * 3. CMD 23 and followed CMD25/18 procedure.
  572. */
  573. ret = mmc_rpmb_start_req(card, &rpmb_req);
  574. if (ret) {
  575. msdc_pr_err("%s, mmc_rpmb_part_ops failed!! (%x)\n", __func__, ret);
  576. return ret;
  577. }
  578. ret = mmc_rpmb_post_frame(&rpmb_req);
  579. msdc_pr_info("%s, rpmb_req.result=%x\n", __func__, rpmb_cfg.result);
  580. /*
  581. * 4. Check result.
  582. */
  583. ret = mmc_rpmb_check_result(rpmb_cfg.result);
  584. if (ret)
  585. msdc_pr_err("%s, check result error!!\n", __func__);
  586. left_size -= tran_size;
  587. }
  588. return ret;
  589. }
  590. #endif