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