diff --git a/Kernel/Core/macros.rs b/Kernel/Core/macros.rs
index fd4febe854ff00a319a889bec5a8b1b716c70dc7..a3c3b5ad4a3c2a660418db04f7d5a1380e290a09 100644
--- a/Kernel/Core/macros.rs
+++ b/Kernel/Core/macros.rs
@@ -21,7 +21,7 @@ macro_rules! _count
 #[macro_export]
 macro_rules! module_define
 {
-	($name:ident, [$($deps:ident),*], $init:path) => (
+	($name:ident, [ $( $(#[$da:meta])* $deps:ident ),*], $init:path) => (
 		//#[assume_reachable]
 		#[doc(hidden)]
 		#[link_section = ".MODULE_LIST"]
@@ -34,7 +34,7 @@ macro_rules! module_define
 			_rsvd: [0,0,0],
 		};
 		#[doc(hidden)]
-		static S_DEPS: [&'static str; _count!($($deps),*)] = [$(stringify!($deps)),*];
+		const S_DEPS: &'static [&'static str] = &[$( $(#[$da])* stringify!($deps) ),*];
 	);
 }
 
diff --git a/Kernel/Makefile-xargo b/Kernel/Makefile-xargo
index ec447a8dd9c884e2e5ed41685f9db4d06cc539fb..ec0805ec3a4b03f174a09e71dc9e4af843193efd 100644
--- a/Kernel/Makefile-xargo
+++ b/Kernel/Makefile-xargo
@@ -4,6 +4,25 @@
 V ?= @
 -include ../common.mk
 
+# ---------------------------------------
+# List of linked-in modules
+# - NOTE: These need to be listed in Cargo.toml too
+MODS :=
+#MODS += syscalls
+MODS += network
+MODS += virtio
+MODS += storage_ata
+MODS += input_ps2
+MODS += fs_fat fs_iso9660 fs_extN
+MODS += storage_ahci
+MODS += nic_rtl8139
+ifeq ($(ARCH),amd64)
+#MODS += video_vga
+endif
+MODS += usb_core usb_ohci
+
+# ---------------------------------------
+
 # - ACPICA can only be used on x86_64/amd64
 ifeq ($(ARCH),amd64)
  USE_ACPICA ?= 1
@@ -32,7 +51,7 @@ EXCLUDE_FEATURES :=
 
 ifeq ($(USE_ACPICA),1)
   OBJS += $(OBJDIR)libacpica.a
-  CARGO_FEATURES += acpica
+  CARGO_FEATURES += kernel/acpica
 endif
 
 XARGO := RUST_TARGET_PATH=$(abspath targets) $(XARGO)
@@ -45,6 +64,7 @@ dsm: bin/kernel-$(ARCH).bin.dsm
 # 
 # Final linking stage
 # 
+# TODO: Need to get the library list from cargo
 bin/kernel-$(ARCH).bin: $(OBJS) Core/arch/$(ARCH)/link.ld
 	@mkdir -p bin/
 	@echo [LD] -o $@
@@ -69,12 +89,18 @@ endif
 # Invoke xargo to build the main part of the kernel
 # - This includes all modules enabled in ./Cargo.toml
 #
-$(OBJDIR)libmain.a: PHONY targets/target-$(ARCH).json
+$(OBJDIR)libmain.a: PHONY $(OBJDIR)modules.rs targets/target-$(ARCH).json
 	@echo "[XARGO] . > $@"
-	$V$(ENV) $(XARGO) rustc --target=target-$(ARCH) --release --features "$(CARGO_FEATURES)" -- -C target-feature=$(subst $(space),$(comma),$(EXCLUDE_FEATURES:%=-%))
+	$VRUSTOS_MODPATH=../$(OBJDIR)modules.rs RUSTFLAGS="-C target-feature=$(subst $(space),$(comma),$(EXCLUDE_FEATURES:%=-%))" $(ENV) $(XARGO) build --target=target-$(ARCH) --release --features "$(CARGO_FEATURES)"
 	@mkdir -p $(dir $@)
 	@cp target/target-$(ARCH)/release/libmain.a $@
+$(patsubst %,$(OBJDIR)lib%.a,main $(MODS)): $(OBJDIR)libmain.a
 
+# - Module listing
+$(OBJDIR)modules.rs: Makefile-xargo
+	@echo "" > $@
+	@echo '$(patsubst %,extern crate %;\n,$(MODS))' >> $@
+	@echo "pub static MODLIST: &'static [&::kernel::modules::ModuleInfo] = &[\n\t$(patsubst %,&%::S_MODULE$(comma)\n\t,$(MODS))];" >> $@
 targets/target-$(ARCH).json: Core/arch/$(ARCH)/target.json
 	@mkdir -p $(dir $@)
 	$Vcp $< $@
diff --git a/Kernel/Modules/input_ps2/lib.rs b/Kernel/Modules/input_ps2/lib.rs
index 3e6dd94161b48b4753ece3362b88cb7dffca5ffb..d10259eab2c0fb973938a8c011df027670287305 100644
--- a/Kernel/Modules/input_ps2/lib.rs
+++ b/Kernel/Modules/input_ps2/lib.rs
@@ -16,10 +16,13 @@ extern crate gui;
 use kernel::prelude::*;
 
 // HACK: Requires USB to be active to ensure that emulation is off
-#[cfg(any(arch="amd64", arch="x86"))]
-module_define!{PS2, [DeviceManager, ACPI, GUI/*, USB*/], init}
-#[cfg(any(arch="armv7",arch="armv8"))]
-module_define!{PS2, [DeviceManager, GUI/*, USB*/], init}
+module_define!{PS2, [
+	DeviceManager,
+	#[cfg(any(arch="x86",arch="amd64",target_arch="x86",target_arch="x86_64"))]
+	ACPI,
+	GUI
+	/*, USB*/
+	], init}
 
 #[derive(Debug)]
 enum PS2Dev
@@ -44,7 +47,7 @@ enum EnumWaitState
 mod keyboard;
 mod mouse;
 
-#[cfg(any(arch="amd64", arch="x86"))]
+#[cfg(any(arch="x86",arch="amd64",target_arch="x86",target_arch="x86_64"))]
 fn init()
 {
 	#[path="i8042.rs"]
diff --git a/Kernel/main/main.rs b/Kernel/main/main.rs
index d3dc9a308e90a9443164888ac4d214ae0fa057e6..f6ddc33a5c989570c68889770fdb15915cb997f1 100644
--- a/Kernel/main/main.rs
+++ b/Kernel/main/main.rs
@@ -13,12 +13,45 @@
 extern crate kernel;
 extern crate syscalls;
 
+#[cfg(false_)]
+pub mod modules {
+	include!{ env!("RUSTOS_MODPATH") }
+}
+#[cfg(not(false_))]
+pub mod modules {
+	extern crate network;
+	extern crate virtio;
+	extern crate storage_ata;
+	extern crate input_ps2;
+	extern crate fs_fat;
+	extern crate fs_iso9660;
+	extern crate fs_extN;
+	extern crate storage_ahci;
+	extern crate nic_rtl8139;
+	extern crate usb_core;
+	extern crate usb_ohci;
+	pub static MODLIST: &'static [&::kernel::modules::ModuleInfo] = &[
+		//&network::S_MODULE,
+		//&virtio::S_MODULE,
+		//&storage_ata::S_MODULE,
+		//&input_ps2::S_MODULE,
+		//&fs_fat::S_MODULE,
+		//&fs_iso9660::S_MODULE,
+		//&fs_extN::S_MODULE,
+		//&storage_ahci::S_MODULE,
+		//&nic_rtl8139::S_MODULE,
+		//&usb_core::S_MODULE,
+		//&usb_ohci::S_MODULE,
+		];
+}
+
 /// Kernel entrypoint
 #[no_mangle]
 pub extern "C" fn kmain()
 {
 	log_notice!("{} starting", ::kernel::VERSION_STRING);
 	log_notice!("> {}", ::kernel::BUILD_STRING);
+	log_notice!("{} compiled-in modules", modules::MODLIST.len());	// NOTE: Needed to ensure that the modules are linked
 	
 	// Initialise core services before attempting modules
 	::kernel::memory::phys::init();
@@ -206,7 +239,7 @@ fn spawn_init(loader_path: &str, init_cmdline: &str) -> Result<::kernel::Void, &
 		};
 	
 	// - Load the loader into memory
-	let (header_ptr, memsize) = try!( load_loader(&loader) );
+	let (header_ptr, memsize) = load_loader(&loader)?;
 
 	// - Populate argument region and return size written
 	// SAFE: Addresses are checked by load_loader