My 4th bootloader, comments
Posted: Mon Apr 09, 2018 3:26 am
This is my 5th bootloader, can you give advises or comments or did i miss something, or something will cause a problem in the future. i am still learning i am not sure about this code.
Code: Select all
[ORG 0x7C00]
[BITS 16]
%define PS2_DATA_PORT 0x60
%define PS2_STATUS_REG 0x64
%define PS2_CMD_REG 0x64
%define PS2_STATUS_OUTPUT_FULL 0x1 ; 0000`0001
%define PS2_STATUS_INPUT_FULL 0x2 ; 0000`0010
%define PS2_CMD_DISABLE_PORT1 0xAD
%define PS2_CMD_DISABLE_PORT2 0xA7
%define PS2_CMD_READ_OUTPUT 0xD0
%define PS2_CMD_WRITE_OUTPUT 0xD1 ; write byte to controler output port
%define PS2_CMD_ENABLE_PORT1 0xAE
%define PS2_CMD_ENABLE_PORT2 0xA8
%define PS2_OUTPUT_BIT_A20 0x2 ; 0000`0010
%define ERR_INT13_RESET 0x1
%define ERR_INT13_EX 0x2
%define ERR_INT13_READ 0x3
%define ERR_STAGE2_MAGIC 0x4
%define ERR_A20_LINE 0x5
%define ERR_STAGE2_FAILED 0x6
%define STAGE2_SECTOR_INDEX 1 ;sectors are counted from 0, the bootloader (this code) is in sector 0
%define STAGE2_SECTORS_COUNT 2
%define STAGE2_BASE_ADDRESS 0x7E00
%define STAGE2_MAGIC 0x66AA
%define STAGE2_ENTRYPOINT_ADDRESS STAGE2_BASE_ADDRESS + 2
Main:
jmp 0x00:Init
nop
cBootDrive: db 0
cLastError: db 0x0F
SzErrorMsgPart1: db "Critical error: 0x", 0x0
SzErrorMsgPart2: db 0xA, 0xA, 0xD, "Press any key to restart", 0x0
SzBooting: db "Booting...", 0xA, 0xD, 0x0
DapRead: db 0x10
db 0
dw STAGE2_SECTORS_COUNT
dd STAGE2_BASE_ADDRESS
dq STAGE2_SECTOR_INDEX
Gdt: dq 0 ; null desc
dw 0xFFFF
dw 0
db 0
db 0x92 ; 1001`0010
db 0xCF ; 1100`1111
db 0
GdtPtr: dw (GdtPtr - Gdt) - 1
dd Gdt
;assuming there is no keyboard
A20Test: ; if CF is set, A20 is disaled
push ds
push es
push di
push si
cli
clc
xor ax, ax
mov es, ax
mov di, 0x500 ; 0000:0500
mov ax, 0xFFFF
mov ds, ax
mov si, 0x510 ; (0xFFFF + 0x510) - (0x10 "16 bytes")
mov al, byte [es:di]
push ax
mov al, byte [ds:si]
push ax
mov byte [es:di], 0x00
mov byte [ds:si], 0xFF
cmp byte [es:di], 0xFF
jne .L1
stc
.L1:
pop ax
mov byte [es:di], al
pop ax
mov byte [ds:si], al
sti
pop es
pop di
pop si
pop ds
ret
PS2WaitForData:
in al, PS2_STATUS_REG
test al, PS2_STATUS_OUTPUT_FULL
jnz PS2WaitForCmd
ret
PS2WaitForCmd:
in al, PS2_STATUS_REG
test al, PS2_STATUS_INPUT_FULL
jnz PS2WaitForCmd
ret
PutS:
mov ah, 0x0E
.L2:
lodsb
test al, al
jz .L1
int 0x10
jmp .L2
.L1:
ret
FlushError:
lea si, [SzErrorMsgPart1]
call PutS
mov ah, 0xE
mov al, [cLastError]
cmp al, 0xA
jl .L1
add al, 0x7
.L1:
add al, '0'
int 0x10
lea si, [SzErrorMsgPart2]
call PutS
xor ah, ah
int 0x16 ;read key, block mode
jmp 0xFFFF:0x000 ;restart
Init:
cli
xor ax, ax
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
mov sp, 0x7B00
sti
mov byte [cBootDrive], dl
ResetDisk:
mov byte [cLastError], ERR_INT13_RESET ; set last error to not be 0
xor ax, ax
int 0x13
jc FlushError
CheckInt13Ex:
inc byte [cLastError] ; ERR_INT13_EX
mov bx, 0x55AA
mov ah, 0x41
int 0x13
jc FlushError
FindStage2:
inc byte [cLastError] ; ERR_INT13_READ
mov ah, 0x42
lea si, [DapRead]
int 0x13
jc FlushError
CheckStage2Magic:
inc byte [cLastError] ; ERR_STAGE2_MAGIC
lea si, [STAGE2_BASE_ADDRESS]
lodsw
cmp ax, STAGE2_MAGIC
jne FlushError
A20Enable:
xor cl, cl
inc byte [cLastError] ; ERR_A20_LINE
A20FromBios:
call A20Test
jnc EnterUnreal
mov ax, 0x2401
int 0x15
jnc EnterUnreal
call A20Test
jnc EnterUnreal
A20FromPS2:
call PS2WaitForCmd
mov al, PS2_CMD_DISABLE_PORT1
out PS2_CMD_REG, al
call PS2WaitForCmd
mov al, PS2_CMD_DISABLE_PORT2
out PS2_CMD_REG, al
call PS2WaitForCmd
mov al, PS2_CMD_READ_OUTPUT
out PS2_CMD_REG, al
call PS2WaitForData
in al, PS2_DATA_PORT ;get output port current value
push ax ;save it
call PS2WaitForCmd
mov al, PS2_CMD_WRITE_OUTPUT
out PS2_CMD_REG, al
call PS2WaitForCmd
pop ax
or ax, PS2_OUTPUT_BIT_A20
out PS2_DATA_PORT, al
call PS2WaitForCmd
mov al, PS2_CMD_ENABLE_PORT1
out PS2_CMD_REG, al
call PS2WaitForCmd
mov al, PS2_CMD_ENABLE_PORT2
out PS2_CMD_REG, al
call A20Test
jnc EnterUnreal
mov ax, 0x0E41
int 0x10
inc cl
cmp cl, 4
jbe A20FromBios
; final try, risky
A20FastGate:
in al, 0x92
or al, 2
out 0x92, al
mov ax, 0x0E42
int 0x10
call A20Test
jc FlushError
EnterUnreal:
cli
push ds
lgdt [GdtPtr]
mov eax, cr0
or al, 1 ; enter protected mode
mov cr0, eax
mov bx, 0x08 ;use the first descriptor
mov ds, bx
and al, 0xFE ; remove protected mode bit
mov cr0, eax
pop ds
sti
EnterStage2:
lea si, [SzBooting]
call PutS
;@TODO: jmp to stage2
SysHlt:
cli
hlt
jmp SysHlt
times 510 - ($ - $$) db 0
db 0x55
db 0xAA