Index: arch/ppc32/Makefile.inc
===================================================================
--- arch/ppc32/Makefile.inc	(revision a62347a99f0c39a8befc49032525a31fbb841467)
+++ arch/ppc32/Makefile.inc	(revision 3eee37ddabc214eeb234269114c36548c82f7e4d)
@@ -30,9 +30,9 @@
 
 image.boot: kernel uspace
-	make -C arch/$(ARCH)/loader COMPILER=$(COMPILER) KERNEL=../../../$(KERNELDIR)/kernel.bin INIT=../../../$(USPACEDIR)/init/init
+	make -C arch/$(ARCH)/loader COMPILER=$(COMPILER) KERNELDIR=../../../$(KERNELDIR) USPACEDIR=../../../$(USPACEDIR)
 	cp arch/$(ARCH)/loader/image.boot image.boot
 
 clean: clean_kernel clean_uspace
-	make -C arch/$(ARCH)/loader clean
+	make -C arch/$(ARCH)/loader clean KERNELDIR=../../../$(KERNELDIR) USPACEDIR=../../../$(USPACEDIR)
 	-rm -f image.boot
 
Index: arch/ppc32/loader/Makefile
===================================================================
--- arch/ppc32/loader/Makefile	(revision a62347a99f0c39a8befc49032525a31fbb841467)
+++ arch/ppc32/loader/Makefile	(revision 3eee37ddabc214eeb234269114c36548c82f7e4d)
@@ -57,5 +57,12 @@
 	boot.S
 
+COMPONENTS = \
+	$(KERNELDIR)/kernel.bin \
+	$(USPACEDIR)/ns/ns \
+	$(USPACEDIR)/init/init \
+	$(USPACEDIR)/fb/fb
+
 OBJECTS := $(addsuffix .o,$(basename $(SOURCES)))
+COMPONENT_OBJECTS := $(addsuffix .o,$(basename $(notdir $(COMPONENTS))))
 
 .PHONY: all clean depend
@@ -65,6 +72,6 @@
 -include Makefile.depend
 
-image.boot: depend $(OBJECTS) kernel.o init.o
-	$(LD) -no-check-sections -N -T _link.ld $(OBJECTS) kernel.o init.o -o $@
+image.boot: depend _components.h _link.ld $(COMPONENT_OBJECTS) $(OBJECTS) kernel.o 
+	$(LD) -no-check-sections -N -T _link.ld $(COMPONENT_OBJECTS) $(OBJECTS) -o $@
 
 depend:
@@ -72,11 +79,8 @@
 
 clean:
-	-rm -f $(OBJECTS) image.boot kernel.o init.o Makefile.depend
+	-rm -f _components.h _link.ld $(COMPONENT_OBJECTS) $(OBJECTS) image.boot Makefile.depend
 
-kernel.o: $(KERNEL)
-	$(OBJCOPY) -I binary -O elf32-powerpc -B powerpc:common --rename-section .data=.kernel_image $(KERNEL) $@
-
-init.o: $(INIT)
-	$(OBJCOPY) -I binary -O elf32-powerpc -B powerpc:common --rename-section .data=.init_image $(INIT) $@
+_components.h _link.ld $(COMPONENT_OBJECTS): $(COMPONENTS)
+	./pack $(OBJCOPY) $(COMPONENTS)
 
 %.o: %.S
Index: ch/ppc32/loader/_link.ld
===================================================================
--- arch/ppc32/loader/_link.ld	(revision a62347a99f0c39a8befc49032525a31fbb841467)
+++ 	(revision )
@@ -1,31 +1,0 @@
-/*
- *  PPC linker script
- *
- */
-
-OUTPUT_FORMAT("elf32-powerpc")
-OUTPUT_ARCH(powerpc:common)
-ENTRY(start)
-
-SECTIONS {
-	.boot 0x10000000: AT (0) { 
-		*(BOOTSTRAP);
-		*(REALMODE);
-		*(.text);
-		
-		*(.rodata);
-		*(.rodata.*);
-		*(.data);		/* initialized data */
-		*(.sdata);
-		*(.sdata2);
-		*(.sbss);
-		*(.bss);		/* uninitialized static variables */	
-		*(COMMON); 		/* global variables */
-		
-		. = ALIGN(4096);
-		*(.kernel_image);
-		
-		. = ALIGN(4096);
-		*(.init_image);
-	}
-}
Index: arch/ppc32/loader/main.c
===================================================================
--- arch/ppc32/loader/main.c	(revision a62347a99f0c39a8befc49032525a31fbb841467)
+++ arch/ppc32/loader/main.c	(revision 3eee37ddabc214eeb234269114c36548c82f7e4d)
@@ -30,12 +30,5 @@
 #include "printf.h"
 #include "asm.h"
-
-#define KERNEL_START ((void *) &_binary_____________kernel_kernel_bin_start)
-#define KERNEL_END ((void *) &_binary_____________kernel_kernel_bin_end)
-#define KERNEL_SIZE ((unsigned int) KERNEL_END - (unsigned int) KERNEL_START)
-
-#define INIT_START ((void *) &_binary_____________uspace_init_init_start)
-#define INIT_END ((void *) &_binary_____________uspace_init_init_end)
-#define INIT_SIZE ((unsigned int) INIT_END - (unsigned int) INIT_START)
+#include "_components.h"
 
 #define HEAP_GAP 1024000
@@ -83,21 +76,26 @@
 	printf("\nHelenOS PPC Bootloader\n");
 	
-	check_align(KERNEL_START, "Kernel image");
-	check_align(INIT_START, "Init image");
-	check_align(&real_mode, "Bootstrap trampoline");
-	check_align(&trans, "Translation table");
+	init_components();
+	
+	unsigned int i;
+	
+	for (i = 0; i < COMPONENTS; i++)
+		check_align(components[i].start, components[i].name);
+	
+	check_align(&real_mode, "bootstrap trampoline");
+	check_align(&trans, "translation table");
 	
 	if (!ofw_memmap(&bootinfo.memmap)) {
-		printf("Error: Unable to get memory map, halting.\n");
+		printf("Error: unable to get memory map, halting.\n");
 		halt();
 	}
 	
 	if (bootinfo.memmap.total == 0) {
-		printf("Error: No memory detected, halting.\n");
+		printf("Error: no memory detected, halting.\n");
 		halt();
 	}
 	
 	if (!ofw_screen(&bootinfo.screen)) {
-		printf("Error: Unable to get screen properties, halting.\n");
+		printf("Error: unable to get screen properties, halting.\n");
 		halt();
 	}
@@ -112,37 +110,46 @@
 	
 	printf("\nMemory statistics (total %d MB)\n", bootinfo.memmap.total >> 20);
-	printf(" kernel image         at %L (size %d bytes)\n", KERNEL_START, KERNEL_SIZE);
-	printf(" init image           at %L (size %d bytes)\n", INIT_START, INIT_SIZE);
-	printf(" boot info structure  at %L (physical %L)\n", &bootinfo, bootinfo_pa);
-	printf(" bootstrap trampoline at %L (physical %L)\n", &real_mode, real_mode_pa);
-	printf(" translation table    at %L (physical %L)\n", &trans, trans_pa);
+	printf(" %L: boot info structure (physical %L)\n", &bootinfo, bootinfo_pa);
+	printf(" %L: bootstrap trampoline (physical %L)\n", &real_mode, real_mode_pa);
+	printf(" %L: translation table (physical %L)\n", &trans, trans_pa);
+	for (i = 0; i < COMPONENTS; i++)
+		printf(" %L: %s image (size %d bytes)\n", components[i].start, components[i].name, components[i].size);
 	
-	unsigned int top = ALIGN_UP(KERNEL_SIZE, PAGE_SIZE) + ALIGN_UP(INIT_SIZE, PAGE_SIZE);
-	unsigned int kernel_pages = ALIGN_UP(KERNEL_SIZE, PAGE_SIZE) >> PAGE_WIDTH;
-	unsigned int init_pages = ALIGN_UP(INIT_SIZE, PAGE_SIZE) >> PAGE_WIDTH;
+	unsigned int top = 0;
+	for (i = 0; i < COMPONENTS; i++)
+		top += ALIGN_UP(components[i].size, PAGE_SIZE);
 	
-	unsigned int i;
+	unsigned int pages = ALIGN_UP(KERNEL_SIZE, PAGE_SIZE) >> PAGE_WIDTH;
 	
-	for (i = 0; i < kernel_pages; i++) {
+	for (i = 0; i < pages; i++) {
 		void *pa = ofw_translate(KERNEL_START + (i << PAGE_WIDTH));
-		fix_overlap(KERNEL_START + (i << PAGE_WIDTH), &pa, "Kernel image", &top);
+		fix_overlap(KERNEL_START + (i << PAGE_WIDTH), &pa, "kernel", &top);
 		trans[i] = pa;
 	}
 	
-	for (i = 0; i < init_pages; i++) {
-		void *pa = ofw_translate(INIT_START + (i << PAGE_WIDTH));
-		fix_overlap(INIT_START + (i << PAGE_WIDTH), &pa, "Init image", &top);
-		trans[kernel_pages + i] = pa;
-		if (i == 0) {
-			bootinfo.init.addr = (void *) ((kernel_pages + i) << PAGE_WIDTH);
-			bootinfo.init.size = INIT_SIZE;
+	bootinfo.taskmap.count = 0;
+	for (i = 1; i < COMPONENTS; i++) {
+		unsigned int component_pages = ALIGN_UP(components[i].size, PAGE_SIZE) >> PAGE_WIDTH;
+		unsigned int j;
+		
+		for (j = 0; j < component_pages; j++) {
+			void *pa = ofw_translate(components[i].start + (j << PAGE_WIDTH));
+			fix_overlap(components[i].start + (j << PAGE_WIDTH), &pa, components[i].name, &top);
+			trans[pages + j] = pa;
+			if (j == 0) {
+				bootinfo.taskmap.tasks[bootinfo.taskmap.count].addr = (void *) (pages << PAGE_WIDTH);
+				bootinfo.taskmap.tasks[bootinfo.taskmap.count].size = components[i].size;
+				bootinfo.taskmap.count++;
+			}
 		}
+		
+		pages += component_pages;
 	}
 	
-	fix_overlap(&real_mode, &real_mode_pa, "Bootstrap trampoline", &top);
-	fix_overlap(&trans, &trans_pa, "Translation table", &top);
-	fix_overlap(&bootinfo, &bootinfo_pa, "Boot info", &top);
+	fix_overlap(&real_mode, &real_mode_pa, "bootstrap trampoline", &top);
+	fix_overlap(&trans, &trans_pa, "translation table", &top);
+	fix_overlap(&bootinfo, &bootinfo_pa, "boot info", &top);
 	
 	printf("\nBooting the kernel...\n");
-	jump_to_kernel(bootinfo_pa, sizeof(bootinfo), trans_pa, (kernel_pages + init_pages) << PAGE_WIDTH, fb, real_mode_pa);
+	jump_to_kernel(bootinfo_pa, sizeof(bootinfo), trans_pa, pages << PAGE_WIDTH, fb, real_mode_pa);
 }
Index: arch/ppc32/loader/main.h
===================================================================
--- arch/ppc32/loader/main.h	(revision a62347a99f0c39a8befc49032525a31fbb841467)
+++ arch/ppc32/loader/main.h	(revision 3eee37ddabc214eeb234269114c36548c82f7e4d)
@@ -39,20 +39,21 @@
 #define ALIGN_UP(addr, align) (((addr) + ((align) - 1)) & ~((align) - 1))
 
+#define TASKMAP_MAX_RECORDS 32
+
 typedef struct {
 	void *addr;
 	unsigned int size;
-} utask_t;
+} task_t;
 
 typedef struct {
-	utask_t init;
+	unsigned int count;
+	task_t tasks[TASKMAP_MAX_RECORDS];
+} taskmap_t;
+
+typedef struct {
+	taskmap_t taskmap;
 	memmap_t memmap;
 	screen_t screen;
 } bootinfo_t;
-
-extern int _binary_____________kernel_kernel_bin_start;
-extern int _binary_____________kernel_kernel_bin_end;
-
-extern int _binary_____________uspace_init_init_start;
-extern int _binary_____________uspace_init_init_end;
 
 extern void start(void);
Index: arch/ppc32/loader/pack
===================================================================
--- arch/ppc32/loader/pack	(revision 3eee37ddabc214eeb234269114c36548c82f7e4d)
+++ arch/ppc32/loader/pack	(revision 3eee37ddabc214eeb234269114c36548c82f7e4d)
@@ -0,0 +1,118 @@
+#! /bin/sh
+
+#
+# Copyright (C) 2006 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.
+#
+
+[ "$#" -lt 1 ] && exit 1
+
+OBJCOPY="$1"
+LINK="_link.ld"
+HEADER="_components.h"
+
+shift
+
+echo 'OUTPUT_FORMAT("elf32-powerpc")
+OUTPUT_ARCH(powerpc:common)
+ENTRY(start)
+
+SECTIONS {
+	.boot 0x10000000: AT (0) { 
+		*(BOOTSTRAP);
+		*(REALMODE);
+		*(.text);
+		
+		*(.rodata);
+		*(.rodata.*);
+		*(.data);		/* initialized data */
+		*(.sdata);
+		*(.sdata2);
+		*(.sbss);
+		*(.bss);		/* uninitialized static variables */	
+		*(COMMON); 		/* global variables */
+		
+		. = ALIGN(4096);
+		*(.kernel_image);' > "$LINK"
+
+echo '#ifndef ___COMPONENTS_H__
+#define ___COMPONENTS_H__
+
+typedef struct {
+	char *name;
+	
+	void *start;
+	void *end;
+	unsigned int size;
+} component_t;' > "$HEADER"
+
+COUNT="0"
+DATA=""
+
+for TASK in "$@" ; do
+	BASENAME="`basename "$TASK" | sed 's/^\(.*\)\.[^.]*$/\1/'`"
+	OBJECT="${BASENAME}.o"
+	SYMBOL="`echo "_binary_$TASK" | tr "./" "__"`"
+	MACRO="`echo "$BASENAME" | tr [:lower:] [:upper:]`"
+	echo "$TASK -> $OBJECT"
+	
+	echo "
+		. = ALIGN(4096);
+		*(.${BASENAME}_image);" >> "$LINK"
+	
+	echo "
+extern int ${SYMBOL}_start;
+extern int ${SYMBOL}_end;
+
+#define ${MACRO}_START ((void *) &${SYMBOL}_start)
+#define ${MACRO}_END ((void *) &${SYMBOL}_end)
+#define ${MACRO}_SIZE ((unsigned int) ${MACRO}_END - (unsigned int) ${MACRO}_START)" >> "$HEADER"
+	
+	"$OBJCOPY" -I binary -O elf32-powerpc -B powerpc:common --rename-section ".data=.${BASENAME}_image" "$TASK" "$OBJECT"
+		
+	DATA="${DATA}
+	components[$COUNT].name = \"${BASENAME}\";
+	components[$COUNT].start = ${MACRO}_START;
+	components[$COUNT].end = ${MACRO}_END;
+	components[$COUNT].size = ${MACRO}_SIZE;";
+	COUNT="`expr "$COUNT" + 1`"
+done
+
+echo '	}
+}' >> "$LINK"
+
+echo "
+#define COMPONENTS $COUNT
+
+component_t components[COMPONENTS]; 
+
+static void init_components(void)
+{
+$DATA
+}
+
+#endif
+" >> "$HEADER"
