Index: kernel/arch/amd64/include/arch.h
===================================================================
--- kernel/arch/amd64/include/arch.h	(revision c22e964a598c0c20654391f6a11e7333830cbf37)
+++ kernel/arch/amd64/include/arch.h	(revision 5d8d71ebf89df6dbc2bd7f5a55aa3d4c73a286cd)
@@ -36,4 +36,8 @@
 #define KERN_amd64_ARCH_H_
 
+#include <genarch/multiboot/multiboot.h>
+
+extern void arch_pre_main(uint32_t, const multiboot_info_t *);
+
 #endif
 
Index: kernel/arch/amd64/include/boot/boot.h
===================================================================
--- kernel/arch/amd64/include/boot/boot.h	(revision c22e964a598c0c20654391f6a11e7333830cbf37)
+++ kernel/arch/amd64/include/boot/boot.h	(revision 5d8d71ebf89df6dbc2bd7f5a55aa3d4c73a286cd)
@@ -43,5 +43,14 @@
 #define MULTIBOOT_HEADER_FLAGS	0x00010003
 
-#define MULTIBOOT_LOADER_MAGIC	0x2BADB002
+#ifndef __ASM__
+
+#ifdef CONFIG_SMP
+
+/* This is only a symbol so the type is dummy. Obtain the value using &. */
+extern int _hardcoded_unmapped_size;
+
+#endif /* CONFIG_SMP */
+
+#endif /* __ASM__ */
 
 #endif
Index: kernel/arch/amd64/src/amd64.c
===================================================================
--- kernel/arch/amd64/src/amd64.c	(revision c22e964a598c0c20654391f6a11e7333830cbf37)
+++ kernel/arch/amd64/src/amd64.c	(revision 5d8d71ebf89df6dbc2bd7f5a55aa3d4c73a286cd)
@@ -40,4 +40,5 @@
 
 #include <proc/thread.h>
+#include <genarch/multiboot/multiboot.h>
 #include <genarch/drivers/legacy/ia32/io.h>
 #include <genarch/drivers/ega/ega.h>
@@ -46,4 +47,5 @@
 #include <arch/drivers/i8254.h>
 #include <arch/drivers/i8259.h>
+#include <arch/boot/boot.h>
 
 #ifdef CONFIG_SMP
@@ -66,5 +68,4 @@
 #include <sysinfo/sysinfo.h>
 
-
 /** Disable I/O on non-privileged levels
  *
@@ -95,4 +96,21 @@
 		::: "%rax"
 	);
+}
+
+/** Perform amd64-specific initialization before main_bsp() is called.
+ *
+ * @param signature Should contain the multiboot signature.
+ * @param mi        Pointer to the multiboot information structure.
+ */
+void arch_pre_main(uint32_t signature, const multiboot_info_t *mi)
+{
+	/* Parse multiboot information obtained from the bootloader. */
+	multiboot_info_parse(signature, mi);
+	
+#ifdef CONFIG_SMP
+	/* Copy AP bootstrap routines below 1 MB. */
+	memcpy((void *) AP_BOOT_OFFSET, (void *) BOOT_OFFSET,
+	    (size_t) &_hardcoded_unmapped_size);
+#endif
 }
 
Index: kernel/arch/amd64/src/boot/boot.S
===================================================================
--- kernel/arch/amd64/src/boot/boot.S	(revision c22e964a598c0c20654391f6a11e7333830cbf37)
+++ kernel/arch/amd64/src/boot/boot.S	(revision 5d8d71ebf89df6dbc2bd7f5a55aa3d4c73a286cd)
@@ -176,116 +176,15 @@
 start64:
 	movq $(PA2KA(START_STACK)), %rsp
-	movl grub_eax, %eax
-	movl grub_ebx, %ebx
-	
-	cmpl $MULTIBOOT_LOADER_MAGIC, %eax			# compare GRUB signature
-	je valid_boot
-		
-		xorl %ecx, %ecx					# no memory size or map available
-		movl %ecx, e820counter
-		
-		jmp invalid_boot
-		
-	valid_boot:
-		
-		movl (%ebx), %eax				# ebx = physical address of struct multiboot_info
-		
-		bt $3, %eax					# mbi->flags[3] (mods_count, mods_addr valid)
-		jc mods_valid
-			
-			xorq %rcx, %rcx
-			movq %rcx, init
-			jmp mods_end
-		
-		mods_valid:
-		
-		xorq %rcx, %rcx
-		movl 20(%ebx), %ecx				# mbi->mods_count
-		movq %rcx, init
-		
-		cmpl $0, %ecx
-		je mods_end
-		
-		movl 24(%ebx), %esi				# mbi->mods_addr
-		movq $init, %rdi
-		
-		mods_loop:
-			
-			xorq %rdx, %rdx
-			movl 0(%esi), %edx			# mods->mod_start
-			movq $0xffff800000000000, %r10
-			addq %r10, %rdx
-			movq %rdx, 8(%rdi)
-			
-			xorq %rdx, %rdx
-			movl 4(%esi), %edx
-			subl 0(%esi), %edx			# mods->mod_end - mods->mod_start
-			movq %rdx, 16(%rdi)
-			
-			addl $16, %esi
-			addq $48, %rdi
-			
-			loop mods_loop
-			
-		mods_end:
-		
-		bt $6, %eax					# mbi->flags[6] (mmap_length, mmap_addr valid)	
-		jc mmap_valid
-			
-			xorl %edx, %edx
-			jmp mmap_invalid
-			
-		mmap_valid:
-		movl 44(%ebx), %ecx				# mbi->mmap_length
-		movl 48(%ebx), %esi				# mbi->mmap_addr
-		movq $e820table, %rdi
-		xorl %edx, %edx
-		
-		mmap_loop:
-			cmpl $0, %ecx
-			jle mmap_end
-			
-			movl 4(%esi), %eax			# mmap->base_addr_low
-			movl %eax, (%rdi)
-			
-			movl 8(%esi), %eax			# mmap->base_addr_high
-			movl %eax, 4(%rdi)
-			
-			movl 12(%esi), %eax			# mmap->length_low
-			movl %eax, 8(%rdi)
-			
-			movl 16(%esi), %eax			# mmap->length_high
-			movl %eax, 12(%rdi)
-			
-			movl 20(%esi), %eax			# mmap->type
-			movl %eax, 16(%rdi)
-			
-			movl (%esi), %eax			# mmap->size
-			addl $0x4, %eax
-			addl %eax, %esi
-			subl %eax, %ecx
-			addq $MEMMAP_E820_RECORD_SIZE, %rdi
-			incl %edx
-			jmp mmap_loop
-		
-		mmap_end:
-		
-		mmap_invalid:
-		movl %edx, e820counter
-		
-	invalid_boot:
-	
-#ifdef CONFIG_SMP
-	
-	# copy AP bootstrap routines below 1 MB
-	
-	movq $BOOT_OFFSET, %rsi
-	movq $AP_BOOT_OFFSET, %rdi
-	movq $_hardcoded_unmapped_size, %rcx
-	rep movsb
-	
-#endif
-	
-	call main_bsp   # never returns
+
+	# arch_pre_main(grub_eax, grub_ebx)
+	xorq %rdi, %rdi
+	movl grub_eax, %edi
+	xorq %rsi, %rsi
+	movl grub_ebx, %esi
+	call arch_pre_main
+
+	call main_bsp  
+
+	# Not reached.
 	
 	cli
Index: kernel/arch/ia32/include/arch.h
===================================================================
--- kernel/arch/ia32/include/arch.h	(revision c22e964a598c0c20654391f6a11e7333830cbf37)
+++ kernel/arch/ia32/include/arch.h	(revision 5d8d71ebf89df6dbc2bd7f5a55aa3d4c73a286cd)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2005 Martin Decky
+ * Copyright (c) 2009 Martin Decky
  * All rights reserved.
  *
@@ -36,7 +36,7 @@
 #define KERN_ia32_ARCH_H_
 
-#include <arch/boot/multiboot.h>
+#include <genarch/multiboot/multiboot.h>
 
-extern void arch_pre_main(uint32_t signature, const mb_info_t *mi);
+extern void arch_pre_main(uint32_t, const multiboot_info_t *);
 
 #endif
Index: kernel/arch/ia32/include/boot/boot.h
===================================================================
--- kernel/arch/ia32/include/boot/boot.h	(revision c22e964a598c0c20654391f6a11e7333830cbf37)
+++ kernel/arch/ia32/include/boot/boot.h	(revision 5d8d71ebf89df6dbc2bd7f5a55aa3d4c73a286cd)
@@ -43,10 +43,9 @@
 #define MULTIBOOT_HEADER_FLAGS  0x00010003
 
-#define MULTIBOOT_LOADER_MAGIC  0x2BADB002
-
 #ifndef __ASM__
 
 #ifdef CONFIG_SMP
 
+/* This is only a symbol so the type is dummy. Obtain the value using &. */
 extern int _hardcoded_unmapped_size;
 
Index: kernel/arch/ia32/include/boot/multiboot.h
===================================================================
--- kernel/arch/ia32/include/boot/multiboot.h	(revision c22e964a598c0c20654391f6a11e7333830cbf37)
+++ 	(revision )
@@ -1,90 +1,0 @@
-/*
- * Copyright (c) 2005 Martin Decky
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup ia32
- * @{
- */
-/** @file
- */
-
-#ifndef KERN_ia32_MULTIBOOT_H__
-#define KERN_ia32_MULTIBOOT_H_
-
-#include <arch/types.h>
-#include <arch/boot/memmap.h>
-
-/** Multiboot mod structure */
-typedef struct {
-	uintptr_t start;
-	uintptr_t end;
-	char *string;
-	uint32_t reserved;
-} __attribute__ ((packed)) mb_mod_t;
-
-/** Multiboot mmap structure */
-typedef struct {
-	uint32_t size;
-	e820memmap_t mm_info;
-} __attribute__ ((packed)) mb_mmap_t;
-
-/** Multiboot information structure */
-typedef struct {
-	uint32_t flags;
-	uintptr_t mem_lower;
-	uintptr_t mem_upper;
-	
-	uint32_t boot_device;
-	char *cmdline;
-	
-	uint32_t mods_count;
-	mb_mod_t *mods_addr;
-	
-	uint32_t syms[4];
-	
-	uint32_t mmap_length;
-	mb_mmap_t *mmap_addr;
-	
-	/* ... */
-} __attribute__ ((packed)) mb_info_t;
-
-enum mb_info_flags {
-	MBINFO_FLAGS_MEM     = 0x01,
-	MBINFO_FLAGS_BOOT    = 0x02,
-	MBINFO_FLAGS_CMDLINE = 0x04,
-	MBINFO_FLAGS_MODS    = 0x08,
-	MBINFO_FLAGS_SYMS1   = 0x10,
-	MBINFO_FLAGS_SYMS2   = 0x20,
-	MBINFO_FLAGS_MMAP    = 0x40
-	
-	/* ... */
-};
-
-#endif
-
-/** @}
- */
Index: kernel/arch/ia32/src/ia32.c
===================================================================
--- kernel/arch/ia32/src/ia32.c	(revision c22e964a598c0c20654391f6a11e7333830cbf37)
+++ kernel/arch/ia32/src/ia32.c	(revision 5d8d71ebf89df6dbc2bd7f5a55aa3d4c73a286cd)
@@ -41,4 +41,5 @@
 #include <arch/pm.h>
 
+#include <genarch/multiboot/multiboot.h>
 #include <genarch/drivers/legacy/ia32/io.h>
 #include <genarch/drivers/ega/ega.h>
@@ -67,6 +68,4 @@
 #include <sysinfo/sysinfo.h>
 #include <arch/boot/boot.h>
-#include <string.h>
-#include <macros.h>
 
 #ifdef CONFIG_SMP
@@ -74,104 +73,13 @@
 #endif
 
-/** Extract command name from the multiboot module command line.
- *
- * @param buf      Destination buffer (will always null-terminate).
- * @param n        Size of destination buffer.
- * @param cmd_line Input string (the command line).
- *
- */
-static void extract_command(char *buf, size_t n, const char *cmd_line)
-{
-	const char *start, *end, *cp;
-	size_t max_len;
-	
-	/* Find the first space. */
-	end = strchr(cmd_line, ' ');
-	if (end == NULL)
-		end = cmd_line + strlen(cmd_line);
-	
-	/*
-	 * Find last occurence of '/' before 'end'. If found, place start at
-	 * next character. Otherwise, place start at beginning of buffer.
-	 */
-	cp = end;
-	start = buf;
-	while (cp != start) {
-		if (*cp == '/') {
-			start = cp + 1;
-			break;
-		}
-		--cp;
-	}
-	
-	/* Copy the command and null-terminate the string. */
-	max_len = min(n - 1, (size_t) (end - start));
-	strncpy(buf, start, max_len + 1);
-	buf[max_len] = '\0';
-}
-
-/** C part of ia32 boot sequence.
+/** Perform ia32-specific initialization before main_bsp() is called.
  *
  * @param signature Should contain the multiboot signature.
  * @param mi        Pointer to the multiboot information structure.
  */
-void arch_pre_main(uint32_t signature, const mb_info_t *mi)
-{
-	uint32_t flags;
-	mb_mod_t *mods;
-	uint32_t i;
-	
-	if (signature == MULTIBOOT_LOADER_MAGIC)
-		flags = mi->flags;
-	else {
-		/* No multiboot info available. */
-		flags = 0;
-	}
-	
-	/* Copy module information. */
-	
-	if ((flags & MBINFO_FLAGS_MODS) != 0) {
-		init.cnt = mi->mods_count;
-		mods = mi->mods_addr;
-		
-		for (i = 0; i < init.cnt; i++) {
-			init.tasks[i].addr = mods[i].start + 0x80000000;
-			init.tasks[i].size = mods[i].end - mods[i].start;
-			
-			/* Copy command line, if available. */
-			if (mods[i].string) {
-				extract_command(init.tasks[i].name,
-				    CONFIG_TASK_NAME_BUFLEN,
-				    mods[i].string);
-			} else
-				init.tasks[i].name[0] = '\0';
-		}
-	} else
-		init.cnt = 0;
-	
-	/* Copy memory map. */
-	
-	int32_t mmap_length;
-	mb_mmap_t *mme;
-	uint32_t size;
-	
-	if ((flags & MBINFO_FLAGS_MMAP) != 0) {
-		mmap_length = mi->mmap_length;
-		mme = mi->mmap_addr;
-		e820counter = 0;
-		
-		i = 0;
-		while (mmap_length > 0) {
-			e820table[i++] = mme->mm_info;
-			
-			/* Compute address of next structure. */
-			size = sizeof(mme->size) + mme->size;
-			mme = ((void *) mme) + size;
-			mmap_length -= size;
-		}
-		
-		e820counter = i;
-	} else
-		e820counter = 0;
+void arch_pre_main(uint32_t signature, const multiboot_info_t *mi)
+{
+	/* Parse multiboot information obtained from the bootloader. */
+	multiboot_info_parse(signature, mi);	
 	
 #ifdef CONFIG_SMP
Index: kernel/genarch/Makefile.inc
===================================================================
--- kernel/genarch/Makefile.inc	(revision c22e964a598c0c20654391f6a11e7333830cbf37)
+++ kernel/genarch/Makefile.inc	(revision 5d8d71ebf89df6dbc2bd7f5a55aa3d4c73a286cd)
@@ -102,4 +102,9 @@
 endif
 
+ifeq ($(CONFIG_MULTIBOOT), y)
+	GENARCH_SOURCES += \
+		genarch/src/multiboot/multiboot.c
+endif
+
 ifeq ($(CONFIG_EGA), y)
 	GENARCH_SOURCES += \
Index: kernel/genarch/include/multiboot/multiboot.h
===================================================================
--- kernel/genarch/include/multiboot/multiboot.h	(revision 5d8d71ebf89df6dbc2bd7f5a55aa3d4c73a286cd)
+++ kernel/genarch/include/multiboot/multiboot.h	(revision 5d8d71ebf89df6dbc2bd7f5a55aa3d4c73a286cd)
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2009 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup genarch
+ * @{
+ */
+/** @file
+ */
+
+#ifndef KERN_MULTIBOOT_H_
+#define KERN_MULTIBOOT_H_
+
+#include <arch/types.h>
+#include <arch/boot/memmap.h>
+
+/** Multiboot 32-bit address. */
+typedef uint32_t mbaddr_t;
+
+/** Multiboot mod structure */
+typedef struct {
+	mbaddr_t start;
+	mbaddr_t end;
+	mbaddr_t string;
+	uint32_t reserved;
+} __attribute__ ((packed)) multiboot_mod_t;
+
+/** Multiboot mmap structure */
+typedef struct {
+	uint32_t size;
+	e820memmap_t mm_info;
+} __attribute__ ((packed)) multiboot_mmap_t;
+
+/** Multiboot information structure */
+typedef struct {
+	uint32_t flags;
+	uint32_t mem_lower;
+	uint32_t mem_upper;
+	
+	uint32_t boot_device;
+	uint32_t cmdline;
+	
+	uint32_t mods_count;
+	mbaddr_t mods_addr;
+	
+	uint32_t syms[4];
+	
+	uint32_t mmap_length;
+	mbaddr_t mmap_addr;
+	
+	/* ... */
+} __attribute__ ((packed)) multiboot_info_t;
+
+enum multiboot_info_flags {
+	MBINFO_FLAGS_MEM     = 0x01,
+	MBINFO_FLAGS_BOOT    = 0x02,
+	MBINFO_FLAGS_CMDLINE = 0x04,
+	MBINFO_FLAGS_MODS    = 0x08,
+	MBINFO_FLAGS_SYMS1   = 0x10,
+	MBINFO_FLAGS_SYMS2   = 0x20,
+	MBINFO_FLAGS_MMAP    = 0x40
+	
+	/* ... */
+};
+
+#define MULTIBOOT_LOADER_MAGIC  0x2BADB002
+
+/** Convert 32-bit multiboot address to a pointer. */
+#define MULTIBOOT_PTR(mba) ((void *)(uintptr_t) (mba))
+
+extern void multiboot_info_parse(uint32_t, const multiboot_info_t *);
+
+#endif
+
+/** @}
+ */
Index: kernel/genarch/src/multiboot/multiboot.c
===================================================================
--- kernel/genarch/src/multiboot/multiboot.c	(revision 5d8d71ebf89df6dbc2bd7f5a55aa3d4c73a286cd)
+++ kernel/genarch/src/multiboot/multiboot.c	(revision 5d8d71ebf89df6dbc2bd7f5a55aa3d4c73a286cd)
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2009 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup genarch
+ * @{
+ */
+/** @file
+ */
+
+#include <genarch/multiboot/multiboot.h>
+#include <arch/types.h>
+#include <typedefs.h>
+#include <config.h>
+#include <string.h>
+#include <macros.h>
+
+/** Extract command name from the multiboot module command line.
+ *
+ * @param buf      Destination buffer (will always null-terminate).
+ * @param n        Size of destination buffer.
+ * @param cmd_line Input string (the command line).
+ *
+ */
+static void extract_command(char *buf, size_t n, const char *cmd_line)
+{
+	const char *start, *end, *cp;
+	size_t max_len;
+	
+	/* Find the first space. */
+	end = strchr(cmd_line, ' ');
+	if (end == NULL)
+		end = cmd_line + strlen(cmd_line);
+	
+	/*
+	 * Find last occurence of '/' before 'end'. If found, place start at
+	 * next character. Otherwise, place start at beginning of buffer.
+	 */
+	cp = end;
+	start = buf;
+	while (cp != start) {
+		if (*cp == '/') {
+			start = cp + 1;
+			break;
+		}
+		--cp;
+	}
+	
+	/* Copy the command and null-terminate the string. */
+	max_len = min(n - 1, (size_t) (end - start));
+	strncpy(buf, start, max_len + 1);
+	buf[max_len] = '\0';
+}
+
+/** Parse multiboot information structure.
+ *
+ * If @a signature does not contain a valid multiboot signature,
+ * assumes no multiboot information is available.
+ *
+ * @param signature Should contain the multiboot signature.
+ * @param mi        Pointer to the multiboot information structure.
+ */
+void multiboot_info_parse(uint32_t signature, const multiboot_info_t *mi)
+{
+	uint32_t flags;
+	multiboot_mod_t *mods;
+	uint32_t i;
+	
+	if (signature == MULTIBOOT_LOADER_MAGIC)
+		flags = mi->flags;
+	else {
+		/* No multiboot info available. */
+		flags = 0;
+	}
+	
+	/* Copy module information. */
+	
+	if ((flags & MBINFO_FLAGS_MODS) != 0) {
+		init.cnt = mi->mods_count;
+		mods = (multiboot_mod_t *) MULTIBOOT_PTR(mi->mods_addr);
+		
+		for (i = 0; i < init.cnt; i++) {
+			init.tasks[i].addr = PA2KA(mods[i].start);
+			init.tasks[i].size = mods[i].end - mods[i].start;
+			
+			/* Copy command line, if available. */
+			if (mods[i].string) {
+				extract_command(init.tasks[i].name,
+				    CONFIG_TASK_NAME_BUFLEN,
+				    MULTIBOOT_PTR(mods[i].string));
+			} else
+				init.tasks[i].name[0] = '\0';
+		}
+	} else
+		init.cnt = 0;
+	
+	/* Copy memory map. */
+	
+	int32_t mmap_length;
+	multiboot_mmap_t *mme;
+	uint32_t size;
+	
+	if ((flags & MBINFO_FLAGS_MMAP) != 0) {
+		mmap_length = mi->mmap_length;
+		mme = MULTIBOOT_PTR(mi->mmap_addr);
+		e820counter = 0;
+		
+		i = 0;
+		while (mmap_length > 0) {
+			e820table[i++] = mme->mm_info;
+			
+			/* Compute address of next structure. */
+			size = sizeof(mme->size) + mme->size;
+			mme = ((void *) mme) + size;
+			mmap_length -= size;
+		}
+		
+		e820counter = i;
+	} else
+		e820counter = 0;
+}
+
+/** @}
+ */
