diff --git a/Makefile b/Makefile
index 9cb518a..69488f3 100644
--- a/Makefile
+++ b/Makefile
@@ -4,12 +4,13 @@ TOPDIR     := $(dir $(realpath $(lastword $(MAKEFILE_LIST))))
 SYSROOTDIR := $(TOPDIR)/sysroot
 TOOLSDIR   := $(TOPDIR)/tools
 
-RM = echo
+AS = fasm
+RM = rm -f
 
 MK_BUGREPORT := \"https://git.cute.engineering/d0p1/StupidOS/issues\"
 MK_COMMIT    := \"$(shell git rev-parse --short HEAD)\"
 
-SUBDIRS	:= tools include boot kernel lib bin
+SUBDIRS	:= external tools include boot kernel lib bin
 
 TARGET	= stupid.tar.gz floppy_boot.img
 ifneq ($(OS),Windows_NT)
@@ -28,7 +29,7 @@ clean: GOAL:=clean
 .PHONY: $(SUBDIRS)
 $(SUBDIRS):
 	@echo "📁 $@"
-	DESTDIR=$(SYSROOTDIR) $(MAKE) -C $@ $(GOAL)
+	@DESTDIR=$(SYSROOTDIR) $(MAKE) -C $@ $(GOAL)
 
 .PHONY: stupid.iso
 stupid.iso: $(SUBDIRS)
@@ -46,8 +47,8 @@ stupid.tar.gz: $(SUBDIRS)
 floppy_boot.img: $(SUBDIRS)
 	dd if=/dev/zero of=$@ bs=512 count=1440
 	mformat -C -f 1440 -i $@
-	dd if=boot/bootsector.bin of=$@ conv=notrunc
-	mcopy -i $@ boot/stpdboot.sys ::/STPDBOOT.SYS
+	dd if=boot/bootsect/bootsector.bin of=$@ conv=notrunc
+	mcopy -i $@ boot/loader/stpdldr.sys ::/STPDLDR.SYS
 	mcopy -i $@ kernel/vmstupid.sys ::/VMSTUPID.SYS
 
 .PHONY: run
@@ -63,4 +64,4 @@ run: all
 
 .PHONY: clean
 clean: $(SUBDIRS)
-	$(RM) $(TARGET) $(SYSROOTDIR)
+	$(RM) $(TARGET) 
diff --git a/bin/Makefile b/bin/Makefile
index d66369a..974f1bf 100644
--- a/bin/Makefile
+++ b/bin/Makefile
@@ -1,5 +1,3 @@
-SUBDIRS = cmd
-
 TOPGOALS = all clean install
 
 SUBDIRS = cmd
@@ -7,7 +5,7 @@ SUBDIRS = cmd
 .PHONY: $(SUBDIRS)
 $(SUBDIRS):
 	@echo "📁 bin/$@"
-	DESTDIR=$(DESTDIR)/bin $(MAKE) -C $@ $(MAKECMDGOALS)
+	@DESTDIR=$(DESTDIR)/bin $(MAKE) -C $@ $(MAKECMDGOALS)
 
 .PHONY: $(TOPGOALS)
 $(TOPGOALS): $(SUBDIRS)
diff --git a/bin/cmd/cmd.asm b/bin/cmd/cmd.asm
index af13008..c7318ae 100644
--- a/bin/cmd/cmd.asm
+++ b/bin/cmd/cmd.asm
@@ -1,11 +1,13 @@
-	format COFF
-
-	section '.text' code
-
-	public main
-main:
-	int 0x2A
-
-	section '.data' data
-
-	INCLUDE 'builtins.inc'
+	format COFF
+
+	section '.text' code
+
+	public main
+	public _start
+_start:	
+main:
+	int 0x2A
+
+	section '.data' data
+
+	INCLUDE 'builtins.inc'
diff --git a/boot/Makefile b/boot/Makefile
index 07a39f9..401141e 100644
--- a/boot/Makefile
+++ b/boot/Makefile
@@ -1,39 +1,11 @@
-AS = fasm
-RM = rm
+TOPGOALS = all clean install
 
-TARGET = bootsector.bin stpdboot.sys bootia32.efi
+SUBDIRS = bootsect loader efi
 
-STAGE0_SRCS	= boot0.asm \
-			const.inc \
-			fat12.inc
+.PHONY: $(SUBDIRS)
+$(SUBDIRS):
+	@echo "📁 boot/$@"
+	@DESTDIR=$(DESTDIR) $(MAKE) -C $@ $(MAKECMDGOALS)
 
-STAGE1_SRCS	= boot1.asm \
-			const.inc \
-			a20.inc \
-			multiboot.inc
-
-BOOTIA32_EFI_SRCS = bootia32.asm \
-					uefi.inc
-
-.PHONY: all
-all: $(TARGET)
-
-bootsector.bin: $(STAGE0_SRCS)
-	$(AS) boot0.asm $@
-
-stpdboot.sys: $(STAGE1_SRCS)
-	$(AS) boot1.asm $@
-
-bootia32.efi: $(BOOTIA32_EFI_SRCS)
-	$(AS) bootia32.asm $@
-
-.PHONY: clean
-clean:
-	$(RM) $(TARGET)
-
-.PHONY: install
-install: $(TARGET)
-	@ mkdir -p $(DESTDIR)
-	install stpdboot.sys $(DESTDIR)
-	@ mkdir -p $(DESTDIR)/EFI/BOOT
-	install bootia32.efi $(DESTDIR)/EFI/BOOT
+.PHONY: $(TOPGOALS)
+$(TOPGOALS): $(SUBDIRS)
diff --git a/boot/boot0.asm b/boot/boot0.asm
deleted file mode 100644
index 7468a24..0000000
--- a/boot/boot0.asm
+++ /dev/null
@@ -1,120 +0,0 @@
-        INCLUDE 'const.inc'
-
-        ORG STAGE0_BASE
-        USE16
-
-        jmp short _start
-        nop
-
-        ; Boot Record
-OEM_identifier      db 'STUPID  '
-bytes_per_sector    dw 512
-sectors_per_cluster db 1
-reserved_sectors    dw 1
-FAT_count           db 2
-root_dir_entries    dw 224
-total_sectors       dw 2880
-media_desc_type     db 0xF0
-sectors_per_FAT     dw 9
-sectors_per_track   dw 18
-heads_per_cylinder  dw 2
-hidden_sectors      dd 0
-large_sector_count  dd 0
-
-        ; Extended Boot Record
-drive_number db 0x0
-reserved     db 0x0
-signature    db 0x29   ; 0x28 or 0x29
-volume_id    dd 0xB00B135 ; hope mine will grow :'(
-volume_label db 'Stupid Boot'
-system_id    db 'FAT12  '
-
-
-_start:
-        cli
-        cld
-        jmp 0x0:.canonicalize_cs
-
-.canonicalize_cs:
-        xor ax, ax
-        mov ds, ax
-        mov ss, ax
-        mov es, ax
-        mov sp, 0x7c00
-
-        mov [drive_number], dl
-
-        ; reset floppy disk
-@@:
-        mov dl, [drive_number]
-        xor ah, ah
-        int 0x13
-        jc @b
-
-        call fat_load_root
-
-        ; search in root directory
-
-        mov si, kernel_file
-        call fat_search_root
-        jc .error_not_found
-        mov [kernel_start], ax
-
-        mov si, stage1_file
-        call fat_search_root
-        jc .error_not_found
-        mov [stage1_start], ax
-
-        ; load fat
-        xor ax, ax
-        mov al, [FAT_count]
-        mul word [sectors_per_FAT]
-        mov cx, ax
-        mov ax, [reserved_sectors]
-
-        xor bx, bx
-
-        call disk_read_sectors
-
-        ; preload kernel
-        mov ax, KERNEL_PRELOAD/0x10
-        mov es, ax
-        mov ax, [kernel_start]
-        xor bx, bx
-        call fat_load_binary
-
-        ; load stage 2
-        mov ax, STAGE1_BASE/0x10
-        mov es, ax
-        mov ax, [stage1_start]
-        xor bx, bx
-        call fat_load_binary
-
-        jmp 0x0:STAGE1_BASE
-
-.error_not_found:
-        push si
-        mov si, msg_error
-        call bios_print
-        pop si
-        call bios_print
-        mov si, msg_not_found
-        call bios_print
-        hlt
-        jmp $
-
-        INCLUDE "utils.inc"
-        INCLUDE "fat12.inc"
-
-msg_error                  db "ERROR: ", 0
-msg_not_found              db " not found", CR, LF, 0
-
-kernel_file db "VMSTUPIDSYS", 0
-stage1_file db "STPDBOOTSYS", 0
-
-kernel_start dw 0x0
-stage1_start dw 0x0
-
-
-        rb 0x7C00+512-2-$
-        db 0x55, 0xAA
diff --git a/boot/bootsect/Makefile b/boot/bootsect/Makefile
new file mode 100644
index 0000000..a08c32d
--- /dev/null
+++ b/boot/bootsect/Makefile
@@ -0,0 +1,18 @@
+TARGET = bootsector.bin
+
+FLOPPY_SRCS	= floppy.asm \
+			../common/const.inc \
+			../common/fat12.inc
+
+.PHONY: all
+all: $(TARGET)
+
+bootsector.bin: $(FLOPPY_SRCS)
+	$(AS) floppy.asm $@
+
+.PHONY: clean
+clean:
+	$(RM) $(TARGET)
+
+.PHONY: install
+install: $(TARGET)
diff --git a/boot/bootsect/floppy.asm b/boot/bootsect/floppy.asm
new file mode 100644
index 0000000..b6418fc
--- /dev/null
+++ b/boot/bootsect/floppy.asm
@@ -0,0 +1,122 @@
+	format binary
+	use16
+
+	include '../common/const.inc'
+
+	org BOOTSECT_BASE
+
+	jmp short _start
+	nop
+
+	; Boot Record
+OEM_identifier      db 'STUPID  '
+bytes_per_sector    dw 512
+sectors_per_cluster db 1
+reserved_sectors    dw 1
+FAT_count           db 2
+root_dir_entries    dw 224
+total_sectors       dw 2880
+media_desc_type     db 0xF0
+sectors_per_FAT     dw 9
+sectors_per_track   dw 18
+heads_per_cylinder  dw 2
+hidden_sectors      dd 0
+large_sector_count  dd 0
+
+	; Extended Boot Record
+drive_number db 0x0
+reserved     db 0x0
+signature    db 0x29   		; 0x28 or 0x29
+volume_id    dd 0xB00B135 	; hope mine will grow :'(
+volume_label db 'Stupid Boot'
+system_id    db 'FAT12  '
+
+
+_start:
+	cli
+	cld
+	jmp 0x0:.canonicalize_cs
+
+.canonicalize_cs:
+	xor ax, ax
+	mov ds, ax
+	mov ss, ax
+	mov es, ax
+	mov sp, 0x7c00
+
+	mov [drive_number], dl
+
+	; reset floppy disk
+@@:
+	mov dl, [drive_number]
+	xor ah, ah
+	int 0x13
+	jc @b
+
+	call fat_load_root
+
+	; search in root directory
+
+	mov si, kernel_file
+	call fat_search_root
+	jc .error_not_found
+	mov [kernel_start], ax
+
+	mov si, stage1_file
+	call fat_search_root
+	jc .error_not_found
+	mov [stage1_start], ax
+
+	; load fat
+	xor ax, ax
+	mov al, [FAT_count]
+	mul word [sectors_per_FAT]
+	mov cx, ax
+	mov ax, [reserved_sectors]
+
+	xor bx, bx
+
+	call disk_read_sectors
+
+	; preload kernel
+	mov ax, KERNEL_PRELOAD/0x10
+	mov es, ax
+	mov ax, [kernel_start]
+	xor bx, bx
+	call fat_load_binary
+
+	; load stage 2
+	mov ax, LOADER_BASE/0x10
+	mov es, ax
+	mov ax, [stage1_start]
+	xor bx, bx
+	call fat_load_binary
+
+	jmp 0x0:LOADER_BASE
+
+.error_not_found:
+	push si
+	mov si, msg_error
+	call bios_print
+	pop si
+	call bios_print
+	mov si, msg_not_found
+	call bios_print
+	hlt
+	jmp $
+
+	include '../common/bios.inc'
+	include '../common/fat12.inc'
+
+msg_error                  db "ERROR: ", 0
+msg_not_found              db " not found", CR, LF, 0
+
+kernel_file db "VMSTUPIDSYS", 0
+stage1_file db "STPDLDR SYS", 0
+
+kernel_start dw 0x0
+stage1_start dw 0x0
+
+
+	rb 0x7C00+512-2-$
+	db 0x55, 0xAA
diff --git a/boot/utils.inc b/boot/common/bios.inc
similarity index 100%
rename from boot/utils.inc
rename to boot/common/bios.inc
diff --git a/boot/const.inc b/boot/common/const.inc
similarity index 83%
rename from boot/const.inc
rename to boot/common/const.inc
index b053e62..4bdd4a0 100644
--- a/boot/const.inc
+++ b/boot/common/const.inc
@@ -2,8 +2,8 @@ CR   = 0x0D
 LF   = 0x0A
 
 ; -------- Address ----------
-STAGE0_BASE    = 0x7C00
-STAGE1_BASE    = 0x1000
+BOOTSECT_BASE  = 0x7C00
+LOADER_BASE    = 0x1000
 MULTIBOOT_BASE = 0x100000
 DISK_BUFFER    = 0x8000
 KERNEL_PRELOAD = 0xF000
diff --git a/boot/fat12.inc b/boot/common/fat12.inc
similarity index 100%
rename from boot/fat12.inc
rename to boot/common/fat12.inc
diff --git a/boot/common/macro.inc b/boot/common/macro.inc
new file mode 100644
index 0000000..610e5b6
--- /dev/null
+++ b/boot/common/macro.inc
@@ -0,0 +1,6 @@
+macro defn name
+{
+	virtual at 0
+		name name
+	end virtual
+}
diff --git a/boot/efi/Makefile b/boot/efi/Makefile
new file mode 100644
index 0000000..918ce3e
--- /dev/null
+++ b/boot/efi/Makefile
@@ -0,0 +1,21 @@
+TARGET = BOOTIA32.EFI
+
+BOOTIA32_EFI_SRCS = bootia32.asm \
+					uefi.inc \
+					../common/const.inc \
+					../common/macro.inc
+
+.PHONY: all
+all: $(TARGET)
+
+BOOTIA32.EFI: $(BOOTIA32_EFI_SRCS)
+	$(AS) bootia32.asm $@
+
+.PHONY: clean
+clean:
+	$(RM) $(TARGET)
+
+.PHONY: install
+install: $(TARGET)
+	@ mkdir -p $(DESTDIR)/EFI/BOOT
+	install $(TARGET) $(DESTDIR)/EFI/BOOT
diff --git a/boot/bootia32.asm b/boot/efi/bootia32.asm
similarity index 80%
rename from boot/bootia32.asm
rename to boot/efi/bootia32.asm
index d58353e..a31a3a3 100644
--- a/boot/bootia32.asm
+++ b/boot/efi/bootia32.asm
@@ -3,6 +3,8 @@
 
 	section '.text' code executable readable
 
+	include '../common/const.inc'
+	include '../common/macro.inc'
 	include 'uefi.inc'
 
 	; ESP     => return address
@@ -29,14 +31,15 @@ efimain:
 
 	jmp $
 
+	xor eax, eax
 	ret
 
-
 	section '.reloc' fixups data discardable
 
 	section '.data' data readable writeable
 
-hello_msg du 'StupidOS EFI Bootloader', 13, 10, 0
+hello_msg   du 'StupidOS EFI Bootloader', 13, 10, 0
+kernel_file du 'vmstupid.sys', 0
 
 handle       dd ?
 system_table dd ? 
diff --git a/boot/uefi.inc b/boot/efi/uefi.inc
similarity index 98%
rename from boot/uefi.inc
rename to boot/efi/uefi.inc
index 50a0c25..7542920 100644
--- a/boot/uefi.inc
+++ b/boot/efi/uefi.inc
@@ -1,10 +1,3 @@
-macro defn name
-{
-	virtual at 0
-		name name
-	end virtual
-}
-
 struc BOOLEAN
 {
 	. db ?
diff --git a/boot/loader/Makefile b/boot/loader/Makefile
new file mode 100644
index 0000000..379aba2
--- /dev/null
+++ b/boot/loader/Makefile
@@ -0,0 +1,22 @@
+TARGET = stpdldr.sys
+
+LOADER_SRCS	= loader.asm \
+				../common/const.inc \
+				a20.inc \
+				multiboot.inc
+
+.PHONY: all
+all: $(TARGET)
+
+
+stpdldr.sys: $(LOADER_SRCS)
+	$(AS) loader.asm $@
+
+.PHONY: clean
+clean:
+	$(RM) $(TARGET)
+
+.PHONY: install
+install: $(TARGET)
+	@ mkdir -p $(DESTDIR)
+	install $(TARGET) $(DESTDIR)
diff --git a/boot/a20.inc b/boot/loader/a20.inc
similarity index 100%
rename from boot/a20.inc
rename to boot/loader/a20.inc
diff --git a/boot/boot1.asm b/boot/loader/loader.asm
similarity index 79%
rename from boot/boot1.asm
rename to boot/loader/loader.asm
index 221621e..ee94e7e 100644
--- a/boot/boot1.asm
+++ b/boot/loader/loader.asm
@@ -1,12 +1,14 @@
-	INCLUDE 'const.inc'
-	INCLUDE 'multiboot.inc'
+	format binary
 
-	ORG STAGE1_BASE
-	USE32
+	include '../common/const.inc'
+	include 'multiboot.inc'
+
+	org LOADER_BASE
+	use32
 
 	jmp _start
 
-	ALIGN 4
+	align 4
 multiboot_header:
 	mb_header MultibootHeader multiboot_header
 
@@ -14,7 +16,7 @@ _start:
 	cmp eax, MULTIBOOT_MAGIC
 	je .multiboot
 
-	USE16
+	use16
 	;; non multiboot process
 	push cs
 	pop ds
@@ -46,16 +48,15 @@ _start:
 	hlt
 	jmp $
 
-	INCLUDE 'a20.inc'
-	INCLUDE 'utils.inc'
-	INCLUDE 'memory.inc'
-	INCLUDE 'video.inc'
+	include 'a20.inc'
+	include '../common/bios.inc'
+	include 'memory.inc'
+	include 'video.inc'
 
 msg_stage2       db "StupidOS Bootloader (Stage 1)", CR, LF, 0
 msg_error_a20    db "ERROR: can't enable a20 line", CR, LF, 0
 msg_error_memory db "ERROR: can't detect available memory", CR, LF, 0
 
-
 	;;
 bi_screen_width:	dw 0
 bi_screen_height:	dw 0
diff --git a/boot/memory.inc b/boot/loader/memory.inc
similarity index 100%
rename from boot/memory.inc
rename to boot/loader/memory.inc
diff --git a/boot/multiboot.inc b/boot/loader/multiboot.inc
similarity index 95%
rename from boot/multiboot.inc
rename to boot/loader/multiboot.inc
index fff67db..aadbcaf 100644
--- a/boot/multiboot.inc
+++ b/boot/loader/multiboot.inc
@@ -15,7 +15,7 @@ struc MultibootHeader addr
 
         ; address fields (we'll just skip them)
         .header_addr   dd addr
-        .load_addr     dd STAGE1_BASE
+        .load_addr     dd LOADER_BASE
         .load_end_addr dd _edata
         .bss_end_addr  dd _end
         .entry_addr    dd _start
@@ -106,3 +106,11 @@ MULTIBOOT_MEMORY_RESERVED  = 0x2
 MULTIBOOT_MEMORY_ACPI      = 0x3
 MULTIBOOT_MEMORY_NVS       = 0x4
 MULTIBOOT_MEMORY_BADPARAM  = 0x5
+
+struc MultibootModule
+{
+	.mod_start dd ?
+	.mod_end   dd ?
+	.cmdline   dd ?
+	.pad       dd ?
+}
diff --git a/boot/video.inc b/boot/loader/video.inc
similarity index 100%
rename from boot/video.inc
rename to boot/loader/video.inc
diff --git a/lib/Makefile b/lib/Makefile
index b25107e..b315fda 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -5,7 +5,7 @@ TOPGOALS = all clean install
 .PHONY: $(SUBDIRS)
 $(SUBDIRS):
 	@echo "📁 lib/$@"
-	DESTDIR=$(DESTDIR)/lib $(MAKE) -C $@ $(MAKECMDGOALS)
+	@DESTDIR=$(DESTDIR)/lib $(MAKE) -C $@ $(MAKECMDGOALS)
 
 .PHONY: $(TOPGOALS)
 $(TOPGOALS): $(SUBDIRS)
diff --git a/tools/Makefile b/tools/Makefile
index 41b25ca..c402fdb 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -17,3 +17,6 @@ coff-ld$(EXEXT): coff-ld.c
 
 .PHONY: install
 install: $(TARGET)
+
+.PHONY: clean
+clean:
diff --git a/tools/create-iso b/tools/create-iso
index d3f42eb..1e73530 100755
--- a/tools/create-iso
+++ b/tools/create-iso
@@ -8,7 +8,7 @@ set default=0
 menuentry "StupidOS" {
    echo "verify system integrity"
    hashsum --hash sha256 --check /boot/hashfile --prefix /
-   multiboot /stpdboot.sys
+   multiboot /stpdldr.sys
    module /vmstupid.sys
    boot
 }
@@ -21,9 +21,9 @@ gen_iso_file() {
 	echo "$grub_config" > "$2/boot/grub/grub.cfg"
 	(cd "$2"; 
 		sha256sum -b -t "vmstupid.sys" > "boot/hashfile";
-		sha256sum -b -t "stpdboot.sys" >> "boot/hashfile"
+		sha256sum -b -t "stpdldr.sys" >> "boot/hashfile"
 	)
-	grub-file --is-x86-multiboot "$2/stpdboot.sys" || exit 1
+	grub-file --is-x86-multiboot "$2/stpdldr.sys" || exit 1
 
 	grub-mkrescue -o $1 $2
 }