hacking the 1st stage loader
authorJohn Tsiombikas <nuclear@member.fsf.org>
Sun, 8 Apr 2018 05:11:47 +0000 (08:11 +0300)
committerJohn Tsiombikas <nuclear@member.fsf.org>
Sun, 8 Apr 2018 05:11:47 +0000 (08:11 +0300)
gdbnotes [new file with mode: 0644]
pcboot.ld
src/boot/boot.s
src/boot/boot2.s [new file with mode: 0644]

diff --git a/gdbnotes b/gdbnotes
new file mode 100644 (file)
index 0000000..e03261f
--- /dev/null
+++ b/gdbnotes
@@ -0,0 +1,10 @@
+$ qemu-system-i386 -fda test.bin -s -S
+$ gdb
+target remote localhost:1234
+set architecture i8086
+display/i $pc
+b *0x7c00
+
+examine register with: i r eax
+
+$ objdump -D test
index f629124..28fb7e6 100644 (file)
--- a/pcboot.ld
+++ b/pcboot.ld
@@ -1,10 +1,20 @@
 OUTPUT_ARCH(i386)
 
 SECTIONS {
-       /* BIOS will load us at 0x7c000h */
-       . = 0x7c000;
+       /* BIOS loads the boot code at 0000:7c00 */
+       . = 0x7c00;
 
        .boot : { * (.boot); }
+
+       /* second stage boot loader */
+       .boot2 : { * (.boot2); }
+       _boot2_size = SIZEOF(.boot2);
+
+       /* main program will be loaded at 1MB by the second stage
+        * boot loader
+        */
+       . = 1M;
+
        .startup : { * (.startup); }
        .text : { * (.text); }
        .rodata : { * (.rodata); }
index e3fd206..ffd1408 100644 (file)
        .code16
        .section .boot,"a"
 
-       mov $0x13, %ax
-       int $0x10
-
-       mov $1, %al
-       mov $0x3c8, %dx
-       outb %al, %dx
-       mov $0x3c9, %dx
-       mov $63, %al
-       outb %al, %dx
-       xor %al, %al
-       outb %al, %dx
-       outb %al, %dx
-
-       mov $200, %ebx
-       mov $0x00000101, %eax
-       pushl $0xa000
-       popl %es
-       xor %di, %di
-fill:
-       mov %ebx, %ecx
-       and $1, %ecx
-       jnz 0f
-       rol $16, %eax
-0:     mov $80, %ecx
-       rep stosl
-       dec %ebx
-       jnz fill
+       cli
+       cld
+       # move stack to the top of 512k
+       mov $0x7000, %ax
+       mov %ax, %ss
+       xor %sp, %sp
+       # use the code segment for data access
+       mov %cs, %ax
+       mov %ax, %ds
+       mov %ax, %es
+
+       call clearscr
+
+       mov $_boot2_size, %eax
+       call print_num
+
+       # load the second stage boot loader and jump to it
+       mov $_boot2_size, %eax
+       mov %eax, %ebx
+       shr $9, %eax
+       and $0x1ff, %ebx
+       jz 0f
+       inc %eax
+0:     pushw %ax
+       pushw $1
+       # set es to the start of the destination buffer to allow reading in
+       # full 64k chunks
+       mov $boot2_addr, %bx
+       shr $4, %bx
+       mov %bx, %es
+       xor %bx, %bx
+       call readsect
+       jmp boot2_addr
 
        cli
        hlt
 
+       .set SECT_PER_TRACK, 18
+
+       .set ARG_NSECT, 6
+       .set ARG_SIDX, 4
+       .set VAR_NTRACKS, -2
+
+# readsect(first, num)
+readsect:
+       push %bp
+       mov %sp, %bp
+       sub $2, %sp
+
+       # calculate how many tracks to read
+       mov ARG_NSECT(%bp), %ax
+       xor %dx, %dx
+       mov $SECT_PER_TRACK, %cx
+       div %cx
+       cmp $0, %dx
+       jz 0f
+       inc %ax
+0:     mov %ax, VAR_NTRACKS(%bp)
+
+       xor %cx, %cx
+0:     cmp VAR_NTRACKS(%bp), %cx
+       jz 0f
+       push %cx
+       call read_track
+       pop %cx
+       jmp 0b
+0:
+       # TODO cont.
+       pop %bp
+       ret
+
+read_track:
+       ret
+
+clearscr:
+       push %es
+       pushw $0xb800
+       pop %es
+       xor %eax, %eax
+       xor %di, %di
+       movl $500, %ecx
+       rep stosl
+       pop %es
+       ret
+
+print_num:
+       # save es
+       push %es
+
+       xor %cx, %cx
+       movw $numbuf, %si
+       mov $10, %ebx
+
+0:     xor %edx, %edx
+       div %ebx
+       add $48, %dl
+       mov %dl, (%si)
+       inc %si
+       inc %cx
+       cmp $0, %eax
+       jnz 0b
+
+       # print the backwards string
+       pushw $0xb800
+       pop %es
+       xor %di, %di
+
+0:     dec %si
+       mov (%si), %al
+       movb %al, %es:(%di)
+       inc %di
+       mov $7, %al
+       movb %al, %es:(%di)
+       inc %di
+       dec %cx
+       jnz 0b
+
+       # restore es
+       pop %es
+       ret
+
+numbuf: .space 10
        .org 510
        .byte 0x55
        .byte 0xaa
+
+boot2_addr:
diff --git a/src/boot/boot2.s b/src/boot/boot2.s
new file mode 100644 (file)
index 0000000..47121ee
--- /dev/null
@@ -0,0 +1,36 @@
+# this is the second-stage boot loader
+       .code16
+       .section .boot2,"a"
+
+       mov $0x13, %ax
+       int $0x10
+
+       pushw $63
+       pushw $63
+       pushw $0
+       pushw $0xff
+       call set_palette
+       add $8, %sp
+
+       pushw $0xa000
+       pop %es
+       xor %di, %di
+       mov $16000, %ecx
+       mov $0xffffffff, %eax
+       rep stosl
+
+       hlt
+
+set_palette:
+       mov %sp, %bp
+       mov $0x3c8, %dx
+       movw 2(%bp), %ax
+       outb %al, %dx
+       inc %dx
+       movw 4(%bp), %ax
+       outb %al, %dx
+       movw 6(%bp), %ax
+       outb %al, %dx
+       movw 8(%bp), %ax
+       outb %al, %dx
+       ret