Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
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
90struct 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
101struct 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
159XE_GUC_FIRMWARE_DEFS(XE_UC_MODULE_FIRMWARE,
160 fw_filename_mmp_ver, fw_filename_major_ver)
161XE_HUC_FIRMWARE_DEFS(XE_UC_MODULE_FIRMWARE,
162 fw_filename_mmp_ver, fw_filename_no_ver)
163XE_GSC_FIRMWARE_DEFS(XE_UC_MODULE_FIRMWARE, fw_filename_major_ver)
164
165static 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
182static 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
187static 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
192static void
193uc_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
240static void
241uc_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 */
276size_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
290static 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
300static 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
324int 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
362fail:
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 */
370static 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
425static bool is_cpd_header(const void *data)
426{
427 const u32 *marker = data;
428
429 return *marker == GSC_CPD_HEADER_MARKER;
430}
431
432static 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 */
447static 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
533static 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
600static 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_, ...) \
626do { \
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
637static 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
708fail:
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
723static void uc_fw_release(const struct firmware *fw)
724{
725 release_firmware(fw);
726}
727
728static 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
755fail:
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
763int 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
785static u32 uc_fw_ggtt_offset(struct xe_uc_fw *uc_fw)
786{
787 return xe_bo_ggtt_addr(uc_fw->bo);
788}
789
790static 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
834int 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
853fail:
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
861static 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
873void 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}