drm/nouveau/secboot: pass max supported FW version to LS load funcs
[linux-2.6-microblaze.git] / drivers / gpu / drm / nouveau / nvkm / subdev / secboot / acr_r367.c
1 /*
2  * Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved.
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 shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20  * DEALINGS IN THE SOFTWARE.
21  */
22
23 #include "acr_r367.h"
24 #include "acr_r361.h"
25
26 #include <core/gpuobj.h>
27
28 /*
29  * r367 ACR: new LS signature format requires a rewrite of LS firmware and
30  * blob creation functions. Also the hsflcn_desc layout has changed slightly.
31  */
32
33 #define LSF_LSB_DEPMAP_SIZE 11
34
35 /**
36  * struct acr_r367_lsf_lsb_header - LS firmware header
37  *
38  * See also struct acr_r352_lsf_lsb_header for documentation.
39  */
40 struct acr_r367_lsf_lsb_header {
41         /**
42          * LS falcon signatures
43          * @prd_keys:           signature to use in production mode
44          * @dgb_keys:           signature to use in debug mode
45          * @b_prd_present:      whether the production key is present
46          * @b_dgb_present:      whether the debug key is present
47          * @falcon_id:          ID of the falcon the ucode applies to
48          */
49         struct {
50                 u8 prd_keys[2][16];
51                 u8 dbg_keys[2][16];
52                 u32 b_prd_present;
53                 u32 b_dbg_present;
54                 u32 falcon_id;
55                 u32 supports_versioning;
56                 u32 version;
57                 u32 depmap_count;
58                 u8 depmap[LSF_LSB_DEPMAP_SIZE * 2 * 4];
59                 u8 kdf[16];
60         } signature;
61         u32 ucode_off;
62         u32 ucode_size;
63         u32 data_size;
64         u32 bl_code_size;
65         u32 bl_imem_off;
66         u32 bl_data_off;
67         u32 bl_data_size;
68         u32 app_code_off;
69         u32 app_code_size;
70         u32 app_data_off;
71         u32 app_data_size;
72         u32 flags;
73 };
74
75 /**
76  * struct acr_r367_lsf_wpr_header - LS blob WPR Header
77  *
78  * See also struct acr_r352_lsf_wpr_header for documentation.
79  */
80 struct acr_r367_lsf_wpr_header {
81         u32 falcon_id;
82         u32 lsb_offset;
83         u32 bootstrap_owner;
84         u32 lazy_bootstrap;
85         u32 bin_version;
86         u32 status;
87 #define LSF_IMAGE_STATUS_NONE                           0
88 #define LSF_IMAGE_STATUS_COPY                           1
89 #define LSF_IMAGE_STATUS_VALIDATION_CODE_FAILED         2
90 #define LSF_IMAGE_STATUS_VALIDATION_DATA_FAILED         3
91 #define LSF_IMAGE_STATUS_VALIDATION_DONE                4
92 #define LSF_IMAGE_STATUS_VALIDATION_SKIPPED             5
93 #define LSF_IMAGE_STATUS_BOOTSTRAP_READY                6
94 #define LSF_IMAGE_STATUS_REVOCATION_CHECK_FAILED                7
95 };
96
97 /**
98  * struct ls_ucode_img_r367 - ucode image augmented with r367 headers
99  */
100 struct ls_ucode_img_r367 {
101         struct ls_ucode_img base;
102
103         struct acr_r367_lsf_wpr_header wpr_header;
104         struct acr_r367_lsf_lsb_header lsb_header;
105 };
106 #define ls_ucode_img_r367(i) container_of(i, struct ls_ucode_img_r367, base)
107
108 struct ls_ucode_img *
109 acr_r367_ls_ucode_img_load(const struct acr_r352 *acr,
110                            const struct nvkm_secboot *sb,
111                            enum nvkm_secboot_falcon falcon_id)
112 {
113         const struct nvkm_subdev *subdev = acr->base.subdev;
114         const struct acr_r352_ls_func *func = acr->func->ls_func[falcon_id];
115         struct ls_ucode_img_r367 *img;
116         int ret;
117
118         img = kzalloc(sizeof(*img), GFP_KERNEL);
119         if (!img)
120                 return ERR_PTR(-ENOMEM);
121
122         img->base.falcon_id = falcon_id;
123
124         ret = func->load(sb, func->version_max, &img->base);
125         if (ret < 0) {
126                 kfree(img->base.ucode_data);
127                 kfree(img->base.sig);
128                 kfree(img);
129                 return ERR_PTR(ret);
130         }
131
132         /* Check that the signature size matches our expectations... */
133         if (img->base.sig_size != sizeof(img->lsb_header.signature)) {
134                 nvkm_error(subdev, "invalid signature size for %s falcon!\n",
135                            nvkm_secboot_falcon_name[falcon_id]);
136                 return ERR_PTR(-EINVAL);
137         }
138
139         /* Copy signature to the right place */
140         memcpy(&img->lsb_header.signature, img->base.sig, img->base.sig_size);
141
142         /* not needed? the signature should already have the right value */
143         img->lsb_header.signature.falcon_id = falcon_id;
144
145         return &img->base;
146 }
147
148 #define LSF_LSB_HEADER_ALIGN 256
149 #define LSF_BL_DATA_ALIGN 256
150 #define LSF_BL_DATA_SIZE_ALIGN 256
151 #define LSF_BL_CODE_SIZE_ALIGN 256
152 #define LSF_UCODE_DATA_ALIGN 4096
153
154 static u32
155 acr_r367_ls_img_fill_headers(struct acr_r352 *acr,
156                              struct ls_ucode_img_r367 *img, u32 offset)
157 {
158         struct ls_ucode_img *_img = &img->base;
159         struct acr_r367_lsf_wpr_header *whdr = &img->wpr_header;
160         struct acr_r367_lsf_lsb_header *lhdr = &img->lsb_header;
161         struct ls_ucode_img_desc *desc = &_img->ucode_desc;
162         const struct acr_r352_ls_func *func =
163                                             acr->func->ls_func[_img->falcon_id];
164
165         /* Fill WPR header */
166         whdr->falcon_id = _img->falcon_id;
167         whdr->bootstrap_owner = acr->base.boot_falcon;
168         whdr->bin_version = lhdr->signature.version;
169         whdr->status = LSF_IMAGE_STATUS_COPY;
170
171         /* Skip bootstrapping falcons started by someone else than ACR */
172         if (acr->lazy_bootstrap & BIT(_img->falcon_id))
173                 whdr->lazy_bootstrap = 1;
174
175         /* Align, save off, and include an LSB header size */
176         offset = ALIGN(offset, LSF_LSB_HEADER_ALIGN);
177         whdr->lsb_offset = offset;
178         offset += sizeof(*lhdr);
179
180         /*
181          * Align, save off, and include the original (static) ucode
182          * image size
183          */
184         offset = ALIGN(offset, LSF_UCODE_DATA_ALIGN);
185         _img->ucode_off = lhdr->ucode_off = offset;
186         offset += _img->ucode_size;
187
188         /*
189          * For falcons that use a boot loader (BL), we append a loader
190          * desc structure on the end of the ucode image and consider
191          * this the boot loader data. The host will then copy the loader
192          * desc args to this space within the WPR region (before locking
193          * down) and the HS bin will then copy them to DMEM 0 for the
194          * loader.
195          */
196         lhdr->bl_code_size = ALIGN(desc->bootloader_size,
197                                    LSF_BL_CODE_SIZE_ALIGN);
198         lhdr->ucode_size = ALIGN(desc->app_resident_data_offset,
199                                  LSF_BL_CODE_SIZE_ALIGN) + lhdr->bl_code_size;
200         lhdr->data_size = ALIGN(desc->app_size, LSF_BL_CODE_SIZE_ALIGN) +
201                                 lhdr->bl_code_size - lhdr->ucode_size;
202         /*
203          * Though the BL is located at 0th offset of the image, the VA
204          * is different to make sure that it doesn't collide the actual
205          * OS VA range
206          */
207         lhdr->bl_imem_off = desc->bootloader_imem_offset;
208         lhdr->app_code_off = desc->app_start_offset +
209                              desc->app_resident_code_offset;
210         lhdr->app_code_size = desc->app_resident_code_size;
211         lhdr->app_data_off = desc->app_start_offset +
212                              desc->app_resident_data_offset;
213         lhdr->app_data_size = desc->app_resident_data_size;
214
215         lhdr->flags = func->lhdr_flags;
216         if (_img->falcon_id == acr->base.boot_falcon)
217                 lhdr->flags |= LSF_FLAG_DMACTL_REQ_CTX;
218
219         /* Align and save off BL descriptor size */
220         lhdr->bl_data_size = ALIGN(func->bl_desc_size, LSF_BL_DATA_SIZE_ALIGN);
221
222         /*
223          * Align, save off, and include the additional BL data
224          */
225         offset = ALIGN(offset, LSF_BL_DATA_ALIGN);
226         lhdr->bl_data_off = offset;
227         offset += lhdr->bl_data_size;
228
229         return offset;
230 }
231
232 int
233 acr_r367_ls_fill_headers(struct acr_r352 *acr, struct list_head *imgs)
234 {
235         struct ls_ucode_img_r367 *img;
236         struct list_head *l;
237         u32 count = 0;
238         u32 offset;
239
240         /* Count the number of images to manage */
241         list_for_each(l, imgs)
242                 count++;
243
244         /*
245          * Start with an array of WPR headers at the base of the WPR.
246          * The expectation here is that the secure falcon will do a single DMA
247          * read of this array and cache it internally so it's ok to pack these.
248          * Also, we add 1 to the falcon count to indicate the end of the array.
249          */
250         offset = sizeof(img->wpr_header) * (count + 1);
251
252         /*
253          * Walk the managed falcons, accounting for the LSB structs
254          * as well as the ucode images.
255          */
256         list_for_each_entry(img, imgs, base.node) {
257                 offset = acr_r367_ls_img_fill_headers(acr, img, offset);
258         }
259
260         return offset;
261 }
262
263 int
264 acr_r367_ls_write_wpr(struct acr_r352 *acr, struct list_head *imgs,
265                       struct nvkm_gpuobj *wpr_blob, u64 wpr_addr)
266 {
267         struct ls_ucode_img *_img;
268         u32 pos = 0;
269         u32 max_desc_size = 0;
270         u8 *gdesc;
271
272         list_for_each_entry(_img, imgs, node) {
273                 const struct acr_r352_ls_func *ls_func =
274                                             acr->func->ls_func[_img->falcon_id];
275
276                 max_desc_size = max(max_desc_size, ls_func->bl_desc_size);
277         }
278
279         gdesc = kmalloc(max_desc_size, GFP_KERNEL);
280         if (!gdesc)
281                 return -ENOMEM;
282
283         nvkm_kmap(wpr_blob);
284
285         list_for_each_entry(_img, imgs, node) {
286                 struct ls_ucode_img_r367 *img = ls_ucode_img_r367(_img);
287                 const struct acr_r352_ls_func *ls_func =
288                                             acr->func->ls_func[_img->falcon_id];
289
290                 nvkm_gpuobj_memcpy_to(wpr_blob, pos, &img->wpr_header,
291                                       sizeof(img->wpr_header));
292
293                 nvkm_gpuobj_memcpy_to(wpr_blob, img->wpr_header.lsb_offset,
294                                      &img->lsb_header, sizeof(img->lsb_header));
295
296                 /* Generate and write BL descriptor */
297                 memset(gdesc, 0, ls_func->bl_desc_size);
298                 ls_func->generate_bl_desc(&acr->base, _img, wpr_addr, gdesc);
299
300                 nvkm_gpuobj_memcpy_to(wpr_blob, img->lsb_header.bl_data_off,
301                                       gdesc, ls_func->bl_desc_size);
302
303                 /* Copy ucode */
304                 nvkm_gpuobj_memcpy_to(wpr_blob, img->lsb_header.ucode_off,
305                                       _img->ucode_data, _img->ucode_size);
306
307                 pos += sizeof(img->wpr_header);
308         }
309
310         nvkm_wo32(wpr_blob, pos, NVKM_SECBOOT_FALCON_INVALID);
311
312         nvkm_done(wpr_blob);
313
314         kfree(gdesc);
315
316         return 0;
317 }
318
319 struct acr_r367_hsflcn_desc {
320         u8 reserved_dmem[0x200];
321         u32 signatures[4];
322         u32 wpr_region_id;
323         u32 wpr_offset;
324         u32 mmu_memory_range;
325 #define FLCN_ACR_MAX_REGIONS 2
326         struct {
327                 u32 no_regions;
328                 struct {
329                         u32 start_addr;
330                         u32 end_addr;
331                         u32 region_id;
332                         u32 read_mask;
333                         u32 write_mask;
334                         u32 client_mask;
335                         u32 shadow_mem_start_addr;
336                 } region_props[FLCN_ACR_MAX_REGIONS];
337         } regions;
338         u32 ucode_blob_size;
339         u64 ucode_blob_base __aligned(8);
340         struct {
341                 u32 vpr_enabled;
342                 u32 vpr_start;
343                 u32 vpr_end;
344                 u32 hdcp_policies;
345         } vpr_desc;
346 };
347
348 void
349 acr_r367_fixup_hs_desc(struct acr_r352 *acr, struct nvkm_secboot *sb,
350                        void *_desc)
351 {
352         struct acr_r367_hsflcn_desc *desc = _desc;
353         struct nvkm_gpuobj *ls_blob = acr->ls_blob;
354
355         /* WPR region information if WPR is not fixed */
356         if (sb->wpr_size == 0) {
357                 u64 wpr_start = ls_blob->addr;
358                 u64 wpr_end = ls_blob->addr + ls_blob->size;
359
360                 if (acr->func->shadow_blob)
361                         wpr_start += ls_blob->size / 2;
362
363                 desc->wpr_region_id = 1;
364                 desc->regions.no_regions = 2;
365                 desc->regions.region_props[0].start_addr = wpr_start >> 8;
366                 desc->regions.region_props[0].end_addr = wpr_end >> 8;
367                 desc->regions.region_props[0].region_id = 1;
368                 desc->regions.region_props[0].read_mask = 0xf;
369                 desc->regions.region_props[0].write_mask = 0xc;
370                 desc->regions.region_props[0].client_mask = 0x2;
371                 if (acr->func->shadow_blob)
372                         desc->regions.region_props[0].shadow_mem_start_addr =
373                                                              ls_blob->addr >> 8;
374                 else
375                         desc->regions.region_props[0].shadow_mem_start_addr = 0;
376         } else {
377                 desc->ucode_blob_base = ls_blob->addr;
378                 desc->ucode_blob_size = ls_blob->size;
379         }
380 }
381
382 const struct acr_r352_func
383 acr_r367_func = {
384         .fixup_hs_desc = acr_r367_fixup_hs_desc,
385         .generate_hs_bl_desc = acr_r361_generate_hs_bl_desc,
386         .hs_bl_desc_size = sizeof(struct acr_r361_flcn_bl_desc),
387         .shadow_blob = true,
388         .ls_ucode_img_load = acr_r367_ls_ucode_img_load,
389         .ls_fill_headers = acr_r367_ls_fill_headers,
390         .ls_write_wpr = acr_r367_ls_write_wpr,
391         .ls_func = {
392                 [NVKM_SECBOOT_FALCON_FECS] = &acr_r361_ls_fecs_func,
393                 [NVKM_SECBOOT_FALCON_GPCCS] = &acr_r361_ls_gpccs_func,
394                 [NVKM_SECBOOT_FALCON_PMU] = &acr_r361_ls_pmu_func,
395                 [NVKM_SECBOOT_FALCON_SEC2] = &acr_r361_ls_sec2_func,
396         },
397 };
398
399 struct nvkm_acr *
400 acr_r367_new(enum nvkm_secboot_falcon boot_falcon,
401              unsigned long managed_falcons)
402 {
403         return acr_r352_new_(&acr_r367_func, boot_falcon, managed_falcons);
404 }