blob: 40f5ce482792eb1351705694aaccace798e7f379 [file] [log] [blame]
Michal Wajdeczkoa16b4312017-10-04 15:33:25 +00001/*
2 * Copyright © 2016-2017 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
22 *
23 */
24
25#include <linux/firmware.h>
26
27#include "intel_uc_fw.h"
28#include "i915_drv.h"
29
30/**
31 * intel_uc_fw_fetch - fetch uC firmware
32 *
33 * @dev_priv: device private
34 * @uc_fw: uC firmware
35 *
36 * Fetch uC firmware into GEM obj.
37 */
38void intel_uc_fw_fetch(struct drm_i915_private *dev_priv,
39 struct intel_uc_fw *uc_fw)
40{
41 struct pci_dev *pdev = dev_priv->drm.pdev;
42 struct drm_i915_gem_object *obj;
43 const struct firmware *fw = NULL;
44 struct uc_css_header *css;
45 size_t size;
46 int err;
47
48 if (!uc_fw->path)
49 return;
50
51 uc_fw->fetch_status = INTEL_UC_FIRMWARE_PENDING;
52
53 DRM_DEBUG_DRIVER("before requesting firmware: uC fw fetch status %s\n",
54 intel_uc_fw_status_repr(uc_fw->fetch_status));
55
56 err = request_firmware(&fw, uc_fw->path, &pdev->dev);
57 if (err)
58 goto fail;
59 if (!fw)
60 goto fail;
61
62 DRM_DEBUG_DRIVER("fetch uC fw from %s succeeded, fw %p\n",
63 uc_fw->path, fw);
64
65 /* Check the size of the blob before examining buffer contents */
66 if (fw->size < sizeof(struct uc_css_header)) {
67 DRM_NOTE("Firmware header is missing\n");
68 goto fail;
69 }
70
71 css = (struct uc_css_header *)fw->data;
72
73 /* Firmware bits always start from header */
74 uc_fw->header_offset = 0;
75 uc_fw->header_size = (css->header_size_dw - css->modulus_size_dw -
76 css->key_size_dw - css->exponent_size_dw) *
77 sizeof(u32);
78
79 if (uc_fw->header_size != sizeof(struct uc_css_header)) {
80 DRM_NOTE("CSS header definition mismatch\n");
81 goto fail;
82 }
83
84 /* then, uCode */
85 uc_fw->ucode_offset = uc_fw->header_offset + uc_fw->header_size;
86 uc_fw->ucode_size = (css->size_dw - css->header_size_dw) * sizeof(u32);
87
Michal Wajdeczkoafb34842017-10-16 14:47:16 +000088 /* Header and uCode will be loaded to WOPCM */
89 size = uc_fw->header_size + uc_fw->ucode_size;
90 if (size > intel_guc_wopcm_size(dev_priv)) {
91 DRM_WARN("%s: Firmware is too large to fit in WOPCM\n",
92 intel_uc_fw_type_repr(uc_fw->type));
93 err = -E2BIG;
94 goto fail;
95 }
96
Michal Wajdeczkoa16b4312017-10-04 15:33:25 +000097 /* now RSA */
98 if (css->key_size_dw != UOS_RSA_SCRATCH_MAX_COUNT) {
99 DRM_NOTE("RSA key size is bad\n");
100 goto fail;
101 }
102 uc_fw->rsa_offset = uc_fw->ucode_offset + uc_fw->ucode_size;
103 uc_fw->rsa_size = css->key_size_dw * sizeof(u32);
104
105 /* At least, it should have header, uCode and RSA. Size of all three. */
106 size = uc_fw->header_size + uc_fw->ucode_size + uc_fw->rsa_size;
107 if (fw->size < size) {
108 DRM_NOTE("Missing firmware components\n");
109 goto fail;
110 }
111
112 /*
113 * The GuC firmware image has the version number embedded at a
114 * well-known offset within the firmware blob; note that major / minor
115 * version are TWO bytes each (i.e. u16), although all pointers and
116 * offsets are defined in terms of bytes (u8).
117 */
118 switch (uc_fw->type) {
119 case INTEL_UC_FW_TYPE_GUC:
Michal Wajdeczkoa16b4312017-10-04 15:33:25 +0000120 uc_fw->major_ver_found = css->guc.sw_version >> 16;
121 uc_fw->minor_ver_found = css->guc.sw_version & 0xFFFF;
122 break;
123
124 case INTEL_UC_FW_TYPE_HUC:
125 uc_fw->major_ver_found = css->huc.sw_version >> 16;
126 uc_fw->minor_ver_found = css->huc.sw_version & 0xFFFF;
127 break;
128
129 default:
130 DRM_ERROR("Unknown firmware type %d\n", uc_fw->type);
131 err = -ENOEXEC;
132 goto fail;
133 }
134
135 if (uc_fw->major_ver_wanted == 0 && uc_fw->minor_ver_wanted == 0) {
136 DRM_NOTE("Skipping %s firmware version check\n",
137 intel_uc_fw_type_repr(uc_fw->type));
138 } else if (uc_fw->major_ver_found != uc_fw->major_ver_wanted ||
139 uc_fw->minor_ver_found < uc_fw->minor_ver_wanted) {
140 DRM_NOTE("%s firmware version %d.%d, required %d.%d\n",
141 intel_uc_fw_type_repr(uc_fw->type),
142 uc_fw->major_ver_found, uc_fw->minor_ver_found,
143 uc_fw->major_ver_wanted, uc_fw->minor_ver_wanted);
144 err = -ENOEXEC;
145 goto fail;
146 }
147
148 DRM_DEBUG_DRIVER("firmware version %d.%d OK (minimum %d.%d)\n",
149 uc_fw->major_ver_found, uc_fw->minor_ver_found,
150 uc_fw->major_ver_wanted, uc_fw->minor_ver_wanted);
151
152 obj = i915_gem_object_create_from_data(dev_priv, fw->data, fw->size);
153 if (IS_ERR(obj)) {
154 err = PTR_ERR(obj);
155 goto fail;
156 }
157
158 uc_fw->obj = obj;
159 uc_fw->size = fw->size;
160
161 DRM_DEBUG_DRIVER("uC fw fetch status SUCCESS, obj %p\n",
162 uc_fw->obj);
163
164 release_firmware(fw);
165 uc_fw->fetch_status = INTEL_UC_FIRMWARE_SUCCESS;
166 return;
167
168fail:
169 DRM_WARN("Failed to fetch valid uC firmware from %s (error %d)\n",
170 uc_fw->path, err);
171 DRM_DEBUG_DRIVER("uC fw fetch status FAIL; err %d, fw %p, obj %p\n",
172 err, fw, uc_fw->obj);
173
174 release_firmware(fw); /* OK even if fw is NULL */
175 uc_fw->fetch_status = INTEL_UC_FIRMWARE_FAIL;
176}
177
178/**
179 * intel_uc_fw_fini - cleanup uC firmware
180 *
181 * @uc_fw: uC firmware
182 *
183 * Cleans up uC firmware by releasing the firmware GEM obj.
184 */
185void intel_uc_fw_fini(struct intel_uc_fw *uc_fw)
186{
187 struct drm_i915_gem_object *obj;
188
189 obj = fetch_and_zero(&uc_fw->obj);
190 if (obj)
191 i915_gem_object_put(obj);
192
193 uc_fw->fetch_status = INTEL_UC_FIRMWARE_NONE;
194}