From 455b498d8de6dc82aecd5c893f4a3f2314b8f3ae Mon Sep 17 00:00:00 2001 From: joel cristobal Date: Fri, 6 Nov 2026 02:07:57 -0500 Subject: [PATCH 1/2] drm/asahi: g15: pin the cd05 firmware TEXT on the J516S Some 16-inch M3 Pro (J516S) units on the 14.7 boot chain load a B0 GPU firmware image whose TEXT digest differs from the pinned J516S row: TEXT 0x5c000, DATA 0x114000, GKTS marker 0x58e88 and TEXT sha256 cd05af6a828b52e4c2fed20086d3d18a7db42e03a8fd6f8354f9f06e0a61363e. The build is refused with "loaded GFX TEXT identity mismatch", so there is no render node and the compositor falls back to llvmpipe. The GPU only starts with the g15_accept_text_prefix bring-up override. Add this build as a J516S-only row. Rows still pin on the machine they name; nothing changes on the J514S or on other machines. Extend the maintained-handoff host test to check the new row and refresh the zero-words golden pins for hw.rs and the T6030 module, which change by exactly this one row. Measured on a J516S (apple,j516s apple,t6030; os-fw 14.7, system-fw 15.5, iBoot2 iBoot-10151.140.19.700.2) with linux-aurora 7.2.11.aurora14-1 and the override: the admission line reports the identical sizes, marker and digest, and the GPU reaches READY with renderD128 present. Link: https://github.com/omacom/linux-aurora/issues/247 Link: https://github.com/omacom/omarchy/issues/17739 Signed-off-by: joel cristobal --- drivers/gpu/drm/asahi/g15/hw.rs | 16 ++++++++++++++++ tools/asahi/g15-maintained-handoff-tests.py | 9 ++++++--- tools/asahi/g15-zero-words-tests.py | 14 +++++++------- 3 files changed, 29 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/asahi/g15/hw.rs b/drivers/gpu/drm/asahi/g15/hw.rs index 8351d35cd77ec6..39141bdc6605d7 100644 --- a/drivers/gpu/drm/asahi/g15/hw.rs +++ b/drivers/gpu/drm/asahi/g15/hw.rs @@ -194,6 +194,22 @@ pub(crate) mod t6030 { 0x54, 0xf9, 0xf0, 0x6e, 0x0a, 0x61, 0x36, 0x3e, ], }, + // Some J516S units on the same 14.7 boot chain load a different B0 + // TEXT image with identical sizes and marker. Pin its complete + // measured digest for the J516S only. + FirmwareBuild { + name: "J516S cd05 firmware (14.7 boot chain)", + machine: Some(kernel::c_str!("apple,j516s")), + text_size: 0x5c000, + data_size: 0x114000, + marker: 0x58e88, + text_sha256: [ + 0xcd, 0x05, 0xaf, 0x6a, 0x82, 0x8b, 0x52, 0xe4, + 0xc2, 0xfe, 0xd2, 0x00, 0x86, 0xd3, 0xd1, 0x8a, + 0x7d, 0xb4, 0x2e, 0x03, 0xa8, 0xfd, 0x6f, 0x83, + 0x54, 0xf9, 0xf0, 0x6e, 0x0a, 0x61, 0x36, 0x3e, + ], + }, ], machine: kernel::c_str!("apple,t6030"), platform: super::Platform::AdtWithPmp, diff --git a/tools/asahi/g15-maintained-handoff-tests.py b/tools/asahi/g15-maintained-handoff-tests.py index e0fb4438de3793..f2e344697dc3d9 100644 --- a/tools/asahi/g15-maintained-handoff-tests.py +++ b/tools/asahi/g15-maintained-handoff-tests.py @@ -137,12 +137,15 @@ def item(s, marker): OWNER_CALLS.set(0); let bytes = fixture(kind); assert!(parse(&dev, &Adt { data: &bytes }).is_err()); assert_eq!(OWNER_CALLS.get(), 0); } - assert_eq!(BUILDS.len(), 4, "maintained B0 firmware row must not require an absent profile symbol"); + assert_eq!(BUILDS.len(), 5, "maintained B0 firmware row must not require an absent profile symbol"); for (row, machine) in [(1, &b"apple,j516s"[..]), (2, &b"apple,j514s"[..])] { assert_eq!(BUILDS[row].machine.unwrap().to_bytes(), machine); assert_eq!((BUILDS[row].text_size, BUILDS[row].data_size, BUILDS[row].marker), (0x5c000, 0x114000, 0x58e88)); assert_eq!(BUILDS[row].text_sha256, [0xda,0x26,0xec,0xca,0xb1,0xf8,0x59,0x8d,0xa8,0x0c,0x85,0x5e,0xca,0x91,0x65,0x20,0x40,0x6d,0x1d,0x06,0x70,0xf1,0xd4,0x70,0xe7,0x9b,0xb9,0xb0,0x22,0x09,0xdb,0x53]); } + assert_eq!(BUILDS[4].machine.unwrap().to_bytes(), b"apple,j516s"); + assert_eq!((BUILDS[4].text_size, BUILDS[4].data_size, BUILDS[4].marker), (0x5c000, 0x114000, 0x58e88)); + assert_eq!(BUILDS[4].text_sha256, [0xcd,0x05,0xaf,0x6a,0x82,0x8b,0x52,0xe4,0xc2,0xfe,0xd2,0x00,0x86,0xd3,0xd1,0x8a,0x7d,0xb4,0x2e,0x03,0xa8,0xfd,0x6f,0x83,0x54,0xf9,0xf0,0x6e,0x0a,0x61,0x36,0x3e]); // Issue #247: this J514S build must pin without the bring-up override. use identity::lookup::{Measured, Verdict, verdict}; let measured = Measured { @@ -157,9 +160,9 @@ def item(s, marker): marker: b.marker, sha256: b.text_sha256 }, b.machine.map_or(true, |board| board.to_bytes() == machine), )), 0); - assert!(matches!(identify(&measured, b"apple,j514s"), Verdict::Pinned(_)), + assert!(matches!(identify(&measured, b"apple,j514s"), Verdict::Pinned(3)), "J514S cd05 firmware must pin without a prefix override"); - assert_eq!(identify(&measured, b"apple,j516s"), Verdict::Refused); + assert_eq!(identify(&measured, b"apple,j516s"), Verdict::Pinned(4)); let mut changed = measured; changed.sha256[31] ^= 1; assert_eq!(identify(&changed, b"apple,j514s"), Verdict::Refused); diff --git a/tools/asahi/g15-zero-words-tests.py b/tools/asahi/g15-zero-words-tests.py index 03e287fa06cb38..104ddf8c3cfd85 100644 --- a/tools/asahi/g15-zero-words-tests.py +++ b/tools/asahi/g15-zero-words-tests.py @@ -16,11 +16,11 @@ gated on CONFIG_DRM_ASAHI_G15 for the T8122 runtime without the G15 backend (one #[cfg] line; the tables are unchanged). Its T6030 configuration module is independently pinned to the original bytes, -except for the J514S B0 FirmwareBuild row and the J514S cd05 FirmwareBuild row -added to its firmware table: the module is the original pinned bytes (0079ae08) -plus those two 15-line rows, and the whole hw.rs pin was refreshed with each -(with the cd05 row removed, both pins are their earlier values e9b80be9 and -cab592b5). prepare_board() is pinned too; +except for the J514S B0 FirmwareBuild row and the J514S cd05 and J516S cd05 +FirmwareBuild rows added to its firmware table: the module is the original +pinned bytes (0079ae08) plus those three rows, and the whole hw.rs pin was +refreshed with each (with the cd05 rows removed, both pins are their earlier +values e9b80be9 and cab592b5). prepare_board() is pinned too; it was refreshed for the same Board change (its T6030 arm is unchanged). """ @@ -37,11 +37,11 @@ GOLDEN_FILES = { "board/data.rs": "7c5ff1077ca3296cbfc9e7144294162b6dea78a3774c38eeed4b0f59a14d7a5c", "board/template.rs": "286872f5474a67534f214e83e659253299f85143f3dc59035fa80894022e2549", - "hw.rs": "66df80458865ccd0c701145759e6fd8fd1f5a6695a98a7a318b38fbc1368a001", + "hw.rs": "fb2118b69c7d183a104baa920fee9b347ebee854e75ed74796d0425f3f129503", "power/idle.rs": "4928ecf7699b3ca85ff5143eb6e996efd40d47321e29a238a02c8873bc9f102c", } GOLDEN_FUNCTIONS = { - ("hw.rs", "pub(crate) mod t6030 {"): "d6c3020007646cba504db26bdfe5232e45185aba1d4603931da9a8d29bec40de", + ("hw.rs", "pub(crate) mod t6030 {"): "2667963ad7a0957bacf8118965a500586637b622a99e49916f111fcd02670fcd", ("initdata.rs", "fn templates("): "c3115c9926d3d7d93317cb8510e93b04f30b0c256811d7137568e822dd93b8ee", ("initdata.rs", "pub(crate) fn prepare_board("): "ebef64ab87ef7b1f994eb7fa2a2424d05bc4fc9e88cbfbf18e51570bdfc4222d", ("board.rs", "pub(crate) fn from_adt("): "cecd0b28db5bd94d3b75c1bbb5f35204e8bf0699f74e5b3d08228c59025f6ac2", From 83725f6a359e6a564b4410a4d6eaa44b8745bfbe Mon Sep 17 00:00:00 2001 From: Scott Jones Date: Sun, 8 Nov 2026 15:32:06 -0500 Subject: [PATCH 2/2] drm/asahi: g15: pin the 4118 firmware TEXT on the J514S and J516S Some 14-inch (J514S) and 16-inch (J516S) M3 Pro units on the 14.7 boot chain load a third B0 GPU firmware image: TEXT 0x5c000, DATA 0x114000, GKTS marker 0x58e88 and TEXT sha256 411833a7ded773feeac4a181552e3ff5582eaf4435f2dd8f620c1ed0b31df1b0. No row pins it, so probe fails with "loaded GFX TEXT identity mismatch", there is no render node and the compositor falls back to llvmpipe. Three machines have reported it in issue #247, all on the 14.7 stub with system firmware 26.6.2: a J514S and a J516S (both iBoot-10151.140.19.700.2, mBoot-18000.161.10), which logged the identical sizes, marker and digest, and a second 14-inch M3 Pro. With g15_accept_text_prefix=0x411833a7ded773fe all three reached firmware READY with renderD128 present. The boot chain matches the J514S cd05 reports, so the chain alone does not select the image. Add one row per board, J514S then J516S, so each pin still names the machine it was measured on; nothing changes for other machines. Extend the maintained-handoff host test: both boards pin to their own row with the override disabled, other boards are refused, and an altered digest suffix, TEXT or DATA size or marker is refused. Refresh the zero-words golden pins for hw.rs and the T6030 module; with the two rows removed both are their previous values. Link: https://github.com/omacom/linux-aurora/issues/247 Assisted-by: Claude:claude-opus-5-5 Signed-off-by: Scott Jones --- drivers/gpu/drm/asahi/g15/hw.rs | 32 +++++++++++++++++++++ tools/asahi/g15-maintained-handoff-tests.py | 32 ++++++++++++++++++++- tools/asahi/g15-zero-words-tests.py | 15 +++++----- 3 files changed, 71 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/asahi/g15/hw.rs b/drivers/gpu/drm/asahi/g15/hw.rs index 39141bdc6605d7..b3e0d0cb58acff 100644 --- a/drivers/gpu/drm/asahi/g15/hw.rs +++ b/drivers/gpu/drm/asahi/g15/hw.rs @@ -210,6 +210,38 @@ pub(crate) mod t6030 { 0x54, 0xf9, 0xf0, 0x6e, 0x0a, 0x61, 0x36, 0x3e, ], }, + // J514S (14-inch) firmware measured on the 14.7 boot chain with + // system firmware 26.6.2; the GPU reached READY with the bring-up + // prefix override (issue #247). + FirmwareBuild { + name: "J514S 4118 firmware (14.7 boot chain)", + machine: Some(kernel::c_str!("apple,j514s")), + text_size: 0x5c000, + data_size: 0x114000, + marker: 0x58e88, + text_sha256: [ + 0x41, 0x18, 0x33, 0xa7, 0xde, 0xd7, 0x73, 0xfe, + 0xea, 0xc4, 0xa1, 0x81, 0x55, 0x2e, 0x3f, 0xf5, + 0x58, 0x2e, 0xaf, 0x44, 0x35, 0xf2, 0xdd, 0x8f, + 0x62, 0x0c, 0x1e, 0xd0, 0xb3, 0x1d, 0xf1, 0xb0, + ], + }, + // J516S (16-inch) firmware measured on the 14.7 boot chain with + // system firmware 26.6.2; the GPU reached READY with the bring-up + // prefix override (issue #247). + FirmwareBuild { + name: "J516S 4118 firmware (14.7 boot chain)", + machine: Some(kernel::c_str!("apple,j516s")), + text_size: 0x5c000, + data_size: 0x114000, + marker: 0x58e88, + text_sha256: [ + 0x41, 0x18, 0x33, 0xa7, 0xde, 0xd7, 0x73, 0xfe, + 0xea, 0xc4, 0xa1, 0x81, 0x55, 0x2e, 0x3f, 0xf5, + 0x58, 0x2e, 0xaf, 0x44, 0x35, 0xf2, 0xdd, 0x8f, + 0x62, 0x0c, 0x1e, 0xd0, 0xb3, 0x1d, 0xf1, 0xb0, + ], + }, ], machine: kernel::c_str!("apple,t6030"), platform: super::Platform::AdtWithPmp, diff --git a/tools/asahi/g15-maintained-handoff-tests.py b/tools/asahi/g15-maintained-handoff-tests.py index f2e344697dc3d9..738facb331e521 100644 --- a/tools/asahi/g15-maintained-handoff-tests.py +++ b/tools/asahi/g15-maintained-handoff-tests.py @@ -137,7 +137,7 @@ def item(s, marker): OWNER_CALLS.set(0); let bytes = fixture(kind); assert!(parse(&dev, &Adt { data: &bytes }).is_err()); assert_eq!(OWNER_CALLS.get(), 0); } - assert_eq!(BUILDS.len(), 5, "maintained B0 firmware row must not require an absent profile symbol"); + assert_eq!(BUILDS.len(), 7, "maintained B0 firmware row must not require an absent profile symbol"); for (row, machine) in [(1, &b"apple,j516s"[..]), (2, &b"apple,j514s"[..])] { assert_eq!(BUILDS[row].machine.unwrap().to_bytes(), machine); assert_eq!((BUILDS[row].text_size, BUILDS[row].data_size, BUILDS[row].marker), (0x5c000, 0x114000, 0x58e88)); @@ -172,6 +172,36 @@ def item(s, marker): assert_eq!(identify(&changed, b"apple,j514s"), Verdict::Refused); changed = measured; changed.marker += 8; assert_eq!(identify(&changed, b"apple,j514s"), Verdict::Refused); + // Issue #247: the 4118 build pins on the J514S and the J516S, each to + // its own row, without the bring-up override. + let digest = [0x41,0x18,0x33,0xa7,0xde,0xd7,0x73,0xfe, + 0xea,0xc4,0xa1,0x81,0x55,0x2e,0x3f,0xf5, + 0x58,0x2e,0xaf,0x44,0x35,0xf2,0xdd,0x8f, + 0x62,0x0c,0x1e,0xd0,0xb3,0x1d,0xf1,0xb0]; + for (row, machine) in [(5, &b"apple,j514s"[..]), (6, &b"apple,j516s"[..])] { + assert_eq!(BUILDS[row].machine.unwrap().to_bytes(), machine); + assert_eq!((BUILDS[row].text_size, BUILDS[row].data_size, BUILDS[row].marker), (0x5c000, 0x114000, 0x58e88)); + assert_eq!(BUILDS[row].text_sha256, digest); + } + let measured = Measured { text_size: 0x5c000, data_size: 0x114000, marker: 0x58e88, sha256: digest }; + assert_eq!(identify(&measured, b"apple,j514s"), Verdict::Pinned(5), + "J514S 4118 firmware must pin without a prefix override"); + assert_eq!(identify(&measured, b"apple,j516s"), Verdict::Pinned(6), + "J516S 4118 firmware must pin without a prefix override"); + for other in [&b"apple,j514c"[..], b"apple,j516c", b"apple,j514m", b"apple,j516m", b"apple,t6030"] { + assert_eq!(identify(&measured, other), Verdict::Refused); + } + for machine in [&b"apple,j514s"[..], b"apple,j516s"] { + let mut changed = measured; + changed.sha256[31] ^= 1; + assert_eq!(identify(&changed, machine), Verdict::Refused); + changed = measured; changed.text_size += 0x1000; + assert_eq!(identify(&changed, machine), Verdict::Refused); + changed = measured; changed.data_size += 0x1000; + assert_eq!(identify(&changed, machine), Verdict::Refused); + changed = measured; changed.marker += 8; + assert_eq!(identify(&changed, machine), Verdict::Refused); + } for error in [0, -517, -12] { INIT_ERROR.set(error); let shared = Arc::new(Shared); let result = Rtkit::new(&dev, &shared); assert_eq!(result.is_ok(), error == 0); diff --git a/tools/asahi/g15-zero-words-tests.py b/tools/asahi/g15-zero-words-tests.py index 104ddf8c3cfd85..abcd6cf599e95b 100644 --- a/tools/asahi/g15-zero-words-tests.py +++ b/tools/asahi/g15-zero-words-tests.py @@ -16,11 +16,12 @@ gated on CONFIG_DRM_ASAHI_G15 for the T8122 runtime without the G15 backend (one #[cfg] line; the tables are unchanged). Its T6030 configuration module is independently pinned to the original bytes, -except for the J514S B0 FirmwareBuild row and the J514S cd05 and J516S cd05 -FirmwareBuild rows added to its firmware table: the module is the original -pinned bytes (0079ae08) plus those three rows, and the whole hw.rs pin was -refreshed with each (with the cd05 rows removed, both pins are their earlier -values e9b80be9 and cab592b5). prepare_board() is pinned too; +except for the J514S B0 FirmwareBuild row, the J514S cd05 and J516S cd05 +FirmwareBuild rows and the J514S 4118 and J516S 4118 FirmwareBuild rows added +to its firmware table: the module is the original pinned bytes (0079ae08) plus +those five rows, and the whole hw.rs pin was refreshed with each (with the 4118 +rows removed, both pins are their earlier values fb2118b6 and 2667963a; with +the cd05 rows also removed, e9b80be9 and cab592b5). prepare_board() is pinned too; it was refreshed for the same Board change (its T6030 arm is unchanged). """ @@ -37,11 +38,11 @@ GOLDEN_FILES = { "board/data.rs": "7c5ff1077ca3296cbfc9e7144294162b6dea78a3774c38eeed4b0f59a14d7a5c", "board/template.rs": "286872f5474a67534f214e83e659253299f85143f3dc59035fa80894022e2549", - "hw.rs": "fb2118b69c7d183a104baa920fee9b347ebee854e75ed74796d0425f3f129503", + "hw.rs": "76d91bb3cd4c4b676ac13572a756d404cad81e2dc07e5b0bf48dce7e114011e0", "power/idle.rs": "4928ecf7699b3ca85ff5143eb6e996efd40d47321e29a238a02c8873bc9f102c", } GOLDEN_FUNCTIONS = { - ("hw.rs", "pub(crate) mod t6030 {"): "2667963ad7a0957bacf8118965a500586637b622a99e49916f111fcd02670fcd", + ("hw.rs", "pub(crate) mod t6030 {"): "4016ec0d46831482382a92791b625e10fb2f6e4e28115a9498fdde0776f82e52", ("initdata.rs", "fn templates("): "c3115c9926d3d7d93317cb8510e93b04f30b0c256811d7137568e822dd93b8ee", ("initdata.rs", "pub(crate) fn prepare_board("): "ebef64ab87ef7b1f994eb7fa2a2424d05bc4fc9e88cbfbf18e51570bdfc4222d", ("board.rs", "pub(crate) fn from_adt("): "cecd0b28db5bd94d3b75c1bbb5f35204e8bf0699f74e5b3d08228c59025f6ac2",