mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-09-29 16:21:29 +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
Notes:
sideshowbarker
2024-07-18 07:29:18 +09:00
Author: https://github.com/supercomputer7 Commit: https://github.com/SerenityOS/serenity/commit/7c617394a15 Pull-request: https://github.com/SerenityOS/serenity/pull/8964 Reviewed-by: https://github.com/awesomekling Reviewed-by: https://github.com/caoimhebyrne
|
@ -33,7 +33,7 @@ static u8 bcd_to_binary(u8 bcd)
|
|||
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
|
||||
size_t time_passed_in_milliseconds = 0;
|
||||
|
@ -54,7 +54,7 @@ void read_registers(unsigned& year, unsigned& month, unsigned& day, unsigned& ho
|
|||
hour = 0;
|
||||
minute = 0;
|
||||
second = 0;
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
u8 status_b = CMOS::read(0x0b);
|
||||
|
@ -85,20 +85,31 @@ void read_registers(unsigned& year, unsigned& month, unsigned& day, unsigned& ho
|
|||
}
|
||||
|
||||
year += 2000;
|
||||
return true;
|
||||
}
|
||||
|
||||
time_t now()
|
||||
{
|
||||
// FIXME: We should probably do something more robust here.
|
||||
// Perhaps read all the values twice and verify that they were identical.
|
||||
// We don't want to be caught in the middle of an RTC register update.
|
||||
while (update_in_progress())
|
||||
;
|
||||
|
||||
auto check_registers_against_preloaded_values = [](unsigned year, unsigned month, unsigned day, unsigned hour, unsigned minute, unsigned second) {
|
||||
unsigned checked_year, checked_month, checked_day, checked_hour, checked_minute, checked_second;
|
||||
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;
|
||||
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);
|
||||
return ((days_since_epoch * 24 + hour) * 60 + minute) * 60 + second;
|
||||
|
|
|
@ -13,6 +13,5 @@ namespace RTC {
|
|||
void initialize();
|
||||
time_t now();
|
||||
time_t boot_time();
|
||||
void read_registers(unsigned& year, unsigned& month, unsigned& day, unsigned& hour, unsigned& minute, unsigned& second);
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue