[PATCH i-g-t v3 6/6] tools/intel-gfx-fw-info: Add proper HuC parser

Gustavo Sousa gustavo.sousa at intel.com
Mon Aug 26 18:38:09 UTC 2024


Quoting Lucas De Marchi (2024-08-26 12:26:56-03:00)
>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
>
>Acked-by: Kamil Konieczny <kamil.konieczny at linux.intel.com>
>Signed-off-by: Lucas De Marchi <lucas.demarchi at intel.com>
>---
> tools/intel-gfx-fw-info | 105 ++++++++++++++++++++++++++++++++--------
> 1 file changed, 84 insertions(+), 21 deletions(-)
>
>diff --git a/tools/intel-gfx-fw-info b/tools/intel-gfx-fw-info
>index fb98f1bcc..c3b98ebc1 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 ImportError as e:
>     raise SystemExit(1) from e
> 
> 
>+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 _ 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)

I think this is the only meaningful assignment to self.fw. I think we
could use a local variable for the CPD header.

Other than that,

    Reviewed-by: Gustavo Sousa <gustavo.sousa at intel.com>

>+        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
> 
>-- 
>2.43.0
>


More information about the igt-dev mailing list