int image_arm64_load(int argc, char **argv, const char *kernel_buf,
	off_t kernel_size, struct kexec_info *info)
{
	int result;
	uint64_t start;
	const struct arm64_image_header *h;
	char *header_option = NULL;

	h = (const struct arm64_image_header *)(kernel_buf);

	arm64_mem.text_offset = le64_to_cpu(h->text_offset);
	arm64_mem.image_size = le64_to_cpu(h->image_size);

	arm64_mem.page_offset = get_kernel_page_offset();

	if (info->kexec_flags & KEXEC_ON_CRASH) {
		result = load_crashdump_segments(info, &header_option);

		if (result) {
			fprintf(stderr, "kexec: load crashdump segments failed.\n");
			return -1;
		}
		start = crash_reserved_mem.start;
	} else {
		result = parse_iomem_single("Kernel code\n", &start, NULL);

		if (result) {
			fprintf(stderr, "kexec: Could not get kernel code address.\n");
			return -1;
		}
		start -= arm64_mem.text_offset;
	}

	/* Add kernel */
	add_segment_phys_virt(info, kernel_buf, kernel_size,
			start + arm64_mem.text_offset,
			kernel_size, 0);

	info->entry = (void *)start + arm64_mem.text_offset;

	result = arm64_load_other_segments(info, (unsigned long)info->entry,
		header_option);

	if (header_option)
		free(header_option);

	return result;
}
Example #2
0
unsigned long add_buffer_phys_virt(struct kexec_info *info,
	const void *buf, unsigned long bufsz, unsigned long memsz,
	unsigned long buf_align, unsigned long buf_min, unsigned long buf_max,
	int buf_end, int phys)
{
	unsigned long base, start, end;
	int result;
	int pagesize;

	result = sort_segments(info);
	if (result < 0) {
		die("sort_segments failed\n");
	}

	/* Round memsz up to a multiple of pagesize */
	pagesize = getpagesize();
	memsz = (memsz + (pagesize - 1)) & ~(pagesize - 1);

//	base = locate_hole(info, memsz, buf_align, buf_min, buf_max, buf_end);

        /* local_hole will find memory at end of RAM where capture kernel
         * is generally allocated, but in case HIGHMEM is supported then
         * capture kernel need not be at the end of RAM */
	result = get_crashkernel_mem_range(&start, &end);
	if (result < 0) {
		die("get_crashkernel_mem_range failed");
	}

	base = end - memsz + 1;
	if ((base <= start) || (base >= end)) {
		die("locate_hole failed\n");
	}

	add_segment_phys_virt(info, buf, bufsz, base, memsz, phys);
	return base;
}
Example #3
0
/*
 * add_segment() should convert base to a physical address on superh,
 * while the default is just to work with base as is */
void add_segment(struct kexec_info *info, const void *buf, size_t bufsz,
                 unsigned long base, size_t memsz)
{
        add_segment_phys_virt(info, buf, bufsz, base, memsz, 1);
}