Enable A20 line and enter 'unreal mode' in the bootsect
diff --git a/bootsect/a20_enabler.inc b/bootsect/a20_enabler.inc
new file mode 100644
index 00000000..0a50d234
--- /dev/null
+++ b/bootsect/a20_enabler.inc
@@ -0,0 +1,126 @@
+a20_check:
+
+; *************************************************
+; Checks if the A20 address line is enabled
+; *************************************************
+
+; OUT:
+; Carry if disabled, cleared if enabled
+
+push ax ; Save registers
+push bx
+push es
+push fs
+
+xor ax, ax ; Set ES segment to zero
+mov es, ax
+not ax ; Set FS segment to 0xFFFF
+mov fs, ax
+
+mov ax, word [es:0x7DFE] ; Check using boot signature
+cmp word [fs:0x7E0E], ax ; If A20 is disabled, this should be the
+ ; same address as the boot signature
+je .change_values ; If they are equal, check again with another value
+
+.enabled:
+
+clc ; A20 is enabled, clear carry flag
+jmp .done
+
+.change_values:
+
+mov word [es:0x7DFE], 0x1234 ; Change the value of 0000:7DFE to 0x1234
+cmp word [fs:0x7E0E], 0x1234 ; Is FFFF:7E0E changed as well?
+jne .enabled ; If it is, A20 is enabled
+
+stc ; Otherwise set carry
+
+.done:
+
+mov word [es:0x7DFE], ax ; Restore boot signature
+pop fs ; Restore registers
+pop es
+pop bx
+pop ax
+ret ; Exit routine
+
+
+
+
+enable_a20:
+
+; ********************************************
+; Tries to enable the A20 address line
+; ********************************************
+
+; OUT:
+; Carry cleared if success, set if fail
+
+push eax ; Save registers
+
+call a20_check ; Check if a20 is already enabled
+jnc .done ; If it is, we are done
+
+mov ax, 0x2401 ; Use BIOS to try to enable a20
+int 0x15
+
+call a20_check ; Check again to see if BIOS succeeded
+jnc .done ; If it has, we are done
+
+.keyboard_method:
+
+cli ; Disable interrupts
+
+call .a20wait ; Use the keyboard controller to try and
+mov al, 0xAD ; open the A20 gate
+out 0x64, al
+
+call .a20wait
+mov al, 0xD0
+out 0x64, al
+
+call .a20wait2
+in al, 0x60
+push eax
+
+call .a20wait
+mov al, 0xD1
+out 0x64, al
+
+call .a20wait
+pop eax
+or al, 2
+out 0x60, al
+
+call .a20wait
+mov al, 0xAE
+out 0x64, al
+
+call .a20wait
+sti ; Enable interrupts back
+
+jmp .keyboard_done
+
+.a20wait:
+
+in al, 0x64
+test al, 2
+jnz .a20wait
+ret
+
+.a20wait2:
+
+in al, 0x64
+test al, 1
+jz .a20wait2
+ret
+
+.keyboard_done:
+
+call a20_check ; Check for success
+
+; Now just quit the routine, forwarding the carry flag to the caller
+
+.done:
+pop eax
+ret
diff --git a/bootsect/bootsect.asm b/bootsect/bootsect.asm
index 08d6e97b..d9668a1b 100644
--- a/bootsect/bootsect.asm
+++ b/bootsect/bootsect.asm
@@ -15,8 +15,6 @@ mov ss, ax
mov sp, 0x7c00
sti
-mov byte [drive_number], dl
-
mov si, LoadingMsg
call simple_print
@@ -27,7 +25,7 @@ call simple_print
mov ax, 1
mov ebx, 0x7e00
-mov cx, 7
+mov cx, 1
call read_sectors
jc err
@@ -45,23 +43,82 @@ halt:
hlt
jmp halt
-;Data
+; Data
-LoadingMsg db 0x0D, 0x0A, '<qLoader 2>', 0x0D, 0x0A, 0x0A, 0x00
-Stage2Msg db 'stage1: Loading stage2...', 0x00
-ErrMsg db 0x0D, 0x0A, 'Error, system halted.', 0x00
-DoneMsg db ' DONE', 0x0D, 0x0A, 0x00
+LoadingMsg db 0x0D, 0x0A, '<qLoader 2>', 0x0D, 0x0A, 0x0A, 0x00
+Stage2Msg db 'stage1: Loading stage2...', 0x00
+ErrMsg db 0x0D, 0x0A, 'Error, system halted.', 0x00
+DoneMsg db ' DONE', 0x0D, 0x0A, 0x00
times 0xda-($-$$) db 0
times 6 db 0
-;Includes
+; Includes
%include 'simple_print.inc'
%include 'disk.inc'
-drive_number db 0
-
times 0x1b8-($-$$) db 0
times 510-($-$$) db 0
dw 0xaa55
+
+; ********************* Stage 2 *********************
+
+; ***** A20 *****
+
+call enable_a20
+jc err
+
+; Enable 4GiB limits
+
+lgdt [GDT] ; Load the GDT
+
+cli
+
+mov eax, cr0
+or eax, 00000001b
+mov cr0, eax
+
+jmp 0x08:.pmodeu
+
+.pmodeu:
+
+mov ax, 0x10
+mov ds, ax
+mov es, ax
+mov fs, ax
+mov gs, ax
+mov ss, ax
+
+mov eax, cr0
+and eax, 11111110b
+mov cr0, eax
+
+jmp 0x0000:.unreal_mode
+
+.unreal_mode:
+
+xor ax, ax
+mov ds, ax
+mov es, ax
+mov fs, ax
+mov gs, ax
+mov ss, ax
+
+sti
+
+; Load stage 3
+
+mov ax, 2
+mov ebx, 0x8000
+mov cx, 6
+call read_sectors
+
+jc err
+
+jmp 0x8000
+
+%include 'a20_enabler.inc'
+%include 'gdt.inc'
+
+times 1024-($-$$) db 0
diff --git a/bootsect/gdt.inc b/bootsect/gdt.inc
new file mode 100644
index 00000000..15045d27
--- /dev/null
+++ b/bootsect/gdt.inc
@@ -0,0 +1,59 @@
+GDT:
+
+dw .GDTEnd - .GDTStart - 1 ; GDT size
+dd .GDTStart ; GDT start
+
+.GDTStart:
+
+; Null descriptor (required)
+
+.NullDescriptor:
+
+dw 0x0000 ; Limit
+dw 0x0000 ; Base (low 16 bits)
+db 0x00 ; Base (mid 8 bits)
+db 00000000b ; Access
+db 00000000b ; Granularity
+db 0x00 ; Base (high 8 bits)
+
+; Unreal mode
+
+.UnrealCode:
+
+dw 0xFFFF ; Limit
+dw 0x0000 ; Base (low 16 bits)
+db 0x00 ; Base (mid 8 bits)
+db 10011010b ; Access
+db 10001111b ; Granularity
+db 0x00 ; Base (high 8 bits)
+
+.UnrealData:
+
+dw 0xFFFF ; Limit
+dw 0x0000 ; Base (low 16 bits)
+db 0x00 ; Base (mid 8 bits)
+db 10010010b ; Access
+db 10001111b ; Granularity
+db 0x00 ; Base (high 8 bits)
+
+; Protected mode
+
+.PmodeCode:
+
+dw 0xFFFF ; Limit
+dw 0x0000 ; Base (low 16 bits)
+db 0x00 ; Base (mid 8 bits)
+db 10011010b ; Access
+db 11001111b ; Granularity
+db 0x00 ; Base (high 8 bits)
+
+.PmodeData:
+
+dw 0xFFFF ; Limit
+dw 0x0000 ; Base (low 16 bits)
+db 0x00 ; Base (mid 8 bits)
+db 10010010b ; Access
+db 11001111b ; Granularity
+db 0x00 ; Base (high 8 bits)
+
+.GDTEnd:
diff --git a/linker.ld b/linker.ld
index 10e9a0f1..941634d8 100644
--- a/linker.ld
+++ b/linker.ld
@@ -3,7 +3,7 @@ ENTRY(main)
SECTIONS
{
- . = 0x7e00;
+ . = 0x8000;
.text : {
bootsect_begin = .;
@@ -14,7 +14,7 @@ SECTIONS
.data : {
KEEP(*(.data*))
KEEP(*(.bss*))
- . += 3584 - (. - bootsect_begin);
+ . += 3072 - (. - bootsect_begin);
}
}
