OSDev.org

The Place to Start for Operating System Developers
It is currently Thu Mar 28, 2024 9:46 am

All times are UTC - 6 hours




Post new topic Reply to topic  [ 5 posts ] 
Author Message
 Post subject: Use BIOS funcions from long mode
PostPosted: Tue Feb 08, 2011 2:55 pm 
Offline
Member
Member
User avatar

Joined: Tue Feb 08, 2011 1:58 pm
Posts: 496
Before any of you write "no, you cannot do that", I have a working solution I want to share.
Prerequirements:
1. I assume you have set up long mode properly
2. Your kernel is _not_ in the first 64k, so you have to alter CS for real mode. This example code use 1000h, but change it to your needs (kinda homework).
3. The original IVT is untouched

The code uses fasm syntax.
Code:
;this code is placed somewhere after 10000h
;-----we're in LONG MODE-----
      mov          qword [.stckptr], rsp   ;first of all save stack
      sgdt         [.gdtv64]               ;save your gdt pointer
      lgdt         [.gdtv16]               ;load a new one
      sidt         [.idt64]                ;save your idt pointer
      lidt         [.idt16]                ;load real mode idt
      ;far jump in long mode is not possible, do a trick
      push         DESC_REAL
      push         @f-10000h               ;this is CS*10h, modify if needed!
      retfq
.stckptr:
      dq           0
      align        16
.gdtv64:
      dw           0
      dq           0
      align        16
.gdtv16:
      dw           .gdtend-.gdt-1
      dd           .gdt,0
      align        16
.gdt:
      dd           0,0                      ;null descriptor
DESC_DATA=8                                 ;descriptor in YOUR GDT (modify)
DESC_LONG=$-.gdt
      dd           00000000h,00209800h      ;64 bit long mode cs
DESC_REAL=$-.gdt
      dd           0000FFFFh,00009801h      ;16 bit real mode cs (modify base if needed!)
.gdtend:
      align        16
.idt64:
      dw           0
      dq           0
      align        16
.idt16:
      dw           3FFh
      dq           0
      USE16
;-----we're in COMPATIBLITY MODE-----
      ;disable paging and protmode at once
@@:   mov          eax, cr0
      and          eax, 7FFFFFFEh   
      mov          cr0, eax
      ;set up real mode segment registers and stack
      mov          esp, realmode_stack_top          ;modify it to your needs!
      xor          ax, ax
      mov          ds, ax
      mov          es, ax
      mov          fs, ax
      mov          gs, ax
      mov          ss, ax
      ;convert long mode rip to real mode cs:ip
      ;jmp CS:(longmode address)-CS*10h
      jmp          1000h:@f-10000h                  ;modify if needed!
;-----we're in REAL MODE-----
@@:   ;***********call some BIOS interrupt here**********
      mov          ax, 3
      int          10h

      ;switch back to long mode
      mov          eax, cr0
      or           eax, 80000001h
      mov          cr0, eax                         ;enable protmode and paging
      ;jmp         DESC_LONG:@f
      db           66h
      db           0EAh
      dd           @f
      dw           DESC_LONG
      USE64
;-----we're in COMPATIBILITY MODE-----
@@:   lgdt         [cs:.gdtv64]                    ;restore gdt
      mov          ax, DESC_DATA                   ;read YOUR DATA descriptor to selectors
      mov          ds, ax
      mov          es, ax
      mov          fs, ax
      mov          gs, ax
      mov          ss, ax
      lidt         [.idt64]                        ;restore idt
      mov          rsp, qword [.stckptr]           ;restore stack
      ;must be a non rip-relative jump
      mov          rax, @f
      jmp          rax
@@:
;-----we're in LONG MODE again-----

Not so ugly as it first seems :-) Hope that would be useful.


Top
 Profile  
 
 Post subject: Re: Use BIOS funcions from long mode
PostPosted: Wed Feb 09, 2011 12:13 am 
Offline
Member
Member
User avatar

Joined: Wed Oct 18, 2006 3:45 am
Posts: 9301
Location: On the balcony, where I can actually keep 1½m distance
You're technically not calling the BIOS from long mode, but from real mode. That obviously comes with all the problems of temporarily disabling your OS that come with it.

_________________
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]


Top
 Profile  
 
 Post subject: Re: Use BIOS funcions from long mode
PostPosted: Wed Feb 09, 2011 1:44 am 
Offline
Member
Member
User avatar

Joined: Wed May 21, 2008 4:33 am
Posts: 294
Location: Mars MTC +6:00
I'm not playing in long mode yet, but I was thinking could you fake a vm86 mode using 16bit pmode segments. I think 16 bit selectors are legal in long mode (compatibility mode). This is just a theory and I haven't tried it so it could all be BS.

using ldt entries cs = 0x00 ds = 0x08 es = 0x10 fs = 0x18 gs = 0x20 ss = 0x28
(for gdt entries just start with cs = 0x08 instead)
whenever a real mode program (BIOS interrupt) program faults by using an invalid segment then set the allocated selector to the base with a limit of 64K and reload it back into the selector. Because the real mode IVT goes up to 0x0400 most programs wont request anything below this as a segment except maybe 0x00 which will trigger a fault because to use selector 0x00 it would need to be loaded as 0x07 for ring3/ldt flags.

This is basically a normal vm86 monitor to handle protected instruction but also it sets the selectors whenever an invalid read/write happens. You can still set the v86 bit in the eflags for long mode to detect whether you need to set selectors.

Just curious if this is a viable option.

_________________
"God! Not Unix" - Richard Stallman

Website: venom Dev
OS project: venom OS
Hexadecimal Editor: hexed


Top
 Profile  
 
 Post subject: Re: Use BIOS funcions from long mode
PostPosted: Wed Feb 09, 2011 2:26 am 
Offline
Member
Member
User avatar

Joined: Wed Oct 18, 2006 3:45 am
Posts: 9301
Location: On the balcony, where I can actually keep 1½m distance
b.zaar wrote:
I'm not playing in long mode yet, but I was thinking could you fake a vm86 mode using 16bit pmode segments. I think 16 bit selectors are legal in long mode (compatibility mode). This is just a theory and I haven't tried it so it could all be BS.

using ldt entries cs = 0x00 ds = 0x08 es = 0x10 fs = 0x18 gs = 0x20 ss = 0x28
(for gdt entries just start with cs = 0x08 instead)
whenever a real mode program (BIOS interrupt) program faults by using an invalid segment then set the allocated selector to the base with a limit of 64K and reload it back into the selector. Because the real mode IVT goes up to 0x0400 most programs wont request anything below this as a segment except maybe 0x00 which will trigger a fault because to use selector 0x00 it would need to be loaded as 0x07 for ring3/ldt flags.

This is basically a normal vm86 monitor to handle protected instruction but also it sets the selectors whenever an invalid read/write happens. You can still set the v86 bit in the eflags for long mode to detect whether you need to set selectors.

Just curious if this is a viable option.


In theory, it doesn't work, because you can't easily deal with these cases:
- Real mode applications using 0 for a segment register (all accesses will fail)
- using CS=DS (or any other form of data-code aliasing) requires that the same entry contains both a code and data selector, which might have you end up with unwritable segments for code descriptors, or faults for data descriptors.
- using segment and segment +1 (so they alias the same table access), which will result in wrong addresses used
- using the same segment value as one used for your kernel.

And you can't modify a segment register upon fault if the process uses some form of paragraph arithmetic (even simple instances like push ds; pop es;) because you can't check if a segment is an actual location, or some operation based on whatever value you previously replaced.

You'll probably find #1 and #2 very often in production code.


[EDIT] Brendan added the quote, so that turdus doesn't make the mistake of thinking that Combuster is saying his "switch to real mode" idea won't work.[/EDIT]

_________________
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]


Top
 Profile  
 
 Post subject: Re: Use BIOS funcions from long mode
PostPosted: Wed Feb 09, 2011 12:25 pm 
Offline
Member
Member
User avatar

Joined: Tue Feb 08, 2011 1:58 pm
Posts: 496
b.zaar wrote:
I'm not playing in long mode yet, but I was thinking could you fake a vm86 mode using 16bit pmode segments. I think 16 bit selectors are legal in long mode (compatibility mode).

Usually an OS won't call any BIOS calls, it's very-very rare. Maybe at boottime and switching video modes, that's all, so it not worth the candle imho.


Last edited by turdus on Wed Feb 09, 2011 12:37 pm, edited 1 time in total.

Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 5 posts ] 

All times are UTC - 6 hours


Who is online

Users browsing this forum: Bing [Bot], DotBot [Bot], Majestic-12 [Bot] and 65 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group