From patchwork Wed Jul 5 17:47:13 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Heinrich Schuchardt X-Patchwork-Id: 784802 X-Patchwork-Delegate: agraf@suse.de Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 3x2pKB4WJ0z9s75 for ; Thu, 6 Jul 2017 03:49:18 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id 62CA7C21EB9; Wed, 5 Jul 2017 17:49:15 +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, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2 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 628D7C21ED6; Wed, 5 Jul 2017 17:49:13 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 59CAFC21EC9; Wed, 5 Jul 2017 17:48:54 +0000 (UTC) Received: from mout.gmx.net (mout.gmx.net [212.227.15.15]) by lists.denx.de (Postfix) with ESMTPS id C200AC21ECF for ; Wed, 5 Jul 2017 17:48:50 +0000 (UTC) Received: from workstation4.fritz.box ([88.152.145.149]) by mail.gmx.com (mrgmx002 [212.227.17.184]) with ESMTPSA (Nemesis) id 0ML72n-1dSXQR0iQ5-000JOi; Wed, 05 Jul 2017 19:48:10 +0200 From: Heinrich Schuchardt To: Alexander Graf Date: Wed, 5 Jul 2017 19:47:13 +0200 Message-Id: <20170705174715.28626-2-xypron.glpk@gmx.de> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20170705174715.28626-1-xypron.glpk@gmx.de> References: <20170705174715.28626-1-xypron.glpk@gmx.de> X-Provags-ID: V03:K0:yY98zi3PP7fuxSWWRyuDuiFdjZ2F6lRT0pYLwE9g5YNln8siOkd bElmVpgWAAeYfhdsA3tP4KzeCTs0BfiEraSl2d6TLN6RpY0Qn6SY8tfMh3tfy1t7TXeWiTQ mydEtLfdWIwIrx8vajCCM8dFWHcJOT9zgTDS/ShG8oJVV+pyuacEsXaKmxYIlsTmfXSB772 nKDPd1ThXKiWH9fRiS8+g== X-UI-Out-Filterresults: notjunk:1; V01:K0:P52YadL/EHE=:Td0ruV7WhZ+Ek4uVTEj+MV diwTYv0vcX2E9FFG4bSwbD+Cv1r2DDxth5dnC7ETWhEitHQe8s8r0qW9fRjtTCgoMl2hnrVc0 JXUFuoEf+eQsmof84PDOX1tSdEiQuEiJXvMmf9dOvOMsevpc10uxHtTTQC4LxwPTXAn+OEhf7 meRLnKw2aovPywnrdHkYiF9NHNVKL4jLpIVnx+mkNM6kQs3u3GEn4RjzBSPnS7gj2Y+aIdT4o 43t9OXQr07q+zp2e2jcjdc+EFoGfqHq/3sO3Yerz2Pcx8dLDSjI+pg/8KrSYlj7Z+y7OqnPYI ALS/ALb6Y1WrtIQGOVhYHmCsJGwtOGlywXsnDJ4D9HNFrFvrdKiwcegKu1Q/Kg5Zg9CuqeVAT bqof3kfn4m9yeCZstewtczI7dwIaGzvT3rkEcYCFIy9lXAuSXnfnzkLR5DZvjN155ko8PC3Vu wGWfoadLtyQr+YNY5L8puhxVvmlNCchbcoNBKjhviCusoRKydgitrXGhwFYxuADKGFpkuypHJ oTAx1wtmCaC5cne0j5EvRvPdHcSFHCutncY3b7O42wuZ1nw/c+2/7KivLbMjugYDm+AOQDpmf Y8k2s13YCGasE77h3ZuYWn76D5a3wKhZiDqZ6/RSk1xV48QCxEcwepQHKjVd13o2mHDWU55ir yB8KUSeL9zv1x/fRZFguPgRNngSbrNz6Fe01YR1RsdCcmNhe1cDQ5KugmLUU5zCqOSUaEu0Fo pbXmCWoWNQQ/qvtDkc4QVuUYnnNt2coIqUfRCvKB0WEOQJbJEpd+cZG3biA= Cc: u-boot@lists.denx.de, Heinrich Schuchardt Subject: [U-Boot] [PATCH 1/3] efi_loader: implement multiple event support 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" Up to now the boot time supported only a single event. This patch now allows four events. Signed-off-by: Heinrich Schuchardt --- include/efi_api.h | 8 ++- include/efi_loader.h | 23 ++++++ lib/efi_loader/efi_boottime.c | 161 ++++++++++++++++++++++++++---------------- 3 files changed, 131 insertions(+), 61 deletions(-) diff --git a/include/efi_api.h b/include/efi_api.h index 42cd47ff08..18bef722c6 100644 --- a/include/efi_api.h +++ b/include/efi_api.h @@ -28,8 +28,12 @@ enum efi_event_type { EFI_TIMER_RELATIVE = 2 }; -#define EVT_NOTIFY_WAIT 0x00000100 -#define EVT_NOTIFY_SIGNAL 0x00000200 +#define EVT_TIMER 0x80000000 +#define EVT_RUNTIME 0x40000000 +#define EVT_NOTIFY_WAIT 0x00000100 +#define EVT_NOTIFY_SIGNAL 0x00000200 +#define EVT_SIGNAL_EXIT_BOOT_SERVICES 0x00000201 +#define EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE 0x60000202 /* EFI Boot Services table */ struct efi_boot_services { diff --git a/include/efi_loader.h b/include/efi_loader.h index c620652307..a35b971f7e 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -71,6 +71,29 @@ struct efi_object { void *handle; }; +/** + * struct efi_event + * + * @type: Type of event + * @trigger_type: Type of timer + * @trigger_time: Period of the timer + * @trigger_next: Next time to trigger the timer + * @nofify_function: Function to call when the event is triggered + * @notify_context: Data to be passed to the notify function + * @signaled: The notify function was already called + */ +struct efi_event { + u32 type; + unsigned long notify_tpl; + void (EFIAPI *notify_function)(void *event, void *context); + void *notify_context; + u64 trigger_next; + u32 trigger_time; + enum efi_event_type trigger_type; + int signaled; +}; + + /* This list contains all UEFI objects we know of */ extern struct list_head efi_obj_list; diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index 3060c25a2a..ef3e7d9d52 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -162,21 +162,10 @@ static efi_status_t EFIAPI efi_free_pool_ext(void *buffer) } /* - * Our event capabilities are very limited. Only support a single - * event to exist, so we don't need to maintain lists. + * Our event capabilities are very limited. Only a small limited + * number of events is allowed to coexist. */ -static struct { - enum efi_event_type type; - u32 trigger_type; - u32 trigger_time; - u64 trigger_next; - unsigned long notify_tpl; - void (EFIAPI *notify_function) (void *event, void *context); - void *notify_context; -} efi_event = { - /* Disable timers on bootup */ - .trigger_next = -1ULL, -}; +static struct efi_event efi_events[16]; static efi_status_t EFIAPI efi_create_event( enum efi_event_type type, ulong notify_tpl, @@ -184,13 +173,10 @@ static efi_status_t EFIAPI efi_create_event( void *context), void *notify_context, void **event) { + int i; + EFI_ENTRY("%d, 0x%lx, %p, %p", type, notify_tpl, notify_function, notify_context); - if (efi_event.notify_function) { - /* We only support one event at a time */ - return EFI_EXIT(EFI_OUT_OF_RESOURCES); - } - if (event == NULL) return EFI_EXIT(EFI_INVALID_PARAMETER); @@ -201,13 +187,20 @@ static efi_status_t EFIAPI efi_create_event( notify_function == NULL) return EFI_EXIT(EFI_INVALID_PARAMETER); - efi_event.type = type; - efi_event.notify_tpl = notify_tpl; - efi_event.notify_function = notify_function; - efi_event.notify_context = notify_context; - *event = &efi_event; - - return EFI_EXIT(EFI_SUCCESS); + for (i = 0; i < ARRAY_SIZE(efi_events); ++i) { + if (efi_events[i].type) + continue; + efi_events[i].type = type; + efi_events[i].notify_tpl = notify_tpl; + efi_events[i].notify_function = notify_function; + efi_events[i].notify_context = notify_context; + /* Disable timers on bootup */ + efi_events[i].trigger_next = -1ULL; + efi_events[i].signaled = 0; + *event = &efi_events[i]; + return EFI_EXIT(EFI_SUCCESS); + } + return EFI_EXIT(EFI_OUT_OF_RESOURCES); } /* @@ -216,17 +209,25 @@ static efi_status_t EFIAPI efi_create_event( */ void efi_timer_check(void) { + int i; u64 now = timer_get_us(); - if (now >= efi_event.trigger_next) { - /* Triggering! */ - if (efi_event.trigger_type == EFI_TIMER_PERIODIC) - efi_event.trigger_next += efi_event.trigger_time / 10; - if (efi_event.type & (EVT_NOTIFY_WAIT | EVT_NOTIFY_SIGNAL)) - efi_event.notify_function(&efi_event, - efi_event.notify_context); + for (i = 0; i < ARRAY_SIZE(efi_events); ++i) { + if (!(efi_events[i].type & EVT_TIMER) || + efi_events[i].trigger_type == EFI_TIMER_STOP || + now < efi_events[i].trigger_next) + continue; + if (efi_events[i].trigger_type == EFI_TIMER_PERIODIC) + efi_events[i].trigger_next += + efi_events[i].trigger_time / 10; + efi_events[i].signaled = 1; + if (efi_events[i].type & EVT_NOTIFY_SIGNAL) { + EFI_EXIT(EFI_SUCCESS); + efi_events[i].notify_function(&efi_events[i], + efi_events[i].notify_context); + efi_restore_gd(); + } } - WATCHDOG_RESET(); } @@ -236,67 +237,109 @@ static efi_status_t EFIAPI efi_set_timer(void *event, int type, /* We don't have 64bit division available everywhere, so limit timer * distances to 32bit bits. */ u32 trigger32 = trigger_time; + int i; EFI_ENTRY("%p, %d, %"PRIx64, event, type, trigger_time); if (trigger32 < trigger_time) { + trigger32 = 0xffffffff; printf("WARNING: Truncating timer from %"PRIx64" to %x\n", trigger_time, trigger32); } - if (event != &efi_event) { - /* We only support one event at a time */ - return EFI_EXIT(EFI_INVALID_PARAMETER); - } + for (i = 0; i < ARRAY_SIZE(efi_events); ++i) { + if (event != &efi_events[i]) + continue; - switch (type) { - case EFI_TIMER_STOP: - efi_event.trigger_next = -1ULL; - break; - case EFI_TIMER_PERIODIC: - case EFI_TIMER_RELATIVE: - efi_event.trigger_next = timer_get_us() + (trigger32 / 10); - break; - default: - return EFI_EXIT(EFI_INVALID_PARAMETER); + switch (type) { + case EFI_TIMER_STOP: + efi_events[i].trigger_next = -1ULL; + break; + case EFI_TIMER_PERIODIC: + case EFI_TIMER_RELATIVE: + efi_events[i].trigger_next = + timer_get_us() + (trigger32 / 10); + break; + default: + return EFI_EXIT(EFI_INVALID_PARAMETER); + } + efi_events[i].trigger_type = type; + efi_events[i].trigger_time = trigger_time; + return EFI_EXIT(EFI_SUCCESS); } - efi_event.trigger_type = type; - efi_event.trigger_time = trigger_time; - - return EFI_EXIT(EFI_SUCCESS); + return EFI_EXIT(EFI_INVALID_PARAMETER); } static efi_status_t EFIAPI efi_wait_for_event(unsigned long num_events, void *event, unsigned long *index) { - u64 now; + int i; EFI_ENTRY("%ld, %p, %p", num_events, event, index); - now = timer_get_us(); - while (now < efi_event.trigger_next) { } - efi_timer_check(); - + for (i = 0; i < ARRAY_SIZE(efi_events); ++i) { + if (event != &efi_events[i]) + continue; + while (!efi_events[i].signaled) + efi_timer_check(); + efi_events[i].signaled = 0; + break; + } return EFI_EXIT(EFI_SUCCESS); } static efi_status_t EFIAPI efi_signal_event(void *event) { + int i; + EFI_ENTRY("%p", event); + for (i = 0; i < ARRAY_SIZE(efi_events); ++i) { + if (event != &efi_events[i]) + continue; + if (efi_events[i].signaled) + break; + efi_events[i].signaled = 1; + if (efi_events[i].type & EVT_NOTIFY_SIGNAL) { + EFI_EXIT(EFI_SUCCESS); + efi_events[i].notify_function(&efi_events[i], + efi_events[i].notify_context); + efi_restore_gd(); + } + break; + } return EFI_EXIT(EFI_SUCCESS); } static efi_status_t EFIAPI efi_close_event(void *event) { + int i; + EFI_ENTRY("%p", event); - efi_event.trigger_next = -1ULL; + for (i = 0; i < ARRAY_SIZE(efi_events); ++i) { + if (event != &efi_events[i]) + continue; + efi_events[i].type = 0; + efi_events[i].trigger_next = -1ULL; + efi_events[i].signaled = 0; + break; + } return EFI_EXIT(EFI_SUCCESS); } static efi_status_t EFIAPI efi_check_event(void *event) { + int i; + EFI_ENTRY("%p", event); - return EFI_EXIT(EFI_NOT_READY); + efi_timer_check(); + for (i = 0; i < ARRAY_SIZE(efi_events); ++i) { + if (event != &efi_events[i]) + continue; + if (efi_events[i].signaled) + return EFI_EXIT(EFI_SUCCESS); + return EFI_EXIT(EFI_NOT_READY); + } + return EFI_EXIT(EFI_INVALID_PARAMETER); } static efi_status_t EFIAPI efi_install_protocol_interface(void **handle,