diff options
author | Alexandre Courbot <acourbot@nvidia.com> | 2017-01-26 02:12:10 -0500 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2017-03-07 02:05:15 -0500 |
commit | c5e1fef4875b75df48a7e9828243062799e444dc (patch) | |
tree | 4aced08b30c0858dd91387f72f570a9a10868844 | |
parent | b58b41716302ed95df16d8fcefc7edb1ce5cf794 (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.c | 60 |
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 | */ |
604 | static void | 605 | static void |
605 | acr_r352_hsf_patch_signature(struct nvkm_secboot *sb, void *acr_image) | 606 | acr_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 | ||
626 | void | 642 | void |
@@ -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 | ||
689 | void * | ||
690 | acr_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; |