[fixed]VGA BIOS Interrupts After Switching Back to Real Mode
-
- Posts: 4
- Joined: Fri Jun 28, 2013 7:55 am
[fixed]VGA BIOS Interrupts After Switching Back to Real Mode
Hello all,
I'm currently working on a basic OS, and one of the features I want is a sort-of fatal error handler (akin to Windows BSoD or Linux kernel panic).
Right now, I have the error handler switch to 16-bit real mode in order to use VGA BIOS interrupts. However, as soon as I invoke BIOS int 10h, it seems to enter an infinite loop in the BIOS code. I tried this both in QEMU and on real hardware (Dell Latitude E6400), but they both experience the same issue.
I've double-checked the mode-switch code, and I correctly restore the real-mode IVT and re-enable interrupts, and all of my segment registers are properly set. I've also made sure that none of my code touches the BDA.
Could the issue be caused by booting from syslinux with mboot.c32? Could it possibly modify any BDA/EBDA structures? Or is there something else I need to (re)set before I can use VGA BIOS interrupts again?
I can provide more details if needed.
I'm currently working on a basic OS, and one of the features I want is a sort-of fatal error handler (akin to Windows BSoD or Linux kernel panic).
Right now, I have the error handler switch to 16-bit real mode in order to use VGA BIOS interrupts. However, as soon as I invoke BIOS int 10h, it seems to enter an infinite loop in the BIOS code. I tried this both in QEMU and on real hardware (Dell Latitude E6400), but they both experience the same issue.
I've double-checked the mode-switch code, and I correctly restore the real-mode IVT and re-enable interrupts, and all of my segment registers are properly set. I've also made sure that none of my code touches the BDA.
Could the issue be caused by booting from syslinux with mboot.c32? Could it possibly modify any BDA/EBDA structures? Or is there something else I need to (re)set before I can use VGA BIOS interrupts again?
I can provide more details if needed.
Last edited by quantumdude on Wed Aug 07, 2013 7:27 am, edited 1 time in total.
Re: VGA BIOS Interrupts After Switching Back to Real Mode
Yes, show the code. I use such technique and all works fine.
If you have seen bad English in my words, tell me what's wrong, please.
Re: VGA BIOS Interrupts After Switching Back to Real Mode
I would like to point out that, even without any fatal error, switching back to real-mode is a total mess - to some extend it may generate more trouble than you can imagine.
There are a lot of discussion about switching back to real mode, due to the huge amount of work for "properly" switching back, and the high risk for being test pilot (since it is about the least things to be QA'ed) even when the OS runs fine, so I would not recommend doing that when things already goes wrong.
There are a lot of discussion about switching back to real mode, due to the huge amount of work for "properly" switching back, and the high risk for being test pilot (since it is about the least things to be QA'ed) even when the OS runs fine, so I would not recommend doing that when things already goes wrong.
-
- Posts: 4
- Joined: Fri Jun 28, 2013 7:55 am
Re: VGA BIOS Interrupts After Switching Back to Real Mode
Code to jump to 16-bit segment:
SEG_CODE16 refers to a 16-bit code selector with base 0x00010000, which is where the 16-bit error handler has been relocated to.
Actual 16-bit code (starts off in protected mode, switches to real mode):
GDT:
(on an unrelated note, is there a way to "hide" all that code? I.e. something like [spoiler]code[/spoiler]?)
Code: Select all
jmp SEG_CODE16:0x0000
Actual 16-bit code (starts off in protected mode, switches to real mode):
Code: Select all
; 16-bit fatal error handler
FATAL_SEG equ 0x1000
bits 16
org 0x0000 ; relative to segmant 0x1000
fatal16:
; disable protected mode and paging
mov eax, cr0
and eax, 0x7ffffffe
mov cr0, eax
xor eax, eax
mov cr3, eax
; setup data segments
mov ax, FATAL_SEG
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
; setup small stack
mov sp, stack
; fix code segment (so interrupts can properly return)
jmp FATAL_SEG:.csFix
.csFix:
; restore real-mode IVT and enable interrupts
lidt [idtr]
sti
; TODO: figure out why VGA BIOS interrupts aren't working
; switch to VGA 80x25
mov ax, 0x0002
int 0x10
; reset cursor
mov ax, 0x0002
xor bh, bh
xor dx, dx
int 0x10
; clear screen (to a nice white-on-red color)
mov ax, 0xb800
mov es, ax
xor di, di
mov ax, 0xcf00
mov cx, 80 * 25
rep stosw
; TODO: display something
mov si, msg
mov cx, msg.len
.loop:
mov ah, 0x0e
mov bx, 0xf400
lodsb
int 0x10
loop .loop
jmp $
align 4
idtr:
dw 0x03ff
dd 0x00000000
msg:
db "UH OH, SPAGHETTI-O'S"
.len equ $ - msg
times 1024 - ($ - $$) db 0
stack:
Code: Select all
section .data
align 4
gdt:
; null entry - re-use space for GDT pointer
gdtp:
dw gdt.size - 1
dd gdt
; pad to 8 bytes
dw 0
SEL_CODE32 equ $ - gdt
; 32-bit code
dw 0xffff
dw 0x0000
db 0x00
db 0x9a
db 0xcf
db 0x00
SEL_DATA32 equ $ - gdt
; 32-bit data
dw 0xffff
dw 0x0000
db 0x00
db 0x92
db 0xcf
db 0x00
SEL_CODE16 equ $ - gdt
; 16-bit code, base 0x00010000
dw 0xffff
dw 0x0000
db 0x01
db 0x9a
db 0x00
db 0x00
gdt.size equ $ - gdt
- Combuster
- Member
- Posts: 9301
- Joined: Wed Oct 18, 2006 3:45 am
- Libera.chat IRC: [com]buster
- Location: On the balcony, where I can actually keep 1½m distance
- Contact:
Re: VGA BIOS Interrupts After Switching Back to Real Mode
Shouldn't that be mode 3h?; switch to VGA 80x25
mov ax, 0x0002
int 0x10
-
- Posts: 4
- Joined: Fri Jun 28, 2013 7:55 am
Re: VGA BIOS Interrupts After Switching Back to Real Mode
Yeah probably, I just took a quick glance at RBIL. But even if I don't do the mode switch at all, it still hangs at the next interrupt.Combuster wrote:Shouldn't that be mode 3h?; switch to VGA 80x25
mov ax, 0x0002
int 0x10
Also, I just realized that the second interrupt call should start
Code: Select all
mov ah,0x02
Code: Select all
mov bx, 0x00f4
Re: VGA BIOS Interrupts After Switching Back to Real Mode
bluemoon, in general I agree, but I was telling about switching to RM right after getting control from Multiboot-compliant boot loader.
quantumdude, I don't see that you load "16-bit data selector". And is recommended to load cs first:
- jmp CODE16_SEL:x;
- set data seg regs with DATA16_SEL;
- clear PE flag;
- jmp CODESEG:x;
- set data seg regs with DATASEG.Maybe too small
Try to save/restore cx value (or to use null-terminated string).
quantumdude, I don't see that you load "16-bit data selector". And is recommended to load cs first:
- jmp CODE16_SEL:x;
- set data seg regs with DATA16_SEL;
- clear PE flag;
- jmp CODESEG:x;
- set data seg regs with DATASEG.
Code: Select all
; setup small stack
mov sp, stack
Code: Select all
mov cx, msg.len
.loop:
mov ah, 0x0e
mov bx, 0x00f4 ; fixed
lodsb
int 0x10
loop .loop
If you have seen bad English in my words, tell me what's wrong, please.
-
- Posts: 4
- Joined: Fri Jun 28, 2013 7:55 am
Re: VGA BIOS Interrupts After Switching Back to Real Mode
I found the issue.
When I set up the small stack:
I forgot that the upper-16 bits of esp are still set, which seems to break BIOS. When I clear out esp first:
Everything works fine. I did, however, make the changes you suggested, egos, so hopefully it'll be more robust.
When I set up the small stack:
Code: Select all
mov sp, stack
Code: Select all
xor esp, esp
mov sp, stack