[PATCH i-g-t v3 6/6] tools/intel-gfx-fw-info: Add proper HuC parser
Daniele Ceraolo Spurio
daniele.ceraolospurio at intel.com
Mon Aug 26 18:37:01 UTC 2024
On 8/26/2024 8:26 AM, Lucas De Marchi wrote:
> 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>
Reviewed-by: Daniele Ceraolo Spurio <daniele.ceraolospurio at intel.com>
Daniele
> ---
> 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)
> + 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
>
More information about the igt-dev
mailing list