Skip to content

Commit 93a575a

Browse files
committed
drm/i915/huc: Parse the GSC-enabled HuC binary
The new binaries that support the 2-step authentication contain the legacy-style binary, which we can use for loading the HuC via DMA. To find out where this is located in the image, we need to parse the manifest of the GSC-enabled HuC binary. The manifest consist of a partition header followed by entries, one of which contains the offset we're looking for. Note that the DG2 GSC binary contains entries with the same names, but it doesn't contain a full legacy binary, so we need to skip assigning the dma offset in that case (which we can do by checking the ccs). Also, since we're now parsing the entries, we can extract the HuC version that way instead of using hardcoded offsets. Note that the GSC binary uses the same structures in its binary header, so they've been added in their own header file. v2: fix structure names to match meu defines (s/CPT/CPD/), update commit message, check ccs validity, drop old version location defines. v3: drop references to the MEU tool to reduce confusion, fix log (John) v4: fix log for real (John) Signed-off-by: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com> Cc: Alan Previn <alan.previn.teres.alexis@intel.com> Cc: John Harrison <John.C.Harrison@Intel.com> Reviewed-by: Alan Previn <alan.previn.teres.alexis@intel.com> #v2 Reviewed-by: John Harrison <John.C.Harrison@Intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20230531235415.1467475-3-daniele.ceraolospurio@intel.com
1 parent 3532e75 commit 93a575a

8 files changed

Lines changed: 274 additions & 53 deletions

File tree

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/* SPDX-License-Identifier: MIT */
2+
/*
3+
* Copyright © 2023 Intel Corporation
4+
*/
5+
6+
#ifndef _INTEL_GSC_BINARY_HEADERS_H_
7+
#define _INTEL_GSC_BINARY_HEADERS_H_
8+
9+
#include <linux/types.h>
10+
11+
/* Code partition directory (CPD) structures */
12+
struct intel_gsc_cpd_header_v2 {
13+
u32 header_marker;
14+
#define INTEL_GSC_CPD_HEADER_MARKER 0x44504324
15+
16+
u32 num_of_entries;
17+
u8 header_version;
18+
u8 entry_version;
19+
u8 header_length; /* in bytes */
20+
u8 flags;
21+
u32 partition_name;
22+
u32 crc32;
23+
} __packed;
24+
25+
struct intel_gsc_cpd_entry {
26+
u8 name[12];
27+
28+
/*
29+
* Bits 0-24: offset from the beginning of the code partition
30+
* Bit 25: huffman compressed
31+
* Bits 26-31: reserved
32+
*/
33+
u32 offset;
34+
#define INTEL_GSC_CPD_ENTRY_OFFSET_MASK GENMASK(24, 0)
35+
#define INTEL_GSC_CPD_ENTRY_HUFFMAN_COMP BIT(25)
36+
37+
/*
38+
* Module/Item length, in bytes. For Huffman-compressed modules, this
39+
* refers to the uncompressed size. For software-compressed modules,
40+
* this refers to the compressed size.
41+
*/
42+
u32 length;
43+
44+
u8 reserved[4];
45+
} __packed;
46+
47+
struct intel_gsc_version {
48+
u16 major;
49+
u16 minor;
50+
u16 hotfix;
51+
u16 build;
52+
} __packed;
53+
54+
struct intel_gsc_manifest_header {
55+
u32 header_type; /* 0x4 for manifest type */
56+
u32 header_length; /* in dwords */
57+
u32 header_version;
58+
u32 flags;
59+
u32 vendor;
60+
u32 date;
61+
u32 size; /* In dwords, size of entire manifest (header + extensions) */
62+
u32 header_id;
63+
u32 internal_data;
64+
struct intel_gsc_version fw_version;
65+
u32 security_version;
66+
struct intel_gsc_version meu_kit_version;
67+
u32 meu_manifest_version;
68+
u8 general_data[4];
69+
u8 reserved3[56];
70+
u32 modulus_size; /* in dwords */
71+
u32 exponent_size; /* in dwords */
72+
} __packed;
73+
74+
#endif

drivers/gpu/drm/i915/gt/uc/intel_huc.c

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,23 +6,14 @@
66
#include <linux/types.h>
77

88
#include "gt/intel_gt.h"
9-
#include "gt/intel_gt_print.h"
109
#include "intel_guc_reg.h"
1110
#include "intel_huc.h"
11+
#include "intel_huc_print.h"
1212
#include "i915_drv.h"
1313

1414
#include <linux/device/bus.h>
1515
#include <linux/mei_aux.h>
1616

17-
#define huc_printk(_huc, _level, _fmt, ...) \
18-
gt_##_level(huc_to_gt(_huc), "HuC: " _fmt, ##__VA_ARGS__)
19-
#define huc_err(_huc, _fmt, ...) huc_printk((_huc), err, _fmt, ##__VA_ARGS__)
20-
#define huc_warn(_huc, _fmt, ...) huc_printk((_huc), warn, _fmt, ##__VA_ARGS__)
21-
#define huc_notice(_huc, _fmt, ...) huc_printk((_huc), notice, _fmt, ##__VA_ARGS__)
22-
#define huc_info(_huc, _fmt, ...) huc_printk((_huc), info, _fmt, ##__VA_ARGS__)
23-
#define huc_dbg(_huc, _fmt, ...) huc_printk((_huc), dbg, _fmt, ##__VA_ARGS__)
24-
#define huc_probe_error(_huc, _fmt, ...) huc_printk((_huc), probe_error, _fmt, ##__VA_ARGS__)
25-
2617
/**
2718
* DOC: HuC
2819
*

drivers/gpu/drm/i915/gt/uc/intel_huc_fw.c

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,147 @@
55

66
#include "gt/intel_gsc.h"
77
#include "gt/intel_gt.h"
8+
#include "intel_gsc_binary_headers.h"
89
#include "intel_huc.h"
910
#include "intel_huc_fw.h"
11+
#include "intel_huc_print.h"
1012
#include "i915_drv.h"
1113
#include "pxp/intel_pxp_huc.h"
1214

15+
static void get_version_from_gsc_manifest(struct intel_uc_fw_ver *ver, const void *data)
16+
{
17+
const struct intel_gsc_manifest_header *manifest = data;
18+
19+
ver->major = manifest->fw_version.major;
20+
ver->minor = manifest->fw_version.minor;
21+
ver->patch = manifest->fw_version.hotfix;
22+
}
23+
24+
static bool css_valid(const void *data, size_t size)
25+
{
26+
const struct uc_css_header *css = data;
27+
28+
if (unlikely(size < sizeof(struct uc_css_header)))
29+
return false;
30+
31+
if (css->module_type != 0x6)
32+
return false;
33+
34+
if (css->module_vendor != PCI_VENDOR_ID_INTEL)
35+
return false;
36+
37+
return true;
38+
}
39+
40+
static inline u32 entry_offset(const struct intel_gsc_cpd_entry *entry)
41+
{
42+
return entry->offset & INTEL_GSC_CPD_ENTRY_OFFSET_MASK;
43+
}
44+
45+
int intel_huc_fw_get_binary_info(struct intel_uc_fw *huc_fw, const void *data, size_t size)
46+
{
47+
struct intel_huc *huc = container_of(huc_fw, struct intel_huc, fw);
48+
const struct intel_gsc_cpd_header_v2 *header = data;
49+
const struct intel_gsc_cpd_entry *entry;
50+
size_t min_size = sizeof(*header);
51+
int i;
52+
53+
if (!huc_fw->loaded_via_gsc) {
54+
huc_err(huc, "Invalid FW type for GSC header parsing!\n");
55+
return -EINVAL;
56+
}
57+
58+
if (size < sizeof(*header)) {
59+
huc_err(huc, "FW too small! %zu < %zu\n", size, min_size);
60+
return -ENODATA;
61+
}
62+
63+
/*
64+
* The GSC-enabled HuC binary starts with a directory header, followed
65+
* by a series of entries. Each entry is identified by a name and
66+
* points to a specific section of the binary containing the relevant
67+
* data. The entries we're interested in are:
68+
* - "HUCP.man": points to the GSC manifest header for the HuC, which
69+
* contains the version info.
70+
* - "huc_fw": points to the legacy-style binary that can be used for
71+
* load via the DMA. This entry only contains a valid CSS
72+
* on binaries for platforms that support 2-step HuC load
73+
* via dma and auth via GSC (like MTL).
74+
*
75+
* --------------------------------------------------
76+
* [ intel_gsc_cpd_header_v2 ]
77+
* --------------------------------------------------
78+
* [ intel_gsc_cpd_entry[] ]
79+
* [ entry1 ]
80+
* [ ... ]
81+
* [ entryX ]
82+
* [ "HUCP.man" ]
83+
* [ ... ]
84+
* [ offset >----------------------------]------o
85+
* [ ... ] |
86+
* [ entryY ] |
87+
* [ "huc_fw" ] |
88+
* [ ... ] |
89+
* [ offset >----------------------------]----------o
90+
* -------------------------------------------------- | |
91+
* | |
92+
* -------------------------------------------------- | |
93+
* [ intel_gsc_manifest_header ]<-----o |
94+
* [ ... ] |
95+
* [ intel_gsc_version fw_version ] |
96+
* [ ... ] |
97+
* -------------------------------------------------- |
98+
* |
99+
* -------------------------------------------------- |
100+
* [ data[] ]<---------o
101+
* [ ... ]
102+
* [ ... ]
103+
* --------------------------------------------------
104+
*/
105+
106+
if (header->header_marker != INTEL_GSC_CPD_HEADER_MARKER) {
107+
huc_err(huc, "invalid marker for CPD header: 0x%08x!\n",
108+
header->header_marker);
109+
return -EINVAL;
110+
}
111+
112+
/* we only have binaries with header v2 and entry v1 for now */
113+
if (header->header_version != 2 || header->entry_version != 1) {
114+
huc_err(huc, "invalid CPD header/entry version %u:%u!\n",
115+
header->header_version, header->entry_version);
116+
return -EINVAL;
117+
}
118+
119+
if (header->header_length < sizeof(struct intel_gsc_cpd_header_v2)) {
120+
huc_err(huc, "invalid CPD header length %u!\n",
121+
header->header_length);
122+
return -EINVAL;
123+
}
124+
125+
min_size = header->header_length + sizeof(*entry) * header->num_of_entries;
126+
if (size < min_size) {
127+
huc_err(huc, "FW too small! %zu < %zu\n", size, min_size);
128+
return -ENODATA;
129+
}
130+
131+
entry = data + header->header_length;
132+
133+
for (i = 0; i < header->num_of_entries; i++, entry++) {
134+
if (strcmp(entry->name, "HUCP.man") == 0)
135+
get_version_from_gsc_manifest(&huc_fw->file_selected.ver,
136+
data + entry_offset(entry));
137+
138+
if (strcmp(entry->name, "huc_fw") == 0) {
139+
u32 offset = entry_offset(entry);
140+
141+
if (offset < size && css_valid(data + offset, size - offset))
142+
huc_fw->dma_start_offset = offset;
143+
}
144+
}
145+
146+
return 0;
147+
}
148+
13149
int intel_huc_fw_load_and_auth_via_gsc(struct intel_huc *huc)
14150
{
15151
int ret;

drivers/gpu/drm/i915/gt/uc/intel_huc_fw.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,11 @@
77
#define _INTEL_HUC_FW_H_
88

99
struct intel_huc;
10+
struct intel_uc_fw;
11+
12+
#include <linux/types.h>
1013

1114
int intel_huc_fw_load_and_auth_via_gsc(struct intel_huc *huc);
1215
int intel_huc_fw_upload(struct intel_huc *huc);
13-
16+
int intel_huc_fw_get_binary_info(struct intel_uc_fw *huc_fw, const void *data, size_t size);
1417
#endif
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/* SPDX-License-Identifier: MIT */
2+
/*
3+
* Copyright © 2023 Intel Corporation
4+
*/
5+
6+
#ifndef __INTEL_HUC_PRINT__
7+
#define __INTEL_HUC_PRINT__
8+
9+
#include "gt/intel_gt.h"
10+
#include "gt/intel_gt_print.h"
11+
12+
#define huc_printk(_huc, _level, _fmt, ...) \
13+
gt_##_level(huc_to_gt(_huc), "HuC: " _fmt, ##__VA_ARGS__)
14+
#define huc_err(_huc, _fmt, ...) huc_printk((_huc), err, _fmt, ##__VA_ARGS__)
15+
#define huc_warn(_huc, _fmt, ...) huc_printk((_huc), warn, _fmt, ##__VA_ARGS__)
16+
#define huc_notice(_huc, _fmt, ...) huc_printk((_huc), notice, _fmt, ##__VA_ARGS__)
17+
#define huc_info(_huc, _fmt, ...) huc_printk((_huc), info, _fmt, ##__VA_ARGS__)
18+
#define huc_dbg(_huc, _fmt, ...) huc_printk((_huc), dbg, _fmt, ##__VA_ARGS__)
19+
#define huc_probe_error(_huc, _fmt, ...) huc_printk((_huc), probe_error, _fmt, ##__VA_ARGS__)
20+
21+
#endif /* __INTEL_HUC_PRINT__ */

0 commit comments

Comments
 (0)