[Concept,08/16] boot: pxe: Add a test for fdtdir path-resolution

Message ID 20260109015323.3411528-9-sjg@u-boot.org
State New
Headers
Series test: pxe: Add some decent tests for the PXE/extlinux parser |

Commit Message

Simon Glass Jan. 9, 2026, 1:53 a.m. UTC
  From: Simon Glass <simon.glass@canonical.com>

Add a test that verifies fdtdir path-construction via sysboot:
- fdtdir with fdtfile env var uses the variable directly
- fdtdir with soc/board env vars constructs {soc}-{board}.dtb

The test runs sysboot twice with different environment settings and
checks console output to verify the correct FDT paths are constructed.

Co-developed-by: Claude Opus 4.5 <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
---

 test/boot/pxe.c                  | 93 ++++++++++++++++++++++++++++++++
 test/py/tests/test_pxe_parser.py | 65 ++++++++++++++++++++++
 2 files changed, 158 insertions(+)
  

Patch

diff --git a/test/boot/pxe.c b/test/boot/pxe.c
index 3d560fd9ade..a924247bf98 100644
--- a/test/boot/pxe.c
+++ b/test/boot/pxe.c
@@ -318,3 +318,96 @@  static int pxe_test_sysboot_norun(struct unit_test_state *uts)
 PXE_TEST_ARGS(pxe_test_sysboot_norun, UTF_CONSOLE | UTF_MANUAL,
 	{ "fs_image", UT_ARG_STR },
 	{ "cfg_path", UT_ARG_STR });
+
+/**
+ * Test fdtdir path resolution via sysboot
+ *
+ * This test verifies fdtdir path construction by running sysboot and
+ * checking console output:
+ * 1. fdtdir with fdtfile env var - uses fdtfile value directly
+ * 2. fdtdir with soc/board env vars - constructs {soc}-{board}.dtb
+ * 3. fdtdir without trailing slash - slash is inserted
+ */
+static int pxe_test_fdtdir_norun(struct unit_test_state *uts)
+{
+	const char *fs_image = ut_str(PXE_ARG_FS_IMAGE);
+	const char *cfg_path = ut_str(PXE_ARG_CFG_PATH);
+	void *fdt;
+
+	ut_assertnonnull(fs_image);
+	ut_assertnonnull(cfg_path);
+
+	/* Bind the filesystem image */
+	ut_assertok(run_commandf("host bind 0 %s", fs_image));
+
+	/*
+	 * Test 1: fdtdir with fdtfile env var
+	 * The first label uses fdtdir=/dtb/ and we set fdtfile=test-board.dtb
+	 * so it should retrieve /dtb/test-board.dtb
+	 */
+	ut_assertok(env_set_hex("pxefile_addr_r", PXE_LOAD_ADDR));
+	ut_assertok(env_set_hex("kernel_addr_r", PXE_KERNEL_ADDR));
+	ut_assertok(env_set_hex("fdt_addr_r", PXE_FDT_ADDR));
+	ut_assertok(env_set_hex("fdtoverlay_addr_r", PXE_OVERLAY_ADDR));
+	ut_assertok(env_set("fdtfile", "test-board.dtb"));
+	ut_assertok(env_set("bootfile", cfg_path));
+
+	ut_assertok(run_commandf("sysboot host 0:0 any %x %s",
+				 PXE_LOAD_ADDR, cfg_path));
+
+	/* Skip to the boot attempt - first label is fdtfile-test */
+	ut_assert_skip_to_line("Enter choice: 1:\tTest fdtfile env var");
+
+	/* Verify fdtdir used fdtfile env var to construct path */
+	ut_assert_nextline("Retrieving file: /vmlinuz");
+	ut_assert_nextline("append: console=ttyS0");
+	ut_assert_nextline("Retrieving file: /dtb/test-board.dtb");
+	ut_assert_nextline("Retrieving file: /dtb/overlay1.dtbo");
+
+	/* Boot fails but we verified the path construction */
+	ut_assert_nextline("Unrecognized zImage");
+	ut_assert_nextlinen("       unmap_physmem");
+
+	/* Verify FDT was loaded correctly */
+	fdt = map_sysmem(PXE_FDT_ADDR, 0);
+	ut_assertok(fdt_check_header(fdt));
+
+	/*
+	 * Test 2: fdtdir with soc/board env vars (no fdtfile)
+	 * Clear fdtfile and set soc/board - the default label (fdtfile-test)
+	 * will now construct the path from soc-board: /dtb/tegra-jetson.dtb
+	 */
+	ut_assertok(env_set("fdtfile", NULL));  /* Clear fdtfile */
+	ut_assertok(env_set("soc", "tegra"));
+	ut_assertok(env_set("board", "jetson"));
+
+	ut_assertok(run_commandf("sysboot host 0:0 any %x %s",
+				 PXE_LOAD_ADDR, cfg_path));
+
+	/* Still boots default label, but now uses soc-board path construction */
+	ut_assert_skip_to_line("Enter choice: 1:\tTest fdtfile env var");
+
+	/* Verify fdtdir constructed path from soc-board */
+	ut_assert_nextline("Retrieving file: /vmlinuz");
+	ut_assert_nextline("append: console=ttyS0");
+	ut_assert_nextline("Retrieving file: /dtb/tegra-jetson.dtb");
+	ut_assert_nextline("Retrieving file: /dtb/overlay1.dtbo");
+
+	/* Boot fails but we verified the path construction */
+	ut_assert_nextline("Unrecognized zImage");
+	ut_assert_nextlinen("       unmap_physmem");
+
+	/* Verify FDT was loaded */
+	fdt = map_sysmem(PXE_FDT_ADDR, 0);
+	ut_asserteq(FDT_MAGIC, fdt_magic(fdt));
+
+	/* Clean up env vars */
+	env_set("fdtfile", NULL);
+	env_set("soc", NULL);
+	env_set("board", NULL);
+
+	return 0;
+}
+PXE_TEST_ARGS(pxe_test_fdtdir_norun, UTF_CONSOLE | UTF_MANUAL,
+	{ "fs_image", UT_ARG_STR },
+	{ "cfg_path", UT_ARG_STR });
diff --git a/test/py/tests/test_pxe_parser.py b/test/py/tests/test_pxe_parser.py
index c2467f70f5d..ee8acb8c674 100644
--- a/test/py/tests/test_pxe_parser.py
+++ b/test/py/tests/test_pxe_parser.py
@@ -269,6 +269,64 @@  def pxe_image(u_boot_config):
         fsh.cleanup()
 
 
+@pytest.fixture
+def pxe_fdtdir_image(u_boot_config):
+    """Create a filesystem image with fdtdir-based configuration
+
+    This tests the fdtdir path-resolution logic where the FDT filename
+    is constructed from environment variables.
+    """
+    fsh = FsHelper(u_boot_config, 'vfat', 4, prefix='pxe_fdtdir')
+    fsh.setup()
+
+    # Create labels using fdtdir instead of explicit fdt path
+    labels = [
+        {
+            'name': 'fdtfile-test',
+            'menu': 'Test fdtfile env var',
+            'kernel': '/vmlinuz',
+            'append': 'console=ttyS0',
+            'fdtdir': '/dtb/',  # Will use fdtfile env var
+            'fdtoverlays': '/dtb/overlay1.dtbo',
+            'default': True,
+        },
+        {
+            'name': 'socboard-test',
+            'menu': 'Test soc/board construction',
+            'kernel': '/vmlinuz',
+            'append': 'console=ttyS0',
+            'fdtdir': '/dtb',  # No trailing slash - tests slash insertion
+        },
+    ]
+
+    cfg_path = create_extlinux_conf(fsh.srcdir, labels)
+
+    # Create DTB directory with files for different naming conventions
+    dtbdir = os.path.join(fsh.srcdir, 'dtb')
+    os.makedirs(dtbdir, exist_ok=True)
+
+    # DTB for fdtfile env var test (fdtfile=test-board.dtb)
+    compile_dts(BASE_DTS, os.path.join(dtbdir, 'test-board.dtb'))
+
+    # DTB for soc-board construction (soc=tegra, board=jetson)
+    compile_dts(BASE_DTS, os.path.join(dtbdir, 'tegra-jetson.dtb'))
+
+    # Overlay for fdtdir test
+    compile_dts(OVERLAY1_DTS, os.path.join(dtbdir, 'overlay1.dtbo'),
+                is_overlay=True)
+
+    # Create dummy kernel
+    with open(os.path.join(fsh.srcdir, 'vmlinuz'), 'wb') as fd:
+        fd.write(b'kernel')
+        fd.write(b'\x00' * (1024 - 6))
+
+    fsh.mk_fs()
+
+    yield fsh.fs_img, cfg_path
+
+    fsh.cleanup()
+
+
 @pytest.mark.boardspec('sandbox')
 @pytest.mark.requiredtool('dtc')
 class TestPxeParser:
@@ -287,3 +345,10 @@  class TestPxeParser:
         with ubman.log.section('Test PXE sysboot'):
             ubman.run_ut('pxe', 'pxe_test_sysboot',
                          fs_image=fs_img, cfg_path=cfg_path)
+
+    def test_pxe_fdtdir(self, ubman, pxe_fdtdir_image):
+        """Test fdtdir path resolution with fdtfile and soc/board env vars"""
+        fs_img, cfg_path = pxe_fdtdir_image
+        with ubman.log.section('Test PXE fdtdir'):
+            ubman.run_ut('pxe', 'pxe_test_fdtdir',
+                         fs_image=fs_img, cfg_path=cfg_path)