├── .gitignore ├── LICENSE.txt ├── Makefile ├── README.md ├── linker.ld ├── loader.asm └── main.dats /.gitignore: -------------------------------------------------------------------------------- 1 | floppy.img 2 | loader.bin 3 | main.bin 4 | main_dats.o 5 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014 Brian McKenna 2 | 3 | MIT License 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | "Software"), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 20 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | LD=i386-elf-ld 2 | ATSOPT=patsopt 3 | CC=gcc 4 | CCFLAGS=-std=c99 -I${PATSHOME}/ccomp/runtime -I${PATSHOME} -D_ATS_CCOMP_RUNTIME_NONE -D_ATS_CCOMP_EXCEPTION_NONE -Wall -Wextra -Wno-unused -Wno-unused-parameter --target=i386-intel-linux -Os -m32 -nostdlib -fno-stack-protector -ffunction-sections -fdata-sections -fomit-frame-pointer -Wl,--gc-sections -g 5 | NASM=nasm 6 | QEMU=qemu-system-i386 7 | 8 | all: floppy.img 9 | 10 | .SUFFIXES: .o .dats .asm 11 | 12 | .PHONY: clean run 13 | 14 | %_dats.c: %.dats 15 | $(ATSOPT) -o $@ -d $< 16 | 17 | %_dats.o: %_dats.c 18 | $(CC) $(CCFLAGS) -c $< 19 | 20 | .asm.o: 21 | $(NASM) -f elf32 -o $@ $< 22 | 23 | loader.bin: loader.asm 24 | $(NASM) -o $@ -f bin $< 25 | 26 | floppy.img: loader.bin main.bin 27 | dd if=/dev/zero of=$@ bs=512 count=2 &>/dev/null 28 | cat $^ | dd if=/dev/stdin of=$@ conv=notrunc &>/dev/null 29 | 30 | main.bin: linker.ld main_dats.o 31 | $(LD) -m elf_i386 -o $@ -T $^ 32 | 33 | run: floppy.img 34 | $(QEMU) -fda $< 35 | 36 | clean: 37 | rm -f *.bin *.o *.img 38 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # atsboot 2 | 3 | A tiny 32 bit kernel written in ATS. 4 | 5 | This was largely based on the 6 | [rustboot](https://github.com/charliesome/rustboot) project which does 7 | the same but using [Rust](http://www.rust-lang.org/). 8 | 9 | It paints the screen bright red and then hangs. That's it: 10 | 11 | ![](http://i.imgur.com/aglQ890.png) 12 | 13 | ## Setup 14 | 15 | You need a few things to run atsboot: 16 | 17 | 1. qemu 18 | 2. a cross-compiler for i386 19 | 3. nasm 20 | 4. [ATS2 Positiats](http://www.ats-lang.org/DOWNLOAD/) 21 | 22 | ## Running it 23 | 24 | To compile, simply 25 | 26 | ```sh 27 | $ make 28 | ``` 29 | 30 | To run, 31 | 32 | ```sh 33 | $ make run 34 | ``` 35 | -------------------------------------------------------------------------------- /linker.ld: -------------------------------------------------------------------------------- 1 | ENTRY(main) 2 | OUTPUT_FORMAT(binary) 3 | 4 | MEMORY { 5 | ram : org = 0x7e00, l = 12K 6 | } 7 | 8 | SECTIONS { 9 | . = 0x7e00; 10 | 11 | .text : { 12 | *(.text) 13 | } >ram 14 | 15 | /DISCARD/ : { 16 | *(.comment) 17 | *(.eh_frame) 18 | *(.rel.eh_frame) 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /loader.asm: -------------------------------------------------------------------------------- 1 | use16 2 | 3 | org 0x7c00 4 | 5 | boot: 6 | ; initialize segment registers 7 | xor ax, ax 8 | mov ds, ax 9 | mov es, ax 10 | mov ss, ax 11 | ; initialize stack 12 | mov sp, 0x7bfe 13 | ; load rust code into 0x7e00 so we can jump to it later 14 | mov ah, 2 ; read 15 | mov al, 24 ; 24 sectors (12 KiB) 16 | mov ch, 0 ; cylinder & 0xff 17 | mov cl, 2 ; sector | ((cylinder >> 2) & 0xc0) 18 | mov dh, 0 ; head 19 | mov bx, 0x7e00 ; read buffer 20 | int 0x13 21 | jc error 22 | ; load protected mode GDT and a null IDT (we don't need interrupts) 23 | cli 24 | lgdt [gdtr] 25 | lidt [idtr] 26 | ; set protected mode bit of cr0 27 | mov eax, cr0 28 | or eax, 1 29 | mov cr0, eax 30 | ; far jump to load CS with 32 bit segment 31 | jmp 0x08:protected_mode 32 | 33 | error: 34 | mov si, .msg 35 | .loop: 36 | lodsb 37 | or al, al 38 | jz .done 39 | mov ah, 0x0e 40 | int 0x10 41 | jmp .loop 42 | .done: 43 | jmp $ 44 | .msg db "could not read disk", 0 45 | 46 | protected_mode: 47 | use32 48 | ; load all the other segments with 32 bit data segments 49 | mov eax, 0x10 50 | mov ds, eax 51 | mov es, eax 52 | mov fs, eax 53 | mov gs, eax 54 | mov ss, eax 55 | ; set up stack 56 | mov esp, 0x7bfc 57 | ; jump into rust 58 | call 0x7e00 59 | jmp $ 60 | 61 | gdtr: 62 | dw (gdt_end - gdt) + 1 ; size 63 | dd gdt ; offset 64 | 65 | idtr: 66 | dw 0 67 | dd 0 68 | 69 | gdt: 70 | ; null entry 71 | dq 0 72 | ; code entry 73 | dw 0xffff ; limit 0:15 74 | dw 0x0000 ; base 0:15 75 | db 0x00 ; base 16:23 76 | db 0b10011010 ; access byte - code 77 | db 0x4f ; flags/(limit 16:19). flag is set to 32 bit protected mode 78 | db 0x00 ; base 24:31 79 | ; data entry 80 | dw 0xffff ; limit 0:15 81 | dw 0x0000 ; base 0:15 82 | db 0x00 ; base 16:23 83 | db 0b10010010 ; access byte - data 84 | db 0x4f ; flags/(limit 16:19). flag is set to 32 bit protected mode 85 | db 0x00 ; base 24:31 86 | gdt_end: 87 | 88 | times 510-($-$$) db 0 89 | db 0x55 90 | db 0xaa 91 | -------------------------------------------------------------------------------- /main.dats: -------------------------------------------------------------------------------- 1 | #include "share/atspre_staload.hats" 2 | 3 | %{^ 4 | #define get_vram() ((void *) 0xB8000) 5 | %} 6 | 7 | typedef cell = @{ ch = char, attrib = uint8 } 8 | 9 | extern fun get_vram ():<> [l: agz] (@[cell][80*25] @ l | ptr l) = "mac#get_vram" 10 | 11 | extern prfun eat_vram {l: agz} {n: int} (pf: @[cell][n] @ l): void 12 | 13 | extern castfn uint8_of {n: nat} (i: int n): uint8 n 14 | 15 | implement main0 () = 16 | let 17 | val (pf_vram | vram) = get_vram () 18 | var i: int 19 | in 20 | begin 21 | for* {i: nat | i <= 80*25} .<80*25 - i>. (i: int i) 22 | => (i := 0; i < 80*25; i := i + 1) 23 | vram->[i] := @{ ch = '\0', attrib = uint8_of 192 }; 24 | end; 25 | let prval () = eat_vram pf_vram in () end 26 | end 27 | --------------------------------------------------------------------------------