* [PATCH] Improve ramdisk support
@ 2004-11-21 3:06 Thiemo Seufer
2004-11-21 16:20 ` Thiemo Seufer
0 siblings, 1 reply; 3+ messages in thread
From: Thiemo Seufer @ 2004-11-21 3:06 UTC (permalink / raw)
To: linux-mips; +Cc: ralf
Hello All,
there are currently two methods to use an initial ramdisk in the
kernel, either by compiling it in via CONFIG_EMBEDDED_RAMDISK or by
tacking the ramdisk on the kernel image via addinitrd. A third method
currently under development is a compiled in cpio archive handled via
initramfs.
There is, however, no way to add an initial ramdisk after the kernel
was built. The appended patch introduces "rd_start" and "rd_size"
command line parameters which allow a bootloader to preload the
ramdisk and make its location known to the kernel by feeding
appropriate rd_start/rd_size values.
Debian used an earlier version of this patch for several years now.
Thiemo
Index: arch/mips/kernel/setup.c
===================================================================
RCS file: /home/cvs/linux/arch/mips/kernel/setup.c,v
retrieving revision 1.171
diff -u -p -r1.171 setup.c
--- arch/mips/kernel/setup.c 28 Jun 2004 21:04:12 -0000 1.171
+++ arch/mips/kernel/setup.c 20 Nov 2004 16:46:39 -0000
@@ -194,6 +194,68 @@ static inline void parse_cmdline_early(v
}
}
+static inline int parse_rd_cmdline(unsigned long* rd_start, unsigned long* rd_end)
+{
+ /*
+ * "rd_start=0xNNNNNNNN" defines the memory address of an initrd
+ * "rd_size=0xNN" it's size
+ */
+ unsigned long start = 0;
+ unsigned long size = 0;
+ unsigned long end;
+ char cmd_line[CL_SIZE];
+ char *start_str;
+ char *size_str;
+ char *tmp;
+
+ strcpy(cmd_line, command_line);
+ *command_line = 0;
+ tmp = cmd_line;
+ /* Ignore "rd_start=" strings in other parameters. */
+ start_str = strstr(cmd_line, "rd_start=");
+ if (start_str && start_str != cmd_line && *(start_str - 1) != ' ')
+ start_str = strstr(start_str, " rd_start=");
+ while (start_str) {
+ if (start_str != cmd_line)
+ strncat(command_line, tmp, start_str - tmp);
+ start = memparse(start_str + 9, &start_str);
+ tmp = start_str + 1;
+ start_str = strstr(start_str, " rd_start=");
+ }
+ if (*tmp)
+ strcat(command_line, tmp);
+
+ strcpy(cmd_line, command_line);
+ *command_line = 0;
+ tmp = cmd_line;
+ /* Ignore "rd_size" strings in other parameters. */
+ size_str = strstr(cmd_line, "rd_size=");
+ if (size_str && size_str != cmd_line && *(size_str - 1) != ' ')
+ size_str = strstr(size_str, " rd_size=");
+ while (size_str) {
+ if (size_str != cmd_line)
+ strncat(command_line, tmp, size_str - tmp);
+ size = memparse(size_str + 8, &size_str);
+ tmp = size_str + 1;
+ size_str = strstr(size_str, " rd_size=");
+ }
+ if (*tmp)
+ strcat(command_line, tmp);
+
+#ifdef CONFIG_MIPS64
+ /* HACK: Guess if the sign extension was forgotten */
+ if (start > 0x0000000080000000 && start < 0x00000000ffffffff)
+ start |= 0xffffffff00000000;
+#endif
+
+ end = start + size;
+ if (start && end) {
+ *rd_start = start;
+ *rd_end = end;
+ return 1;
+ }
+ return 0;
+}
#define PFN_UP(x) (((x) + PAGE_SIZE - 1) >> PAGE_SHIFT)
#define PFN_DOWN(x) ((x) >> PAGE_SHIFT)
@@ -205,30 +267,45 @@ static inline void parse_cmdline_early(v
static inline void bootmem_init(void)
{
unsigned long start_pfn;
+ unsigned long reserved_end = (unsigned long)&_end;
#ifndef CONFIG_SGI_IP27
- unsigned long bootmap_size, max_low_pfn, first_usable_pfn;
+ unsigned long first_usable_pfn;
+ unsigned long bootmap_size;
int i;
#endif
#ifdef CONFIG_BLK_DEV_INITRD
- unsigned long tmp;
- unsigned long *initrd_header;
+ int initrd_reserve_bootmem = 0;
- tmp = (((unsigned long)&_end + PAGE_SIZE-1) & PAGE_MASK) - 8;
- if (tmp < (unsigned long)&_end)
- tmp += PAGE_SIZE;
- initrd_header = (unsigned long *)tmp;
- if (initrd_header[0] == 0x494E5244) {
- initrd_start = (unsigned long)&initrd_header[2];
- initrd_end = initrd_start + initrd_header[1];
+ /* Board specific code should have set up initrd_start and initrd_end */
+ ROOT_DEV = Root_RAM0;
+ if (&__rd_start != &__rd_end) {
+ initrd_start = (unsigned long)&__rd_start;
+ initrd_end = (unsigned long)&__rd_end;
+ } else if (parse_rd_cmdline(&initrd_start, &initrd_end)) {
+ reserved_end = max(reserved_end, initrd_end);
+ initrd_reserve_bootmem = 1;
+ } else {
+ unsigned long tmp;
+ unsigned long *initrd_header;
+
+ tmp = ((reserved_end + PAGE_SIZE-1) & PAGE_MASK) - 8;
+ if (tmp < reserved_end)
+ tmp += PAGE_SIZE;
+ initrd_header = (unsigned long *)tmp;
+ if (initrd_header[0] == 0x494E5244) {
+ initrd_start = (unsigned long)&initrd_header[2];
+ initrd_end = initrd_start + initrd_header[1];
+ reserved_end = max(reserved_end, initrd_end);
+ initrd_reserve_bootmem = 1;
+ }
}
- start_pfn = PFN_UP(CPHYSADDR((&_end)+(initrd_end - initrd_start) + PAGE_SIZE));
-#else
+#endif /* CONFIG_BLK_DEV_INITRD */
+
/*
* Partially used pages are not usable - thus
* we are rounding upwards.
*/
- start_pfn = PFN_UP(CPHYSADDR(&_end));
-#endif /* CONFIG_BLK_DEV_INITRD */
+ start_pfn = PFN_UP(CPHYSADDR(reserved_end));
#ifndef CONFIG_SGI_IP27
/* Find the highest page frame number we have available. */
@@ -341,21 +418,14 @@ static inline void bootmem_init(void)
/* Reserve the bootmap memory. */
reserve_bootmem(PFN_PHYS(first_usable_pfn), bootmap_size);
-#endif
+#endif /* CONFIG_SGI_IP27 */
#ifdef CONFIG_BLK_DEV_INITRD
- /* Board specific code should have set up initrd_start and initrd_end */
- ROOT_DEV = Root_RAM0;
- if (&__rd_start != &__rd_end) {
- initrd_start = (unsigned long)&__rd_start;
- initrd_end = (unsigned long)&__rd_end;
- }
initrd_below_start_ok = 1;
if (initrd_start) {
unsigned long initrd_size = ((unsigned char *)initrd_end) - ((unsigned char *)initrd_start);
printk("Initial ramdisk at: 0x%p (%lu bytes)\n",
- (void *)initrd_start,
- initrd_size);
+ (void *)initrd_start, initrd_size);
if (CPHYSADDR(initrd_end) > PFN_PHYS(max_low_pfn)) {
printk("initrd extends beyond end of memory "
@@ -363,7 +433,11 @@ static inline void bootmem_init(void)
sizeof(long) * 2, CPHYSADDR(initrd_end),
sizeof(long) * 2, PFN_PHYS(max_low_pfn));
initrd_start = initrd_end = 0;
+ initrd_reserve_bootmem = 0;
}
+
+ if (initrd_reserve_bootmem)
+ reserve_bootmem(CPHYSADDR(initrd_start), initrd_size);
}
#endif /* CONFIG_BLK_DEV_INITRD */
}
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH] Improve ramdisk support
2004-11-21 3:06 [PATCH] Improve ramdisk support Thiemo Seufer
@ 2004-11-21 16:20 ` Thiemo Seufer
2004-11-21 19:32 ` Ralf Baechle
0 siblings, 1 reply; 3+ messages in thread
From: Thiemo Seufer @ 2004-11-21 16:20 UTC (permalink / raw)
To: linux-mips; +Cc: ralf
Thiemo Seufer wrote:
> Hello All,
>
> there are currently two methods to use an initial ramdisk in the
> kernel, either by compiling it in via CONFIG_EMBEDDED_RAMDISK or by
> tacking the ramdisk on the kernel image via addinitrd. A third method
> currently under development is a compiled in cpio archive handled via
> initramfs.
>
> There is, however, no way to add an initial ramdisk after the kernel
> was built. The appended patch introduces "rd_start" and "rd_size"
> command line parameters which allow a bootloader to preload the
> ramdisk and make its location known to the kernel by feeding
> appropriate rd_start/rd_size values.
>
> Debian used an earlier version of this patch for several years now.
CONFIG_EMBEDDED_RAMDISK is gone now. The updated patch below removes
some leftovers.
Thiemo
Index: arch/mips/au1000/common/setup.c
===================================================================
RCS file: /home/cvs/linux/arch/mips/au1000/common/setup.c,v
retrieving revision 1.20
diff -u -p -r1.20 setup.c
--- arch/mips/au1000/common/setup.c 11 Oct 2004 20:01:14 -0000 1.20
+++ arch/mips/au1000/common/setup.c 21 Nov 2004 16:14:03 -0000
@@ -42,11 +42,6 @@
#include <asm/mach-au1x00/au1000.h>
#include <asm/time.h>
-#ifdef CONFIG_BLK_DEV_INITRD
-extern unsigned long initrd_start, initrd_end;
-extern void * __rd_start, * __rd_end;
-#endif
-
extern char * __init prom_getcmdline(void);
extern void __init board_setup(void);
extern void au1000_restart(char *);
@@ -153,12 +148,6 @@ static int __init au1x00_setup(void)
iomem_resource.start = IOMEM_RESOURCE_START;
iomem_resource.end = IOMEM_RESOURCE_END;
-#ifdef CONFIG_BLK_DEV_INITRD
- ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0);
- initrd_start = (unsigned long)&__rd_start;
- initrd_end = (unsigned long)&__rd_end;
-#endif
-
while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_E0S);
au_writel(SYS_CNTRL_E0 | SYS_CNTRL_EN0, SYS_COUNTER_CNTRL);
au_sync();
Index: arch/mips/dec/setup.c
===================================================================
RCS file: /home/cvs/linux/arch/mips/dec/setup.c,v
retrieving revision 1.41
diff -u -p -r1.41 setup.c
--- arch/mips/dec/setup.c 20 Aug 2004 09:19:01 -0000 1.41
+++ arch/mips/dec/setup.c 21 Nov 2004 16:14:03 -0000
@@ -48,11 +48,6 @@ extern irqreturn_t dec_intr_halt(int irq
extern asmlinkage void decstation_handle_int(void);
-#ifdef CONFIG_BLK_DEV_INITRD
-extern unsigned long initrd_start, initrd_end;
-extern void * __rd_start, * __rd_end;
-#endif
-
spinlock_t ioasic_ssr_lock;
volatile u32 *ioasic_base;
@@ -136,11 +131,6 @@ extern void dec_timer_setup(struct irqac
static void __init decstation_setup(void)
{
-#ifdef CONFIG_BLK_DEV_INITRD
- ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0);
- initrd_start = (unsigned long)&__rd_start;
- initrd_end = (unsigned long)&__rd_end;
-#endif
board_be_init = dec_be_init;
board_time_init = dec_time_init;
board_timer_setup = dec_timer_setup;
Index: arch/mips/dec/boot/decstation.c
===================================================================
RCS file: /home/cvs/linux/arch/mips/dec/boot/decstation.c,v
retrieving revision 1.2
diff -u -p -r1.2 decstation.c
--- arch/mips/dec/boot/decstation.c 4 Jun 2003 18:14:26 -0000 1.2
+++ arch/mips/dec/boot/decstation.c 21 Nov 2004 16:14:03 -0000
@@ -26,7 +26,6 @@
#define INITRD_SIZE (*(unsigned long *) (PARAM+0x21c))
extern int _ftext, _end; /* begin and end of kernel image */
-extern void *__rd_start, *__rd_end; /* begin and end of ramdisk image */
extern void kernel_entry(int, char **, unsigned long, int *);
void * memcpy(void * dest, const void *src, unsigned int count)
@@ -81,11 +80,5 @@ void dec_entry(int argc, char **argv,
rex_clear_cache();
}
-#ifdef CONFIG_BLK_DEV_INITRD
- LOADER_TYPE = 1;
- INITRD_START = (long)&__rd_start;
- INITRD_SIZE = (long)&__rd_end - (long)&__rd_start;
-#endif
-
kernel_entry(argc, argv, magic, prom_vec);
}
Index: arch/mips/jmr3927/rbhma3100/setup.c
===================================================================
RCS file: /home/cvs/linux/arch/mips/jmr3927/rbhma3100/setup.c,v
retrieving revision 1.14
diff -u -p -r1.14 setup.c
--- arch/mips/jmr3927/rbhma3100/setup.c 20 Aug 2004 11:29:06 -0000 1.14
+++ arch/mips/jmr3927/rbhma3100/setup.c 21 Nov 2004 16:14:03 -0000
@@ -184,10 +184,6 @@ unsigned long jmr3927_do_gettimeoffset(v
}
-#if defined(CONFIG_BLK_DEV_INITRD)
-extern unsigned long __rd_start, __rd_end, initrd_start, initrd_end;
-#endif
-
//#undef DO_WRITE_THROUGH
#define DO_WRITE_THROUGH
#define DO_ENABLE_CACHE
Index: arch/mips/kernel/setup.c
===================================================================
RCS file: /home/cvs/linux/arch/mips/kernel/setup.c,v
retrieving revision 1.171
diff -u -p -r1.171 setup.c
--- arch/mips/kernel/setup.c 28 Jun 2004 21:04:12 -0000 1.171
+++ arch/mips/kernel/setup.c 21 Nov 2004 16:14:03 -0000
@@ -56,8 +56,6 @@ unsigned int PCI_DMA_BUS_IS_PHYS;
EXPORT_SYMBOL(PCI_DMA_BUS_IS_PHYS);
-extern void * __rd_start, * __rd_end;
-
/*
* Setup information
*
@@ -194,6 +192,68 @@ static inline void parse_cmdline_early(v
}
}
+static inline int parse_rd_cmdline(unsigned long* rd_start, unsigned long* rd_end)
+{
+ /*
+ * "rd_start=0xNNNNNNNN" defines the memory address of an initrd
+ * "rd_size=0xNN" it's size
+ */
+ unsigned long start = 0;
+ unsigned long size = 0;
+ unsigned long end;
+ char cmd_line[CL_SIZE];
+ char *start_str;
+ char *size_str;
+ char *tmp;
+
+ strcpy(cmd_line, command_line);
+ *command_line = 0;
+ tmp = cmd_line;
+ /* Ignore "rd_start=" strings in other parameters. */
+ start_str = strstr(cmd_line, "rd_start=");
+ if (start_str && start_str != cmd_line && *(start_str - 1) != ' ')
+ start_str = strstr(start_str, " rd_start=");
+ while (start_str) {
+ if (start_str != cmd_line)
+ strncat(command_line, tmp, start_str - tmp);
+ start = memparse(start_str + 9, &start_str);
+ tmp = start_str + 1;
+ start_str = strstr(start_str, " rd_start=");
+ }
+ if (*tmp)
+ strcat(command_line, tmp);
+
+ strcpy(cmd_line, command_line);
+ *command_line = 0;
+ tmp = cmd_line;
+ /* Ignore "rd_size" strings in other parameters. */
+ size_str = strstr(cmd_line, "rd_size=");
+ if (size_str && size_str != cmd_line && *(size_str - 1) != ' ')
+ size_str = strstr(size_str, " rd_size=");
+ while (size_str) {
+ if (size_str != cmd_line)
+ strncat(command_line, tmp, size_str - tmp);
+ size = memparse(size_str + 8, &size_str);
+ tmp = size_str + 1;
+ size_str = strstr(size_str, " rd_size=");
+ }
+ if (*tmp)
+ strcat(command_line, tmp);
+
+#ifdef CONFIG_MIPS64
+ /* HACK: Guess if the sign extension was forgotten */
+ if (start > 0x0000000080000000 && start < 0x00000000ffffffff)
+ start |= 0xffffffff00000000;
+#endif
+
+ end = start + size;
+ if (start && end) {
+ *rd_start = start;
+ *rd_end = end;
+ return 1;
+ }
+ return 0;
+}
#define PFN_UP(x) (((x) + PAGE_SIZE - 1) >> PAGE_SHIFT)
#define PFN_DOWN(x) ((x) >> PAGE_SHIFT)
@@ -205,30 +265,42 @@ static inline void parse_cmdline_early(v
static inline void bootmem_init(void)
{
unsigned long start_pfn;
+ unsigned long reserved_end = (unsigned long)&_end;
#ifndef CONFIG_SGI_IP27
- unsigned long bootmap_size, max_low_pfn, first_usable_pfn;
+ unsigned long first_usable_pfn;
+ unsigned long bootmap_size;
int i;
#endif
#ifdef CONFIG_BLK_DEV_INITRD
- unsigned long tmp;
- unsigned long *initrd_header;
+ int initrd_reserve_bootmem = 0;
- tmp = (((unsigned long)&_end + PAGE_SIZE-1) & PAGE_MASK) - 8;
- if (tmp < (unsigned long)&_end)
- tmp += PAGE_SIZE;
- initrd_header = (unsigned long *)tmp;
- if (initrd_header[0] == 0x494E5244) {
- initrd_start = (unsigned long)&initrd_header[2];
- initrd_end = initrd_start + initrd_header[1];
+ /* Board specific code should have set up initrd_start and initrd_end */
+ ROOT_DEV = Root_RAM0;
+ if (parse_rd_cmdline(&initrd_start, &initrd_end)) {
+ reserved_end = max(reserved_end, initrd_end);
+ initrd_reserve_bootmem = 1;
+ } else {
+ unsigned long tmp;
+ unsigned long *initrd_header;
+
+ tmp = ((reserved_end + PAGE_SIZE-1) & PAGE_MASK) - 8;
+ if (tmp < reserved_end)
+ tmp += PAGE_SIZE;
+ initrd_header = (unsigned long *)tmp;
+ if (initrd_header[0] == 0x494E5244) {
+ initrd_start = (unsigned long)&initrd_header[2];
+ initrd_end = initrd_start + initrd_header[1];
+ reserved_end = max(reserved_end, initrd_end);
+ initrd_reserve_bootmem = 1;
+ }
}
- start_pfn = PFN_UP(CPHYSADDR((&_end)+(initrd_end - initrd_start) + PAGE_SIZE));
-#else
+#endif /* CONFIG_BLK_DEV_INITRD */
+
/*
* Partially used pages are not usable - thus
* we are rounding upwards.
*/
- start_pfn = PFN_UP(CPHYSADDR(&_end));
-#endif /* CONFIG_BLK_DEV_INITRD */
+ start_pfn = PFN_UP(CPHYSADDR(reserved_end));
#ifndef CONFIG_SGI_IP27
/* Find the highest page frame number we have available. */
@@ -341,21 +413,14 @@ static inline void bootmem_init(void)
/* Reserve the bootmap memory. */
reserve_bootmem(PFN_PHYS(first_usable_pfn), bootmap_size);
-#endif
+#endif /* CONFIG_SGI_IP27 */
#ifdef CONFIG_BLK_DEV_INITRD
- /* Board specific code should have set up initrd_start and initrd_end */
- ROOT_DEV = Root_RAM0;
- if (&__rd_start != &__rd_end) {
- initrd_start = (unsigned long)&__rd_start;
- initrd_end = (unsigned long)&__rd_end;
- }
initrd_below_start_ok = 1;
if (initrd_start) {
unsigned long initrd_size = ((unsigned char *)initrd_end) - ((unsigned char *)initrd_start);
printk("Initial ramdisk at: 0x%p (%lu bytes)\n",
- (void *)initrd_start,
- initrd_size);
+ (void *)initrd_start, initrd_size);
if (CPHYSADDR(initrd_end) > PFN_PHYS(max_low_pfn)) {
printk("initrd extends beyond end of memory "
@@ -363,7 +428,11 @@ static inline void bootmem_init(void)
sizeof(long) * 2, CPHYSADDR(initrd_end),
sizeof(long) * 2, PFN_PHYS(max_low_pfn));
initrd_start = initrd_end = 0;
+ initrd_reserve_bootmem = 0;
}
+
+ if (initrd_reserve_bootmem)
+ reserve_bootmem(CPHYSADDR(initrd_start), initrd_size);
}
#endif /* CONFIG_BLK_DEV_INITRD */
}
Index: arch/mips/sibyte/cfe/setup.c
===================================================================
RCS file: /home/cvs/linux/arch/mips/sibyte/cfe/setup.c,v
retrieving revision 1.19
diff -u -p -r1.19 setup.c
--- arch/mips/sibyte/cfe/setup.c 21 Nov 2004 13:50:35 -0000 1.19
+++ arch/mips/sibyte/cfe/setup.c 21 Nov 2004 16:14:04 -0000
@@ -56,7 +56,6 @@ int cfe_cons_handle;
#ifdef CONFIG_BLK_DEV_INITRD
extern unsigned long initrd_start, initrd_end;
-extern void * __rd_start, * __rd_end;
#endif
#ifdef CONFIG_KGDB
Index: arch/mips/sibyte/swarm/setup.c
===================================================================
RCS file: /home/cvs/linux/arch/mips/sibyte/swarm/setup.c,v
retrieving revision 1.32
diff -u -p -r1.32 setup.c
--- arch/mips/sibyte/swarm/setup.c 14 Sep 2004 21:23:33 -0000 1.32
+++ arch/mips/sibyte/swarm/setup.c 21 Nov 2004 16:14:04 -0000
@@ -52,10 +52,6 @@ extern int m41t81_probe(void);
extern int m41t81_set_time(unsigned long);
extern unsigned long m41t81_get_time(void);
-#ifdef CONFIG_BLK_DEV_INITRD
-extern void * __rd_start, * __rd_end;
-#endif
-
const char *get_system_type(void)
{
return "SiByte " SIBYTE_BOARD_NAME;
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH] Improve ramdisk support
2004-11-21 16:20 ` Thiemo Seufer
@ 2004-11-21 19:32 ` Ralf Baechle
0 siblings, 0 replies; 3+ messages in thread
From: Ralf Baechle @ 2004-11-21 19:32 UTC (permalink / raw)
To: Thiemo Seufer; +Cc: linux-mips
On Sun, Nov 21, 2004 at 05:20:54PM +0100, Thiemo Seufer wrote:
> CONFIG_EMBEDDED_RAMDISK is gone now. The updated patch below removes
> some leftovers.
Thanks for updating your patch so quickly.
Ralf
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2004-11-21 19:34 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-11-21 3:06 [PATCH] Improve ramdisk support Thiemo Seufer
2004-11-21 16:20 ` Thiemo Seufer
2004-11-21 19:32 ` Ralf Baechle
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox