[Concept,09/16] boot: pxe: Add a test for FDT error-handling

Message ID 20260109015323.3411528-10-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 error-handling when FDT files are missing:

1. Explicit FDT not found - when a label specifies an explicit fdt= path
   that doesn't exist, the label fails and sysboot moves to the next
   label

2. fdtdir FDT not found - when fdtdir is specified but the constructed
   FDT path doesn't exist, sysboot warns but continues to boot attempt

The test uses sysboot and verifies behaviour through console output.

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

 test/boot/pxe.c                  | 72 ++++++++++++++++++++++++++++++++
 test/py/tests/test_pxe_parser.py | 68 ++++++++++++++++++++++++++++++
 2 files changed, 140 insertions(+)
  

Patch

diff --git a/test/boot/pxe.c b/test/boot/pxe.c
index a924247bf98..3ccb0c977e9 100644
--- a/test/boot/pxe.c
+++ b/test/boot/pxe.c
@@ -411,3 +411,75 @@  static int pxe_test_fdtdir_norun(struct unit_test_state *uts)
 PXE_TEST_ARGS(pxe_test_fdtdir_norun, UTF_CONSOLE | UTF_MANUAL,
 	{ "fs_image", UT_ARG_STR },
 	{ "cfg_path", UT_ARG_STR });
+
+/**
+ * Test error handling for missing FDT files via sysboot
+ *
+ * This test verifies error handling by running sysboot and checking
+ * console output:
+ * 1. Explicit FDT not found - label fails with error, tries next label
+ * 2. fdtdir FDT not found - warns but continues to boot attempt
+ */
+static int pxe_test_errors_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);
+
+	ut_assertnonnull(fs_image);
+	ut_assertnonnull(cfg_path);
+
+	/* Bind the filesystem image */
+	ut_assertok(run_commandf("host bind 0 %s", fs_image));
+
+	/* Set up environment for loading */
+	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", "missing.dtb"));  /* For fdtdir test */
+	ut_assertok(env_set("bootfile", cfg_path));
+
+	/*
+	 * Run sysboot - it will try labels in sequence:
+	 * 1. missing-fdt: fails because explicit FDT doesn't exist
+	 * 2. missing-fdtdir: warns about missing FDT but attempts boot
+	 * 3. missing-overlay: loads FDT, warns about missing overlay, boots
+	 */
+	ut_assertok(run_commandf("sysboot host 0:0 any %x %s",
+				 PXE_LOAD_ADDR, cfg_path));
+
+	/*
+	 * Test 1: Explicit FDT file not found
+	 * First label (missing-fdt) has fdt=/dtb/nonexistent.dtb
+	 * Should fail and move to next label
+	 */
+	ut_assert_skip_to_line("Enter choice: 1:\tMissing explicit FDT");
+	ut_assert_nextline("Retrieving file: /vmlinuz");
+	ut_assert_nextline("Retrieving file: /dtb/nonexistent.dtb");
+	ut_assert_nextline("Skipping missing-fdt for failure retrieving FDT");
+
+	/*
+	 * Test 2: fdtdir with missing FDT file
+	 * Second label (missing-fdtdir) has fdtdir=/dtb/ but fdtfile=missing.dtb
+	 * Should warn but continue to boot attempt
+	 */
+	ut_assert_nextline("2:\tMissing fdtdir FDT");
+	ut_assert_nextline("Retrieving file: /vmlinuz");
+	ut_assert_nextline("Retrieving file: /dtb/missing.dtb");
+	ut_assert_nextline("Skipping fdtdir /dtb/ for failure retrieving dts");
+
+	/*
+	 * Boot attempt without FDT - sandbox can't boot, but this verifies
+	 * that label loading continued despite missing fdtdir FDT
+	 */
+	ut_assert_nextline("Unrecognized zImage");
+	ut_assert_nextlinen("       unmap_physmem");
+
+	/* Clean up env vars */
+	env_set("fdtfile", NULL);
+
+	return 0;
+}
+PXE_TEST_ARGS(pxe_test_errors_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 ee8acb8c674..2afe3a93b86 100644
--- a/test/py/tests/test_pxe_parser.py
+++ b/test/py/tests/test_pxe_parser.py
@@ -327,6 +327,67 @@  def pxe_fdtdir_image(u_boot_config):
     fsh.cleanup()
 
 
+@pytest.fixture
+def pxe_error_image(u_boot_config):
+    """Create a filesystem image for testing error handling
+
+    This tests various error conditions:
+    - Explicit FDT file that doesn't exist (should fail label)
+    - fdtdir with missing FDT file (should continue)
+    - Missing overlay file (should continue)
+    """
+    fsh = FsHelper(u_boot_config, 'vfat', 4, prefix='pxe_error')
+    fsh.setup()
+
+    labels = [
+        {
+            # Explicit FDT that doesn't exist - should fail this label
+            'name': 'missing-fdt',
+            'menu': 'Missing explicit FDT',
+            'kernel': '/vmlinuz',
+            'fdt': '/dtb/nonexistent.dtb',
+            'default': True,
+        },
+        {
+            # fdtdir with missing FDT - should warn but continue
+            'name': 'missing-fdtdir',
+            'menu': 'Missing fdtdir FDT',
+            'kernel': '/vmlinuz',
+            'fdtdir': '/dtb/',
+        },
+        {
+            # Valid FDT but missing overlay - should continue
+            'name': 'missing-overlay',
+            'menu': 'Missing overlay',
+            'kernel': '/vmlinuz',
+            'fdt': '/dtb/board.dtb',
+            'fdtoverlays': '/dtb/nonexistent.dtbo /dtb/overlay1.dtbo',
+        },
+    ]
+
+    cfg_path = create_extlinux_conf(fsh.srcdir, labels)
+
+    # Create DTB directory with only some files
+    dtbdir = os.path.join(fsh.srcdir, 'dtb')
+    os.makedirs(dtbdir, exist_ok=True)
+
+    # Only create board.dtb and overlay1.dtbo - others are missing
+    compile_dts(BASE_DTS, os.path.join(dtbdir, 'board.dtb'))
+    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:
@@ -352,3 +413,10 @@  class TestPxeParser:
         with ubman.log.section('Test PXE fdtdir'):
             ubman.run_ut('pxe', 'pxe_test_fdtdir',
                          fs_image=fs_img, cfg_path=cfg_path)
+
+    def test_pxe_errors(self, ubman, pxe_error_image):
+        """Test error handling for missing FDT and overlay files"""
+        fs_img, cfg_path = pxe_error_image
+        with ubman.log.section('Test PXE errors'):
+            ubman.run_ut('pxe', 'pxe_test_errors',
+                         fs_image=fs_img, cfg_path=cfg_path)