static void mtd_panic_notify_add(struct mtd_info *mtd)
{
	struct mtd_ipanic_data *ctx = &mtd_drv_ctx;
	struct ipanic_header *hdr;
	int rc;

	if (strcmp(mtd->name, AEE_IPANIC_PLABEL))
		return;

	ctx->mtd = mtd;

	ctx->bounce = kzalloc(ctx->mtd->writesize, GFP_KERNEL);
	if (ctx->bounce == NULL)
	  xlog_printk(ANDROID_LOG_ERROR, IPANIC_LOG_TAG, "%s: mtd buffer kzalloc failed, %d \n", __func__, ctx->mtd->writesize);
	  
        hdr = ctx->bounce;  
	if (!mtd_ipanic_block_scan(ctx))
		goto out_err;

	rc = mtd_ipanic_block_read_single(ctx, 0);
	if (rc < 0) {
		xlog_printk(ANDROID_LOG_ERROR, IPANIC_LOG_TAG, "aee-ipanic: Error reading block 0 (%d)\n", rc);
		mtd_ipanic_block_erase();
		goto out_err;
	}

	xlog_printk(ANDROID_LOG_INFO, IPANIC_LOG_TAG, "aee-ipanic: Bound to mtd partition '%s', write size(%d), write size shift(%d)\n", mtd->name, mtd->writesize, mtd->writesize_shift);
	switch (ipanic_header_check(hdr)) {
	case 0:
		break;
	case 1:
		return;
	case 2:
		mtd_ipanic_block_erase();
		return;
	}

	memcpy(&ctx->curr, hdr, sizeof(struct ipanic_header));
	ipanic_header_dump(hdr);

	ctx->oops = create_proc_read_entry("aee_ipanic_oops", 
					   0444, NULL, 
					   mtd_ipanic_proc_oops,
					   NULL);
	if (ctx->oops == NULL) {
		xlog_printk(ANDROID_LOG_ERROR, IPANIC_LOG_TAG, " %s: failed to create proc file apanic_oops\n", __func__);
	}

	/*it will free the ctx->curr assigne during bootup. then 
     open the ke device will return NULL. so lose db
    */
    //mtd_ipanic_oops_dump();
	
    return;

out_err:
	ctx->mtd = NULL;
}
static struct aee_oops *mtd_ipanic_oops_copy(void)
{
	struct mtd_ipanic_data *ctx = &mtd_drv_ctx;
	struct aee_oops *oops;

	if ((ctx->curr.magic != AEE_IPANIC_MAGIC) || (ctx->curr.version != AEE_IPANIC_PHDR_VERSION)) {
		return NULL;
	}

	oops = aee_oops_create(AE_DEFECT_FATAL, AE_KE, IPANIC_MODULE_TAG);
	if (oops != NULL) {
		struct ipanic_oops_header *oops_header = kzalloc(sizeof(struct ipanic_oops_header), GFP_KERNEL);
		if (oops_header == NULL)
			goto error_return;

		if (mtd_ipanic_block_read(ctx, ctx->curr.oops_header_offset, ctx->curr.oops_header_length, oops_header) != 0) {
			xlog_printk(ANDROID_LOG_ERROR, IPANIC_LOG_TAG, "%s: mtd read header failed\n", __FUNCTION__);
			kfree(oops_header);
			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(ctx->curr.oops_detail_length != 0)
        {
            oops->detail = kmalloc(ctx->curr.oops_detail_length, GFP_KERNEL);
            oops->detail_len = ctx->curr.oops_detail_length;
            if (oops->detail != NULL) {
                if (mtd_ipanic_block_read(ctx, ctx->curr.oops_detail_offset, ctx->curr.oops_detail_length, oops->detail) != 0) {
                    xlog_printk(ANDROID_LOG_ERROR, IPANIC_LOG_TAG, "%s: mtd read detail failed\n", __FUNCTION__);
                    kfree(oops->detail);
                    goto error_return;
                }
            }
        }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: kmalloc failed at detail\n", __FUNCTION__);
            kfree(oops);
            return NULL;
        }

		oops->console = kmalloc(ctx->curr.console_length, GFP_KERNEL);
		oops->console_len = ctx->curr.console_length;
		if (oops->console != NULL) {
			if (mtd_ipanic_block_read(ctx, ctx->curr.console_offset, ctx->curr.console_length, oops->console) != 0) {
				xlog_printk(ANDROID_LOG_ERROR, IPANIC_LOG_TAG, "%s: mtd read console failed\n", __FUNCTION__);
				kfree(oops->detail);
				goto error_return;
			}
		}
		else {
			xlog_printk(ANDROID_LOG_ERROR, IPANIC_LOG_TAG, "%s: kmalloc failed at detail\n", __FUNCTION__);
			kfree(oops);
			return NULL;
		}
		
		/* Android log */
		oops->android_main = kmalloc(ctx->curr.android_main_length, GFP_KERNEL);
		oops->android_main_len = ctx->curr.android_main_length;
		if (oops->android_main)	{
			if (mtd_ipanic_block_read(ctx, ctx->curr.android_main_offset, ctx->curr.android_main_length, oops->android_main) != 0) {
				xlog_printk(ANDROID_LOG_ERROR, IPANIC_LOG_TAG, "%s: mtd read android_main failed\n", __FUNCTION__);
				kfree(oops->detail);
				kfree(oops->console);
				goto error_return;
			}
		}
		else {
			xlog_printk(ANDROID_LOG_ERROR, IPANIC_LOG_TAG, "%s: kmalloc failed at android_main\n", __FUNCTION__);
			aee_oops_free(oops);
			return NULL;
		}

		oops->android_radio = kmalloc(ctx->curr.android_radio_length, GFP_KERNEL);
		oops->android_radio_len = ctx->curr.android_radio_length;
		if (oops->android_radio) {
			if (mtd_ipanic_block_read(ctx, ctx->curr.android_radio_offset, ctx->curr.android_radio_length, oops->android_radio) != 0) {
				xlog_printk(ANDROID_LOG_ERROR, IPANIC_LOG_TAG, "%s: mtd read android_radio failed\n", __FUNCTION__);
				kfree(oops->detail);
				kfree(oops->console);
				kfree(oops->android_main);
				goto error_return;
			}		    
		}
		else {
			xlog_printk(ANDROID_LOG_ERROR, IPANIC_LOG_TAG, "%s: kmalloc failed at android_radio\n", __FUNCTION__);
			aee_oops_free(oops);
			return NULL;
		}
		
		oops->android_system = kmalloc(ctx->curr.android_system_length, GFP_KERNEL);
		oops->android_system_len = ctx->curr.android_system_length;
		if (oops->android_system) {
			if (mtd_ipanic_block_read(ctx, ctx->curr.android_system_offset, ctx->curr.android_system_length, oops->android_system) != 0) {
				xlog_printk(ANDROID_LOG_ERROR, IPANIC_LOG_TAG, "%s: mtd read android_system failed\n", __FUNCTION__);
				kfree(oops->detail);
				kfree(oops->console);
				kfree(oops->android_main);
				kfree(oops->android_radio);
				goto error_return;
			}		    
		}
		else {
			xlog_printk(ANDROID_LOG_ERROR, IPANIC_LOG_TAG, "%s: kmalloc failed at android_system\n", __FUNCTION__);
			aee_oops_free(oops);
			return NULL;
		}

#if 0		
		xlog_printk(ANDROID_LOG_INFO, IPANIC_LOG_TAG, "android log length, 0x%x, 0x%x, 0x%x, 0x%x\n",
			    oops->android_main_len,oops->android_event_len,oops->android_radio_len,oops->android_system_len);
#endif
		/* Process dump */
		oops->userspace_info = kmalloc(ctx->curr.userspace_info_length, GFP_KERNEL);
		oops->userspace_info_len = ctx->curr.userspace_info_length;
		if (oops->userspace_info) {
			if (mtd_ipanic_block_read(ctx, ctx->curr.userspace_info_offset, ctx->curr.userspace_info_length, oops->userspace_info) != 0) {
				xlog_printk(ANDROID_LOG_ERROR, IPANIC_LOG_TAG, "%s: mtd read usrespace info failed\n", __FUNCTION__);
				kfree(oops->detail);
				kfree(oops->console);
				kfree(oops->android_main);
				kfree(oops->android_radio);
				kfree(oops->userspace_info);
				goto error_return;
			}		    
		}
		else {
			xlog_printk(ANDROID_LOG_ERROR, IPANIC_LOG_TAG, "%s: kmalloc failed at userspace info failed\n", __FUNCTION__);
			aee_oops_free(oops);
			return NULL;
		}
		
		xlog_printk(ANDROID_LOG_DEBUG, IPANIC_LOG_TAG, "ipanic_oops_copy return OK\n");
		return oops;
	}
	else {
		xlog_printk(ANDROID_LOG_ERROR, IPANIC_LOG_TAG, "%s: kmalloc failed at header\n", __FUNCTION__);
		return NULL;
	}
error_return:
	kfree(oops);
	memset(&ctx->curr, 0, sizeof(struct ipanic_header));
	mtd_ipanic_block_erase();
	return NULL;
}