322 lines
12 KiB
C
322 lines
12 KiB
C
|
/* SPDX-License-Identifier: MIT */
|
||
|
/*
|
||
|
* Copyright © 2022 Intel Corporation
|
||
|
*/
|
||
|
|
||
|
#ifndef _XE_UC_FW_ABI_H
|
||
|
#define _XE_UC_FW_ABI_H
|
||
|
|
||
|
#include <linux/build_bug.h>
|
||
|
#include <linux/types.h>
|
||
|
|
||
|
/**
|
||
|
* 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
|