Пример #1
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_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;

	/* 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;
}
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;

}
Пример #3
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;
}
Пример #4
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 = 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;
}
Пример #5
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;

	/* 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;
}
Пример #6
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;
}