--- /dev/null
+*.o
+*.d
+*.swp
+*.elf
+*.bin
+*.img
+*.map
+bootbios
+*.efi
--- /dev/null
+New operating system project
+============================
+
+Short term goals:
+ - support booting from BIOS, EFI and multiboot boot loaders.
+ - equally usable from display/keyboard or serial port from early boot.
+ - support GDB debugging over serial port as early as possible.
+
+Long term goals:
+ - VM system with user/kernel priviledge levels.
+ - support for 32bit and 64bit mode operation.
+ - built-in C compiler and assembler (tcc?) like templeOS.
+ - usable on a 386 with 2MB RAM (don't ignore base memory).
+ - support for USB devices (at least HID and ideally also mass storage).
+ - networking (start with the NE2000 on the 486).
+ - graphical desktop (VBE + chip-specific drivers).
--- /dev/null
+src = $(wildcard src/*.asm)
+obj = $(src:.asm=.o)
+bin = bootbios
+
+LDFLAGS = -m elf_i386 -T bootbios.ld -Map bootbios.map
+
+$(bin): $(obj)
+ $(LD) -o $(bin) $(obj) $(LDFLAGS)
+
+.SUFFIXES: .asm
+
+.asm.o:
+ nasm -o $@ -f elf $<
+
+.PHONY: clean
+clean:
+ rm -f $(OBJ)
--- /dev/null
+OUTPUT_FORMAT(binary)
+
+SECTIONS {
+ . = 0x7c00;
+
+ .boot : { * (.boot); }
+
+ /* second stage boot loader */
+ .boot2 : {
+ * (.boot2);
+ /* pad to the next sector boundary */
+ . = ALIGN(512);
+ }
+ _boot2_size = SIZEOF(.boot2);
+}
--- /dev/null
+ bits 16
+ section .boot
+
+start:
+ cli
+ xor ax, ax
+ mov ds, ax
+ mov es, ax
+ mov ss, ax
+ jmp 0:.setcs
+.setcs:
+ mov sp, ax
+
+ mov si, str_load2
+ call printstr
+
+ sti
+hang: hlt
+ jmp hang
+
+str_load2 db 'Loading 2nd stage boot loader...',13,10,0
+
+printstr:
+ lodsb
+ test al, al
+ jz .done
+ mov ah, 0eh
+ xor bx, bx
+ int 10h
+ jmp printstr
+.done: ret
+
+
+ times 510-($-$$) db 0
+ dw 0aa55h
+; vi:ft=nasm ts=8 sts=8 sw=8:
--- /dev/null
+.PHONY: all
+all: disk.img
+
+bootx64.efi: bootefi.bin src/hdr.asm
+ nasm -o $@ -f bin src/hdr.asm
+
+bootefi.bin: src/bootefi.asm
+ nasm -o $@ -f bin $<
+
+part.img: bootx64.efi
+ dd if=/dev/zero of=$@ bs=1024 count=2080
+ mkfs -t vfat $@
+ mmd -i $@ ::/EFI
+ mmd -i $@ ::/EFI/BOOT
+ mcopy -i $@ $< ::/EFI/BOOT
+
+disk.img: part.img
+ dd if=/dev/zero of=$@ bs=1024 count=2048
+ echo start=2048 type=ef | sfdisk $@
+ dd if=$< of=$@ bs=512 seek=2048 conv=notrunc
+
+.PHONY: clean
+clean:
+ rm -f bootx64.efi bootefi.bin
+
+.PHONY: run
+run: disk.img
+ qemu-system-x86_64 -bios /usr/share/ovmf/OVMF.fd -hda $< -net none -serial stdio
+
+.PHONY: debug
+debug: disk.img
+ qemu-system-x86_64 -bios /usr/share/ovmf/OVMF.fd -S -s -hda $< -net none -serial stdio
+
+
+disasm: bootx64.efi
+ ndisasm -b 64 -o 0x1000 -e 4096 $< >$@
+
+disasm16: bootx64.efi
+ ndisasm -b 16 -o 0x1000 -e 4096 $< >$@
--- /dev/null
+ bits 64
+ org 1000h
+
+%include "src/serial.inc"
+
+BOOT_SERVICES equ 96
+BOOT_GET_MEMORY_MAP equ 56
+BOOT_EXIT_BOOT_SERVICES equ 232
+
+start:
+ mov [efihandle], rcx
+ mov [systab], rdx
+
+ ; retrieve memory map
+ ; args: RCX, RDX, R8, and R9.
+ lea rcx, [mmap_size]
+ lea rdx, [mmapbuf]
+ lea r8, [mmap_key]
+ lea r9, [mmap_descsz]
+ lea rax, [mmap_descver]
+ push rax
+ sub rsp, 32
+ mov rax, [systab]
+ mov rbx, [rax + BOOT_SERVICES]
+ call [rbx + BOOT_GET_MEMORY_MAP]
+ add rsp, 40
+ ; exit boot services
+ mov rcx, [efihandle]
+ mov rdx, [mmap_key]
+ mov rax, [systab]
+ mov rbx, [rax + BOOT_SERVICES]
+ call [rbx + BOOT_EXIT_BOOT_SERVICES]
+
+ ; move code to absolute 1000h
+ call get_rip
+.after_call:
+ sub rax, .after_call - start
+ mov rsi, rax ; source address
+ mov rdi, start ; destination
+ mov rcx, end - start
+ shr rcx, 2 ; dwords
+ cld
+ rep movsd ; copy code to make it absolute
+
+ mov rax, .abs
+ jmp rax
+.abs:
+ call setup_serial
+
+ ; switch to 32-bit compatibility long mode
+ lgdt [gdtlim]
+ push word 8
+ push qword start32
+ retfq
+
+get_rip:
+ mov rax, [rsp]
+ ret
+
+ ; serial port setup
+setup_serial:
+ ; set clock divisor
+ mov al, LCTL_DLAB
+ mov dx, UART_LCTL
+ out dx, al
+ mov ax, DIV_9600
+ mov dx, UART_DIVLO
+ out dx, al
+ mov al, ah
+ mov dx, UART_DIVHI
+ out dx, al
+ ; set format 8n1
+ mov al, LCTL_8N1
+ mov dx, UART_LCTL
+ out dx, al
+ ; clear and enable fifo
+ mov al, FIFO_ENABLE_CLEAR
+ mov dx, UART_FIFO
+ out dx, al
+ ; assert RTS and DTR
+ mov al, MCTL_DTR_RTS_OUT2
+ mov dx, UART_MCTL
+ out dx, al
+ ret
+
+
+; ----------- 32bit code ----------
+
+ bits 32
+start32:
+ mov ax, 10h
+ mov ds, ax
+ mov ss, ax
+ mov es, ax
+ mov gs, ax
+ mov fs, ax
+
+ ; disable paging to deactivate long mode
+ mov eax, cr0
+ and eax, 7fffffffh
+ mov cr0, eax
+
+ ; disable long mode (EFER.LME = 0)
+ ; TODO: EFER is MSR c0000080, LME is bit 8
+ mov ecx, 0c0000080h
+ rdmsr
+ and eax, 0fffffeffh
+ wrmsr
+
+ ; halt for ever
+ sti
+halt: hlt
+ jmp halt
+
+ser_putchar:
+ mov ah, al
+ ; wait until transmit register is empty
+ mov dx, UART_LSTAT
+.wait: in al, dx
+ and al, LST_TREG_EMPTY
+ jz .wait
+ mov dx, UART_DATA
+ mov al, ah
+ out dx, al
+ ret
+
+ser_putstr:
+ mov al, [si]
+ test al, al
+ jz .done
+ call ser_putchar
+ inc si
+ jmp ser_putstr
+.done: ret
+
+
+; ---------- data ------------
+
+ align 8
+efihandle dq 0
+systab dq 0
+; memory map data
+mmap_size dq 4096
+mmap_key dq 0
+mmap_descsz dq 0
+mmap_descver dq 0
+
+ align 4096
+mmapbuf: times 4096 db 0
+
+str_hello db 'hello!',13,10,0
+
+ align 4
+gdtlim dw 31
+gdtbase dq gdt
+
+ align 8
+gdt: ; 0: null segment
+ dd 0, 0
+ ; 1: code - base:0, lim:4g, G:4k, 32bit, avl, pres|app, dpl:0, type:code/non-conf/rd
+ dd 0x0000ffff
+ dd 0x00cf9a00
+ ; 2: data - base:0, lim:4g, G:4k, 32bit, avl, pres|app, dpl:0, type:data/rw
+ dd 0x0000ffff
+ dd 0x00cf9200
+ ; 3: code16
+ dd 0x0000ffff
+ dd 0x00009a00
+
+ align 4
+end:
+; vi:ft=nasm:
--- /dev/null
+; vi:ft=nasm:
+ org 0
+
+ ; DOS stub
+ db "MZ"
+ times 3ah db 0
+ dd 40h ; PE offset
+ ; PE signature
+ db "PE",0,0
+ ; COFF header
+ dw 8664h ; machine type: x86-64
+ dw 1 ; number of sections
+ dd 0 ; creation time
+ dd 0 ; offset to symbol table
+ dd 0 ; number of symbols
+ dw opthdr_end - opthdr ; size of optional header
+ dw 2022h ; characteristics: DLL, exec image, can handle > 2gb addr
+ ; optional header - standard fields
+opthdr: dw 020bh ; magic: PE32+
+ dw 0 ; linker version
+ dd prog_end - prog ; size of code
+ dd 0 ; size of init data
+ dd 0 ; size of uninit data
+ dd prog ; entry point
+ dd prog ; base of code
+ ; optional header - windows-specific fields
+ dq 100000h ; image base
+ dd 4096 ; section alignment
+ dd 4096 ; file alignment
+ dd 0 ; os version
+ dd 0 ; img version
+ dd 0 ; subsys version
+ dd 0
+ dd image_end ; size of image
+ dd prog ; size of headers
+ dd 0 ; checksum
+ dw 10 ; subsystem: EFI application
+ dw 0040h ; DLL characteristics: relocatable at runtime
+ dq 4096 ; size of stack reserve
+ dq 4096 ; size of stack commit
+ dq 4096 ; size of heap reserve
+ dq 0 ; size of heap commit
+ dd 0
+ dd 0 ; number of rva and sizes
+opthdr_end:
+
+ ; sections
+ db ".text",0,0,0
+ dd image_end - prog ; virtual size
+ dd prog ; virtual address
+ dd image_end - prog ; raw data size
+ dd prog ; raw data
+ dd 0 ; relocations offset
+ dd 0 ; line numbers offset
+ dw 0 ; num reloc
+ dw 0 ; num line numbers
+ dd 60000020h ; characteristics: exec, readable, code
+
+ align 4096
+prog:
+ incbin "bootefi.bin"
+prog_end:
+ align 4096
+image_end:
--- /dev/null
+UART_DATA equ 0x3f8
+UART_DIVLO equ 0x3f8
+UART_DIVHI equ 0x3f9
+UART_FIFO equ 0x3fa
+UART_LCTL equ 0x3fb
+UART_MCTL equ 0x3fc
+UART_LSTAT equ 0x3fd
+DIV_9600 equ 115200 / 9600
+LCTL_8N1 equ 0x03
+LCTL_DLAB equ 0x80
+FIFO_ENABLE_CLEAR equ 0x07
+MCTL_DTR_RTS_OUT2 equ 0x0b
+LST_TREG_EMPTY equ 0x20
+
+; vi:ft=nasm:
--- /dev/null
+csrc = $(wildcard src/*.c) $(wildcard src/libc/*.c)
+ssrc = $(wildcard src/*.s) $(wildcard src/libc/*.s)
+
+obj = $(csrc:.c=.o) $(ssrc:.s=.o)
+dep = $(csrc:.c=.d)
+elf = kern.elf
+
+warn = -pedantic -Wall
+dbg = -g
+inc = -Isrc -Isrc/libc
+gccflags = -fno-pic -ffreestanding -nostdinc -fno-builtin -fcommon
+
+CFLAGS = $(ccarch) -march=i386 $(warn) $(opt) $(dbg) $(gccflags) $(inc) $(def) -MMD
+ASFLAGS = $(asarch) -march=i386 $(dbg) -nostdinc -fno-builtin $(inc)
+LDFLAGS = $(ldarch) -nostdlib -T kern.ld -print-gc-sections
+
+ifneq ($(shell uname -m), i386)
+ ccarch = -m32
+ asarch = --32
+ ldarch = -m elf_i386
+endif
+
+# uncomment to use a specific toolchain
+#TOOLPREFIX = x86_64-elf-
+
+CC = $(TOOLPREFIX)gcc
+AS = $(TOOLPREFIX)as
+LD = $(TOOLPREFIX)ld
+OBJCOPY = $(TOOLPREFIX)objcopy
+OBJDUMP = $(TOOLPREFIX)objdump
+
+
+$(elf): $(obj)
+ $(LD) -o $@ $(obj) -Map link.map $(LDFLAGS)
+
+%.o: %.S
+ $(CC) -o $@ $(CFLAGS) -c $<
+
+-include $(dep)
+
+.PHONY: clean
+clean:
+ rm -f $(obj) $(elf)
+
+
+.PHONY: cleandep
+cleandep:
+ rm -f $(dep)
+
+
+QEMUFLAGS = -serial file:serial.log
+
+.PHONY: run
+run: $(elf)
+ qemu-system-i386 -kernel $(elf) $(QEMUFLAGS)
+
+.PHONY: debug
+debug: $(elf)
+ qemu-system-i386 -kernel $(elf) $(QEMUFLAGS) -s -S
--- /dev/null
+OUTPUT_ARCH(i386)
+
+SECTIONS {
+ /* kernel loaded at 1MB */
+ . = 1M;
+ _kimg_start = .;
+
+ .startup : { * (.startup); }
+ .multiboot : { * (.multiboot); }
+ .text : { * (.text); }
+ .rodata : { * (.rodata); }
+ .data : { * (.data); }
+
+ .bss ALIGN(4): {
+ _bss_start = .;
+ * (.bss);
+ * (COMMON);
+ . = ALIGN(4);
+ _bss_end = .;
+ }
+ _bss_size = SIZEOF(.bss);
+
+ _kimg_size = . - _kimg_start;
+ _mem_start = .;
+}