/* This function will pack the data to be sent to the modem using the * payload, payload length and pack id
*/ staticint ipc_flash_proc_format_ebl_pack(struct iosm_flash_data *flash_req,
u32 pack_length, u16 pack_id,
u8 *payload, u32 payload_length)
{
u16 checksum = pack_id;
u32 i;
if (payload_length + IOSM_EBL_HEAD_SIZE > pack_length) return -EINVAL;
for (i = 0; i < payload_length; i++)
checksum += payload[i];
flash_req->checksum = cpu_to_le16(checksum);
return 0;
}
/* validate the response received from modem and * check the type of errors received
*/ staticint ipc_flash_proc_check_ebl_rsp(void *hdr_rsp, void *payload_rsp)
{ struct iosm_ebl_error *err_info = payload_rsp;
u16 *rsp_code = hdr_rsp;
u32 i;
if (*rsp_code == IOSM_EBL_RSP_BUFF) { for (i = 0; i < IOSM_MAX_ERRORS; i++) { if (!err_info->error[i].error_code) {
pr_err("EBL: error_class = %d, error_code = %d",
err_info->error[i].error_class,
err_info->error[i].error_code);
}
} return -EINVAL;
}
return 0;
}
/* Send data to the modem */ staticint ipc_flash_send_data(struct iosm_devlink *ipc_devlink, u32 size,
u16 pack_id, u8 *payload, u32 payload_length)
{ struct iosm_flash_data flash_req; int ret;
ret = ipc_flash_proc_format_ebl_pack(&flash_req, size,
pack_id, payload, payload_length); if (ret) {
dev_err(ipc_devlink->dev, "EBL2 pack failed for pack_id:%d",
pack_id); goto ipc_free_payload;
}
ret = ipc_imem_sys_devlink_write(ipc_devlink, (u8 *)&flash_req,
IOSM_EBL_HEAD_SIZE); if (ret) {
dev_err(ipc_devlink->dev, "EBL Header write failed for Id:%x",
pack_id); goto ipc_free_payload;
}
ret = ipc_imem_sys_devlink_write(ipc_devlink, payload, payload_length); if (ret) {
dev_err(ipc_devlink->dev, "EBL Payload write failed for Id:%x",
pack_id);
}
ipc_free_payload: return ret;
}
/** * ipc_flash_link_establish - Flash link establishment * @ipc_imem: Pointer to struct iosm_imem * * Returns: 0 on success and failure value on error
*/ int ipc_flash_link_establish(struct iosm_imem *ipc_imem)
{
u8 ler_data[IOSM_LER_RSP_SIZE];
u32 bytes_read;
/* Allocate channel for flashing/cd collection */
ipc_imem->ipc_devlink->devlink_sio.channel =
ipc_imem_sys_devlink_open(ipc_imem);
if (!ipc_imem->ipc_devlink->devlink_sio.channel) goto chl_open_fail;
if (ipc_imem_sys_devlink_read(ipc_imem->ipc_devlink, ler_data,
IOSM_LER_RSP_SIZE, &bytes_read)) goto devlink_read_fail;
if (bytes_read != IOSM_LER_RSP_SIZE) goto devlink_read_fail;
/* Receive data from the modem */ staticint ipc_flash_receive_data(struct iosm_devlink *ipc_devlink, u32 size,
u8 *mdm_rsp)
{
u8 mdm_rsp_hdr[IOSM_EBL_HEAD_SIZE];
u32 bytes_read; int ret;
ret = ipc_imem_sys_devlink_read(ipc_devlink, mdm_rsp_hdr,
IOSM_EBL_HEAD_SIZE, &bytes_read); if (ret) {
dev_err(ipc_devlink->dev, "EBL rsp to read %d bytes failed",
IOSM_EBL_HEAD_SIZE); goto ipc_flash_recv_err;
}
if (bytes_read != IOSM_EBL_HEAD_SIZE) {
ret = -EINVAL; goto ipc_flash_recv_err;
}
ret = ipc_imem_sys_devlink_read(ipc_devlink, mdm_rsp, size,
&bytes_read); if (ret) {
dev_err(ipc_devlink->dev, "EBL rsp to read %d bytes failed",
size); goto ipc_flash_recv_err;
}
if (bytes_read != size) {
ret = -EINVAL; goto ipc_flash_recv_err;
}
ret = ipc_flash_proc_check_ebl_rsp(mdm_rsp_hdr + 2, mdm_rsp);
ipc_flash_recv_err: return ret;
}
/* Function to send command to modem and receive response */ staticint ipc_flash_send_receive(struct iosm_devlink *ipc_devlink, u16 pack_id,
u8 *payload, u32 payload_length, u8 *mdm_rsp)
{
size_t frame_len = IOSM_EBL_DW_PACK_SIZE; int ret;
if (pack_id == FLASH_SET_PROT_CONF)
frame_len = IOSM_EBL_W_PACK_SIZE;
ret = ipc_flash_send_data(ipc_devlink, frame_len, pack_id, payload,
payload_length); if (ret) goto ipc_flash_send_rcv;
ret = ipc_flash_receive_data(ipc_devlink,
frame_len - IOSM_EBL_HEAD_SIZE, mdm_rsp);
ipc_flash_send_rcv: return ret;
}
/** * ipc_flash_boot_set_capabilities - Set modem boot capabilities in flash * @ipc_devlink: Pointer to devlink structure * @mdm_rsp: Pointer to modem response buffer * * Returns: 0 on success and failure value on error
*/ int ipc_flash_boot_set_capabilities(struct iosm_devlink *ipc_devlink,
u8 *mdm_rsp)
{
ipc_devlink->ebl_ctx.ebl_sw_info_version =
ipc_devlink->ebl_ctx.m_ebl_resp[EBL_RSP_SW_INFO_VER];
ipc_devlink->ebl_ctx.m_ebl_resp[EBL_SKIP_ERASE] = IOSM_CAP_NOT_ENHANCED;
ipc_devlink->ebl_ctx.m_ebl_resp[EBL_SKIP_CRC] = IOSM_CAP_NOT_ENHANCED;
if (ipc_devlink->ebl_ctx.m_ebl_resp[EBL_CAPS_FLAG] &
IOSM_CAP_USE_EXT_CAP) { if (ipc_devlink->param.erase_full_flash)
ipc_devlink->ebl_ctx.m_ebl_resp[EBL_OOS_CONFIG] &=
~((u8)IOSM_EXT_CAP_ERASE_ALL); else
ipc_devlink->ebl_ctx.m_ebl_resp[EBL_OOS_CONFIG] &=
~((u8)IOSM_EXT_CAP_COMMIT_ALL);
ipc_devlink->ebl_ctx.m_ebl_resp[EBL_EXT_CAPS_HANDLED] =
IOSM_CAP_USE_EXT_CAP;
}
/* Write back the EBL capability to modem * Request Set Protcnf command
*/ return ipc_flash_send_receive(ipc_devlink, FLASH_SET_PROT_CONF,
ipc_devlink->ebl_ctx.m_ebl_resp,
IOSM_EBL_RSP_SIZE, mdm_rsp);
}
/* Read the SWID type and SWID value from the EBL */ int ipc_flash_read_swid(struct iosm_devlink *ipc_devlink, u8 *mdm_rsp)
{ struct iosm_flash_msg_control cmd_msg; struct iosm_swid_table *swid; char ebl_swid[IOSM_SWID_STR]; int ret;
if (ipc_devlink->ebl_ctx.ebl_sw_info_version !=
IOSM_EXT_CAP_SWID_OOS_PACK) return -EINVAL;
/* Function to check if full erase or conditional erase was successful */ staticint ipc_flash_erase_check(struct iosm_devlink *ipc_devlink, u8 *mdm_rsp)
{ int ret, count = 0;
u16 mdm_rsp_data;
/* Request Flash Erase Check */ do {
mdm_rsp_data = IOSM_MDM_SEND_DATA;
ret = ipc_flash_send_receive(ipc_devlink, FLASH_ERASE_CHECK,
(u8 *)&mdm_rsp_data,
IOSM_MDM_SEND_2, mdm_rsp); if (ret) goto ipc_erase_chk_err;
if (mdm_rsp_data != IOSM_MDM_ERASE_RSP) {
dev_err(ipc_devlink->dev, "Modem erase check timeout failure!");
ret = -ETIMEDOUT;
}
ipc_erase_chk_err: return ret;
}
/* Full erase function which will erase the nand flash through EBL command */ staticint ipc_flash_full_erase(struct iosm_devlink *ipc_devlink, u8 *mdm_rsp)
{
u32 erase_address = IOSM_ERASE_START_ADDR; struct iosm_flash_msg_control cmd_msg;
u32 erase_length = IOSM_ERASE_LEN; int ret;
if (read_data[0] == 0x00 && read_data[1] == 0xCD) {
dev_dbg(ipc_devlink->dev, "Coredump detected");
ret = ipc_coredump_get_list(ipc_devlink,
rpsi_cmd_coredump_start); if (ret)
dev_err(ipc_devlink->dev, "Failed to get cd list");
}
dev_dbg(ipc_devlink->dev, "Boot transfer EBL");
ret = ipc_devlink_send_cmd(ipc_devlink, rpsi_cmd_code_ebl,
IOSM_RPSI_LOAD_SIZE); if (ret) {
dev_err(ipc_devlink->dev, "Sending rpsi_cmd_code_ebl failed"); goto ipc_flash_ebl_err;
}
ret = ipc_imem_sys_devlink_read(ipc_devlink, read_data, IOSM_READ_SIZE,
&bytes_read); if (ret) {
dev_err(ipc_devlink->dev, "rpsi_cmd_code_ebl read failed"); goto ipc_flash_ebl_err;
}
if (bytes_read != IOSM_READ_SIZE) {
ret = -EINVAL; goto ipc_flash_ebl_err;
}
ret = ipc_imem_sys_devlink_write(ipc_devlink, (u8 *)&ebl_size, sizeof(ebl_size)); if (ret) {
dev_err(ipc_devlink->dev, "EBL length write failed"); goto ipc_flash_ebl_err;
}
ret = ipc_imem_sys_devlink_read(ipc_devlink, read_data, IOSM_READ_SIZE,
&bytes_read); if (ret) {
dev_err(ipc_devlink->dev, "EBL read failed"); goto ipc_flash_ebl_err;
}
if (bytes_read != IOSM_READ_SIZE) {
ret = -EINVAL; goto ipc_flash_ebl_err;
}
ret = ipc_imem_sys_devlink_write(ipc_devlink,
(u8 *)fw->data + IOSM_DEVLINK_HDR_SIZE,
ebl_size); if (ret) {
dev_err(ipc_devlink->dev, "EBL data transfer failed"); goto ipc_flash_ebl_err;
}
ret = ipc_imem_sys_devlink_read(ipc_devlink, read_data, IOSM_READ_SIZE,
&bytes_read); if (ret) {
dev_err(ipc_devlink->dev, "EBL read failed"); goto ipc_flash_ebl_err;
}
if (bytes_read != IOSM_READ_SIZE) {
ret = -EINVAL; goto ipc_flash_ebl_err;
}
ret = ipc_imem_sys_devlink_read(ipc_devlink,
ipc_devlink->ebl_ctx.m_ebl_resp,
IOSM_EBL_RSP_SIZE, &bytes_read); if (ret) {
dev_err(ipc_devlink->dev, "EBL response read failed"); goto ipc_flash_ebl_err;
}
if (bytes_read != IOSM_EBL_RSP_SIZE)
ret = -EINVAL;
ipc_flash_ebl_err: return ret;
}
Messung V0.5
¤ Dauer der Verarbeitung: 0.2 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.