u-boot.lists.denx.de archive mirror
 help / color / mirror / Atom feed
* [PATCH v4 0/5] Add fastboot to SPL
@ 2026-08-20 18:08 Carlo Caione
  2026-08-20 18:08 ` [PATCH v4 1/5] fastboot: factor out the USB session runner Carlo Caione
                   ` (5 more replies)
  0 siblings, 6 replies; 14+ messages in thread
From: Carlo Caione @ 2026-08-20 18:08 UTC (permalink / raw)
  To: u-boot, GSS_MTK_Uboot_upstream
  Cc: Suhrid Subramaniam, Macpaul Lin (林智斌),
	Pablo Sun (孫毓翔), Arnaud Ferraris,
	Mattijs Korpershoek, Tom Rini, Simon Glass, Sam Day,
	Quentin Schulz, Carlo Caione, David Lechner, Vitor Sato Eschholz,
	Lukasz Majewski, Marek Vasut, Peng Fan, Jaehoon Chung,
	Neil Armstrong, Julien Masson, Alexey Charkov, Adrian Freihofer,
	Francois Berder, Ilias Apalodimas, Marek Vasut, Vincent Jardin,
	Peter Robinson

Some recovery and initial-provisioning flows need a standard host protocol
before usable firmware is available in persistent storage. U-Boot already
provides fastboot, but the implementation can currently be started only
from the U-Boot-proper command line.

This series makes USB fastboot available as an opt-in SPL service,
including MMC partition flashing and Android sparse images. The interface
is kept deliberately narrower in SPL: it does not support the boot command
or filesystem probing, and reboot support remains platform-dependent.

The first four patches separate the generic preparation from SPL
enablement. They factor out the USB session runner, route USB reboot
through the common handler, make shared fastboot configuration phase-aware,
and add phase-aware sparse-image support. The final patch then contains the
SPL-specific Kconfig, gadget behavior, and documentation.

No fastboot code or supporting library is added to SPL when SPL_FASTBOOT is
disabled, so the feature has no size cost for existing SPL builds.

---
Changes in v4:
- Drop RFC status.
- Make the USB fastboot helper and gadget build rules phase-aware.
- Use a separate command table for the SPL-supported command subset.
- Document the commands available in SPL.
- Apply the requested Makefile, annotation and preprocessor cleanups.
- Link to v3: https://patch.msgid.link/20260731-ccaione-upstream-spl-fastboot-v3-0-dbea3ff4529e@baylibre.com

Changes in v3:
- Rename the USB session helper to fastboot_usb_run().
- Initialize UDP and TCP sessions in their transport helpers.
- Remove a redundant USB session return assignment.
- Collect the Reviewed-by tag.
- Link to v2: https://patch.msgid.link/20260722-ccaione-upstream-spl-fastboot-v2-0-2ba3f71c42bc@baylibre.com

Changes in v2:
- Split the common USB session runner into a prerequisite patch.
- Route USB reboot through the common fastboot handler separately.
- Split phase-aware fastboot configuration and build rules.
- Split phase-aware Android sparse-image support.
- Keep SPL-specific behavior in the final patch.
- No functional change from v1.
- Link to v1: https://patch.msgid.link/20260719-ccaione-upstream-spl-fastboot-v1-1-c9bab5b0ba72@baylibre.com

---
Carlo Caione (5):
      fastboot: factor out the USB session runner
      fastboot: use the common handler for USB reboot
      fastboot: make shared configuration checks phase-aware
      image: sparse: add phase-aware SPL support
      fastboot: add SPL support

 cmd/fastboot.c                  | 53 +++-------------------
 doc/android/fastboot.rst        | 31 +++++++++++++
 drivers/Makefile                |  2 +-
 drivers/fastboot/Kconfig        | 92 +++++++++++++++++++++++++++++++++++++-
 drivers/fastboot/Makefile       |  9 ++--
 drivers/fastboot/fb_block.c     |  9 ++--
 drivers/fastboot/fb_command.c   | 97 ++++++++++++++++++++++++++++++++---------
 drivers/fastboot/fb_common.c    | 23 +++++++++-
 drivers/fastboot/fb_getvar.c    | 19 +++++---
 drivers/fastboot/fb_mmc.c       | 36 +++++++--------
 drivers/fastboot/fb_usb.c       | 66 ++++++++++++++++++++++++++++
 drivers/usb/gadget/Makefile     |  2 +-
 drivers/usb/gadget/f_fastboot.c |  6 ++-
 include/fastboot.h              | 10 +++++
 lib/Kconfig                     | 11 +++++
 lib/Makefile                    |  3 +-
 lib/image-sparse.c              |  2 +-
 17 files changed, 360 insertions(+), 111 deletions(-)
---
base-commit: 527115ef6783cec49e5610c523c124b399011361
change-id: 20260718-ccaione-upstream-spl-fastboot-14fa2b6b2b64

Best regards,
--  
Carlo Caione <ccaione@baylibre.com>


^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH v4 1/5] fastboot: factor out the USB session runner
  2026-08-20 18:08 [PATCH v4 0/5] Add fastboot to SPL Carlo Caione
@ 2026-08-20 18:08 ` Carlo Caione
  2026-08-20 18:08 ` [PATCH v4 2/5] fastboot: use the common handler for USB reboot Carlo Caione
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 14+ messages in thread
From: Carlo Caione @ 2026-08-20 18:08 UTC (permalink / raw)
  To: u-boot, GSS_MTK_Uboot_upstream
  Cc: Suhrid Subramaniam, Macpaul Lin (林智斌),
	Pablo Sun (孫毓翔), Arnaud Ferraris,
	Mattijs Korpershoek, Tom Rini, Simon Glass, Sam Day,
	Quentin Schulz, Carlo Caione, David Lechner, Vitor Sato Eschholz,
	Lukasz Majewski, Marek Vasut, Peng Fan, Jaehoon Chung,
	Neil Armstrong, Julien Masson, Alexey Charkov, Adrian Freihofer,
	Francois Berder, Ilias Apalodimas, Marek Vasut, Vincent Jardin,
	Peter Robinson

The fastboot command currently owns USB gadget setup, protocol
initialization, the service loop and teardown. This prevents callers
which do not use the command line from starting USB fastboot without
duplicating the same session lifecycle.

Move that lifecycle into fastboot_usb_run() and leave cmd/fastboot.c
responsible only for argument parsing and transport selection.
Initialize network sessions in their transport path so their existing
behavior is preserved.

Signed-off-by: Julien Masson <jmasson@baylibre.com>
Signed-off-by: Vitor Sato Eschholz <vsatoes@baylibre.com>
Reviewed-by: Mattijs Korpershoek <mkorpershoek@kernel.org>
Signed-off-by: Carlo Caione <ccaione@baylibre.com>
---
 cmd/fastboot.c            | 53 ++++-----------------------------------
 drivers/fastboot/Makefile |  1 +
 drivers/fastboot/fb_usb.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++
 include/fastboot.h        | 10 ++++++++
 4 files changed, 79 insertions(+), 48 deletions(-)

diff --git a/cmd/fastboot.c b/cmd/fastboot.c
index f3929f88dfa..ace877b6e28 100644
--- a/cmd/fastboot.c
+++ b/cmd/fastboot.c
@@ -7,12 +7,9 @@
  * Rob Herring <robh@kernel.org>
  */
 #include <command.h>
-#include <console.h>
-#include <g_dnl.h>
 #include <fastboot.h>
 #include <net.h>
-#include <usb.h>
-#include <watchdog.h>
+#include <vsprintf.h>
 #include <linux/printk.h>
 #include <linux/stringify.h>
 
@@ -27,6 +24,7 @@ static int do_fastboot_udp(int argc, char *const argv[],
 		return CMD_RET_FAILURE;
 	}
 
+	fastboot_init((void *)buf_addr, buf_size);
 	err = net_loop(FASTBOOT_UDP);
 
 	if (err < 0) {
@@ -47,6 +45,7 @@ static int do_fastboot_tcp(int argc, char *const argv[],
 		return CMD_RET_FAILURE;
 	}
 
+	fastboot_init((void *)buf_addr, buf_size);
 	err = net_loop(FASTBOOT_TCP);
 
 	if (err < 0) {
@@ -63,7 +62,6 @@ static int do_fastboot_usb(int argc, char *const argv[],
 {
 	int controller_index;
 	char *usb_controller;
-	struct udevice *udc;
 	char *endp;
 	int ret;
 
@@ -82,48 +80,9 @@ static int do_fastboot_usb(int argc, char *const argv[],
 		return CMD_RET_FAILURE;
 	}
 
-	ret = udc_device_get_by_index(controller_index, &udc);
-	if (ret) {
-		pr_err("USB init failed: %d\n", ret);
-		return CMD_RET_FAILURE;
-	}
-
-	g_dnl_clear_detach();
-	ret = g_dnl_register("usb_dnl_fastboot");
-	if (ret)
-		return ret;
-
-	if (!g_dnl_board_usb_cable_connected()) {
-		puts("\rUSB cable not detected.\n" \
-		     "Command exit.\n");
-		ret = CMD_RET_FAILURE;
-		goto exit;
-	}
+	ret = fastboot_usb_run(controller_index, (void *)buf_addr, buf_size);
 
-	while (1) {
-		if (g_dnl_detach())
-			break;
-		if (IS_ENABLED(CONFIG_CMD_FASTBOOT_ABORT_KEYED)) {
-			if (tstc()) {
-				getchar();
-				puts("\rOperation aborted.\n");
-				break;
-			}
-		} else if (ctrlc()) {
-			break;
-		}
-		schedule();
-		dm_usb_gadget_handle_interrupts(udc);
-	}
-
-	ret = CMD_RET_SUCCESS;
-
-exit:
-	udc_device_put(udc);
-	g_dnl_unregister();
-	g_dnl_clear_detach();
-
-	return ret;
+	return ret ? CMD_RET_FAILURE : CMD_RET_SUCCESS;
 }
 
 static int do_fastboot(struct cmd_tbl *cmdtp, int flag, int argc,
@@ -167,8 +126,6 @@ NXTARG:
 		return CMD_RET_USAGE;
 	}
 
-	fastboot_init((void *)buf_addr, buf_size);
-
 #if CONFIG_IS_ENABLED(NET_LEGACY)
 	if (!strcmp(argv[1], "udp"))
 		return do_fastboot_udp(argc, argv, buf_addr, buf_size);
diff --git a/drivers/fastboot/Makefile b/drivers/fastboot/Makefile
index a341af076d1..32e8e072c88 100644
--- a/drivers/fastboot/Makefile
+++ b/drivers/fastboot/Makefile
@@ -3,6 +3,7 @@
 obj-y += fb_common.o
 obj-y += fb_getvar.o
 obj-y += fb_command.o
+obj-$(CONFIG_USB_FUNCTION_FASTBOOT) += fb_usb.o
 obj-$(CONFIG_FASTBOOT_FLASH_BLOCK) += fb_block.o
 # MMC reuses block implementation
 obj-$(CONFIG_FASTBOOT_FLASH_MMC) += fb_block.o fb_mmc.o
diff --git a/drivers/fastboot/fb_usb.c b/drivers/fastboot/fb_usb.c
new file mode 100644
index 00000000000..ecb27f28362
--- /dev/null
+++ b/drivers/fastboot/fb_usb.c
@@ -0,0 +1,63 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2008 - 2009 Windriver, <www.windriver.com>
+ * Author: Tom Rix <Tom.Rix@windriver.com>
+ *
+ * (C) Copyright 2014 Linaro, Ltd.
+ * Rob Herring <robh@kernel.org>
+ */
+
+#include <console.h>
+#include <fastboot.h>
+#include <g_dnl.h>
+#include <usb.h>
+#include <u-boot/schedule.h>
+#include <linux/errno.h>
+#include <linux/printk.h>
+
+int fastboot_usb_run(int controller_index, void *buf_addr, u32 buf_size)
+{
+	struct udevice *udc;
+	int ret;
+
+	ret = udc_device_get_by_index(controller_index, &udc);
+	if (ret) {
+		pr_err("USB init failed: %d\n", ret);
+		return ret;
+	}
+
+	fastboot_init(buf_addr, buf_size);
+	g_dnl_clear_detach();
+
+	ret = g_dnl_register("usb_dnl_fastboot");
+	if (ret)
+		goto err_put;
+
+	if (!g_dnl_board_usb_cable_connected()) {
+		puts("\rUSB cable not detected.\n");
+		ret = -ENODEV;
+		goto err_unregister;
+	}
+
+	while (!g_dnl_detach()) {
+		if (IS_ENABLED(CONFIG_CMD_FASTBOOT_ABORT_KEYED)) {
+			if (tstc()) {
+				getchar();
+				puts("\rOperation aborted.\n");
+				break;
+			}
+		} else if (ctrlc()) {
+			break;
+		}
+		schedule();
+		dm_usb_gadget_handle_interrupts(udc);
+	}
+
+err_unregister:
+	g_dnl_unregister();
+	g_dnl_clear_detach();
+err_put:
+	udc_device_put(udc);
+
+	return ret;
+}
diff --git a/include/fastboot.h b/include/fastboot.h
index b106d617749..f02d2559f2b 100644
--- a/include/fastboot.h
+++ b/include/fastboot.h
@@ -125,6 +125,16 @@ void fastboot_set_progress_callback(void (*progress)(const char *msg));
  */
 void fastboot_init(void *buf_addr, u32 buf_size);
 
+/**
+ * fastboot_usb_run() - run a USB fastboot session
+ *
+ * @controller_index: USB gadget controller index
+ * @buf_addr: Pointer to download buffer, or NULL for default
+ * @buf_size: Size of download buffer, or zero for default
+ * Return: 0 on success, or a negative error code
+ */
+int fastboot_usb_run(int controller_index, void *buf_addr, u32 buf_size);
+
 /**
  * fastboot_boot() - Execute fastboot boot command
  *

-- 
2.55.0


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH v4 2/5] fastboot: use the common handler for USB reboot
  2026-08-20 18:08 [PATCH v4 0/5] Add fastboot to SPL Carlo Caione
  2026-08-20 18:08 ` [PATCH v4 1/5] fastboot: factor out the USB session runner Carlo Caione
@ 2026-08-20 18:08 ` Carlo Caione
  2026-08-20 18:08 ` [PATCH v4 3/5] fastboot: make shared configuration checks phase-aware Carlo Caione
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 14+ messages in thread
From: Carlo Caione @ 2026-08-20 18:08 UTC (permalink / raw)
  To: u-boot, GSS_MTK_Uboot_upstream
  Cc: Suhrid Subramaniam, Macpaul Lin (林智斌),
	Pablo Sun (孫毓翔), Arnaud Ferraris,
	Mattijs Korpershoek, Tom Rini, Simon Glass, Sam Day,
	Quentin Schulz, Carlo Caione, David Lechner, Vitor Sato Eschholz,
	Lukasz Majewski, Marek Vasut, Peng Fan, Jaehoon Chung,
	Neil Armstrong, Julien Masson, Alexey Charkov, Adrian Freihofer,
	Francois Berder, Ilias Apalodimas, Marek Vasut, Vincent Jardin,
	Peter Robinson

USB fastboot resets the device directly from its request-completion
callback, while the network transports route completed commands through
fastboot_handle_boot(). Keeping reset policy in the transport makes it
harder to support callers with a different reset interface.

Send the USB reboot completion through the common handler as
well. U-Boot proper retains the same do_reset() behavior, while
execution-phase-specific policy can be contained in the shared code.

Signed-off-by: Julien Masson <jmasson@baylibre.com>
Signed-off-by: Vitor Sato Eschholz <vsatoes@baylibre.com>
Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>
Reviewed-by: Mattijs Korpershoek <mkorpershoek@kernel.org>
Signed-off-by: Carlo Caione <ccaione@baylibre.com>
---
 drivers/usb/gadget/f_fastboot.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/usb/gadget/f_fastboot.c b/drivers/usb/gadget/f_fastboot.c
index 8df0e3f331d..471c0e87042 100644
--- a/drivers/usb/gadget/f_fastboot.c
+++ b/drivers/usb/gadget/f_fastboot.c
@@ -422,7 +422,7 @@ static int fastboot_tx_write_str(const char *buffer)
 static void compl_do_reset(struct usb_ep *ep, struct usb_request *req)
 {
 	g_dnl_unregister();
-	do_reset(NULL, 0, 0, NULL);
+	fastboot_handle_boot(FASTBOOT_COMMAND_REBOOT, true);
 }
 
 static unsigned int rx_bytes_expected(struct usb_ep *ep)

-- 
2.55.0


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH v4 3/5] fastboot: make shared configuration checks phase-aware
  2026-08-20 18:08 [PATCH v4 0/5] Add fastboot to SPL Carlo Caione
  2026-08-20 18:08 ` [PATCH v4 1/5] fastboot: factor out the USB session runner Carlo Caione
  2026-08-20 18:08 ` [PATCH v4 2/5] fastboot: use the common handler for USB reboot Carlo Caione
@ 2026-08-20 18:08 ` Carlo Caione
  2026-08-20 18:08 ` [PATCH v4 4/5] image: sparse: add phase-aware SPL support Carlo Caione
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 14+ messages in thread
From: Carlo Caione @ 2026-08-20 18:08 UTC (permalink / raw)
  To: u-boot, GSS_MTK_Uboot_upstream
  Cc: Suhrid Subramaniam, Macpaul Lin (林智斌),
	Pablo Sun (孫毓翔), Arnaud Ferraris,
	Mattijs Korpershoek, Tom Rini, Simon Glass, Sam Day,
	Quentin Schulz, Carlo Caione, David Lechner, Vitor Sato Eschholz,
	Lukasz Majewski, Marek Vasut, Peng Fan, Jaehoon Chung,
	Neil Armstrong, Julien Masson, Alexey Charkov, Adrian Freihofer,
	Francois Berder, Ilias Apalodimas, Marek Vasut, Vincent Jardin,
	Peter Robinson

Fastboot currently builds only for U-Boot proper, so its source and
Makefile rules test CONFIG_FASTBOOT_* directly. The same checks would
select U-Boot-proper options when these files are compiled for another
phase, potentially compiling unavailable backends or using the wrong
configuration values.

Use CONFIG_IS_ENABLED(), CONFIG_VAL() and CONFIG_$(PHASE_) consistently
for code and object selection. The empty phase prefix preserves the
existing U-Boot-proper configuration and behavior while making the
shared implementation safe to reuse from SPL.

Signed-off-by: Julien Masson <jmasson@baylibre.com>
Signed-off-by: Vitor Sato Eschholz <vsatoes@baylibre.com>
Signed-off-by: Carlo Caione <ccaione@baylibre.com>
---
 drivers/Makefile              |  2 +-
 drivers/fastboot/Makefile     | 10 +++++-----
 drivers/fastboot/fb_block.c   |  9 ++++-----
 drivers/fastboot/fb_command.c | 31 +++++++++++++++++--------------
 drivers/fastboot/fb_common.c  |  4 ++--
 drivers/fastboot/fb_getvar.c  | 14 +++++++-------
 drivers/fastboot/fb_mmc.c     | 36 ++++++++++++++++++------------------
 drivers/fastboot/fb_usb.c     |  2 +-
 8 files changed, 55 insertions(+), 53 deletions(-)

diff --git a/drivers/Makefile b/drivers/Makefile
index 4c7ba741acb..19f5c3802a4 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -12,6 +12,7 @@ obj-$(CONFIG_$(PHASE_)DMA) += dma/
 obj-$(CONFIG_$(PHASE_)DMA_LEGACY) += dma/
 obj-$(CONFIG_$(PHASE_)DFU) += dfu/
 obj-$(CONFIG_$(PHASE_)EXTCON) += extcon/
+obj-$(CONFIG_$(PHASE_)FASTBOOT) += fastboot/
 obj-$(CONFIG_$(PHASE_)GPIO) += gpio/
 obj-$(CONFIG_$(PHASE_)DRIVERS_MISC) += misc/
 obj-$(CONFIG_$(PHASE_)SYSRESET) += sysreset/
@@ -94,7 +95,6 @@ obj-y += block/
 obj-y += cache/
 obj-$(CONFIG_CPU) += cpu/
 obj-y += crypto/
-obj-$(CONFIG_FASTBOOT) += fastboot/
 obj-$(CONFIG_FWU_MDATA) += fwu-mdata/
 obj-y += misc/
 obj-$(CONFIG_MMC) += mmc/
diff --git a/drivers/fastboot/Makefile b/drivers/fastboot/Makefile
index 32e8e072c88..7eb666bdd60 100644
--- a/drivers/fastboot/Makefile
+++ b/drivers/fastboot/Makefile
@@ -3,9 +3,9 @@
 obj-y += fb_common.o
 obj-y += fb_getvar.o
 obj-y += fb_command.o
-obj-$(CONFIG_USB_FUNCTION_FASTBOOT) += fb_usb.o
-obj-$(CONFIG_FASTBOOT_FLASH_BLOCK) += fb_block.o
+obj-$(CONFIG_$(PHASE_)USB_FUNCTION_FASTBOOT) += fb_usb.o
+obj-$(CONFIG_$(PHASE_)FASTBOOT_FLASH_BLOCK) += fb_block.o
 # MMC reuses block implementation
-obj-$(CONFIG_FASTBOOT_FLASH_MMC) += fb_block.o fb_mmc.o
-obj-$(CONFIG_FASTBOOT_FLASH_NAND) += fb_nand.o
-obj-$(CONFIG_FASTBOOT_FLASH_SPI) += fb_spi_flash.o
+obj-$(CONFIG_$(PHASE_)FASTBOOT_FLASH_MMC) += fb_block.o fb_mmc.o
+obj-$(CONFIG_$(PHASE_)FASTBOOT_FLASH_NAND) += fb_nand.o
+obj-$(CONFIG_$(PHASE_)FASTBOOT_FLASH_SPI) += fb_spi_flash.o
diff --git a/drivers/fastboot/fb_block.c b/drivers/fastboot/fb_block.c
index 51d1abb18c7..9658b14e668 100644
--- a/drivers/fastboot/fb_block.c
+++ b/drivers/fastboot/fb_block.c
@@ -130,11 +130,10 @@ int fastboot_block_get_part_info(const char *part_name,
 				 char *response)
 {
 	int ret;
-	const char *interface = config_opt_enabled(CONFIG_FASTBOOT_FLASH_BLOCK,
-						   CONFIG_FASTBOOT_FLASH_BLOCK_INTERFACE_NAME,
-						   NULL);
-	const int device = config_opt_enabled(CONFIG_FASTBOOT_FLASH_BLOCK,
-					      CONFIG_FASTBOOT_FLASH_BLOCK_DEVICE_ID, -1);
+	const char *interface = CONFIG_IS_ENABLED(FASTBOOT_FLASH_BLOCK,
+		(CONFIG_VAL(FASTBOOT_FLASH_BLOCK_INTERFACE_NAME)), (NULL));
+	const int device = CONFIG_IS_ENABLED(FASTBOOT_FLASH_BLOCK,
+		(CONFIG_VAL(FASTBOOT_FLASH_BLOCK_DEVICE_ID)), (-1));
 
 	if (!part_name || !strcmp(part_name, "")) {
 		fastboot_fail("partition not given", response);
diff --git a/drivers/fastboot/fb_command.c b/drivers/fastboot/fb_command.c
index 18d86988f4c..111516fd1b3 100644
--- a/drivers/fastboot/fb_command.c
+++ b/drivers/fastboot/fb_command.c
@@ -339,19 +339,19 @@ void fastboot_data_complete(char *response)
  */
 static void __maybe_unused flash(char *cmd_parameter, char *response)
 {
-	if (IS_ENABLED(CONFIG_FASTBOOT_FLASH_BLOCK))
+	if (CONFIG_IS_ENABLED(FASTBOOT_FLASH_BLOCK))
 		fastboot_block_flash_write(cmd_parameter, fastboot_buf_addr,
 					   image_size, response);
 
-	if (IS_ENABLED(CONFIG_FASTBOOT_FLASH_MMC))
+	if (CONFIG_IS_ENABLED(FASTBOOT_FLASH_MMC))
 		fastboot_mmc_flash_write(cmd_parameter, fastboot_buf_addr,
 					 image_size, response);
 
-	if (IS_ENABLED(CONFIG_FASTBOOT_FLASH_NAND))
+	if (CONFIG_IS_ENABLED(FASTBOOT_FLASH_NAND))
 		fastboot_nand_flash_write(cmd_parameter, fastboot_buf_addr,
 					  image_size, response);
 
-	if (IS_ENABLED(CONFIG_FASTBOOT_FLASH_SPI))
+	if (CONFIG_IS_ENABLED(FASTBOOT_FLASH_SPI))
 		fastboot_spi_flash_write(cmd_parameter, fastboot_buf_addr,
 					 image_size, response);
 }
@@ -367,16 +367,16 @@ static void __maybe_unused flash(char *cmd_parameter, char *response)
  */
 static void __maybe_unused erase(char *cmd_parameter, char *response)
 {
-	if (IS_ENABLED(CONFIG_FASTBOOT_FLASH_BLOCK))
+	if (CONFIG_IS_ENABLED(FASTBOOT_FLASH_BLOCK))
 		fastboot_block_erase(cmd_parameter, response);
 
-	if (IS_ENABLED(CONFIG_FASTBOOT_FLASH_MMC))
+	if (CONFIG_IS_ENABLED(FASTBOOT_FLASH_MMC))
 		fastboot_mmc_erase(cmd_parameter, response);
 
-	if (IS_ENABLED(CONFIG_FASTBOOT_FLASH_NAND))
+	if (CONFIG_IS_ENABLED(FASTBOOT_FLASH_NAND))
 		fastboot_nand_erase(cmd_parameter, response);
 
-	if (IS_ENABLED(CONFIG_FASTBOOT_FLASH_SPI))
+	if (CONFIG_IS_ENABLED(FASTBOOT_FLASH_SPI))
 		fastboot_spi_flash_erase(cmd_parameter, response);
 }
 
@@ -482,8 +482,9 @@ static void reboot_recovery(char *cmd_parameter, char *response)
 static void __maybe_unused oem_format(char *cmd_parameter, char *response)
 {
 	char cmdbuf[32];
-	const int mmc_dev = config_opt_enabled(CONFIG_FASTBOOT_FLASH_MMC,
-					       CONFIG_FASTBOOT_FLASH_MMC_DEV, -1);
+	const int mmc_dev = CONFIG_IS_ENABLED(FASTBOOT_FLASH_MMC,
+					      (CONFIG_VAL(FASTBOOT_FLASH_MMC_DEV)),
+					      (-1));
 
 	if (!env_get("partitions")) {
 		fastboot_fail("partitions not set", response);
@@ -505,8 +506,9 @@ static void __maybe_unused oem_format(char *cmd_parameter, char *response)
 static void __maybe_unused oem_partconf(char *cmd_parameter, char *response)
 {
 	char cmdbuf[32];
-	const int mmc_dev = config_opt_enabled(CONFIG_FASTBOOT_FLASH_MMC,
-					       CONFIG_FASTBOOT_FLASH_MMC_DEV, -1);
+	const int mmc_dev = CONFIG_IS_ENABLED(FASTBOOT_FLASH_MMC,
+					      (CONFIG_VAL(FASTBOOT_FLASH_MMC_DEV)),
+					      (-1));
 
 	if (!cmd_parameter) {
 		fastboot_fail("Expected command parameter", response);
@@ -531,8 +533,9 @@ static void __maybe_unused oem_partconf(char *cmd_parameter, char *response)
 static void __maybe_unused oem_bootbus(char *cmd_parameter, char *response)
 {
 	char cmdbuf[32];
-	const int mmc_dev = config_opt_enabled(CONFIG_FASTBOOT_FLASH_MMC,
-					       CONFIG_FASTBOOT_FLASH_MMC_DEV, -1);
+	const int mmc_dev = CONFIG_IS_ENABLED(FASTBOOT_FLASH_MMC,
+					      (CONFIG_VAL(FASTBOOT_FLASH_MMC_DEV)),
+					      (-1));
 
 	if (!cmd_parameter) {
 		fastboot_fail("Expected command parameter", response);
diff --git a/drivers/fastboot/fb_common.c b/drivers/fastboot/fb_common.c
index 9c52e004588..3c0013490cc 100644
--- a/drivers/fastboot/fb_common.c
+++ b/drivers/fastboot/fb_common.c
@@ -234,8 +234,8 @@ void fastboot_set_progress_callback(void (*progress)(const char *msg))
  */
 void fastboot_init(void *buf_addr, u32 buf_size)
 {
-#if IS_ENABLED(CONFIG_FASTBOOT_FLASH_BLOCK)
-	if (!strcmp(CONFIG_FASTBOOT_FLASH_BLOCK_INTERFACE_NAME, "mmc"))
+#if CONFIG_IS_ENABLED(FASTBOOT_FLASH_BLOCK)
+	if (!strcmp(CONFIG_VAL(FASTBOOT_FLASH_BLOCK_INTERFACE_NAME), "mmc"))
 		printf("Warning: the fastboot block backend features are limited, consider using the MMC backend\n");
 #endif
 
diff --git a/drivers/fastboot/fb_getvar.c b/drivers/fastboot/fb_getvar.c
index e8aa0e09aa6..9e8e8889d08 100644
--- a/drivers/fastboot/fb_getvar.c
+++ b/drivers/fastboot/fb_getvar.c
@@ -70,19 +70,19 @@ static const struct {
 		.variable = "current-slot",
 		.dispatch = getvar_current_slot,
 		.list = true
-#if IS_ENABLED(CONFIG_FASTBOOT_FLASH)
+#if CONFIG_IS_ENABLED(FASTBOOT_FLASH)
 	}, {
 		.variable = "has-slot",
 		.dispatch = getvar_has_slot,
 		.list = false
 #endif
-#if IS_ENABLED(CONFIG_FASTBOOT_FLASH_MMC)
+#if CONFIG_IS_ENABLED(FASTBOOT_FLASH_MMC)
 	}, {
 		.variable = "partition-type",
 		.dispatch = getvar_partition_type,
 		.list = false
 #endif
-#if IS_ENABLED(CONFIG_FASTBOOT_FLASH)
+#if CONFIG_IS_ENABLED(FASTBOOT_FLASH)
 	}, {
 		.variable = "partition-size",
 		.dispatch = getvar_partition_size,
@@ -116,21 +116,21 @@ static int getvar_get_part_info(const char *part_name, char *response,
 	struct disk_partition disk_part;
 	struct part_info *part_info;
 
-	if (IS_ENABLED(CONFIG_FASTBOOT_FLASH_BLOCK)) {
+	if (CONFIG_IS_ENABLED(FASTBOOT_FLASH_BLOCK)) {
 		r = fastboot_block_get_part_info(part_name, &dev_desc, &disk_part,
 						 response);
 		if (r >= 0 && size)
 			*size = disk_part.size * disk_part.blksz;
-	} else if (IS_ENABLED(CONFIG_FASTBOOT_FLASH_MMC)) {
+	} else if (CONFIG_IS_ENABLED(FASTBOOT_FLASH_MMC)) {
 		r = fastboot_mmc_get_part_info(part_name, &dev_desc, &disk_part,
 					       response);
 		if (r >= 0 && size)
 			*size = disk_part.size * disk_part.blksz;
-	} else if (IS_ENABLED(CONFIG_FASTBOOT_FLASH_NAND)) {
+	} else if (CONFIG_IS_ENABLED(FASTBOOT_FLASH_NAND)) {
 		r = fastboot_nand_get_part_info(part_name, &part_info, response);
 		if (r >= 0 && size)
 			*size = part_info->size;
-	} else if (IS_ENABLED(CONFIG_FASTBOOT_FLASH_SPI)) {
+	} else if (CONFIG_IS_ENABLED(FASTBOOT_FLASH_SPI)) {
 		r = fastboot_spi_flash_get_part_info(part_name, &disk_part,
 						     response);
 		if (r >= 0 && size)
diff --git a/drivers/fastboot/fb_mmc.c b/drivers/fastboot/fb_mmc.c
index 9bc782ccd02..ae33e35365b 100644
--- a/drivers/fastboot/fb_mmc.c
+++ b/drivers/fastboot/fb_mmc.c
@@ -75,7 +75,7 @@ static int do_get_part_info(struct blk_desc **dev_desc, const char *name,
 	int ret;
 
 	/* First try partition names on the default device */
-	*dev_desc = blk_get_dev("mmc", CONFIG_FASTBOOT_FLASH_MMC_DEV);
+	*dev_desc = blk_get_dev("mmc", CONFIG_VAL(FASTBOOT_FLASH_MMC_DEV));
 	if (*dev_desc) {
 		ret = part_get_info_by_name(*dev_desc, name, info);
 		if (ret >= 0)
@@ -111,7 +111,7 @@ static int part_get_info_by_name_or_alias(struct blk_desc **dev_desc,
 	return do_get_part_info(dev_desc, name, info);
 }
 
-#ifdef CONFIG_FASTBOOT_MMC_BOOT_SUPPORT
+#if CONFIG_IS_ENABLED(FASTBOOT_MMC_BOOT_SUPPORT)
 static void fb_mmc_boot_ops(struct blk_desc *dev_desc, void *buffer,
 			    int hwpart, u32 buff_sz, char *response)
 {
@@ -130,7 +130,7 @@ static void fb_mmc_boot_ops(struct blk_desc *dev_desc, void *buffer,
 }
 #endif
 
-#ifdef CONFIG_ANDROID_BOOT_IMAGE
+#if CONFIG_IS_ENABLED(ANDROID_BOOT_IMAGE)
 /**
  * Read Android boot image header from boot partition.
  *
@@ -346,7 +346,7 @@ int fastboot_mmc_get_part_info(const char *part_name,
 static struct blk_desc *fastboot_mmc_get_dev(char *response)
 {
 	struct blk_desc *ret = blk_get_dev("mmc",
-					   CONFIG_FASTBOOT_FLASH_MMC_DEV);
+					   CONFIG_VAL(FASTBOOT_FLASH_MMC_DEV));
 
 	if (!ret || ret->type == DEV_TYPE_UNKNOWN) {
 		pr_err("invalid mmc device\n");
@@ -370,15 +370,15 @@ void fastboot_mmc_flash_write(const char *cmd, void *download_buffer,
 	struct blk_desc *dev_desc;
 	struct disk_partition info = {0};
 
-#ifdef CONFIG_FASTBOOT_MMC_BOOT_SUPPORT
-	if (strcmp(cmd, CONFIG_FASTBOOT_MMC_BOOT1_NAME) == 0) {
+#if CONFIG_IS_ENABLED(FASTBOOT_MMC_BOOT_SUPPORT)
+	if (!strcmp(cmd, CONFIG_VAL(FASTBOOT_MMC_BOOT1_NAME))) {
 		dev_desc = fastboot_mmc_get_dev(response);
 		if (dev_desc)
 			fb_mmc_boot_ops(dev_desc, download_buffer, 1,
 					download_bytes, response);
 		return;
 	}
-	if (strcmp(cmd, CONFIG_FASTBOOT_MMC_BOOT2_NAME) == 0) {
+	if (!strcmp(cmd, CONFIG_VAL(FASTBOOT_MMC_BOOT2_NAME))) {
 		dev_desc = fastboot_mmc_get_dev(response);
 		if (dev_desc)
 			fb_mmc_boot_ops(dev_desc, download_buffer, 2,
@@ -388,7 +388,7 @@ void fastboot_mmc_flash_write(const char *cmd, void *download_buffer,
 #endif
 
 #if CONFIG_IS_ENABLED(EFI_PARTITION)
-	if (strcmp(cmd, CONFIG_FASTBOOT_GPT_NAME) == 0) {
+	if (!strcmp(cmd, CONFIG_VAL(FASTBOOT_GPT_NAME))) {
 		dev_desc = fastboot_mmc_get_dev(response);
 		if (!dev_desc)
 			return;
@@ -415,7 +415,7 @@ void fastboot_mmc_flash_write(const char *cmd, void *download_buffer,
 #endif
 
 #if CONFIG_IS_ENABLED(DOS_PARTITION)
-	if (strcmp(cmd, CONFIG_FASTBOOT_MBR_NAME) == 0) {
+	if (!strcmp(cmd, CONFIG_VAL(FASTBOOT_MBR_NAME))) {
 		dev_desc = fastboot_mmc_get_dev(response);
 		if (!dev_desc)
 			return;
@@ -440,7 +440,7 @@ void fastboot_mmc_flash_write(const char *cmd, void *download_buffer,
 	}
 #endif
 
-#ifdef CONFIG_ANDROID_BOOT_IMAGE
+#if CONFIG_IS_ENABLED(ANDROID_BOOT_IMAGE)
 	if (strncasecmp(cmd, "zimage", 6) == 0) {
 		dev_desc = fastboot_mmc_get_dev(response);
 		if (dev_desc)
@@ -450,8 +450,8 @@ void fastboot_mmc_flash_write(const char *cmd, void *download_buffer,
 	}
 #endif
 
-#if IS_ENABLED(CONFIG_FASTBOOT_MMC_USER_SUPPORT)
-	if (strcmp(cmd, CONFIG_FASTBOOT_MMC_USER_NAME) == 0) {
+#if CONFIG_IS_ENABLED(FASTBOOT_MMC_USER_SUPPORT)
+	if (!strcmp(cmd, CONFIG_VAL(FASTBOOT_MMC_USER_NAME))) {
 		dev_desc = fastboot_mmc_get_dev(response);
 		if (!dev_desc)
 			return;
@@ -485,17 +485,17 @@ void fastboot_mmc_erase(const char *cmd, char *response)
 {
 	struct blk_desc *dev_desc;
 	struct disk_partition info;
-	struct mmc *mmc = find_mmc_device(CONFIG_FASTBOOT_FLASH_MMC_DEV);
+	struct mmc *mmc = find_mmc_device(CONFIG_VAL(FASTBOOT_FLASH_MMC_DEV));
 
-#ifdef CONFIG_FASTBOOT_MMC_BOOT_SUPPORT
-	if (strcmp(cmd, CONFIG_FASTBOOT_MMC_BOOT1_NAME) == 0) {
+#if CONFIG_IS_ENABLED(FASTBOOT_MMC_BOOT_SUPPORT)
+	if (!strcmp(cmd, CONFIG_VAL(FASTBOOT_MMC_BOOT1_NAME))) {
 		/* erase EMMC boot1 */
 		dev_desc = fastboot_mmc_get_dev(response);
 		if (dev_desc)
 			fb_mmc_boot_ops(dev_desc, NULL, 1, 0, response);
 		return;
 	}
-	if (strcmp(cmd, CONFIG_FASTBOOT_MMC_BOOT2_NAME) == 0) {
+	if (!strcmp(cmd, CONFIG_VAL(FASTBOOT_MMC_BOOT2_NAME))) {
 		/* erase EMMC boot2 */
 		dev_desc = fastboot_mmc_get_dev(response);
 		if (dev_desc)
@@ -504,8 +504,8 @@ void fastboot_mmc_erase(const char *cmd, char *response)
 	}
 #endif
 
-#ifdef CONFIG_FASTBOOT_MMC_USER_SUPPORT
-	if (strcmp(cmd, CONFIG_FASTBOOT_MMC_USER_NAME) == 0) {
+#if CONFIG_IS_ENABLED(FASTBOOT_MMC_USER_SUPPORT)
+	if (!strcmp(cmd, CONFIG_VAL(FASTBOOT_MMC_USER_NAME))) {
 		/* erase EMMC userdata */
 		dev_desc = fastboot_mmc_get_dev(response);
 		if (!dev_desc)
diff --git a/drivers/fastboot/fb_usb.c b/drivers/fastboot/fb_usb.c
index ecb27f28362..028193618f1 100644
--- a/drivers/fastboot/fb_usb.c
+++ b/drivers/fastboot/fb_usb.c
@@ -40,7 +40,7 @@ int fastboot_usb_run(int controller_index, void *buf_addr, u32 buf_size)
 	}
 
 	while (!g_dnl_detach()) {
-		if (IS_ENABLED(CONFIG_CMD_FASTBOOT_ABORT_KEYED)) {
+		if (CONFIG_IS_ENABLED(CMD_FASTBOOT_ABORT_KEYED)) {
 			if (tstc()) {
 				getchar();
 				puts("\rOperation aborted.\n");

-- 
2.55.0


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH v4 4/5] image: sparse: add phase-aware SPL support
  2026-08-20 18:08 [PATCH v4 0/5] Add fastboot to SPL Carlo Caione
                   ` (2 preceding siblings ...)
  2026-08-20 18:08 ` [PATCH v4 3/5] fastboot: make shared configuration checks phase-aware Carlo Caione
@ 2026-08-20 18:08 ` Carlo Caione
  2026-08-20 18:08 ` [PATCH v4 5/5] fastboot: add " Carlo Caione
  2026-09-04  7:06 ` [PATCH v4 0/5] Add fastboot to SPL Carlo Caione
  5 siblings, 0 replies; 14+ messages in thread
From: Carlo Caione @ 2026-08-20 18:08 UTC (permalink / raw)
  To: u-boot, GSS_MTK_Uboot_upstream
  Cc: Suhrid Subramaniam, Macpaul Lin (林智斌),
	Pablo Sun (孫毓翔), Arnaud Ferraris,
	Mattijs Korpershoek, Tom Rini, Simon Glass, Sam Day,
	Quentin Schulz, Carlo Caione, David Lechner, Vitor Sato Eschholz,
	Lukasz Majewski, Marek Vasut, Peng Fan, Jaehoon Chung,
	Neil Armstrong, Julien Masson, Alexey Charkov, Adrian Freihofer,
	Francois Berder, Ilias Apalodimas, Marek Vasut, Vincent Jardin,
	Peter Robinson

The Android sparse-image writer is selected and configured only through
U-Boot-proper symbols. An SPL storage service therefore cannot reuse
it without either pulling it into every SPL build or interpreting the
U-Boot-proper fill-buffer setting.

Add opt-in SPL symbols, build the writer through the phase-aware object
rule and read the matching phase value with CONFIG_VAL(). Existing
U-Boot-proper builds continue to use IMAGE_SPARSE and retain the same
fill-buffer default.

Signed-off-by: Julien Masson <jmasson@baylibre.com>
Signed-off-by: Vitor Sato Eschholz <vsatoes@baylibre.com>
Reviewed-by: Mattijs Korpershoek <mkorpershoek@kernel.org>
Signed-off-by: Carlo Caione <ccaione@baylibre.com>
---
 lib/Kconfig        | 11 +++++++++++
 lib/Makefile       |  3 ++-
 lib/image-sparse.c |  2 +-
 3 files changed, 14 insertions(+), 2 deletions(-)

diff --git a/lib/Kconfig b/lib/Kconfig
index 24e55ade4d3..07ee3c88fd3 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -205,6 +205,9 @@ config VPL_STRTO
 config IMAGE_SPARSE
 	bool
 
+config SPL_IMAGE_SPARSE
+	bool
+
 config IMAGE_SPARSE_FILLBUF_SIZE
 	hex "Android sparse image CHUNK_TYPE_FILL buffer size"
 	default 0x80000
@@ -213,6 +216,14 @@ config IMAGE_SPARSE_FILLBUF_SIZE
 	  Set the size of the fill buffer used when processing CHUNK_TYPE_FILL
 	  chunks.
 
+config SPL_IMAGE_SPARSE_FILLBUF_SIZE
+	hex "Android sparse image fill buffer size in SPL"
+	default 0x80000
+	depends on SPL_IMAGE_SPARSE
+	help
+	  Set the size of the fill buffer used when processing CHUNK_TYPE_FILL
+	  chunks in SPL.
+
 config USE_PRIVATE_LIBGCC
 	bool "Use private libgcc"
 	depends on HAVE_PRIVATE_LIBGCC
diff --git a/lib/Makefile b/lib/Makefile
index 222378a8531..014fda82860 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -44,7 +44,6 @@ obj-$(CONFIG_GENERATE_SMBIOS_TABLE) += smbios.o
 endif
 
 obj-$(CONFIG_SMBIOS_PARSER) += smbios-parser.o
-obj-$(CONFIG_IMAGE_SPARSE) += image-sparse.o
 obj-y += ldiv.o
 obj-$(CONFIG_XXHASH) += xxhash.o
 obj-y += net_utils.o
@@ -56,6 +55,8 @@ obj-y += list_sort.o
 obj-$(CONFIG_PMBUS) += pmbus.o
 endif
 
+obj-$(CONFIG_$(PHASE_)IMAGE_SPARSE) += image-sparse.o
+
 obj-$(CONFIG_$(PHASE_)TPM) += tpm-common.o
 ifeq ($(CONFIG_$(PHASE_)TPM),y)
 obj-$(CONFIG_TPM) += tpm_api.o
diff --git a/lib/image-sparse.c b/lib/image-sparse.c
index 09225692e9b..48e5d8ee869 100644
--- a/lib/image-sparse.c
+++ b/lib/image-sparse.c
@@ -125,7 +125,7 @@ int write_sparse_image(struct sparse_storage *info,
 	int i;
 	int j;
 
-	fill_buf_num_blks = CONFIG_IMAGE_SPARSE_FILLBUF_SIZE / info->blksz;
+	fill_buf_num_blks = CONFIG_VAL(IMAGE_SPARSE_FILLBUF_SIZE) / info->blksz;
 
 	/* Read and skip over sparse image header */
 	sparse_header = (sparse_header_t *)data;

-- 
2.55.0


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH v4 5/5] fastboot: add SPL support
  2026-08-20 18:08 [PATCH v4 0/5] Add fastboot to SPL Carlo Caione
                   ` (3 preceding siblings ...)
  2026-08-20 18:08 ` [PATCH v4 4/5] image: sparse: add phase-aware SPL support Carlo Caione
@ 2026-08-20 18:08 ` Carlo Caione
  2026-09-04  7:06 ` [PATCH v4 0/5] Add fastboot to SPL Carlo Caione
  5 siblings, 0 replies; 14+ messages in thread
From: Carlo Caione @ 2026-08-20 18:08 UTC (permalink / raw)
  To: u-boot, GSS_MTK_Uboot_upstream
  Cc: Suhrid Subramaniam, Macpaul Lin (林智斌),
	Pablo Sun (孫毓翔), Arnaud Ferraris,
	Mattijs Korpershoek, Tom Rini, Simon Glass, Sam Day,
	Quentin Schulz, Carlo Caione, David Lechner, Vitor Sato Eschholz,
	Lukasz Majewski, Marek Vasut, Peng Fan, Jaehoon Chung,
	Neil Armstrong, Julien Masson, Alexey Charkov, Adrian Freihofer,
	Francois Berder, Ilias Apalodimas, Marek Vasut, Vincent Jardin,
	Peter Robinson

Some recovery and initial-provisioning flows run before usable firmware
is available in persistent storage. In these flows the SoC ROM loads a
small first stage, but that stage must still provide a standard protocol
with which the host can provision the device.

U-Boot already provides fastboot for this purpose, but its
implementation is currently restricted to U-Boot proper and coupled
to command-line support. This forces platforms that need provisioning
from SPL to maintain a separate downloader or an out-of-tree fastboot
implementation.

Allow boards to run USB fastboot as a service directly from SPL. Include
MMC partition flashing and Android sparse-image handling so that the SPL
service can provision the same storage images accepted by fastboot in
U-Boot proper.

Keep the SPL interface deliberately narrower. The fastboot boot command
is not supported because SPL is being used for provisioning rather than
OS boot orchestration. Filesystem probing is also omitted, so partition
types are reported as raw. Reboot support remains optional since reset
and persistent reboot-reason handling are platform-specific.

SPL size remains an important constraint. Make the support entirely
opt-in and phase-specific: when CONFIG_SPL_FASTBOOT is disabled, no
fastboot code or supporting library is added to SPL and its binary size
is unchanged.

Signed-off-by: Julien Masson <jmasson@baylibre.com>
Signed-off-by: Vitor Sato Eschholz <vsatoes@baylibre.com>
Signed-off-by: Carlo Caione <ccaione@baylibre.com>
---
 doc/android/fastboot.rst        | 31 ++++++++++++++
 drivers/fastboot/Kconfig        | 92 ++++++++++++++++++++++++++++++++++++++++-
 drivers/fastboot/fb_command.c   | 66 ++++++++++++++++++++++++++---
 drivers/fastboot/fb_common.c    | 19 +++++++++
 drivers/fastboot/fb_getvar.c    |  5 +++
 drivers/fastboot/fb_usb.c       |  3 ++
 drivers/usb/gadget/Makefile     |  2 +-
 drivers/usb/gadget/f_fastboot.c |  4 ++
 8 files changed, 213 insertions(+), 9 deletions(-)

diff --git a/doc/android/fastboot.rst b/doc/android/fastboot.rst
index 96c544ae11b..35dcaa8d5c3 100644
--- a/doc/android/fastboot.rst
+++ b/doc/android/fastboot.rst
@@ -72,6 +72,37 @@ platform. The location of the buffer and size are set with
 may be overridden on the fastboot command line using ``-l`` and
 ``-s``.
 
+Fastboot in SPL
+^^^^^^^^^^^^^^^
+
+Fastboot can be used from SPL without enabling the command line. Enable
+``CONFIG_SPL_FASTBOOT`` together with the platform's SPL USB gadget support,
+then start the session from board code::
+
+   ret = fastboot_usb_run(controller_index, NULL, 0);
+
+A ``NULL`` buffer and zero size select ``CONFIG_FASTBOOT_BUF_ADDR`` and
+``CONFIG_FASTBOOT_BUF_SIZE``. Passing explicit values overrides these
+defaults. Unlike the command-line invocation, an SPL session cannot be aborted
+from the local console.
+
+SPL supports ``getvar``, ``download``, ``continue`` and the ``set_active``
+stub. The ``continue`` command ends the session and returns control to the
+caller. The ``flash`` and ``erase`` commands are available when their SPL
+backend is enabled.
+
+MMC flash and erase support is enabled with
+``CONFIG_SPL_FASTBOOT_FLASH_MMC``. The SPL partition-table parser matching the
+storage layout must also be enabled, for example ``CONFIG_SPL_EFI_PARTITION``
+for GPT.
+
+Reboot commands require ``CONFIG_SPL_FASTBOOT_REBOOT`` and a platform
+``reset_cpu()`` implementation. The ``reboot-bootloader``, ``reboot-fastboot``
+and ``reboot-recovery`` commands also require a platform
+``fastboot_set_reboot_flag()`` implementation.
+
+The ``boot``, ``ucmd``, ``acmd`` and OEM commands are not available in SPL.
+
 Fastboot environment variables
 ------------------------------
 
diff --git a/drivers/fastboot/Kconfig b/drivers/fastboot/Kconfig
index 90212fcf9ef..24e92968851 100644
--- a/drivers/fastboot/Kconfig
+++ b/drivers/fastboot/Kconfig
@@ -1,5 +1,6 @@
 menu "Fastboot support"
-	depends on CMDLINE
+
+if CMDLINE
 
 config FASTBOOT
 	bool
@@ -47,7 +48,30 @@ config TCP_FUNCTION_FASTBOOT
 	help
 	  This enables the fastboot protocol over TCP.
 
-if FASTBOOT
+endif # CMDLINE
+
+config SPL_FASTBOOT
+	bool "Support fastboot in SPL"
+	depends on USB_GADGET && SPL_USB_GADGET
+	depends on SPL_ENV_SUPPORT
+	depends on !SPL_USE_TINY_PRINTF
+	select SPL_LIBCOMMON_SUPPORT
+	select SPL_LIBGENERIC_SUPPORT
+	select SPL_PRINTF
+	help
+	  Enable the USB fastboot protocol in SPL. The board is responsible
+	  for starting the fastboot session.
+
+config SPL_USB_FUNCTION_FASTBOOT
+	def_bool y if SPL_FASTBOOT
+
+config SPL_FASTBOOT_REBOOT
+	bool "Enable fastboot reboot commands in SPL"
+	depends on SPL_FASTBOOT
+	help
+	  Enable the fastboot reboot commands in SPL.
+
+if FASTBOOT || SPL_FASTBOOT
 
 config FASTBOOT_BUF_ADDR
 	hex "Define FASTBOOT buffer address"
@@ -79,6 +103,10 @@ config FASTBOOT_BUF_SIZE
 	  downloads. This buffer should be as large as possible for a
 	  platform. Define this to the size available RAM for fastboot.
 
+endif # FASTBOOT || SPL_FASTBOOT
+
+if FASTBOOT
+
 config FASTBOOT_USB_DEV
 	int "USB controller number"
 	depends on USB_FUNCTION_FASTBOOT
@@ -294,4 +322,64 @@ config FASTBOOT_OEM_BOARD
 
 endif # FASTBOOT
 
+config SPL_FASTBOOT_FLASH
+	bool
+	default y if SPL_FASTBOOT_FLASH_MMC
+	select SPL_IMAGE_SPARSE
+
+config SPL_FASTBOOT_FLASH_MMC
+	bool "Enable fastboot MMC flashing in SPL"
+	depends on SPL_FASTBOOT && SPL_MMC && SPL_DM_MMC && SPL_PARTITIONS
+	select SPL_MMC_WRITE
+	help
+	  Build the fastboot MMC flashing backend into SPL. This allows the
+	  fastboot flash and erase commands to operate on MMC partitions. A
+	  suitable SPL partition-table parser must also be enabled.
+
+config SPL_FASTBOOT_FLASH_MMC_DEV
+	int "Define fastboot MMC flash device in SPL"
+	depends on SPL_FASTBOOT_FLASH_MMC
+	default 0
+	help
+	  Define the MMC device that the SPL fastboot flash backend uses.
+
+config SPL_FASTBOOT_MMC_BOOT_SUPPORT
+	bool "Enable eMMC boot-partition flash/erase in SPL"
+	depends on SPL_FASTBOOT_FLASH_MMC && SUPPORT_EMMC_BOOT
+	help
+	  Enable the special fastboot targets used to flash or erase the eMMC
+	  boot hardware partitions from SPL.
+
+config SPL_FASTBOOT_MMC_BOOT1_NAME
+	string "Target name for updating eMMC boot partition 1 in SPL"
+	depends on SPL_FASTBOOT_MMC_BOOT_SUPPORT
+	default "mmc0boot0"
+
+config SPL_FASTBOOT_MMC_BOOT2_NAME
+	string "Target name for updating eMMC boot partition 2 in SPL"
+	depends on SPL_FASTBOOT_MMC_BOOT_SUPPORT
+	default "mmc0boot1"
+
+config SPL_FASTBOOT_MMC_USER_SUPPORT
+	bool "Enable eMMC user-area flash/erase in SPL"
+	depends on SPL_FASTBOOT_FLASH_MMC
+	help
+	  Enable a special fastboot target for flashing or erasing the complete
+	  eMMC user area from SPL.
+
+config SPL_FASTBOOT_MMC_USER_NAME
+	string "Target name for updating the eMMC user area in SPL"
+	depends on SPL_FASTBOOT_MMC_USER_SUPPORT
+	default "mmc0"
+
+config SPL_FASTBOOT_GPT_NAME
+	string "Target name for updating GPT from SPL"
+	depends on SPL_FASTBOOT_FLASH_MMC && SPL_EFI_PARTITION
+	default "gpt"
+
+config SPL_FASTBOOT_MBR_NAME
+	string "Target name for updating MBR from SPL"
+	depends on SPL_FASTBOOT_FLASH_MMC && SPL_DOS_PARTITION
+	default "mbr"
+
 endmenu
diff --git a/drivers/fastboot/fb_command.c b/drivers/fastboot/fb_command.c
index 111516fd1b3..a4f1c74aa7f 100644
--- a/drivers/fastboot/fb_command.c
+++ b/drivers/fastboot/fb_command.c
@@ -48,10 +48,59 @@ static void oem_board(char *, char *);
 static void run_ucmd(char *, char *);
 static void run_acmd(char *, char *);
 
-static const struct {
+struct fastboot_command {
 	const char *command;
 	void (*dispatch)(char *cmd_parameter, char *response);
-} commands[FASTBOOT_COMMAND_COUNT] = {
+};
+
+#ifdef CONFIG_XPL_BUILD
+static const struct fastboot_command commands[FASTBOOT_COMMAND_COUNT] = {
+	[FASTBOOT_COMMAND_GETVAR] = {
+		.command = "getvar",
+		.dispatch = getvar
+	},
+	[FASTBOOT_COMMAND_DOWNLOAD] = {
+		.command = "download",
+		.dispatch = download
+	},
+	[FASTBOOT_COMMAND_FLASH] =  {
+		.command = "flash",
+		.dispatch = CONFIG_IS_ENABLED(FASTBOOT_FLASH, (flash), (NULL))
+	},
+	[FASTBOOT_COMMAND_ERASE] =  {
+		.command = "erase",
+		.dispatch = CONFIG_IS_ENABLED(FASTBOOT_FLASH, (erase), (NULL))
+	},
+	[FASTBOOT_COMMAND_CONTINUE] =  {
+		.command = "continue",
+		.dispatch = okay
+	},
+	[FASTBOOT_COMMAND_REBOOT] =  {
+		.command = "reboot",
+		.dispatch = CONFIG_IS_ENABLED(FASTBOOT_REBOOT, (okay), (NULL))
+	},
+	[FASTBOOT_COMMAND_REBOOT_BOOTLOADER] =  {
+		.command = "reboot-bootloader",
+		.dispatch = CONFIG_IS_ENABLED(FASTBOOT_REBOOT,
+					     (reboot_bootloader), (NULL))
+	},
+	[FASTBOOT_COMMAND_REBOOT_FASTBOOTD] =  {
+		.command = "reboot-fastboot",
+		.dispatch = CONFIG_IS_ENABLED(FASTBOOT_REBOOT,
+					     (reboot_fastbootd), (NULL))
+	},
+	[FASTBOOT_COMMAND_REBOOT_RECOVERY] =  {
+		.command = "reboot-recovery",
+		.dispatch = CONFIG_IS_ENABLED(FASTBOOT_REBOOT,
+					     (reboot_recovery), (NULL))
+	},
+	[FASTBOOT_COMMAND_SET_ACTIVE] =  {
+		.command = "set_active",
+		.dispatch = okay
+	},
+};
+#else
+static const struct fastboot_command commands[FASTBOOT_COMMAND_COUNT] = {
 	[FASTBOOT_COMMAND_GETVAR] = {
 		.command = "getvar",
 		.dispatch = getvar
@@ -129,6 +178,7 @@ static const struct {
 		.dispatch = CONFIG_IS_ENABLED(FASTBOOT_UUU_SUPPORT, (run_acmd), (NULL))
 	},
 };
+#endif
 
 /**
  * fastboot_handle_command - Handle fastboot command
@@ -147,7 +197,8 @@ int fastboot_handle_command(char *cmd_string, char *response)
 	strsep(&cmd_parameter, ":");
 
 	for (i = 0; i < FASTBOOT_COMMAND_COUNT; i++) {
-		if (!strcmp(commands[i].command, cmd_string)) {
+		if (commands[i].command &&
+		    !strcmp(commands[i].command, cmd_string)) {
 			if (commands[i].dispatch) {
 				commands[i].dispatch(cmd_parameter,
 							response);
@@ -437,7 +488,8 @@ static void __maybe_unused run_acmd(char *cmd_parameter, char *response)
  * @cmd_parameter: Pointer to command parameter
  * @response: Pointer to fastboot response buffer
  */
-static void reboot_bootloader(char *cmd_parameter, char *response)
+static void __maybe_unused reboot_bootloader(char *cmd_parameter,
+					     char *response)
 {
 	if (fastboot_set_reboot_flag(FASTBOOT_REBOOT_REASON_BOOTLOADER))
 		fastboot_fail("Cannot set reboot flag", response);
@@ -451,7 +503,8 @@ static void reboot_bootloader(char *cmd_parameter, char *response)
  * @cmd_parameter: Pointer to command parameter
  * @response: Pointer to fastboot response buffer
  */
-static void reboot_fastbootd(char *cmd_parameter, char *response)
+static void __maybe_unused reboot_fastbootd(char *cmd_parameter,
+					    char *response)
 {
 	if (fastboot_set_reboot_flag(FASTBOOT_REBOOT_REASON_FASTBOOTD))
 		fastboot_fail("Cannot set fastboot flag", response);
@@ -465,7 +518,8 @@ static void reboot_fastbootd(char *cmd_parameter, char *response)
  * @cmd_parameter: Pointer to command parameter
  * @response: Pointer to fastboot response buffer
  */
-static void reboot_recovery(char *cmd_parameter, char *response)
+static void __maybe_unused reboot_recovery(char *cmd_parameter,
+					   char *response)
 {
 	if (fastboot_set_reboot_flag(FASTBOOT_REBOOT_REASON_RECOVERY))
 		fastboot_fail("Cannot set recovery flag", response);
diff --git a/drivers/fastboot/fb_common.c b/drivers/fastboot/fb_common.c
index 3c0013490cc..38d4a2678d3 100644
--- a/drivers/fastboot/fb_common.c
+++ b/drivers/fastboot/fb_common.c
@@ -12,6 +12,7 @@
 
 #include <bcb.h>
 #include <command.h>
+#include <cpu_func.h>
 #include <env.h>
 #include <fastboot.h>
 #include <net.h>
@@ -89,6 +90,12 @@ void fastboot_okay(const char *reason, char *response)
  * which sets whatever flag your board specific Android bootloader flow
  * requires in order to re-enter the bootloader.
  */
+#ifdef CONFIG_XPL_BUILD
+int __weak fastboot_set_reboot_flag(enum fastboot_reboot_reason reason)
+{
+	return -EOPNOTSUPP;
+}
+#else
 int __weak fastboot_set_reboot_flag(enum fastboot_reboot_reason reason)
 {
 	int ret;
@@ -127,6 +134,7 @@ out:
 	bcb_reset();
 	return ret;
 }
+#endif
 
 /**
  * fastboot_get_progress_callback() - Return progress callback
@@ -138,6 +146,7 @@ void (*fastboot_get_progress_callback(void))(const char *)
 	return fastboot_progress_callback;
 }
 
+#ifndef CONFIG_XPL_BUILD
 /**
  * fastboot_boot() - Execute fastboot boot command
  *
@@ -175,6 +184,7 @@ void fastboot_boot(void)
 		do_reset(NULL, 0, 0, NULL);
 	}
 }
+#endif
 
 /**
  * fastboot_handle_boot() - Shared implementation of system reaction to
@@ -189,12 +199,14 @@ void fastboot_handle_boot(int command, bool success)
 		return;
 
 	switch (command) {
+#ifndef CONFIG_XPL_BUILD
 	case FASTBOOT_COMMAND_BOOT:
 		fastboot_boot();
 #if CONFIG_IS_ENABLED(NET_LEGACY)
 		net_set_state(NETLOOP_SUCCESS);
 #endif
 		break;
+#endif
 
 	case FASTBOOT_COMMAND_CONTINUE:
 #if CONFIG_IS_ENABLED(NET_LEGACY)
@@ -206,7 +218,14 @@ void fastboot_handle_boot(int command, bool success)
 	case FASTBOOT_COMMAND_REBOOT_BOOTLOADER:
 	case FASTBOOT_COMMAND_REBOOT_FASTBOOTD:
 	case FASTBOOT_COMMAND_REBOOT_RECOVERY:
+#ifdef CONFIG_XPL_BUILD
+#if CONFIG_IS_ENABLED(FASTBOOT_REBOOT)
+		/* SPL may omit CMDLINE, so use the platform reset hook directly. */
+		reset_cpu();
+#endif
+#else
 		do_reset(NULL, 0, 0, NULL);
+#endif
 		break;
 	}
 }
diff --git a/drivers/fastboot/fb_getvar.c b/drivers/fastboot/fb_getvar.c
index 9e8e8889d08..608a62299af 100644
--- a/drivers/fastboot/fb_getvar.c
+++ b/drivers/fastboot/fb_getvar.c
@@ -240,12 +240,17 @@ static void __maybe_unused getvar_partition_type(char *part_name, char *response
 	r = fastboot_mmc_get_part_info(part_name, &dev_desc, &part_info,
 				       response);
 	if (r >= 0) {
+#ifdef CONFIG_XPL_BUILD
+		/* SPL does not pull in filesystem probing just for this getvar. */
+		fastboot_okay("raw", response);
+#else
 		r = fs_set_blk_dev_with_part(dev_desc, r);
 		if (r < 0)
 			/* If we don't know then just default to raw */
 			fastboot_okay("raw", response);
 		else
 			fastboot_okay(fs_get_type_name(), response);
+#endif
 	}
 }
 
diff --git a/drivers/fastboot/fb_usb.c b/drivers/fastboot/fb_usb.c
index 028193618f1..ba06468d487 100644
--- a/drivers/fastboot/fb_usb.c
+++ b/drivers/fastboot/fb_usb.c
@@ -40,6 +40,8 @@ int fastboot_usb_run(int controller_index, void *buf_addr, u32 buf_size)
 	}
 
 	while (!g_dnl_detach()) {
+#ifndef CONFIG_XPL_BUILD
+		/* SPL callers own the session lifetime and may have no console. */
 		if (CONFIG_IS_ENABLED(CMD_FASTBOOT_ABORT_KEYED)) {
 			if (tstc()) {
 				getchar();
@@ -49,6 +51,7 @@ int fastboot_usb_run(int controller_index, void *buf_addr, u32 buf_size)
 		} else if (ctrlc()) {
 			break;
 		}
+#endif
 		schedule();
 		dm_usb_gadget_handle_interrupts(udc);
 	}
diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
index f2aebf4e480..9dd3abe2a5c 100644
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -6,6 +6,7 @@
 obj-$(CONFIG_$(PHASE_)USB_GADGET) += epautoconf.o config.o usbstring.o
 obj-$(CONFIG_$(PHASE_)USB_ETHER) += epautoconf.o config.o usbstring.o ether.o
 obj-$(CONFIG_$(PHASE_)USB_ETH_RNDIS) += rndis.o
+obj-$(CONFIG_$(PHASE_)USB_FUNCTION_FASTBOOT) += f_fastboot.o
 
 ifdef CONFIG_XPL_BUILD
 obj-$(CONFIG_SPL_USB_GADGET) += g_dnl.o
@@ -25,7 +26,6 @@ obj-$(CONFIG_USB_GADGET_DOWNLOAD) += g_dnl.o
 obj-$(CONFIG_USB_FUNCTION_THOR) += f_thor.o
 obj-$(CONFIG_DFU_OVER_USB) += f_dfu.o
 obj-$(CONFIG_USB_FUNCTION_MASS_STORAGE) += f_mass_storage.o
-obj-$(CONFIG_USB_FUNCTION_FASTBOOT) += f_fastboot.o
 obj-$(CONFIG_USB_FUNCTION_SDP) += f_sdp.o
 obj-$(CONFIG_USB_FUNCTION_ROCKUSB) += f_rockusb.o
 obj-$(CONFIG_USB_FUNCTION_ACM)	+= f_acm.o
diff --git a/drivers/usb/gadget/f_fastboot.c b/drivers/usb/gadget/f_fastboot.c
index 471c0e87042..49cacde9db5 100644
--- a/drivers/usb/gadget/f_fastboot.c
+++ b/drivers/usb/gadget/f_fastboot.c
@@ -490,11 +490,13 @@ static void do_exit_on_complete(struct usb_ep *ep, struct usb_request *req)
 	g_dnl_trigger_detach();
 }
 
+#ifndef CONFIG_XPL_BUILD
 static void do_bootm_on_complete(struct usb_ep *ep, struct usb_request *req)
 {
 	fastboot_boot();
 	do_exit_on_complete(ep, req);
 }
+#endif
 
 static int multiresponse_cmd = -1;
 static void multiresponse_on_complete(struct usb_ep *ep, struct usb_request *req)
@@ -560,7 +562,9 @@ static void rx_handler_command(struct usb_ep *ep, struct usb_request *req)
 	if (!strncmp("OKAY", response, 4)) {
 		switch (cmd) {
 		case FASTBOOT_COMMAND_BOOT:
+#ifndef CONFIG_XPL_BUILD
 			fastboot_func->in_req->complete = do_bootm_on_complete;
+#endif
 			break;
 
 		case FASTBOOT_COMMAND_CONTINUE:

-- 
2.55.0


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [PATCH v4 0/5] Add fastboot to SPL
       [not found] <20260820-ccaione-upstream-spl-fastboot-v4-0-57e5ef71c74d__17726.0234997206$1787249364$gmane$org@baylibre.com>
@ 2026-08-20 18:50 ` Stefan Monnier
  2026-08-21  4:05   ` E Shattow
  2026-08-21  7:05   ` Carlo Caione
  0 siblings, 2 replies; 14+ messages in thread
From: Stefan Monnier @ 2026-08-20 18:50 UTC (permalink / raw)
  To: u-boot, Carlo Caione, Jonas Karlman

Carlo Caione [2026-08-20 20:08:24] wrote:
> Some recovery and initial-provisioning flows need a standard host protocol
> before usable firmware is available in persistent storage. U-Boot already
> provides fastboot, but the implementation can currently be started only
> from the U-Boot-proper command line.

I'm curious.  In my limited exposure to U-Boot, I got the impression that
the split between SPL and U-Boot proper is mostly a "technical detail",
usually mostly hidden from those who install it onto a device: you just
take the combined U-Boot + SPL image and write it at the appropriate
offset on the relevant device.  And usually if SPL works, U-Boot
also works.

So a bit like Jonas in the recent "hotkey in SPL" patch for rockchip
SoCs, I'm curious why/when we'd want to add to SPL functionality already
supported from U-Boot.


=== Stefan


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v4 0/5] Add fastboot to SPL
  2026-08-20 18:50 ` Stefan Monnier
@ 2026-08-21  4:05   ` E Shattow
  2026-08-21  7:05   ` Carlo Caione
  1 sibling, 0 replies; 14+ messages in thread
From: E Shattow @ 2026-08-21  4:05 UTC (permalink / raw)
  To: Stefan Monnier, u-boot, Carlo Caione, Jonas Karlman

Hi Stefan,

On 8/20/26 11:50, Stefan Monnier wrote:
> Carlo Caione [2026-08-20 20:08:24] wrote:
>> Some recovery and initial-provisioning flows need a standard host protocol
>> before usable firmware is available in persistent storage. U-Boot already
>> provides fastboot, but the implementation can currently be started only
>> from the U-Boot-proper command line.
> 
> I'm curious.  In my limited exposure to U-Boot, I got the impression that
> the split between SPL and U-Boot proper is mostly a "technical detail",
> usually mostly hidden from those who install it onto a device: you just
> take the combined U-Boot + SPL image and write it at the appropriate
> offset on the relevant device.  And usually if SPL works, U-Boot
> also works.
> 
> So a bit like Jonas in the recent "hotkey in SPL" patch for rockchip
> SoCs, I'm curious why/when we'd want to add to SPL functionality already
> supported from U-Boot.
> 
> 
> === Stefan
> 

The purpose of SPL is to have small codesize so that it may run in SoC
on-die memory in the most permissive operational mode, select for
hardware configuration settings (devicetree model), load U-Boot main app
to more plentiful off-die memory (DRAM), and then either jump execution
to U-Boot main app itself or pass execution to a system supervisor that
would run U-Boot main app in some different operational mode.

This requires that U-Boot main app exists somewhere that may be loaded
from (UART serial, SPI flash, MMC storage...) and further complicates
the use of U-Boot SPL as a fast and efficient recovery tool.

If adding fastboot feature to SPL does not balloon the codesize beyond
hardware limits then it is a very interesting feature to enable, indeed.

Sometimes the SPL is not something we control or have insight into. The
vendor may have provided some proprietary SPL via code obscurity or
cryptographic signing or it will be the functionality of some
proprietary on-die firmware IP block. More typically though the on-die
boot ROM has functionality that may include fastboot-alike
functionality, UART loading, and MMC loading capability for transferring
SPL and jumping code execution to that but without initializing DRAM.

Additionally there may be additional firmware for some SoC cores that
require initializing with e.g. realtime operating system for power
management or DSP functions, and that must be done before changing the
operational mode (so before U-Boot main app).

I'm no expert on this but if I get some detail wrong it is not
intentional, much of this confusion was the same for me when I begin to
look at the situation for RISC-V.

-E

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v4 0/5] Add fastboot to SPL
  2026-08-20 18:50 ` Stefan Monnier
  2026-08-21  4:05   ` E Shattow
@ 2026-08-21  7:05   ` Carlo Caione
  2026-08-21 12:21     ` Stefan Monnier
  1 sibling, 1 reply; 14+ messages in thread
From: Carlo Caione @ 2026-08-21  7:05 UTC (permalink / raw)
  To: Stefan Monnier, u-boot, Carlo Caione, Jonas Karlman; +Cc: E Shattow

On Thu Aug 20, 2026 at 8:50 PM CEST, Stefan Monnier wrote:
> Carlo Caione [2026-08-20 20:08:24] wrote:
>> Some recovery and initial-provisioning flows need a standard host protocol
>> before usable firmware is available in persistent storage. U-Boot already
>> provides fastboot, but the implementation can currently be started only
>> from the U-Boot-proper command line.
>
> I'm curious.  In my limited exposure to U-Boot, I got the impression that
> the split between SPL and U-Boot proper is mostly a "technical detail",
> usually mostly hidden from those who install it onto a device: you just
> take the combined U-Boot + SPL image and write it at the appropriate
> offset on the relevant device.  And usually if SPL works, U-Boot
> also works.
>
> So a bit like Jonas in the recent "hotkey in SPL" patch for rockchip
> SoCs, I'm curious why/when we'd want to add to SPL functionality already
> supported from U-Boot.

Hi Stefan,

Thanks for the question. E Shattow's reply describes the general SPL
constraints well. The detail specific to this series is that "if SPL
works, U-Boot proper also works" assumes that U-Boot proper is already
available from storage that SPL can read and this is not always true.

More specifically the use case we are trying to tackle here is initial
provisioning or recovery of blank or corrupted persistent storage:

Boot ROM -> host-loaded bootstrap -> fastboot -> provision storage

At that point U-Boot proper may not exist on the device yet; it may be
one of the images that fastboot is expected to write on the storage
(through SPL indeed).

It is possible to include U-Boot proper in the host-loaded bootstrap and
use its existing fastboot implementation. That is a valid approach and
is preferable where the Boot ROM download limit and memory budget allow
it. But it is not always possible: some platforms (like the one we
are enabling) impose a strict size limit on the bootstrap, or only
provide enough early memory for the DDR initialization code and (small)
SPL-sized payload.

Fastboot in SPL provides the smaller alternative for those platforms.
It is intended as a provisioning endpoint, not as part of the normal
installed boot path. Once storage has been provisioned, the usual SPL-
to-U-Boot-proper flow remains unchanged.

Hope this clarify the background of this work,

Cheers!

--
Carlo Caione

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v4 0/5] Add fastboot to SPL
  2026-08-21  7:05   ` Carlo Caione
@ 2026-08-21 12:21     ` Stefan Monnier
  2026-08-21 16:13       ` Carlo Caione
  0 siblings, 1 reply; 14+ messages in thread
From: Stefan Monnier @ 2026-08-21 12:21 UTC (permalink / raw)
  To: Carlo Caione; +Cc: u-boot, Jonas Karlman, E Shattow

Carlo Caione [2026-08-21 09:05:37] wrote:
> It is possible to include U-Boot proper in the host-loaded bootstrap
> and use its existing fastboot implementation. That is a valid approach
> and is preferable where the Boot ROM download limit and memory budget
> allow it.

Right, that's the situation I'm familiar with.

> But it is not always possible: some platforms (like the one we are
> enabling) impose a strict size limit on the bootstrap, or only provide
> enough early memory for the DDR initialization code and (small)
> SPL-sized payload.

I associate "fastboot" with the Android nebula, so I find it hard to
imagine a machine with enough resources to run Android yet with a small
enough boot memory for U-Boot not to fit into it.  I assume the SPL is
pre-installed in some dedicated boot memory (SPI NOR?) whereas the main
storage is left uninitialized during production.  And the NOR flash is
so small that it can't even accommodate a proper U-Boot?

I wonder how many cents it saves the manufacturer (e.g. compared to
having a slightly bigger NOR, or not having the NOR at all and
pre-installing U-Boot on the main storage) 🙁

Anyway, this is clearly getting offtopic.  Thanks for the answer.


=== Stefan


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v4 0/5] Add fastboot to SPL
  2026-08-21 12:21     ` Stefan Monnier
@ 2026-08-21 16:13       ` Carlo Caione
  0 siblings, 0 replies; 14+ messages in thread
From: Carlo Caione @ 2026-08-21 16:13 UTC (permalink / raw)
  To: Stefan Monnier, Carlo Caione; +Cc: u-boot, Jonas Karlman, E Shattow

On Fri Aug 21, 2026 at 2:21 PM CEST, Stefan Monnier wrote:
> Carlo Caione [2026-08-21 09:05:37] wrote:
>> It is possible to include U-Boot proper in the host-loaded bootstrap
>> and use its existing fastboot implementation. That is a valid approach
>> and is preferable where the Boot ROM download limit and memory budget
>> allow it.
>
> Right, that's the situation I'm familiar with.
>
>> But it is not always possible: some platforms (like the one we are
>> enabling) impose a strict size limit on the bootstrap, or only provide
>> enough early memory for the DDR initialization code and (small)
>> SPL-sized payload.
>
> I associate "fastboot" with the Android nebula, so I find it hard to
> imagine a machine with enough resources to run Android yet with a small
> enough boot memory for U-Boot not to fit into it.  I assume the SPL is
> pre-installed in some dedicated boot memory (SPI NOR?) whereas the main
> storage is left uninitialized during production.  And the NOR flash is
> so small that it can't even accommodate a proper U-Boot?
>
> I wonder how many cents it saves the manufacturer (e.g. compared to
> having a slightly bigger NOR, or not having the NOR at all and
> pre-installing U-Boot on the main storage) 🙁

Hi Stefan,

Just one clarification: SPL is not pre-installed in NOR here. The
Boot ROM downloads a transient bootstrap over USB into a fixed-size
on-chip memory window. That downloaded bootstrap then contains the DDR
initialization code and SPL, while the eMMC may be completely blank.

Also fastboot is used only as the provisioning protocol; it does not
imply Android.

For more info about the SPL on this kind of platforms you can also look
at [0], there is some documentation about this in there.

> Anyway, this is clearly getting offtopic.  Thanks for the answer.

Thanks for the discussion :)

Cheers,

[0] https://lore.kernel.org/all/20260814-ccaione-upstream-mt8390-spl-v4-0-f4f92978a79e@baylibre.com/

--
Carlo Caione

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v4 0/5] Add fastboot to SPL
  2026-08-20 18:08 [PATCH v4 0/5] Add fastboot to SPL Carlo Caione
                   ` (4 preceding siblings ...)
  2026-08-20 18:08 ` [PATCH v4 5/5] fastboot: add " Carlo Caione
@ 2026-09-04  7:06 ` Carlo Caione
  2026-09-06 15:48   ` Carlo Caione
  5 siblings, 1 reply; 14+ messages in thread
From: Carlo Caione @ 2026-09-04  7:06 UTC (permalink / raw)
  To: u-boot, GSS_MTK_Uboot_upstream
  Cc: Suhrid Subramaniam, Macpaul Lin (林智斌),
	Pablo Sun (孫毓翔), Arnaud Ferraris,
	Mattijs Korpershoek, Tom Rini, Simon Glass, Sam Day,
	Quentin Schulz, David Lechner, Vitor Sato Eschholz,
	Lukasz Majewski, Marek Vasut, Peng Fan, Jaehoon Chung,
	Neil Armstrong, Julien Masson, Alexey Charkov, Adrian Freihofer,
	Francois Berder, Ilias Apalodimas, Marek Vasut, Vincent Jardin,
	Peter Robinson

On Thu, Aug 20, 2026 at 20:08:24 +0100, Carlo Caione wrote:
> Some recovery and initial-provisioning flows need a standard host protocol
> before usable firmware is available in persistent storage. U-Boot already
> provides fastboot, but the implementation can currently be started only
> from the U-Boot-proper command line.

Hey Mattijs (and all), could you please take a look at this again?

Cheers,

--
Carlo Caione
 

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v4 0/5] Add fastboot to SPL
  2026-09-04  7:06 ` [PATCH v4 0/5] Add fastboot to SPL Carlo Caione
@ 2026-09-06 15:48   ` Carlo Caione
  2026-09-07  8:48     ` Mattijs Korpershoek
  0 siblings, 1 reply; 14+ messages in thread
From: Carlo Caione @ 2026-09-06 15:48 UTC (permalink / raw)
  To: u-boot, GSS_MTK_Uboot_upstream
  Cc: Suhrid Subramaniam, Macpaul Lin (林智斌),
	Pablo Sun (孫毓翔), Arnaud Ferraris,
	Mattijs Korpershoek, Tom Rini, Simon Glass, Sam Day,
	Quentin Schulz, David Lechner, Vitor Sato Eschholz,
	Lukasz Majewski, Marek Vasut, Peng Fan, Jaehoon Chung,
	Neil Armstrong, Julien Masson, Alexey Charkov, Adrian Freihofer,
	Francois Berder, Ilias Apalodimas, Marek Vasut, Vincent Jardin,
	Peter Robinson

On Fri, Sep 04, 2026 at 09:06:39 +0100, Carlo Caione wrote:
> On Thu, Aug 20, 2026 at 20:08:24 +0100, Carlo Caione wrote:
> > Some recovery and initial-provisioning flows need a standard host protocol
> > before usable firmware is available in persistent storage. U-Boot already
> > provides fastboot, but the implementation can currently be started only
> > from the U-Boot-proper command line.
> 
> Hey Mattijs (and all), could you please take a look at this again?

Actually I got an off-list review so I'm preparing a V5.

Thanks,

--
Carlo Caione

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v4 0/5] Add fastboot to SPL
  2026-09-06 15:48   ` Carlo Caione
@ 2026-09-07  8:48     ` Mattijs Korpershoek
  0 siblings, 0 replies; 14+ messages in thread
From: Mattijs Korpershoek @ 2026-09-07  8:48 UTC (permalink / raw)
  To: Carlo Caione, u-boot, GSS_MTK_Uboot_upstream
  Cc: Suhrid Subramaniam, Macpaul Lin (林智斌),
	Pablo Sun (孫毓翔), Arnaud Ferraris, Tom Rini,
	Simon Glass, Sam Day, Quentin Schulz, David Lechner,
	Vitor Sato Eschholz, Lukasz Majewski, Marek Vasut, Peng Fan,
	Jaehoon Chung, Neil Armstrong, Julien Masson, Alexey Charkov,
	Adrian Freihofer, Francois Berder, Ilias Apalodimas, Marek Vasut,
	Vincent Jardin, Peter Robinson

On Sun, Sep 06, 2026 at 17:48, Carlo Caione <ccaione@baylibre.com> wrote:

> On Fri, Sep 04, 2026 at 09:06:39 +0100, Carlo Caione wrote:
>> On Thu, Aug 20, 2026 at 20:08:24 +0100, Carlo Caione wrote:
>> > Some recovery and initial-provisioning flows need a standard host protocol
>> > before usable firmware is available in persistent storage. U-Boot already
>> > provides fastboot, but the implementation can currently be started only
>> > from the U-Boot-proper command line.
>> 
>> Hey Mattijs (and all), could you please take a look at this again?
>
> Actually I got an off-list review so I'm preparing a V5.

I'll have a look at V5 this week.

Sorry for the delays

Cheers
Mattijs

>
> Thanks,
>
> --
> Carlo Caione

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2026-09-07  8:49 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-20 18:08 [PATCH v4 0/5] Add fastboot to SPL Carlo Caione
2026-08-20 18:08 ` [PATCH v4 1/5] fastboot: factor out the USB session runner Carlo Caione
2026-08-20 18:08 ` [PATCH v4 2/5] fastboot: use the common handler for USB reboot Carlo Caione
2026-08-20 18:08 ` [PATCH v4 3/5] fastboot: make shared configuration checks phase-aware Carlo Caione
2026-08-20 18:08 ` [PATCH v4 4/5] image: sparse: add phase-aware SPL support Carlo Caione
2026-08-20 18:08 ` [PATCH v4 5/5] fastboot: add " Carlo Caione
2026-09-04  7:06 ` [PATCH v4 0/5] Add fastboot to SPL Carlo Caione
2026-09-06 15:48   ` Carlo Caione
2026-09-07  8:48     ` Mattijs Korpershoek
     [not found] <20260820-ccaione-upstream-spl-fastboot-v4-0-57e5ef71c74d__17726.0234997206$1787249364$gmane$org@baylibre.com>
2026-08-20 18:50 ` Stefan Monnier
2026-08-21  4:05   ` E Shattow
2026-08-21  7:05   ` Carlo Caione
2026-08-21 12:21     ` Stefan Monnier
2026-08-21 16:13       ` Carlo Caione

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).