Page 1 of 1
Unreal Mode
Posted: Thu Feb 28, 2008 7:21 pm
by Masterkiller
I need to read a physical memory above one megabyte, but my kernel is not ready to switch to pmode, yet. I have read that using unreal mode it can use a 32-bit offset. If I enable A20 line and go to unreal mode, is it possible to read the memory above one megabyte, and how do I do it. I have 16-bit segment in ds for example and 32-bit offset, how they generate 32-bit address and if the result address linear or physical. I just need to read ACPI tables, but RSDP points to physical address 0x00FF0000, that is out of real-mode memory
Posted: Thu Feb 28, 2008 7:54 pm
by Hangin10
Hope I don't mess this up on my first post (although I've read the forum
for a *VERY* long time)
.
The wiki has a pretty good article on
Unreal Mode.
According the article on the wiki, the segment:offset works just like real
mode; you just get more bits of offset.
Personally, I think it's easiest to get Unreal Mode setup first, then clear
DS (except if needed by BIOS interrupts, etc [but then again, for a
bootloader, it's easiest to run in seg zero anyway]). That way you can
just use physical 32bit addresses offset from zero, eg. [eax], and not
worry about extra address translation.
Posted: Thu Feb 28, 2008 8:44 pm
by Dex
Also here is some well commented source, for unrealmode:
Posted: Fri Feb 29, 2008 5:08 pm
by Masterkiller
Thanks a lot to all
I notice some strange thing about (un)real mode. Example is below.
Code: Select all
es:s=0x0008, dl=0x0000ffff, dh=0x008f9300
Where 's' is the visible part used in real mode and 'dl' and 'dh' are invisible parts storing the descriptor value. In the shown example descriptor points to the physical address of 0 (zero) and ES:0x10000000 should access at 0x10000000 memory, but it access at 0x10000008, don't know why but physical address is the result of:
Code: Select all
descriptor base + 32-bit offset giver + (segment register visible part*16)
The invisible part never changes in real-mode, but the visible part of the segment register also take place of calculating the physical address. To me the mode looks like huge device flaw...
CPU: "Oh, I'm in real mode, so multiplythis value to 16... but wait there is valid descriptor, so I add it... but wait it is given 32-bit offset... if A20 enabled... I messed everything... just execute
"
Anyway I am extremely super-duper happy that I can write to linear flat VESA mode video buffer from real mode. SVGA looks so nice, even that was not the main purpose to go to that mode. Thanks a lot to all
Posted: Wed Mar 05, 2008 8:21 am
by sancho1980
Can you describe what exactly you did to get into unreal mode? Turning on A20 alone will not do. I have a feeling you're not in unreal mode...
Posted: Fri Mar 07, 2008 9:45 pm
by Philip
i think if you plan to have a bright future for your os
use protected mode instead, try to use it
Posted: Sat Mar 08, 2008 3:29 am
by Masterkiller
sancho1980 wrote:Can you describe what exactly you did to get into unreal mode? Turning on A20 alone will not do. I have a feeling you're not in unreal mode...
I also go into protected mode, load segment selector, go back to real-mode. I can access to 4GB Physical memory, it worked when I tried to write flat video buffer provided in some VBE modes. There were special note that pointer returned in the VBE information is physical address, not virtual or linear, so now I know I'm writing to physical memory.
Here is the code for enabling A20:
Code: Select all
EnableA20:
PUSH ax
CLI
;First Verify if A20 is already set
XOR ax, ax
IN al, 0x92
TEST al, 02h
JNZ ea20_Success
OR al, 02h
AND al, 0xFE
OUT 0x92, al
XOR ax, ax
IN al, 0x92
TEST al, 02h
JNZ ea20_Success
POP ax
STC
STI
RET
ea20_Success:
POP ax
CLC
STI
RET
GDT:
Code: Select all
gdt:
null_desc:
dd 0
dd 0
linear_data equ $-gdt
dd 00000000000000001111111111111111b
dd 00000000100011111001001100000000b
gdt_end:
gdtpointer:
dw gdt_end - gdt - 1
dd 10000h+gdt ;kernel is placed at address 0x10000 (1000h:0000)
Code to enter unreal mode:
Code: Select all
CALL EnableA20
JC Exit
LGDT [gdtpointer]
CLI
MOV eax, cr0
OR al, 1
MOV cr0, eax
MOV ax, linear_data
MOV ES, ax
MOV eax, cr0
AND al, 0xFE
MOV cr0, eax
STI
Only ES actually writes to locations bigger than 1MB. Testing answer my question, accessing memory through unreal mode use physical addresses (may be with this descriptor only). It worked, so there is no problem