Unreal Mode

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
User avatar
Masterkiller
Member
Member
Posts: 153
Joined: Sat May 05, 2007 6:20 pm

Unreal Mode

Post 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 :(
Hangin10
Member
Member
Posts: 162
Joined: Wed Feb 27, 2008 12:40 am

Post 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.
User avatar
Dex
Member
Member
Posts: 1444
Joined: Fri Jan 27, 2006 12:00 am
Contact:

Post by Dex »

Also here is some well commented source, for unrealmode:
Attachments
PM5.ASM
Unreal-mode
(11.82 KiB) Downloaded 86 times
User avatar
Masterkiller
Member
Member
Posts: 153
Joined: Sat May 05, 2007 6:20 pm

Post by Masterkiller »

Thanks a lot to all :wink:
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 :D :D :D
sancho1980
Member
Member
Posts: 199
Joined: Fri Jul 13, 2007 6:37 am
Location: Stuttgart/Germany
Contact:

Post 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...
User avatar
Philip
Member
Member
Posts: 59
Joined: Thu Mar 06, 2008 11:37 pm
Location: Singapore

Post by Philip »

i think if you plan to have a bright future for your os
use protected mode instead, try to use it
User avatar
Masterkiller
Member
Member
Posts: 153
Joined: Sat May 05, 2007 6:20 pm

Post 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 :wink:
Post Reply