rimage: add support for automatic MEU signing

This patch allows rimage to sign FW binaries using MEU tool.
Paths to MEU and private key have to be provided during config step.

Signed-off-by: Tomasz Lauda <tomasz.lauda@linux.intel.com>
This commit is contained in:
Tomasz Lauda 2018-06-04 12:03:42 +01:00 committed by Daniel Leung
parent d99e6d53c1
commit 81eba29a2f
5 changed files with 149 additions and 46 deletions

View File

@ -539,12 +539,13 @@ static int man_module_create_reloc(struct image *image, struct module *module,
return 0;
}
static int man_write_unsigned_mod(struct image *image)
static int man_write_unsigned_mod(struct image *image, int meta_start_offset,
int meta_end_offset)
{
int count;
/* write metadata file for unsigned FW */
count = fwrite(image->fw_image + MAN_META_EXT_OFFSET,
count = fwrite(image->fw_image + meta_start_offset,
sizeof(struct sof_man_adsp_meta_file_ext), 1,
image->out_man_fd);
@ -557,8 +558,8 @@ static int man_write_unsigned_mod(struct image *image)
fclose(image->out_man_fd);
/* now prepare the unsigned rimage */
count = fwrite(image->fw_image + MAN_FW_DESC_OFFSET,
image->image_end - MAN_FW_DESC_OFFSET,
count = fwrite(image->fw_image + meta_end_offset,
image->image_end - meta_end_offset,
1, image->out_unsigned_fd);
/* did the unsigned FW write succeed ? */
@ -601,13 +602,59 @@ static int man_write_fw_mod(struct image *image)
return 0;
}
static int man_create_modules(struct image *image, struct sof_man_fw_desc *desc)
{
struct module *module;
struct sof_man_module *man_module;
int err;
int i;
for (i = 0; i < image->num_modules; i++) {
man_module = sof_man_get_module(desc, i);
module = &image->module[i];
/* set module file offset */
if (i == 0)
module->foffset = FILE_TEXT_OFFSET;
else
module->foffset = image->image_end;
if (image->reloc)
err = man_module_create_reloc(image, module,
man_module);
else
err = man_module_create(image, module, man_module);
if (err < 0)
return err;
}
return 0;
}
static int man_hash_modules(struct image *image, struct sof_man_fw_desc *desc)
{
struct sof_man_module *man_module;
int i;
for (i = 0; i < image->num_modules; i++) {
man_module = sof_man_get_module(desc, i);
ri_hash(image,
man_module->segment[SOF_MAN_SEGMENT_TEXT].file_offset,
(man_module->segment[SOF_MAN_SEGMENT_TEXT].flags.r.length +
man_module->segment[SOF_MAN_SEGMENT_RODATA].flags.r.length) *
MAN_PAGE_SIZE, man_module->hash);
}
return 0;
}
/* used by others */
static int man_write_fw(struct image *image)
{
struct sof_man_fw_desc *desc;
struct fw_image_manifest *m;
struct module *module;
struct sof_man_module *man_module;
uint8_t hash[SOF_MAN_MOD_SHA256_LEN];
int ret, i;
@ -637,31 +684,13 @@ static int man_write_fw(struct image *image)
/* create each module */
m->desc.header.num_module_entries = image->num_modules;
for (i = 0; i < image->num_modules; i++) {
man_module = sof_man_get_module(desc, i);
module = &image->module[i];
/* set module file offset */
if (i == 0) {
module->foffset = FILE_TEXT_OFFSET;
} else {
module->foffset = image->image_end;
}
if (image->reloc)
ret = man_module_create_reloc(image, module,
man_module);
else
ret = man_module_create(image, module, man_module);
if (ret < 0)
goto err;
}
man_create_modules(image, desc);
fprintf(stdout, "Firmware completing manifest\n");
/* create structures from end of file to start of file */
ri_adsp_meta_data_create(image);
ri_adsp_meta_data_create(image, MAN_META_EXT_OFFSET,
MAN_FW_DESC_OFFSET);
ri_plat_ext_data_create(image);
ri_css_hdr_create(image);
ri_cse_create(image);
@ -671,16 +700,7 @@ static int man_write_fw(struct image *image)
desc->header.preload_page_count);
/* calculate hash for each module */
for (i = 0; i < image->num_modules; i++) {
module = &image->module[i];
man_module = sof_man_get_module(desc, i);
ri_hash(image, man_module->segment[SOF_MAN_SEGMENT_TEXT].file_offset,
(man_module->segment[SOF_MAN_SEGMENT_TEXT].flags.r.length +
man_module->segment[SOF_MAN_SEGMENT_RODATA].flags.r.length) *
MAN_PAGE_SIZE, man_module->hash);
}
man_hash_modules(image, desc);
/* calculate hash for ADSP meta data extension - 0x480 to end */
ri_hash(image, MAN_FW_DESC_OFFSET, image->image_end
@ -708,7 +728,8 @@ static int man_write_fw(struct image *image)
goto err;
/* write the unsigned files*/
ret = man_write_unsigned_mod(image);
ret = man_write_unsigned_mod(image, MAN_META_EXT_OFFSET,
MAN_FW_DESC_OFFSET);
if (ret < 0)
goto err;
@ -723,6 +744,79 @@ err:
return ret;
}
/* used to sign with MEU */
static int man_write_fw_meu(struct image *image)
{
const int meta_start_offset = image->meu_offset -
sizeof(struct sof_man_adsp_meta_file_ext) - MAN_EXT_PADDING;
struct sof_man_adsp_meta_file_ext *meta;
struct sof_man_fw_desc *desc;
uint32_t preload_size;
int ret;
/* allocate image */
image->fw_image = calloc(image->adsp->image_size, 1);
if (image->fw_image == NULL) {
ret = -ENOMEM;
goto err;
}
/* open unsigned firmware */
ret = man_open_unsigned_file(image);
if (ret < 0)
goto err;
/* create the manifest */
ret = man_open_manifest_file(image);
if (ret < 0)
goto err;
/* create the module */
meta = image->fw_image + meta_start_offset;
desc = image->fw_image + MAN_DESC_OFFSET;
/* copy data */
memcpy(meta, &image->adsp->man->adsp_file_ext,
sizeof(struct sof_man_adsp_meta_file_ext));
memcpy(desc, &image->adsp->man->desc,
sizeof(struct sof_man_fw_desc));
/* create each module */
desc->header.num_module_entries = image->num_modules;
man_create_modules(image, desc);
fprintf(stdout, "Firmware completing manifest\n");
/* create structures from end of file to start of file */
ri_adsp_meta_data_create(image, meta_start_offset, image->meu_offset);
/* write preload page count */
preload_size = meta->comp_desc[0].limit_offset - MAN_DESC_OFFSET;
preload_size += MAN_PAGE_SIZE - (preload_size % MAN_PAGE_SIZE);
desc->header.preload_page_count = preload_size / MAN_PAGE_SIZE;
/* calculate hash for each module */
man_hash_modules(image, desc);
/* calculate hash for ADSP meta data extension */
ri_hash(image, image->meu_offset, image->image_end -
image->meu_offset, meta->comp_desc[0].hash);
/* write the unsigned files */
ret = man_write_unsigned_mod(image, meta_start_offset,
image->meu_offset);
if (ret < 0)
goto err;
fprintf(stdout, "Firmware manifest completed!\n");
return 0;
err:
free(image->fw_image);
unlink(image->out_file);
return ret;
}
#define ADSP_APL_DSP_ROM_BASE 0xBEFE0000
#define ADSP_APL_DSP_ROM_SIZE 0x00002000
#define APL_DSP_BASE_ENTRY 0xa000a000
@ -743,6 +837,7 @@ const struct adsp machine_apl = {
.dram_offset = 0,
.machine_id = MACHINE_APOLLOLAKE,
.write_firmware = man_write_fw,
.write_firmware_meu = man_write_fw_meu,
.man = &apl_manifest,
};
@ -758,5 +853,6 @@ const struct adsp machine_cnl = {
.dram_offset = 0,
.machine_id = MACHINE_CANNONLAKE,
.write_firmware = man_write_fw,
.write_firmware_meu = man_write_fw_meu,
.man = &cnl_manifest,
};

View File

@ -18,15 +18,16 @@
#include "manifest.h"
#include "plat_auth.h"
void ri_adsp_meta_data_create(struct image *image)
void ri_adsp_meta_data_create(struct image *image, int meta_start_offset,
int meta_end_offset)
{
struct sof_man_adsp_meta_file_ext *meta =
image->fw_image + MAN_META_EXT_OFFSET;
image->fw_image + meta_start_offset;
fprintf(stdout, " meta: completing ADSP manifest\n");
meta->comp_desc[0].limit_offset = MAN_DESC_OFFSET + image->image_end
- MAN_FW_DESC_OFFSET;
- meta_end_offset;
fprintf(stdout, " meta: limit is 0x%x\n",
meta->comp_desc[0].limit_offset);

View File

@ -86,7 +86,8 @@ struct partition_info_ext {
(sizeof(struct partition_info_ext) + \
sizeof(struct signed_pkg_info_ext))
void ri_adsp_meta_data_create(struct image *image);
void ri_adsp_meta_data_create(struct image *image, int meta_start_offset,
int meta_end_offset);
void ri_plat_ext_data_create(struct image *image);
#endif

View File

@ -39,6 +39,7 @@ static void usage(char *name)
name);
fprintf(stdout, "\t -v enable verbose output\n");
fprintf(stdout, "\t -r enable relocatable ELF files\n");
fprintf(stdout, "\t -s MEU signing offset\n");
exit(0);
}
@ -50,7 +51,7 @@ int main(int argc, char *argv[])
memset(&image, 0, sizeof(image));
while ((opt = getopt(argc, argv, "ho:m:vba:sk:l:r")) != -1) {
while ((opt = getopt(argc, argv, "ho:m:vba:s:k:l:r")) != -1) {
switch (opt) {
case 'o':
image.out_file = optarg;
@ -62,7 +63,7 @@ int main(int argc, char *argv[])
image.verbose = 1;
break;
case 's':
image.dump_sections = 1;
image.meu_offset = atoi(optarg);
break;
case 'a':
image.abi = atoi(optarg);
@ -130,7 +131,10 @@ found:
}
/* process and write output */
ret = image.adsp->write_firmware(&image);
if (image.meu_offset)
ret = image.adsp->write_firmware_meu(&image);
else
ret = image.adsp->write_firmware(&image);
out:
/* close files */
if (image.out_fd)

View File

@ -99,7 +99,7 @@ struct image {
int num_modules;
struct module module[MAX_MODULES];
uint32_t image_end;/* module end, equal to output image size */
int dump_sections;
int meu_offset;
/* SHA 256 */
const char *key_name;
@ -140,6 +140,7 @@ struct adsp {
enum machine_id machine_id;
int (*write_firmware)(struct image *image);
int (*write_firmware_meu)(struct image *image);
struct fw_image_manifest *man;
};