Hi,
I am working on a BIOS porting for a AMD Geode LX processor.
In this project I have to access a register of a device which is at address 0xFF000000. But I am not sure how to access this register.
The BIOS itself lies in the address range 0xFFFC0000 to 0xFFFFFFFF.
The machine starts at address 0xFFFFFFF0, which the processor accesses by setting the code segment cs to 0xf000 and the program counter eip to 0xFFF0. In the debugger I see a additional register called cs.base, which is FFFF000. So it seems that this cs.base is somehow calculated from cs and I get the correct memory address by adding cs.base and eip.
For me it looks as if the cs.base is calculated from cs by multiplaying by 16 and then doing a sign extension to 32 bits.
So with the help of this cs.base this access to the BIOS range is possible. (Otherwise the machine wouldn't boot at all)
But in my example I need to access the address 0xFF000000. I was able to read this address by using the debugger and manually setting cs to 0 and cs.base to 0xFF000000. But how can I access this cs.base register using normal assembler code written in MASM? If my explanation above is corrected I would need to set cs to 0x0FF0.0000 to get the correct cs.base, but since cs is only 16 bits wide, this is not possible.
Or is there a way to set the processor into protectedl mode and directly address 0xFF000000 without using segmentation? I used code segment cs in the explanation above, but in my code I might use data segment ds, but the problem stays the same.
I hope someone can help me with my problem.
Thanks,
Oliver
Hi Oliver - welcome to the forum :U
the segment value is always on 16-byte boundries
(a change of one in the segment value is a change of 16 in calculated linear address)
with a segment value of 0F000h, you can access everything to the end of x86 memory
segment F000 16 bits
offset F000 16 bits
address FF000 24 bit address - accesses 1 Mb linear address space
you would normally see it written as "F000:F000"
that is essentially the same address as "FF00:0000"
that address is normally part of the BIOS ROM
sometimes, you may see other values written in the form XXXX:YYYY
that may indicate XXXXYYYY
in the case of segmented addressing, it is XXXX0+YYYY
Hi,
The base is a part of the protected mode selector. In
real mode, as on boot-up, your addresses are from 00000H
to FFFFFH, a 1 MB range. The 20 bit address is formed as
pointed out by Dave. To get a 32-bit address you need to
be in protected mode. Even in real mode there is a selector
defined for each of the segment registers, but it is not accessible.
Check the documentation about your chip's startup memory
addressing. It may have a 32-bit address until some code is
executed and normal real mode addressing is enforced.
Regards,
Steve N.
Edit: One source says you do execute with a 32-bit address until
a far jump is executed. So (if this is correct) you do start at
FFFFFFF0H. But after a far jump you go into segmented mode.
SRN
So why can the processor access the start adress 0xFFFFFFF0 which can not be written as a segmented address, if it starts in real mode? Or does the instruction fetch always happen in protected mode?
And why can I access the ds.base with the debugger? Does it automatically switch to protected mode to access this register ?
the processor starts execution at address F000:FFF0
when you run the debug program, windows recognizes that it is a 16-bit program and runs it under ntvdm.dll
that creates a virtual machine real-mode world for your 16-bit code to run under
Hi,
I checked some Intel documentation I have, and found the
following paragraph in the 486 data sheet. While a Geode is
not a 486, it may help.
"The 486 microprocessor will start executing instructions at
location FFFFFFF0H after a RESET. When the first InterSegment Jump
or Call is executed, address lines A20-A31 will drop LOW for for
CS-relative memory cycles, and the 486 microprocessor will only
execute instructions in the lower one Mbyte of physical memory.
This allows the system designer to use a ROM at the top of physical
memory to initialize the system and take care of RESETs."
What the other segments are doing is not mentioned. A table
shows them as zeroed out. You might be able to use CS overrides
on memory access instructions. Anyway, check something a bit
more informative than a data sheet to find out what is happening.
HTH,
Steve N.
Quote from: dedndave on January 08, 2010, 03:03:57 PM
the processor starts execution at address F000:FFF0
when you run the debug program, windows recognizes that it is a 16-bit program and runs it under ntvdm.dll
that creates a virtual machine real-mode world for your 16-bit code to run under
My question was not why my PC can understand the 16 bit mode, it was why the Geode processor which works in 16 bit mode can still access a 32 bit address.
But FORTRANS gave the right idea. So I guess the address 0xFF000000 is not accessible at all in real mode. And the register cs.base seems to be a helpregister the processor uses at startup to expand the 16bit address to 32bits. So the only remaining question is whether I can access this register.
hiya Steve
all of the BIOS code i have looked at begins with a far jump at F000:FFF0
there are only 16 bytes of code space available - lol
usually, that jump is followed by the vendor name and ID code, as well as a ROM checksum value
that jump sets the CS and IP registers, of course
the code at that target address usually begins by setting the other segment registers
Hi Dave,
One memory about a BIOS is that the hardware would
have the ROM code addressed in both places. So that the
end of the 32-bit address space would have the same code
as the end of the 16-bit address space. And you only have
16 bytes in any event, so some kind of jump seems to be
required. And so, unless you are careful, you end up in real
mode with segmented addressing real quick.
Doing an intrasegment jump presumably leaves the 32-bit
address open, but it seems the selectors are not in a very
good state, and so you would have to set them up as part of
the start-up code. And you then need an intersegment jump
to activate them. I imagine you might as well go into protected
mode at the same time if 4 Gig addressing is wanted.
I have a lot of trivia saved up, but I am not an expert here.
Regards,
Steve N.
that's ok Steve - i am no expert, either
i was pretty good with th 8086 - lol
of course, all that info was a waste of time :P
Im a bit confused about the memory segmentation too, I can access the Video RAM just like it was part of my RAM. I wonder how if I was having a 4 GB memory, how to access all of it when the register was sharing with the VRAM too.
To access the 0xFF000000 you will need to jump to protected mode and then set the base memory to 0xff000000. You should understand LGDT instruction, I've forgot the GDT table field. But If you had send the GDT to the processor, you will just need to switch using the segment register.
LGDT some_GDT
mov ds,The_GDT
mov eax,ds:[esi]
the video ram is paged into a window of the x86 address space
typically, the A000 and B000 segments can be used
on the video card, there are I/O accessible registers that allow you to control which pages of video memory are enabled
unfortunately, all that I/O stuff requires ring 0 access under win 2000 and up
it was fun to program for win 95/98, because you could still do hardware I/O
one of these days, i will have to play with ring 0 and see how hard it is to code
Intel docs, volume 3A, section 8.1.4
QuoteThe first instruction that is fetched and executed following a hardware reset is located at physical address FFFFFFF0H. This address is 16 bytes below the
processor's uppermost physical address. The EPROM containing the software-initialization code must be located at this address.
The address FFFFFFF0H is beyond the 1-MByte addressable range of the processor while in real-address mode. The processor is initialized to this starting address as
follows. The CS register has two parts: the visible segment selector part and the hidden base address part. In real-address mode, the base address is normally
formed by shifting the 16-bit segment selector value 4 bits to the left to produce a 20-bit base address. However, during a hardware reset, the segment selector in the
CS register is loaded with F000H and the base address is loaded with FFFF0000H. The starting address is thus formed by adding the base address to the value in the EIP
register (that is, FFFF0000 + FFF0H = FFFFFFF0H).
The first time the CS register is loaded with a new value after a hardware reset, the processor will follow the normal rule for address translation in real-address mode
(that is, [CS base address = CS segment selector * 16]). To insure that the base address in the CS register remains unchanged until the EPROM based software-
initialization code is completed, the code must not contain a far jump or far call or allow an interrupt to occur (which would cause the CS selector value to be changed).
To access your device at FF000000 you would need to be in protected mode. The easiest way to do that is base=0,limit=FFFFFFFF with interrupts disabled.
Program the device, then go back to real mode.
It's not actually necessary to be in protected mode at the time of the access, if you first enter protected mode temporarily to load the necessary base and limit into the descriptor cache for whatever segment register is being used for the access. The attachment contains an app that does this, and compares the 16 bytes at absolute address FFFF0 to the 16 bytes at absolute address FFFFFFF0. Note that the app will not work under Windows 2000, but it might under Windows 9x. Here are the results for my test system, running under MS-DOS 6.22:
EA5BE000F030342F31302F393800FCD3
0
1
EA5BE000F030342F31302F393800FCD3
2EFF26F5FF1BC000EA1DC000F000002B
The first 5 bytes are:
2EFF26F5FF JMP WORD PTR CS:[FFF5]
And the others appear to be data.
EA5BE000F030342F31302F393800FCD3
EA5BE000F0 = JMP F000:E05B
30342F31302F393800 = DB '04/10/98',0
FCD3 = DW 0D3FCh ;probably the ROM checksum compliment (so the total ROM checksum = 0)
the date serves as the revision number - the checksum is sometimes used that way, too
if you look at the lower addresses of the ROM, you will probably find who it was written by and/or the machine OEM
Michael, if i win the lottery, i am buying you a new machine - lol
I had a good idea of what EA5BE000F030342F31302F393800FCD3 was, my focus was on the 2EFF26F5FF1BC000EA1DC000F000002B sequence and how it related to the description that sinsi posted. Clearly, it's not as simple as the BIOS being mapped to two addresses.
QuoteMichael, if i win the lottery, i am buying you a new machine – lol
Why wait, my self-esteem could use the boost now :lol
your self-esteem should be just fine, Michael - lol
you write more good code on your old machine that a lot of guys do with newer ones
and - your code is tested on an older machine :P
2EFF26F5FF JMP Word Ptr CS:[FFF5]
1B C0 00
EA1DC000F0 JMP F000:C01D
00 00 2B
the 3 bytes (twice) must be data of some sort
C01B seems a little low for BIOS
Hi,
Tried it on four machines. Two (same brand) showed
the same lines. Two showed different lines, But all started
with:
EA5BE000F0
Regards,
Steve N.
I modified my code to display 35 bytes starting at absolute address FFFFC01B, and then using the same test system I got:
EB 06 BB 2A CC E9 61 07 2E 8E 06 65 C7 67 26 81
3D F1 FF 00 00 5B E0 74 05 EA 6C C7 00 F0 EA F0
FF 00 F0
And here is the disassembly done with Japheth's Debug clone:
-m6
-a c01b
0B04:C01B db EB 06 BB 2A CC E9 61 07 2E 8E 06 65 C7 67 26 81
0B04:C02B db 3D F1 FF 00 00 5B E0 74 05 EA 6C C7 00 F0 EA F0
0B04:C03B db FF 00 F0
0B04:C03E
-u c01b
0B04:C01B EB06 JMP C023
0B04:C01D BB2ACC MOV BX,CC2A
0B04:C020 E96107 JMP C784
0B04:C023 2E8E0665C7 MOV ES,WORD PTR CS:[C765]
0B04:C028 6726813DF1FF0000
5BE0 CMP WORD PTR ES:[0000FFF1],E05B
0B04:C032 7405 JZ C039
0B04:C034 EA6CC700F0 JMP F000:C76C
0B04:C039 EAF0FF00F0 JMP F000:FFF0
So at least one of the possible execution paths goes to F000:FFF0, and both paths reload CS, causing it to revert to the normal RM behavior and base address.
I wonder if the thread starter could create a tiny PC whic only had a Monitor and external keyboard with 2 USB port and 1 MMC slot. I'd like to know how the price. This would be a good toys, no need a harddisk anymore. USB is enough.
they have a number of embedded controllers out there that will run windows, Onan
you could probably get something going for around $200 US
google is your friend :bg
Hi,
Iwas trying to refind a page on the OP's Geode LX processor
on AMD's site that had a nice looking "reference system" but
could not locate it. A cute little box with nice features.
Anyway, after browsing around I stumbled on Northec's site
and their products. Two of interest (to me) were:
Quote
At only US$88.00, the MicroClient JrSX represents the least
expensive x86 compatible computer solution available.
Quote
The Gecko laptop is a small, energy efficient, rugged laptop.
The Gecko laptop will run virtually any x86 operating system,
including Windows and Linux.
That laptop uses standard AA batteries and is inexpensive.
(And has some cute videos.)
Cheers,
Steve N.
that is cute - lol
it would be nice to have at least one ISA expansion slot, though
hard to see how they make a profit on that laptop
the LCD screen, plastic moldings, and the BIOS code pretty much cover the $200 - lol
$200 would be a good price. And also, a GSM card slot for cellphone.