static int __init ram_console_late_init(void) { struct proc_dir_entry *entry; struct persistent_ram_zone *prz = ram_console_zone; if (!prz) return 0; if (persistent_ram_old_size(prz) == 0) return 0; entry = create_proc_entry("last_kmsg", S_IFREG | S_IRUGO, NULL); if (!entry) { printk(KERN_ERR "ram_console: failed to create proc entry\n"); persistent_ram_free_old(prz); return 0; } entry->proc_fops = &ram_console_file_ops; entry->size = persistent_ram_old_size(prz) + persistent_ram_ecc_string(prz, NULL, 0) + bootinfo_size; return 0; }
static int __init ram_console_late_init(void) { struct proc_dir_entry *entry; struct persistent_ram_zone *prz = ram_console_zone; #if defined(CONFIG_HTC_DEBUG_RAMCONSOLE) bool is_last_bldr_ramdump_mode = false; #endif if (!prz) return 0; if (persistent_ram_old_size(prz) == 0) return 0; entry = create_proc_entry("last_kmsg", S_IFREG | S_IRUGO, NULL); if (!entry) { printk(KERN_ERR "ram_console: failed to create proc entry\n"); persistent_ram_free_old(prz); return 0; } #if defined(CONFIG_HTC_DEBUG_RAMCONSOLE) if (bl_old_log != NULL) { bl_old_log_buf = kmalloc(bl_old_log_size, GFP_KERNEL); if (bl_old_log_buf == NULL) { printk(KERN_ERR "[K] ram_console: failed to allocate buffer for last bootloader log, size: %zu\n", bl_old_log_size); } else { printk(KERN_INFO "[K] ram_console: allocate buffer for last bootloader log, size: %zu\n", bl_old_log_size); bldr_log_parser(bl_old_log, bl_old_log_buf, bl_old_log_size, &bl_old_log_buf_size); is_last_bldr_ramdump_mode = bldr_rst_msg_parser(bl_old_log_buf, bl_old_log_buf_size, true); if (is_last_bldr_ramdump_mode) printk(KERN_INFO "[K] ram_console: Found abnormal rst_msg pattern in last bootloader log\n"); } } if (bl_log != NULL) { bl_log_buf = kmalloc(bl_log_size, GFP_KERNEL); if (bl_log_buf == NULL) { printk(KERN_ERR "[K] ram_console: failed to allocate buffer for bootloader log, size: %zu\n", bl_log_size); } else { printk(KERN_INFO "[K] ram_console: allocate buffer for bootloader log, size: %zu\n", bl_log_size); bldr_log_parser(bl_log, bl_log_buf, bl_log_size, &bl_log_buf_size); if (!is_last_bldr_ramdump_mode) { if (bldr_rst_msg_parser(bl_log_buf, bl_log_buf_size, false)) printk(KERN_INFO "[K] ram_console: Found abnormal rst_msg pattern in bootloader log\n"); } } } #endif entry->proc_fops = &ram_console_file_ops; entry->size = persistent_ram_old_size(prz) + persistent_ram_ecc_string(prz, NULL, 0) + bootinfo_size; #if defined(CONFIG_HTC_DEBUG_RAMCONSOLE) entry->size += bl_old_log_buf_size; entry->size += bl_log_buf_size; #endif return 0; }
static ssize_t ramoops_pstore_read(u64 *id, enum pstore_type_id *type, int *count, struct timespec *time, char **buf, struct pstore_info *psi) { ssize_t size; ssize_t ecc_notice_size; struct ramoops_context *cxt = psi->data; struct persistent_ram_zone *prz; prz = ramoops_get_next_prz(cxt->przs, &cxt->dump_read_cnt, cxt->max_dump_cnt, id, type, PSTORE_TYPE_DMESG, 1); if (!prz_ok(prz)) { prz = ramoops_get_next_prz(&cxt->cprz, &cxt->console_read_cnt, 1, id, type, PSTORE_TYPE_CONSOLE, 0); if (prz && !persistent_ram_old_size(prz)) persistent_ram_annotation_merge(NULL); } if (!prz_ok(prz)) prz = ramoops_get_next_prz(&cxt->fprz, &cxt->ftrace_read_cnt, 1, id, type, PSTORE_TYPE_FTRACE, 0); if (!prz_ok(prz)) { prz = ramoops_get_next_prz(&cxt->aprz, &cxt->annotate_read_cnt, 1, id, type, PSTORE_TYPE_ANNOTATE, 0); persistent_ram_annotation_merge(prz); } if (!prz_ok(prz)) prz = ramoops_get_next_prz(&cxt->mprz, &cxt->pmsg_read_cnt, 1, id, type, PSTORE_TYPE_PMSG, 0); if (!prz_ok(prz)) return 0; /* TODO(kees): Bogus time for the moment. */ time->tv_sec = 0; time->tv_nsec = 0; size = persistent_ram_old_size(prz); /* ECC correction notice */ ecc_notice_size = persistent_ram_ecc_string(prz, NULL, 0); *buf = kmalloc(size + ecc_notice_size + 1, GFP_KERNEL); if (*buf == NULL) return -ENOMEM; memcpy(*buf, persistent_ram_old(prz), size); persistent_ram_ecc_string(prz, *buf + size, ecc_notice_size + 1); return size + ecc_notice_size; }
static ssize_t ramoops_pstore_read(u64 *id, enum pstore_type_id *type, int *count, struct timespec *time, char **buf, struct pstore_info *psi) { ssize_t size; struct ramoops_context *cxt = psi->data; struct persistent_ram_zone *prz; prz = ramoops_get_next_prz(cxt->przs, &cxt->dump_read_cnt, cxt->max_dump_cnt, id, type, PSTORE_TYPE_DMESG, 1); if (!prz) prz = ramoops_get_next_prz(&cxt->cprz, &cxt->console_read_cnt, 1, id, type, PSTORE_TYPE_CONSOLE, 0); if (!prz) prz = ramoops_get_next_prz(&cxt->fprz, &cxt->ftrace_read_cnt, 1, id, type, PSTORE_TYPE_FTRACE, 0); if (!prz) return 0; /* TODO(kees): Bogus time for the moment. */ time->tv_sec = 0; time->tv_nsec = 0; size = persistent_ram_old_size(prz); *buf = kmalloc(size, GFP_KERNEL); if (*buf == NULL) return -ENOMEM; memcpy(*buf, persistent_ram_old(prz), size); return size; }
static int __devinit persistent_trace_probe(struct platform_device *pdev) { struct dentry *d; int ret; persistent_trace = persistent_ram_init_ringbuffer(&pdev->dev, false); if (IS_ERR(persistent_trace)) { pr_err("persistent_trace: failed to init ringbuffer: %ld\n", PTR_ERR(persistent_trace)); return PTR_ERR(persistent_trace); } ret = register_tracer(&persistent_tracer); if (ret) pr_err("persistent_trace: failed to register tracer"); if (persistent_ram_old_size(persistent_trace) > 0) { d = debugfs_create_file("persistent_trace", S_IRUGO, NULL, NULL, &persistent_trace_old_fops); if (IS_ERR_OR_NULL(d)) pr_err("persistent_trace: failed to create old file\n"); } return 0; }
static struct persistent_ram_zone * ramoops_get_next_prz(struct persistent_ram_zone *przs[], uint *c, uint max, u64 *id, enum pstore_type_id *typep, enum pstore_type_id type, bool update) { struct persistent_ram_zone *prz; int i = (*c)++; if (i >= max) return NULL; prz = przs[i]; if (!prz) return NULL; /* Update old/shadowed buffer. */ if (update) persistent_ram_save_old(prz); if (!persistent_ram_old_size(prz)) return NULL; *typep = type; *id = i; return prz; }
static int __init ram_console_late_init(void) { struct proc_dir_entry *entry; struct persistent_ram_zone *prz = ram_console_zone; /*Skies-2012/09/07, create proc file for crash status++*/ struct proc_dir_entry *entry_cs; int size = 0; /*Skies-2012/09/07, create proc file for crash status--*/ /*Skies-2012/09/07, create proc file for crash status++*/ entry_cs = create_proc_entry("crash_status", S_IFREG|S_IRUGO/*|S_IWUGO*/, NULL); if (!entry_cs) { pr_err("%s: failed to create proc entry\n", __func__); return 0; } entry_cs->proc_fops = &crash_status_file_ops; entry_cs->size = CRASH_STATUS_CMD_SIZE; debug_info_buf = smem_get_entry(SMEM_ID_VENDOR0, &size); if (debug_info_buf != NULL) { memcpy(&debug_info, debug_info_buf, sizeof(debug_info)); }else { return 0; } /*Skies-2012/09/07, create proc file for crash status--*/ if (!prz) return 0; if (persistent_ram_old_size(prz) == 0) return 0; entry = create_proc_entry("last_kmsg", S_IFREG | S_IRUGO, NULL); if (!entry) { printk(KERN_ERR "ram_console: failed to create proc entry\n"); persistent_ram_free_old(prz); return 0; } entry->proc_fops = &ram_console_file_ops; entry->size = persistent_ram_old_size(prz) + persistent_ram_ecc_string(prz, NULL, 0) + bootinfo_size; return 0; }
static ssize_t ram_console_read_old(struct file *file, char __user *buf, size_t len, loff_t *offset) { loff_t pos = *offset; ssize_t count; struct persistent_ram_zone *prz = ram_console_zone; size_t old_log_size = persistent_ram_old_size(prz); const char *old_log = persistent_ram_old(prz); char *str; int ret; #ifndef CONFIG_MACH_MSM8974_14001 //[email protected], 2014/01/16, Delete for solve the problem that can not read /proc/last_kmsg right. if (dmesg_restrict && !capable(CAP_SYSLOG)) return -EPERM; #endif /* CONFIG_MACH_MSM8974_14001 */ /* Main last_kmsg log */ if (pos < old_log_size) { count = min(len, (size_t)(old_log_size - pos)); if (copy_to_user(buf, old_log + pos, count)) return -EFAULT; goto out; } /* ECC correction notice */ pos -= old_log_size; count = persistent_ram_ecc_string(prz, NULL, 0); if (pos < count) { str = kmalloc(count, GFP_KERNEL); if (!str) return -ENOMEM; persistent_ram_ecc_string(prz, str, count + 1); count = min(len, (size_t)(count - pos)); ret = copy_to_user(buf, str + pos, count); kfree(str); if (ret) return -EFAULT; goto out; } /* Boot info passed through pdata */ pos -= count; if (pos < bootinfo_size) { count = min(len, (size_t)(bootinfo_size - pos)); if (copy_to_user(buf, bootinfo + pos, count)) return -EFAULT; goto out; } /* EOF */ return 0; out: *offset += count; return count; }
static ssize_t ram_console_read_old(struct file *file, char __user *buf, size_t len, loff_t *offset) { loff_t pos = *offset; ssize_t count; struct persistent_ram_zone *prz = ram_console_zone; size_t old_log_size = persistent_ram_old_size(prz); const char *old_log = persistent_ram_old(prz); char *str; int ret; /*<<Skies-2012/11/29, remove permission restriction*/ #if 0 if (dmesg_restrict && !capable(CAP_SYSLOG)) return -EPERM; #endif /*>>Skies-2012/11/29, remove permission restriction*/ /* Main last_kmsg log */ if (pos < old_log_size) { count = min(len, (size_t)(old_log_size - pos)); if (copy_to_user(buf, old_log + pos, count)) return -EFAULT; goto out; } /* ECC correction notice */ pos -= old_log_size; count = persistent_ram_ecc_string(prz, NULL, 0); if (pos < count) { str = kmalloc(count, GFP_KERNEL); if (!str) return -ENOMEM; persistent_ram_ecc_string(prz, str, count + 1); count = min(len, (size_t)(count - pos)); ret = copy_to_user(buf, str + pos, count); kfree(str); if (ret) return -EFAULT; goto out; } /* Boot info passed through pdata */ pos -= count; if (pos < bootinfo_size) { count = min(len, (size_t)(bootinfo_size - pos)); if (copy_to_user(buf, bootinfo + pos, count)) return -EFAULT; goto out; } /* EOF */ return 0; out: *offset += count; return count; }
static int __init ram_console_late_init(void) { struct proc_dir_entry *entry; struct persistent_ram_zone *prz = ram_console_zone; persistent_ram_ext_oldbuf_merge(prz); if (!prz) return 0; if (persistent_ram_old_size(prz) == 0) return 0; if (!bootinfo) { bootinfo = kstrdup(boot_command_line, GFP_KERNEL); if (bootinfo) { bootinfo_size = strlen(bootinfo); bootreason_size = 1 + snprintf(NULL, 0, bootreason_label, bi_bootreason()); } } entry = create_proc_entry("last_kmsg", S_IFREG | S_IRUGO, NULL); if (!entry) { printk(KERN_ERR "ram_console: failed to create proc entry\n"); persistent_ram_free_old(prz); return 0; } entry->proc_fops = &ram_console_file_ops; entry->size = persistent_ram_old_size(prz) + persistent_ram_ecc_string(prz, NULL, 0) + bootinfo_size + bootreason_size; return 0; }
static ssize_t ramoops_pstore_read(u64 *id, enum pstore_type_id *type, int *count, struct timespec *time, char **buf, bool *compressed, struct pstore_info *psi) { ssize_t size; ssize_t ecc_notice_size; struct ramoops_context *cxt = psi->data; struct persistent_ram_zone *prz; prz = ramoops_get_next_prz(cxt->przs, &cxt->dump_read_cnt, cxt->max_dump_cnt, id, type, PSTORE_TYPE_DMESG, 1); if (!prz_ok(prz)) prz = ramoops_get_next_prz(&cxt->cprz, &cxt->console_read_cnt, 1, id, type, PSTORE_TYPE_CONSOLE, 0); if (!prz_ok(prz)) { prz = ramoops_get_next_prz(&cxt->bprz, &cxt->bconsole_read_cnt, 1, id, type, PSTORE_TYPE_CONSOLE, 0); /*pr_notice("pstore: pstore_read bprz type: %d count %d id %llx\n", *type, cxt->bconsole_read_cnt, *id); *id = 2;*/ } if (!prz_ok(prz)) prz = ramoops_get_next_prz(&cxt->fprz, &cxt->ftrace_read_cnt, 1, id, type, PSTORE_TYPE_FTRACE, 0); if (!prz_ok(prz)) prz = ramoops_get_next_prz(&cxt->mprz, &cxt->pmsg_read_cnt, 1, id, type, PSTORE_TYPE_PMSG, 0); if (!prz_ok(prz)) return 0; size = persistent_ram_old_size(prz); /* ECC correction notice */ ecc_notice_size = persistent_ram_ecc_string(prz, NULL, 0); *buf = kmalloc(size + ecc_notice_size + 1, GFP_KERNEL); if (*buf == NULL) return -ENOMEM; memcpy(*buf, persistent_ram_old(prz), size); ramoops_read_kmsg_hdr(*buf, time, compressed); persistent_ram_ecc_string(prz, *buf + size, ecc_notice_size + 1); return size + ecc_notice_size; }
static ssize_t ramoops_pstore_read(u64 *id, enum pstore_type_id *type, int *count, struct timespec *time, char **buf, bool *compressed, struct pstore_info *psi) { ssize_t size; ssize_t ecc_notice_size; struct ramoops_context *cxt = psi->data; struct persistent_ram_zone *prz; int header_length; prz = ramoops_get_next_prz(cxt->przs, &cxt->dump_read_cnt, cxt->max_dump_cnt, id, type, PSTORE_TYPE_DMESG, 1); if (!prz) prz = ramoops_get_next_prz(&cxt->cprz, &cxt->console_read_cnt, 1, id, type, PSTORE_TYPE_CONSOLE, 0); if (!prz) prz = ramoops_get_next_prz(&cxt->fprz, &cxt->ftrace_read_cnt, 1, id, type, PSTORE_TYPE_FTRACE, 0); if (!prz) return 0; if (!persistent_ram_old(prz)) return 0; size = persistent_ram_old_size(prz); header_length = ramoops_read_kmsg_hdr(persistent_ram_old(prz), time, compressed); size -= header_length; /* ECC correction notice */ ecc_notice_size = persistent_ram_ecc_string(prz, NULL, 0); *buf = kmalloc(size + ecc_notice_size + 1, GFP_KERNEL); if (*buf == NULL) return -ENOMEM; memcpy(*buf, (char *)persistent_ram_old(prz) + header_length, size); persistent_ram_ecc_string(prz, *buf + size, ecc_notice_size + 1); return size + ecc_notice_size; }
void *persistent_trace_seq_start(struct seq_file *s, loff_t *pos) { struct persistent_trace_seq_data *data; data = kzalloc(sizeof(*data), GFP_KERNEL); if (!data) return NULL; data->ptr = persistent_ram_old(persistent_trace); data->size = persistent_ram_old_size(persistent_trace); data->off = data->size % REC_SIZE; data->off += *pos * REC_SIZE; if (data->off + REC_SIZE > data->size) { kfree(data); return NULL; } return data; }
static ssize_t ramoops_pstore_read(u64 *id, enum pstore_type_id *type, int *count, struct timespec *time, char **buf, bool *compressed, ssize_t *ecc_notice_size, struct pstore_info *psi) { ssize_t size; struct ramoops_context *cxt = psi->data; struct persistent_ram_zone *prz = NULL; int header_length = 0; /* Ramoops headers provide time stamps for PSTORE_TYPE_DMESG, but * PSTORE_TYPE_CONSOLE and PSTORE_TYPE_FTRACE don't currently have * valid time stamps, so it is initialized to zero. */ time->tv_sec = 0; time->tv_nsec = 0; *compressed = false; /* Find the next valid persistent_ram_zone for DMESG */ while (cxt->dump_read_cnt < cxt->max_dump_cnt && !prz) { prz = ramoops_get_next_prz(cxt->przs, &cxt->dump_read_cnt, cxt->max_dump_cnt, id, type, PSTORE_TYPE_DMESG, 1); if (!prz_ok(prz)) continue; header_length = ramoops_read_kmsg_hdr(persistent_ram_old(prz), time, compressed); /* Clear and skip this DMESG record if it has no valid header */ if (!header_length) { persistent_ram_free_old(prz); persistent_ram_zap(prz); prz = NULL; } } if (!prz_ok(prz)) prz = ramoops_get_next_prz(&cxt->cprz, &cxt->console_read_cnt, 1, id, type, PSTORE_TYPE_CONSOLE, 0); if (!prz_ok(prz)) prz = ramoops_get_next_prz(&cxt->fprz, &cxt->ftrace_read_cnt, 1, id, type, PSTORE_TYPE_FTRACE, 0); if (!prz_ok(prz)) prz = ramoops_get_next_prz(&cxt->mprz, &cxt->pmsg_read_cnt, 1, id, type, PSTORE_TYPE_PMSG, 0); if (!prz_ok(prz)) return 0; size = persistent_ram_old_size(prz) - header_length; /* ECC correction notice */ *ecc_notice_size = persistent_ram_ecc_string(prz, NULL, 0); *buf = kmalloc(size + *ecc_notice_size + 1, GFP_KERNEL); if (*buf == NULL) return -ENOMEM; memcpy(*buf, (char *)persistent_ram_old(prz) + header_length, size); persistent_ram_ecc_string(prz, *buf + size, *ecc_notice_size + 1); return size; }
static bool prz_ok(struct persistent_ram_zone *prz) { return !!prz && !!(persistent_ram_old_size(prz) + persistent_ram_ecc_string(prz, NULL, 0)); }
static ssize_t ram_console_read_old(struct file *file, char __user *buf, size_t len, loff_t *offset) { loff_t pos = *offset; ssize_t count; struct persistent_ram_zone *prz = ram_console_zone; size_t old_log_size = persistent_ram_old_size(prz); const char *old_log = persistent_ram_old(prz); char *str; int ret; if (dmesg_restrict && !capable(CAP_SYSLOG)) return -EPERM; #if defined(CONFIG_HTC_DEBUG_RAMCONSOLE) /* last bootloader log */ if (pos < bl_old_log_buf_size) { count = min(len, (size_t)(bl_old_log_buf_size - pos)); if (copy_to_user(buf, bl_old_log_buf + pos, count)) return -EFAULT; goto out; } pos -= bl_old_log_buf_size; #endif /* Main last_kmsg log */ if (pos < old_log_size) { count = min(len, (size_t)(old_log_size - pos)); if (copy_to_user(buf, old_log + pos, count)) return -EFAULT; goto out; } /* ECC correction notice */ pos -= old_log_size; count = persistent_ram_ecc_string(prz, NULL, 0); if (pos < count) { str = kmalloc(count, GFP_KERNEL); if (!str) return -ENOMEM; persistent_ram_ecc_string(prz, str, count + 1); count = min(len, (size_t)(count - pos)); ret = copy_to_user(buf, str + pos, count); kfree(str); if (ret) return -EFAULT; goto out; } /* Append the boot reason required by Google */ pos -= count; if (pos < rst_msg_buf_size) { count = min(len, (size_t)(rst_msg_buf_size - pos)); if (copy_to_user(buf, rst_msg_buf + pos, count)) return -EFAULT; goto out; } /* Boot info passed through pdata */ pos -= rst_msg_buf_size; if (pos < bootinfo_size) { count = min(len, (size_t)(bootinfo_size - pos)); if (copy_to_user(buf, bootinfo + pos, count)) return -EFAULT; goto out; } #if defined(CONFIG_HTC_DEBUG_RAMCONSOLE) /* bootloader log */ pos -= bootinfo_size; if (pos < bl_log_buf_size) { count = min(len, (size_t)(bl_log_buf_size - pos)); if (copy_to_user(buf, bl_log_buf + pos, count)) return -EFAULT; goto out; } #endif /* EOF */ return 0; out: *offset += count; return count; }
static ssize_t ramoops_pstore_read(u64 *id, enum pstore_type_id *type, int *count, struct timespec *time, char **buf, bool *compressed, ssize_t *ecc_notice_size, struct pstore_info *psi) { ssize_t size = 0; struct ramoops_context *cxt = psi->data; struct persistent_ram_zone *prz = NULL; int header_length = 0; bool free_prz = false; /* Ramoops headers provide time stamps for PSTORE_TYPE_DMESG, but * PSTORE_TYPE_CONSOLE and PSTORE_TYPE_FTRACE don't currently have * valid time stamps, so it is initialized to zero. */ time->tv_sec = 0; time->tv_nsec = 0; *compressed = false; /* Find the next valid persistent_ram_zone for DMESG */ while (cxt->dump_read_cnt < cxt->max_dump_cnt && !prz) { prz = ramoops_get_next_prz(cxt->dprzs, &cxt->dump_read_cnt, cxt->max_dump_cnt, id, type, PSTORE_TYPE_DMESG, 1); if (!prz_ok(prz)) continue; header_length = ramoops_read_kmsg_hdr(persistent_ram_old(prz), time, compressed); /* Clear and skip this DMESG record if it has no valid header */ if (!header_length) { persistent_ram_free_old(prz); persistent_ram_zap(prz); prz = NULL; } } if (!prz_ok(prz)) prz = ramoops_get_next_prz(&cxt->cprz, &cxt->console_read_cnt, 1, id, type, PSTORE_TYPE_CONSOLE, 0); if (!prz_ok(prz)) prz = ramoops_get_next_prz(&cxt->mprz, &cxt->pmsg_read_cnt, 1, id, type, PSTORE_TYPE_PMSG, 0); /* ftrace is last since it may want to dynamically allocate memory. */ if (!prz_ok(prz)) { if (!(cxt->flags & RAMOOPS_FLAG_FTRACE_PER_CPU)) { prz = ramoops_get_next_prz(cxt->fprzs, &cxt->ftrace_read_cnt, 1, id, type, PSTORE_TYPE_FTRACE, 0); } else { /* * Build a new dummy record which combines all the * per-cpu records including metadata and ecc info. */ struct persistent_ram_zone *tmp_prz, *prz_next; tmp_prz = kzalloc(sizeof(struct persistent_ram_zone), GFP_KERNEL); if (!tmp_prz) return -ENOMEM; free_prz = true; while (cxt->ftrace_read_cnt < cxt->max_ftrace_cnt) { prz_next = ramoops_get_next_prz(cxt->fprzs, &cxt->ftrace_read_cnt, cxt->max_ftrace_cnt, id, type, PSTORE_TYPE_FTRACE, 0); if (!prz_ok(prz_next)) continue; tmp_prz->ecc_info = prz_next->ecc_info; tmp_prz->corrected_bytes += prz_next->corrected_bytes; tmp_prz->bad_blocks += prz_next->bad_blocks; size = ftrace_log_combine(tmp_prz, prz_next); if (size) goto out; } *id = 0; prz = tmp_prz; } } if (!prz_ok(prz)) { size = 0; goto out; } size = persistent_ram_old_size(prz) - header_length; /* ECC correction notice */ *ecc_notice_size = persistent_ram_ecc_string(prz, NULL, 0); *buf = kmalloc(size + *ecc_notice_size + 1, GFP_KERNEL); if (*buf == NULL) { size = -ENOMEM; goto out; } memcpy(*buf, (char *)persistent_ram_old(prz) + header_length, size); persistent_ram_ecc_string(prz, *buf + size, *ecc_notice_size + 1); out: if (free_prz) { kfree(prz->old_log); kfree(prz); } return size; }
static ssize_t ram_console_read_old(struct file *file, char __user *buf, size_t len, loff_t *offset) { loff_t pos = *offset; ssize_t count; struct persistent_ram_zone *prz = ram_console_zone; size_t old_log_size = persistent_ram_old_size(prz); const char *old_log = persistent_ram_old(prz); char *str; int ret; if (dmesg_restrict && !capable(CAP_SYSLOG)) return -EPERM; /* Main last_kmsg log */ if (pos < old_log_size) { count = min(len, (size_t)(old_log_size - pos)); if (copy_to_user(buf, old_log + pos, count)) return -EFAULT; goto out; } /* ECC correction notice */ pos -= old_log_size; count = persistent_ram_ecc_string(prz, NULL, 0); if (pos < count) { str = kmalloc(count, GFP_KERNEL); if (!str) return -ENOMEM; persistent_ram_ecc_string(prz, str, count + 1); count = min(len, (size_t)(count - pos)); ret = copy_to_user(buf, str + pos, count); kfree(str); str = NULL; if (ret) return -EFAULT; goto out; } /* bootreason label */ pos -= count; count = 1 + snprintf(NULL, 0, bootreason_label, bi_bootreason()); if (pos < count) { str = kmalloc(count, GFP_KERNEL); if (!str) return -ENOMEM; snprintf(str, count, bootreason_label, bi_bootreason()); count = min(len, (size_t)(count - pos)); ret = copy_to_user(buf, str + pos, count); kfree(str); if (ret) return -EFAULT; goto out; } /* Boot info passed through cmdline */ pos -= count; if (pos < (bootinfo_size)) { count = min(len, (size_t)(bootinfo_size - pos)); if (copy_to_user(buf, bootinfo + pos, count)) return -EFAULT; goto out; } /* EOF */ return 0; out: *offset += count; return count; }