This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] AM623:在选项中锁定 OTP 行

Guru**** 2487425 points


请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/processors-group/processors/f/processors-forum/1435743/am623-lock-otp-row-in-opteeos

器件型号:AM623

工具与软件:

您好、TI 专家!  

我有 AM6234的开发环境、其中包含我们自己的评估板。

软件 SDK 版本是 SDK-AM62X-08.06.00.42 PROCESSOR-SDK-LINUX-RT。

optee 版本为 3.20.0

我只想对扩展 OTP 行执行 HW_READ_LOCK、但在实际测试中、不仅锁定了行读取、还锁定了行写入、如下所示:

锁定外部 OTP 行的日志

2.外部 OTP 行的锁定状态:

相应的测试代码如下所示:

// ti-processor-sdk-linux-rt-am62xx-evm-08.06.00.42\board-support\optee_os-3.20.0\core\pta\k3\otp.c
static TEE_Result lock_otp_row(uint32_t param_types, TEE_Param params[4])
{
	TEE_Result ret = TEE_SUCCESS;
	uint8_t hw_write_lock = 0;
	uint8_t hw_read_lock = 0;
	uint8_t soft_lock = 0;
	const uint32_t exp_param_types =
		TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_NONE,
				TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE);

	/*
	 * Safely get the invocation parameters
	 */
	if (param_types != exp_param_types)
		return TEE_ERROR_BAD_PARAMETERS;

	if (params[0].value.b & K3_OTP_KEYWRITING_SOFT_LOCK)
		soft_lock = 0x5A;
	if (params[0].value.b & K3_OTP_KEYWRITING_HW_READ_LOCK)
		hw_read_lock = 0x5A;
	if (params[0].value.b & K3_OTP_KEYWRITING_HW_WRITE_LOCK)
		hw_write_lock = 0x5A;

	DMSG("hw_write_lock: 0x%x", hw_write_lock);
	DMSG("hw_read_lock: 0x%x", hw_read_lock);
	DMSG("soft_lock: 0x%x", soft_lock);

	ret = ti_sci_lock_otp_row(params[0].value.a, hw_write_lock,
				  hw_read_lock, soft_lock);

	if (ret)
		return ret;

	DMSG("Locked the row: 0x%08"PRIx32, params[1].value.a);

	return TEE_SUCCESS;
}

static TEE_Result get_otp_row_lock_status(uint32_t param_types, TEE_Param params[4])
{
    TEE_Result ret = TEE_SUCCESS;
    uint8_t global_soft_lock, hw_write_lock, hw_read_lock, row_soft_lock;
    const uint32_t exp_param_types =
        TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_VALUE_OUTPUT,
                        TEE_PARAM_TYPE_VALUE_OUTPUT, TEE_PARAM_TYPE_VALUE_OUTPUT);

    /*
     * Safely get the invocation parameters
     */
    if (param_types != exp_param_types)
        return TEE_ERROR_BAD_PARAMETERS;

    ret = ti_sci_get_otp_row_lock_status(params[0].value.a, &global_soft_lock,
                                         &hw_write_lock, &hw_read_lock, &row_soft_lock);
    if (ret)
        return ret;

    params[1].value.a = global_soft_lock;
    params[2].value.a = hw_write_lock;
    params[3].value.a = hw_read_lock;
    params[3].value.b = row_soft_lock;

    DMSG("OTP row %u lock status: global_soft_lock=0x%02x, hw_write_lock=0x%02x, hw_read_lock=0x%02x, row_soft_lock=0x%02x",
         params[0].value.a, global_soft_lock, hw_write_lock, hw_read_lock, row_soft_lock);

    return TEE_SUCCESS;
}


// ti-processor-sdk-linux-rt-am62xx-evm-08.06.00.42\board-support\optee_os-3.20.0\core\arch\arm\plat-k3\drivers\ti_sci.c
int ti_sci_lock_otp_row(uint8_t row_idx, uint8_t hw_write_lock,
			uint8_t hw_read_lock, uint8_t row_soft_lock)
{
	struct ti_sci_msg_req_lock_otp_row req = { };
	struct ti_sci_msg_resp_lock_otp_row resp = { };
	struct ti_sci_xfer xfer = { };
	int ret = 0;

	ret = ti_sci_setup_xfer(TI_SCI_MSG_LOCK_OTP_ROW, 0,
				&req, sizeof(req), &resp, sizeof(resp), &xfer);
	if (ret)
		return ret;

	req.row_idx = row_idx;
	req.hw_write_lock = hw_write_lock;
	req.hw_read_lock = hw_read_lock;
	req.row_soft_lock = row_soft_lock;

	DMSG("row_idx: 0x%x", req.row_idx);
	DMSG("hw_write_lock: 0x%x", req.hw_write_lock);
	DMSG("hw_read_lock: 0x%x", req.hw_read_lock);
	DMSG("soft_lock: 0x%x", req.row_soft_lock);

	ret = ti_sci_do_xfer(&xfer);
	if (ret)
		return ret;

	return 0;
}

int ti_sci_get_otp_row_lock_status(uint8_t row_idx, uint8_t *global_soft_lock,
                                  uint8_t *hw_write_lock, uint8_t *hw_read_lock,
                                  uint8_t *row_soft_lock)
{
	struct ti_sci_msg_req_get_otp_row_lock_status req = { };
	struct ti_sci_msg_resp_get_otp_row_lock_status resp = { };
	struct ti_sci_xfer xfer = { };
	int ret = 0;

	ret = ti_sci_setup_xfer(TI_SCI_MSG_GET_OTP_ROW_LOCK_STATUS, 0,
						   &req, sizeof(req), &resp, sizeof(resp), &xfer);
	if (ret)
		return ret;

	req.row_idx = row_idx;

	ret = ti_sci_do_xfer(&xfer);
	if (ret)
		return ret;

	*global_soft_lock = resp.global_soft_lock;
	*hw_write_lock = resp.hw_write_lock;
	*hw_read_lock = resp.hw_read_lock;
	*row_soft_lock = resp.row_soft_lock;

	return 0;
}

此致、

Li

 

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好!

    我只想对扩展 OTP 行执行 hw_read_lock、但在实际测试中、不仅锁定了行读取、还锁定了行写入、如下所示:

    这是预期行为。 如果为一行请求了读取锁定、TIFS 也会启用写入锁定。

    此致、

    Prashant

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好!

    当我仅执行硬件写入锁定操作时、会发生硬件读取锁定、如下图所示

    但我在 MCU SDK 中执行相同的操作、只有硬件写入锁定和硬件读取解锁、我对 Optee 中为什么会发生此类错误感到不解。

    此致、

    Li

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好!

    您是否尝试过从 MCU+ SDK 中读取第3行的状态?

    目的是查看在 OPTE_OS 或 TEE_OTP 客户端中获取状态时是否存在实现错误。

    此致、

    Prashant

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好!

    我使用 MCU SDK 读取第3行的锁定状态、结果显示硬读取锁定:

    从上面的结果可以推断出、在 Optee 下执行硬读取锁定时、硬写入也会锁定。 同样、在执行硬写入锁定时、硬读取会锁定。 如何解决这一问题?

    MCU SDK 中不会出现上述现象。

    同时、即使硬件读取已锁定、仍可使用 Linux 中的 CA 程序读取第3行。 为什么即使在读取被锁定后也可以读取第3行?

    此致、

    Li

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好!

    同样、在执行硬写锁时、硬读锁也锁住了。

    此部件是意外出现的。 我先介绍 TISCI_MSG_LOCK_OTP_ROW 的 OPTEE 实现、然后回复。

    为什么即使在读取锁定后也可以读取第3行?

    读取由以下设置进行控制

    https://software-dl.ti.com/tisci/esd/latest/3_boardcfg/BOARDCFG_SEC.html#pub-boardcfg-otp-entry

    如果已将`host_id`设置为 ALL、则所有主机都可以读取相应的 MMR。

    此致、

    Prashant

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好!

    [报价 userid="531297" url="~/support/processors-group/processors/f/processors-forum/1435743/am623-lock-otp-row-in-opteeos/5507228 #5507228"]

    如果已将`host_id`设置为 ALL、则所有主机都可以读取相应的 MMR。

    [报价]

    扩展 OTP 的行硬件读取锁定是否意味着所有主机都无法读取扩展 OTP 的行?

    如果将 host_id 设置为 all 且仍然可以读取扩展 OTP 的行、则读取锁定有什么意义? 有哪些应用场景?

    此致、

    Li

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好!

    读取锁定权限位是低级 OTP 行的属性、而不是 MMR。 在冷复位时、扩展 OTP 行始终锁存到扩展 OTP MMR。

    然后、TIFS 提供 TISCI_MSG_READ_OTP_MMR API 以读取这些 MMR 而不是低电平 OTP 行。 然后、MMR 读取由安全板配置中的 host_id 字段控制。

    此致、

    Prashant

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好!

    [报价 userid="565545" url="~/support/processors-group/processors/f/processors-forum/1435743/am623-lock-otp-row-in-opteeos/5506657 #55066557"]

    同时、即使硬件读取已锁定、仍可使用 Linux 中的 CA 程序读取第3行。 为什么即使在读取被锁定后也可以读取第3行?

    [报价]

    我明白这句话的意思、即使在锁定该行后、使用 TISCI_MSG_READ_OTP_MMR  仍然可以正常读取 MMR。 但是、MCU SDK   为行读取提供了接口 ext_OTP_readRow、它会调用 MMR 读取接口  ext_OTP_readMmr。 因此、可以理解的是、即使在锁定该行后、行读取和 MMR 读取都可以正常读取 OTP。

    我的问题是、当行锁定后、OTP 读取不会受到任何影响。 行锁定 API 接口的用途是什么? 在什么情况下将使用行锁定功能?

    行读取和 MMR 读取的接口如下所示:

    // src\zy\ti-processor-sdk-mcu-plus-am62x-evm-08.06.00.18\examples\drivers\ipc\ipc_rpmsg_echo_linux\ext_otp.c
    /**
     *  \brief Function to read OTP MMR.
     *  	   Note: Host should have read permission to row.
     *  	   Read permissions to perticular row can be set via
     *  	   board configuration security.
     *
     *  \param mmrIdx   [IN] MMR index to read [0,31]
     *  \param mmrVal   [IN] Pointer to store read value
     *
     *  \return status [out] SystemP_SUCCESS on success
     */
    int32_t ext_otp_readMmr(uint8_t mmrIdx, uint32_t *mmrVal)
    {
    	int32_t status = SystemP_SUCCESS;
    	Sciclient_ReqPrm_t reqParam;
    	Sciclient_RespPrm_t respParam;
    	struct tisci_msg_read_otp_mmr_req request;
    	struct tisci_msg_read_otp_mmr_resp response;
    
    	request.mmr_idx           = mmrIdx;
    
    	reqParam.messageType	  = (uint16_t) TISCI_MSG_READ_OTP_MMR;
    	reqParam.flags            = (uint32_t) TISCI_MSG_FLAG_AOP;
    	reqParam.pReqPayload      = (const uint8_t *) &request;
    	reqParam.reqPayloadSize   = (uint32_t) sizeof (request);
    	reqParam.timeout          = (uint32_t) SystemP_WAIT_FOREVER;
    
    	respParam.flags           = (uint32_t) 0;   /* Populated by the API */
    	respParam.pRespPayload    = (uint8_t *) &response;
    	respParam.respPayloadSize = (uint32_t) sizeof (response);
    
    	status = Sciclient_service(&reqParam, &respParam);
    	DebugP_logInfo("status: 0x%x respParam.flags:0x%x response.mmr_val:0x%x\r\n", status, respParam.flags, response.mmr_val);
    	if ( (status==SystemP_SUCCESS) && ((respParam.flags & TISCI_MSG_FLAG_ACK) == TISCI_MSG_FLAG_ACK) )
    	{
    		*mmrVal = response.mmr_val;
    		DebugP_logInfo("Success Reading OTP MMR %d\r\n", mmrIdx);
    		DebugP_logInfo("OTP MMR Value reported :0x%x \r\n", (uint32_t) *mmrVal);
    	}
    	else
    	{
    		DebugP_logError("Error Reading OTP MMR %d, status:%d resFlags:%d\r\n", mmrIdx, status, respParam.flags);
    		status = SystemP_FAILURE;
    	}
    
    	return status;
    }
    
    /**
     *  \brief Function to read OTP ROM row value.
     *
     *  \param rowIdx  [IN] Row index to read
     *  \param rowVal  [OUT] Pointer to store read value
     *
     *  \return status [out] SystemP_SUCCESS on success
     */
    int32_t ext_otp_readRow(uint8_t rowIdx, uint32_t *rowVal)
    {
        int32_t status = SystemP_SUCCESS;
        uint32_t mmrIdx, mmrOffset;
        uint32_t mmrVal1 = 0, mmrVal2 = 0;
        uint32_t resultVal = 0;
    
        /* Calculate which MMR contains this row */
        mmrIdx = (rowIdx * NUM_BITS_PER_OTP_ROW - OTP_COL_OFFSET) / MMR_SIZE_BITS;
    
        /* Calculate bit offset within the MMR(s) */
        mmrOffset = (rowIdx * NUM_BITS_PER_OTP_ROW - OTP_COL_OFFSET) % MMR_SIZE_BITS;
    
        /* Read first MMR */
        status = ext_otp_readMmr(mmrIdx, &mmrVal1);
        if(status != SystemP_SUCCESS) {
            return status;
        }
    
        if(mmrOffset + NUM_BITS_PER_OTP_ROW <= MMR_SIZE_BITS) {
            /* Row fits in single MMR */
            resultVal = (mmrVal1 >> mmrOffset) & OTP_ROW_FULL_MASK;
        } else {
            /* Row spans two MMRs */
            status = ext_otp_readMmr(mmrIdx + 1, &mmrVal2);
            if(status != SystemP_SUCCESS) {
                return status;
            }
    
            /* Combine values from both MMRs */
            uint32_t bits_from_mmr1 = MMR_SIZE_BITS - mmrOffset;
            uint32_t bits_from_mmr2 = NUM_BITS_PER_OTP_ROW - bits_from_mmr1;
    
            resultVal = ((mmrVal1 >> mmrOffset) & ((1U << bits_from_mmr1) - 1)) |
                       ((mmrVal2 & ((1U << bits_from_mmr2) - 1)) << bits_from_mmr1);
            resultVal &= OTP_ROW_FULL_MASK;
        }
    
        *rowVal = resultVal;
    
        DebugP_logInfo("Success Reading OTP ROM row %d\r\n", rowIdx);
        DebugP_logInfo("ROM Value: 0x%x\r\n", resultVal);
    
        return status;
    }

    此致、
    Li

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好!

    因此、可以理解、即使在锁定行后、行读取和 MMR 读取也能正常读取 OTP。

    TIFS 不提供任何用于读取低级行的 API。 `ext_otp_readMmr`函数虽然用于读取行、但它只是计算所需的要读取的 MMR 索引并从这些索引中派生行值。 因此、从不读取低级别行。

    我的问题是、在锁定该行后、对 OTP 的读取不会受到任何影响。 行锁定 API 接口的用途是什么? 在什么情况下将使用此行锁定功能?

    对于扩展 OTP、读取锁定实际上没有任何用例。 假设、如果 TIFS 提供一个 API 接口来读取低电平行、那么它本来可以利用读取锁定权限位以某种方式控制读取。

    与安全 OTP 类似、TIFS 利用读取锁定权限位来确定是否可以使用 TISCI_MSG_READ_KEYCNT_KEYREV 读回 KEYCNT、KEYREV 。

    此致、

    Prashant

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好!

    感谢您的详细回答!

    您对上一个问题有任何想法?

    [报价 userid="531297" url="~/support/processors-group/processors/f/processors-forum/1435743/am623-lock-otp-row-in-opteeos/5507228 #5507228"]

    此部件是意外出现的。 我先介绍 TISCI_MSG_LOCK_OTP_ROW 的 OPTEE 实现、然后回复。

    [报价]

    此致、
    Li

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好!

    [报价 userid="531297" url="~/support/processors-group/processors/f/processors-forum/1435743/am623-lock-otp-row-in-opteeos/5507228 #5507228"]

    此部件是意外出现的。 我先介绍 TISCI_MSG_LOCK_OTP_ROW 的 OPTEE 实现、然后回复。

    [报价]

    是否有解决此问题的方法?

    此致、
    Li

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好!

    我已经检查了实现情况、一切看起来都很好。

    如果可能、您是否可以为不同的行再次执行该过程并共享所有引导日志? 更具体地说、 我想查看仅写入锁定时`ti_sci_lock_OTP_row`函数中变量的值。

    谢谢!