summaryrefslogtreecommitdiff
path: root/sys/arch
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2016-05-14 21:22:57 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2016-05-14 21:22:57 +0000
commit1125da851d322ce096fad8322d337929f2e37d8a (patch)
treee5aabe140fb32a8593ffd3e1347cc41468a67bde /sys/arch
parent27ca7493ad97dd4089b28be2c625def9d994c4d8 (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.c82
-rw-r--r--sys/arch/armv7/stand/efiboot/exec.c4
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);