|
@@ -145,13 +145,12 @@ static int __init rd_start_early(char *p)
|
|
|
unsigned long start = memparse(p, &p);
|
|
|
|
|
|
#ifdef CONFIG_64BIT
|
|
|
- /* HACK: Guess if the sign extension was forgotten */
|
|
|
- if (start > 0x0000000080000000 && start < 0x00000000ffffffff)
|
|
|
- start |= 0xffffffff00000000UL;
|
|
|
+ /* Guess if the sign extension was forgotten by bootloader */
|
|
|
+ if (start < XKPHYS)
|
|
|
+ start = (int)start;
|
|
|
#endif
|
|
|
initrd_start = start;
|
|
|
initrd_end += start;
|
|
|
-
|
|
|
return 0;
|
|
|
}
|
|
|
early_param("rd_start", rd_start_early);
|
|
@@ -159,41 +158,64 @@ early_param("rd_start", rd_start_early);
|
|
|
static int __init rd_size_early(char *p)
|
|
|
{
|
|
|
initrd_end += memparse(p, &p);
|
|
|
-
|
|
|
return 0;
|
|
|
}
|
|
|
early_param("rd_size", rd_size_early);
|
|
|
|
|
|
+/* it returns the next free pfn after initrd */
|
|
|
static unsigned long __init init_initrd(void)
|
|
|
{
|
|
|
- unsigned long tmp, end, size;
|
|
|
+ unsigned long end;
|
|
|
u32 *initrd_header;
|
|
|
|
|
|
- ROOT_DEV = Root_RAM0;
|
|
|
-
|
|
|
/*
|
|
|
* Board specific code or command line parser should have
|
|
|
* already set up initrd_start and initrd_end. In these cases
|
|
|
* perfom sanity checks and use them if all looks good.
|
|
|
*/
|
|
|
- size = initrd_end - initrd_start;
|
|
|
- if (initrd_end == 0 || size == 0) {
|
|
|
- initrd_start = 0;
|
|
|
- initrd_end = 0;
|
|
|
- } else
|
|
|
- return initrd_end;
|
|
|
-
|
|
|
- end = (unsigned long)&_end;
|
|
|
- tmp = PAGE_ALIGN(end) - sizeof(u32) * 2;
|
|
|
- if (tmp < end)
|
|
|
- tmp += PAGE_SIZE;
|
|
|
-
|
|
|
- initrd_header = (u32 *)tmp;
|
|
|
- if (initrd_header[0] == 0x494E5244) {
|
|
|
- initrd_start = (unsigned long)&initrd_header[2];
|
|
|
- initrd_end = initrd_start + initrd_header[1];
|
|
|
+ if (initrd_start && initrd_end > initrd_start)
|
|
|
+ goto sanitize;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * See if initrd has been added to the kernel image by
|
|
|
+ * arch/mips/boot/addinitrd.c. In that case a header is
|
|
|
+ * prepended to initrd and is made up by 8 bytes. The fisrt
|
|
|
+ * word is a magic number and the second one is the size of
|
|
|
+ * initrd. Initrd start must be page aligned in any cases.
|
|
|
+ */
|
|
|
+ initrd_header = __va(PAGE_ALIGN(__pa_symbol(&_end) + 8)) - 8;
|
|
|
+ if (initrd_header[0] != 0x494E5244)
|
|
|
+ goto disable;
|
|
|
+ initrd_start = (unsigned long)(initrd_header + 2);
|
|
|
+ initrd_end = initrd_start + initrd_header[1];
|
|
|
+
|
|
|
+sanitize:
|
|
|
+ if (initrd_start & ~PAGE_MASK) {
|
|
|
+ printk(KERN_ERR "initrd start must be page aligned\n");
|
|
|
+ goto disable;
|
|
|
}
|
|
|
- return initrd_end;
|
|
|
+ if (initrd_start < PAGE_OFFSET) {
|
|
|
+ printk(KERN_ERR "initrd start < PAGE_OFFSET\n");
|
|
|
+ goto disable;
|
|
|
+ }
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Sanitize initrd addresses. For example firmware
|
|
|
+ * can't guess if they need to pass them through
|
|
|
+ * 64-bits values if the kernel has been built in pure
|
|
|
+ * 32-bit. We need also to switch from KSEG0 to XKPHYS
|
|
|
+ * addresses now, so the code can now safely use __pa().
|
|
|
+ */
|
|
|
+ end = __pa(initrd_end);
|
|
|
+ initrd_end = (unsigned long)__va(end);
|
|
|
+ initrd_start = (unsigned long)__va(__pa(initrd_start));
|
|
|
+
|
|
|
+ ROOT_DEV = Root_RAM0;
|
|
|
+ return PFN_UP(end);
|
|
|
+disable:
|
|
|
+ initrd_start = 0;
|
|
|
+ initrd_end = 0;
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
static void __init finalize_initrd(void)
|
|
@@ -259,8 +281,7 @@ static void __init bootmem_init(void)
|
|
|
* not selected. Once that done we can determine the low bound
|
|
|
* of usable memory.
|
|
|
*/
|
|
|
- reserved_end = init_initrd();
|
|
|
- reserved_end = PFN_UP(max(__pa(reserved_end), __pa_symbol(&_end)));
|
|
|
+ reserved_end = max(init_initrd(), PFN_UP(__pa_symbol(&_end)));
|
|
|
|
|
|
/*
|
|
|
* Find the highest page frame number we have available.
|