/* * Program to save/restore/verify the CMOS data of an AT BIOS. * * Copyright 1991-1995 Dave Dunfield * All rights reserved. * * Compile with: cc cmos -fop */ #include #define MAX_SIZE 128-0x10 /* Maximum potential size of CMOS ram */ unsigned char buffer1[MAX_SIZE], buffer2[MAX_SIZE], verbose = -1; int size = 32, ignore[50]; icount = 0; char *help[] = { "\nUse: CMOS [options]\n", "command: Save - Save CMOS data to a file", " Restore - Recover CMOS data from file", " Verify - Compare CMOS data to file\n", "options: -Q - QUIET, inhibit messages", " I=value - Ignore byte at this offset (Verify)", " S=value - Bytes of CMOS to SAVE (default 32)\n", "Copyright 1991 Dave Dunfield", "All rights reserved", 0 }; /* * Main program */ main(argc, argv) int argc; char *argv[]; { int i; char *ptr; FILE *fp; if(argc < 3) { for(i = 0; help[i]; ++i) { fputs(help[i], stderr); putc('\n', stderr); } return; } for(i=3; i < argc; ++i) { ptr = argv[i]; switch((*ptr++ << 8) | *ptr++) { case '-q' : /* Request QUIET mode */ case '-Q' : verbose = 0; break; case 's=' : /* Specify size to save */ case 'S=' : size = atoi(ptr); break; case 'i=' : /* Specify IGNORE bytes */ case 'I=' : ignore[icount++] = atoi(ptr); break; default: fputs("Invalid option: ", stderr); fputs(argv[i], stderr); return; } } switch(*argv[1]) { case 's' : /* Save CMOS data to a file */ case 'S' : read_cmos(buffer1, 0x1000+size); fp = fopen(argv[2], "wvqb"); fput(buffer1, size, fp); fclose(fp); message("CMOS data saved"); break; case 'r' : /* Restore CMOS data from a file */ case 'R' : fp = fopen(argv[2], "rvqb"); size = fget(buffer1, MAX_SIZE, fp); fclose(fp); write_cmos(buffer1, 0x1000+size); message("CMOS data restored"); break; case 'v' : /* Verify CMOS data with file */ case 'V' : fp = fopen(argv[2], "rvqb"); size = fget(buffer2, MAX_SIZE, fp); fclose(fp); read_cmos(buffer1, 0x1000+size); for(i=0; i < icount; ++i) buffer1[ignore[i]] = buffer2[ignore[i]] = 0; for(i=0; i < size; ++i) { if(buffer1[i] != buffer2[i]) { message("CMOS verify FAILED!!!"); exit(-1); } } message("CMOS Data verified"); break; default: /* Invalid command */ fputs("Unknown command: ", stderr); fputs(argv[1], stderr); return; } } /* * Issue message to used only if "verbose" enabled */ message(string) char *string; { if(verbose) fputs(string, stdout); } /* * Read data from the CMOS ram */ read_cmos(dest, addr_size) asm { MOV BX,6[BP] ; Get destination MOV CX,4[BP] ; Get start/size CLI ; Disallow interruptions rdloop: MOV AL,CH ; Get address OUT 70h,AL ; Write it INC CH ; Advance address IN AL,71h ; Read the data MOV [BX],AL ; Write it in dest INC BX ; Advance destination DEC CL ; Reduce count JNZ rdloop ; And continue STI ; Allow interruptions } /* * Write data to the CMOS ram */ write_cmos(source, addr_size) asm { MOV BX,6[BP] ; Get destination MOV CX,4[BP] ; Get start/size CLI ; Disallow interruptions wrloop: MOV AL,CH ; Get address OUT 70h,AL ; Write it MOV AL,[BX] ; Get value to write OUT 71h,AL ; Write it INC CH ; Advance address INC BX ; Advance destination DEC CL ; Reduce count JNZ wrloop ; And continue STI ; Allow interruptions }