Merge patch series "global_data: Reduce size of struct global_data"

Simon Glass <sjg@chromium.org> says:

The global data structure has grown quite a lot over the years, being
the best place to put an important pointer or something that must be
accessed before and after relocation.

This series attempts to reduce the size a little, by moving some things
out and shrinking and aligning some fields.

Some fields are needed during init but not afterwards. To deal with this
a new 'boardf' structure is created, which sits on the stack and is only
present during board_init_f(). It is possible that more fields could
move to this struct, but for now only 4 are moved.

An assumption is made that an int is 32-bits wide on all architectures,
which seems to be true, but maintainers should be able to confirm.

Mostly the code-size impact is neutral, but the patch
'Use less space for environment fields' does increase U-Boot's size by
about 30 bytes on aarch64.

For firefly-rk3399 (64-bit) the size of global reduces from 456 to 368
bytes. For SPL it reduces from 416 to 272 bytes.

There are other things which could be attempted, for example:
- Using hlist instead of list for some lists
- Checking that only necessary fields are present in SPL
diff --git a/arch/arm/cpu/arm926ejs/mxs/spl_boot.c b/arch/arm/cpu/arm926ejs/mxs/spl_boot.c
index 76a69d7..dd74832 100644
--- a/arch/arm/cpu/arm926ejs/mxs/spl_boot.c
+++ b/arch/arm/cpu/arm926ejs/mxs/spl_boot.c
@@ -117,7 +117,7 @@
 	gd->bd = &bdata;
 	gd->baudrate = CONFIG_BAUDRATE;
 	serial_init();
-	gd->have_console = 1;
+	gd->flags |= GD_FLG_HAVE_CONSOLE;
 #endif
 }
 
diff --git a/arch/arm/lib/bdinfo.c b/arch/arm/lib/bdinfo.c
index 7c49462..c7fff01 100644
--- a/arch/arm/lib/bdinfo.c
+++ b/arch/arm/lib/bdinfo.c
@@ -58,7 +58,7 @@
 	printf("Board Type  = %ld\n", gd->board_type);
 #endif
 #if CONFIG_IS_ENABLED(SYS_MALLOC_F)
-	printf("Early malloc usage: %lx / %x\n", gd->malloc_ptr,
+	printf("Early malloc usage: %x / %x\n", gd->malloc_ptr,
 	       CONFIG_VAL(SYS_MALLOC_F_LEN));
 #endif
 }
diff --git a/arch/arm/mach-exynos/spl_boot.c b/arch/arm/mach-exynos/spl_boot.c
index bd5a064..219d7fb 100644
--- a/arch/arm/mach-exynos/spl_boot.c
+++ b/arch/arm/mach-exynos/spl_boot.c
@@ -312,7 +312,7 @@
 	memzero((void *)gd, sizeof(gd_t));
 	gd->flags |= GD_FLG_RELOC;
 	gd->baudrate = CONFIG_BAUDRATE;
-	gd->have_console = 1;
+	gd->flags |= GD_FLG_HAVE_CONSOLE;
 }
 
 void board_init_f(unsigned long bootflag)
diff --git a/arch/arm/mach-k3/common.c b/arch/arm/mach-k3/common.c
index eaa7d36..df48ec8 100644
--- a/arch/arm/mach-k3/common.c
+++ b/arch/arm/mach-k3/common.c
@@ -104,7 +104,7 @@
 
 	gd->cur_serial_dev = dev;
 	gd->flags |= GD_FLG_SERIAL_READY;
-	gd->have_console = 1;
+	gd->flags |= GD_FLG_HAVE_CONSOLE;
 
 	return 0;
 }
diff --git a/arch/arm/mach-k3/r5/sysfw-loader.c b/arch/arm/mach-k3/r5/sysfw-loader.c
index 94d051b..188731e 100644
--- a/arch/arm/mach-k3/r5/sysfw-loader.c
+++ b/arch/arm/mach-k3/r5/sysfw-loader.c
@@ -451,7 +451,7 @@
 		 * the case when continuing to boot serially from the same
 		 * UART that the ROM loaded the initial bootloader from.
 		 */
-		if (!gd->have_console)
+		if (!(gd->flags & GD_FLG_HAVE_CONSOLE))
 			early_console_init();
 #endif
 		ret = spl_ymodem_load_image(&spl_image, &bootdev);
diff --git a/arch/arm/mach-tegra/board2.c b/arch/arm/mach-tegra/board2.c
index 479137e..7971e3b 100644
--- a/arch/arm/mach-tegra/board2.c
+++ b/arch/arm/mach-tegra/board2.c
@@ -423,10 +423,6 @@
 	gd->bd->bi_dram[0].start = CFG_SYS_SDRAM_BASE;
 	gd->bd->bi_dram[0].size = usable_ram_size_below_4g();
 
-#ifdef CONFIG_PCI
-	gd->pci_ram_top = gd->bd->bi_dram[0].start + gd->bd->bi_dram[0].size;
-#endif
-
 #ifdef CONFIG_PHYS_64BIT
 	if (gd->ram_size > SZ_2G) {
 		gd->bd->bi_dram[1].start = 0x100000000;
diff --git a/arch/arm/mach-tegra/cboot.c b/arch/arm/mach-tegra/cboot.c
index c12543d..e2342b2 100644
--- a/arch/arm/mach-tegra/cboot.c
+++ b/arch/arm/mach-tegra/cboot.c
@@ -189,10 +189,6 @@
 		gd->bd->bi_dram[i].size = tegra_mem_map[1 + i].size;
 	}
 
-#ifdef CONFIG_PCI
-	gd->pci_ram_top = ram_top;
-#endif
-
 	return 0;
 }
 
diff --git a/arch/m68k/cpu/mcf5445x/cpu.c b/arch/m68k/cpu/mcf5445x/cpu.c
index b811ac3..3fbd6a5 100644
--- a/arch/m68k/cpu/mcf5445x/cpu.c
+++ b/arch/m68k/cpu/mcf5445x/cpu.c
@@ -92,7 +92,7 @@
 		       strmhz(buf3, gd->arch.flb_clk));
 #ifdef CONFIG_PCI
 		printf("       PCI CLK %s MHz INP CLK %s MHz VCO CLK %s MHz\n",
-		       strmhz(buf1, gd->pci_clk),
+		       strmhz(buf1, gd->arch.pci_clk),
 		       strmhz(buf2, gd->arch.inp_clk),
 		       strmhz(buf3, gd->arch.vco_clk));
 #else
diff --git a/arch/m68k/include/asm/global_data.h b/arch/m68k/include/asm/global_data.h
index 93efc72..4ac8869 100644
--- a/arch/m68k/include/asm/global_data.h
+++ b/arch/m68k/include/asm/global_data.h
@@ -26,6 +26,8 @@
 #if defined(CONFIG_FSL_ESDHC)
 	unsigned long sdhc_per_clk;
 #endif
+	/** @pci_clk: PCI clock rate in Hz */
+	unsigned long pci_clk;
 };
 
 #include <asm-generic/global_data.h>
diff --git a/arch/m68k/lib/bdinfo.c b/arch/m68k/lib/bdinfo.c
index cf6ae5a..891e94b 100644
--- a/arch/m68k/lib/bdinfo.c
+++ b/arch/m68k/lib/bdinfo.c
@@ -22,7 +22,7 @@
 	bd->bi_busfreq = gd->bus_clk;	/* Bus Freq,      in Hz */
 
 	if (IS_ENABLED(CONFIG_PCI))
-		bd->bi_pcifreq = gd->pci_clk;
+		bd->bi_pcifreq = gd->arch.pci_clk;
 
 #if defined(CONFIG_EXTRA_CLOCK)
 	bd->bi_inpfreq = gd->arch.inp_clk;	/* input Freq in Hz */
diff --git a/arch/mips/mach-ath79/ar934x/clk.c b/arch/mips/mach-ath79/ar934x/clk.c
index bdaa683..231a21c 100644
--- a/arch/mips/mach-ath79/ar934x/clk.c
+++ b/arch/mips/mach-ath79/ar934x/clk.c
@@ -327,8 +327,8 @@
 {
 	ar934x_update_clock();
 	printf("CPU:       %8ld MHz\n", gd->cpu_clk / 1000000);
-	printf("Memory:    %8ld MHz\n", gd->mem_clk / 1000000);
-	printf("AHB:       %8ld MHz\n", gd->bus_clk / 1000000);
+	printf("Memory:    %8d MHz\n", gd->mem_clk / 1000000);
+	printf("AHB:       %8d MHz\n", gd->bus_clk / 1000000);
 	return 0;
 }
 
diff --git a/arch/mips/mach-octeon/cpu.c b/arch/mips/mach-octeon/cpu.c
index c7744e8..c771da6 100644
--- a/arch/mips/mach-octeon/cpu.c
+++ b/arch/mips/mach-octeon/cpu.c
@@ -67,7 +67,7 @@
 	gd->cpu_clk = ref_clock * FIELD_GET(RST_BOOT_C_MUL, val);
 	gd->bus_clk = ref_clock * FIELD_GET(RST_BOOT_PNR_MUL, val);
 
-	debug("%s: cpu: %lu, bus: %lu\n", __func__, gd->cpu_clk, gd->bus_clk);
+	debug("%s: cpu: %lu, bus: %u\n", __func__, gd->cpu_clk, gd->bus_clk);
 
 	return 0;
 }
diff --git a/arch/powerpc/cpu/mpc83xx/pci.c b/arch/powerpc/cpu/mpc83xx/pci.c
index 6f378c4..aef1123 100644
--- a/arch/powerpc/cpu/mpc83xx/pci.c
+++ b/arch/powerpc/cpu/mpc83xx/pci.c
@@ -45,7 +45,7 @@
 			do_fixup_by_path(blob, path, "bus-range",
 				&tmp, sizeof(tmp), 1);
 
-			tmp[0] = cpu_to_be32(gd->pci_clk);
+			tmp[0] = cpu_to_be32(gd->arch.pci_clk);
 			do_fixup_by_path(blob, path, "clock-frequency",
 				&tmp, sizeof(tmp[0]), 1);
 		}
@@ -60,7 +60,7 @@
 			do_fixup_by_path(blob, path, "bus-range",
 				&tmp, sizeof(tmp), 1);
 
-			tmp[0] = cpu_to_be32(gd->pci_clk);
+			tmp[0] = cpu_to_be32(gd->arch.pci_clk);
 			do_fixup_by_path(blob, path, "clock-frequency",
 				&tmp, sizeof(tmp[0]), 1);
 		}
diff --git a/arch/powerpc/cpu/mpc83xx/speed.c b/arch/powerpc/cpu/mpc83xx/speed.c
index 7246496..0185ab5 100644
--- a/arch/powerpc/cpu/mpc83xx/speed.c
+++ b/arch/powerpc/cpu/mpc83xx/speed.c
@@ -456,7 +456,7 @@
 #if defined(CONFIG_ARCH_MPC837X)
 	gd->arch.sata_clk = sata_clk;
 #endif
-	gd->pci_clk = pci_sync_in;
+	gd->arch.pci_clk = pci_sync_in;
 	gd->cpu_clk = gd->arch.core_clk;
 	gd->bus_clk = gd->arch.csb_clk;
 	return 0;
diff --git a/arch/powerpc/include/asm/global_data.h b/arch/powerpc/include/asm/global_data.h
index a9efbbd..cc2ce61 100644
--- a/arch/powerpc/include/asm/global_data.h
+++ b/arch/powerpc/include/asm/global_data.h
@@ -87,6 +87,8 @@
 #if defined(CONFIG_LWMON5)
 	unsigned long kbd_status;
 #endif
+	/** @pci_clk: PCI clock rate in Hz */
+	unsigned long pci_clk;
 };
 
 #include <asm-generic/global_data.h>
diff --git a/arch/x86/cpu/i386/cpu.c b/arch/x86/cpu/i386/cpu.c
index db2727d..934e98a 100644
--- a/arch/x86/cpu/i386/cpu.c
+++ b/arch/x86/cpu/i386/cpu.c
@@ -412,12 +412,6 @@
 	return 32;
 }
 
-/* Don't allow PCI region 3 to use memory in the 2-4GB memory hole */
-static void setup_pci_ram_top(void)
-{
-	gd_set_pci_ram_top(0x80000000U);
-}
-
 static void setup_mtrr(void)
 {
 	u64 mtrr_cap;
@@ -469,7 +463,6 @@
 		setup_cpu_features();
 	setup_identity();
 	setup_mtrr();
-	setup_pci_ram_top();
 
 	/* Set up the i8254 timer if required */
 	if (IS_ENABLED(CONFIG_I8254_TIMER))
@@ -483,7 +476,6 @@
 	long addr;
 
 	setup_identity();
-	setup_pci_ram_top();
 	addr = locate_coreboot_table();
 	if (addr >= 0) {
 		gd->arch.coreboot_table = addr;
diff --git a/arch/x86/cpu/intel_common/cpu_from_spl.c b/arch/x86/cpu/intel_common/cpu_from_spl.c
index 48b2ef2..5aad2ae 100644
--- a/arch/x86/cpu/intel_common/cpu_from_spl.c
+++ b/arch/x86/cpu/intel_common/cpu_from_spl.c
@@ -24,9 +24,7 @@
 	int ret;
 
 #if CONFIG_IS_ENABLED(HANDOFF) && IS_ENABLED(CONFIG_USE_HOB)
-	struct spl_handoff *ho = gd->spl_handoff;
-
-	gd->arch.hob_list = ho->arch.hob_list;
+	gd->arch.hob_list = handoff_get();
 #endif
 	ret = x86_cpu_reinit_f();
 
diff --git a/arch/x86/cpu/ivybridge/cpu.c b/arch/x86/cpu/ivybridge/cpu.c
index d71ab0a..05691a3 100644
--- a/arch/x86/cpu/ivybridge/cpu.c
+++ b/arch/x86/cpu/ivybridge/cpu.c
@@ -55,7 +55,6 @@
 
 static int ivybridge_cpu_init(void)
 {
-	struct pci_controller *hose;
 	struct udevice *bus, *dev;
 	int ret;
 
@@ -65,10 +64,6 @@
 	if (ret)
 		return ret;
 	post_code(0x72);
-	hose = dev_get_uclass_priv(bus);
-
-	/* TODO(sjg@chromium.org): Get rid of gd->hose */
-	gd->hose = hose;
 
 	ret = uclass_first_device_err(UCLASS_LPC, &dev);
 	if (ret)
diff --git a/arch/x86/lib/fsp/fsp_graphics.c b/arch/x86/lib/fsp/fsp_graphics.c
index 5f77012..ad25020 100644
--- a/arch/x86/lib/fsp/fsp_graphics.c
+++ b/arch/x86/lib/fsp/fsp_graphics.c
@@ -103,7 +103,6 @@
 	 * For IGD, it seems to be always on BAR2.
 	 */
 	vesa->phys_base_ptr = dm_pci_read_bar32(dev, 2);
-	gd->fb_base = vesa->phys_base_ptr;
 
 	ret = vesa_setup_video_priv(vesa, vesa->phys_base_ptr, uc_priv, plat);
 	if (ret)
diff --git a/arch/x86/lib/fsp2/fsp_dram.c b/arch/x86/lib/fsp2/fsp_dram.c
index 83c6d7b..a50dc98 100644
--- a/arch/x86/lib/fsp2/fsp_dram.c
+++ b/arch/x86/lib/fsp2/fsp_dram.c
@@ -59,7 +59,7 @@
 #endif
 	} else {
 #if CONFIG_IS_ENABLED(HANDOFF)
-		struct spl_handoff *ho = gd->spl_handoff;
+		struct spl_handoff *ho = handoff_get();
 
 		if (!ho) {
 			log_debug("No SPL handoff found\n");
@@ -82,7 +82,7 @@
 		return gd->ram_size;
 
 #if CONFIG_IS_ENABLED(HANDOFF)
-	struct spl_handoff *ho = gd->spl_handoff;
+	struct spl_handoff *ho = handoff_get();
 
 	log_debug("usable_ram_top = %lx\n", ho->arch.usable_ram_top);
 
diff --git a/board/freescale/ls2080ardb/eth_ls2080rdb.c b/board/freescale/ls2080ardb/eth_ls2080rdb.c
index 44d9782..7fc4fec 100644
--- a/board/freescale/ls2080ardb/eth_ls2080rdb.c
+++ b/board/freescale/ls2080ardb/eth_ls2080rdb.c
@@ -12,7 +12,7 @@
 int board_eth_init(struct bd_info *bis)
 {
 
-#ifdef CONFIG_PHY_AQUANTIA
+#if defined(CONFIG_PHY_AQUANTIA) && !defined(CONFIG_SPL_BUILD)
 	/*
 	 * Export functions to be used by AQ firmware
 	 * upload application
diff --git a/board/friendlyarm/nanopi2/board.c b/board/friendlyarm/nanopi2/board.c
index c8cbc5a..b32dfc6 100644
--- a/board/friendlyarm/nanopi2/board.c
+++ b/board/friendlyarm/nanopi2/board.c
@@ -11,6 +11,7 @@
 #ifdef CONFIG_PWM_NX
 #include <pwm.h>
 #endif
+#include <video.h>
 #include <asm/global_data.h>
 #include <asm/io.h>
 
@@ -492,12 +493,8 @@
 					 ARRAY_SIZE(splash_locations));
 	}
 
-	if (!err) {
-		char addr[64];
-
-		sprintf(addr, "0x%lx", gd->fb_base);
-		env_set("fb_addr", addr);
-	}
+	if (!err)
+		env_set_hex("fb_addr", video_get_fb());
 
 	return err;
 }
diff --git a/board/ronetix/pm9263/pm9263.c b/board/ronetix/pm9263/pm9263.c
index 1de1bd6..8125f06 100644
--- a/board/ronetix/pm9263/pm9263.c
+++ b/board/ronetix/pm9263/pm9263.c
@@ -9,6 +9,7 @@
 
 #include <config.h>
 #include <init.h>
+#include <video.h>
 #include <asm/global_data.h>
 #include <linux/sizes.h>
 #include <asm/io.h>
@@ -110,11 +111,12 @@
 #ifdef CONFIG_DISPLAY_BOARDINFO
 int checkboard (void)
 {
+	ulong fb_base = video_get_fb();
 	char *ss;
 
 	printf ("Board : Ronetix PM9263\n");
 
-	switch (gd->fb_base) {
+	switch (fb_base) {
 	case PHYS_PSRAM:
 		ss = "(PSRAM)";
 		break;
@@ -127,7 +129,7 @@
 		ss = "";
 		break;
 	}
-	printf("Video memory : 0x%08lX %s\n", gd->fb_base, ss );
+	printf("Video memory : 0x%08lX %s\n", fb_base, ss);
 
 	printf ("\n");
 	return 0;
diff --git a/board/siemens/common/board_am335x.c b/board/siemens/common/board_am335x.c
index 2a72760..e6537b0 100644
--- a/board/siemens/common/board_am335x.c
+++ b/board/siemens/common/board_am335x.c
@@ -36,7 +36,7 @@
 	/* enable early the console */
 	gd->baudrate = CONFIG_BAUDRATE;
 	serial_init();
-	gd->have_console = 1;
+	gd->flags |= GD_FLG_HAVE_CONSOLE;
 
 	siemens_ee_setup();
 	if (draco_read_eeprom() < 0)
diff --git a/cmd/bdinfo.c b/cmd/bdinfo.c
index 437ac4e..59fbaea 100644
--- a/cmd/bdinfo.c
+++ b/cmd/bdinfo.c
@@ -154,8 +154,6 @@
 	if (IS_ENABLED(CONFIG_CMD_NET))
 		print_eth();
 	bdinfo_print_num_l("fdt_blob", (ulong)map_to_sysmem(gd->fdt_blob));
-	bdinfo_print_num_l("new_fdt", (ulong)map_to_sysmem(gd->new_fdt));
-	bdinfo_print_num_l("fdt_size", (ulong)gd->fdt_size);
 	if (IS_ENABLED(CONFIG_VIDEO))
 		show_video_info();
 #if CONFIG_IS_ENABLED(MULTI_DTB_FIT)
diff --git a/cmd/sb.c b/cmd/sb.c
index 1aa5921..db485fd 100644
--- a/cmd/sb.c
+++ b/cmd/sb.c
@@ -14,8 +14,10 @@
 			 char *const argv[])
 {
 #if CONFIG_IS_ENABLED(HANDOFF)
-	if (gd->spl_handoff)
-		printf("SPL handoff magic %lx\n", gd->spl_handoff->arch.magic);
+	struct spl_handoff *handoff = handoff_get();
+
+	if (handoff)
+		printf("SPL handoff magic %lx\n", handoff->arch.magic);
 	else
 		printf("SPL handoff info not received\n");
 
diff --git a/common/board_f.c b/common/board_f.c
index 454426d..d9fe6f9 100644
--- a/common/board_f.c
+++ b/common/board_f.c
@@ -305,17 +305,6 @@
 	return 0;
 }
 
-static int setup_spl_handoff(void)
-{
-#if CONFIG_IS_ENABLED(HANDOFF)
-	gd->spl_handoff = bloblist_find(BLOBLISTT_U_BOOT_SPL_HANDOFF,
-					sizeof(struct spl_handoff));
-	debug("Found SPL hand-off info %p\n", gd->spl_handoff);
-#endif
-
-	return 0;
-}
-
 __weak int arch_cpu_init(void)
 {
 	return 0;
@@ -351,7 +340,7 @@
 
 static int setup_dest_addr(void)
 {
-	debug("Monitor len: %08lX\n", gd->mon_len);
+	debug("Monitor len: %08x\n", gd->mon_len);
 	/*
 	 * Ram is setup, size stored in gd !!
 	 */
@@ -488,7 +477,7 @@
 		gd->relocaddr &= ~(65536 - 1);
 	#endif
 
-		debug("Reserving %ldk for U-Boot at: %08lx\n",
+		debug("Reserving %dk for U-Boot at: %08lx\n",
 		      gd->mon_len >> 10, gd->relocaddr);
 	}
 
@@ -575,12 +564,15 @@
 		 * section, then it will be relocated with other data.
 		 */
 		if (gd->fdt_blob) {
-			gd->fdt_size = ALIGN(fdt_totalsize(gd->fdt_blob), 32);
+			gd->boardf->fdt_size =
+				ALIGN(fdt_totalsize(gd->fdt_blob), 32);
 
-			gd->start_addr_sp = reserve_stack_aligned(gd->fdt_size);
-			gd->new_fdt = map_sysmem(gd->start_addr_sp, gd->fdt_size);
+			gd->start_addr_sp = reserve_stack_aligned(
+				gd->boardf->fdt_size);
+			gd->boardf->new_fdt = map_sysmem(gd->start_addr_sp,
+							 gd->boardf->fdt_size);
 			debug("Reserving %lu Bytes for FDT at: %08lx\n",
-			      gd->fdt_size, gd->start_addr_sp);
+			      gd->boardf->fdt_size, gd->start_addr_sp);
 		}
 	}
 
@@ -593,7 +585,7 @@
 	int size = bootstage_get_size();
 
 	gd->start_addr_sp = reserve_stack_aligned(size);
-	gd->new_bootstage = map_sysmem(gd->start_addr_sp, size);
+	gd->boardf->new_bootstage = map_sysmem(gd->start_addr_sp, size);
 	debug("Reserving %#x Bytes for bootstage at: %08lx\n", size,
 	      gd->start_addr_sp);
 #endif
@@ -624,8 +616,8 @@
 	/* Align to a 4KB boundary for easier reading of addresses */
 	gd->start_addr_sp = ALIGN_DOWN(gd->start_addr_sp -
 				       CONFIG_BLOBLIST_SIZE_RELOC, 0x1000);
-	gd->new_bloblist = map_sysmem(gd->start_addr_sp,
-				      CONFIG_BLOBLIST_SIZE_RELOC);
+	gd->boardf->new_bloblist = map_sysmem(gd->start_addr_sp,
+					      CONFIG_BLOBLIST_SIZE_RELOC);
 #endif
 
 	return 0;
@@ -668,10 +660,10 @@
 static int reloc_fdt(void)
 {
 	if (!IS_ENABLED(CONFIG_OF_EMBED)) {
-		if (gd->new_fdt) {
-			memcpy(gd->new_fdt, gd->fdt_blob,
+		if (gd->boardf->new_fdt) {
+			memcpy(gd->boardf->new_fdt, gd->fdt_blob,
 			       fdt_totalsize(gd->fdt_blob));
-			gd->fdt_blob = gd->new_fdt;
+			gd->fdt_blob = gd->boardf->new_fdt;
 		}
 	}
 
@@ -683,9 +675,8 @@
 #ifdef CONFIG_BOOTSTAGE
 	if (gd->flags & GD_FLG_SKIP_RELOC)
 		return 0;
-	if (gd->new_bootstage) {
-		bootstage_relocate(gd->new_bootstage);
-	}
+	if (gd->boardf->new_bootstage)
+		bootstage_relocate(gd->boardf->new_bootstage);
 #endif
 
 	return 0;
@@ -702,10 +693,11 @@
 		debug("Not relocating bloblist\n");
 		return 0;
 	}
-	if (gd->new_bloblist) {
+	if (gd->boardf->new_bloblist) {
 		debug("Copying bloblist from %p to %p, size %x\n",
-		      gd->bloblist, gd->new_bloblist, gd->bloblist->total_size);
-		return bloblist_reloc(gd->new_bloblist,
+		      gd->bloblist, gd->boardf->new_bloblist,
+	gd->bloblist->total_size);
+		return bloblist_reloc(gd->boardf->new_bloblist,
 				      CONFIG_BLOBLIST_SIZE_RELOC);
 	}
 #endif
@@ -888,7 +880,6 @@
 	initf_bootstage,	/* uses its own timer, so does not need DM */
 	event_init,
 	bloblist_maybe_init,
-	setup_spl_handoff,
 #if defined(CONFIG_CONSOLE_RECORD_INIT_F)
 	console_record_init,
 #endif
@@ -1021,8 +1012,11 @@
 
 void board_init_f(ulong boot_flags)
 {
+	struct board_f boardf;
+
 	gd->flags = boot_flags;
-	gd->have_console = 0;
+	gd->flags &= ~GD_FLG_HAVE_CONSOLE;
+	gd->boardf = &boardf;
 
 	if (initcall_run_list(init_sequence_f))
 		hang();
diff --git a/common/board_r.c b/common/board_r.c
index f445803..e88b7ea 100644
--- a/common/board_r.c
+++ b/common/board_r.c
@@ -192,7 +192,7 @@
 	ulong start;
 
 #if CONFIG_IS_ENABLED(SYS_MALLOC_F)
-	debug("Pre-reloc malloc() used %#lx bytes (%ld KB)\n", gd->malloc_ptr,
+	debug("Pre-reloc malloc() used %#x bytes (%d KB)\n", gd->malloc_ptr,
 	      gd->malloc_ptr / 1024);
 #endif
 	/* The malloc area is immediately below the monitor copy in DRAM */
diff --git a/common/console.c b/common/console.c
index 63f7800..f398213 100644
--- a/common/console.c
+++ b/common/console.c
@@ -189,6 +189,7 @@
 		/* Assign the new device (leaving the existing one started) */
 		stdio_devices[file] = dev;
 
+#ifndef CONFIG_SPL_BUILD
 		/*
 		 * Update monitor functions
 		 * (to use the console stuff by other applications)
@@ -206,7 +207,7 @@
 			break;
 		}
 		break;
-
+#endif
 	default:		/* Invalid file ID */
 		error = -1;
 	}
@@ -586,7 +587,7 @@
 	if (IS_ENABLED(CONFIG_DISABLE_CONSOLE) && (gd->flags & GD_FLG_DISABLE_CONSOLE))
 		return 0;
 
-	if (!gd->have_console)
+	if (!(gd->flags & GD_FLG_HAVE_CONSOLE))
 		return 0;
 
 	ch = console_record_getc();
@@ -607,7 +608,7 @@
 	if (IS_ENABLED(CONFIG_DISABLE_CONSOLE) && (gd->flags & GD_FLG_DISABLE_CONSOLE))
 		return 0;
 
-	if (!gd->have_console)
+	if (!(gd->flags & GD_FLG_HAVE_CONSOLE))
 		return 0;
 
 	if (console_record_tstc())
@@ -715,7 +716,7 @@
 	if (IS_ENABLED(CONFIG_DISABLE_CONSOLE) && (gd->flags & GD_FLG_DISABLE_CONSOLE))
 		return;
 
-	if (!gd->have_console)
+	if (!(gd->flags & GD_FLG_HAVE_CONSOLE))
 		return pre_console_putc(c);
 
 	if (gd->flags & GD_FLG_DEVINIT) {
@@ -759,7 +760,7 @@
 	if (IS_ENABLED(CONFIG_DISABLE_CONSOLE) && (gd->flags & GD_FLG_DISABLE_CONSOLE))
 		return;
 
-	if (!gd->have_console)
+	if (!(gd->flags & GD_FLG_HAVE_CONSOLE))
 		return pre_console_puts(s);
 
 	if (gd->flags & GD_FLG_DEVINIT) {
@@ -793,7 +794,7 @@
 	if (IS_ENABLED(CONFIG_DISABLE_CONSOLE) && (gd->flags & GD_FLG_DISABLE_CONSOLE))
 		return;
 
-	if (!gd->have_console)
+	if (!(gd->flags & GD_FLG_HAVE_CONSOLE))
 		return;
 
 	if (gd->flags & GD_FLG_DEVINIT) {
@@ -872,7 +873,7 @@
 static int ctrlc_was_pressed = 0;
 int ctrlc(void)
 {
-	if (!ctrlc_disabled && gd->have_console) {
+	if (!ctrlc_disabled && (gd->flags & GD_FLG_HAVE_CONSOLE)) {
 		if (tstc()) {
 			switch (getchar()) {
 			case 0x03:		/* ^C - Control C */
@@ -1011,7 +1012,7 @@
 /* Called before relocation - use serial functions */
 int console_init_f(void)
 {
-	gd->have_console = 1;
+	gd->flags |= GD_FLG_HAVE_CONSOLE;
 
 	console_update_silent();
 
diff --git a/common/hwconfig.c b/common/hwconfig.c
index afaa6cb..25a8cd5 100644
--- a/common/hwconfig.c
+++ b/common/hwconfig.c
@@ -77,7 +77,13 @@
 
 	/* if we are passed a buffer use it, otherwise try the environment */
 	if (!env_hwconfig) {
-		if (!(gd->flags & GD_FLG_ENV_READY) && gd->env_valid != ENV_VALID) {
+#if CONFIG_IS_ENABLED(ENV_SUPPORT)
+		if (!(gd->flags & GD_FLG_ENV_READY) &&
+		    gd->env_valid != ENV_VALID)
+#else
+		if (true)
+#endif
+		{
 			printf("WARNING: Calling __hwconfig without a buffer "
 					"and before environment is ready\n");
 			return NULL;
diff --git a/common/init/handoff.c b/common/init/handoff.c
index a7cd065..86c020e 100644
--- a/common/init/handoff.c
+++ b/common/init/handoff.c
@@ -5,6 +5,7 @@
  * Copyright 2018 Google, Inc
  */
 
+#include <bloblist.h>
 #include <handoff.h>
 #include <asm/global_data.h>
 
@@ -38,3 +39,14 @@
 		bd->bi_dram[i].size = ho->ram_bank[i].size;
 	}
 }
+
+struct spl_handoff *handoff_get(void)
+{
+	struct spl_handoff *handoff;
+
+	handoff = bloblist_find(BLOBLISTT_U_BOOT_SPL_HANDOFF,
+				sizeof(struct spl_handoff));
+	debug("Found SPL hand-off info %p\n", handoff);
+
+	return handoff;
+}
diff --git a/common/malloc_simple.c b/common/malloc_simple.c
index 4e6d795..5a8ec53 100644
--- a/common/malloc_simple.c
+++ b/common/malloc_simple.c
@@ -23,7 +23,7 @@
 
 	addr = ALIGN(gd->malloc_base + gd->malloc_ptr, align);
 	new_ptr = addr + bytes - gd->malloc_base;
-	log_debug("size=%lx, ptr=%lx, limit=%lx: ", (ulong)bytes, new_ptr,
+	log_debug("size=%lx, ptr=%lx, limit=%x: ", (ulong)bytes, new_ptr,
 		  gd->malloc_limit);
 	if (new_ptr > gd->malloc_limit) {
 		log_err("alloc space exhausted\n");
@@ -87,6 +87,6 @@
 
 void malloc_simple_info(void)
 {
-	log_info("malloc_simple: %lx bytes used, %lx remain\n", gd->malloc_ptr,
+	log_info("malloc_simple: %x bytes used, %x remain\n", gd->malloc_ptr,
 		 CONFIG_VAL(SYS_MALLOC_F_LEN) - gd->malloc_ptr);
 }
diff --git a/common/spl/spl.c b/common/spl/spl.c
index 7c6e322..da110ee 100644
--- a/common/spl/spl.c
+++ b/common/spl/spl.c
@@ -782,7 +782,7 @@
 	}
 	if (CONFIG_IS_ENABLED(SYS_MALLOC_F) &&
 	    !IS_ENABLED(CONFIG_SPL_SYS_MALLOC_SIZE))
-		debug("SPL malloc() used 0x%lx bytes (%ld KB)\n",
+		debug("SPL malloc() used 0x%x bytes (%d KB)\n",
 		      gd_malloc_ptr(), gd_malloc_ptr() / 1024);
 
 	bootstage_mark_name(get_bootstage_id(false), "end phase");
@@ -838,7 +838,7 @@
 
 	serial_init();		/* serial communications setup */
 
-	gd->have_console = 1;
+	gd->flags |= GD_FLG_HAVE_CONSOLE;
 
 #if CONFIG_IS_ENABLED(BANNER_PRINT)
 	puts("\nU-Boot " SPL_TPL_NAME " " PLAIN_VERSION " (" U_BOOT_DATE " - "
@@ -901,7 +901,7 @@
 
 #if defined(CONFIG_SPL_SYS_MALLOC_SIMPLE) && CONFIG_IS_ENABLED(SYS_MALLOC_F)
 	if (CONFIG_SPL_STACK_R_MALLOC_SIMPLE_LEN) {
-		debug("SPL malloc() before relocation used 0x%lx bytes (%ld KB)\n",
+		debug("SPL malloc() before relocation used 0x%x bytes (%d KB)\n",
 		      gd->malloc_ptr, gd->malloc_ptr / 1024);
 		ptr -= CONFIG_SPL_STACK_R_MALLOC_SIMPLE_LEN;
 		gd->malloc_base = ptr;
diff --git a/doc/develop/global_data.rst b/doc/develop/global_data.rst
index d143f27..2863154 100644
--- a/doc/develop/global_data.rst
+++ b/doc/develop/global_data.rst
@@ -51,6 +51,31 @@
 whenever U-Boot is reentered. This is also relevant for the implementation of
 function tracing. For setting the value of gd function set_gd() can be used.
 
+Guidelines
+----------
+
+The global_data structure is placed in some memory which is available very early
+after boot to allow for a minimum set of global variables during system
+initialisation (until the memory controller is set up and RAM can be used). It
+is the primary data structure passed from pre-relocation U-Boot to
+post-relocation, i.e. ``from board_init_f()`` ``to board_init_r()``.
+
+The global_data struct exists for the lifetime of U-Boot. Since the struct is
+used by all architectures, fields added should be useful for most architectures.
+Fields which are only needed on one or two architectures can be placed in the
+architecture-specific ``struct arch_global_data``.
+
+In any case the struct should be kept small, since it uses precious SRAM on
+many boards.
+
+SPL also uses global data, as well as U-Boot proper, so take care to avoid
+adding fields to SPL which are not actually used by SPL. You can create
+access functions or macros in the header file to avoid filling the C code with
+#ifdefs.
+
+A flags word is available, which provides a convenient means to track the state
+of various initialisation phases within U-Boot.
+
 Global data structure
 ---------------------
 
diff --git a/doc/README.generic-board b/doc/develop/historical/generic_board.rst
similarity index 95%
rename from doc/README.generic-board
rename to doc/develop/historical/generic_board.rst
index bc35179..12550a1 100644
--- a/doc/README.generic-board
+++ b/doc/develop/historical/generic_board.rst
@@ -1,10 +1,9 @@
-# SPDX-License-Identifier: GPL-2.0+
-#
-# (C) Copyright 2014 Google, Inc
-# Simon Glass <sjg@chromium.org>
+.. SPDX-License-Identifier: GPL-2.0+
+.. (C) Copyright 2014 Google, Inc
+.. sectionauthor:: Simon Glass <sjg@chromium.org>
 
-Background
-----------
+Generic board
+-------------
 
 U-Boot traditionally had a board.c file for each architecture. This introduced
 quite a lot of duplication, with each architecture tending to do
@@ -16,7 +15,7 @@
 
 
 What has changed?
------------------
+~~~~~~~~~~~~~~~~~
 
 The main change is that the arch/<arch>/lib/board.c file is removed in
 favour of common/board_f.c (for pre-relocation init) and common/board_r.c
@@ -28,7 +27,7 @@
 
 
 Further Background
-------------------
+~~~~~~~~~~~~~~~~~~
 
 The full text of the original generic board series is reproduced below.
 
@@ -132,4 +131,6 @@
 
 Simon Glass, sjg@chromium.org
 March 2014
+
 Updated after final removal, May 2016
+
diff --git a/doc/develop/historical/index.rst b/doc/develop/historical/index.rst
new file mode 100644
index 0000000..e4462f5
--- /dev/null
+++ b/doc/develop/historical/index.rst
@@ -0,0 +1,12 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+Historical Documents
+====================
+
+This section provides documentation about major changes in U-Boot over the
+years.
+
+.. toctree::
+   :maxdepth: 1
+
+   generic_board
diff --git a/doc/develop/index.rst b/doc/develop/index.rst
index c0107a7..0d0e60a 100644
--- a/doc/develop/index.rst
+++ b/doc/develop/index.rst
@@ -99,3 +99,11 @@
    :maxdepth: 1
 
    python_cq
+
+Historical documentation
+------------------------
+
+.. toctree::
+   :maxdepth: 2
+
+   historical/index
diff --git a/drivers/clk/mpc83xx_clk.c b/drivers/clk/mpc83xx_clk.c
index a29ad0d..a43fff2 100644
--- a/drivers/clk/mpc83xx_clk.c
+++ b/drivers/clk/mpc83xx_clk.c
@@ -358,7 +358,7 @@
 	gd->mem_clk = priv->speed[MPC83XX_CLK_MEM];
 
 	if (mpc83xx_has_pci(type))
-		gd->pci_clk = priv->speed[MPC83XX_CLK_PCI];
+		gd->arch.pci_clk = priv->speed[MPC83XX_CLK_PCI];
 
 	gd->cpu_clk = priv->speed[MPC83XX_CLK_CORE];
 	gd->bus_clk = priv->speed[MPC83XX_CLK_CSB];
diff --git a/drivers/clk/rockchip/clk_rk3399.c b/drivers/clk/rockchip/clk_rk3399.c
index 24cefeb..8992404 100644
--- a/drivers/clk/rockchip/clk_rk3399.c
+++ b/drivers/clk/rockchip/clk_rk3399.c
@@ -8,6 +8,7 @@
 #include <dm.h>
 #include <dt-structs.h>
 #include <errno.h>
+#include <handoff.h>
 #include <log.h>
 #include <malloc.h>
 #include <mapmem.h>
@@ -1467,7 +1468,7 @@
 	init_clocks = true;
 #elif CONFIG_IS_ENABLED(HANDOFF)
 	if (!(gd->flags & GD_FLG_RELOC)) {
-		if (!(gd->spl_handoff))
+		if (!handoff_get())
 			init_clocks = true;
 	}
 #endif
diff --git a/drivers/video/imx/mxc_ipuv3_fb.c b/drivers/video/imx/mxc_ipuv3_fb.c
index 039b220..fdeb3ca 100644
--- a/drivers/video/imx/mxc_ipuv3_fb.c
+++ b/drivers/video/imx/mxc_ipuv3_fb.c
@@ -403,7 +403,6 @@
 		(uint32_t) fbi->fix.smem_start, fbi->fix.smem_len);
 
 	fbi->screen_size = fbi->fix.smem_len;
-	gd->fb_base = fbi->fix.smem_start;
 
 	/* Clear the screen */
 	memset((char *)fbi->screen_base, 0, fbi->fix.smem_len);
@@ -633,7 +632,6 @@
 	mmu_set_region_dcache_behaviour(fb_start, fb_end - fb_start,
 					DCACHE_WRITEBACK);
 	video_set_flush_dcache(dev, true);
-	gd->fb_base = fb_start;
 
 	return 0;
 }
diff --git a/drivers/video/mxsfb.c b/drivers/video/mxsfb.c
index 792d631..e72839c 100644
--- a/drivers/video/mxsfb.c
+++ b/drivers/video/mxsfb.c
@@ -335,7 +335,6 @@
 	mmu_set_region_dcache_behaviour(fb_start, fb_end - fb_start,
 					DCACHE_WRITEBACK);
 	video_set_flush_dcache(dev, true);
-	gd->fb_base = plat->base;
 
 	return ret;
 }
diff --git a/drivers/video/video-uclass.c b/drivers/video/video-uclass.c
index a5aa8dd..41bb764 100644
--- a/drivers/video/video-uclass.c
+++ b/drivers/video/video-uclass.c
@@ -145,13 +145,26 @@
 		*addrp -= CONFIG_VAL(VIDEO_PCI_DEFAULT_FB_SIZE);
 
 	gd->video_bottom = *addrp;
-	gd->fb_base = *addrp;
 	debug("Video frame buffers from %lx to %lx\n", gd->video_bottom,
 	      gd->video_top);
 
 	return 0;
 }
 
+ulong video_get_fb(void)
+{
+	struct udevice *dev;
+
+	uclass_find_first_device(UCLASS_VIDEO, &dev);
+	if (dev) {
+		const struct video_uc_plat *uc_plat = dev_get_uclass_plat(dev);
+
+		return uc_plat->base;
+	}
+
+	return 0;
+}
+
 int video_fill_part(struct udevice *dev, int xstart, int ystart, int xend,
 		    int yend, u32 colour)
 {
@@ -210,7 +223,6 @@
 		return -ENOENT;
 
 	gd->video_bottom = ho->fb;
-	gd->fb_base = ho->fb;
 	gd->video_top = ho->fb + ho->size;
 	debug("%s: Reserving %lx bytes at %08x as per bloblist received\n",
 	      __func__, (unsigned long)ho->size, (u32)ho->fb);
diff --git a/drivers/video/zynqmp/zynqmp_dpsub.c b/drivers/video/zynqmp/zynqmp_dpsub.c
index 1405b29..76abfea 100644
--- a/drivers/video/zynqmp/zynqmp_dpsub.c
+++ b/drivers/video/zynqmp/zynqmp_dpsub.c
@@ -49,7 +49,7 @@
 			     DPDMA_DESCRIPTOR_ADDR_EXT_SRC_ADDR_EXT_SHIFT) |
 			     (upper_32_bits((u64)&cur_desc)));
 	cur_desc.next_desr = lower_32_bits((u64)&cur_desc);
-	cur_desc.src_addr = lower_32_bits((u64)gd->fb_base);
+	cur_desc.src_addr = lower_32_bits((u64)video_get_fb());
 }
 
 static void dma_set_descriptor_address(struct udevice *dev)
@@ -2134,7 +2134,6 @@
 	dev_dbg(dev, "BPP in bits %d, bpix %d\n",
 		priv->non_live_graphics->bpp, uc_priv->bpix);
 
-	uc_priv->fb = (void *)gd->fb_base;
 	uc_priv->xsize = vidc_video_timing_modes[priv->video_mode].video_timing.h_active;
 	uc_priv->ysize = vidc_video_timing_modes[priv->video_mode].video_timing.v_active;
 	/* Calculated by core but need it for my own setup */
diff --git a/include/asm-generic/global_data.h b/include/asm-generic/global_data.h
index 19c66e1..d6c15e2 100644
--- a/include/asm-generic/global_data.h
+++ b/include/asm-generic/global_data.h
@@ -20,6 +20,7 @@
  */
 
 #ifndef __ASSEMBLY__
+#include <board_f.h>
 #include <cyclic.h>
 #include <event_internal.h>
 #include <fdtdec.h>
@@ -43,38 +44,140 @@
 	 */
 	struct bd_info *bd;
 	/**
+	 * @new_gd: pointer to relocated global data
+	 */
+	struct global_data *new_gd;
+	/**
+	 * @fdt_blob: U-Boot's own device tree, NULL if none
+	 */
+	const void *fdt_blob;
+	/**
+	 * @cur_serial_dev: current serial device
+	 */
+	struct udevice *cur_serial_dev;
+#ifndef CONFIG_SPL_BUILD
+	/**
+	 * @jt: jump table
+	 *
+	 * The jump table contains pointers to exported functions. A pointer to
+	 * the jump table is passed to standalone applications.
+	 */
+	struct jt_funcs *jt;
+	/**
+	 * @boardf: information only used before relocation
+	 */
+	struct board_f *boardf;
+#endif
+	/**
+	 * @ram_size: RAM size in bytes
+	 */
+	phys_size_t ram_size;
+	/**
+	 * @ram_top: top address of RAM used by U-Boot
+	 */
+	phys_addr_t ram_top;
+	/**
 	 * @flags: global data flags
 	 *
 	 * See &enum gd_flags
 	 */
 	unsigned long flags;
 	/**
+	 * @cpu_clk: CPU clock rate in Hz
+	 */
+	unsigned long cpu_clk;
+#if CONFIG_IS_ENABLED(ENV_SUPPORT)
+	/**
+	 * @env_addr: address of environment structure
+	 *
+	 * @env_addr contains the address of the structure holding the
+	 * environment variables.
+	 */
+	unsigned long env_addr;
+#endif /* ENV_SUPPORT */
+	/**
+	 * @ram_base: base address of RAM used by U-Boot
+	 */
+	unsigned long ram_base;
+	/**
+	 * @relocaddr: start address of U-Boot in RAM
+	 *
+	 * After relocation this field indicates the address to which U-Boot
+	 * has been relocated. It can be displayed using the bdinfo command.
+	 * Its value is needed to display the source code when debugging with
+	 * GDB using the 'add-symbol-file u-boot <relocaddr>' command.
+	 */
+	unsigned long relocaddr;
+	/**
+	 * @irq_sp: IRQ stack pointer
+	 */
+	unsigned long irq_sp;
+	/**
+	 * @start_addr_sp: initial stack pointer address
+	 */
+	unsigned long start_addr_sp;
+	/**
+	 * @reloc_off: relocation offset
+	 */
+	unsigned long reloc_off;
+	/**
+	 * @bus_clk: platform clock rate in Hz
+	 */
+	unsigned int bus_clk;
+	/**
+	 * @mem_clk: memory clock rate in Hz
+	 */
+	unsigned int mem_clk;
+	/**
+	 * @mon_len: monitor length in bytes
+	 */
+	unsigned int mon_len;
+	/**
 	 * @baudrate: baud rate of the serial interface
 	 */
 	unsigned int baudrate;
+#if CONFIG_IS_ENABLED(ENV_SUPPORT)
 	/**
-	 * @cpu_clk: CPU clock rate in Hz
+	 * @env_has_init: bit mask indicating environment locations
+	 *
+	 * &enum env_location defines which bit relates to which location
 	 */
-	unsigned long cpu_clk;
+	unsigned short env_has_init;
 	/**
-	 * @bus_clk: platform clock rate in Hz
+	 * @env_valid: environment is valid
+	 *
+	 * See &enum env_valid
 	 */
-	unsigned long bus_clk;
+	unsigned char env_valid;
 	/**
-	 * @pci_clk: PCI clock rate in Hz
+	 * @env_load_prio: priority of the loaded environment
 	 */
-	/* We cannot bracket this with CONFIG_PCI due to mpc5xxx */
-	unsigned long pci_clk;
+	char env_load_prio;
 	/**
-	 * @mem_clk: memory clock rate in Hz
+	 * @env_buf: buffer for env_get() before reloc
 	 */
-	unsigned long mem_clk;
-#if CONFIG_IS_ENABLED(VIDEO)
+	char env_buf[32];
+#endif /* ENV_SUPPORT */
 	/**
-	 * @fb_base: base address of frame buffer memory
+	 * @fdt_src: Source of FDT
 	 */
-	unsigned long fb_base;
-#endif
+	enum fdt_source_t fdt_src;
+	/**
+	 * @arch: architecture-specific data
+	 */
+	struct arch_global_data arch;
+	/**
+	 * @dmtag_list: List of DM tags
+	 */
+	struct list_head dmtag_list;
+	/**
+	 * @timebase_h: high 32 bits of timer
+	 */
+	unsigned int timebase_h;
+	/**
+	 * @timebase_l: low 32 bits of timer
+	 */
+	unsigned int timebase_l;
 #if defined(CONFIG_POST)
 	/**
 	 * @post_log_word: active POST tests
@@ -104,15 +207,6 @@
 	 */
 	unsigned long board_type;
 #endif
-	/**
-	 * @have_console: console is available
-	 *
-	 * A value of 1 indicates that serial_init() was called and a console
-	 * is available.
-	 * A value of 0 indicates that console input and output drivers shall
-	 * not be called.
-	 */
-	unsigned long have_console;
 #if CONFIG_IS_ENABLED(PRE_CONSOLE_BUFFER)
 	/**
 	 * @precon_buf_idx: pre-console buffer index
@@ -126,71 +220,6 @@
 	 */
 	long precon_buf_idx;
 #endif
-	/**
-	 * @env_addr: address of environment structure
-	 *
-	 * @env_addr contains the address of the structure holding the
-	 * environment variables.
-	 */
-	unsigned long env_addr;
-	/**
-	 * @env_valid: environment is valid
-	 *
-	 * See &enum env_valid
-	 */
-	unsigned long env_valid;
-	/**
-	 * @env_has_init: bit mask indicating environment locations
-	 *
-	 * &enum env_location defines which bit relates to which location
-	 */
-	unsigned long env_has_init;
-	/**
-	 * @env_load_prio: priority of the loaded environment
-	 */
-	int env_load_prio;
-	/**
-	 * @ram_base: base address of RAM used by U-Boot
-	 */
-	unsigned long ram_base;
-	/**
-	 * @ram_top: top address of RAM used by U-Boot
-	 */
-	phys_addr_t ram_top;
-	/**
-	 * @relocaddr: start address of U-Boot in RAM
-	 *
-	 * After relocation this field indicates the address to which U-Boot
-	 * has been relocated. It can be displayed using the bdinfo command.
-	 * Its value is needed to display the source code when debugging with
-	 * GDB using the 'add-symbol-file u-boot <relocaddr>' command.
-	 */
-	unsigned long relocaddr;
-	/**
-	 * @ram_size: RAM size in bytes
-	 */
-	phys_size_t ram_size;
-	/**
-	 * @mon_len: monitor length in bytes
-	 */
-	unsigned long mon_len;
-	/**
-	 * @irq_sp: IRQ stack pointer
-	 */
-	unsigned long irq_sp;
-	/**
-	 * @start_addr_sp: initial stack pointer address
-	 */
-	unsigned long start_addr_sp;
-	/**
-	 * @reloc_off: relocation offset
-	 */
-	unsigned long reloc_off;
-	/**
-	 * @new_gd: pointer to relocated global data
-	 */
-	struct global_data *new_gd;
-
 #ifdef CONFIG_DM
 	/**
 	 * @dm_root: root instance for Driver Model
@@ -235,46 +264,18 @@
 	 */
 	struct udevice *timer;
 #endif
-	/**
-	 * @fdt_blob: U-Boot's own device tree, NULL if none
-	 */
-	const void *fdt_blob;
-	/**
-	 * @new_fdt: relocated device tree
-	 */
-	void *new_fdt;
-	/**
-	 * @fdt_size: space reserved for relocated device space
-	 */
-	unsigned long fdt_size;
-	/**
-	 * @fdt_src: Source of FDT
-	 */
-	enum fdt_source_t fdt_src;
 #if CONFIG_IS_ENABLED(OF_LIVE)
 	/**
 	 * @of_root: root node of the live tree
 	 */
 	struct device_node *of_root;
 #endif
-
 #if CONFIG_IS_ENABLED(MULTI_DTB_FIT)
 	/**
 	 * @multi_dtb_fit: pointer to uncompressed multi-dtb FIT image
 	 */
 	const void *multi_dtb_fit;
 #endif
-	/**
-	 * @jt: jump table
-	 *
-	 * The jump table contains pointers to exported functions. A pointer to
-	 * the jump table is passed to standalone applications.
-	 */
-	struct jt_funcs *jt;
-	/**
-	 * @env_buf: buffer for env_get() before reloc
-	 */
-	char env_buf[32];
 #ifdef CONFIG_TRACE
 	/**
 	 * @trace_buff: trace buffer
@@ -290,18 +291,10 @@
 	 */
 	int cur_i2c_bus;
 #endif
-	/**
-	 * @timebase_h: high 32 bits of timer
-	 */
-	unsigned int timebase_h;
-	/**
-	 * @timebase_l: low 32 bits of timer
-	 */
-	unsigned int timebase_l;
+#if CONFIG_IS_ENABLED(CMD_BDINFO_EXTRA)
 	/**
 	 * @malloc_start: start of malloc() region
 	 */
-#if CONFIG_IS_ENABLED(CMD_BDINFO_EXTRA)
 	unsigned long malloc_start;
 #endif
 #if CONFIG_IS_ENABLED(SYS_MALLOC_F)
@@ -310,43 +303,14 @@
 	 */
 	unsigned long malloc_base;
 	/**
-	 * @malloc_limit: limit address of early malloc()
+	 * @malloc_limit: maximum size of early malloc()
 	 */
-	unsigned long malloc_limit;
+	unsigned int malloc_limit;
 	/**
-	 * @malloc_ptr: current address of early malloc()
+	 * @malloc_ptr: currently used bytes of early malloc()
 	 */
-	unsigned long malloc_ptr;
+	unsigned int malloc_ptr;
 #endif
-#ifdef CONFIG_PCI
-	/**
-	 * @hose: PCI hose for early use
-	 */
-	struct pci_controller *hose;
-	/**
-	 * @pci_ram_top: top of region accessible to PCI
-	 */
-	phys_addr_t pci_ram_top;
-#endif
-#ifdef CONFIG_PCI_BOOTDELAY
-	/**
-	 * @pcidelay_done: delay time before scanning of PIC hose expired
-	 *
-	 * If CONFIG_PCI_BOOTDELAY=y, pci_hose_scan() waits for the number of
-	 * milliseconds defined by environment variable pcidelay before
-	 * scanning. Once this delay has expired the flag @pcidelay_done
-	 * is set to 1.
-	 */
-	int pcidelay_done;
-#endif
-	/**
-	 * @cur_serial_dev: current serial device
-	 */
-	struct udevice *cur_serial_dev;
-	/**
-	 * @arch: architecture-specific data
-	 */
-	struct arch_global_data arch;
 #ifdef CONFIG_CONSOLE_RECORD
 	/**
 	 * @console_out: output buffer for console recording
@@ -377,13 +341,19 @@
 	 * @bootstage: boot stage information
 	 */
 	struct bootstage_data *bootstage;
-	/**
-	 * @new_bootstage: relocated boot stage information
-	 */
-	struct bootstage_data *new_bootstage;
 #endif
 #ifdef CONFIG_LOG
 	/**
+	 * @log_head: list of logging devices
+	 */
+	struct list_head log_head;
+	/**
+	 * @log_fmt: bit mask for logging format
+	 *
+	 * The @log_fmt bit mask selects the fields to be shown in log messages.
+	 * &enum log_fmt defines the bits of the bit mask.
+	 */
+	/**
 	 * @log_drop_count: number of dropped log messages
 	 *
 	 * This counter is incremented for each log message which can not
@@ -397,60 +367,39 @@
 	 * For logging devices without filters @default_log_level defines the
 	 * logging level, cf. &enum log_level_t.
 	 */
-	int default_log_level;
-	/**
-	 * @log_head: list of logging devices
-	 */
-	struct list_head log_head;
-	/**
-	 * @log_fmt: bit mask for logging format
-	 *
-	 * The @log_fmt bit mask selects the fields to be shown in log messages.
-	 * &enum log_fmt defines the bits of the bit mask.
-	 */
-	int log_fmt;
-
-	/**
-	 * @processing_msg: a log message is being processed
-	 *
-	 * This flag is used to suppress the creation of additional messages
-	 * while another message is being processed.
-	 */
-	bool processing_msg;
+	char default_log_level;
+	char log_fmt;
 	/**
 	 * @logc_prev: logging category of previous message
 	 *
 	 * This value is used as logging category for continuation messages.
 	 */
-	int logc_prev;
+	unsigned char logc_prev;
 	/**
 	 * @logl_prev: logging level of the previous message
 	 *
 	 * This value is used as logging level for continuation messages.
 	 */
-	int logl_prev;
+	unsigned char logl_prev;
 	/**
 	 * @log_cont: Previous log line did not finished wtih \n
 	 *
 	 * This allows for chained log messages on the same line
 	 */
 	bool log_cont;
+	/**
+	 * @processing_msg: a log message is being processed
+	 *
+	 * This flag is used to suppress the creation of additional messages
+	 * while another message is being processed.
+	 */
+	bool processing_msg;
 #endif
 #if CONFIG_IS_ENABLED(BLOBLIST)
 	/**
 	 * @bloblist: blob list information
 	 */
 	struct bloblist_hdr *bloblist;
-	/**
-	 * @new_bloblist: relocated blob list information
-	 */
-	struct bloblist_hdr *new_bloblist;
-#endif
-#if CONFIG_IS_ENABLED(HANDOFF)
-	/**
-	 * @spl_handoff: SPL hand-off information
-	 */
-	struct spl_handoff *spl_handoff;
 #endif
 #if defined(CONFIG_TRANSLATION_OFFSET)
 	/**
@@ -488,10 +437,6 @@
 	 */
 	struct hlist_head cyclic_list;
 #endif
-	/**
-	 * @dmtag_list: List of DM tags
-	 */
-	struct list_head dmtag_list;
 #if CONFIG_IS_ENABLED(UPL)
 	/**
 	 * @upl: Universal Payload-handoff information
@@ -585,12 +530,6 @@
 #define gd_set_malloc_start(val)
 #endif
 
-#if CONFIG_IS_ENABLED(PCI)
-#define gd_set_pci_ram_top(val)	gd->pci_ram_top = val
-#else
-#define gd_set_pci_ram_top(val)
-#endif
-
 #if CONFIG_VAL(SYS_MALLOC_F_LEN)
 #define gd_malloc_ptr()		gd->malloc_ptr
 #else
@@ -720,6 +659,12 @@
 	 * @GD_FLG_UPL: Read/write a Universal Payload (UPL) handoff
 	 */
 	GD_FLG_UPL = 0x4000000,
+	/**
+	 * @GD_FLG_HAVE_CONSOLE: serial_init() was called and a console
+	 * is available. When not set, indicates that console input and output
+	 * drivers shall not be called.
+	 */
+	GD_FLG_HAVE_CONSOLE = 0x8000000,
 };
 
 #endif /* __ASSEMBLY__ */
diff --git a/include/board_f.h b/include/board_f.h
new file mode 100644
index 0000000..05aa515
--- /dev/null
+++ b/include/board_f.h
@@ -0,0 +1,35 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright 2024 Google LLC
+ * Written by: Simon Glass <sjg@chromeium.org>
+ */
+
+#ifndef __BOARD_F
+#define __BOARD_F
+
+/**
+ * struct board_f: Information used only before relocation
+ *
+ * This struct is set up in board_init_f() and used to deal with relocation. It
+ * is not available after relocation.
+ */
+struct board_f {
+	/**
+	 * @new_fdt: relocated device tree
+	 */
+	void *new_fdt;
+	/**
+	 * @fdt_size: space reserved for relocated device space
+	 */
+	unsigned long fdt_size;
+	/**
+	 * @new_bootstage: relocated boot stage information
+	 */
+	struct bootstage_data *new_bootstage;
+	/**
+	 * @new_bloblist: relocated blob list information
+	 */
+	struct bloblist_hdr *new_bloblist;
+};
+
+#endif
diff --git a/include/env_default.h b/include/env_default.h
index 076ffdd..aa3dd40 100644
--- a/include/env_default.h
+++ b/include/env_default.h
@@ -82,9 +82,6 @@
 #ifdef	CONFIG_SYS_LOAD_ADDR
 	"loadaddr="	__stringify(CONFIG_SYS_LOAD_ADDR)"\0"
 #endif
-#if defined(CONFIG_PCI_BOOTDELAY) && (CONFIG_PCI_BOOTDELAY > 0)
-	"pcidelay="	__stringify(CONFIG_PCI_BOOTDELAY)"\0"
-#endif
 #ifdef	CONFIG_ENV_VARS_UBOOT_CONFIG
 	"arch="		CONFIG_SYS_ARCH			"\0"
 #ifdef CONFIG_SYS_CPU
diff --git a/include/env_internal.h b/include/env_internal.h
index 0a267e3..c1c0727 100644
--- a/include/env_internal.h
+++ b/include/env_internal.h
@@ -100,6 +100,7 @@
 #include <env_flags.h>
 #include <search.h>
 
+/* this is stored as bits in gd->env_has_init so is limited to 16 entries */
 enum env_location {
 	ENVL_UNKNOWN,
 	ENVL_EEPROM,
diff --git a/include/handoff.h b/include/handoff.h
index c0ae7b1..0072ea8 100644
--- a/include/handoff.h
+++ b/include/handoff.h
@@ -32,6 +32,13 @@
 void handoff_load_dram_banks(struct spl_handoff *ho);
 
 /**
+ * handoff_get() - Get the SPL handoff information
+ *
+ * Return: Pointer to SPL handoff if received, else NULL
+ */
+struct spl_handoff *handoff_get(void);
+
+/**
  * handoff_arch_save() - Save arch-specific info into the handoff area
  *
  * This is defined to an empty function by default, but arch-specific code can
diff --git a/include/video.h b/include/video.h
index 4013a94..606c8a3 100644
--- a/include/video.h
+++ b/include/video.h
@@ -420,4 +420,15 @@
  */
 int video_reserve_from_bloblist(struct video_handoff *ho);
 
+/**
+ * video_get_fb() - Get the first framebuffer address
+ *
+ * This function does not probe video devices, so can only be used after a video
+ * device has been activated.
+ *
+ * Return: address of the framebuffer of the first video device found, or 0 if
+ * there is no device
+ */
+ulong video_get_fb(void);
+
 #endif
diff --git a/lib/asm-offsets.c b/lib/asm-offsets.c
index 4e2dbda..b6bbcbf 100644
--- a/lib/asm-offsets.c
+++ b/lib/asm-offsets.c
@@ -44,7 +44,9 @@
 
 	DEFINE(GD_NEW_GD, offsetof(struct global_data, new_gd));
 
+#if CONFIG_IS_ENABLED(ENV_SUPPORT)
 	DEFINE(GD_ENV_ADDR, offsetof(struct global_data, env_addr));
+#endif
 
 	return 0;
 }
diff --git a/test/cmd/bdinfo.c b/test/cmd/bdinfo.c
index 027848c..5913905 100644
--- a/test/cmd/bdinfo.c
+++ b/test/cmd/bdinfo.c
@@ -185,9 +185,6 @@
 	ut_assert(map_to_sysmem(gd->fdt_blob) == env_get_hex("fdtcontroladdr", 0x1234));
 	ut_assertok(test_num_l(uts, "fdt_blob",
 			       (ulong)map_to_sysmem(gd->fdt_blob)));
-	ut_assertok(test_num_l(uts, "new_fdt",
-			       (ulong)map_to_sysmem(gd->new_fdt)));
-	ut_assertok(test_num_l(uts, "fdt_size", (ulong)gd->fdt_size));
 
 	if (IS_ENABLED(CONFIG_VIDEO))
 		ut_assertok(test_video_info(uts));
diff --git a/test/log/log_test.c b/test/log/log_test.c
index 7ef8994..18f8a2d 100644
--- a/test/log/log_test.c
+++ b/test/log/log_test.c
@@ -379,9 +379,9 @@
 
 	ut_assertok(console_record_reset_enable());
 	log_run();
-	check_log_entries_flags_levels(EXPECT_LOG | EXPECT_DIRECT | EXPECT_FORCE,
-				       LOGL_WARNING + 1,
-				       min(gd->default_log_level, LOGL_INFO));
+	check_log_entries_flags_levels(
+		EXPECT_LOG | EXPECT_DIRECT | EXPECT_FORCE,
+		LOGL_WARNING + 1, min((int)gd->default_log_level, LOGL_INFO));
 
 	ut_assertok(log_remove_filter("console", filt1));
 	ut_assertok(log_remove_filter("console", filt2));