/** * msm_eeprom_match_crc - verify multiple regions using crc * @data: data block to be verified * * Iterates through all regions stored in @data. Regions with odd index * are treated as data, and its next region is treated as checksum. Thus * regions of even index must have valid_size of 4 or 0 (skip verification). * Returns a bitmask of verified regions, starting from LSB. 1 indicates * a checksum match, while 0 indicates checksum mismatch or not verified. */ static uint32_t msm_eeprom_match_crc(struct msm_eeprom_memory_block_t *data) { int j, rc; uint32_t *sum; uint32_t ret = 0; uint8_t *memptr; struct msm_eeprom_memory_map_t *map; if (!data) { pr_err("%s data is NULL", __func__); return -EINVAL; } map = data->map; memptr = data->mapdata; for (j = 0; j + 1 < data->num_map; j += 2) { /* empty table or no checksum */ if (!map[j].mem.valid_size || !map[j+1].mem.valid_size) { memptr += map[j].mem.valid_size + map[j+1].mem.valid_size; continue; } if (map[j+1].mem.valid_size != sizeof(uint32_t)) { CDBG("%s: malformatted data mapping\n", __func__); return -EINVAL; } sum = (uint32_t *) (memptr + map[j].mem.valid_size); rc = msm_eeprom_verify_sum(memptr, map[j].mem.valid_size, *sum); if (!rc) ret |= 1 << (j/2); memptr += map[j].mem.valid_size + map[j+1].mem.valid_size; } return ret; }
static int eeprom_config_read_compressed_data(struct msm_eeprom_ctrl_t *e_ctrl, struct msm_eeprom_cfg_data *cdata) { int rc = 0; #if 0 // just once to power up when load lib bool down; #endif uint8_t *buf_comp = NULL; uint8_t *buf_decomp = NULL; uint32_t decomp_size; pr_err("%s: address (0x%x) comp_size (%d) after decomp (%d)", __func__, cdata->cfg.read_data.addr, cdata->cfg.read_data.comp_size, cdata->cfg.read_data.num_bytes); buf_comp = kmalloc(cdata->cfg.read_data.comp_size, GFP_KERNEL); buf_decomp = kmalloc(cdata->cfg.read_data.num_bytes, GFP_KERNEL); if (!buf_decomp || !buf_comp) { pr_err("%s: kmalloc fail", __func__); rc = -ENOMEM; goto FREE; } #if 0 // just once to power up when load lib rc = msm_eeprom_power_up(e_ctrl, &down); if (rc < 0) { pr_err("%s: failed to power on eeprom\n", __func__); goto FREE; } #endif rc = e_ctrl->i2c_client.i2c_func_tbl->i2c_read_seq( &(e_ctrl->i2c_client), cdata->cfg.read_data.addr, buf_comp, cdata->cfg.read_data.comp_size); if (rc < 0) { pr_err("%s: failed to read data, rc %d\n", __func__, rc); goto POWER_DOWN; } pr_err("%s: crc = 0x%08X\n", __func__, *(uint32_t*)&buf_comp[cdata->cfg.read_data.comp_size-4]); // compressed data(buf_comp) contains uncompressed crc32 value. rc = msm_eeprom_verify_sum(buf_comp, cdata->cfg.read_data.comp_size-4, *(uint32_t*)&buf_comp[cdata->cfg.read_data.comp_size-4]); if (rc < 0) { pr_err("%s: crc check error, rc %d\n", __func__, rc); goto POWER_DOWN; } decomp_size = cdata->cfg.read_data.num_bytes; rc = lzo1x_decompress_safe(buf_comp, cdata->cfg.read_data.comp_size-4, buf_decomp, &decomp_size); if (rc != LZO_E_OK) { pr_err("%s: decompression failed %d", __func__, rc); goto POWER_DOWN; } rc = copy_to_user(cdata->cfg.read_data.dbuffer, buf_decomp, decomp_size); if (rc < 0) { pr_err("%s: failed to copy to user\n", __func__); goto POWER_DOWN; } pr_info("%s: done", __func__); POWER_DOWN: #if 0 // just once to power up when load lib msm_eeprom_power_down(e_ctrl, down); #endif FREE: if (buf_comp) kfree(buf_comp); if (buf_decomp) kfree(buf_decomp); return rc; }