diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..023b9a7 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,8 @@ +root = true + +[*] +end_of_line = lf +insert_final_newline = true +charset = utf-8 +indent_style = tab +indent_size = 4 \ No newline at end of file diff --git a/.gitignore b/.gitignore index 242cbeb..17661a9 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,6 @@ *.img *.bin *~ + +*.elf +*.dump diff --git a/Makefile b/Makefile index 37fe02e..653ab56 100644 --- a/Makefile +++ b/Makefile @@ -1,22 +1,41 @@ -all: stupid.img kern.bin +.SUFFIXES: +.DELETE_ON_ERROR: +.DEFAULT_GOAL := all -stupid.img: floppy.bin kern.bin - mkdosfs -F 12 -C $@ 1440 - dd status=noxfer conv=notrunc if=floppy.bin of=$@ - mcopy -i $@ kern.bin ::kern.sys +AS = nasm +LD = ld.lld +OBJDUMP = llvm-objdump +RM = rm -f -floppy.bin: boot/floppy.s - nasm -fbin -o $@ $^ +BIN_DIR = bin +DOC_DIR = doc +KERNEL_DIR = kernel +LIB_DIR = lib +TOOLS_DIR = tools -kern.bin: kern/kernel.s - nasm -fbin -o $@ $^ +include $(TOOLS_DIR)/build.mk + +ASFLAGS = -DSTUPID_VERSION=\"$(shell $(GIT-VERSION))\" -Ilib + +GARBADGE = stupid.img + +include $(KERNEL_DIR)/build.mk + +all: stupid.img + +stupid.img: $(KERNEL_BIN) $(KERNEL_DUMP) + +#stupid.img: floppy.bin kern.bin +# mkdosfs -F 12 -C $@ 1440 +# dd status=noxfer conv=notrunc if=floppy.bin of=$@ +# mcopy -i $@ kern.bin ::kern.sys + +%.dump: %.elf + $(OBJDUMP) -D $^ > $@ clean: - rm -rf floppy.bin kern.bin + $(RM) $(GARBADGE) -fclean: clean - rm -rf stupid.img +re: clean all -re: fclean all - -.PHONY: all clean fclean re +.PHONY: all clean re diff --git a/README.md b/README.md index 8205a9f..1bf5023 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ # StupidOS -16bit real mode Operating System in assembly +32-bit Operating System in assembly. diff --git a/boot/floppy.s b/boot/floppy.s deleted file mode 100644 index 52f5c49..0000000 --- a/boot/floppy.s +++ /dev/null @@ -1,127 +0,0 @@ - [ORG 0x7c00] - [BITS 16] - - jmp short entry - nop - - ;; ----------------------------------------------------------- - ;; OEM & Bios Parameter Block - ;; ----------------------------------------------------------- - db "StupidOS" - -bpb_bytes_per_sector dw 512 ; bytes per sector -bpb_sectors_per_cluster db 1 ; sector per cluster -bpb_reserved_sectors dw 1 ; reserved sector -bpb_number_of_fats db 2 ; number of FATs -bpb_root_entries dw 224 ; root entries -bpb_total_sectors dw 2880 ; total sector -bpb_media db 0xF0 ; media descriptor type -bpb_sectors_per_fat dw 9 ; sectors per FAT -bpb_sectors_per_track dw 18 ; sectors per track -bpb_heads_per_cylinder dw 2 ; heads per cylinder -bpb_hidden_sectors dd 0 ; hidden sectors -bpb_total_sector_big dd 0 ; total sector big -bpb_drive_number db 0 ; drive number -bpb_unused db 0 ; unused -bpb_signature db 0x29 ; drive signature (0x29 = floppy) -bpb_serial_number dd 0x00000000 ; serial number (ignore) -bpb_volume_label db 'STUPID DISK' ; volume label -bpb_filesystem db 'FAT12 ' ; filesystem type - - ;; ----------------------------------------------------------- - ;; entry - ;; ----------------------------------------------------------- -entry: - xor ax, ax - mov ds, ax - - mov si, msg_boot - call boot_print - mov si, msg_copyright - call boot_print -reset_disk: - xor ah, ah - xor dl, dl - int 0x13 - jc reset_disk - - ;; load kernel from FAT - ;; store size of root dir in cx - xor cx, cx - xor dx, dx - mov ax, 0x0020 - mul word [bpb_root_entries] - div word [bpb_bytes_per_sector] - xchg ax, cx - - ;; store loc of root directory in ax - mov al, byte [bpb_number_of_fats] - mul word [bpb_sectors_per_fat] - add ax, word [bpb_reserved_sectors] - ;; mov word [datasec], ax - ;; mov word [datasec], cx - - mov bx, 0x0200 - -hang: - jmp hang - cli - hlt - - ;; ----------------------------------------------------------- - ;; Print string using bios interrupt - ;; ----------------------------------------------------------- -boot_print: - pusha -.loop: - lodsb - cmp al, 0 - jz .end - mov ah, 0x0E ; bios print - mov bx, 0x07 - int 0x10 - jmp .loop -.end: - popa - ret - -fatal_error: - pusha - mov cx, si - mov si, msg_error - call boot_print - mov si, cx - call boot_print - mov si, msg_press_any_key - call boot_print - xor ax, ax - int 0x16 ; wait keypressed - int 0x19 ; reboot - popa - ret - -disk_read_sector: - pusha - - popa - ret - - ;; ----------------------------------------------------------- - ;; Variables - ;; ----------------------------------------------------------- - msg_boot db "StupidOS - Bootloader", 13, 10, 0 - msg_copyright db "Copyright (c) d0p1", 13, 10, 0 - msg_press_any_key db "Press any key...", 13, 10, 0 - - msg_error db "[ERROR] ", 0 - err_kern_not_found db "KERNEL.BIN not found...", 13, 10, 0 - - kernel_filename db "KERNEL BIN" - - ;; ----------------------------------------------------------- - ;; End - ;; ----------------------------------------------------------- - times 510-($-$$) db 0 - db 0x55 - db 0xAA - diff --git a/kern/kernel.s b/kern/kernel.s deleted file mode 100644 index 8a93847..0000000 --- a/kern/kernel.s +++ /dev/null @@ -1 +0,0 @@ -[BITS 16] diff --git a/kernel/build.mk b/kernel/build.mk new file mode 100644 index 0000000..3bae25e --- /dev/null +++ b/kernel/build.mk @@ -0,0 +1,21 @@ +include kernel/drivers/build.mk + +KERNEL_SRCS = head.s gdt.s idt.s paging.s lib/log.s +KERNEL_OBJS = $(addprefix kernel/, $(KERNEL_SRCS:.s=.o) $(DRIVERS_OBJS)) +KERNEL_BIN = stupid.elf +KERNEL_DUMP = $(KERNEL_BIN:.elf=.dump) + +KERNEL_ASFLAGS = $(ASFLAGS) -D__KERNEL__ + +GARBADGE += $(KERNEL_OBJS) $(KERNEL_BIN) $(KERNEL_DUMP) + +$(KERNEL_BIN): $(KERNEL_OBJS) + $(LD) -T $(KERNEL_DIR)/linker.ld -nostdlib -o $@ $^ + +kernel/lib/%.o: lib/base/%.s + mkdir -p $(@D) + $(AS) -felf -o $@ $< $(KERNEL_ASFLAGS) + +kernel/%.o: kernel/%.s + $(AS) -felf -o $@ $< $(KERNEL_ASFLAGS) + diff --git a/kernel/drivers/build.mk b/kernel/drivers/build.mk new file mode 100644 index 0000000..4eb0dbc --- /dev/null +++ b/kernel/drivers/build.mk @@ -0,0 +1,2 @@ +DRIVERS_SRCS = serial.s +DRIVERS_OBJS = $(addprefix drivers/, $(DRIVERS_SRCS:.s=.o)) diff --git a/kernel/drivers/serial.s b/kernel/drivers/serial.s new file mode 100644 index 0000000..6d040b5 --- /dev/null +++ b/kernel/drivers/serial.s @@ -0,0 +1,48 @@ +section .text + +COM1 equ 0x3F8 +COM2 equ 0x2F8 +COM3 equ 0x3E8 +COM4 equ 0x2E8 + +THR equ 0x0 +RBR equ 0x0 +IER equ 0x1 +IIR equ 0x2 +LCR equ 0x3 +MCR equ 0x4 +LSR equ 0x5 +MSR equ 0x7 +DLL equ 0x0 +DLH equ 0x0 + +%macro COM_OUT 3 + mov dx, %1+%2 + mov al, %3 + out dx, al +%endmacro + +%macro COM_IN 2 + mov dx, %1+%2 + in al, dx +%endmacro + +global serial_init +serial_init: + COM_OUT COM1, IER, 0x00 + COM_OUT COM1, LCR, 0x80 + COM_OUT COM1, DLH, 0x00 + COM_OUT COM1, DLL, 0x0C + + COM_OUT COM1, LCR, 0x03 + + ret + +global serial_write +serial_write: + push ebp + mov ebp, esp + mov ecx, [ebp + 8] + COM_OUT COM1, THR, cl + pop ebp + ret diff --git a/kernel/gdt.s b/kernel/gdt.s new file mode 100644 index 0000000..cdbbb2e --- /dev/null +++ b/kernel/gdt.s @@ -0,0 +1,66 @@ +[BITS 32] + +section .text + +global setup_gdt +setup_gdt: + lgdt [gdt_ptr] + jmp 0x08:.flush_cs +.flush_cs: + mov ax, 0x10 + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + mov ss, ax + ret + +section .data + +gdt_ptr: + dw gdt_entries.end - gdt_entries - 1 + dd gdt_entries + +gdt_entries: + ;; null descriptor + dw 0x0 ; limit + dw 0x0 ; base (low) + db 0x0 ; base (mid) + db 0x0 ; access + db 0x0 ; granularity + db 0x0 ; base (high) + + ;; kernel mode code segment + dw 0xFFFF + dw 0x00 + db 0x00 + db 0x9A + db 0xCF + db 0x00 + + ;; kernel mode data segment + dw 0xFFFF + dw 0x00 + db 0x00 + db 0x92 + db 0xCF + db 0x00 + + ;; user mode code segment + dw 0xFFFF + dw 0x00 + db 0x00 + db 0xFA + db 0xCF + db 0x00 + + ;; user mode data segment + dw 0xFFFF + dw 0x00 + db 0x00 + db 0xF2 + db 0xCF + db 0x00 + + ;; TSS +.end: diff --git a/kernel/head.s b/kernel/head.s new file mode 100644 index 0000000..8bb1fe1 --- /dev/null +++ b/kernel/head.s @@ -0,0 +1,47 @@ +[BITS 32] + +%include "base.inc" + +MULTIBOOT_MAGIC equ 0x1BADB002 +MULTIBOOT_ALIGN equ 1 << 0 +MULTIBOOT_MEMINFO equ 1 << 1 +MULTIBOOT_FLAGS equ MULTIBOOT_ALIGN | MULTIBOOT_MEMINFO + +section .multiboot +align 4 + dd MULTIBOOT_MAGIC + dd MULTIBOOT_FLAGS + dd -(MULTIBOOT_MAGIC + MULTIBOOT_FLAGS) + +section .bss +align 16 +stack_bottom: + resb 16384 +stack_top: + +section .text +global entry +entry: + mov esp, stack_top + + cli + + extern serial_init + call serial_init + + extern setup_gdt + call setup_gdt + + extern setup_idt + call setup_idt + + extern setup_paging + call setup_paging + + LOG file + +hang: + hlt + jmp hang + +file db __FILE__, 0 diff --git a/kernel/idt.s b/kernel/idt.s new file mode 100644 index 0000000..3c4202e --- /dev/null +++ b/kernel/idt.s @@ -0,0 +1,16 @@ +[BITS 32] +section .text +global setup_idt +setup_idt: + lidt [idt_ptr] + ret + +section .data + +idt_ptr: + dw idt_entries.end - idt_entries - 1 + dd idt_entries + +idt_entries: + times 256 dd 0x00000000, 0x00000000 +.end: diff --git a/kernel/kernel.s b/kernel/kernel.s new file mode 100644 index 0000000..4b84bd3 --- /dev/null +++ b/kernel/kernel.s @@ -0,0 +1,2 @@ +[BITS 32] + diff --git a/kernel/linker.ld b/kernel/linker.ld new file mode 100644 index 0000000..2082c45 --- /dev/null +++ b/kernel/linker.ld @@ -0,0 +1,25 @@ +OUTPUT_ARCH(i386) +ENTRY(entry) + +SECTIONS +{ + . = 1M; + + .text : ALIGN(4) { + KEEP(*(.multiboot)) + *(.text) + } + + .rodata : ALIGN(4) { + *(.rodata) + } + + .data : ALIGN(4) { + *(.data) + } + + .bss : ALIGN(4) { + *(COMMON) + *(.bss) + } +} diff --git a/kernel/paging.s b/kernel/paging.s new file mode 100644 index 0000000..612d691 --- /dev/null +++ b/kernel/paging.s @@ -0,0 +1,20 @@ +[BITS 32] + +section .data +align 4096 + +page_directory: + times 1024 dd 0x00000002 + +section .text + +global setup_paging +setup_paging: + mov eax, page_directory + mov cr3, eax + + mov eax, cr0 + or eax, 0x80000001 + mov cr0, eax + + ret diff --git a/lib/base.inc b/lib/base.inc new file mode 100644 index 0000000..394835d --- /dev/null +++ b/lib/base.inc @@ -0,0 +1,10 @@ +extern log_impl + +%macro LOG 1 + push %1 + push file + + call log_impl + + add esp, 8 +%endmacro diff --git a/lib/base/log.s b/lib/base/log.s new file mode 100644 index 0000000..c65a0e0 --- /dev/null +++ b/lib/base/log.s @@ -0,0 +1,75 @@ +[BITS 32] + +%ifdef __KERNEL__ +extern serial_write +%endif + +section .text + +putstr: + push ebp + mov ebp, esp + mov ebx, [ebp + 8] +.loop: + mov eax, [ebx] + cmp al, 0 + je .end + push eax +%ifdef __KERNEL__ + call serial_write +%else +%endif + add esp, 4 + inc ebx + jmp .loop +.end: + pop ebp + ret + +putuint: + push ebp + mov ebp, esp + + mov ebx, [ebp + 8] + mov edx, [ebp + 12] + + mov eax, buffer + push eax + call putstr + + pop ebp + ret + +global log_impl +log_impl: + push ebp + mov ebp, esp + mov eax, [ebp + 8] + + push eax + call putstr + add esp, 4 + +%ifdef __KERNEL__ + push ':' + call serial_write + add esp, 4 +%else +%endif + mov eax, [ebp + 12] + push eax + call putstr + add esp, 4 + +%ifdef __KERNEL__ + mov al, 0xA + push eax + call serial_write + add esp, 4 +%else +%endif + pop ebp + ret + +digits db '0123456789ABCDEF' +buffer db '0000000000', 0 diff --git a/tools/build.mk b/tools/build.mk new file mode 100644 index 0000000..30b7f5b --- /dev/null +++ b/tools/build.mk @@ -0,0 +1,9 @@ +define TOOLS_TEMPLATE + +$(1) = $$(addprefix $$(TOOLS_DIR)/, $$(shell echo -n $(1) | tr A-Z a-z)) + +endef + +TOOLS = GIT-VERSION + +$(foreach tool, $(TOOLS), $(eval $(call TOOLS_TEMPLATE, $(tool)))) diff --git a/tools/git-version b/tools/git-version new file mode 100755 index 0000000..d92e4f6 --- /dev/null +++ b/tools/git-version @@ -0,0 +1,16 @@ +#!/bin/env sh + +vers="$(git describe --abbrev=4 --match='v[0-9]*' HEAD 2>/dev/null)" + +if [ ! -n "$vers" ]; then + vers="0.0" +fi + +commit="$(git rev-parse --short HEAD)" + +full_vers="${vers}-${commit}" +if [ -n "$(git status)" ]; then + full_vers="${full_vers}-dirty" +fi + +echo -n "${full_vers}"