Monday, 6 September 2010

Digging into the BIOS CMOS Memory

The BIOS settings of a PC are stored in non-volatile memory (sometimes known as NVRAM) to ensure they are saved when the machine is off. On a PC, this NVRAM is CMOS (Complimentary Metal Oxide Semiconductor) memory and is trickle charged by a small battery to ensure the data is preserved. CMOS memory requires very little power hence it can be kept non-volatile by a battery for several years.

One can access the CMOS memory via ports 0x70 and 0x71. One writes the address of the CMOS memory location you want to read to port 0x70 and then read the contents via a read of port 0x70. I implemented this as follows:

unsigned char cmos_read(int offset)
{
unsigned char value;

ioperm(0x70, 0x2, 1);
ioperm(0x80, 0x1, 1);

outb(offset, 0x70);
outb(0, 0x80); /* Small delay */
value = inb(0x71);

ioperm(0x80, 0x1, 0);
ioperm(0x70, 0x2, 0);

return value;
}
..I was not 100% sure of a small port delay was required between the write to port 0x70 and the read of data on port 0x71, but I added one in by writing to port 0x80 just in case. The ioperm() calls are required to get access to the I/O ports, and one needs to run this code with root privileges otherwise you will get a segmentation fault.

Then it is a case of reading 128 bytes or so of CMOS memory using this function. The next step is decoding this raw data. Web-pages such as http://www.bioscentral.com/misc/cmosmap.htm contain CMOS memory maps, but it does tend to vary from machine to machine. With data from several memory map descriptions that I found on the Web I have figured out some common across different BIOS implementations and written some code to annotate the contents of the CMOS memory. There are a bunch of fields that need a little more decoding, but that's work in progress...

My aim is to add this into the Firmware Test Suite for 11.04 as part of a diagnostic feature.

No comments:

Post a Comment