]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r352.c
drm/nouveau/secboot: safer zeroing of BL descriptors
[karo-tx-linux.git] / drivers / gpu / drm / nouveau / nvkm / subdev / secboot / acr_r352.c
1 /*
2  * Copyright (c) 2016, 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_r352.h"
24
25 #include <core/gpuobj.h>
26 #include <core/firmware.h>
27 #include <engine/falcon.h>
28
29 /**
30  * struct hsf_fw_header - HS firmware descriptor
31  * @sig_dbg_offset:     offset of the debug signature
32  * @sig_dbg_size:       size of the debug signature
33  * @sig_prod_offset:    offset of the production signature
34  * @sig_prod_size:      size of the production signature
35  * @patch_loc:          offset of the offset (sic) of where the signature is
36  * @patch_sig:          offset of the offset (sic) to add to sig_*_offset
37  * @hdr_offset:         offset of the load header (see struct hs_load_header)
38  * @hdr_size:           size of above header
39  *
40  * This structure is embedded in the HS firmware image at
41  * hs_bin_hdr.header_offset.
42  */
43 struct hsf_fw_header {
44         u32 sig_dbg_offset;
45         u32 sig_dbg_size;
46         u32 sig_prod_offset;
47         u32 sig_prod_size;
48         u32 patch_loc;
49         u32 patch_sig;
50         u32 hdr_offset;
51         u32 hdr_size;
52 };
53
54 /**
55  * struct acr_r352_flcn_bl_desc - DMEM bootloader descriptor
56  * @signature:          16B signature for secure code. 0s if no secure code
57  * @ctx_dma:            DMA context to be used by BL while loading code/data
58  * @code_dma_base:      256B-aligned Physical FB Address where code is located
59  *                      (falcon's $xcbase register)
60  * @non_sec_code_off:   offset from code_dma_base where the non-secure code is
61  *                      located. The offset must be multiple of 256 to help perf
62  * @non_sec_code_size:  the size of the nonSecure code part.
63  * @sec_code_off:       offset from code_dma_base where the secure code is
64  *                      located. The offset must be multiple of 256 to help perf
65  * @sec_code_size:      offset from code_dma_base where the secure code is
66  *                      located. The offset must be multiple of 256 to help perf
67  * @code_entry_point:   code entry point which will be invoked by BL after
68  *                      code is loaded.
69  * @data_dma_base:      256B aligned Physical FB Address where data is located.
70  *                      (falcon's $xdbase register)
71  * @data_size:          size of data block. Should be multiple of 256B
72  *
73  * Structure used by the bootloader to load the rest of the code. This has
74  * to be filled by host and copied into DMEM at offset provided in the
75  * hsflcn_bl_desc.bl_desc_dmem_load_off.
76  */
77 struct acr_r352_flcn_bl_desc {
78         u32 reserved[4];
79         u32 signature[4];
80         u32 ctx_dma;
81         u32 code_dma_base;
82         u32 non_sec_code_off;
83         u32 non_sec_code_size;
84         u32 sec_code_off;
85         u32 sec_code_size;
86         u32 code_entry_point;
87         u32 data_dma_base;
88         u32 data_size;
89 };
90
91 /**
92  * acr_r352_generate_flcn_bl_desc - generate generic BL descriptor for LS image
93  */
94 static void
95 acr_r352_generate_flcn_bl_desc(const struct nvkm_acr *acr,
96                                const struct ls_ucode_img *_img, u64 wpr_addr,
97                                void *_desc)
98 {
99         struct ls_ucode_img_r352 *img = ls_ucode_img_r352(_img);
100         struct acr_r352_flcn_bl_desc *desc = _desc;
101         const struct ls_ucode_img_desc *pdesc = &_img->ucode_desc;
102         u64 base, addr_code, addr_data;
103
104         base = wpr_addr + img->lsb_header.ucode_off + pdesc->app_start_offset;
105         addr_code = (base + pdesc->app_resident_code_offset) >> 8;
106         addr_data = (base + pdesc->app_resident_data_offset) >> 8;
107
108         desc->ctx_dma = FALCON_DMAIDX_UCODE;
109         desc->code_dma_base = lower_32_bits(addr_code);
110         desc->non_sec_code_off = pdesc->app_resident_code_offset;
111         desc->non_sec_code_size = pdesc->app_resident_code_size;
112         desc->code_entry_point = pdesc->app_imem_entry;
113         desc->data_dma_base = lower_32_bits(addr_data);
114         desc->data_size = pdesc->app_resident_data_size;
115 }
116
117
118 /**
119  * struct hsflcn_acr_desc - data section of the HS firmware
120  *
121  * This header is to be copied at the beginning of DMEM by the HS bootloader.
122  *
123  * @signature:          signature of ACR ucode
124  * @wpr_region_id:      region ID holding the WPR header and its details
125  * @wpr_offset:         offset from the WPR region holding the wpr header
126  * @regions:            region descriptors
127  * @nonwpr_ucode_blob_size:     size of LS blob
128  * @nonwpr_ucode_blob_start:    FB location of LS blob is
129  */
130 struct hsflcn_acr_desc {
131         union {
132                 u8 reserved_dmem[0x200];
133                 u32 signatures[4];
134         } ucode_reserved_space;
135         u32 wpr_region_id;
136         u32 wpr_offset;
137         u32 mmu_mem_range;
138 #define FLCN_ACR_MAX_REGIONS 2
139         struct {
140                 u32 no_regions;
141                 struct {
142                         u32 start_addr;
143                         u32 end_addr;
144                         u32 region_id;
145                         u32 read_mask;
146                         u32 write_mask;
147                         u32 client_mask;
148                 } region_props[FLCN_ACR_MAX_REGIONS];
149         } regions;
150         u32 ucode_blob_size;
151         u64 ucode_blob_base __aligned(8);
152         struct {
153                 u32 vpr_enabled;
154                 u32 vpr_start;
155                 u32 vpr_end;
156                 u32 hdcp_policies;
157         } vpr_desc;
158 };
159
160
161 /*
162  * Low-secure blob creation
163  */
164
165 /**
166  * ls_ucode_img_load() - create a lsf_ucode_img and load it
167  */
168 struct ls_ucode_img *
169 acr_r352_ls_ucode_img_load(const struct acr_r352 *acr,
170                            enum nvkm_secboot_falcon falcon_id)
171 {
172         const struct nvkm_subdev *subdev = acr->base.subdev;
173         struct ls_ucode_img_r352 *img;
174         int ret;
175
176         img = kzalloc(sizeof(*img), GFP_KERNEL);
177         if (!img)
178                 return ERR_PTR(-ENOMEM);
179
180         img->base.falcon_id = falcon_id;
181
182         ret = acr->func->ls_func[falcon_id]->load(subdev, &img->base);
183
184         if (ret) {
185                 kfree(img->base.ucode_data);
186                 kfree(img->base.sig);
187                 kfree(img);
188                 return ERR_PTR(ret);
189         }
190
191         /* Check that the signature size matches our expectations... */
192         if (img->base.sig_size != sizeof(img->lsb_header.signature)) {
193                 nvkm_error(subdev, "invalid signature size for %s falcon!\n",
194                            nvkm_secboot_falcon_name[falcon_id]);
195                 return ERR_PTR(-EINVAL);
196         }
197
198         /* Copy signature to the right place */
199         memcpy(&img->lsb_header.signature, img->base.sig, img->base.sig_size);
200
201         /* not needed? the signature should already have the right value */
202         img->lsb_header.signature.falcon_id = falcon_id;
203
204         return &img->base;
205 }
206
207 #define LSF_LSB_HEADER_ALIGN 256
208 #define LSF_BL_DATA_ALIGN 256
209 #define LSF_BL_DATA_SIZE_ALIGN 256
210 #define LSF_BL_CODE_SIZE_ALIGN 256
211 #define LSF_UCODE_DATA_ALIGN 4096
212
213 /**
214  * acr_r352_ls_img_fill_headers - fill the WPR and LSB headers of an image
215  * @acr:        ACR to use
216  * @img:        image to generate for
217  * @offset:     offset in the WPR region where this image starts
218  *
219  * Allocate space in the WPR area from offset and write the WPR and LSB headers
220  * accordingly.
221  *
222  * Return: offset at the end of this image.
223  */
224 static u32
225 acr_r352_ls_img_fill_headers(struct acr_r352 *acr,
226                              struct ls_ucode_img_r352 *img, u32 offset)
227 {
228         struct ls_ucode_img *_img = &img->base;
229         struct acr_r352_lsf_wpr_header *whdr = &img->wpr_header;
230         struct acr_r352_lsf_lsb_header *lhdr = &img->lsb_header;
231         struct ls_ucode_img_desc *desc = &_img->ucode_desc;
232         const struct acr_r352_ls_func *func =
233                                             acr->func->ls_func[_img->falcon_id];
234
235         /* Fill WPR header */
236         whdr->falcon_id = _img->falcon_id;
237         whdr->bootstrap_owner = acr->base.boot_falcon;
238         whdr->status = LSF_IMAGE_STATUS_COPY;
239
240         /* Align, save off, and include an LSB header size */
241         offset = ALIGN(offset, LSF_LSB_HEADER_ALIGN);
242         whdr->lsb_offset = offset;
243         offset += sizeof(*lhdr);
244
245         /*
246          * Align, save off, and include the original (static) ucode
247          * image size
248          */
249         offset = ALIGN(offset, LSF_UCODE_DATA_ALIGN);
250         lhdr->ucode_off = offset;
251         offset += _img->ucode_size;
252
253         /*
254          * For falcons that use a boot loader (BL), we append a loader
255          * desc structure on the end of the ucode image and consider
256          * this the boot loader data. The host will then copy the loader
257          * desc args to this space within the WPR region (before locking
258          * down) and the HS bin will then copy them to DMEM 0 for the
259          * loader.
260          */
261         lhdr->bl_code_size = ALIGN(desc->bootloader_size,
262                                    LSF_BL_CODE_SIZE_ALIGN);
263         lhdr->ucode_size = ALIGN(desc->app_resident_data_offset,
264                                  LSF_BL_CODE_SIZE_ALIGN) + lhdr->bl_code_size;
265         lhdr->data_size = ALIGN(desc->app_size, LSF_BL_CODE_SIZE_ALIGN) +
266                                 lhdr->bl_code_size - lhdr->ucode_size;
267         /*
268          * Though the BL is located at 0th offset of the image, the VA
269          * is different to make sure that it doesn't collide the actual
270          * OS VA range
271          */
272         lhdr->bl_imem_off = desc->bootloader_imem_offset;
273         lhdr->app_code_off = desc->app_start_offset +
274                              desc->app_resident_code_offset;
275         lhdr->app_code_size = desc->app_resident_code_size;
276         lhdr->app_data_off = desc->app_start_offset +
277                              desc->app_resident_data_offset;
278         lhdr->app_data_size = desc->app_resident_data_size;
279
280         lhdr->flags = func->lhdr_flags;
281         if (_img->falcon_id == acr->base.boot_falcon)
282                 lhdr->flags |= LSF_FLAG_DMACTL_REQ_CTX;
283
284         /* Align and save off BL descriptor size */
285         lhdr->bl_data_size = ALIGN(func->bl_desc_size, LSF_BL_DATA_SIZE_ALIGN);
286
287         /*
288          * Align, save off, and include the additional BL data
289          */
290         offset = ALIGN(offset, LSF_BL_DATA_ALIGN);
291         lhdr->bl_data_off = offset;
292         offset += lhdr->bl_data_size;
293
294         return offset;
295 }
296
297 /**
298  * acr_r352_ls_fill_headers - fill WPR and LSB headers of all managed images
299  */
300 int
301 acr_r352_ls_fill_headers(struct acr_r352 *acr, struct list_head *imgs)
302 {
303         struct ls_ucode_img_r352 *img;
304         struct list_head *l;
305         u32 count = 0;
306         u32 offset;
307
308         /* Count the number of images to manage */
309         list_for_each(l, imgs)
310                 count++;
311
312         /*
313          * Start with an array of WPR headers at the base of the WPR.
314          * The expectation here is that the secure falcon will do a single DMA
315          * read of this array and cache it internally so it's ok to pack these.
316          * Also, we add 1 to the falcon count to indicate the end of the array.
317          */
318         offset = sizeof(img->wpr_header) * (count + 1);
319
320         /*
321          * Walk the managed falcons, accounting for the LSB structs
322          * as well as the ucode images.
323          */
324         list_for_each_entry(img, imgs, base.node) {
325                 offset = acr_r352_ls_img_fill_headers(acr, img, offset);
326         }
327
328         return offset;
329 }
330
331 /**
332  * acr_r352_ls_write_wpr - write the WPR blob contents
333  */
334 int
335 acr_r352_ls_write_wpr(struct acr_r352 *acr, struct list_head *imgs,
336                       struct nvkm_gpuobj *wpr_blob, u32 wpr_addr)
337 {
338         struct ls_ucode_img *_img;
339         u32 pos = 0;
340
341         nvkm_kmap(wpr_blob);
342
343         list_for_each_entry(_img, imgs, node) {
344                 struct ls_ucode_img_r352 *img = ls_ucode_img_r352(_img);
345                 const struct acr_r352_ls_func *ls_func =
346                                             acr->func->ls_func[_img->falcon_id];
347                 u8 gdesc[ls_func->bl_desc_size];
348
349                 nvkm_gpuobj_memcpy_to(wpr_blob, pos, &img->wpr_header,
350                                       sizeof(img->wpr_header));
351
352                 nvkm_gpuobj_memcpy_to(wpr_blob, img->wpr_header.lsb_offset,
353                                      &img->lsb_header, sizeof(img->lsb_header));
354
355                 /* Generate and write BL descriptor */
356                 memset(gdesc, 0, ls_func->bl_desc_size);
357                 ls_func->generate_bl_desc(&acr->base, _img, wpr_addr, gdesc);
358
359                 nvkm_gpuobj_memcpy_to(wpr_blob, img->lsb_header.bl_data_off,
360                                       gdesc, ls_func->bl_desc_size);
361
362                 /* Copy ucode */
363                 nvkm_gpuobj_memcpy_to(wpr_blob, img->lsb_header.ucode_off,
364                                       _img->ucode_data, _img->ucode_size);
365
366                 pos += sizeof(img->wpr_header);
367         }
368
369         nvkm_wo32(wpr_blob, pos, NVKM_SECBOOT_FALCON_INVALID);
370
371         nvkm_done(wpr_blob);
372
373         return 0;
374 }
375
376 /* Both size and address of WPR need to be 128K-aligned */
377 #define WPR_ALIGNMENT   0x20000
378 /**
379  * acr_r352_prepare_ls_blob() - prepare the LS blob
380  *
381  * For each securely managed falcon, load the FW, signatures and bootloaders and
382  * prepare a ucode blob. Then, compute the offsets in the WPR region for each
383  * blob, and finally write the headers and ucode blobs into a GPU object that
384  * will be copied into the WPR region by the HS firmware.
385  */
386 static int
387 acr_r352_prepare_ls_blob(struct acr_r352 *acr, u64 wpr_addr, u32 wpr_size)
388 {
389         const struct nvkm_subdev *subdev = acr->base.subdev;
390         struct list_head imgs;
391         struct ls_ucode_img *img, *t;
392         unsigned long managed_falcons = acr->base.managed_falcons;
393         int managed_count = 0;
394         u32 image_wpr_size;
395         int falcon_id;
396         int ret;
397
398         INIT_LIST_HEAD(&imgs);
399
400         /* Load all LS blobs */
401         for_each_set_bit(falcon_id, &managed_falcons, NVKM_SECBOOT_FALCON_END) {
402                 struct ls_ucode_img *img;
403
404                 img = acr->func->ls_ucode_img_load(acr, falcon_id);
405                 if (IS_ERR(img)) {
406                         ret = PTR_ERR(img);
407                         goto cleanup;
408                 }
409
410                 list_add_tail(&img->node, &imgs);
411                 managed_count++;
412         }
413
414         /*
415          * Fill the WPR and LSF headers with the right offsets and compute
416          * required WPR size
417          */
418         image_wpr_size = acr->func->ls_fill_headers(acr, &imgs);
419         image_wpr_size = ALIGN(image_wpr_size, WPR_ALIGNMENT);
420
421         /* Allocate GPU object that will contain the WPR region */
422         ret = nvkm_gpuobj_new(subdev->device, image_wpr_size, WPR_ALIGNMENT,
423                               false, NULL, &acr->ls_blob);
424         if (ret)
425                 goto cleanup;
426
427         nvkm_debug(subdev, "%d managed LS falcons, WPR size is %d bytes\n",
428                     managed_count, image_wpr_size);
429
430         /* If WPR address and size are not fixed, set them to fit the LS blob */
431         if (wpr_size == 0) {
432                 wpr_addr = acr->ls_blob->addr;
433                 wpr_size = image_wpr_size;
434         /*
435          * But if the WPR region is set by the bootloader, it is illegal for
436          * the HS blob to be larger than this region.
437          */
438         } else if (image_wpr_size > wpr_size) {
439                 nvkm_error(subdev, "WPR region too small for FW blob!\n");
440                 nvkm_error(subdev, "required: %dB\n", image_wpr_size);
441                 nvkm_error(subdev, "available: %dB\n", wpr_size);
442                 ret = -ENOSPC;
443                 goto cleanup;
444         }
445
446         /* Write LS blob */
447         ret = acr->func->ls_write_wpr(acr, &imgs, acr->ls_blob, wpr_addr);
448         if (ret)
449                 nvkm_gpuobj_del(&acr->ls_blob);
450
451 cleanup:
452         list_for_each_entry_safe(img, t, &imgs, node) {
453                 kfree(img->ucode_data);
454                 kfree(img->sig);
455                 kfree(img);
456         }
457
458         return ret;
459 }
460
461
462
463
464 /**
465  * acr_r352_hsf_patch_signature() - patch HS blob with correct signature
466  */
467 static void
468 acr_r352_hsf_patch_signature(struct nvkm_secboot *sb, void *acr_image)
469 {
470         struct fw_bin_header *hsbin_hdr = acr_image;
471         struct hsf_fw_header *fw_hdr = acr_image + hsbin_hdr->header_offset;
472         void *hs_data = acr_image + hsbin_hdr->data_offset;
473         void *sig;
474         u32 sig_size;
475
476         /* Falcon in debug or production mode? */
477         if (sb->boot_falcon->debug) {
478                 sig = acr_image + fw_hdr->sig_dbg_offset;
479                 sig_size = fw_hdr->sig_dbg_size;
480         } else {
481                 sig = acr_image + fw_hdr->sig_prod_offset;
482                 sig_size = fw_hdr->sig_prod_size;
483         }
484
485         /* Patch signature */
486         memcpy(hs_data + fw_hdr->patch_loc, sig + fw_hdr->patch_sig, sig_size);
487 }
488
489 static void
490 acr_r352_fixup_hs_desc(struct acr_r352 *acr, struct nvkm_secboot *sb,
491                        struct hsflcn_acr_desc *desc)
492 {
493         struct nvkm_gpuobj *ls_blob = acr->ls_blob;
494
495         desc->ucode_blob_base = ls_blob->addr;
496         desc->ucode_blob_size = ls_blob->size;
497
498         desc->wpr_offset = 0;
499
500         /* WPR region information if WPR is not fixed */
501         if (sb->wpr_size == 0) {
502                 desc->wpr_region_id = 1;
503                 desc->regions.no_regions = 1;
504                 desc->regions.region_props[0].region_id = 1;
505                 desc->regions.region_props[0].start_addr = ls_blob->addr >> 8;
506                 desc->regions.region_props[0].end_addr =
507                                            (ls_blob->addr + ls_blob->size) >> 8;
508         }
509 }
510
511 static void
512 acr_r352_generate_hs_bl_desc(const struct hsf_load_header *hdr, void *_bl_desc,
513                              u64 offset)
514 {
515         struct acr_r352_flcn_bl_desc *bl_desc = _bl_desc;
516         u64 addr_code, addr_data;
517
518         addr_code = offset >> 8;
519         addr_data = (offset + hdr->data_dma_base) >> 8;
520
521         bl_desc->ctx_dma = FALCON_DMAIDX_VIRT;
522         bl_desc->code_dma_base = lower_32_bits(addr_code);
523         bl_desc->non_sec_code_off = hdr->non_sec_code_off;
524         bl_desc->non_sec_code_size = hdr->non_sec_code_size;
525         bl_desc->sec_code_off = hdr->app[0].sec_code_off;
526         bl_desc->sec_code_size = hdr->app[0].sec_code_size;
527         bl_desc->code_entry_point = 0;
528         bl_desc->data_dma_base = lower_32_bits(addr_data);
529         bl_desc->data_size = hdr->data_size;
530 }
531
532 /**
533  * acr_r352_prepare_hs_blob - load and prepare a HS blob and BL descriptor
534  *
535  * @sb secure boot instance to prepare for
536  * @fw name of the HS firmware to load
537  * @blob pointer to gpuobj that will be allocated to receive the HS FW payload
538  * @bl_desc pointer to the BL descriptor to write for this firmware
539  * @patch whether we should patch the HS descriptor (only for HS loaders)
540  */
541 static int
542 acr_r352_prepare_hs_blob(struct acr_r352 *acr, struct nvkm_secboot *sb,
543                          const char *fw, struct nvkm_gpuobj **blob,
544                          struct hsf_load_header *load_header, bool patch)
545 {
546         struct nvkm_subdev *subdev = &sb->subdev;
547         void *acr_image;
548         struct fw_bin_header *hsbin_hdr;
549         struct hsf_fw_header *fw_hdr;
550         struct hsf_load_header *load_hdr;
551         void *acr_data;
552         int ret;
553
554         acr_image = nvkm_acr_load_firmware(subdev, fw, 0);
555         if (IS_ERR(acr_image))
556                 return PTR_ERR(acr_image);
557
558         hsbin_hdr = acr_image;
559         fw_hdr = acr_image + hsbin_hdr->header_offset;
560         load_hdr = acr_image + fw_hdr->hdr_offset;
561         acr_data = acr_image + hsbin_hdr->data_offset;
562
563         /* Patch signature */
564         acr_r352_hsf_patch_signature(sb, acr_image);
565
566         /* Patch descriptor with WPR information? */
567         if (patch) {
568                 struct hsflcn_acr_desc *desc;
569
570                 desc = acr_data + load_hdr->data_dma_base;
571                 acr_r352_fixup_hs_desc(acr, sb, desc);
572         }
573
574         if (load_hdr->num_apps > ACR_R352_MAX_APPS) {
575                 nvkm_error(subdev, "more apps (%d) than supported (%d)!",
576                            load_hdr->num_apps, ACR_R352_MAX_APPS);
577                 ret = -EINVAL;
578                 goto cleanup;
579         }
580         memcpy(load_header, load_hdr, sizeof(*load_header) +
581                                (sizeof(load_hdr->app[0]) * load_hdr->num_apps));
582
583         /* Create ACR blob and copy HS data to it */
584         ret = nvkm_gpuobj_new(subdev->device, ALIGN(hsbin_hdr->data_size, 256),
585                               0x1000, false, NULL, blob);
586         if (ret)
587                 goto cleanup;
588
589         nvkm_kmap(*blob);
590         nvkm_gpuobj_memcpy_to(*blob, 0, acr_data, hsbin_hdr->data_size);
591         nvkm_done(*blob);
592
593 cleanup:
594         kfree(acr_image);
595
596         return ret;
597 }
598
599 static int
600 acr_r352_prepare_hsbl_blob(struct acr_r352 *acr)
601 {
602         const struct nvkm_subdev *subdev = acr->base.subdev;
603         struct fw_bin_header *hdr;
604         struct fw_bl_desc *hsbl_desc;
605
606         acr->hsbl_blob = nvkm_acr_load_firmware(subdev, "acr/bl", 0);
607         if (IS_ERR(acr->hsbl_blob)) {
608                 int ret = PTR_ERR(acr->hsbl_blob);
609
610                 acr->hsbl_blob = NULL;
611                 return ret;
612         }
613
614         hdr = acr->hsbl_blob;
615         hsbl_desc = acr->hsbl_blob + hdr->header_offset;
616
617         /* virtual start address for boot vector */
618         acr->base.start_address = hsbl_desc->start_tag << 8;
619
620         return 0;
621 }
622
623 /**
624  * acr_r352_load_blobs - load blobs common to all ACR V1 versions.
625  *
626  * This includes the LS blob, HS ucode loading blob, and HS bootloader.
627  *
628  * The HS ucode unload blob is only used on dGPU if the WPR region is variable.
629  */
630 int
631 acr_r352_load_blobs(struct acr_r352 *acr, struct nvkm_secboot *sb)
632 {
633         int ret;
634
635         /* Firmware already loaded? */
636         if (acr->firmware_ok)
637                 return 0;
638
639         /* Load and prepare the managed falcon's firmwares */
640         ret = acr_r352_prepare_ls_blob(acr, sb->wpr_addr, sb->wpr_size);
641         if (ret)
642                 return ret;
643
644         /* Load the HS firmware that will load the LS firmwares */
645         if (!acr->load_blob) {
646                 ret = acr_r352_prepare_hs_blob(acr, sb, "acr/ucode_load",
647                                                &acr->load_blob,
648                                                &acr->load_bl_header, true);
649                 if (ret)
650                         return ret;
651         }
652
653         /* If the ACR region is dynamically programmed, we need an unload FW */
654         if (sb->wpr_size == 0) {
655                 ret = acr_r352_prepare_hs_blob(acr, sb, "acr/ucode_unload",
656                                                &acr->unload_blob,
657                                                &acr->unload_bl_header, false);
658                 if (ret)
659                         return ret;
660         }
661
662         /* Load the HS firmware bootloader */
663         if (!acr->hsbl_blob) {
664                 ret = acr_r352_prepare_hsbl_blob(acr);
665                 if (ret)
666                         return ret;
667         }
668
669         acr->firmware_ok = true;
670         nvkm_debug(&sb->subdev, "LS blob successfully created\n");
671
672         return 0;
673 }
674
675 /**
676  * acr_r352_load() - prepare HS falcon to run the specified blob, mapped
677  * at GPU address offset.
678  */
679 static int
680 acr_r352_load(struct nvkm_acr *_acr, struct nvkm_secboot *sb,
681               struct nvkm_gpuobj *blob, u64 offset)
682 {
683         struct acr_r352 *acr = acr_r352(_acr);
684         struct nvkm_falcon *falcon = sb->boot_falcon;
685         struct fw_bin_header *hdr = acr->hsbl_blob;
686         struct fw_bl_desc *hsbl_desc = acr->hsbl_blob + hdr->header_offset;
687         void *blob_data = acr->hsbl_blob + hdr->data_offset;
688         void *hsbl_code = blob_data + hsbl_desc->code_off;
689         void *hsbl_data = blob_data + hsbl_desc->data_off;
690         u32 code_size = ALIGN(hsbl_desc->code_size, 256);
691         const struct hsf_load_header *load_hdr;
692         const u32 bl_desc_size = acr->func->hs_bl_desc_size;
693         u8 bl_desc[bl_desc_size];
694
695         /* Find the bootloader descriptor for our blob and copy it */
696         if (blob == acr->load_blob) {
697                 load_hdr = &acr->load_bl_header;
698         } else if (blob == acr->unload_blob) {
699                 load_hdr = &acr->unload_bl_header;
700         } else {
701                 nvkm_error(_acr->subdev, "invalid secure boot blob!\n");
702                 return -EINVAL;
703         }
704
705         /*
706          * Copy HS bootloader data
707          */
708         nvkm_falcon_load_dmem(falcon, hsbl_data, 0x0, hsbl_desc->data_size, 0);
709
710         /* Copy HS bootloader code to end of IMEM */
711         nvkm_falcon_load_imem(falcon, hsbl_code, falcon->code.limit - code_size,
712                               code_size, hsbl_desc->start_tag, 0, false);
713
714         /* Generate the BL header */
715         memset(bl_desc, 0, bl_desc_size);
716         acr->func->generate_hs_bl_desc(load_hdr, bl_desc, offset);
717
718         /*
719          * Copy HS BL header where the HS descriptor expects it to be
720          */
721         nvkm_falcon_load_dmem(falcon, bl_desc, hsbl_desc->dmem_load_off,
722                               bl_desc_size, 0);
723
724         return 0;
725 }
726
727 static int
728 acr_r352_shutdown(struct acr_r352 *acr, struct nvkm_secboot *sb)
729 {
730         int i;
731
732         /* Run the unload blob to unprotect the WPR region */
733         if (acr->unload_blob && sb->wpr_set) {
734                 int ret;
735
736                 nvkm_debug(&sb->subdev, "running HS unload blob\n");
737                 ret = sb->func->run_blob(sb, acr->unload_blob);
738                 if (ret)
739                         return ret;
740                 nvkm_debug(&sb->subdev, "HS unload blob completed\n");
741         }
742
743         for (i = 0; i < NVKM_SECBOOT_FALCON_END; i++)
744                 acr->falcon_state[i] = NON_SECURE;
745
746         sb->wpr_set = false;
747
748         return 0;
749 }
750
751 static int
752 acr_r352_bootstrap(struct acr_r352 *acr, struct nvkm_secboot *sb)
753 {
754         int ret;
755
756         if (sb->wpr_set)
757                 return 0;
758
759         /* Make sure all blobs are ready */
760         ret = acr_r352_load_blobs(acr, sb);
761         if (ret)
762                 return ret;
763
764         nvkm_debug(&sb->subdev, "running HS load blob\n");
765         ret = sb->func->run_blob(sb, acr->load_blob);
766         if (ret)
767                 return ret;
768         nvkm_debug(&sb->subdev, "HS load blob completed\n");
769
770         sb->wpr_set = true;
771
772         return 0;
773 }
774
775 /*
776  * acr_r352_reset() - execute secure boot from the prepared state
777  *
778  * Load the HS bootloader and ask the falcon to run it. This will in turn
779  * load the HS firmware and run it, so once the falcon stops all the managed
780  * falcons should have their LS firmware loaded and be ready to run.
781  */
782 static int
783 acr_r352_reset(struct nvkm_acr *_acr, struct nvkm_secboot *sb,
784                enum nvkm_secboot_falcon falcon)
785 {
786         struct acr_r352 *acr = acr_r352(_acr);
787         int ret;
788
789         /*
790          * Dummy GM200 implementation: perform secure boot each time we are
791          * called on FECS. Since only FECS and GPCCS are managed and started
792          * together, this ought to be safe.
793          *
794          * Once we have proper PMU firmware and support, this will be changed
795          * to a proper call to the PMU method.
796          */
797         if (falcon != NVKM_SECBOOT_FALCON_FECS)
798                 goto end;
799
800         ret = acr_r352_shutdown(acr, sb);
801         if (ret)
802                 return ret;
803
804         acr_r352_bootstrap(acr, sb);
805         if (ret)
806                 return ret;
807
808 end:
809         acr->falcon_state[falcon] = RESET;
810         return 0;
811 }
812
813 static int
814 acr_r352_start(struct nvkm_acr *_acr, struct nvkm_secboot *sb,
815                     enum nvkm_secboot_falcon falcon)
816 {
817         struct acr_r352 *acr = acr_r352(_acr);
818         const struct nvkm_subdev *subdev = &sb->subdev;
819         int base;
820
821         switch (falcon) {
822         case NVKM_SECBOOT_FALCON_FECS:
823                 base = 0x409000;
824                 break;
825         case NVKM_SECBOOT_FALCON_GPCCS:
826                 base = 0x41a000;
827                 break;
828         default:
829                 nvkm_error(subdev, "cannot start unhandled falcon!\n");
830                 return -EINVAL;
831         }
832
833         nvkm_wr32(subdev->device, base + 0x130, 0x00000002);
834         acr->falcon_state[falcon] = RUNNING;
835
836         return 0;
837 }
838
839 static int
840 acr_r352_fini(struct nvkm_acr *_acr, struct nvkm_secboot *sb, bool suspend)
841 {
842         struct acr_r352 *acr = acr_r352(_acr);
843
844         return acr_r352_shutdown(acr, sb);
845 }
846
847 static void
848 acr_r352_dtor(struct nvkm_acr *_acr)
849 {
850         struct acr_r352 *acr = acr_r352(_acr);
851
852         nvkm_gpuobj_del(&acr->unload_blob);
853
854         kfree(acr->hsbl_blob);
855         nvkm_gpuobj_del(&acr->load_blob);
856         nvkm_gpuobj_del(&acr->ls_blob);
857
858         kfree(acr);
859 }
860
861 const struct acr_r352_ls_func
862 acr_r352_ls_fecs_func = {
863         .load = acr_ls_ucode_load_fecs,
864         .generate_bl_desc = acr_r352_generate_flcn_bl_desc,
865         .bl_desc_size = sizeof(struct acr_r352_flcn_bl_desc),
866 };
867
868 const struct acr_r352_ls_func
869 acr_r352_ls_gpccs_func = {
870         .load = acr_ls_ucode_load_gpccs,
871         .generate_bl_desc = acr_r352_generate_flcn_bl_desc,
872         .bl_desc_size = sizeof(struct acr_r352_flcn_bl_desc),
873         /* GPCCS will be loaded using PRI */
874         .lhdr_flags = LSF_FLAG_FORCE_PRIV_LOAD,
875 };
876
877 const struct acr_r352_func
878 acr_r352_func = {
879         .generate_hs_bl_desc = acr_r352_generate_hs_bl_desc,
880         .hs_bl_desc_size = sizeof(struct acr_r352_flcn_bl_desc),
881         .ls_ucode_img_load = acr_r352_ls_ucode_img_load,
882         .ls_fill_headers = acr_r352_ls_fill_headers,
883         .ls_write_wpr = acr_r352_ls_write_wpr,
884         .ls_func = {
885                 [NVKM_SECBOOT_FALCON_FECS] = &acr_r352_ls_fecs_func,
886                 [NVKM_SECBOOT_FALCON_GPCCS] = &acr_r352_ls_gpccs_func,
887         },
888 };
889
890 static const struct nvkm_acr_func
891 acr_r352_base_func = {
892         .dtor = acr_r352_dtor,
893         .fini = acr_r352_fini,
894         .load = acr_r352_load,
895         .reset = acr_r352_reset,
896         .start = acr_r352_start,
897 };
898
899 struct nvkm_acr *
900 acr_r352_new_(const struct acr_r352_func *func,
901               enum nvkm_secboot_falcon boot_falcon,
902               unsigned long managed_falcons)
903 {
904         struct acr_r352 *acr;
905
906         acr = kzalloc(sizeof(*acr), GFP_KERNEL);
907         if (!acr)
908                 return ERR_PTR(-ENOMEM);
909
910         acr->base.boot_falcon = boot_falcon;
911         acr->base.managed_falcons = managed_falcons;
912         acr->base.func = &acr_r352_base_func;
913         acr->func = func;
914
915         return &acr->base;
916 }
917
918 struct nvkm_acr *
919 acr_r352_new(unsigned long managed_falcons)
920 {
921         return acr_r352_new_(&acr_r352_func, NVKM_SECBOOT_FALCON_PMU,
922                              managed_falcons);
923 }