[media] drx-j: Split firmware size check from the main routine

The firmware upload routine is already complex enough. Split the
first loop that verifies the firmware size into a separate routine,
making the code more readable.
Acked-by: NDevin Heitmueller <dheitmueller@kernellabs.com>
Signed-off-by: NMauro Carvalho Chehab <m.chehab@samsung.com>
上级 b48293db
master alk-4.19.24 alk-4.19.30 alk-4.19.34 alk-4.19.36 alk-4.19.43 alk-4.19.48 alk-4.19.57 ck-4.19.67 ck-4.19.81 ck-4.19.91 github/fork/deepanshu1422/fix-typo-in-comment github/fork/haosdent/fix-typo linux-next v4.19.91 v4.19.90 v4.19.89 v4.19.88 v4.19.87 v4.19.86 v4.19.85 v4.19.84 v4.19.83 v4.19.82 v4.19.81 v4.19.80 v4.19.79 v4.19.78 v4.19.77 v4.19.76 v4.19.75 v4.19.74 v4.19.73 v4.19.72 v4.19.71 v4.19.70 v4.19.69 v4.19.68 v4.19.67 v4.19.66 v4.19.65 v4.19.64 v4.19.63 v4.19.62 v4.19.61 v4.19.60 v4.19.59 v4.19.58 v4.19.57 v4.19.56 v4.19.55 v4.19.54 v4.19.53 v4.19.52 v4.19.51 v4.19.50 v4.19.49 v4.19.48 v4.19.47 v4.19.46 v4.19.45 v4.19.44 v4.19.43 v4.19.42 v4.19.41 v4.19.40 v4.19.39 v4.19.38 v4.19.37 v4.19.36 v4.19.35 v4.19.34 v4.19.33 v4.19.32 v4.19.31 v4.19.30 v4.19.29 v4.19.28 v4.19.27 v4.19.26 v4.19.25 v4.19.24 v4.19.23 v4.19.22 v4.19.21 v4.19.20 v4.19.19 v4.19.18 v4.19.17 v4.19.16 v4.19.15 v4.19.14 v4.19.13 v4.19.12 v4.19.11 v4.19.10 v4.19.9 v4.19.8 v4.19.7 v4.19.6 v4.19.5 v4.19.4 v4.19.3 v4.19.2 v4.19.1 v4.19 v4.19-rc8 v4.19-rc7 v4.19-rc6 v4.19-rc5 v4.19-rc4 v4.19-rc3 v4.19-rc2 v4.19-rc1 ck-release-21 ck-release-20 ck-release-19.2 ck-release-19.1 ck-release-19 ck-release-18 ck-release-17.2 ck-release-17.1 ck-release-17 ck-release-16 ck-release-15.1 ck-release-15 ck-release-14 ck-release-13.2 ck-release-13 ck-release-12 ck-release-11 ck-release-10 ck-release-9 ck-release-7 alk-release-15 alk-release-14 alk-release-13.2 alk-release-13 alk-release-12 alk-release-11 alk-release-10 alk-release-9 alk-release-7
无相关合并请求
......@@ -933,6 +933,86 @@ static u16 u_code_compute_crc(u8 *block_data, u16 nr_words)
/*============================================================================*/
static int check_firmware(struct drx_demod_instance *demod, u8 *mc_data,
unsigned size)
{
struct drxu_code_block_hdr block_hdr;
int i;
unsigned count = 2 * sizeof(u16);
u32 mc_dev_type, mc_version, mc_base_version;
u16 mc_nr_of_blks = u_code_read16(mc_data + sizeof(u16));
/*
* Scan microcode blocks first for version info
* and firmware check
*/
/* Clear version block */
DRX_ATTR_MCRECORD(demod).aux_type = 0;
DRX_ATTR_MCRECORD(demod).mc_dev_type = 0;
DRX_ATTR_MCRECORD(demod).mc_version = 0;
DRX_ATTR_MCRECORD(demod).mc_base_version = 0;
for (i = 0; i < mc_nr_of_blks; i++) {
if (count + 3 * sizeof(u16) + sizeof(u32) > size)
goto eof;
/* Process block header */
block_hdr.addr = u_code_read32(mc_data + count);
count += sizeof(u32);
block_hdr.size = u_code_read16(mc_data + count);
count += sizeof(u16);
block_hdr.flags = u_code_read16(mc_data + count);
count += sizeof(u16);
block_hdr.CRC = u_code_read16(mc_data + count);
count += sizeof(u16);
pr_debug("%u: addr %u, size %u, flags 0x%04x, CRC 0x%04x\n",
count, block_hdr.addr, block_hdr.size, block_hdr.flags,
block_hdr.CRC);
if (block_hdr.flags & 0x8) {
u8 *auxblk = ((void *)mc_data) + block_hdr.addr;
u16 auxtype;
if (block_hdr.addr + sizeof(u16) > size)
goto eof;
auxtype = u_code_read16(auxblk);
/* Aux block. Check type */
if (DRX_ISMCVERTYPE(auxtype)) {
if (block_hdr.addr + 2 * sizeof(u16) + 2 * sizeof (u32) > size)
goto eof;
auxblk += sizeof(u16);
mc_dev_type = u_code_read32(auxblk);
auxblk += sizeof(u32);
mc_version = u_code_read32(auxblk);
auxblk += sizeof(u32);
mc_base_version = u_code_read32(auxblk);
DRX_ATTR_MCRECORD(demod).aux_type = auxtype;
DRX_ATTR_MCRECORD(demod).mc_dev_type = mc_dev_type;
DRX_ATTR_MCRECORD(demod).mc_version = mc_version;
DRX_ATTR_MCRECORD(demod).mc_base_version = mc_base_version;
pr_info("Firmware dev %x, ver %x, base ver %x\n",
mc_dev_type, mc_version, mc_base_version);
}
} else if (count + block_hdr.size * sizeof(u16) > size)
goto eof;
count += block_hdr.size * sizeof(u16);
}
return 0;
eof:
pr_err("Firmware is truncated at pos %u/%u\n", count, size);
return -EINVAL;
}
/**
* \brief Handle microcode upload or verify.
* \param dev_addr: Address of device.
......@@ -962,24 +1042,15 @@ ctrl_u_code(struct drx_demod_instance *demod,
u16 mc_magic_word = 0;
const u8 *mc_data_init = NULL;
u8 *mc_data = NULL;
unsigned size;
char *mc_file = mc_info->mc_file;
/* Check arguments */
if (!mc_info || !mc_file)
return -EINVAL;
if (demod->firmware) {
mc_data_init = demod->firmware->data;
mc_data = (void *)mc_data_init;
/* Check data */
mc_magic_word = u_code_read16(mc_data);
mc_data += sizeof(u16);
mc_nr_of_blks = u_code_read16(mc_data);
mc_data += sizeof(u16);
} else {
if (!demod->firmware) {
const struct firmware *fw = NULL;
unsigned size = 0;
rc = request_firmware(&fw, mc_file, demod->i2c->dev.parent);
if (rc < 0) {
......@@ -987,95 +1058,49 @@ ctrl_u_code(struct drx_demod_instance *demod,
return -ENOENT;
}
demod->firmware = fw;
mc_data_init = demod->firmware->data;
size = demod->firmware->size;
pr_info("Firmware %s, size %u\n", mc_file, size);
mc_data = (void *)mc_data_init;
/* Check data */
if (mc_data - mc_data_init + 2 * sizeof(u16) > size)
goto eof;
mc_magic_word = u_code_read16(mc_data);
mc_data += sizeof(u16);
mc_nr_of_blks = u_code_read16(mc_data);
mc_data += sizeof(u16);
if ((mc_magic_word != DRX_UCODE_MAGIC_WORD) || (mc_nr_of_blks == 0)) {
rc = -EINVAL; /* wrong endianess or wrong data ? */
pr_err("Firmware magic word doesn't match\n");
if (demod->firmware->size < 2 * sizeof(u16)) {
rc = -EINVAL;
pr_err("Firmware is too short!\n");
goto release;
}
/*
* Scan microcode blocks first for version info
* and firmware check
*/
/* Clear version block */
DRX_ATTR_MCRECORD(demod).aux_type = 0;
DRX_ATTR_MCRECORD(demod).mc_dev_type = 0;
DRX_ATTR_MCRECORD(demod).mc_version = 0;
DRX_ATTR_MCRECORD(demod).mc_base_version = 0;
for (i = 0; i < mc_nr_of_blks; i++) {
struct drxu_code_block_hdr block_hdr;
if (mc_data - mc_data_init +
3 * sizeof(u16) + sizeof(u32) > size)
goto eof;
/* Process block header */
block_hdr.addr = u_code_read32(mc_data);
mc_data += sizeof(u32);
block_hdr.size = u_code_read16(mc_data);
mc_data += sizeof(u16);
block_hdr.flags = u_code_read16(mc_data);
mc_data += sizeof(u16);
block_hdr.CRC = u_code_read16(mc_data);
mc_data += sizeof(u16);
if (block_hdr.flags & 0x8) {
u8 *auxblk = ((void *)mc_data_init) + block_hdr.addr;
u16 auxtype;
if (mc_data - mc_data_init + sizeof(u16) +
2 * sizeof(u32) > size)
goto eof;
pr_info("Firmware %s, size %zu\n",
mc_file, demod->firmware->size);
}
/* Aux block. Check type */
auxtype = u_code_read16(auxblk);
if (DRX_ISMCVERTYPE(auxtype)) {
DRX_ATTR_MCRECORD(demod).aux_type = u_code_read16(auxblk);
auxblk += sizeof(u16);
DRX_ATTR_MCRECORD(demod).mc_dev_type = u_code_read32(auxblk);
auxblk += sizeof(u32);
DRX_ATTR_MCRECORD(demod).mc_version = u_code_read32(auxblk);
auxblk += sizeof(u32);
DRX_ATTR_MCRECORD(demod).mc_base_version = u_code_read32(auxblk);
}
}
if (mc_data - mc_data_init +
block_hdr.size * sizeof(u16) > size)
goto eof;
mc_data_init = demod->firmware->data;
size = demod->firmware->size;
/* Next block */
mc_data += block_hdr.size * sizeof(u16);
}
mc_data = (void *)mc_data_init;
/* Check data */
mc_magic_word = u_code_read16(mc_data);
mc_data += sizeof(u16);
mc_nr_of_blks = u_code_read16(mc_data);
mc_data += sizeof(u16);
/* Restore data pointer */
mc_data = ((void *)mc_data_init) + 2 * sizeof(u16);
if ((mc_magic_word != DRX_UCODE_MAGIC_WORD) || (mc_nr_of_blks == 0)) {
rc = -EINVAL;
pr_err("Firmware magic word doesn't match\n");
goto release;
}
if (action == UCODE_UPLOAD) {
rc = check_firmware(demod, (u8 *)mc_data_init, size);
if (rc)
goto release;
/* After scanning, validate the microcode.
It is also valid if no validation control exists.
*/
rc = drx_ctrl(demod, DRX_CTRL_VALIDATE_UCODE, NULL);
if (rc != 0 && rc != -ENOTSUPP) {
pr_err("Validate ucode not supported\n");
goto release;
return rc;
}
pr_info("Uploading firmware %s\n", mc_file);
} else if (action == UCODE_VERIFY) {
pr_info("Verifying if firmware upload was ok.\n");
}
/* Process microcode blocks */
......@@ -1093,6 +1118,10 @@ ctrl_u_code(struct drx_demod_instance *demod,
block_hdr.CRC = u_code_read16(mc_data);
mc_data += sizeof(u16);
pr_debug("%u: addr %u, size %u, flags 0x%04x, CRC 0x%04x\n",
(unsigned)(mc_data - mc_data_init), block_hdr.addr,
block_hdr.size, block_hdr.flags, block_hdr.CRC);
/* Check block header on:
- data larger than 64Kb
- if CRC enabled check CRC
......@@ -1114,17 +1143,18 @@ ctrl_u_code(struct drx_demod_instance *demod,
/* Perform the desired action */
switch (action) {
case UCODE_UPLOAD:
/* Upload microcode */
case UCODE_UPLOAD: /* Upload microcode */
if (demod->my_access_funct->write_block_func(dev_addr,
block_hdr.addr,
mc_block_nr_bytes,
mc_data, 0x0000)) {
pr_err("error writing firmware\n");
rc = -EIO;
pr_err("error writing firmware at pos %u\n",
(unsigned)(mc_data - mc_data_init));
goto release;
}
break;
case UCODE_VERIFY: {
case UCODE_VERIFY: { /* Verify uploaded microcode */
int result = 0;
u8 mc_data_buffer[DRX_UCODE_MAX_BUF_SIZE];
u32 bytes_to_comp = 0;
......@@ -1144,8 +1174,9 @@ ctrl_u_code(struct drx_demod_instance *demod,
(u16)bytes_to_comp,
(u8 *)mc_data_buffer,
0x0000)) {
pr_err("error reading firmware\n");
goto release;
pr_err("error reading firmware at pos %u\n",
(unsigned)(mc_data - mc_data_init));
return -EIO;
}
result =drxbsp_hst_memcmp(curr_ptr,
......@@ -1153,7 +1184,8 @@ ctrl_u_code(struct drx_demod_instance *demod,
bytes_to_comp);
if (result) {
pr_err("error verifying firmware\n");
pr_err("error verifying firmware at pos %u\n",
(unsigned)(mc_data - mc_data_init));
return -EIO;
}
......@@ -1172,10 +1204,7 @@ ctrl_u_code(struct drx_demod_instance *demod,
}
return 0;
eof:
rc = -ENOENT;
pr_err("Firmware file %s is truncated at pos %lu\n",
mc_file, (unsigned long)(mc_data - mc_data_init));
release:
release_firmware(demod->firmware);
demod->firmware = NULL;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册
反馈
建议
客服 返回
顶部