RK3368 GPU: Rogue N Init.
[firefly-linux-kernel-4.4.55.git] / drivers / staging / imgtec / rogue / rgxfwload.c
1 /*************************************************************************/ /*!
2 @File
3 @Title          Services firmware load and access routines for Linux
4 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
5 @Description    Device specific functions
6 @License        Dual MIT/GPLv2
7
8 The contents of this file are subject to the MIT license as set out below.
9
10 Permission is hereby granted, free of charge, to any person obtaining a copy
11 of this software and associated documentation files (the "Software"), to deal
12 in the Software without restriction, including without limitation the rights
13 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 copies of the Software, and to permit persons to whom the Software is
15 furnished to do so, subject to the following conditions:
16
17 The above copyright notice and this permission notice shall be included in
18 all copies or substantial portions of the Software.
19
20 Alternatively, the contents of this file may be used under the terms of
21 the GNU General Public License Version 2 ("GPL") in which case the provisions
22 of GPL are applicable instead of those above.
23
24 If you wish to allow use of your version of this file only under the terms of
25 GPL, and not to allow others to use your version of this file under the terms
26 of the MIT license, indicate your decision by deleting the provisions above
27 and replace them with the notice and other provisions required by GPL as set
28 out in the file called "GPL-COPYING" included in this distribution. If you do
29 not delete the provisions above, a recipient may use your version of this file
30 under the terms of either the MIT license or GPL.
31
32 This License is also included in this distribution in the file called
33 "MIT-COPYING".
34
35 EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
36 PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
37 BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
38 PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
39 COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
40 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
41 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
42 */ /**************************************************************************/
43
44 #include <linux/firmware.h>
45 #include <linux/version.h>
46 #include <linux/kernel.h>
47 #include <linux/err.h>
48
49 #include "device.h"
50 #include "module_common.h"
51 #include "rgxfwload.h"
52 #include "pvr_debug.h"
53 #include "srvkm.h"
54
55 struct RGXFW
56 {
57         const struct firmware sFW;
58 };
59
60 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,13,0)) && defined(RGX_FW_SIGNED)
61
62 /* The Linux kernel does not support the RSA PSS padding mode. It only
63  * supports the legacy PKCS#1 padding mode.
64  */
65 #if defined(RGX_FW_PKCS1_PSS_PADDING)
66 #error Linux does not support verification of RSA PSS padded signatures
67 #endif
68
69 #include <crypto/public_key.h>
70 #include <crypto/hash_info.h>
71 #include <crypto/hash.h>
72
73 #include <keys/asymmetric-type.h>
74 #include <keys/system_keyring.h>
75
76 #include "signfw.h"
77
78 static bool VerifyFirmware(const struct firmware *psFW)
79 {
80         struct FirmwareSignatureHeader *psHeader;
81         struct public_key_signature *psPKS;
82         unsigned char *szKeyID, *pcKeyID;
83         size_t uDigestSize, uDescSize;
84         void *pvSignature, *pvSigner;
85         struct crypto_shash *psTFM;
86         struct shash_desc *psDesc;
87         uint32_t ui32SignatureLen;
88         bool bVerified = false;
89         key_ref_t hKey;
90         uint8_t i;
91         int res;
92
93         if (psFW->size < FW_SIGN_BACKWARDS_OFFSET)
94         {
95                 PVR_DPF((PVR_DBG_ERROR, "%s: Firmware is too small (%zu bytes)",
96                                                                 __func__, psFW->size));
97                 goto err_release_firmware;
98         }
99
100         psHeader = (struct FirmwareSignatureHeader *)
101                                         (psFW->data + (psFW->size - FW_SIGN_BACKWARDS_OFFSET));
102
103         /* All derived from u8 so can't be exploited to flow out of this page */
104         pvSigner    = (u8 *)psHeader + sizeof(struct FirmwareSignatureHeader);
105         pcKeyID     = (unsigned char *)((u8 *)pvSigner + psHeader->ui8SignerLen);
106         pvSignature = (u8 *)pcKeyID + psHeader->ui8KeyIDLen;
107
108         /* We cannot update KERNEL_RO in-place, so we must copy the len */
109         ui32SignatureLen = ntohl(psHeader->ui32SignatureLen);
110
111         if (psHeader->ui8Algo >= PKEY_ALGO__LAST)
112         {
113                 PVR_DPF((PVR_DBG_ERROR, "%s: Public key algorithm %u is not supported",
114                                                                 __func__, psHeader->ui8Algo));
115                 goto err_release_firmware;
116         }
117
118         if (psHeader->ui8HashAlgo >= PKEY_HASH__LAST)
119         {
120                 PVR_DPF((PVR_DBG_ERROR, "%s: Hash algorithm %u is not supported",
121                                                                 __func__, psHeader->ui8HashAlgo));
122                 goto err_release_firmware;
123         }
124
125         if (psHeader->ui8IDType != PKEY_ID_X509)
126         {
127                 PVR_DPF((PVR_DBG_ERROR, "%s: Only asymmetric X.509 PKI certificates "
128                                                                 "are supported", __func__));
129                 goto err_release_firmware;
130         }
131
132         /* Generate a hash of the fw data (including the padding) */
133
134         psTFM = crypto_alloc_shash(hash_algo_name[psHeader->ui8HashAlgo], 0, 0);
135         if (IS_ERR(psTFM))
136         {
137                 PVR_DPF((PVR_DBG_ERROR, "%s: crypto_alloc_shash() failed (%ld)",
138                                                                 __func__, PTR_ERR(psTFM)));
139                 goto err_release_firmware;
140         }
141
142         uDescSize = crypto_shash_descsize(psTFM) + sizeof(*psDesc);
143         uDigestSize = crypto_shash_digestsize(psTFM);
144
145         psPKS = kzalloc(sizeof(*psPKS) + uDescSize + uDigestSize, GFP_KERNEL);
146         if (!psPKS)
147                 goto err_free_crypto_shash;
148
149         psDesc = (struct shash_desc *)((u8 *)psPKS + sizeof(*psPKS));
150         psDesc->tfm = psTFM;
151         psDesc->flags = CRYPTO_TFM_REQ_MAY_SLEEP;
152
153         psPKS->pkey_algo = psHeader->ui8Algo;
154         psPKS->pkey_hash_algo = psHeader->ui8HashAlgo;
155
156         psPKS->digest = (u8 *)psPKS + sizeof(*psPKS) + uDescSize;
157         psPKS->digest_size = uDigestSize;
158
159         res = crypto_shash_init(psDesc);
160         if (res < 0)
161         {
162                 PVR_DPF((PVR_DBG_ERROR, "%s: crypto_shash_init() failed (%d)",
163                                                                 __func__, res));
164                 goto err_free_pks;
165         }
166
167         res = crypto_shash_finup(psDesc, psFW->data, psFW->size - FW_SIGN_BACKWARDS_OFFSET,
168                                                          psPKS->digest);
169         if (res < 0)
170         {
171                 PVR_DPF((PVR_DBG_ERROR, "%s: crypto_shash_finup() failed (%d)",
172                                                                 __func__, res));
173                 goto err_free_pks;
174         }
175
176         /* Populate the MPI with the signature payload */
177
178         psPKS->nr_mpi = 1;
179         psPKS->rsa.s = mpi_read_raw_data(pvSignature, ui32SignatureLen);
180         if (!psPKS->rsa.s)
181         {
182                 PVR_DPF((PVR_DBG_ERROR, "%s: mpi_read_raw_data() failed", __func__));
183                 goto err_free_pks;
184         }
185
186         /* Look up the key we'll use to verify this signature */
187
188         szKeyID = kmalloc(psHeader->ui8SignerLen + 2 +
189                                           psHeader->ui8KeyIDLen * 2 + 1, GFP_KERNEL);
190         if (!szKeyID)
191                 goto err_free_mpi;
192
193         memcpy(szKeyID, pvSigner, psHeader->ui8SignerLen);
194
195         szKeyID[psHeader->ui8SignerLen + 0] = ':';
196         szKeyID[psHeader->ui8SignerLen + 1] = ' ';
197
198         for (i = 0; i < psHeader->ui8KeyIDLen; i++)
199                 sprintf(&szKeyID[psHeader->ui8SignerLen + 2 + i * 2],
200                                 "%02x", pcKeyID[i]);
201
202         szKeyID[psHeader->ui8SignerLen + 2 + psHeader->ui8KeyIDLen * 2] = 0;
203
204         hKey = keyring_search(make_key_ref(system_trusted_keyring, 1),
205                                                   &key_type_asymmetric, szKeyID);
206         if (IS_ERR(hKey))
207         {
208                 PVR_DPF((PVR_DBG_ERROR, "Request for unknown key '%s' (%ld)",
209                                                                 szKeyID, PTR_ERR(hKey)));
210                 goto err_free_keyid_string;
211         }
212
213         res = verify_signature(key_ref_to_ptr(hKey), psPKS);
214         if (res)
215         {
216                 PVR_DPF((PVR_DBG_ERROR, "%s: Firmware digital signature verification "
217                                                                 "failed (%d)", __func__, res));
218                 goto err_put_key;
219         }
220
221         PVR_LOG(("Digital signature for '%s' verified successfully.",
222                          RGX_FW_FILENAME));
223         bVerified = true;
224 err_put_key:
225         key_put(key_ref_to_ptr(hKey));
226 err_free_keyid_string:
227         kfree(szKeyID);
228 err_free_mpi:
229         mpi_free(psPKS->rsa.s);
230 err_free_pks:
231         kfree(psPKS);
232 err_free_crypto_shash:
233         crypto_free_shash(psTFM);
234 err_release_firmware:
235         return bVerified;
236 }
237
238 #else /* defined(RGX_FW_SIGNED) */
239
240 static inline bool VerifyFirmware(const struct firmware *psFW)
241 {
242         return true;
243 }
244
245 #endif /* defined(RGX_FW_SIGNED) */
246
247 IMG_INTERNAL struct RGXFW *
248 RGXLoadFirmware(SHARED_DEV_CONNECTION psDeviceNode, const IMG_CHAR *pszBVNCString, const IMG_CHAR *pszBVpNCString)
249 {
250         const struct firmware *psFW;
251         int res;
252
253         if(pszBVNCString != NULL)
254         {
255                 res = request_firmware(&psFW, pszBVNCString, psDeviceNode->psDevConfig->pvOSDevice);
256                 if (res != 0)
257                 {
258                         if(pszBVpNCString != NULL)
259                         {
260                                 PVR_DPF((PVR_DBG_WARNING, "%s: request_firmware('%s') failed (%d), trying '%s'",
261                                                                                 __func__, pszBVNCString, res, pszBVpNCString));
262                                 res = request_firmware(&psFW, pszBVpNCString, psDeviceNode->psDevConfig->pvOSDevice);
263                         }
264                         if (res != 0)
265                         {
266                                 PVR_DPF((PVR_DBG_WARNING, "%s: request_firmware('%s') failed (%d), trying '%s'",
267                                                                                 __func__, pszBVpNCString, res, RGX_FW_FILENAME));
268                                 res = request_firmware(&psFW, RGX_FW_FILENAME, psDeviceNode->psDevConfig->pvOSDevice);
269                         }
270                 }
271         }
272         else
273         {
274                 res = request_firmware(&psFW, RGX_FW_FILENAME, psDeviceNode->psDevConfig->pvOSDevice);
275         }
276         if (res != 0)
277         {
278                 PVR_DPF((PVR_DBG_ERROR, "%s: request_firmware('%s') failed (%d)",
279                                                                 __func__, RGX_FW_FILENAME, res));
280                 return NULL;
281         }
282
283         if (!VerifyFirmware(psFW))
284         {
285                 release_firmware(psFW);
286                 return NULL;
287         }
288
289         return (struct RGXFW *)psFW;
290 }
291
292 IMG_INTERNAL void
293 RGXUnloadFirmware(struct RGXFW *psRGXFW)
294 {
295         const struct firmware *psFW = &psRGXFW->sFW;
296
297         release_firmware(psFW);
298 }
299
300 IMG_INTERNAL size_t
301 RGXFirmwareSize(struct RGXFW *psRGXFW)
302 {
303 #if     defined(PVRSRV_GPUVIRT_GUESTDRV)
304         PVR_UNREFERENCED_PARAMETER(psRGXFW);
305         return 0;
306 #else
307         const struct firmware *psFW = &psRGXFW->sFW;
308
309         return psFW->size;
310 #endif
311 }
312
313 IMG_INTERNAL const void *
314 RGXFirmwareData(struct RGXFW *psRGXFW)
315 {
316         const struct firmware *psFW = &psRGXFW->sFW;
317
318         return psFW->data;
319 }
320
321 /******************************************************************************
322  End of file (rgxfwload.c)
323 ******************************************************************************/