[PATCH i-g-t 4/4] tools/intel-gfx-fw-info: Add proper HuC parser
Lucas De Marchi
lucas.demarchi at intel.com
Mon Aug 19 19:56:00 UTC 2024
Initial implementation to parse HuC's header was lazy and assumed the
manifest was the first entry in the cpd, which is not necessarily true.
Add proper parsing for the headers that matches the one documented
in https://docs.kernel.org/gpu/xe/xe_firmware.html#firmware-layout
as "GSC-based HuC firmware layout ".
Before (wrong):
$ intel-gfx-fw-info -c /lib/firmware/xe/lnl_huc.bin
header-type: GSC
version: 13.91.1
checksum: 320e765cbe42b0f5f95333794a6a00a4e67246d6ad8393b59b64efdc3506cfe9
After (fixed):
$ intel-gfx-fw-info -c /lib/firmware/xe/lnl_huc.bin
header-type: GSC
version: 9.4.13
checksum: 320e765cbe42b0f5f95333794a6a00a4e67246d6ad8393b59b64efdc3506cfe9
Signed-off-by: Lucas De Marchi <lucas.demarchi at intel.com>
---
tools/intel-gfx-fw-info | 106 ++++++++++++++++++++++++++++++++--------
1 file changed, 85 insertions(+), 21 deletions(-)
diff --git a/tools/intel-gfx-fw-info b/tools/intel-gfx-fw-info
index 85f99b75a..d34c51906 100755
--- a/tools/intel-gfx-fw-info
+++ b/tools/intel-gfx-fw-info
@@ -60,19 +60,68 @@ struct uc_css_header {
u32 header_info;
};
-#define HUC_GSC_VERSION_HI_DW 44
-#define HUC_GSC_MAJOR_VER_HI_MASK (0xFF << 0)
-#define HUC_GSC_MINOR_VER_HI_MASK (0xFF << 16)
-#define HUC_GSC_VERSION_LO_DW 45
-#define HUC_GSC_PATCH_VER_LO_MASK (0xFF << 0)
-
-// Add a fake definition for the GSC's header so this script can still
-// check the version
-
-struct uc_huc_gsc_header {
- u32 rsvd[HUC_GSC_VERSION_HI_DW];
- u32 ver_hi;
- u32 ver_lo;
+/* Code partition directory (CPD) structures */
+#define GSC_CPD_HEADER_MARKER 0x44504324
+struct gsc_cpd_header_v2 {
+ u32 header_marker;
+
+ u32 num_of_entries;
+ u8 header_version;
+ u8 entry_version;
+ u8 header_length; /* in bytes */
+ u8 flags;
+ u32 partition_name;
+ u32 crc32;
+};
+
+// Added as python code
+// #define GSC_CPD_ENTRY_OFFSET_MASK GENMASK(24, 0)
+
+struct gsc_version {
+ u16 major;
+ u16 minor;
+ u16 hotfix;
+ u16 build;
+};
+
+struct gsc_cpd_entry {
+ u8 name[12];
+
+ /*
+ * Bits 0-24: offset from the beginning of the code partition
+ * Bit 25: huffman compressed
+ * Bits 26-31: reserved
+ */
+ u32 offset;
+
+ /*
+ * Module/Item length, in bytes. For Huffman-compressed modules, this
+ * refers to the uncompressed size. For software-compressed modules,
+ * this refers to the compressed size.
+ */
+ u32 length;
+
+ u8 reserved[4];
+};
+
+struct gsc_manifest_header {
+ u32 header_type; /* 0x4 for manifest type */
+ u32 header_length; /* in dwords */
+ u32 header_version;
+ u32 flags;
+ u32 vendor;
+ u32 date;
+ u32 size; /* In dwords, size of entire manifest (header + extensions) */
+ u32 header_id;
+ u32 internal_data;
+ struct gsc_version fw_version;
+ u32 security_version;
+ struct gsc_version meu_kit_version;
+ u32 meu_manifest_version;
+ u8 general_data[4];
+ u8 reserved3[56];
+ u32 modulus_size; /* in dwords */
+ u32 exponent_size; /* in dwords */
};
struct magic {
@@ -91,6 +140,9 @@ except:
raise SystemExit(1)
+GSC_CPD_ENTRY_OFFSET_MASK = 0x1ffffff
+
+
def ffs(x: int) -> int:
"""Returns the index, counting from 0, of the
least significant set bit in `x`.
@@ -181,17 +233,28 @@ class FwGsc(Fw):
def decode(self):
self.f.seek(0, 0)
- self.fw = self.cparser.uc_huc_gsc_header(self.f)
+ self.fw = self.cparser.gsc_cpd_header_v2(self.f)
data = ["header-type: GSC"]
- HUC_GSC_MINOR_VER_HI_MASK = 0xFF << 16
- HUC_GSC_MAJOR_VER_HI_MASK = 0xFF
- HUC_GSC_PATCH_VER_LO_MASK = 0xFF
- major = FIELD_GET(HUC_GSC_MAJOR_VER_HI_MASK, self.fw.ver_hi)
- minor = FIELD_GET(HUC_GSC_MINOR_VER_HI_MASK, self.fw.ver_hi)
- patch = FIELD_GET(HUC_GSC_PATCH_VER_LO_MASK, self.fw.ver_lo)
- data += [f"version: {major}.{minor}.{patch}"]
+ # find manifest entry
+ self.f.seek(self.fw.header_length, 0)
+ for i in range(self.fw.num_of_entries):
+ entry = self.cparser.gsc_cpd_entry(self.f)
+ s = ''.join(map(chr, entry.name)).rstrip('\x00')
+ if s == 'HUCP.man':
+ offset = entry.offset & GSC_CPD_ENTRY_OFFSET_MASK
+ self.f.seek(offset, 0)
+ break;
+ else:
+ logging.fatal("Unknown/corrupted firmware - no manifest available")
+ sys.exit(1)
+
+ self.fw = self.cparser.gsc_manifest_header(self.f)
+ major = self.fw.fw_version.major
+ minor = self.fw.fw_version.minor
+ hotfix = self.fw.fw_version.hotfix
+ data += [f"version: {major}.{minor}.{hotfix}"]
return data
@@ -220,6 +283,7 @@ def main(argv: typing.List[str]) -> int:
fw = Fw.create(f)
if not fw:
logging.fatal("Unknown firmware type in '{args.filename}'")
+ sys.exit(1)
decoded_data = fw.decode()
if args.checksum:
--
2.43.0
More information about the igt-dev
mailing list