arch/powerpc/boot/main.c

Source file repositories/reference/linux-study-clean/arch/powerpc/boot/main.c

File Facts

System
Linux kernel
Corpus path
arch/powerpc/boot/main.c
Extension
.c
Size
8616 bytes
Lines
285
Domain
Architecture Layer
Bucket
arch/powerpc
Inferred role
Architecture Layer: implementation source
Status
source implementation candidate

Why This File Exists

CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.

Dependency Surface

Detected Declarations

Annotated Snippet

struct addr_range {
	void *addr;
	unsigned long size;
};

#undef DEBUG

static struct addr_range prep_kernel(void)
{
	char elfheader[256];
	unsigned char *vmlinuz_addr = (unsigned char *)_vmlinux_start;
	unsigned long vmlinuz_size = _vmlinux_end - _vmlinux_start;
	void *addr = 0;
	struct elf_info ei;
	long len;
	int uncompressed_image = 0;

	len = partial_decompress(vmlinuz_addr, vmlinuz_size,
		elfheader, sizeof(elfheader), 0);
	/* assume uncompressed data if -1 is returned */
	if (len == -1) {
		uncompressed_image = 1;
		memcpy(elfheader, vmlinuz_addr, sizeof(elfheader));
		printf("No valid compressed data found, assume uncompressed data\n\r");
	}

	if (!parse_elf64(elfheader, &ei) && !parse_elf32(elfheader, &ei))
		fatal("Error: not a valid PPC32 or PPC64 ELF file!\n\r");

	if (platform_ops.image_hdr)
		platform_ops.image_hdr(elfheader);

	/* We need to alloc the memsize: gzip will expand the kernel
	 * text/data, then possible rubbish we don't care about. But
	 * the kernel bss must be claimed (it will be zero'd by the
	 * kernel itself)
	 */
	printf("Allocating 0x%lx bytes for kernel...\n\r", ei.memsize);

	if (platform_ops.vmlinux_alloc) {
		addr = platform_ops.vmlinux_alloc(ei.memsize);
	} else {
		/*
		 * Check if the kernel image (without bss) would overwrite the
		 * bootwrapper. The device tree has been moved in fdt_init()
		 * to an area allocated with malloc() (somewhere past _end).
		 */
		if ((unsigned long)_start < ei.loadsize)
			fatal("Insufficient memory for kernel at address 0!"
			       " (_start=%p, uncompressed size=%08lx)\n\r",
			       _start, ei.loadsize);

		if ((unsigned long)_end < ei.memsize)
			fatal("The final kernel image would overwrite the "
					"device tree\n\r");
	}

	if (uncompressed_image) {
		memcpy(addr, vmlinuz_addr + ei.elfoffset, ei.loadsize);
		printf("0x%lx bytes of uncompressed data copied\n\r",
		       ei.loadsize);
		goto out;
	}

	/* Finally, decompress the kernel */
	printf("Decompressing (0x%p <- 0x%p:0x%p)...\n\r", addr,
	       vmlinuz_addr, vmlinuz_addr+vmlinuz_size);

	len = partial_decompress(vmlinuz_addr, vmlinuz_size,
		addr, ei.loadsize, ei.elfoffset);

	if (len < 0)
		fatal("Decompression failed with error code %ld\n\r", len);

	if (len != ei.loadsize)
		 fatal("Decompression error: got 0x%lx bytes, expected 0x%lx.\n\r",
			 len, ei.loadsize);

	printf("Done! Decompressed 0x%lx bytes\n\r", len);
out:
	flush_cache(addr, ei.loadsize);

	return (struct addr_range){addr, ei.memsize};
}

static struct addr_range prep_initrd(struct addr_range vmlinux, void *chosen,
				     unsigned long initrd_addr,
				     unsigned long initrd_size)
{
	/* If we have an image attached to us, it overrides anything

Annotation

Implementation Notes