static unsigned long read_rdtags(char *name)
{
	unsigned long tag_data;
	char *log_data;
	int err = -EINVAL;
	size_t bufsize;

	if (rdtags_get_tag_data(name, NULL, &bufsize) != -ENOBUFS) {
		dev_err(dev, "Could not find tag \"%s\"!\n",
			name ? name : "NULL");
		return 0;
	}

	log_data = kzalloc(bufsize, GFP_KERNEL);
	if (!log_data) {
		dev_err(dev, "Could not allocate %zd bytes of memory!\n",
			bufsize);
		return 0;
	}

	err = rdtags_get_tag_data(name, log_data, &bufsize);
	if (err) {
		dev_err(dev, "Could not get %zd bytes of data to tag %s %d\n",
				bufsize, name, err);
		kfree(log_data);
		return 0;
	}

	err = kstrtoul(log_data, 16, &tag_data);
	if (err < 0) {
		dev_err(dev, "Failed kstrtoul %s %lx\n",
			log_data, tag_data);
		kfree(log_data);
		return 0;
	}

	dev_dbg(dev, "logbuf tags verify %s %lx\n",
			log_data, tag_data);

	kfree(log_data);
	return tag_data;
}
static int extract_last_kmsg(void)
{
    struct last_logs *buffer = (struct last_logs *)kmsg_base;
    unsigned long log_addr[NR_LOG_INFO];
    char log_data[NR_LOG_INFO][LOG_INFO_LEN];
    int i, wrap, size, err, index = 0;
    char *log_buf;
    unsigned int *log_buf_len;
    unsigned int *log_end;
    ssize_t buf_len;
    char *logbuf_name[] = {
        "__log_buf",
        "log_end",
        "log_buf_len",
    };

    for (i = 0; i < NR_LOG_INFO; i++) {
        /* Indicate max size */
        size = LOG_INFO_LEN;
        err = rdtags_get_tag_data(logbuf_name[i], log_data[i], &size);
        if (err < 0) {
            dev_err(dev, "tag %s not found: %d\n",
                    logbuf_name[i], err);
            return -EINVAL;
        }

        err = kstrtoul(log_data[i], 16, &log_addr[i]);
        if (err < 0) {
            dev_err(dev, "Failed kstrtoul %s %lx\n",
                    log_data[i], log_addr[i]);
            return -EINVAL;
        }

        dev_dbg(dev, "logbuf tags verify %s %lx\n",
                log_data[i], log_addr[i]);
    }

    log_buf_len = (unsigned int *)ioremap(log_addr[2], sizeof(int));
    if (!log_buf_len) {
        dev_err(dev, "log_buf_len: Ioremap Failed !!\n");
        goto exit1;
    }

    dev_dbg(dev, "log_buf_len = %d\n", *log_buf_len);

    log_buf = (char *)ioremap(log_addr[0], (*log_buf_len));
    if (!log_buf) {
        dev_err(dev, "log_buf: Ioremap Failed!!\n");
        goto exit2;
    }

    log_end = (unsigned int *)ioremap(log_addr[1], sizeof(unsigned));
    if (!log_end) {
        dev_err(dev, "log_end: Ioremap Failed!!\n");
        goto exit3;
    }

    if ((*log_end) > (*log_buf_len))
        wrap = 1;
    else
        wrap = 0;

    buf_len = *log_buf_len;
    if (buf_len > (kmsg_size - (buffer->data - (uint8_t *)buffer)))
        buf_len = kmsg_size - (buffer->data - (uint8_t *)buffer);

    buffer->sig = KMSGLOG_SIG;
    buffer->size = buf_len;

    index = (*log_end & (buf_len - 1));

    if (wrap) {
        memcpy(buffer->data, &log_buf[index],
               (buffer->size - index));
        memcpy(&buffer->data[buffer->size - index],
               log_buf, index);
    } else {
        memcpy(buffer->data, log_buf, index);
        buffer->size = index;
    }


    iounmap(log_buf);
    iounmap(log_buf_len);
    iounmap(log_end);
    return 0;
exit3:
    if (log_buf)
        iounmap(log_buf);

    if (log_buf_len)
        iounmap(log_buf_len);

exit2:
    if (log_buf_len)
        iounmap(log_buf_len);

exit1:
    return -ENOMEM;

}