CMOS: Difference between revisions

1,006 bytes added ,  26 days ago
m
Bot: Replace deprecated source tag with syntaxhighlight
[unchecked revision][unchecked revision]
(Century Register As Time and Date Sanity Check)
m (Bot: Replace deprecated source tag with syntaxhighlight)
 
(16 intermediate revisions by 11 users not shown)
Line 1:
"CMOS" is a tiny bit of very low power static memory that lives on the same chip as the Real-Time Clock (RTC). It
It was introduced to IBM PC AT in 1984 which used Motorola MC146818A RTC.
is fairly convenient to actually think of the RTC as being "part" of CMOS.
 
CMOS (and the Real-Time Clock) can only be accessed through IO Ports 0x70 and 0x71. The function of the CMOS
memory is to store 50 (or 114) bytes of "Setup" information for the BIOS while the computer is turned off --
Line 36 ⟶ 37:
as follows:
 
* <tt>outb (0x70, (NMI_disable_bit << 7) | (selected CMOS register number));</tt>
 
Once a register is selected, you either read the value of that register on Port 0x71 (with inb or an equivalent
function), or you write a new value to that register -- also on Port 0x71 (with outb, for example):
 
* <tt>val_8bit = inb (0x71);</tt>
 
Note1: Reading or writing Port 0x71 seems to default the "selected register" back to 0xD. So you need to
Line 89 ⟶ 90:
holes", it ignores memory mapped hardware, and it ignores memory reserved for important ACPI system tables.
 
(Register 0x350x31 (high byte) | Register 0x340x30 (low byte)) << 16 = total memory between 16M and 4G ... usually.
But this number is untrustworthy when the system has more than 4G, it ignores "memory holes", it ignores
memory mapped hardware, and it ignores memory reserved for important ACPI system tables.
Line 99 ⟶ 100:
Better information can always be obtained via BIOS function INT13h AH=8, or by sending an ATA 'Identify'
command to the disk in [[ATA PIO Mode]].
 
 
== The Real-Time Clock ==
Line 119:
 
<pre>
Register Contents Range
0x00 Seconds 0–59
0x02 Minutes 0–59
0x04 Hours 0–23 in 24-hour mode,
1–12 in 12-hour mode, highest bit set if pm
0x06 Weekday
0x06 Weekday 1–7, Sunday = 1
0x07 Day of Month
0x080x07 Day of Month 1–31
0x08 Month 1–12
0x09 Year 0–99
0x32 Century (maybe) 19–20?
0x0A Status Register A
0x0B Status Register B
Line 139 ⟶ 140:
 
If there is no century register then software can guess. For example, a piece of software written in 1990 can use the (2 digit) year register to determine the most likely century - if the RTC year register is higher than or equal to 90 then the year is probably be "19YY" and if the RTC year register is less than 90 than the year must be "20YY". In this way, software can correctly determine the century for up to 99 years after the software is written.
 
 
==== Century Register As Time and Date Sanity Check ====
Line 149:
Essentially; the method (described above) for guessing the century when there is no century register is much more reliable than the CMOS/RTC century register (if it exists). This means that the century register (if/when present) can be used in reverse, as a way to check if the CMOS/RTC time and date are sane (or if the CMOS/RTC has a flat battery or something).
 
Basically, you'd guess the century (based on the software's release datadate and RTC's year), then seecheck if the CMOS/RTC century is the same as your guess, and if it's not the samethen assume that theall CMOS/RTC hastime an invalidand date andfields timeare invalid.
 
 
=== Weekday Register ===
 
The RTC chip is able to keep track of the current day of the week. All it does is increment its "Weekday" register at midnight and reset it to zero1 if itthe reachesincremented value would go above 7[https://groups.google.com/d/msg/alt.os.development/qPxWHKC48rw/yjAt-c8IAQAJ]. Unfortunately there is no guarantee that this register was ever set correctly by anything (including when the user changes the time and date using the BIOS configuration screen). It is entirely unreliable and should not be used.
 
The correct way to determine the current day of the week is to calculate it from the date (see [http://en.wikipedia.org/wiki/Weekday_determination the article on Wikipedia] for details of this calculation).
 
 
=== RTC Update In Progress ===
Line 172 ⟶ 170:
 
The second alternative is to be prepared for dodgy/inconsistent values and cope with them if they occur. To do this, make sure the "Update in progress" flag is clear (e.g. "''while(update_in_progress_flag != clear)''") then read all the time and date registers; then make sure the "Update in progress" flag is clear again (e.g. "''while(update_in_progress_flag != clear)''") and read all the time and date registers again. If the values that were read the first time are the same as the value that were read the second time then the values must be correct. If any of the values are different you need to do it again, and keep doing it again until the newest values are the same as the previous values.
 
 
=== Format of Bytes ===
Line 210 ⟶ 207:
 
=== Reading from the CMOS ===
<sourcesyntaxhighlight lang="c">
ReadFromCMOS (unsigned char array [])
{
Line 232 ⟶ 229:
}
}
</syntaxhighlight>
</source>
 
=== Writing to the CMOS ===
<sourcesyntaxhighlight lang="c">
WriteTOCMOS(unsigned char array[])
{
Line 255 ⟶ 252:
}
}
</syntaxhighlight>
</source>
 
=== Reading All RTC Time and Date Registers ===
<sourcesyntaxhighlight lang="c">
#define CURRENT_YEAR 20142023 // Change this each year!
 
int century_register = 0x00; // Set by ACPI table parsing code if possible
Line 277 ⟶ 274:
cmos_data = 0x71
};
 
 
int get_update_in_progress_flag() {
Line 283 ⟶ 279:
return (in_byte(cmos_data) & 0x80);
}
 
 
unsigned char get_RTC_register(int reg) {
Line 289 ⟶ 284:
return in_byte(cmos_data);
}
 
 
void read_rtc() {
Line 370 ⟶ 364:
}
}
</syntaxhighlight>
</source>
 
== See Also ==
* [[RTC]]
[https://web.archive.org/web/20111209041013/http://www-ivs.cs.uni-magdeburg.de/~zbrog/asm/cmos.html Old CMOS Map]
 
[http://www.bioscentral.com/misc/cmosmap.htm Better CMOS Map]
== External Links ==
* [https://web.archive.org/web/20111209041013/http://www-ivs.cs.uni-magdeburg.de/~zbrog/asm/cmos.html Old CMOS Map]
* [http://www.bioscentral.com/misc/cmosmap.htm Better CMOS Map]
* [http://bitsavers.trailing-edge.com/pdf/ibm/pc/at/1502494_PC_AT_Technical_Reference_Mar84.pdf IBM PC AT Technical Reference]
* [http://web.stanford.edu/class/cs140/projects/pintos/specs/mc146818a.pdf MC146818A REAL-TIME CLOCK PLUS RAM (RTC)]
* [http://www.bitsavers.org/pdf/ibm/pc/ps2/PS2_Model_50_Technical_Reference_May88.pdf IBM PS/2 Technical Reference]
* [https://www.singlix.com/trdos/archive/pdf_archive/real-time-clock-nmi-enable-paper.pdf Intel Application Note: Accessing the Real Time Clock Registers and NMI Enable Bit]
 
[[Category:X86]]
[[Category:Time]]