diff options
| author | Tom Rini <[email protected]> | 2025-11-07 08:56:22 -0600 |
|---|---|---|
| committer | Tom Rini <[email protected]> | 2025-11-07 08:56:22 -0600 |
| commit | 64b3478eb51d246a2790dce99fe0be330b9c2cc6 (patch) | |
| tree | cc91a54d37906fc73c8f5b7ed3dfbdaf1a6389e5 | |
| parent | df786b4c57f582b4f875effe68d3ae22bbb478a9 (diff) | |
| parent | 10da28729949f3e2160f98d82df45833d4c175cf (diff) | |
Merge tag 'u-boot-dfu-20251107' of https://source.denx.de/u-boot/custodians/u-boot-dfu
u-boot-dfu-20251107:
CI: https://source.denx.de/u-boot/custodians/u-boot-dfu/-/pipelines/28223
Android:
* Add bootargs environment to kernel commandline
DFU:
* Support DFU over PCIe in SPL
| -rw-r--r-- | boot/bootmeth_android.c | 35 | ||||
| -rw-r--r-- | common/spl/Kconfig | 62 | ||||
| -rw-r--r-- | common/spl/spl_dfu.c | 91 | ||||
| -rw-r--r-- | common/spl/spl_ram.c | 18 | ||||
| -rw-r--r-- | drivers/Makefile | 1 |
5 files changed, 207 insertions, 0 deletions
diff --git a/boot/bootmeth_android.c b/boot/bootmeth_android.c index 8c2bde10e17..1374551dbeb 100644 --- a/boot/bootmeth_android.c +++ b/boot/bootmeth_android.c @@ -512,6 +512,37 @@ static int run_avb_verification(struct bootflow *bflow) } #endif /* AVB_VERIFY */ +static int append_bootargs_to_cmdline(struct bootflow *bflow) +{ + char *bootargs; + int len = 0; + + /* + * Check any additionnal bootargs coming from U-Boot env. If any, + * merge them with the current cmdline + */ + bootargs = env_get("bootargs"); + if (bootargs) { + len += strlen(bootargs) + 1; /* Extra space character needed */ + len += strlen(bflow->cmdline); + + char *newcmdline = malloc(len + 1); /* +1 for the '\0' */ + + if (!newcmdline) + return log_msg_ret("newcmdline malloc", -ENOMEM); + + strcpy(newcmdline, bootargs); + strcat(newcmdline, " "); + strcat(newcmdline, bflow->cmdline); + + /* Free the previous cmdline and replace it */ + free(bflow->cmdline); + bflow->cmdline = newcmdline; + } + + return 0; +} + static int boot_android_normal(struct bootflow *bflow) { struct blk_desc *desc = dev_get_uclass_plat(bflow->blk); @@ -546,6 +577,10 @@ static int boot_android_normal(struct bootflow *bflow) if (priv->slot) free(priv->slot); + ret = append_bootargs_to_cmdline(bflow); + if (ret < 0) + return log_msg_ret("bootargs append", ret); + ret = bootm_boot_start(loadaddr, bflow->cmdline); return log_msg_ret("boot", ret); diff --git a/common/spl/Kconfig b/common/spl/Kconfig index 9edea35e26a..8dade2b501e 100644 --- a/common/spl/Kconfig +++ b/common/spl/Kconfig @@ -1312,6 +1312,14 @@ config SPL_PCI necessary driver support. This enables the drivers in drivers/pci as part of an SPL build. +config SPL_PCI_ENDPOINT + bool "Support for PCI endpoint drivers" + help + Enable this configuration option to support configurable PCI + endpoints at SPL. This should be enabled if the platform has + a PCI controllers that can operate in endpoint mode (as a device + connected to PCI host or bridge). + config SPL_PCH bool "Support PCH drivers" help @@ -1372,6 +1380,60 @@ config SPL_RAM_DEVICE be already in memory when SPL takes over, e.g. loaded by the boot ROM. +config SPL_PCI_DFU + bool "PCIe boot support" + depends on SPL_PCI_ENDPOINT + help + This config enables support to download bootloaders over PCIe + when device is acting as an PCI endpoint. + +if SPL_PCI_DFU + +config SPL_PCI_DFU_SPL_LOAD_FIT_ADDRESS + hex "Address to load FIT image when booting via DFU over PCIe" + help + Specify the load address of the fit image that will be loaded + by SPL via DFU over PCIe. + +config SPL_PCI_DFU_BAR_SIZE + hex "BAR size to advertise for PCIe DFU" + default 0x800000 + help + This config sets the size of BAR to be advertised to the Root + Complex. The size should be large enough to fit the FIT image + being downloaded via DFU over PCIe. + +config SPL_PCI_DFU_MAGIC_WORD + hex "Completion magic word for PCIe DFU boot" + default 0xdeadbeef + help + Specify the magic word which will be written to a specific + address to signal the completion of transfer of FIT image + when using DFU over PCIe to download the image. Size of magic + word should be 32-bit. + +config SPL_PCI_DFU_VENDOR_ID + hex "PCI Vendor ID for PCI endpoint" + help + PCI Vendor ID for endpoint device for DFU over PCIe. This should + be set to your assigned 16-bit PCI Vendor ID. + +config SPL_PCI_DFU_DEVICE_ID + hex "PCI Vendor ID for PCI endpoint" + help + A 16-bit PCI Vendor ID for endpoint device for DFU over PCIe. + +config SPL_PCI_DFU_BOOT_PHASE + string "Current boot phase for PCI DFU boot" + help + Specify the current boot phase when booting via DFU over PCIe. + This value can be read by the root complex to determine the + current boot phase. Value of this config is written to memory + location (BAR_start + PCI_DFU_BAR_SIZE - 70). Max size of this + config is 63 bytes. + +endif + config SPL_REMOTEPROC bool "Support REMOTEPROCS" default y if (CPU_V7R && ARCH_K3) diff --git a/common/spl/spl_dfu.c b/common/spl/spl_dfu.c index e9f381c392c..b09f82790c9 100644 --- a/common/spl/spl_dfu.c +++ b/common/spl/spl_dfu.c @@ -15,6 +15,17 @@ #include <usb.h> #include <dfu.h> #include <linux/printk.h> +#include <pci_ep.h> +#include <dm/uclass.h> +#include <cpu_func.h> +#include <linux/io.h> + +/* + * Macros define size of magic word and boot phase string + * in bytes. + */ +#define MAGIC_WORD_SIZE 4 +#define BOOT_PHASE_STRING_SIZE 63 static int run_dfu(int usb_index, char *interface, char *devstring) { @@ -32,11 +43,91 @@ exit: return ret; } +#ifdef CONFIG_SPL_PCI_DFU +static int dfu_over_pcie(void) +{ + u32 offset, magic_word; + volatile void *addr; + struct udevice *dev; + struct pci_bar bar; + struct pci_ep_header hdr; + uint fn = 0; + int ret; + char *bootphase; + + uclass_get_device_by_seq(UCLASS_PCI_EP, 0, &dev); + if (!dev) { + pr_err("Failed to get pci ep device\n"); + return -ENODEV; + } + + hdr.deviceid = CONFIG_SPL_PCI_DFU_DEVICE_ID; + hdr.vendorid = CONFIG_SPL_PCI_DFU_VENDOR_ID; + hdr.baseclass_code = PCI_BASE_CLASS_MEMORY; + hdr.subclass_code = PCI_CLASS_MEMORY_RAM; + + ret = pci_ep_write_header(dev, fn, &hdr); + if (ret) { + pr_err("Failed to write header: %d\n", ret); + return ret; + } + + bar.barno = BAR_0; + bar.phys_addr = (dma_addr_t)CONFIG_SPL_PCI_DFU_SPL_LOAD_FIT_ADDRESS; + bar.flags = PCI_BASE_ADDRESS_SPACE_MEMORY | + PCI_BASE_ADDRESS_MEM_TYPE_32 | + PCI_BASE_ADDRESS_MEM_PREFETCH; + + bar.size = CONFIG_SPL_PCI_DFU_BAR_SIZE; + + ret = pci_ep_set_bar(dev, fn, &bar); + if (ret) { + pr_err("Failed to set bar: %d\n", ret); + return ret; + } + + ret = pci_ep_start(dev); + if (ret) { + pr_err("Failed to start ep: %d\n", ret); + return ret; + } + + addr = (void *)CONFIG_SPL_PCI_DFU_SPL_LOAD_FIT_ADDRESS; + offset = CONFIG_SPL_PCI_DFU_BAR_SIZE - MAGIC_WORD_SIZE; + + if (sizeof(CONFIG_SPL_PCI_DFU_BOOT_PHASE) > BOOT_PHASE_STRING_SIZE) { + pr_err("Not copying boot phase. String too long\n"); + } else { + bootphase = (char *)(addr + CONFIG_SPL_PCI_DFU_BAR_SIZE - + (BOOT_PHASE_STRING_SIZE + MAGIC_WORD_SIZE + 1)); + strlcpy(bootphase, CONFIG_SPL_PCI_DFU_BOOT_PHASE, + sizeof(CONFIG_SPL_PCI_DFU_BOOT_PHASE) + 1); + } + + addr = addr + offset; + magic_word = CONFIG_SPL_PCI_DFU_MAGIC_WORD; + (*(int *)addr) = 0; + flush_dcache_all(); + for (;;) { + if (*(int *)addr == magic_word) + break; + invalidate_dcache_all(); + } + + return 0; +} +#endif + int spl_dfu_cmd(int usbctrl, char *dfu_alt_info, char *interface, char *devstr) { char *str_env; int ret; +#ifdef CONFIG_SPL_PCI_DFU + if (spl_boot_device() == BOOT_DEVICE_PCIE) + return dfu_over_pcie(); +#endif + /* set default environment */ env_set_default(NULL, 0); str_env = env_get(dfu_alt_info); diff --git a/common/spl/spl_ram.c b/common/spl/spl_ram.c index 71b7a8374bb..0c501cf02f2 100644 --- a/common/spl/spl_ram.c +++ b/common/spl/spl_ram.c @@ -27,6 +27,11 @@ static ulong spl_ram_load_read(struct spl_load_info *load, ulong sector, if (IS_ENABLED(CONFIG_SPL_LOAD_FIT)) { addr = IF_ENABLED_INT(CONFIG_SPL_LOAD_FIT, CONFIG_SPL_LOAD_FIT_ADDRESS); + +#ifdef CONFIG_SPL_PCI_DFU + if (spl_boot_device() == BOOT_DEVICE_PCIE) + addr = CONFIG_SPL_PCI_DFU_SPL_LOAD_FIT_ADDRESS; +#endif } addr += sector; if (CONFIG_IS_ENABLED(IMAGE_PRE_LOAD)) @@ -47,6 +52,11 @@ static int spl_ram_load_image(struct spl_image_info *spl_image, if (IS_ENABLED(CONFIG_SPL_LOAD_FIT)) { addr = IF_ENABLED_INT(CONFIG_SPL_LOAD_FIT, CONFIG_SPL_LOAD_FIT_ADDRESS); + +#ifdef CONFIG_SPL_PCI_DFU + if (spl_boot_device() == BOOT_DEVICE_PCIE) + addr = CONFIG_SPL_PCI_DFU_SPL_LOAD_FIT_ADDRESS; +#endif } if (CONFIG_IS_ENABLED(IMAGE_PRE_LOAD)) { @@ -64,6 +74,11 @@ static int spl_ram_load_image(struct spl_image_info *spl_image, spl_dfu_cmd(0, "dfu_alt_info_ram", "ram", "0"); #endif +#if CONFIG_IS_ENABLED(PCI_DFU) + if (bootdev->boot_device == BOOT_DEVICE_PCIE) + spl_dfu_cmd(0, "dfu_alt_info_ram", "ram", "0"); +#endif + if (IS_ENABLED(CONFIG_SPL_LOAD_FIT) && image_get_magic(header) == FDT_MAGIC) { struct spl_load_info load; @@ -102,3 +117,6 @@ SPL_LOAD_IMAGE_METHOD("RAM", 0, BOOT_DEVICE_RAM, spl_ram_load_image); #if CONFIG_IS_ENABLED(DFU) SPL_LOAD_IMAGE_METHOD("DFU", 0, BOOT_DEVICE_DFU, spl_ram_load_image); #endif +#if CONFIG_IS_ENABLED(PCI_DFU) +SPL_LOAD_IMAGE_METHOD("PCIE", 0, BOOT_DEVICE_PCIE, spl_ram_load_image); +#endif diff --git a/drivers/Makefile b/drivers/Makefile index 7560008a842..77fc66eb8ba 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -26,6 +26,7 @@ obj-$(CONFIG_MULTIPLEXER) += mux/ obj-$(CONFIG_$(PHASE_)ETH) += net/ obj-$(CONFIG_$(PHASE_)PCH) += pch/ obj-$(CONFIG_$(PHASE_)PCI) += pci/ +obj-$(CONFIG_$(PHASE_)PCI_ENDPOINT) += pci_endpoint/ obj-$(CONFIG_$(PHASE_)PHY) += phy/ obj-$(CONFIG_$(PHASE_)PINCTRL) += pinctrl/ obj-$(CONFIG_$(PHASE_)POWER) += power/ |
