| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688 |
- /* 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 CFG_RPMB_KEY_RETRY_IN_PL
- #include <hmac.h>
- extern char g_rpmb_key[];
- #endif
- #if defined(MTK_UFS_DRV_DA)
- #include "malloc.h"
- #include "boot/security_export/rpmb_hmac.h"
- #endif
- 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;
- u8 *data_for_hmac;
- if (pfrm == NULL) {
- UFS_DBG_LOGE("[%s]: RPMB pfrm pointer NULL\n", __func__);
- return -1;
- }
- data_for_hmac = pfrm->data;
- memcpy(shared_msg_addr1, data_for_hmac, HMAC_TEXT_LEN);
- 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 = (u8 *)malloc(RPMB_FRM_NONCE_LEN);
- if (nonce_buf == NULL)
- return -1;
- 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);
- free(nonce_buf);
- 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
- free(nonce_buf);
- return ret;
- }
- #if defined(MTK_UFS_DRV_LK) || defined(MTK_UFS_DRV_DA)
- #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)
- 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 (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_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)
- 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;
- }
- 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_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)
- 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 (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_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]), 0x00, 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]), 0x00, WP_ENTRY_SIZE * (SWPWP_ENTRY_NUM - 1));
- }
- otp_found++;
- } else {
- /* clear all other entries */
- memset(&(swpcb->wp_entry[i]), 0x00, 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]), 0x00, 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;
- u32 blk_num = 1;
- int ret = 0;
- u8 wp_entry = 0;
- nonce_buf = (u8 *)malloc(RPMB_FRM_NONCE_LEN);
- if (nonce_buf == NULL)
- return -1;
- memset(nonce_buf, 0, RPMB_FRM_NONCE_LEN);
- data_buf = (u8 *)malloc(256 * blk_num);
- if (data_buf == NULL) {
- free(nonce_buf);
- return -1;
- }
- memset(data_buf, 0x0, 256 * blk_num);
- /* 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, blk_num, 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, blk_num, 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 0x%x blks\n",blk_num);
- exit:
- free(nonce_buf);
- free(data_buf);
- 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;
- u32 blk_num = 1;
- int ret = 0;
- u8 wp_entry = 0;
- struct secure_wp_config_block *swpcb;
- nonce_buf = (u8 *)malloc(RPMB_FRM_NONCE_LEN);
- if (nonce_buf == NULL)
- return -1;
- memset(nonce_buf, 0, RPMB_FRM_NONCE_LEN);
- data_buf = (u8 *)malloc(256 * blk_num);
- if (data_buf == NULL) {
- free(nonce_buf);
- return -1;
- }
- memset(data_buf, 0x0, 256 * blk_num);
- 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, blk_num, 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 0x%x blks\n", blk_num);
- exit:
- free(nonce_buf);
- free(data_buf);
- 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 ufs_set_write_protect start: partition = %d blknr = 0x%lx, blkcnt = 0x%x, wp_type = %d \n", __func__, partition, blknr, blkcnt, type);
- 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);
- err |= ufs_set_write_protect(0, UFS_LU_BOOT2, 0, 0, WP_DISABLE);
- err |= ufs_set_write_protect(0, UFS_LU_USER, 0, 0, WP_DISABLE);
- return err;
- }
- #endif /* #if defined(MTK_UFS_DRV_LK) || defined(MTK_UFS_DRV_DA) */
- #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 = (u8 *)malloc(RPMB_FRM_NONCE_LEN);
- if (nonce_buf == NULL)
- return -1;
- 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);
- free(nonce_buf);
- 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 = (u8 *)malloc(RPMB_FRM_NONCE_LEN);
- if (nonce_buf == NULL)
- return -1;
- 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:
- free(nonce_buf);
- return ret;
- }
- #endif //#if defined(MTK_UFS_DRV_LK)
|