fastboot: introduce 'oem board' subcommand

Currently, fastboot protocol in U-Boot has no opportunity
to execute vendor custom code with verifed boot. This patch
introduce new fastboot subcommand fastboot oem board:<cmd>,
which allow to run custom oem_board function.

Default implementation is __weak. Vendor must redefine it in
board/ folder with his own logic.

For example, some vendors have their custom nand/emmc partition
flashing or erasing. Here some typical command for such use cases:

- flashing:

  $ fastboot stage bootloader.img
  $ fastboot oem board:write_bootloader

- erasing:

  $ fastboot oem board:erase_env

Signed-off-by: Alexey Romanov <avromanov@salutedevices.com>
Reviewed-by: Mattijs Korpershoek <mkorpershoek@baylibre.com>
Reviewed-by: Quentin Schulz <quentin.schulz@theobroma-systems.com>
Link: https://lore.kernel.org/r/20240418100129.1691822-2-avromanov@salutedevices.com
Signed-off-by: Mattijs Korpershoek <mkorpershoek@baylibre.com>
This commit is contained in:
Alexey Romanov 2024-04-18 13:01:29 +03:00 committed by Mattijs Korpershoek
parent 2c3fa4b8ad
commit b2acf59baf
4 changed files with 56 additions and 0 deletions

View file

@ -30,6 +30,7 @@ The following OEM commands are supported (if enabled):
- ``oem bootbus`` - this executes ``mmc bootbus %x %s`` to configure eMMC - ``oem bootbus`` - this executes ``mmc bootbus %x %s`` to configure eMMC
- ``oem run`` - this executes an arbitrary U-Boot command - ``oem run`` - this executes an arbitrary U-Boot command
- ``oem console`` - this dumps U-Boot console record buffer - ``oem console`` - this dumps U-Boot console record buffer
- ``oem board`` - this executes a custom board function which is defined by the vendor
Support for both eMMC and NAND devices is included. Support for both eMMC and NAND devices is included.
@ -247,6 +248,23 @@ including multiple commands (using e.g. ``;`` or ``&&``) and control structures
(``if``, ``while``, etc.). The exit code of ``fastboot`` will reflect the exit (``if``, ``while``, etc.). The exit code of ``fastboot`` will reflect the exit
code of the command you ran. code of the command you ran.
Running Custom Vendor Code
^^^^^^^^^^^^^^^^^^^^^^^^^^
U-Boot allows you to execute custom fastboot logic, which can be defined
in board/ files. It can still be used for production devices with verified
boot, because the vendor defines logic at compile time by implementing
fastboot_oem_board() function. The attacker will not be able to execute
custom commands / code. For example, this can be useful for custom flashing
or erasing protocols::
$ fastboot stage bootloader.img
$ fastboot oem board:write_bootloader
In this case, ``cmd_parameter`` argument of the function ``fastboot_oem_board()``
will contain string "write_bootloader" and ``data`` argument is a pointer to
fastboot input buffer, which contains the contents of bootloader.img file.
References References
---------- ----------

View file

@ -252,6 +252,13 @@ config FASTBOOT_CMD_OEM_CONSOLE
Add support for the "oem console" command to input and read console Add support for the "oem console" command to input and read console
record buffer. record buffer.
config FASTBOOT_OEM_BOARD
bool "Enable the 'oem board' command"
help
This extends the fastboot protocol with an "oem board" command. This
command allows running vendor custom code defined in board/ files.
Otherwise, it will do nothing and send fastboot fail.
endif # FASTBOOT endif # FASTBOOT
endmenu endmenu

View file

@ -43,6 +43,7 @@ static void oem_format(char *, char *);
static void oem_partconf(char *, char *); static void oem_partconf(char *, char *);
static void oem_bootbus(char *, char *); static void oem_bootbus(char *, char *);
static void oem_console(char *, char *); static void oem_console(char *, char *);
static void oem_board(char *, char *);
static void run_ucmd(char *, char *); static void run_ucmd(char *, char *);
static void run_acmd(char *, char *); static void run_acmd(char *, char *);
@ -114,6 +115,10 @@ static const struct {
.command = "oem console", .command = "oem console",
.dispatch = CONFIG_IS_ENABLED(FASTBOOT_CMD_OEM_CONSOLE, (oem_console), (NULL)) .dispatch = CONFIG_IS_ENABLED(FASTBOOT_CMD_OEM_CONSOLE, (oem_console), (NULL))
}, },
[FASTBOOT_COMMAND_OEM_BOARD] = {
.command = "oem board",
.dispatch = CONFIG_IS_ENABLED(FASTBOOT_OEM_BOARD, (oem_board), (NULL))
},
[FASTBOOT_COMMAND_UCMD] = { [FASTBOOT_COMMAND_UCMD] = {
.command = "UCmd", .command = "UCmd",
.dispatch = CONFIG_IS_ENABLED(FASTBOOT_UUU_SUPPORT, (run_ucmd), (NULL)) .dispatch = CONFIG_IS_ENABLED(FASTBOOT_UUU_SUPPORT, (run_ucmd), (NULL))
@ -549,3 +554,28 @@ static void __maybe_unused oem_console(char *cmd_parameter, char *response)
else else
fastboot_response(FASTBOOT_MULTIRESPONSE_START, response, NULL); fastboot_response(FASTBOOT_MULTIRESPONSE_START, response, NULL);
} }
/**
* fastboot_oem_board() - Execute the OEM board command. This is default
* weak implementation, which may be overwritten in board/ files.
*
* @cmd_parameter: Pointer to command parameter
* @data: Pointer to fastboot input buffer
* @size: Size of the fastboot input buffer
* @response: Pointer to fastboot response buffer
*/
void __weak fastboot_oem_board(char *cmd_parameter, void *data, u32 size, char *response)
{
fastboot_fail("oem board function not defined", response);
}
/**
* oem_board() - Execute the OEM board command
*
* @cmd_parameter: Pointer to command parameter
* @response: Pointer to fastboot response buffer
*/
static void __maybe_unused oem_board(char *cmd_parameter, char *response)
{
fastboot_oem_board(cmd_parameter, (void *)fastboot_buf_addr, image_size, response);
}

View file

@ -48,6 +48,7 @@ enum {
FASTBOOT_COMMAND_OEM_BOOTBUS, FASTBOOT_COMMAND_OEM_BOOTBUS,
FASTBOOT_COMMAND_OEM_RUN, FASTBOOT_COMMAND_OEM_RUN,
FASTBOOT_COMMAND_OEM_CONSOLE, FASTBOOT_COMMAND_OEM_CONSOLE,
FASTBOOT_COMMAND_OEM_BOARD,
FASTBOOT_COMMAND_ACMD, FASTBOOT_COMMAND_ACMD,
FASTBOOT_COMMAND_UCMD, FASTBOOT_COMMAND_UCMD,
FASTBOOT_COMMAND_COUNT FASTBOOT_COMMAND_COUNT