xref: /linux/drivers/gpu/drm/xe/xe_uc_fw.c (revision d53b8e36925256097a08d7cb749198d85cbf9b2b)
1 // SPDX-License-Identifier: MIT
2 /*
3  * Copyright © 2022 Intel Corporation
4  */
5 
6 #include <linux/bitfield.h>
7 #include <linux/firmware.h>
8 
9 #include <drm/drm_managed.h>
10 
11 #include "regs/xe_guc_regs.h"
12 #include "xe_bo.h"
13 #include "xe_device_types.h"
14 #include "xe_force_wake.h"
15 #include "xe_gsc.h"
16 #include "xe_gt.h"
17 #include "xe_gt_printk.h"
18 #include "xe_guc.h"
19 #include "xe_map.h"
20 #include "xe_mmio.h"
21 #include "xe_module.h"
22 #include "xe_sriov.h"
23 #include "xe_uc_fw.h"
24 
25 /*
26  * List of required GuC and HuC binaries per-platform. They must be ordered
27  * based on platform, from newer to older.
28  *
29  * Versioning follows the guidelines from
30  * Documentation/driver-api/firmware/firmware-usage-guidelines.rst. There is a
31  * distinction for platforms being officially supported by the driver or not.
32  * Platforms not available publicly or not yet officially supported by the
33  * driver (under force-probe), use the mmp_ver(): the firmware autoselect logic
34  * will select the firmware from disk with filename that matches the full
35  * "mpp version", i.e. major.minor.patch. mmp_ver() should only be used for
36  * this case.
37  *
38  * For platforms officially supported by the driver, the filename always only
39  * ever contains the major version (GuC) or no version at all (HuC).
40  *
41  * After loading the file, the driver parses the versions embedded in the blob.
42  * The major version needs to match a major version supported by the driver (if
43  * any). The minor version is also checked and a notice emitted to the log if
44  * the version found is smaller than the version wanted. This is done only for
45  * informational purposes so users may have a chance to upgrade, but the driver
46  * still loads and use the older firmware.
47  *
48  * Examples:
49  *
50  *	1) Platform officially supported by i915 - using Tigerlake as example.
51  *	   Driver loads the following firmware blobs from disk:
52  *
53  *		- i915/tgl_guc_<major>.bin
54  *		- i915/tgl_huc.bin
55  *
56  *	   <major> number for GuC is checked that it matches the version inside
57  *	   the blob. <minor> version is checked and if smaller than the expected
58  *	   an info message is emitted about that.
59  *
60  *	1) XE_<FUTUREINTELPLATFORM>, still under require_force_probe. Using
61  *	   "wipplat" as a short-name. Driver loads the following firmware blobs
62  *	   from disk:
63  *
64  *		- xe/wipplat_guc_<major>.<minor>.<patch>.bin
65  *		- xe/wipplat_huc_<major>.<minor>.<patch>.bin
66  *
67  *	   <major> and <minor> are checked that they match the version inside
68  *	   the blob. Both of them need to match exactly what the driver is
69  *	   expecting, otherwise it fails.
70  *
71  *	3) Platform officially supported by xe and out of force-probe. Using
72  *	   "plat" as a short-name. Except for the different directory, the
73  *	   behavior is the same as (1). Driver loads the following firmware
74  *	   blobs from disk:
75  *
76  *		- xe/plat_guc_<major>.bin
77  *		- xe/plat_huc.bin
78  *
79  *	   <major> number for GuC is checked that it matches the version inside
80  *	   the blob. <minor> version is checked and if smaller than the expected
81  *	   an info message is emitted about that.
82  *
83  * For the platforms already released with a major version, they should never be
84  * removed from the table. Instead new entries with newer versions may be added
85  * before them, so they take precedence.
86  *
87  * TODO: Currently there's no fallback on major version. That's because xe
88  * driver only supports the one major version of each firmware in the table.
89  * This needs to be fixed when the major version of GuC is updated.
90  */
91 
92 struct uc_fw_entry {
93 	enum xe_platform platform;
94 	struct {
95 		const char *path;
96 		u16 major;
97 		u16 minor;
98 		u16 patch;
99 		bool full_ver_required;
100 	};
101 };
102 
103 struct fw_blobs_by_type {
104 	const struct uc_fw_entry *entries;
105 	u32 count;
106 };
107 
108 #define XE_GUC_FIRMWARE_DEFS(fw_def, mmp_ver, major_ver)			\
109 	fw_def(BATTLEMAGE,	major_ver(xe,	guc,	bmg,	70, 29, 2))	\
110 	fw_def(LUNARLAKE,	major_ver(xe,	guc,	lnl,	70, 29, 2))	\
111 	fw_def(METEORLAKE,	major_ver(i915,	guc,	mtl,	70, 29, 2))	\
112 	fw_def(DG2,		major_ver(i915,	guc,	dg2,	70, 29, 2))	\
113 	fw_def(DG1,		major_ver(i915,	guc,	dg1,	70, 29, 2))	\
114 	fw_def(ALDERLAKE_N,	major_ver(i915,	guc,	tgl,	70, 29, 2))	\
115 	fw_def(ALDERLAKE_P,	major_ver(i915,	guc,	adlp,	70, 29, 2))	\
116 	fw_def(ALDERLAKE_S,	major_ver(i915,	guc,	tgl,	70, 29, 2))	\
117 	fw_def(ROCKETLAKE,	major_ver(i915,	guc,	tgl,	70, 29, 2))	\
118 	fw_def(TIGERLAKE,	major_ver(i915,	guc,	tgl,	70, 29, 2))
119 
120 #define XE_HUC_FIRMWARE_DEFS(fw_def, mmp_ver, no_ver)		\
121 	fw_def(BATTLEMAGE,	no_ver(xe,	huc,		bmg))		\
122 	fw_def(LUNARLAKE,	no_ver(xe,	huc,		lnl))		\
123 	fw_def(METEORLAKE,	no_ver(i915,	huc_gsc,	mtl))		\
124 	fw_def(DG1,		no_ver(i915,	huc,		dg1))		\
125 	fw_def(ALDERLAKE_P,	no_ver(i915,	huc,		tgl))		\
126 	fw_def(ALDERLAKE_S,	no_ver(i915,	huc,		tgl))		\
127 	fw_def(ROCKETLAKE,	no_ver(i915,	huc,		tgl))		\
128 	fw_def(TIGERLAKE,	no_ver(i915,	huc,		tgl))
129 
130 /* for the GSC FW we match the compatibility version and not the release one */
131 #define XE_GSC_FIRMWARE_DEFS(fw_def, major_ver)		\
132 	fw_def(LUNARLAKE,	major_ver(xe,	gsc,	lnl,	1, 0, 0)) \
133 	fw_def(METEORLAKE,	major_ver(i915,	gsc,	mtl,	1, 0, 0))
134 
135 #define MAKE_FW_PATH(dir__, uc__, shortname__, version__)			\
136 	__stringify(dir__) "/" __stringify(shortname__) "_" __stringify(uc__) version__ ".bin"
137 
138 #define fw_filename_mmp_ver(dir_, uc_, shortname_, a, b, c)			\
139 	MAKE_FW_PATH(dir_, uc_, shortname_, "_" __stringify(a ## . ## b ## . ## c))
140 #define fw_filename_major_ver(dir_, uc_, shortname_, a, b, c)			\
141 	MAKE_FW_PATH(dir_, uc_, shortname_, "_" __stringify(a))
142 #define fw_filename_no_ver(dir_, uc_, shortname_)				\
143 	MAKE_FW_PATH(dir_, uc_, shortname_, "")
144 
145 #define uc_fw_entry_mmp_ver(dir_, uc_, shortname_, a, b, c)			\
146 	{ fw_filename_mmp_ver(dir_, uc_, shortname_, a, b, c),			\
147 	  a, b, c, true }
148 #define uc_fw_entry_major_ver(dir_, uc_, shortname_, a, b, c)			\
149 	{ fw_filename_major_ver(dir_, uc_, shortname_, a, b, c),		\
150 	  a, b, c }
151 #define uc_fw_entry_no_ver(dir_, uc_, shortname_)				\
152 	{ fw_filename_no_ver(dir_, uc_, shortname_),				\
153 	  0, 0 }
154 
155 /* All blobs need to be declared via MODULE_FIRMWARE() */
156 #define XE_UC_MODULE_FIRMWARE(platform__, fw_filename)				\
157 	MODULE_FIRMWARE(fw_filename);
158 
159 #define XE_UC_FW_ENTRY(platform__, entry__)					\
160 	{									\
161 		.platform = XE_ ## platform__,					\
162 		entry__,							\
163 	},
164 
165 XE_GUC_FIRMWARE_DEFS(XE_UC_MODULE_FIRMWARE,
166 		     fw_filename_mmp_ver, fw_filename_major_ver)
167 XE_HUC_FIRMWARE_DEFS(XE_UC_MODULE_FIRMWARE,
168 		     fw_filename_mmp_ver, fw_filename_no_ver)
169 XE_GSC_FIRMWARE_DEFS(XE_UC_MODULE_FIRMWARE, fw_filename_major_ver)
170 
171 static struct xe_gt *
172 __uc_fw_to_gt(struct xe_uc_fw *uc_fw, enum xe_uc_fw_type type)
173 {
174 	XE_WARN_ON(type >= XE_UC_FW_NUM_TYPES);
175 
176 	switch (type) {
177 	case XE_UC_FW_TYPE_GUC:
178 		return container_of(uc_fw, struct xe_gt, uc.guc.fw);
179 	case XE_UC_FW_TYPE_HUC:
180 		return container_of(uc_fw, struct xe_gt, uc.huc.fw);
181 	case XE_UC_FW_TYPE_GSC:
182 		return container_of(uc_fw, struct xe_gt, uc.gsc.fw);
183 	default:
184 		return NULL;
185 	}
186 }
187 
188 static struct xe_gt *uc_fw_to_gt(struct xe_uc_fw *uc_fw)
189 {
190 	return __uc_fw_to_gt(uc_fw, uc_fw->type);
191 }
192 
193 static struct xe_device *uc_fw_to_xe(struct xe_uc_fw *uc_fw)
194 {
195 	return gt_to_xe(uc_fw_to_gt(uc_fw));
196 }
197 
198 static void
199 uc_fw_auto_select(struct xe_device *xe, struct xe_uc_fw *uc_fw)
200 {
201 	static const struct uc_fw_entry entries_guc[] = {
202 		XE_GUC_FIRMWARE_DEFS(XE_UC_FW_ENTRY,
203 				     uc_fw_entry_mmp_ver,
204 				     uc_fw_entry_major_ver)
205 	};
206 	static const struct uc_fw_entry entries_huc[] = {
207 		XE_HUC_FIRMWARE_DEFS(XE_UC_FW_ENTRY,
208 				     uc_fw_entry_mmp_ver,
209 				     uc_fw_entry_no_ver)
210 	};
211 	static const struct uc_fw_entry entries_gsc[] = {
212 		XE_GSC_FIRMWARE_DEFS(XE_UC_FW_ENTRY, uc_fw_entry_major_ver)
213 	};
214 	static const struct fw_blobs_by_type blobs_all[XE_UC_FW_NUM_TYPES] = {
215 		[XE_UC_FW_TYPE_GUC] = { entries_guc, ARRAY_SIZE(entries_guc) },
216 		[XE_UC_FW_TYPE_HUC] = { entries_huc, ARRAY_SIZE(entries_huc) },
217 		[XE_UC_FW_TYPE_GSC] = { entries_gsc, ARRAY_SIZE(entries_gsc) },
218 	};
219 	static const struct uc_fw_entry *entries;
220 	enum xe_platform p = xe->info.platform;
221 	u32 count;
222 	int i;
223 
224 	xe_assert(xe, uc_fw->type < ARRAY_SIZE(blobs_all));
225 	entries = blobs_all[uc_fw->type].entries;
226 	count = blobs_all[uc_fw->type].count;
227 
228 	for (i = 0; i < count && p <= entries[i].platform; i++) {
229 		if (p == entries[i].platform) {
230 			uc_fw->path = entries[i].path;
231 			uc_fw->versions.wanted.major = entries[i].major;
232 			uc_fw->versions.wanted.minor = entries[i].minor;
233 			uc_fw->versions.wanted.patch = entries[i].patch;
234 			uc_fw->full_ver_required = entries[i].full_ver_required;
235 
236 			if (uc_fw->type == XE_UC_FW_TYPE_GSC)
237 				uc_fw->versions.wanted_type = XE_UC_FW_VER_COMPATIBILITY;
238 			else
239 				uc_fw->versions.wanted_type = XE_UC_FW_VER_RELEASE;
240 
241 			break;
242 		}
243 	}
244 }
245 
246 static void
247 uc_fw_override(struct xe_uc_fw *uc_fw)
248 {
249 	char *path_override = NULL;
250 
251 	/* empty string disables, but it's not allowed for GuC */
252 	switch (uc_fw->type) {
253 	case XE_UC_FW_TYPE_GUC:
254 		if (xe_modparam.guc_firmware_path && *xe_modparam.guc_firmware_path)
255 			path_override = xe_modparam.guc_firmware_path;
256 		break;
257 	case XE_UC_FW_TYPE_HUC:
258 		path_override = xe_modparam.huc_firmware_path;
259 		break;
260 	case XE_UC_FW_TYPE_GSC:
261 		path_override = xe_modparam.gsc_firmware_path;
262 		break;
263 	default:
264 		break;
265 	}
266 
267 	if (path_override) {
268 		uc_fw->path = path_override;
269 		uc_fw->user_overridden = true;
270 	}
271 }
272 
273 /**
274  * xe_uc_fw_copy_rsa - copy fw RSA to buffer
275  *
276  * @uc_fw: uC firmware
277  * @dst: dst buffer
278  * @max_len: max number of bytes to copy
279  *
280  * Return: number of copied bytes.
281  */
282 size_t xe_uc_fw_copy_rsa(struct xe_uc_fw *uc_fw, void *dst, u32 max_len)
283 {
284 	struct xe_device *xe = uc_fw_to_xe(uc_fw);
285 	u32 size = min_t(u32, uc_fw->rsa_size, max_len);
286 
287 	xe_assert(xe, !(size % 4));
288 	xe_assert(xe, xe_uc_fw_is_available(uc_fw));
289 
290 	xe_map_memcpy_from(xe, dst, &uc_fw->bo->vmap,
291 			   xe_uc_fw_rsa_offset(uc_fw), size);
292 
293 	return size;
294 }
295 
296 static void uc_fw_fini(struct drm_device *drm, void *arg)
297 {
298 	struct xe_uc_fw *uc_fw = arg;
299 
300 	if (!xe_uc_fw_is_available(uc_fw))
301 		return;
302 
303 	xe_uc_fw_change_status(uc_fw, XE_UC_FIRMWARE_SELECTED);
304 }
305 
306 static int guc_read_css_info(struct xe_uc_fw *uc_fw, struct uc_css_header *css)
307 {
308 	struct xe_gt *gt = uc_fw_to_gt(uc_fw);
309 	struct xe_uc_fw_version *release = &uc_fw->versions.found[XE_UC_FW_VER_RELEASE];
310 	struct xe_uc_fw_version *compatibility = &uc_fw->versions.found[XE_UC_FW_VER_COMPATIBILITY];
311 
312 	xe_gt_assert(gt, uc_fw->type == XE_UC_FW_TYPE_GUC);
313 
314 	/* We don't support GuC releases older than 70.29.2 */
315 	if (MAKE_GUC_VER_STRUCT(*release) < MAKE_GUC_VER(70, 29, 2)) {
316 		xe_gt_err(gt, "Unsupported GuC v%u.%u.%u! v70.29.2 or newer is required\n",
317 			  release->major, release->minor, release->patch);
318 		return -EINVAL;
319 	}
320 
321 	compatibility->major = FIELD_GET(CSS_SW_VERSION_UC_MAJOR, css->submission_version);
322 	compatibility->minor = FIELD_GET(CSS_SW_VERSION_UC_MINOR, css->submission_version);
323 	compatibility->patch = FIELD_GET(CSS_SW_VERSION_UC_PATCH, css->submission_version);
324 
325 	uc_fw->private_data_size = css->private_data_size;
326 
327 	return 0;
328 }
329 
330 int xe_uc_fw_check_version_requirements(struct xe_uc_fw *uc_fw)
331 {
332 	struct xe_device *xe = uc_fw_to_xe(uc_fw);
333 	struct xe_uc_fw_version *wanted = &uc_fw->versions.wanted;
334 	struct xe_uc_fw_version *found = &uc_fw->versions.found[uc_fw->versions.wanted_type];
335 
336 	/* Driver has no requirement on any version, any is good. */
337 	if (!wanted->major)
338 		return 0;
339 
340 	/*
341 	 * If full version is required, both major and minor should match.
342 	 * Otherwise, at least the major version.
343 	 */
344 	if (wanted->major != found->major ||
345 	    (uc_fw->full_ver_required &&
346 	     ((wanted->minor != found->minor) ||
347 	      (wanted->patch != found->patch)))) {
348 		drm_notice(&xe->drm, "%s firmware %s: unexpected version: %u.%u.%u != %u.%u.%u\n",
349 			   xe_uc_fw_type_repr(uc_fw->type), uc_fw->path,
350 			   found->major, found->minor, found->patch,
351 			   wanted->major, wanted->minor, wanted->patch);
352 		goto fail;
353 	}
354 
355 	if (wanted->minor > found->minor ||
356 	    (wanted->minor == found->minor && wanted->patch > found->patch)) {
357 		drm_notice(&xe->drm, "%s firmware (%u.%u.%u) is recommended, but only (%u.%u.%u) was found in %s\n",
358 			   xe_uc_fw_type_repr(uc_fw->type),
359 			   wanted->major, wanted->minor, wanted->patch,
360 			   found->major, found->minor, found->patch,
361 			   uc_fw->path);
362 		drm_info(&xe->drm, "Consider updating your linux-firmware pkg or downloading from %s\n",
363 			 XE_UC_FIRMWARE_URL);
364 	}
365 
366 	return 0;
367 
368 fail:
369 	if (xe_uc_fw_is_overridden(uc_fw))
370 		return 0;
371 
372 	return -ENOEXEC;
373 }
374 
375 /* Refer to the "CSS-based Firmware Layout" documentation entry for details */
376 static int parse_css_header(struct xe_uc_fw *uc_fw, const void *fw_data, size_t fw_size)
377 {
378 	struct xe_device *xe = uc_fw_to_xe(uc_fw);
379 	struct xe_uc_fw_version *release = &uc_fw->versions.found[XE_UC_FW_VER_RELEASE];
380 	struct uc_css_header *css;
381 	size_t size;
382 
383 	/* Check the size of the blob before examining buffer contents */
384 	if (unlikely(fw_size < sizeof(struct uc_css_header))) {
385 		drm_warn(&xe->drm, "%s firmware %s: invalid size: %zu < %zu\n",
386 			 xe_uc_fw_type_repr(uc_fw->type), uc_fw->path,
387 			 fw_size, sizeof(struct uc_css_header));
388 		return -ENODATA;
389 	}
390 
391 	css = (struct uc_css_header *)fw_data;
392 
393 	/* Check integrity of size values inside CSS header */
394 	size = (css->header_size_dw - css->key_size_dw - css->modulus_size_dw -
395 		css->exponent_size_dw) * sizeof(u32);
396 	if (unlikely(size != sizeof(struct uc_css_header))) {
397 		drm_warn(&xe->drm,
398 			 "%s firmware %s: unexpected header size: %zu != %zu\n",
399 			 xe_uc_fw_type_repr(uc_fw->type), uc_fw->path,
400 			 fw_size, sizeof(struct uc_css_header));
401 		return -EPROTO;
402 	}
403 
404 	/* uCode size must calculated from other sizes */
405 	uc_fw->ucode_size = (css->size_dw - css->header_size_dw) * sizeof(u32);
406 
407 	/* now RSA */
408 	uc_fw->rsa_size = css->key_size_dw * sizeof(u32);
409 
410 	/* At least, it should have header, uCode and RSA. Size of all three. */
411 	size = sizeof(struct uc_css_header) + uc_fw->ucode_size +
412 		uc_fw->rsa_size;
413 	if (unlikely(fw_size < size)) {
414 		drm_warn(&xe->drm, "%s firmware %s: invalid size: %zu < %zu\n",
415 			 xe_uc_fw_type_repr(uc_fw->type), uc_fw->path,
416 			 fw_size, size);
417 		return -ENOEXEC;
418 	}
419 
420 	/* Get version numbers from the CSS header */
421 	release->major = FIELD_GET(CSS_SW_VERSION_UC_MAJOR, css->sw_version);
422 	release->minor = FIELD_GET(CSS_SW_VERSION_UC_MINOR, css->sw_version);
423 	release->patch = FIELD_GET(CSS_SW_VERSION_UC_PATCH, css->sw_version);
424 
425 	if (uc_fw->type == XE_UC_FW_TYPE_GUC)
426 		return guc_read_css_info(uc_fw, css);
427 
428 	return 0;
429 }
430 
431 static bool is_cpd_header(const void *data)
432 {
433 	const u32 *marker = data;
434 
435 	return *marker == GSC_CPD_HEADER_MARKER;
436 }
437 
438 static u32 entry_offset(const struct gsc_cpd_header_v2 *header, const char *name)
439 {
440 	const struct gsc_cpd_entry *entry;
441 	int i;
442 
443 	entry = (void *)header + header->header_length;
444 
445 	for (i = 0; i < header->num_of_entries; i++, entry++)
446 		if (strcmp(entry->name, name) == 0)
447 			return entry->offset & GSC_CPD_ENTRY_OFFSET_MASK;
448 
449 	return 0;
450 }
451 
452 /* Refer to the "GSC-based Firmware Layout" documentation entry for details */
453 static int parse_cpd_header(struct xe_uc_fw *uc_fw, const void *data, size_t size,
454 			    const char *manifest_entry, const char *css_entry)
455 {
456 	struct xe_gt *gt = uc_fw_to_gt(uc_fw);
457 	struct xe_device *xe = gt_to_xe(gt);
458 	const struct gsc_cpd_header_v2 *header = data;
459 	struct xe_uc_fw_version *release = &uc_fw->versions.found[XE_UC_FW_VER_RELEASE];
460 	const struct gsc_manifest_header *manifest;
461 	size_t min_size = sizeof(*header);
462 	u32 offset;
463 
464 	/* manifest_entry is mandatory, css_entry is optional */
465 	xe_assert(xe, manifest_entry);
466 
467 	if (size < min_size || !is_cpd_header(header))
468 		return -ENOENT;
469 
470 	if (header->header_length < sizeof(struct gsc_cpd_header_v2)) {
471 		xe_gt_err(gt, "invalid CPD header length %u!\n", header->header_length);
472 		return -EINVAL;
473 	}
474 
475 	min_size = header->header_length + sizeof(struct gsc_cpd_entry) * header->num_of_entries;
476 	if (size < min_size) {
477 		xe_gt_err(gt, "FW too small! %zu < %zu\n", size, min_size);
478 		return -ENODATA;
479 	}
480 
481 	/* Look for the manifest first */
482 	offset = entry_offset(header, manifest_entry);
483 	if (!offset) {
484 		xe_gt_err(gt, "Failed to find %s manifest!\n",
485 			  xe_uc_fw_type_repr(uc_fw->type));
486 		return -ENODATA;
487 	}
488 
489 	min_size = offset + sizeof(struct gsc_manifest_header);
490 	if (size < min_size) {
491 		xe_gt_err(gt, "FW too small! %zu < %zu\n", size, min_size);
492 		return -ENODATA;
493 	}
494 
495 	manifest = data + offset;
496 
497 	release->major = manifest->fw_version.major;
498 	release->minor = manifest->fw_version.minor;
499 	release->patch = manifest->fw_version.hotfix;
500 
501 	if (uc_fw->type == XE_UC_FW_TYPE_GSC) {
502 		struct xe_gsc *gsc = container_of(uc_fw, struct xe_gsc, fw);
503 
504 		release->build = manifest->fw_version.build;
505 		gsc->security_version = manifest->security_version;
506 	}
507 
508 	/* then optionally look for the css header */
509 	if (css_entry) {
510 		int ret;
511 
512 		/*
513 		 * This section does not contain a CSS entry on DG2. We
514 		 * don't support DG2 HuC right now, so no need to handle
515 		 * it, just add a reminder in case that changes.
516 		 */
517 		xe_assert(xe, xe->info.platform != XE_DG2);
518 
519 		offset = entry_offset(header, css_entry);
520 
521 		/* the CSS header parser will check that the CSS header fits */
522 		if (offset > size) {
523 			xe_gt_err(gt, "FW too small! %zu < %u\n", size, offset);
524 			return -ENODATA;
525 		}
526 
527 		ret = parse_css_header(uc_fw, data + offset, size - offset);
528 		if (ret)
529 			return ret;
530 
531 		uc_fw->css_offset = offset;
532 	}
533 
534 	uc_fw->has_gsc_headers = true;
535 
536 	return 0;
537 }
538 
539 static int parse_gsc_layout(struct xe_uc_fw *uc_fw, const void *data, size_t size)
540 {
541 	struct xe_gt *gt = uc_fw_to_gt(uc_fw);
542 	const struct gsc_layout_pointers *layout = data;
543 	const struct gsc_bpdt_header *bpdt_header = NULL;
544 	const struct gsc_bpdt_entry *bpdt_entry = NULL;
545 	size_t min_size = sizeof(*layout);
546 	int i;
547 
548 	if (size < min_size) {
549 		xe_gt_err(gt, "GSC FW too small! %zu < %zu\n", size, min_size);
550 		return -ENODATA;
551 	}
552 
553 	min_size = layout->boot1.offset + layout->boot1.size;
554 	if (size < min_size) {
555 		xe_gt_err(gt, "GSC FW too small for boot section! %zu < %zu\n",
556 			  size, min_size);
557 		return -ENODATA;
558 	}
559 
560 	min_size = sizeof(*bpdt_header);
561 	if (layout->boot1.size < min_size) {
562 		xe_gt_err(gt, "GSC FW boot section too small for BPDT header: %u < %zu\n",
563 			  layout->boot1.size, min_size);
564 		return -ENODATA;
565 	}
566 
567 	bpdt_header = data + layout->boot1.offset;
568 	if (bpdt_header->signature != GSC_BPDT_HEADER_SIGNATURE) {
569 		xe_gt_err(gt, "invalid signature for BPDT header: 0x%08x!\n",
570 			  bpdt_header->signature);
571 		return -EINVAL;
572 	}
573 
574 	min_size += sizeof(*bpdt_entry) * bpdt_header->descriptor_count;
575 	if (layout->boot1.size < min_size) {
576 		xe_gt_err(gt, "GSC FW boot section too small for BPDT entries: %u < %zu\n",
577 			  layout->boot1.size, min_size);
578 		return -ENODATA;
579 	}
580 
581 	bpdt_entry = (void *)bpdt_header + sizeof(*bpdt_header);
582 	for (i = 0; i < bpdt_header->descriptor_count; i++, bpdt_entry++) {
583 		if ((bpdt_entry->type & GSC_BPDT_ENTRY_TYPE_MASK) !=
584 		    GSC_BPDT_ENTRY_TYPE_GSC_RBE)
585 			continue;
586 
587 		min_size = bpdt_entry->sub_partition_offset;
588 
589 		/* the CPD header parser will check that the CPD header fits */
590 		if (layout->boot1.size < min_size) {
591 			xe_gt_err(gt, "GSC FW boot section too small for CPD offset: %u < %zu\n",
592 				  layout->boot1.size, min_size);
593 			return -ENODATA;
594 		}
595 
596 		return parse_cpd_header(uc_fw,
597 					(void *)bpdt_header + min_size,
598 					layout->boot1.size - min_size,
599 					"RBEP.man", NULL);
600 	}
601 
602 	xe_gt_err(gt, "couldn't find CPD header in GSC binary!\n");
603 	return -ENODATA;
604 }
605 
606 static int parse_headers(struct xe_uc_fw *uc_fw, const struct firmware *fw)
607 {
608 	int ret;
609 
610 	/*
611 	 * All GuC releases and older HuC ones use CSS headers, while newer HuC
612 	 * releases use GSC CPD headers.
613 	 */
614 	switch (uc_fw->type) {
615 	case XE_UC_FW_TYPE_GSC:
616 		return parse_gsc_layout(uc_fw, fw->data, fw->size);
617 	case XE_UC_FW_TYPE_HUC:
618 		ret = parse_cpd_header(uc_fw, fw->data, fw->size, "HUCP.man", "huc_fw");
619 		if (!ret || ret != -ENOENT)
620 			return ret;
621 		fallthrough;
622 	case XE_UC_FW_TYPE_GUC:
623 		return parse_css_header(uc_fw, fw->data, fw->size);
624 	default:
625 		return -EINVAL;
626 	}
627 
628 	return 0;
629 }
630 
631 #define print_uc_fw_version(p_, version_, prefix_, ...) \
632 do { \
633 	struct xe_uc_fw_version *ver_ = (version_); \
634 	if (ver_->build) \
635 		drm_printf(p_, prefix_ " version %u.%u.%u.%u\n", ##__VA_ARGS__, \
636 			   ver_->major, ver_->minor, \
637 			   ver_->patch, ver_->build); \
638 	else \
639 		drm_printf(p_, prefix_ " version %u.%u.%u\n", ##__VA_ARGS__, \
640 			  ver_->major, ver_->minor, ver_->patch); \
641 } while (0)
642 
643 static int uc_fw_request(struct xe_uc_fw *uc_fw, const struct firmware **firmware_p)
644 {
645 	struct xe_device *xe = uc_fw_to_xe(uc_fw);
646 	struct device *dev = xe->drm.dev;
647 	struct drm_printer p = drm_info_printer(dev);
648 	const struct firmware *fw = NULL;
649 	int err;
650 
651 	/*
652 	 * we use FIRMWARE_UNINITIALIZED to detect checks against uc_fw->status
653 	 * before we're looked at the HW caps to see if we have uc support
654 	 */
655 	BUILD_BUG_ON(XE_UC_FIRMWARE_UNINITIALIZED);
656 	xe_assert(xe, !uc_fw->status);
657 	xe_assert(xe, !uc_fw->path);
658 
659 	uc_fw_auto_select(xe, uc_fw);
660 
661 	if (IS_SRIOV_VF(xe)) {
662 		/* Only GuC/HuC are supported */
663 		if (uc_fw->type != XE_UC_FW_TYPE_GUC &&
664 		    uc_fw->type != XE_UC_FW_TYPE_HUC)
665 			uc_fw->path = NULL;
666 		/* VF will support only firmwares that driver can autoselect */
667 		xe_uc_fw_change_status(uc_fw, uc_fw->path ?
668 				       XE_UC_FIRMWARE_PRELOADED :
669 				       XE_UC_FIRMWARE_NOT_SUPPORTED);
670 		return 0;
671 	}
672 
673 	uc_fw_override(uc_fw);
674 
675 	xe_uc_fw_change_status(uc_fw, uc_fw->path ?
676 			       XE_UC_FIRMWARE_SELECTED :
677 			       XE_UC_FIRMWARE_NOT_SUPPORTED);
678 
679 	if (!xe_uc_fw_is_supported(uc_fw)) {
680 		if (uc_fw->type == XE_UC_FW_TYPE_GUC) {
681 			drm_err(&xe->drm, "No GuC firmware defined for platform\n");
682 			return -ENOENT;
683 		}
684 		return 0;
685 	}
686 
687 	/* an empty path means the firmware is disabled */
688 	if (!xe_device_uc_enabled(xe) || !(*uc_fw->path)) {
689 		xe_uc_fw_change_status(uc_fw, XE_UC_FIRMWARE_DISABLED);
690 		drm_dbg(&xe->drm, "%s disabled", xe_uc_fw_type_repr(uc_fw->type));
691 		return 0;
692 	}
693 
694 	err = request_firmware(&fw, uc_fw->path, dev);
695 	if (err)
696 		goto fail;
697 
698 	err = parse_headers(uc_fw, fw);
699 	if (err)
700 		goto fail;
701 
702 	print_uc_fw_version(&p,
703 			    &uc_fw->versions.found[XE_UC_FW_VER_RELEASE],
704 			    "Using %s firmware from %s",
705 			    xe_uc_fw_type_repr(uc_fw->type), uc_fw->path);
706 
707 	/* for GSC FW we want the compatibility version, which we query after load */
708 	if (uc_fw->type != XE_UC_FW_TYPE_GSC) {
709 		err = xe_uc_fw_check_version_requirements(uc_fw);
710 		if (err)
711 			goto fail;
712 	}
713 
714 	*firmware_p = fw;
715 
716 	return 0;
717 
718 fail:
719 	xe_uc_fw_change_status(uc_fw, err == -ENOENT ?
720 			       XE_UC_FIRMWARE_MISSING :
721 			       XE_UC_FIRMWARE_ERROR);
722 
723 	drm_notice(&xe->drm, "%s firmware %s: fetch failed with error %d\n",
724 		   xe_uc_fw_type_repr(uc_fw->type), uc_fw->path, err);
725 	drm_info(&xe->drm, "%s firmware(s) can be downloaded from %s\n",
726 		 xe_uc_fw_type_repr(uc_fw->type), XE_UC_FIRMWARE_URL);
727 
728 	release_firmware(fw);		/* OK even if fw is NULL */
729 
730 	return err;
731 }
732 
733 static void uc_fw_release(const struct firmware *fw)
734 {
735 	release_firmware(fw);
736 }
737 
738 static int uc_fw_copy(struct xe_uc_fw *uc_fw, const void *data, size_t size, u32 flags)
739 {
740 	struct xe_device *xe = uc_fw_to_xe(uc_fw);
741 	struct xe_gt *gt = uc_fw_to_gt(uc_fw);
742 	struct xe_tile *tile = gt_to_tile(gt);
743 	struct xe_bo *obj;
744 	int err;
745 
746 	obj = xe_managed_bo_create_from_data(xe, tile, data, size, flags);
747 	if (IS_ERR(obj)) {
748 		drm_notice(&xe->drm, "%s firmware %s: failed to create / populate bo",
749 			   xe_uc_fw_type_repr(uc_fw->type), uc_fw->path);
750 		err = PTR_ERR(obj);
751 		goto fail;
752 	}
753 
754 	uc_fw->bo = obj;
755 	uc_fw->size = size;
756 
757 	xe_uc_fw_change_status(uc_fw, XE_UC_FIRMWARE_AVAILABLE);
758 
759 	err = drmm_add_action_or_reset(&xe->drm, uc_fw_fini, uc_fw);
760 	if (err)
761 		goto fail;
762 
763 	return 0;
764 
765 fail:
766 	xe_uc_fw_change_status(uc_fw, XE_UC_FIRMWARE_ERROR);
767 	drm_notice(&xe->drm, "%s firmware %s: copy failed with error %d\n",
768 		   xe_uc_fw_type_repr(uc_fw->type), uc_fw->path, err);
769 
770 	return err;
771 }
772 
773 int xe_uc_fw_init(struct xe_uc_fw *uc_fw)
774 {
775 	const struct firmware *fw = NULL;
776 	int err;
777 
778 	err = uc_fw_request(uc_fw, &fw);
779 	if (err)
780 		return err;
781 
782 	/* no error and no firmware means nothing to copy */
783 	if (!fw)
784 		return 0;
785 
786 	err = uc_fw_copy(uc_fw, fw->data, fw->size,
787 			 XE_BO_FLAG_SYSTEM | XE_BO_FLAG_GGTT |
788 			 XE_BO_FLAG_GGTT_INVALIDATE);
789 
790 	uc_fw_release(fw);
791 
792 	return err;
793 }
794 
795 static u32 uc_fw_ggtt_offset(struct xe_uc_fw *uc_fw)
796 {
797 	return xe_bo_ggtt_addr(uc_fw->bo);
798 }
799 
800 static int uc_fw_xfer(struct xe_uc_fw *uc_fw, u32 offset, u32 dma_flags)
801 {
802 	struct xe_device *xe = uc_fw_to_xe(uc_fw);
803 	struct xe_gt *gt = uc_fw_to_gt(uc_fw);
804 	u64 src_offset;
805 	u32 dma_ctrl;
806 	int ret;
807 
808 	xe_force_wake_assert_held(gt_to_fw(gt), XE_FW_GT);
809 
810 	/* Set the source address for the uCode */
811 	src_offset = uc_fw_ggtt_offset(uc_fw) + uc_fw->css_offset;
812 	xe_mmio_write32(gt, DMA_ADDR_0_LOW, lower_32_bits(src_offset));
813 	xe_mmio_write32(gt, DMA_ADDR_0_HIGH,
814 			upper_32_bits(src_offset) | DMA_ADDRESS_SPACE_GGTT);
815 
816 	/* Set the DMA destination */
817 	xe_mmio_write32(gt, DMA_ADDR_1_LOW, offset);
818 	xe_mmio_write32(gt, DMA_ADDR_1_HIGH, DMA_ADDRESS_SPACE_WOPCM);
819 
820 	/*
821 	 * Set the transfer size. The header plus uCode will be copied to WOPCM
822 	 * via DMA, excluding any other components
823 	 */
824 	xe_mmio_write32(gt, DMA_COPY_SIZE,
825 			sizeof(struct uc_css_header) + uc_fw->ucode_size);
826 
827 	/* Start the DMA */
828 	xe_mmio_write32(gt, DMA_CTRL,
829 			_MASKED_BIT_ENABLE(dma_flags | START_DMA));
830 
831 	/* Wait for DMA to finish */
832 	ret = xe_mmio_wait32(gt, DMA_CTRL, START_DMA, 0, 100000, &dma_ctrl,
833 			     false);
834 	if (ret)
835 		drm_err(&xe->drm, "DMA for %s fw failed, DMA_CTRL=%u\n",
836 			xe_uc_fw_type_repr(uc_fw->type), dma_ctrl);
837 
838 	/* Disable the bits once DMA is over */
839 	xe_mmio_write32(gt, DMA_CTRL, _MASKED_BIT_DISABLE(dma_flags));
840 
841 	return ret;
842 }
843 
844 int xe_uc_fw_upload(struct xe_uc_fw *uc_fw, u32 offset, u32 dma_flags)
845 {
846 	struct xe_device *xe = uc_fw_to_xe(uc_fw);
847 	int err;
848 
849 	/* make sure the status was cleared the last time we reset the uc */
850 	xe_assert(xe, !xe_uc_fw_is_loaded(uc_fw));
851 
852 	if (!xe_uc_fw_is_loadable(uc_fw))
853 		return -ENOEXEC;
854 
855 	/* Call custom loader */
856 	err = uc_fw_xfer(uc_fw, offset, dma_flags);
857 	if (err)
858 		goto fail;
859 
860 	xe_uc_fw_change_status(uc_fw, XE_UC_FIRMWARE_TRANSFERRED);
861 	return 0;
862 
863 fail:
864 	drm_err(&xe->drm, "Failed to load %s firmware %s (%d)\n",
865 		xe_uc_fw_type_repr(uc_fw->type), uc_fw->path,
866 		err);
867 	xe_uc_fw_change_status(uc_fw, XE_UC_FIRMWARE_LOAD_FAIL);
868 	return err;
869 }
870 
871 static const char *version_type_repr(enum xe_uc_fw_version_types type)
872 {
873 	switch (type) {
874 	case XE_UC_FW_VER_RELEASE:
875 		return "release";
876 	case XE_UC_FW_VER_COMPATIBILITY:
877 		return "compatibility";
878 	default:
879 		return "Unknown version type";
880 	}
881 }
882 
883 void xe_uc_fw_print(struct xe_uc_fw *uc_fw, struct drm_printer *p)
884 {
885 	int i;
886 
887 	drm_printf(p, "%s firmware: %s\n",
888 		   xe_uc_fw_type_repr(uc_fw->type), uc_fw->path);
889 	drm_printf(p, "\tstatus: %s\n",
890 		   xe_uc_fw_status_repr(uc_fw->status));
891 
892 	print_uc_fw_version(p, &uc_fw->versions.wanted, "\twanted %s",
893 			    version_type_repr(uc_fw->versions.wanted_type));
894 
895 	for (i = 0; i < XE_UC_FW_VER_TYPE_COUNT; i++) {
896 		struct xe_uc_fw_version *ver = &uc_fw->versions.found[i];
897 
898 		if (ver->major)
899 			print_uc_fw_version(p, ver, "\tfound %s",
900 					    version_type_repr(i));
901 	}
902 
903 	if (uc_fw->ucode_size)
904 		drm_printf(p, "\tuCode: %u bytes\n", uc_fw->ucode_size);
905 	if (uc_fw->rsa_size)
906 		drm_printf(p, "\tRSA: %u bytes\n", uc_fw->rsa_size);
907 }
908