diff --git a/boot/pxe_parse.c b/boot/pxe_parse.c
index b115fb413a2..6d148756b0d 100644
--- a/boot/pxe_parse.c
+++ b/boot/pxe_parse.c
@@ -106,14 +106,14 @@ static struct pxe_label *label_create(void)
 	if (!label)
 		return NULL;
 	memset(label, 0, sizeof(struct pxe_label));
-	alist_init_struct(&label->fdtoverlays, char *);
+	alist_init_struct(&label->fdtoverlays, struct pxe_fdtoverlay);
 
 	return label;
 }
 
 void label_destroy(struct pxe_label *label)
 {
-	char **overlayp;
+	struct pxe_fdtoverlay *overlay;
 
 	free(label->name);
 	free(label->kernel_label);
@@ -123,8 +123,8 @@ void label_destroy(struct pxe_label *label)
 	free(label->initrd);
 	free(label->fdt);
 	free(label->fdtdir);
-	alist_for_each(overlayp, &label->fdtoverlays)
-		free(*overlayp);
+	alist_for_each(overlay, &label->fdtoverlays)
+		free(overlay->path);
 	alist_uninit(&label->fdtoverlays);
 	free(label->say);
 	free(label);
@@ -323,7 +323,7 @@ static int parse_fdtoverlays(char **c, struct alist *overlays)
 		return err;
 
 	while (*val) {
-		char *path;
+		struct pxe_fdtoverlay item;
 		char *end;
 
 		/* Skip leading spaces */
@@ -336,15 +336,16 @@ static int parse_fdtoverlays(char **c, struct alist *overlays)
 		/* Find end of this path */
 		end = strchr(val, ' ');
 		if (end) {
-			path = strndup(val, end - val);
+			item.path = strndup(val, end - val);
 			val = end;
 		} else {
-			path = strdup(val);
+			item.path = strdup(val);
 			val += strlen(val);
 		}
+		item.addr = 0;
 
-		if (!path || !alist_add(overlays, path)) {
-			free(path);
+		if (!item.path || !alist_add(overlays, item)) {
+			free(item.path);
 			return -ENOMEM;
 		}
 	}
diff --git a/boot/pxe_utils.c b/boot/pxe_utils.c
index a50fa4bc333..8d565d971fc 100644
--- a/boot/pxe_utils.c
+++ b/boot/pxe_utils.c
@@ -306,9 +306,9 @@ static void label_boot_kaslrseed(struct pxe_context *ctx)
 static void label_boot_fdtoverlay(struct pxe_context *ctx,
 				  struct pxe_label *label)
 {
+	struct pxe_fdtoverlay *overlay;
 	struct fdt_header *blob;
 	ulong fdtoverlay_addr;
-	char **overlayp;
 	bool use_lmb;
 	char *envaddr;
 	int err;
@@ -331,38 +331,43 @@ static void label_boot_fdtoverlay(struct pxe_context *ctx,
 		use_lmb = true;
 	}
 
-	/* Apply each overlay file in order */
-	alist_for_each(overlayp, &label->fdtoverlays) {
-		const char *overlayfile = *overlayp;
+	/* First pass: load all overlay files */
+	alist_for_each(overlay, &label->fdtoverlays) {
 		ulong addr = fdtoverlay_addr;
 		ulong size;
 
-		/* Load overlay file */
-		err = get_relfile(ctx, overlayfile, &addr, SZ_4K,
+		err = get_relfile(ctx, overlay->path, &addr, SZ_4K,
 				  (enum bootflow_img_t)IH_TYPE_FLATDT, &size);
 		if (err < 0) {
-			printf("Failed loading overlay %s\n", overlayfile);
+			printf("Failed loading overlay %s\n", overlay->path);
 			continue;
 		}
+		overlay->addr = addr;
 
-		/* Resize main fdt */
-		fdt_shrink_to_minimum(ctx->fdt, 8192);
+		/* Move to next address if using fixed addresses */
+		if (!use_lmb)
+			fdtoverlay_addr = addr + size;
+	}
+
+	/* Resize main fdt to make room for overlays */
+	fdt_shrink_to_minimum(ctx->fdt, 8192);
 
-		blob = map_sysmem(addr, 0);
+	/* Second pass: apply all loaded overlays */
+	alist_for_each(overlay, &label->fdtoverlays) {
+		if (!overlay->addr)
+			continue;
+
+		blob = map_sysmem(overlay->addr, 0);
 		err = fdt_check_header(blob);
 		if (err) {
-			printf("Invalid overlay %s, skipping\n", overlayfile);
+			printf("Invalid overlay %s, skipping\n", overlay->path);
 			continue;
 		}
 
 		err = fdt_overlay_apply_verbose(ctx->fdt, blob);
 		if (err)
 			printf("Failed to apply overlay %s, skipping\n",
-			       overlayfile);
-
-		/* Move to next address if using fixed addresses */
-		if (!use_lmb)
-			fdtoverlay_addr = addr + size;
+			       overlay->path);
 	}
 }
 
diff --git a/include/pxe_utils.h b/include/pxe_utils.h
index 52a520e4823..d2062c03997 100644
--- a/include/pxe_utils.h
+++ b/include/pxe_utils.h
@@ -24,6 +24,17 @@
  * take a 'include file getter' function.
  */
 
+/**
+ * struct pxe_fdtoverlay - info about an FDT overlay
+ *
+ * @path: Path to the overlay file
+ * @addr: Address where the overlay was loaded (0 if not yet loaded)
+ */
+struct pxe_fdtoverlay {
+	char *path;
+	ulong addr;
+};
+
 /**
  * struct pxe_label - describes a single label in a pxe file
  *
@@ -39,7 +50,7 @@
  * @initrd: path to the initrd to use for this label.
  * @fdt: path to FDT to use
  * @fdtdir: path to FDT directory to use
- * @fdtoverlays: list of paths of FDT overlays to apply (alist of char *)
+ * @fdtoverlays: list of FDT overlays to apply (alist of struct pxe_fdtoverlay)
  * @say: message to print when this label is selected for booting
  * @ipappend: flags for appending IP address (0x1) and MAC address (0x3)
  * @attempted: 0 if we haven't tried to boot this label, 1 if we have
diff --git a/test/boot/pxe.c b/test/boot/pxe.c
index 47cfa4042f5..df5c106caab 100644
--- a/test/boot/pxe.c
+++ b/test/boot/pxe.c
@@ -192,9 +192,9 @@ static int pxe_test_parse_norun(struct unit_test_state *uts)
 	ut_assertnull(label->fdtdir);
 	ut_asserteq(2, label->fdtoverlays.count);
 	ut_asserteq_str("/dtb/overlay1.dtbo",
-			*alist_get(&label->fdtoverlays, 0, char *));
+			alist_get(&label->fdtoverlays, 0, struct pxe_fdtoverlay)->path);
 	ut_asserteq_str("/dtb/overlay2.dtbo",
-			*alist_get(&label->fdtoverlays, 1, char *));
+			alist_get(&label->fdtoverlays, 1, struct pxe_fdtoverlay)->path);
 	ut_asserteq_str("Booting default Linux kernel", label->say);
 	ut_asserteq(0, label->ipappend);
 	ut_asserteq(0, label->attempted);
