static int ramoops_pstore_erase(enum pstore_type_id type, u64 id, int count, struct timespec time, struct pstore_info *psi) { struct ramoops_context *cxt = psi->data; struct persistent_ram_zone *prz; switch (type) { case PSTORE_TYPE_DMESG: if (id >= cxt->max_dump_cnt) return -EINVAL; prz = cxt->przs[id]; break; case PSTORE_TYPE_CONSOLE: prz = cxt->cprz; break; case PSTORE_TYPE_FTRACE: prz = cxt->fprz; break; case PSTORE_TYPE_PMSG: prz = cxt->mprz; break; default: return -EINVAL; } persistent_ram_free_old(prz); persistent_ram_zap(prz); return 0; }
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 ramoops_pstore_erase(struct pstore_record *record) { struct ramoops_context *cxt = record->psi->data; struct persistent_ram_zone *prz; switch (record->type) { case PSTORE_TYPE_DMESG: if (record->id >= cxt->max_dump_cnt) return -EINVAL; prz = cxt->dprzs[record->id]; break; case PSTORE_TYPE_CONSOLE: prz = cxt->cprz; break; case PSTORE_TYPE_FTRACE: if (record->id >= cxt->max_ftrace_cnt) return -EINVAL; prz = cxt->fprzs[record->id]; break; case PSTORE_TYPE_PMSG: prz = cxt->mprz; break; default: return -EINVAL; } persistent_ram_free_old(prz); persistent_ram_zap(prz); 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 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 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, 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 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; }