Merge branch '2022-01-28-assorted-fixes'

- Extend the pci command to support a few more features.
- Add support for custom SPL boot device names (so it's easier for users
  to understand)
- Updates for am64x to address some review comments.
- Migration deadline notice for DM_SERIAL
- coreboot payload test
- Support rsa3072 signatures.
- DFU should skip writing empty UBI pages, bootcount printf format char
  correction.
diff --git a/.azure-pipelines.yml b/.azure-pipelines.yml
index c0f72a8..f2aa332 100644
--- a/.azure-pipelines.yml
+++ b/.azure-pipelines.yml
@@ -222,6 +222,10 @@
           TEST_PY_TEST_SPEC: "test_ofplatdata or test_handoff or test_spl"
         sandbox_flattree:
           TEST_PY_BD: "sandbox_flattree"
+        coreboot:
+          TEST_PY_BD: "coreboot"
+          TEST_PY_ID: "--id qemu"
+          TEST_PY_TEST_SPEC: "not sleep"
         evb_ast2500:
           TEST_PY_BD: "evb-ast2500"
           TEST_PY_ID: "--id qemu"
@@ -353,6 +357,12 @@
               genimage --inputpath . --config board/sifive/unleashed/genimage_spi-nor.cfg;
               cp images/spi-nor.img ${UBOOT_TRAVIS_BUILD_DIR}/;
           fi
+          if [[ "${TEST_PY_BD}" == "coreboot" ]]; then
+              wget -O - "https://drive.google.com/uc?id=1x6nrtWIyIRPLS2cQBwYTnT2TbOI8UjmM&export=download" |xz -dc >${UBOOT_TRAVIS_BUILD_DIR}/coreboot.rom;
+              wget -O - "https://drive.google.com/uc?id=149Cz-5SZXHNKpi9xg6R_5XITWohu348y&export=download" >cbfstool;
+              chmod a+x cbfstool;
+              ./cbfstool ${UBOOT_TRAVIS_BUILD_DIR}/coreboot.rom add-flat-binary -f ${UBOOT_TRAVIS_BUILD_DIR}/u-boot.bin -n fallback/payload -c LZMA -l 0x1110000 -e 0x1110000;
+          fi
           virtualenv -p /usr/bin/python3 /tmp/venv
           . /tmp/venv/bin/activate
           pip install -r test/py/requirements.txt
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 4c44c01..75ad67f 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -52,6 +52,16 @@
         genimage --inputpath . --config board/sifive/unleashed/genimage_spi-nor.cfg;
         cp images/spi-nor.img ${UBOOT_TRAVIS_BUILD_DIR}/;
       fi
+    - if [[ "${TEST_PY_BD}" == "coreboot" ]]; then
+        wget -O -
+          "https://drive.google.com/uc?id=1x6nrtWIyIRPLS2cQBwYTnT2TbOI8UjmM&export=download" |
+          xz -dc >${UBOOT_TRAVIS_BUILD_DIR}/coreboot.rom;
+        wget -O -
+          "https://drive.google.com/uc?id=149Cz-5SZXHNKpi9xg6R_5XITWohu348y&export=download" >
+          cbfstool;
+        chmod a+x cbfstool;
+        ./cbfstool ${UBOOT_TRAVIS_BUILD_DIR}/coreboot.rom add-flat-binary -f ${UBOOT_TRAVIS_BUILD_DIR}/u-boot.bin -n fallback/payload -c LZMA -l 0x1110000 -e 0x1110000;
+      fi
     - virtualenv -p /usr/bin/python3 /tmp/venv
     - . /tmp/venv/bin/activate
     - pip install -r test/py/requirements.txt
@@ -61,6 +71,10 @@
       ./test/py/test.py -ra --bd ${TEST_PY_BD} ${TEST_PY_ID}
         ${TEST_PY_TEST_SPEC:+"-k ${TEST_PY_TEST_SPEC}"}
         --build-dir "$UBOOT_TRAVIS_BUILD_DIR"
+    # It seems that the files in /tmp go away, so copy out what we need
+    - if [[ "${TEST_PY_BD}" == "coreboot" ]]; then
+        cp -v /tmp/coreboot/*.{html,css} .;
+      fi
 
 build all 32bit ARM platforms:
   stage: world build
@@ -387,3 +401,15 @@
     TEST_PY_TEST_SPEC: "not sleep"
     TEST_PY_ID: "--id qemu"
   <<: *buildman_and_testpy_dfn
+
+coreboot test.py:
+  variables:
+    TEST_PY_BD: "coreboot"
+    TEST_PY_TEST_SPEC: "not sleep"
+    TEST_PY_ID: "--id qemu"
+  artifacts:
+    paths:
+      - "*.html"
+      - "*.css"
+    expire_in: 1 week
+  <<: *buildman_and_testpy_dfn
diff --git a/Makefile b/Makefile
index 10879f1..2121245 100644
--- a/Makefile
+++ b/Makefile
@@ -1133,6 +1133,7 @@
 	@# confuses this rule. Use if() to send just a single character which
 	@# is enable to tell 'deprecated' that one of these symbols exists
 	$(call deprecated,CONFIG_TIMER,Timer drivers,v2023.01,$(if $(strip $(CONFIG_SYS_TIMER_RATE)$(CONFIG_SYS_TIMER_COUNTER)),x))
+	$(call deprecated,CONFIG_DM_SERIAL,Serial drivers,v2023.04,$(CONFIG_SERIAL))
 	@# Check that this build does not use CONFIG options that we do not
 	@# know about unless they are in Kconfig. All the existing CONFIG
 	@# options are whitelisted, so new ones should not be added.
diff --git a/arch/arm/dts/k3-am642-r5-sk.dts b/arch/arm/dts/k3-am642-r5-sk.dts
index 3a17448..7d1cb85 100644
--- a/arch/arm/dts/k3-am642-r5-sk.dts
+++ b/arch/arm/dts/k3-am642-r5-sk.dts
@@ -231,23 +231,12 @@
 		     &rgmii2_pins_default>;
 };
 
-&cpsw_port1 {
-	phy-mode = "rgmii-rxid";
-	phy-handle = <&cpsw3g_phy0>;
-};
-
 &cpsw_port2 {
 	phy-mode = "rgmii-rxid";
 	phy-handle = <&cpsw3g_phy1>;
 };
 
 &cpsw3g_mdio {
-	cpsw3g_phy0: ethernet-phy@0 {
-		reg = <0>;
-		ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
-		ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
-	};
-
 	cpsw3g_phy1: ethernet-phy@1 {
 		reg = <1>;
 		ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
diff --git a/arch/arm/dts/k3-am642-sk-u-boot.dtsi b/arch/arm/dts/k3-am642-sk-u-boot.dtsi
index 2f5cfaa..e5c26b8 100644
--- a/arch/arm/dts/k3-am642-sk-u-boot.dtsi
+++ b/arch/arm/dts/k3-am642-sk-u-boot.dtsi
@@ -117,10 +117,6 @@
 	u-boot,dm-spl;
 };
 
-&cpsw_port1 {
-	u-boot,dm-spl;
-};
-
 &main_bcdma {
 	u-boot,dm-spl;
 };
@@ -141,10 +137,6 @@
 	u-boot,dm-spl;
 };
 
-&cpsw3g_phy0 {
-	u-boot,dm-spl;
-};
-
 &cpsw3g_phy1 {
 	u-boot,dm-spl;
 };
diff --git a/cmd/pci.c b/cmd/pci.c
index 389b41c..a99e8f8 100644
--- a/cmd/pci.c
+++ b/cmd/pci.c
@@ -256,10 +256,8 @@
     }
 }
 
-static void pciinfo_header(int busnum, bool short_listing)
+static void pciinfo_header(bool short_listing)
 {
-	printf("Scanning PCI devices on bus %d\n", busnum);
-
 	if (short_listing) {
 		printf("BusDevFun  VendorId   DeviceId   Device Class       Sub-Class\n");
 		printf("_____________________________________________________________\n");
@@ -288,11 +286,15 @@
 	       pci_class_str(class), subclass);
 }
 
-static void pciinfo(struct udevice *bus, bool short_listing)
+static void pciinfo(struct udevice *bus, bool short_listing, bool multi)
 {
 	struct udevice *dev;
 
-	pciinfo_header(dev_seq(bus), short_listing);
+	if (!multi)
+		printf("Scanning PCI devices on bus %d\n", dev_seq(bus));
+
+	if (!multi || dev_seq(bus) == 0)
+		pciinfo_header(short_listing);
 
 	for (device_find_first_child(bus, &dev);
 	     dev;
@@ -443,7 +445,7 @@
 
 static void pci_show_regions(struct udevice *bus)
 {
-	struct pci_controller *hose = dev_get_uclass_priv(bus);
+	struct pci_controller *hose = dev_get_uclass_priv(pci_get_controller(bus));
 	const struct pci_region *reg;
 	int i, j;
 
@@ -452,6 +454,7 @@
 		return;
 	}
 
+	printf("Buses %02x-%02x\n", hose->first_busno, hose->last_busno);
 	printf("#   %-18s %-18s %-18s  %s\n", "Bus start", "Phys start", "Size",
 	       "Flags");
 	for (i = 0, reg = hose->regions; i < hose->region_count; i++, reg++) {
@@ -482,10 +485,11 @@
 	ulong addr = 0, value = 0, cmd_size = 0;
 	enum pci_size_t size = PCI_SIZE_32;
 	struct udevice *dev, *bus;
-	int busnum = 0;
+	int busnum = -1;
 	pci_dev_t bdf = 0;
 	char cmd = 's';
 	int ret = 0;
+	char *endp;
 
 	if (argc > 1)
 		cmd = argv[1][0];
@@ -520,8 +524,36 @@
 				value = 0;
 				argc--;
 			}
+			if (argc > 2 || (argc > 1 && cmd != 'r' && argv[1][0] != 's')) {
+				if (argv[argc - 1][0] != '*') {
+					busnum = hextoul(argv[argc - 1], &endp);
+					if (*endp)
+						goto usage;
+				}
+				argc--;
+			}
+			if (cmd == 'r' && argc > 2)
+				goto usage;
+			else if (cmd != 'r' && (argc > 2 || (argc == 2 && argv[1][0] != 's')))
+				goto usage;
+		}
+		if (busnum == -1) {
+			if (cmd != 'r') {
+				for (busnum = 0;
+				     uclass_get_device_by_seq(UCLASS_PCI, busnum, &bus) == 0;
+				     busnum++)
+					pciinfo(bus, value, true);
+			} else {
+				for (busnum = 0;
+				     uclass_get_device_by_seq(UCLASS_PCI, busnum, &bus) == 0;
+				     busnum++) {
+					/* Regions are controller specific so skip non-root buses */
+					if (device_is_on_pci_bus(bus))
+						continue;
+					pci_show_regions(bus);
+				}
+			}
-			if (argc > 1)
-				busnum = hextoul(argv[1], NULL);
+			return 0;
 		}
 		ret = uclass_get_device_by_seq(UCLASS_PCI, busnum, &bus);
 		if (ret) {
@@ -531,7 +563,7 @@
 		if (cmd == 'r')
 			pci_show_regions(bus);
 		else
-			pciinfo(bus, value);
+			pciinfo(bus, value, false);
 		return 0;
 	}
 
@@ -578,7 +610,7 @@
 
 #ifdef CONFIG_SYS_LONGHELP
 static char pci_help_text[] =
-	"[bus] [long]\n"
+	"[bus|*] [long]\n"
 	"    - short or long list of PCI devices on bus 'bus'\n"
 	"pci enum\n"
 	"    - Enumerate PCI buses\n"
@@ -586,7 +618,7 @@
 	"    - show header of PCI device 'bus.device.function'\n"
 	"pci bar b.d.f\n"
 	"    - show BARs base and size for device b.d.f'\n"
-	"pci regions\n"
+	"pci regions [bus|*]\n"
 	"    - show PCI regions\n"
 	"pci display[.b, .w, .l] b.d.f [address] [# of objects]\n"
 	"    - display PCI configuration space (CFG)\n"
diff --git a/common/spl/spl.c b/common/spl/spl.c
index 6945ecb..884102b 100644
--- a/common/spl/spl.c
+++ b/common/spl/spl.c
@@ -174,6 +174,11 @@
 {
 }
 
+__weak const char *spl_board_loader_name(u32 boot_device)
+{
+	return NULL;
+}
+
 #if CONFIG_IS_ENABLED(OPTEE_IMAGE)
 __weak void __noreturn jump_to_image_optee(struct spl_image_info *spl_image)
 {
diff --git a/configs/am64x_evm_a53_defconfig b/configs/am64x_evm_a53_defconfig
index 3ce2129..77010a3 100644
--- a/configs/am64x_evm_a53_defconfig
+++ b/configs/am64x_evm_a53_defconfig
@@ -30,6 +30,7 @@
 CONFIG_SPL_LOAD_FIT_ADDRESS=0x81000000
 CONFIG_BOOTCOMMAND="run findfdt; run envboot; run init_${boot}; run get_kern_${boot}; run get_fdt_${boot}; run run_kern"
 CONFIG_BOARD_LATE_INIT=y
+CONFIG_SPL_BOARD_INIT=y
 CONFIG_SPL_SYS_MALLOC_SIMPLE=y
 CONFIG_SPL_STACK_R=y
 CONFIG_SPL_SEPARATE_BSS=y
@@ -38,8 +39,11 @@
 CONFIG_SPL_DMA=y
 CONFIG_SPL_ENV_SUPPORT=y
 CONFIG_SPL_I2C=y
+CONFIG_SPL_ETH=y
 CONFIG_SPL_DM_MAILBOX=y
 CONFIG_SPL_DM_SPI_FLASH=y
+CONFIG_SPL_NET=y
+CONFIG_SPL_NET_VCI_STRING="AM64X U-Boot A53 SPL"
 CONFIG_SPL_POWER_DOMAIN=y
 CONFIG_SPL_RAM_SUPPORT=y
 CONFIG_SPL_RAM_DEVICE=y
diff --git a/configs/am64x_evm_r5_defconfig b/configs/am64x_evm_r5_defconfig
index 2b609ad..e51a251 100644
--- a/configs/am64x_evm_r5_defconfig
+++ b/configs/am64x_evm_r5_defconfig
@@ -38,10 +38,14 @@
 CONFIG_SPL_EARLY_BSS=y
 CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR=y
 CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR=0x400
+CONFIG_SPL_DMA=y
 CONFIG_SPL_ENV_SUPPORT=y
 CONFIG_SPL_I2C=y
+CONFIG_SPL_ETH=y
 CONFIG_SPL_DM_MAILBOX=y
 CONFIG_SPL_DM_SPI_FLASH=y
+CONFIG_SPL_NET=y
+CONFIG_SPL_NET_VCI_STRING="AM64X U-Boot R5 SPL"
 CONFIG_SPL_DM_RESET=y
 CONFIG_SPL_POWER_DOMAIN=y
 CONFIG_SPL_RAM_SUPPORT=y
@@ -63,6 +67,7 @@
 CONFIG_CMD_USB=y
 CONFIG_CMD_USB_MASS_STORAGE=y
 # CONFIG_CMD_SETEXPR is not set
+CONFIG_CMD_DHCP=y
 CONFIG_CMD_TIME=y
 CONFIG_CMD_FAT=y
 CONFIG_OF_CONTROL=y
@@ -90,12 +95,15 @@
 CONFIG_DFU_RAM=y
 CONFIG_DFU_SF=y
 CONFIG_SYS_DFU_DATA_BUF_SIZE=0x5000
+CONFIG_DMA_CHANNELS=y
+CONFIG_TI_K3_NAVSS_UDMA=y
 CONFIG_TI_SCI_PROTOCOL=y
 CONFIG_DA8XX_GPIO=y
 CONFIG_DM_I2C=y
 CONFIG_SYS_I2C_OMAP24XX=y
 CONFIG_DM_MAILBOX=y
 CONFIG_K3_SEC_PROXY=y
+CONFIG_SPL_MISC=y
 CONFIG_MMC_SDHCI=y
 CONFIG_MMC_SDHCI_ADMA=y
 CONFIG_SPL_MMC_SDHCI_ADMA=y
@@ -108,6 +116,9 @@
 CONFIG_PHY_CADENCE_SIERRA=y
 CONFIG_PHY_CADENCE_TORRENT=y
 CONFIG_PHY_J721E_WIZ=y
+CONFIG_PHY_TI_DP83867=y
+CONFIG_DM_ETH=y
+CONFIG_TI_AM65_CPSW_NUSS=y
 CONFIG_PINCTRL=y
 # CONFIG_PINCTRL_GENERIC is not set
 CONFIG_SPL_PINCTRL=y
@@ -125,6 +136,7 @@
 CONFIG_RESET_TI_SCI=y
 CONFIG_SPECIFY_CONSOLE_INDEX=y
 CONFIG_DM_SERIAL=y
+CONFIG_SOC_TI=y
 CONFIG_SPI=y
 CONFIG_DM_SPI=y
 CONFIG_CADENCE_QSPI=y
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index 19cde87..d0886b7 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -312,3 +312,4 @@
 CONFIG_UNIT_TEST=y
 CONFIG_UT_TIME=y
 CONFIG_UT_DM=y
+CONFIG_SHA384=y
diff --git a/doc/develop/driver-model/migration.rst b/doc/develop/driver-model/migration.rst
index 10f474e..5a60436 100644
--- a/doc/develop/driver-model/migration.rst
+++ b/doc/develop/driver-model/migration.rst
@@ -118,3 +118,11 @@
 There is only one method to implement, unless you want to support bootstage,
 in which case you need an early timer also. For example drivers, see
 sandbox_timer.c and rockchip_timer.c
+
+CONFIG_DM_SERIAL
+----------------
+Deadline: 2023.04
+
+The serial subsystem has supported the driver model since late 2014.
+Maintainers should submit patches switching over to using CONFIG_DM_SERIAL and
+other base driver model options in time for inclusion in the 2022.10 release.
diff --git a/drivers/bootcount/bootcount_syscon.c b/drivers/bootcount/bootcount_syscon.c
index 413fd5b..f80d870 100644
--- a/drivers/bootcount/bootcount_syscon.c
+++ b/drivers/bootcount/bootcount_syscon.c
@@ -107,8 +107,8 @@
 		return -EINVAL;
 	}
 	if (reg_size != 4) {
-		dev_err(dev, "%s: Unsupported register size: %d\n", __func__,
-			reg_size);
+		dev_err(dev, "%s: Unsupported register size: %pa\n", __func__,
+			&reg_size);
 		return -EINVAL;
 	}
 
diff --git a/drivers/dfu/dfu_mtd.c b/drivers/dfu/dfu_mtd.c
index 0b7f177..cce9ce0 100644
--- a/drivers/dfu/dfu_mtd.c
+++ b/drivers/dfu/dfu_mtd.c
@@ -18,6 +18,20 @@
 	return !do_div(size, mtd->erasesize);
 }
 
+/* Logic taken from cmd/mtd.c:mtd_oob_write_is_empty() */
+static bool mtd_page_is_empty(struct mtd_oob_ops *op)
+{
+	int i;
+
+	for (i = 0; i < op->len; i++)
+		if (op->datbuf[i] != 0xff)
+			return false;
+
+	/* oob is not used, with MTD_OPS_AUTO_OOB & ooblen=0 */
+
+	return true;
+}
+
 static int mtd_block_op(enum dfu_op op, struct dfu_entity *dfu,
 			u64 offset, void *buf, long *len)
 {
@@ -129,8 +143,14 @@
 
 		if (op == DFU_OP_READ)
 			ret = mtd_read_oob(mtd, off, &io_op);
-		else
+		else if (has_pages && dfu->data.mtd.ubi && mtd_page_is_empty(&io_op)) {
+			/* in case of ubi partition, do not write an empty page, only skip it */
+			ret = 0;
+			io_op.retlen = mtd->writesize;
+			io_op.oobretlen = mtd->oobsize;
+		} else {
 			ret = mtd_write_oob(mtd, off, &io_op);
+		}
 
 		if (ret) {
 			printf("Failure while %s at offset 0x%llx\n",
diff --git a/drivers/net/ti/am65-cpsw-nuss.c b/drivers/net/ti/am65-cpsw-nuss.c
index 6ae69b5..454986f 100644
--- a/drivers/net/ti/am65-cpsw-nuss.c
+++ b/drivers/net/ti/am65-cpsw-nuss.c
@@ -752,7 +752,7 @@
 
 		ret = device_bind_driver_to_node(dev, "am65_cpsw_nuss_port", ofnode_get_name(node), node, &port_dev);
 		if (ret)
-			printf("SCREEEM\n");
+			dev_err(dev, "Failed to bind to %s node\n", ofnode_get_name(node));
 	}
 
 	for (i = 0; i < AM65_CPSW_CPSWNU_MAX_PORTS; i++) {
diff --git a/drivers/pci/pci-uclass.c b/drivers/pci/pci-uclass.c
index c66cd75..33dda00 100644
--- a/drivers/pci/pci-uclass.c
+++ b/drivers/pci/pci-uclass.c
@@ -560,6 +560,8 @@
 		if (pplat->class == (PCI_CLASS_DISPLAY_VGA << 8))
 			set_vga_bridge_bits(dev);
 	}
+	if (hose->last_busno < sub_bus)
+		hose->last_busno = sub_bus;
 	debug("%s: done\n", __func__);
 
 	return log_msg_ret("sub", sub_bus);
diff --git a/fs/squashfs/sqfs.c b/fs/squashfs/sqfs.c
index e2d91c6..5d9c52a 100644
--- a/fs/squashfs/sqfs.c
+++ b/fs/squashfs/sqfs.c
@@ -728,6 +728,8 @@
 	*inode_table = malloc(metablks_count * SQFS_METADATA_BLOCK_SIZE);
 	if (!*inode_table) {
 		ret = -ENOMEM;
+		printf("Error: failed to allocate squashfs inode_table of size %i, increasing CONFIG_SYS_MALLOC_LEN could help\n",
+		       metablks_count * SQFS_METADATA_BLOCK_SIZE);
 		goto free_itb;
 	}
 
diff --git a/include/configs/am64x_evm.h b/include/configs/am64x_evm.h
index 9962408..135cb3c 100644
--- a/include/configs/am64x_evm.h
+++ b/include/configs/am64x_evm.h
@@ -33,7 +33,7 @@
  * our memory footprint. The less we use for BSS the more we have available
  * for everything else.
  */
-#define CONFIG_SPL_BSS_MAX_SIZE		0x1000
+#define CONFIG_SPL_BSS_MAX_SIZE		0x4000
 /*
  * Link BSS to be within SPL in a dedicated region located near the top of
  * the MCU SRAM, this way making it available also before relocation. Note
diff --git a/include/spl.h b/include/spl.h
index 8748497..bb92bc6 100644
--- a/include/spl.h
+++ b/include/spl.h
@@ -463,6 +463,17 @@
 int spl_board_boot_device(u32 boot_device);
 
 /**
+ * spl_board_loader_name() - Return a name for the loader
+ *
+ * This is a weak function which might be overridden by the board code. With
+ * that a board specific value for the device where the U-Boot will be loaded
+ * from can be set. By default it returns NULL.
+ *
+ * @boot_device:	ID of the device which SPL wants to load U-Boot from.
+ */
+const char *spl_board_loader_name(u32 boot_device);
+
+/**
  * jump_to_image_linux() - Jump to a Linux kernel from SPL
  *
  * This jumps into a Linux kernel using the information in @spl_image.
@@ -544,7 +555,9 @@
 static inline const char *spl_loader_name(const struct spl_image_loader *loader)
 {
 #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
-	return loader->name;
+	const char *name;
+	name = spl_board_loader_name(loader->boot_device);
+	return name ?: loader->name;
 #else
 	return NULL;
 #endif
diff --git a/include/u-boot/rsa.h b/include/u-boot/rsa.h
index 01b480d..b9634e3 100644
--- a/include/u-boot/rsa.h
+++ b/include/u-boot/rsa.h
@@ -111,6 +111,7 @@
 #define RSA_DEFAULT_PADDING_NAME		"pkcs-1.5"
 
 #define RSA2048_BYTES	(2048 / 8)
+#define RSA3072_BYTES	(3072 / 8)
 #define RSA4096_BYTES	(4096 / 8)
 
 /* This is the minimum/maximum key size we support, in bits */
diff --git a/lib/rsa/rsa-verify.c b/lib/rsa/rsa-verify.c
index 32c7507..1126640 100644
--- a/lib/rsa/rsa-verify.c
+++ b/lib/rsa/rsa-verify.c
@@ -595,6 +595,12 @@
 	.verify = rsa_verify,
 };
 
+U_BOOT_CRYPTO_ALGO(rsa3072) = {
+	.name = "rsa3072",
+	.key_len = RSA3072_BYTES,
+	.verify = rsa_verify,
+};
+
 U_BOOT_CRYPTO_ALGO(rsa4096) = {
 	.name = "rsa4096",
 	.key_len = RSA4096_BYTES,
diff --git a/test/py/tests/test_vboot.py b/test/py/tests/test_vboot.py
index 095e00c..b080d48 100644
--- a/test/py/tests/test_vboot.py
+++ b/test/py/tests/test_vboot.py
@@ -45,6 +45,8 @@
     ['sha256-pss-pad', 'sha256', '-pss', '-E -p 0x10000', False, False],
     ['sha256-pss-required', 'sha256', '-pss', None, True, False],
     ['sha256-pss-pad-required', 'sha256', '-pss', '-E -p 0x10000', True, True],
+    ['sha384-basic', 'sha384', '', None, False, False],
+    ['sha384-pad', 'sha384', '', '-E -p 0x10000', False, False],
 ]
 
 @pytest.mark.boardspec('sandbox')
@@ -180,10 +182,16 @@
             name: Name of of the key (e.g. 'dev')
         """
         public_exponent = 65537
+
+        if sha_algo == "sha384":
+            rsa_keygen_bits = 3072
+        else:
+            rsa_keygen_bits = 2048
+
         util.run_and_log(cons, 'openssl genpkey -algorithm RSA -out %s%s.key '
-                     '-pkeyopt rsa_keygen_bits:2048 '
+                     '-pkeyopt rsa_keygen_bits:%d '
                      '-pkeyopt rsa_keygen_pubexp:%d' %
-                     (tmpdir, name, public_exponent))
+                     (tmpdir, name, rsa_keygen_bits, public_exponent))
 
         # Create a certificate containing the public key
         util.run_and_log(cons, 'openssl req -batch -new -x509 -key %s%s.key '
diff --git a/test/py/tests/vboot/sign-configs-sha384.its b/test/py/tests/vboot/sign-configs-sha384.its
new file mode 100644
index 0000000..2869401
--- /dev/null
+++ b/test/py/tests/vboot/sign-configs-sha384.its
@@ -0,0 +1,45 @@
+/dts-v1/;
+
+/ {
+	description = "Chrome OS kernel image with one or more FDT blobs";
+	#address-cells = <1>;
+
+	images {
+		kernel {
+			data = /incbin/("test-kernel.bin");
+			type = "kernel_noload";
+			arch = "sandbox";
+			os = "linux";
+			compression = "none";
+			load = <0x4>;
+			entry = <0x8>;
+			kernel-version = <1>;
+			hash-1 {
+				algo = "sha384";
+			};
+		};
+		fdt-1 {
+			description = "snow";
+			data = /incbin/("sandbox-kernel.dtb");
+			type = "flat_dt";
+			arch = "sandbox";
+			compression = "none";
+			fdt-version = <1>;
+			hash-1 {
+				algo = "sha384";
+			};
+		};
+	};
+	configurations {
+		default = "conf-1";
+		conf-1 {
+			kernel = "kernel";
+			fdt = "fdt-1";
+			signature {
+				algo = "sha384,rsa3072";
+				key-name-hint = "dev";
+				sign-images = "fdt", "kernel";
+			};
+		};
+	};
+};
diff --git a/test/py/tests/vboot/sign-images-sha384.its b/test/py/tests/vboot/sign-images-sha384.its
new file mode 100644
index 0000000..be1a9a6
--- /dev/null
+++ b/test/py/tests/vboot/sign-images-sha384.its
@@ -0,0 +1,42 @@
+/dts-v1/;
+
+/ {
+	description = "Chrome OS kernel image with one or more FDT blobs";
+	#address-cells = <1>;
+
+	images {
+		kernel {
+			data = /incbin/("test-kernel.bin");
+			type = "kernel_noload";
+			arch = "sandbox";
+			os = "linux";
+			compression = "none";
+			load = <0x4>;
+			entry = <0x8>;
+			kernel-version = <1>;
+			signature {
+				algo = "sha384,rsa3072";
+				key-name-hint = "dev";
+			};
+		};
+		fdt-1 {
+			description = "snow";
+			data = /incbin/("sandbox-kernel.dtb");
+			type = "flat_dt";
+			arch = "sandbox";
+			compression = "none";
+			fdt-version = <1>;
+			signature {
+				algo = "sha384,rsa3072";
+				key-name-hint = "dev";
+			};
+		};
+	};
+	configurations {
+		default = "conf-1";
+		conf-1 {
+			kernel = "kernel";
+			fdt = "fdt-1";
+		};
+	};
+};
diff --git a/tools/image-sig-host.c b/tools/image-sig-host.c
index 8ed6998..d0133ae 100644
--- a/tools/image-sig-host.c
+++ b/tools/image-sig-host.c
@@ -56,6 +56,13 @@
 		.verify = rsa_verify,
 	},
 	{
+		.name = "rsa3072",
+		.key_len = RSA3072_BYTES,
+		.sign = rsa_sign,
+		.add_verify_data = rsa_add_verify_data,
+		.verify = rsa_verify,
+	},
+	{
 		.name = "rsa4096",
 		.key_len = RSA4096_BYTES,
 		.sign = rsa_sign,