2 * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
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:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
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.
25 #include <core/gpuobj.h>
26 #include <core/firmware.h>
27 #include <engine/falcon.h>
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
40 * This structure is embedded in the HS firmware image at
41 * hs_bin_hdr.header_offset.
43 struct hsf_fw_header {
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
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
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.
77 struct acr_r352_flcn_bl_desc {
83 u32 non_sec_code_size;
92 * acr_r352_generate_flcn_bl_desc - generate generic BL descriptor for LS image
95 acr_r352_generate_flcn_bl_desc(const struct nvkm_acr *acr,
96 const struct ls_ucode_img *_img, u64 wpr_addr,
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;
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;
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;
119 * struct hsflcn_acr_desc - data section of the HS firmware
121 * This header is to be copied at the beginning of DMEM by the HS bootloader.
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
130 struct hsflcn_acr_desc {
132 u8 reserved_dmem[0x200];
134 } ucode_reserved_space;
138 #define FLCN_ACR_MAX_REGIONS 2
148 } region_props[FLCN_ACR_MAX_REGIONS];
151 u64 ucode_blob_base __aligned(8);
162 * Low-secure blob creation
166 * ls_ucode_img_load() - create a lsf_ucode_img and load it
168 struct ls_ucode_img *
169 acr_r352_ls_ucode_img_load(const struct acr_r352 *acr,
170 enum nvkm_secboot_falcon falcon_id)
172 const struct nvkm_subdev *subdev = acr->base.subdev;
173 struct ls_ucode_img_r352 *img;
176 img = kzalloc(sizeof(*img), GFP_KERNEL);
178 return ERR_PTR(-ENOMEM);
180 img->base.falcon_id = falcon_id;
182 ret = acr->func->ls_func[falcon_id]->load(subdev, &img->base);
185 kfree(img->base.ucode_data);
186 kfree(img->base.sig);
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);
198 /* Copy signature to the right place */
199 memcpy(&img->lsb_header.signature, img->base.sig, img->base.sig_size);
201 /* not needed? the signature should already have the right value */
202 img->lsb_header.signature.falcon_id = falcon_id;
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
214 * acr_r352_ls_img_fill_headers - fill the WPR and LSB headers of an image
216 * @img: image to generate for
217 * @offset: offset in the WPR region where this image starts
219 * Allocate space in the WPR area from offset and write the WPR and LSB headers
222 * Return: offset at the end of this image.
225 acr_r352_ls_img_fill_headers(struct acr_r352 *acr,
226 struct ls_ucode_img_r352 *img, u32 offset)
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];
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;
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);
246 * Align, save off, and include the original (static) ucode
249 offset = ALIGN(offset, LSF_UCODE_DATA_ALIGN);
250 lhdr->ucode_off = offset;
251 offset += _img->ucode_size;
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
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;
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
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;
280 lhdr->flags = func->lhdr_flags;
281 if (_img->falcon_id == acr->base.boot_falcon)
282 lhdr->flags |= LSF_FLAG_DMACTL_REQ_CTX;
284 /* Align and save off BL descriptor size */
285 lhdr->bl_data_size = ALIGN(func->bl_desc_size, LSF_BL_DATA_SIZE_ALIGN);
288 * Align, save off, and include the additional BL data
290 offset = ALIGN(offset, LSF_BL_DATA_ALIGN);
291 lhdr->bl_data_off = offset;
292 offset += lhdr->bl_data_size;
298 * acr_r352_ls_fill_headers - fill WPR and LSB headers of all managed images
301 acr_r352_ls_fill_headers(struct acr_r352 *acr, struct list_head *imgs)
303 struct ls_ucode_img_r352 *img;
308 /* Count the number of images to manage */
309 list_for_each(l, imgs)
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.
318 offset = sizeof(img->wpr_header) * (count + 1);
321 * Walk the managed falcons, accounting for the LSB structs
322 * as well as the ucode images.
324 list_for_each_entry(img, imgs, base.node) {
325 offset = acr_r352_ls_img_fill_headers(acr, img, offset);
332 * acr_r352_ls_write_wpr - write the WPR blob contents
335 acr_r352_ls_write_wpr(struct acr_r352 *acr, struct list_head *imgs,
336 struct nvkm_gpuobj *wpr_blob, u32 wpr_addr)
338 struct ls_ucode_img *_img;
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];
349 nvkm_gpuobj_memcpy_to(wpr_blob, pos, &img->wpr_header,
350 sizeof(img->wpr_header));
352 nvkm_gpuobj_memcpy_to(wpr_blob, img->wpr_header.lsb_offset,
353 &img->lsb_header, sizeof(img->lsb_header));
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);
359 nvkm_gpuobj_memcpy_to(wpr_blob, img->lsb_header.bl_data_off,
360 gdesc, ls_func->bl_desc_size);
363 nvkm_gpuobj_memcpy_to(wpr_blob, img->lsb_header.ucode_off,
364 _img->ucode_data, _img->ucode_size);
366 pos += sizeof(img->wpr_header);
369 nvkm_wo32(wpr_blob, pos, NVKM_SECBOOT_FALCON_INVALID);
376 /* Both size and address of WPR need to be 128K-aligned */
377 #define WPR_ALIGNMENT 0x20000
379 * acr_r352_prepare_ls_blob() - prepare the LS blob
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.
387 acr_r352_prepare_ls_blob(struct acr_r352 *acr, u64 wpr_addr, u32 wpr_size)
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;
398 INIT_LIST_HEAD(&imgs);
400 /* Load all LS blobs */
401 for_each_set_bit(falcon_id, &managed_falcons, NVKM_SECBOOT_FALCON_END) {
402 struct ls_ucode_img *img;
404 img = acr->func->ls_ucode_img_load(acr, falcon_id);
410 list_add_tail(&img->node, &imgs);
415 * Fill the WPR and LSF headers with the right offsets and compute
418 image_wpr_size = acr->func->ls_fill_headers(acr, &imgs);
419 image_wpr_size = ALIGN(image_wpr_size, WPR_ALIGNMENT);
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);
427 nvkm_debug(subdev, "%d managed LS falcons, WPR size is %d bytes\n",
428 managed_count, image_wpr_size);
430 /* If WPR address and size are not fixed, set them to fit the LS blob */
432 wpr_addr = acr->ls_blob->addr;
433 wpr_size = image_wpr_size;
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.
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);
447 ret = acr->func->ls_write_wpr(acr, &imgs, acr->ls_blob, wpr_addr);
449 nvkm_gpuobj_del(&acr->ls_blob);
452 list_for_each_entry_safe(img, t, &imgs, node) {
453 kfree(img->ucode_data);
465 * acr_r352_hsf_patch_signature() - patch HS blob with correct signature
468 acr_r352_hsf_patch_signature(struct nvkm_secboot *sb, void *acr_image)
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;
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;
481 sig = acr_image + fw_hdr->sig_prod_offset;
482 sig_size = fw_hdr->sig_prod_size;
485 /* Patch signature */
486 memcpy(hs_data + fw_hdr->patch_loc, sig + fw_hdr->patch_sig, sig_size);
490 acr_r352_fixup_hs_desc(struct acr_r352 *acr, struct nvkm_secboot *sb,
491 struct hsflcn_acr_desc *desc)
493 struct nvkm_gpuobj *ls_blob = acr->ls_blob;
495 desc->ucode_blob_base = ls_blob->addr;
496 desc->ucode_blob_size = ls_blob->size;
498 desc->wpr_offset = 0;
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;
512 acr_r352_generate_hs_bl_desc(const struct hsf_load_header *hdr, void *_bl_desc,
515 struct acr_r352_flcn_bl_desc *bl_desc = _bl_desc;
516 u64 addr_code, addr_data;
518 addr_code = offset >> 8;
519 addr_data = (offset + hdr->data_dma_base) >> 8;
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;
533 * acr_r352_prepare_hs_blob - load and prepare a HS blob and BL descriptor
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)
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)
546 struct nvkm_subdev *subdev = &sb->subdev;
548 struct fw_bin_header *hsbin_hdr;
549 struct hsf_fw_header *fw_hdr;
550 struct hsf_load_header *load_hdr;
554 acr_image = nvkm_acr_load_firmware(subdev, fw, 0);
555 if (IS_ERR(acr_image))
556 return PTR_ERR(acr_image);
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;
563 /* Patch signature */
564 acr_r352_hsf_patch_signature(sb, acr_image);
566 /* Patch descriptor with WPR information? */
568 struct hsflcn_acr_desc *desc;
570 desc = acr_data + load_hdr->data_dma_base;
571 acr_r352_fixup_hs_desc(acr, sb, desc);
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);
580 memcpy(load_header, load_hdr, sizeof(*load_header) +
581 (sizeof(load_hdr->app[0]) * load_hdr->num_apps));
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);
590 nvkm_gpuobj_memcpy_to(*blob, 0, acr_data, hsbin_hdr->data_size);
600 acr_r352_prepare_hsbl_blob(struct acr_r352 *acr)
602 const struct nvkm_subdev *subdev = acr->base.subdev;
603 struct fw_bin_header *hdr;
604 struct fw_bl_desc *hsbl_desc;
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);
610 acr->hsbl_blob = NULL;
614 hdr = acr->hsbl_blob;
615 hsbl_desc = acr->hsbl_blob + hdr->header_offset;
617 /* virtual start address for boot vector */
618 acr->base.start_address = hsbl_desc->start_tag << 8;
624 * acr_r352_load_blobs - load blobs common to all ACR V1 versions.
626 * This includes the LS blob, HS ucode loading blob, and HS bootloader.
628 * The HS ucode unload blob is only used on dGPU if the WPR region is variable.
631 acr_r352_load_blobs(struct acr_r352 *acr, struct nvkm_secboot *sb)
635 /* Firmware already loaded? */
636 if (acr->firmware_ok)
639 /* Load and prepare the managed falcon's firmwares */
640 ret = acr_r352_prepare_ls_blob(acr, sb->wpr_addr, sb->wpr_size);
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",
648 &acr->load_bl_header, true);
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",
657 &acr->unload_bl_header, false);
662 /* Load the HS firmware bootloader */
663 if (!acr->hsbl_blob) {
664 ret = acr_r352_prepare_hsbl_blob(acr);
669 acr->firmware_ok = true;
670 nvkm_debug(&sb->subdev, "LS blob successfully created\n");
676 * acr_r352_load() - prepare HS falcon to run the specified blob, mapped
677 * at GPU address offset.
680 acr_r352_load(struct nvkm_acr *_acr, struct nvkm_secboot *sb,
681 struct nvkm_gpuobj *blob, u64 offset)
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];
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;
701 nvkm_error(_acr->subdev, "invalid secure boot blob!\n");
706 * Copy HS bootloader data
708 nvkm_falcon_load_dmem(falcon, hsbl_data, 0x0, hsbl_desc->data_size, 0);
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);
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);
719 * Copy HS BL header where the HS descriptor expects it to be
721 nvkm_falcon_load_dmem(falcon, bl_desc, hsbl_desc->dmem_load_off,
728 acr_r352_shutdown(struct acr_r352 *acr, struct nvkm_secboot *sb)
732 /* Run the unload blob to unprotect the WPR region */
733 if (acr->unload_blob && sb->wpr_set) {
736 nvkm_debug(&sb->subdev, "running HS unload blob\n");
737 ret = sb->func->run_blob(sb, acr->unload_blob);
740 nvkm_debug(&sb->subdev, "HS unload blob completed\n");
743 for (i = 0; i < NVKM_SECBOOT_FALCON_END; i++)
744 acr->falcon_state[i] = NON_SECURE;
752 acr_r352_bootstrap(struct acr_r352 *acr, struct nvkm_secboot *sb)
759 /* Make sure all blobs are ready */
760 ret = acr_r352_load_blobs(acr, sb);
764 nvkm_debug(&sb->subdev, "running HS load blob\n");
765 ret = sb->func->run_blob(sb, acr->load_blob);
768 nvkm_debug(&sb->subdev, "HS load blob completed\n");
776 * acr_r352_reset() - execute secure boot from the prepared state
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.
783 acr_r352_reset(struct nvkm_acr *_acr, struct nvkm_secboot *sb,
784 enum nvkm_secboot_falcon falcon)
786 struct acr_r352 *acr = acr_r352(_acr);
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.
794 * Once we have proper PMU firmware and support, this will be changed
795 * to a proper call to the PMU method.
797 if (falcon != NVKM_SECBOOT_FALCON_FECS)
800 ret = acr_r352_shutdown(acr, sb);
804 acr_r352_bootstrap(acr, sb);
809 acr->falcon_state[falcon] = RESET;
814 acr_r352_start(struct nvkm_acr *_acr, struct nvkm_secboot *sb,
815 enum nvkm_secboot_falcon falcon)
817 struct acr_r352 *acr = acr_r352(_acr);
818 const struct nvkm_subdev *subdev = &sb->subdev;
822 case NVKM_SECBOOT_FALCON_FECS:
825 case NVKM_SECBOOT_FALCON_GPCCS:
829 nvkm_error(subdev, "cannot start unhandled falcon!\n");
833 nvkm_wr32(subdev->device, base + 0x130, 0x00000002);
834 acr->falcon_state[falcon] = RUNNING;
840 acr_r352_fini(struct nvkm_acr *_acr, struct nvkm_secboot *sb, bool suspend)
842 struct acr_r352 *acr = acr_r352(_acr);
844 return acr_r352_shutdown(acr, sb);
848 acr_r352_dtor(struct nvkm_acr *_acr)
850 struct acr_r352 *acr = acr_r352(_acr);
852 nvkm_gpuobj_del(&acr->unload_blob);
854 kfree(acr->hsbl_blob);
855 nvkm_gpuobj_del(&acr->load_blob);
856 nvkm_gpuobj_del(&acr->ls_blob);
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),
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,
877 const struct 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,
885 [NVKM_SECBOOT_FALCON_FECS] = &acr_r352_ls_fecs_func,
886 [NVKM_SECBOOT_FALCON_GPCCS] = &acr_r352_ls_gpccs_func,
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,
900 acr_r352_new_(const struct acr_r352_func *func,
901 enum nvkm_secboot_falcon boot_falcon,
902 unsigned long managed_falcons)
904 struct acr_r352 *acr;
906 acr = kzalloc(sizeof(*acr), GFP_KERNEL);
908 return ERR_PTR(-ENOMEM);
910 acr->base.boot_falcon = boot_falcon;
911 acr->base.managed_falcons = managed_falcons;
912 acr->base.func = &acr_r352_base_func;
919 acr_r352_new(unsigned long managed_falcons)
921 return acr_r352_new_(&acr_r352_func, NVKM_SECBOOT_FALCON_PMU,