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