second_stage.asm

back


;
; Copyright (c) 2019, k4m1 <k4m1@protonmail.com>
; All rights reserved. Read /LICENSE for full license agreement.
; 
; This file contains code responsible of enabling A20, and
; then proceeding to call loader_main
;

loader_entry:
	pop	dx
	mov	sp, 0x9c00
	mov	bp, sp

	mov	byte [boot_device], dl

	call	enable_a20_with_bios
	test	eax, eax
	jz	.a20_is_on

	call	enable_a20_with_kbdctl
	test	eax, eax
	jz	.a20_is_on

	call	enable_a20_with_fast_92
	call	check_a20
	test	eax, eax
	jz	.a20_is_on

	call	enable_a20_ioee
	test	eax, eax
	jz	.a20_is_on

	mov	esi, msg_a20_fail
	call	panic

.a20_is_on:
	mov	si, msg_a20_is_on
	call	write_serial

	call	loader_main

	cli
	hlt

; =================================================================== ;
; Messages to output                                                  ;
; =================================================================== ;
msg_a20_fail:
	db	"FAILED TO ENABLE A20!", 0

msg_a20_is_on:
	db	"A20 enabled.", 0x0A, 0x0D, 0

; =================================================================== ;
; Code related to a20 gate.                                           ;
; =================================================================== ;

enable_a20_with_fast_92:
	in	al, 0x92
	test	al, 2
	jnz	.no_92
	or	al, 2
	out	0x92, al
.no_92:
	ret

kbd_wait_for_clear:
	in	al, 0x64
	test	al, 2
	jnz	kbd_wait_for_clear
	ret

enable_a20_ioee:
	push	bp
	mov	bp, sp
	in	al, 0xee
	call	check_a20
	mov	sp, bp
	pop	bp
	ret

enable_a20_with_kbdctl:
	push	bp
	mov	bp, sp

	cli
	call	kbd_wait_for_clear

	; Send write command
	mov	al, 0xd1
	out	0x64, al

	; Wait for kbdctl
	call	kbd_wait_for_clear

	; set A20 on
	mov	al, 0xdf
	out	0x60, al

	; wait for kbdctl
	call	kbd_wait_for_clear

	; Check if we succeeded or not
	call	check_a20

	sti
	mov	sp, bp
	pop	bp
	ret

check_a20:
	; Check if we enabled a20 or not
	mov	eax, 0x012345
	mov	ebx, 0x112345
	mov	[eax], eax
	mov	[ebx], ebx
	mov	eax, dword [eax]
	mov	ebx, dword [ebx]
	cmp	eax, ebx
	jne	.a20_on
	mov	eax, 1
	ret
.a20_on:
	xor	eax, eax
	ret

enable_a20_with_bios:
	; check if BIOS support is present
	mov	ax, 0x2403
	int	0x15
	jb	.fail
	test	ah, ah
	jz	.fail

	; It is? get a20 status
	mov	ax, 0x2402
	int	0x15
	jb	.fail
	test	ah, ah
	jz	.fail

	; See if a20 is already activated
	cmp	al, 1
	jz	.a20_is_on

	mov	ax, 0x2401
	int	0x15
	jb	.fail
	test	ah, ah
	jz	.fail

.a20_is_on:
	mov	eax, 0
	ret

.fail:
	mov	eax, 1
	ret

; Reserved single byte to store boot-device ID
boot_device:
	db	0

%include "src/consoles.asm"
%include "src/loader_main.asm"