CMOS memory

In order to read the content of the CMOS memory of my IBM PS/1 model 2011, I wrote the following C program.
It compiles with Turbo C and it needs TASM as well.

The content of the CMOS memory of my PS/1 can be found here.

You can download a precompiled version of the program here.

Pastebin of the following program

#include <stdio.h>
#define CMOS_SIZE 64

/* 
This function reads a value from the CMOS, preserving the passed NMI bit value.
To read the CMOS this function disables NMIs. It's responsibility of the caller to inform this function 
about the current state of the NMI bit.
So to read CMOS byte 0Fh with NMI restored to enabled call read_cmos(0x0F). Call read_cmos(0x8F) otherwise.

The asm procedure was taken from the BIOS of a IBM PS/1 model 2011.
*/
unsigned char read_cmos(unsigned char _addr)
{
	unsigned char value;
	asm {
	mov	al, _addr
	pushf			/* save the CPU flags */	
	rol     al, 1		/* rotate 8-bit AL left once (AL[0] = AL[7]) */
	stc			/* CF = 1 */
	rcr     al, 1		/* save the original value of _addr[7] (the NMI bit) in CF.
				rotate 9-bits (CF, AL) right once. now AL[7]=1 (NMI disabled) and CF=AL[0] */
	cli			/* IF = 0 (disable interrupts) */
	out     70h, al		/* inform the CMOS about the memory register we want to read */
	jmp     short $+2	/* delay */
	in      al, 71h		/* read the CMOS register value and put it in AL */
	push    ax		/* save AX */
	mov     al, 1Eh		/* AL = 11110b (0Fh shifted left by 1) */
	rcr     al, 1		/* reset the NMI bit to its original value. rotate 9-bits (CF, AL) right once */
	out     70h, al		/* CMOS reg = AL (it can be 8Fh or 0Fh) */
	jmp     short $+2	/* delay */
	in      al, 71h		/* bogus CMOS read to keep the chip happy */
	pop     ax		/* restore AX */
	popf			/* restore CPU flags */
	mov	value, al	/* return the read CMOS value for index _addr */
	}
	/* 
	The "mov value, al" is redundant, because to translate "return value;" the compiler will add 
	"mov al, [bp+var_1]" at the end anyway (AL is the register where the function return value should be).
	But I will leave the instruction there, with the associated "return value;", just for clarity. 
	*/
	return value;
}

int main()
{
	unsigned char p, cmos[CMOS_SIZE];
	FILE *outf;
	
	/* read the CMOS in its entirety */
	for(p=0; p<CMOS_SIZE; p++) {
		cmos[p] = read_cmos(p);
	}
	
	/* write the CMOS data to screen and file */
	outf = fopen("cmos.txt","w");
	if(outf == NULL) {
		printf("error opening file\n");
		return 1;
	}
	for(p=0; p<CMOS_SIZE; p++) {
		printf("[%2X=%2X] ", p, cmos[p]);
		fprintf(outf, "%2X = %2X\n", p, cmos[p]);
	}
	fclose(outf);
	
	return 0;
}

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.