Linux Audio

Check our new training course

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