Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9d896f3e authored by Alexandre Courbot's avatar Alexandre Courbot Committed by Ben Skeggs
Browse files

drm/nouveau/secboot: abstract LS firmware loading functions



The WPR and LSB headers, used to generate the LS blob, may have a
different layout and sizes depending on the driver version they come
from. Abstract them and confine their use to driver-specific code.

Signed-off-by: default avatarAlexandre Courbot <acourbot@nvidia.com>
Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent 9839307c
Loading
Loading
Loading
Loading
+62 −40
Original line number Diff line number Diff line
@@ -21,7 +21,6 @@
 */

#include "acr_r352.h"
#include "ls_ucode.h"

#include <core/gpuobj.h>
#include <core/firmware.h>
@@ -94,11 +93,12 @@ struct acr_r352_flcn_bl_desc {
 */
static void
acr_r352_generate_flcn_bl_desc(const struct nvkm_acr *acr,
			       const struct ls_ucode_img *img, u64 wpr_addr,
			       const struct ls_ucode_img *_img, u64 wpr_addr,
			       void *_desc)
{
	struct ls_ucode_img_r352 *img = ls_ucode_img_r352(_img);
	struct acr_r352_flcn_bl_desc *desc = _desc;
	const struct ls_ucode_img_desc *pdesc = &img->ucode_desc;
	const struct ls_ucode_img_desc *pdesc = &_img->ucode_desc;
	u64 base, addr_code, addr_data;

	base = wpr_addr + img->lsb_header.ucode_off + pdesc->app_start_offset;
@@ -163,29 +163,46 @@ struct hsflcn_acr_desc {
 * Low-secure blob creation
 */

typedef int (*lsf_load_func)(const struct nvkm_subdev *, struct ls_ucode_img *);

/**
 * ls_ucode_img_load() - create a lsf_ucode_img and load it
 */
static struct ls_ucode_img *
ls_ucode_img_load(const struct nvkm_subdev *subdev, lsf_load_func load_func)
struct ls_ucode_img *
acr_r352_ls_ucode_img_load(const struct acr_r352 *acr,
			   enum nvkm_secboot_falcon falcon_id)
{
	struct ls_ucode_img *img;
	const struct nvkm_subdev *subdev = acr->base.subdev;
	struct ls_ucode_img_r352 *img;
	int ret;

	img = kzalloc(sizeof(*img), GFP_KERNEL);
	if (!img)
		return ERR_PTR(-ENOMEM);

	ret = load_func(subdev, img);
	img->base.falcon_id = falcon_id;

	ret = acr->func->ls_func[falcon_id]->load(subdev, &img->base);

	if (ret) {
		kfree(img->base.ucode_data);
		kfree(img->base.sig);
		kfree(img);
		return ERR_PTR(ret);
	}

	return img;
	/* Check that the signature size matches our expectations... */
	if (img->base.sig_size != sizeof(img->lsb_header.signature)) {
		nvkm_error(subdev, "invalid signature size for %s falcon!\n",
			   nvkm_secboot_falcon_name[falcon_id]);
		return ERR_PTR(-EINVAL);
	}

	/* Copy signature to the right place */
	memcpy(&img->lsb_header.signature, img->base.sig, img->base.sig_size);

	/* not needed? the signature should already have the right value */
	img->lsb_header.signature.falcon_id = falcon_id;

	return &img->base;
}

#define LSF_LSB_HEADER_ALIGN 256
@@ -195,7 +212,7 @@ ls_ucode_img_load(const struct nvkm_subdev *subdev, lsf_load_func load_func)
#define LSF_UCODE_DATA_ALIGN 4096

/**
 * ls_ucode_img_fill_headers - fill the WPR and LSB headers of an image
 * acr_r352_ls_img_fill_headers - fill the WPR and LSB headers of an image
 * @acr:	ACR to use
 * @img:	image to generate for
 * @offset:	offset in the WPR region where this image starts
@@ -206,24 +223,25 @@ ls_ucode_img_load(const struct nvkm_subdev *subdev, lsf_load_func load_func)
 * Return: offset at the end of this image.
 */
static u32
ls_ucode_img_fill_headers(struct acr_r352 *acr, struct ls_ucode_img *img,
			  u32 offset)
acr_r352_ls_img_fill_headers(struct acr_r352 *acr,
			     struct ls_ucode_img_r352 *img, u32 offset)
{
	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;
	struct ls_ucode_img *_img = &img->base;
	struct acr_r352_lsf_wpr_header *whdr = &img->wpr_header;
	struct acr_r352_lsf_lsb_header *lhdr = &img->lsb_header;
	struct ls_ucode_img_desc *desc = &_img->ucode_desc;
	const struct acr_r352_ls_func *func =
					    acr->func->ls_func[img->falcon_id];
					    acr->func->ls_func[_img->falcon_id];

	/* Fill WPR header */
	whdr->falcon_id = img->falcon_id;
	whdr->falcon_id = _img->falcon_id;
	whdr->bootstrap_owner = acr->base.boot_falcon;
	whdr->status = LSF_IMAGE_STATUS_COPY;

	/* Align, save off, and include an LSB header size */
	offset = ALIGN(offset, LSF_LSB_HEADER_ALIGN);
	whdr->lsb_offset = offset;
	offset += sizeof(struct lsf_lsb_header);
	offset += sizeof(*lhdr);

	/*
	 * Align, save off, and include the original (static) ucode
@@ -231,7 +249,7 @@ ls_ucode_img_fill_headers(struct acr_r352 *acr, struct ls_ucode_img *img,
	 */
	offset = ALIGN(offset, LSF_UCODE_DATA_ALIGN);
	lhdr->ucode_off = offset;
	offset += img->ucode_size;
	offset += _img->ucode_size;

	/*
	 * For falcons that use a boot loader (BL), we append a loader
@@ -261,7 +279,7 @@ ls_ucode_img_fill_headers(struct acr_r352 *acr, struct ls_ucode_img *img,
	lhdr->app_data_size = desc->app_resident_data_size;

	lhdr->flags = func->lhdr_flags;
	if (img->falcon_id == acr->base.boot_falcon)
	if (_img->falcon_id == acr->base.boot_falcon)
		lhdr->flags |= LSF_FLAG_DMACTL_REQ_CTX;

	/* Align and save off BL descriptor size */
@@ -280,10 +298,10 @@ ls_ucode_img_fill_headers(struct acr_r352 *acr, struct ls_ucode_img *img,
/**
 * acr_r352_ls_fill_headers - fill WPR and LSB headers of all managed images
 */
static int
int
acr_r352_ls_fill_headers(struct acr_r352 *acr, struct list_head *imgs)
{
	struct ls_ucode_img *img;
	struct ls_ucode_img_r352 *img;
	struct list_head *l;
	u32 count = 0;
	u32 offset;
@@ -298,34 +316,35 @@ acr_r352_ls_fill_headers(struct acr_r352 *acr, struct list_head *imgs)
	 * read of this array and cache it internally so it's ok to pack these.
	 * Also, we add 1 to the falcon count to indicate the end of the array.
	 */
	offset = sizeof(struct lsf_wpr_header) * (count + 1);
	offset = sizeof(img->wpr_header) * (count + 1);

	/*
	 * Walk the managed falcons, accounting for the LSB structs
	 * as well as the ucode images.
	 */
	list_for_each_entry(img, imgs, node) {
		offset = ls_ucode_img_fill_headers(acr, img, offset);
	list_for_each_entry(img, imgs, base.node) {
		offset = acr_r352_ls_img_fill_headers(acr, img, offset);
	}

	return offset;
}

/**
 * ls_ucode_mgr_write_wpr - write the WPR blob contents
 * acr_r352_ls_write_wpr - write the WPR blob contents
 */
static int
ls_ucode_mgr_write_wpr(struct acr_r352 *acr, struct list_head *imgs,
int
acr_r352_ls_write_wpr(struct acr_r352 *acr, struct list_head *imgs,
		      struct nvkm_gpuobj *wpr_blob, u32 wpr_addr)
{
	struct ls_ucode_img *img;
	struct ls_ucode_img *_img;
	u32 pos = 0;

	nvkm_kmap(wpr_blob);

	list_for_each_entry(img, imgs, node) {
	list_for_each_entry(_img, imgs, node) {
		struct ls_ucode_img_r352 *img = ls_ucode_img_r352(_img);
		const struct acr_r352_ls_func *ls_func =
					     acr->func->ls_func[img->falcon_id];
					    acr->func->ls_func[_img->falcon_id];
		u8 gdesc[ls_func->bl_desc_size];

		nvkm_gpuobj_memcpy_to(wpr_blob, pos, &img->wpr_header,
@@ -335,14 +354,14 @@ ls_ucode_mgr_write_wpr(struct acr_r352 *acr, struct list_head *imgs,
				     &img->lsb_header, sizeof(img->lsb_header));

		/* Generate and write BL descriptor */
		ls_func->generate_bl_desc(&acr->base, img, wpr_addr, gdesc);
		ls_func->generate_bl_desc(&acr->base, _img, wpr_addr, gdesc);

		nvkm_gpuobj_memcpy_to(wpr_blob, img->lsb_header.bl_data_off,
				      gdesc, ls_func->bl_desc_size);

		/* Copy ucode */
		nvkm_gpuobj_memcpy_to(wpr_blob, img->lsb_header.ucode_off,
				      img->ucode_data, img->ucode_size);
				      _img->ucode_data, _img->ucode_size);

		pos += sizeof(img->wpr_header);
	}
@@ -382,13 +401,12 @@ acr_r352_prepare_ls_blob(struct acr_r352 *acr, u64 wpr_addr, u32 wpr_size)
	for_each_set_bit(falcon_id, &managed_falcons, NVKM_SECBOOT_FALCON_END) {
		struct ls_ucode_img *img;

		img = ls_ucode_img_load(subdev,
					acr->func->ls_func[falcon_id]->load);

		img = acr->func->ls_ucode_img_load(acr, falcon_id);
		if (IS_ERR(img)) {
			ret = PTR_ERR(img);
			goto cleanup;
		}

		list_add_tail(&img->node, &imgs);
		managed_count++;
	}
@@ -397,7 +415,7 @@ acr_r352_prepare_ls_blob(struct acr_r352 *acr, u64 wpr_addr, u32 wpr_size)
	 * Fill the WPR and LSF headers with the right offsets and compute
	 * required WPR size
	 */
	image_wpr_size = acr_r352_ls_fill_headers(acr, &imgs);
	image_wpr_size = acr->func->ls_fill_headers(acr, &imgs);
	image_wpr_size = ALIGN(image_wpr_size, WPR_ALIGNMENT);

	/* Allocate GPU object that will contain the WPR region */
@@ -426,13 +444,14 @@ acr_r352_prepare_ls_blob(struct acr_r352 *acr, u64 wpr_addr, u32 wpr_size)
	}

	/* Write LS blob */
	ret = ls_ucode_mgr_write_wpr(acr, &imgs, acr->ls_blob, wpr_addr);
	ret = acr->func->ls_write_wpr(acr, &imgs, acr->ls_blob, wpr_addr);
	if (ret)
		nvkm_gpuobj_del(&acr->ls_blob);

cleanup:
	list_for_each_entry_safe(img, t, &imgs, node) {
		kfree(img->ucode_data);
		kfree(img->sig);
		kfree(img);
	}

@@ -859,6 +878,9 @@ const struct acr_r352_func
acr_r352_func = {
	.generate_hs_bl_desc = acr_r352_generate_hs_bl_desc,
	.hs_bl_desc_size = sizeof(struct acr_r352_flcn_bl_desc),
	.ls_ucode_img_load = acr_r352_ls_ucode_img_load,
	.ls_fill_headers = acr_r352_ls_fill_headers,
	.ls_write_wpr = acr_r352_ls_write_wpr,
	.ls_func = {
		[NVKM_SECBOOT_FALCON_FECS] = &acr_r352_ls_fecs_func,
		[NVKM_SECBOOT_FALCON_GPCCS] = &acr_r352_ls_gpccs_func,
+119 −0
Original line number Diff line number Diff line
@@ -23,11 +23,116 @@
#define __NVKM_SECBOOT_ACR_R352_H__

#include "acr.h"
#include "ls_ucode.h"

struct ls_ucode_img;

#define ACR_R352_MAX_APPS 8

/*
 *
 * LS blob structures
 *
 */

/**
 * struct acr_r352_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 acr_r352_lsf_lsb_header {
	/**
	 * LS falcon signatures
	 * @prd_keys:		signature to use in production mode
	 * @dgb_keys:		signature to use 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
	 */
	struct {
		u8 prd_keys[2][16];
		u8 dbg_keys[2][16];
		u32 b_prd_present;
		u32 b_dbg_present;
		u32 falcon_id;
	} 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 acr_r352_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 acr_r352_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_r352 - ucode image augmented with r352 headers
 */
struct ls_ucode_img_r352 {
	struct ls_ucode_img base;

	struct acr_r352_lsf_wpr_header wpr_header;
	struct acr_r352_lsf_lsb_header lsb_header;
};
#define ls_ucode_img_r352(i) container_of(i, struct ls_ucode_img_r352, base)


/*
 * HS blob structures
 */

struct hsf_load_header_app {
	u32 sec_code_off;
	u32 sec_code_size;
@@ -62,6 +167,8 @@ struct acr_r352_ls_func {
	u32 lhdr_flags;
};

struct acr_r352;

/**
 * struct acr_r352_func - manages nuances between ACR versions
 *
@@ -74,6 +181,12 @@ struct acr_r352_func {
				    u64);
	u32 hs_bl_desc_size;

	struct ls_ucode_img *(*ls_ucode_img_load)(const struct acr_r352 *,
						  enum nvkm_secboot_falcon);
	int (*ls_fill_headers)(struct acr_r352 *, struct list_head *);
	int (*ls_write_wpr)(struct acr_r352 *, struct list_head *,
			    struct nvkm_gpuobj *, u32);

	const struct acr_r352_ls_func *ls_func[NVKM_SECBOOT_FALCON_END];
};

@@ -125,4 +238,10 @@ struct acr_r352 {
struct nvkm_acr *acr_r352_new_(const struct acr_r352_func *,
			       enum nvkm_secboot_falcon, unsigned long);

struct ls_ucode_img *acr_r352_ls_ucode_img_load(const struct acr_r352 *,
						enum nvkm_secboot_falcon);
int acr_r352_ls_fill_headers(struct acr_r352 *, struct list_head *);
int acr_r352_ls_write_wpr(struct acr_r352 *, struct list_head *,
			  struct nvkm_gpuobj *, u32);

#endif
+6 −3
Original line number Diff line number Diff line
@@ -21,7 +21,6 @@
 */

#include "acr_r352.h"
#include "ls_ucode.h"

#include <engine/falcon.h>

@@ -64,11 +63,12 @@ struct acr_r361_flcn_bl_desc {

static void
acr_r361_generate_flcn_bl_desc(const struct nvkm_acr *acr,
			       const struct ls_ucode_img *img, u64 wpr_addr,
			       const struct ls_ucode_img *_img, u64 wpr_addr,
			       void *_desc)
{
	struct ls_ucode_img_r352 *img = ls_ucode_img_r352(_img);
	struct acr_r361_flcn_bl_desc *desc = _desc;
	const struct ls_ucode_img_desc *pdesc = &img->ucode_desc;
	const struct ls_ucode_img_desc *pdesc = &img->base.ucode_desc;
	u64 base, addr_code, addr_data;

	base = wpr_addr + img->lsb_header.ucode_off + pdesc->app_start_offset;
@@ -123,6 +123,9 @@ const struct acr_r352_func
acr_r361_func = {
	.generate_hs_bl_desc = acr_r361_generate_hs_bl_desc,
	.hs_bl_desc_size = sizeof(struct acr_r361_flcn_bl_desc),
	.ls_ucode_img_load = acr_r352_ls_ucode_img_load,
	.ls_fill_headers = acr_r352_ls_fill_headers,
	.ls_write_wpr = acr_r352_ls_write_wpr,
	.ls_func = {
		[NVKM_SECBOOT_FALCON_FECS] = &acr_r361_ls_fecs_func,
		[NVKM_SECBOOT_FALCON_GPCCS] = &acr_r361_ls_gpccs_func,
+5 −4
Original line number Diff line number Diff line
@@ -88,8 +88,8 @@
#include <subdev/timer.h>
#include <subdev/pmu.h>

static const char *
managed_falcons_names[] = {
const char *
nvkm_secboot_falcon_name[] = {
	[NVKM_SECBOOT_FALCON_PMU] = "PMU",
	[NVKM_SECBOOT_FALCON_RESERVED] = "<reserved>",
	[NVKM_SECBOOT_FALCON_FECS] = "FECS",
@@ -135,7 +135,7 @@ nvkm_secboot_oneinit(struct nvkm_subdev *subdev)
		break;
	default:
		nvkm_error(subdev, "Unmanaged boot falcon %s!\n",
			   managed_falcons_names[sb->acr->boot_falcon]);
			                nvkm_secboot_falcon_name[sb->acr->boot_falcon]);
		return -EINVAL;
	}

@@ -197,7 +197,8 @@ nvkm_secboot_ctor(const struct nvkm_secboot_func *func, struct nvkm_acr *acr,
	nvkm_debug(&sb->subdev, "securely managed falcons:\n");
	for_each_set_bit(fid, &sb->acr->managed_falcons,
			 NVKM_SECBOOT_FALCON_END)
		nvkm_debug(&sb->subdev, "- %s\n", managed_falcons_names[fid]);
		nvkm_debug(&sb->subdev, "- %s\n",
			   nvkm_secboot_falcon_name[fid]);

	return 0;
}
+4 −96
Original line number Diff line number Diff line
@@ -27,98 +27,6 @@
#include <core/subdev.h>
#include <subdev/secboot.h>

/*
 *
 * 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
@@ -175,8 +83,8 @@ struct ls_ucode_img_desc {
 * @ucode_desc:		loaded or generated map of ucode_data
 * @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
 * @sig:		signature for this firmware
 * @sig:size:		size of the signature in bytes
 *
 * 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
@@ -190,8 +98,8 @@ struct ls_ucode_img {
	u8 *ucode_data;
	u32 ucode_size;

	struct lsf_wpr_header wpr_header;
	struct lsf_lsb_header lsb_header;
	u8 *sig;
	u32 sig_size;
};

/**
Loading