aboutsummaryrefslogtreecommitdiff
path: root/mubios/arch/mode_switch.S
diff options
context:
space:
mode:
authorRichard Qin <richard.qin.x@gmail.com>2026-11-08 07:46:07 +0800
committerRichard Qin <richard.qin.x@gmail.com>2026-11-08 07:46:07 +0800
commit9bfc57c3684f7aebba0f6865a1ea248f576b947f (patch)
tree8dafb3b4c9487b02a1fa634dbf4ae11509a37e7d /mubios/arch/mode_switch.S
parent1a211405d76b2e8997ec21d53831147441c8de24 (diff)
downloadrcc-project-9bfc57c3684f7aebba0f6865a1ea248f576b947f.tar.gz
rcc-project-9bfc57c3684f7aebba0f6865a1ea248f576b947f.tar.xz
[mubios] Add switching and return paths between real-mode interrupts and protected-mode C services.
Signed-off-by: Richard Qin <richard.qin.x@gmail.com>
Diffstat (limited to 'mubios/arch/mode_switch.S')
-rw-r--r--mubios/arch/mode_switch.S103
1 files changed, 103 insertions, 0 deletions
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