[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