diff options
author | Mark Kettenis <kettenis@cvs.openbsd.org> | 2016-05-14 21:22:57 +0000 |
---|---|---|
committer | Mark Kettenis <kettenis@cvs.openbsd.org> | 2016-05-14 21:22:57 +0000 |
commit | 1125da851d322ce096fad8322d337929f2e37d8a (patch) | |
tree | e5aabe140fb32a8593ffd3e1347cc41468a67bde /sys/arch | |
parent | 27ca7493ad97dd4089b28be2c625def9d994c4d8 (diff) |
Since GetTime() doesn't work on U-Boot, use timer events to simulate a clock
that ticks at every second. This makes the boot prompt timeout work.
Diffstat (limited to 'sys/arch')
-rw-r--r-- | sys/arch/armv7/stand/efiboot/efiboot.c | 82 | ||||
-rw-r--r-- | sys/arch/armv7/stand/efiboot/exec.c | 4 |
2 files changed, 55 insertions, 31 deletions
diff --git a/sys/arch/armv7/stand/efiboot/efiboot.c b/sys/arch/armv7/stand/efiboot/efiboot.c index 3265ce28e11..8f7aae61d91 100644 --- a/sys/arch/armv7/stand/efiboot/efiboot.c +++ b/sys/arch/armv7/stand/efiboot/efiboot.c @@ -1,4 +1,4 @@ -/* $OpenBSD: efiboot.c,v 1.3 2016/05/14 20:00:24 kettenis Exp $ */ +/* $OpenBSD: efiboot.c,v 1.4 2016/05/14 21:22:56 kettenis Exp $ */ /* * Copyright (c) 2015 YASUOKA Masahiko <yasuoka@yasuoka.net> @@ -41,6 +41,9 @@ static EFI_GUID imgp_guid = LOADED_IMAGE_PROTOCOL; static EFI_GUID blkio_guid = BLOCK_IO_PROTOCOL; static EFI_GUID devp_guid = DEVICE_PATH_PROTOCOL; +static void efi_timer_init(void); +static void efi_timer_cleanup(void); + EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *systab) { @@ -231,10 +234,19 @@ machdep(void) efi_loadaddr = addr; efi_heap_init(); + efi_timer_init(); efi_diskprobe(); } void +efi_cleanup(void) +{ + efi_timer_cleanup(); + + BS->ExitBootServices(NULL, 0); +} + +void _rtt(void) { #ifdef EFI_DEBUG @@ -254,40 +266,52 @@ _rtt(void) while (1) { } } -time_t -getsecs(void) +/* + * U-Boot only implements the GetTime() Runtime Service if it has been + * configured with CONFIG_DM_RTC. Most board configurations don't + * include that option, so we can't use it to implement our boot + * prompt timeout. Instead we use timer events to simulate a clock + * that ticks ever second. + */ + +EFI_EVENT timer; +int ticks; + +static VOID +efi_timer(EFI_EVENT event, VOID *context) { - EFI_TIME t; - EFI_STATUS status; - time_t r = 0; - int y = 0; - const int daytab[][14] = { - { 0, -1, 30, 58, 89, 119, 150, 180, 211, 242, 272, 303, 333, 364 }, - { 0, -1, 30, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }, - }; -#define isleap(_y) (((_y) % 4) == 0 && (((_y) % 100) != 0 || ((_y) % 400) == 0)) - - status = EFI_CALL(ST->RuntimeServices->GetTime, &t, NULL); - if (EFI_ERROR(status)) - return 0; + ticks++; +} - /* Calc days from UNIX epoch */ - r = (t.Year - 1970) * 365; - for (y = 1970; y < t.Year; y++) { - if (isleap(y)) - r++; - } - r += daytab[isleap(t.Year)? 1 : 0][t.Month] + t.Day; +static void +efi_timer_init(void) +{ + EFI_STATUS status; - /* Calc secs */ - r *= 60 * 60 * 24; - r += ((t.Hour * 60) + t.Minute) * 60 + t.Second; - if (-24 * 60 < t.TimeZone && t.TimeZone < 24 * 60) - r += t.TimeZone * 60; + status = BS->CreateEvent(EVT_TIMER, TPL_CALLBACK, + efi_timer, NULL, &timer); + if (status == EFI_SUCCESS) + status = BS->SetTimer(timer, TimerPeriodic, 10000000); + if (EFI_ERROR(status)) + printf("Can't create timer\n"); +} - return (r); +static void +efi_timer_cleanup(void) +{ + BS->CloseEvent(timer); } +time_t +getsecs(void) +{ + return ticks; +} + +/* + * Various device-related bits. + */ + void devboot(dev_t dev, char *p) { diff --git a/sys/arch/armv7/stand/efiboot/exec.c b/sys/arch/armv7/stand/efiboot/exec.c index 02c12f0a0d0..5abf40c6e3c 100644 --- a/sys/arch/armv7/stand/efiboot/exec.c +++ b/sys/arch/armv7/stand/efiboot/exec.c @@ -1,4 +1,4 @@ -/* $OpenBSD: exec.c,v 1.3 2016/05/14 20:00:24 kettenis Exp $ */ +/* $OpenBSD: exec.c,v 1.4 2016/05/14 21:22:56 kettenis Exp $ */ /* * Copyright (c) 2006, 2016 Mark Kettenis @@ -132,7 +132,7 @@ run_loadfile(u_long *marks, int howto) memcpy((void *)0x10000000, tags, sizeof(tags)); - BS->ExitBootServices(NULL, 0); + efi_cleanup(); (*(startfuncp)(marks[MARK_ENTRY]))(NULL, (void *)4821, (void *)0x10000000); |