| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752 |
- /* Copyright Statement:
- *
- * This software/firmware and related documentation ("MediaTek Software") are
- * protected under relevant copyright laws. The information contained herein
- * is confidential and proprietary to MediaTek Inc. and/or its licensors.
- * Without the prior written permission of MediaTek inc. and/or its licensors,
- * any reproduction, modification, use or disclosure of MediaTek Software,
- * and information contained herein, in whole or in part, shall be strictly prohibited.
- */
- /* MediaTek Inc. (C) 2015. All rights reserved.
- *
- * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
- * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
- * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON
- * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
- * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
- * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
- * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH
- * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES
- * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES
- * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK
- * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
- * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND
- * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
- * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
- * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO
- * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
- */
- #include "ufs_aio_cfg.h" // Include ufs_aio_cfg.h for defining MTK_UFS_DRV_PRELOADER
- #include "ufs_aio_types.h"
- #include "ufs_aio.h"
- #include "ufs_aio_hcd.h"
- #include "ufs_aio_core.h"
- #include "ufs_aio_utils.h"
- #include "ufs_aio_error.h"
- #include "ufs_aio_rpmb.h"
- #if defined(MTK_UFS_DRV_LK)
- #include <stdlib.h>
- #include <arch/arm/mmu.h>
- #include "partition_wp.h"
- #include <arch/ops.h> /* arch_clean_invalidate_cache_range() is defined in bootable/bootloader/include/arch/ops.h */
- #endif
- #if defined(MTK_UFS_DRV_PRELOADER)
- #include <hmac.h>
- #if CFG_RPMB_KEY_RETRY_IN_PL
- extern char g_rpmb_key[];
- #endif
- #endif
- #if defined(MTK_UFS_DRV_DA)
- #include "malloc.h"
- #include "boot/security_export/rpmb_hmac.h"
- #endif
- static u8 rpmb_nonce_buf[RPMB_FRM_NONCE_LEN] __attribute__((aligned(UFS_PLATFORM_CACHE_LINE_SIZE)));
- static u8 rpmb_frame_buf[RPMB_FRM_DATA_LEN] __attribute__((aligned(UFS_PLATFORM_CACHE_LINE_SIZE)));
- void rpmb_req_copy_data_for_hmac(u8 *buf, struct rpmb_data_frame *f)
- {
- u32 size;
- /*
- * Copy below members for HMAC calculation
- * one by one with specifically assigning
- * buf to each member to pass buffer-overrun checker.
- *
- * u8 data[RPMB_FRM_DATA_LEN];
- * u8 nonce[RPMB_FRM_NONCE_LEN];
- * u32 wr_cnt;
- * u16 addr;
- * u16 blk_cnt;
- * u16 result;
- * u16 req_resp;
- */
- memcpy(buf, f->data, RPMB_FRM_DATA_LEN);
- buf += RPMB_FRM_DATA_LEN;
- size = sizeof(f->nonce);
- memcpy(buf, f->nonce, size);
- buf += size;
- size = sizeof(f->wr_cnt);
- memcpy(buf, &f->wr_cnt, size);
- buf += size;
- size = sizeof(f->addr);
- memcpy(buf, &f->addr, size);
- buf += size;
- size = sizeof(f->blk_cnt);
- memcpy(buf, &f->blk_cnt, size);
- buf += size;
- size = sizeof(f->result);
- memcpy(buf, &f->result, size);
- buf += size;
- size = sizeof(f->req_resp);
- memcpy(buf, &f->req_resp, size);
- buf += size;
- }
- #if defined(MTK_UFS_DRV_LK)
- extern int32_t rpmb_hmac(uint32_t pattern, uint32_t size);
- extern int32_t rpmb_init(void);
- u32 *shared_msg_addr1 = (u32 *)(LK_SHARED_MEM_ADDR + 0x40); /* fixed and pre-allocated in lk */
- u32 *shared_hmac_addr1 = (u32 *)(LK_SHARED_MEM_ADDR+ 0xCE0); /* fixed and pre-allocated in lk */
- int init_rpmb_sharemem()
- {
- uint32_t start, size;
- int ret = 0;
- /* map shared memory for rpmb */
- start = ROUNDDOWN((uint32_t)LK_SHARED_MEM_ADDR, PAGE_SIZE);
- size = PAGE_SIZE;
- arch_mmu_map((uint64_t)start, (uint32_t)start,
- MMU_MEMORY_TYPE_NORMAL_WRITE_BACK | MMU_MEMORY_AP_P_RW_U_NA, ROUNDUP(size, PAGE_SIZE));
- ret = rpmb_init();
- if (ret) {
- UFS_DBG_LOGE("[%s]: RPMB rpmb_init error, ret = %d \n", __func__, ret);
- return ret;
- }
- return 0;
- }
- static int rpmb_get_mac(struct rpmb_data_frame *pfrm)
- {
- int ret = 0;
- if (pfrm == NULL) {
- UFS_DBG_LOGE("[%s]: RPMB pfrm pointer NULL\n", __func__);
- return -1;
- }
- rpmb_req_copy_data_for_hmac((u8*)shared_msg_addr1, pfrm);
- arch_clean_invalidate_cache_range((addr_t) LK_SHARED_MEM_ADDR, 4096);
- ret = rpmb_hmac(0, 284);
- if (ret) {
- UFS_DBG_LOGE("[%s]: RPMB rpmb_hmac error, ret = %d \n", __func__, ret);
- return ret;
- }
- return 0;
- }
- #endif //#if defined(MTK_UFS_DRV_LK)
- static void cmd_scsi_security_protocol_out(struct ufs_aio_scsi_cmd *cmd, u32 tag, u32 blk_cnt, u8 protocol, u32 protocol_specific)
- {
- if (cmd == NULL) {
- UFS_DBG_LOGE("[%s]: RPMB cmd pointer NULL\n", __func__);
- return;
- }
- memset(cmd->cmd_data, 0, MAX_CDB_SIZE);
- cmd->lun = WLUN_RPMB;
- cmd->tag = tag;
- cmd->dir = DMA_TO_DEVICE;
- cmd->exp_len = blk_cnt << 9; //block size:512
- cmd->attr = ATTR_SIMPLE;
- cmd->cmd_len = 12;
- cmd->cmd_data[0] = SECURITY_PROTOCOL_OUT; //opcode
- cmd->cmd_data[1] = protocol; //security protocol
- cmd->cmd_data[2] = (protocol_specific >> 8) & 0xFF; //security protocol specific
- cmd->cmd_data[3] = protocol_specific & 0xFF; //security protocol specific
- cmd->cmd_data[4] = 0x0; // INC_512 = 0
- cmd->cmd_data[5] = 0x0; //Reserved
- cmd->cmd_data[6] = ((blk_cnt << 9) >> 24) & 0xFF; //Reserved
- cmd->cmd_data[7] = ((blk_cnt << 9) >> 16) & 0xFF; //Reserved
- cmd->cmd_data[8] = ((blk_cnt << 9) >> 8) & 0xFF; //Reserved
- cmd->cmd_data[9] = 0x0; //(blk_cnt << 9) & 0xFF; actually = 0 //Reserved
- cmd->cmd_data[10] = 0x0; //Reserved
- cmd->cmd_data[11] = 0x0; //control = 0
- }
- static void ufshcd_authen_key_prog_req_prepare(struct ufs_aio_scsi_cmd *cmd,
- const char *authenKey, unsigned int key_sz)
- {
- struct rpmb_data_frame *pfrm = NULL;
- if (cmd == NULL) {
- UFS_DBG_LOGE("[%s]: RPMB cmd pointer NULL\n", __func__);
- return;
- }
- if (authenKey == NULL) {
- UFS_DBG_LOGE("[%s]: RPMB authenKey pointer NULL\n", __func__);
- return;
- }
- pfrm = cmd->data_buf;
- if (pfrm == NULL) {
- UFS_DBG_LOGE("[%s]: RPMB pfrm pointer NULL\n", __func__);
- return;
- }
- memset(pfrm, 0, sizeof(struct rpmb_data_frame));
- memcpy(pfrm->key_MAC, authenKey, key_sz);
- pfrm->req_resp = cpu_to_be16(RPMB_REQ_AUTHEN_KEY_PRG);
- }
- static void ufshcd_authen_result_read_req_prepare(struct ufs_aio_scsi_cmd *cmd)
- {
- struct rpmb_data_frame *pfrm = NULL;
- if (cmd == NULL) {
- UFS_DBG_LOGE("[%s]: RPMB cmd pointer NULL\n", __func__);
- return;
- }
- pfrm = cmd->data_buf;
- if (pfrm == NULL) {
- UFS_DBG_LOGE("[%s]: RPMB pfrm pointer NULL\n", __func__);
- return;
- }
- memset(pfrm, 0, sizeof(struct rpmb_data_frame));
- pfrm->req_resp = cpu_to_be16(RPMB_REQ_RESULT_RD);
- }
- static void cmd_scsi_security_protocol_in(struct ufs_aio_scsi_cmd *cmd, u32 tag, u32 blk_cnt, u8 protocol, u32 protocol_specific)
- {
- if (cmd == NULL) {
- UFS_DBG_LOGE("[%s]: RPMB cmd pointer NULL\n", __func__);
- return;
- }
- memset(cmd->cmd_data, 0, MAX_CDB_SIZE);
- cmd->lun = WLUN_RPMB;
- cmd->tag = tag;
- cmd->dir = DMA_FROM_DEVICE;
- cmd->exp_len = blk_cnt * 512;
- cmd->attr = ATTR_SIMPLE;
- cmd->cmd_len = 12;
- cmd->cmd_data[0] = SECURITY_PROTOCOL_IN; //opcode
- cmd->cmd_data[1] = protocol; //security protocol
- cmd->cmd_data[2] = (protocol_specific >> 8) & 0xFF; //security protocol specific
- cmd->cmd_data[3] = protocol_specific & 0xFF; //security protocol specific
- cmd->cmd_data[4] = 0x0; // INC_512 = 0
- cmd->cmd_data[5] = 0x0; //Reserved
- cmd->cmd_data[6] = ((blk_cnt << 9) >> 24) & 0xFF; //Reserved
- cmd->cmd_data[7] = ((blk_cnt << 9) >> 16) & 0xFF; //Reserved
- cmd->cmd_data[8] = ((blk_cnt << 9) >> 8) & 0xFF; //Reserved
- cmd->cmd_data[9] = 0x0; //(blk_cnt << 9) & 0xFF; actually = 0 //Reserved
- cmd->cmd_data[10] = 0x0; //Reserved
- cmd->cmd_data[11] = 0x0; //control = 0
- }
- /*Response Frame check for Authenkey program request and write data request*/
- static int ufshcd_authen_result_read_rsp_check(u32 host_id, struct ufs_aio_scsi_cmd *cmd,
- u16 addr, u32 wcnt,
- enum enum_rpmb_msg type)
- {
- struct rpmb_data_frame *rpmb_frame = NULL;
- unsigned int idx = 0;
- if (cmd == NULL) {
- UFS_DBG_LOGE("[%s]: RPMB cmd pointer NULL\n", __func__);
- return -1;
- }
- rpmb_frame = cmd->data_buf;
- if (rpmb_frame == NULL) {
- UFS_DBG_LOGE("[%s]: RPMB rpmb_frame pointer NULL\n", __func__);
- return -1;
- }
- if ( rpmb_frame->req_resp != cpu_to_be16(type)) {
- /* Check response type */
- UFS_DBG_LOGE("[%s]: RPMB Fail in checking response type : 0x%x\r\n", __func__ , cpu_to_be16(rpmb_frame->req_resp));
- return -1;
- } else if ((idx = (cpu_to_be16(rpmb_frame->result) & 0x7F))) {
- /* Check response type */
- UFS_DBG_LOGE("[%s]: RPMB Fail in checking result : %s \r\n", __func__ , rpmb_oper_result[idx]);
- return -1;
- }
- return 0;
- }
- unsigned char ufs_rpmb_buf[sizeof(struct rpmb_data_frame)]; /* for RPMB only */
- int rpmb_authen_key_program(u32 host_id, const char *authen_key, u32 Key_sz)
- {
- struct ufs_aio_scsi_cmd cmd;
- struct ufs_hba *hba;
- int ret = 0;
- int tag;
- if (authen_key == NULL) {
- UFS_DBG_LOGE("[%s]: RPMB authen_key pointer NULL\n", __func__);
- return -1;
- }
- cmd.data_buf = ufs_rpmb_buf;
- hba = ufs_aio_get_host(host_id);
- if (!ufshcd_get_free_tag(hba, &tag))
- return -1;
- /*Step1. Authen key Data */
- cmd_scsi_security_protocol_out(&cmd, tag, 1,
- UFS_SECURITY_PROTOCOL,
- RPMB_PROTOCOL_ID);
- ufshcd_authen_key_prog_req_prepare(&cmd, authen_key,
- Key_sz);
- if ((ret = ufshcd_queuecommand(hba, &cmd))) {
- UFS_DBG_LOGE("[%s]: RPMB Fail in Sending authen key program request, ret = %d \n", __func__, ret);
- goto exit;
- }
- /*Step2. Result Register Read Request*/
- cmd_scsi_security_protocol_out(&cmd, tag, 1,
- UFS_SECURITY_PROTOCOL,
- RPMB_PROTOCOL_ID);
- ufshcd_authen_result_read_req_prepare(&cmd);
- if ((ret = ufshcd_queuecommand(hba, &cmd))) {
- UFS_DBG_LOGE("[%s]: RPMB Fail in Sending result register read request, ret = %d \n", __func__, ret);
- goto exit;
- }
- /*Step3. Resp for Resutl Register Request*/
- cmd_scsi_security_protocol_in(&cmd, tag, 1,
- UFS_SECURITY_PROTOCOL,
- RPMB_PROTOCOL_ID);
- if ((ret = ufshcd_queuecommand(hba, &cmd))) {
- UFS_DBG_LOGE("[%s]: RPMB Fail in Sending request get result register response, ret = %d \n", __func__, ret);
- goto exit;
- }
- /*Step4. Resp frame check*/
- if ((ret = ufshcd_authen_result_read_rsp_check(host_id, &cmd, 0, 0,
- RPMB_RSP_AUTHEN_KEY_PRG))) {
- UFS_DBG_LOGE("[%s]: RPMB Authentication Key Program Fail, ret = %d \n", __func__, ret);
- goto exit;
- }
- exit:
- ufshcd_put_tag(hba, tag);
- return ret;
- }
- ////////////////////////////////////////////////////////////////////////////
- #define RPMB_MAC_DUMP_DEBUG 0
- #if RPMB_MAC_DUMP_DEBUG
- static inline void ufshcd_rpmb_mac_dump(const u8 *mac, u32 mac_len)
- {
- u32 i = 0;
- UFS_DBG_LOGE("mac dump:\n");
- if (mac == NULL) {
- UFS_DBG_LOGE("[%s]: RPMB mac pointer NULL\n", __func__);
- return;
- }
- for (i = 0; i < mac_len; i++) {
- UFS_DBG_LOGE("[%d]:0x%x\n", i, *(mac+i));
- }
- UFS_DBG_LOGE("\n");
- }
- #else
- static inline void ufshcd_rpmb_mac_dump(const u8 *mac, u32 mac_len)
- {
- }
- #endif
- static int ufshcd_authen_wcnt_read_req_prepare(struct ufs_aio_scsi_cmd *cmd,
- u8 *nonce, unsigned int nonce_len)
- {
- struct rpmb_data_frame *pfrm = NULL;
- // struct ufs_hba *hba;
- unsigned int i = 0;
- int ret = 0;
- // hba = ufs_aio_get_host(host_id);
- if (cmd == NULL) {
- UFS_DBG_LOGE("[%s]: RPMB cmd pointer NULL\n", __func__);
- return -1;
- }
- if (nonce ==NULL) {
- UFS_DBG_LOGE("[%s]: RPMB nonce pointer NULL\n", __func__);
- return -1;
- }
- pfrm = cmd->data_buf;
- if (pfrm == NULL) {
- UFS_DBG_LOGE("[%s]: RPMB pfrm pointer NULL\n", __func__);
- return -1;
- }
- if (nonce_len > RPMB_FRM_NONCE_LEN) {
- UFS_DBG_LOGE(
- "[%s]: RPMB Fail Nonce data length larger than max allow len(%d)", __func__ ,
- RPMB_FRM_NONCE_LEN);
- return -1;
- }
- memset(pfrm, 0, sizeof(struct rpmb_data_frame));
- /* Prepare the max 16 bytes nonce */
- for (i = 0; i < nonce_len; i++)
- nonce[i] = (u8)i & 0xFF; /* ToDO: get random nonce */
- memcpy(pfrm->nonce, nonce, nonce_len);
- pfrm->req_resp = cpu_to_be16(RPMB_REQ_READ_WR_CNT);
- return ret;
- }
- static int ufshcd_authensss_wcnt_read_rsp_check(u32 host_id,
- struct ufs_aio_scsi_cmd *cmd, u32 *wcnt,
- u8 *nonce, unsigned int nonce_len,
- enum enum_rpmb_msg type)
- {
- struct rpmb_data_frame *rpmb_frame = NULL;
- unsigned int idx = 0;
- int ret = 0;
- #if (CFG_RPMB_KEY_RETRY_IN_PL || defined(MTK_UFS_DRV_DA))
- u8 rpmb_hmac_data[HMAC_TEXT_LEN] = {0};
- u8 rpmb_hmac_derived[RPMB_FRM_KEY_MAC_LEN] = {0};
- #endif
- if (cmd == NULL) {
- UFS_DBG_LOGE("[%s]: RPMB cmd pointer NULL\n", __func__);
- return -1;
- }
- if (wcnt == NULL) {
- UFS_DBG_LOGE("[%s]: RPMB wcnt pointer NULL\n", __func__);
- return -1;
- }
- if (nonce == NULL) {
- UFS_DBG_LOGE("[%s]: RPMB nonce pointer NULL\n", __func__);
- return -1;
- }
- rpmb_frame = cmd->data_buf;
- if (rpmb_frame == NULL) {
- UFS_DBG_LOGE("[%s]: RPMB rpmb_frame pointer NULL\n", __func__);
- return -1;
- }
- if ( rpmb_frame->req_resp != cpu_to_be16(type)) {
- /* Check response type */
- UFS_DBG_LOGE("[%s]: RPMB Fail in checking response type : 0x%x\r\n", __func__, cpu_to_be16(rpmb_frame->req_resp));
- return -1;
- } else if ((idx = (cpu_to_be16(rpmb_frame->result) & 0x7F))) {
- /* Check response type */
- UFS_DBG_LOGE("[%s]: RPMB Fail in checking result : %s \r\n", __func__, rpmb_oper_result[idx]);
- return -1;
- } else if (cpu_to_be16(rpmb_frame->result) & 0x80) {
- /*Check Write Counter*/
- UFS_DBG_LOGE("[%s]: RPMB write counter is expired\r\n", __func__);
- }
- if ( memcmp(rpmb_frame->nonce, nonce, nonce_len) ) {
- /*for other response type noce will be "0"*/
- UFS_DBG_LOGE("[%s]: RPMB Fail in checking nonce\r\n", __func__);
- return -1;
- }
- #if defined(MTK_UFS_DRV_LK)
- // Then check MAC
- ret = rpmb_get_mac(rpmb_frame);
- if (ret) {
- UFS_DBG_LOGE("[%s]: RPMB ufshcd_authensss_wcnt_read_rsp_check rpmb_get_mac fail\r\n", __func__);
- return -1;
- }
- if (memcmp(rpmb_frame->key_MAC, shared_hmac_addr1, RPMB_FRM_KEY_MAC_LEN)) {
- UFS_DBG_LOGE("[%s]: RPMB Fail in Mac Check!\n", __func__);
- UFS_DBG_LOGE("Device Return ");
- ufshcd_rpmb_mac_dump((const u8*)rpmb_frame->key_MAC, RPMB_FRM_KEY_MAC_LEN);
- UFS_DBG_LOGE("Host Recalc");
- ufshcd_rpmb_mac_dump((const u8*)shared_hmac_addr1, RPMB_FRM_KEY_MAC_LEN);
- return -1;
- }
- #endif
- #if CFG_RPMB_KEY_RETRY_IN_PL
- /* copy rpmb_frame contents for hmac one by one to avoid coverity issue */
- rpmb_req_copy_data_for_hmac(rpmb_hmac_data, rpmb_frame);
- ret = hmac_sha256(g_rpmb_key, 32, rpmb_hmac_data, HMAC_TEXT_LEN, rpmb_hmac_derived);
- if (ret) {
- UFS_DBG_LOGE("%s, rpmb_hmac error.\n", __func__);
- return -1;
- }
- if (memcmp(rpmb_frame->key_MAC, rpmb_hmac_derived, RPMB_FRM_KEY_MAC_LEN)) {
- UFS_DBG_LOGE("%s, compare hmac error!!\n", __func__);
- return -1;
- }
- #endif //CFG_RPMB_KEY_RETRY_IN_PL
- #if defined(MTK_UFS_DRV_DA)
- rpmb_req_copy_data_for_hmac(rpmb_hmac_data, rpmb_frame);
- ret = rpmb_hmac(rpmb_hmac_data, HMAC_TEXT_LEN, rpmb_hmac_derived);
- if (ret) {
- UFS_DBG_LOGE("[%s]: RPMB ufshcd_authensss_wcnt_read_rsp_check rpmb_get_mac fail\r\n", __func__);
- return -1;
- }
- if (memcmp(rpmb_frame->key_MAC, rpmb_hmac_derived, RPMB_FRM_KEY_MAC_LEN)) {
- UFS_DBG_LOGE("[%s]: RPMB Fail in Mac Check!\n", __func__);
- UFS_DBG_LOGE("Device Return ");
- ufshcd_rpmb_mac_dump((const u8*)rpmb_frame->key_MAC, RPMB_FRM_KEY_MAC_LEN);
- UFS_DBG_LOGE("Host Recalc");
- ufshcd_rpmb_mac_dump((const u8*)rpmb_hmac_derived, RPMB_FRM_KEY_MAC_LEN);
- return -1;
- }
- #endif
- // Then Return WCNT
- *wcnt = cpu_to_be32(rpmb_frame->wr_cnt);
- return 0;
- }
- int rpmb_authen_read_counter(u32 host_id, u8 *nonce_buf, u32 nonce_len,
- u32 *wr_cnt)
- {
- struct ufs_aio_scsi_cmd cmd;
- struct ufs_hba *hba;
- int ret = 0;
- int tag;
- if (nonce_buf == NULL) {
- UFS_DBG_LOGE("[%s]: RPMB nonce_buf pointer NULL\n", __func__);
- return -1;
- }
- if (wr_cnt == NULL) {
- UFS_DBG_LOGE("[%s]: RPMB wr_cnt pointer NULL\n", __func__);
- return -1;
- }
- cmd.data_buf = ufs_rpmb_buf;
- hba = ufs_aio_get_host(host_id);
- if (!ufshcd_get_free_tag(hba, &tag))
- return -1;
- /*Step1 write counter read request */
- cmd_scsi_security_protocol_out(&cmd, tag, 1,
- UFS_SECURITY_PROTOCOL,
- RPMB_PROTOCOL_ID);
- ufshcd_authen_wcnt_read_req_prepare(&cmd,
- nonce_buf, nonce_len);
- if ((ret = ufshcd_queuecommand(hba, &cmd))) {
- UFS_DBG_LOGE("[%s]: RPMB Fail in Sending Write counter read request, ret = %d \n", __func__, ret);
- goto exit;
- }
- /*Step2. Resp for write counter read Request*/
- cmd_scsi_security_protocol_in(&cmd, tag, 1, UFS_SECURITY_PROTOCOL, RPMB_PROTOCOL_ID);
- if ((ret = ufshcd_queuecommand(hba, &cmd))) {
- UFS_DBG_LOGE("[%s]: RPMB Fail in Sending request get result register response, ret = %d \n", __func__, ret);
- goto exit;
- }
- /*Step3. Response frame check*/
- if ((ret = ufshcd_authensss_wcnt_read_rsp_check(host_id, &cmd, wr_cnt,
- nonce_buf, nonce_len,
- RPMB_RSP_READ_WR_CNT))) {
- UFS_DBG_LOGE("[%s]: RPMB WriteCounter Read Resp Check Fail, ret = %d \n", __func__, ret);
- }
- exit:
- ufshcd_put_tag(hba, tag);
- return ret;
- }
- int ufs_rpmb_authen_key_program(const char *authen_key, int *rpmb_result)
- {
- int ret = 0;
- u32 host_id = 0;
- u8 *nonce_buf = NULL;
- u32 wr_cnt = 0;
- if (authen_key == NULL) {
- UFS_DBG_LOGE("[%s]: RPMB authen_key pointer NULL\n", __func__);
- return -1;
- }
- nonce_buf = rpmb_nonce_buf;
- memset(nonce_buf, 0, RPMB_FRM_NONCE_LEN);
- /* If read counter success, it means key has been written -> return without program key again */
- ret = rpmb_authen_read_counter(host_id, nonce_buf, RPMB_FRM_NONCE_LEN,
- &wr_cnt);
- if (!ret) {
- UFS_DBG_LOGE("[%s]: RPMB Key has been written! ret = %d\n", __func__, ret);
- return 0;
- }
- #if CFG_RPMB_KEY_PROGRAMED_IN_KERNEL
- if (rpmb_result != NULL)
- *rpmb_result = 7; /* Key not program */
- print("UFS rpmb key will be programmed in kernel, skip now!\n" );
- #else
- ret = rpmb_authen_key_program(host_id, authen_key, RPMB_FRM_KEY_MAC_LEN);
- if (ret)
- UFS_DBG_LOGE("[%s]: RPMB [Failed]Authentication Key not Programed this time, ret = %d\n", __func__, ret);
- else
- UFS_DBG_LOGI("[%s]: RPMB [PASS]Authentication Key Program Success\n", __func__);
- #endif
- return ret;
- }
- #ifdef MTK_UFS_OTP
- int otp_found = 0;
- #endif
- static void dump_swpcb(struct secure_wp_config_block *swpcb)
- {
- int i;
- UFS_DBG_LOGE("swpcb lun %d\n", swpcb->lun);
- UFS_DBG_LOGE("swpcb data_length %d\n", swpcb->data_length);
- for (i = 0; i < (swpcb->data_length/WP_ENTRY_SIZE); i++) {
- UFS_DBG_LOGE("swpcb entry[%d] wpt_wpf 0x%x\n", i, swpcb->wp_entry[i].wpt_wpf);
- UFS_DBG_LOGE("swpcb entry[%d] upper_addr 0x%x\n", i, swpcb->wp_entry[i].upper_addr);
- UFS_DBG_LOGE("swpcb entry[%d] lower_addr 0x%x\n", i, swpcb->wp_entry[i].lower_addr);
- UFS_DBG_LOGE("swpcb entry[%d] block_num 0x%x\n", i, swpcb->wp_entry[i].block_num);
- }
- }
- static int ufshcd_swp_conf_block_write_prepare(u32 host_id, struct ufs_aio_scsi_cmd *cmd,
- u16 blk_num, u32 wr_cnt, STORAGE_WP_TYPE type, unsigned long blknr, u32 blkcnt, ufs_logical_unit partition,u8 wp_entry,const u8 *data_buf)
- {
- struct rpmb_data_frame *pfrm = NULL;
- int err = 0;
- struct secure_wp_config_block *swpcb = (void *)data_buf;
- int skip_new_entry = 0;
- #if (defined(MTK_UFS_DRV_DA) || defined(MTK_UFS_DRV_PRELOADER))
- u8 rpmb_hmac_data[HMAC_TEXT_LEN] = {0};
- u8 rpmb_hmac_derived[RPMB_FRM_KEY_MAC_LEN] = {0};
- #endif
- #if defined(MTK_UFS_DRV_PRELOADER)
- char rpmb_key[RPMB_KEY_SIZE] = {0};
- #endif
- if (cmd == NULL) {
- UFS_DBG_LOGE("[%s]: RPMB cmd pointer NULL\n", __func__);
- return -1;
- }
- if (data_buf == NULL) {
- UFS_DBG_LOGE("[%s]: RPMB data_buf pointer NULL\n", __func__);
- return -1;
- }
- pfrm = cmd->data_buf;
- if (pfrm == NULL) {
- UFS_DBG_LOGE("[%s]: RPMB pfrm pointer NULL\n", __func__);
- return -1;
- }
- #ifdef MTK_UFS_OTP
- if (type == WP_PERMANENT && otp_found) {
- /*
- * Do not add new entry if we want to add an OTP entry but
- * OTP region is already existed in configuration block.
- *
- * We are here because we still need to write
- * modified configuration block after clean job in the 1st round.
- */
- skip_new_entry = 1;
- }
- #endif
- memset(pfrm, 0, sizeof(struct rpmb_data_frame) * blk_num);
- pfrm->req_resp = cpu_to_be16(RPMB_REQ_SEC_WPCB_WRITE);
- pfrm->blk_cnt = cpu_to_be16(blk_num);
- pfrm->addr = 0;
- pfrm->wr_cnt = cpu_to_be32(wr_cnt);
- /*fix nonce data to 0*/
- /* LUN */
- swpcb->lun= (partition - 1);
- /* Data length */
- if ( partition == UFS_LU_BOOT1 || partition == UFS_LU_BOOT2)
- swpcb->data_length = WP_ENTRY_SIZE; //Boot partition only needs one secure write protect block entry
- else {
- if (skip_new_entry)
- swpcb->data_length = WP_ENTRY_SIZE * wp_entry;
- else
- swpcb->data_length = WP_ENTRY_SIZE * (wp_entry + 1);
- }
- /* WP entries configuration */
- /* Protect entire BOOT1 & BOOT2 area */
- if ( partition == UFS_LU_BOOT1 || partition == UFS_LU_BOOT2) {
- if (type == WP_DISABLE)
- swpcb->wp_entry[0].wpt_wpf = WP_WPF_DISABLE;
- else
- swpcb->wp_entry[0].wpt_wpf = WP_WPF_EN | (type << WPT_BIT);
- //Number of Logical Blocks : 0x0 protect all blocks
- swpcb->wp_entry[0].block_num = 0;
- swpcb->wp_entry[0].upper_addr = 0;
- swpcb->wp_entry[0].lower_addr = 0;
- } else { //only update latest wp_entry
- if (!skip_new_entry) {
- if (type == WP_DISABLE)
- swpcb->wp_entry[wp_entry].wpt_wpf = WP_WPF_DISABLE;
- else
- swpcb->wp_entry[wp_entry].wpt_wpf = WP_WPF_EN | (type << WPT_BIT);
- //Logical Block Address
- //swpcb->wp_entry[wp_entry].upper_addr = ((blknr>>56) & 0xFF) | (((blknr>>48) & 0xFF) <<8) | (((blknr>>40) & 0xFF) <<16) | (((blknr>>32) & 0xFF) <<24); /* unsigned long in lk is only 32bits */
- swpcb->wp_entry[wp_entry].lower_addr = ((blknr>>24) & 0xFF) | (((blknr>>16) & 0xFF) <<8) | (((blknr>>8) & 0xFF) <<16) | ((blknr& 0xFF) <<24);
- //Number of Logical Blocks
- swpcb->wp_entry[wp_entry].block_num = ((blkcnt>>24) & 0xFF) | (((blkcnt>>16) & 0xFF) <<8) | (((blkcnt>>8) & 0xFF) <<16) | ((blkcnt & 0xFF) <<24);
- }
- }
- UFS_DBG_LOGE("[%s]: Write swpcb\n", __func__);
- dump_swpcb(swpcb);
- /* Copy entire "data_buf" to "pfrm->data" before calculate HMAC */
- memcpy(pfrm->data, data_buf, WP_CONF_BLOCK_SIZE);
- #if defined(MTK_UFS_DRV_LK)
- // Calculate MAC
- err = rpmb_get_mac(pfrm);
- if (err) {
- UFS_DBG_LOGE("[%s]: RPMB rpmb_get_mac fail, ret = %d\r\n", __func__, err);
- return -1;
- }
- memcpy(pfrm->key_MAC, shared_hmac_addr1, RPMB_FRM_KEY_MAC_LEN);
- #endif
- #if defined(MTK_UFS_DRV_PRELOADER)
- err = rpmb_get_key(&rpmb_key[0], RPMB_KEY_SIZE);
- if (err) {
- print("\n RPMB storage get key fail err = %d\n", err);
- return err;
- }
- rpmb_req_copy_data_for_hmac(rpmb_hmac_data, pfrm);
- err = hmac_sha256(rpmb_key, 32, rpmb_hmac_data, HMAC_TEXT_LEN, rpmb_hmac_derived);
- if (err) {
- UFS_DBG_LOGE("[%s]: RPMB rpmb_get_mac fail, ret = %d\r\n", __func__, err);
- return -1;
- }
- memcpy(pfrm->key_MAC, rpmb_hmac_derived, RPMB_FRM_KEY_MAC_LEN);
- #endif
- #if defined(MTK_UFS_DRV_DA)
- rpmb_req_copy_data_for_hmac(rpmb_hmac_data, pfrm);
- err = rpmb_hmac(rpmb_hmac_data, HMAC_TEXT_LEN, rpmb_hmac_derived);
- if (err) {
- UFS_DBG_LOGE("[%s]: RPMB rpmb_get_mac fail, ret = %d\r\n", __func__, err);
- return -1;
- }
- memcpy(pfrm->key_MAC, rpmb_hmac_derived, RPMB_FRM_KEY_MAC_LEN);
- #endif
- return err;
- }
- static int ufshcd_swp_conf_block_read_prepare(u32 host_id, struct ufs_aio_scsi_cmd *cmd,
- u16 blk_num,
- u8 *nonce, unsigned int nonce_len, ufs_logical_unit partition)
- {
- struct rpmb_data_frame *pfrm = NULL;
- unsigned int i = 0;
- int ret = 0;
- if (cmd == NULL) {
- UFS_DBG_LOGE("[%s]: RPMB cmd pointer NULL\n", __func__);
- return -1;
- }
- if (nonce == NULL) {
- UFS_DBG_LOGE("[%s]: RPMB nonce pointer NULL\n", __func__);
- return -1;
- }
- pfrm = cmd->data_buf;
- if (pfrm == NULL) {
- UFS_DBG_LOGE("[%s]: RPMB pfrm pointer NULL\n", __func__);
- return -1;
- }
- memset(pfrm, 0, sizeof(struct rpmb_data_frame));
- pfrm->req_resp = cpu_to_be16(RPMB_REQ_SEC_WPCB_READ);
- pfrm->blk_cnt = cpu_to_be16(blk_num);
- pfrm->addr = 0;
- /* Prepare the max 16 bytes nonce */
- for (i = 0; i < nonce_len; i++)
- nonce[i] = (u8)i & 0xFF; /* ToDO: get random nonce */
- memcpy(pfrm->nonce, nonce, nonce_len);
- pfrm->data[0] = partition - 1;
- return ret;
- }
- static int ufshcd_authen_data_write_rsp_check(u32 host_id, struct ufs_aio_scsi_cmd *cmd, u32 wcnt,
- enum enum_rpmb_msg type)
- {
- struct rpmb_data_frame *rpmb_frame = NULL;
- unsigned int idx = 0;
- int ret = 0;
- #if (defined(MTK_UFS_DRV_DA) || defined(MTK_UFS_DRV_PRELOADER))
- u8 rpmb_hmac_data[HMAC_TEXT_LEN] = {0};
- u8 rpmb_hmac_derived[RPMB_FRM_KEY_MAC_LEN] = {0};
- #endif
- #if defined(MTK_UFS_DRV_PRELOADER)
- char rpmb_key[RPMB_KEY_SIZE] = {0};
- #endif
- if (cmd == NULL) {
- UFS_DBG_LOGE("[%s]: RPMB cmd pointer NULL\n", __func__);
- return -1;
- }
- rpmb_frame = cmd->data_buf;
- if (rpmb_frame == NULL) {
- UFS_DBG_LOGE("[%s]: RPMB rpmb_frame pointer NULL\n", __func__);
- return -1;
- }
- if ( rpmb_frame->req_resp != cpu_to_be16(type)) {
- /* Check response type */
- UFS_DBG_LOGE("[%s]: RPMB Fail in checking response type : 0x%x\r\n", __func__, cpu_to_be16(rpmb_frame->req_resp));
- return -1;
- } else if ((idx = (cpu_to_be16(rpmb_frame->result) & 0x7F))) {
- /* Check response type */
- UFS_DBG_LOGE("[%s]: RPMB Fail in checking result : %s \r\n", __func__, rpmb_oper_result[idx]);
- return -1;
- } else if (cpu_to_be16(rpmb_frame->result) & 0x80) {
- /*Check Write Counter*/
- UFS_DBG_LOGE("[%s]: RPMB write counter is expired\r\n", __func__);
- }
- #if defined(MTK_UFS_DRV_LK)
- // Then check MAC
- ret = rpmb_get_mac(rpmb_frame);
- if (ret) {
- UFS_DBG_LOGE("[%s]: RPMB ufshcd_authen_data_write_rsp_check rpmb_get_mac fail, ret = %d\r\n", __func__, ret);
- return -1;
- }
- if (memcmp(rpmb_frame->key_MAC, shared_hmac_addr1, RPMB_FRM_KEY_MAC_LEN)) {
- UFS_DBG_LOGE("[%s]: RPMB Fail in Mac Check!\n", __func__);
- UFS_DBG_LOGE("Device Return ");
- ufshcd_rpmb_mac_dump((const u8*)rpmb_frame->key_MAC, RPMB_FRM_KEY_MAC_LEN);
- UFS_DBG_LOGE("Host Recalc");
- ufshcd_rpmb_mac_dump((const u8*)shared_hmac_addr1, RPMB_FRM_KEY_MAC_LEN);
- return -1;
- }
- #endif
- #if defined(MTK_UFS_DRV_PRELOADER)
- ret = rpmb_get_key(&rpmb_key[0], RPMB_KEY_SIZE);
- if (ret) {
- print("\n RPMB storage get key fail err = %d\n", ret);
- return ret;
- }
- rpmb_req_copy_data_for_hmac(rpmb_hmac_data, rpmb_frame);
- ret = hmac_sha256(rpmb_key, 32, rpmb_hmac_data, HMAC_TEXT_LEN, rpmb_hmac_derived);
- if (ret) {
- UFS_DBG_LOGE("[%s]: RPMB rpmb_get_mac fail, ret = %d\r\n", __func__, ret);
- return -1;
- }
- if (memcmp(rpmb_frame->key_MAC, rpmb_hmac_derived, RPMB_FRM_KEY_MAC_LEN)) {
- UFS_DBG_LOGE("[%s]: RPMB Fail in Mac Check!\n", __func__);
- UFS_DBG_LOGE("Device Return ");
- ufshcd_rpmb_mac_dump((const u8*)rpmb_frame->key_MAC, RPMB_FRM_KEY_MAC_LEN);
- UFS_DBG_LOGE("Host Recalc");
- ufshcd_rpmb_mac_dump((const u8*)rpmb_hmac_derived, RPMB_FRM_KEY_MAC_LEN);
- return -1;
- }
- #endif
- #if defined(MTK_UFS_DRV_DA)
- rpmb_req_copy_data_for_hmac(rpmb_hmac_data, rpmb_frame);
- ret = rpmb_hmac(rpmb_hmac_data, HMAC_TEXT_LEN, rpmb_hmac_derived);
- if (ret) {
- UFS_DBG_LOGE("%s, rpmb_hmac error.\n", __func__);
- return -1;
- }
- if (memcmp(rpmb_frame->key_MAC, rpmb_hmac_derived, RPMB_FRM_KEY_MAC_LEN)) {
- UFS_DBG_LOGE("[%s]: RPMB Fail in Mac Check!\n", __func__);
- UFS_DBG_LOGE("Device Return ");
- ufshcd_rpmb_mac_dump((const u8*)rpmb_frame->key_MAC, RPMB_FRM_KEY_MAC_LEN);
- UFS_DBG_LOGE("Host Recalc");
- ufshcd_rpmb_mac_dump((const u8*)rpmb_hmac_derived, RPMB_FRM_KEY_MAC_LEN);
- return -1;
- }
- #endif
- // Check Wr_cnt increasement
- if (rpmb_frame->wr_cnt != cpu_to_be32(wcnt + 1)) {
- UFS_DBG_LOGE("[%s]: RPMB Fail in Write Counter Increasement!\n", __func__);
- return -1;
- }
- return ret;
- }
- static int ufshcd_authen_data_read_rsp_check(u32 host_id, struct ufs_aio_scsi_cmd *cmd,
- const u8 *nonce_buf, unsigned int nonce_len, u8 *data_buf,
- enum enum_rpmb_msg type)
- {
- struct rpmb_data_frame *pfrm = NULL;
- unsigned int idx = 0;
- int ret = 0;
- #if (defined(MTK_UFS_DRV_DA) || defined(MTK_UFS_DRV_PRELOADER))
- u8 rpmb_hmac_data[HMAC_TEXT_LEN] = {0};
- u8 rpmb_hmac_derived[RPMB_FRM_KEY_MAC_LEN] = {0};
- #endif
- #if defined(MTK_UFS_DRV_PRELOADER)
- char rpmb_key[RPMB_KEY_SIZE] = {0};
- #endif
- if (cmd == NULL) {
- UFS_DBG_LOGE("[%s]: RPMB cmd pointer NULL\n", __func__);
- return -1;
- }
- if (nonce_buf == NULL) {
- UFS_DBG_LOGE("[%s]: RPMB nonce_buf pointer NULL\n", __func__);
- return -1;
- }
- if (data_buf == NULL) {
- UFS_DBG_LOGE("[%s]: RPMB ata_buf pointer NULL\n", __func__);
- return -1;
- }
- pfrm = cmd->data_buf;
- if (pfrm == NULL) {
- UFS_DBG_LOGE("[%s]: RPMB pfrm pointer NULL\n", __func__);
- return -1;
- }
- if (pfrm->req_resp != cpu_to_be16(type)) {
- /* Check response type */
- UFS_DBG_LOGE("[%s]: RPMB Fail in checking response type : 0x%x\r\n", __func__, cpu_to_be16(pfrm->req_resp));
- return -1;
- } else if ((idx = (cpu_to_be16(pfrm->result) & 0x7F))) {
- /* Check response type */
- UFS_DBG_LOGE("[%s]: RPMB Fail in checking result : %s \r\n", __func__, rpmb_oper_result[idx]);
- return -1;
- } else if (cpu_to_be16(pfrm->result) & 0x80) {
- /*Check Write Counter*/
- UFS_DBG_LOGE("[%s]: RPMB write counter is expired\r\n", __func__);
- }
- if (memcmp(pfrm->nonce, nonce_buf, nonce_len) ) {
- /*for other response type noce will be "0"*/
- UFS_DBG_LOGE("[%s]: RPMB Fail in checking nonce\r\n", __func__);
- return -1;
- }
- #if defined(MTK_UFS_DRV_LK)
- ret = rpmb_get_mac(pfrm);
- if (ret) {
- UFS_DBG_LOGE("[%s]: RPMB rpmb_get_mac fail, ret = %d \r\n", __func__, ret);
- return -1;
- }
- if (memcmp(pfrm->key_MAC, shared_hmac_addr1, RPMB_FRM_KEY_MAC_LEN) ) {
- /*for other response type noce will be "0"*/
- UFS_DBG_LOGE("[%s]: RPMB Fail in checking MAC\r\n", __func__);
- UFS_DBG_LOGE("Device Return");
- ufshcd_rpmb_mac_dump((const u8*)pfrm->key_MAC, RPMB_FRM_KEY_MAC_LEN);
- UFS_DBG_LOGE("Host Recalc");
- ufshcd_rpmb_mac_dump((const u8*)shared_hmac_addr1, RPMB_FRM_KEY_MAC_LEN);
- return -1;
- }
- #endif
- #if defined(MTK_UFS_DRV_PRELOADER)
- ret = rpmb_get_key(&rpmb_key[0], RPMB_KEY_SIZE);
- if (ret) {
- print("\n RPMB storage get key fail err = %d\n", ret);
- return ret;
- }
- rpmb_req_copy_data_for_hmac(rpmb_hmac_data, pfrm);
- ret = hmac_sha256(rpmb_key, 32, rpmb_hmac_data, HMAC_TEXT_LEN, rpmb_hmac_derived);
- if (ret) {
- UFS_DBG_LOGE("[%s]: RPMB rpmb_get_mac fail, ret = %d\r\n", __func__, ret);
- return -1;
- }
- if (memcmp(pfrm->key_MAC, rpmb_hmac_derived, RPMB_FRM_KEY_MAC_LEN)) {
- UFS_DBG_LOGE("[%s]: RPMB Fail in checking MAC\r\n", __func__);
- UFS_DBG_LOGE("Device Return");
- ufshcd_rpmb_mac_dump((const u8*)pfrm->key_MAC, RPMB_FRM_KEY_MAC_LEN);
- UFS_DBG_LOGE("Host Recalc");
- ufshcd_rpmb_mac_dump((const u8*)rpmb_hmac_derived, RPMB_FRM_KEY_MAC_LEN);
- return -1;
- }
- #endif
- #if defined(MTK_UFS_DRV_DA)
- rpmb_req_copy_data_for_hmac(rpmb_hmac_data, pfrm);
- ret = rpmb_hmac(rpmb_hmac_data, HMAC_TEXT_LEN, rpmb_hmac_derived);
- if (ret) {
- UFS_DBG_LOGE("%s, rpmb_hmac error.\n", __func__);
- return -1;
- }
- if (memcmp(pfrm->key_MAC, rpmb_hmac_derived, RPMB_FRM_KEY_MAC_LEN)) {
- UFS_DBG_LOGE("[%s]: RPMB Fail in checking MAC\r\n", __func__);
- UFS_DBG_LOGE("Device Return");
- ufshcd_rpmb_mac_dump((const u8*)pfrm->key_MAC, RPMB_FRM_KEY_MAC_LEN);
- UFS_DBG_LOGE("Host Recalc");
- ufshcd_rpmb_mac_dump((const u8*)rpmb_hmac_derived, RPMB_FRM_KEY_MAC_LEN);
- return -1;
- }
- #endif
- memcpy(data_buf, pfrm->data, WP_CONF_BLOCK_SIZE); //Copy Secure Write Protect Block to data_buf
- return 0;
- }
- static int rpmb_authen_secure_write_protect_conf_block_write(u32 host_id, u32 wr_cnt,
- const u8 *dat_buf,
- u32 blk_num, STORAGE_WP_TYPE type, unsigned long blknr, u32 blkcnt, ufs_logical_unit partition, u8 wp_entry)
- {
- struct ufs_aio_scsi_cmd cmd;
- struct ufs_hba *hba;
- int ret = 0;
- int tag;
- if (dat_buf == NULL) {
- UFS_DBG_LOGE("[%s]: RPMB data_buf pointer NULL\n", __func__);
- return -1;
- }
- cmd.data_buf = ufs_rpmb_buf;
- hba = ufs_aio_get_host(host_id);
- if (!ufshcd_get_free_tag(hba, &tag))
- return -1;
- /*Step1 write counter read request */
- cmd_scsi_security_protocol_out(&cmd, tag, blk_num,
- UFS_SECURITY_PROTOCOL,
- RPMB_PROTOCOL_ID);
- //cmd.cmd_data[4] = 0x80; //INC_512 = 1
- ufshcd_swp_conf_block_write_prepare(host_id, &cmd,
- blk_num, wr_cnt, type, blknr, blkcnt, partition, wp_entry, dat_buf);
- ufshcd_rpmb_mac_dump(dat_buf, RPMB_SWP_CB_VALID_DATA_SIZE);
- if ((ret = ufshcd_queuecommand(hba, &cmd))) {
- UFS_DBG_LOGE("[%s]: RPMB Fail in Sending Secure Write Protect Conf. Block write request, ret = %d \n", __func__, ret);
- goto exit;
- }
- /*Step2. Result Register Read Request*/
- cmd_scsi_security_protocol_out(&cmd, tag, 1,
- UFS_SECURITY_PROTOCOL,
- RPMB_PROTOCOL_ID);
- ufshcd_authen_result_read_req_prepare(&cmd);
- if ((ret = ufshcd_queuecommand(hba, &cmd))) {
- UFS_DBG_LOGE("[%s]: RPMB Fail in Sending result register read request, ret = %d \n", __func__, ret);
- return ret;
- }
- /*Step3 Check Response for Result Read Request*/
- cmd_scsi_security_protocol_in(&cmd, tag, 1, UFS_SECURITY_PROTOCOL, RPMB_PROTOCOL_ID);
- if ((ret = ufshcd_queuecommand(hba, &cmd))) {
- UFS_DBG_LOGE("[%s]: RPMB Fail in Sending request get result register response, ret = %d \n", __func__, ret);
- goto exit;
- }
- /*Step3. Response frame check*/
- if ((ret = ufshcd_authen_data_write_rsp_check(host_id, &cmd, wr_cnt,
- RPMB_RSP_SEC_WPCB_WRITE))) {
- UFS_DBG_LOGE("[%s]: RPMB WriteCounter Read Resp Check Fail, ret = %d \n", __func__, ret);
- goto exit;
- }
- exit:
- ufshcd_put_tag(hba, tag);
- return ret;
- }
- static int rpmb_authen_secure_write_protect_conf_block_read(u32 host_id,u8 * data_buf,
- u8 *nonce_buf, u32 nonce_len,
- u32 blk_num, ufs_logical_unit partition)
- {
- struct ufs_aio_scsi_cmd cmd;
- struct ufs_hba *hba;
- int ret = 0;
- int tag;
- if (data_buf == NULL) {
- UFS_DBG_LOGE("[%s]: RPMB data_buf pointer NULL\n", __func__);
- return -1;
- }
- if (nonce_buf == NULL) {
- UFS_DBG_LOGE("[%s]: RPMB nonce_buf pointer NULL\n", __func__);
- return -1;
- }
- cmd.data_buf = ufs_rpmb_buf;
- hba = ufs_aio_get_host(host_id);
- if (!ufshcd_get_free_tag(hba, &tag))
- return -1;
- /*Step1 authen data read request */
- cmd_scsi_security_protocol_out(&cmd, tag, 1,
- UFS_SECURITY_PROTOCOL,
- RPMB_PROTOCOL_ID);
- //cmd.cmd_data[4] = 0x80; //INC_512 = 1
- ufshcd_swp_conf_block_read_prepare(host_id, &cmd,
- blk_num, nonce_buf, nonce_len, partition);
- if ((ret = ufshcd_queuecommand(hba, &cmd))) {
- UFS_DBG_LOGE("[%s]: RPMB Fail in Sending Secure Write Protect Conf. Block read request, ret = %d \n", __func__, ret);
- goto exit;
- }
- /*Step2 Send protocol in cmd for data read*/
- cmd_scsi_security_protocol_in(&cmd, tag, blk_num, UFS_SECURITY_PROTOCOL, RPMB_PROTOCOL_ID);
- if ((ret = ufshcd_queuecommand(hba, &cmd))) {
- UFS_DBG_LOGE("[%s]: RPMB Fail in Sending request get result register response, ret = %d \n", __func__, ret);
- goto exit;
- }
- /*Step3 Check Response and parser data*/
- if ((ret = ufshcd_authen_data_read_rsp_check(host_id, &cmd,
- nonce_buf, nonce_len, data_buf, RPMB_RSP_SEC_WPCB_READ))) {
- UFS_DBG_LOGE("[%s]: RPMB Data Read Resp Check Fail, ret = %d \n", __func__, ret);
- goto exit;
- }
- /* ufshcd_rpmb_mac_dump(data_buf, RPMB_SWP_CB_VALID_DATA_SIZE); */
- exit:
- ufshcd_put_tag(hba, tag);
- return ret;
- }
- static int rpmb_authen_secure_write_protect_conf_block_check(u8 *data_buf, u8 *wp_entry , unsigned long blknr, u32 blkcnt, ufs_logical_unit partition, STORAGE_WP_TYPE type)
- {
- static int round = 0;
- #ifdef MTK_UFS_OTP
- u8 i = 0;
- #endif
- struct secure_wp_config_block *swpcb = (void *)data_buf;
- if (data_buf == NULL) {
- UFS_DBG_LOGE("[%s]: RPMB data_buf pointer NULL\n", __func__);
- return -1;
- }
- if (wp_entry==NULL) {
- UFS_DBG_LOGE("[%s]: RPMB wp_entry pointer NULL\n", __func__);
- return -1;
- }
- UFS_DBG_LOGE("[%s]: Read swpcb\n", __func__);
- dump_swpcb(swpcb);
- /* For Boot1/Boot2, only lock all region. And only have one wp_entry */
- if (partition == UFS_LU_BOOT1 || partition == UFS_LU_BOOT2 || type == WP_DISABLE) {
- memset(&(swpcb->wp_entry[0]), 0, WP_ENTRY_SIZE * SWPWP_ENTRY_NUM);
- *wp_entry = 0;
- return 0;
- }
- /* For USER partition */
- /* For OTP: Each Boot, we re-write secure write protect Entries. Only keep OTP entry. */
- /* Because protect start & size may change, SW have no idea how they change. */
- #ifdef MTK_UFS_OTP
- /* First enter write protect secure write protect entries, need to keep OTP entery if any */
- if (round == 0) {
- UFS_DBG_LOGD("[%s] Finding OTP entry ...\n", __func__);
- for (i = 0 ; i < (swpcb->data_length / WP_ENTRY_SIZE); i++) {
- UFS_DBG_LOGD("[%s] Checking entry %d, wpt_wtf: 0x%x\n", __func__, i, swpcb->wp_entry[i].wpt_wpf);
- /* If find OTP entries, copy OTP to entry 0, clear other entries, set wp_entry to 1 */
- if ((swpcb->wp_entry[i].wpt_wpf & 0x7) == 0x1) { /* WPT = 0, WPF = 1 */
- UFS_DBG_LOGD("[%s] OTP entry is found in index %d\n", __func__, i);
- if (i != 0) {
- /* only need copy i to 0 if i != 0 */
- UFS_DBG_LOGD("[%s] Copy OTP entry %d -> 0\n", __func__, i);
- memcpy(&(swpcb->wp_entry[0]), &(swpcb->wp_entry[i]), sizeof(struct secure_wp_entry));
- memset(&(swpcb->wp_entry[i]), 0, WP_ENTRY_SIZE * (SWPWP_ENTRY_NUM - 1));
- }
- otp_found++;
- } else {
- /* clear all other entries */
- memset(&(swpcb->wp_entry[i]), 0, sizeof(struct secure_wp_entry));
- }
- }
- if (otp_found > 1) {
- UFS_DBG_LOGE("[%s] Found multiple OTP entries, ERROR!\n", __func__);
- return UFS_OTP_INVALID_ENTRY;
- }
- if (otp_found)
- *wp_entry = 1;
- else
- *wp_entry = 0;
- } else { /* Not first enter, just write to last free entry later */
- if (swpcb->data_length == WP_MAX_ENTRY_SIZE) {
- UFS_DBG_LOGE("[%s]: RPMB exceed WP entries size!!! \n", __func__);
- return UFS_POWER_ON_WP_ENTRY_FULL;
- }
- *wp_entry = swpcb->data_length / WP_ENTRY_SIZE;
- }
- round++;
- if (otp_found > 0 && round > 1 && type == WP_PERMANENT) {
- /*
- * If we want to lock OTP but OTP entry is found in configruation block,
- * do not modify original entry, just write it (old one) to configuration block.
- *
- * For round == 1, we still need to write modified configuration block (after clean job)
- * anyway, so do not return error code here to let programming flow continue.
- *
- * For round > 1, just return error code because we do not need any programming.
- */
- UFS_DBG_LOGD("[%s]: OTP already locked previously! Skipped.\n", __func__);
- return UFS_OTP_ALREADY_LOCKED;
- }
- #else
- /*
- * For non OTP project, always clean wp entries at first time.
- *
- * Note: OTP protected region will be clear and reset by this job!
- */
- if (round == 0) {
- memset(&(swpcb->wp_entry[0]), 0, WP_ENTRY_SIZE * SWPWP_ENTRY_NUM);
- *wp_entry = 0;
- } else {
- if (swpcb->data_length == WP_MAX_ENTRY_SIZE) {
- UFS_DBG_LOGE("[%s]: RPMB exceed WP entries size!!! \n", __func__);
- return UFS_POWER_ON_WP_ENTRY_FULL;
- }
- *wp_entry = swpcb->data_length/WP_ENTRY_SIZE;
- }
- round++;
- #endif
- return 0;
- }
- int rpmb_ufs_set_wp(u32 host_id, STORAGE_WP_TYPE type, unsigned long blknr,
- u32 blkcnt,ufs_logical_unit partition)
- {
- u8 *nonce_buf = NULL;
- u8 *data_buf = NULL;
- u32 wr_cnt = 0;
- int ret = 0;
- u8 wp_entry = 0;
- nonce_buf = rpmb_nonce_buf;
- memset(nonce_buf, 0, RPMB_FRM_NONCE_LEN);
- data_buf = rpmb_frame_buf;
- memset(data_buf, 0, RPMB_FRM_DATA_LEN);
- /* Read Old Secure Write Protect Conf Block */
- ret = rpmb_authen_read_counter(host_id, nonce_buf, RPMB_FRM_NONCE_LEN,
- &wr_cnt);
- if (ret) {
- UFS_DBG_LOGE("[%s]: RPMB rpmb_authen_read_counter fail! ret = %d\n", __func__, ret);
- goto exit;
- }
- ret = rpmb_authen_secure_write_protect_conf_block_read(host_id, data_buf, nonce_buf, RPMB_FRM_NONCE_LEN, 1, partition);
- if (ret ) {
- UFS_DBG_LOGE("[%s]: RPMB rpmb_authen_secure_write_protect_conf_block_read fail! ret = %d\n", __func__, ret);
- goto exit;
- } else
- UFS_DBG_LOGD("Authenticated Data Read Success!\n");
- ret = rpmb_authen_secure_write_protect_conf_block_check(data_buf, &wp_entry, blknr, blkcnt, partition, type);
- if (ret) {
- UFS_DBG_LOGE("[%s]: RPMB rpmb_authen_secure_write_protect_conf_block_check fail! ret = %d\n", __func__, ret);
- goto exit;
- }
- /* Get Current Write Counter */
- ret = rpmb_authen_read_counter(host_id, nonce_buf, RPMB_FRM_NONCE_LEN,
- &wr_cnt);
- if (ret) {
- UFS_DBG_LOGE("[%s]: RPMB rpmb_authen_read_counter fail! ret = %d\n", __func__, ret);
- goto exit;
- }
- /* Authenticated Data Write */
- ret = rpmb_authen_secure_write_protect_conf_block_write(host_id, wr_cnt,
- data_buf, 1, type, blknr, blkcnt, partition, wp_entry);
- if (ret ) {
- UFS_DBG_LOGE("[%s]: RPMB rpmb_authen_secure_write_protect_conf_block_write Fail! ret = %d\n", __func__, ret);
- goto exit;
- } else
- UFS_DBG_LOGD("Authenticated Data Write Success 1 blks\n");
- exit:
- return ret;
- }
- int rpmb_ufs_clr_wp(u32 host_id, ufs_logical_unit partition)
- {
- u8 *nonce_buf = NULL;
- u8 *data_buf = NULL;
- u32 wr_cnt = 0;
- int ret = 0;
- u8 wp_entry = 0;
- struct secure_wp_config_block *swpcb;
- nonce_buf = rpmb_nonce_buf;
- memset(nonce_buf, 0, RPMB_FRM_NONCE_LEN);
- data_buf = rpmb_frame_buf;
- memset(data_buf, 0, RPMB_FRM_DATA_LEN);
- swpcb = (void *)data_buf;
- swpcb->data_length = 16;
- wp_entry = 0;
- /* Get Current Write Counter */
- ret = rpmb_authen_read_counter(host_id, nonce_buf, RPMB_FRM_NONCE_LEN,
- &wr_cnt);
- if (ret) {
- UFS_DBG_LOGE("[%s]: RPMB rpmb_authen_read_counter fail! ret = %d\n", __func__, ret);
- goto exit;
- }
- /* Authenticated Data Write */
- ret = rpmb_authen_secure_write_protect_conf_block_write(host_id, wr_cnt,
- data_buf, 1, WP_DISABLE, 0, 0, partition, wp_entry);
- if (ret ) {
- UFS_DBG_LOGE("[%s]: RPMB rpmb_authen_secure_write_protect_conf_block_write Fail! ret = %d\n", __func__, ret);
- goto exit;
- } else
- UFS_DBG_LOGD("Authenticated Data Write Success 1 blks\n");
- exit:
- return ret;
- }
- #if 0 /* Test code only */
- int ts_secure_write_protect(u32 host_id)
- {
- int ret = 0;
- off_t offset = 0;
- size_t size = 32;
- u8 *buf_test[32] = {1};
- ret = ufs_set_write_protect(host_id, UFS_LU_USER, 0x0, 0x100, WP_POWER_ON);
- if (ret)
- goto exit;
- ret = ufs_set_write_protect(host_id, UFS_LU_USER, 0x100, 0x100, WP_POWER_ON);
- if (ret)
- goto exit;
- ret = ufs_set_write_protect(host_id, UFS_LU_USER, 0x200, 0x100, WP_POWER_ON);
- if (ret)
- goto exit;
- /* Note: Different for other projects need to contain nvram region */
- if (ret)
- ret = ufs_set_write_protect(host_id, UFS_LU_USER, 0xf000, 0xc000, WP_POWER_ON);
- goto exit;
- ret = ufs_set_write_protect(host_id, UFS_LU_BOOT1, 0x0, 0x200, WP_POWER_ON);
- if (ret)
- goto exit;
- if (32!= partition_write("nvram", offset, buf_test, size))
- UFS_DBG_LOGE("[%s]: RPMB write nvram fail!\n", __func__);
- if (32!= partition_write("preloader", offset, buf_test, size))
- UFS_DBG_LOGE("[%s]: RPMB write preloader fail!\n", __func__);
- exit:
- return ret;
- }
- #endif
- int ufs_set_write_protect(int dev_num, ufs_logical_unit partition, unsigned long blknr, u32 blkcnt, STORAGE_WP_TYPE type)
- {
- int err = UFS_POWER_ON_WP_ERR;
- UFS_DBG_LOGI("[%s]: RPMB partition = %d, wp_type = %d, blknr = 0x%lx, blkcnt = 0x%x\n",
- __func__, partition, type, blknr, blkcnt);
- if ((type == WP_POWER_ON || type == WP_PERMANENT || type == WP_PERMANENT_AWP) && partition == UFS_LU_USER) {
- UFS_DBG_LOGD("[%s]: blknr: 0x%lx blkcnt: 0x%x\n",__func__ , blknr, blkcnt);
- err = rpmb_ufs_set_wp(dev_num,type, blknr, blkcnt, partition);
- if (err) {
- UFS_DBG_LOGE("[%s]: RPMB rpmb_ufs_set_wp err! ret = %d\n", __func__, err);
- return err;
- }
- } else if (((type == WP_POWER_ON || type == WP_PERMANENT_AWP) && partition == UFS_LU_BOOT1) ||
- ((type == WP_POWER_ON || type == WP_PERMANENT_AWP) && partition == UFS_LU_BOOT2)) {
- if (partition == UFS_LU_BOOT1) {
- err = rpmb_ufs_set_wp(dev_num, type, blknr, blkcnt, UFS_LU_BOOT1);
- if (err) {
- UFS_DBG_LOGE("[%s]: RPMB rpmb_ufs_set_wp boot1 partition err ret= %d\n", __func__, err);
- return err;
- }
- } else if (partition == UFS_LU_BOOT2) {
- err = rpmb_ufs_set_wp(dev_num, type, blknr, blkcnt, UFS_LU_BOOT2);
- if (err) {
- UFS_DBG_LOGE("[%s]: RPMB rpmb_ufs_set_wp boot2 partition err%d\n", __func__,err);
- return err;
- }
- }
- } else if (type == WP_TEMPORARY) {
- UFS_DBG_LOGE("[%s]: RPMB WP Type Not Support\n", __func__);
- return 0;
- } else if (type == WP_DISABLE) {
- err = rpmb_ufs_clr_wp(dev_num, partition);
- if (err) {
- UFS_DBG_LOGE("[%s]: RPMB rpmb_ufs_clear_wp err%d\n", __func__, err);
- return err;
- }
- return 0;
- } else if (partition == UFS_LU_UNKNOWN ||partition == UFS_LU_RPMB
- ||partition == UFS_LU_END) {
- UFS_DBG_LOGE("[%s]: RPMB partition Not Support\n", __func__);
- return 0;
- } else {
- return err;
- }
- return err;
- }
- int ufs_clr_write_protect(void)
- {
- int err = 0;
- err = ufs_set_write_protect(0, UFS_LU_BOOT1, 0, 0, WP_DISABLE);
- if (err) {
- UFS_DBG_LOGE("[%s]: Clear UFS_LU_BOOT1 write protect fail\n", __func__);
- goto out;
- }
- err = ufs_set_write_protect(0, UFS_LU_BOOT2, 0, 0, WP_DISABLE);
- if (err) {
- UFS_DBG_LOGE("[%s]: Clear UFS_LU_BOOT2 write protect fail\n", __func__);
- goto out;
- }
- err |= ufs_set_write_protect(0, UFS_LU_USER, 0, 0, WP_DISABLE);
- if (err) {
- UFS_DBG_LOGE("[%s]: Clear UFS_LU_USER write protect fail\n", __func__);
- goto out;
- }
- out:
- return err;
- }
- #if defined(MTK_UFS_DRV_LK)
- static int ufshcd_rpmb_read_data_req_prepare(struct ufs_aio_scsi_cmd *cmd,
- u32 size, u16 addr)
- {
- struct rpmb_data_frame *pfrm = NULL;
- if (cmd == NULL) {
- UFS_DBG_LOGE("[%s]: RPMB cmd pointer NULL\n", __func__);
- return -1;
- }
- pfrm = cmd->data_buf;
- if (pfrm == NULL) {
- UFS_DBG_LOGE("[%s]: RPMB pfrm pointer NULL\n", __func__);
- return -1;
- }
- memset(pfrm, 0, sizeof(struct rpmb_data_frame));
- /* Prepare write frame */
- pfrm->addr = cpu_to_be16(addr);
- pfrm->blk_cnt = cpu_to_be16(1);
- pfrm->req_resp = cpu_to_be16(RPMB_REQ_AUTHEN_READ);
- return 0;
- }
- int ufs_rpmb_read_data(u32 addr, u32 *buf, u32 buf_len)
- {
- struct ufs_aio_scsi_cmd cmd;
- struct ufs_hba *hba;
- int tag;
- u8 *nonce_buf = NULL;
- u8 *data_buf;
- u32 host_id = 0;
- u32 blk_len;
- u32 left_size = buf_len;
- u32 tran_size;
- u32 i;
- int ret = 0;
- cmd.data_buf = ufs_rpmb_buf;
- hba = ufs_aio_get_host(0);
- if (buf_len % RPMB_FRM_DATA_LEN != 0) {
- UFS_DBG_LOGE("[%s]: RPMB read write need 256 ytes align\n", __func__);
- return -1;
- }
- blk_len = buf_len / RPMB_FRM_DATA_LEN;
- data_buf = (u8 *)buf;
- if (!ufshcd_get_free_tag(hba, &tag))
- return -1;
- nonce_buf = rpmb_nonce_buf;
- memset(nonce_buf, 0, RPMB_FRM_NONCE_LEN);
- for (i = 0; i < blk_len; i++) {
- /* Step 1. Authen data read request */
- if (left_size >= RPMB_FRM_DATA_LEN)
- tran_size = RPMB_FRM_DATA_LEN;
- else
- tran_size = left_size;
- cmd_scsi_security_protocol_out(&cmd, tag, 1,
- UFS_SECURITY_PROTOCOL,
- RPMB_PROTOCOL_ID);
- ret = ufshcd_rpmb_read_data_req_prepare(&cmd, tran_size, addr + i);
- if (ret) {
- UFS_DBG_LOGE("[%s]: RPMB Fail in prepare frame, ret = %d \n", __func__, ret);
- goto exit;
- }
- ret = ufshcd_queuecommand(hba, &cmd);
- if (ret) {
- UFS_DBG_LOGE("[%s]: RPMB Fail in send read frame, ret = %d \n", __func__, ret);
- goto exit;
- }
- /* Step 2. Authen data read response */
- cmd_scsi_security_protocol_in(&cmd, tag, 1,
- UFS_SECURITY_PROTOCOL,
- RPMB_PROTOCOL_ID);
- ret = ufshcd_queuecommand(hba, &cmd);
- if (ret) {
- UFS_DBG_LOGE("[%s]: RPMB Fail in get read response, ret = %d \n", __func__, ret);
- goto exit;
- }
- /* Step3. Check Response and parser data*/
- ret = ufshcd_authen_data_read_rsp_check(host_id, &cmd,
- nonce_buf, RPMB_FRM_NONCE_LEN, (data_buf + i * RPMB_FRM_DATA_LEN), RPMB_RSP_AUTHEN_READ);
- if (ret) {
- UFS_DBG_LOGE("[%s]: RPMB Data Read Resp Check Fail, ret = %d \n", __func__, ret);
- goto exit;
- }
- left_size -= tran_size;
- }
- exit:
- ufshcd_put_tag(hba, tag);
- return ret;
- }
- static int ufshcd_rpmb_write_data_req_prepare(struct ufs_aio_scsi_cmd *cmd,
- const u8 *data_buf, u32 size, u32 wr_cnt, u16 addr)
- {
- struct rpmb_data_frame *pfrm = NULL;
- int ret = 0;
- if (cmd == NULL) {
- UFS_DBG_LOGE("[%s]: RPMB cmd pointer NULL\n", __func__);
- return -1;
- }
- if (data_buf == NULL) {
- UFS_DBG_LOGE("[%s]: RPMB data pointer NULL\n", __func__);
- return -1;
- }
- pfrm = cmd->data_buf;
- if (pfrm == NULL) {
- UFS_DBG_LOGE("[%s]: RPMB pfrm pointer NULL\n", __func__);
- return -1;
- }
- memset(pfrm, 0, sizeof(struct rpmb_data_frame));
- /* Prepare write frame */
- memcpy(pfrm->data, data_buf, size);
- pfrm->wr_cnt = cpu_to_be32(wr_cnt);
- pfrm->addr = cpu_to_be16(addr);
- pfrm->blk_cnt = cpu_to_be16(1);
- pfrm->req_resp = cpu_to_be16(RPMB_REQ_AUTHEN_WRITE);
- /* Compute hmac. */
- ret = rpmb_get_mac(pfrm);
- if (ret) {
- UFS_DBG_LOGE("[%s]: rpmb_get_mac fail\r\n", __func__);
- return -1;
- }
- memcpy(pfrm->key_MAC, shared_hmac_addr1, RPMB_FRM_KEY_MAC_LEN);
- return 0;
- }
- int ufs_rpmb_write_data(u32 addr, u32 *buf, u32 buf_len)
- {
- struct ufs_aio_scsi_cmd cmd;
- struct ufs_hba *hba;
- int tag;
- u8 *nonce_buf = NULL;
- u8 *data_buf;
- u32 wr_cnt = 0;
- u32 host_id = 0;
- u32 blk_len;
- u32 left_size = buf_len;
- u32 tran_size;
- u32 i;
- int ret = 0;
- cmd.data_buf = ufs_rpmb_buf;
- hba = ufs_aio_get_host(0);
- if (buf_len % RPMB_FRM_DATA_LEN != 0) {
- UFS_DBG_LOGE("[%s]: RPMB read write need 256 ytes align\n", __func__);
- return -1;
- }
- blk_len = buf_len / RPMB_FRM_DATA_LEN;
- data_buf = (u8 *)buf;
- /* Read RPMB write counter */
- nonce_buf = rpmb_nonce_buf;
- memset(nonce_buf, 0, RPMB_FRM_NONCE_LEN);
- ret = rpmb_authen_read_counter(host_id, nonce_buf, RPMB_FRM_NONCE_LEN,
- &wr_cnt);
- if (ret) {
- UFS_DBG_LOGE("[%s]: RPMB rpmb_authen_read_counter fail! ret = %d\n", __func__, ret);
- goto free_nonce_buf;
- }
- if (!ufshcd_get_free_tag(hba, &tag)) {
- ret = -1;
- goto free_nonce_buf;
- }
- for (i = 0; i < blk_len; i++) {
- /* Step 1. Authen data write request */
- if (left_size >= RPMB_FRM_DATA_LEN)
- tran_size = RPMB_FRM_DATA_LEN;
- else
- tran_size = left_size;
- cmd_scsi_security_protocol_out(&cmd, tag, 1,
- UFS_SECURITY_PROTOCOL,
- RPMB_PROTOCOL_ID);
- ret = ufshcd_rpmb_write_data_req_prepare(&cmd, (data_buf + i * RPMB_FRM_DATA_LEN), tran_size, wr_cnt, addr + i);
- if (ret) {
- UFS_DBG_LOGE("[%s]: RPMB Fail in prepare frame, ret = %d \n", __func__, ret);
- goto exit;
- }
- ret = ufshcd_queuecommand(hba, &cmd);
- if (ret) {
- UFS_DBG_LOGE("[%s]: RPMB Fail in send write frame, ret = %d \n", __func__, ret);
- goto exit;
- }
- /* Step 2. Result Register Read Request */
- cmd_scsi_security_protocol_out(&cmd, tag, 1,
- UFS_SECURITY_PROTOCOL,
- RPMB_PROTOCOL_ID);
- ufshcd_authen_result_read_req_prepare(&cmd);
- ret = ufshcd_queuecommand(hba, &cmd);
- if (ret) {
- UFS_DBG_LOGE("[%s]: RPMB Fail in sending result register read request, ret = %d \n", __func__, ret);
- goto exit;
- }
- /* Step3. Check Response for Result Read Request */
- cmd_scsi_security_protocol_in(&cmd, tag, 1,
- UFS_SECURITY_PROTOCOL,
- RPMB_PROTOCOL_ID);
- if ((ret = ufshcd_queuecommand(hba, &cmd))) {
- UFS_DBG_LOGE("[%s]: RPMB Fail in sending request get result register response, ret = %d \n", __func__, ret);
- goto exit;
- }
- /* Step3. Response frame check */
- if ((ret = ufshcd_authen_data_write_rsp_check(host_id, &cmd, wr_cnt,
- RPMB_RSP_AUTHEN_WRITE))) {
- UFS_DBG_LOGE("[%s]: RPMB WriteCounter Read Resp Check Fail, ret = %d \n", __func__, ret);
- goto exit;
- }
- left_size -= tran_size;
- wr_cnt++;
- }
- exit:
- ufshcd_put_tag(hba, tag);
- free_nonce_buf:
- return ret;
- }
- #endif //#if defined(MTK_UFS_DRV_LK)
|