Full Member level 2
This post related to my Award BIOS Reverse Engineering article, which can be read at _hxxp://www.geocities.com/mamanzip/Articles/Award_Bios_RE/Award_Bios_RE_guide.html. It's a response from one of the reader that I think a very valuable programming trick that is known only to few "elite" system level programmer.
A snapshot of my article:
There are couples of tricky areas in the BIOS code due to the execution of some of its parts in ROM. I'll present some of my findings below.
call instruction is not available during bios code execution from within BIOS ROM chip. This is due to call instruction uses/manipulate stack while we don't have writeable area in BIOS ROM chip to be used for stack. What I mean by manipulating stack here is the "implicit" push instruction which is executed by the call instruction to "write/save" the return address in the stack. As we know clearly, address pointed to by ss:sp at this point is in ROM, meaning: we can't write into it. If you think, why don't use the RAM altogether ? the DRAM chip is not even available at this point. It hasn't been tested by the BIOS code, thus we haven't know if RAM even exists!
response from Mark_Larson (a reader of the article):
Sort of. On current Intel processors their is a feature called Cache As Ram. It allows you to use your cache as if it were RAM before memory is initialized. Cache As Ram is only supported on the latest processors. On older processors in some BIOSes a trick was used to "fake" a stack in the cache. This allowed the BIOS programmer to do CALLs and RETs without memory having been set up. You fake a stack in the cache and then disable the cache. All accesses to the stack come from the cache. The fake stack never gets removed from the cache because the cache is disabled. AMI first did this about 8 years ago.
a follow up from Mark_Larson (a reader of the article):
I'll expand a bit on both parts.
1) Cache As Ram - Intel basically allows you to set the cache to respond to memory acceses from a certain memory range. For instance you could set the memory range 1000h:0 for 8k to be your stack in Cache as Ram. When the processor accesses anything in the 8k range of 1000h:0 it will get the information from the cache. So setting up a stack somewhere is trivial. That allows you to do CALLs and RETs
2) "Faking a stack" -
A) Make sure the L1 is enabled and on and the L2 cache is off.
B) Have 1K ( or however big you want your stack to be), set aside as data in the BIOS ROM chip. Doesn't matter what the 1k of data is, as long as you don't use it for anything else.
C) Read that data in, forcing it to go into the L1 cache ( rep lods).
D) Disable the L1 cache.
E) Now set up the stack through the appropriate commands to point to the data that you just read in.
F) All accesses to the stack now go through the cache, but the data never gets removed from the cache since it's disabled.
G) Having the cache disabled doesn't really mean it's "disabled". What it means is that nothing new can be added to the cache. It still responds to all "hits" with the appropriate data.
As a variation, you can do this with the code in the BIOS ROM as well, and use both the L1 and L2. I only used the L1 to make it easier to illustrate. Their is actually an MSR on P3 and earlier processors ( I think it got added in the pentium pro), that lets you directly write to the cache. A lot of 3rd party testing tools use this to test the cache. It works like a memory test. You write a pattern and read it back via this MSR. But you can also use it to load up the data or code you want to use directly into the cache. You can also use that mechanism to create the stack in the cache. However it won't work on P4's. So the above method is more robust, since it works in all cases. AMI if I remember right used the MSR method. Look in Book 3 of any of the processor manuals in the appendix under MSRs ( appendix B). In my P4 book it's under the section "MSRs in the P6 Family Processors". It spans multiple MSRs starting at 88h. Keep in mind that this is no longer on the P4.