add generic EFI timer
Subsystems (2)
cover add generic EFI timer
Hi,
On EFI you have 3 ways to get to do "timer"
1: Simply by waiting X us and calling Boot Service udelay
2: By using event
3: By use the Timestamp GUID
for barebox this would be the best but even on EDK II this is never ever compiled on any target.
So we have 2 choice, use a Hardware specific timer or implement the timer using timestamp
This pull request allow you to enable 2 timers and use the best one at runtime.
EFI x86 (HW specific)
EFI Generic (based on Event)
please pull
The following changes since commit d92ed454107b4d6f0d30fa0271da191ae5911d18:
Merge branch 'for-next/video' into next (2017-02-27 08:51:08 +0100)
are available in the git repository at:
git://git.jcrosoft.org/barebox.git delivery/efi-cs
for you to fetch changes up to f14af7444ad9d8ce674382f222119f5fcd3f2576:
efi: add veriable to report secure boot support and status (2017-02-28 23:05:31 +0800)
----------------------------------------------------------------
Jean-Christophe PLAGNIOL-VILLARD (9):
efi: add prototype and definition for creating and closing event
efi: add prototype and definition for setting timer
efi: move LoaderTimeInitUSec and LoaderDevicePartUUID to postcore initcall
efi: move x86 clocksource init at core initcall level
clocksource: allow to have multiple device from clock source
clocksource: move dummy clock source to init_clock
efi: move x86 clocksource to device/driver
efi: clocksoure: add EFI event timer
efi: add veriable to report secure boot support and status
arch/x86/Kconfig | 2 +- arch/x86/mach-efi/Makefile | 1 + arch/x86/mach-efi/clocksource.c | 11 +++++++++++ common/clock.c | 44 +++++++++++++++++++++++++++++++++++--------- common/efi/efi.c | 24 +++++++++++++++++++----- drivers/clocksource/Kconfig | 6 +++++- drivers/clocksource/Makefile | 1 + drivers/clocksource/efi.c | 110 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------------------- drivers/clocksource/efi_x86.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ drivers/efi/efi-device.c | 33 +++++++++++++++++++++++++++++++++ include/clock.h | 3 ++- include/efi.h | 25 ++++++++++++++++++++++--- include/efi/efi.h | 2 -- 13 files changed, 290 insertions(+), 51 deletions(-) create mode 100644 arch/x86/mach-efi/clocksource.c create mode 100644 drivers/clocksource/efi_x86.c
Best Regards,
J.
_______________________________________________
barebox mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/barebox
PATCH 1/9 efi: add prototype and definition for creating and closing event
--- include/efi.h | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-)
include/efi.h +15 -2
@@ -185,12 +185,25 @@ typedef struct { unsigned long *, u32 *); efi_status_t (EFIAPI *allocate_pool)(int, unsigned long, void **); efi_status_t (EFIAPI *free_pool)(void *); -void *create_event; +#define EFI_EVT_TIMER 0x80000000 +#define EFI_EVT_RUNTIME 0x40000000 +#define EFI_EVT_NOTIFY_WAIT 0x00000100 +#define EFI_EVT_NOTIFY_SIGNAL 0x00000200 +#define EFI_EVT_SIGNAL_EXIT_BOOT_SERVICES 0x00000201 +#define EFI_EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE 0x60000202 + +#define EFI_TPL_APPLICATION 4 +#define EFI_TPL_CALLBACK 8 +#define EFI_TPL_NOTIFY 16 +#define EFI_TPL_HIGH_LEVEL 31 + efi_status_t(EFIAPI *create_event)(u32 type , unsigned long tpl, +void (*fn) (void *event, void *ctx), + void *ctx, void **event);void *set_timer; efi_status_t(EFIAPI *wait_for_event)(unsigned long number_of_events, void *event, unsigned long *index);void *signal_event; -void *close_event; +efi_status_t (EFIAPI *close_event)(void *event);void *check_event;void *install_protocol_interface;void *reinstall_protocol_interface;
Signature · 7 lines
2.11.0 _______________________________________________ barebox mailing list [email protected] http://lists.infradead.org/mailman/listinfo/barebox
PATCH 2/9 efi: add prototype and definition for setting timer
--- include/efi.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)
include/efi.h +7 -1
@@ -171,6 +171,12 @@ struct efi_open_protocol_information_entry {u32 open_count; }; +typedef enum { +EFI_TIMER_CANCEL =0 , +EFI_TIMER_PERIODIC =1 , +EFI_TIMER_RELATIVE =2 +}efi_timer_delay_t ; +/* * EFI Boot Services table */
@@ -199,7 +205,7 @@ typedef struct { efi_status_t(EFIAPI *create_event)(u32 type , unsigned long tpl,void (*fn) (void *event, void *ctx), void *ctx, void **event); -void *set_timer; + efi_status_t(EFIAPI *set_timer)(void *event, efi_timer_delay_t type, uint64_t time); efi_status_t(EFIAPI *wait_for_event)(unsigned long number_of_events, void *event, unsigned long *index);void *signal_event;
Signature · 7 lines
2.11.0 _______________________________________________ barebox mailing list [email protected] http://lists.infradead.org/mailman/listinfo/barebox
PATCH 3/9 efi: move LoaderTimeInitUSec and LoaderDevicePartUUID to postcore initcall
In reply to Jean-Christophe PLAGNIOL-VILLARDso we can use device/driver for the timer
--- common/efi/efi.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-)
common/efi/efi.c +11 -4
@@ -314,7 +314,6 @@ efi_status_t efi_main(efi_handle_t image, efi_system_table_t *sys_table)efi_physical_addr_t mem;size_t memsize;efi_status_t efiret; -char *uuid;#ifdef DEBUG sys_table->con_out->output_string (sys_table->con_out,L"barebox\n" );
@@ -350,6 +349,15 @@ efi_status_t efi_main(efi_handle_t image, efi_system_table_t *sys_table)mem_malloc_init ((void *)mem, (void *)mem + memsize);efi_clocksource_init (); +start_barebox (); + +return EFI_SUCCESS ; +} + +static int efi_postcore_init (void ) +{ +char *uuid; +efi_set_variable_usec ("LoaderTimeInitUSec" , &efi_systemd_vendor_guid,get_time_ns ()/1000 );
@@ -366,10 +374,9 @@ efi_status_t efi_main(efi_handle_t image, efi_system_table_t *sys_table)free (uuid16); } -start_barebox (); - -return EFI_SUCCESS ; +return 0 ; } +postcore_initcall (efi_postcore_init);static int do_efiexit (int argc,char *argv[]) {
Signature · 7 lines
2.11.0 _______________________________________________ barebox mailing list [email protected] http://lists.infradead.org/mailman/listinfo/barebox
PATCH 4/9 efi: move x86 clocksource init at core initcall level
In reply to Jean-Christophe PLAGNIOL-VILLARDso we can use device/driver model
--- common/efi/efi.c | 1 - drivers/clocksource/efi.c | 5 ++++- include/efi/efi.h | 2 -- 3 files changed, 4 insertions(+), 4 deletions(-)
common/efi/efi.c +0 -1
@@ -348,7 +348,6 @@ efi_status_t efi_main(efi_handle_t image, efi_system_table_t *sys_table) efi_strerror(efiret));mem_malloc_init ((void *)mem, (void *)mem + memsize); -efi_clocksource_init ();start_barebox ();return EFI_SUCCESS ;
drivers/clocksource/efi.c +4 -1
@@ -1,4 +1,5 @@#include <common.h> +#include <init.h> #include <efi.h> #include <efi/efi.h> #include <clock.h>
@@ -48,7 +49,7 @@ static struct clocksource cs = { .shift = 0, }; -int efi_clocksource_init (void ) +static int efi_clocksource_init (void ) { cs.mult =clocksource_hz2mult (1000 *1000 , cs.shift);
@@ -56,3 +57,5 @@ int efi_clocksource_init(void)return init_clock (&cs); } +/* for efi the time must be init at core initcall level */ +core_initcall (efi_clocksource_init);
include/efi/efi.h +0 -2
@@ -12,8 +12,6 @@ extern efi_loaded_image_t *efi_loaded_image;int efi_errno (efi_status_t err); -int efi_clocksource_init (void ); -void *efi_get_variable (char *name,efi_guid_t *vendor,int *var_size);static inline void *efi_get_global_var (char *name,int *var_size)
Signature · 7 lines
2.11.0 _______________________________________________ barebox mailing list [email protected] http://lists.infradead.org/mailman/listinfo/barebox
PATCH 5/9 clocksource: allow to have multiple device from clock source
In reply to Jean-Christophe PLAGNIOL-VILLARDuse the one with the most priority.
We can not select the clocksource at user level.
--- common/clock.c | 11 +++++++++++ include/clock.h | 3 ++- 2 files changed, 13 insertions(+), 1 deletion(-)
common/clock.c +11 -0
@@ -213,6 +213,17 @@ EXPORT_SYMBOL(mdelay_non_interruptible);int init_clock (struct clocksource *cs) { +if (current_clock && cs->priority <= current_clock->priority) +return 0 ; + +if (cs->init) { +int ret; + + ret = cs->init (cs); +if (ret) +return ret; + } + current_clock = cs; time_beginning =get_time_ns ();
include/clock.h +2 -1
@@ -12,7 +12,8 @@ struct clocksource {uint64_t (*read)(void );uint64_t cycle_last;uint64_t mask; - +int priority; +int (*init)(struct clocksource *); };static inline uint32_t cyc2ns (struct clocksource *cs,uint64_t cycles)
Signature · 7 lines
2.11.0 _______________________________________________ barebox mailing list [email protected] http://lists.infradead.org/mailman/listinfo/barebox
PATCH 6/9 clocksource: move dummy clock source to init_clock
In reply to Jean-Christophe PLAGNIOL-VILLARDAnd registered it as soon as possible (at pure initcall).
So we not need to check the cs all the time.
As get_time_ns() is one of the most called function of barebox at runtime.
--- common/clock.c | 33 ++++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-)
common/clock.c +24 -9
@@ -36,9 +36,32 @@ static uint64_t time_ns;*/ uint64_t time_beginning; +static uint64_t dummy_read (void ) +{ +static uint64_t dummy_counter; + + dummy_counter +=CONFIG_CLOCKSOURCE_DUMMY_RATE ; + +return dummy_counter; +} + +static struct clocksource dummy_cs = { + .shift =0 , + .mult =1 , + .read = dummy_read, + .mask =CLOCKSOURCE_MASK (64 ), + .priority =-1 , +}; + +static int dummy_csrc_init (void ) +{ +return init_clock (&dummy_cs); +} +pure_initcall (dummy_csrc_init); +static int dummy_csrc_warn (void ) { -if (!current_clock) { +if (current_clock == &dummy_cs) {pr_warn ("Warning: Using dummy clocksource\n" ); }
@@ -55,14 +78,6 @@ uint64_t get_time_ns(void)uint64_t cycle_now, cycle_delta;uint64_t ns_offset; -if (!cs) { -static uint64_t dummy_counter; - - dummy_counter +=CONFIG_CLOCKSOURCE_DUMMY_RATE ; - -return dummy_counter; - } -/* read clocksource: */ cycle_now = cs->read () & cs->mask;
Signature · 7 lines
2.11.0 _______________________________________________ barebox mailing list [email protected] http://lists.infradead.org/mailman/listinfo/barebox
PATCH 7/9 efi: move x86 clocksource to device/driver
In reply to Jean-Christophe PLAGNIOL-VILLARDso we can dynamicly register the device
As we may need to use HW IP for clocksource.
As on EFI we could use Timestamp GUID if present (Not often the case as it's not even enabled by default on any Target on EDK II not even OVMF)
Or if we choose we could use a Simulated Timestamp driver that work on Event (Add Later)
---
arch/x86/Kconfig | 2 +-
arch/x86/mach-efi/Makefile | 1 +
arch/x86/mach-efi/clocksource.c | 11 +++++++++++
drivers/clocksource/Kconfig | 6 +++---
drivers/clocksource/Makefile | 2 +-
drivers/clocksource/{efi.c => efi_x86.c} | 34 ++++++++++++++++++++++++--------
6 files changed, 43 insertions(+), 13 deletions(-)
create mode 100644 arch/x86/mach-efi/clocksource.c
rename drivers/clocksource/{efi.c => efi_x86.c} (56%)arch/x86/Kconfig +1 -1
@@ -77,7 +77,7 @@ choice select EFI_GUID select EFI_DEVICEPATH select PRINTF_UUID - select CLOCKSOURCE_EFI + select CLOCKSOURCE_EFI_X86 config X86_BIOS_BRINGUP bool "16 bit BIOS"
arch/x86/mach-efi/Makefile +1 -0
@@ -1,4 +1,5 @@ obj-$(CONFIG_X86_64) += reloc_x86_64.o crt0-efi-x86_64.o obj-$(CONFIG_X86_32) += reloc_ia32.o crt0-efi-ia32.o +obj-y += clocksource.o extra-$(CONFIG_X86_32) += elf_ia32_efi.lds extra-$(CONFIG_X86_64) += elf_x86_64_efi.lds
arch/x86/mach-efi/clocksource.c new file +11 -0
@@ -0,0 +1,11 @@ +#include <common.h> +#include <init.h> +#include <driver.h> + +static int efi_x86_pure_init (void ) +{ +struct device_d *dev =device_alloc ("efi-cs-x86" ,DEVICE_ID_SINGLE ); + +return platform_device_register (dev); +} +core_initcall (efi_x86_pure_init);
drivers/clocksource/Kconfig +3 -3
@@ -34,9 +34,9 @@ config CLOCKSOURCE_DUMMY_RATE The option CONFIG_CLOCKSOURCE_DUMMY_RATE is used to adjust this clocksource. The bigger rate valuest makes clocksource "faster". -config CLOCKSOURCE_EFI - bool - depends on EFI_BOOTUP +config CLOCKSOURCE_EFI_X86 + bool "EFI X86 HW driver" + depends on EFI_BOOTUP && X86 config CLOCKSOURCE_MVEBU bool
drivers/clocksource/Makefile +1 -1
@@ -3,7 +3,7 @@ obj-$(CONFIG_ARM_SMP_TWD) += arm_smp_twd.o obj-$(CONFIG_CLOCKSOURCE_BCM283X) += bcm2835.o obj-$(CONFIG_CLOCKSOURCE_CLPS711X) += clps711x.o obj-$(CONFIG_CLOCKSOURCE_DIGIC) += digic.o -obj-$(CONFIG_CLOCKSOURCE_EFI) += efi.o +obj-$(CONFIG_CLOCKSOURCE_EFI_X86) += efi_x86.o obj-$(CONFIG_CLOCKSOURCE_MVEBU) += mvebu.o obj-$(CONFIG_CLOCKSOURCE_NOMADIK) += nomadik.o obj-$(CONFIG_CLOCKSOURCE_ORION) += orion.o
drivers/clocksource/efi_x86.c renamed from drivers/clocksource/efi.c +26 -8
@@ -1,5 +1,6 @@#include <common.h> #include <init.h> +#include <driver.h> #include <efi.h> #include <efi/efi.h> #include <clock.h>
@@ -38,24 +39,41 @@ static uint64_t ticks_freq(void)return (ticks_end - ticks_start) *1000 ; } -static uint64_t efi_clocksource_read (void ) +static uint64_t efi_x86_cs_read (void ) {return 1000 *1000 *ticks_read () / freq; } -static struct clocksource cs = { - .read = efi_clocksource_read, +static int efi_x86_cs_init (struct clocksource *cs) +{ + cs->mult =clocksource_hz2mult (1000 *1000 , cs->shift); + + freq =ticks_freq (); + +return 0 ; +} + +static struct clocksource efi_x86_cs = { + .read = efi_x86_cs_read, .mask =CLOCKSOURCE_MASK (64 ), .shift =0 , + .priority =100 , + .init = efi_x86_cs_init, }; -static int efi_clocksource_init (void ) +static int efi_x86_cs_probe (struct device_d *dev) { - cs.mult =clocksource_hz2mult (1000 *1000 , cs.shift); +return init_clock (&efi_x86_cs); +} - freq =ticks_freq (); +static struct driver_d efi_x86_cs_driver = { + .name ="efi-cs-x86" , + .probe = efi_x86_cs_probe, +}; -return init_clock (&cs); +static int efi_x86_cs_initcall (void ) +{ +return platform_driver_register (&efi_x86_cs_driver); }/* for efi the time must be init at core initcall level */ -core_initcall (efi_clocksource_init); +core_initcall (efi_x86_cs_initcall);
Signature · 7 lines
2.11.0 _______________________________________________ barebox mailing list [email protected] http://lists.infradead.org/mailman/listinfo/barebox
PATCH 8/9 efi: clocksoure: add EFI event timer
In reply to Jean-Christophe PLAGNIOL-VILLARDwith this we can be hw generic
If the EFI implement timestamp protocol we could use instead of event but even EDK2 Never Ever compile it for any target.
--- common/efi/efi.c | 8 ++++ drivers/clocksource/Kconfig | 4 ++ drivers/clocksource/Makefile | 1 + drivers/clocksource/efi.c | 110 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 123 insertions(+) create mode 100644 drivers/clocksource/efi.c
common/efi/efi.c +8 -0
@@ -353,6 +353,14 @@ efi_status_t efi_main(efi_handle_t image, efi_system_table_t *sys_table)return EFI_SUCCESS ; } +static int efi_core_init (void ) +{ +struct device_d *dev =device_alloc ("efi-cs" ,DEVICE_ID_SINGLE ); + +return platform_device_register (dev); +} +core_initcall (efi_core_init); +static int efi_postcore_init (void ) {char *uuid;
drivers/clocksource/Kconfig +4 -0
@@ -34,6 +34,10 @@ config CLOCKSOURCE_DUMMY_RATE The option CONFIG_CLOCKSOURCE_DUMMY_RATE is used to adjust this clocksource. The bigger rate valuest makes clocksource "faster". +config CLOCKSOURCE_EFI + bool "Generic EFI Driver" + depends on EFI_BOOTUP + config CLOCKSOURCE_EFI_X86 bool "EFI X86 HW driver" depends on EFI_BOOTUP && X86
drivers/clocksource/Makefile +1 -0
@@ -3,6 +3,7 @@ obj-$(CONFIG_ARM_SMP_TWD) += arm_smp_twd.o obj-$(CONFIG_CLOCKSOURCE_BCM283X) += bcm2835.o obj-$(CONFIG_CLOCKSOURCE_CLPS711X) += clps711x.o obj-$(CONFIG_CLOCKSOURCE_DIGIC) += digic.o +obj-$(CONFIG_CLOCKSOURCE_EFI) += efi.o obj-$(CONFIG_CLOCKSOURCE_EFI_X86) += efi_x86.o obj-$(CONFIG_CLOCKSOURCE_MVEBU) += mvebu.o obj-$(CONFIG_CLOCKSOURCE_NOMADIK) += nomadik.o
drivers/clocksource/efi.c new file +110 -0
110 lines not on this page · raw message
Signature · 7 lines
2.11.0 _______________________________________________ barebox mailing list [email protected] http://lists.infradead.org/mailman/listinfo/barebox
Re: [PATCH 8/9] efi: clocksoure: add EFI event timer
Quoted 7 lines · Jean-Christophe PLAGNIOL-VILLARD
with this we can be hw generic
If the EFI implement timestamp protocol we could use instead of event but even EDK2 Never Ever compile it for any target.
Signed-off-by Jean-Christophe PLAGNIOL-VILLARD <[email protected]>---
drivers/clocksource/efi.c line 75
Quoted 7 lines
drivers/clocksource/efi.c new file +7
-0+ freq =1000 *1000 ; +if (ticks_freq () <800 *1000 ) { +uint64_t nb_100ns; + + freq =ticks_freq_x86 (); + nb_100ns =10 *1000 *1000 / freq; +pr_warn ("EFI Event timer too slow freq = %llu Hz\n" , freq);
Applied this series for now. I weakened this message somewhat:
pr_warn("EFI Event timer slow, freq = %lluHz\n", freq);As this is not really an error, only an information one might want to know.
Sascha
Signature · 9 lines
Pengutronix e.K. | | Industrial Linux Solutions | http://www.pengutronix.de/ | Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 | _______________________________________________ barebox mailing list [email protected] http://lists.infradead.org/mailman/listinfo/barebox
PATCH 9/9 efi: add veriable to report secure boot support and status
In reply to Jean-Christophe PLAGNIOL-VILLARD--- drivers/efi/efi-device.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+)
drivers/efi/efi-device.c +33 -0
@@ -354,11 +354,41 @@ static void efi_businfo(struct device_d *dev) } } +static int efi_is_secure_boot (void ) +{ +uint8_t *val; +int ret =0 ; + + val =efi_get_variable ("SecureBoot" , &efi_global_variable_guid,NULL ); +if (!IS_ERR (val)) { + ret = *val; +free (val); + } + +return ret !=1 ; +} + +static int efi_is_setup_mode (void ) +{ +uint8_t *val; +int ret =0 ; + + val =efi_get_variable ("SetupMode" , &efi_global_variable_guid,NULL ); +if (!IS_ERR (val)) { + ret = *val; +free (val); + } + +return ret !=1 ; +} +static int efi_init_devices (void ) {char *fw_vendor =NULL ;u16 sys_major = efi_sys_table->hdr.revision >>16 ;u16 sys_minor = efi_sys_table->hdr.revision &0xffff ; +int secure_boot =efi_is_secure_boot (); +int setup_mode =efi_is_setup_mode (); fw_vendor =strdup_wchar_to_char ((const wchar_t *)efi_sys_table->fw_vendor);
@@ -374,6 +404,9 @@ static int efi_init_devices(void)dev_add_param_int_ro (efi_bus.dev,"major" , sys_major,"%u" );dev_add_param_int_ro (efi_bus.dev,"minor" , sys_minor,"%u" );dev_add_param_int_ro (efi_bus.dev,"fw_revision" , efi_sys_table->fw_revision,"%u" ); +dev_add_param_int_ro (efi_bus.dev,"secure_boot" , secure_boot,"%d" ); +dev_add_param_int_ro (efi_bus.dev,"secure_mode" , + secure_boot & setup_mode,"%u" ); efi_bus.dev->info = efi_businfo;
Signature · 7 lines
2.11.0 _______________________________________________ barebox mailing list [email protected] http://lists.infradead.org/mailman/listinfo/barebox