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