Commit graph

35 commits

Author SHA1 Message Date
Heinrich Schuchardt
72fa9cd59e efi_loader: create boot options without file path
Allow the efidebug command to create boot options without file path, e.g.

    efidebug boot add -b 0001 'short dev only' host 0:1 ''
    efidebug boot add -B 0002 'long dev only' host 0:1 ''

Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
2022-06-12 13:02:34 +02:00
Heinrich Schuchardt
178667b34b efi_loader: allow booting from short dev only DP
Allow booting from a short form device-path without file path, e.g.

    /HD(1,GPT,5ef79931-a1aa-4c70-9d67-611e8f69eafd,0x800,0x1000)

Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
2022-06-12 09:17:54 +02:00
AKASHI Takahiro
57ad624103 efi_loader: bootmgr: fix a problem in loading an image from a short-path
Booting from a short-form device path which starts with the first element
being a File Path Media Device Path failed because it doesn't contain
any valid device with simple file system protocol and efi_dp_find_obj()
in efi_load_image_from_path() will return NULL.
For instance,
/VenHw(e61d73b9-a384-4acc-aeab-82e828f3628b)/Scsi(0,0)/\helloworld.efi
-> shortened version: /\helloworld.efi

With this patch applied, all the media devices with simple file system
protocol are enumerated and the boot manager attempts to boot temporarily
generated device paths one-by-one.

This new implementation is still a bit incompatible with the UEFI
specification in terms of:
* not creating real boot options
* not try
  "If a device does not support the EFI_SIMPLE_FILE_SYSTEM_PROTOCOL, but
  supports the EFI_BLOCK_IO_PROTOCOL protocol, then the EFI Boot Service
  ConnectController must be called for this device with DriverImageHandle
  and RemainingDevicePath set to NULL and the Recursive flag is set to TRUE."
(See section 3.1.2 "Load Option Processing".)

But it still gives us a closer and better solution than the current.

Fixes: commit 9cdf470274 ("efi_loader: support booting via short-form device-path")
Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
Reviewed-by: Heinrich Schuchardt <heinrich.schuchardt@canonical.com>
2022-05-28 10:59:27 +02:00
AKASHI Takahiro
4e65ca00f3 efi_loader: bootmgr: add booting from removable media
Under the current implementation, booting from removable media using
a architecture-specific default image name, say BOOTAA64.EFI, is
supported only in distro_bootcmd script. See the commit 74522c898b
("efi_loader: Add distro boot script for removable media").

This is, however, half-baked implementation because
1) UEFI specification requires this feature to be implemented as part
   of Boot Manager's responsibility:

  3 - Boot Manager
  3.5.1 Boot via the Simple File Protocol
  When booting via the EFI_SIMPLE_FILE_SYSTEM_PROTOCOL, the FilePath will
  start with a device path that points to the device that implements the
  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL or the EFI_BLOCK_IO_PROTOCOL. The next
  part of the FilePath may point to the file name, including
  subdirectories, which contain the bootable image. If the file name is
  a null device path, the file name must be generated from the rules
  defined below.
  ...
  3.5.1.1 Removable Media Boot Behavior
  To generate a file name when none is present in the FilePath, the
  firmware must append a default file name in the form
  \EFI\BOOT\BOOT{machine type short-name}.EFI ...

2) So (1) entails the hehavior that the user's preference of boot media
   order should be determined by Boot#### and BootOrder variables.

With this patch, the semantics mentioned above is fully implemented.
For example, if you want to boot the system from USB and SCSI in this
order,
* define Boot0001 which contains only a device path to the USB device
  (without any file path/name)
* define Boot0002 which contains only a device path to the SCSI device,
and
* set BootOrder to Boot0001:Boot0002

To avoid build error for sandbox, default file name "BOOTSANDBOX.efi"
is defined even if it is out of scope of UEFI specification.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
Signed-off-by: Masahisa Kojima <masahisa.kojima@linaro.org>
On sandbox use binary name corresponding to host architecture.
Reviewed-by: Heinrich Schuchardt <heinrich.schuchardt@canonical.com>
2022-05-03 21:39:22 +02:00
Heinrich Schuchardt
4f419960bf efi_loader: simplify try_load_entry()
Use function efi_create_indexed_name() to create the BootXXXX variable
name.

Signed-off-by: Heinrich Schuchardt <heinrich.schuchardt@canonical.com>
2022-04-29 14:25:39 +02:00
Heinrich Schuchardt
7ea79e511d efi_loader: don't call log with __func__ as parameter
The log functions print file name, line number, and function name if
selected via the log command or customizing. Don't print the function
name twice.

Signed-off-by: Heinrich Schuchardt <heinrich.schuchardt@canonical.com>
2022-04-29 14:23:30 +02:00
Simon Glass
156ccbc3c4 efi: Use 16-bit unicode strings
At present we use wide characters for unicode but this is not necessary.
Change the code to use the 'u' literal instead. This helps to fix build
warnings for sandbox on rpi.

Signed-off-by: Simon Glass <sjg@chromium.org>
Suggested-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
Reviewed-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
2022-02-03 12:16:01 -05:00
Ilias Apalodimas
f4dc1bc9f0 efi_loader: Cleanup get_var duplication
get_var() is defined statically in efi_bootmgr.c and doesn't properly
check a buffer allocation.  Remove it completely and use the exported
function from efi_var_common.c that does the same thing

Signed-off-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
2021-04-10 12:00:24 +02:00
Ilias Apalodimas
53f6a5aa86 efi_loader: Replace config option for initrd loading
Up to now we install EFI_LOAD_FILE2_PROTOCOL to load an initrd
unconditionally. Although we correctly return various EFI exit codes
depending on the file status (i.e EFI_NO_MEDIA, EFI_NOT_FOUND etc), the
kernel loader, only falls back to the cmdline interpreted initrd if the
protocol is not installed.

This creates a problem for EFI installers, since they won't be able to
load their own initrd and continue the installation. It also makes the
feature hard to use, since we can either have a single initrd or we have
to recompile u-boot if the filename changes.

So let's introduce a different logic that will decouple the initrd
path from the config option we currently have.
When defining a UEFI BootXXXX we can use the filepathlist and store
a file path pointing to our initrd. Specifically the EFI spec describes:

"The first element of the array is a device path that describes the device
and location of the Image for this load option. Other device paths may
optionally exist in the FilePathList, but their usage is OSV specific"

When the EFI application is launched through the bootmgr, we'll try to
interpret the extra device path. If that points to a file that exists on
our disk, we'll now install the load_file2 and the efi-stub will be able
to use it.

This opens up another path using U-Boot and defines a new boot flow.
A user will be able to control the kernel/initrd pairs without explicit
cmdline args or GRUB.

Signed-off-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Reviewed-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
2021-03-25 20:14:26 +01:00
Heinrich Schuchardt
2363effb7a efi_loader: move load options to new module
Move all load options related functions to a new module. So that they can
be compiled independently.

Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
2021-01-19 18:56:08 +01:00
Heinrich Schuchardt
e434311dba efi_loader: avoid invalid free
load_options passed from do_efibootmgr() to do_bootefi_exec() may contain
invalid data from the stack which will lead to an invalid free().

Fixes: 0ad64007fe ("efi_loader: set load options in boot manager")
Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
2020-12-29 02:09:04 +01:00
Heinrich Schuchardt
15d8f008dc efi_loader: validate device path length in boot manager
Bootxxxx variables are provided by the user and therefore cannot be
trusted. We have to validate them before usage.

A device path provided by a Bootxxxx variable must have an end node within
the indicated device path length.

Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
2020-08-24 16:37:53 +02:00
Heinrich Schuchardt
0ad64007fe efi_loader: set load options in boot manager
Up to now we used the value of the bootargs environment variable as load
options in the boot manager. This is not correct. The data has to be taken
from the Boot#### variable.

Let the boot manager copy the optional data of the EFI_LOAD_OPTION as load
options to the loaded image protocol.

Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
2020-08-08 19:03:24 +02:00
Heinrich Schuchardt
1064d04920 efi_loader: factor out efi_set_load_options()
The bootefi bootmgr command has to set the load options for a loaded image
from the value of BootXXXX variable. If the boot manager is not used, the
value is set from the environment variable bootargs (or efi_selftest).

Factor out a common function efi_set_load_options().

Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
2020-08-08 19:03:24 +02:00
Heinrich Schuchardt
dda8c7163a efi_loader: simplify boot manager
Simplify the implementation of the UEFI boot manager:

* avoid EFI_CALL for SetVariable() and GetVariable()
* remove unnecessary type conversions

Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
2020-07-11 23:14:17 +02:00
Heinrich Schuchardt
7a373e5435 efi_loader: use log function in boot manager
When booting via the boot manager use log function for user messages
instead of printf() and debug().

Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
2020-07-03 18:03:47 +02:00
Heinrich Schuchardt
0e69bcfb27 efi_loader: validate load option
For passing the optional data of the load option to the loaded imaged
protocol we need its size.

efi_deserialize_load_option() is changed to return the size of the optional
data.

As a by-product we get a partial validation of the load option.
Checking the length of the device path remains to be implemented.

Some Coverity defects identified the load options as user input because
get_unaligned_le32() and get_unaligned_le16() is called. But non of these
Coverity defects can be resolved without marking functions with Coverity
specific tags.

Reported-by: Coverity (CID 303760)
Reported-by: Coverity (CID 303768)
Reported-by: Coverity (CID 303776)
Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
2020-06-03 17:19:17 +02:00
Simon Glass
f7ae49fc4f common: Drop log.h from common header
Move this header out of the common header.

Signed-off-by: Simon Glass <sjg@chromium.org>
2020-05-18 21:19:18 -04:00
Heinrich Schuchardt
15621aa2cb efi_loader: function comments efi_bootmgr.c
Convert function descriptions to Sphinx style.

Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
2019-07-16 22:17:20 +00:00
AKASHI Takahiro
366161cf97 efi_loader: bootmgr: make BootNext non-volatile
Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
Reviewed-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
2019-06-04 23:56:14 +02:00
AKASHI Takahiro
94e6e55053 efi_loader: bootmgr: print a message when loading from BootNext failed
If a user defines BootNext but not BootOrder and loading from BootNext
fails, you will see only a message like this:
	BootOrder not defined

This may confuse a user. Adding an error message will be helpful.

An example output looks like this:

=> efidebug boot add 0001 label1 scsi 0:1 "\path1\file1.efi" "--option foo"
=> efidebug boot add 0002 label2 scsi 0:1 "\path2\file2.efi" "--option bar"
=> efidebug boot add 0003 label3 scsi 0:1 "\path3\file3.efi" "--option no"
=> efidebug boot order 0001 0002
=> efidebug boot next 0003
=> bootefi bootmgr
Loading from Boot0003 'label3' failed
Loading from BootNext failed, falling back to BootOrder
Loading from Boot0001 'label1' failed
Loading from Boot0002 'label2' failed
EFI boot manager: Cannot load any image

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
Adjust messages.
Reviewed-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
2019-06-04 22:09:26 +02:00
Heinrich Schuchardt
39a1ff8cea efi_loader: optional data in load options are binary
The field boot OptionalData in structure _EFI_LOAD_OPTIONS is for binary
data.

When we use `efidebug boot add` we should convert the 5th argument from
UTF-8 to UTF-16 before putting it into the BootXXXX variable.

When printing boot variables with `efidebug boot dump` we should support
the OptionalData being arbitrary binary data. So let's dump the data as
hexadecimal values.

Here is an example session protocol:

=> efidebug boot add 00a1 label1 scsi 0:1 doit1 'my option'
=> efidebug boot add 00a2 label2 scsi 0:1 doit2
=> efidebug boot dump
Boot00A0:
  attributes: A-- (0x00000001)
  label: label1
  file_path: .../HD(1,MBR,0xeac4e18b,0x800,0x3fffe)/doit1
  data:
    00000000: 6d 00 79 00 20 00 6f 00 70 00 74 00 69 00 6f 00  m.y. .o.p.t.i.o.
    00000010: 6e 00 00 00                                      n...
Boot00A1:
  attributes: A-- (0x00000001)
  label: label2
  file_path: .../HD(1,MBR,0xeac4e18b,0x800,0x3fffe)/doit2
  data:

Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
2019-05-02 18:17:50 +02:00
AKASHI Takahiro
6b95b38c41 efi_loader: rework bootmgr/bootefi using load_image API
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>
2019-04-23 00:37:28 +02:00
AKASHI Takahiro
37279ad3ee efi_loader: bootmgr: support BootNext and BootCurrent variable behavior
See UEFI v2.7, section 3.1.2 for details of the specification.

With efidebug command, you can run any EFI boot option as follows:
  => efi boot add 1 SHELL ...
  => efi boot add 2 HELLO ...
  => efi boot order 1 2
  => efi bootmgr
     (starting SHELL ...)

  => efi boot next 2
  => efi bootmgr
     (starting HELLO ...)
  => env print -e
  <snip ...>
  BootCurrent: {boot,run}(blob)
  00000000:  02 00                    ..
  BootOrder: {boot,run}(blob)
  00000000:  01 00 02 00              ....

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
Reviewed-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
2019-04-07 14:17:06 +02:00
AKASHI Takahiro
454568b4f0 efi_loader: define load option attributes
See UEFI specification v2.7a, section 3.1.3, "Load Option Processing."

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
Reviewed-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
2019-02-25 12:47:13 +01:00
Heinrich Schuchardt
ccecc3456a efi_loader: fix entry count in bootmgr
Since commit 914df75b0c ("efi_loader: fix EFI entry counting")
entry_count is already set to 1 before efi_bootmgr_load() is called. So we
should not increment it when entering the function.

Without the patch an assert error occurs in efi_get_variable() if DEBUG is
defined.

Fixes: 914df75b0c ("efi_loader: fix EFI entry counting")
Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
2019-02-25 12:39:48 +01:00
Heinrich Schuchardt
33e44971a2 efi_loader: error message if BootOrder not defined
For booting via `bootefi bootmgr` it is necessary that the EFI variable
BootOrder is defined. Provide a diagnostic message if the variable is
missing.

Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
2019-02-25 12:39:47 +01:00
Heinrich Schuchardt
0e18f584de efi_loader: LoadImage: always allocate new pages
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>
2019-02-16 15:42:20 +01:00
AKASHI Takahiro
1a82b3413c efi_loader: bootmgr: add load option helper functions
In this patch, helper functions for an load option variable (BootXXXX)
are added:
* efi_deserialize_load_option(): parse a string into load_option data
			(renamed from parse_load_option and exported)
* efi_serialize_load_option(): convert load_option data into a string

Those functions will be used to implement efishell command.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
Signed-off-by: Alexander Graf <agraf@suse.de>
2018-12-03 00:17:45 +01:00
Heinrich Schuchardt
e1fec152fe efi_loader: fix typos
Fix typos in EFI subsystem comments.

Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
Signed-off-by: Alexander Graf <agraf@suse.de>
2018-12-02 21:59:37 +01:00
Heinrich Schuchardt
1dde0d57a5 efi_loader: rename utf16_strlen, utf16_strnlen
The function names utf16_strlen() and utf16_strnlen() are misnomers.
The functions do not count utf-16 characters but non-zero words.
So let's rename them to u16_strlen and u16_strnlen().

In utf16_dup() avoid assignment in if clause.

Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
Signed-off-by: Alexander Graf <agraf@suse.de>
2018-09-23 21:55:29 +02:00
Heinrich Schuchardt
45c66f9cdf efi_loader: adjust definitions of variable services
The definitons of the variable services are adjusted:
- use efi_uintn_t instead of unsigned long
- use u16 * instead of s16 * for Unicode strings
- correct definition of QueryVariableInfo
- rename efi_get_next_variable to efi_get_next_variable_name

Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
Signed-off-by: Alexander Graf <agraf@suse.de>
2018-06-03 15:27:20 +02:00
Tom Rini
f739fcd831 SPDX: Convert a few files that were missed before
As part of the main conversion a few files were missed.  These files had
additional whitespace after the '*' and before the SPDX tag and my
previous regex was too strict.  This time I did a grep for all SPDX tags
and then filtered out anything that matched the correct styles.

Fixes: 83d290c56f ("SPDX: Convert all of our single license tags to Linux Kernel style")
Reported-by: Heinrich Schuchardt <xypron.debian@gmx.de>
Signed-off-by: Tom Rini <trini@konsulko.com>
2018-05-10 20:38:35 -04:00
Heinrich Schuchardt
4a8b5e7900 efi_loader: consistently use %pD to print device paths
Now that we have %pD support in vsprintf we should avoid separate
logic for printing device paths in other places.

Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
Signed-off-by: Alexander Graf <agraf@suse.de>
2018-01-28 21:37:13 +01:00
Rob Clark
9975fe96b6 efi_loader: add bootmgr
Similar to a "real" UEFI implementation, the bootmgr looks at the
BootOrder and BootXXXX variables to try to find an EFI payload to load
and boot.  This is added as a sub-command of bootefi.

The idea is that the distro bootcmd would first try loading a payload
via the bootmgr, and then if that fails (ie. first boot or corrupted
EFI variables) it would fallback to loading bootaa64.efi.  (Which
would then load fallback.efi which would look for \EFI\*\boot.csv and
populate BootOrder and BootXXXX based on what it found.)

Signed-off-by: Rob Clark <robdclark@gmail.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
2017-09-20 11:08:01 +02:00