aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexandre Courbot <acourbot@nvidia.com>2017-01-26 02:12:10 -0500
committerBen Skeggs <bskeggs@redhat.com>2017-03-07 02:05:15 -0500
commitc5e1fef4875b75df48a7e9828243062799e444dc (patch)
tree4aced08b30c0858dd91387f72f570a9a10868844
parentb58b41716302ed95df16d8fcefc7edb1ce5cf794 (diff)
drm/nouveau/secboot: support standard NVIDIA HS binaries
I had the brilliant idea to "improve" the binary format by removing a useless indirection in the HS binary files. In the end it just makes things more complicated than they ought to be as NVIDIA-provided files need to be adapted. Since the format used can be identified by the header, support both. Signed-off-by: Alexandre Courbot <acourbot@nvidia.com> Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r352.c60
1 files changed, 52 insertions, 8 deletions
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r352.c b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r352.c
index 77ed8f007776..b4e0add13a33 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r352.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r352.c
@@ -599,19 +599,35 @@ cleanup:
599 599
600 600
601/** 601/**
602 * acr_r352_hsf_patch_signature() - patch HS blob with correct signature 602 * acr_r352_hsf_patch_signature() - patch HS blob with correct signature for
603 * specified falcon.
603 */ 604 */
604static void 605static void
605acr_r352_hsf_patch_signature(struct nvkm_secboot *sb, void *acr_image) 606acr_r352_hsf_patch_signature(const struct nvkm_falcon *falcon, void *acr_image,
607 bool new_format)
606{ 608{
607 struct fw_bin_header *hsbin_hdr = acr_image; 609 struct fw_bin_header *hsbin_hdr = acr_image;
608 struct hsf_fw_header *fw_hdr = acr_image + hsbin_hdr->header_offset; 610 struct hsf_fw_header *fw_hdr = acr_image + hsbin_hdr->header_offset;
609 void *hs_data = acr_image + hsbin_hdr->data_offset; 611 void *hs_data = acr_image + hsbin_hdr->data_offset;
610 void *sig; 612 void *sig;
611 u32 sig_size; 613 u32 sig_size;
614 u32 patch_loc, patch_sig;
615
616 /*
617 * I had the brilliant idea to "improve" the binary format by
618 * removing this useless indirection. However to make NVIDIA files
619 * directly compatible, let's support both format.
620 */
621 if (new_format) {
622 patch_loc = fw_hdr->patch_loc;
623 patch_sig = fw_hdr->patch_sig;
624 } else {
625 patch_loc = *(u32 *)(acr_image + fw_hdr->patch_loc);
626 patch_sig = *(u32 *)(acr_image + fw_hdr->patch_sig);
627 }
612 628
613 /* Falcon in debug or production mode? */ 629 /* Falcon in debug or production mode? */
614 if (sb->boot_falcon->debug) { 630 if (falcon->debug) {
615 sig = acr_image + fw_hdr->sig_dbg_offset; 631 sig = acr_image + fw_hdr->sig_dbg_offset;
616 sig_size = fw_hdr->sig_dbg_size; 632 sig_size = fw_hdr->sig_dbg_size;
617 } else { 633 } else {
@@ -620,7 +636,7 @@ acr_r352_hsf_patch_signature(struct nvkm_secboot *sb, void *acr_image)
620 } 636 }
621 637
622 /* Patch signature */ 638 /* Patch signature */
623 memcpy(hs_data + fw_hdr->patch_loc, sig + fw_hdr->patch_sig, sig_size); 639 memcpy(hs_data + patch_loc, sig + patch_sig, sig_size);
624} 640}
625 641
626void 642void
@@ -670,6 +686,37 @@ acr_r352_generate_hs_bl_desc(const struct hsf_load_header *hdr, void *_bl_desc,
670 bl_desc->data_size = hdr->data_size; 686 bl_desc->data_size = hdr->data_size;
671} 687}
672 688
689void *
690acr_r352_load_hs_blob(struct nvkm_secboot *sb, const struct nvkm_falcon *falcon,
691 const char *fw)
692{
693 struct nvkm_subdev *subdev = &sb->subdev;
694 void *acr_image;
695 bool new_format;
696
697 acr_image = nvkm_acr_load_firmware(subdev, fw, 0);
698 if (IS_ERR(acr_image))
699 return acr_image;
700
701 /* detect the format to define how signature should be patched */
702 switch (((u32 *)acr_image)[0]) {
703 case 0x3b1d14f0:
704 new_format = true;
705 break;
706 case 0x000010de:
707 new_format = false;
708 break;
709 default:
710 nvkm_error(subdev, "unknown header for HS blob %s\n", fw);
711 return ERR_PTR(-EINVAL);
712 }
713
714 /* Patch signature */
715 acr_r352_hsf_patch_signature(falcon, acr_image, new_format);
716
717 return acr_image;
718}
719
673/** 720/**
674 * acr_r352_prepare_hs_blob - load and prepare a HS blob and BL descriptor 721 * acr_r352_prepare_hs_blob - load and prepare a HS blob and BL descriptor
675 * 722 *
@@ -692,7 +739,7 @@ acr_r352_prepare_hs_blob(struct acr_r352 *acr, struct nvkm_secboot *sb,
692 void *acr_data; 739 void *acr_data;
693 int ret; 740 int ret;
694 741
695 acr_image = nvkm_acr_load_firmware(subdev, fw, 0); 742 acr_image = acr_r352_load_hs_blob(sb, sb->boot_falcon, fw);
696 if (IS_ERR(acr_image)) 743 if (IS_ERR(acr_image))
697 return PTR_ERR(acr_image); 744 return PTR_ERR(acr_image);
698 745
@@ -701,9 +748,6 @@ acr_r352_prepare_hs_blob(struct acr_r352 *acr, struct nvkm_secboot *sb,
701 load_hdr = acr_image + fw_hdr->hdr_offset; 748 load_hdr = acr_image + fw_hdr->hdr_offset;
702 acr_data = acr_image + hsbin_hdr->data_offset; 749 acr_data = acr_image + hsbin_hdr->data_offset;
703 750
704 /* Patch signature */
705 acr_r352_hsf_patch_signature(sb, acr_image);
706
707 /* Patch descriptor with WPR information? */ 751 /* Patch descriptor with WPR information? */
708 if (patch) { 752 if (patch) {
709 struct hsflcn_acr_desc *desc; 753 struct hsflcn_acr_desc *desc;