[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