[astro] 6.20211109.1.3166212 u-boot source

GitOrigin-RevId: 3bececf3e1d4d5fddd4d40bc773f7ce711835ef5
Change-Id: Ic0d8acd3cc54dfc7d6e2678cb00f4ad98fb4c1df
Reviewed-on: https://turquoise-internal-review.googlesource.com/c/third_party/u-boot/+/546224
Reviewed-by: Yecheng Zhao <zyecheng@google.com>
diff --git a/arch/arm/cpu/armv8/g12a/bl31_apis.c b/arch/arm/cpu/armv8/g12a/bl31_apis.c
index 10aa0d2..8a159fa 100644
--- a/arch/arm/cpu/armv8/g12a/bl31_apis.c
+++ b/arch/arm/cpu/armv8/g12a/bl31_apis.c
@@ -427,3 +427,51 @@
 
 	return (int)ret;
 }
+
+uint64_t bl31_vx_get_bootloader_lock_state(void)
+{
+	uint64_t ret = -1;
+
+	/* The command ID is the only param. */
+	register uint64_t x0 asm("x0") = VX_GET_BOOTLOADER_LOCK_STATE;
+	asm volatile(
+		__asmeq("%0", "x0")
+		"smc #0\n"
+		: "+r"(x0)
+	);
+	ret = x0;
+
+	return ret;
+}
+
+int bl31_vx_unlock_bootloader(void)
+{
+	uint64_t ret = -1;
+
+	/* The command ID is the only param. */
+	register uint64_t x0 asm("x0") = VX_UNLOCK_BOOTLOADER;
+	asm volatile(
+		__asmeq("%0", "x0")
+		"smc #0\n"
+		: "+r"(x0)
+	);
+	ret = x0;
+
+	return (int)ret;
+}
+
+int bl31_vx_exit_bootloader(void)
+{
+	uint64_t ret = -1;
+
+	/* The command ID is the only param. */
+	register uint64_t x0 asm("x0") = VX_EXIT_BOOTLOADER;
+	asm volatile(
+		__asmeq("%0", "x0")
+		"smc #0\n"
+		: "+r"(x0)
+	);
+	ret = x0;
+
+	return (int)ret;
+}
diff --git a/arch/arm/include/asm/arch-g12a/bl31_apis.h b/arch/arm/include/asm/arch-g12a/bl31_apis.h
index 2d7516e..8f6451b 100644
--- a/arch/arm/include/asm/arch-g12a/bl31_apis.h
+++ b/arch/arm/include/asm/arch-g12a/bl31_apis.h
@@ -127,11 +127,32 @@
 	#define AML_D_P_EXT_IMG_DECRYPT_V3   (0x51)
 	#define AML_D_P_UPGRADE_CHECK        (0x80)
 
-/* Permanent attributes */
+/* Verified execution */
 #define PERMANENT_ATTRIBUTES_READ	0x82000090
 #define PERMANENT_ATTRIBUTES_SIZE	1052
 #define PERMANENT_ATTRIBUTES_HASH_SIZE	32
 
+/* Returns the bootloader lock state in X0.
+ *
+ * Important: to protect against bitflip attacks/errors, always require the
+ * state match the expectation exactly; for example, if an operation is only
+ * allowed when unlocked, do this:
+ *   if (state == VX_BOOTLOADER_LOCK_STATE_UNLOCKED) { privilegedOp(); }
+ * not this:
+ *   if (state != VX_BOOTLOADER_LOCK_STATE_LOCKED) { privilegedOp(); }
+ * so that anything other than an exact match defaults to the lower-privilege
+ * state. */
+#define VX_GET_BOOTLOADER_LOCK_STATE		0x82000091
+#define VX_BOOTLOADER_LOCK_STATE_LOCKED 	0xDE64135Au
+#define VX_BOOTLOADER_LOCK_STATE_UNLOCKED 	0xC9FD41C3u
+
+/* Unlocks the bootloader. Returns 0 in X0 on success. */
+#define VX_UNLOCK_BOOTLOADER			0x82000092
+
+/* Exits the bootloader. Returns 0 in X0 on success.
+ * Must be called successfully before jumping to Zircon. */
+#define VX_EXIT_BOOTLOADER			0x82000093
+
 #define GXB_EFUSE_PATTERN_SIZE      (0x500)
 #define GXB_IMG_SIZE                (24<<20)
 #define GXB_IMG_LOAD_ADDR           (0x1080000)
@@ -165,4 +186,9 @@
  */
 int bl31_get_permanent_attributes(const void *in_hash, void *out_attrs);
 
+/* BL31 VX SIP wrappers. See documentation above. */
+uint64_t bl31_vx_get_bootloader_lock_state(void);
+int bl31_vx_unlock_bootloader(void);
+int bl31_vx_exit_bootloader(void);
+
 #endif
diff --git a/arch/arm/lib/bootm.c b/arch/arm/lib/bootm.c
index 85c437d..ef43024 100644
--- a/arch/arm/lib/bootm.c
+++ b/arch/arm/lib/bootm.c
@@ -445,6 +445,13 @@
 	// this will pass the zbi pointer to the kernel via x0
 	images->ft_addr = (char *)zbi;
 
+	// Tell BL31 we're exiting the bootloader to disable any bootloader-only
+	// functionality.
+	if (zircon_exit_bootloader() != 0) {
+		printf("Error: failed to exit bootloader, cannot boot Zircon\n");
+		return -1;
+	}
+
 	boot_jump_linux(images, flag);
 	return 0;
 }
diff --git a/board/amlogic/configs/g12a_estelle_bx.h b/board/amlogic/configs/g12a_estelle_bx.h
index 3740acb..9def690 100755
--- a/board/amlogic/configs/g12a_estelle_bx.h
+++ b/board/amlogic/configs/g12a_estelle_bx.h
@@ -173,10 +173,14 @@
 		"fi;fi;fi;fi;" \
 		"\0" \
 	"storeboot=" \
-		/* zvb_load_and_boot doesn't return on success */ \
-		"zvb_load_and_boot kernel ${loadaddr} ${loadsize};" \
+		"if zbi_load kernel ${loadaddr} ${loadsize}; then " \
+			"zbi_boot ${loadaddr};" \
+		"fi;" \
 		"run update;" \
 		"\0" \
+	"ramboot=" \
+		"zbi_boot ${loadaddr};" \
+		"\0" \
 	"factory_reset_poweroff_protect=" \
 		"echo wipe_data=${wipe_data};" \
 		"echo wipe_cache=${wipe_cache};" \
@@ -199,7 +203,9 @@
 		"\0" \
 	/* load and boot an image from 'recovery' partition to restore the device. */ \
 	"recovery_from_flash=" \
-		"zvb_load_and_boot recovery ${loadaddr} ${loadsize};" \
+		"if zbi_load recovery ${loadaddr} ${loadsize}; then " \
+			"zbi_boot ${loadaddr};" \
+		"fi;" \
 		"\0" \
 	"reset_ddic=" \
 		"gpio clear GPIOH_6" \
diff --git a/board/amlogic/g12a_estelle_bx/zircon.c b/board/amlogic/g12a_estelle_bx/zircon.c
index 573c748..2d3052d 100644
--- a/board/amlogic/g12a_estelle_bx/zircon.c
+++ b/board/amlogic/g12a_estelle_bx/zircon.c
@@ -5,6 +5,7 @@
  */
 
 #include <aml_i2c.h>
+#include <asm/arch/bl31_apis.h>
 #include <asm/arch/efuse.h>
 #include <asm/arch/secure_apb.h>
 #include <asm/reboot.h>
@@ -252,69 +253,37 @@
 	return dst;
 }
 
-static bool s_vboot_enabled = true;
 bool zircon_is_vboot_enabled(void)
 {
-	return s_vboot_enabled;
+	/* Anything other than our specific UNLOCKED value means vboot is on. */
+	return bl31_vx_get_bootloader_lock_state() !=
+	       VX_BOOTLOADER_LOCK_STATE_UNLOCKED;
 }
 
-#if defined(CONFIG_ZIRCON_VBOOT_UNLOCK)
-/* 511th bit of user area */
-#define FUSE_UNLOCK_DISABLE_FLAG 511
-#define FUSE_UNLOCK_DISABLE_FLAG_BYTE_OFFSET (FUSE_UNLOCK_DISABLE_FLAG / 8)
-#define FUSE_UNLOCK_DISABLE_FLAG_MASK (1 << (FUSE_UNLOCK_DISABLE_FLAG % 8))
-
-bool zircon_is_vboot_unlock_enabled(void)
+int zircon_vboot_unlock(void)
 {
-	char unlock_disable = 0;
-
-	loff_t offset = FUSE_UNLOCK_DISABLE_FLAG_BYTE_OFFSET;
-	ssize_t ret = efuse_read_usr(&unlock_disable, 1, &offset);
-	if (ret != 1) {
-		/* unlock is disabled by default */
-		return false;
-	}
-
-	debugP("UNLOCK disable flag %d\n", unlock_disable);
-
-	return !(unlock_disable & FUSE_UNLOCK_DISABLE_FLAG_MASK);
-}
-
-int zircon_vboot_disable_vboot_unlock(void)
-{
-	char unlock_disable = FUSE_UNLOCK_DISABLE_FLAG_MASK;
-
-	if (!s_vboot_enabled) {
-		/* device has to be locked first */
-		printf("error: the device has to be locked first\n");
+	/* These log strings are load-bearing in the firmware test suite, make
+	 * sure to keep them in sync if you change them here. */
+	if (bl31_vx_unlock_bootloader() != 0) {
+		printf("Error: failed to unlock the bootloader\n");
 		return -1;
 	}
-
-	loff_t offset = FUSE_UNLOCK_DISABLE_FLAG_BYTE_OFFSET;
-	ssize_t ret = efuse_write_usr(&unlock_disable, 1, &offset);
-	if (ret != 1) {
-		return -1;
-	}
+	printf("Bootloader unlock success\n");
 
 	return 0;
 }
 
-int zircon_vboot_set_unlock(bool unlock)
+int zircon_exit_bootloader(void)
 {
-	if (!unlock) {
-		s_vboot_enabled = true;
-		return 0;
-	}
-
-	if (!zircon_is_vboot_unlock_enabled()) {
-		debugP("Unlock feature is permanently disabled.\n");
+	/* These log strings are load-bearing in the firmware test suite, make
+	 * sure to keep them in sync if you change them here. */
+	if (bl31_vx_exit_bootloader() != 0) {
+		printf("Error: failed to exit bootloader\n");
 		return -1;
 	}
-
-	s_vboot_enabled = false;
+	printf("Bootloader exit success\n");
 	return 0;
 }
-#endif /* CONFIG_ZIRCON_VBOOT_UNLOCK */
 
 /* Helper to add a ZBI item. Returns 0 on success, -1 and logs on failure.*/
 int append_zbi_item_or_log(void *zbi, size_t capacity, uint32_t type,
diff --git a/board/amlogic/g12a_estelle_bx/zircon_partition.c b/board/amlogic/g12a_estelle_bx/zircon_partition.c
index 4cdb1ac..bec8a97 100644
--- a/board/amlogic/g12a_estelle_bx/zircon_partition.c
+++ b/board/amlogic/g12a_estelle_bx/zircon_partition.c
@@ -352,7 +352,7 @@
 static unsigned char sys_cfg_write_buf[ERASE_GRP_SIZE_MAX];
 static unsigned char sys_cfg_erase_buf[ERASE_GRP_SIZE_MAX];
 
-#define SYS_CFG_NUM_READ_RETRIES 3
+#define NAND_READ_RETRIES 3
 /**
  * The sys-config partition contains 4 replicated copies, each of which are the
  * size of an erase block. This tries to read each copy 3 times until a read
@@ -399,7 +399,7 @@
 
 		bool read_succeeded = false;
 
-		for (retry = 0; retry < SYS_CFG_NUM_READ_RETRIES; retry++) {
+		for (retry = 0; retry < NAND_READ_RETRIES; retry++) {
 			size_t len = size;
 
 			if (!nand_read(data_nand_info, read_offset, &len,
@@ -1297,6 +1297,119 @@
 	return -1;
 }
 
+// Reads a single page (data + OOB) starting at byte |address| into |buffer|.
+// Retries a few times on failure; |buffer| does not need to be aligned.
+// Returns 0 on success.
+static int read_oob_page(nand_info_t *nand, uint64_t address, uint8_t *buffer)
+{
+	// Normal page data buffer needs to be DMA-aligned, OOB does not.
+	static uint8_t aligned_buffer[PAGE_SIZE] __aligned(ARCH_DMA_MINALIGN);
+
+	struct mtd_oob_ops ops = {
+		.mode = MTD_OPS_AUTO_OOB,
+		.len = PAGE_SIZE,
+		.ooblen = OOB_SIZE,
+		.ooboffs = 0,
+		.datbuf = aligned_buffer,
+		.oobbuf = &buffer[PAGE_SIZE],
+	};
+
+	for (int i = 0; i < NAND_READ_RETRIES; ++i) {
+		if (mtd_read_oob(nand, address, &ops) == 0) {
+			memcpy(buffer, aligned_buffer, PAGE_SIZE);
+			return 0;
+		}
+
+		printf("Warning: read #%d failed at 0x%llX\n", i + 1, address);
+	}
+
+	return -1;
+}
+
+int zircon_partition_read_oob(const char *name, uint64_t offset,
+			      uint8_t *buffer, size_t size,
+			      uint64_t *offset_out, size_t *size_out)
+{
+	init_partition_map();
+	const zbi_partition_t *part = get_partition_by_name(name);
+	if (part == NULL) {
+		printf("Error: failed to find partition '%s'\n", name);
+		return -1;
+	}
+
+	nand_info_t *nand =
+		(strcmp(name, "bl2") == 0) ? bl2_nand_info : data_nand_info;
+
+	// Existing code uses PAGE_SIZE/OOB_SIZE constants pretty heavily, so
+	// we'll do the same here for consistency. For our purposes the NAND
+	// configuration will always be constant, just double-check here to be
+	// sure.
+	if (nand->writesize != PAGE_SIZE) {
+		printf("Error: expected %u NAND write size, got %u\n",
+		       PAGE_SIZE, nand->writesize);
+		return -1;
+	}
+	if (nand->oobavail < OOB_SIZE) {
+		printf("Error: expected %u NAND OOB bytes, got %u\n", OOB_SIZE,
+		       nand->oobavail);
+		return -1;
+	}
+
+	if (offset % PAGE_SIZE) {
+		printf("Error: cannot read from non-page-aligned offset 0x%llX\n",
+		       offset);
+		return -1;
+	}
+
+	// Since we define partitions boundaries in terms of pages they will all
+	// by definition be page-aligned.
+	const uint64_t part_start = part->first_block * PAGE_SIZE;
+	const uint64_t part_end = (part->last_block + 1) * PAGE_SIZE;
+
+	uint64_t read_addr = part_start + offset;
+	if (read_addr >= part_end || read_addr < part_start) {
+		printf("Error: partition offset overflow\n");
+		return -1;
+	}
+
+	// Make sure we can fit at least one page in the output buffer.
+	if (size < PAGE_PLUS_OOB_SIZE) {
+		printf("Error: buffer too small for a data+OOB page\n");
+		return -1;
+	}
+
+	// Keep reading until we run out of partition or buffer.
+	const uint8_t *buffer_start = buffer;
+	while (size >= PAGE_PLUS_OOB_SIZE && read_addr < part_end) {
+		const char *error_code = NULL;
+
+		// We need to track every page, even if we couldn't read it, so
+		// that the caller knows the exact NAND state. Read failures
+		// are marked by an 8-char string followed by zeros.
+		if (nand_block_isbad(nand, read_addr)) {
+			error_code = READ_OOB_ERROR_CODE_BAD_BLOCK;
+		} else if (read_oob_page(nand, read_addr, buffer)) {
+			error_code = READ_OOB_ERROR_CODE_READ_FAILURE;
+		}
+
+		if (error_code) {
+			printf("Warning: [%s] on page 0x%llX-0x%llX\n",
+			       error_code, read_addr,
+			       read_addr + PAGE_SIZE - 1);
+			memset(buffer, 0, PAGE_PLUS_OOB_SIZE);
+			memcpy(buffer, error_code, strlen(error_code));
+		}
+
+		size -= PAGE_PLUS_OOB_SIZE;
+		buffer += PAGE_PLUS_OOB_SIZE;
+		read_addr += PAGE_SIZE;
+	}
+
+	*offset_out = (read_addr < part_end) ? read_addr : 0;
+	*size_out = buffer - buffer_start;
+	return 0;
+}
+
 int zircon_get_partititon_size(const char *name, uint64_t *size)
 {
 	assert(size != NULL);
diff --git a/common/Makefile b/common/Makefile
index 28a5b47..1c7d6fd 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -353,5 +353,5 @@
 obj-$(CONFIG_CMD_VIU_PROBE) +=cmd_viuprobe.o
 CFLAGS_env_embedded.o := -Wa,--no-warn -DENV_CRC=$(shell tools/envcrc 2>/dev/null)
 
-obj-$(CONFIG_ZIRCON_VBOOT) += zircon-avb.o zircon-vboot.o
+obj-$(CONFIG_ZIRCON_VBOOT) += zircon-avb.o zircon-vboot.o zircon-bootimg.o
 obj-$(CONFIG_FIRMWARE_TESTING_DEV_BUILD) += zircon-fw-testing.o
diff --git a/common/aml_dt.c b/common/aml_dt.c
index 0807c11..73c7548 100644
--- a/common/aml_dt.c
+++ b/common/aml_dt.c
@@ -104,11 +104,7 @@
 		printf("      Multi dtb detected\n");
 		/* check and set aml_dt */
 		int i = 0;
-		char *aml_dt_buf = NULL;
-		aml_dt_buf = (char *)malloc(sizeof(char)*64);
-		if (!aml_dt_buf)
-			return -1;
-		memset(aml_dt_buf, 0, sizeof(aml_dt_buf));
+		char aml_dt_buf[64] = {0};
 
 		/* update 2016.07.27, checkhw and setenv everytime,
 		or else aml_dt will set only once if it is reserved */
@@ -123,11 +119,9 @@
 			memcpy(aml_dt_buf, aml_dt, (strlen(aml_dt)>64?64:(strlen(aml_dt)+1)));
 #endif
 
-		unsigned int aml_dt_len = aml_dt_buf ? strlen(aml_dt_buf) : 0;
+		unsigned int aml_dt_len = strlen(aml_dt_buf);
 		if (aml_dt_len <= 0) {
 			printf("      Get env aml_dt failed!\n");
-			if (aml_dt_buf)
-				free(aml_dt_buf);
 			return fdt_addr;
 		}
 
@@ -151,12 +145,12 @@
 
 		/* split aml_dt to 3 strings */
 		char *tokens[3] = {NULL, NULL, NULL};
+		char *sep_start = aml_dt_buf;
 		for (i = 0; i < AML_DT_ID_VARI_TOTAL; i++) {
-			tokens[i] = strsep(&aml_dt_buf, "_");
+			tokens[i] = strsep(&sep_start, "_");
 		}
-		if (aml_dt_buf)
-			free(aml_dt_buf);
-		printf("        aml_dt soc: %s platform: %s variant: %s\n", tokens[0], tokens[1], tokens[2]);
+		printf("        aml_dt soc: %s platform: %s variant: %s\n", tokens[0],
+		       tokens[1], tokens[2]);
 
 		/*match and print result*/
 		char **dt_info;
diff --git a/common/cmd_zircon.c b/common/cmd_zircon.c
index 24e4b44..8c3ddb3 100644
--- a/common/cmd_zircon.c
+++ b/common/cmd_zircon.c
@@ -28,15 +28,15 @@
 
 #define errorP(fmt...) printf("Err %s(L%d):", __func__, __LINE__), printf(fmt)
 
-static int do_image_load_and_boot(cmd_tbl_t *cmdtp, int flag, int argc,
-				  char *const argv[])
+static size_t img_offset;
+
+static int do_zbi_load(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
 {
 	long unsigned int loadaddr = 0;
 	size_t loadsize = 0;
 	aml_boot_header_t *aml_hdr;
 	const char *type = NULL;
 	bool force_recovery = false;
-	size_t offset = 0;
 	int ret;
 
 	if (argc < 4) {
@@ -68,12 +68,12 @@
 	aml_hdr = (aml_boot_header_t *)loadaddr;
 	if (aml_hdr->magic == AML_BOOT_HEADER_MAGIC) {
 		debugP("AML image header is detected.\n");
-		offset = sizeof(aml_boot_header_t);
+		img_offset = sizeof(aml_boot_header_t);
 	}
-	debugP("Kernel offset is %zu bytes\n", offset);
+	debugP("Kernel offset is %zu bytes\n", img_offset);
 
-	zbi_header_t *zbi = (zbi_header_t *)(loadaddr + offset);
-	size_t capacity = loadsize - offset;
+	zbi_header_t *zbi = (zbi_header_t *)(loadaddr + img_offset);
+	size_t capacity = loadsize - img_offset;
 	ret = zircon_fixup_zbi(zbi, capacity);
 	if (ret) {
 		fprintf(stderr,
@@ -81,9 +81,24 @@
 		return __LINE__;
 	}
 
+	return 0;
+}
+
+
+static int do_zbi_boot(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
+{
+	long unsigned int loadaddr = 0;
+	int ret;
+
+	if (argc < 2) {
+		return 1;
+	}
+
+	loadaddr = simple_strtoul(argv[1], NULL, 16);
+
 	char argv0_new[12] = { 0 };
 	char *argv_new = (char *)&argv0_new;
-	snprintf(argv0_new, sizeof(argv0_new), "%lx", loadaddr + offset);
+	snprintf(argv0_new, sizeof(argv0_new), "%lx", loadaddr + img_offset);
 	argc = 1;
 	argv = (char **)&argv_new;
 
@@ -140,9 +155,13 @@
 U_BOOT_CMD(zvb_check_abr_support, 1, 0, do_abr_check,
 	   "check if ZBI A/B images are present on the device.", "");
 
-U_BOOT_CMD(zvb_load_and_boot, 4, 0, do_image_load_and_boot,
-	   "Read the image from internal flash with actual size and boot it",
+U_BOOT_CMD(zbi_load, 4, 0, do_zbi_load,
+	   "Read the image from internal flash with actual size",
 	   "argv: <imageType> <loadaddr> <loadsize>\n"
 	   "\t<imageType>: current support is kernel or recovery\n"
-	   "\t<loadaddr>: address to store the image\n"
+	   "\t<loadaddr>: memory address in hex to store the image\n"
 	   "\t<loadsize>: size in hex of the loadaddr buffer\n");
+
+U_BOOT_CMD(zbi_boot, 2, 0, do_zbi_boot, "Boot the ZBI at the specified address",
+	   "argv: <addr>\n"
+	   "\t<addr>: memory address in hex of the image to boot\n");
diff --git a/common/image-zircon.c b/common/image-zircon.c
index f888de5..b9bf136 100644
--- a/common/image-zircon.c
+++ b/common/image-zircon.c
@@ -26,7 +26,7 @@
 int zircon_image_get_kernel(const void *hdr, int verify, ulong *os_data,
 			    ulong *os_len)
 {
-	if (zbi_check_complete(hdr, NULL) != ZBI_RESULT_OK) {
+	if (zbi_check_bootable(hdr, NULL) != ZBI_RESULT_OK) {
 		return -1;
 	}
 
diff --git a/common/image.c b/common/image.c
index fb9ec5d..fe599fc 100644
--- a/common/image.c
+++ b/common/image.c
@@ -749,7 +749,7 @@
 		return IMAGE_FORMAT_ANDROID;
 #endif
 #ifdef CONFIG_ZIRCON_BOOT_IMAGE
-	if (zbi_check_complete(img_addr, NULL) == ZBI_RESULT_OK)
+	if (zbi_check_bootable(img_addr, NULL) == ZBI_RESULT_OK)
 		return IMAGE_FORMAT_ZIRCON;
 #endif
 
diff --git a/common/zircon-avb.c b/common/zircon-avb.c
index 040eb5c..5b70219 100644
--- a/common/zircon-avb.c
+++ b/common/zircon-avb.c
@@ -435,6 +435,141 @@
 	return result;
 }
 
+typedef struct {
+	uint8_t *preloaded_img_addr;
+	size_t preloaded_img_size;
+
+	uint8_t *preloaded_vbmeta_addr;
+	size_t preloaded_vbmeta_size;
+} vboot_ramboot_context_t;
+
+#define VBOOT_RAMBOOT_ZBI_PARTITION "ramboot_zbi"
+
+static AvbIOResult
+get_preloaded_partition_ramboot(AvbOps *ops, const char *partition,
+				size_t num_bytes, uint8_t **out_pointer,
+				size_t *out_num_bytes_preloaded)
+{
+	vboot_ramboot_context_t *context =
+		(vboot_ramboot_context_t *)ops->user_data;
+
+	// Only support preloaded `ramboot_zbi` partition
+	if (strcmp(partition, VBOOT_RAMBOOT_ZBI_PARTITION)) {
+		*out_pointer = NULL;
+		return AVB_IO_RESULT_OK;
+	}
+	*out_num_bytes_preloaded = min(num_bytes, context->preloaded_img_size);
+	*out_pointer = context->preloaded_img_addr;
+
+	return AVB_IO_RESULT_OK;
+}
+
+static AvbIOResult read_from_partition_ramboot(AvbOps *ops,
+					       const char *partition,
+					       int64_t offset, size_t num_bytes,
+					       void *buffer,
+					       size_t *out_num_read)
+{
+	// Only support preloaded `vbmeta` partition
+	if (strcmp(partition, "vbmeta") || offset != 0) {
+		return AVB_SLOT_VERIFY_RESULT_ERROR_IO;
+	}
+
+	vboot_ramboot_context_t *context =
+		(vboot_ramboot_context_t *)ops->user_data;
+
+	*out_num_read = min(num_bytes, context->preloaded_vbmeta_size);
+
+	memcpy(buffer, context->preloaded_vbmeta_addr, *out_num_read);
+
+	return AVB_IO_RESULT_OK;
+}
+
+/* This is not called, but needs to be non-null. */
+static AvbIOResult get_size_of_partition_ramboot(AvbOps *ops,
+						 const char *partition,
+						 uint64_t *out_size_num_bytes)
+{
+	return AVB_SLOT_VERIFY_RESULT_ERROR_IO;
+}
+
+/* Assume all partitions exist for ramboot. */
+static AvbIOResult get_unique_guid_for_partition_ramboot(AvbOps *ops,
+							 const char *partition,
+							 char *guid_buf,
+							 size_t guid_buf_size)
+{
+	guid_buf[0] = '\0';
+	return AVB_IO_RESULT_OK;
+}
+
+/* RAM-booting does not increment key versions. */
+static void set_key_version_ramboot(AvbAtxOps *atx_ops,
+				    size_t rollback_index_location,
+				    uint64_t key_version)
+{
+}
+
+// ramboot_atx_ops and ramboot_ops have all disk write functionality removed.
+static AvbAtxOps ramboot_atx_ops = {
+	.ops = &ops,
+	.read_permanent_attributes = avb_read_permanent_attributes,
+	.read_permanent_attributes_hash = avb_read_permanent_attributes_hash,
+	.set_key_version = set_key_version_ramboot,
+	.get_random = get_random,
+};
+
+static AvbOps ramboot_ops = {
+	.atx_ops = &ramboot_atx_ops,
+	.read_from_partition = read_from_partition_ramboot,
+	.get_preloaded_partition = get_preloaded_partition_ramboot,
+	.validate_vbmeta_public_key = avb_atx_validate_vbmeta_public_key,
+	.read_rollback_index = avb_read_rollback_index,
+	.read_is_device_unlocked = read_is_device_unlocked,
+	.get_unique_guid_for_partition = get_unique_guid_for_partition_ramboot,
+	.get_size_of_partition = get_size_of_partition_ramboot,
+	.read_persistent_value = read_persistent_value,
+};
+
+bool zircon_vboot_preloaded_img_verify(unsigned char *zbi, size_t zbi_size,
+				       unsigned char *vbmeta,
+				       size_t vbmeta_size,
+				       AvbSlotVerifyData **verify_data)
+{
+	const bool locked = zircon_is_vboot_enabled();
+
+	const char *const requested_partitions[2] = {
+		VBOOT_RAMBOOT_ZBI_PARTITION, NULL
+	};
+
+	vboot_ramboot_context_t context = { 0 };
+	context.preloaded_img_addr = zbi;
+	context.preloaded_img_size = zbi_size;
+	context.preloaded_vbmeta_addr = vbmeta;
+	context.preloaded_vbmeta_size = vbmeta_size;
+
+	ramboot_ops.user_data = (void *)&context;
+
+	AvbSlotVerifyResult verify_result = avb_slot_verify(
+		&ramboot_ops, requested_partitions, "",
+		locked ? AVB_SLOT_VERIFY_FLAGS_NONE :
+			       AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR,
+		AVB_HASHTREE_ERROR_MODE_EIO, verify_data);
+
+	if (verify_result == AVB_SLOT_VERIFY_RESULT_OK) {
+		return true;
+	}
+
+	printf("Failed to verify ZBI: error %d\n", verify_result);
+
+	if (!locked) {
+		printf("Unlocked, allowing unverified ZBI boot\n");
+		return true;
+	}
+
+	return false;
+}
+
 int zircon_vboot_generate_unlock_challenge(AvbAtxUnlockChallenge *out)
 {
 	AvbIOResult ret = avb_atx_generate_unlock_challenge(&atx_ops, out);
diff --git a/common/zircon-bootimg.c b/common/zircon-bootimg.c
new file mode 100644
index 0000000..6ca818c
--- /dev/null
+++ b/common/zircon-bootimg.c
@@ -0,0 +1,52 @@
+// Copyright 2021 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <zircon-estelle/bootimg.h>
+#include <common.h>
+
+uint32_t validate_bootimg(void *bootimg)
+{
+	boot_img_hdr_v0 *hdr = (boot_img_hdr_v0 *)bootimg;
+	if (!strncmp((char *)(hdr->magic), BOOT_MAGIC, BOOT_MAGIC_SIZE)) {
+		return hdr->header_version;
+	}
+	return (uint32_t)(-1);
+}
+
+uint32_t get_kernel_size(void *bootimg, uint32_t hdr_version)
+{
+	switch (hdr_version) {
+	case 0:
+		return ((boot_img_hdr_v0 *)bootimg)->kernel_size;
+	case 1:
+		return ((boot_img_hdr_v1 *)bootimg)->kernel_size;
+	case 2:
+		return ((boot_img_hdr_v2 *)bootimg)->kernel_size;
+	case 3:
+		return ((boot_img_hdr_v3 *)bootimg)->kernel_size;
+	case 4:
+		return ((boot_img_hdr_v4 *)bootimg)->kernel_size;
+	default:
+		return (uint32_t)(-1);
+	}
+}
+
+uint32_t get_kernel_offset(void *bootimg, uint32_t hdr_version)
+{
+	switch (hdr_version) {
+	case 0:
+		return ((boot_img_hdr_v0 *)bootimg)->page_size;
+	case 1:
+		return ((boot_img_hdr_v1 *)bootimg)->page_size;
+	case 2:
+		return ((boot_img_hdr_v2 *)bootimg)->page_size;
+	case 3:
+	case 4:
+		// Versions 3 and 4 fix the page size at 4096, see:
+		// https://android.googlesource.com/platform/system/tools/mkbootimg/+/refs/heads/master/include/bootimg/bootimg.h#219
+		return 4096;
+	default:
+		return (uint32_t)(-1);
+	}
+}
diff --git a/common/zircon-vboot.c b/common/zircon-vboot.c
index d21119a..14b5eb0 100644
--- a/common/zircon-vboot.c
+++ b/common/zircon-vboot.c
@@ -43,8 +43,6 @@
 
 static AvbSlotVerifyData *g_slot_verify_data = NULL;
 
-typedef struct andr_img_hdr boot_img_hdr;
-
 /* libabr callback implementations to read/write metadata from disk. */
 
 #ifdef CONFIG_ABR_WEAR_LEVELING
@@ -358,12 +356,42 @@
 	return 0;
 }
 
+int zircon_vboot_preloaded_img_load(unsigned char *loadaddr, size_t loadsize,
+				    unsigned char *zbi, size_t zbi_size,
+				    unsigned char *vbmeta, size_t vbmeta_size)
+{
+	AVB_DATA_FREE(g_slot_verify_data);
+
+	bool verified = zircon_vboot_preloaded_img_verify(
+		zbi, zbi_size, vbmeta, vbmeta_size, &g_slot_verify_data);
+
+	if (!verified || zbi_size > loadsize) {
+		return -1;
+	}
+
+	memcpy(loadaddr, zbi, zbi_size);
+	return 0;
+}
+
 const char *zircon_vboot_get_current_slot(void)
 {
 	int slot = AbrGetBootSlot(&kAbrOps, false, NULL);
 	return AbrGetSlotSuffix(slot);
 }
 
+const char *zircon_vboot_get_slot_last_set_active(void)
+{
+	AbrSlotIndex slot;
+	AbrResult res = AbrGetSlotLastMarkedActive(&kAbrOps, &slot);
+	if (res != kAbrResultOk) {
+		return NULL;
+	}
+
+	const char *ret = AbrGetSlotSuffix(slot);
+	//&ret[1] skips the first '_' character. i.e. "_a" is returned as "a".
+	return ret ? &ret[1] : NULL;
+}
+
 int zircon_vboot_get_slot_info(int slot_number, AbrSlotInfo *info)
 {
 	AbrResult res = AbrGetSlotInfo(&kAbrOps, slot_number, info);
diff --git a/drivers/usb/gadget/f_fastboot.c b/drivers/usb/gadget/f_fastboot.c
index 41bd254..dc1b0ee 100644
--- a/drivers/usb/gadget/f_fastboot.c
+++ b/drivers/usb/gadget/f_fastboot.c
@@ -42,10 +42,11 @@
 #include <partition_table.h>
 #include <android_image.h>
 #include <image.h>
+#include <zircon-estelle/bootimg.h>
 #include <zircon-estelle/driver-config.h>
-#include <zircon-estelle/zircon.h>
-#include <zircon-estelle/vboot.h>
 #include <zircon-estelle/partition.h>
+#include <zircon-estelle/vboot.h>
+#include <zircon-estelle/zircon.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -569,11 +570,11 @@
 	return s;
 }
 
-static const char *get_hw_revision(const char *arg)
+// Returns the board that the bootloader was compiled for.
+static const char *get_bootloader_board(const char *arg)
 {
 	const char *s = "unknown";
 
-	// Don't leak internal names, convert "estelle" -> "astro".
 	if (!strncmp(BOARD_NAME, "estelle-b3", sizeof(BOARD_NAME))) {
 		s = "astro-b3";
 	} else if (!strncmp(BOARD_NAME, "estelle-b4", sizeof(BOARD_NAME))) {
@@ -583,6 +584,36 @@
 	return s;
 }
 
+// Returns the actual hardware revision given by the revision GPIOs.
+static const char *get_hw_revision(const char *arg)
+{
+	char *hw_id_str = getenv("hw_id");
+	if (hw_id_str == NULL || hw_id_str[0] == '\0') {
+		return "unknown";
+	}
+
+	// See Fuchsia //src/devices/board/drivers/astro/astro.h, but note the
+	// bootloader looks at 2 more GPIO bits compared to Fuchsia, which
+	// adds 0x08 to all board IDs.
+	const uint32_t hw_id = simple_strtoul(hw_id_str, NULL, 16);
+	switch (hw_id) {
+	case 0x08:
+		return "astro-p1";
+	case 0x09:
+		return "astro-p2";
+	case 0x0A:
+		return "astro-b1"; // EVT 1
+	case 0x0B:
+		return "astro-b2"; // EVT 2
+	case 0x0C:
+		return "astro-b3"; // DVT
+	case 0x0D:
+		return "astro-b4"; // PVT
+	}
+
+	return "unknown";
+}
+
 static const char *get_vx_locked_status(const char *arg)
 {
 	return zircon_is_vboot_enabled() ? "yes": "no";
@@ -590,11 +621,7 @@
 
 static const char *get_vx_unlockable_status(const char *arg)
 {
-#if defined(CONFIG_ZIRCON_VBOOT_UNLOCK)
-	return zircon_is_vboot_unlock_enabled() ? "yes" : "no";
-#else
-	return "no";
-#endif /* CONFIG_ZIRCON_VBOOT_UNLOCK */
+	return "ephemeral";
 }
 
 static const char *get_currect_slot(const char *arg)
@@ -604,6 +631,11 @@
 	return ret ? &ret[1] : NULL;
 }
 
+static const char *get_slot_last_set_active(const char *arg)
+{
+	return zircon_vboot_get_slot_last_set_active();
+}
+
 static const char *check_slot_successful(const char *arg)
 {
 	int i = 0;
@@ -741,10 +773,18 @@
 // keep items in varlist sorted by their names
 static struct fastboot_var varlist[] = {
 	{
+		.name = "bootloader-board",
+		.func = get_bootloader_board,
+	},
+	{
 		.name = "bootloader-min-versions",
 		.func = get_bootloader_min_versions,
 	},
 	{
+		.name = "bootloader-variant",
+		.value = BOOTLOADER_BUILD_VARIANT,
+	},
+	{
 		.name = "current-slot",
 		.func = get_currect_slot,
 	},
@@ -777,6 +817,10 @@
 		.value = "2",
 	},
 	{
+		.name = "slot-last-set-active",
+		.func = get_slot_last_set_active,
+	},
+	{
 		.name = "slot-retry-count",
 		.func = get_slot_retry_count,
 		.default_args = s_slot_suffix_list,
@@ -804,10 +848,6 @@
 		.value = U_BOOT_VERSION,
 	},
 	{
-		.name = "bootloader-variant",
-		.value = BOOTLOADER_BUILD_VARIANT,
-	},
-	{
 		.name = "vx-locked",
 		.func = get_vx_locked_status,
 	},
@@ -852,15 +892,11 @@
 	} else {
 		const char **arg = var->default_args;
 		static int s_arg_idx = 0;
-		if (arg[s_arg_idx]) {
-			snprintf(response,
-				 RESPONSE_LEN,
-				 "%s:%s: %s",
-				 var->name,
-				 arg[s_arg_idx], var->func(arg[s_arg_idx]));
+		snprintf(response, RESPONSE_LEN, "%s:%s: %s", var->name,
+			 arg[s_arg_idx], var->func(arg[s_arg_idx]));
+		s_arg_idx++;
 
-			s_arg_idx++;
-		} else {
+		if (arg[s_arg_idx] == NULL) {
 			s_arg_idx = 0;
 			s_getvar_idx++;
 		}
@@ -1094,15 +1130,84 @@
 	fastboot_func->in_req->complete = tx_handler_upload_image;
 }
 
-typedef struct andr_img_hdr boot_img_hdr;
-
 static void do_bootm_on_complete(struct usb_ep *ep, struct usb_request *req)
 {
-	fastboot_fail("not supported");
+	puts("RAM-booting kernel..\n");
+	run_command("run ramboot", 0);
+
+	/* This only happens if image is somehow faulty so we start over */
+	do_reset(NULL, 0, 0, NULL);
 }
 
 static void cb_boot(struct usb_ep *ep, struct usb_request *req)
 {
+	void *bootimg = (void *)CONFIG_USB_FASTBOOT_BUF_ADDR;
+
+	uint32_t bootimg_hdr_version = validate_bootimg(bootimg);
+	if (bootimg_hdr_version == (uint32_t)(-1)) {
+		fastboot_fail("invalid boot image magic");
+		return;
+	}
+
+	uint32_t kernel_size = get_kernel_size(bootimg, bootimg_hdr_version);
+	if (kernel_size == (uint32_t)(-1)) {
+		fastboot_fail("failed to get kernel size from bootimg");
+		return;
+	}
+
+	uint32_t kernel_offset =
+		get_kernel_offset(bootimg, bootimg_hdr_version);
+	if (kernel_offset == (uint32_t)(-1)) {
+		fastboot_fail("failed to get page size from bootimg");
+		return;
+	}
+
+	if (kernel_size > CONFIG_DEFAULT_KERNEL_SIZE) {
+		fastboot_fail("image too large");
+		return;
+	}
+
+	if (kernel_offset > CONFIG_DEFAULT_KERNEL_SIZE) {
+		fastboot_fail("offset too large");
+		return;
+	}
+
+	if (kernel_size + kernel_offset > download_bytes) {
+		fastboot_fail("inconsistent boot image");
+		return;
+	}
+
+	zbi_header_t *zbi = (zbi_header_t *)(bootimg + kernel_offset);
+	size_t zbi_size = sizeof(zbi_header_t) + zbi->length;
+
+	if (zbi_size < zbi->length || zbi_size > kernel_size) {
+		fastboot_fail("invalid zbi size");
+		return;
+	}
+
+	void *vbmeta = ((uint8_t *)zbi) + zbi_size;
+	size_t vbmeta_size = kernel_size - zbi_size;
+
+	// Copy vbmeta to ensure correct alignment.
+	void *new_vbmeta = (void *)CONFIG_DEFAULT_KERNEL_ADDR;
+	memcpy(new_vbmeta, vbmeta, vbmeta_size);
+
+	zbi_header_t *zbi_boot_location =
+		(zbi_header_t *)CONFIG_DEFAULT_KERNEL_ADDR;
+	size_t capacity = CONFIG_DEFAULT_KERNEL_SIZE;
+
+	if (zircon_vboot_preloaded_img_load((void *)zbi_boot_location, capacity,
+					    (void *)zbi, zbi_size, new_vbmeta,
+					    vbmeta_size)) {
+		fastboot_fail("Failed to load/validate zbi/vbmeta");
+		return;
+	}
+
+	if (zircon_fixup_zbi(zbi_boot_location, capacity)) {
+		fastboot_fail("Failed to fixup the ZBI image");
+		return;
+	}
+
 	fastboot_func->in_req->complete = do_bootm_on_complete;
 	fastboot_okay(NULL);
 }
@@ -1419,9 +1524,8 @@
 	}
 }
 
-#if defined(CONFIG_ZIRCON_VBOOT_UNLOCK)
-static void cb_zvb_get_vboot_unlock_challenge(struct usb_ep *ep,
-					      struct usb_request *req)
+static void cb_vx_get_unlock_challenge(struct usb_ep *ep,
+				       struct usb_request *req)
 {
 	AvbAtxUnlockChallenge *unlock_challenge;
 	unlock_challenge =
@@ -1438,19 +1542,7 @@
 	fastboot_okay(NULL);
 }
 
-static void cb_zvb_disable_unlock_vboot(struct usb_ep *ep,
-					struct usb_request *req)
-{
-	int ret = zircon_vboot_disable_vboot_unlock();
-	if (ret) {
-		fastboot_fail("permanent disabling unlock feature");
-		return;
-	}
-
-	fastboot_okay(NULL);
-}
-
-static void cb_zvb_unlock_vboot(struct usb_ep *ep, struct usb_request *req)
+static void cb_vx_unlock(struct usb_ep *ep, struct usb_request *req)
 {
 	bool is_trusted = false;
 	AvbAtxUnlockCredential *unlock_credential =
@@ -1476,17 +1568,15 @@
 		return;
 	}
 
-	zircon_vboot_set_unlock(true);
+	zircon_vboot_unlock();
 
 	fastboot_okay("unlocked");
 }
 
-static void cb_zvb_lock_vboot(struct usb_ep *ep, struct usb_request *req)
+static void cb_vx_lock(struct usb_ep *ep, struct usb_request *req)
 {
-	zircon_vboot_set_unlock(false);
-	fastboot_okay(NULL);
+	fastboot_fail("Re-locking not supported; reboot device instead");
 }
-#endif /* CONFIG_ZIRCON_VBOOT_UNLOCK */
 
 static void cb_staged_bootloader_file(struct usb_ep *ep,
 				      struct usb_request *req)
@@ -1544,6 +1634,85 @@
 	fastboot_okay(NULL);
 }
 
+// This is a very low-level command, so it doesn't need to be overly clever.
+// We can assume that users want to dump as much as possible, and always want
+// entire pages (since partial OOB doesn't make any sense).
+//
+// To continue a partial dump, call this again with a final "continue" arg.
+static void cb_stage_partition_oob(struct usb_ep *ep, struct usb_request *req)
+{
+	// A NAND dump isn't against our security model, but we generally only
+	// need it for testing so restrict it to the test build by default. It
+	// is OK to remove this condition and put on a prod build if necessary.
+	//
+	// TODO(b/218376566): gate behind unlock instead of build variant.
+#ifndef CONFIG_FIRMWARE_TESTING_DEV_BUILD
+	fastboot_fail("Command not supported on this build");
+	return;
+#else
+
+	// Finish if we just printed an info message.
+	static bool info_sent = false;
+	if (info_sent) {
+		info_sent = false;
+		fastboot_okay(NULL);
+		return;
+	}
+
+	char *command = req->buf;
+
+	// skip past "oem stage-partition-oob"
+	if (!(strsep(&command, " ") && strsep(&command, " ") &&
+	      command)) {
+		fastboot_fail("No partition given");
+		return;
+	}
+	const char *name = command;
+
+	// There are a few partitions we never want to dump on a prod build,
+	// always leave this guard in.
+#ifndef CONFIG_FIRMWARE_TESTING_DEV_BUILD
+	if (!strcmp(name, "factory") || !strcmp(name, "migration")) {
+		fastboot_fail("This partition is restricted to test builds");
+		return;
+	}
+#endif  // !CONFIG_FIRMWARE_TESTING_DEV_BUILD
+
+	// When continuing, leave the previous offset in place. Otherwise
+	// start over from zero.
+	static uint64_t offset = 0;
+	if (strsep(&command, " ") && command && !strcmp(command, "continue")) {
+		if (offset == 0) {
+			fastboot_fail("No partition to continue");
+			return;
+		}
+	} else {
+		offset = 0;
+	}
+
+	size_t read_size = 0;
+	if (zircon_partition_read_oob(name, offset,
+				      (uint8_t *)CONFIG_USB_FASTBOOT_BUF_ADDR,
+				      CONFIG_USB_FASTBOOT_BUF_SIZE,
+				      &offset, &read_size)) {
+		fastboot_fail("Failed to read partition");
+		return;
+	}
+	upload_size = read_size;
+
+	if (offset == 0) {
+		fastboot_info("Finished reading partition");
+	} else {
+		fastboot_info("More data to read, re-call with `continue` arg");
+	}
+	info_sent = true;
+	// Restore enough of the command so the fastboot loop brings us back to
+	// send the final fastboot_okay().
+	strcpy((char *)req->buf, "oem stage-partition-oob");
+
+#endif  // CONFIG_FIRMWARE_TESTING_DEV_BUILD
+}
+
 #ifdef CONFIG_FIRMWARE_TESTING_DEV_BUILD
 
 /* Exposes bl31_get_permanent_attributes() for testing.
@@ -1588,6 +1757,17 @@
 	fastboot_okay(NULL);
 }
 
+/* Manually sends the "exit bootloader" SMC message to BL31.
+ * Used only for testing. */
+static void cb_exit_bootloader(struct usb_ep *ep, struct usb_request *req)
+{
+	if (zircon_exit_bootloader() != 0) {
+		fastboot_fail("Failed to exit bootloader");
+		return;
+	}
+	fastboot_okay(NULL);
+}
+
 extern void disable_watchdog_petting(void);
 static void cb_disable_watchdog_petting(struct usb_ep *ep,
 					struct usb_request *req)
@@ -1905,6 +2085,25 @@
 		.cmd = "oem get-vx-perm-attr-hash",
 		.cb = cb_get_vx_perm_attr_hash,
 	},
+	{
+		/* This function has internal logic to restrict to test-only.
+		 * Note that this needs to come before `oem stage-partition`
+		 * since the function matcher only looks at the prefix. */
+		.cmd = "oem stage-partition-oob",
+		.cb = cb_stage_partition_oob,
+	},
+	{
+		.cmd = "oem vx-get-unlock-challenge",
+		.cb = cb_vx_get_unlock_challenge,
+	},
+	{
+		.cmd = "oem vx-unlock",
+		.cb = cb_vx_unlock,
+	},
+	{
+		.cmd = "oem vx-lock",
+		.cb = cb_vx_lock,
+	},
 #ifdef CONFIG_FIRMWARE_TESTING_DEV_BUILD
 	{
 		.cmd = "oem test-flash-read",
@@ -1946,25 +2145,11 @@
 		.cmd = "oem check-perm-attrs-hash",
 		.cb = cb_check_perm_attrs_hash,
 	},
+	{
+		.cmd = "oem exit-bootloader",
+		.cb = cb_exit_bootloader,
+	},
 #endif /* CONFIG_FIRMWARE_TESTING_DEV_BUILD */
-#if defined(CONFIG_ZIRCON_VBOOT_UNLOCK)
-	{
-		.cmd = "oem zvb-disable-unlock-vboot",
-		.cb = cb_zvb_disable_unlock_vboot,
-	},
-	{
-		.cmd = "oem zvb-get-vboot-unlock-challenge",
-		.cb = cb_zvb_get_vboot_unlock_challenge,
-	},
-	{
-		.cmd = "oem zvb-unlock-vboot",
-		.cb = cb_zvb_unlock_vboot,
-	},
-	{
-		.cmd = "oem zvb-lock-vboot",
-		.cb = cb_zvb_lock_vboot,
-	},
-#endif /* CONFIG_ZIRCON_VBOOT_UNLOCK */
 };
 
 /* cb for out_req->complete */
diff --git a/fs/ubifs/ubifs.c b/fs/ubifs/ubifs.c
index 32e97a8..ec3f3eb 100644
--- a/fs/ubifs/ubifs.c
+++ b/fs/ubifs/ubifs.c
@@ -487,7 +487,8 @@
 	int symlink_count = 0; /* Don't allow symlink recursion */
 	char link_name[64];
 
-	strcpy(fpath, filename);
+	strncpy(fpath, filename, sizeof(fpath));
+	fpath[sizeof(fpath) - 1] = '\0';
 
 	/* Remove all leading slashes */
 	while (*name == '/')
@@ -522,15 +523,13 @@
 		ui = ubifs_inode(inode);
 
 		if ((inode->i_mode & S_IFMT) == S_IFLNK) {
-			char buf[128];
-
 			/* We have some sort of symlink recursion, bail out */
 			if (symlink_count++ > 8) {
 				printf("Symlink recursion, aborting\n");
 				return 0;
 			}
-			memcpy(link_name, ui->data, ui->data_len);
-			link_name[ui->data_len] = '\0';
+			strncpy(link_name, (char*)(ui->data), sizeof(link_name));
+			link_name[sizeof(link_name) - 1] = '\0';
 
 			if (link_name[0] == '/') {
 				/* Absolute path, redo everything without
@@ -540,9 +539,9 @@
 				continue;
 			}
 			/* Relative to cur dir */
-			sprintf(buf, "%s/%s",
-					link_name, next == NULL ? "" : next);
-			memcpy(symlinkpath, buf, sizeof(buf));
+			snprintf(symlinkpath, sizeof(symlinkpath), "%s/%s",
+				 link_name, next == NULL ? "" : next);
+			symlinkpath[sizeof(symlinkpath) - 1] = '\0';
 			next = name = symlinkpath;
 			continue;
 		}
diff --git a/include/zircon-estelle/bootimg.h b/include/zircon-estelle/bootimg.h
new file mode 100644
index 0000000..62d499e
--- /dev/null
+++ b/include/zircon-estelle/bootimg.h
@@ -0,0 +1,138 @@
+// Copyright 2021 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef _ZIRCON_BOOTIMG_H_
+#define _ZIRCON_BOOTIMG_H_
+
+#define BOOT_MAGIC "ANDROID!"
+#define BOOT_MAGIC_SIZE 8
+#define BOOT_NAME_SIZE 16
+#define BOOT_ARGS_SIZE 512
+#define BOOT_EXTRA_ARGS_SIZE 1024
+
+#include <common.h>
+
+// See https://android.googlesource.com/platform/system/tools/mkbootimg/+/refs/heads/master/include/bootimg/bootimg.h
+// for a full explanation of these structs and their fields.
+
+typedef struct {
+	uint8_t magic[BOOT_MAGIC_SIZE];
+	uint32_t kernel_size;
+	uint32_t kernel_addr;
+	uint32_t ramdisk_size;
+	uint32_t ramdisk_addr;
+	uint32_t second_size;
+	uint32_t second_addr;
+	uint32_t tags_addr;
+	uint32_t page_size;
+	uint32_t header_version;
+	uint32_t os_version;
+	uint8_t name[BOOT_NAME_SIZE];
+	uint8_t cmdline[BOOT_ARGS_SIZE];
+	uint32_t id[8];
+	uint8_t extra_cmdline[BOOT_EXTRA_ARGS_SIZE];
+} __attribute((packed)) boot_img_hdr_v0;
+
+typedef struct {
+	uint8_t magic[BOOT_MAGIC_SIZE];
+	uint32_t kernel_size;
+	uint32_t kernel_addr;
+	uint32_t ramdisk_size;
+	uint32_t ramdisk_addr;
+	uint32_t second_size;
+	uint32_t second_addr;
+	uint32_t tags_addr;
+	uint32_t page_size;
+	uint32_t header_version;
+	uint32_t os_version;
+	uint8_t name[BOOT_NAME_SIZE];
+	uint8_t cmdline[BOOT_ARGS_SIZE];
+	uint32_t id[8];
+	uint8_t extra_cmdline[BOOT_EXTRA_ARGS_SIZE];
+
+	uint32_t recovery_dtbo_size;
+	uint64_t recovery_dtbo_offset;
+	uint32_t header_size;
+} __attribute((packed)) boot_img_hdr_v1;
+
+typedef struct {
+	uint8_t magic[BOOT_MAGIC_SIZE];
+	uint32_t kernel_size;
+	uint32_t kernel_addr;
+	uint32_t ramdisk_size;
+	uint32_t ramdisk_addr;
+	uint32_t second_size;
+	uint32_t second_addr;
+	uint32_t tags_addr;
+	uint32_t page_size;
+	uint32_t header_version;
+	uint32_t os_version;
+	uint8_t name[BOOT_NAME_SIZE];
+	uint8_t cmdline[BOOT_ARGS_SIZE];
+	uint32_t id[8];
+	uint8_t extra_cmdline[BOOT_EXTRA_ARGS_SIZE];
+
+	uint32_t recovery_dtbo_size;
+	uint64_t recovery_dtbo_offset;
+	uint32_t header_size;
+
+	uint32_t dtb_size;
+	uint64_t dtb_addr;
+} __attribute((packed)) boot_img_hdr_v2;
+
+typedef struct {
+	uint8_t magic[BOOT_MAGIC_SIZE];
+	uint32_t kernel_size;
+	uint32_t ramdisk_size;
+	uint32_t os_version;
+	uint32_t header_size;
+	uint32_t reserved[4];
+	uint32_t header_version;
+	uint8_t cmdline[BOOT_ARGS_SIZE + BOOT_EXTRA_ARGS_SIZE];
+} __attribute((packed)) boot_img_hdr_v3;
+
+typedef struct {
+	uint8_t magic[BOOT_MAGIC_SIZE];
+	uint32_t kernel_size;
+	uint32_t ramdisk_size;
+	uint32_t os_version;
+	uint32_t header_size;
+	uint32_t reserved[4];
+	uint32_t header_version;
+	uint8_t cmdline[BOOT_ARGS_SIZE + BOOT_EXTRA_ARGS_SIZE];
+
+	uint32_t signature_size;
+} __attribute((packed)) boot_img_hdr_v4;
+
+/**
+ * Validates fastboot boot image.
+ *
+ * @bootimg: Address of the boot image to validate.
+ *
+ * Return: boot image version if successful (uint32_t)(-1) if not.
+ */
+uint32_t validate_bootimg(void *bootimg);
+
+/**
+ * Gets kernel size of fastboot boot image.
+ *
+ * @bootimg: address of the boot image.
+ * @hdr_version: android boot header version.
+ *
+ * Return: kernel_size in bytes if successful, (uint32_t)(-1) on failure.
+ */
+uint32_t get_kernel_size(void *bootimg, uint32_t hdr_version);
+
+/**
+ * Gets kernel offset relative to the start of the fastboot boot image.
+ *
+ * @bootimg: address of the boot image.
+ * @hdr_version: android boot header version.
+ *
+ * Return: offset in bytes if successful, (uint32_t)(-1) on failure.
+ */
+uint32_t get_kernel_offset(void *bootimg, uint32_t hdr_version);
+
+
+#endif //_ZIRCON_BOOTIMG_H_
diff --git a/include/zircon-estelle/partition.h b/include/zircon-estelle/partition.h
index eb86aba..4227cc8 100644
--- a/include/zircon-estelle/partition.h
+++ b/include/zircon-estelle/partition.h
@@ -32,6 +32,40 @@
 int zircon_partition_read(const char *name, uint64_t offset,
 			  unsigned char *data, size_t size);
 
+/* Reads data + OOB bytes from NAND.
+ *
+ * Data is read as interleaved data->oob->data->oob->... bytes. Read failures
+ * are marked by an 8-char error code with the rest of the page all 0s. See
+ * constants below for the possible error codes.
+ *
+ * This function is designed to support sequential calls to fetch chunks of
+ * partitions at a time if the partition is too large to fit in the buffer.
+ * |offset_out| gives the next offset to start at, or 0 if we reached the
+ * end of the partition.
+ *
+ * @name: partition name.
+ * @offset: partition byte offset to start reading at; must be page-aligned.
+ * @buffer: buffer to read into.
+ * @size: buffer size; may not be filled completely if the partition ends
+ *        early or we can't fit another whole page.
+ * @offset_out: offset to start the next read at, or 0 if we reached the
+ *              partition end.
+ * @size_out: total number of bytes (data + OOB) copied into buffer; always
+ *            contains complete pages.
+ *
+ * Returns 0 on success, nonzero on failure.
+ */
+int zircon_partition_read_oob(const char *name, uint64_t offset,
+			      uint8_t *buffer, size_t size,
+			      uint64_t *offset_out, size_t *size_out);
+
+/* Encountered a known bad block and skipped without attempting to read. */
+#define READ_OOB_ERROR_CODE_BAD_BLOCK "BADBLOCK"
+
+/* Attempted to read multiple times but failed each time. */
+#define READ_OOB_ERROR_CODE_READ_FAILURE "READFAIL"
+
 /* Erase |name| partition */
 int zircon_partition_erase(const char *name);
+
 #endif /* _ZIRCON_PARTITION_H_ */
diff --git a/include/zircon-estelle/vboot.h b/include/zircon-estelle/vboot.h
index bd37983..53bece9 100644
--- a/include/zircon-estelle/vboot.h
+++ b/include/zircon-estelle/vboot.h
@@ -36,6 +36,26 @@
 int zircon_vboot_img_load(unsigned char *loadaddr, size_t loadsize,
 			  bool force_recovery);
 
+/**
+ * Loads and verifies a preloaded zbi + vbmeta.
+ *
+ * The validation is done in-place, so loadaddr is not touched until the
+ * validation has completed successfully. This function also sets some global
+ * state required to correctly extract items from vbmeta.
+ *
+ * @loadaddr: address to load the validated zbi.
+ * @loadsize: size of the load buffer.
+ * @zbi: address of the preloaded zbi.
+ * @zbi_size: size of the preloaded zbi.
+ * @vbmeta: address of the preloaded vbmeta.
+ * @vbmeta_size: size of the preloaded vbmeta.
+ *
+ * Return: 0 if successful, non-zero value on failure.
+ */
+int zircon_vboot_preloaded_img_load(unsigned char *loadaddr, size_t loadsize,
+				    unsigned char *zbi, size_t zbi_size,
+				    unsigned char *vbmeta, size_t vbmeta_size);
+
 /* Performs a full load + verification of the indicated slot.
  *
  * @loadaddr: address at which to load the Zircon image.
@@ -56,9 +76,31 @@
 			 AvbAtxSlotState slot_state,
 			 AvbSlotVerifyData **verify_data);
 
+/**
+ * Verifies a preloaded zbi + vbmeta.
+ *
+ * @zbi: address of the preloaded zbi.
+ * @zbi_size: size of the preloaded zbi.
+ * @vbmeta: address of the preloaded vbmeta.
+ * @vbmeta_size: size of the preloaded vbmeta.
+ * @verify_data: verification data, will be allocated and filled if vbmeta
+ *               verification succeeds; note that this can still be NULL even
+ *               if the function succeeds if we're booting unlocked and no
+ *               vbmeta was provided.
+ *
+ * Return: true if either the ZBI verified successfully, or we're unlocked.
+ */
+bool zircon_vboot_preloaded_img_verify(unsigned char *zbi, size_t zbi_size,
+				       unsigned char *vbmeta,
+				       size_t vbmeta_size,
+				       AvbSlotVerifyData **verify_data);
+
 /* Get current slot to boot */
 const char *zircon_vboot_get_current_slot(void);
 
+/* Get slot last set active */
+const char *zircon_vboot_get_slot_last_set_active(void);
+
 /* Get slot info for |slot_number| slot.
  *
  * Returns > 0 if an error occured.
@@ -83,15 +125,21 @@
 avb_read_permanent_attributes_hash(AvbAtxOps *atx_ops,
 				   uint8_t hash[AVB_SHA256_DIGEST_SIZE]);
 
-#if defined(CONFIG_ZIRCON_VBOOT_UNLOCK)
-/* True if ZVB unlock feature is enabled */
-bool zircon_is_vboot_unlock_enabled(void);
-
-/* Permanently disable ZVB unlock feature */
-int zircon_vboot_disable_vboot_unlock(void);
-
-/* set ZVB unlock state */
-int zircon_vboot_set_unlock(bool unlock);
-#endif /* CONFIG_ZIRCON_VBOOT_UNLOCK */
+/* Unlocks verified boot, allowing unsigned Zircon images to boot.
+ *
+ * Since we lack the VX TA on this board, we can't easily disable sensitive
+ * TA operations (e.g. zxcrypt key access), so instead BL31 will disable OP-TEE
+ * SMC calls until reboot. This will likely cause some runtime errors in
+ * Fuchsia, but should be fine for loading a simple diagnostic image.
+ *
+ * Re-locking is not supported; once OP-TEE routing has been disabled the
+ * device must be rebooted to return to normal operation.
+ *
+ * The calling code MUST have successfully authenticated an unlock token before
+ * calling this.
+ *
+ * Returns 0 on success.
+ */
+int zircon_vboot_unlock(void);
 
 #endif // _ZIRCON_VBOOT_H_
diff --git a/include/zircon-estelle/zircon.h b/include/zircon-estelle/zircon.h
index 619aaa0..beb89ae 100644
--- a/include/zircon-estelle/zircon.h
+++ b/include/zircon-estelle/zircon.h
@@ -72,4 +72,14 @@
 int zircon_stage_zbi_file(const char *name, const uint8_t *data,
 			  size_t data_len);
 
+/**
+ * Informs BL31 that we are exiting the bootloader.
+ *
+ * This is mostly a bl31_vx_exit_bootloader() wrapper, but prints some log
+ * messages used by the firmware test suite.
+ *
+ * Returns: 0 on success.
+ */
+int zircon_exit_bootloader(void);
+
 #endif
diff --git a/lib/fuchsia/README.estelle.md b/lib/fuchsia/README.estelle.md
index 8c67004..1fbb978 100644
--- a/lib/fuchsia/README.estelle.md
+++ b/lib/fuchsia/README.estelle.md
@@ -25,6 +25,9 @@
 * `util.c`:
   * Add `<util.h>` include
 * Add `abr_sysdeps.c` to provide sysdep implementations
+* `data.h`:
+  * change `static const char* kAbrMagic = "\0AB0";` to
+    `#define kAbrMagic "\0AB0"`
 
 ## libavb
 
diff --git a/lib/fuchsia/README.md b/lib/fuchsia/README.md
new file mode 100644
index 0000000..58ee4c0
--- /dev/null
+++ b/lib/fuchsia/README.md
@@ -0,0 +1,105 @@
+# Fuchsia Firmware SDK
+
+The Firmware SDK provides definitions and reference code used to develop
+bootloader firmware for Fuchsia devices. The intent is for this SDK to provide
+common functionality needed by all firmware, such as the ZBI structure needed
+to boot the Zircon kernel, so it doesn't have to be re-implemented from scratch
+when bringing up a new board.
+
+## Building the Firmware SDK
+
+The Firmware SDK build rules live in `//sdk/BUILD.gn`. The SDK is not built
+in the normal flow, but can be built manually as follows:
+
+1. Add `build_sdk_archives=true` to your gn args, typically by one of:
+   1. `fx set ... --args=build_sdk_archives=true`, or
+   2. `fx args` and add `build_sdk_archives = true` to the args file
+1. Run `fx build sdk:firmware`
+1. Find the resulting SDK archive at `<build_dir>/sdk/archive/firmware.tar.gz`
+
+## Porting
+
+Firmware development is usually device-specific so it's not expected that this
+code will be usable directly; some porting work will be necessary. However, to
+ease the porting burden, everything in the Firmare SDK has a pure C
+implementation available, as firmware toolchains are commonly C-only.
+
+General porting steps are:
+
+1. Build the Firmware SDK archive (see instructions above)
+1. Unpack the archive in the firmware source tree
+1. Add the required files and paths to the firmware build system
+1. If necessary, modify SDK headers to work with the firmware source (e.g.
+   some files use standard library headers which may not exist)
+
+## Backwards Compatibility
+
+### ABI
+
+The structures used to communicate between the OS and bootloader will maintain
+ABI backwards compatibility:
+
+* ZBI format
+* vbmeta format
+* A/B/R metadata
+
+This backwards compatibility is required so that we can continue to evolve the
+Fuchsia implementation as needed without also requiring simultaneous firmware
+updates.
+
+### API
+
+The Firmware SDK does not enforce any API compatibility, meaning function
+signatures, constant/type names, etc may change at any time. However, any such
+changes should be relatively infrequent, and will only affect firmware when
+uprevving to a newer Firmware SDK version.
+
+## Components
+
+### ZBI format
+
+The ZBI format defines the structure of ZBI images. The firmware needs to know
+this in order to load the ZBI from disk into memory, append a number of ZBI
+items, and then pass control to the ZBI kernel.
+
+There's currently no way to provide these definitions alone in an SDK; instead
+they are included as part of the larger Zircon sysroot SDK (fxbug.dev/65907).
+
+The ZBI definitions are currently located in the Firmware SDK under
+`arch/<arch>/sysroot/include/zircon/boot/`, primarily `image.h`.
+
+### libzbi
+
+libzbi is a reference library, wrapping the ZBI format in a more convenient API.
+Firmware is not required to use libzbi, it just has to adhere to the underlying
+ZBI format.
+
+libzbi will be in the Firmware SDK under `pkg/zbi/`.
+
+### libabr
+
+libabr provides A/B/R booting support. A/B/R booting is optional, for example a
+dev board may have no real need for A/B OTA updates, and it is not mandatory for
+booting Zircon.
+
+libabr will be in the Firmware SDK under `pkg/abr/`.
+
+### libavb
+
+libavb provides verified boot support, i.e. using vbmeta images to authenticate
+Zircon images loaded from disk before attempting to use them. Like libabr, this
+library is not required and may be omitted for things like dev boards.
+
+This library originally comes from
+[Android](https://android.googlesource.com/platform/external/avb/). While we
+intend to upstream any necessary changes so they should be functionally
+identical, firmware should use the copy in the Firmware SDK in case there are
+local changes, and to make sure there aren't any version mismatch issues with
+the code used by the Fuchsia build to generate the vbmeta images.
+
+libavb will be in the Firmware SDK under `pkg/avb/`.
+
+### Demo/Test avb_keys
+
+The "avb_key" subdirectory holds a set of board/product specific certificates
+and keys for for demonstrating the use of verified booting with libavb.
diff --git a/lib/fuchsia/arch/arm64/sysroot/dist/lib/asan-ubsan/ld.so.1 b/lib/fuchsia/arch/arm64/sysroot/dist/lib/asan-ubsan/ld.so.1
index 78afcce..1967c11 100755
--- a/lib/fuchsia/arch/arm64/sysroot/dist/lib/asan-ubsan/ld.so.1
+++ b/lib/fuchsia/arch/arm64/sysroot/dist/lib/asan-ubsan/ld.so.1
Binary files differ
diff --git a/lib/fuchsia/arch/arm64/sysroot/dist/lib/asan/ld.so.1 b/lib/fuchsia/arch/arm64/sysroot/dist/lib/asan/ld.so.1
index 4428ea1..4fe238b 100755
--- a/lib/fuchsia/arch/arm64/sysroot/dist/lib/asan/ld.so.1
+++ b/lib/fuchsia/arch/arm64/sysroot/dist/lib/asan/ld.so.1
Binary files differ
diff --git a/lib/fuchsia/arch/arm64/sysroot/dist/lib/ld.so.1 b/lib/fuchsia/arch/arm64/sysroot/dist/lib/ld.so.1
index 9cd2a22..26746b1 100755
--- a/lib/fuchsia/arch/arm64/sysroot/dist/lib/ld.so.1
+++ b/lib/fuchsia/arch/arm64/sysroot/dist/lib/ld.so.1
Binary files differ
diff --git a/lib/fuchsia/arch/arm64/sysroot/include/netinet/tcp.h b/lib/fuchsia/arch/arm64/sysroot/include/netinet/tcp.h
index e892dd2..8cef584 100644
--- a/lib/fuchsia/arch/arm64/sysroot/include/netinet/tcp.h
+++ b/lib/fuchsia/arch/arm64/sysroot/include/netinet/tcp.h
@@ -30,6 +30,17 @@
 #define TCP_CC_INFO 26
 #define TCP_SAVE_SYN 27
 #define TCP_SAVED_SYN 28
+#define TCP_REPAIR_WINDOW 29
+#define TCP_FASTOPEN_CONNECT 30
+#define TCP_ULP 31
+#define TCP_MD5SIG_EXT 32
+#define TCP_FASTOPEN_KEY 33
+#define TCP_FASTOPEN_NO_COOKIE 34
+#define TCP_ZEROCOPY_RECEIVE 35
+#define TCP_INQ 36
+#define TCP_TX_DELAY 37
+
+#define TCP_CM_INQ TCP_INQ
 
 #define TCP_ESTABLISHED 1
 #define TCP_SYN_SENT 2
@@ -43,6 +54,34 @@
 #define TCP_LISTEN 10
 #define TCP_CLOSING 11
 
+enum {
+  TCP_NLA_PAD,
+  TCP_NLA_BUSY,
+  TCP_NLA_RWND_LIMITED,
+  TCP_NLA_SNDBUF_LIMITED,
+  TCP_NLA_DATA_SEGS_OUT,
+  TCP_NLA_TOTAL_RETRANS,
+  TCP_NLA_PACING_RATE,
+  TCP_NLA_DELIVERY_RATE,
+  TCP_NLA_SND_CWND,
+  TCP_NLA_REORDERING,
+  TCP_NLA_MIN_RTT,
+  TCP_NLA_RECUR_RETRANS,
+  TCP_NLA_DELIVERY_RATE_APP_LMT,
+  TCP_NLA_SNDQ_SIZE,
+  TCP_NLA_CA_STATE,
+  TCP_NLA_SND_SSTHRESH,
+  TCP_NLA_DELIVERED,
+  TCP_NLA_DELIVERED_CE,
+  TCP_NLA_BYTES_SENT,
+  TCP_NLA_BYTES_RETRANS,
+  TCP_NLA_DSACK_DUPS,
+  TCP_NLA_REORD_SEEN,
+  TCP_NLA_SRTT,
+  TCP_NLA_TIMEOUT_REHASH,
+  TCP_NLA_BYTES_NOTSENT,
+};
+
 #if defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
 #define TCPOPT_EOL 0
 #define TCPOPT_NOP 1
@@ -58,7 +97,6 @@
 
 #define SOL_TCP 6
 
-#include <endian.h>
 #include <stdint.h>
 #include <sys/socket.h>
 #include <sys/types.h>
@@ -146,6 +184,13 @@
 #define TCP_CA_Recovery 3
 #define TCP_CA_Loss 4
 
+enum tcp_fastopen_client_fail {
+  TFO_STATUS_UNSPEC,
+  TFO_COOKIE_UNAVAILABLE,
+  TFO_DATA_NOT_ACKED,
+  TFO_SYN_RETRANSMITTED,
+};
+
 struct tcp_info {
   uint8_t tcpi_state;
   uint8_t tcpi_ca_state;
@@ -154,6 +199,7 @@
   uint8_t tcpi_backoff;
   uint8_t tcpi_options;
   uint8_t tcpi_snd_wscale : 4, tcpi_rcv_wscale : 4;
+  uint8_t tcpi_delivery_rate_app_limited : 1, tcpi_fastopen_client_fail : 2;
   uint32_t tcpi_rto;
   uint32_t tcpi_ato;
   uint32_t tcpi_snd_mss;
@@ -184,18 +230,66 @@
   uint64_t tcpi_bytes_received;
   uint32_t tcpi_segs_out;
   uint32_t tcpi_segs_in;
+  uint32_t tcpi_notsent_bytes;
+  uint32_t tcpi_min_rtt;
+  uint32_t tcpi_data_segs_in;
+  uint32_t tcpi_data_segs_out;
+  uint64_t tcpi_delivery_rate;
+  uint64_t tcpi_busy_time;
+  uint64_t tcpi_rwnd_limited;
+  uint64_t tcpi_sndbuf_limited;
+  uint32_t tcpi_delivered;
+  uint32_t tcpi_delivered_ce;
+  uint64_t tcpi_bytes_sent;
+  uint64_t tcpi_bytes_retrans;
+  uint32_t tcpi_dsack_dups;
+  uint32_t tcpi_reord_seen;
+  uint32_t tcpi_rcv_ooopack;
+  uint32_t tcpi_snd_wnd;
 };
 
 #define TCP_MD5SIG_MAXKEYLEN 80
 
+#define TCP_MD5SIG_FLAG_PREFIX 0x1
+#define TCP_MD5SIG_FLAG_IFINDEX 0x2
+
 struct tcp_md5sig {
   struct sockaddr_storage tcpm_addr;
-  uint16_t __tcpm_pad1;
+  uint8_t tcpm_flags;
+  uint8_t tcpm_prefixlen;
   uint16_t tcpm_keylen;
-  uint32_t __tcpm_pad2;
+  int tcpm_ifindex;
   uint8_t tcpm_key[TCP_MD5SIG_MAXKEYLEN];
 };
 
+struct tcp_diag_md5sig {
+  uint8_t tcpm_family;
+  uint8_t tcpm_prefixlen;
+  uint16_t tcpm_keylen;
+  uint32_t tcpm_addr[4];
+  uint8_t tcpm_key[TCP_MD5SIG_MAXKEYLEN];
+};
+
+#define TCP_REPAIR_ON 1
+#define TCP_REPAIR_OFF 0
+#define TCP_REPAIR_OFF_NO_WP -1
+
+struct tcp_repair_window {
+  uint32_t snd_wl1;
+  uint32_t snd_wnd;
+  uint32_t max_window;
+  uint32_t rcv_wnd;
+  uint32_t rcv_wup;
+};
+
+struct tcp_zerocopy_receive {
+  uint64_t address;
+  uint32_t length;
+  uint32_t recv_skip_hint;
+  uint32_t inq;
+  int32_t err;
+};
+
 #endif
 
 #endif  // SYSROOT_NETINET_TCP_H_
diff --git a/lib/fuchsia/arch/arm64/sysroot/include/sys/mman.h b/lib/fuchsia/arch/arm64/sysroot/include/sys/mman.h
index 7a913ae..1810781 100644
--- a/lib/fuchsia/arch/arm64/sysroot/include/sys/mman.h
+++ b/lib/fuchsia/arch/arm64/sysroot/include/sys/mman.h
@@ -92,6 +92,10 @@
 int madvise(void*, size_t, int);
 #endif
 
+#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
+int memfd_create(const char* name, unsigned int flags);
+#endif
+
 int shm_open(const char*, int, mode_t);
 int shm_unlink(const char*);
 
diff --git a/lib/fuchsia/arch/arm64/sysroot/include/zircon/analyzer.h b/lib/fuchsia/arch/arm64/sysroot/include/zircon/analyzer.h
new file mode 100644
index 0000000..90b4a9b
--- /dev/null
+++ b/lib/fuchsia/arch/arm64/sysroot/include/zircon/analyzer.h
@@ -0,0 +1,31 @@
+// Copyright 2020 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This file provides macros for Fuchsia handle annotations to better facilitate
+// Clang static analysis.
+
+#ifndef SYSROOT_ZIRCON_ANALYZER_H_
+#define SYSROOT_ZIRCON_ANALYZER_H_
+
+#if defined(__clang_analyzer__)
+// The argument that has this annotation would be generated by callee
+// and handled back to the caller. Caller is responsible for freeing the handle.
+#define ZX_HANDLE_ACQUIRE __attribute__((acquire_handle("Fuchsia")))
+// The argument that has this annotation would be released by callee.
+// Caller must not use the handle again after calling the function.
+#define ZX_HANDLE_RELEASE __attribute__((release_handle("Fuchsia")))
+// The argument that has this annotation would be used by callee. Caller still
+// owns this handle and is responsible for freeing the handle.
+#define ZX_HANDLE_USE __attribute__((use_handle("Fuchsia")))
+// When an argument has this annotation, the caller borrows the argument from
+// resource (e.g. handle) from the callee. Caller must not free the handle.
+#define ZX_HANDLE_ACQUIRE_UNOWNED __attribute__((acquire_handle("FuchsiaUnowned")))
+#else
+#define ZX_HANDLE_ACQUIRE
+#define ZX_HANDLE_RELEASE
+#define ZX_HANDLE_USE
+#define ZX_HANDLE_ACQUIRE_UNOWNED
+#endif  // __clang_analyzer__
+
+#endif  // SYSROOT_ZIRCON_ANALYZER_H_
diff --git a/lib/fuchsia/arch/arm64/sysroot/include/zircon/boot/crash-reason.h b/lib/fuchsia/arch/arm64/sysroot/include/zircon/boot/crash-reason.h
index f626fac..5fadc52 100644
--- a/lib/fuchsia/arch/arm64/sysroot/include/zircon/boot/crash-reason.h
+++ b/lib/fuchsia/arch/arm64/sysroot/include/zircon/boot/crash-reason.h
@@ -38,6 +38,11 @@
 // HW reboot reason may be known, but only if the bootloader reports it to us.
 #define ZIRCON_CRASH_REASON_SOFTWARE_WATCHDOG ((uint32_t)5)
 
+// "Userspace root job termination" indicates a crash triggered by the system
+// because it detected the termination of the userspace root job, most likely
+// because one its critical processes crashed.
+#define ZIRCON_CRASH_REASON_USERSPACE_ROOT_JOB_TERMINATION ((uint32_t)6)
+
 #ifndef __ASSEMBLER__
 #if !__cplusplus
 typedef uint32_t zircon_crash_reason_t;
@@ -49,6 +54,7 @@
   Oom = ZIRCON_CRASH_REASON_OOM,
   Panic = ZIRCON_CRASH_REASON_PANIC,
   SoftwareWatchdog = ZIRCON_CRASH_REASON_SOFTWARE_WATCHDOG,
+  UserspaceRootJobTermination = ZIRCON_CRASH_REASON_USERSPACE_ROOT_JOB_TERMINATION,
 };
 
 // Using alias to maintain compatibility with APIs meant to be used by both C and C++.
diff --git a/lib/fuchsia/arch/arm64/sysroot/include/zircon/boot/driver-config.h b/lib/fuchsia/arch/arm64/sysroot/include/zircon/boot/driver-config.h
index 7f72fca..fb83c44 100644
--- a/lib/fuchsia/arch/arm64/sysroot/include/zircon/boot/driver-config.h
+++ b/lib/fuchsia/arch/arm64/sysroot/include/zircon/boot/driver-config.h
@@ -34,11 +34,13 @@
 typedef struct {
   uint64_t mmio_phys;
   uint32_t irq;
+  uint32_t reserved;
 } dcfg_simple_t;
 
 // Used by KDRV_I8250_PIO_UART.
 typedef struct {
   uint16_t base;
+  uint16_t reserved;
   uint32_t irq;
 } dcfg_simple_pio_t;
 
@@ -47,11 +49,13 @@
   uint64_t soc_mmio_phys;
   uint64_t uart_mmio_phys;
   uint32_t irq;
+  uint32_t reserved;
 } dcfg_soc_uart_t;
 
 // for KDRV_ARM_PSCI
 typedef struct {
-  bool use_hvc;
+  uint8_t use_hvc;
+  uint8_t reserved[7];
   uint64_t shutdown_args[3];
   uint64_t reboot_args[3];
   uint64_t reboot_bootloader_args[3];
@@ -72,8 +76,9 @@
   uint64_t gich_offset;
   uint64_t gicv_offset;
   uint32_t ipi_base;
-  bool optional;
-  bool use_msi;
+  uint8_t optional;
+  uint8_t use_msi;
+  uint16_t reserved;
 } dcfg_arm_gicv2_driver_t;
 
 // for KDRV_ARM_GIC_V3
@@ -84,7 +89,8 @@
   uint64_t gicr_stride;
   uint64_t mx8_gpr_phys;
   uint32_t ipi_base;
-  bool optional;
+  uint8_t optional;
+  uint8_t reserved[3];
 } dcfg_arm_gicv3_driver_t;
 
 // for KDRV_ARM_GENERIC_TIMER
@@ -158,6 +164,7 @@
   dcfg_generic_32bit_watchdog_action_t disable_action;
   zx_duration_t watchdog_period_nsec;
   uint32_t flags;
+  uint32_t reserved;
 } dcfg_generic_32bit_watchdog_t;
 
 #endif  // SYSROOT_ZIRCON_BOOT_DRIVER_CONFIG_H_
diff --git a/lib/fuchsia/arch/arm64/sysroot/include/zircon/boot/image.h b/lib/fuchsia/arch/arm64/sysroot/include/zircon/boot/image.h
index 326dc00..5461614 100644
--- a/lib/fuchsia/arch/arm64/sysroot/include/zircon/boot/image.h
+++ b/lib/fuchsia/arch/arm64/sysroot/include/zircon/boot/image.h
@@ -5,15 +5,11 @@
 #ifndef SYSROOT_ZIRCON_BOOT_IMAGE_H_
 #define SYSROOT_ZIRCON_BOOT_IMAGE_H_
 
-// This file contains assembly code that cannot be clang formatted.
-// clang-format off
-
 #ifndef __ASSEMBLER__
 // Local modification for Estelle. See lib/fuchsia/README.estelle.md.
 #include <common.h>  // <stdint.h>
 #endif
 
-
 // Zircon Boot Image format (ZBI).
 //
 // A Zircon Boot Image consists of a container header followed by boot
@@ -29,20 +25,20 @@
 // up to a ZBI_ALIGNMENT (8-byte) boundary.  This padding is not reflected
 // in the zbi_header_t.length value.
 //
-// A "complete" ZBI can be booted by a Zircon-compatible boot loader.
+// A bootable ZBI can be booted by a Zircon-compatible boot loader.
 // It contains one ZBI_TYPE_KERNEL_{ARCH} boot item that must come first,
-// followed by any number of additional boot items, which must include
-// exactly one ZBI_TYPE_STORAGE_BOOTFS item.
+// followed by any number of additional boot items whose number, types,
+// and details much comport with that kernel's expectations.
 //
 // A partial ZBI cannot be booted, and is only used during the build process.
-// It contains one or more boot items and can be combined with other ZBIs to
-// make a complete ZBI.
+// It contains one or more boot items and can be combined with a kernel and
+// other ZBIs to make a bootable ZBI.
 
 // All items begin at an 8-byte aligned offset into the image.
 #ifdef __ASSEMBLER__
-#define ZBI_ALIGNMENT           (8)
+#define ZBI_ALIGNMENT (8)
 #else
-#define ZBI_ALIGNMENT           (8u)
+#define ZBI_ALIGNMENT (8u)
 #endif
 
 // Round n up to the next 8 byte boundary
@@ -50,63 +46,65 @@
 #ifdef __cplusplus
 constexpr
 #endif
-static inline uint32_t ZBI_ALIGN(uint32_t n) {
-    return ((n + ZBI_ALIGNMENT - 1) & -ZBI_ALIGNMENT);
+    static inline uint32_t
+    ZBI_ALIGN(uint32_t n) {
+  return ((n + ZBI_ALIGNMENT - 1) & -ZBI_ALIGNMENT);
 }
 #endif
 
 // LSW of sha256("bootdata")
-#define ZBI_CONTAINER_MAGIC     (0x868cf7e6)
+#define ZBI_CONTAINER_MAGIC (0x868cf7e6)
 
 // LSW of sha256("bootitem")
-#define ZBI_ITEM_MAGIC          (0xb5781729)
+#define ZBI_ITEM_MAGIC (0xb5781729)
 
 // This flag is always required.
-#define ZBI_FLAG_VERSION        (0x00010000)
+#define ZBI_FLAG_VERSION (0x00010000)
 
 // ZBI items with the CRC32 flag must have a valid crc32.
 // Otherwise their crc32 field must contain ZBI_ITEM_NO_CRC32
-#define ZBI_FLAG_CRC32          (0x00020000)
+#define ZBI_FLAG_CRC32 (0x00020000)
 
 // Value for zbi_header_t.crc32 when ZBI_FLAG_CRC32 is not set.
-#define ZBI_ITEM_NO_CRC32       (0x4a87e8d6)
+#define ZBI_ITEM_NO_CRC32 (0x4a87e8d6)
 
 #ifndef __ASSEMBLER__
 // Each header must be 8-byte aligned.  The length field specifies the
 // actual payload length and does not include the size of padding.
 typedef struct {
-    // ZBI_TYPE_* constant, see below.
-    uint32_t type;
+  // ZBI_TYPE_* constant, see below.
+  uint32_t type;
 
-    // Size of the payload immediately following this header.  This
-    // does not include the header itself nor any alignment padding
-    // after the payload.
-    uint32_t length;
+  // Size of the payload immediately following this header.  This
+  // does not include the header itself nor any alignment padding
+  // after the payload.
+  uint32_t length;
 
-    // Type-specific extra data.  Each type specifies the use of this
-    // field; see below.  When not explicitly specified, it should be zero.
-    uint32_t extra;
+  // Type-specific extra data.  Each type specifies the use of this
+  // field; see below.  When not explicitly specified, it should be zero.
+  uint32_t extra;
 
-    // Flags for this item.  This must always include ZBI_FLAG_VERSION.
-    // It should contain ZBI_FLAG_CRC32 for any item where it's feasible
-    // to compute the CRC32 at build time.  Other flags are specific to
-    // each type; see below.
-    uint32_t flags;
+  // Flags for this item.  This must always include ZBI_FLAG_VERSION.
+  // It should contain ZBI_FLAG_CRC32 for any item where it's feasible
+  // to compute the CRC32 at build time.  Other flags are specific to
+  // each type; see below.
+  uint32_t flags;
 
-    // For future expansion.  Set to 0.
-    uint32_t reserved0;
-    uint32_t reserved1;
+  // For future expansion.  Set to 0.
+  uint32_t reserved0;
+  uint32_t reserved1;
 
-    // Must be ZBI_ITEM_MAGIC.
-    uint32_t magic;
+  // Must be ZBI_ITEM_MAGIC.
+  uint32_t magic;
 
-    // Must be the CRC32 of payload if ZBI_FLAG_CRC32 is set,
-    // otherwise must be ZBI_ITEM_NO_CRC32.
-    uint32_t crc32;
+  // Must be the CRC32 of payload if ZBI_FLAG_CRC32 is set,
+  // otherwise must be ZBI_ITEM_NO_CRC32.
+  uint32_t crc32;
 } zbi_header_t;
 #endif
 
 // Be sure to add new types to ZBI_ALL_TYPES.
+// clang-format off
 #define ZBI_ALL_TYPES(macro) \
     macro(ZBI_TYPE_CONTAINER, "CONTAINER", ".bin") \
     macro(ZBI_TYPE_KERNEL_X64, "KERNEL_X64", ".bin") \
@@ -115,6 +113,7 @@
     macro(ZBI_TYPE_STORAGE_RAMDISK, "RAMDISK", ".bin") \
     macro(ZBI_TYPE_STORAGE_BOOTFS, "BOOTFS", ".bin") \
     macro(ZBI_TYPE_STORAGE_BOOTFS_FACTORY, "BOOTFS_FACTORY", ".bin") \
+    macro(ZBI_TYPE_STORAGE_KERNEL, "KERNEL", ".bin") \
     macro(ZBI_TYPE_CMDLINE, "CMDLINE", ".txt") \
     macro(ZBI_TYPE_CRASHLOG, "CRASHLOG", ".bin") \
     macro(ZBI_TYPE_NVRAM, "NVRAM", ".bin") \
@@ -138,7 +137,9 @@
     macro(ZBI_TYPE_HW_REBOOT_REASON, "HW_REBOOT_REASON", ".bin") \
     macro(ZBI_TYPE_SERIAL_NUMBER, "SERIAL_NUMBER", ".txt") \
     macro(ZBI_TYPE_BOOTLOADER_FILE, "BOOTLOADER_FILE", ".bin") \
-    macro(ZBI_TYPE_DEVICETREE, "DEVICETREE", ".dtb")
+    macro(ZBI_TYPE_DEVICETREE, "DEVICETREE", ".dtb") \
+    macro(ZBI_TYPE_SECURE_ENTROPY, "ENTROPY", ".bin")
+// clang-format on
 
 // Each ZBI starts with a container header.
 //     length:          Total size of the image after this header.
@@ -147,12 +148,13 @@
 //                      Must be a multiple of ZBI_ALIGNMENT.
 //     extra:           Must be ZBI_CONTAINER_MAGIC.
 //     flags:           Must be ZBI_FLAG_VERSION and no other flags.
-#define ZBI_TYPE_CONTAINER      (0x544f4f42) // BOOT
+#define ZBI_TYPE_CONTAINER (0x544f4f42)  // BOOT
 
 // Define a container header in assembly code.  The symbol name is defined
 // as a local label; use .global symbol to make it global.  The length
 // argument can use assembly label arithmetic like any immediate operand.
 #ifdef __ASSEMBLER__
+// clang-format off
 #define ZBI_CONTAINER_HEADER(symbol, length)    \
     .balign ZBI_ALIGNMENT;                      \
     symbol:                                     \
@@ -166,21 +168,16 @@
         .int ZBI_ITEM_NO_CRC32;                 \
     .size symbol, . - symbol;                   \
     .type symbol, %object
+// clang-format on
 #else
-#define ZBI_CONTAINER_HEADER(length) {          \
-    ZBI_TYPE_CONTAINER,                         \
-    (length),                                   \
-    ZBI_CONTAINER_MAGIC,                        \
-    ZBI_FLAG_VERSION,                           \
-    0,                                          \
-    0,                                          \
-    ZBI_ITEM_MAGIC,                             \
-    ZBI_ITEM_NO_CRC32,                          \
-}
+#define ZBI_CONTAINER_HEADER(length)                                                           \
+  {                                                                                            \
+    ZBI_TYPE_CONTAINER, (length), ZBI_CONTAINER_MAGIC, ZBI_FLAG_VERSION, 0, 0, ZBI_ITEM_MAGIC, \
+        ZBI_ITEM_NO_CRC32,                                                                     \
+  }
 #endif
 
-
-// The kernel image.  In a complete ZBI this item must always be first,
+// The kernel image.  In a bootable ZBI this item must always be first,
 // immediately after the ZBI_TYPE_CONTAINER header.  The contiguous memory
 // image of the kernel is formed from the ZBI_TYPE_CONTAINER header, the
 // ZBI_TYPE_KERNEL_{ARCH} header, and the payload.
@@ -228,40 +225,37 @@
 //     holds the physical address of the bootloader-constructed ZBI.
 //     All other registers are unspecified.
 //
-#define ZBI_TYPE_KERNEL_PREFIX     (0x004e524b) // KRN\0
-#define ZBI_TYPE_KERNEL_MASK       (0x00FFFFFF)
-#define ZBI_TYPE_KERNEL_X64        (0x4c4e524b) // KRNL
-#define ZBI_TYPE_KERNEL_ARM64      (0x384e524b) // KRN8
-#define ZBI_IS_KERNEL_BOOTITEM(x)  (((x) & ZBI_TYPE_KERNEL_MASK) ==  \
-                                    ZBI_TYPE_KERNEL_PREFIX)
+#define ZBI_TYPE_KERNEL_PREFIX (0x004e524b)  // KRN\0
+#define ZBI_TYPE_KERNEL_MASK (0x00FFFFFF)    // Mask to compare to the prefix.
+#define ZBI_TYPE_KERNEL_X64 (0x4c4e524b)     // KRNL
+#define ZBI_TYPE_KERNEL_ARM64 (0x384e524b)   // KRN8
+#define ZBI_IS_KERNEL_BOOTITEM(x) (((x)&ZBI_TYPE_KERNEL_MASK) == ZBI_TYPE_KERNEL_PREFIX)
 
 #ifndef __ASSEMBLER__
 typedef struct {
-    // Entry-point address.  The interpretation of this differs by machine.
-    uint64_t entry;
-    // Minimum amount (in bytes) of scratch memory that the kernel requires
-    // immediately after its load image.
-    uint64_t reserve_memory_size;
+  // Entry-point address.  The interpretation of this differs by machine.
+  uint64_t entry;
+  // Minimum amount (in bytes) of scratch memory that the kernel requires
+  // immediately after its load image.
+  uint64_t reserve_memory_size;
 } zbi_kernel_t;
 
 // The whole contiguous image loaded into memory by the boot loader.
 typedef struct {
-    zbi_header_t hdr_file;
-    zbi_header_t hdr_kernel;
-    zbi_kernel_t data_kernel;
-    uint8_t contents[/*hdr_kernel.length - sizeof(zbi_kernel_t)*/];
-    // data_kernel.reserve_memory_size bytes in memory are free after contents.
+  zbi_header_t hdr_file;
+  zbi_header_t hdr_kernel;
+  zbi_kernel_t data_kernel;
+  uint8_t contents[/*hdr_kernel.length - sizeof(zbi_kernel_t)*/];
+  // data_kernel.reserve_memory_size bytes in memory are free after contents.
 } zircon_kernel_t;
 #endif
 
-
 // A discarded item that should just be ignored.  This is used for an
 // item that was already processed and should be ignored by whatever
 // stage is now looking at the ZBI.  An earlier stage already "consumed"
 // this information, but avoided copying data around to remove it from
 // the ZBI item stream.
-#define ZBI_TYPE_DISCARD        (0x50494b53) // SKIP
-
+#define ZBI_TYPE_DISCARD (0x50494b53)  // SKIP
 
 // ZBI_TYPE_STORAGE_* types represent an image that might otherwise
 // appear on some block storage device, i.e. a RAM disk of some sort.
@@ -292,21 +286,28 @@
 //    only support one particular compression format.
 //  - The `zbi` tool will usually retain the ability to compress and
 //    decompress for old formats, and can be used to convert between formats.
-#define ZBI_FLAG_STORAGE_COMPRESSED     (0x00000001)
+#define ZBI_FLAG_STORAGE_COMPRESSED (0x00000001)
 
 // A virtual disk image.  This is meant to be treated as if it were a
 // storage device.  The payload (after decompression) is the contents of
 // the storage device, in whatever format that might be.
-#define ZBI_TYPE_STORAGE_RAMDISK        (0x4b534452) // RDSK
+#define ZBI_TYPE_STORAGE_RAMDISK (0x4b534452)  // RDSK
 
 // The /boot filesystem in BOOTFS format, specified in <zircon/boot/bootfs.h>.
-// A complete ZBI must have exactly one ZBI_TYPE_STORAGE_BOOTFS item.
 // Zircon [userboot](../../../../docs/userboot.md) handles the contents
 // of this filesystem.
-#define ZBI_TYPE_STORAGE_BOOTFS         (0x42534642) // BFSB
+#define ZBI_TYPE_STORAGE_BOOTFS (0x42534642)  // BFSB
+
+// Storage used by the kernel (such as a compressed image containing the actual
+// kernel).  The meaning and format of the data is specific to the kernel,
+// though it always uses the standard storage compression protocol described
+// above.  Each particular KERNEL_{ARCH} item image and its STORAGE_KERNEL item
+// image are intimately tied and one cannot work without the exact correct
+// corresponding other.
+#define ZBI_TYPE_STORAGE_KERNEL (0x5254534b)  // KSTR
 
 // Device-specific factory data, stored in BOOTFS format, specified below.
-#define ZBI_TYPE_STORAGE_BOOTFS_FACTORY (0x46534642) // BFSF
+#define ZBI_TYPE_STORAGE_BOOTFS_FACTORY (0x46534642)  // BFSF
 
 // The remaining types are used to communicate information from the boot
 // loader to the kernel.  Usually these are synthesized in memory by the
@@ -315,78 +316,77 @@
 // and crc32 fields to zero, though setting them to ZBI_FLAG_VERSION and
 // ZBI_ITEM_NO_CRC32 is specified.  The kernel doesn't check.
 
-
 // A kernel command line fragment, a NUL-terminated UTF-8 string.
 // Multiple ZBI_TYPE_CMDLINE items can appear.  They are treated as if
 // concatenated with ' ' between each item, in the order they appear:
-// first items in the complete ZBI containing the kernel; then items in
+// first items in the bootable ZBI containing the kernel; then items in
 // the ZBI synthesized by the boot loader.  The kernel interprets the
 // [whole command line](../../../../docs/kernel_cmdline.md).
-#define ZBI_TYPE_CMDLINE                (0x4c444d43) // CMDL
+#define ZBI_TYPE_CMDLINE (0x4c444d43)  // CMDL
 
 // The crash log from the previous boot, a UTF-8 string.
-#define ZBI_TYPE_CRASHLOG               (0x4d4f4f42) // BOOM
+#define ZBI_TYPE_CRASHLOG (0x4d4f4f42)  // BOOM
 
 // Physical memory region that will persist across warm boots.
 // zbi_nvram_t gives the physical base address and length in bytes.
-#define ZBI_TYPE_NVRAM                  (0x4c4c564e) // NVLL
+#define ZBI_TYPE_NVRAM (0x4c4c564e)  // NVLL
 // This reflects a typo we need to support for a while.
-#define ZBI_TYPE_NVRAM_DEPRECATED       (0x4c4c5643) // CVLL
+#define ZBI_TYPE_NVRAM_DEPRECATED (0x4c4c5643)  // CVLL
 #ifndef __ASSEMBLER__
 typedef struct {
-    uint64_t base;
-    uint64_t length;
+  uint64_t base;
+  uint64_t length;
 } zbi_nvram_t;
 #endif
 
 #define ZBI_BOARD_NAME_LEN 32
 
 // Platform ID Information.
-#define ZBI_TYPE_PLATFORM_ID            (0x44494C50) // PLID
+#define ZBI_TYPE_PLATFORM_ID (0x44494C50)  // PLID
 #ifndef __ASSEMBLER__
 typedef struct {
-    uint32_t vid;
-    uint32_t pid;
-    char board_name[ZBI_BOARD_NAME_LEN];
+  uint32_t vid;
+  uint32_t pid;
+  char board_name[ZBI_BOARD_NAME_LEN];
 } zbi_platform_id_t;
 #endif
 
-#define ZBI_TYPE_DRV_BOARD_INFO         (0x4953426D) // mBSI
+#define ZBI_TYPE_DRV_BOARD_INFO (0x4953426D)  // mBSI
 // Board-specific information.
 #ifndef __ASSEMBLER__
 typedef struct {
-    uint32_t revision;
+  uint32_t revision;
 } zbi_board_info_t;
 #endif
 
 // CPU configuration, a zbi_cpu_config_t header followed by one or more
 // zbi_cpu_cluster_t entries.  zbi_header_t.length must equal
 // zbi_cpu_config_t.cluster_count * sizeof(zbi_cpu_cluster_t).
-#define ZBI_TYPE_CPU_CONFIG             (0x43555043) // CPUC
+#define ZBI_TYPE_CPU_CONFIG (0x43555043)  // CPUC
 #ifndef __ASSEMBLER__
 typedef struct {
-    // Number of CPU cores in the cluster.
-    uint32_t cpu_count;
+  // Number of CPU cores in the cluster.
+  uint32_t cpu_count;
 
-    // Reserved for future use.  Set to 0.
-    uint32_t type;
-    uint32_t flags;
-    uint32_t reserved;
+  // Reserved for future use.  Set to 0.
+  uint32_t type;
+  uint32_t flags;
+  uint32_t reserved;
 } zbi_cpu_cluster_t;
 
 typedef struct {
-    // Number of zbi_cpu_cluster_t entries following this header.
-    uint32_t cluster_count;
+  // Number of zbi_cpu_cluster_t entries following this header.
+  uint32_t cluster_count;
 
-    // Reserved for future use.  Set to 0.
-    uint32_t reserved[3];
+  // Reserved for future use.  Set to 0.
+  uint32_t reserved[3];
 
-    // cluster_count entries follow.
-    zbi_cpu_cluster_t clusters[];
+  // cluster_count entries follow.
+  zbi_cpu_cluster_t clusters[];
 } zbi_cpu_config_t;
 #endif
 
-#define ZBI_TYPE_CPU_TOPOLOGY           (0x544F504F) // TOPO
+#define ZBI_TYPE_CPU_TOPOLOGY (0x544F504F)  // TOPO
 
 #ifndef __ASSEMBLER__
 
@@ -404,74 +404,74 @@
 #define ZBI_TOPOLOGY_NO_PARENT 0xFFFF
 
 typedef enum {
-    ZBI_TOPOLOGY_ARCH_UNDEFINED = 0, // Intended primarily for testing.
-    ZBI_TOPOLOGY_ARCH_X86 = 1,
-    ZBI_TOPOLOGY_ARCH_ARM = 2,
+  ZBI_TOPOLOGY_ARCH_UNDEFINED = 0,  // Intended primarily for testing.
+  ZBI_TOPOLOGY_ARCH_X86 = 1,
+  ZBI_TOPOLOGY_ARCH_ARM = 2,
 } zbi_topology_architecture_t;
 
 typedef struct {
-    // Cluster ids for each level, one being closest to the cpu.
-    // These map to aff1, aff2, and aff3 values in the ARM registers.
-    uint8_t cluster_1_id;
-    uint8_t cluster_2_id;
-    uint8_t cluster_3_id;
+  // Cluster ids for each level, one being closest to the cpu.
+  // These map to aff1, aff2, and aff3 values in the ARM registers.
+  uint8_t cluster_1_id;
+  uint8_t cluster_2_id;
+  uint8_t cluster_3_id;
 
-    // Id of the cpu inside of the bottom-most cluster, aff0 value.
-    uint8_t cpu_id;
+  // Id of the cpu inside of the bottom-most cluster, aff0 value.
+  uint8_t cpu_id;
 
-    // The GIC interface number for this processor.
-    // In GIC v3+ this is not necessary as the processors are addressed by their
-    // affinity routing (all cluster ids followed by cpu_id).
-    uint8_t gic_id;
-}  zbi_topology_arm_info_t;
+  // The GIC interface number for this processor.
+  // In GIC v3+ this is not necessary as the processors are addressed by their
+  // affinity routing (all cluster ids followed by cpu_id).
+  uint8_t gic_id;
+} zbi_topology_arm_info_t;
 
 typedef struct {
-    // Indexes here correspond to the logical_ids index for the thread.
-    uint32_t apic_ids[ZBI_MAX_SMT];
-    uint32_t apic_id_count;
-}  zbi_topology_x86_info_t;
+  // Indexes here correspond to the logical_ids index for the thread.
+  uint32_t apic_ids[ZBI_MAX_SMT];
+  uint32_t apic_id_count;
+} zbi_topology_x86_info_t;
 
 typedef struct {
-    uint16_t logical_ids[ZBI_MAX_SMT];
-    uint8_t logical_id_count;
+  uint16_t logical_ids[ZBI_MAX_SMT];
+  uint8_t logical_id_count;
 
-    uint16_t flags;
+  uint16_t flags;
 
-    // Should be one of zbi_topology_arm_info_t.
-    // If UNDEFINED then nothing will be set in arch_info.
-    uint8_t architecture;
-    union {
-        zbi_topology_arm_info_t arm;
-        zbi_topology_x86_info_t x86;
-    } architecture_info;
+  // Should be one of zbi_topology_arm_info_t.
+  // If UNDEFINED then nothing will be set in arch_info.
+  uint8_t architecture;
+  union {
+    zbi_topology_arm_info_t arm;
+    zbi_topology_x86_info_t x86;
+  } architecture_info;
 
 } zbi_topology_processor_t;
 
 typedef struct {
-    // Relative performance level of this processor in the system. The value is
-    // interpreted as the performance of this processor relative to the maximum
-    // performance processor in the system. No specific values are required for
-    // the performance level, only that the following relationship holds:
-    //
-    //   Pmax is the value of performance_class for the maximum performance
-    //   processor in the system, operating at its maximum operating point.
-    //
-    //   P is the value of performance_class for this processor, operating at
-    //   its maximum operating point.
-    //
-    //   R is the performance ratio of this processor to the maximum performance
-    //   processor in the system in the range (0.0, 1.0].
-    //
-    //   R = (P + 1) / (Pmax + 1)
-    //
-    // If accuracy is limited, choose a conservative value that slightly under-
-    // estimates the performance of lower-performance processors.
-    uint8_t performance_class;
+  // Relative performance level of this processor in the system. The value is
+  // interpreted as the performance of this processor relative to the maximum
+  // performance processor in the system. No specific values are required for
+  // the performance level, only that the following relationship holds:
+  //
+  //   Pmax is the value of performance_class for the maximum performance
+  //   processor in the system, operating at its maximum operating point.
+  //
+  //   P is the value of performance_class for this processor, operating at
+  //   its maximum operating point.
+  //
+  //   R is the performance ratio of this processor to the maximum performance
+  //   processor in the system in the range (0.0, 1.0].
+  //
+  //   R = (P + 1) / (Pmax + 1)
+  //
+  // If accuracy is limited, choose a conservative value that slightly under-
+  // estimates the performance of lower-performance processors.
+  uint8_t performance_class;
 } zbi_topology_cluster_t;
 
 typedef struct {
-    // Unique id of this cache node. No other semantics are assumed.
-    uint32_t cache_id;
+  // Unique id of this cache node. No other semantics are assumed.
+  uint32_t cache_id;
 } zbi_topology_cache_t;
 
 typedef struct {
@@ -481,178 +481,196 @@
 } zbi_topology_numa_region_t;
 
 typedef enum {
-    ZBI_TOPOLOGY_ENTITY_UNDEFINED = 0, // Unused default.
-    ZBI_TOPOLOGY_ENTITY_PROCESSOR = 1,
-    ZBI_TOPOLOGY_ENTITY_CLUSTER = 2,
-    ZBI_TOPOLOGY_ENTITY_CACHE = 3,
-    ZBI_TOPOLOGY_ENTITY_DIE = 4,
-    ZBI_TOPOLOGY_ENTITY_SOCKET = 5,
-    ZBI_TOPOLOGY_ENTITY_POWER_PLANE = 6,
-    ZBI_TOPOLOGY_ENTITY_NUMA_REGION = 7,
+  ZBI_TOPOLOGY_ENTITY_UNDEFINED = 0,  // Unused default.
+  ZBI_TOPOLOGY_ENTITY_PROCESSOR = 1,
+  ZBI_TOPOLOGY_ENTITY_CLUSTER = 2,
+  ZBI_TOPOLOGY_ENTITY_CACHE = 3,
+  ZBI_TOPOLOGY_ENTITY_DIE = 4,
+  ZBI_TOPOLOGY_ENTITY_SOCKET = 5,
+  ZBI_TOPOLOGY_ENTITY_POWER_PLANE = 6,
+  ZBI_TOPOLOGY_ENTITY_NUMA_REGION = 7,
 } zbi_topology_entity_type_t;
 
 typedef struct {
-    // Should be one of zbi_topology_entity_type_t.
-    uint8_t entity_type;
-    uint16_t parent_index;
-    union {
-        zbi_topology_processor_t processor;
-        zbi_topology_cluster_t cluster;
-        zbi_topology_numa_region_t numa_region;
-        zbi_topology_cache_t cache;
-    } entity;
+  // Should be one of zbi_topology_entity_type_t.
+  uint8_t entity_type;
+  uint16_t parent_index;
+  union {
+    zbi_topology_processor_t processor;
+    zbi_topology_cluster_t cluster;
+    zbi_topology_numa_region_t numa_region;
+    zbi_topology_cache_t cache;
+  } entity;
 } zbi_topology_node_t;
 
 #endif
 
-// Memory configuration, one or more zbi_mem_range_t entries.
-// zbi_header_t.length is sizeof(zbi_mem_range_t) times the number of entries.
-#define ZBI_TYPE_MEM_CONFIG             (0x434D454D) // MEMC
+// Device memory configuration, consisting of one or more `zbi_mem_range_t`
+// entries.
+//
+// The length of the item is `sizeof(zbi_mem_range_t)` times the number of
+// entries. Each entry describes a contiguous range of memory:
+//
+//   * ZBI_MEM_RANGE_RAM ranges are standard RAM.
+//
+//   * ZBI_MEM_RANGE_PERIPHERAL are ranges that cover one or more devices.
+//
+//   * ZBI_MEM_RANGE_RESERVED are reserved ranges that should not be used by
+//     the system. Reserved ranges may overlap previous or later
+//     ZBI_MEM_RANGE_RAM or ZBI_MEM_RANGE_PERIPHERAL regions, in which case the
+//     reserved range takes precedence.
+//
+//   * Any other `type` should be treated as `ZBI_MEM_RANGE_RESERVED` to allow
+//     forwards compatibility.
+//
+// Entries in the table may be in any order, and only a single item of type
+// ZBI_TYPE_MEM_CONFIG should be present in the ZBI.
+#define ZBI_TYPE_MEM_CONFIG (0x434D454D)  // MEMC
 #ifndef __ASSEMBLER__
 typedef struct {
-    uint64_t    paddr;
-    uint64_t    length;
-    uint32_t    type;
-    uint32_t    reserved;
+  uint64_t paddr;
+  uint64_t length;
+  uint32_t type;
+  uint32_t reserved;
 } zbi_mem_range_t;
 #endif
-#define ZBI_MEM_RANGE_RAM               (1)
-#define ZBI_MEM_RANGE_PERIPHERAL        (2)
-#define ZBI_MEM_RANGE_RESERVED          (3)
+#define ZBI_MEM_RANGE_RAM (1)
+#define ZBI_MEM_RANGE_PERIPHERAL (2)
+#define ZBI_MEM_RANGE_RESERVED (3)
 
 // Kernel driver configuration.  The zbi_header_t.extra field gives a
 // KDRV_* type that determines the payload format.
 // See [driver-config.h](<zircon/boot/driver-config.h>) for details.
-#define ZBI_TYPE_KERNEL_DRIVER          (0x5652444B) // KDRV
+#define ZBI_TYPE_KERNEL_DRIVER (0x5652444B)  // KDRV
 
 // ACPI Root Table Pointer, a uint64_t physical address.
-#define ZBI_TYPE_ACPI_RSDP              (0x50445352) // RSDP
+#define ZBI_TYPE_ACPI_RSDP (0x50445352)  // RSDP
 
 // SMBIOS entry point, a uint64_t physical address.
-#define ZBI_TYPE_SMBIOS                 (0x49424d53) // SMBI
+#define ZBI_TYPE_SMBIOS (0x49424d53)  // SMBI
 
 // EFI memory map, a uint64_t entry size followed by a sequence of
 // EFI memory descriptors aligned on that entry size.
-#define ZBI_TYPE_EFI_MEMORY_MAP         (0x4d494645) // EFIM
+#define ZBI_TYPE_EFI_MEMORY_MAP (0x4d494645)  // EFIM
 
 // EFI system table, a uint64_t physical address.
-#define ZBI_TYPE_EFI_SYSTEM_TABLE       (0x53494645) // EFIS
+#define ZBI_TYPE_EFI_SYSTEM_TABLE (0x53494645)  // EFIS
 
 // E820 memory table, an array of e820entry_t.
-#define ZBI_TYPE_E820_TABLE             (0x30323845) // E820
+#define ZBI_TYPE_E820_TABLE (0x30323845)  // E820
 
 /* EFI Variable for Crash Log */
-#define ZIRCON_VENDOR_GUID \
-    {0x82305eb2, 0xd39e, 0x4575, {0xa0, 0xc8, 0x6c, 0x20, 0x72, 0xd0, 0x84, 0x4c}}
+#define ZIRCON_VENDOR_GUID                                                         \
+  {                                                                                \
+    0x82305eb2, 0xd39e, 0x4575, { 0xa0, 0xc8, 0x6c, 0x20, 0x72, 0xd0, 0x84, 0x4c } \
+  }
 #define ZIRCON_CRASHLOG_EFIVAR \
-    { 'c', 'r', 'a', 's', 'h', 'l', 'o', 'g', 0 }
+  { 'c', 'r', 'a', 's', 'h', 'l', 'o', 'g', 0 }
 #define ZIRCON_CRASHLOG_EFIATTR \
-    (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS)
+  (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS)
 
 // Framebuffer parameters, a zbi_swfb_t entry.
-#define ZBI_TYPE_FRAMEBUFFER            (0x42465753) // SWFB
+#define ZBI_TYPE_FRAMEBUFFER (0x42465753)  // SWFB
 
 // The image arguments, data is a trivial text format of one "key=value" per line
 // with leading whitespace stripped and "#" comment lines and blank lines ignored.
 // It is processed by bootsvc and parsed args are shared to others via Arguments service.
 // TODO: the format can be streamlined after the /config/devmgr compat support is removed.
-#define ZBI_TYPE_IMAGE_ARGS          (0x47524149) // IARG
+#define ZBI_TYPE_IMAGE_ARGS (0x47524149)  // IARG
 
 // A copy of the boot version stored within the sysconfig
 // partition
-#define ZBI_TYPE_BOOT_VERSION       (0x53525642) // BVRS
+#define ZBI_TYPE_BOOT_VERSION (0x53525642)  // BVRS
 
 #ifndef __ASSEMBLER__
 typedef struct {
-    // Physical memory address.
-    uint64_t base;
+  // Physical memory address.
+  uint64_t base;
 
-    // Pixel layout and format.
-    // See [../pixelformat.h](<zircon/pixelformat.h>).
-    uint32_t width;
-    uint32_t height;
-    uint32_t stride;
-    uint32_t format;
+  // Pixel layout and format.
+  // See [../pixelformat.h](<zircon/pixelformat.h>).
+  uint32_t width;
+  uint32_t height;
+  uint32_t stride;
+  uint32_t format;
 } zbi_swfb_t;
 #endif
 
-
 // ZBI_TYPE_DRV_* types (LSB is 'm') contain driver metadata.
-#define ZBI_TYPE_DRV_METADATA(type)     (((type) & 0xFF) == 0x6D) // 'm'
+#define ZBI_TYPE_DRV_METADATA(type) (((type)&0xFF) == 0x6D)  // 'm'
 
 // MAC address for Ethernet, Wifi, Bluetooth, etc.  zbi_header_t.extra
 // is a board-specific index to specify which device the MAC address
 // applies to.  zbi_header_t.length gives the size in bytes, which
 // varies depending on the type of address appropriate for the device.
-#define ZBI_TYPE_DRV_MAC_ADDRESS        (0x43414D6D) // mMAC
+#define ZBI_TYPE_DRV_MAC_ADDRESS (0x43414D6D)  // mMAC
 
 // A partition map for a storage device, a zbi_partition_map_t header
 // followed by one or more zbi_partition_t entries.  zbi_header_t.extra
 // is a board-specific index to specify which device this applies to.
-#define ZBI_TYPE_DRV_PARTITION_MAP      (0x5452506D) // mPRT
-#define ZBI_PARTITION_NAME_LEN          (32)
-#define ZBI_PARTITION_GUID_LEN          (16)
+#define ZBI_TYPE_DRV_PARTITION_MAP (0x5452506D)  // mPRT
+#define ZBI_PARTITION_NAME_LEN (32)
+#define ZBI_PARTITION_GUID_LEN (16)
 
 // Private information for the board driver.
-#define ZBI_TYPE_DRV_BOARD_PRIVATE      (0x524F426D) // mBOR
+#define ZBI_TYPE_DRV_BOARD_PRIVATE (0x524F426D)  // mBOR
 
 #ifndef __ASSEMBLER__
 typedef struct {
-    // GUID specifying the format and use of data stored in the partition.
-    uint8_t type_guid[ZBI_PARTITION_GUID_LEN];
+  // GUID specifying the format and use of data stored in the partition.
+  uint8_t type_guid[ZBI_PARTITION_GUID_LEN];
 
-    // GUID unique to this partition.
-    uint8_t uniq_guid[ZBI_PARTITION_GUID_LEN];
+  // GUID unique to this partition.
+  uint8_t uniq_guid[ZBI_PARTITION_GUID_LEN];
 
-    // First and last block occupied by this partition.
-    uint64_t first_block;
-    uint64_t last_block;
+  // First and last block occupied by this partition.
+  uint64_t first_block;
+  uint64_t last_block;
 
-    // Reserved for future use.  Set to 0.
-    uint64_t flags;
+  // Reserved for future use.  Set to 0.
+  uint64_t flags;
 
-    char name[ZBI_PARTITION_NAME_LEN];
+  char name[ZBI_PARTITION_NAME_LEN];
 } zbi_partition_t;
 
 typedef struct {
-    // Total blocks used on the device.
-    uint64_t block_count;
-    // Size of each block in bytes.
-    uint64_t block_size;
+  // Total blocks used on the device.
+  uint64_t block_count;
+  // Size of each block in bytes.
+  uint64_t block_size;
 
-    // Number of partitions in the map.
-    uint32_t partition_count;
+  // Number of partitions in the map.
+  uint32_t partition_count;
 
-    // Reserved for future use.
-    uint32_t reserved;
+  // Reserved for future use.
+  uint32_t reserved;
 
-    // Device GUID.
-    uint8_t guid[ZBI_PARTITION_GUID_LEN];
+  // Device GUID.
+  uint8_t guid[ZBI_PARTITION_GUID_LEN];
 
-    // partition_count partition entries follow.
-    zbi_partition_t partitions[];
+  // partition_count partition entries follow.
+  zbi_partition_t partitions[];
 } zbi_partition_map_t;
 #endif
 
+#define ZBI_TYPE_HW_REBOOT_REASON (0x42525748)  // HWRB
 
-#define ZBI_TYPE_HW_REBOOT_REASON       (0x42525748) // HWRB
-
-#define ZBI_HW_REBOOT_UNDEFINED         ((uint32_t)0)
-#define ZBI_HW_REBOOT_COLD              ((uint32_t)1)
-#define ZBI_HW_REBOOT_WARM              ((uint32_t)2)
-#define ZBI_HW_REBOOT_BROWNOUT          ((uint32_t)3)
-#define ZBI_HW_REBOOT_WATCHDOG          ((uint32_t)4)
+#define ZBI_HW_REBOOT_UNDEFINED ((uint32_t)0)
+#define ZBI_HW_REBOOT_COLD ((uint32_t)1)
+#define ZBI_HW_REBOOT_WARM ((uint32_t)2)
+#define ZBI_HW_REBOOT_BROWNOUT ((uint32_t)3)
+#define ZBI_HW_REBOOT_WATCHDOG ((uint32_t)4)
 
 #ifndef __ASSEMBLER__
 #ifndef __cplusplus
 typedef uint32_t zbi_hw_reboot_reason_t;
 #else
 enum class ZbiHwRebootReason : uint32_t {
-    Undefined = ZBI_HW_REBOOT_UNDEFINED,
-    Cold = ZBI_HW_REBOOT_COLD,
-    Warm = ZBI_HW_REBOOT_WARM,
-    Brownout = ZBI_HW_REBOOT_BROWNOUT,
-    Watchdog = ZBI_HW_REBOOT_WATCHDOG,
+  Undefined = ZBI_HW_REBOOT_UNDEFINED,
+  Cold = ZBI_HW_REBOOT_COLD,
+  Warm = ZBI_HW_REBOOT_WARM,
+  Brownout = ZBI_HW_REBOOT_BROWNOUT,
+  Watchdog = ZBI_HW_REBOOT_WATCHDOG,
 };
 using zbi_hw_reboot_reason_t = ZbiHwRebootReason;
 #endif  // __cplusplus
@@ -660,7 +678,7 @@
 
 // The serial number, an unterminated ASCII string of printable non-whitespace
 // characters with length zbi_header_t.length.
-#define ZBI_TYPE_SERIAL_NUMBER          (0x4e4c5253) // SRLN
+#define ZBI_TYPE_SERIAL_NUMBER (0x4e4c5253)  // SRLN
 
 // This type specifies a binary file passed in by the bootloader.
 // The first byte specifies the length of the filename without a NUL terminator.
@@ -669,7 +687,7 @@
 //
 // Layout: | name_len |        name       |   payload
 //           ^(1 byte)  ^(name_len bytes)     ^(length of file)
-#define ZBI_TYPE_BOOTLOADER_FILE        (0x4C465442) // BTFL
+#define ZBI_TYPE_BOOTLOADER_FILE (0x4C465442)  // BTFL
 
 // The devicetree blob from the legacy boot loader, if any.  This is used only
 // for diagnostic and development purposes.  Zircon kernel and driver
@@ -677,6 +695,12 @@
 // loader.  The boot shims for legacy boot loaders pass the raw devicetree
 // along for development purposes, but extract information from it to populate
 // specific ZBI items such as ZBI_TYPE_KERNEL_DRIVER et al.
-#define ZBI_TYPE_DEVICETREE             (0xd00dfeed)
+#define ZBI_TYPE_DEVICETREE (0xd00dfeed)
+
+// An arbitrary number of random bytes attested to have high entropy.  Any
+// number of items of any size can be provided, but no data should be provided
+// that is not true entropy of cryptographic quality.  This is used to seed
+// secure cryptographic pseudo-random number generators.
+#define ZBI_TYPE_SECURE_ENTROPY (0x444e4152)  // RAND
 
 #endif  // SYSROOT_ZIRCON_BOOT_IMAGE_H_
diff --git a/lib/fuchsia/arch/arm64/sysroot/include/zircon/boot/netboot.h b/lib/fuchsia/arch/arm64/sysroot/include/zircon/boot/netboot.h
index 1586352..2446740 100644
--- a/lib/fuchsia/arch/arm64/sysroot/include/zircon/boot/netboot.h
+++ b/lib/fuchsia/arch/arm64/sysroot/include/zircon/boot/netboot.h
@@ -5,6 +5,7 @@
 #ifndef SYSROOT_ZIRCON_BOOT_NETBOOT_H_
 #define SYSROOT_ZIRCON_BOOT_NETBOOT_H_
 
+#include <limits.h>
 #include <stddef.h>
 #include <stdint.h>
 #include <zircon/types.h>
@@ -57,7 +58,6 @@
 
 #define NB_FILENAME_PREFIX "<<netboot>>"
 #define NB_KERNEL_FILENAME NB_FILENAME_PREFIX "kernel.bin"
-#define NB_RAMDISK_FILENAME NB_FILENAME_PREFIX "ramdisk.bin"
 #define NB_CMDLINE_FILENAME NB_FILENAME_PREFIX "cmdline"
 
 #define NB_IMAGE_PREFIX "<<image>>"
@@ -112,9 +112,11 @@
   uint8_t mac_address[8];
 } board_info_t;
 
+#define NB_PATH_MAX 4096
+
 typedef struct modify_partition_table_info {
   // Path of block device to initialize or wipe.
-  char block_device_path[ZX_MAX_NAME_LEN + 1];
+  char block_device_path[NB_PATH_MAX + 1];
 } modify_partition_table_info_t;
 
 typedef struct nbmsg_t {
@@ -131,7 +133,7 @@
     size_t offset; // write pointer
 } nbfile;
 
-int netboot_init(const char* nodename);
+int netboot_init(const char* nodename, uint32_t namegen);
 const char* netboot_nodename(void);
 int netboot_poll(void);
 void netboot_close(void);
diff --git a/lib/fuchsia/arch/arm64/sysroot/include/zircon/compiler.h b/lib/fuchsia/arch/arm64/sysroot/include/zircon/compiler.h
index eb7fb51..8429a68 100644
--- a/lib/fuchsia/arch/arm64/sysroot/include/zircon/compiler.h
+++ b/lib/fuchsia/arch/arm64/sysroot/include/zircon/compiler.h
@@ -2,84 +2,298 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+// This file provides macros for unifying differences in C/C++ compiler
+// extensions, and providing backwards-compatibility for older C++ standards.
+//
+// May be included by C, C++, and assembly files.
+
 #ifndef SYSROOT_ZIRCON_COMPILER_H_
 #define SYSROOT_ZIRCON_COMPILER_H_
 
-#ifndef __has_feature
-#define __has_feature(x) 0
-#endif
-
-#ifndef __has_cpp_attribute
-#define __has_cpp_attribute(x) 0
-#endif
-
-#ifndef __ASSEMBLER__
-
+// Ensure we are using a known compiler.
 #if !defined(__GNUC__) && !defined(__clang__)
 #error "Unrecognized compiler!"
 #endif
 
-#define likely(x) __builtin_expect(!!(x), 1)
-#define unlikely(x) __builtin_expect(!!(x), 0)
-#define __UNUSED __attribute__((__unused__))
-#define __ALWAYS_EMIT __attribute__((__used__))
-#define __PACKED __attribute__((packed))
-#define __ALIGNED(x) __attribute__((aligned(x)))
-#define __PRINTFLIKE(__fmt, __varargs) __attribute__((__format__(__printf__, __fmt, __varargs)))
-#define __SCANFLIKE(__fmt, __varargs) __attribute__((__format__(__scanf__, __fmt, __varargs)))
-#define __SECTION(x) __attribute__((__section__(x)))
-#define __PURE __attribute__((__pure__))
-#define __CONST __attribute__((__const__))
-#define __NO_RETURN __attribute__((__noreturn__))
-#define __MALLOC __attribute__((__malloc__))
-#define __WEAK __attribute__((__weak__))
-#define __GET_CALLER(x) __builtin_return_address(0)
-#define __GET_FRAME(x) __builtin_frame_address(0)
-#define __ISCONSTANT(x) __builtin_constant_p(x)
-#define __NO_INLINE __attribute__((__noinline__))
-#define __RESTRICT __restrict
+// Feature checking macros.
+//
+// If feature checking macros are not provided by the compiler, we assume that the
+// checked features are unavailable.
 
-#ifndef __clang__
-#define __LEAF_FN __attribute__((__leaf__))
-#define __OPTIMIZE(x) __attribute__((__optimize__(x)))
-#define __EXTERNALLY_VISIBLE __attribute__((__externally_visible__))
-#define __NO_SAFESTACK
-#define __THREAD_ANNOTATION(x)
-#else
-#define __LEAF_FN
-#define __OPTIMIZE(x)
-#define __EXTERNALLY_VISIBLE
-// The thread safety annotations are frequently used with C++ standard library
-// types in userspace, so only enable the annotations if we know that the C++
-// standard library types are annotated or if we're in kernel code.
-#if defined(_LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS) || defined(_KERNEL)
-#define __THREAD_ANNOTATION(x) __attribute__((x))
-#else
-#define __THREAD_ANNOTATION(x)
-#endif  // _LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS
-#define __NO_SAFESTACK __attribute__((__no_sanitize__("safe-stack", "shadow-call-stack")))
+// C++11 attribute checking.
+#ifndef __has_cpp_attribute
+#define __has_cpp_attribute(x) 0
 #endif
 
-#define __ALWAYS_INLINE __attribute__((__always_inline__))
-#define __NONNULL(x) __attribute__((__nonnull__ x))
-#define __WARN_UNUSED_RESULT __attribute__((__warn_unused_result__))
-#define __UNREACHABLE __builtin_unreachable()
-#define __WEAK_ALIAS(x) __attribute__((__weak__, __alias__(x)))
-#define __ALIAS(x) __attribute__((__alias__(x)))
-#define __EXPORT __attribute__((__visibility__("default")))
-#define __LOCAL __attribute__((__visibility__("hidden")))
-#define __THREAD __thread
-#define __offsetof(type, field) __builtin_offsetof(type, field)
+// clang feature checking.
+#ifndef __has_feature
+#define __has_feature(x) 0
+#endif
 
-// Only define __NO_UNIQUE_ADDRESS for C++, since it doesn't make sense in C.
+#if !defined(__ASSEMBLER__)
+
+// C++ header guards.
 #ifdef __cplusplus
+#define __BEGIN_CDECLS extern "C" {
+#define __END_CDECLS }
+#else
+#define __BEGIN_CDECLS
+#define __END_CDECLS
+#endif
+
+//
+// Function and data attributes.
+//
+
+// Function inlining directives.
+#define __NO_INLINE __attribute__((__noinline__))
+#define __ALWAYS_INLINE __attribute__((__always_inline__))
+
+// Avoid issuing a warning if the given variable/function is unused.
+#define __UNUSED __attribute__((__unused__))
+
+// Pack the given structure or class, omitting padding between fields.
+#define __PACKED __attribute__((packed))
+
+// Place the variable in thread-local storage.
+#define __THREAD __thread
+
+// Align the variable or type to at least `x` bytes. `x` must be a power of two.
+#define __ALIGNED(x) __attribute__((aligned(x)))
+
+// Declare the given function will never return. (such as `exit`, `abort`, etc).
+#define __NO_RETURN __attribute__((__noreturn__))
+
+// Warn if the result of this function is ignored by the caller.
+#define __WARN_UNUSED_RESULT __attribute__((__warn_unused_result__))
+
+// Declare that the given stack variable may be left uninitialized if it does
+// not have a specified initial value.
+#if defined(__clang__)
+#define __UNINITIALIZED __attribute__((uninitialized))
+#else
+#define __UNINITIALIZED
+#endif
+
+// Warn if a constructed objected is not used by the caller.
+//
+// Generates a warning on code like this:
+//
+//   {
+//     AutoLock(&mutex);  // error: the AutoLock goes out of scope immediately.
+//     locked_variable = 42;
+//   }
+//
+// C++17 defines [[nodiscard]] to do this, but some older but supported
+// versions of GCC support [[nodiscard]] on functions but not constructors.
+// Having a separate __WARN_UNUSED_CONSTRUCTOR allows us to hide the attribute
+// only on constructors on old versions of GCC.
+#if defined(__cplusplus)
+#if __cplusplus >= 201703L && (defined(__clang__) || (defined(__GNUC__) && (__GNUC__ >= 10)))
+#define __WARN_UNUSED_CONSTRUCTOR [[nodiscard]]
+#else
+#define __WARN_UNUSED_CONSTRUCTOR
+#endif
+#endif
+
+// Mark a function or variable as deprecated, warning about any callers.
+#if !defined(__DEPRECATE)
+#define __DEPRECATE __attribute__((__deprecated__))
+#endif
+
+// Mark a function as having no visible side-effects: It may read memory, but
+// will not modify it.
+//
+// Multiple calls to the function may be optimized away by the compiler.
+#define __PURE __attribute__((__pure__))
+
+// Mark a function has having an output determined solely on its input
+// parameters (but not memory).
+//
+// Multiple calls to the function may be optimized away by the compiler, even
+// if memory is modified between calls.
+#define __CONST __attribute__((__const__))
+
+// The given function is malloc-like, returning a pointer to new, unused
+// memory.
+//
+// The compiler can assume that the returned pointer does not alias any other
+// pointer, which may help the compiler optimize the program.
+#define __MALLOC __attribute__((__malloc__))
+
+// Indicate that the given function takes a printf/scanf-style format string.
+//
+// "__fmt" is the argument number of the format string, indexed from 1.
+// "__varargs" is the argument number of the variable args "..." argument
+// counting from 1.
+//
+// If applied to a class method, the implicit "this" parameter counts as the
+// first argument.
+#define __PRINTFLIKE(__fmt, __varargs) __attribute__((__format__(__printf__, __fmt, __varargs)))
+#define __SCANFLIKE(__fmt, __varargs) __attribute__((__format__(__scanf__, __fmt, __varargs)))
+
+// Indicate that the `n`th argument to a function is non-null.
+//
+// The compiler will emit warnings if it can prove an argument is null, and
+// may optimise assuming that the values are non-null.
+#define __NONNULL(n) __attribute__((__nonnull__ n))
+
+// The given function is a "leaf", and won't call further functions.
+//
+// Leaf functions must only return directly, and not call back into the
+// current compilation unit (either via direct calls, or function pointers).
+//
+// May help the compiler optimize calls to the function in some cases.
+#define __LEAF_FN __attribute__((__leaf__))
+
+// Mark the given function or variable as `constexpr`.
+//
+// Used in code included by both C and C++. Code that is pure C++ should use
+// `constexpr` directly.
+#ifdef __cplusplus
+#define __CONSTEXPR constexpr
+#else
+#define __CONSTEXPR
+#endif
+
+// Optimize the given function using custom flags.
+//
+// For example,
+//
+//  __OPTIMIZE("O3") int myfunction() { ... }
+//
+// will cause GCC to optimize the function at the O3 level, independent
+// of what the compiler optimization flags are.
+#if !defined(__clang__)
+#define __OPTIMIZE(x) __attribute__((__optimize__(x)))
+#else
+#define __OPTIMIZE(x)
+#endif
+
+// Indicate the given function should not use LLVM's stack hardening features,
+// but instead put all local variables on the standard stack.
+//
+// c.f. https://clang.llvm.org/docs/SafeStack.html
+#if defined(__clang__)
+#define __NO_SAFESTACK __attribute__((__no_sanitize__("safe-stack", "shadow-call-stack")))
+#else
+#define __NO_SAFESTACK
+#endif
+
+// Indicate the given function or global variable shouldn't be instrumented
+// for ASAN.
+#if defined(__clang__)
+#define __NO_ASAN [[clang::no_sanitize("address")]]
+#else
+#define __NO_ASAN __attribute__((no_sanitize_address))
+#endif
+
+// The given C++ class or struct need not have a unique address when part of
+// a larger struct or class, but can be safely collapsed into a zero-byte
+// object by the compiler.
 #if __has_cpp_attribute(no_unique_address)
 #define __NO_UNIQUE_ADDRESS [[no_unique_address]]
 #else
 #define __NO_UNIQUE_ADDRESS
 #endif
-#endif  // ifdef __cplusplus
 
+// Indicate that the given function should be treated by the Clang static
+// analyzer as if it doesn't return.
+//
+// A workaround to help static analyzer identify assertion failures
+#if defined(__clang__)
+#define __ANALYZER_CREATE_SINK __attribute__((analyzer_noreturn))
+#else
+#define __ANALYZER_CREATE_SINK
+#endif
+
+// Mark the given function as externally visible, and shouldn't be optimized
+// away by link-time optimizations or whole-program optimizations.
+#if !defined(__clang__)
+#define __EXTERNALLY_VISIBLE __attribute__((__externally_visible__))
+#else
+#define __EXTERNALLY_VISIBLE
+#endif
+
+// Declare that this function declaration should be emitted as an alias for
+// another function.
+#define __ALIAS(x) __attribute__((__alias__(x)))
+
+// Place the given global into a particular linker section.
+#define __SECTION(x) __attribute__((__section__(x)))
+
+// The given function or global should be given a weak symbol, or a weak
+// alias to another symbol.
+#define __WEAK __attribute__((__weak__))
+#define __WEAK_ALIAS(x) __attribute__((__weak__, __alias__(x)))
+
+// The given static variable should still be emitted by the compiler, even if it
+// appears unused to the compiler.
+//
+// Rarely needed. Not to be confused with "__UNUSED", which avoids the
+// compiler warning if a variable appears unused.
+#define __ALWAYS_EMIT __attribute__((__used__))
+
+// Declare this object's ELF symbol visibility.
+#define __EXPORT __attribute__((__visibility__("default")))
+#define __LOCAL __attribute__((__visibility__("hidden")))
+
+//
+// Builtin functions.
+//
+
+// Provide a hint to the compiler that the given expression is likely/unlikely
+// to be true.
+//
+//   if (unlikely(status != ZX_OK)) {
+//     error(...);
+//   }
+//
+#define likely(x) __builtin_expect(!!(x), 1)
+#define unlikely(x) __builtin_expect(!!(x), 0)
+
+// Return the program counter of the calling function.
+#define __GET_CALLER(x) __builtin_return_address(0)
+
+// Return the address of the current stack frame.
+#define __GET_FRAME(x) __builtin_frame_address(0)
+
+// Return true if the given expression is a known compile-time constant.
+#define __ISCONSTANT(x) __builtin_constant_p(x)
+
+// Assume this branch of code cannot be reached.
+#define __UNREACHABLE __builtin_unreachable()
+
+// Get the offset of `field` from the beginning of the struct or class `type`.
+#define __offsetof(type, field) __builtin_offsetof(type, field)
+
+// Return the number of elements in the given C-style array.
+//
+// TODO: add type check
+#if !defined(countof)
+#define countof(a) (sizeof(a) / sizeof((a)[0]))
+#endif
+
+// Perform an arithmetic operation, returning "true" if the operation overflowed.
+//
+// Equivalent to: { *result = a + b; return _overflow_occurred; }
+#define add_overflow(a, b, result) __builtin_add_overflow(a, b, result)
+#define sub_overflow(a, b, result) __builtin_sub_overflow(a, b, result)
+#define mul_overflow(a, b, result) __builtin_mul_overflow(a, b, result)
+
+// Indicate the given case of a switch statement is intended to fall through
+// to the next case, and avoid generating a compiler warning.
+//
+//   switch (n) {
+//     case 0:
+//     case 1:
+//       handle_zero_and_one_case();
+//       __FALLTHROUGH;
+//     default:
+//       handle_all_cases();
+//       break;
+//   }
+//
 #if defined(__cplusplus) && __cplusplus >= 201703L
 #define __FALLTHROUGH [[fallthrough]]
 #elif defined(__cplusplus) && defined(__clang__)
@@ -94,27 +308,20 @@
   } while (0)
 #endif
 
-// C++17 onwards supports [[nodiscard]] on a constructor, warning if
-// a temporary object is created without a name. Such objects would be
-// immediately destroyed again, while the user's expectation might be
-// that it would last the scope.
+// Locking annotations.
 //
-// We could ideally just use [[nodiscard]] (or __WARN_UNUSED_RESULT)
-// directly, except GCC < 10.0 has a bug preventing it from being used
-// on constructors. __WARN_UNUSED_CONSTRUCTOR allows us to tag
-// constructors in supported compilers, and is simply ignored in older
-// compilers.
-#if defined(__cplusplus)
-// Clang and GCC versions >= 10.0 support [[nodiscard]] on constructors.
-#if __cplusplus >= 201703L && (defined(__clang__) || (defined(__GNUC__) && (__GNUC__ >= 10)))
-#define __WARN_UNUSED_CONSTRUCTOR [[nodiscard]]
+// The following annotations allow compile-time checking that annotated data
+// is only accessed while holding the correct locks.
+//
+// The annotations are only supported by Clang, and frequently used with C++
+// standard library types in userspace, so only enable in Clang when we know
+// that the C++ standard library types are annotated or if we're in kernel
+// code.
+#if defined(__clang__) && (defined(_LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS) || defined(_KERNEL))
+#define __THREAD_ANNOTATION(x) __attribute__((x))
 #else
-#define __WARN_UNUSED_CONSTRUCTOR
+#define __THREAD_ANNOTATION(x)
 #endif
-#endif
-
-// Publicly exposed thread annotation macros. These have a long and ugly name to
-// minimize the chance of collision with consumers of Zircon's public headers.
 #define __TA_CAPABILITY(x) __THREAD_ANNOTATION(__capability__(x))
 #define __TA_GUARDED(x) __THREAD_ANNOTATION(__guarded_by__(x))
 #define __TA_ACQUIRE(...) __THREAD_ANNOTATION(__acquire_capability__(__VA_ARGS__))
@@ -133,45 +340,7 @@
 #define __TA_SCOPED_CAPABILITY __THREAD_ANNOTATION(__scoped_lockable__)
 #define __TA_NO_THREAD_SAFETY_ANALYSIS __THREAD_ANNOTATION(__no_thread_safety_analysis__)
 
-#endif  // ifndef __ASSEMBLER__
-
-#if !defined(__DEPRECATE)
-#define __DEPRECATE __attribute__((__deprecated__))
-#endif
-
-/* TODO: add type check */
-#if !defined(countof)
-#define countof(a) (sizeof(a) / sizeof((a)[0]))
-#endif
-
-/* CPP header guards */
-#ifdef __cplusplus
-#define __BEGIN_CDECLS extern "C" {
-#define __END_CDECLS }
-#else
-#define __BEGIN_CDECLS
-#define __END_CDECLS
-#endif
-
-// constexpr annotation for use in static inlines usable in both C and C++
-#ifdef __cplusplus
-#define __CONSTEXPR constexpr
-#else
-#define __CONSTEXPR
-#endif
-
-#define add_overflow(a, b, c) __builtin_add_overflow(a, b, c)
-#define sub_overflow(a, b, c) __builtin_sub_overflow(a, b, c)
-#define mul_overflow(a, b, c) __builtin_mul_overflow(a, b, c)
-
-// A workaround to help static analyzer identify assertion failures
-#if defined(__clang__)
-#define __ANALYZER_CREATE_SINK __attribute__((analyzer_noreturn))
-#else
-#define __ANALYZER_CREATE_SINK  // no-op
-#endif
-
-// Lifetime analysis
+// Experimental lifetime analysis annotations.
 #ifndef __OWNER
 #ifdef __clang__
 #define __OWNER(x) [[gsl::Owner(x)]]
@@ -182,4 +351,6 @@
 #endif
 #endif
 
+#endif // !defined(__ASSEMBLER__)
+
 #endif  // SYSROOT_ZIRCON_COMPILER_H_
diff --git a/lib/fuchsia/arch/arm64/sysroot/include/zircon/device/audio.h b/lib/fuchsia/arch/arm64/sysroot/include/zircon/device/audio.h
index 01b966e..935043c 100644
--- a/lib/fuchsia/arch/arm64/sysroot/include/zircon/device/audio.h
+++ b/lib/fuchsia/arch/arm64/sysroot/include/zircon/device/audio.h
@@ -102,7 +102,7 @@
 //
 typedef uint32_t audio_set_gain_flags_t;
 #define AUDIO_SGF_MUTE_VALID \
-  ((audio_set_gain_flags_t)0x1)  // Whether or not the mute flag is valid.
+  ((audio_set_gain_flags_t)0x1)                            // Whether or not the mute flag is valid.
 #define AUDIO_SGF_AGC_VALID ((audio_set_gain_flags_t)0x2)  // Whether or not the agc flag is valid.
 #define AUDIO_SGF_GAIN_VALID \
   ((audio_set_gain_flags_t)0x4)  // Whether or not the gain float is valid.
@@ -437,7 +437,7 @@
 typedef struct audio_rb_cmd_start_resp {
   audio_cmd_hdr_t hdr;
   zx_status_t result;
-  uint64_t start_time;
+  uint64_t start_time;  // external_delay impact should not be incorporated into this value.
 } audio_rb_cmd_start_resp_t;
 
 // AUDIO_RB_CMD_STOP
@@ -455,6 +455,7 @@
   audio_cmd_hdr_t hdr;
 
   // The time, per system monotonic clock, of the below byte position.
+  // external_delay impact should not be incorporated into this value.
   zx_time_t monotonic_time;
 
   // The current position (in bytes) of the driver/hardware's read (output) or
diff --git a/lib/fuchsia/arch/arm64/sysroot/include/zircon/errors.h b/lib/fuchsia/arch/arm64/sysroot/include/zircon/errors.h
index 390acfb..511ee7a 100644
--- a/lib/fuchsia/arch/arm64/sysroot/include/zircon/errors.h
+++ b/lib/fuchsia/arch/arm64/sysroot/include/zircon/errors.h
@@ -5,13 +5,7 @@
 #ifndef SYSROOT_ZIRCON_ERRORS_H_
 #define SYSROOT_ZIRCON_ERRORS_H_
 
-// Zircon statuses are signed 32 bit integers. The space of values is
-// divided as follows:
-// - The zero value is for the OK status.
-// - Negative values are defined by the system, in this file.
-// - Positive values are reserved for protocol-specific error values,
-//   and will never be defined by the system.
-
+// ZX_OK: Indicates an operation was successful.
 #define ZX_OK (0)
 
 // ======= Internal failures =======
diff --git a/lib/fuchsia/arch/arm64/sysroot/include/zircon/fidl.h b/lib/fuchsia/arch/arm64/sysroot/include/zircon/fidl.h
index 3a25b89..6aeea98 100644
--- a/lib/fuchsia/arch/arm64/sysroot/include/zircon/fidl.h
+++ b/lib/fuchsia/arch/arm64/sysroot/include/zircon/fidl.h
@@ -237,6 +237,72 @@
   };
 } fidl_envelope_t;
 
+typedef struct {
+  union {
+    // The size of the entire envelope contents, including any additional
+    // out-of-line objects that the envelope may contain. For example, a
+    // vector<string>'s num_bytes for ["hello", "world"] would include the
+    // string contents in the size, not just the outer vector. Always a multiple
+    // of 8; must be zero if envelope is null.
+    //
+    // This field is only valid when |num_bytes| > 4. Smaller values are
+    // instead inlined and |inline_value| is set instead.
+    uint32_t num_bytes;
+
+    // In the case in which the size of the value <= 4, |inline_value| will
+    // be assigned the value of the envelope and bit 0 of |flags| will be
+    // set to indicate that inlining is being used.
+    uint8_t inline_value[4];
+  };
+
+  // The number of handles in the envelope, including any additional
+  // out-of-line objects that the envelope contains. Must be zero if envelope is null.
+  uint16_t num_handles;
+
+  // Flags describing the state of the envelope.
+  // A value of 1 indicates that the value of the envelope is inlined.
+  uint16_t flags;
+} fidl_envelope_v2_t;
+
+static_assert(sizeof(fidl_envelope_t) == 16, "");
+static_assert(sizeof(fidl_envelope_v2_t) == 8, "");
+
+// Bit 0 in flags indicates if the object is inlined in the envelope.
+#define FIDL_ENVELOPE_FLAGS_INLINING_MASK 0x01
+
+// Objects <= 4 bytes in size are inlined in envelopes.
+#define FIDL_ENVELOPE_INLINING_SIZE_THRESHOLD 4
+
+// |fidl_envelope_v2_unknown_data_t| is the decoded, representation of an unknown envelope for
+// the v2 wire format for C-family bindings.
+// In addition to what is in |fidl_envelope_v2_t|, |fidl_envelope_v2_unknown_data_t| also provides
+// an |offset| field which makes it possible to locate the inner object using data stored only
+// within the confines of the 8-byte |fidl_envelope_v2_unknown_data_t|.
+typedef struct {
+  union {
+    // When flags == 1, inline_value contains the inlined envelope value.
+    uint8_t inline_value[4];
+    // Out of line case.
+    struct {
+      // The number of bytes in the envelope, including any additional
+      // out-of-line objects that the envelope contains. Must be zero if envelope is null.
+      uint16_t num_bytes;
+      // Offset of the out of line contents, relative to the start of the message bytes.
+      uint16_t offset;
+    } out_of_line;
+  };
+
+  // The number of handles in the envelope, including any additional
+  // out-of-line objects that the envelope contains. Must be zero if envelope is null.
+  uint16_t num_handles;
+
+  // Flags describing the state of the envelope.
+  // A value of 1 indicates that the value of the envelope is inlined.
+  uint16_t flags;
+} fidl_envelope_v2_unknown_data_t;
+
+static_assert(sizeof(fidl_envelope_v2_unknown_data_t) == 8, "");
+
 // Handle types.
 
 // Handle types are encoded directly. Just like primitive types, there
@@ -354,14 +420,29 @@
   fidl_envelope_t envelope;
 } fidl_xunion_t;
 
+typedef struct {
+  fidl_xunion_tag_t tag;
+  fidl_envelope_v2_t envelope;
+} fidl_xunion_v2_t;
+
+static_assert(sizeof(fidl_xunion_t) == 24, "");
+static_assert(sizeof(fidl_xunion_v2_t) == 16, "");
+
 // Messages.
 
+typedef uint32_t FidlWireFormatVersion;
+
+#define FIDL_WIRE_FORMAT_VERSION_V1 ((uint32_t)1)
+#define FIDL_WIRE_FORMAT_VERSION_V2 ((uint32_t)2)
+
 // All fidl messages share a common 16 byte header.
 
 enum {
   kFidlWireFormatMagicNumberInitial = 1,
 };
 
+#define FIDL_MESSAGE_HEADER_FLAGS_0_USE_VERSION_V2 0x02
+
 typedef struct fidl_message_header {
   zx_txid_t txid;
   uint8_t flags[3];
@@ -376,8 +457,10 @@
 
 #define FIDL_TXID_NO_RESPONSE 0ul
 
-// An outgoing FIDL message.
-typedef struct fidl_outgoing_msg {
+// An outgoing FIDL message represented with contiguous bytes.
+//
+// See fidl_outgoing_msg_iovec_t for a represention using iovec.
+typedef struct fidl_outgoing_msg_byte {
   // The bytes of the message.
   //
   // The bytes of the message might be in the encoded or decoded form.
@@ -397,6 +480,44 @@
 
   // The number of handles in |handles|.
   uint32_t num_handles;
+} fidl_outgoing_msg_byte_t;
+
+// An outgoing FIDL message represented with iovec.
+//
+// See fidl_outgoing_msg_byte_t for a represention using bytes.
+typedef struct fidl_outgoing_msg_iovec {
+  // The output iovecs of the message.
+  //
+  // See |num_iovecs| for the number of iovecs in the message.
+  zx_channel_iovec_t* iovecs;
+
+  // The total number of iovecs in |iovecs|.
+  uint32_t num_iovecs;
+
+  // The output handles of the message.
+  //
+  // See |num_handles| for the number of handles in the message.
+  zx_handle_disposition_t* handles;
+
+  // The number of handles in |handles|.
+  uint32_t num_handles;
+} fidl_outgoing_msg_iovec_t;
+
+typedef uint8_t fidl_outgoing_msg_type;
+
+#define FIDL_OUTGOING_MSG_TYPE_BYTE ((fidl_outgoing_msg_type)1)
+#define FIDL_OUTGOING_MSG_TYPE_IOVEC ((fidl_outgoing_msg_type)2)
+
+// An outgoing FIDL message, in either byte or iovec form.
+typedef struct fidl_outgoing_msg {
+  // Type of the outgoing message.
+  fidl_outgoing_msg_type type;
+
+  // Selection of the outgoing message body.
+  union {
+    fidl_outgoing_msg_byte_t byte;
+    fidl_outgoing_msg_iovec_t iovec;
+  };
 } fidl_outgoing_msg_t;
 
 // An incoming FIDL message.
diff --git a/lib/fuchsia/arch/arm64/sysroot/include/zircon/hw/pci.h b/lib/fuchsia/arch/arm64/sysroot/include/zircon/hw/pci.h
index 7de1bca..9333364 100644
--- a/lib/fuchsia/arch/arm64/sysroot/include/zircon/hw/pci.h
+++ b/lib/fuchsia/arch/arm64/sysroot/include/zircon/hw/pci.h
@@ -11,14 +11,14 @@
 __BEGIN_CDECLS
 
 // Structure for passing around PCI address information
-typedef struct pci_bdf {
+typedef struct zx_pci_bdf {
   uint8_t bus_id;
   uint8_t device_id;
   uint8_t function_id;
-} pci_bdf_t;
+} zx_pci_bdf_t;
 
 // TODO(cja): This header is used for the transition of these defines from
-// kernel to userspace, but due to pci_bdf_t some of the kernel includes it.
+// kernel to userspace, but due to zx_pci_bdf_t some of the kernel includes it.
 // Make sure defines here don't clash with those in pci_common.h by having this
 // guard, but remove it after the transition.
 #ifndef WITH_KERNEL_PCIE
diff --git a/lib/fuchsia/arch/arm64/sysroot/include/zircon/hw/usb.h b/lib/fuchsia/arch/arm64/sysroot/include/zircon/hw/usb.h
index c62e948..f742acf 100644
--- a/lib/fuchsia/arch/arm64/sysroot/include/zircon/hw/usb.h
+++ b/lib/fuchsia/arch/arm64/sysroot/include/zircon/hw/usb.h
@@ -105,7 +105,7 @@
 #define USB_DEVICE_REMOTE_WAKEUP           0x01
 #define USB_DEVICE_TEST_MODE               0x02
 
-/* Configuration attributes (bmAttributes) */
+/* Configuration attributes (bm_attributes) */
 #define USB_CONFIGURATION_REMOTE_WAKEUP    0x20
 #define USB_CONFIGURATION_SELF_POWERED     0x40
 #define USB_CONFIGURATION_RESERVED_7       0x80 // This bit must be set
@@ -116,21 +116,21 @@
 #define USB_ENDPOINT_DIR_MASK              0x80
 #define USB_ENDPOINT_NUM_MASK              0x1F
 
-/* Endpoint types (bmAttributes) */
+/* Endpoint types (bm_attributes) */
 #define USB_ENDPOINT_CONTROL               0x00
 #define USB_ENDPOINT_ISOCHRONOUS           0x01
 #define USB_ENDPOINT_BULK                  0x02
 #define USB_ENDPOINT_INTERRUPT             0x03
 #define USB_ENDPOINT_TYPE_MASK             0x03
 
-/* Endpoint synchronization type (bmAttributes) */
+/* Endpoint synchronization type (bm_attributes) */
 #define USB_ENDPOINT_NO_SYNCHRONIZATION    0x00
 #define USB_ENDPOINT_ASYNCHRONOUS          0x04
 #define USB_ENDPOINT_ADAPTIVE              0x08
 #define USB_ENDPOINT_SYNCHRONOUS           0x0C
 #define USB_ENDPOINT_SYNCHRONIZATION_MASK  0x0C
 
-/* Endpoint usage type (bmAttributes) */
+/* Endpoint usage type (bm_attributes) */
 #define USB_ENDPOINT_DATA                  0x00
 #define USB_ENDPOINT_FEEDBACK              0x10
 #define USB_ENDPOINT_IMPLICIT_FEEDBACK     0x20
@@ -138,149 +138,130 @@
 
 #define USB_ENDPOINT_HALT                  0x00
 
-// Values in this set match those used in XHCI and other parts of the USB specification
-#define USB_SPEED_UNDEFINED 0
-#define USB_SPEED_FULL 1
-#define USB_SPEED_LOW 2
-#define USB_SPEED_HIGH 3
-#define USB_SPEED_SUPER 4
-typedef uint32_t usb_speed_t;
-
 /* general USB defines */
 typedef struct {
-    uint8_t bmRequestType;
-    uint8_t bRequest;
-    uint16_t wValue;
-    uint16_t wIndex;
-    uint16_t wLength;
-} __attribute__ ((packed)) usb_setup_t;
+    uint8_t bm_request_type;
+    uint8_t b_request;
+    uint16_t w_value;
+    uint16_t w_index;
+    uint16_t w_length;
+} __attribute__ ((packed)) usb_setup_info_t;
 
 typedef struct {
-    uint8_t bLength;
-    uint8_t bDescriptorType;
+    uint8_t b_length;
+    uint8_t b_descriptor_type;
 } __attribute__ ((packed)) usb_descriptor_header_t;
 
 typedef struct {
-    uint8_t bLength;
-    uint8_t bDescriptorType;    // USB_DT_DEVICE
-    uint16_t bcdUSB;
-    uint8_t bDeviceClass;
-    uint8_t bDeviceSubClass;
-    uint8_t bDeviceProtocol;
-    uint8_t bMaxPacketSize0;
-    uint16_t idVendor;
-    uint16_t idProduct;
-    uint16_t bcdDevice;
-    uint8_t iManufacturer;
-    uint8_t iProduct;
-    uint8_t iSerialNumber;
-    uint8_t bNumConfigurations;
-} __attribute__ ((packed)) usb_device_descriptor_t;
+    uint8_t b_length;
+    uint8_t b_descriptor_type;    // USB_DT_DEVICE
+    uint16_t bcd_usb;
+    uint8_t b_device_class;
+    uint8_t b_device_sub_class;
+    uint8_t b_device_protocol;
+    uint8_t b_max_packet_size0;
+    uint16_t id_vendor;
+    uint16_t id_product;
+    uint16_t bcd_device;
+    uint8_t i_manufacturer;
+    uint8_t i_product;
+    uint8_t i_serial_number;
+    uint8_t b_num_configurations;
+} __attribute__ ((packed)) usb_device_descriptor_info_t;
 
 typedef struct {
-    uint8_t bLength;
-    uint8_t bDescriptorType;    // USB_DT_CONFIG
-    uint16_t wTotalLength;
-    uint8_t bNumInterfaces;
-    uint8_t bConfigurationValue;
-    uint8_t iConfiguration;
-    uint8_t bmAttributes;
-    uint8_t bMaxPower;
+    uint8_t b_length;
+    uint8_t b_descriptor_type;    // USB_DT_CONFIG
+    uint16_t w_total_length;
+    uint8_t b_num_interfaces;
+    uint8_t b_configuration_value;
+    uint8_t i_configuration;
+    uint8_t bm_attributes;
+    uint8_t b_max_power;
 } __attribute__ ((packed)) usb_configuration_descriptor_t;
 
 typedef struct {
-    uint8_t bLength;
-    uint8_t bDescriptorType;    // USB_DT_STRING
-    uint8_t bString[];
+    uint8_t b_length;
+    uint8_t b_descriptor_type;    // USB_DT_STRING
+    uint8_t b_string[];
 } __attribute__ ((packed)) usb_string_descriptor_t;
 
 typedef struct {
-    uint8_t bLength;
-    uint8_t bDescriptorType;    // USB_DT_INTERFACE
-    uint8_t bInterfaceNumber;
-    uint8_t bAlternateSetting;
-    uint8_t bNumEndpoints;
-    uint8_t bInterfaceClass;
-    uint8_t bInterfaceSubClass;
-    uint8_t bInterfaceProtocol;
-    uint8_t iInterface;
-} __attribute__ ((packed)) usb_interface_descriptor_t;
+    uint8_t b_length;
+    uint8_t b_descriptor_type;    // USB_DT_INTERFACE
+    uint8_t b_interface_number;
+    uint8_t b_alternate_setting;
+    uint8_t b_num_endpoints;
+    uint8_t b_interface_class;
+    uint8_t b_interface_sub_class;
+    uint8_t b_interface_protocol;
+    uint8_t i_interface;
+} __attribute__ ((packed)) usb_interface_info_descriptor_t;
 
 typedef struct {
-    uint8_t bLength;
-    uint8_t bDescriptorType;    // USB_DT_ENDPOINT
-    uint8_t bEndpointAddress;
-    uint8_t bmAttributes;
-    uint16_t wMaxPacketSize;
-    uint8_t bInterval;
-} __attribute__ ((packed)) usb_endpoint_descriptor_t;
-#define usb_ep_num(ep)          ((ep)->bEndpointAddress & USB_ENDPOINT_NUM_MASK)
-// usb_ep_num2() useful with you have bEndpointAddress outside of a descriptor.
-#define usb_ep_num2(addr)       ((addr) & USB_ENDPOINT_NUM_MASK)
-#define usb_ep_direction(ep)    ((ep)->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
-#define usb_ep_type(ep)         ((ep)->bmAttributes & USB_ENDPOINT_TYPE_MASK)
-#define usb_ep_sync_type(ep)    ((ep)->bmAttributes & USB_ENDPOINT_SYNCHRONIZATION_MASK)
-// max packet size is in bits 10..0
-#define usb_ep_max_packet(ep)   (le16toh((ep)->wMaxPacketSize) & 0x07FF)
-// for high speed interrupt and isochronous endpoints, additional transactions per microframe
-// are in bits 12..11
-#define usb_ep_add_mf_transactions(ep) ((le16toh((ep)->wMaxPacketSize) >> 11) & 3)
+    uint8_t b_length;
+    uint8_t b_descriptor_type;    // USB_DT_ENDPOINT
+    uint8_t b_endpoint_address;
+    uint8_t bm_attributes;
+    uint16_t w_max_packet_size;
+    uint8_t b_interval;
+} __attribute__ ((packed)) usb_endpoint_info_descriptor_t;
 
 typedef struct {
-    uint8_t bLength;
-    uint8_t bDescriptorType;    // USB_DT_DEVICE_QUALIFIER
-    uint16_t bcdUSB;
-    uint8_t bDeviceClass;
-    uint8_t bDeviceSubClass;
-    uint8_t bDeviceProtocol;
-    uint8_t bMaxPacketSize0;
-    uint8_t bNumConfigurations;
-    uint8_t bReserved;
+    uint8_t b_length;
+    uint8_t b_descriptor_type;    // USB_DT_DEVICE_QUALIFIER
+    uint16_t bcd_usb;
+    uint8_t b_device_class;
+    uint8_t b_device_sub_class;
+    uint8_t b_device_protocol;
+    uint8_t b_max_packet_size0;
+    uint8_t b_num_configurations;
+    uint8_t b_reserved;
 } __attribute__ ((packed)) usb_device_qualifier_descriptor_t;
 
 typedef struct {
-    uint8_t bLength;
-    uint8_t bDescriptorType;    // USB_DT_SS_EP_COMPANION
-    uint8_t bMaxBurst;
-    uint8_t bmAttributes;
-    uint16_t wBytesPerInterval;
-} __attribute__ ((packed)) usb_ss_ep_comp_descriptor_t;
-#define usb_ss_ep_comp_isoc_mult(ep) ((ep)->bmAttributes & 0x3)
-#define usb_ss_ep_comp_isoc_comp(ep) (!!((ep)->bmAttributes & 0x80))
+    uint8_t b_length;
+    uint8_t b_descriptor_type;    // USB_DT_SS_EP_COMPANION
+    uint8_t b_max_burst;
+    uint8_t bm_attributes;
+    uint16_t w_bytes_per_interval;
+} __attribute__ ((packed)) usb_ss_ep_comp_descriptor_info_t;
+#define usb_ss_ep_comp_isoc_mult(ep) ((ep)->bm_attributes & 0x3)
+#define usb_ss_ep_comp_isoc_comp(ep) (!!((ep)->bm_attributes & 0x80))
 
 typedef struct {
-    uint8_t bLength;
-    uint8_t bDescriptorType;    // USB_DT_SS_ISOCH_EP_COMPANION
-    uint16_t wReserved;
-    uint32_t dwBytesPerInterval;
+    uint8_t b_length;
+    uint8_t b_descriptor_type;    // USB_DT_SS_ISOCH_EP_COMPANION
+    uint16_t w_reserved;
+    uint32_t dw_bytes_per_interval;
 } __attribute__ ((packed)) usb_ss_isoch_ep_comp_descriptor_t;
 
 typedef struct {
-    uint8_t bLength;
-    uint8_t bDescriptorType;    // USB_DT_INTERFACE_ASSOCIATION
-    uint8_t bFirstInterface;
-    uint8_t bInterfaceCount;
-    uint8_t bFunctionClass;
-    uint8_t bFunctionSubClass;
-    uint8_t bFunctionProtocol;
-    uint8_t iFunction;
+    uint8_t b_length;
+    uint8_t b_descriptor_type;    // USB_DT_INTERFACE_ASSOCIATION
+    uint8_t b_first_interface;
+    uint8_t b_interface_count;
+    uint8_t b_function_class;
+    uint8_t b_function_sub_class;
+    uint8_t b_function_protocol;
+    uint8_t i_function;
 } __attribute__ ((packed)) usb_interface_assoc_descriptor_t;
 
 typedef struct {
-    uint8_t bLength;
-    uint8_t bDescriptorType;    // USB_DT_CS_INTERFACE
-    uint8_t bDescriptorSubType;
+    uint8_t b_length;
+    uint8_t b_descriptor_type;    // USB_DT_CS_INTERFACE
+    uint8_t b_descriptor_sub_type;
 } __attribute__ ((packed)) usb_cs_interface_descriptor_t;
 
 typedef struct {
-    uint8_t bLength;
-    uint8_t bDescriptorType;    // USB_DT_STRING
-    uint16_t wLangIds[127];
+    uint8_t b_length;
+    uint8_t b_descriptor_type;    // USB_DT_STRING
+    uint16_t w_lang_ids[127];
 } __attribute__ ((packed)) usb_langid_desc_t;
 
 typedef struct {
-    uint8_t bLength;
-    uint8_t bDescriptorType;    // USB_DT_STRING
+    uint8_t b_length;
+    uint8_t b_descriptor_type;    // USB_DT_STRING
     uint16_t code_points[127];
 } __attribute__ ((packed)) usb_string_desc_t;
 
diff --git a/lib/fuchsia/arch/arm64/sysroot/include/zircon/limits.h b/lib/fuchsia/arch/arm64/sysroot/include/zircon/limits.h
index f062d5e..239eb71 100644
--- a/lib/fuchsia/arch/arm64/sysroot/include/zircon/limits.h
+++ b/lib/fuchsia/arch/arm64/sysroot/include/zircon/limits.h
@@ -11,4 +11,23 @@
 #define ZX_PAGE_SIZE ((uintptr_t)(1u << ZX_PAGE_SHIFT))
 #define ZX_PAGE_MASK (ZX_PAGE_SIZE - 1u)
 
+#if defined(__x86_64__) || defined(__i386__)
+
+#define ZX_MIN_PAGE_SHIFT ((uint32_t)12u)
+#define ZX_MAX_PAGE_SHIFT ((uint32_t)21u)
+
+#elif defined(__aarch64__)
+
+#define ZX_MIN_PAGE_SHIFT ((uint32_t)12u)
+#define ZX_MAX_PAGE_SHIFT ((uint32_t)16u)
+
+#else
+
+#error what architecture?
+
+#endif
+
+#define ZX_MIN_PAGE_SIZE ((uintptr_t)(1u << ZX_MIN_PAGE_SHIFT))
+#define ZX_MAX_PAGE_SIZE ((uintptr_t)(1u << ZX_MAX_PAGE_SHIFT))
+
 #endif  // SYSROOT_ZIRCON_LIMITS_H_
diff --git a/lib/fuchsia/arch/arm64/sysroot/include/zircon/pixelformat.h b/lib/fuchsia/arch/arm64/sysroot/include/zircon/pixelformat.h
index f28f35f..1ae2107 100644
--- a/lib/fuchsia/arch/arm64/sysroot/include/zircon/pixelformat.h
+++ b/lib/fuchsia/arch/arm64/sysroot/include/zircon/pixelformat.h
@@ -23,6 +23,8 @@
 #define ZX_PIXEL_FORMAT_RGB_888    ((zx_pixel_format_t)0x00030009)
 #define ZX_PIXEL_FORMAT_ABGR_8888  ((zx_pixel_format_t)0x0004000a)
 #define ZX_PIXEL_FORMAT_BGR_888x   ((zx_pixel_format_t)0x0004000b)
+#define ZX_PIXEL_FORMAT_ARGB_2_10_10_10   ((zx_pixel_format_t)0x0004000c)
+#define ZX_PIXEL_FORMAT_ABGR_2_10_10_10   ((zx_pixel_format_t)0x0004000d)
 #define ZX_PIXEL_FORMAT_BYTES(pf)  (((pf) >> 16) & 7)
 
 #endif // SYSROOT_ZIRCON_PIXELFORMAT_H_
diff --git a/lib/fuchsia/arch/arm64/sysroot/include/zircon/process.h b/lib/fuchsia/arch/arm64/sysroot/include/zircon/process.h
index ef2bcb1..044c03d 100644
--- a/lib/fuchsia/arch/arm64/sysroot/include/zircon/process.h
+++ b/lib/fuchsia/arch/arm64/sysroot/include/zircon/process.h
@@ -6,6 +6,7 @@
 #define SYSROOT_ZIRCON_PROCESS_H_
 
 #include <stdint.h>
+#include <zircon/analyzer.h>
 #include <zircon/types.h>
 
 __BEGIN_CDECLS
@@ -21,11 +22,11 @@
 zx_handle_t _zx_thread_self(void);
 zx_handle_t zx_thread_self(void);
 
-zx_handle_t _zx_process_self(void);
-zx_handle_t zx_process_self(void);
+ZX_HANDLE_ACQUIRE_UNOWNED zx_handle_t _zx_process_self(void);
+ZX_HANDLE_ACQUIRE_UNOWNED zx_handle_t zx_process_self(void);
 
-zx_handle_t _zx_vmar_root_self(void);
-zx_handle_t zx_vmar_root_self(void);
+ZX_HANDLE_ACQUIRE_UNOWNED zx_handle_t _zx_vmar_root_self(void);
+ZX_HANDLE_ACQUIRE_UNOWNED zx_handle_t zx_vmar_root_self(void);
 
 zx_handle_t _zx_job_default(void);
 zx_handle_t zx_job_default(void);
diff --git a/lib/fuchsia/arch/arm64/sysroot/include/zircon/processargs.h b/lib/fuchsia/arch/arm64/sysroot/include/zircon/processargs.h
index 75a3c7b..43475b1 100644
--- a/lib/fuchsia/arch/arm64/sysroot/include/zircon/processargs.h
+++ b/lib/fuchsia/arch/arm64/sysroot/include/zircon/processargs.h
@@ -145,7 +145,8 @@
 // the ELF runner by serving the |fuchsia.process.Lifecycle| protocol.
 #define PA_LIFECYCLE 0x3Au
 
-// Server endpoint for handling connection to appmgr services.
+// Server endpoint for a processes' outgoing directory.
+// https://fuchsia.dev/fuchsia-src/glossary?hl=en#outgoing-directory
 #define PA_DIRECTORY_REQUEST 0x3Bu
 
 // Used by devmgr and devhosts
diff --git a/lib/fuchsia/arch/arm64/sysroot/include/zircon/rights.h b/lib/fuchsia/arch/arm64/sysroot/include/zircon/rights.h
index 1cfa768..5319802 100644
--- a/lib/fuchsia/arch/arm64/sysroot/include/zircon/rights.h
+++ b/lib/fuchsia/arch/arm64/sysroot/include/zircon/rights.h
@@ -29,6 +29,7 @@
 #define ZX_RIGHT_MANAGE_PROCESS ((zx_rights_t)1u << 17)
 #define ZX_RIGHT_MANAGE_THREAD ((zx_rights_t)1u << 18)
 #define ZX_RIGHT_APPLY_PROFILE ((zx_rights_t)1u << 19)
+#define ZX_RIGHT_MANAGE_SOCKET ((zx_rights_t)1u << 20)
 #define ZX_RIGHT_SAME_RIGHTS ((zx_rights_t)1u << 31)
 
 // Convenient names for commonly grouped rights.
@@ -86,7 +87,7 @@
 
 #define ZX_DEFAULT_SOCKET_RIGHTS                                                    \
   (ZX_RIGHTS_BASIC | ZX_RIGHTS_IO | ZX_RIGHT_GET_PROPERTY | ZX_RIGHT_SET_PROPERTY | \
-   ZX_RIGHT_SIGNAL | ZX_RIGHT_SIGNAL_PEER)
+   ZX_RIGHT_SIGNAL | ZX_RIGHT_SIGNAL_PEER | ZX_RIGHT_MANAGE_SOCKET)
 
 #define ZX_DEFAULT_STREAM_RIGHTS (ZX_RIGHTS_BASIC | ZX_RIGHTS_PROPERTY | ZX_RIGHT_SIGNAL)
 
diff --git a/lib/fuchsia/arch/arm64/sysroot/include/zircon/sanitizer.h b/lib/fuchsia/arch/arm64/sysroot/include/zircon/sanitizer.h
index c2f2e8e..49984ae 100644
--- a/lib/fuchsia/arch/arm64/sysroot/include/zircon/sanitizer.h
+++ b/lib/fuchsia/arch/arm64/sysroot/include/zircon/sanitizer.h
@@ -72,14 +72,22 @@
 // blob of data; the string is not used after this call returns.  The
 // caller creates a VMO (e.g. zx_vmo_create) and passes it in; the VMO
 // handle is consumed by this call.  Each particular data sink has its
-// own conventions about both the format of the data in the VMO and the
-// protocol for when data must be written there.  For some sinks, the
-// VMO's data is used immediately.  For other sinks, the caller is
+// own conventions about both the format of the data in the VMO and
+// the protocol for when data must be written there.  For some sinks,
+// the VMO's data is used immediately.  For other sinks, the caller is
 // expected to have the VMO mapped in and be writing more data there
 // throughout the life of the process, to be analyzed only after the
 // process terminates.  Yet others might use an asynchronous shared
-// memory protocol between producer and consumer.
-void __sanitizer_publish_data(const char* sink_name, zx_handle_t vmo);
+// memory protocol between producer and consumer.  The return value is
+// either ZX_HANDLE_INVALID or a Zircon handle whose lifetime is used
+// to signal the readiness of the data in the VMO.  This handle can be
+// passed to zx_handle_close() to indicate the data is ready to be
+// consumed.  Or the handle can safely be leaked by just ignoring the
+// return value; the data will be ready when the process exits.  Note
+// there is no indication of success or failure returned here (though
+// it may be logged).  A value of ZX_HANDLE_INVALID merely indicates
+// there is no way to communicate data readiness before process exit.
+zx_handle_t __sanitizer_publish_data(const char* sink_name, zx_handle_t vmo);
 
 // Runtimes that want to read configuration files use this interface.
 // The name is a string from the user (something akin to a file name
@@ -114,6 +122,16 @@
                                  sanitizer_memory_snapshot_callback_t* tls,
                                  void (*done)(zx_status_t, void*), void* arg);
 
+// This does a fast, best-effort attempt to collect a backtrace.  It writes PC
+// values (return addresses) for up to max_frames call frames into the
+// pc_buffer, and returns the number of frames collected.  The first frame
+// (pc_buffer[0]) will be the caller of __sanitizer_fast_backtrace (and that's
+// the only frame guaranteed to be collected), the second will be that frame's
+// caller, and so on.  This is safe even if register and memory state is bogus.
+// It's best-effort and results will be imprecise in the face of code that
+// doesn't use either shadow-call-stack or frame pointers.
+size_t __sanitizer_fast_backtrace(uintptr_t* pc_buffer, size_t max_frames);
+
 // The "hook" interfaces are functions that the sanitizer runtime library
 // can define and libc will call.  There are default definitions in libc
 // which do nothing, but any other definitions will override those.  These
diff --git a/lib/fuchsia/arch/arm64/sysroot/include/zircon/string_view.h b/lib/fuchsia/arch/arm64/sysroot/include/zircon/string_view.h
index f54ff2a..15dd36e 100644
--- a/lib/fuchsia/arch/arm64/sysroot/include/zircon/string_view.h
+++ b/lib/fuchsia/arch/arm64/sysroot/include/zircon/string_view.h
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef SYSROOT_ZIRCON_STRING_VIEW_H_
+#define SYSROOT_ZIRCON_STRING_VIEW_H_
 
 #include <stddef.h>
 #if __cplusplus >= 201103L && __has_include(<type_traits>)
@@ -22,7 +23,7 @@
 // source.  C++ 17 callers can take advantage of direct coercion to
 // the standard std::string_view and std::u8string_view types, which
 // also allows e.g. direct construction of std::string.
-typedef struct {
+typedef struct zx_string_view {
   const char* c_str;  // UTF-8, guaranteed to be '\0'-terminated.
   size_t length;      // Length, not including the '\0' terminator.
 
@@ -65,3 +66,5 @@
   size_type size() const { return length; }
 #endif
 } zx_string_view_t;
+
+#endif  // SYSROOT_ZIRCON_STRING_VIEW_H_
diff --git a/lib/fuchsia/arch/arm64/sysroot/include/zircon/syscalls.h b/lib/fuchsia/arch/arm64/sysroot/include/zircon/syscalls.h
index 9e79e55..da15f35 100644
--- a/lib/fuchsia/arch/arm64/sysroot/include/zircon/syscalls.h
+++ b/lib/fuchsia/arch/arm64/sysroot/include/zircon/syscalls.h
@@ -5,6 +5,7 @@
 #ifndef SYSROOT_ZIRCON_SYSCALLS_H_
 #define SYSROOT_ZIRCON_SYSCALLS_H_
 
+#include <zircon/compiler.h>
 #include <zircon/string_view.h>
 #include <zircon/syscalls/object.h>
 #include <zircon/syscalls/pci.h>
@@ -15,8 +16,8 @@
 __BEGIN_CDECLS
 
 #define _ZX_SYSCALL_DECL(name, type, attrs, nargs, arglist, prototype) \
-  extern attrs type zx_##name prototype;                               \
-  extern attrs type _zx_##name prototype;
+  extern attrs __LEAF_FN type zx_##name prototype;                     \
+  extern attrs __LEAF_FN type _zx_##name prototype;
 
 #ifdef __clang__
 #define _ZX_SYSCALL_ANNO(attr) __attribute__((attr))
diff --git a/lib/fuchsia/arch/arm64/sysroot/include/zircon/syscalls/clock.h b/lib/fuchsia/arch/arm64/sysroot/include/zircon/syscalls/clock.h
index eab1cd1..eb702d7 100644
--- a/lib/fuchsia/arch/arm64/sysroot/include/zircon/syscalls/clock.h
+++ b/lib/fuchsia/arch/arm64/sysroot/include/zircon/syscalls/clock.h
@@ -15,42 +15,60 @@
 // arguments encode a version number in the options field of the syscall.  This
 // version field is in the same location and is the same size for each syscall,
 // so a common set of macros may be used for encoding and decoding.
-#define ZX_CLOCK_ARGS_VERSION_SHIFT              ((uint64_t)58u)
-#define ZX_CLOCK_ARGS_VERSION_BITS               ((uint64_t)6u)
+#define ZX_CLOCK_ARGS_VERSION_SHIFT ((uint64_t)58u)
+#define ZX_CLOCK_ARGS_VERSION_BITS  ((uint64_t)6u)
 #define ZX_CLOCK_ARGS_VERSION_MASK \
   (((((uint64_t)1) << ZX_CLOCK_ARGS_VERSION_BITS) - 1) << ZX_CLOCK_ARGS_VERSION_SHIFT)
 #define ZX_CLOCK_ARGS_VERSION(_N) \
   (((uint64_t)(_N) << ZX_CLOCK_ARGS_VERSION_SHIFT) & ZX_CLOCK_ARGS_VERSION_MASK)
 
 // Clock creation options.
-#define ZX_CLOCK_OPT_MONOTONIC                   ((uint64_t)1u << 0)
-#define ZX_CLOCK_OPT_CONTINUOUS                  ((uint64_t)1u << 1)
-#define ZX_CLOCK_OPT_AUTO_START                  ((uint64_t)1u << 2)
+#define ZX_CLOCK_OPT_MONOTONIC  ((uint64_t)1u << 0)
+#define ZX_CLOCK_OPT_CONTINUOUS ((uint64_t)1u << 1)
+#define ZX_CLOCK_OPT_AUTO_START ((uint64_t)1u << 2)
 
 #define ZX_CLOCK_OPTS_ALL ( \
         ZX_CLOCK_OPT_MONOTONIC | \
         ZX_CLOCK_OPT_CONTINUOUS | \
         ZX_CLOCK_OPT_AUTO_START)
 
-// Clock update flags
-#define ZX_CLOCK_UPDATE_OPTION_VALUE_VALID       ((uint64_t)1u << 0)
-#define ZX_CLOCK_UPDATE_OPTION_RATE_ADJUST_VALID ((uint64_t)1u << 1)
-#define ZX_CLOCK_UPDATE_OPTION_ERROR_BOUND_VALID ((uint64_t)1u << 2)
+// v1 clock update flags
+#define ZX_CLOCK_UPDATE_OPTION_VALUE_VALID        ((uint64_t)1u << 0)
+#define ZX_CLOCK_UPDATE_OPTION_RATE_ADJUST_VALID  ((uint64_t)1u << 1)
+#define ZX_CLOCK_UPDATE_OPTION_ERROR_BOUND_VALID  ((uint64_t)1u << 2)
+
+// Additional v2 clock update flags
+#define ZX_CLOCK_UPDATE_OPTION_REFERENCE_VALUE_VALID  ((uint64_t)1u << 3)
+#define ZX_CLOCK_UPDATE_OPTION_SYNTHETIC_VALUE_VALID  ZX_CLOCK_UPDATE_OPTION_VALUE_VALID
+#define ZX_CLOCK_UPDATE_OPTION_BOTH_VALUES_VALID ( \
+        ZX_CLOCK_UPDATE_OPTION_REFERENCE_VALUE_VALID | \
+        ZX_CLOCK_UPDATE_OPTION_SYNTHETIC_VALUE_VALID)
 
 #define ZX_CLOCK_UPDATE_OPTIONS_ALL ( \
-        ZX_CLOCK_UPDATE_OPTION_VALUE_VALID |  \
+        ZX_CLOCK_UPDATE_OPTION_SYNTHETIC_VALUE_VALID |  \
         ZX_CLOCK_UPDATE_OPTION_RATE_ADJUST_VALID | \
-        ZX_CLOCK_UPDATE_OPTION_ERROR_BOUND_VALID)
+        ZX_CLOCK_UPDATE_OPTION_ERROR_BOUND_VALID | \
+        ZX_CLOCK_UPDATE_OPTION_REFERENCE_VALUE_VALID)
 
 // Clock rate adjustment limits
-#define ZX_CLOCK_UPDATE_MIN_RATE_ADJUST          ((int32_t)-1000)
-#define ZX_CLOCK_UPDATE_MAX_RATE_ADJUST          ((int32_t)1000)
+#define ZX_CLOCK_UPDATE_MIN_RATE_ADJUST ((int32_t)-1000)
+#define ZX_CLOCK_UPDATE_MAX_RATE_ADJUST ((int32_t)1000)
 
 // Special clock error values
-#define ZX_CLOCK_UNKNOWN_ERROR                   ((uint64_t)0xFFFFFFFFFFFFFFFF)
+#define ZX_CLOCK_UNKNOWN_ERROR  ((uint64_t)0xFFFFFFFFFFFFFFFF)
 
 // clang-format on
 
+// Make certain that the new name introduced with the v2 version of the clock
+// update structure always tracks the original v2 name.
+#ifdef __cplusplus
+static_assert(ZX_CLOCK_UPDATE_OPTION_VALUE_VALID == ZX_CLOCK_UPDATE_OPTION_SYNTHETIC_VALUE_VALID,
+              "Mismatch between v1 VALUE and v2 SYNTHETIC_VALUE clock update flags!");
+#else
+_Static_assert(ZX_CLOCK_UPDATE_OPTION_VALUE_VALID == ZX_CLOCK_UPDATE_OPTION_SYNTHETIC_VALUE_VALID,
+               "Mismatch between v1 VALUE and v2 SYNTHETIC_VALUE clock update flags!");
+#endif
+
 typedef struct zx_clock_create_args_v1 {
   zx_time_t backstop_time;
 } zx_clock_create_args_v1_t;
@@ -87,4 +105,12 @@
   uint64_t error_bound;
 } zx_clock_update_args_v1_t;
 
+typedef struct zx_clock_update_args_v2 {
+  int32_t rate_adjust;
+  uint8_t padding1[4];
+  int64_t synthetic_value;
+  int64_t reference_value;
+  uint64_t error_bound;
+} zx_clock_update_args_v2_t;
+
 #endif  // SYSROOT_ZIRCON_SYSCALLS_CLOCK_H_
diff --git a/lib/fuchsia/arch/arm64/sysroot/include/zircon/syscalls/exception.h b/lib/fuchsia/arch/arm64/sysroot/include/zircon/syscalls/exception.h
index cd4c5e8..fa3eb00 100644
--- a/lib/fuchsia/arch/arm64/sysroot/include/zircon/syscalls/exception.h
+++ b/lib/fuchsia/arch/arm64/sysroot/include/zircon/syscalls/exception.h
@@ -21,6 +21,8 @@
 // |report.context.arch|.
 
 #define ZX_EXCP_GENERAL                 ((uint32_t) 0x008u)
+// The error code for the fatal page fault can be found in the |synth_code| field
+// of the report, which will be a |zx_status_t| value typecast to a |uint32_t|.
 #define ZX_EXCP_FATAL_PAGE_FAULT        ((uint32_t) 0x108u)
 #define ZX_EXCP_UNDEFINED_INSTRUCTION   ((uint32_t) 0x208u)
 #define ZX_EXCP_SW_BREAKPOINT           ((uint32_t) 0x308u)
@@ -73,7 +75,7 @@
 #define ZX_EXCP_POLICY_CODE_AMBIENT_MARK_VMO_EXEC 14u
 #define ZX_EXCP_POLICY_CODE_CHANNEL_FULL_WRITE    15u
 #define ZX_EXCP_POLICY_CODE_PORT_TOO_MANY_PACKETS 16u
-#define ZX_EXCP_POLICY_CODE_BAD_SYSCALL           17u
+#define ZX_EXCP_POLICY_CODE_BAD_SYSCALL           17u  // synth_data is the syscall number.
 
 // A process is starting.
 // This exception is sent to job debuggers only
diff --git a/lib/fuchsia/arch/arm64/sysroot/include/zircon/syscalls/internal/cdecls.inc b/lib/fuchsia/arch/arm64/sysroot/include/zircon/syscalls/internal/cdecls.inc
index ed41995..1e2d89a 100644
--- a/lib/fuchsia/arch/arm64/sysroot/include/zircon/syscalls/internal/cdecls.inc
+++ b/lib/fuchsia/arch/arm64/sysroot/include/zircon/syscalls/internal/cdecls.inc
@@ -100,20 +100,9 @@
     uint32_t* actual_bytes,
     uint32_t* actual_handles))
 
-_ZX_SYSCALL_DECL(clock_get, zx_status_t, /* no attributes */, 2,
-    (clock_id, out), (
-    zx_clock_t clock_id,
-    zx_time_t* out))
-
 _ZX_SYSCALL_DECL(clock_get_monotonic, zx_time_t, /* no attributes */, 0,
     (), (void))
 
-_ZX_SYSCALL_DECL(clock_adjust, zx_status_t, /* no attributes */, 3,
-    (handle, clock_id, offset), (
-    _ZX_SYSCALL_ANNO(use_handle("Fuchsia")) zx_handle_t handle,
-    zx_clock_t clock_id,
-    int64_t offset))
-
 _ZX_SYSCALL_DECL(clock_create, zx_status_t, /* no attributes */, 3,
     (options, args, out), (
     uint64_t options,
@@ -782,6 +771,12 @@
     _ZX_SYSCALL_ANNO(use_handle("Fuchsia")) zx_handle_t handle,
     uint32_t options))
 
+_ZX_SYSCALL_DECL(socket_set_disposition, zx_status_t, /* no attributes */, 3,
+    (handle, disposition, disposition_peer), (
+    _ZX_SYSCALL_ANNO(use_handle("Fuchsia")) zx_handle_t handle,
+    uint32_t disposition,
+    uint32_t disposition_peer))
+
 _ZX_SYSCALL_DECL(stream_create, zx_status_t, /* no attributes */, 4,
     (options, vmo, seek, out_stream), (
     uint32_t options,
@@ -839,6 +834,9 @@
 _ZX_SYSCALL_DECL(system_get_version_string, zx_string_view_t, __CONST, 0,
     (), (void))
 
+_ZX_SYSCALL_DECL(system_get_page_size, uint32_t, __CONST, 0,
+    (), (void))
+
 _ZX_SYSCALL_DECL(system_get_physmem, uint64_t, /* no attributes */, 0,
     (), (void))
 
diff --git a/lib/fuchsia/arch/arm64/sysroot/include/zircon/syscalls/log.h b/lib/fuchsia/arch/arm64/sysroot/include/zircon/syscalls/log.h
index c6af1d9..afc1923 100644
--- a/lib/fuchsia/arch/arm64/sysroot/include/zircon/syscalls/log.h
+++ b/lib/fuchsia/arch/arm64/sysroot/include/zircon/syscalls/log.h
@@ -11,7 +11,11 @@
 
 // Defines and structures for zx_log_*()
 typedef struct zx_log_record {
-  uint32_t rollout;
+  // Each log record is assigned a sequence number at the time it enters the
+  // debuglog. A record's sequence number is exactly one greater than the record
+  // that preceded it.
+  uint64_t sequence;
+  uint8_t padding1[4];
   uint16_t datalen;
   uint8_t severity;
   uint8_t flags;
@@ -21,11 +25,16 @@
   char data[];
 } zx_log_record_t;
 
+// The maximum size of zx_log_record_t.
+#define ZX_LOG_RECORD_MAX ((size_t)256)
+
+// The maximum size of zx_log_record_t::data. Records containing more than this
+// amount of data may be truncated to this value or less.
+#define ZX_LOG_RECORD_DATA_MAX (ZX_LOG_RECORD_MAX - sizeof(zx_log_record_t))
+
 // ask clang format not to mess up the indentation:
 // clang-format off
 
-#define ZX_LOG_RECORD_MAX     256
-
 // Log Levels
 #define ZX_LOG_TRACE          (0x10)
 #define ZX_LOG_DEBUG          (0x20)
@@ -46,6 +55,8 @@
 
 #define ZX_LOG_FLAG_READABLE  0x40000000
 
+// clang-format on
+
 __END_CDECLS
 
 #endif  // SYSROOT_ZIRCON_SYSCALLS_LOG_H_
diff --git a/lib/fuchsia/arch/arm64/sysroot/include/zircon/syscalls/object.h b/lib/fuchsia/arch/arm64/sysroot/include/zircon/syscalls/object.h
index ce1e4b9..627bd94 100644
--- a/lib/fuchsia/arch/arm64/sysroot/include/zircon/syscalls/object.h
+++ b/lib/fuchsia/arch/arm64/sysroot/include/zircon/syscalls/object.h
@@ -20,7 +20,9 @@
 #define ZX_INFO_NONE                        ((zx_object_info_topic_t)  0u)
 #define ZX_INFO_HANDLE_VALID                ((zx_object_info_topic_t)  1u)
 #define ZX_INFO_HANDLE_BASIC                ((zx_object_info_topic_t)  2u) // zx_info_handle_basic_t[1]
-#define ZX_INFO_PROCESS                     ((zx_object_info_topic_t)  3u) // zx_info_process_t[1]
+#define ZX_INFO_PROCESS_V1                  __ZX_INFO_TOPIC(3u, 0u)        // zx_info_process_v1_t[1]
+#define ZX_INFO_PROCESS_V2                  __ZX_INFO_TOPIC(3u, 1u)        // zx_info_process_v2_t[1]
+#define ZX_INFO_PROCESS ZX_INFO_PROCESS_V2
 #define ZX_INFO_PROCESS_THREADS             ((zx_object_info_topic_t)  4u) // zx_koid_t[n]
 #define ZX_INFO_VMAR                        ((zx_object_info_topic_t)  7u) // zx_info_vmar_t[1]
 #define ZX_INFO_JOB_CHILDREN                ((zx_object_info_topic_t)  8u) // zx_koid_t[n]
@@ -48,7 +50,8 @@
 #define ZX_INFO_HANDLE_TABLE                ((zx_object_info_topic_t) 27u) // zx_info_handle_extended_t[n]
 #define ZX_INFO_MSI                         ((zx_object_info_topic_t) 28u) // zx_info_msi_t[1]
 #define ZX_INFO_GUEST_STATS                 ((zx_object_info_topic_t) 29u) // zx_info_guest_stats_t[1]
-#define ZX_INFO_TASK_RUNTIME                ((zx_object_info_topic_t) 30u) // zx_info_task_runtime_t[1]
+#define ZX_INFO_TASK_RUNTIME_V1             __ZX_INFO_TOPIC(30u, 0)        // zx_info_task_runtime_t[1]
+#define ZX_INFO_TASK_RUNTIME                __ZX_INFO_TOPIC(30u, 1)        // zx_info_task_runtime_t[1]
 #define ZX_INFO_KMEM_STATS_EXTENDED         ((zx_object_info_topic_t) 31u) // zx_info_kmem_stats_extended_t[1]
 
 // Return codes set when a task is killed.
@@ -133,7 +136,9 @@
     uint32_t handle_count[ZX_OBJ_TYPE_UPPER_BOUND];
 } zx_info_process_handle_stats_t;
 
-typedef struct zx_info_process {
+
+// TODO(fxbug.dev/30751): Deprecated in favor of zx_info_process_v2_t.
+typedef struct zx_info_process_v1 {
     // The process's return code; only valid if |exited| is true.
     // If the process was killed, it will be one of the ZX_TASK_RETCODE values.
     int64_t return_code;
@@ -149,7 +154,40 @@
     bool debugger_attached;
 
     uint8_t padding1[5];
-} zx_info_process_t;
+} zx_info_process_v1_t;
+
+typedef uint32_t zx_info_process_flags_t;
+
+// Whether the process has started. `zx_process_info_t::start_time` is only
+// valid if this flag is set.
+#define ZX_INFO_PROCESS_FLAG_STARTED (zx_info_process_flags_t (1u << 0))
+
+// Whether the process has exited.
+#define ZX_INFO_PROCESS_FLAG_EXITED (zx_info_process_flags_t (1u << 1))
+
+// Whether a debugger is attached to the process.
+#define ZX_INFO_PROCESS_FLAG_DEBUGGER_ATTACHED (zx_info_process_flags_t (1u << 2))
+
+// TODO(fxbug.dev/30751): This will replace zx_info_process_v2_t and will be
+// renamed to `zx_info_process_t` later in the transition.
+typedef struct zx_info_process_v2 {
+    // The process's return code; only valid if the
+    // |ZX_INFO_PROCESS_FLAG_EXITED| flag is set. If the process was killed, it
+    // will be one of the |ZX_TASK_RETCODE| values.
+    int64_t return_code;
+
+    // The monotonic time at which `zx_process_start()` was called, only valid
+    // if the |ZX_INFO_PROCESS_FLAG_STARTED| flag is set.
+    zx_time_t start_time;
+
+    // Bitwise OR of ZX_INFO_PROCESS_FLAG_* values.
+    zx_info_process_flags_t flags;
+
+    uint8_t padding1[4];
+} zx_info_process_v2_t;
+
+// TODO(fxbug.dev/30751): Rename `zx_info_process_v2_t` to `zx_info_process_t`.
+typedef zx_info_process_v2_t zx_info_process_t;
 
 typedef struct zx_info_job {
     // The job's return code; only valid if |exited| is true.
@@ -424,9 +462,15 @@
 // the ZX_INFO_VMO_TYPE_PAGED flag set.
 #define ZX_INFO_VMO_PAGER_BACKED            (1u<<5)
 
-// The VMO is contiguous
+// The VMO is contiguous.
 #define ZX_INFO_VMO_CONTIGUOUS              (1u<<6)
 
+// The VMO is discardable.
+#define ZX_INFO_VMO_DISCARDABLE             (1u<<7)
+
+// The VMO is immutable and has been since creation.
+#define ZX_INFO_VMO_IMMUTABLE               (1u<<8)
+
 // Describes a VMO. For mapping information, see |zx_info_maps_t|.
 typedef struct zx_info_vmo {
     // The koid of this VMO.
@@ -534,12 +578,12 @@
     uint64_t xsetbv_instructions;
     uint64_t pause_instructions;
     uint64_t vmcall_instructions;
-} zx_x86_64_info_guest_stats;
+} zx_x86_64_info_guest_stats_t;
 
 #if defined(__aarch64__)
 typedef zx_arm64_info_guest_stats_t zx_info_guest_stats_t;
 #elif defined(__x86_64__)
-typedef zx_x86_64_info_guest_stats zx_info_guest_stats_t;
+typedef zx_x86_64_info_guest_stats_t zx_info_guest_stats_t;
 #endif
 
 // Info on the runtime of a task.
@@ -559,8 +603,29 @@
     // * Jobs include the queue time for all of their processes (including processes that previously
     // exited).
     zx_duration_t queue_time;
+
+    // The total amount of time this task and its children spent handling page faults.
+    // * Threads include only their own page fault handling time.
+    // * Processes include the page fault time for all of their threads (including threads that
+    // previously exited).
+    // * Jobs include the page fault time for all of their processes (including processes that
+    // previously exited).
+    zx_duration_t page_fault_time;
+
+    // The total amount of time this task and its children spent waiting on contended kernel locks.
+    // * Threads include only their own wait time.
+    // * Processes include the wait time for all of their threads (including threads that
+    // previously exited).
+    // * Jobs include the wait time for all of their processes (including processes that
+    // previously exited).
+    zx_duration_t lock_contention_time;
 } zx_info_task_runtime_t;
 
+typedef struct zx_info_task_runtime_v1 {
+    zx_duration_t cpu_time;
+    zx_duration_t queue_time;
+} zx_info_task_runtime_v1_t;
+
 
 // kernel statistics per cpu
 // TODO(cpu), expose the deprecated stats via a new syscall.
@@ -797,6 +862,7 @@
 // ZX_PROP_EXCEPTION_STATE values.
 #define ZX_EXCEPTION_STATE_TRY_NEXT         0u
 #define ZX_EXCEPTION_STATE_HANDLED          1u
+#define ZX_EXCEPTION_STATE_THREAD_EXIT      2u
 
 // How an exception should be handled
 // ZX_PROP_EXCEPTION_STRATEGY values.
diff --git a/lib/fuchsia/arch/arm64/sysroot/include/zircon/syscalls/pci.h b/lib/fuchsia/arch/arm64/sysroot/include/zircon/syscalls/pci.h
index d1049c2..2f98905 100644
--- a/lib/fuchsia/arch/arm64/sysroot/include/zircon/syscalls/pci.h
+++ b/lib/fuchsia/arch/arm64/sysroot/include/zircon/syscalls/pci.h
@@ -126,8 +126,9 @@
 typedef uint32_t zx_pci_irq_mode_t;
 #define ZX_PCIE_IRQ_MODE_DISABLED ((zx_pci_irq_mode_t) 0u)
 #define ZX_PCIE_IRQ_MODE_LEGACY ((zx_pci_irq_mode_t) 1u)
-#define ZX_PCIE_IRQ_MODE_MSI ((zx_pci_irq_mode_t) 2u)
-#define ZX_PCIE_IRQ_MODE_MSI_X ((zx_pci_irq_mode_t) 3u)
+#define ZX_PCIE_IRQ_MODE_LEGACY_NOACK ((zx_pci_irq_mode_t) 2u)
+#define ZX_PCIE_IRQ_MODE_MSI ((zx_pci_irq_mode_t) 3u)
+#define ZX_PCIE_IRQ_MODE_MSI_X ((zx_pci_irq_mode_t) 4u)
 
 __END_CDECLS
 
diff --git a/lib/fuchsia/arch/arm64/sysroot/include/zircon/syscalls/resource.h b/lib/fuchsia/arch/arm64/sysroot/include/zircon/syscalls/resource.h
index c79bd0a..adf8235 100644
--- a/lib/fuchsia/arch/arm64/sysroot/include/zircon/syscalls/resource.h
+++ b/lib/fuchsia/arch/arm64/sysroot/include/zircon/syscalls/resource.h
@@ -36,6 +36,7 @@
 #define ZX_RSRC_SYSTEM_HYPERVISOR_BASE ((zx_rsrc_system_base_t)0u)
 #define ZX_RSRC_SYSTEM_VMEX_BASE ((zx_rsrc_system_base_t)1u)
 #define ZX_RSRC_SYSTEM_DEBUG_BASE ((zx_rsrc_system_base_t)2u)
-#define ZX_RSRC_SYSTEM_COUNT ((zx_rsrc_system_base_t)3u)
+#define ZX_RSRC_SYSTEM_INFO_BASE ((zx_rsrc_system_base_t)3u)
+#define ZX_RSRC_SYSTEM_COUNT ((zx_rsrc_system_base_t)4u)
 
 #endif  // SYSROOT_ZIRCON_SYSCALLS_RESOURCE_H_
diff --git a/lib/fuchsia/arch/arm64/sysroot/include/zircon/time.h b/lib/fuchsia/arch/arm64/sysroot/include/zircon/time.h
index 33f5452..2acb77b 100644
--- a/lib/fuchsia/arch/arm64/sysroot/include/zircon/time.h
+++ b/lib/fuchsia/arch/arm64/sysroot/include/zircon/time.h
@@ -139,6 +139,42 @@
   return zx_duration_mul_int64(3600000000000, n);
 }
 
+__CONSTEXPR static inline zx_ticks_t zx_ticks_add_ticks(zx_ticks_t ticks1, zx_ticks_t ticks2) {
+  zx_ticks_t x = 0;
+  if (unlikely(add_overflow(ticks1, ticks2, &x))) {
+    if (x >= 0) {
+      return ZX_TIME_INFINITE_PAST;
+    } else {
+      return ZX_TIME_INFINITE;
+    }
+  }
+  return x;
+}
+
+__CONSTEXPR static inline zx_ticks_t zx_ticks_sub_ticks(zx_ticks_t ticks1, zx_ticks_t ticks2) {
+  zx_ticks_t x = 0;
+  if (unlikely(sub_overflow(ticks1, ticks2, &x))) {
+    if (x >= 0) {
+      return ZX_TIME_INFINITE_PAST;
+    } else {
+      return ZX_TIME_INFINITE;
+    }
+  }
+  return x;
+}
+
+__CONSTEXPR static inline zx_ticks_t zx_ticks_mul_int64(zx_ticks_t ticks, int64_t multiplier) {
+  zx_ticks_t x = 0;
+  if (unlikely(mul_overflow(ticks, multiplier, &x))) {
+    if ((ticks > 0 && multiplier > 0) || (ticks < 0 && multiplier < 0)) {
+      return ZX_TIME_INFINITE;
+    } else {
+      return ZX_TIME_INFINITE_PAST;
+    }
+  }
+  return x;
+}
+
 #if __has_include(<time.h>)
 
 __CONSTEXPR static inline zx_duration_t zx_duration_from_timespec(struct timespec ts) {
diff --git a/lib/fuchsia/arch/arm64/sysroot/include/zircon/types.h b/lib/fuchsia/arch/arm64/sysroot/include/zircon/types.h
index 5832d95..1f92eb1 100644
--- a/lib/fuchsia/arch/arm64/sysroot/include/zircon/types.h
+++ b/lib/fuchsia/arch/arm64/sysroot/include/zircon/types.h
@@ -37,7 +37,21 @@
 #define ZX_HANDLE_INVALID           ((zx_handle_t)0)
 #define ZX_HANDLE_FIXED_BITS_MASK   ((zx_handle_t)0x3)
 
-// See errors.h for the values zx_status_t can take.
+// `zx_status_t` is a simple error type used to communicate whether a particular
+// action was successful or not. It is defined as being a signed 32-bit integer.
+// The value `ZX_OK` (0) indicates an operation was successful. All other values
+// indicate an error of some form.
+//
+// The range of valid `zx_status_t` values is `[-2^30, 0]` (that is,
+// `-1073741824` to `0`). All values in this range will be system-defined error
+// codes or the single success code `ZX_OK`.
+//
+// Application-defined error codes (previously defined as all positive
+// `zx_status_t` values) are deprecated.
+//
+// * See errors.h for currently defined `zx_status_t` values.
+// * See https://fuchsia.dev/fuchsia-src/contribute/governance/rfcs/0085_reducing_zx_status_t_space
+//   for additional details about `zx_status_t`.
 typedef int32_t zx_status_t;
 
 // clock ids
@@ -176,6 +190,7 @@
 
 // VM Object creation options
 #define ZX_VMO_RESIZABLE                 ((uint32_t)1u << 1)
+#define ZX_VMO_DISCARDABLE               ((uint32_t)1u << 2)
 
 // VM Object opcodes
 #define ZX_VMO_OP_COMMIT                 ((uint32_t)1u)
@@ -189,6 +204,24 @@
 #define ZX_VMO_OP_CACHE_CLEAN            ((uint32_t)8u)
 #define ZX_VMO_OP_CACHE_CLEAN_INVALIDATE ((uint32_t)9u)
 #define ZX_VMO_OP_ZERO                   ((uint32_t)10u)
+#define ZX_VMO_OP_TRY_LOCK               ((uint32_t)11u)
+#define ZX_VMO_OP_DONT_NEED              ((uint32_t)12u)
+#define ZX_VMO_OP_ALWAYS_NEED            ((uint32_t)13u)
+
+// |buffer| for zx_vmo_op_range() with ZX_VMO_OP_LOCK.
+typedef struct zx_vmo_lock_state {
+  // |offset| and |size| track the locked range, and will be set to the |offset|
+  // and |size| arguments passed in if the ZX_VMO_OP_LOCK is successful.
+  uint64_t offset;
+  uint64_t size;
+  // |discarded_offset| and |discarded_size| track the discarded range prior to
+  // the lock operation. This is the maximal range within the locked range that
+  // contains discarded pages; not all pages within this range might have been
+  // discarded. Both |discarded_offset| and |discarded_size| will be set to 0 if
+  // the range was not discarded.
+  uint64_t discarded_offset;
+  uint64_t discarded_size;
+} zx_vmo_lock_state_t;
 
 // VMAR opcodes
 // Keep value in sync with ZX_VMO_OP_DECOMMIT.
@@ -204,10 +237,6 @@
 #define ZX_VMO_CHILD_RESIZABLE            ((uint32_t)1u << 2)
 #define ZX_VMO_CHILD_SLICE                ((uint32_t)1u << 3)
 #define ZX_VMO_CHILD_NO_WRITE             ((uint32_t)1u << 5)
-// Old clone flags that are on the path to deprecation.
-#define ZX_VMO_CLONE_COPY_ON_WRITE        ((uint32_t)1u << 4)
-#define ZX_VMO_CHILD_COPY_ON_WRITE        ((uint32_t)1u << 4)
-#define ZX_VMO_CHILD_PRIVATE_PAGER_COPY   ((uint32_t)1u << 4)
 
 typedef uint32_t zx_vm_option_t;
 // Mapping flags to vmar routines
@@ -307,21 +336,29 @@
 
 // Channel options and limits.
 #define ZX_CHANNEL_READ_MAY_DISCARD         ((uint32_t)1u)
+#define ZX_CHANNEL_WRITE_USE_IOVEC          ((uint32_t)2u)
 
 // TODO(fxbug.dev/7802): This must be manually kept in sync with zx_common.fidl.
 // Eventually (some of) this file will be generated from //zircon/vdso.
 #define ZX_CHANNEL_MAX_MSG_BYTES            ((uint32_t)65536u)
 #define ZX_CHANNEL_MAX_MSG_HANDLES          ((uint32_t)64u)
+#define ZX_CHANNEL_MAX_MSG_IOVECS           ((uint32_t)8192u)
 
 // Fifo limits.
 #define ZX_FIFO_MAX_SIZE_BYTES              ZX_PAGE_SIZE
 
 // Socket options and limits.
+
 // These options can be passed to zx_socket_shutdown().
+// TODO(https://fxbug.dev/78128): Remove after ABI transition.
 #define ZX_SOCKET_SHUTDOWN_WRITE            ((uint32_t)1u << 0)
 #define ZX_SOCKET_SHUTDOWN_READ             ((uint32_t)1u << 1)
 #define ZX_SOCKET_SHUTDOWN_MASK             (ZX_SOCKET_SHUTDOWN_WRITE | ZX_SOCKET_SHUTDOWN_READ)
 
+// These options can be passed to zx_socket_set_disposition().
+#define ZX_SOCKET_DISPOSITION_WRITE_DISABLED ((uint32_t)1u << 0)
+#define ZX_SOCKET_DISPOSITION_WRITE_ENABLED  ((uint32_t)1u << 1)
+
 // These can be passed to zx_socket_create().
 #define ZX_SOCKET_STREAM                    ((uint32_t)0u)
 #define ZX_SOCKET_DATAGRAM                  ((uint32_t)1u << 0)
@@ -415,6 +452,7 @@
 #define ZX_SYSTEM_EVENT_MEMORY_PRESSURE_CRITICAL    ((zx_system_event_type_t)2u)
 #define ZX_SYSTEM_EVENT_MEMORY_PRESSURE_WARNING     ((zx_system_event_type_t)3u)
 #define ZX_SYSTEM_EVENT_MEMORY_PRESSURE_NORMAL      ((zx_system_event_type_t)4u)
+#define ZX_SYSTEM_EVENT_IMMINENT_OUT_OF_MEMORY      ((zx_system_event_type_t)5u)
 
 // Used in channel_read_etc.
 typedef struct zx_handle_info {
@@ -463,6 +501,12 @@
     uint32_t rd_num_handles;
 } zx_channel_call_etc_args_t;
 
+typedef struct zx_channel_iovec {
+  const void* buffer;
+  uint32_t capacity;
+  uint32_t reserved;
+} zx_channel_iovec_t;
+
 // The ZX_VM_FLAG_* constants are to be deprecated in favor of the ZX_VM_*
 // versions.
 #define ZX_VM_FLAG_PERM_READ              ((uint32_t)1u << 0)
diff --git a/lib/fuchsia/arch/arm64/sysroot/lib/libc.so b/lib/fuchsia/arch/arm64/sysroot/lib/libc.so
index 3ca4768..3a020f9 100755
--- a/lib/fuchsia/arch/arm64/sysroot/lib/libc.so
+++ b/lib/fuchsia/arch/arm64/sysroot/lib/libc.so
Binary files differ
diff --git a/lib/fuchsia/arch/arm64/sysroot/lib/libzircon.so b/lib/fuchsia/arch/arm64/sysroot/lib/libzircon.so
old mode 100755
new mode 100644
index 737a974..413b30d
--- a/lib/fuchsia/arch/arm64/sysroot/lib/libzircon.so
+++ b/lib/fuchsia/arch/arm64/sysroot/lib/libzircon.so
Binary files differ
diff --git a/lib/fuchsia/docs/firmware.json b/lib/fuchsia/docs/firmware.json
new file mode 100644
index 0000000..95208eb
--- /dev/null
+++ b/lib/fuchsia/docs/firmware.json
@@ -0,0 +1,7 @@
+{
+  "docs": [
+    "README.md"
+  ],
+  "name": "firmware",
+  "type": "documentation"
+}
\ No newline at end of file
diff --git a/lib/fuchsia/docs/metadata_schemas.json b/lib/fuchsia/docs/metadata_schemas.json
index d460e24..8c55f10 100644
--- a/lib/fuchsia/docs/metadata_schemas.json
+++ b/lib/fuchsia/docs/metadata_schemas.json
@@ -5,13 +5,18 @@
     "meta/schemas/common.json",
     "meta/schemas/dart_library.json",
     "meta/schemas/data.json",
-    "meta/schemas/device_profile.json",
     "meta/schemas/documentation.json",
+    "meta/schemas/emu_manifest.json",
     "meta/schemas/fidl_library.json",
+    "meta/schemas/flash_manifest-835e8f26.json",
+    "meta/schemas/hardware-f6f47515.json",
     "meta/schemas/host_tool.json",
     "meta/schemas/loadable_module.json",
     "meta/schemas/manifest.json",
-    "meta/schemas/sysroot.json"
+    "meta/schemas/physical_device-0bd5d21f.json",
+    "meta/schemas/product_bundle-6320eef1.json",
+    "meta/schemas/sysroot.json",
+    "meta/schemas/version_history.json"
   ],
   "name": "metadata_schemas",
   "type": "documentation"
diff --git a/lib/fuchsia/meta/manifest.json b/lib/fuchsia/meta/manifest.json
index cf3f731..abe021c 100644
--- a/lib/fuchsia/meta/manifest.json
+++ b/lib/fuchsia/meta/manifest.json
@@ -8,6 +8,10 @@
   "id": "",
   "parts": [
     {
+      "meta": "docs/firmware.json",
+      "type": "documentation"
+    },
+    {
       "meta": "docs/metadata_schemas.json",
       "type": "documentation"
     },
diff --git a/lib/fuchsia/meta/schemas/cc_prebuilt_library.json b/lib/fuchsia/meta/schemas/cc_prebuilt_library.json
index 9a72c8e..0e8567e 100644
--- a/lib/fuchsia/meta/schemas/cc_prebuilt_library.json
+++ b/lib/fuchsia/meta/schemas/cc_prebuilt_library.json
@@ -1,117 +1,116 @@
 {
-  "$schema": "http://json-schema.org/draft-04/schema#",
-  "id": "http://fuchsia.com/schemas/sdk/cc_prebuilt_library.json",
-  "description": "A prebuilt C/C++ library",
-  "type": "object",
-  "allOf": [
-    {
-      "$ref": "common.json#/definitions/sdk_element"
+    "$schema": "http://json-schema.org/draft-04/schema#",
+    "allOf": [
+        {
+            "$ref": "common.json#/definitions/sdk_element"
+        },
+        {
+            "additionalProperties": false,
+            "properties": {
+                "binaries": {
+                    "additionalProperties": false,
+                    "description": "The binary files for the library, per architecture",
+                    "maxProperties": 2,
+                    "minProperties": 1,
+                    "properties": {
+                        "arm64": {
+                            "$ref": "#/definitions/binaryGroup",
+                            "description": "Binaries for the arm64 architecture"
+                        },
+                        "x64": {
+                            "$ref": "#/definitions/binaryGroup",
+                            "description": "Binaries for the x64 architecture"
+                        }
+                    },
+                    "type": "object"
+                },
+                "deps": {
+                    "description": "List of C/C++ libraries this library depends on",
+                    "items": {
+                        "$ref": "common.json#/definitions/cc_library_name"
+                    },
+                    "type": "array"
+                },
+                "format": {
+                    "description": "The distribution format of the binaries",
+                    "enum": [
+                        "shared",
+                        "static"
+                    ],
+                    "type": "string"
+                },
+                "headers": {
+                    "description": "List of public headers",
+                    "items": {
+                        "$ref": "common.json#/definitions/file"
+                    },
+                    "type": "array"
+                },
+                "include_dir": {
+                    "$ref": "common.json#/definitions/file",
+                    "description": "Path to the base directory for includes"
+                },
+                "name": {
+                    "$ref": "common.json#/definitions/cc_library_name",
+                    "description": "Name of the library"
+                },
+                "root": {
+                    "description": "The root of the element in the SDK",
+                    "type": "string"
+                },
+                "type": {
+                    "allOf": [
+                        {
+                            "$ref": "common.json#/definitions/kind"
+                        },
+                        {
+                            "enum": [
+                                "cc_prebuilt_library"
+                            ]
+                        }
+                    ]
+                }
+            },
+            "required": [
+                "binaries",
+                "deps",
+                "format",
+                "headers",
+                "include_dir",
+                "root",
+                "name",
+                "type"
+            ]
+        }
+    ],
+    "definitions": {
+        "binaryGroup": {
+            "description": "A set of binary files compiled for a given architecture",
+            "properties": {
+                "debug": {
+                    "$ref": "common.json#/definitions/file",
+                    "description": "The unstripped version of the library"
+                },
+                "dist": {
+                    "$ref": "common.json#/definitions/file",
+                    "description": "The version of the library to add to Fuchsia packages"
+                },
+                "dist_path": {
+                    "$ref": "common.json#/definitions/file",
+                    "description": "Path where the library should be installed in Fuchsia packages"
+                },
+                "link": {
+                    "$ref": "common.json#/definitions/file",
+                    "description": "The link-time version of the library"
+                }
+            },
+            "required": [
+                "link"
+            ],
+            "type": "object"
+        }
     },
-    {
-      "properties": {
-        "type": {
-          "allOf": [
-            {
-              "$ref": "common.json#/definitions/type"
-            },
-            {
-              "enum": [
-                "cc_prebuilt_library"
-              ]
-            }
-          ]
-        },
-        "name": {
-          "description": "Name of the library",
-          "$ref": "common.json#/definitions/cc_library_name"
-        },
-        "root": {
-          "description": "The root of the element in the SDK",
-          "type": "string"
-        },
-        "format": {
-          "description": "The distribution format of the binaries",
-          "type": "string",
-          "enum": [
-            "shared",
-            "static"
-          ]
-        },
-        "headers": {
-          "description": "List of public headers",
-          "type": "array",
-          "items": {
-            "$ref": "common.json#/definitions/file"
-          }
-        },
-        "include_dir": {
-          "description": "Path to the base directory for includes",
-          "$ref": "common.json#/definitions/file"
-        },
-        "deps": {
-          "description": "List of C/C++ libraries this library depends on",
-          "type": "array",
-          "items": {
-            "$ref": "common.json#/definitions/cc_library_name"
-          }
-        },
-        "binaries": {
-          "description": "The binary files for the library, per architecture",
-          "type": "object",
-          "properties": {
-            "x64": {
-              "description": "Binaries for the x64 architecture",
-              "$ref": "#/definitions/binaryGroup"
-            },
-            "arm64": {
-              "description": "Binaries for the arm64 architecture",
-              "$ref": "#/definitions/binaryGroup"
-            }
-          },
-          "additionalProperties": false,
-          "minProperties": 1,
-          "maxProperties": 2
-        }
-      },
-      "required": [
-        "binaries",
-        "deps",
-        "format",
-        "headers",
-        "include_dir",
-        "root",
-
-        "name",
-        "type"
-      ],
-      "additionalProperties": false
-    }
-  ],
-  "definitions": {
-    "binaryGroup": {
-      "description": "A set of binary files compiled for a given architecture",
-      "type": "object",
-      "properties": {
-        "link": {
-          "description": "The link-time version of the library",
-          "$ref": "common.json#/definitions/file"
-        },
-        "dist": {
-          "description": "The version of the library to add to Fuchsia packages",
-          "$ref": "common.json#/definitions/file"
-        },
-        "dist_path": {
-          "description": "Path where the library should be installed in Fuchsia packages",
-          "$ref": "common.json#/definitions/file"
-        },
-        "debug": {
-          "description": "The unstripped version of the library",
-          "$ref": "common.json#/definitions/file"
-        }
-      },
-      "required": [
-        "link"
-      ]
-    }
-  }
+    "description": "A prebuilt C/C++ library",
+    "id": "http://fuchsia.com/schemas/sdk/cc_prebuilt_library.json",
+    "type": "object"
 }
diff --git a/lib/fuchsia/meta/schemas/cc_source_library.json b/lib/fuchsia/meta/schemas/cc_source_library.json
index 36ceb11..28b5cdb 100644
--- a/lib/fuchsia/meta/schemas/cc_source_library.json
+++ b/lib/fuchsia/meta/schemas/cc_source_library.json
@@ -1,88 +1,87 @@
 {
-  "$schema": "http://json-schema.org/draft-04/schema#",
-  "id": "http://fuchsia.com/schemas/sdk/cc_source_library.json",
-  "description": "A set of C/C++ sources",
-  "type": "object",
-  "allOf": [
-    {
-      "$ref": "common.json#/definitions/sdk_element"
-    },
-    {
-      "properties": {
-        "type": {
-          "allOf": [
-            {
-              "$ref": "common.json#/definitions/type"
+    "$schema": "http://json-schema.org/draft-04/schema#",
+    "allOf": [
+        {
+            "$ref": "common.json#/definitions/sdk_element"
+        },
+        {
+            "additionalProperties": false,
+            "properties": {
+                "banjo_deps": {
+                    "description": "List of BANJO libraries this library depends on",
+                    "items": {
+                        "$ref": "common.json#/definitions/banjo_library_name"
+                    },
+                    "type": "array"
+                },
+                "deps": {
+                    "description": "List of C/C++ libraries this library depends on",
+                    "items": {
+                        "$ref": "common.json#/definitions/cc_library_name"
+                    },
+                    "type": "array"
+                },
+                "fidl_deps": {
+                    "description": "List of FIDL libraries this library depends on",
+                    "items": {
+                        "$ref": "common.json#/definitions/fidl_library_name"
+                    },
+                    "type": "array"
+                },
+                "headers": {
+                    "description": "List of public headers",
+                    "items": {
+                        "$ref": "common.json#/definitions/file"
+                    },
+                    "minItems": 1,
+                    "type": "array"
+                },
+                "include_dir": {
+                    "$ref": "common.json#/definitions/file",
+                    "description": "Path to the base directory for includes"
+                },
+                "name": {
+                    "$ref": "common.json#/definitions/cc_library_name",
+                    "description": "Name of the library"
+                },
+                "root": {
+                    "description": "The root of the element in the SDK",
+                    "type": "string"
+                },
+                "sources": {
+                    "description": "List of library sources",
+                    "items": {
+                        "$ref": "common.json#/definitions/file"
+                    },
+                    "type": "array"
+                },
+                "type": {
+                    "allOf": [
+                        {
+                            "$ref": "common.json#/definitions/kind"
+                        },
+                        {
+                            "enum": [
+                                "cc_source_library"
+                            ]
+                        }
+                    ]
+                }
             },
-            {
-              "enum": [
-                "cc_source_library"
-              ]
-            }
-          ]
-        },
-        "name": {
-          "description": "Name of the library",
-          "$ref": "common.json#/definitions/cc_library_name"
-        },
-        "root": {
-          "description": "The root of the element in the SDK",
-          "type": "string"
-        },
-        "sources": {
-          "description": "List of library sources",
-          "type": "array",
-          "items": {
-            "$ref": "common.json#/definitions/file"
-          }
-        },
-        "headers": {
-          "description": "List of public headers",
-          "type": "array",
-          "minItems": 1,
-          "items": {
-            "$ref": "common.json#/definitions/file"
-          }
-        },
-        "include_dir": {
-          "description": "Path to the base directory for includes",
-          "$ref": "common.json#/definitions/file"
-        },
-        "deps": {
-          "description": "List of C/C++ libraries this library depends on",
-          "type": "array",
-          "items": {
-            "$ref": "common.json#/definitions/cc_library_name"
-          }
-        },
-        "fidl_deps": {
-          "description": "List of FIDL libraries this library depends on",
-          "type": "array",
-          "items": {
-            "$ref": "common.json#/definitions/fidl_library_name"
-          }
-        },
-        "banjo_deps": {
-          "description": "List of BANJO libraries this library depends on",
-          "type": "array",
-          "items": {
-            "$ref": "common.json#/definitions/banjo_library_name"
-          }
+            "required": [
+                "banjo_deps",
+                "deps",
+                "fidl_deps",
+                "headers",
+                "include_dir",
+                "root",
+                "sources",
+                "name",
+                "type"
+            ]
         }
-      },
-      "required": [
-        "banjo_deps",
-        "deps",
-        "fidl_deps",
-        "headers",
-        "include_dir",
-        "root",
-        "sources",
-
-        "name",
-        "type"
-      ],
-      "additionalProperties": false
-    }
-  ]
+    ],
+    "description": "A set of C/C++ sources",
+    "id": "http://fuchsia.com/schemas/sdk/cc_source_library.json",
+    "type": "object"
 }
diff --git a/lib/fuchsia/meta/schemas/common.json b/lib/fuchsia/meta/schemas/common.json
index b02b160..d4e15bc 100644
--- a/lib/fuchsia/meta/schemas/common.json
+++ b/lib/fuchsia/meta/schemas/common.json
@@ -1,52 +1,135 @@
 {
-  "$schema": "http://json-schema.org/draft-04/schema#",
-  "id": "http://fuchsia.com/schemas/sdk/common.json",
-  "definitions": {
-    "file": {
-      "description": "Path to a file from the root of the SDK",
-      "type": "string"
-    },
-    "type": {
-      "description": "Represents the type of an SDK element",
-      "type": "string"
-    },
-    "sdk_element": {
-      "description": "Base type for SDK elements",
-      "type": "object",
-      "properties": {
-        "type": {
-          "description": "The type of the element",
-          "$ref": "#/definitions/type"
+    "$schema": "http://json-schema.org/draft-07/schema#",
+    "definitions": {
+        "banjo_library_name": {
+            "description": "Name of a BANJO library",
+            "type": "string"
         },
-        "name": {
-          "description": "The name of the element",
-          "type": "string"
+        "cc_library_name": {
+            "description": "Name of a C/C++ library",
+            "type": "string"
+        },
+        "envelope": {
+            "additionalProperties": false,
+            "description": "A versioned envelope.",
+            "properties": {
+                "data": {
+                    "description": "The payload."
+                },
+                "schema_id": {
+                    "description": "The value of the '$id' property of the schema that constraints this JSON document.",
+                    "minLength": 1,
+                    "type": "string"
+                }
+            },
+            "required": [
+                "data",
+                "schema_id"
+            ],
+            "type": "object"
+        },
+        "fidl_library_name": {
+            "description": "Name of a FIDL library",
+            "type": "string"
+        },
+        "file": {
+            "description": "Path to a file from the root of the SDK",
+            "type": "string"
+        },
+        "key_value": {
+            "additionalItems": false,
+            "description": "A key-value pair.",
+            "items": [
+                {
+                    "type": "string"
+                },
+                {
+                    "type": [
+                        "number",
+                        "string",
+                        "boolean"
+                    ]
+                }
+            ],
+            "minItems": 2,
+            "type": "array"
+        },
+        "key_value_list": {
+            "description": "A list of key-value pairs.",
+            "items": {
+                "$ref": "#/definitions/key_value"
+            },
+            "type": "array"
+        },
+        "kind": {
+            "description": "Represents the type of an SDK element",
+            "type": "string"
+        },
+        "sdk_element": {
+            "description": "Base type for SDK elements",
+            "properties": {
+                "name": {
+                    "description": "The name of the element",
+                    "type": "string"
+                },
+                "type": {
+                    "$ref": "#/definitions/kind"
+                }
+            },
+            "required": [
+                "name",
+                "type"
+            ],
+            "type": "object"
+        },
+        "target_arch": {
+            "description": "Target architecture",
+            "enum": [
+                "arm64",
+                "x64"
+            ],
+            "type": "string"
+        },
+        "version": {
+            "description": "An opaque version string. The string may include any characters. Tools must not attempt to draw any conclusions about inter version compatibility other than the version 'X' manifest complies with the version 'X' of the schema and is therefore parsable by the version 'X' parser. There are no guarantees, for example, a parser for version 'B' may be able to parse a JSON document versioned 'A'.",
+            "minLength": 1,
+            "type": "string"
+        },
+        "versioned_sdk_element": {
+            "allOf": [
+                {
+                    "$ref": "#/definitions/envelope"
+                },
+                {
+                    "properties": {
+                        "data": {
+                            "description": "Base type for SDK elements",
+                            "properties": {
+                                "description": {
+                                    "description": "A human readable description of the SDK element.",
+                                    "maxLength": 1024,
+                                    "type": "string"
+                                },
+                                "name": {
+                                    "description": "The name of the element",
+                                    "type": "string"
+                                },
+                                "type": {
+                                    "$ref": "#/definitions/kind"
+                                }
+                            },
+                            "required": [
+                                "type",
+                                "name"
+                            ],
+                            "type": "object"
+                        }
+                    },
+                    "type": "object"
+                }
+            ],
+            "type": "object"
         }
-      },
-      "required": [
-        "name",
-        "type"
-      ]
     },
-    "banjo_library_name": {
-      "description": "Name of a BANJO library",
-      "type": "string"
-    },
-    "fidl_library_name": {
-      "description": "Name of a FIDL library",
-      "type": "string"
-    },
-    "cc_library_name": {
-      "description": "Name of a C/C++ library",
-      "type": "string"
-    },
-    "target_arch": {
-      "description": "Target architecture",
-      "type": "string",
-      "enum": [
-        "arm64",
-        "x64"
-      ]
-    }
-  }
+    "id": "http://fuchsia.com/schemas/sdk/common.json"
 }
diff --git a/lib/fuchsia/meta/schemas/dart_library.json b/lib/fuchsia/meta/schemas/dart_library.json
index e91ac63..176a67f 100644
--- a/lib/fuchsia/meta/schemas/dart_library.json
+++ b/lib/fuchsia/meta/schemas/dart_library.json
@@ -1,104 +1,103 @@
 {
-  "$schema": "http://json-schema.org/draft-04/schema#",
-  "id": "http://fuchsia.com/schemas/sdk/dart_library.json",
-  "description": "A Dart library",
-  "type": "object",
-  "allOf": [
-    {
-      "$ref": "common.json#/definitions/sdk_element"
-    },
-    {
-      "properties": {
-        "type": {
-          "allOf": [
-            {
-              "$ref": "common.json#/definitions/type"
+    "$schema": "http://json-schema.org/draft-04/schema#",
+    "allOf": [
+        {
+            "$ref": "common.json#/definitions/sdk_element"
+        },
+        {
+            "additionalProperties": false,
+            "properties": {
+                "dart_library_null_safe": {
+                    "default": false,
+                    "description": "A flag that enables null safety checks in a dart library",
+                    "type": "boolean"
+                },
+                "deps": {
+                    "description": "List of Dart libraries this library depends on",
+                    "items": {
+                        "$ref": "#/definitions/package_name"
+                    },
+                    "type": "array"
+                },
+                "fidl_deps": {
+                    "description": "List of FIDL libraries this library depends on",
+                    "items": {
+                        "$ref": "common.json#/definitions/fidl_library_name"
+                    },
+                    "type": "array"
+                },
+                "name": {
+                    "$ref": "#/definitions/package_name",
+                    "description": "Name of the library"
+                },
+                "root": {
+                    "$ref": "common.json#/definitions/file",
+                    "description": "The root of the element in the SDK"
+                },
+                "sources": {
+                    "description": "List of library sources",
+                    "items": {
+                        "$ref": "common.json#/definitions/file"
+                    },
+                    "minItems": 1,
+                    "type": "array"
+                },
+                "third_party_deps": {
+                    "description": "List of third-party dependencies",
+                    "items": {
+                        "$ref": "#/definitions/third_party_library"
+                    },
+                    "type": "array"
+                },
+                "type": {
+                    "allOf": [
+                        {
+                            "$ref": "common.json#/definitions/kind"
+                        },
+                        {
+                            "enum": [
+                                "dart_library"
+                            ]
+                        }
+                    ]
+                }
             },
-            {
-              "enum": [
-                "dart_library"
-              ]
-            }
-          ]
-        },
-        "dart_library_null_safe": {
-          "description": "A flag that enables null safety checks in a dart library",
-          "type": "boolean",
-          "default": false
-        },
-        "name": {
-          "description": "Name of the library",
-          "$ref": "#/definitions/package_name"
-        },
-        "root": {
-          "description": "The root of the element in the SDK",
-          "$ref": "common.json#/definitions/file"
-        },
-        "sources": {
-          "description": "List of library sources",
-          "type": "array",
-          "minItems": 1,
-          "items": {
-            "$ref": "common.json#/definitions/file"
-          }
-        },
-        "deps": {
-          "description": "List of Dart libraries this library depends on",
-          "type": "array",
-          "items": {
-            "$ref": "#/definitions/package_name"
-          }
-        },
-        "third_party_deps": {
-          "description": "List of third-party dependencies",
-          "type": "array",
-          "items": {
-            "$ref": "#/definitions/third_party_library"
-          }
-        },
-        "fidl_deps": {
-          "description": "List of FIDL libraries this library depends on",
-          "type": "array",
-          "items": {
-            "$ref": "common.json#/definitions/fidl_library_name"
-          }
+            "required": [
+                "deps",
+                "fidl_deps",
+                "root",
+                "sources",
+                "third_party_deps",
+                "name",
+                "type"
+            ]
         }
-      },
-      "required": [
-        "deps",
-        "fidl_deps",
-        "root",
-        "sources",
-        "third_party_deps",
-        "name",
-        "type"
-      ],
-      "additionalProperties": false
-    }
-  ],
-  "definitions": {
-    "package_name": {
-      "description": "A Dart package name",
-      "type": "string"
+    ],
+    "definitions": {
+        "package_name": {
+            "description": "A Dart package name",
+            "type": "string"
+        },
+        "third_party_library": {
+            "description": "A third-party Dart package",
+            "properties": {
+                "name": {
+                    "$ref": "#/definitions/package_name",
+                    "description": "Name of the package"
+                },
+                "version": {
+                    "description": "Version number of the package",
+                    "type": "string"
+                }
+            },
+            "required": [
+                "name",
+                "version"
+            ],
+            "type": "object"
+        }
     },
-    "third_party_library": {
-      "description": "A third-party Dart package",
-      "type": "object",
-      "properties": {
-        "name": {
-          "description": "Name of the package",
-          "$ref": "#/definitions/package_name"
-        },
-        "version": {
-          "description": "Version number of the package",
-          "type": "string"
-        }
-      },
-      "required": [
-        "name",
-        "version"
-      ]
-    }
-  }
+    "description": "A Dart library",
+    "id": "http://fuchsia.com/schemas/sdk/dart_library.json",
+    "type": "object"
 }
-
diff --git a/lib/fuchsia/meta/schemas/data.json b/lib/fuchsia/meta/schemas/data.json
index 1afbddb..dcb0b1d 100644
--- a/lib/fuchsia/meta/schemas/data.json
+++ b/lib/fuchsia/meta/schemas/data.json
@@ -1,47 +1,47 @@
 {
-  "$schema": "http://json-schema.org/draft-04/schema#",
-  "id": "http://fuchsia.com/schemas/sdk/documentation.json",
-  "description": "A set of data files",
-  "type": "object",
-  "allOf": [
-    {
-      "$ref": "common.json#/definitions/sdk_element"
-    },
-    {
-      "properties": {
-        "type": {
-          "allOf": [
-            {
-              "$ref": "common.json#/definitions/type"
+    "$schema": "http://json-schema.org/draft-04/schema#",
+    "allOf": [
+        {
+            "$ref": "common.json#/definitions/sdk_element"
+        },
+        {
+            "additionalProperties": false,
+            "properties": {
+                "data": {
+                    "description": "The list of data files pertaining to the set",
+                    "items": {
+                        "$ref": "common.json#/definitions/file"
+                    },
+                    "minItems": 1,
+                    "type": "array"
+                },
+                "name": {
+                    "description": "Name of the data set",
+                    "type": "string"
+                },
+                "type": {
+                    "allOf": [
+                        {
+                            "$ref": "common.json#/definitions/kind"
+                        },
+                        {
+                            "enum": [
+                                "component_manifest",
+                                "config",
+                                "license"
+                            ]
+                        }
+                    ]
+                }
             },
-            {
-              "enum": [
-                "config",
-                "license"
-              ]
-            }
-          ]
-        },
-        "name": {
-          "description": "Name of the data set",
-          "type": "string"
-        },
-        "data": {
-          "description": "The list of data files pertaining to the set",
-          "type": "array",
-          "minItems": 1,
-          "items": {
-            "$ref": "common.json#/definitions/file"
-          }
+            "required": [
+                "data",
+                "name",
+                "type"
+            ]
         }
-      },
-      "required": [
-        "data",
-
-        "name",
-        "type"
-      ],
-      "additionalProperties": false
-    }
-  ]
+    ],
+    "description": "A set of data files",
+    "id": "http://fuchsia.com/schemas/sdk/documentation.json",
+    "type": "object"
 }
diff --git a/lib/fuchsia/meta/schemas/documentation.json b/lib/fuchsia/meta/schemas/documentation.json
index 040ccd6..4478e3c 100644
--- a/lib/fuchsia/meta/schemas/documentation.json
+++ b/lib/fuchsia/meta/schemas/documentation.json
@@ -1,46 +1,45 @@
 {
-  "$schema": "http://json-schema.org/draft-04/schema#",
-  "id": "http://fuchsia.com/schemas/sdk/documentation.json",
-  "description": "A set of documents",
-  "type": "object",
-  "allOf": [
-    {
-      "$ref": "common.json#/definitions/sdk_element"
-    },
-    {
-      "properties": {
-        "type": {
-          "allOf": [
-            {
-              "$ref": "common.json#/definitions/type"
+    "$schema": "http://json-schema.org/draft-04/schema#",
+    "allOf": [
+        {
+            "$ref": "common.json#/definitions/sdk_element"
+        },
+        {
+            "additionalProperties": false,
+            "properties": {
+                "docs": {
+                    "description": "The list of documents pertaining to the set",
+                    "items": {
+                        "$ref": "common.json#/definitions/file"
+                    },
+                    "minItems": 1,
+                    "type": "array"
+                },
+                "name": {
+                    "description": "Name of the document set",
+                    "type": "string"
+                },
+                "type": {
+                    "allOf": [
+                        {
+                            "$ref": "common.json#/definitions/kind"
+                        },
+                        {
+                            "enum": [
+                                "documentation"
+                            ]
+                        }
+                    ]
+                }
             },
-            {
-              "enum": [
-                "documentation"
-              ]
-            }
-          ]
-        },
-        "name": {
-          "description": "Name of the document set",
-          "type": "string"
-        },
-        "docs": {
-          "description": "The list of documents pertaining to the set",
-          "type": "array",
-          "minItems": 1,
-          "items": {
-            "$ref": "common.json#/definitions/file"
-          }
+            "required": [
+                "docs",
+                "name",
+                "type"
+            ]
         }
-      },
-      "required": [
-        "docs",
-
-        "name",
-        "type"
-      ],
-      "additionalProperties": false
-    }
-  ]
+    ],
+    "description": "A set of documents",
+    "id": "http://fuchsia.com/schemas/sdk/documentation.json",
+    "type": "object"
 }
diff --git a/lib/fuchsia/meta/schemas/emu_manifest.json b/lib/fuchsia/meta/schemas/emu_manifest.json
new file mode 100644
index 0000000..5c3657f
--- /dev/null
+++ b/lib/fuchsia/meta/schemas/emu_manifest.json
@@ -0,0 +1,37 @@
+{
+    "$schema": "http://json-schema.org/draft-07/schema#",
+    "definitions": {
+        "manifest": {
+            "additionalProperties": false,
+            "description": "A manifest that describes how to boot an emulator.",
+            "properties": {
+                "disk_images": {
+                    "description": "A list of one or more disk image paths to FVM images. Each path is relative to the image bundle base.",
+                    "items": {
+                        "minLength": 1,
+                        "type": "string"
+                    },
+                    "minItems": 1,
+                    "type": "array"
+                },
+                "initial_ramdisk": {
+                    "description": "A path to the initial ramdisk, the kernel ZBI. The path is relative to the image bundle base.",
+                    "minLength": 1,
+                    "type": "string"
+                },
+                "kernel": {
+                    "description": "A path to the kernel image file. The path is relative to the image bundle base.",
+                    "minLength": 1,
+                    "type": "string"
+                }
+            },
+            "required": [
+                "kernel",
+                "initial_ramdisk",
+                "disk_images"
+            ],
+            "type": "object"
+        }
+    },
+    "id": "http://fuchsia.com/schemas/sdk/emu_manifest.json"
+}
diff --git a/lib/fuchsia/meta/schemas/fidl_library.json b/lib/fuchsia/meta/schemas/fidl_library.json
index eec1fe3..26de25f 100644
--- a/lib/fuchsia/meta/schemas/fidl_library.json
+++ b/lib/fuchsia/meta/schemas/fidl_library.json
@@ -1,59 +1,58 @@
 {
-  "$schema": "http://json-schema.org/draft-04/schema#",
-  "id": "http://fuchsia.com/schemas/sdk/fidl_library.json",
-  "description": "A FIDL library",
-  "type": "object",
-  "allOf": [
-    {
-      "$ref": "common.json#/definitions/sdk_element"
-    },
-    {
-      "properties": {
-        "type": {
-          "allOf": [
-            {
-              "$ref": "common.json#/definitions/type"
+    "$schema": "http://json-schema.org/draft-04/schema#",
+    "allOf": [
+        {
+            "$ref": "common.json#/definitions/sdk_element"
+        },
+        {
+            "additionalProperties": false,
+            "properties": {
+                "deps": {
+                    "description": "List of libraries this library depends on",
+                    "items": {
+                        "$ref": "common.json#/definitions/fidl_library_name"
+                    },
+                    "type": "array"
+                },
+                "name": {
+                    "$ref": "common.json#/definitions/fidl_library_name",
+                    "description": "Name of the library"
+                },
+                "root": {
+                    "description": "The root of the element in the SDK",
+                    "type": "string"
+                },
+                "sources": {
+                    "description": "List of library sources",
+                    "items": {
+                        "$ref": "common.json#/definitions/file"
+                    },
+                    "minItems": 1,
+                    "type": "array"
+                },
+                "type": {
+                    "allOf": [
+                        {
+                            "$ref": "common.json#/definitions/kind"
+                        },
+                        {
+                            "enum": [
+                                "fidl_library"
+                            ]
+                        }
+                    ]
+                }
             },
-            {
-              "enum": [
-                "fidl_library"
-              ]
-            }
-          ]
-        },
-        "name": {
-          "description": "Name of the library",
-          "$ref": "common.json#/definitions/fidl_library_name"
-        },
-        "root": {
-          "description": "The root of the element in the SDK",
-          "type": "string"
-        },
-        "sources": {
-          "description": "List of library sources",
-          "type": "array",
-          "minItems": 1,
-          "items": {
-            "$ref": "common.json#/definitions/file"
-          }
-        },
-        "deps": {
-          "description": "List of libraries this library depends on",
-          "type": "array",
-          "items": {
-            "$ref": "common.json#/definitions/fidl_library_name"
-          }
+            "required": [
+                "deps",
+                "root",
+                "sources",
+                "name",
+                "type"
+            ]
         }
-      },
-      "required": [
-        "deps",
-        "root",
-        "sources",
-
-        "name",
-        "type"
-      ],
-      "additionalProperties": false
-    }
-  ]
+    ],
+    "description": "A FIDL library",
+    "id": "http://fuchsia.com/schemas/sdk/fidl_library.json",
+    "type": "object"
 }
diff --git a/lib/fuchsia/meta/schemas/flash_manifest-835e8f26.json b/lib/fuchsia/meta/schemas/flash_manifest-835e8f26.json
new file mode 100644
index 0000000..8413ac4
--- /dev/null
+++ b/lib/fuchsia/meta/schemas/flash_manifest-835e8f26.json
@@ -0,0 +1,135 @@
+{
+    "$schema": "http://json-schema.org/draft-07/schema#",
+    "additionalProperties": false,
+    "definitions": {
+        "condition": {
+            "additionalProperties": false,
+            "description": "A condition that must be true for a partition to be flashed.",
+            "properties": {
+                "value": {
+                    "description": "The value of the variable that must match for this condition to be true.",
+                    "type": "string"
+                },
+                "variable": {
+                    "description": "A variable name to check on a target device.",
+                    "type": "string"
+                }
+            },
+            "required": [
+                "variable",
+                "value"
+            ],
+            "type": "object"
+        },
+        "manifest": {
+            "additionalProperties": false,
+            "description": "A named list of partitions and OEM files necessary to flash a device.",
+            "properties": {
+                "hw_revision": {
+                    "description": "A board name used to verify whether the device can be flashed using this manifest.",
+                    "type": "string"
+                },
+                "products": {
+                    "description": "A list of product specifications that can be flashed onto the device.",
+                    "items": {
+                        "$ref": "#/definitions/product"
+                    },
+                    "minItems": 1,
+                    "type": "array"
+                }
+            },
+            "required": [
+                "hw_revision",
+                "products"
+            ],
+            "type": "object"
+        },
+        "oem_file": {
+            "additionalProperties": false,
+            "description": "A OEM file that is uploaded followed by a given OEM command.",
+            "properties": {
+                "command": {
+                    "type": "string"
+                },
+                "path": {
+                    "type": "string"
+                }
+            },
+            "required": [
+                "path",
+                "command"
+            ],
+            "type": "object"
+        },
+        "partition": {
+            "additionalProperties": false,
+            "description": "A condition that must be true for a partition to be flashed.",
+            "properties": {
+                "condition": {
+                    "$ref": "#/definitions/condition"
+                },
+                "name": {
+                    "type": "string"
+                },
+                "path": {
+                    "type": "string"
+                }
+            },
+            "required": [
+                "name",
+                "path"
+            ],
+            "type": "object"
+        },
+        "product": {
+            "additionalProperties": false,
+            "description": "A named product specification.",
+            "properties": {
+                "bootloader_partitions": {
+                    "description": "A list of partition names and file names corresponding to the partitions.",
+                    "items": {
+                        "$ref": "#/definitions/partition"
+                    },
+                    "type": "array"
+                },
+                "name": {
+                    "description": "A unique name of this manifest.",
+                    "type": "string"
+                },
+                "oem_files": {
+                    "description": "A list of OEM command and file names corresponding to the command.",
+                    "items": {
+                        "$ref": "#/definitions/oem_file"
+                    },
+                    "type": "array"
+                },
+                "partitions": {
+                    "description": "A list of partition names and file names corresponding to the partitions.",
+                    "items": {
+                        "$ref": "#/definitions/partition"
+                    },
+                    "type": "array"
+                }
+            },
+            "required": [
+                "name"
+            ],
+            "type": "object"
+        }
+    },
+    "description": "A manifest that describes how to flash a device.",
+    "id": "http://fuchsia.com/schemas/sdk/flash_manifest-835e8f26.json",
+    "properties": {
+        "manifest": {
+            "$ref": "#/definitions/manifest"
+        },
+        "version": {
+            "$ref": "common.json#/definitions/version"
+        }
+    },
+    "required": [
+        "version",
+        "manifest"
+    ],
+    "type": "object"
+}
diff --git a/lib/fuchsia/meta/schemas/hardware-f6f47515.json b/lib/fuchsia/meta/schemas/hardware-f6f47515.json
new file mode 100644
index 0000000..b85c7a7
--- /dev/null
+++ b/lib/fuchsia/meta/schemas/hardware-f6f47515.json
@@ -0,0 +1,41 @@
+{
+    "$schema": "http://json-schema.org/draft-07/schema#",
+    "definitions": {
+        "requirements": {
+            "properties": {
+                "hardware": {
+                    "additionalProperties": false,
+                    "properties": {
+                        "cpu": {
+                            "additionalProperties": false,
+                            "properties": {
+                                "arch": {
+                                    "type": "string"
+                                }
+                            },
+                            "required": [
+                                "arch"
+                            ],
+                            "type": "object"
+                        }
+                    },
+                    "required": [
+                        "cpu"
+                    ],
+                    "type": "object"
+                }
+            },
+            "required": [
+                "hardware"
+            ],
+            "type": "object"
+        }
+    },
+    "description": "Hardware requirements for running a product image.",
+    "id": "http://fuchsia.com/schemas/sdk/hardware-f6f47515.json",
+    "oneOf": [
+        {
+            "$ref": "#/definitions/requirements"
+        }
+    ]
+}
diff --git a/lib/fuchsia/meta/schemas/host_tool.json b/lib/fuchsia/meta/schemas/host_tool.json
index 97c9cc3..00b9e4c 100644
--- a/lib/fuchsia/meta/schemas/host_tool.json
+++ b/lib/fuchsia/meta/schemas/host_tool.json
@@ -1,72 +1,71 @@
 {
-  "$schema": "http://json-schema.org/draft-04/schema#",
-  "id": "http://fuchsia.com/schemas/sdk/host_tool.json",
-  "description": "A host tool",
-  "type": "object",
-  "allOf": [
-    {
-      "$ref": "common.json#/definitions/sdk_element"
-    },
-    {
-      "properties": {
-        "type": {
-          "allOf": [
-            {
-              "$ref": "common.json#/definitions/type"
+    "$schema": "http://json-schema.org/draft-04/schema#",
+    "allOf": [
+        {
+            "$ref": "common.json#/definitions/sdk_element"
+        },
+        {
+            "additionalProperties": false,
+            "properties": {
+                "files": {
+                    "$ref": "#/definitions/fileGroup",
+                    "description": "The list of files pertaining to the element"
+                },
+                "name": {
+                    "description": "Name of the tool",
+                    "type": "string"
+                },
+                "root": {
+                    "description": "The root of the element in the SDK",
+                    "type": "string"
+                },
+                "target_files": {
+                    "additionalProperties": false,
+                    "description": "The target-specific files, per architecture",
+                    "maxProperties": 2,
+                    "minProperties": 1,
+                    "properties": {
+                        "arm64": {
+                            "$ref": "#/definitions/fileGroup",
+                            "description": "Files for the arm64 architecture"
+                        },
+                        "x64": {
+                            "$ref": "#/definitions/fileGroup",
+                            "description": "Files for the x64 architecture"
+                        }
+                    },
+                    "type": "object"
+                },
+                "type": {
+                    "allOf": [
+                        {
+                            "$ref": "common.json#/definitions/kind"
+                        },
+                        {
+                            "enum": [
+                                "host_tool"
+                            ]
+                        }
+                    ]
+                }
             },
-            {
-              "enum": [
-                "host_tool"
-              ]
-            }
-          ]
-        },
-        "name": {
-          "description": "Name of the tool",
-          "type": "string"
-        },
-        "root": {
-          "description": "The root of the element in the SDK",
-          "type": "string"
-        },
-        "files": {
-          "description": "The list of files pertaining to the element",
-          "$ref": "#/definitions/fileGroup"
-        },
-        "target_files": {
-          "description": "The target-specific files, per architecture",
-          "type": "object",
-          "properties": {
-            "x64": {
-              "description": "Files for the x64 architecture",
-              "$ref": "#/definitions/fileGroup"
-            },
-            "arm64": {
-              "description": "Files for the arm64 architecture",
-              "$ref": "#/definitions/fileGroup"
-            }
-          },
-          "additionalProperties": false,
-          "minProperties": 1,
-          "maxProperties": 2
+            "required": [
+                "root",
+                "name",
+                "type"
+            ]
         }
-      },
-      "required": [
-        "root",
-
-        "name",
-        "type"
-      ],
-      "additionalProperties": false
-    }
-  ],
-  "definitions": {
-    "fileGroup": {
-      "description": "A collection of files",
-      "type": "array",
-      "items": {
-        "$ref": "common.json#/definitions/file"
-      }
-    }
-  }
+    ],
+    "definitions": {
+        "fileGroup": {
+            "description": "A collection of files",
+            "items": {
+                "$ref": "common.json#/definitions/file"
+            },
+            "type": "array"
+        }
+    },
+    "description": "A host tool",
+    "id": "http://fuchsia.com/schemas/sdk/host_tool.json",
+    "type": "object"
 }
diff --git a/lib/fuchsia/meta/schemas/loadable_module.json b/lib/fuchsia/meta/schemas/loadable_module.json
index 308b45c..a0e6e35 100644
--- a/lib/fuchsia/meta/schemas/loadable_module.json
+++ b/lib/fuchsia/meta/schemas/loadable_module.json
@@ -1,76 +1,75 @@
 {
-  "$schema": "http://json-schema.org/draft-04/schema#",
-  "id": "http://fuchsia.com/schemas/sdk/loadable_module.json",
-  "description": "A collection of object files that can be loaded at runtime",
-  "type": "object",
-  "allOf": [
-    {
-      "$ref": "common.json#/definitions/sdk_element"
-    },
-    {
-      "properties": {
-        "type": {
-          "allOf": [
-            {
-              "$ref": "common.json#/definitions/type"
+    "$schema": "http://json-schema.org/draft-04/schema#",
+    "allOf": [
+        {
+            "$ref": "common.json#/definitions/sdk_element"
+        },
+        {
+            "additionalProperties": false,
+            "properties": {
+                "binaries": {
+                    "additionalProperties": false,
+                    "description": "The binary files for the module, per architecture",
+                    "maxProperties": 2,
+                    "minProperties": 1,
+                    "properties": {
+                        "arm64": {
+                            "$ref": "#/definitions/binaryGroup",
+                            "description": "Binaries for the arm64 architecture"
+                        },
+                        "x64": {
+                            "$ref": "#/definitions/binaryGroup",
+                            "description": "Binaries for the x64 architecture"
+                        }
+                    },
+                    "type": "object"
+                },
+                "name": {
+                    "description": "Name of the module",
+                    "type": "string"
+                },
+                "resources": {
+                    "description": "Resource files associated with the module",
+                    "items": {
+                        "$ref": "common.json#/definitions/file"
+                    },
+                    "type": "array"
+                },
+                "root": {
+                    "description": "The root of the element in the SDK",
+                    "type": "string"
+                },
+                "type": {
+                    "allOf": [
+                        {
+                            "$ref": "common.json#/definitions/kind"
+                        },
+                        {
+                            "enum": [
+                                "loadable_module"
+                            ]
+                        }
+                    ]
+                }
             },
-            {
-              "enum": [
-                "loadable_module"
-              ]
-            }
-          ]
-        },
-        "name": {
-          "description": "Name of the module",
-          "type": "string"
-        },
-        "root": {
-          "description": "The root of the element in the SDK",
-          "type": "string"
-        },
-        "resources": {
-          "description": "Resource files associated with the module",
-          "type": "array",
-          "items": {
-            "$ref": "common.json#/definitions/file"
-          }
-        },
-        "binaries": {
-          "description": "The binary files for the module, per architecture",
-          "type": "object",
-          "properties": {
-            "x64": {
-              "description": "Binaries for the x64 architecture",
-              "$ref": "#/definitions/binaryGroup"
-            },
-            "arm64": {
-              "description": "Binaries for the arm64 architecture",
-              "$ref": "#/definitions/binaryGroup"
-            }
-          },
-          "additionalProperties": false,
-          "minProperties": 1,
-          "maxProperties": 2
+            "required": [
+                "binaries",
+                "resources",
+                "name",
+                "type"
+            ]
         }
-      },
-      "required": [
-        "binaries",
-        "resources",
-
-        "name",
-        "type"
-      ],
-      "additionalProperties": false
-    }
-  ],
-  "definitions": {
-    "binaryGroup": {
-      "description": "A set of binary files compiled for a given architecture",
-      "type": "array",
-      "items": {
-        "$ref": "common.json#/definitions/file"
-      }
-    }
-  }
+    ],
+    "definitions": {
+        "binaryGroup": {
+            "description": "A set of binary files compiled for a given architecture",
+            "items": {
+                "$ref": "common.json#/definitions/file"
+            },
+            "type": "array"
+        }
+    },
+    "description": "A collection of object files that can be loaded at runtime",
+    "id": "http://fuchsia.com/schemas/sdk/loadable_module.json",
+    "type": "object"
 }
diff --git a/lib/fuchsia/meta/schemas/manifest.json b/lib/fuchsia/meta/schemas/manifest.json
index 5c3be80..a454ef8 100644
--- a/lib/fuchsia/meta/schemas/manifest.json
+++ b/lib/fuchsia/meta/schemas/manifest.json
@@ -1,68 +1,68 @@
 {
-  "$schema": "http://json-schema.org/draft-04/schema#",
-  "id": "http://fuchsia.com/schemas/sdk/manifest.json",
-  "description": "The manifest describing the contents of the SDK",
-  "type": "object",
-  "properties": {
-    "arch": {
-      "description": "The various architectures encountered in the SDK",
-      "type": "object",
-      "properties": {
-        "host": {
-          "description": "The host architecture",
-          "type": "string"
+    "$schema": "http://json-schema.org/draft-04/schema#",
+    "additionalProperties": false,
+    "description": "The manifest describing the contents of the SDK",
+    "id": "http://fuchsia.com/schemas/sdk/manifest.json",
+    "properties": {
+        "arch": {
+            "additionalProperties": false,
+            "description": "The various architectures encountered in the SDK",
+            "properties": {
+                "host": {
+                    "description": "The host architecture",
+                    "type": "string"
+                },
+                "target": {
+                    "description": "The target architectures",
+                    "items": {
+                        "$ref": "common.json#/definitions/target_arch"
+                    },
+                    "type": "array"
+                }
+            },
+            "required": [
+                "host",
+                "target"
+            ],
+            "type": "object"
         },
-        "target": {
-          "description": "The target architectures",
-          "type": "array",
-          "items": {
-            "$ref": "common.json#/definitions/target_arch"
-          }
+        "id": {
+            "description": "An opaque identifier for this SDK",
+            "type": "string"
+        },
+        "parts": {
+            "description": "The elements in this SDK",
+            "items": {
+                "additionalProperties": false,
+                "properties": {
+                    "meta": {
+                        "$ref": "common.json#/definitions/file",
+                        "description": "The metadata file for the element"
+                    },
+                    "type": {
+                        "$ref": "common.json#/definitions/kind",
+                        "description": "The type of the element"
+                    }
+                },
+                "required": [
+                    "meta",
+                    "type"
+                ],
+                "type": "object"
+            },
+            "minItems": 1,
+            "type": "array"
+        },
+        "schema_version": {
+            "description": "An opaque identifier for metadata schemas in the SDK",
+            "type": "string"
         }
-      },
-      "additionalProperties": false,
-      "required": [
-        "host",
-        "target"
-      ]
     },
-    "id": {
-      "description": "An opaque identifier for this SDK",
-      "type": "string"
-    },
-    "parts": {
-      "description": "The elements in this SDK",
-      "type": "array",
-      "minItems": 1,
-      "items": {
-        "type": "object",
-        "properties": {
-          "type": {
-            "description": "The type of the element",
-            "$ref": "common.json#/definitions/type"
-          },
-          "meta": {
-            "description": "The metadata file for the element",
-            "$ref": "common.json#/definitions/file"
-          }
-        },
-        "required": [
-          "meta",
-          "type"
-        ],
-        "additionalProperties": false
-      }
-    },
-    "schema_version": {
-      "description": "An opaque identifier for metadata schemas in the SDK",
-      "type": "string"
-    }
-  },
-  "required": [
-    "arch",
-    "id",
-    "parts",
-    "schema_version"
-  ],
-  "additionalProperties": false
+    "required": [
+        "arch",
+        "id",
+        "parts",
+        "schema_version"
+    ],
+    "type": "object"
 }
diff --git a/lib/fuchsia/meta/schemas/physical_device-0bd5d21f.json b/lib/fuchsia/meta/schemas/physical_device-0bd5d21f.json
new file mode 100644
index 0000000..5dda291
--- /dev/null
+++ b/lib/fuchsia/meta/schemas/physical_device-0bd5d21f.json
@@ -0,0 +1,44 @@
+{
+    "$schema": "http://json-schema.org/draft-07/schema#",
+    "allOf": [
+        {
+            "$ref": "common.json#/definitions/versioned_sdk_element"
+        },
+        {
+            "properties": {
+                "data": {
+                    "allOf": [
+                        {
+                            "properties": {
+                                "type": {
+                                    "allOf": [
+                                        {
+                                            "$ref": "common.json#/definitions/kind"
+                                        },
+                                        {
+                                            "enum": [
+                                                "physical_device"
+                                            ]
+                                        }
+                                    ]
+                                }
+                            }
+                        },
+                        {
+                            "$ref": "hardware-f6f47515.json#/definitions/requirements"
+                        }
+                    ],
+                    "required": [
+                        "hardware",
+                        "type",
+                        "name"
+                    ]
+                }
+            },
+            "type": "object"
+        }
+    ],
+    "description": "A physical device specification.",
+    "id": "http://fuchsia.com/schemas/sdk/physical_device-0bd5d21f.json",
+    "type": "object"
+}
diff --git a/lib/fuchsia/meta/schemas/product_bundle-6320eef1.json b/lib/fuchsia/meta/schemas/product_bundle-6320eef1.json
new file mode 100644
index 0000000..a772045
--- /dev/null
+++ b/lib/fuchsia/meta/schemas/product_bundle-6320eef1.json
@@ -0,0 +1,137 @@
+{
+    "$schema": "http://json-schema.org/draft-07/schema#",
+    "allOf": [
+        {
+            "$ref": "common.json#/definitions/versioned_sdk_element"
+        },
+        {
+            "properties": {
+                "data": {
+                    "properties": {
+                        "device_refs": {
+                            "description": "A list of physical or virtual device names this product can run on.",
+                            "items": {
+                                "minLength": 1,
+                                "type": "string"
+                            },
+                            "minItems": 1,
+                            "type": "array"
+                        },
+                        "images": {
+                            "description": "A list of system image bundles.",
+                            "items": {
+                                "$ref": "#/definitions/image_bundle"
+                            },
+                            "minItems": 1,
+                            "type": "array"
+                        },
+                        "manifests": {
+                            "description": "Manifests describing how to boot the product on a device.",
+                            "properties": {
+                                "emu": {
+                                    "$ref": "emu_manifest.json#/definitions/manifest"
+                                },
+                                "flash": {
+                                    "$ref": "flash_manifest-835e8f26.json#/definitions/manifest"
+                                }
+                            },
+                            "type": "object"
+                        },
+                        "metadata": {
+                            "$ref": "common.json#/definitions/key_value_list",
+                            "description": "A list of key-value pairs describing product dimensions. Tools must not rely on the presence or absence of certain keys. Tools may display them to the human user in order to assist them in selecting a desired image or log them for the sake of analytics. Typical metadata keys are: build_info_board, build_info_product, is_debug."
+                        },
+                        "packages": {
+                            "description": "A list of package bundles.",
+                            "items": {
+                                "$ref": "#/definitions/package_bundle"
+                            },
+                            "minItems": 1,
+                            "type": "array"
+                        },
+                        "type": {
+                            "allOf": [
+                                {
+                                    "$ref": "common.json#/definitions/kind"
+                                },
+                                {
+                                    "enum": [
+                                        "product_bundle"
+                                    ]
+                                }
+                            ]
+                        }
+                    },
+                    "required": [
+                        "device_refs",
+                        "images",
+                        "type",
+                        "name",
+                        "packages"
+                    ],
+                    "type": "object"
+                }
+            },
+            "type": "object"
+        }
+    ],
+    "definitions": {
+        "bundle_uri": {
+            "description": "Allowed system image and package bundle URIs.",
+            "format": "uri",
+            "pattern": "^(?:http|https|gs|file)://",
+            "type": "string"
+        },
+        "image_bundle": {
+            "additionalProperties": false,
+            "description": "A set of artifacts necessary to provision a physical or virtual device.",
+            "properties": {
+                "base_uri": {
+                    "$ref": "#/definitions/bundle_uri",
+                    "description": "A base URI for accessing artifacts in the bundle."
+                },
+                "format": {
+                    "description": "Bundle format: files - a directory layout; tgz - a gzipped tarball.",
+                    "enum": [
+                        "files",
+                        "tgz"
+                    ]
+                }
+            },
+            "required": [
+                "base_uri",
+                "format"
+            ],
+            "type": "object"
+        },
+        "package_bundle": {
+            "additionalProperties": false,
+            "description": "A set of artifacts necessary to run a physical or virtual device.",
+            "properties": {
+                "blob_uri": {
+                    "$ref": "#/definitions/bundle_uri",
+                    "description": "An optional blob repository URI. If omitted, it is assumed to be <repo_uri>/blobs. If repo_uri refers to a gzipped tarball, ./blobs directory is expected to be found inside the tarball."
+                },
+                "format": {
+                    "description": "Repository format: files - a directory layout; tgz - a gzipped tarball.",
+                    "enum": [
+                        "files",
+                        "tgz"
+                    ]
+                },
+                "repo_uri": {
+                    "$ref": "#/definitions/bundle_uri",
+                    "description": "A package repository URI. This may be an archive or a directory."
+                }
+            },
+            "required": [
+                "repo_uri",
+                "format"
+            ],
+            "type": "object"
+        }
+    },
+    "description": "Artifacts required to boot and run software on a device.",
+    "id": "http://fuchsia.com/schemas/sdk/product_bundle-6320eef1.json",
+    "type": "object"
+}
diff --git a/lib/fuchsia/meta/schemas/sysroot.json b/lib/fuchsia/meta/schemas/sysroot.json
index 9924ce2..e030e6a 100644
--- a/lib/fuchsia/meta/schemas/sysroot.json
+++ b/lib/fuchsia/meta/schemas/sysroot.json
@@ -1,116 +1,115 @@
 {
-  "$schema": "http://json-schema.org/draft-04/schema#",
-  "id": "http://fuchsia.com/schemas/sdk/sysroot.json",
-  "description": "The sysroot",
-  "type": "object",
-  "allOf": [
-    {
-      "$ref": "common.json#/definitions/sdk_element"
+    "$schema": "http://json-schema.org/draft-04/schema#",
+    "allOf": [
+        {
+            "$ref": "common.json#/definitions/sdk_element"
+        },
+        {
+            "additionalProperties": false,
+            "properties": {
+                "name": {
+                    "description": "Always 'sysroot'",
+                    "enum": [
+                        "sysroot"
+                    ],
+                    "type": "string"
+                },
+                "type": {
+                    "allOf": [
+                        {
+                            "$ref": "common.json#/definitions/kind"
+                        },
+                        {
+                            "enum": [
+                                "sysroot"
+                            ]
+                        }
+                    ]
+                },
+                "versions": {
+                    "additionalProperties": false,
+                    "description": "The various versions of the sysroot, per architecture",
+                    "maxProperties": 2,
+                    "minProperties": 1,
+                    "properties": {
+                        "arm64": {
+                            "$ref": "#/definitions/version",
+                            "description": "arm64 version"
+                        },
+                        "x64": {
+                            "$ref": "#/definitions/version",
+                            "description": "x64 version"
+                        }
+                    },
+                    "type": "object"
+                }
+            },
+            "required": [
+                "versions",
+                "name",
+                "type"
+            ]
+        }
+    ],
+    "definitions": {
+        "version": {
+            "additionalProperties": false,
+            "description": "Sysroot files for a given architecture",
+            "properties": {
+                "debug_libs": {
+                    "description": "List of libraries for debugging",
+                    "items": {
+                        "$ref": "common.json#/definitions/file"
+                    },
+                    "type": "array"
+                },
+                "dist_dir": {
+                    "$ref": "common.json#/definitions/file",
+                    "description": "Path to the base directory for prebuilt libraries"
+                },
+                "dist_libs": {
+                    "description": "List of libraries for inclusion in packages",
+                    "items": {
+                        "$ref": "common.json#/definitions/file"
+                    },
+                    "type": "array"
+                },
+                "headers": {
+                    "description": "List of public headers",
+                    "items": {
+                        "$ref": "common.json#/definitions/file"
+                    },
+                    "type": "array"
+                },
+                "include_dir": {
+                    "$ref": "common.json#/definitions/file",
+                    "description": "Path to the base directory for includes"
+                },
+                "link_libs": {
+                    "description": "List of link-time libraries",
+                    "items": {
+                        "$ref": "common.json#/definitions/file"
+                    },
+                    "type": "array"
+                },
+                "root": {
+                    "$ref": "common.json#/definitions/file",
+                    "description": "Path to the root of the sysroot"
+                }
+            },
+            "required": [
+                "root",
+                "headers",
+                "include_dir",
+                "link_libs",
+                "dist_libs",
+                "debug_libs",
+                "dist_dir"
+            ],
+            "type": "object"
+        }
     },
-    {
-      "properties": {
-        "type": {
-          "allOf": [
-            {
-              "$ref": "common.json#/definitions/type"
-            },
-            {
-              "enum": [
-                "sysroot"
-              ]
-            }
-          ]
-        },
-        "name": {
-          "description": "Always 'sysroot'",
-          "type": "string",
-          "enum": [
-            "sysroot"
-          ]
-        },
-        "versions": {
-          "description": "The various versions of the sysroot, per architecture",
-          "type": "object",
-          "properties": {
-            "x64": {
-              "description": "x64 version",
-              "$ref": "#/definitions/version"
-            },
-            "arm64": {
-              "description": "arm64 version",
-              "$ref": "#/definitions/version"
-            }
-          },
-          "additionalProperties": false,
-          "minProperties": 1,
-          "maxProperties": 2
-        }
-      },
-      "required": [
-        "versions",
-
-        "name",
-        "type"
-      ],
-      "additionalProperties": false
-    }
-  ],
-  "definitions": {
-    "version": {
-      "description": "Sysroot files for a given architecture",
-      "type": "object",
-      "properties": {
-        "root": {
-          "description": "Path to the root of the sysroot",
-          "$ref": "common.json#/definitions/file"
-        },
-        "headers": {
-          "description": "List of public headers",
-          "type": "array",
-          "items": {
-            "$ref": "common.json#/definitions/file"
-          }
-        },
-        "dist_dir": {
-          "description": "Path to the base directory for prebuilt libraries",
-          "$ref": "common.json#/definitions/file"
-        },
-        "include_dir": {
-          "description": "Path to the base directory for includes",
-          "$ref": "common.json#/definitions/file"
-        },
-        "link_libs": {
-          "description": "List of link-time libraries",
-          "type": "array",
-          "items": {
-            "$ref": "common.json#/definitions/file"
-          }
-        },
-        "dist_libs": {
-          "description": "List of libraries for inclusion in packages",
-          "type": "array",
-          "items": {
-            "$ref": "common.json#/definitions/file"
-          }
-        },
-        "debug_libs": {
-          "description": "List of libraries for debugging",
-          "type": "array",
-          "items": {
-            "$ref": "common.json#/definitions/file"
-          }
-        }
-      },
-      "required": [
-        "root",
-        "headers",
-        "include_dir",
-        "link_libs",
-        "dist_libs",
-        "debug_libs",
-        "dist_dir"
-      ],
-      "additionalProperties": false
-    }
-  }
+    "description": "The sysroot",
+    "id": "http://fuchsia.com/schemas/sdk/sysroot.json",
+    "type": "object"
 }
diff --git a/lib/fuchsia/meta/schemas/version_history.json b/lib/fuchsia/meta/schemas/version_history.json
new file mode 100644
index 0000000..0ce1c28
--- /dev/null
+++ b/lib/fuchsia/meta/schemas/version_history.json
@@ -0,0 +1,43 @@
+{
+    "$schema": "http://json-schema.org/schema#",
+    "additionalProperties": false,
+    "definitions": {
+        "v1": {
+            "additionalProperties": false,
+            "properties": {
+                "versions": {
+                    "items": {
+                        "$ref": "#/definitions/version"
+                    },
+                    "type": "array"
+                }
+            },
+            "type": "object"
+        },
+        "version": {
+            "additionalProperties": false,
+            "properties": {
+                "abi_revision": {
+                    "pattern": "^0x[0-9A-F]{8}$",
+                    "type": "string"
+                },
+                "api_level": {
+                    "pattern": "^[1-9][0-9]*$",
+                    "type": "string"
+                }
+            },
+            "type": "object"
+        }
+    },
+    "properties": {
+        "contents": {
+            "$ref": "#/definitions/v1"
+        },
+        "version": {
+            "pattern": "^[1-9][0-9]*$",
+            "type": "string"
+        }
+    },
+    "title": "Schema for Fuchsia platform version history",
+    "type": "object"
+}
diff --git a/lib/fuchsia/pkg/abr/flow.c b/lib/fuchsia/pkg/abr/flow.c
index 41d7d7e..358a97a 100644
--- a/lib/fuchsia/pkg/abr/flow.c
+++ b/lib/fuchsia/pkg/abr/flow.c
@@ -69,20 +69,28 @@
 }
 
 static void set_slot_unbootable(AbrSlotData* slot) {
-  slot->priority = 0;
   slot->tries_remaining = 0;
   slot->successful_boot = 0;
 }
 
-static bool is_slot_active(const AbrData* abr_data, AbrSlotIndex slot_index) {
-  AbrSlotIndex active_slot =
-      (abr_data->slot_data[kAbrSlotIndexB].priority > abr_data->slot_data[kAbrSlotIndexA].priority)
-          ? kAbrSlotIndexB
-          : kAbrSlotIndexA;
-  if (!is_slot_bootable(&abr_data->slot_data[active_slot])) {
-    active_slot = kAbrSlotIndexR;
+static uint8_t get_normalized_priority(const AbrSlotData* slot) {
+  return is_slot_bootable(slot) ? slot->priority : 0;
+}
+
+static AbrSlotIndex get_active_slot(const AbrData* abr_data) {
+  uint8_t priority_a = get_normalized_priority(&abr_data->slot_data[kAbrSlotIndexA]);
+  uint8_t priority_b = get_normalized_priority(&abr_data->slot_data[kAbrSlotIndexB]);
+  // zero priority means unbootable.
+  if (priority_b > priority_a) {
+    return kAbrSlotIndexB;
+  } else if (priority_a) {
+    return kAbrSlotIndexA;
   }
-  return (active_slot == slot_index);
+  return kAbrSlotIndexR;
+}
+
+static bool is_slot_active(const AbrData* abr_data, AbrSlotIndex slot_index) {
+  return get_active_slot(abr_data) == slot_index;
 }
 
 /* Ensure all unbootable or invalid states are marked as the canonical 'unbootable' state. That is,
@@ -117,17 +125,25 @@
   uint8_t serialized[sizeof(*abr_data)];
 
   ABR_DEBUG("Writing A/B metadata to disk.\n");
+  if (abr_ops->write_abr_metadata_custom) {
+    if (!abr_ops->write_abr_metadata_custom(abr_ops->context, &abr_data->slot_data[0],
+                                            &abr_data->slot_data[1],
+                                            abr_data->one_shot_recovery_boot)) {
+      ABR_ERROR("Failed to write metadata.\n");
+      return kAbrResultErrorIo;
+    }
+  } else {
+    abr_data_serialize(abr_data, serialized);
 
-  abr_data_serialize(abr_data, serialized);
+    if (abr_ops->write_abr_metadata == NULL) {
+      ABR_ERROR("Failed to write metadata (not implemented).\n");
+      return kAbrResultErrorIo;
+    }
 
-  if (abr_ops->write_abr_metadata == NULL) {
-    ABR_ERROR("Failed to write metadata (not implemented).\n");
-    return kAbrResultErrorIo;
-  }
-
-  if (!abr_ops->write_abr_metadata(abr_ops->context, serialized, sizeof(serialized))) {
-    ABR_ERROR("Failed to write metadata.\n");
-    return kAbrResultErrorIo;
+    if (!abr_ops->write_abr_metadata(abr_ops->context, serialized, sizeof(serialized))) {
+      ABR_ERROR("Failed to write metadata.\n");
+      return kAbrResultErrorIo;
+    }
   }
 
   return kAbrResultOk;
@@ -146,27 +162,37 @@
   AbrResult result = kAbrResultOk;
   uint8_t serialized[sizeof(*abr_data)];
 
-  if (abr_ops->read_abr_metadata == NULL) {
+  if (abr_ops->read_abr_metadata == NULL && abr_ops->read_abr_metadata_custom == NULL) {
     ABR_ERROR("Failed to read metadata (not implemented).\n");
     return kAbrResultErrorIo;
   }
 
-  if (!abr_ops->read_abr_metadata(abr_ops->context, sizeof(serialized), serialized)) {
-    ABR_ERROR("Failed to read metadata.\n");
-    return kAbrResultErrorIo;
-  }
+  if (abr_ops->read_abr_metadata != NULL) {
+    if (!abr_ops->read_abr_metadata(abr_ops->context, sizeof(serialized), serialized)) {
+      ABR_ERROR("Failed to read metadata.\n");
+      return kAbrResultErrorIo;
+    }
 
-  result = abr_data_deserialize(serialized, sizeof(serialized), abr_data);
-  if (result == kAbrResultErrorUnsupportedVersion) {
-    /* We don't want to clobber valid data in persistent storage, but we can't use this data, so
-     * bail out.
-     */
-    return result;
-  } else if (result != kAbrResultOk) {
-    /* No valid data exists. Use default data and set original data to trigger update. */
+    result = abr_data_deserialize(serialized, sizeof(serialized), abr_data);
+    if (result == kAbrResultErrorUnsupportedVersion) {
+      /* We don't want to clobber valid data in persistent storage, but we can't use this data, so
+       * bail out.
+       */
+      return result;
+    } else if (result != kAbrResultOk) {
+      /* No valid data exists. Use default data and set original data to trigger update. */
+      abr_data_init(abr_data);
+      AbrMemset(abr_data_orig, 0, sizeof(*abr_data_orig));
+      return kAbrResultOk;
+    }
+  } else {
     abr_data_init(abr_data);
-    AbrMemset(abr_data_orig, 0, sizeof(*abr_data_orig));
-    return kAbrResultOk;
+    if (!abr_ops->read_abr_metadata_custom(abr_ops->context, &abr_data->slot_data[kAbrSlotIndexA],
+                                           &abr_data->slot_data[kAbrSlotIndexB],
+                                           &abr_data->one_shot_recovery_boot)) {
+      ABR_ERROR("Failed to read metadata.\n");
+      return kAbrResultErrorIo;
+    }
   }
 
   *abr_data_orig = *abr_data;
@@ -194,6 +220,19 @@
   return true;
 }
 
+AbrResult AbrGetSlotLastMarkedActive(const AbrOps* abr_ops, AbrSlotIndex* out_slot) {
+  AbrData abr_data, abr_data_orig;
+  AbrResult result = load_metadata(abr_ops, &abr_data, &abr_data_orig);
+  if (result != kAbrResultOk) {
+    return result;
+  }
+
+  uint8_t priority_a = abr_data.slot_data[kAbrSlotIndexA].priority;
+  uint8_t priority_b = abr_data.slot_data[kAbrSlotIndexB].priority;
+  *out_slot = priority_b > priority_a ? kAbrSlotIndexB : kAbrSlotIndexA;
+  return result;
+}
+
 AbrSlotIndex AbrGetBootSlot(const AbrOps* abr_ops, bool update_metadata,
                             bool* is_slot_marked_successful) {
   AbrData abr_data, abr_data_orig;
@@ -219,18 +258,14 @@
     abr_data.one_shot_recovery_boot = 1;
   }
 
-  /* Choose the highest priority slot. This logic assumes normalized metadata. */
-  slot_to_boot =
-      (abr_data.slot_data[kAbrSlotIndexB].priority > abr_data.slot_data[kAbrSlotIndexA].priority)
-          ? kAbrSlotIndexB
-          : kAbrSlotIndexA;
-  if (is_slot_bootable(&abr_data.slot_data[slot_to_boot])) {
+  /* Choose the highest priority and bootable slot, if there is one, otherwise R slot*/
+  slot_to_boot = get_active_slot(&abr_data);
+  if (slot_to_boot == kAbrSlotIndexR) {
+    ABR_DEBUG("All slots are unbootable, falling back to recovery mode.\n");
+  } else {
     if (is_slot_marked_successful && abr_data.slot_data[slot_to_boot].successful_boot) {
       *is_slot_marked_successful = true;
     }
-  } else {
-    ABR_DEBUG("All slots are unbootable, falling back to recovery mode.\n");
-    slot_to_boot = kAbrSlotIndexR;
   }
 
   if (update_metadata) {
diff --git a/lib/fuchsia/pkg/abr/include/lib/abr/abr.h b/lib/fuchsia/pkg/abr/include/lib/abr/abr.h
index 4947c2f..a895229 100644
--- a/lib/fuchsia/pkg/abr/include/lib/abr/abr.h
+++ b/lib/fuchsia/pkg/abr/include/lib/abr/abr.h
@@ -111,6 +111,19 @@
  */
 AbrResult AbrMarkSlotActive(const AbrOps* abr_ops, AbrSlotIndex slot_index);
 
+/* Returns the slot index on which AbrMarkSlotActive was lastly called. The result is stored in
+ * |out_slot|.
+ *
+ * This function is typically used by the recovery system (i.e. the R slot OS) to retry the slot
+ * that was lastly marked as active after fixing problems. Specifically, in the event of boot
+ * failures where the device ends up in R slot, after issues are fixed, this function can be used to
+ * query the slot that was lastly marked active by AbrMarkSlotActive, then AbrMarkSlotActive can be
+ * used again to re-mark it as active so that it can be retried.
+ *
+ * If A/B/R metadata is not valid, it will be reset and slot A will be the default active slot.
+ */
+AbrResult AbrGetSlotLastMarkedActive(const AbrOps* abr_ops, AbrSlotIndex* out_slot);
+
 /* Marks the given |slot_index| as unbootable. Returns kAbrResultOk on success.
  *
  * Calling this on kAbrSlotIndexR is an error and kAbrResultErrorInvalidData will be returned.
diff --git a/lib/fuchsia/pkg/abr/include/lib/abr/data.h b/lib/fuchsia/pkg/abr/include/lib/abr/data.h
index 76d6bd4..7cd5685 100644
--- a/lib/fuchsia/pkg/abr/include/lib/abr/data.h
+++ b/lib/fuchsia/pkg/abr/include/lib/abr/data.h
@@ -17,7 +17,8 @@
  */
 
 /* Magic for the A/B struct when serialized. */
-static const char* kAbrMagic = "\0AB0";
+// Local modification for estelle. See lib/fuchsia/README.md.
+#define kAbrMagic "\0AB0"
 #define kAbrMagicLen 4
 
 /* Versioning for the on-disk A/B metadata. */
diff --git a/lib/fuchsia/pkg/abr/include/lib/abr/ops.h b/lib/fuchsia/pkg/abr/include/lib/abr/ops.h
index a57bffc..5ef2c3f 100644
--- a/lib/fuchsia/pkg/abr/include/lib/abr/ops.h
+++ b/lib/fuchsia/pkg/abr/include/lib/abr/ops.h
@@ -6,6 +6,7 @@
 #ifndef SRC_FIRMWARE_LIB_ABR_INCLUDE_LIB_ABR_OPS_H_
 #define SRC_FIRMWARE_LIB_ABR_INCLUDE_LIB_ABR_OPS_H_
 
+#include "data.h"
 #include "sysdeps.h"
 
 #ifdef __cplusplus
@@ -23,16 +24,43 @@
   /* Reads |size| bytes of A/B/R metadata from persistent storage into |buffer|.
    *
    * On success, populates |buffer| and returns true. This function must fail if fewer than |size|
-   * bytes are read. Setting this function to NULL will cause libabr to return I/O errors.
+   * bytes are read.
+   *
+   * Either read_abr_metadata or read_abr_metadata_custom must be provided, and the other must be
+   * NULL.
    */
   bool (*read_abr_metadata)(void* context, size_t size, uint8_t* buffer);
 
   /* Writes |size| bytes of A/B/R metadata from |buffer| to persistent storage.
    *
    * Returns true on success. This function must fail if fewer than |size| bytes are written.
-   * Setting this function to NULL is appropriate in environments where metadata is read-only.
+   *
+   * Either write_abr_metadata or write_abr_metadata_custom may be provided, but not both. In
+   * read-only environments, they may both be NULL.
    */
   bool (*write_abr_metadata)(void* context, const uint8_t* buffer, size_t size);
+
+  /* Reads ABR data into |a_slot_data|, |b_slot_data|, and |one_shot_recovery|.
+   *
+   * Returns true on success. This function must fail if any metadata fails to read.
+   * The client is responsible for ensuring the integrity of the data.
+   *
+   * Either read_abr_metadata or read_abr_metadata_custom must be provided, and the other must be
+   * NULL.
+   */
+  bool (*read_abr_metadata_custom)(void* context, AbrSlotData* a_slot_data,
+                                   AbrSlotData* b_slot_data, uint8_t* one_shot_recovery);
+
+  /* Writes ABR data from |a_slot_data|, |b_slot_data|, and |one_shot_recovery| to disk.
+   *
+   * Returns true on success. This function must fail if any metadata fails to write.
+   * The client is responsible for ensuring the integrity of the data.
+   *
+   * Either write_abr_metadata or write_abr_metadata_custom may be provided, but not both. In
+   * read-only environments, they may both be NULL.
+   */
+  bool (*write_abr_metadata_custom)(void* context, const AbrSlotData* a_slot_data,
+                                    const AbrSlotData* b_slot_data, uint8_t one_shot_recovery);
 } AbrOps;
 
 #ifdef __cplusplus
diff --git a/lib/fuchsia/pkg/avb/libavb/avb_rsa.c b/lib/fuchsia/pkg/avb/libavb/avb_rsa.c
index f4cb322..a6f5c78 100644
--- a/lib/fuchsia/pkg/avb/libavb/avb_rsa.c
+++ b/lib/fuchsia/pkg/avb/libavb/avb_rsa.c
@@ -33,6 +33,7 @@
  */
 
 #include "avb_rsa.h"
+
 #include "avb_sha.h"
 #include "avb_util.h"
 #include "avb_vbmeta_image.h"
@@ -185,7 +186,9 @@
 
   /* Convert from big endian byte array to little endian word array. */
   for (i = 0; i < (int)key->len; ++i) {
-    uint32_t tmp = (inout[((key->len - 1 - i) * 4) + 0] << 24) |
+    // Explicitly cast to uint32_t for 24-bit shift to avoid fuchsia sanitizer
+    // error that complains it can't be represented in 'int' type.
+    uint32_t tmp = (((uint32_t)inout[((key->len - 1 - i) * 4) + 0]) << 24) |
                    (inout[((key->len - 1 - i) * 4) + 1] << 16) |
                    (inout[((key->len - 1 - i) * 4) + 2] << 8) |
                    (inout[((key->len - 1 - i) * 4) + 3] << 0);
diff --git a/lib/fuchsia/pkg/sysroot/meta.json b/lib/fuchsia/pkg/sysroot/meta.json
index ffee70d..570fb86 100644
--- a/lib/fuchsia/pkg/sysroot/meta.json
+++ b/lib/fuchsia/pkg/sysroot/meta.json
@@ -4,10 +4,9 @@
   "versions": {
     "arm64": {
       "debug_libs": [
-        ".build-id/8c/018073bc48082f.debug",
-        ".build-id/fb/e4295f23dfd98e.debug",
-        ".build-id/79/d476e6c9a484a0.debug",
-        ".build-id/5b/b8d12db992dc0e.debug"
+        ".build-id/08/a31a2b8b223e18.debug",
+        ".build-id/6d/af2980dba841de.debug",
+        ".build-id/a8/80e02cad3f7e8e.debug"
       ],
       "dist_dir": "arch/arm64/sysroot",
       "dist_libs": [
@@ -17,6 +16,7 @@
       ],
       "headers": [
         "arch/arm64/sysroot/include/zircon/assert.h",
+        "arch/arm64/sysroot/include/zircon/analyzer.h",
         "arch/arm64/sysroot/include/zircon/boot/bootfs.h",
         "arch/arm64/sysroot/include/zircon/boot/crash-reason.h",
         "arch/arm64/sysroot/include/zircon/boot/driver-config.h",
@@ -39,7 +39,6 @@
         "arch/arm64/sysroot/include/zircon/hw/usb/cdc.h",
         "arch/arm64/sysroot/include/zircon/hw/usb/dfu.h",
         "arch/arm64/sysroot/include/zircon/hw/usb/hid.h",
-        "arch/arm64/sysroot/include/zircon/hw/usb/hub.h",
         "arch/arm64/sysroot/include/zircon/hw/usb/ums.h",
         "arch/arm64/sysroot/include/zircon/hw/usb/video.h",
         "arch/arm64/sysroot/include/zircon/limits.h",
diff --git a/lib/fuchsia/pkg/zbi/include/lib/zbi/zbi.h b/lib/fuchsia/pkg/zbi/include/lib/zbi/zbi.h
index f7dfb0b..54872c1 100644
--- a/lib/fuchsia/pkg/zbi/include/lib/zbi/zbi.h
+++ b/lib/fuchsia/pkg/zbi/include/lib/zbi/zbi.h
@@ -43,7 +43,6 @@
   ZBI_RESULT_TOO_BIG,
 
   ZBI_RESULT_INCOMPLETE_KERNEL,
-  ZBI_RESULT_INCOMPLETE_BOOTFS,
 } zbi_result_t;
 
 typedef zbi_result_t (*zbi_foreach_cb_t)(zbi_header_t* hdr, void* payload, void* cookie);
@@ -84,7 +83,7 @@
 // Validates the ZBI for the host platform.
 //
 // Same as zbi_check but also diagnoses ZBI_RESULT_INCOMPLETE_* result codes
-// if the ZBI is not a valid complete ZBI for the host platform.
+// if the ZBI is not a valid, bootable ZBI for the host platform.
 //
 // Parameters:
 //     base - The ZBI to check.
@@ -94,7 +93,7 @@
 //     ZBI_RESULT_OK - On success.
 //     ZBI_RESULT_ERROR - If base is NULL.
 //     Not ZBI_RESULT_OK - Indicating the error.
-zbi_result_t zbi_check_complete(const void* base, zbi_header_t** err);
+zbi_result_t zbi_check_bootable(const void* base, zbi_header_t** err);
 
 // Calls the callback with a pointer to the header and payload of each ZBI
 // entry (excluding the container).
@@ -141,7 +140,7 @@
 //     ZBI_RESULT_BAD_TYPE - If the base ZBI is not a valid ZBI container.
 //     ZBI_RESULT_TOO_BIG - If the base ZBI is too small.
 zbi_result_t zbi_create_entry(void* base, size_t capacity, uint32_t type, uint32_t extra,
-                              uint32_t flags, uint32_t payload_length, void** payload);
+                              uint32_t flags, size_t payload_length, void** payload);
 
 // Creates a new ZBI entry with the provided payload.
 //
@@ -169,7 +168,7 @@
 //     ZBI_RESULT_TOO_BIG - If the base ZBI is too small.
 zbi_result_t zbi_create_entry_with_payload(void* base, size_t capacity, uint32_t type,
                                            uint32_t extra, uint32_t flags, const void* payload,
-                                           uint32_t payload_length);
+                                           size_t payload_length);
 
 // Returns the payload buffer for the next ZBI entry to add.
 //
diff --git a/lib/fuchsia/pkg/zbi/zbi.c b/lib/fuchsia/pkg/zbi/zbi.c
index f12c11b..630ffed 100644
--- a/lib/fuchsia/pkg/zbi/zbi.c
+++ b/lib/fuchsia/pkg/zbi/zbi.c
@@ -8,14 +8,9 @@
 // Local modification for Estelle. See lib/fuchsia/README.estelle.md.
 #include <common.h>  // <string.h>
 
-// At most, a ZBI container can be the header + 32 bytes of length.
+// At most, a ZBI container can be the header + 32 bits of length.
 #define MAX_CONTAINER_SIZE (sizeof(zbi_header_t) + 0xFFFFFFFFull)
 
-struct check_state {
-  zbi_header_t** err;
-  bool seen_bootfs;
-};
-
 static bool is_zbi_container(const zbi_header_t* hdr) {
   return (hdr->type == ZBI_TYPE_CONTAINER) && (hdr->magic == ZBI_ITEM_MAGIC) &&
          (hdr->extra == ZBI_CONTAINER_MAGIC);
@@ -48,8 +43,7 @@
 }
 
 static zbi_result_t for_each_check_entry(zbi_header_t* hdr, void* payload, void* cookie) {
-  struct check_state* const state = cookie;
-
+  zbi_header_t** err = cookie;
   zbi_result_t result = ZBI_RESULT_OK;
 
   if (hdr->magic != ZBI_ITEM_MAGIC) {
@@ -61,18 +55,14 @@
   }
 
   // If we found a problem, try to report it back up to the caller.
-  if (state->err != NULL && result != ZBI_RESULT_OK) {
-    *state->err = hdr;
-  }
-
-  if (hdr->type == ZBI_TYPE_STORAGE_BOOTFS) {
-    state->seen_bootfs = true;
+  if (err != NULL && result != ZBI_RESULT_OK) {
+    *err = hdr;
   }
 
   return result;
 }
 
-static zbi_result_t zbi_check_internal(const void* base, uint32_t check_complete,
+static zbi_result_t zbi_check_internal(const void* base, uint32_t check_bootable,
                                        zbi_header_t** err) {
   if (!base) {
     return ZBI_RESULT_ERROR;
@@ -101,22 +91,16 @@
     return res;
   }
 
-  struct check_state state = {.err = err};
-  res = zbi_for_each(base, for_each_check_entry, &state);
+  res = zbi_for_each(base, for_each_check_entry, err);
 
-  if (res == ZBI_RESULT_OK && check_complete != 0) {
+  if (res == ZBI_RESULT_OK && check_bootable != 0) {
     if (header->length == 0) {
       res = ZBI_RESULT_ERR_TRUNCATED;
-    } else if (header[1].type != check_complete) {
+    } else if (header[1].type != check_bootable) {
       res = ZBI_RESULT_INCOMPLETE_KERNEL;
       if (err) {
         *err = (zbi_header_t*)(header + 1);
       }
-    } else if (!state.seen_bootfs) {
-      res = ZBI_RESULT_INCOMPLETE_BOOTFS;
-      if (err) {
-        *err = (zbi_header_t*)header;
-      }
     }
   }
 
@@ -132,7 +116,7 @@
   return zbi_check_internal(base, 0, err);
 }
 
-zbi_result_t zbi_check_complete(const void* base, zbi_header_t** err) {
+zbi_result_t zbi_check_bootable(const void* base, zbi_header_t** err) {
   return zbi_check_internal(base,
 #ifdef __aarch64__
                             ZBI_TYPE_KERNEL_ARM64,
@@ -175,12 +159,12 @@
 
 zbi_result_t zbi_create_entry_with_payload(void* base, const size_t capacity, uint32_t type,
                                            uint32_t extra, uint32_t flags, const void* payload,
-                                           uint32_t payload_length) {
+                                           size_t payload_length) {
   if (!base || !payload) {
     return ZBI_RESULT_ERROR;
   }
 
-  uint8_t* new_section;
+  uint8_t* new_section = NULL;
   zbi_result_t result =
       zbi_create_entry(base, capacity, type, extra, flags, payload_length, (void**)&new_section);
 
@@ -194,7 +178,7 @@
 }
 
 zbi_result_t zbi_create_entry(void* base, size_t capacity, uint32_t type, uint32_t extra,
-                              uint32_t flags, uint32_t payload_length, void** payload) {
+                              uint32_t flags, size_t payload_length, void** payload) {
   if (!base) {
     return ZBI_RESULT_ERROR;
   }
@@ -204,6 +188,10 @@
     return ZBI_RESULT_ERROR;
   }
 
+  if (payload_length > 0xFFFFFFFFU) {
+    return ZBI_RESULT_TOO_BIG;
+  }
+
   zbi_header_t* hdr = (zbi_header_t*)base;
 
   // Find the payload entry point and make sure we have enough room.
@@ -223,7 +211,7 @@
   zbi_header_t* new_header = (void*)((uint8_t*)(hdr + 1) + hdr->length);
   *new_header = (zbi_header_t){
       .type = type,
-      .length = payload_length,
+      .length = (uint32_t)payload_length,
       .extra = extra,
       .flags = flags | ZBI_FLAG_VERSION,
       .magic = ZBI_ITEM_MAGIC,
@@ -266,7 +254,9 @@
   // take, e.g. a bootloader may just supply whatever leftover memory it has.
   // Just truncate to the max ZBI size and ignore any extra capacity.
   if (capacity > MAX_CONTAINER_SIZE) {
-    capacity = MAX_CONTAINER_SIZE;
+    // On systems with a 32-bit size_t, this cast is necessary to avoid an error.
+    // Note that this code will never run on those systems.
+    capacity = (size_t)MAX_CONTAINER_SIZE;
   }
   if (capacity < sizeof(*hdr) || capacity - sizeof(*hdr) < hdr->length) {
     return ZBI_RESULT_TOO_BIG;
diff --git a/tools/nandoob_to_image.py b/tools/nandoob_to_image.py
new file mode 100755
index 0000000..5642222
--- /dev/null
+++ b/tools/nandoob_to_image.py
@@ -0,0 +1,197 @@
+#!/usr/bin/env python3
+"""Converts a NAND+OOB dump into a flashable image.
+
+To extract the NAND+OOB image:
+  $ fastboot oem stage-partition-oob <partition>
+  $ fastboot get_staged <file>
+
+To flash it back after converting:
+  $ fastboot flash <partition> <converted_file>
+
+In general, we can't exactly replicate the source NAND+OOB state since each
+device has its own bad block map, so trying to replay a dump from one device
+onto a different device may not work as expected.
+"""
+
+import argparse
+import logging
+import struct
+import sys
+from typing import List
+
+NAND_PAGE_SIZE = 4096
+NAND_OOB_SIZE = 8
+NANDOOB_PAGE_SIZE = NAND_PAGE_SIZE + NAND_OOB_SIZE
+
+ESTELLE_NUM_FVM_PAGES = 0x1AD00
+ESTELLE_PAGES_PER_BLOCK = 64
+
+BADBLOCK_PAGE = b"BADBLOCK" + (b"\x00" * 4096)
+READFAIL_PAGE = b"READFAIL" + (b"\x00" * 4096)
+EMPTY_PAGE = b"\xFF" * NANDOOB_PAGE_SIZE
+
+FVM_FTL_IMAGE_MAGIC = 0x12A17178711A711D
+FVM_FTL_IMAGE_MAJOR = 1
+FVM_FTL_IMAGE_MINOR = 1
+FVM_FTL_IMAGE_FLAG_REQUIRE_WIPE = 1
+FVM_FTL_IMAGE_FORMAT_RAW = 0
+
+ZBI_TYPE_CONTAINER = 0x544f4f42
+ZBI_CONTAINER_MAGIC = 0x868cf7e6
+ZBI_ITEM_MAGIC = 0xb5781729
+
+
+def nandoob_to_pages(nandoob: bytes) -> List[bytes]:
+    """Splits a NAND+OOB dump into pages.
+
+    Args:
+        nandoob: NAND+OOB dump from `oem stage-partition-oob`
+
+    Returns:
+        A list of 4096+8 byte pages, does not include any BADBLOCK pages or
+        trailing empty pages.
+    """
+    pages = []
+    empty_count = 0
+    index = 0
+    readfails = []
+    for (page,) in struct.iter_unpack(f"{NANDOOB_PAGE_SIZE}s", nandoob):
+        if page == BADBLOCK_PAGE:
+            # I *think* the NDM driver should transparently swap out bad blocks
+            # on each device so that the FTL doesn't have to know or care about
+            # them, which should mean that we can just ignore them on both the
+            # original dump and the target device.
+            logging.debug("Skipping BADBLOCK page %s", index)
+        elif page == READFAIL_PAGE:
+            # The best we can do with read errors is leave it empty and hope it
+            # wasn't mapped by the FTL. We'll print out a warning at the end.
+            readfails.append(index)
+            empty_count += 1
+        elif page == EMPTY_PAGE:
+            # No point writing trailing empty pages, just buffer it for now.
+            empty_count += 1
+        else:
+            # Flush any pending empty pages now that we've encountered data.
+            pages += ([EMPTY_PAGE] * empty_count) + [page]
+            empty_count = 0
+        index += 1
+
+    if readfails:
+        logging.warning("Found READFAIL page(s): %s", readfails)
+        logging.warning("Leaving contents at 0xFF on-device")
+        logging.warning("If this page was in use, expect errors")
+
+    return pages
+
+
+def pages_to_fvm_image(pages: List[bytes]) -> bytes:
+    """Converts a list of NAND+OOB pages into a fastboot flashable FVM image."""
+    # Log the number of unused pages and blocks.
+    unused_pages = ESTELLE_NUM_FVM_PAGES - len(pages)
+    unused_blocks = unused_pages // ESTELLE_PAGES_PER_BLOCK
+    logging.info("Unused pages: %s", unused_pages)
+    logging.info("Target device can have at most %s bad blocks", unused_blocks)
+
+    # Header format:
+    #  uint64_t magic
+    #  uint32_t version_major
+    #  uint32_t version_minor
+    #  uint32_t flags
+    #  uint32_t format
+    #  uint32_t page_size
+    #  uint8_t oob_size
+    #  uint8_t reserved[3] (0xFF)
+    header = struct.pack("<QIIIII4B", FVM_FTL_IMAGE_MAGIC, FVM_FTL_IMAGE_MAJOR,
+                         FVM_FTL_IMAGE_MINOR, FVM_FTL_IMAGE_FLAG_REQUIRE_WIPE,
+                         FVM_FTL_IMAGE_FORMAT_RAW, NAND_PAGE_SIZE,
+                         NAND_OOB_SIZE, 0xFF, 0xFF, 0xFF)
+    return header + b''.join(pages)
+
+
+def pages_to_skip_block_image(pages: List[bytes]) -> bytes:
+    """Converts a list of NAND+OOB pages into a skip-block image.
+
+    Skip-block images just ignore OOB data and bad blocks altogether. No
+    wear-leveling is applied, bad blocks are just skipped entirely.
+    """
+    return b''.join([p[:NAND_PAGE_SIZE] for p in pages])
+
+
+def pages_to_zbi_image(pages: List[bytes]) -> bytes:
+    """A ZBI image is just a skip-block image trunctated to the ZBI size."""
+    # ZBI header format:
+    #   uint32_t type
+    #   uint32_t length
+    #   uint32_t extra
+    #   uint32_t flags
+    #   uint32_t reserved0
+    #   uint32_t reserved1
+    #   uint32_t magic
+    #   uint32_t crc32
+    header_format = "<IIIIIIII"
+    header_size = struct.calcsize(header_format)
+    (type, length, extra, _, _, _, magic,
+     _) = struct.unpack_from(header_format, pages[0])
+    if not (type == ZBI_TYPE_CONTAINER and extra == ZBI_CONTAINER_MAGIC and
+            magic == ZBI_ITEM_MAGIC):
+        raise ValueError(f"Image does not look like a ZBI")
+
+    # Return just the ZBI according to the size indicated in the header.
+    entire_partition = pages_to_skip_block_image(pages)
+    return entire_partition[:header_size + length]
+
+
+def _parse_args() -> argparse.Namespace:
+    parser = argparse.ArgumentParser(
+        description=__doc__,
+        formatter_class=argparse.RawDescriptionHelpFormatter)
+
+    parser.add_argument("type",
+                        choices=["fvm", "skip_block", "zbi"],
+                        help="Image type. 'fvm' creates a fastboot-flashable"
+                        " FVM image. 'skip_block' strips out OOB bytes and bad"
+                        " blocks and returns just the data. 'zbi' does"
+                        " skip_block processing but also truncates to just the"
+                        " ZBI image.")
+    parser.add_argument("source", help="Raw stage-partition-oob data")
+    parser.add_argument(
+        "dest",
+        nargs="?",
+        help="Output file, <source>.nandoob_to_flashable by default")
+    parser.add_argument("-f",
+                        "--force",
+                        action="store_true",
+                        help="Overwrite dest if it exists")
+
+    args = parser.parse_args()
+
+    # Set the default dest if necessary.
+    if not args.dest:
+        args.dest = f"{args.source}.nandoob_to_{args.type}"
+
+    return args
+
+
+def _main() -> int:
+    logging.basicConfig(level=logging.INFO)
+    args = _parse_args()
+
+    with open(args.source, "rb") as file:
+        nandoob = file.read()
+
+    pages = nandoob_to_pages(nandoob)
+    if args.type == "fvm":
+        image = pages_to_fvm_image(pages)
+    elif args.type == "skip_block":
+        image = pages_to_skip_block_image(pages)
+    elif args.type == "zbi":
+        image = pages_to_zbi_image(pages)
+
+    with open(args.dest, "wb" if args.force else "xb") as file:
+        file.write(image)
+
+    return 0
+
+
+if __name__ == "__main__":
+    sys.exit(_main())