[Skiboot] [PATCH v2] init: Test device tree for binary kernel

Michael Neuling mikey at neuling.org
Wed Mar 9 11:29:16 AEDT 2016


Test device tree for binary kernel in /chosen/kernel-base-address.
Use this if found and then detect if it's an elf or a raw binary.

This can reduce the boot time since the kernel no longer needs to
relocate itself when loaded directly at 0.

An example of how to do this using mambo is given with the follow
skiboot.tcl patch and these commands:

% objcopy -O binary vmlinux vmlinux.raw
% SKIBOOT_ZIMAGE=vmlinux.raw

diff --git a/external/mambo/skiboot.tcl b/external/mambo/skiboot.tcl
index d3b4120..b68cf27 100644
--- a/external/mambo/skiboot.tcl
+++ b/external/mambo/skiboot.tcl
@@ -34,7 +34,7 @@ if { ![info exists env(SKIBOOT_ZIMAGE)] } {
 mconfig payload PAYLOAD $env(SKIBOOT_ZIMAGE)

 # Paylod: Memory location for a Linux style ramdisk/initrd
-mconfig payload_addr PAYLOAD_ADDR 0x20000000;
+mconfig payload_addr PAYLOAD_ADDR 0x0;

 # FW: Where should ePAPR Flat Devtree Binary be loaded
 mconfig epapr_dt_addr EPAPR_DT_ADDR 0x1f00000;# place at 31M
@@ -170,9 +170,9 @@ lappend compat "ibm,power8-xscom"
 set compat [of::encode_compat $compat]
 mysim of addprop $xscom_node byte_array "compatible" $compat

+set chosen_node [mysim of find_device /chosen]
 if { [info exists env(SKIBOOT_INITRD)] } {
     set cpio_file $env(SKIBOOT_INITRD)
-    set chosen_node [mysim of find_device /chosen]
     set cpio_size [file size $cpio_file]
     set cpio_start 0x10000000
     set cpio_end [expr $cpio_start + $cpio_size]
@@ -180,6 +180,8 @@ if { [info exists env(SKIBOOT_INITRD)] } {
     mysim of addprop $chosen_node int "linux,initrd-end"   $cpio_end
     mysim mcm 0 memory fread $cpio_start $cpio_size $cpio_file
 }
+set reg [list $mconf(payload_addr) ]
+mysim of addprop $chosen_node array64 "kernel-base-address" reg

 # Flatten it

Signed-off-by: Michael Neuling <mikey at neuling.org>

---

Stewart and I painted the bikeshed offline and ended up with
/choosen/kernel-base-address. This can point to either an elf or raw
stripped binary and skiboot will detect it.

Mikey

diff --git a/core/init.c b/core/init.c
index 0576f46..f877a0d 100644
--- a/core/init.c
+++ b/core/init.c
@@ -318,6 +318,7 @@ static bool start_preload_kernel(void)
 
 static bool load_kernel(void)
 {
+	const struct dt_property *prop;
 	struct elf_hdr *kh;
 	int loaded;
 
@@ -345,13 +346,32 @@ static bool load_kernel(void)
 		}
 	}
 
-	if (!kernel_size)
-		printf("Assuming kernel at %p\n", KERNEL_LOAD_BASE);
+	prop = dt_find_property(dt_chosen, "kernel-base-address");
+	if (prop) {
+		kernel_entry = dt_get_number(prop->prop, 2);
+		printf("INIT: Kernel image at 0x%llx\n",
kernel_entry);
+		kh = (struct elf_hdr *)kernel_entry;
+		/*
+		 * If the kernel is at 0, copy back what we wrote over
+		 * for the null branch catcher.
+		 */
+		if (kernel_entry == 0)
+			memcpy(0, zero_location, 16);
+	} else {
+		if (!kernel_size)
+			printf("INIT: Assuming kernel at %p\n",
+			       KERNEL_LOAD_BASE);
+		kh = (struct elf_hdr *)KERNEL_LOAD_BASE;
+	}
 
 	printf("INIT: Kernel loaded, size: %zu bytes (0 = unknown
preload)\n",
 	       kernel_size);
 
-	kh = (struct elf_hdr *)KERNEL_LOAD_BASE;
+	if (kh->ei_ident != ELF_IDENT) {
+		printf("INIT: ELF header not found. Assuming raw
binary.\n");
+		return true;
+	}
+
 	if (kh->ei_class == ELF_CLASS_64)
 		return try_load_elf64(kh);
 	else if (kh->ei_class == ELF_CLASS_32)


More information about the Skiboot mailing list