I want to call a real mode interrupt from SMM. SMM is essentially flat real mode (4GB limit instead of 64k).
How do I go about executing the BIOS interrupts? I don't know if I have to switch back to real mode and execute the code, or set up an IDT. I've tried to execute the code directly by pushing EFLAGS, CS, and IP on the stack, jumping to the memory address, but this locks up (unless I'm doing it wrong).
Example code is the best. The problem with SMM is that the processor initiates the mode, so I don't have tables of GDT etc. to play with, and don't know if it's safe to modify the SMM GDT.
Comments
rewrite it by tracing the interrupt, and dumping the code. The lock-up
usually occurs when it tries to reference a real memory location.
All you should need to do is fix-up the memory locations, and you
can call it as a normal procedure.
URL:http://acheronx.ml.org/home/
: rewrite it by tracing the interrupt, and dumping the code. The lock-up
: usually occurs when it tries to reference a real memory location.
: All you should need to do is fix-up the memory locations, and you
: can call it as a normal procedure.
A real mode context switch shouldn't be a problem (I'm gonna find out today). The question is "Can I get the processor back into the state when SMM was entered?" I would think that I should also be able to create a 16-bit code and 16-bit data segment, push CS and DS, load CS and DS with those selectors, do the BIOS call, then pop DS and CS. In that case, I would have to modify the LDT or GDT, which I don't think is a safe thing to do in SMM, seeing as how I don't control the CPU state. Documentation says this is a bad thing as well. The other issue is if I need to ADD to the GDT or LDT, and I'm given the limit and base of each in the SMM state save map, how can I be assured that adding to them won't stomp on memory? There's no guarantee that there is enough room in memory where the GDT and LDT is stored for me to add entries.
What I need to do is detect the amount of RAM in a system and dump a complete memory image to disk when SMI goes low. The only way to do this is through BIOS calls. My stand-alone programs work, now it's just a matter of incorporating them into SMM.
(1) Is SMM, you don't have to mess with GDT/ LDT/ etc, because address computation is performed the same way as in real mode (value in seg register shifted left 4 bits plus offset). The locations in SMRAM are used to store the values of these registers in the program that was interrupted. A RSM instruction restores everything (includign GDT/ LDT) from the save area.
(2) The default data/code size in 16 bits, so don't push EFLAGS but FLAGS, etc. In fact, the only difference between real mode and SMM is that limits for segments are set to 4Meg instead of 64k, so you can use the operand-size prefix to address all the memory.
(3) The interrupt table is the same as for real mode. However, Intel says that using INT/ INTO/ etc in SMM is not recomended.
(4) A problem I see is that a processor's pin signals that it is in SMM, and the external chips may decode memory accesses to address other physical memory than in real mode (to prevent overwritting the SMRAM). Another problem is that the BIOS may relocate the SMRAM, so the entry into the SMI handler is not at the default address (I haven't found how to figure out the current SMRAM base address).
(5) Software switching out of SMM: only with the RSM instruction, which restores everything from the save area in SMRAM.
(6) Switch into SMM (when restoring from hd): only by SMI. You can use the "auto interrupt" mecanism of the local APIC to generate a SMI by software.
In case you dont't have the Intel 32bit Processors manuals, you can download them from the link below. Volume 3 contains a detailed description of SMM (and the local APIC too).
URL:http://developer.intel.com/design/pentiumii/xeon/manuals/