It's a little hard to tell from this snapshot, but I think we can make a few assumptions.
Opcode 66h is defined as a Operand-size override prefix or Precision-size override prefix.
BSWAP is defined as
Changes the byte order of a 32 bit register from big endian to little endian or vice versa. Result left in destination register is undefined if the operand is a 16 bit register.
So the 66h is part of the bswap instruction in this case. If written in 32 bit code, bswap edx = 0F CA. In bios code it's 66 0F CA.
We can't really tell what was in eax/edx at the start of this code, but if we look at the known parts of the instructions
mov al, 80h
bswap eax
eax will be 80000000 after executing these 2 instructions (assuming the rest of the register bits were 0).
Now let's go down to the next part
mov al, dh
and al, 0FCh
I'm going to make a leap of faith here and say dh contains 9D (I'll explain why in a minute).
So eax is already 80000000
then it becomes 8000009D after mov al, dh
after the AND instruction it becomes 8000009C.
Aah, 8000009C is familiar right?
The next instructions write the value of eax = 8000009C to PCI port CF8. This is equivalent to the WRITE_PORT_ULONG API.
mov dx, 0CF8h
out dx, eax
Now if we look at the Memory Controller Hub (MCH) Datasheet (for my 82848P system it's in section 3.5 DRAM Controller/Host-Hub Interface Device Register Address Map) we find that 0x9D is the address offset for the SMRAM System Management RAM Control Register (Device 0). The SMRAMC register controls how accesses to Compatible and Extended SMRAM spaces are treated. A little further down are details of each of the bits in the register.
Here's a little snippet which simply reads the complete contents of the SMRAM register. You should be able to see where the 0x8000009C comes from. In this code it's the CONFIG_CMD macro, in your bios code it's embedded within all those cryptic bswap instructions and the final 'and al, 0FCh'.
Code:
#define MCH_SMRAM 0x9D // SMRAM System Management RAM Control
#define CONFIG_ADDRESS 0x0CF8 // Configuration Address Register
#define CONFIG_DATA 0x0CFC // Configuration Data Register
#define CONFIG_CMD(bus, dev_fn, where) \
(0x80000000 | (((ULONG)(bus)) << 16) | (((dev_fn) & 0x1F) << 11) | (((dev_fn) & 0xE0) << 3) | ((where) & ~3))
// 0x80000000 enables CONFIG_ADDRESS Configuration Enable (CFGE) bit 31
/* alternate definition
#define CONFIG_CMD(bus, dev_fn, where) \
(0x80000000 | (bus << 16) | (dev_fn << 8) | (where & ~3))
*/
////////////////////////////////////////////////////
ULONG Bus = 0;
ULONG Device = 0;
ULONG Register = MCH_SMRAM; // SMRAM System Management RAM Control 0x9D
ULONG Original_CONFIG_ADDRESS;
ULONG current_MCH_SMRAM;
////////////////////////////////////////////////////
// DbgPrint("%08X\n", CONFIG_CMD(Bus, Device, Register)); // 0x8000009C
// Save original Configuration Address Register (0x0CF8) value
Original_CONFIG_ADDRESS = READ_PORT_ULONG((PULONG)CONFIG_ADDRESS);
// Specify which address to read/write to by writing to Configuration Address Register
WRITE_PORT_ULONG((PULONG)CONFIG_ADDRESS, CONFIG_CMD(Bus, Device, Register));
// Read result from Configuration Data Register
current_MCH_SMRAM = READ_PORT_ULONG((PULONG)CONFIG_DATA);
// DbgPrint("MCH_SMRAM %08X\n", current_MCH_SMRAM); // MCH_SMRAM 0038_0A_00
// 0A 1010 bits 1 3 set
// bit 2:0 C_BASE_SEG - hardwired to 010
// bit 3 Global SMRAM Enable
And here's what that sequence looks like disassembled
Code:
mov ebx, ds:__imp__READ_PORT_ULONG@4
mov edi, 0CF8h
push edi ; Port
call ebx ; READ_PORT_ULONG(x)
mov [Original_CONFIG_ADDRESS], eax
mov esi, ds:__imp__WRITE_PORT_ULONG@8
push 8000009Ch ; Value
push edi ; Port
call esi ; WRITE_PORT_ULONG(x,x)
mov ebp, 0CFCh
push ebp ; Port
call ebx ; READ_PORT_ULONG(x)
mov [current_MCH_SMRAM], eax
The expanded versions of those API's as you see in the bios code are:
Code:
_WRITE_PORT_ULONG@8 proc
Port = dword ptr 4
Value = dword ptr 8
mov edx, [esp+Port]
mov eax, [esp+Value]
out dx, eax
retn 8
_WRITE_PORT_ULONG@8 endp
_READ_PORT_ULONG@4 proc
Port = dword ptr 4
mov edx, [esp+Port]
in eax, dx
retn 4
_READ_PORT_ULONG@4 endp
Hopefully this gives you an idea of how such a sequence is written in "normal" 32 bit code, and how it equates to the type of thing you might be seeing in the bios code.
Errmm, I've been sort of side stepping this, but while there are valid reasons for 'initializing SMRAM' as you put it, this is also exactly in the realm of SMM rootkit code and is why I'm familiar with the details. Is there any chance this is actually what we're talking about here?
Kayaker