diff options
Diffstat (limited to 'drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gm200.c')
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gm200.c | 239 |
1 files changed, 42 insertions, 197 deletions
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gm200.c b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gm200.c index 27479891a973..94cdc979a770 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gm200.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gm200.c @@ -131,175 +131,6 @@ struct fw_bl_desc { }; -/* - * - * LS blob structures - * - */ - -/** - * struct lsf_ucode_desc - LS falcon signatures - * @prd_keys: signature to use when the GPU is in production mode - * @dgb_keys: signature to use when the GPU is in debug mode - * @b_prd_present: whether the production key is present - * @b_dgb_present: whether the debug key is present - * @falcon_id: ID of the falcon the ucode applies to - * - * Directly loaded from a signature file. - */ -struct lsf_ucode_desc { - u8 prd_keys[2][16]; - u8 dbg_keys[2][16]; - u32 b_prd_present; - u32 b_dbg_present; - u32 falcon_id; -}; - -/** - * struct lsf_lsb_header - LS firmware header - * @signature: signature to verify the firmware against - * @ucode_off: offset of the ucode blob in the WPR region. The ucode - * blob contains the bootloader, code and data of the - * LS falcon - * @ucode_size: size of the ucode blob, including bootloader - * @data_size: size of the ucode blob data - * @bl_code_size: size of the bootloader code - * @bl_imem_off: offset in imem of the bootloader - * @bl_data_off: offset of the bootloader data in WPR region - * @bl_data_size: size of the bootloader data - * @app_code_off: offset of the app code relative to ucode_off - * @app_code_size: size of the app code - * @app_data_off: offset of the app data relative to ucode_off - * @app_data_size: size of the app data - * @flags: flags for the secure bootloader - * - * This structure is written into the WPR region for each managed falcon. Each - * instance is referenced by the lsb_offset member of the corresponding - * lsf_wpr_header. - */ -struct lsf_lsb_header { - struct lsf_ucode_desc signature; - u32 ucode_off; - u32 ucode_size; - u32 data_size; - u32 bl_code_size; - u32 bl_imem_off; - u32 bl_data_off; - u32 bl_data_size; - u32 app_code_off; - u32 app_code_size; - u32 app_data_off; - u32 app_data_size; - u32 flags; -#define LSF_FLAG_LOAD_CODE_AT_0 1 -#define LSF_FLAG_DMACTL_REQ_CTX 4 -#define LSF_FLAG_FORCE_PRIV_LOAD 8 -}; - -/** - * struct lsf_wpr_header - LS blob WPR Header - * @falcon_id: LS falcon ID - * @lsb_offset: offset of the lsb_lsf_header in the WPR region - * @bootstrap_owner: secure falcon reponsible for bootstrapping the LS falcon - * @lazy_bootstrap: skip bootstrapping by ACR - * @status: bootstrapping status - * - * An array of these is written at the beginning of the WPR region, one for - * each managed falcon. The array is terminated by an instance which falcon_id - * is LSF_FALCON_ID_INVALID. - */ -struct lsf_wpr_header { - u32 falcon_id; - u32 lsb_offset; - u32 bootstrap_owner; - u32 lazy_bootstrap; - u32 status; -#define LSF_IMAGE_STATUS_NONE 0 -#define LSF_IMAGE_STATUS_COPY 1 -#define LSF_IMAGE_STATUS_VALIDATION_CODE_FAILED 2 -#define LSF_IMAGE_STATUS_VALIDATION_DATA_FAILED 3 -#define LSF_IMAGE_STATUS_VALIDATION_DONE 4 -#define LSF_IMAGE_STATUS_VALIDATION_SKIPPED 5 -#define LSF_IMAGE_STATUS_BOOTSTRAP_READY 6 -}; - - -/** - * struct ls_ucode_img_desc - descriptor of firmware image - * @descriptor_size: size of this descriptor - * @image_size: size of the whole image - * @bootloader_start_offset: start offset of the bootloader in ucode image - * @bootloader_size: size of the bootloader - * @bootloader_imem_offset: start off set of the bootloader in IMEM - * @bootloader_entry_point: entry point of the bootloader in IMEM - * @app_start_offset: start offset of the LS firmware - * @app_size: size of the LS firmware's code and data - * @app_imem_offset: offset of the app in IMEM - * @app_imem_entry: entry point of the app in IMEM - * @app_dmem_offset: offset of the data in DMEM - * @app_resident_code_offset: offset of app code from app_start_offset - * @app_resident_code_size: size of the code - * @app_resident_data_offset: offset of data from app_start_offset - * @app_resident_data_size: size of data - * - * A firmware image contains the code, data, and bootloader of a given LS - * falcon in a single blob. This structure describes where everything is. - * - * This can be generated from a (bootloader, code, data) set if they have - * been loaded separately, or come directly from a file. - */ -struct ls_ucode_img_desc { - u32 descriptor_size; - u32 image_size; - u32 tools_version; - u32 app_version; - char date[64]; - u32 bootloader_start_offset; - u32 bootloader_size; - u32 bootloader_imem_offset; - u32 bootloader_entry_point; - u32 app_start_offset; - u32 app_size; - u32 app_imem_offset; - u32 app_imem_entry; - u32 app_dmem_offset; - u32 app_resident_code_offset; - u32 app_resident_code_size; - u32 app_resident_data_offset; - u32 app_resident_data_size; - u32 nb_overlays; - struct {u32 start; u32 size; } load_ovl[64]; - u32 compressed; -}; - -/** - * struct ls_ucode_img - temporary storage for loaded LS firmwares - * @node: to link within lsf_ucode_mgr - * @falcon_id: ID of the falcon this LS firmware is for - * @ucode_desc: loaded or generated map of ucode_data - * @ucode_header: header of the firmware - * @ucode_data: firmware payload (code and data) - * @ucode_size: size in bytes of data in ucode_data - * @wpr_header: WPR header to be written to the LS blob - * @lsb_header: LSB header to be written to the LS blob - * - * Preparing the WPR LS blob requires information about all the LS firmwares - * (size, etc) to be known. This structure contains all the data of one LS - * firmware. - */ -struct ls_ucode_img { - struct list_head node; - enum nvkm_secboot_falcon falcon_id; - - struct ls_ucode_img_desc ucode_desc; - u32 *ucode_header; - u8 *ucode_data; - u32 ucode_size; - - struct lsf_wpr_header wpr_header; - struct lsf_lsb_header lsb_header; -}; - /** * struct ls_ucode_mgr - manager for all LS falcon firmwares * @count: number of managed LS falcons @@ -364,7 +195,7 @@ struct hsf_load_header { * it has the required minimum size. */ static void * -gm200_secboot_load_firmware(struct nvkm_subdev *subdev, const char *name, +gm200_secboot_load_firmware(const struct nvkm_subdev *subdev, const char *name, size_t min_size) { const struct firmware *fw; @@ -457,7 +288,7 @@ ls_ucode_img_build(const struct firmware *bl, const struct firmware *code, * blob. Also generate the corresponding ucode descriptor. */ static int -ls_ucode_img_load_generic(struct nvkm_subdev *subdev, +ls_ucode_img_load_generic(const struct nvkm_subdev *subdev, struct ls_ucode_img *img, const char *falcon_name, const u32 falcon_id) { @@ -518,17 +349,17 @@ error: return ret; } -typedef int (*lsf_load_func)(struct nvkm_subdev *, struct ls_ucode_img *); +typedef int (*lsf_load_func)(const struct nvkm_subdev *, struct ls_ucode_img *); -static int -ls_ucode_img_load_fecs(struct nvkm_subdev *subdev, struct ls_ucode_img *img) +int +gm200_ls_load_fecs(const struct nvkm_subdev *subdev, struct ls_ucode_img *img) { return ls_ucode_img_load_generic(subdev, img, "fecs", NVKM_SECBOOT_FALCON_FECS); } -static int -ls_ucode_img_load_gpccs(struct nvkm_subdev *subdev, struct ls_ucode_img *img) +int +gm200_ls_load_gpccs(const struct nvkm_subdev *subdev, struct ls_ucode_img *img) { return ls_ucode_img_load_generic(subdev, img, "gpccs", NVKM_SECBOOT_FALCON_GPCCS); @@ -556,14 +387,8 @@ ls_ucode_img_load(struct nvkm_subdev *subdev, lsf_load_func load_func) return img; } -static const lsf_load_func lsf_load_funcs[] = { - [NVKM_SECBOOT_FALCON_END] = NULL, /* reserve enough space */ - [NVKM_SECBOOT_FALCON_FECS] = ls_ucode_img_load_fecs, - [NVKM_SECBOOT_FALCON_GPCCS] = ls_ucode_img_load_gpccs, -}; - /** - * ls_ucode_img_populate_bl_desc() - populate a DMEM BL descriptor for LS image + * gm200_secboot_ls_bl_desc() - populate a DMEM BL descriptor for LS image * @img: ucode image to generate against * @desc: descriptor to populate * @sb: secure boot state to use for base addresses @@ -573,10 +398,11 @@ static const lsf_load_func lsf_load_funcs[] = { * */ static void -ls_ucode_img_populate_bl_desc(struct ls_ucode_img *img, u64 wpr_addr, - struct gm200_flcn_bl_desc *desc) +gm200_secboot_ls_bl_desc(const struct ls_ucode_img *img, u64 wpr_addr, + void *_desc) { - struct ls_ucode_img_desc *pdesc = &img->ucode_desc; + struct gm200_flcn_bl_desc *desc = _desc; + const struct ls_ucode_img_desc *pdesc = &img->ucode_desc; u64 addr_base; addr_base = wpr_addr + img->lsb_header.ucode_off + @@ -621,6 +447,8 @@ ls_ucode_img_fill_headers(struct gm200_secboot *gsb, struct ls_ucode_img *img, struct lsf_wpr_header *whdr = &img->wpr_header; struct lsf_lsb_header *lhdr = &img->lsb_header; struct ls_ucode_img_desc *desc = &img->ucode_desc; + const struct secboot_ls_single_func *func = + (*gsb->ls_func)[img->falcon_id]; if (img->ucode_header) { nvkm_fatal(&gsb->base.subdev, @@ -681,9 +509,9 @@ ls_ucode_img_fill_headers(struct gm200_secboot *gsb, struct ls_ucode_img *img, if (img->falcon_id == NVKM_SECBOOT_FALCON_GPCCS) lhdr->flags |= LSF_FLAG_FORCE_PRIV_LOAD; - /* Align (size bloat) and save off BL descriptor size */ - lhdr->bl_data_size = ALIGN(sizeof(struct gm200_flcn_bl_desc), - LSF_BL_DATA_SIZE_ALIGN); + /* Align and save off BL descriptor size */ + lhdr->bl_data_size = ALIGN(func->bl_desc_size, LSF_BL_DATA_SIZE_ALIGN); + /* * Align, save off, and include the additional BL data */ @@ -769,15 +597,16 @@ ls_ucode_mgr_write_wpr(struct gm200_secboot *gsb, struct ls_ucode_mgr *mgr, /* Generate and write BL descriptor */ if (!img->ucode_header) { - u8 desc[gsb->func->bl_desc_size]; - struct gm200_flcn_bl_desc gdesc; + const struct secboot_ls_single_func *ls_func = + (*gsb->ls_func)[img->falcon_id]; + u8 gdesc[ls_func->bl_desc_size]; + + ls_func->generate_bl_desc(img, gsb->acr_wpr_addr, + &gdesc); - ls_ucode_img_populate_bl_desc(img, gsb->acr_wpr_addr, - &gdesc); - gsb->func->fixup_bl_desc(&gdesc, &desc); nvkm_gpuobj_memcpy_to(wpr_blob, img->lsb_header.bl_data_off, - &desc, gsb->func->bl_desc_size); + &gdesc, ls_func->bl_desc_size); } /* Copy ucode */ @@ -816,11 +645,12 @@ gm200_secboot_prepare_ls_blob(struct gm200_secboot *gsb) ls_ucode_mgr_init(&mgr); /* Load all LS blobs */ - for_each_set_bit(falcon_id, &gsb->base.func->managed_falcons, + for_each_set_bit(falcon_id, &sb->func->managed_falcons, NVKM_SECBOOT_FALCON_END) { struct ls_ucode_img *img; - img = ls_ucode_img_load(&sb->subdev, lsf_load_funcs[falcon_id]); + img = ls_ucode_img_load(&sb->subdev, + (*gsb->ls_func)[falcon_id]->load); if (IS_ERR(img)) { ret = PTR_ERR(img); @@ -865,6 +695,20 @@ cleanup: return ret; } +static const secboot_ls_func +gm200_ls_func = { + [NVKM_SECBOOT_FALCON_FECS] = &(struct secboot_ls_single_func) { + .load = gm200_ls_load_fecs, + .generate_bl_desc = gm200_secboot_ls_bl_desc, + .bl_desc_size = sizeof(struct gm200_flcn_bl_desc), + }, + [NVKM_SECBOOT_FALCON_GPCCS] = &(struct secboot_ls_single_func) { + .load = gm200_ls_load_gpccs, + .generate_bl_desc = gm200_secboot_ls_bl_desc, + .bl_desc_size = sizeof(struct gm200_flcn_bl_desc), + }, +}; + /* * High-secure blob creation */ @@ -1443,6 +1287,7 @@ gm200_secboot_new(struct nvkm_device *device, int index, return ret; gsb->func = &gm200_secboot_func; + gsb->ls_func = &gm200_ls_func; return 0; } |