/**
  * 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;
}