From patchwork Wed Oct 18 16:13:04 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Heinrich Schuchardt X-Patchwork-Id: 827712 X-Patchwork-Delegate: agraf@suse.de Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 3yHHMR0Q9bz9sBd for ; Thu, 19 Oct 2017 03:19:46 +1100 (AEDT) Received: by lists.denx.de (Postfix, from userid 105) id 96AABC21F01; Wed, 18 Oct 2017 16:17:06 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=FREEMAIL_FROM autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id 67146C21EA5; Wed, 18 Oct 2017 16:13:57 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 054F9C21EC5; Wed, 18 Oct 2017 16:13:36 +0000 (UTC) Received: from mout.gmx.net (mout.gmx.net [212.227.15.15]) by lists.denx.de (Postfix) with ESMTPS id A99F2C21EA2 for ; Wed, 18 Oct 2017 16:13:32 +0000 (UTC) Received: from workstation4.fritz.box ([94.114.42.150]) by mail.gmx.com (mrgmx001 [212.227.17.184]) with ESMTPSA (Nemesis) id 0LgptO-1dPgnF0YkA-00oHZi; Wed, 18 Oct 2017 18:13:31 +0200 From: Heinrich Schuchardt To: Alexander Graf Date: Wed, 18 Oct 2017 18:13:04 +0200 Message-Id: <20171018161320.7231-3-xypron.glpk@gmx.de> X-Mailer: git-send-email 2.14.2 In-Reply-To: <20171018161320.7231-1-xypron.glpk@gmx.de> References: <20171018161320.7231-1-xypron.glpk@gmx.de> X-Provags-ID: V03:K0:xMu/gxFfR0w/SvlsiCpcQqGpWHb0ycjUakkCC8+0Y8FrRwWMGjb XzI6kBtRezVU2TxP5IqTPkzvKRjU4zGRPcvDovzXX1D59yPdkYYJHwXD4KMo9ziIsFyNVRa ig2ts3gYmUFInmf3oYA6jRjSLlxWDtIr+30BMw3qi5mjqXvwtU9izW+IiFTPXkTwOLob6vC rZtYkahMzCJmq0R75mo/g== X-UI-Out-Filterresults: notjunk:1; V01:K0:/inEcZ7OV4Q=:HCAmVeSeDb69KFmUa7XkEw 5E6F8zc2sV+0l2yiJCi4s9gPhG6wQ9wPnWuC5V6Zr5HwKC+YvJPxXrUc63I8/4hVw3XX4AAGR O5R6+Mes/nOPyCOhgEpDXq+ayJl1mrR+ECDTaWRb/7ckNL0vf8A/9du/PE+0pq+pfIZ4hivTi LytCTUl09DLDTf5b5fW5COB19xDjndmlD3r8Ph1M6ecbiMKzQDi/B2gj7N2vFLsYVsOkKCI0e di5K8HxvzX9ImtvZqBwENO2jAndUZkWFwillRUZySNSrIpLMBRudzf3UAvUJkU3PHq+7L3Q5k y48nK1Cq9iebnA2S4JdC4w32hMXjgBZyUstLg+xtl6uv6ctGS4WxyCUsMNF2dYs3pKfVwvKwq kTWlqK4iP7aiuYgkIDzhCrIZK4q0KyKWvHY8QVylhW1M+jWyMGMeexTe1pxiRV7qAxPV49MYz U4sdGwD7vKp3vDer9JGasX+a/mpHZ00duXWiFnsDdoCcm9idKvauPKWOb9T3ES+WIlyiQrVIT 5uTeZnuyiOPtE8lKoN1g0PLPc6Sn+qaGx7Iys+PsHnv59mvEBvnlrBZcsSbWL5GWPp3exo7Gm LAV3DAxA/UH9WRT6/UTom4W+yqv/R4B/7RDPimGkG0n+0Ys+Q5UOcIF63vu4Si7T0Rgn4FTBZ 2mK2KNL9cfuv0o6GVjuAddb/a6flcjNkO79qSwIY/vFTHd49J0RAL3yd49xQ+sZG3f7hi/zNU /T8BPDZX694UVh66EcOx/4lm8sWDeUOhecU5msUcQV4AGh7N8Pzrq/boHQh4LzxJeeHBavkLf lqNGN9yxg6BdprKXLHOc0Oa830qFA== Cc: u-boot@lists.denx.de, Heinrich Schuchardt Subject: [U-Boot] [PATCH v4 02/18] efi_loader: implement SetWatchdogTimer X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" The watchdog is initialized with a 5 minute timeout period. It can be reset by SetWatchdogTimer. It is stopped by ExitBoottimeServices. Signed-off-by: Heinrich Schuchardt --- v4 no change v3 add a constant for 1s to 100ns conversion v2 code comments updated --- cmd/bootefi.c | 1 + include/efi_loader.h | 4 ++ lib/efi_loader/Makefile | 2 +- lib/efi_loader/efi_boottime.c | 17 ++------- lib/efi_loader/efi_watchdog.c | 89 +++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 98 insertions(+), 15 deletions(-) create mode 100644 lib/efi_loader/efi_watchdog.c diff --git a/cmd/bootefi.c b/cmd/bootefi.c index 478bc116e2..18176a1266 100644 --- a/cmd/bootefi.c +++ b/cmd/bootefi.c @@ -43,6 +43,7 @@ static void efi_init_obj_list(void) #ifdef CONFIG_GENERATE_SMBIOS_TABLE efi_smbios_register(); #endif + efi_watchdog_register(); /* Initialize EFI runtime services */ efi_reset_system_init(); diff --git a/include/efi_loader.h b/include/efi_loader.h index 1b92edbd77..af64b11cee 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -163,6 +163,8 @@ int efi_disk_register(void); int efi_gop_register(void); /* Called by bootefi to make the network interface available */ int efi_net_register(void); +/* Called by bootefi to make the watchdog available */ +int efi_watchdog_register(void); /* Called by bootefi to make SMBIOS tables available */ void efi_smbios_register(void); @@ -171,6 +173,8 @@ efi_fs_from_path(struct efi_device_path *fp); /* Called by networking code to memorize the dhcp ack package */ void efi_net_set_dhcp_ack(void *pkt, int len); +/* Called by efi_set_watchdog_timer to reset the timer */ +efi_status_t efi_set_watchdog(unsigned long timeout); /* Called from places to check whether a timer expired */ void efi_timer_check(void); diff --git a/lib/efi_loader/Makefile b/lib/efi_loader/Makefile index ddb978f650..83d879b686 100644 --- a/lib/efi_loader/Makefile +++ b/lib/efi_loader/Makefile @@ -17,7 +17,7 @@ endif obj-$(CONFIG_CMD_BOOTEFI_HELLO) += helloworld_efi.o obj-y += efi_image_loader.o efi_boottime.o efi_runtime.o efi_console.o obj-y += efi_memory.o efi_device_path_to_text.o efi_device_path.o -obj-y += efi_file.o efi_variable.o efi_bootmgr.o +obj-y += efi_file.o efi_variable.o efi_bootmgr.o efi_watchdog.o obj-$(CONFIG_LCD) += efi_gop.o obj-$(CONFIG_DM_VIDEO) += efi_gop.o obj-$(CONFIG_PARTITIONS) += efi_disk.o diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index 30577f717e..fd8d15655b 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -155,18 +155,6 @@ void efi_signal_event(struct efi_event *event) event->is_queued = false; } -/* - * Write a debug message for an EPI API service that is not implemented yet. - * - * @funcname function that is not yet implemented - * @return EFI_UNSUPPORTED - */ -static efi_status_t efi_unsupported(const char *funcname) -{ - debug("EFI: App called into unimplemented function %s\n", funcname); - return EFI_EXIT(EFI_UNSUPPORTED); -} - /* * Raise the task priority level. * @@ -1454,6 +1442,7 @@ static efi_status_t EFIAPI efi_exit_boot_services(void *image_handle, bootm_disable_interrupts(); /* Give the payload some time to boot */ + efi_set_watchdog(0); WATCHDOG_RESET(); return EFI_EXIT(EFI_SUCCESS); @@ -1497,7 +1486,7 @@ static efi_status_t EFIAPI efi_stall(unsigned long microseconds) /* * Reset the watchdog timer. * - * This function implements the WatchdogTimer service. + * This function implements the SetWatchdogTimer service. * See the Unified Extensible Firmware Interface (UEFI) specification * for details. * @@ -1514,7 +1503,7 @@ static efi_status_t EFIAPI efi_set_watchdog_timer(unsigned long timeout, { EFI_ENTRY("%ld, 0x%"PRIx64", %ld, %p", timeout, watchdog_code, data_size, watchdog_data); - return efi_unsupported(__func__); + return EFI_EXIT(efi_set_watchdog(timeout)); } /* diff --git a/lib/efi_loader/efi_watchdog.c b/lib/efi_loader/efi_watchdog.c new file mode 100644 index 0000000000..35a45dedf8 --- /dev/null +++ b/lib/efi_loader/efi_watchdog.c @@ -0,0 +1,89 @@ +/* + * EFI watchdog + * + * Copyright (c) 2017 Heinrich Schuchardt + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include + +/* Conversion factor from seconds to multiples of 100ns */ +#define EFI_SECONDS_TO_100NS 10000000ULL + +static struct efi_event *watchdog_timer_event; + +/* + * Reset the system when the watchdog event is notified. + * + * @event: the watchdog event + * @context: not used + */ +static void EFIAPI efi_watchdog_timer_notify(struct efi_event *event, + void *context) +{ + EFI_ENTRY("%p, %p", event, context); + + printf("\nEFI: Watchdog timeout\n"); + EFI_CALL_VOID(efi_runtime_services.reset_system(EFI_RESET_COLD, + EFI_SUCCESS, 0, NULL)); + + EFI_EXIT(EFI_UNSUPPORTED); +} + +/* + * Reset the watchdog timer. + * + * This function is used by the SetWatchdogTimer service. + * + * @timeout: seconds before reset by watchdog + * @return: status code + */ +efi_status_t efi_set_watchdog(unsigned long timeout) +{ + efi_status_t r; + + if (timeout) + /* Reset watchdog */ + r = efi_set_timer(watchdog_timer_event, EFI_TIMER_RELATIVE, + EFI_SECONDS_TO_100NS * timeout); + else + /* Deactivate watchdog */ + r = efi_set_timer(watchdog_timer_event, EFI_TIMER_STOP, 0); + return r; +} + +/* + * Initialize the EFI watchdog. + * + * This function is called by efi_init_obj_list() + */ +int efi_watchdog_register(void) +{ + efi_status_t r; + + /* + * Create a timer event. + */ + r = efi_create_event(EVT_TIMER | EVT_NOTIFY_SIGNAL, TPL_CALLBACK, + efi_watchdog_timer_notify, NULL, + &watchdog_timer_event); + if (r != EFI_SUCCESS) { + printf("ERROR: Failed to register watchdog event\n"); + return r; + } + /* + * The UEFI standard requires that the watchdog timer is set to five + * minutes when invoking an EFI boot option. + * + * Unified Extensible Firmware Interface (UEFI), version 2.7 Errata A + * 7.5. Miscellaneous Boot Services - EFI_BOOT_SERVICES.SetWatchdogTimer + */ + r = efi_set_watchdog(300); + if (r != EFI_SUCCESS) { + printf("ERROR: Failed to set watchdog timer\n"); + return r; + } + return 0; +}