aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mubios/arch/interrupt.S346
-rw-r--r--mubios/arch/mode_switch.S103
2 files changed, 166 insertions, 283 deletions
diff --git a/mubios/arch/interrupt.S b/mubios/arch/interrupt.S
index 88ccfbf..0822b1a 100644
--- a/mubios/arch/interrupt.S
+++ b/mubios/arch/interrupt.S
@@ -6,31 +6,21 @@
#
# RCC-Project is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free
-# Software Foundation; either version 3 of the License, or (at your option) any
-# later version.
+# Software Foundation; either version 3 of the License, or (at your option)
+# any later version.
#
-# RCC-Project is distributed in the hope that it will be useful, but WITHOUT ANY
-# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
-# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along with
-# RCC-Project; see the file COPYING. If not see
-# <http://www.gnu.org/licenses/>.
+# RCC-Project is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+# more details.
.intel_syntax noprefix
.code16
- .equ ATA_DATA, 0x1F0
- .equ ATA_SECTOR_COUNT, 0x1F2
- .equ ATA_LBA_LOW, 0x1F3
- .equ ATA_LBA_MID, 0x1F4
- .equ ATA_LBA_HIGH, 0x1F5
- .equ ATA_DRIVE, 0x1F6
- .equ ATA_STATUS, 0x1F7
- .equ ATA_COMMAND, 0x1F7
-
.section .text16.irq, "ax"
+ .extern enter_protected_service
+
.global int1a_entry
.type int1a_entry, @function
@@ -58,268 +48,58 @@ int1a_entry:
int1a_return:
iret
- .global int10_entry
- .type int10_entry, @function
-
-int10_entry:
- cmp ah, 0x0E
- jne int10_return
-
- push bp
- mov bp, sp
-
- push ax
- push bx
- push dx
- push si
- push di
- push ds
- push es
-
- xor ax, ax
- mov ds, ax
-
- mov ax, 0xB800
- mov es, ax
-
- mov si, 0x0050
- mov dx, word ptr [si]
-
- mov al, byte ptr [bp - 2]
- mov bl, byte ptr [bp - 4]
-
- cmp al, 0x0D
- je int10_carriage_return
-
- cmp al, 0x0A
- je int10_line_feed
-
- cmp al, 0x08
- je int10_backspace
-
- mov di, dx
- shl di, 1
- mov ah, bl
- mov word ptr es:[di], ax
- inc dx
- jmp int10_store_cursor
-
-
-int10_carriage_return:
- mov ax, dx
- mov si, 80
- xor dx, dx
- div si
- mul si
- mov dx, ax
- jmp int10_store_cursor
-
-int10_line_feed:
- add dx, 80
- jmp int10_store_cursor
-
-int10_backspace:
- cmp dx, 0
- je int10_store_cursor
-
- dec dx
- mov di, dx
- shl di, 1
- mov al, 0x20
- mov ah, bl
- mov word ptr es:[di], ax
-
-int10_store_cursor:
- cmp dx, 2000
- jb int10_save_cursor
-
- xor dx, dx
-
-int10_save_cursor:
- mov word ptr [0x0050], dx
-
- pop es
- pop ds
- pop di
- pop si
- pop dx
- pop bx
- pop ax
- pop bp
-
-int10_return:
- iret
-
- .global int13_entry
- .type int13_entry, @function
-
-int13_entry:
- cmp ah, 0x42
- je int13_extended_read
-
- cmp ah, 0x41
- jne int13_return
-
- push bp
- mov bp, sp
-
- cmp bx, 0x55AA
- jne int13_fail
-
- mov bx, 0xAA55
- mov cx, 0x0001
- mov ax, 0x3000
-
- # Clear CF in the FLAGS saved by INT.
- and word ptr [bp + 6], 0xFFFE
-
- pop bp
- iret
-
-int13_fail:
- mov ah, 0x01
-
- # Set CF in the FLAGS saved by INT.
- or word ptr [bp + 6], 0x0001
-
- pop bp
- iret
-
-int13_return:
- push bp
- mov bp, sp
-
- mov ah, 0x01
-
- # Set CF in the FLAGS saved by INT.
- or word ptr [bp + 6], 0x0001
-
- pop bp
- iret
-int13_extended_read:
- push bp
- mov bp, sp
-
- push bx
- push cx
- push dx
- push si
- push di
- push ds
- push es
-
- # DAP size must be 0x10.
- cmp byte ptr [si], 0x10
- jne int13_extended_fail
-
- # This step supports exactly one sector.
- cmp word ptr [si + 2], 1
- jne int13_extended_fail
-
- # Reject LBA values above 28 bits.
- mov ax, word ptr [si + 12]
- or ax, word ptr [si + 14]
- jnz int13_extended_fail
-
- mov ax, word ptr [si + 10]
- test ax, 0xF000
- jnz int13_extended_fail
-
- # Load DAP buffer ES:DI.
- mov di, word ptr [si + 4]
- mov ax, word ptr [si + 6]
- mov es, ax
-
- cld
-
- # Select ATA drive from DL.
- mov al, 0xE0
- test dl, 1
- jz int13_drive_selected
-
- or al, 0x10
-
-int13_drive_selected:
- mov dx, ATA_DRIVE
- out dx, al
-
- # 400 ns delay.
- mov dx, ATA_STATUS
- in al, dx
- in al, dx
- in al, dx
- in al, dx
-
- # Sector count = 1.
- mov dx, ATA_SECTOR_COUNT
- mov al, 1
- out dx, al
-
- # LBA byte 0.
- mov ax, word ptr [si + 8]
- mov dx, ATA_LBA_LOW
- out dx, al
-
- # LBA byte 1.
- mov al, ah
- mov dx, ATA_LBA_MID
- out dx, al
-
- # LBA byte 2.
- mov ax, word ptr [si + 10]
- mov dx, ATA_LBA_HIGH
- out dx, al
-
- # READ SECTORS command.
- mov dx, ATA_COMMAND
- mov al, 0x20
- out dx, al
-
-int13_wait_data:
- mov dx, ATA_STATUS
- in al, dx
-
- test al, 0x80
- jnz int13_wait_data
-
- test al, 0x01
- jnz int13_extended_fail
-
- test al, 0x08
- jz int13_wait_data
-
- # Read one 512-byte sector.
- mov dx, ATA_DATA
- mov cx, 256
- rep insw
-
- # Clear CF in the saved FLAGS.
- and word ptr [bp + 6], 0xFFFE
-
- pop es
- pop ds
- pop di
- pop si
- pop dx
- pop cx
- pop bx
- pop bp
-
- xor ax, ax
- iret
-
-int13_extended_fail:
- # Set CF in the saved FLAGS.
- or word ptr [bp + 6], 0x0001
-
- pop es
- pop ds
- pop di
- pop si
- pop dx
- pop cx
- pop bx
- pop bp
-
- mov ax, 0x0100
- iret
+ .macro BIOS_SERVICE_ENTRY name, vector
+ .global \name
+ .type \name, @function
+
+\name:
+ # Build struct bios_regs on the interrupted real-mode stack.
+ push 0
+ push es
+ push ds
+ push bp
+ push di
+ push si
+ push dx
+ push cx
+ push bx
+ push ax
+
+ mov bp, sp
+ mov ax, word ptr [bp + 24]
+ mov word ptr [bp + 18], ax
+
+ # ESI = linear address of struct bios_regs.
+ movzx esi, sp
+ xor eax, eax
+ mov ax, ss
+ shl eax, 4
+ add esi, eax
+
+ # EBP = original SS:SP return point, packed as SS:SP.
+ movzx ebp, sp
+ sub ebp, 2
+ xor eax, eax
+ mov ax, ss
+ shl eax, 16
+ or ebp, eax
+
+ mov edi, \vector
+ call enter_protected_service
+
+ # Restore the context modified by the C service.
+ pop ax
+ pop bx
+ pop cx
+ pop dx
+ pop si
+ pop di
+ pop bp
+ pop ds
+ pop es
+ add sp, 2
+ iret
+ .endm
+
+ BIOS_SERVICE_ENTRY int10_entry, 0x10
+ BIOS_SERVICE_ENTRY int13_entry, 0x13
diff --git a/mubios/arch/mode_switch.S b/mubios/arch/mode_switch.S
index 9b2643a..9dc0ab5 100644
--- a/mubios/arch/mode_switch.S
+++ b/mubios/arch/mode_switch.S
@@ -23,6 +23,7 @@
.section .text16.mode, "ax"
.extern post_main
+ .extern bios_service_dispatch
.global enter_protected_mode
.type enter_protected_mode, @function
@@ -59,6 +60,35 @@ enter_protected_mode:
.long protected_mode_entry
.word 0x0008
+ .global enter_protected_service
+ .type enter_protected_service, @function
+
+enter_protected_service:
+ cli
+
+ in al, 0x92
+ or al, 0x02
+ and al, 0xFE
+ out 0x92, al
+
+ push cs
+ pop ds
+
+ call 2f
+2:
+ pop bx
+ add bx, gdt_descriptor - 2b
+ lgdt [bx]
+
+ mov eax, cr0
+ or eax, 0x00000001
+ mov cr0, eax
+
+ .byte 0x66
+ .byte 0xEA
+ .long protected_service_entry
+ .word 0x0008
+
.align 8
gdt_start:
@@ -119,6 +149,30 @@ protected_mode_halt:
hlt
jmp protected_mode_halt
+ .global protected_service_entry
+ .type protected_service_entry, @function
+
+protected_service_entry:
+ mov ax, 0x0010
+ mov ds, ax
+ mov es, ax
+ mov ss, ax
+ mov fs, ax
+ mov gs, ax
+
+ mov esp, 0x00007000
+
+ push esi
+ push edi
+ call bios_service_dispatch
+ add esp, 8
+
+ call leave_service_protected
+
+protected_service_halt:
+ hlt
+ jmp protected_service_halt
+
.global leave_protected_mode
.type leave_protected_mode, @function
@@ -152,6 +206,30 @@ leave_protected_mode:
.byte 0x66
.byte 0xFF, 0x2C, 0x24
+ .global leave_service_protected
+ .type leave_service_protected, @function
+
+leave_service_protected:
+ sub esp, 16
+
+ mov eax, OFFSET FLAT:protected16_service_return
+ mov ebx, OFFSET FLAT:__rom_start
+ sub eax, ebx
+ mov word ptr [esp], ax
+ mov word ptr [esp + 2], 0x0018
+
+ mov eax, OFFSET FLAT:real_mode_service_return
+ mov ebx, OFFSET FLAT:__rom_start
+ sub eax, ebx
+ mov word ptr [esp + 4], ax
+
+ shr ebx, 4
+ mov word ptr [esp + 6], bx
+ mov dword ptr [esp + 8], ebp
+
+ .byte 0x66
+ .byte 0xFF, 0x2C, 0x24
+
.code16
.section .text16.mode, "ax"
@@ -171,6 +249,19 @@ protected16_return:
# Jump to the prepared real-mode CS:IP pointer.
.byte 0xFF, 0x2F
+ .global protected16_service_return
+ .type protected16_service_return, @function
+
+protected16_service_return:
+ mov bx, sp
+ add bx, 4
+
+ mov eax, cr0
+ and eax, 0xFFFFFFFE
+ mov cr0, eax
+
+ .byte 0xFF, 0x2F
+
.global real_mode_return
.type real_mode_return, @function
@@ -184,5 +275,17 @@ real_mode_return:
mov sp, 0x7FFE
ret
+
+ .global real_mode_service_return
+ .type real_mode_service_return, @function
+
+real_mode_service_return:
+ mov bx, sp
+ mov si, word ptr [bx + 8]
+ mov di, word ptr [bx + 10]
+
+ mov ss, di
+ mov sp, si
+ ret