mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 23:27:35 +00:00
Kernel: Ensure we read valid values from the RTC CMOS registers
We try to read twice from the RTC CMOS registers, and if the values are not the same for 5 attempts, we know there's a malfunction with the hardware so we declare these values as bogus in the kernel log.
This commit is contained in:
parent
517460d3a9
commit
7c617394a1
2 changed files with 20 additions and 10 deletions
|
@ -33,7 +33,7 @@ static u8 bcd_to_binary(u8 bcd)
|
||||||
return (bcd & 0x0F) + ((bcd >> 4) * 10);
|
return (bcd & 0x0F) + ((bcd >> 4) * 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
void read_registers(unsigned& year, unsigned& month, unsigned& day, unsigned& hour, unsigned& minute, unsigned& second)
|
static bool try_to_read_registers(unsigned& year, unsigned& month, unsigned& day, unsigned& hour, unsigned& minute, unsigned& second)
|
||||||
{
|
{
|
||||||
// Note: Let's wait 0.01 seconds until we stop trying to query the RTC CMOS
|
// Note: Let's wait 0.01 seconds until we stop trying to query the RTC CMOS
|
||||||
size_t time_passed_in_milliseconds = 0;
|
size_t time_passed_in_milliseconds = 0;
|
||||||
|
@ -54,7 +54,7 @@ void read_registers(unsigned& year, unsigned& month, unsigned& day, unsigned& ho
|
||||||
hour = 0;
|
hour = 0;
|
||||||
minute = 0;
|
minute = 0;
|
||||||
second = 0;
|
second = 0;
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
u8 status_b = CMOS::read(0x0b);
|
u8 status_b = CMOS::read(0x0b);
|
||||||
|
@ -85,20 +85,31 @@ void read_registers(unsigned& year, unsigned& month, unsigned& day, unsigned& ho
|
||||||
}
|
}
|
||||||
|
|
||||||
year += 2000;
|
year += 2000;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
time_t now()
|
time_t now()
|
||||||
{
|
{
|
||||||
// FIXME: We should probably do something more robust here.
|
|
||||||
// Perhaps read all the values twice and verify that they were identical.
|
auto check_registers_against_preloaded_values = [](unsigned year, unsigned month, unsigned day, unsigned hour, unsigned minute, unsigned second) {
|
||||||
// We don't want to be caught in the middle of an RTC register update.
|
unsigned checked_year, checked_month, checked_day, checked_hour, checked_minute, checked_second;
|
||||||
while (update_in_progress())
|
if (!try_to_read_registers(checked_year, checked_month, checked_day, checked_hour, checked_minute, checked_second))
|
||||||
;
|
return false;
|
||||||
|
return checked_year == year && checked_month == month && checked_day == day && checked_hour == hour && checked_minute == minute && checked_second == second;
|
||||||
|
};
|
||||||
|
|
||||||
unsigned year, month, day, hour, minute, second;
|
unsigned year, month, day, hour, minute, second;
|
||||||
read_registers(year, month, day, hour, minute, second);
|
bool did_read_rtc_sucessfully = false;
|
||||||
|
for (size_t attempt = 0; attempt < 5; attempt++) {
|
||||||
|
if (!try_to_read_registers(year, month, day, hour, minute, second))
|
||||||
|
break;
|
||||||
|
if (check_registers_against_preloaded_values(year, month, day, hour, minute, second)) {
|
||||||
|
did_read_rtc_sucessfully = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
dmesgln("RTC: Year: {}, month: {}, day: {}, hour: {}, minute: {}, second: {}", year, month, day, hour, minute, second);
|
dmesgln("RTC: {} Year: {}, month: {}, day: {}, hour: {}, minute: {}, second: {}", (did_read_rtc_sucessfully ? "" : "(failed to read)"), year, month, day, hour, minute, second);
|
||||||
|
|
||||||
time_t days_since_epoch = years_to_days_since_epoch(year) + day_of_year(year, month, day);
|
time_t days_since_epoch = years_to_days_since_epoch(year) + day_of_year(year, month, day);
|
||||||
return ((days_since_epoch * 24 + hour) * 60 + minute) * 60 + second;
|
return ((days_since_epoch * 24 + hour) * 60 + minute) * 60 + second;
|
||||||
|
|
|
@ -13,6 +13,5 @@ namespace RTC {
|
||||||
void initialize();
|
void initialize();
|
||||||
time_t now();
|
time_t now();
|
||||||
time_t boot_time();
|
time_t boot_time();
|
||||||
void read_registers(unsigned& year, unsigned& month, unsigned& day, unsigned& hour, unsigned& minute, unsigned& second);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue