summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Kling <awesomekling@gmail.com>2019-04-01 21:43:07 +0200
committerAndreas Kling <awesomekling@gmail.com>2019-04-01 21:43:07 +0200
commitee4d7c18c8a1a2d4b43261c751c238f35c90a232 (patch)
treed5ca240f3a946d971f0e4b3f63ee24660ca33ce2
parentd5a9f4596b3e1a8ab388ecdc8501f08f25d1a087 (diff)
downloadserenity-ee4d7c18c8a1a2d4b43261c751c238f35c90a232.zip
Kernel: Use a multiboot header instead of a convoluted two-part bootloader.
The old bootloader was hilariously complicated, requiring a floppy disk with the kernel on it, and a hard drive with the file system. This patch removes the floppy disk from the equation and replaces it with a multiboot header. This means the kernel can now be booted with qemu-system-i386 -kernel kernel
-rw-r--r--Kernel/.gitignore3
-rw-r--r--Kernel/Boot/boot.S64
-rwxr-xr-xKernel/Boot/boot.asm252
-rw-r--r--Kernel/Makefile26
-rw-r--r--Kernel/init.cpp2
-rw-r--r--Kernel/linker.ld19
-rwxr-xr-xKernel/run8
7 files changed, 81 insertions, 293 deletions
diff --git a/Kernel/.gitignore b/Kernel/.gitignore
index 2057bb9bd0..95057be2ee 100644
--- a/Kernel/.gitignore
+++ b/Kernel/.gitignore
@@ -1,7 +1,6 @@
*.o
*.d
-.floppy-image
-Boot/boot.bin
+Boot/boot.ao
kernel
kernel.map
_fs_contents
diff --git a/Kernel/Boot/boot.S b/Kernel/Boot/boot.S
new file mode 100644
index 0000000000..694d53f9f1
--- /dev/null
+++ b/Kernel/Boot/boot.S
@@ -0,0 +1,64 @@
+.set MULTIBOOT_MAGIC, 0x1badb002
+.set MULTIBOOT_PAGE_ALIGN, 0x1
+.set MULTIBOOT_MEMORY_INFO, 0x2
+.set MULTIBOOT_VIDEO_MODE, 0x4
+.set multiboot_flags, MULTIBOOT_PAGE_ALIGN | MULTIBOOT_MEMORY_INFO | MULTIBOOT_VIDEO_MODE
+.set multiboot_checksum, -(MULTIBOOT_MAGIC + multiboot_flags)
+
+.section .multiboot
+.align 4
+
+.long MULTIBOOT_MAGIC
+.long multiboot_flags
+.long multiboot_checksum
+
+
+/* for MULTIBOOT_MEMORY_INFO */
+.long 0x00000000 /* header_addr */
+.long 0x00000000 /* load_addr */
+.long 0x00000000 /* load_end_addr */
+.long 0x00000000 /* bss_end_addr */
+.long 0x00000000 /* entry_addr */
+
+/* for MULTIBOOT_VIDEO_MODE */
+.long 0x00000000 /* mode_type */
+.long 0 /* width */
+.long 0 /* height */
+.long 32 /* depth */
+
+.section .stack, "aw", @nobits
+stack_bottom:
+.skip 32768
+stack_top:
+
+.section .text
+
+.global start
+.type start, @function
+
+.extern init
+.type init, @function
+
+start:
+ mov $stack_top, %esp
+
+ and $-16, %esp
+
+ pushl %esp
+ pushl %eax /* Multiboot header magic */
+ pushl %ebx /* Multiboot header pointer */
+
+ cli
+ call init
+
+ pushl $exit_message
+ call kprintf
+
+ cli
+
+loop:
+ hlt
+ jmp loop
+
+exit_message:
+ .asciz "Kernel exited."
diff --git a/Kernel/Boot/boot.asm b/Kernel/Boot/boot.asm
deleted file mode 100755
index bdcfcb7a74..0000000000
--- a/Kernel/Boot/boot.asm
+++ /dev/null
@@ -1,252 +0,0 @@
-; asmsyntax=nasm
-
-[org 0x7c00]
-[bits 16]
-
-boot:
- cli
- mov ax, 0x8000
- mov ss, ax
- mov sp, 0xffff
-
- push cs
- pop ds
- xor bx, bx
- mov ah, 0x0e
- mov si, message
- lodsb
-.lewp:
- int 0x10
- lodsb
- cmp al, 0
- jne .lewp
-
- ; Enable A20
- mov ax, 0x2401
- int 0x15
-
- ; HACK: Load the ELF kernel at 0xf000. Assuming that the first
- ; LOAD header has a file offset of 0x1000, this puts _start
- ; at 0x10000 which we jump to later.
- ; This is all quite rickety.
- mov bx, 0xf00
- mov es, bx
- xor bx, bx
-
- mov cx, word [cur_lba]
-.sector_loop:
- call convert_lba_to_chs
-
- mov ah, 0x02 ; cmd 0x02 - Read Disk Sectors
- mov al, 1 ; 1 sector at a time
- mov dl, 0 ; drive 0 (fd0)
- int 0x13
-
- jc fug
-
- mov ah, 0x0e
- mov al, '.'
- int 0x10
-
- inc word [cur_lba]
- mov cx, word [cur_lba]
- cmp cx, 900
- jz .sector_loop_end
-
- mov bx, es
- add bx, 0x20
- mov es, bx
- xor bx, bx
-
- jmp .sector_loop
-
-.sector_loop_end:
-
- call durk
-
- ; Turn off the floppy motor.
- mov dx, 0x3f2
- xor al, al
- out dx, al
-
- ; Let's look at the ELF header.
- mov bx, 0xf00
- mov fs, bx
- cmp [fs:0], dword 0x464c457f ; ELF magic: { 0x7f "ELF" }
- jne fug
-
- cmp [fs:24], dword 0x10000 ; Entry should be 0x10000
- jne fug
-
- mov ebx, dword [fs:28] ; EBX <- program header table
- mov ecx, dword [fs:44] ; ECX <- program header count
-
-; Let's find the BSS and clear it.
-
-parse_program_header:
- cmp [fs:ebx], dword 0x1 ; Is Load segment?
- jne .next
-
- cmp [fs:ebx+24], dword 0x6 ; Is read+write but not execute?
- jne .next
-
- mov edi, [fs:ebx+8] ; EDI <- p_vaddr
- add edi, [fs:ebx+16] ; skip over 'p_filesz' bytes (leave them intact)
-
- push ecx
-
- sub edi, [fs:ebx+16] ; skip over 'p_filesz' bytes (see above)
-
- ; Since we're in 16-bit real mode, create a segment address.
- mov eax, edi
- shr eax, 4
- mov es, ax
- and edi, 0xf
-
- mov ecx, [fs:ebx+20] ; ECX <- p_memsz
- xor al, al
- rep stosb
-
- pop ecx
-
-.next:
- add ebx, 32
- loop parse_program_header
-
-; Okay we're all set to go!
-
-lets_go:
- lgdt [cs:test_gdt_ptr]
-
- mov eax, cr0
- or al, 1
- mov cr0, eax
-
- jmp 0x08:pmode
-
-durk:
- push cs
- pop ds
- xor bx, bx
- mov ah, 0x0e
- mov si, msg_sectors_loaded
- lodsb
-.lewp:
- int 0x10
- lodsb
- cmp al, 0
- jne .lewp
- ret
-
-pmode:
-[bits 32]
- mov ax, 0x10
- mov ds, ax
- mov es, ax
- mov fs, ax
- mov gs, ax
-
- mov ss, ax
- mov esp, 0x4000
-
- xor eax, eax
- xor ebx, ebx
- xor ecx, ecx
- xor edx, edx
- xor ebp, ebp
- xor esi, esi
- xor edi, edi
-
- jmp 0x10000
-
- hlt
-
-test_gdt_ptr:
- dw (test_gdt_end-test_gdt)
- dd test_gdt
-
-test_gdt:
- dd 0
- dd 0
- dd 0x0000ffff
- dd 0x00cf9a00
- dd 0x0000ffff
- dd 0x00cf9200
- dd 0
- dd 0
- dd 0
- dd 0
-test_gdt_end:
-
-[bits 16]
-fug:
- xor bx, bx
- mov ah, 0x0e
- mov si, fug_message
- lodsb
-.lewp:
- int 0x10
- lodsb
- cmp al, 0
- jne .lewp
-
- cli
- hlt
-
-; Input:
-;
-; AX = LBA
-;
-; Output:
-;
-; CX and DH = C/H/S address formatted for Int13,2
-
-; CL = sector (LBA % sectors_per_track) + 1
-;
-; 1.44M floppy stats:
-; (sectors_per_track: 18)
-; (heads: 2)
-; (sectors: 2880)
-
-convert_lba_to_chs:
- mov ax, cx
-
- ; AX = LBA/spt, DX = LBA%spt
- xor dx, dx
- div word [sectors_per_track]
-
- ; CL = sector (LBA % sectors_per_track) + 1
- mov cl, dl
- inc cl
-
- ; CH = track (LBA / sectors_per_track) / heads
- mov ch, al
- shr ch, 1
-
- ; AX = (LBA/spt)/heads, DX = (LBA/spt)%heads
- xor dx, dx
- div word [heads]
-
- ; DH = sector (LBA / sectors_per_track) % heads
- mov dh, dl
-
- ret
-
-cur_lba:
- dw 1
-sectors_per_track:
- dw 18
-heads:
- dw 2
-
-msg_sectors_loaded:
- db "done!", 0x0d, 0x0a, 0
-
-message:
- db "Loading kernel", 0
-
-fug_message:
- db "FUG!", 0x0d, 0x0a, 0
-
-times 510-($-$$) db 0
-dw 0xaa55
diff --git a/Kernel/Makefile b/Kernel/Makefile
index c57ac37d9c..98826d5628 100644
--- a/Kernel/Makefile
+++ b/Kernel/Makefile
@@ -1,5 +1,4 @@
KERNEL_OBJS = \
- _start.o \
init.o \
kmalloc.o \
StdLib.o \
@@ -65,12 +64,10 @@ AK_OBJS = \
../AK/FileSystemPath.o \
../AK/StdLibExtras.o
-OBJS = $(KERNEL_OBJS) $(VFS_OBJS) $(AK_OBJS)
+CXX_OBJS = $(KERNEL_OBJS) $(VFS_OBJS) $(AK_OBJS)
+OBJS = $(CXX_OBJS) Boot/boot.ao
-NASM = nasm
KERNEL = kernel
-BOOTLOADER = Boot/boot.bin
-IMAGE = .floppy-image
ARCH_FLAGS =
STANDARD_FLAGS = -std=c++17 -nostdinc++ -nostdlib -nostdinc
KERNEL_FLAGS =
@@ -87,9 +84,10 @@ CXXFLAGS = -MMD -MP $(WARNING_FLAGS) $(OPTIMIZATION_FLAGS) $(KERNEL_FLAGS) $(FLA
#CXX = clang $(CLANG_FLAGS)
CXX = i686-elf-g++
LD = i686-elf-ld
+AS = i686-elf-as
LDFLAGS = -T linker.ld
-all: $(KERNEL) $(IMAGE) kernel.map
+all: $(KERNEL) kernel.map
kernel.map: kernel
@echo "MKMAP $@"; sh mkmap.sh
@@ -97,20 +95,14 @@ kernel.map: kernel
$(KERNEL): $(OBJS)
@echo "LD $@"; $(LD) $(LDFLAGS) -o $@ -Ttext 0x10000 $(OBJS)
-$(IMAGE): $(KERNEL) $(BOOTLOADER)
- @echo "CREATE $@"; cat $(BOOTLOADER) $(KERNEL) > .tmp-floppy-image
- @dd if=/dev/zero bs=2M count=1 >> .tmp-floppy-image 2> /dev/null
- @dd if=.tmp-floppy-image of=.floppy-image bs=1440k count=1 2>/dev/null
- @rm -f .tmp-floppy-image
-
-$(BOOTLOADER): Boot/boot.asm
- @echo "NASM $<"; $(NASM) -f bin -o $@ $<
-
.cpp.o:
@echo "CXX $<"; $(CXX) $(CXXFLAGS) -o $@ -c $<
--include $(OBJS:%.o=%.d)
+%.ao: %.S
+ @echo "AS $@"; $(AS) -o $@ $<
+
+-include $(CXX_OBJS:%.o=%.d)
clean:
- @echo "CLEAN"; rm -f $(KERNEL) $(OBJS) $(BOOTLOADER) $(IMAGE) *.d
+ @echo "CLEAN"; rm -f $(KERNEL) $(OBJS) *.d
diff --git a/Kernel/init.cpp b/Kernel/init.cpp
index d9f4c77d57..c91d5235e3 100644
--- a/Kernel/init.cpp
+++ b/Kernel/init.cpp
@@ -136,7 +136,7 @@ VFS* vfs;
ASSERT_NOT_REACHED();
}
-[[noreturn]] void init()
+extern "C" [[noreturn]] void init()
{
cli();
diff --git a/Kernel/linker.ld b/Kernel/linker.ld
index c86217cc94..ef808a575c 100644
--- a/Kernel/linker.ld
+++ b/Kernel/linker.ld
@@ -1,44 +1,29 @@
-/* The bootloader will look at this image and start execution at the symbol
- designated as the entry point. */
-ENTRY(_start)
+ENTRY(start)
-/* Tell where the various sections of the object files will be put in the final
- kernel image. */
SECTIONS
{
- /* Begin putting sections at 1 MiB, a conventional place for kernels to be
- loaded at by the bootloader. */
. = 0x10000;
- /* First put the multiboot header, as it is required to be put very early
- early in the image or the bootloader won't recognize the file format.
- Next we'll put the .text section. */
.text BLOCK(4K) : ALIGN(4K)
{
- _start.o
+ Boot/boot.ao
*(.multiboot)
*(.text)
}
- /* Read-only data. */
.rodata BLOCK(4K) : ALIGN(4K)
{
*(.rodata)
}
- /* Read-write data (initialized) */
.data BLOCK(4K) : ALIGN(4K)
{
*(.data)
}
- /* Read-write data (uninitialized) and stack */
.bss BLOCK(4K) : ALIGN(4K)
{
*(COMMON)
*(.bss)
}
-
- /* The compiler may produce other sections, by default it will put them in
- a segment with the same name. Simply add stuff here as needed. */
}
diff --git a/Kernel/run b/Kernel/run
index b380e46321..640f7bdb95 100755
--- a/Kernel/run
+++ b/Kernel/run
@@ -7,17 +7,17 @@ if [ "$1" = "b" ]; then
bochs -q -f .bochsrc
elif [ "$1" = "qn" ]; then
# ./run qn: qemu without network
- qemu-system-i386 -s -m $ram_size -device e1000 -drive format=raw,file=.floppy-image,if=floppy -drive format=raw,file=_fs_contents #$@
+ qemu-system-i386 -s -m $ram_size -device e1000 -kernel kernel -hda _fs_contents
elif [ "$1" = "qtap" ]; then
# ./run qtap: qemu with tap
- sudo qemu-system-i386 -s -m $ram_size -object filter-dump,id=hue,netdev=br0,file=e1000.pcap -netdev tap,ifname=tap0,id=br0 -device e1000,netdev=br0 -drive format=raw,file=.floppy-image,if=floppy -drive format=raw,file=_fs_contents
+ sudo qemu-system-i386 -s -m $ram_size -object filter-dump,id=hue,netdev=br0,file=e1000.pcap -netdev tap,ifname=tap0,id=br0 -device e1000,netdev=br0 -kernel kernel -hda _fs_contents
else
# ./run: qemu with user networking
qemu-system-i386 -s -m $ram_size \
-object filter-dump,id=hue,netdev=breh,file=e1000.pcap \
-netdev user,id=breh,hostfwd=tcp:127.0.0.1:8888-192.168.5.2:8888 \
-device e1000,netdev=breh \
- -drive format=raw,file=.floppy-image,if=floppy \
- -drive format=raw,file=_fs_contents
+ -kernel kernel \
+ -hda _fs_contents
fi