static int mtd_ipanic_block_read_single(struct mtd_ipanic_data *ctx, loff_t offset)
{
	int rc, len;
	int index = offset >> ctx->mtd->writesize_shift;

	if ((index < 0) || (index >= IPANIC_OOPS_BLOCK_COUNT)) {
		return -EINVAL;
	}

	rc = ctx->mtd->_read(ctx->mtd, ctx->blk_offset[index], ctx->mtd->writesize, &len, ctx->bounce);
	ipanic_block_scramble(ctx->bounce, ctx->mtd->writesize);
#if 0
	if (rc == -EBADMSG) {
		xlog_printk(ANDROID_LOG_WARN, IPANIC_LOG_TAG, "Check sum error (ignore)\n");
		rc = 0;
	}
#endif
	if (rc == -EUCLEAN) {
		xlog_printk(ANDROID_LOG_WARN, IPANIC_LOG_TAG, "ECC Check sum error corrected %lld\n", offset);
		rc = 0;
	}
	if ((rc == 0) && (len != ctx->mtd->writesize)) {
		xlog_printk(ANDROID_LOG_WARN, IPANIC_LOG_TAG, "aee-ipanic: read size mismatch %d\n", len);
		return -EINVAL;
	}
	return rc;
}
Example #2
0
char *emmc_allocate_and_read(int offset, int length)
{
    int size;
    char *buff = NULL;

    if (length == 0) {
        return NULL;
    }

    size = ALIGN(length, EMMC_BLOCK_SIZE);
    buff = kzalloc(size, GFP_KERNEL);
    if (buff != NULL) {
        if (card_dump_func_read(buff, size, offset, DUMP_INTO_BOOT_CARD_IPANIC) != 0) {
            xlog_printk(ANDROID_LOG_ERROR, IPANIC_LOG_TAG,
                        "%s: read from IPANIC data failed(offset:%d,size:%d)\n", __FUNCTION__, offset, size);
            kfree(buff);
            return NULL;
        }
    }
    else {
        xlog_printk(ANDROID_LOG_ERROR, IPANIC_LOG_TAG, "%s: Cannot allocate buffer to read(len:%d)\n", __FUNCTION__, length);
        return NULL;
    }
    ipanic_block_scramble(buff, size);
    return buff;
}
Example #3
0
void* ipanic_next_write(void* (*next)(void *data, unsigned char *buffer, size_t sz_buf, int *size),
                        void *data, int off, size_t *sz_total) {
    void* errno = 0;
    size_t size = 0;
    unsigned char *ipanic_buffer = emmc_bounce;
    size_t sz_ipanic_buffer = PAGE_SIZE;

    errno = next(data, ipanic_buffer, sz_ipanic_buffer, &size);
    if (IS_ERR(errno))
        return errno;

    for (*sz_total = 0; size != 0; *sz_total += size) {
        if (off & (EMMC_BLOCK_SIZE - 1))
            return ERR_PTR(-2); /*invalid offset, not block aligned*/
        ipanic_block_scramble(ipanic_buffer, size);
        if (size != sz_ipanic_buffer) {
            memset(ipanic_buffer + size, 0, sz_ipanic_buffer - size);
        }
        if (card_dump_func_write(ipanic_buffer, ALIGN(size, EMMC_BLOCK_SIZE), off, DUMP_INTO_BOOT_CARD_IPANIC))
            return ERR_PTR(-1);
        off += size;
        errno = next(data, ipanic_buffer, sz_ipanic_buffer, &size);
        if (IS_ERR(errno))
            return errno;
    }
    return 0;
}
void *ipanic_data_from_sd(struct ipanic_data_header *dheader, int encrypt)
{
	void *data;
	data = ipanic_read_size(dheader->offset, dheader->used);
	if (data != 0 && encrypt != 0)
		ipanic_block_scramble((unsigned char *)data, dheader->used);
	return data;
}
Example #5
0
inline int ipanic_func_write(fn_next next, void *data, int off, int total, int encrypt)
{
	int errno = 0;
	size_t size;
	int start = off;
	struct ipanic_header *iheader = ipanic_header();
	unsigned char *ipanic_buffer = (unsigned char *)(unsigned long)iheader->buf;
	size_t sz_ipanic_buffer = iheader->bufsize;
	size_t blksize = iheader->blksize;
	int many = total > iheader->bufsize;
	LOGV("off[%x], encrypt[%d]\n", off, encrypt);

	if (off & (blksize - 1))
		return -2;	/*invalid offset, not block aligned */
	do {
		errno = next(data, ipanic_buffer, sz_ipanic_buffer);
		if (IS_ERR(ERR_PTR(errno)))
			break;
		size = (size_t) errno;
		if (size == 0)
			return (off - start);
		if ((off - start + size) > total) {
			LOGE("%s: data oversize(%zx>%x@%x)\n", __func__, off - start + size, total,
			     start);
			errno = -EFBIG;
			break;
		}
		if (encrypt)
			ipanic_block_scramble(ipanic_buffer, size);
		if (size != sz_ipanic_buffer) {
			memset(ipanic_buffer + size, 0, sz_ipanic_buffer - size);
		}
		LOGV("%x@%x\n", size, off);
		
		if (ipanic_enable)
			errno = ipanic_write_size(ipanic_buffer, off, ALIGN(size, blksize));
		else
			errno = -10;
		if (IS_ERR(ERR_PTR(errno)))
			break;
		off += size;
		if (many == 0)
			return size;
	} while (many);
	return errno;
}
static int emmc_ipanic_write(void *buf, int off, int len)
{
	int rem = len & (EMMC_BLOCK_SIZE - 1);
	len = len & ~(EMMC_BLOCK_SIZE - 1);
	ipanic_block_scramble(buf, len + rem);
	if (len > 0) {
		if (card_dump_func_write((unsigned char *)buf, len, off, EMMC_ID))
			return -1;
	}
	if (rem != 0) {
		memcpy(emmc_bounce, buf + len, rem);
		memset(emmc_bounce + rem, 0, EMMC_BLOCK_SIZE - rem);
		if (card_dump_func_write(buf, EMMC_BLOCK_SIZE, off + len, EMMC_ID))
			return -1;
	}
	return len + rem;
}
static int mtd_ipanic_block_write(struct mtd_ipanic_data *ctx, loff_t to, int bounce_len)
{
	int rc;
	size_t wlen;
	int panic = in_interrupt() | in_atomic();
	int index = to >> ctx->mtd->writesize_shift;

	if ((index < 0) || (index >= IPANIC_OOPS_BLOCK_COUNT)) {
		return -EINVAL;
	}

	if (bounce_len > ctx->mtd->writesize) {
		xlog_printk(ANDROID_LOG_ERROR, IPANIC_LOG_TAG, "aee-ipanic(%s) len too large\n", __func__);
		return -EINVAL;
	}
	if (panic && !ctx->mtd->_panic_write) {
		xlog_printk(ANDROID_LOG_ERROR, IPANIC_LOG_TAG, "%s: No panic_write available\n", __func__);
		return 0;
	} else if (!panic && !ctx->mtd->_write) {
		xlog_printk(ANDROID_LOG_ERROR, IPANIC_LOG_TAG, "%s: No write available\n", __func__);
		return 0;
	}

	if (bounce_len < ctx->mtd->writesize)
		memset(ctx->bounce + bounce_len, 0, ctx->mtd->writesize - bounce_len);
	ipanic_block_scramble(ctx->bounce, ctx->mtd->writesize);

	if (panic)
		rc = ctx->mtd->_panic_write(ctx->mtd, ctx->blk_offset[index], ctx->mtd->writesize, &wlen, ctx->bounce);
	else
		rc = ctx->mtd->_write(ctx->mtd, ctx->blk_offset[index], ctx->mtd->writesize, &wlen, ctx->bounce);

	if (rc) {
		xlog_printk(ANDROID_LOG_ERROR, IPANIC_LOG_TAG,
		       "%s: Error writing data to flash (%d)\n",
		       __func__, rc);
		return rc;
	}

	return wlen;
}
static int ipanic_write_android_buf(unsigned int off, int type)
{
	unsigned int copy_count = 0;

	while (1) {
		int rc = panic_dump_android_log(emmc_bounce, PAGE_SIZE, type);
		BUG_ON(rc < 0);
		if (rc <= 0)
			break;
		if (rc < PAGE_SIZE) {
			memset(emmc_bounce + rc, 0, PAGE_SIZE - rc);
		}
		ipanic_block_scramble(emmc_bounce, PAGE_SIZE);
		if (card_dump_func_write(emmc_bounce, PAGE_SIZE, off, EMMC_ID)) {
			xlog_printk(ANDROID_LOG_ERROR, IPANIC_LOG_TAG, "aee-ipanic-emmc(%s): android log %d write failed, offset %d\n", __FUNCTION__, type, off);
			return -1;
		}
		copy_count += rc;
		off += PAGE_SIZE;
	}
	xlog_printk(ANDROID_LOG_DEBUG, IPANIC_LOG_TAG, "%s: dump droid log type %d, count %d\n", __FUNCTION__, type, copy_count);
	return copy_count;
}
static struct aee_oops *emmc_ipanic_oops_copy(void)
{
	struct aee_oops *oops = NULL;
	struct ipanic_header *hdr = NULL;
	int hdr_size = ALIGN(sizeof(struct ipanic_header), EMMC_BLOCK_SIZE);

	hdr = kzalloc(hdr_size, GFP_KERNEL);
	if (hdr == NULL) {
		xlog_printk(ANDROID_LOG_ERROR, IPANIC_LOG_TAG, "%s: Cannot allocate ipanic header memory\n", __FUNCTION__);
		return NULL;
	}

	if (card_dump_func_read((unsigned char *)hdr, hdr_size, 0, EMMC_ID) < 0) {
		xlog_printk(ANDROID_LOG_ERROR, IPANIC_LOG_TAG, "%s: emmc panic log header read failed\n", __func__);
		return NULL;
	}
	ipanic_block_scramble((unsigned char *)hdr, hdr_size);
	if (ipanic_header_check(hdr) != 0) {
		return NULL;
	}

	oops = aee_oops_create(AE_DEFECT_FATAL, AE_KE, IPANIC_MODULE_TAG);
	if (oops != NULL) {
		struct ipanic_oops_header *oops_header = (struct ipanic_oops_header *)
                emmc_allocate_and_read(hdr->oops_header_offset, hdr->oops_header_length);
		if (oops_header == NULL) { 
			xlog_printk(ANDROID_LOG_ERROR, IPANIC_LOG_TAG, "%s: Can't read oops header(len:%d)\n", __FUNCTION__, hdr->oops_header_length);
			goto error_return;
		}
		aee_oops_set_process_path(oops, oops_header->process_path);
		aee_oops_set_backtrace(oops, oops_header->backtrace);
		kfree(oops_header);

        if(hdr->oops_detail_length != 0)
        {
            oops->detail = emmc_allocate_and_read(hdr->oops_detail_offset, hdr->oops_detail_length);
            oops->detail_len = hdr->oops_detail_length;

        }else {
            #define TMPDETAILSTR  "panic detail is empty"
            oops->detail = kstrdup(TMPDETAILSTR, GFP_KERNEL);
            oops->detail_len = sizeof TMPDETAILSTR;
        }
		if (oops->detail == NULL) {
			xlog_printk(ANDROID_LOG_ERROR, IPANIC_LOG_TAG, "%s: read detail failed(len: %d)\n", __FUNCTION__, oops->detail_len);
			goto error_return;
		}

		oops->console = emmc_allocate_and_read(hdr->console_offset, hdr->console_length);
		oops->console_len = hdr->console_length;
		if (oops->console == NULL) {
			xlog_printk(ANDROID_LOG_ERROR, IPANIC_LOG_TAG, "%s: read console failed(len: %d)\n", __FUNCTION__, oops->console_len);
			goto error_return;
		}

        /*If panic from kernel context, no user sapce info available. Shouldn't fail*/
        if (0 == hdr->userspace_info_length)
        {
            oops->userspace_info = NULL;
            oops->userspace_info_len = 0;
        }
        else
        {
            oops->userspace_info = emmc_allocate_and_read(hdr->userspace_info_offset, hdr->userspace_info_length);
            oops->userspace_info_len = hdr->userspace_info_length;
            if (oops->userspace_info == NULL) {
                xlog_printk(ANDROID_LOG_ERROR, IPANIC_LOG_TAG, "%s: read usrespace info failed\n", __FUNCTION__);
                goto error_return;
            }
        }
	

		oops->android_main = emmc_allocate_and_read(hdr->android_main_offset, hdr->android_main_length);
		oops->android_main_len  = hdr->android_main_length;
		if (oops->android_main == NULL)	{
			xlog_printk(ANDROID_LOG_ERROR, IPANIC_LOG_TAG, "%s: read android_main failed\n", __FUNCTION__);
			goto error_return;
		}
		
		oops->android_radio  = emmc_allocate_and_read(hdr->android_radio_offset, hdr->android_radio_length);
		oops->android_radio_len = hdr->android_radio_length;
		if (oops->android_radio == NULL) {
			xlog_printk(ANDROID_LOG_ERROR, IPANIC_LOG_TAG, "%s: read android_radio failed\n", __FUNCTION__);
			goto error_return;
		}		    
		
		oops->android_system = emmc_allocate_and_read(hdr->android_system_offset, hdr->android_system_length);
		oops->android_system_len = hdr->android_system_length;
		if (oops->android_system == NULL) {
			xlog_printk(ANDROID_LOG_ERROR, IPANIC_LOG_TAG, "%s: read android_system failed\n", __FUNCTION__);
			goto error_return;
		}		    
		
		xlog_printk(ANDROID_LOG_DEBUG, IPANIC_LOG_TAG, "ipanic_oops_copy return OK\n");
		kfree(hdr);
		return oops;
	}
	else {
		xlog_printk(ANDROID_LOG_ERROR, IPANIC_LOG_TAG, "%s: kmalloc failed at header\n", __FUNCTION__);
		kfree(hdr);
		return NULL;
	}
error_return:
	kfree(hdr);
	aee_oops_free(oops);
	return NULL;
}