/* SPDX-License-Identifier: MIT */ /* * Copyright © 2022 Intel Corporation */ #ifndef _XE_UC_FW_ABI_H #define _XE_UC_FW_ABI_H #include #include /** * DOC: CSS-based Firmware Layout * * The CSS-based firmware structure is used for GuC releases on all platforms * and for HuC releases up to DG1. Starting from DG2/MTL the HuC uses the GSC * layout instead. * The CSS firmware layout looks like this:: * * +======================================================================+ * | Firmware blob | * +===============+===============+============+============+============+ * | CSS header | uCode | RSA key | modulus | exponent | * +===============+===============+============+============+============+ * <-header size-> <---header size continued -----------> * <--- size -----------------------------------------------------------> * <-key size-> * <-mod size-> * <-exp size-> * * The firmware may or may not have modulus key and exponent data. The header, * uCode and RSA signature are must-have components that will be used by driver. * Length of each components, which is all in dwords, can be found in header. * In the case that modulus and exponent are not present in fw, a.k.a truncated * image, the length value still appears in header. * * Driver will do some basic fw size validation based on the following rules: * * 1. Header, uCode and RSA are must-have components. * 2. All firmware components, if they present, are in the sequence illustrated * in the layout table above. * 3. Length info of each component can be found in header, in dwords. * 4. Modulus and exponent key are not required by driver. They may not appear * in fw. So driver will load a truncated firmware in this case. */ struct uc_css_header { u32 module_type; /* * header_size includes all non-uCode bits, including css_header, rsa * key, modulus key and exponent data. */ u32 header_size_dw; u32 header_version; u32 module_id; u32 module_vendor; u32 date; #define CSS_DATE_DAY (0xFF << 0) #define CSS_DATE_MONTH (0xFF << 8) #define CSS_DATE_YEAR (0xFFFF << 16) u32 size_dw; /* uCode plus header_size_dw */ u32 key_size_dw; u32 modulus_size_dw; u32 exponent_size_dw; u32 time; #define CSS_TIME_HOUR (0xFF << 0) #define CSS_DATE_MIN (0xFF << 8) #define CSS_DATE_SEC (0xFFFF << 16) char username[8]; char buildnumber[12]; u32 sw_version; #define CSS_SW_VERSION_UC_MAJOR (0xFF << 16) #define CSS_SW_VERSION_UC_MINOR (0xFF << 8) #define CSS_SW_VERSION_UC_PATCH (0xFF << 0) union { u32 submission_version; /* only applies to GuC */ u32 reserved2; }; u32 reserved0[12]; union { u32 private_data_size; /* only applies to GuC */ u32 reserved1; }; u32 header_info; } __packed; static_assert(sizeof(struct uc_css_header) == 128); /** * DOC: GSC-based Firmware Layout * * The GSC-based firmware structure is used for GSC releases on all platforms * and for HuC releases starting from DG2/MTL. Older HuC releases use the * CSS-based layout instead. Differently from the CSS headers, the GSC headers * uses a directory + entries structure (i.e., there is array of addresses * pointing to specific header extensions identified by a name). Although the * header structures are the same, some of the entries are specific to GSC while * others are specific to HuC. The manifest header entry, which includes basic * information about the binary (like the version) is always present, but it is * named differently based on the binary type. * * The HuC binary starts with a Code Partition Directory (CPD) header. The * entries we're interested in for use in the driver are: * * 1. "HUCP.man": points to the manifest header for the HuC. * 2. "huc_fw": points to the FW code. On platforms that support load via DMA * and 2-step HuC authentication (i.e. MTL+) this is a full CSS-based binary, * while if the GSC is the one doing the load (which only happens on DG2) * this section only contains the uCode. * * The GSC-based HuC firmware layout looks like this:: * * +================================================+ * | CPD Header | * +================================================+ * | CPD entries[] | * | entry1 | * | ... | * | entryX | * | "HUCP.man" | * | ... | * | offset >----------------------------|------o * | ... | | * | entryY | | * | "huc_fw" | | * | ... | | * | offset >----------------------------|----------o * +================================================+ | | * | | * +================================================+ | | * | Manifest Header |<-----o | * | ... | | * | FW version | | * | ... | | * +================================================+ | * | * +================================================+ | * | FW binary |<---------o * | CSS (MTL+ only) | * | uCode | * | RSA Key (MTL+ only) | * | ... | * +================================================+ * * The GSC binary starts instead with a layout header, which contains the * locations of the various partitions of the binary. The one we're interested * in is the boot1 partition, where we can find a BPDT header followed by * entries, one of which points to the RBE sub-section of the partition, which * contains the CPD. The GSC blob does not contain a CSS-based binary, so we * only need to look for the manifest, which is under the "RBEP.man" CPD entry. * Note that we have no need to find where the actual FW code is inside the * image because the GSC ROM will itself parse the headers to find it and load * it. * The GSC firmware header layout looks like this:: * * +================================================+ * | Layout Pointers | * | ... | * | Boot1 offset >---------------------------|------o * | ... | | * +================================================+ | * | * +================================================+ | * | BPDT header |<-----o * +================================================+ * | BPDT entries[] | * | entry1 | * | ... | * | entryX | * | type == GSC_RBE | * | offset >-----------------------------|------o * | ... | | * +================================================+ | * | * +================================================+ | * | CPD Header |<-----o * +================================================+ * | CPD entries[] | * | entry1 | * | ... | * | entryX | * | "RBEP.man" | * | ... | * | offset >----------------------------|------o * | ... | | * +================================================+ | * | * +================================================+ | * | Manifest Header |<-----o * | ... | * | FW version | * | ... | * | Security version | * | ... | * +================================================+ */ struct gsc_version { u16 major; u16 minor; u16 hotfix; u16 build; } __packed; struct gsc_partition { u32 offset; u32 size; } __packed; struct gsc_layout_pointers { u8 rom_bypass_vector[16]; /* size of this header section, not including ROM bypass vector */ u16 size; /* * bit0: Backup copy of layout pointers exists * bits1-15: reserved */ u8 flags; u8 reserved; u32 crc32; struct gsc_partition datap; struct gsc_partition boot1; struct gsc_partition boot2; struct gsc_partition boot3; struct gsc_partition boot4; struct gsc_partition boot5; struct gsc_partition temp_pages; } __packed; /* Boot partition structures */ struct gsc_bpdt_header { u32 signature; #define GSC_BPDT_HEADER_SIGNATURE 0x000055AA u16 descriptor_count; /* num of entries after the header */ u8 version; u8 configuration; u32 crc32; u32 build_version; struct gsc_version tool_version; } __packed; struct gsc_bpdt_entry { /* * Bits 0-15: BPDT entry type * Bits 16-17: reserved * Bit 18: code sub-partition * Bits 19-31: reserved */ u32 type; #define GSC_BPDT_ENTRY_TYPE_MASK GENMASK(15, 0) #define GSC_BPDT_ENTRY_TYPE_GSC_RBE 0x1 u32 sub_partition_offset; /* from the base of the BPDT header */ u32 sub_partition_size; } __packed; /* Code partition directory (CPD) structures */ struct gsc_cpd_header_v2 { u32 header_marker; #define GSC_CPD_HEADER_MARKER 0x44504324 u32 num_of_entries; u8 header_version; u8 entry_version; u8 header_length; /* in bytes */ u8 flags; u32 partition_name; u32 crc32; } __packed; 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; #define GSC_CPD_ENTRY_OFFSET_MASK GENMASK(24, 0) #define GSC_CPD_ENTRY_HUFFMAN_COMP BIT(25) /* * 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]; } __packed; 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 */ } __packed; #endif