From 06692d6c927aae4e6f06efd1e401d005839c1e5f Mon Sep 17 00:00:00 2001 From: John Tsiombikas Date: Wed, 16 Nov 2022 02:18:35 +0200 Subject: [PATCH] initial commit --- .gdbinit | 4 + .gitignore | 7 ++ Makefile | 29 +++++++ boot.ld | 29 +++++++ boot/boot.asm | 250 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ boot/boot2.asm | 18 ++++ boot/main.c | 13 +++ 7 files changed, 350 insertions(+) create mode 100644 .gdbinit create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 boot.ld create mode 100644 boot/boot.asm create mode 100644 boot/boot2.asm create mode 100644 boot/main.c diff --git a/.gdbinit b/.gdbinit new file mode 100644 index 0000000..f0a6182 --- /dev/null +++ b/.gdbinit @@ -0,0 +1,4 @@ +target remote localhost:1234 +disp/i $pc +set disassembly-flavor intel +set architecture i8086 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3576cff --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +*.o +*.d +*.swp +*.img +*.map +dis +*.log diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..0bac632 --- /dev/null +++ b/Makefile @@ -0,0 +1,29 @@ +bin = boot.img + +CC = ia16-elf-gcc +LD = ia16-elf-ld + +CFLAGS = -march=i8088 -mtune=i8088 + +$(bin): boot/boot.o boot/boot2.o boot/main.o + $(LD) -T boot.ld -Map boot.map -o $@ $^ + +%.o: %.asm + nasm -o $@ -f elf $< + +.PHONY: clean +clean: + rm -f boot/*.o $(bin) + + +.PHONY: run +run: $(bin) + qemu-system-i386 -fda $(bin) -serial file:serial.log + +.PHONY: debug +debug: $(bin) + qemu-system-i386 -fda $(bin) -serial file:serial.log -s -S + +.PHONY: disasm +disasm: $(bin) + ndisasm -o 0x7c00 $< >dis diff --git a/boot.ld b/boot.ld new file mode 100644 index 0000000..b607e11 --- /dev/null +++ b/boot.ld @@ -0,0 +1,29 @@ +OUTPUT_FORMAT(binary) +ENTRY(_start) + +SECTIONS { + . = 0x7c00; + .bootsect : { + * (.bootsect); + } + + . = 0x7e00; + _stage2_start = .; + .text : { + * (.startup); + * (.text*); + } + .data : { + * (.rodata*); + * (.data*); + } + .bss ALIGN(4) (NOLOAD): { + _bss_start = .; + * (.bss*); + * (COMMON); + . = ALIGN(4); + } + _bss_size = SIZEOF(.bss); + . = ALIGN(4); + _stage2_end = .; +}; diff --git a/boot/boot.asm b/boot/boot.asm new file mode 100644 index 0000000..5b82c2d --- /dev/null +++ b/boot/boot.asm @@ -0,0 +1,250 @@ +; first stage boot loader + cpu 8086 + bits 16 + section .bootsect + +extern _stage2_start +extern _stage2_end + +stacktop equ 7b00h +boot_driveno equ 7b00h +num_read_tries equ 7b06h ; 2 bytes +sect_pending equ 7b08h ; 2 bytes +sect_per_track equ 7b0ah ; 2 bytes +cur_head equ 7b0ch ; 2 bytes - current head +start_sect equ 7b0eh ; 2 bytes - start sector in track +destptr equ 7b10h ; 2 bytes - destination pointer +num_heads equ 7b12h ; 2 bytes - number of heads +cur_cyl equ 7b14h ; 2 bytes - current cylinder + +%macro floppy_motor_off 0 + pushf + and dl, 80h + jnz %%end ; skip if high bit is set (i.e. it's not a floppy) + mov dx, 3f2h + in al, dx + and al, 0fh + out dx, al +%%end: popf +%endmacro + + +bios_param_block: + jmp start ; 2 bytes + nop ; 1 byte + ; start of BPB at offset 3 + db "BSPL 0.1" ; 03h: OEM ident, 8 bytes + dw 512 ; 0bh: bytes per sector + db 1 ; 0dh: sectors per cluster + dw 1 ; 0eh: reserved sectors (including boot record) + db 2 ; 10h: number of FATs + dw 224 ; 11h: number of dir entries + dw 2880 ; 13h: number of sectors in volume + db 0fh ; 15h: media descriptor type (f = 3.5" HD floppy) + dw 9 ; 16h: number of sectors per FAT + dw 18 ; 18h: number of sectors per track + dw 2 ; 1ah: number of heads + dd 0 ; 1ch: number of hidden sectors + dd 0 ; 20h: high bits of sector count + db 0 ; 24h: drive number + db 0 ; 25h: winnt flags + db 28h ; 26h: signature(?) + dd 0 ; 27h: volume serial number + db "80 SIX BOOT"; 2bh: volume label, 11 bytes + db "FAT12 " ; 36h: filesystem id, 8 bytes + +start: + cld + xor ax, ax + mov ds, ax + mov es, ax + mov ss, ax + mov gs, ax + mov fs, ax + jmp 00:.setcs +.setcs: + mov sp, stacktop + mov [boot_driveno], dl + + ; query sectors per track + mov ah, 8 ; get drive parameters call, dl already has the drive + xor di, di + int 13h + jc .queryfail + and cx, 3fh + mov [sect_per_track], cx + mov cl, 8 + shr dx, cl + inc dx + mov [num_heads], dx + jmp .querydone +.queryfail: + ; in case of failure, try 18 sectors per track, 2 heads + mov word [sect_per_track], 18 + mov word [num_heads], 2 +.querydone: + +; load the rest of the code at 7e00h + mov ax, _stage2_end + sub ax, _stage2_start + add ax, 511 + mov cl, 9 + shr ax, cl + inc ax + mov [sect_pending], ax + mov ax, _stage2_start + shr ax, 1 + shr ax, 1 + shr ax, 1 + shr ax, 1 + mov es, ax ; destination segment 7e0h to allow loading up to 64k + mov word [destptr], 0 + mov word [start_sect], 1 ; start from sector 1 to skip boot sector + mov word [cur_cyl], 0 + mov word [cur_head], 0 + +.rdloop: + mov cx, [start_sect] + mov ax, [sect_pending] + sub ax, cx ; num_sect = pending - start_sect + cmp ax, [sect_per_track] + jbe .noadj + mov ax, [sect_per_track] ; read max sect_per_track at a time + sub ax, cx +.noadj: test ax, ax + jz .done + push ax ; save how many sectors we're reading + + push ax + push bx + push cx + push dx + push si + call print_hex_word + mov ax, str_rdtrack2 + call printstr + mov ax, [cur_cyl] + call print_hex_byte + mov ax, str_rdtrack3 + call printstr + mov ax, [cur_head] + call print_hex_byte + mov ax, str_rdtrack3 + call printstr + mov ax, [start_sect] + call print_hex_byte + mov ax, str_newline + call printstr + pop si + pop dx + pop cx + pop bx + pop ax + + mov ch, [cur_cyl] + mov dh, [cur_head] + mov bx, [destptr] + + inc cl ; sector numbers start from 1 + mov ah, 2 ; read sectors is call 2 + mov dl, [boot_driveno] + int 13h + jc .fail + ; track read sucessfully + mov word [start_sect], 0 ; all subsequent tracks are whole + mov ax, [cur_head] + inc ax + cmp ax, [num_heads] + jnz .skip_cyl_adv + xor ax, ax + inc byte [cur_cyl] +.skip_cyl_adv: + mov [cur_head], ax + + pop ax ; num_sect + sub [sect_pending], ax + push cx + mov cl, 9 + shl ax, cl ; convert to bytes + pop cx + add [destptr], ax + jnz .rdloop + + ; loaded sucessfully, reset es back to 0 and jump +.done: xor ax, ax + mov es, ax + jmp _stage2_start + +.fail: add sp, 2 ; clear num_sect off the stack + dec word [num_read_tries] + jz .abort + + ; reset controller and retry + xor ax, ax + mov dl, [boot_driveno] + int 13h + jmp .rdloop + + ; failed to load second sector +.abort: xor ax, ax + mov es, ax + floppy_motor_off ; turn off floppy motor (if dl is < 80h) + mov ax, str_load_fail + call printstr +.hang: hlt + jmp .hang + + ; expects string ptr in ax +printstr: + mov si, ax +.loop: mov al, [si] + inc si + test al, al + jz .done + mov ah, 0eh + mov bx, 7 + int 10h + jmp .loop +.done: ret + +print_hex_word: + mov cx, 4 ; 4 digits to print + jmp print_n_hex_digits + +print_hex_byte: + mov cx, 2 ; 2 digits to print + mov ah, al ; move them in place + +print_n_hex_digits: + rol ax, 1 + rol ax, 1 + rol ax, 1 + rol ax, 1 + mov dx, ax ; save ax, print_hex_digit destroys it + call print_hex_digit + mov ax, dx + dec cx + jnz print_n_hex_digits + ret + +print_hex_digit: + mov bl, al + and bx, 0fh + mov al, [bx + .hexdig_tab] + mov ah, 0eh + mov bx, 7 + int 10h + ret + +.hexdig_tab: + db "0123456789abcdef" + +str_rdtrack2 db " from ",0 +str_rdtrack3 db "/",0 +str_load_fail db "Failed to load 2nd stage!",0 +str_newline db 13,10,0 + + times 510-($-$$) db 0 +bootsig dw 0xaa55 + +; vi:set ts=8 sts=8 sw=8 ft=nasm: diff --git a/boot/boot2.asm b/boot/boot2.asm new file mode 100644 index 0000000..6837579 --- /dev/null +++ b/boot/boot2.asm @@ -0,0 +1,18 @@ +; second stage boot loader C startup + cpu 8086 + bits 16 + section .startup + +extern bootmain + +global _start +_start: + ; TODO floppy off if necessary + ; TODO zero .bss + call bootmain + +hang: hlt + jmp hang + + +; vi:set ts=8 sts=8 sw=8 ft=nasm: diff --git a/boot/main.c b/boot/main.c new file mode 100644 index 0000000..7110581 --- /dev/null +++ b/boot/main.c @@ -0,0 +1,13 @@ +void bootmain(void) +{ + int i, j; + unsigned short __far *vmem = (void __far*)0xb8000000ul; + unsigned short c; + + for(i=0; i<25; i++) { + c = ((i & 0xf) << 8) | '@'; + for(j=0; j<80; j++) { + *vmem++ = c; + } + } +} -- 1.7.10.4