[coreboot] [FILO] r139 - trunk/filo/i386

repository service svn at coreboot.org
Fri Dec 10 05:09:58 CET 2010


Author: stuge
Date: Fri Dec 10 05:09:57 2010
New Revision: 139
URL: http://tracker.coreboot.org/trac/filo/changeset/139

Log:
Support Linux boot protocol v2.10

The current version of FILO is only aware of the Linux boot protocol up
to the version 2.03. This makes it impossible to, e.g., load newer
kernels compiled with CONFIG_RELOCATABLE=y because they require the boot
loader to at least support version 2.05 of the Linux boot loader
protocol. Otherwise the kernel will just panic while trying to
uncompress (because it thinks the load address is NULL).
The attached patch fixes this problem by enhancing the current
implementation to cover the newer protocol versions and respect the new
members, specifically "relocatable_kernel" and "kernel_alignment".

Signed-off-by: Mathias Krause <mathias.krause at secunet.com>
Acked-by: Peter Stuge <peter at stuge.se>

Modified:
   trunk/filo/i386/linux_load.c

Modified: trunk/filo/i386/linux_load.c
==============================================================================
--- trunk/filo/i386/linux_load.c	Tue Aug 31 22:26:34 2010	(r138)
+++ trunk/filo/i386/linux_load.c	Fri Dec 10 05:09:57 2010	(r139)
@@ -57,7 +57,8 @@
 	u8 reserved1[0x1f1];	/* 0x000 */
 	u8 setup_sects;		/* 0x1f1 */
 	u16 root_flags;		/* 0x1f2 */
-	u8 reserved2[6];	/* 0x1f4 */
+	u32 syssize;		/* 0x1f4 (2.04+) */
+	u8 reserved2[2];	/* 0x1f8 */
 	u16 vid_mode;		/* 0x1fa */
 	u16 root_dev;		/* 0x1fc */
 	u16 boot_sector_magic;	/* 0x1fe */
@@ -82,6 +83,24 @@
 	u32 cmd_line_ptr;	/* 0x228 */
 	/* 2.03+ */
 	u32 initrd_addr_max;	/* 0x22c */
+	/* 2.05+ */
+	u32 kernel_alignment;	/* 0x230 */
+	u8 relocatable_kernel;	/* 0x234 */
+	u8 min_alignment;	/* 0x235 (2.10+) */
+	u8 reserved6[2];	/* 0x236 */
+	/* 2.06+ */
+	u32 cmdline_size;	/* 0x238 */
+	/* 2.07+ */
+	u32 hardware_subarch;	/* 0x23c */
+	u64 hardware_subarch_data;/* 0x240 */
+	/* 2.08+ */
+	u32 payload_offset;	/* 0x248 */
+	u32 payload_length;	/* 0x24c */
+	/* 2.09+ */
+	u64 setup_data;		/* 0x250 */
+	/* 2.10+ */
+	u64 pref_address;	/* 0x258 */
+	u32 init_size;		/* 0x260 */
 } __attribute__ ((packed));
 
 /* Paramters passed to 32-bit part of Linux
@@ -160,7 +179,10 @@
 	u32 initrd_size;	/* 0x21c */
 	u8 reserved12_5[8];	/* 0x220 */
 	u32 cmd_line_ptr;	/* 0x228 */
-	u8 reserved13[164];	/* 0x22c */
+	u32 initrd_addr_max;	/* 0x22c */
+	u32 kernel_alignment;	/* 0x230 */
+	u8 relocatable_kernel;	/* 0x234 */
+	u8 reserved13[155];		/* 0x22c */
 	struct e820entry e820_map[E820MAX];	/* 0x2d0 */
 	u8 reserved16[688];	/* 0x550 */
 #define COMMAND_LINE_SIZE 256
@@ -176,8 +198,8 @@
 /* Load the first part the file and check if it's Linux */
 static u32 load_linux_header(struct linux_header *hdr)
 {
+	u32 kern_addr = 0;
 	int load_high;
-	u32 kern_addr;
 
 	if (file_read(hdr, sizeof *hdr) != sizeof *hdr) {
 		printf("Can't read Linux header\n");
@@ -221,12 +243,28 @@
 		debug(" (loadflags %#x)", hdr->loadflags);
 		load_high = hdr->loadflags & 1;
 	}
+
+	/* determine kernel load address */
+	if (hdr->protocol_version >= 0x20a) {
+		if (hdr->pref_address >> 32) {
+			debug(" (ignoring 64bit pref_address)");
+		} else {
+			kern_addr = hdr->pref_address;
+		}
+	}
+
+	if (hdr->protocol_version >= 0x205 && hdr->relocatable_kernel) {
+		printf(" relocatable");
+	}
+
 	if (load_high) {
 		printf(" bzImage");
-		kern_addr = 0x100000;
+		if (kern_addr == 0)
+			kern_addr = 0x100000;
 	} else {
 		printf(" zImage or Image");
-		kern_addr = 0x1000;
+		if (kern_addr == 0)
+			kern_addr = 0x1000;
 	}
 
 	printf(".\n");
@@ -257,6 +295,12 @@
 	params->orig_video_points = 16;
 
 	params->loader_type = 0xff;	/* Unregistered Linux loader */
+
+	/* copy alignment fields for relocatable kernels */
+	if (hdr->protocol_version >= 0x205) {
+		params->relocatable_kernel = hdr->relocatable_kernel;
+		params->kernel_alignment = hdr->kernel_alignment;
+	}
 }
 
 /* Memory map */
@@ -676,6 +720,9 @@
 	/* Entry point */
 	ctx->eip = kern_addr;
 
+	/* set this field in any case to support relocatable kernels */
+	params->kernel_start = kern_addr;
+
 	debug("EIP=%#x\n", kern_addr);
 	printf("Jumping to entry point...\n");
 




More information about the coreboot mailing list