:: commit 563825e44d87cc7ad84ed311b5065552d2674498

mintsuki <mintsuki@protonmail.com> — 2019-05-30 14:25

parents: 3c4c1a878a

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);
     }
 
 }
tab: 248 wrap: offon