efi_loader: allow efi_loader code to call EFI interfaces
PATCH 1/1 efi_loader: allow efi_loader code to call EFI interfaces
To implement efi_load_image() for the case of loading an image from a device path rather than image already loaded into source_buffer, it is convenient to be able to re-use simple-file-system and efi-file interfaces. But these are already using EFI_ENTER()/EFI_EXIT(). Allow entry into EFI interfaces to be recursive, since this greatly simplifies things.
(And hypothetically this would be needed anyways to allow grub to call into interfaces installed by something outside of grub.)
--- lib/efi_loader/efi_boottime.c | 5 +++++ 1 file changed, 5 insertions(+)
lib/efi_loader/efi_boottime.c +5 -0
@@ -47,6 +47,7 @@ static struct efi_configuration_table __efi_runtime_data efi_conf_table[2];* EFI callback entry/exit. */ static volatile void *efi_gd, *app_gd; +static int entry_level =0 ;#endif /* Called from do_bootefi_exec() */
@@ -61,6 +62,8 @@ void efi_save_gd(void)void efi_restore_gd (void ) {#ifdef CONFIG_ARM +if (entry_level++) +return ;/* Only restore if we're already in EFI context */ if (!efi_gd)return ;
@@ -75,6 +78,8 @@ void efi_restore_gd(void)efi_status_t efi_exit_func (efi_status_t ret) {#ifdef CONFIG_ARM +if (--entry_level) +return ret; gd = app_gd;#endif
Signature · 1 line
2.13.0
PATCH 1/1 efi_loader: allow efi_loader code to call EFI interfaces
Quoted 11 lines · Rob Clark
To implement
efi_load_image()for the case of loading an image from a device path rather than image already loaded intosource_buffer, it is convenient to be able to re-use simple-file-system and efi-file interfaces. But these are already using EFI_ENTER()/EFI_EXIT(). Allow entry into EFI interfaces to be recursive, since this greatly simplifies things.(And hypothetically this would be needed anyways to allow grub to call into interfaces installed by something outside of grub.)
Signed-off-by Rob Clark <[email protected]>
So there are 2 ways to do this:
1) Keep a refcount, only transition when passing the 0 level
2) Explicitly split functions with ENTRY/EXIT from their core functions
So far we used approach 2, splitting functions that are used by both internal and external code into _ext (for externally called) and normal functions. You can see this pattern quite a few times throughout efi_loader.
I definitely did try the refcount approach back when I decided for approach 2 and it failed on me in some case, but I can't remember where.
Either way, we should definitely be consistent. Either we always use refcounting or we shouldn't bother with it. So if you can make a version work where all _ext variants disappear and we're magically reentrant, I'll be happy to take that. I'm fairly sure it'll break somewhere though :).
Alex
Quoted 35 lines
--- lib/efi_loader/efi_boottime.c | 5 +++++ 1 file changed, 5 insertions(+)lib/efi_loader/efi_boottime.c +5
-0@@ -47,6 +47,7 @@ static struct efi_configuration_table __efi_runtime_data efi_conf_table[2];* EFI callback entry/exit. */ static volatile void *efi_gd, *app_gd; +static int entry_level =0 ;#endif /* Called from do_bootefi_exec() */ @@ -61,6 +62,8 @@ void efi_save_gd(void)void efi_restore_gd (void ) {#ifdef CONFIG_ARM +if (entry_level++) +return ;/* Only restore if we're already in EFI context */ if (!efi_gd)return ;@@ -75,6 +78,8 @@ void efi_restore_gd(void)efi_status_t efi_exit_func (efi_status_t ret) {#ifdef CONFIG_ARM +if (--entry_level) +return ret; gd = app_gd;#endif
PATCH 1/1 efi_loader: allow efi_loader code to call EFI interfaces
Quoted 26 lines · Alexander Graf
Quoted 8 lines · Rob Clark
To implement
efi_load_image()for the case of loading an image from a device path rather than image already loaded intosource_buffer, it is convenient to be able to re-use simple-file-system and efi-file interfaces. But these are already using EFI_ENTER()/EFI_EXIT(). Allow entry into EFI interfaces to be recursive, since this greatly simplifies things.Quoted 4 lines
(And hypothetically this would be needed anyways to allow grub to call into interfaces installed by something outside of grub.)
Signed-off-by Rob Clark <[email protected]>So there are 2 ways to do this:
1) Keep a refcount, only transition when passing the 0 level
2) Explicitly split functions with ENTRY/EXIT from their core functionsSo far we used approach 2, splitting functions that are used by both internal and external code into
_ext(for externally called) and normal functions. You can see this pattern quite a few times throughoutefi_loader.
Quoted 8 lines
I definitely did try the refcount approach back when I decided for approach 2 and it failed on me in some case, but I can't remember where.
Either way, we should definitely be consistent. Either we always use refcounting or we shouldn't bother with it. So if you can make a version work where all
_extvariants disappear and we're magically reentrant, I'll be happy to take that. I'm fairly sure it'll break somewhere though :).
for load_image via file-path, we end up needing a *bunch* of functions normally called via EFI.. so it is going to be a lot more _ext variants.
BR,
-R
Quoted 38 lines
Alex
Quoted 34 lines
--- lib/efi_loader/efi_boottime.c | 5 +++++ 1 file changed, 5 insertions(+)lib/efi_loader/efi_boottime.c +5
-0@@ -47,6 +47,7 @@ static struct efi_configuration_table __efi_runtime_dataefi_conf_table[2]; * EFI callback entry/exit. */ static volatile void *efi_gd, *app_gd; +static int entry_level =0 ;#endif /* Called from do_bootefi_exec() */ @@ -61,6 +62,8 @@ void efi_save_gd(void)void efi_restore_gd (void ) {#ifdef CONFIG_ARM +if (entry_level++) +return ;/* Only restore if we're already in EFI context */ if (!efi_gd)return ;@@ -75,6 +78,8 @@ void efi_restore_gd(void)efi_status_t efi_exit_func (efi_status_t ret) {#ifdef CONFIG_ARM +if (--entry_level) +return ret; gd = app_gd;#endif
PATCH 1/1 efi_loader: allow efi_loader code to call EFI interfaces
Quoted 36 lines · Rob Clark
Quoted 26 lines · Alexander Graf
Quoted 8 lines · Rob Clark
To implement
efi_load_image()for the case of loading an image from a device path rather than image already loaded intosource_buffer, it is convenient to be able to re-use simple-file-system and efi-file interfaces. But these are already using EFI_ENTER()/EFI_EXIT(). Allow entry into EFI interfaces to be recursive, since this greatly simplifies things.Quoted 4 lines
(And hypothetically this would be needed anyways to allow grub to call into interfaces installed by something outside of grub.)
Signed-off-by Rob Clark <[email protected]>So there are 2 ways to do this:
1) Keep a refcount, only transition when passing the 0 level
2) Explicitly split functions with ENTRY/EXIT from their core functionsSo far we used approach 2, splitting functions that are used by both internal and external code into
_ext(for externally called) and normal functions. You can see this pattern quite a few times throughoutefi_loader.Quoted 8 lines
I definitely did try the refcount approach back when I decided for approach 2 and it failed on me in some case, but I can't remember where.
Either way, we should definitely be consistent. Either we always use refcounting or we shouldn't bother with it. So if you can make a version work where all
_extvariants disappear and we're magically reentrant, I'll be happy to take that. I'm fairly sure it'll break somewhere though :).
Quoted 3 lines
for
load_imagevia file-path, we end up needing a *bunch* of functions normally called via EFI.. so it is going to be a lot more_extvariants.
Yes, but imagine a case like this:
open_protocol
-> open()
-> random_junk()
-> efi_timer_check()
-> timer notifier
-> console print()Here the refcounting will simply fail on us, as the timer notifier needs to be run in UEFI context while efi_timer_check() as well as console print() need to be run in U-Boot context.
And if we start to mix and mesh the 2 approaches, I can promise you that 2 weeks down some corner case nobody thought of falls apart because people don't manage to fully grasp the code flow anymore.
Alex
PATCH 1/1 efi_loader: allow efi_loader code to call EFI interfaces
Quoted 61 lines · Alexander Graf
Quoted 44 lines · Rob Clark
Quoted 35 lines · Alexander Graf
Quoted 9 lines · Rob Clark
To implement
efi_load_image()for the case of loading an image from a device path rather than image already loaded intosource_buffer, it is convenient to be able to re-use simple-file-system and efi-file interfaces. But these are already using EFI_ENTER()/EFI_EXIT(). Allow entry into EFI interfaces to be recursive, since this greatly simplifies things.Quoted 4 lines
(And hypothetically this would be needed anyways to allow grub to call into interfaces installed by something outside of grub.)
Signed-off-by Rob Clark <[email protected]>So there are 2 ways to do this:
1) Keep a refcount, only transition when passing the 0 level
2) Explicitly split functions with ENTRY/EXIT from their core
functionsSo far we used approach 2, splitting functions that are used by both internal and external code into
_ext(for externally called) and normal functions. You can see this pattern quite a few times throughoutefi_loader.I definitely did try the refcount approach back when I decided for approach
2 and it failed on me in some case, but I can't remember where.Quoted 6 lines
Either way, we should definitely be consistent. Either we always use refcounting or we shouldn't bother with it. So if you can make a version work where all
_extvariants disappear and we're magically reentrant, I'll
be happy to take that. I'm fairly sure it'll break somewhere though :).Quoted 3 lines
for
load_imagevia file-path, we end up needing a *bunch* of functions normally called via EFI.. so it is going to be a lot more_extvariants.Yes, but imagine a case like this:
open_protocol
->open()-> random_junk() -> efi_timer_check() -> timer notifier -> console print()
Quoted 8 lines
Here the refcounting will simply fail on us, as the timer notifier needs to be run in UEFI context while
efi_timer_check()as well as consoleprint()need to be run in U-Boot context.And if we start to mix and mesh the 2 approaches, I can promise you that 2 weeks down some corner case nobody thought of falls apart because people don't manage to fully grasp the code flow anymore.
ugg.. gd is a gd pita ;-)
how many places do we have callbacks into UEFI context like this? If just one or two maybe we can suppress them while in u-boot context and handle in efi_exit_func() when entry_count drops to zero?
BR,
-R
PATCH 1/1 efi_loader: allow efi_loader code to call EFI interfaces
Quoted 71 lines · Rob Clark
Quoted 61 lines · Alexander Graf
Quoted 44 lines · Rob Clark
Quoted 35 lines · Alexander Graf
Quoted 9 lines · Rob Clark
To implement
efi_load_image()for the case of loading an image from a device path rather than image already loaded intosource_buffer, it is convenient to be able to re-use simple-file-system and efi-file interfaces. But these are already using EFI_ENTER()/EFI_EXIT(). Allow entry into EFI interfaces to be recursive, since this greatly simplifies things.Quoted 4 lines
(And hypothetically this would be needed anyways to allow grub to call into interfaces installed by something outside of grub.)
Signed-off-by Rob Clark <[email protected]>So there are 2 ways to do this:
1) Keep a refcount, only transition when passing the 0 level
2) Explicitly split functions with ENTRY/EXIT from their core
functionsSo far we used approach 2, splitting functions that are used by both internal and external code into
_ext(for externally called) and normal functions. You can see this pattern quite a few times throughoutefi_loader.I definitely did try the refcount approach back when I decided for approach
2 and it failed on me in some case, but I can't remember where.Quoted 6 lines
Either way, we should definitely be consistent. Either we always use refcounting or we shouldn't bother with it. So if you can make a version work where all
_extvariants disappear and we're magically reentrant, I'll
be happy to take that. I'm fairly sure it'll break somewhere though :).Quoted 3 lines
for
load_imagevia file-path, we end up needing a *bunch* of functions normally called via EFI.. so it is going to be a lot more_extvariants.Yes, but imagine a case like this:
open_protocol
->open()-> random_junk() -> efi_timer_check() -> timer notifier -> console print()Quoted 8 lines
Here the refcounting will simply fail on us, as the timer notifier needs to be run in UEFI context while
efi_timer_check()as well as consoleprint()need to be run in U-Boot context.And if we start to mix and mesh the 2 approaches, I can promise you that 2 weeks down some corner case nobody thought of falls apart because people don't manage to fully grasp the code flow anymore.
Quoted 5 lines
ugg.. gd is a gd pita ;-)
how many places do we have callbacks into UEFI context like this? If just one or two maybe we can suppress them while in u-boot context and handle in
efi_exit_func()whenentry_countdrops to zero?
What do you mean by suppressing? We need to call those helpers synchronously. And yes, we can probably hand massage the refcount on the ones that we remember, but I'm just afraid that the whole thing will be so complicated eventually that nobody understands what's going on.
I personally think having _ext functions in anything exposed to UEFI payloads makes more sense.
Alex
PATCH 1/1 efi_loader: allow efi_loader code to call EFI interfaces
Quoted 93 lines · Alexander Graf
Quoted 83 lines · Rob Clark
Quoted 75 lines · Alexander Graf
Quoted 51 lines · Rob Clark
Quoted 40 lines · Alexander Graf
Quoted 12 lines · Rob Clark
To implement
efi_load_image()for the case of loading an image from a device path rather than image already loaded intosource_buffer, it is convenient to be able to re-use simple-file-system and efi-file interfaces. But these are already using EFI_ENTER()/EFI_EXIT(). Allow
entry into EFI interfaces to be recursive, since this greatly simplifies
things.Quoted 4 lines
(And hypothetically this would be needed anyways to allow grub to call into interfaces installed by something outside of grub.)
Signed-off-by Rob Clark <[email protected]>So there are 2 ways to do this:
1) Keep a refcount, only transition when passing the 0 level
2) Explicitly split functions with ENTRY/EXIT from their core
functionsSo far we used approach 2, splitting functions that are used by both internal and external code into
_ext(for externally called) and normal functions. You can see this pattern quite a few times throughoutefi_loader.I definitely did try the refcount approach back when I decided for approach
2 and it failed on me in some case, but I can't remember where.Quoted 7 lines
Either way, we should definitely be consistent. Either we always use refcounting or we shouldn't bother with it. So if you can make a version
work where all_extvariants disappear and we're magically reentrant, I'll
be happy to take that. I'm fairly sure it'll break somewhere though :).Quoted 3 lines
for
load_imagevia file-path, we end up needing a *bunch* of functions normally called via EFI.. so it is going to be a lot more_extvariants.Yes, but imagine a case like this:
open_protocol
->open()-> random_junk() -> efi_timer_check() -> timer notifier -> console print()Here the refcounting will simply fail on us, as the timer notifier needs to
be run in UEFI context whileefi_timer_check()as well as consoleprint()need to be run in U-Boot context.Quoted 5 lines
And if we start to mix and mesh the 2 approaches, I can promise you that 2
weeks down some corner case nobody thought of falls apart because people don't manage to fully grasp the code flow anymore.Quoted 5 lines
ugg.. gd is a gd pita ;-)
how many places do we have callbacks into UEFI context like this? If just one or two maybe we can suppress them while in u-boot context and handle in
efi_exit_func()whenentry_countdrops to zero?
Quoted 4 lines
What do you mean by suppressing? We need to call those helpers synchronously. And yes, we can probably hand massage the refcount on the ones that we remember, but I'm just afraid that the whole thing will be so complicated eventually that nobody understands what's going on.
Maybe suppress isn't the right word.. I was thinking of delaying the callback until EFI_EXIT() that transitions back to the UEFI world. So from the PoV of the UEFI world, it is still synchronous.
I haven't looked at the efi_event stuff until just now, but from a 30sec look, maybe efi_signal_event() could just put the event on a list of signalled events and not immediately call event->notify_function(), and handle the calling of notify_function() in the last EFI_EXIT()??
Quoted 3 lines
I personally think having
_extfunctions in anything exposed to UEFI payloads makes more sense.
having 2x all the interfaces for file related protocols would be unfortunate. (Also currently they can stay static in efi_file.c and just be called via same efi_file_handle fxn ptrs that the UEFI world would be using, which is kinda nice.)
PATCH 1/1 efi_loader: allow efi_loader code to call EFI interfaces
Quoted 103 lines · Rob Clark
Quoted 93 lines · Alexander Graf
Quoted 83 lines · Rob Clark
Quoted 75 lines · Alexander Graf
Quoted 51 lines · Rob Clark
Quoted 40 lines · Alexander Graf
Quoted 12 lines · Rob Clark
To implement
efi_load_image()for the case of loading an image from a device path rather than image already loaded intosource_buffer, it is convenient to be able to re-use simple-file-system and efi-file interfaces. But these are already using EFI_ENTER()/EFI_EXIT(). Allow
entry into EFI interfaces to be recursive, since this greatly simplifies
things.Quoted 4 lines
(And hypothetically this would be needed anyways to allow grub to call into interfaces installed by something outside of grub.)
Signed-off-by Rob Clark <[email protected]>So there are 2 ways to do this:
1) Keep a refcount, only transition when passing the 0 level
2) Explicitly split functions with ENTRY/EXIT from their core
functionsSo far we used approach 2, splitting functions that are used by both internal and external code into
_ext(for externally called) and normal functions. You can see this pattern quite a few times throughoutefi_loader.I definitely did try the refcount approach back when I decided for approach
2 and it failed on me in some case, but I can't remember where.Quoted 7 lines
Either way, we should definitely be consistent. Either we always use refcounting or we shouldn't bother with it. So if you can make a version
work where all_extvariants disappear and we're magically reentrant, I'll
be happy to take that. I'm fairly sure it'll break somewhere though :).Quoted 3 lines
for
load_imagevia file-path, we end up needing a *bunch* of functions normally called via EFI.. so it is going to be a lot more_extvariants.Yes, but imagine a case like this:
open_protocol-> open() -> random_junk() -> efi_timer_check() -> timer notifier -> console print()Here the refcounting will simply fail on us, as the timer notifier needs to
be run in UEFI context whileefi_timer_check()as well as consoleprint()need to be run in U-Boot context.Quoted 5 lines
And if we start to mix and mesh the 2 approaches, I can promise you that 2
weeks down some corner case nobody thought of falls apart because people don't manage to fully grasp the code flow anymore.Quoted 5 lines
ugg.. gd is a gd pita ;-)
how many places do we have callbacks into UEFI context like this? If just one or two maybe we can suppress them while in u-boot context and handle in
efi_exit_func()whenentry_countdrops to zero?Quoted 4 lines
What do you mean by suppressing? We need to call those helpers synchronously. And yes, we can probably hand massage the refcount on the ones that we remember, but I'm just afraid that the whole thing will be so complicated eventually that nobody understands what's going on.
Maybe suppress isn't the right word.. I was thinking of delaying the callback until
EFI_EXIT()that transitions back to the UEFI world. So from the PoV of the UEFI world, it is still synchronous.
Quoted 5 lines
I haven't looked at the
efi_eventstuff until just now, but from a 30sec look, maybeefi_signal_event()could just put the event on a list of signalled events and not immediately callevent->notify_function(), and handle the calling ofnotify_function()in the lastEFI_EXIT()??
Maybe, I'll leave Heinrich to comment on that.
Quoted 6 lines
Quoted 4 lines
I personally think having
_extfunctions in anything exposed to UEFI payloads makes more sense.having 2x all the interfaces for file related protocols would be
Why 2x the interfaces?
Quoted 3 lines
unfortunate. (Also currently they can stay static in
efi_file.cand just be called via sameefi_file_handlefxn ptrs that the UEFI world would be using, which is kinda nice.)
Ah, that indeed is nice.
So, there is a third option if you want to tackle it:
3) Remove register variable need for gd
If gd is a simple global variable rather than a register variable, we wouldn't have that problem. On x86 it's just a variable for example. I don't know why arm and aarch64 have it as register variable, but I can't see an immediate need for it.
If you manage to solve that, we don't need any ext functions or reference counters ;).
Alex
PATCH 1/1 efi_loader: allow efi_loader code to call EFI interfaces
Quoted 6 lines · Alexander Graf
Quoted 3 lines · Rob Clark
On Tue, Jul 25, 2017 at 8:16 AM, Alexander Graf <[email protected]> wrote:
Quoted 8 lines
Quoted 5 lines
Quoted 3 lines
I personally think having
_extfunctions in anything exposed to UEFI payloads makes more sense.having 2x all the interfaces for file related protocols would be
Why 2x the interfaces?
well, maybe not all, but for efi_load_image() from a device-path to work, we need to be able to use simple-filesystem-protocol and a bunch of the file-protocol interfaces.. so it is definitely more messy.
Quoted 11 lines
Quoted 3 lines
unfortunate. (Also currently they can stay static in
efi_file.cand just be called via sameefi_file_handlefxn ptrs that the UEFI world would be using, which is kinda nice.)Ah, that indeed is nice.
So, there is a third option if you want to tackle it:
3) Remove register variable need for gd
Quoted 7 lines
If gd is a simple global variable rather than a register variable, we wouldn't have that problem. On x86 it's just a variable for example. I don't know why arm and aarch64 have it as register variable, but I can't see an immediate need for it.
If you manage to solve that, we don't need any ext functions or reference counters ;).
It would be nice to not have this gd mess.. although I'm going to leave it to someone else who understands better why we do that in the first place to solve. I have a big pile of display-handover (clk/powerdomain/display-controller-state) issues on my TODO list, and I'm just trying to get the bootloader sorted to the point where I can tackle that. Not to mention a big pile of things todo in mesa, and my actual $day_job.
I think with the EFI interfaces I need to use for efi_load_image, it should be easy enough to keep any of those from calling back into the UEFI world, and we could do some sort of EFI_CALLBACK() macro with some extra error checking to safeguard instead of the EFI_EXIT()+callback+EFI_ENTER() pattern.. and while it is a bit annoying to have to be careful about that, I think it would work ok if no one has a solution for the gd mess in sight.
BR,
-R
PATCH 1/1 efi_loader: allow efi_loader code to call EFI interfaces
Quoted 36 lines · Rob Clark
Quoted 6 lines · Alexander Graf
Quoted 3 lines · Rob Clark
On Tue, Jul 25, 2017 at 8:16 AM, Alexander Graf <[email protected]> wrote:
Quoted 8 lines
Quoted 5 lines
Quoted 3 lines
I personally think having
_extfunctions in anything exposed to UEFI payloads makes more sense.having 2x all the interfaces for file related protocols would be
Why 2x the interfaces?
well, maybe not all, but for
efi_load_image()from a device-path to work, we need to be able to use simple-filesystem-protocol and a bunch of the file-protocol interfaces.. so it is definitely more messy.Quoted 16 lines
Quoted 3 lines
unfortunate. (Also currently they can stay static in
efi_file.cand just be called via sameefi_file_handlefxn ptrs that the UEFI world would be using, which is kinda nice.)Ah, that indeed is nice.
So, there is a third option if you want to tackle it:
3) Remove register variable need for gd
If gd is a simple global variable rather than a register variable, we wouldn't have that problem. On x86 it's just a variable for example. I don't know why arm and aarch64 have it as register variable, but I can't see an immediate need for it.
Quoted 7 lines
Quoted 2 lines
If you manage to solve that, we don't need any ext functions or reference counters ;).
It would be nice to not have this gd mess.. although I'm going to leave it to someone else who understands better why we do that in the first place to solve. I have a big pile of display-handover
Yeah, that was my plan too when I introduced efi_loader. Maybe I'll find time to tackle it one day. But it's certainly nothing short-term :(.
Quoted 4 lines
(clk/powerdomain/display-controller-state) issues on my TODO list, and I'm just trying to get the bootloader sorted to the point where I can tackle that. Not to mention a big pile of things todo in mesa, and my actual $day_job.
No worries, we're all in the same boat :)
Quoted 7 lines
I think with the EFI interfaces I need to use for
efi_load_image, it should be easy enough to keep any of those from calling back into the UEFI world, and we could do some sort ofEFI_CALLBACK()macro with some extra error checking to safeguard instead of the EFI_EXIT()+callback+EFI_ENTER() pattern.. and while it is a bit annoying to have to be careful about that, I think it would work ok if no one has a solution for the gd mess in sight.
If you want to macrorize things to make them more readable, give it a try :).
I really don't mind which path to take, but I want to ensure we're consistent and only have a single way of dealing with entry/exit to worry about.
Alex
PATCH 1/1 efi_loader: allow efi_loader code to call EFI interfaces
In reply to Alexander GrafQuoted 119 lines · Alexander Graf
Quoted 116 lines · Rob Clark
Quoted 105 lines · Alexander Graf
Quoted 95 lines · Rob Clark
Quoted 85 lines · Alexander Graf
Quoted 58 lines · Rob Clark
Quoted 44 lines · Alexander Graf
Quoted 14 lines · Rob Clark
To implement
efi_load_image()for the case of loading an image from a
device path rather than image already loaded intosource_buffer, it is
convenient to be able to re-use simple-file-system and efi-file interfaces. But these are already using EFI_ENTER()/EFI_EXIT(). Allow
entry into EFI interfaces to be recursive, since this greatly simplifies
things.Quoted 5 lines
(And hypothetically this would be needed anyways to allow grub to call
into interfaces installed by something outside of grub.)Signed-off-by Rob Clark <[email protected]>So there are 2 ways to do this:
1) Keep a refcount, only transition when passing the 0 level
2) Explicitly split functions with ENTRY/EXIT from their core
functionsSo far we used approach 2, splitting functions that are used by both internal and external code into
_ext(for externally called) and normal
functions. You can see this pattern quite a few times throughoutefi_loader.I definitely did try the refcount approach back when I decided for approach
2 and it failed on me in some case, but I can't remember where.Quoted 9 lines
Either way, we should definitely be consistent. Either we always use refcounting or we shouldn't bother with it. So if you can make a version
work where all_extvariants disappear and we're magically reentrant,
I'll
be happy to take that. I'm fairly sure it'll break somewhere though :).Quoted 4 lines
for
load_imagevia file-path, we end up needing a *bunch* of functions
normally called via EFI.. so it is going to be a lot more_extvariants.Yes, but imagine a case like this:
open_protocol-> open() -> random_junk() -> efi_timer_check() -> timer notifier -> console print()Here the refcounting will simply fail on us, as the timer notifier needs
to
be run in UEFI context whileefi_timer_check()as well as consoleprint()
need to be run in U-Boot context.Quoted 7 lines
And if we start to mix and mesh the 2 approaches, I can promise you that
2
weeks down some corner case nobody thought of falls apart because people
don't manage to fully grasp the code flow anymore.Quoted 5 lines
ugg.. gd is a gd pita ;-)
how many places do we have callbacks into UEFI context like this? If just one or two maybe we can suppress them while in u-boot context and handle in
efi_exit_func()whenentry_countdrops to zero?Quoted 5 lines
What do you mean by suppressing? We need to call those helpers synchronously. And yes, we can probably hand massage the refcount on the ones that we remember, but I'm just afraid that the whole thing will be so
complicated eventually that nobody understands what's going on.Maybe suppress isn't the right word.. I was thinking of delaying the callback until
EFI_EXIT()that transitions back to the UEFI world. So from the PoV of the UEFI world, it is still synchronous.
Quoted 7 lines
Quoted 5 lines
I haven't looked at the
efi_eventstuff until just now, but from a 30sec look, maybeefi_signal_event()could just put the event on a list of signalled events and not immediately callevent->notify_function(), and handle the calling ofnotify_function()in the lastEFI_EXIT()??Maybe, I'll leave Heinrich to comment on that.
Let the application call WaitForEvent for a keyboard event. Rob suggests that neither timer events nor any other events are served until the user possibly presses a key.
No, we have to call notification functions immediately to serve time critical communication like network traffic.
Best regards
Heinrich
Quoted 31 lines
Quoted 7 lines
Quoted 5 lines
I personally think having
_extfunctions in anything exposed to UEFI payloads makes more sense.having 2x all the interfaces for file related protocols would be
Why 2x the interfaces?
Quoted 3 lines
unfortunate. (Also currently they can stay static in
efi_file.cand just be called via sameefi_file_handlefxn ptrs that the UEFI world would be using, which is kinda nice.)Ah, that indeed is nice.
So, there is a third option if you want to tackle it:
3) Remove register variable need for gd
If gd is a simple global variable rather than a register variable, we wouldn't have that problem. On x86 it's just a variable for example. I don't know why arm and aarch64 have it as register variable, but I can't see an immediate need for it.
If you manage to solve that, we don't need any ext functions or reference counters ;).
Alex
PATCH 1/1 efi_loader: allow efi_loader code to call EFI interfaces
Quoted 126 lines · Heinrich Schuchardt
Quoted 125 lines · Alexander Graf
Quoted 121 lines · Rob Clark
Quoted 105 lines · Alexander Graf
Quoted 95 lines · Rob Clark
Quoted 85 lines · Alexander Graf
Quoted 58 lines · Rob Clark
Quoted 44 lines · Alexander Graf
Quoted 14 lines · Rob Clark
To implement
efi_load_image()for the case of loading an image from a
device path rather than image already loaded intosource_buffer, it is
convenient to be able to re-use simple-file-system and efi-file interfaces. But these are already using EFI_ENTER()/EFI_EXIT(). Allow
entry into EFI interfaces to be recursive, since this greatly simplifies
things.Quoted 5 lines
(And hypothetically this would be needed anyways to allow grub to call
into interfaces installed by something outside of grub.)Signed-off-by Rob Clark <[email protected]>So there are 2 ways to do this:
1) Keep a refcount, only transition when passing the 0 level
2) Explicitly split functions with ENTRY/EXIT from their core
functionsSo far we used approach 2, splitting functions that are used by both internal and external code into
_ext(for externally called) and normal
functions. You can see this pattern quite a few times throughoutefi_loader.I definitely did try the refcount approach back when I decided for approach
2 and it failed on me in some case, but I can't remember where.Quoted 9 lines
Either way, we should definitely be consistent. Either we always use refcounting or we shouldn't bother with it. So if you can make a version
work where all_extvariants disappear and we're magically reentrant,
I'll
be happy to take that. I'm fairly sure it'll break somewhere though :).Quoted 4 lines
for
load_imagevia file-path, we end up needing a *bunch* of functions
normally called via EFI.. so it is going to be a lot more_extvariants.Yes, but imagine a case like this:
open_protocol-> open() -> random_junk() -> efi_timer_check() -> timer notifier -> console print()Here the refcounting will simply fail on us, as the timer notifier needs
to
be run in UEFI context whileefi_timer_check()as well as consoleprint()
need to be run in U-Boot context.Quoted 7 lines
And if we start to mix and mesh the 2 approaches, I can promise you that
2
weeks down some corner case nobody thought of falls apart because people
don't manage to fully grasp the code flow anymore.Quoted 5 lines
ugg.. gd is a gd pita ;-)
how many places do we have callbacks into UEFI context like this? If just one or two maybe we can suppress them while in u-boot context and handle in
efi_exit_func()whenentry_countdrops to zero?Quoted 5 lines
What do you mean by suppressing? We need to call those helpers synchronously. And yes, we can probably hand massage the refcount on the ones that we remember, but I'm just afraid that the whole thing will be so
complicated eventually that nobody understands what's going on.Maybe suppress isn't the right word.. I was thinking of delaying the callback until
EFI_EXIT()that transitions back to the UEFI world. So from the PoV of the UEFI world, it is still synchronous.I haven't looked at the
efi_eventstuff until just now, but from a 30sec look, maybeefi_signal_event()could just put the event on a list of signalled events and not immediately callevent->notify_function(), and handle the calling ofnotify_function()in the lastEFI_EXIT()??
Quoted 9 lines
Quoted 1 line
Maybe, I'll leave Heinrich to comment on that.
Let the application call WaitForEvent for a keyboard event. Rob suggests that neither timer events nor any other events are served until the user possibly presses a key.
No, we have to call notification functions immediately to serve time critical communication like network traffic.
Does WaitForEvent or anything else that dispatches events dispatch more than one event, or is it just one event and then return to UEFI world to poll again? We aren't really multi-threaded so there can't really be async callbacks.
Either way, I think we can make this work by changing EFI_EXIT()/callback/EFI_ENTER() to EFI_CALLBACK(callback).. for the non-nested EFI_ENTER() case we don't have to do anything special (and the nested case probably should never happen in places where we need EFI_CALLBACK())
BR,
-R
PATCH 1/1 efi_loader: allow efi_loader code to call EFI interfaces
Quoted 143 lines · Rob Clark
Quoted 126 lines · Heinrich Schuchardt
Quoted 125 lines · Alexander Graf
Quoted 121 lines · Rob Clark
Quoted 105 lines · Alexander Graf
Quoted 95 lines · Rob Clark
Quoted 85 lines · Alexander Graf
Quoted 58 lines · Rob Clark
Quoted 44 lines · Alexander Graf
Quoted 14 lines · Rob Clark
To implement
efi_load_image()for the case of loading an image from a
device path rather than image already loaded intosource_buffer, it is
convenient to be able to re-use simple-file-system and efi-file interfaces. But these are already using EFI_ENTER()/EFI_EXIT(). Allow
entry into EFI interfaces to be recursive, since this greatly simplifies
things.Quoted 5 lines
(And hypothetically this would be needed anyways to allow grub to call
into interfaces installed by something outside of grub.)Signed-off-by Rob Clark <[email protected]>So there are 2 ways to do this:
1) Keep a refcount, only transition when passing the 0 level
2) Explicitly split functions with ENTRY/EXIT from their core
functionsSo far we used approach 2, splitting functions that are used by both internal and external code into
_ext(for externally called) and normal
functions. You can see this pattern quite a few times throughoutefi_loader.I definitely did try the refcount approach back when I decided for approach
2 and it failed on me in some case, but I can't remember where.Quoted 9 lines
Either way, we should definitely be consistent. Either we always use refcounting or we shouldn't bother with it. So if you can make a version
work where all_extvariants disappear and we're magically reentrant,
I'll
be happy to take that. I'm fairly sure it'll break somewhere though :).Quoted 4 lines
for
load_imagevia file-path, we end up needing a *bunch* of functions
normally called via EFI.. so it is going to be a lot more_extvariants.Yes, but imagine a case like this:
open_protocol-> open() -> random_junk() -> efi_timer_check() -> timer notifier -> console print()Here the refcounting will simply fail on us, as the timer notifier needs
to
be run in UEFI context whileefi_timer_check()as well as consoleprint()
need to be run in U-Boot context.Quoted 7 lines
And if we start to mix and mesh the 2 approaches, I can promise you that
2
weeks down some corner case nobody thought of falls apart because people
don't manage to fully grasp the code flow anymore.Quoted 5 lines
ugg.. gd is a gd pita ;-)
how many places do we have callbacks into UEFI context like this? If just one or two maybe we can suppress them while in u-boot context and handle in
efi_exit_func()whenentry_countdrops to zero?Quoted 5 lines
What do you mean by suppressing? We need to call those helpers synchronously. And yes, we can probably hand massage the refcount on the ones that we remember, but I'm just afraid that the whole thing will be so
complicated eventually that nobody understands what's going on.Maybe suppress isn't the right word.. I was thinking of delaying the callback until
EFI_EXIT()that transitions back to the UEFI world. So from the PoV of the UEFI world, it is still synchronous.I haven't looked at the
efi_eventstuff until just now, but from a 30sec look, maybeefi_signal_event()could just put the event on a list of signalled events and not immediately callevent->notify_function(), and handle the calling ofnotify_function()in the lastEFI_EXIT()??Quoted 9 lines
Quoted 1 line
Maybe, I'll leave Heinrich to comment on that.
Let the application call WaitForEvent for a keyboard event. Rob suggests that neither timer events nor any other events are served until the user possibly presses a key.
No, we have to call notification functions immediately to serve time critical communication like network traffic.
Does WaitForEvent or anything else that dispatches events dispatch more than one event, or is it just one event and then return to UEFI world to poll again? We aren't really multi-threaded so there can't really be async callbacks.
Quoted 5 lines
Either way, I think we can make this work by changing EFI_EXIT()/callback/EFI_ENTER() to
EFI_CALLBACK(callback).. for the non-nestedEFI_ENTER()case we don't have to do anything special (and the nested case probably should never happen in places where we needEFI_CALLBACK())
WaitForEvent and CheckEvent calls will serve all notify_functions of timer events this includes a notify_function checking the keyboard and in future I want to check the watchdog in a notify_function.
Please, consider that in the notify functions any number of UEFI API functions will be called by the EFI application which themselves may signal events which in turn call notify_functions in which again UEFI API functions may be called.
So make no assumptions whatsoever about what is going to happen in a notify function or about the level of nesting.
Best regards
Heinrich
PATCH 1/1 efi_loader: allow efi_loader code to call EFI interfaces
Quoted 150 lines · Heinrich Schuchardt
Quoted 143 lines · Rob Clark
Quoted 126 lines · Heinrich Schuchardt
Quoted 125 lines · Alexander Graf
Quoted 121 lines · Rob Clark
Quoted 105 lines · Alexander Graf
Quoted 95 lines · Rob Clark
Quoted 85 lines · Alexander Graf
Quoted 58 lines · Rob Clark
Quoted 44 lines · Alexander Graf
Quoted 14 lines · Rob Clark
To implement
efi_load_image()for the case of loading an image from a
device path rather than image already loaded intosource_buffer, it is
convenient to be able to re-use simple-file-system and efi-file interfaces. But these are already using EFI_ENTER()/EFI_EXIT(). Allow
entry into EFI interfaces to be recursive, since this greatly simplifies
things.Quoted 5 lines
(And hypothetically this would be needed anyways to allow grub to call
into interfaces installed by something outside of grub.)Signed-off-by Rob Clark <[email protected]>So there are 2 ways to do this:
1) Keep a refcount, only transition when passing the 0 level
2) Explicitly split functions with ENTRY/EXIT from their core
functionsSo far we used approach 2, splitting functions that are used by both internal and external code into
_ext(for externally called) and normal
functions. You can see this pattern quite a few times throughoutefi_loader.I definitely did try the refcount approach back when I decided for approach
2 and it failed on me in some case, but I can't remember where.Quoted 9 lines
Either way, we should definitely be consistent. Either we always use refcounting or we shouldn't bother with it. So if you can make a version
work where all_extvariants disappear and we're magically reentrant,
I'll
be happy to take that. I'm fairly sure it'll break somewhere though :).Quoted 4 lines
for
load_imagevia file-path, we end up needing a *bunch* of functions
normally called via EFI.. so it is going to be a lot more_extvariants.Yes, but imagine a case like this:
open_protocol-> open() -> random_junk() -> efi_timer_check() -> timer notifier -> console print()Here the refcounting will simply fail on us, as the timer notifier needs
to
be run in UEFI context whileefi_timer_check()as well as consoleprint()
need to be run in U-Boot context.Quoted 7 lines
And if we start to mix and mesh the 2 approaches, I can promise you that
2
weeks down some corner case nobody thought of falls apart because people
don't manage to fully grasp the code flow anymore.Quoted 5 lines
ugg.. gd is a gd pita ;-)
how many places do we have callbacks into UEFI context like this? If just one or two maybe we can suppress them while in u-boot context and handle in
efi_exit_func()whenentry_countdrops to zero?Quoted 5 lines
What do you mean by suppressing? We need to call those helpers synchronously. And yes, we can probably hand massage the refcount on the ones that we remember, but I'm just afraid that the whole thing will be so
complicated eventually that nobody understands what's going on.Maybe suppress isn't the right word.. I was thinking of delaying the callback until
EFI_EXIT()that transitions back to the UEFI world. So from the PoV of the UEFI world, it is still synchronous.I haven't looked at the
efi_eventstuff until just now, but from a 30sec look, maybeefi_signal_event()could just put the event on a list of signalled events and not immediately callevent->notify_function(), and handle the calling ofnotify_function()in the lastEFI_EXIT()??Quoted 9 lines
Quoted 1 line
Maybe, I'll leave Heinrich to comment on that.
Let the application call WaitForEvent for a keyboard event. Rob suggests that neither timer events nor any other events are served until the user possibly presses a key.
No, we have to call notification functions immediately to serve time critical communication like network traffic.
Does WaitForEvent or anything else that dispatches events dispatch more than one event, or is it just one event and then return to UEFI world to poll again? We aren't really multi-threaded so there can't really be async callbacks.
Quoted 5 lines
Either way, I think we can make this work by changing EFI_EXIT()/callback/EFI_ENTER() to
EFI_CALLBACK(callback).. for the non-nestedEFI_ENTER()case we don't have to do anything special (and the nested case probably should never happen in places where we needEFI_CALLBACK())
Quoted 8 lines
WaitForEvent and CheckEvent calls will serve all
notify_functionsof timer events this includes anotify_functionchecking the keyboard and in future I want to check the watchdog in anotify_function.Please, consider that in the notify functions any number of UEFI API functions will be called by the EFI application which themselves may signal events which in turn call
notify_functionsin which again UEFI API functions may be called.
sure, one way or another I don't want to call a notifier from nested EFI_ENTER()'s..
so either EFI_CALLBACK() should detect the condition and yell loudly, or it should detect it and queue up callbacks until we are not nested..
I think the first option is probably ok. In the special cases where we might need to dispatch events, _ext() fxns should still be used until gd goes away.
BR,
-R
Quoted 6 lines
So make no assumptions whatsoever about what is going to happen in a notify function or about the level of nesting.
Best regards
Heinrich
PATCH 1/1 efi_loader: allow efi_loader code to call EFI interfaces
Quoted 155 lines · Rob Clark
Quoted 154 lines · Heinrich Schuchardt
Quoted 143 lines · Rob Clark
Quoted 126 lines · Heinrich Schuchardt
Quoted 125 lines · Alexander Graf
Quoted 121 lines · Rob Clark
Quoted 105 lines · Alexander Graf
Quoted 95 lines · Rob Clark
Quoted 85 lines · Alexander Graf
Quoted 58 lines · Rob Clark
Quoted 44 lines · Alexander Graf
Quoted 14 lines · Rob Clark
To implement
efi_load_image()for the case of loading an image from a
device path rather than image already loaded intosource_buffer, it is
convenient to be able to re-use simple-file-system and efi-file interfaces. But these are already using EFI_ENTER()/EFI_EXIT(). Allow
entry into EFI interfaces to be recursive, since this greatly simplifies
things.Quoted 5 lines
(And hypothetically this would be needed anyways to allow grub to call
into interfaces installed by something outside of grub.)Signed-off-by Rob Clark <[email protected]>So there are 2 ways to do this:
1) Keep a refcount, only transition when passing the 0 level
2) Explicitly split functions with ENTRY/EXIT from their core
functionsSo far we used approach 2, splitting functions that are used by both internal and external code into
_ext(for externally called) and normal
functions. You can see this pattern quite a few times throughoutefi_loader.I definitely did try the refcount approach back when I decided for approach
2 and it failed on me in some case, but I can't remember where.Quoted 9 lines
Either way, we should definitely be consistent. Either we always use refcounting or we shouldn't bother with it. So if you can make a version
work where all_extvariants disappear and we're magically reentrant,
I'll
be happy to take that. I'm fairly sure it'll break somewhere though :).Quoted 4 lines
for
load_imagevia file-path, we end up needing a *bunch* of functions
normally called via EFI.. so it is going to be a lot more_extvariants.Yes, but imagine a case like this:
open_protocol-> open() -> random_junk() -> efi_timer_check() -> timer notifier -> console print()Here the refcounting will simply fail on us, as the timer notifier needs
to
be run in UEFI context whileefi_timer_check()as well as consoleprint()
need to be run in U-Boot context.Quoted 7 lines
And if we start to mix and mesh the 2 approaches, I can promise you that
2
weeks down some corner case nobody thought of falls apart because people
don't manage to fully grasp the code flow anymore.Quoted 5 lines
ugg.. gd is a gd pita ;-)
how many places do we have callbacks into UEFI context like this? If just one or two maybe we can suppress them while in u-boot context and handle in
efi_exit_func()whenentry_countdrops to zero?Quoted 5 lines
What do you mean by suppressing? We need to call those helpers synchronously. And yes, we can probably hand massage the refcount on the ones that we remember, but I'm just afraid that the whole thing will be so
complicated eventually that nobody understands what's going on.Maybe suppress isn't the right word.. I was thinking of delaying the callback until
EFI_EXIT()that transitions back to the UEFI world. So from the PoV of the UEFI world, it is still synchronous.I haven't looked at the
efi_eventstuff until just now, but from a 30sec look, maybeefi_signal_event()could just put the event on a list of signalled events and not immediately callevent->notify_function(), and handle the calling ofnotify_function()in the lastEFI_EXIT()??Quoted 9 lines
Quoted 1 line
Maybe, I'll leave Heinrich to comment on that.
Let the application call WaitForEvent for a keyboard event. Rob suggests that neither timer events nor any other events are served until the user possibly presses a key.
No, we have to call notification functions immediately to serve time critical communication like network traffic.
Does WaitForEvent or anything else that dispatches events dispatch more than one event, or is it just one event and then return to UEFI world to poll again? We aren't really multi-threaded so there can't really be async callbacks.
Quoted 5 lines
Either way, I think we can make this work by changing EFI_EXIT()/callback/EFI_ENTER() to
EFI_CALLBACK(callback).. for the non-nestedEFI_ENTER()case we don't have to do anything special (and the nested case probably should never happen in places where we needEFI_CALLBACK())WaitForEvent and CheckEvent calls will serve all
notify_functionsof timer events this includes anotify_functionchecking the keyboard and in future I want to check the watchdog in anotify_function.
Quoted 7 lines
Quoted 4 lines
Please, consider that in the notify functions any number of UEFI API functions will be called by the EFI application which themselves may signal events which in turn call
notify_functionsin which again UEFI API functions may be called.sure, one way or another I don't want to call a notifier from nested EFI_ENTER()'s..
We call EFI_EXIT before calling the notifier function and call EFI_ENTER after returning form the notifier function.
So currently we always switch gd correctly. An nested EFI_ENTER simply does not occur.
I still do not understand why you need to change anything here.
Quoted 4 lines
so either
EFI_CALLBACK()should detect the condition and yell loudly, or it should detect it and queue up callbacks until we are not nested..
Your suggestions are getting more and more complicated.
I would always go for easily maintainable code and not for sophistication. Please, stick to the KISS principle.
If you want to call functions internally as you described in the first mail in this thread, do not call the UEFI functions but supply separate entry points.
Best regards
Heinrich
Quoted 15 lines
I think the first option is probably ok. In the special cases where we might need to dispatch events,
_ext()fxns should still be used until gd goes away.BR,
-RQuoted 6 lines
So make no assumptions whatsoever about what is going to happen in a notify function or about the level of nesting.
Best regards
Heinrich
PATCH 1/1 efi_loader: allow efi_loader code to call EFI interfaces
Quoted 161 lines · Heinrich Schuchardt
Quoted 160 lines · Rob Clark
Quoted 158 lines · Heinrich Schuchardt
Quoted 143 lines · Rob Clark
Quoted 126 lines · Heinrich Schuchardt
Quoted 125 lines · Alexander Graf
Quoted 121 lines · Rob Clark
Quoted 105 lines · Alexander Graf
Quoted 95 lines · Rob Clark
Quoted 85 lines · Alexander Graf
Quoted 58 lines · Rob Clark
Quoted 44 lines · Alexander Graf
Quoted 19 lines · Rob Clark
To implement efi_load_image() for the case of loading an image
from a
device path rather than image already loaded into source_buffer,
it is
convenient to be able to re-use simple-file-system and efi-file
interfaces. But these are already using EFI_ENTER()/EFI_EXIT().
Allow
entry into EFI interfaces to be recursive, since this greatly
simplifies
things.(And hypothetically this would be needed anyways to allow grub
to call
into interfaces installed by something outside of grub.)Signed-off-by: Rob Clark <[email protected]>
So there are 2 ways to do this:
1) Keep a refcount, only transition when passing the 0 level
2) Explicitly split functions with ENTRY/EXIT from their core
functionsSo far we used approach 2, splitting functions that are used by both internal and external code into
_ext(for externally called) and normal
functions. You can see this pattern quite a few times throughoutefi_loader.I definitely did try the refcount approach back when I decided for approach
2 and it failed on me in some case, but I can't remember where.Quoted 9 lines
Either way, we should definitely be consistent. Either we always use refcounting or we shouldn't bother with it. So if you can make a version
work where all_extvariants disappear and we're magically reentrant,
I'll
be happy to take that. I'm fairly sure it'll break somewhere though :).Quoted 4 lines
for
load_imagevia file-path, we end up needing a *bunch* of functions
normally called via EFI.. so it is going to be a lot more_extvariants.Yes, but imagine a case like this:
open_protocol-> open() -> random_junk() -> efi_timer_check() -> timer notifier -> console print()Here the refcounting will simply fail on us, as the timer notifier needs
to
be run in UEFI context whileefi_timer_check()as well as consoleprint()
need to be run in U-Boot context.Quoted 7 lines
And if we start to mix and mesh the 2 approaches, I can promise you that
2
weeks down some corner case nobody thought of falls apart because people
don't manage to fully grasp the code flow anymore.Quoted 5 lines
ugg.. gd is a gd pita ;-)
how many places do we have callbacks into UEFI context like this? If just one or two maybe we can suppress them while in u-boot context and handle in
efi_exit_func()whenentry_countdrops to zero?Quoted 5 lines
What do you mean by suppressing? We need to call those helpers synchronously. And yes, we can probably hand massage the refcount on the ones that we remember, but I'm just afraid that the whole thing will be so
complicated eventually that nobody understands what's going on.Maybe suppress isn't the right word.. I was thinking of delaying the callback until
EFI_EXIT()that transitions back to the UEFI world. So from the PoV of the UEFI world, it is still synchronous.I haven't looked at the
efi_eventstuff until just now, but from a 30sec look, maybeefi_signal_event()could just put the event on a list of signalled events and not immediately callevent->notify_function(), and handle the calling ofnotify_function()in the lastEFI_EXIT()??Quoted 9 lines
Quoted 1 line
Maybe, I'll leave Heinrich to comment on that.
Let the application call WaitForEvent for a keyboard event. Rob suggests that neither timer events nor any other events are served until the user possibly presses a key.
No, we have to call notification functions immediately to serve time critical communication like network traffic.
Does WaitForEvent or anything else that dispatches events dispatch more than one event, or is it just one event and then return to UEFI world to poll again? We aren't really multi-threaded so there can't really be async callbacks.
Quoted 5 lines
Either way, I think we can make this work by changing EFI_EXIT()/callback/EFI_ENTER() to
EFI_CALLBACK(callback).. for the non-nestedEFI_ENTER()case we don't have to do anything special (and the nested case probably should never happen in places where we needEFI_CALLBACK())WaitForEvent and CheckEvent calls will serve all
notify_functionsof timer events this includes anotify_functionchecking the keyboard and in future I want to check the watchdog in anotify_function.Please, consider that in the notify functions any number of UEFI API functions will be called by the EFI application which themselves may signal events which in turn call
notify_functionsin which again UEFI API functions may be called.
Quoted 8 lines
Quoted 2 lines
sure, one way or another I don't want to call a notifier from nested EFI_ENTER()'s..
We call
EFI_EXITbefore calling the notifier function and callEFI_ENTERafter returning form the notifier function.So currently we always switch gd correctly. An nested
EFI_ENTERsimply does not occur.
yes, I understand how it currently works.. although I think an EFI_CALLBACK() macro that did the equiv (with extra error checking if we allow re-entrant EFI_ENTER()) would be clearer. It would make the callbacks to UEFI world easy to spot and make the code a bit more concise.
Quoted 7 lines
I still do not understand why you need to change anything here.
Quoted 4 lines
so either
EFI_CALLBACK()should detect the condition and yell loudly, or it should detect it and queue up callbacks until we are not nested..
Quoted 8 lines
Your suggestions are getting more and more complicated.
I would always go for easily maintainable code and not for sophistication. Please, stick to the KISS principle.
If you want to call functions internally as you described in the first mail in this thread, do not call the UEFI functions but supply separate entry points.
The issue that I am trying to address at the moment is that efi_load_image(), to load an image specified by file_path (as opposed to already loaded into source_buffer, ie. the source_buffer==NULL case, which UEFI spec allows) requires using a handful of APIs from the EFI file interface, and also requires the simple-file-system-protocol, to actually read the image specified by file_path into a buffer.
We could go down the path of continuing to add _ext functions.. but it is a bit ugly, and seems like it would keep growing worse. And it requires exposing functions from different modules which could otherwise remain static. All for a case that won't happen (for these particular APIs at least) or at least is easy to detect. Keeping the _ext functions for only the special cases that could lead to a callback into UEFI world, and avoiding them in the normal case, seems cleaner. It isn't terribly complicated to implement, and it is easy to detect programming errors.
At a *minimum* I'd say that the current EFI_ENTRY()/EFI_EXIT() should detect nesting (since the result if you screw that up is a less than obvious crash). And an EFI_CALLBACK() macro would make the callback into UEFI world more obvious via grep. Once you have that, it is trivial to allow nesting and detect problematic EFI_CALLBACK().
BR,
-R
PATCH 1/1 efi_loader: allow efi_loader code to call EFI interfaces
Quoted 201 lines · Rob Clark
Quoted 161 lines · Heinrich Schuchardt
Quoted 160 lines · Rob Clark
Quoted 158 lines · Heinrich Schuchardt
Quoted 143 lines · Rob Clark
Quoted 126 lines · Heinrich Schuchardt
Quoted 125 lines · Alexander Graf
Quoted 121 lines · Rob Clark
Quoted 105 lines · Alexander Graf
Quoted 95 lines · Rob Clark
Quoted 85 lines · Alexander Graf
Quoted 58 lines · Rob Clark
Quoted 53 lines · Alexander Graf
On 25.07.17 01:47, Rob Clark wrote:
To implement efi_load_image() for the case of loading an image
from a
device path rather than image already loaded into source_buffer,
it is
convenient to be able to re-use simple-file-system and efi-file
interfaces. But these are already using EFI_ENTER()/EFI_EXIT().
Allow
entry into EFI interfaces to be recursive, since this greatly
simplifies
things.(And hypothetically this would be needed anyways to allow grub
to call
into interfaces installed by something outside of grub.)Signed-off-by: Rob Clark <[email protected]>
So there are 2 ways to do this:
1) Keep a refcount, only transition when passing the 0 level
2) Explicitly split functions with ENTRY/EXIT from their core
functionsSo far we used approach 2, splitting functions that are used by both
internal and external code into _ext (for externally called) and
normal
functions. You can see this pattern quite a few times throughout
efi_loader.I definitely did try the refcount approach back when I decided for
approach
2 and it failed on me in some case, but I can't remember where.Either way, we should definitely be consistent. Either we always use
refcounting or we shouldn't bother with it. So if you can make a
version
work where all _ext variants disappear and we're magically
reentrant,
I'll
be happy to take that. I'm fairly sure it'll break somewhere
though :).Quoted 4 lines
for
load_imagevia file-path, we end up needing a *bunch* of functions
normally called via EFI.. so it is going to be a lot more_extvariants.Yes, but imagine a case like this:
open_protocol-> open() -> random_junk() -> efi_timer_check() -> timer notifier -> console print()Here the refcounting will simply fail on us, as the timer notifier needs
to
be run in UEFI context whileefi_timer_check()as well as consoleprint()
need to be run in U-Boot context.Quoted 7 lines
And if we start to mix and mesh the 2 approaches, I can promise you that
2
weeks down some corner case nobody thought of falls apart because people
don't manage to fully grasp the code flow anymore.Quoted 5 lines
ugg.. gd is a gd pita ;-)
how many places do we have callbacks into UEFI context like this? If just one or two maybe we can suppress them while in u-boot context and handle in
efi_exit_func()whenentry_countdrops to zero?Quoted 5 lines
What do you mean by suppressing? We need to call those helpers synchronously. And yes, we can probably hand massage the refcount on the ones that we remember, but I'm just afraid that the whole thing will be so
complicated eventually that nobody understands what's going on.Maybe suppress isn't the right word.. I was thinking of delaying the callback until
EFI_EXIT()that transitions back to the UEFI world. So from the PoV of the UEFI world, it is still synchronous.I haven't looked at the
efi_eventstuff until just now, but from a 30sec look, maybeefi_signal_event()could just put the event on a list of signalled events and not immediately callevent->notify_function(), and handle the calling ofnotify_function()in the lastEFI_EXIT()??Quoted 9 lines
Quoted 1 line
Maybe, I'll leave Heinrich to comment on that.
Let the application call WaitForEvent for a keyboard event. Rob suggests that neither timer events nor any other events are served until the user possibly presses a key.
No, we have to call notification functions immediately to serve time critical communication like network traffic.
Does WaitForEvent or anything else that dispatches events dispatch more than one event, or is it just one event and then return to UEFI world to poll again? We aren't really multi-threaded so there can't really be async callbacks.
Quoted 5 lines
Either way, I think we can make this work by changing EFI_EXIT()/callback/EFI_ENTER() to
EFI_CALLBACK(callback).. for the non-nestedEFI_ENTER()case we don't have to do anything special (and the nested case probably should never happen in places where we needEFI_CALLBACK())WaitForEvent and CheckEvent calls will serve all
notify_functionsof timer events this includes anotify_functionchecking the keyboard and in future I want to check the watchdog in anotify_function.Please, consider that in the notify functions any number of UEFI API functions will be called by the EFI application which themselves may signal events which in turn call
notify_functionsin which again UEFI API functions may be called.Quoted 8 lines
Quoted 2 lines
sure, one way or another I don't want to call a notifier from nested EFI_ENTER()'s..
We call
EFI_EXITbefore calling the notifier function and callEFI_ENTERafter returning form the notifier function.So currently we always switch gd correctly. An nested
EFI_ENTERsimply does not occur.yes, I understand how it currently works.. although I think an
EFI_CALLBACK()macro that did the equiv (with extra error checking if we allow re-entrantEFI_ENTER()) would be clearer. It would make the callbacks to UEFI world easy to spot and make the code a bit more concise.Quoted 7 lines
I still do not understand why you need to change anything here.
Quoted 4 lines
so either
EFI_CALLBACK()should detect the condition and yell loudly, or it should detect it and queue up callbacks until we are not nested..Quoted 8 lines
Your suggestions are getting more and more complicated.
I would always go for easily maintainable code and not for sophistication. Please, stick to the KISS principle.
If you want to call functions internally as you described in the first mail in this thread, do not call the UEFI functions but supply separate entry points.
The issue that I am trying to address at the moment is that
efi_load_image(), to load an image specified byfile_path(as opposed to already loaded intosource_buffer, ie. the source_buffer==NULL case, which UEFI spec allows) requires using a handful of APIs from the EFI file interface, and also requires the simple-file-system-protocol, to actually read the image specified byfile_pathinto a buffer.
Quoted 9 lines
We could go down the path of continuing to add
_extfunctions.. but it is a bit ugly, and seems like it would keep growing worse. And it requires exposing functions from different modules which could otherwise remain static. All for a case that won't happen (for these particular APIs at least) or at least is easy to detect. Keeping the_extfunctions for only the special cases that could lead to a callback into UEFI world, and avoiding them in the normal case, seems cleaner. It isn't terribly complicated to implement, and it is easy to detect programming errors.
Maybe we could turn all of this around and you just call EFI_EXIT() before calling all the callbacks? That way you're back in UEFI context and are free to call anything that doesn't need gd.
So something like
EFI_EXIT(); file_proto *f = bs->find_protocol(); file_foo *g = f->bar(); if (!g) return EFI_AMAZING_ERROR; ... EFI_ENTER();
That way the fs loading code that really only deals with UEFI calls would be self-contained. We do something similar already with efi_signal_event() today.
Alex
PATCH 1/1 efi_loader: allow efi_loader code to call EFI interfaces
Quoted 284 lines · Alexander Graf
Quoted 257 lines · Rob Clark
Quoted 215 lines · Heinrich Schuchardt
Quoted 203 lines · Rob Clark
Quoted 200 lines · Heinrich Schuchardt
Quoted 187 lines · Rob Clark
Quoted 170 lines · Heinrich Schuchardt
Quoted 165 lines · Alexander Graf
Quoted 153 lines · Rob Clark
Quoted 135 lines · Alexander Graf
Quoted 121 lines · Rob Clark
Quoted 107 lines · Alexander Graf
Quoted 80 lines · Rob Clark
On Tue, Jul 25, 2017 at 4:10 AM, Alexander Graf <[email protected]>
wrote:On 25.07.17 01:47, Rob Clark wrote:
To implement efi_load_image() for the case of loading an
image
from a
device path rather than image already loaded into
source_buffer,
it is
convenient to be able to re-use simple-file-system and
efi-file
interfaces. But these are already using
EFI_ENTER()/EFI_EXIT().
Allow
entry into EFI interfaces to be recursive, since this greatly
simplifies
things.(And hypothetically this would be needed anyways to allow
grub
to call
into interfaces installed by something outside of grub.)Signed-off-by: Rob Clark <[email protected]>
So there are 2 ways to do this:
1) Keep a refcount, only transition when passing the 0
level
2) Explicitly split functions with ENTRY/EXIT from their
core
functionsSo far we used approach 2, splitting functions that are used
by both
internal and external code into _ext (for externally called)
and
normal
functions. You can see this pattern quite a few times
throughout
efi_loader.I definitely did try the refcount approach back when I decided
for
approach
2 and it failed on me in some case, but I can't remember
where.Either way, we should definitely be consistent. Either we
always use
refcounting or we shouldn't bother with it. So if you can make
a
version
work where all _ext variants disappear and we're magically
reentrant,
I'll
be happy to take that. I'm fairly sure it'll break somewhere
though :).for load_image via file-path, we end up needing a *bunch* of
functions
normally called via EFI.. so it is going to be a lot more _ext
variants.Yes, but imagine a case like this:
open_protocol-> open() -> random_junk() -> efi_timer_check() -> timer notifier -> console print()Here the refcounting will simply fail on us, as the timer notifier
needs
to
be run in UEFI context whileefi_timer_check()as well as consoleprint()
need to be run in U-Boot context.Quoted 9 lines
And if we start to mix and mesh the 2 approaches, I can promise you
that
2
weeks down some corner case nobody thought of falls apart because
people
don't manage to fully grasp the code flow anymore.Quoted 7 lines
ugg.. gd is a gd pita ;-)
how many places do we have callbacks into UEFI context like this? If
just one or two maybe we can suppress them while in u-boot context and
handle inefi_exit_func()whenentry_countdrops to zero?Quoted 7 lines
What do you mean by suppressing? We need to call those helpers synchronously. And yes, we can probably hand massage the refcount on the
ones that we remember, but I'm just afraid that the whole thing will
be so
complicated eventually that nobody understands what's going on.Maybe suppress isn't the right word.. I was thinking of delaying the
callback untilEFI_EXIT()that transitions back to the UEFI world. So
from the PoV of the UEFI world, it is still synchronous.Quoted 6 lines
I haven't looked at the
efi_eventstuff until just now, but from a 30sec look, maybeefi_signal_event()could just put the event on a list of signalled events and not immediately callevent->notify_function(), and handle the calling ofnotify_function()
in the lastEFI_EXIT()??Quoted 1 line
Maybe, I'll leave Heinrich to comment on that.
Quoted 8 lines
Let the application call WaitForEvent for a keyboard event. Rob suggests that neither timer events nor any other events are served
until the user possibly presses a key.No, we have to call notification functions immediately to serve time critical communication like network traffic.
Does WaitForEvent or anything else that dispatches events dispatch more than one event, or is it just one event and then return to UEFI world to poll again? We aren't really multi-threaded so there can't really be async callbacks.
Quoted 5 lines
Either way, I think we can make this work by changing EFI_EXIT()/callback/EFI_ENTER() to
EFI_CALLBACK(callback).. for the non-nestedEFI_ENTER()case we don't have to do anything special (and the nested case probably should never happen in places where we needEFI_CALLBACK())WaitForEvent and CheckEvent calls will serve all
notify_functionsof timer events this includes anotify_functionchecking the keyboard and in future I want to check the watchdog in anotify_function.Quoted 8 lines
Quoted 4 lines
Please, consider that in the notify functions any number of UEFI API functions will be called by the EFI application which themselves may signal events which in turn call
notify_functionsin which again UEFI API functions may be called.sure, one way or another I don't want to call a notifier from nested EFI_ENTER()'s..
Quoted 5 lines
We call
EFI_EXITbefore calling the notifier function and callEFI_ENTERafter returning form the notifier function.So currently we always switch gd correctly. An nested
EFI_ENTERsimply does not occur.yes, I understand how it currently works.. although I think an
EFI_CALLBACK()macro that did the equiv (with extra error checking if we allow re-entrantEFI_ENTER()) would be clearer. It would make the callbacks to UEFI world easy to spot and make the code a bit more concise.Quoted 8 lines
I still do not understand why you need to change anything here.
Quoted 4 lines
so either
EFI_CALLBACK()should detect the condition and yell loudly, or it should detect it and queue up callbacks until we are not nested..Quoted 8 lines
Your suggestions are getting more and more complicated.
I would always go for easily maintainable code and not for sophistication. Please, stick to the KISS principle.
If you want to call functions internally as you described in the first mail in this thread, do not call the UEFI functions but supply separate entry points.
The issue that I am trying to address at the moment is that
efi_load_image(), to load an image specified byfile_path(as opposed to already loaded intosource_buffer, ie. the source_buffer==NULL case, which UEFI spec allows) requires using a handful of APIs from the EFI file interface, and also requires the simple-file-system-protocol, to actually read the image specified byfile_pathinto a buffer.Quoted 9 lines
We could go down the path of continuing to add
_extfunctions.. but it is a bit ugly, and seems like it would keep growing worse. And it requires exposing functions from different modules which could otherwise remain static. All for a case that won't happen (for these particular APIs at least) or at least is easy to detect. Keeping the_extfunctions for only the special cases that could lead to a callback into UEFI world, and avoiding them in the normal case, seems cleaner. It isn't terribly complicated to implement, and it is easy to detect programming errors.Maybe we could turn all of this around and you just call
EFI_EXIT()before calling all the callbacks? That way you're back in UEFI context and are free to call anything that doesn't need gd.So something like
EFI_EXIT(); file_proto *f = bs->find_protocol(); file_foo *g = f->bar(); if (!g) return EFI_AMAZING_ERROR; ... EFI_ENTER();
Quoted 3 lines
That way the fs loading code that really only deals with UEFI calls would be self-contained. We do something similar already with
efi_signal_event()today.
I guess that would mean no malloc/printf/etc.. seems like just *asking* for someone to screw up ;-)
But I suppose we could do it at a finer granularity.. ie.
efi_load_image(...)
{
EFI_ENTER(..); if (!source_buffer) {
UEFI(ret = fs->open_volume(fs, &f));
while (fp) {
UEFI(ret = f->open(f, &f2, fp->str));
fp = efi_dp_next(fp);
UEFI(ret = f->close(f));
f = f2;
}
UEFI(ret = f->getinfo(f, &efi_file_info_guid, &bs, info));
...
UEFI(ret = f->read(f, ...));
}
...}
And ofc, convert existing callbacks to use UEFI() macro to make it it consistent in the code when things are going back to UEFI world.. ie. basically treat these just like callbacks.
There is more malloc, etc (and when debugging, printf()) in between this all, so I'm more a fan of a one-line macro rather than individual EFI_EXIT/EFI_ENTER. Plus it makes it harder to screw up early returns and that sorta thing.
and I'm still all for adding some error checking to EFI_ENTER/EFI_EXIT/UEFI macros to debug misuse more easily.
BR,
-R
PATCH 1/1 efi_loader: allow efi_loader code to call EFI interfaces
Quoted 285 lines · Rob Clark
Quoted 284 lines · Alexander Graf
Quoted 257 lines · Rob Clark
Quoted 215 lines · Heinrich Schuchardt
Quoted 203 lines · Rob Clark
Quoted 200 lines · Heinrich Schuchardt
Quoted 187 lines · Rob Clark
Quoted 170 lines · Heinrich Schuchardt
Quoted 165 lines · Alexander Graf
Quoted 153 lines · Rob Clark
Quoted 135 lines · Alexander Graf
Quoted 121 lines · Rob Clark
Quoted 116 lines · Alexander Graf
On 25.07.17 13:10, Rob Clark wrote:
On Tue, Jul 25, 2017 at 4:10 AM, Alexander Graf <[email protected]>
wrote:On 25.07.17 01:47, Rob Clark wrote:
To implement efi_load_image() for the case of loading an
image
from a
device path rather than image already loaded into
source_buffer,
it is
convenient to be able to re-use simple-file-system and
efi-file
interfaces. But these are already using
EFI_ENTER()/EFI_EXIT().
Allow
entry into EFI interfaces to be recursive, since this greatly
simplifies
things.(And hypothetically this would be needed anyways to allow
grub
to call
into interfaces installed by something outside of grub.)Signed-off-by: Rob Clark <[email protected]>
So there are 2 ways to do this:
1) Keep a refcount, only transition when passing the 0
level
2) Explicitly split functions with ENTRY/EXIT from their
core
functionsSo far we used approach 2, splitting functions that are used
by both
internal and external code into _ext (for externally called)
and
normal
functions. You can see this pattern quite a few times
throughout
efi_loader.I definitely did try the refcount approach back when I decided
for
approach
2 and it failed on me in some case, but I can't remember
where.Either way, we should definitely be consistent. Either we
always use
refcounting or we shouldn't bother with it. So if you can make
a
version
work where all _ext variants disappear and we're magically
reentrant,
I'll
be happy to take that. I'm fairly sure it'll break somewhere
though :).for load_image via file-path, we end up needing a *bunch* of
functions
normally called via EFI.. so it is going to be a lot more _ext
variants.Yes, but imagine a case like this:
open_protocol
-> open()
-> random_junk()
-> efi_timer_check()
-> timer notifier
-> console print()Here the refcounting will simply fail on us, as the timer
notifier
needs
to
be run in UEFI context while efi_timer_check() as well as
console
print()
need to be run in U-Boot context.And if we start to mix and mesh the 2 approaches, I can promise
you
that
2
weeks down some corner case nobody thought of falls apart
because
people
don't manage to fully grasp the code flow anymore.Quoted 7 lines
ugg.. gd is a gd pita ;-)
how many places do we have callbacks into UEFI context like this? If
just one or two maybe we can suppress them while in u-boot context and
handle inefi_exit_func()whenentry_countdrops to zero?Quoted 7 lines
What do you mean by suppressing? We need to call those helpers synchronously. And yes, we can probably hand massage the refcount on the
ones that we remember, but I'm just afraid that the whole thing will
be so
complicated eventually that nobody understands what's going on.Maybe suppress isn't the right word.. I was thinking of delaying the
callback untilEFI_EXIT()that transitions back to the UEFI world. So
from the PoV of the UEFI world, it is still synchronous.Quoted 6 lines
I haven't looked at the
efi_eventstuff until just now, but from a 30sec look, maybeefi_signal_event()could just put the event on a list of signalled events and not immediately callevent->notify_function(), and handle the calling ofnotify_function()
in the lastEFI_EXIT()??Quoted 1 line
Maybe, I'll leave Heinrich to comment on that.
Quoted 8 lines
Let the application call WaitForEvent for a keyboard event. Rob suggests that neither timer events nor any other events are served
until the user possibly presses a key.No, we have to call notification functions immediately to serve time critical communication like network traffic.
Does WaitForEvent or anything else that dispatches events dispatch more than one event, or is it just one event and then return to UEFI world to poll again? We aren't really multi-threaded so there can't really be async callbacks.
Quoted 5 lines
Either way, I think we can make this work by changing EFI_EXIT()/callback/EFI_ENTER() to
EFI_CALLBACK(callback).. for the non-nestedEFI_ENTER()case we don't have to do anything special (and the nested case probably should never happen in places where we needEFI_CALLBACK())WaitForEvent and CheckEvent calls will serve all
notify_functionsof timer events this includes anotify_functionchecking the keyboard and in future I want to check the watchdog in anotify_function.Quoted 8 lines
Quoted 4 lines
Please, consider that in the notify functions any number of UEFI API functions will be called by the EFI application which themselves may signal events which in turn call
notify_functionsin which again UEFI API functions may be called.sure, one way or another I don't want to call a notifier from nested EFI_ENTER()'s..
Quoted 5 lines
We call
EFI_EXITbefore calling the notifier function and callEFI_ENTERafter returning form the notifier function.So currently we always switch gd correctly. An nested
EFI_ENTERsimply does not occur.yes, I understand how it currently works.. although I think an
EFI_CALLBACK()macro that did the equiv (with extra error checking if we allow re-entrantEFI_ENTER()) would be clearer. It would make the callbacks to UEFI world easy to spot and make the code a bit more concise.Quoted 8 lines
I still do not understand why you need to change anything here.
Quoted 4 lines
so either
EFI_CALLBACK()should detect the condition and yell loudly, or it should detect it and queue up callbacks until we are not nested..Quoted 8 lines
Your suggestions are getting more and more complicated.
I would always go for easily maintainable code and not for sophistication. Please, stick to the KISS principle.
If you want to call functions internally as you described in the first mail in this thread, do not call the UEFI functions but supply separate entry points.
The issue that I am trying to address at the moment is that
efi_load_image(), to load an image specified byfile_path(as opposed to already loaded intosource_buffer, ie. the source_buffer==NULL case, which UEFI spec allows) requires using a handful of APIs from the EFI file interface, and also requires the simple-file-system-protocol, to actually read the image specified byfile_pathinto a buffer.Quoted 9 lines
We could go down the path of continuing to add
_extfunctions.. but it is a bit ugly, and seems like it would keep growing worse. And it requires exposing functions from different modules which could otherwise remain static. All for a case that won't happen (for these particular APIs at least) or at least is easy to detect. Keeping the_extfunctions for only the special cases that could lead to a callback into UEFI world, and avoiding them in the normal case, seems cleaner. It isn't terribly complicated to implement, and it is easy to detect programming errors.Maybe we could turn all of this around and you just call
EFI_EXIT()before calling all the callbacks? That way you're back in UEFI context and are free to call anything that doesn't need gd.So something like
EFI_EXIT(); file_proto *f = bs->find_protocol(); file_foo *g = f->bar(); if (!g) return EFI_AMAZING_ERROR; ... EFI_ENTER();
Quoted 6 lines
Quoted 3 lines
That way the fs loading code that really only deals with UEFI calls would be self-contained. We do something similar already with
efi_signal_event()today.I guess that would mean no malloc/printf/etc.. seems like just *asking* for someone to screw up ;-)
Well, you have to choose a world to be in. You still have the EFI alloc and print methods ;).
Quoted 26 lines
But I suppose we could do it at a finer granularity.. ie.
efi_load_image(...) { EFI_ENTER(..);if (!source_buffer) { UEFI(ret = fs->open_volume(fs, &f)); while (fp) { UEFI(ret = f->open(f, &f2, fp->str)); fp = efi_dp_next(fp); UEFI(ret = f->close(f)); f = f2; } UEFI(ret = f->getinfo(f, &efi_file_info_guid, &bs, info)); ... UEFI(ret = f->read(f, ...)); } ...}
Quoted 8 lines
And ofc, convert existing callbacks to use
UEFI()macro to make it it consistent in the code when things are going back to UEFI world.. ie. basically treat these just like callbacks.There is more malloc, etc (and when debugging,
printf()) in between this all, so I'm more a fan of a one-line macro rather than individual EFI_EXIT/EFI_ENTER. Plus it makes it harder to screw up early returns and that sorta thing.
Yup, that works too.
Quoted 2 lines
and I'm still all for adding some error checking to EFI_ENTER/EFI_EXIT/UEFI macros to debug misuse more easily.
Sure, but that's an orthogonal discussion :).
Alex
PATCH 1/1 efi_loader: allow efi_loader code to call EFI interfaces
Quoted 342 lines · Alexander Graf
Quoted 339 lines · Rob Clark
Quoted 335 lines · Alexander Graf
Quoted 300 lines · Rob Clark
Quoted 253 lines · Heinrich Schuchardt
Quoted 245 lines · Rob Clark
Quoted 234 lines · Heinrich Schuchardt
Quoted 217 lines · Rob Clark
Quoted 198 lines · Heinrich Schuchardt
Quoted 191 lines · Alexander Graf
Quoted 175 lines · Rob Clark
Quoted 153 lines · Alexander Graf
Quoted 144 lines · Rob Clark
On Tue, Jul 25, 2017 at 7:17 AM, Alexander Graf <[email protected]>
wrote:On 25.07.17 13:10, Rob Clark wrote:
On Tue, Jul 25, 2017 at 4:10 AM, Alexander Graf
<[email protected]>
wrote:On 25.07.17 01:47, Rob Clark wrote:
To implement efi_load_image() for the case of loading an
image
from a
device path rather than image already loaded into
source_buffer,
it is
convenient to be able to re-use simple-file-system and
efi-file
interfaces. But these are already using
EFI_ENTER()/EFI_EXIT().
Allow
entry into EFI interfaces to be recursive, since this
greatly
simplifies
things.(And hypothetically this would be needed anyways to allow
grub
to call
into interfaces installed by something outside of grub.)Signed-off-by: Rob Clark <[email protected]>
So there are 2 ways to do this:
1) Keep a refcount, only transition when passing the
0
level
2) Explicitly split functions with ENTRY/EXIT from
their
core
functionsSo far we used approach 2, splitting functions that are used
by both
internal and external code into _ext (for externally called)
and
normal
functions. You can see this pattern quite a few times
throughout
efi_loader.I definitely did try the refcount approach back when I
decided
for
approach
2 and it failed on me in some case, but I can't remember
where.Either way, we should definitely be consistent. Either we
always use
refcounting or we shouldn't bother with it. So if you can
make
a
version
work where all _ext variants disappear and we're magically
reentrant,
I'll
be happy to take that. I'm fairly sure it'll break somewhere
though :).for load_image via file-path, we end up needing a *bunch* of
functions
normally called via EFI.. so it is going to be a lot more
_ext
variants.Yes, but imagine a case like this:
open_protocol
-> open()
-> random_junk()
-> efi_timer_check()
-> timer notifier
-> console print()Here the refcounting will simply fail on us, as the timer
notifier
needs
to
be run in UEFI context while efi_timer_check() as well as
console
print()
need to be run in U-Boot context.And if we start to mix and mesh the 2 approaches, I can
promise
you
that
2
weeks down some corner case nobody thought of falls apart
because
people
don't manage to fully grasp the code flow anymore.ugg.. gd is a gd pita ;-)
how many places do we have callbacks into UEFI context like
this?
If
just one or two maybe we can suppress them while in u-boot
context and
handle in efi_exit_func() when entry_count drops to zero?Quoted 8 lines
What do you mean by suppressing? We need to call those helpers synchronously. And yes, we can probably hand massage the refcount
on the
ones that we remember, but I'm just afraid that the whole thing will
be so
complicated eventually that nobody understands what's going on.Maybe suppress isn't the right word.. I was thinking of delaying the
callback untilEFI_EXIT()that transitions back to the UEFI world.
So
from the PoV of the UEFI world, it is still synchronous.Quoted 8 lines
I haven't looked at the
efi_eventstuff until just now, but from a
30sec look, maybeefi_signal_event()could just put the event on a
list of signalled events and not immediately callevent->notify_function(), and handle the calling ofnotify_function()
in the lastEFI_EXIT()??Quoted 1 line
Maybe, I'll leave Heinrich to comment on that.
Quoted 9 lines
Let the application call WaitForEvent for a keyboard event. Rob suggests that neither timer events nor any other events are served
until the user possibly presses a key.No, we have to call notification functions immediately to serve time
critical communication like network traffic.Does WaitForEvent or anything else that dispatches events dispatch more than one event, or is it just one event and then return to UEFI world to poll again? We aren't really multi-threaded so there can't really be async callbacks.
Quoted 6 lines
Either way, I think we can make this work by changing EFI_EXIT()/callback/EFI_ENTER() to
EFI_CALLBACK(callback).. for the non-nestedEFI_ENTER()case we don't have to do anything special (and
the nested case probably should never happen in places where we needEFI_CALLBACK())WaitForEvent and CheckEvent calls will serve all
notify_functionsof timer events this includes anotify_functionchecking the keyboard and
in future I want to check the watchdog in anotify_function.Quoted 4 lines
Please, consider that in the notify functions any number of UEFI API functions will be called by the EFI application which themselves may signal events which in turn call
notify_functionsin which again UEFI API functions may be called.Quoted 2 lines
sure, one way or another I don't want to call a notifier from nested EFI_ENTER()'s..
Quoted 5 lines
We call
EFI_EXITbefore calling the notifier function and callEFI_ENTERafter returning form the notifier function.So currently we always switch gd correctly. An nested
EFI_ENTERsimply does not occur.yes, I understand how it currently works.. although I think an
EFI_CALLBACK()macro that did the equiv (with extra error checking if we allow re-entrantEFI_ENTER()) would be clearer. It would make the callbacks to UEFI world easy to spot and make the code a bit more concise.Quoted 9 lines
I still do not understand why you need to change anything here.
Quoted 4 lines
so either
EFI_CALLBACK()should detect the condition and yell loudly, or it should detect it and queue up callbacks until we are not nested..Quoted 8 lines
Your suggestions are getting more and more complicated.
I would always go for easily maintainable code and not for sophistication. Please, stick to the KISS principle.
If you want to call functions internally as you described in the first mail in this thread, do not call the UEFI functions but supply separate entry points.
The issue that I am trying to address at the moment is that
efi_load_image(), to load an image specified byfile_path(as opposed to already loaded intosource_buffer, ie. the source_buffer==NULL case, which UEFI spec allows) requires using a handful of APIs from the EFI file interface, and also requires the simple-file-system-protocol, to actually read the image specified byfile_pathinto a buffer.Quoted 9 lines
We could go down the path of continuing to add
_extfunctions.. but it is a bit ugly, and seems like it would keep growing worse. And it requires exposing functions from different modules which could otherwise remain static. All for a case that won't happen (for these particular APIs at least) or at least is easy to detect. Keeping the_extfunctions for only the special cases that could lead to a callback into UEFI world, and avoiding them in the normal case, seems cleaner. It isn't terribly complicated to implement, and it is easy to detect programming errors.Maybe we could turn all of this around and you just call
EFI_EXIT()before
calling all the callbacks? That way you're back in UEFI context and are free
to call anything that doesn't need gd.So something like
EFI_EXIT(); file_proto *f = bs->find_protocol(); file_foo *g = f->bar(); if (!g) return EFI_AMAZING_ERROR; ... EFI_ENTER();That way the fs loading code that really only deals with UEFI calls would be
self-contained. We do something similar already withefi_signal_event()today.
Quoted 6 lines
Quoted 2 lines
I guess that would mean no malloc/printf/etc.. seems like just *asking* for someone to screw up ;-)
Well, you have to choose a world to be in. You still have the EFI alloc and print methods ;).
sure, ofc.. but as long as we have to live with gd it is a good thing if the associated macros make it hard to inadvertently screw up ;-)
Quoted 36 lines
Quoted 26 lines
But I suppose we could do it at a finer granularity.. ie.
efi_load_image(...) { EFI_ENTER(..);if (!source_buffer) { UEFI(ret = fs->open_volume(fs, &f)); while (fp) { UEFI(ret = f->open(f, &f2, fp->str)); fp = efi_dp_next(fp); UEFI(ret = f->close(f)); f = f2; } UEFI(ret = f->getinfo(f, &efi_file_info_guid, &bs, info)); ... UEFI(ret = f->read(f, ...)); } ...}
Quoted 8 lines
And ofc, convert existing callbacks to use
UEFI()macro to make it it consistent in the code when things are going back to UEFI world.. ie. basically treat these just like callbacks.There is more malloc, etc (and when debugging,
printf()) in between this all, so I'm more a fan of a one-line macro rather than individual EFI_EXIT/EFI_ENTER. Plus it makes it harder to screw up early returns and that sorta thing.
Quoted 8 lines
Yup, that works too.
Quoted 2 lines
and I'm still all for adding some error checking to EFI_ENTER/EFI_EXIT/UEFI macros to debug misuse more easily.
Sure, but that's an orthogonal discussion :).
sorta, but not really.. but I'm a big fan of when these sort of things are designed with debugging checks in mind. That is something that the linux kernel does a really good job of (think of the various lockdep, list debug, etc, features).
There is nothing worse when tearing out your hair debugging some problem, when adding an innocent looking printf() in the wrong place makes things blow up in a different and even worse way ;-)
anyways, I'm getting from u-boot -> shim -> fallback -> shim -> grub now :-)
I'll re-work this patch and resend tomorrow.. if any better suggestions than UEFI() let me know.. maybe we should call it IFE() since the EFI* macros kinda do the opposite of what they are named :-P
BR,
-R