[Skiboot] [PATCH v3] init: Test device tree for kernel location

Michael Neuling mikey at neuling.org
Wed Mar 9 20:07:26 AEDT 2016


Test device tree for kernel location 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>

--
v3:
  - Fix screw up with line wrapping in v2
  - Fix patch name to not mention binary anymore
  - Use different dt_* functions

v2:
  Offline bikeshedding with Stewart
---
 core/init.c | 25 ++++++++++++++++++++++---
 1 file changed, 22 insertions(+), 3 deletions(-)

diff --git a/core/init.c b/core/init.c
index 963e467..003956e 100644
--- a/core/init.c
+++ b/core/init.c
@@ -344,13 +344,32 @@ static bool load_kernel(void)
 		}
 	}
 
-	if (!kernel_size)
-		printf("Assuming kernel at %p\n", KERNEL_LOAD_BASE);
+	if (dt_has_node_property(dt_chosen, "kernel-base-address", NULL)) {
+		kernel_entry = dt_prop_get_u64(dt_chosen,
+					       "kernel-base-address");
+		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)
-- 
2.5.0



More information about the Skiboot mailing list