Commit c5e1fef4 authored by Alexandre Courbot's avatar Alexandre Courbot Committed by Ben Skeggs

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: default avatarAlexandre Courbot <acourbot@nvidia.com>
Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent b58b4171
...@@ -599,19 +599,35 @@ acr_r352_prepare_ls_blob(struct acr_r352 *acr, u64 wpr_addr, u32 wpr_size) ...@@ -599,19 +599,35 @@ acr_r352_prepare_ls_blob(struct acr_r352 *acr, u64 wpr_addr, u32 wpr_size)
/** /**
* acr_r352_hsf_patch_signature() - patch HS blob with correct signature * acr_r352_hsf_patch_signature() - patch HS blob with correct signature for
* specified falcon.
*/ */
static void static void
acr_r352_hsf_patch_signature(struct nvkm_secboot *sb, void *acr_image) acr_r352_hsf_patch_signature(const struct nvkm_falcon *falcon, void *acr_image,
bool new_format)
{ {
struct fw_bin_header *hsbin_hdr = acr_image; struct fw_bin_header *hsbin_hdr = acr_image;
struct hsf_fw_header *fw_hdr = acr_image + hsbin_hdr->header_offset; struct hsf_fw_header *fw_hdr = acr_image + hsbin_hdr->header_offset;
void *hs_data = acr_image + hsbin_hdr->data_offset; void *hs_data = acr_image + hsbin_hdr->data_offset;
void *sig; void *sig;
u32 sig_size; u32 sig_size;
u32 patch_loc, patch_sig;
/*
* I had the brilliant idea to "improve" the binary format by
* removing this useless indirection. However to make NVIDIA files
* directly compatible, let's support both format.
*/
if (new_format) {
patch_loc = fw_hdr->patch_loc;
patch_sig = fw_hdr->patch_sig;
} else {
patch_loc = *(u32 *)(acr_image + fw_hdr->patch_loc);
patch_sig = *(u32 *)(acr_image + fw_hdr->patch_sig);
}
/* Falcon in debug or production mode? */ /* Falcon in debug or production mode? */
if (sb->boot_falcon->debug) { if (falcon->debug) {
sig = acr_image + fw_hdr->sig_dbg_offset; sig = acr_image + fw_hdr->sig_dbg_offset;
sig_size = fw_hdr->sig_dbg_size; sig_size = fw_hdr->sig_dbg_size;
} else { } else {
...@@ -620,7 +636,7 @@ acr_r352_hsf_patch_signature(struct nvkm_secboot *sb, void *acr_image) ...@@ -620,7 +636,7 @@ acr_r352_hsf_patch_signature(struct nvkm_secboot *sb, void *acr_image)
} }
/* Patch signature */ /* Patch signature */
memcpy(hs_data + fw_hdr->patch_loc, sig + fw_hdr->patch_sig, sig_size); memcpy(hs_data + patch_loc, sig + patch_sig, sig_size);
} }
void void
...@@ -670,6 +686,37 @@ acr_r352_generate_hs_bl_desc(const struct hsf_load_header *hdr, void *_bl_desc, ...@@ -670,6 +686,37 @@ acr_r352_generate_hs_bl_desc(const struct hsf_load_header *hdr, void *_bl_desc,
bl_desc->data_size = hdr->data_size; bl_desc->data_size = hdr->data_size;
} }
void *
acr_r352_load_hs_blob(struct nvkm_secboot *sb, const struct nvkm_falcon *falcon,
const char *fw)
{
struct nvkm_subdev *subdev = &sb->subdev;
void *acr_image;
bool new_format;
acr_image = nvkm_acr_load_firmware(subdev, fw, 0);
if (IS_ERR(acr_image))
return acr_image;
/* detect the format to define how signature should be patched */
switch (((u32 *)acr_image)[0]) {
case 0x3b1d14f0:
new_format = true;
break;
case 0x000010de:
new_format = false;
break;
default:
nvkm_error(subdev, "unknown header for HS blob %s\n", fw);
return ERR_PTR(-EINVAL);
}
/* Patch signature */
acr_r352_hsf_patch_signature(falcon, acr_image, new_format);
return acr_image;
}
/** /**
* acr_r352_prepare_hs_blob - load and prepare a HS blob and BL descriptor * acr_r352_prepare_hs_blob - load and prepare a HS blob and BL descriptor
* *
...@@ -692,7 +739,7 @@ acr_r352_prepare_hs_blob(struct acr_r352 *acr, struct nvkm_secboot *sb, ...@@ -692,7 +739,7 @@ acr_r352_prepare_hs_blob(struct acr_r352 *acr, struct nvkm_secboot *sb,
void *acr_data; void *acr_data;
int ret; int ret;
acr_image = nvkm_acr_load_firmware(subdev, fw, 0); acr_image = acr_r352_load_hs_blob(sb, sb->boot_falcon, fw);
if (IS_ERR(acr_image)) if (IS_ERR(acr_image))
return PTR_ERR(acr_image); return PTR_ERR(acr_image);
...@@ -701,9 +748,6 @@ acr_r352_prepare_hs_blob(struct acr_r352 *acr, struct nvkm_secboot *sb, ...@@ -701,9 +748,6 @@ acr_r352_prepare_hs_blob(struct acr_r352 *acr, struct nvkm_secboot *sb,
load_hdr = acr_image + fw_hdr->hdr_offset; load_hdr = acr_image + fw_hdr->hdr_offset;
acr_data = acr_image + hsbin_hdr->data_offset; acr_data = acr_image + hsbin_hdr->data_offset;
/* Patch signature */
acr_r352_hsf_patch_signature(sb, acr_image);
/* Patch descriptor with WPR information? */ /* Patch descriptor with WPR information? */
if (patch) { if (patch) {
struct hsflcn_acr_desc *desc; struct hsflcn_acr_desc *desc;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment