The attached patch by Peter Jones <[EMAIL PROTECTED]> implements intelligent placement of the ramdisk in memory during boot of an ELF image created by mkelfimage.

mkelfimage prior to this patch defaults to a hardcoded 1MB which doesn't quite work in all circumstances. The kernel as it is decompressed can overwrite part of the ramdisk. Peter says that pretty much all other boot loaders already do this intelligent detection instead of native hard coding.

This patch allows a wrapped Fedora i586 kernel to boot on both KVM and Artec Group's Thincan DBE61C (coreboot). It probably needs more testing in other circumstances.

Thanks,
Warren Togami
[EMAIL PROTECTED]
diff -up mkelfImage-2.7/linux-i386/convert_params.c.ramdisk_base mkelfImage-2.7/linux-i386/convert_params.c
--- mkelfImage-2.7/linux-i386/convert_params.c.ramdisk_base	2006-03-27 18:44:59.000000000 -0500
+++ mkelfImage-2.7/linux-i386/convert_params.c	2008-05-21 12:55:44.000000000 -0400
@@ -1301,6 +1301,44 @@ static void query_firmware_values(struct
 	
 }
 
+static void relocate_ramdisk(struct param_info *info)
+{
+	struct e820entry *e820_map;
+	struct e820entry *highest = 0;
+	unsigned long load_addr;
+	int i;
+
+	e820_map = info->real_mode->e820_map;
+#if 0
+	printf("initrd_start = 0x%lx\n", info->real_mode->initrd_start);
+	printf("real_mode->e820_map_nr: %d\n", info->real_mode->e820_map_nr);
+#endif
+	for (i = 0; i < info->real_mode->e820_map_nr; i++) {
+		if (e820_map[i].type != E820_RAM)
+			continue;
+#if 0
+		printf("addr: 0x%lx len: %x\n", e820_map[i].addr, e820_map[i].size);
+#endif
+		if (highest && e820_map[i].addr < highest->addr)
+			continue;
+		if (e820_map[i].size < info->real_mode->initrd_size)
+			continue;
+		if (e820_map[i].addr + info->real_mode->initrd_size >= 0x38000000)
+			continue;
+		highest = &e820_map[i];
+	}
+
+	if (highest == 0)
+		return;
+
+	load_addr = highest->addr + highest->size;
+	load_addr -= info->real_mode->initrd_size;
+	load_addr &= ~0xfffUL;
+
+	memcpy((void *)load_addr, (void *)info->real_mode->initrd_start, info->real_mode->initrd_size);
+	printf("relocating ramdisk to 0x%lx\n", load_addr);
+	info->real_mode->initrd_start = load_addr;
+}
 /*
  * Debug
  * =============================================================================
@@ -1533,6 +1571,10 @@ void *convert_params(unsigned type, void
 	query_firmware_class(&info);
 	query_firmware_values(&info);
 	query_bootloader_values(&info);
+	if (info.real_mode->initrd_size) {
+		/* Make sure the initrd is in a relatively safe place. */
+		relocate_ramdisk(&info);
+	}
 
 	/* Do the hardware setup that linux might forget... */
 	hardware_setup(&info);
diff -up mkelfImage-2.7/linux-i386/mkelf-linux-i386.c.ramdisk_base mkelfImage-2.7/linux-i386/mkelf-linux-i386.c
--- mkelfImage-2.7/linux-i386/mkelf-linux-i386.c.ramdisk_base	2006-03-17 09:08:22.000000000 -0500
+++ mkelfImage-2.7/linux-i386/mkelf-linux-i386.c	2008-05-21 10:47:42.000000000 -0400
@@ -352,6 +352,9 @@ int linux_i386_mkelf(int argc, char **ar
 	 */
 	params->initrd_start = params->initrd_size = 0;
 	if (ramdisk_size) {
+		while (ramdisk_base <= kernel_size)
+			ramdisk_base <<= 1;
+
 		phdr[index].p_paddr  = ramdisk_base;
 		phdr[index].p_vaddr  = ramdisk_base;
 		phdr[index].p_filesz = ramdisk_size;
-- 
coreboot mailing list
[email protected]
http://www.coreboot.org/mailman/listinfo/coreboot

Reply via email to