CloseProtocol() must delete all open protocol information records relating
to import parameters not only one.
Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
When a protocol is opened the open protocol information must be updated.
The key fields of the open protocol information records are ImageHandle,
ControllerHandle, and Attributes.
Consider the Attributes field when determining if an open protocol
information record has to be updated or a new one has to be created.
Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
The UEFI specification requires that when a protocol is opened via
HandleProtocol() the agent handle is the image handle of the EFI firmware
(see chapter on EFI_BOOT_SERVICES.OpenProtocol()).
Let efi_handle_protocol() pass efi_root as agent handle to
efi_open_protocol().
Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
When uninstalling a protocol the following steps are needed:
* request all drivers to disconnect
* close protocol for all non-drivers
* check if any open instance of the protocol exists on the handle and
return EFI_ACCESS_DENIED in this case
* remove the protocol interface
By tort we tested for remaining open protocol instances already after
requesting drivers to disconnect.
With this correction the UEFI SCT II tests for UninstallProtocolInterface()
and ReinstallProtocolInterface are passed.
Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
When trying to open a protocol exclusively attached drivers have to be
removed. This removes entries in the open protocol information linked list
over which we are looping. As additionally child controllers may have been
removed the only safe thing to do is to restart the loop over the linked
list when a driver is removed.
By observing the return code of DisconnectController() we can eliminate a
loop.
Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
In LocateProtocol() implement searching by the registration key returned by
RegisterNotifyProtocol().
Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
The code to check if a registration key is a valid key returned by
RegisterProtocolNotify() can be reused. So let us factor it out into a new
function efi_check_register_notify_event().
Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
When a protocol is installed the handle should be queued for the
registration key of each registered event. LocateHandle() should return the
first handle from the queue for the registration key and delete it from the
queue.
Implement the queueing.
Correct the selftest.
With the patch the UEFI SCT tests for LocateHandle() are passed without
failure.
Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
Since commit 226cddbe32 ("efi_loader: check device path in
InstallMultipleProtocolInterfaces") iPXE fails to access the network.
LocateDevicePath() returns EFI_SUCCESS even if a shorter path is found as a
partial match. It returns the remaining path. So to be sure that we found a
complete match we need to check that the remaining path refers to an end
node.
Provide debug output if a device path has already been installed.
Fixes: 226cddbe32 ("efi_loader: check device path in
InstallMultipleProtocolInterfaces")
Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
Do not write to address indicated by NULL pointer.
UEFI SCT II 2.6 (2017), 3.6.5 GetNextMonotonicCount(), 5.1.5.5.1
Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
Not checking the parameters may lead reading or writing from NULL.
Implement the parameter checks prescribed in the UEFI spec.
Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
According to the UEFI spec InstallMultipleProtocolInterfaces() must check
if a device path has already been installed. In this case it must return
EFI_ALREADY_STARTED.
Cf. UEFI SCT II 2.6 A (2017),
3.3.16 InstallMultipleProtocolInterfaces(), 5.1.3.16.1.
Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
UEFI SCT uses this call sequence to determine the current TPL level inside
notification functions:
OldTpl = BS->RaiseTPL(TPL_HIGH_LEVEL);
BS->RestoreTPL(OldTpl);
In RestoreTPL() we trigger the notification function of queued events. If
we do not mark the event as non-queued before calling the notification
function, this results in an infinite recursive call sequence.
Mark the event as non-queued before entering the notification function.
Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
According to the UEFI specification UninstallProtocolInteface() has to
return EFI_NOT_FOUND if the interface is not found.
Correct the return value.
Cf. UEFI SCT II spec (2017), 3.3.2 UninstallProtocolInterface(), 5.1.3.2.4
Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
A parameter check in LocateDevicePath() does not match the requirements of
the UEFI spec.
If device is NULL, only return EFI_INVALID_PARAMETER if a matching handle
is found.
Cf. UEFI SCT II specification (2017)3.3.7 LocateDevicePath(), 5.1.3.7.3
Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
Consistently use efi_uintn_t as type of memory keys.
Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
Reviewed-by: Alexander Graf <graf@amazon.com>
If the size of the source buffer is 0, return EFI_LOAD_ERROR.
(UEFI SCT II 2017: 3.4.1 LoadImage() - 5.1.4.1.6)
Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
If the parent image handle does not refer to a loaded image return
EFI_INVALID_PARAMETER.
(UEFI SCT II 2017: 3.4.1 LoadImage() - 5.1.4.1.1)
Mark our root node as a loaded image to avoid an error when using it as
parent image.
Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
HandleProtocol() and OpenProtocol() have to return EFI_UNSUPPORTED if the
protocol is not installed on the handle.
Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
For correct indentation of messages in the UEFI API implementation use
EFI_PRINT() instead of debug().
Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
Return EFI_INVALID_PARAMETER from CloseProtcol() if the agent handle is not
valid.
Return EFI_INVALID_PARAMETER if the optional controller handle is not
valid.
Return immediately from efi_search_obj if the handle is NULL.
Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
The RegisterProtocolNotify() boot service registers an event to be
notified upon the installation of a protocol interface with the
specified GUID.
Add the missing implementation.
Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
The notification function of events of type EVT_NOTIFY_SIGNAL should always
be queued when SignalEvent() is called.
Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
Implement unloading of images in the Exit() boot services:
* unload images that are not yet started,
* unload started applications,
* unload drivers returning an error.
Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
In UnloadImage() we need to know if an image is already started.
Add a field to the handle structure identifying loaded and started images.
Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
If LocateHandle() does not find an entry EFI_NOT_FOUND has to be returned
even if BufferSize is NULL.
Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
CreateEventEx() does not allow the following event types:
* EVT_SIGNAL_EXIT_BOOT_SERVICES
* EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE
This check is needed to pass the UEFI SCT conformance test.
Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
Reviewed-by: Alexander Graf <agraf@csgraf.de>
In case of a failure exit data may be passed to Exit() which in turn is
returned by StartImage().
Let the `bootefi` command print the exit data string in case of an error.
Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
CreateEvent() and CreateEventEx() should check that a notify function is
provided for either of EVT_NOTIFY_SIGNAL or EVT_NOTIFY_WAIT.
Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
In the current implementation, bootefi command and EFI boot manager
don't use load_image API, instead, use more primitive and internal
functions. This will introduce duplicated code and potentially
unknown bugs as well as inconsistent behaviours.
With this patch, do_efibootmgr() and do_boot_efi() are completely
overhauled and re-implemented using load_image API.
Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
Use efi_root as parent handle for the loaded image.
LoadImage() should be called with BootPolicy = true by the boot manager.
Avoid duplicate free_pool().
Eliminate variable memdp which is not needed after anymore due to
"efi_loader: correctly split device path of loaded image".
Reviewed-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
When the LoadImage() service is called for an image that is already loaded
to memory the file path may be NULL or it will contain both a device path
as well as a media path. We should not assume that there is no media path.
Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
Export function efi_install_multiple_protocol_interfaces() so that we can
call it in others parts of the UEFI subsystem.
Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
We should not install the HII protocols on every loaded image. It is
sufficient to install them once on the root node.
Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
Those two functions will be used later to re-implement do_bootefi_exec().
Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
Reviewed-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
To meet UEFI spec v2.7a section 9.2, we should add
EFI_LOADED_IMAGE_DEVICE_PATH_PROTOCOL to image handle,
instead of EFI_DEVICE_PATH_PROTOCOL.
Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
Reviewed-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
Add parameter checks in the StartImage() and Exit() boottime services:
- check that the image handle is valid and has the loaded image protocol
installed
- in StartImage() record the current image
- in Exit() check that the image is the current image
Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
Commit 0e18f584de ("efi_loader: LoadImage: always allocate new pages")
ensured that whether we load an image from file or from memory we end up
with the same number of newly allocated buffers. But essentially we ended
up with one buffer too many in both cases:
efi_load_pe() copies and rebases the UEFI image.
We do not need the buffer with the file contents afterwards.
Fixes: 0e18f584de ("efi_loader: LoadImage: always allocate new pages")
Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
It does not make any sense to check if a pointer is NULL if we have
dereferenced it before.
Reported-by: Coverity (CID 185827)
Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
`bootefi selftest` fails on qemu-x86_defconfig if efi_selftest() is not
invoked using EFI_CALL().
Likewise we call the entry point of EFI payloads with
EFI_CALL(efi_start_image()).
entry_count indicates if we are in U-Boot (1) or in EFI payload code (0).
As we start in U-Boot code the initial value has to be 1.
Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
Remove the duplicate code in efi_do_enter() and use efi_start_image() to
start the image invoked by the bootefi command.
Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
Up to now efi_load_pe() returns the entry point or NULL in case of an
error. This does not allow to return correct error codes from LoadImage().
Let efi_load_pe() return a status code and fill in the entry point in the
corresponding field of the image object.
Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
If we want to properly unload images in Exit() the memory should always be
allocated in the same way. As we allocate memory when reading from file we
should do the same when the original image is in memory.
A further patch will be needed to free the memory when Exit() is called.
Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
In case of an error we should set the returned pointers to NULL. This
ensures that an illegal free does not occur even if the caller calls
free() for the handles.
If protocols cannot be installed, release all resources.
Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>