t10xx: map the 10G memac cell-index instead of skipping it

NXP's qoriq-fman3 dtsi numbers the 10G memacs 0x8/0x9, and phydevs
holds the 10G port at FM1_10GEC1. Bounding the raw cell-index against
the table traded an out-of-bounds read for a silently dropped MAC
fixup on exactly the DTBs that motivated the guard. Translate instead,
and skip only indexes with no slot.
pull/862/head
Daniele Lacamera 2026-08-18 09:59:01 +02:00
parent 88b637130c
commit 5f26943e6f
3 changed files with 49 additions and 16 deletions

View File

@ -3391,6 +3391,7 @@ int hal_dts_fixup(void* dts_addr)
#ifndef BUILD_LOADER_STAGE1
struct fdt_header *fdt = (struct fdt_header *)dts_addr;
int off, i;
uint32_t cell;
uint32_t *reg;
const char* prev_compat;
@ -3531,14 +3532,23 @@ int hal_dts_fixup(void* dts_addr)
reg = (uint32_t*)fdt_getprop(fdt, off, "cell-index", NULL);
if (reg == NULL)
break;
i = (int)fdt32_to_cpu(*reg);
cell = fdt32_to_cpu(*reg);
/* Translate the DTS cell-index into a phydevs slot before
* touching the table. NXP's qoriq-fman3 dtsi numbers the 1G
* memacs 0..3 and the 10G memacs 0x8/0x9, while phydevs holds
* the 1G ports at 0..3 and the single 10G port at FM1_10GEC1.
* Anything with no slot is skipped rather than indexed. */
if (cell <= FM1_DTSEC4)
i = (int)cell;
else if (cell == 8)
i = FM1_10GEC1;
else
i = -1;
/* Bound the index before touching phydevs, mirroring the
* qman-portal loop above: standard FMan DTBs give the 10G
* MACs cell-index 8/9, outside the 5-entry table. */
if (i < 0 || i >= (int)(sizeof(phydevs) / sizeof(phydevs[0]))) {
wolfBoot_printf("FDT: Ethernet%d: invalid cell-index, skipping\n",
i);
wolfBoot_printf("FDT: Ethernet cell-index %u unsupported, "
"skipping\n", (unsigned)cell);
off = fdt_node_offset_by_compatible(fdt, off, "fsl,fman-memac");
continue;
}

View File

@ -1047,6 +1047,7 @@ nxp_t10xx_fixup_extract.h: ../../hal/nxp_t10xx.c
sed -n '/^struct qportal_info {/,/^};/p' $< >> $@
sed -n '/#define SET_QP_INFO(/,/sdest = dest/p' $< >> $@
sed -n '/^static const struct qportal_info qp_info\[QMAN_NUM_PORTALS\] = {/,/^};/p' $< >> $@
grep -E '^#define FM1_(DTSEC[0-9]|10GEC1) ' $< >> $@
sed -n '/^int hal_dts_fixup(/,/^}/p' $< >> $@
unit-t10xx-dts-memac: unit-t10xx-dts-memac.c nxp_t10xx_fixup_extract.h ../../src/fdt.c

View File

@ -357,16 +357,37 @@ static void teardown(void)
{
}
/* A cell-index outside the 5-entry phydevs table must not produce a
* local-mac-address. Pre-fix the loop read phydevs[8] out of bounds
* and wrote the result into the device tree. */
START_TEST(test_memac_oob_cell_index_skipped)
/* NXP's qoriq-fman3 dtsi gives the first 10G memac cell-index 8, and
* phydevs holds that port at FM1_10GEC1 (slot 4). It must be mapped
* there, not skipped: skipping silently drops the 10G MAC fixup. Pre
* fix the loop read phydevs[8] out of bounds instead. */
START_TEST(test_memac_10g_cell_index_mapped)
{
struct dtb d;
int off, len;
const void *mac;
dtb_build_memac(&d, "memac0", 8);
ck_assert_int_eq(hal_dts_fixup(d.buf), 0);
off = fdt_node_offset_by_compatible(d.buf, -1, "fsl,fman-memac");
ck_assert_int_gt(off, 0);
mac = fdt_getprop(d.buf, off, "local-mac-address", &len);
ck_assert_ptr_nonnull(mac);
ck_assert_int_eq(len, 6);
ck_assert_int_eq(((const uint8_t *)mac)[5], 0x14); /* phydevs[4] */
}
END_TEST
/* A cell-index with no phydevs slot at all (a second 10G port, or a
* malformed DTB) must produce no local-mac-address. */
START_TEST(test_memac_unmapped_cell_index_skipped)
{
struct dtb d;
int off;
const void *mac;
dtb_build_memac(&d, "memac0", 8);
dtb_build_memac(&d, "memac0", 9);
ck_assert_int_eq(hal_dts_fixup(d.buf), 0);
off = fdt_node_offset_by_compatible(d.buf, -1, "fsl,fman-memac");
@ -395,15 +416,15 @@ START_TEST(test_memac_valid_cell_index_fixed)
}
END_TEST
/* An out-of-bounds node must be skipped, not break the loop: the
* following valid node still gets its MAC. */
/* An unmapped node must be skipped, not break the loop: the following
* valid node still gets its MAC. */
START_TEST(test_memac_mixed_oob_then_valid)
{
struct dtb d;
int off0, off1, len;
const void *mac;
dtb_build_memac2(&d, 8, 2);
dtb_build_memac2(&d, 9, 2);
ck_assert_int_eq(hal_dts_fixup(d.buf), 0);
off0 = fdt_node_offset_by_compatible(d.buf, -1, "fsl,fman-memac");
@ -411,7 +432,7 @@ START_TEST(test_memac_mixed_oob_then_valid)
ck_assert_int_gt(off0, 0);
ck_assert_int_gt(off1, 0);
/* node 0 (index 8): skipped */
/* node 0 (index 9): no phydevs slot, skipped */
mac = fdt_getprop(d.buf, off0, "local-mac-address", NULL);
ck_assert_ptr_null(mac);
@ -429,7 +450,8 @@ Suite *t10xx_dts_memac_suite(void)
TCase *tc = tcase_create("memac");
tcase_add_checked_fixture(tc, setup, teardown);
tcase_add_test(tc, test_memac_oob_cell_index_skipped);
tcase_add_test(tc, test_memac_10g_cell_index_mapped);
tcase_add_test(tc, test_memac_unmapped_cell_index_skipped);
tcase_add_test(tc, test_memac_valid_cell_index_fixed);
tcase_add_test(tc, test_memac_mixed_oob_then_valid);
suite_add_tcase(s, tc);