rimage: move rimage to sof firmware repo

This removes cyclic dependency between both repos.

Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
This commit is contained in:
Liam Girdwood 2018-02-13 20:44:03 +00:00
parent f6924b1701
commit 72d797d9dd
20 changed files with 3 additions and 2795 deletions

View File

@ -1 +1 @@
SUBDIRS = rimage rmbox topology
SUBDIRS = rmbox topology

View File

@ -2,9 +2,9 @@
AC_PREREQ([2.69])
AC_INIT([sof-tools], [1.0.1])
AM_INIT_AUTOMAKE([foreign])
AC_CONFIG_SRCDIR([rimage/rimage.c])
AC_CONFIG_SRCDIR([rmbox/rmbox.c])
AC_CONFIG_HEADERS([config.h])
AC_CHECK_HEADER([sof/uapi/manifest.h])
AC_CHECK_HEADER([sof/uapi/abi.h])
AC_CANONICAL_HOST
@ -13,17 +13,8 @@ AM_MAINTAINER_MODE([enable])
AC_PROG_CC
#check for openssl
AC_CHECK_LIB([crypto], [OPENSSL_config], , [AC_MSG_ERROR([Need OpenSSL libcrypto])])
PEM_KEY_PREFIX="/usr/local/share/rimage"
AC_DEFINE_UNQUOTED([PEM_KEY_PREFIX], ["$PEM_KEY_PREFIX"], ["Path for PEM keys"])
AC_SUBST(PEM_KEY_PREFIX)
AC_OUTPUT([
Makefile
rimage/Makefile
rimage/keys/Makefile
rmbox/Makefile
topology/Makefile
topology/common/Makefile
@ -36,7 +27,6 @@ AC_OUTPUT([
echo "
prefix: ${prefix}
PEM: ${PEM_KEY_PREFIX}
Compiler: ${CC}
CFLAGS: ${CFLAGS}
"

View File

@ -1,25 +0,0 @@
SUBDIRS=keys
bin_PROGRAMS = rimage
noinst_HEADERS = \
rimage.h \
css.h \
cse.h \
plat_auth.h \
manifest.h \
file_format.h
rimage_SOURCES = \
file_simple.c \
man_apl.c \
man_cnl.c \
cse.c \
css.c \
plat_auth.c \
hash.c \
pkcs1_5.c \
manifest.c \
elf.c \
rimage.c

View File

@ -1,45 +0,0 @@
/*
* Copyright (c) 2017, Intel Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* Author: Liam Girdwood <liam.r.girdwood@linux.intel.com>
* Keyon Jie <yang.jie@linux.intel.com>
*/
#include <stdio.h>
#include "rimage.h"
#include "cse.h"
#include "manifest.h"
void ri_cse_create(struct image *image)
{
struct CsePartitionDirHeader *cse_hdr = image->fw_image;
struct sof_man_adsp_meta_file_ext *meta = image->fw_image +
MAN_META_EXT_OFFSET;
struct CsePartitionDirEntry *cse_entry =
image->fw_image + sizeof(*cse_hdr);
uint8_t csum = 0, *val = image->fw_image;
int i, size;
fprintf(stdout, " cse: completing CSE manifest\n");
cse_entry[2].length = meta->comp_desc[0].limit_offset -
MAN_DESC_OFFSET;
/* calculate checksum using BSD algo */
size = sizeof(*cse_hdr) + sizeof(*cse_entry) * MAN_CSE_PARTS;
for (i = 0; i < size; i++) {
if (i == 11)
continue;
csum += val[i];
}
cse_hdr->checksum = 0x100 - csum;
}

View File

@ -1,42 +0,0 @@
/*
* Copyright (c) 2017, Intel Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*/
#ifndef __CSE_H__
#define __CSE_H__
#include <stdint.h>
struct image;
#define CSE_HEADER_MAKER 0x44504324 /* "DPC$" */
struct CsePartitionDirHeader {
uint32_t header_marker;
uint32_t nb_entries;
uint8_t header_version;
uint8_t entry_version;
uint8_t header_length;
uint8_t checksum;
uint8_t partition_name[4];
} __attribute__((packed));
struct CsePartitionDirEntry {
uint8_t entry_name[12];
uint32_t offset;
uint32_t length;
uint32_t reserved;
} __attribute__((packed));
void ri_cse_create(struct image *image);
#endif

View File

@ -1,71 +0,0 @@
/*
* Copyright (c) 2017, Intel Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* Author: Liam Girdwood <liam.r.girdwood@linux.intel.com>
* Keyon Jie <yang.jie@linux.intel.com>
*/
#include <stdio.h>
#include <sys/time.h>
#include "rimage.h"
#include "css.h"
#include "manifest.h"
void ri_css_hdr_create(struct image *image)
{
struct css_header *css = image->fw_image + MAN_CSS_HDR_OFFSET;
struct tm *date;
struct timeval tv;
time_t time;
int val;
fprintf(stdout, " cse: completing CSS manifest\n");
/* get local time and date */
gettimeofday(&tv, NULL);
date = localtime(&tv.tv_sec);
date->tm_year += 1900;
fprintf(stdout, " css: set build date to %d:%2.2d:%2.2d\n",
date->tm_year, date->tm_mon, date->tm_mday);
/* year yYyy */
val = date->tm_year / 1000;
css->date |= val << 28;
date->tm_year -= val * 1000;
/* year yyYy */
val = date->tm_year / 100;
css->date |= val << 24;
date->tm_year -= val * 100;
/* year yyyY */
val = date->tm_year / 10;
css->date |= val << 20;
date->tm_year -= val * 10;
/* year Yyyy */
val = date->tm_year;
css->date |= val << 16;
/* month Mm - for some reason month starts at 0 */
val = ++date->tm_mon / 10;
css->date |= val << 12;
date->tm_mon -= (val * 10);
/* month mM */
val = date->tm_mon;
css->date |= val << 8;
/* Day Dd */
val = date->tm_mday / 10;
css->date |= val << 4;
date->tm_mday -= (val * 10);
/* Day dD */
val = date->tm_mday;
css->date |= val << 0;
}

View File

@ -1,69 +0,0 @@
/*
* Copyright (c) 2017, Intel Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*/
#ifndef __CSS_H__
#define __CSS_H__
#include <stdint.h>
struct image;
#define MAN_CSS_MOD_TYPE 4
#define MAN_CSS_HDR_SIZE 161 /* in words */
#define MAN_CSS_HDR_VERSION 0x10000
#define MAN_CSS_MOD_VENDOR 0x8086
#define MAN_CSS_HDR_ID {'$', 'M', 'N', '2'}
#define MAN_CSS_KEY_SIZE (MAN_RSA_KEY_MODULUS_LEN >> 2)
#define MAN_CSS_MOD_SIZE (MAN_RSA_KEY_MODULUS_LEN >> 2)
#define MAN_CSS_EXP_SIZE (MAN_RSA_KEY_EXPONENT_LEN >> 2)
#define MAN_CSS_MAN_SIZE \
(sizeof(struct fw_image_manifest) >> 2)
/*
* RSA Key and Crypto
*/
#define MAN_RSA_KEY_MODULUS_LEN 256
#define MAN_RSA_KEY_EXPONENT_LEN 4
#define MAN_RSA_SIGNATURE_LEN 256
struct fw_version {
uint16_t major_version;
uint16_t minor_version;
uint16_t hotfix_version;
uint16_t build_version;
} __attribute__((packed));
struct css_header {
uint32_t header_type;
uint32_t header_len;
uint32_t header_version;
uint32_t reserved0; /* must be 0x0 */
uint32_t module_vendor;
uint32_t date;
uint32_t size;
uint8_t header_id[4];
uint32_t padding; /* must be 0x0 */
struct fw_version version;
uint32_t svn;
uint32_t reserved1[18]; /* must be 0x0 */
uint32_t modulus_size;
uint32_t exponent_size;
uint8_t modulus[MAN_RSA_KEY_MODULUS_LEN];
uint8_t exponent[MAN_RSA_KEY_EXPONENT_LEN];
uint8_t signature[MAN_RSA_SIGNATURE_LEN];
} __attribute__((packed));
void ri_css_hdr_create(struct image *image);
#endif

View File

@ -1,537 +0,0 @@
/*
* Copyright (c) 2017, Intel Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* Author: Liam Girdwood <liam.r.girdwood@linux.intel.com>
* Keyon Jie <yang.jie@linux.intel.com>
*/
#include <stdio.h>
#include <string.h>
#include "rimage.h"
#include "cse.h"
#include "manifest.h"
static int elf_read_sections(struct image *image, struct module *module)
{
Elf32_Ehdr *hdr = &module->hdr;
Elf32_Shdr *section = module->section;
size_t count;
int i, ret;
uint32_t valid = (SHF_WRITE | SHF_ALLOC | SHF_EXECINSTR);
int man_section_idx;
/* read in section header */
ret = fseek(module->fd, hdr->e_shoff, SEEK_SET);
if (ret < 0) {
fprintf(stderr, "error: can't seek to %s section header %d\n",
module->elf_file, ret);
return ret;
}
/* allocate space for each section header */
section = calloc(sizeof(Elf32_Shdr), hdr->e_shnum);
if (section == NULL)
return -ENOMEM;
module->section = section;
/* read in sections */
count = fread(section, sizeof(Elf32_Shdr), hdr->e_shnum, module->fd);
if (count != hdr->e_shnum) {
fprintf(stderr, "error: failed to read %s section header %d\n",
module->elf_file, -errno);
return -errno;
}
/* find manifest module data */
man_section_idx = elf_find_section(image, module, ".bss");
if (man_section_idx < 0) {
return -EINVAL;
}
module->bss_index = man_section_idx;
fprintf(stdout, " BSS module metadata section at index %d\n",
man_section_idx);
/* parse each section */
for (i = 0; i < hdr->e_shnum; i++) {
/* only write valid sections */
if (!(section[i].sh_flags & valid))
continue;
switch (section[i].sh_type) {
case SHT_NOBITS:
/* bss */
module->bss_size += section[i].sh_size;
module->num_bss++;
break;
case SHT_PROGBITS:
/* text or data */
module->fw_size += section[i].sh_size;
if (section[i].sh_flags & SHF_EXECINSTR)
module->text_size += section[i].sh_size;
else
module->data_size += section[i].sh_size;
break;
default:
continue;
}
module->num_sections++;
if (!image->verbose)
continue;
fprintf(stdout, " %s section-%d: \ttype\t 0x%8.8x\n", module->elf_file,
i, section[i].sh_type);
fprintf(stdout, " %s section-%d: \tflags\t 0x%8.8x\n", module->elf_file,
i, section[i].sh_flags);
fprintf(stdout, " %s section-%d: \taddr\t 0x%8.8x\n", module->elf_file,
i, section[i].sh_addr);
fprintf(stdout, " %s section-%d: \toffset\t 0x%8.8x\n", module->elf_file,
i, section[i].sh_offset);
fprintf(stdout, " %s section-%d: \tsize\t 0x%8.8x\n", module->elf_file,
i, section[i].sh_size);
fprintf(stdout, " %s section-%d: \tlink\t 0x%8.8x\n", module->elf_file,
i, section[i].sh_link);
fprintf(stdout, " %s section-%d: \tinfo\t 0x%8.8x\n\n", module->elf_file,
i, section[i].sh_info);
}
return 0;
}
static int elf_read_programs(struct image *image, struct module *module)
{
Elf32_Ehdr *hdr = &module->hdr;
Elf32_Phdr *prg = module->prg;
size_t count;
int i, ret;
/* read in program header */
ret = fseek(module->fd, hdr->e_phoff, SEEK_SET);
if (ret < 0) {
fprintf(stderr, "error: cant seek to %s program header %d\n",
module->elf_file ,ret);
return ret;
}
/* allocate space for programs */
prg = calloc(sizeof(Elf32_Phdr), hdr->e_phnum);
if (prg == NULL)
return -ENOMEM;
module->prg = prg;
/* read in programs */
count = fread(prg, sizeof(Elf32_Phdr), hdr->e_phnum, module->fd);
if (count != hdr->e_phnum) {
fprintf(stderr, "error: failed to read %s program header %d\n",
module->elf_file, -errno);
return -errno;
}
/* check each program */
for (i = 0; i < hdr->e_phnum; i++) {
if (prg[i].p_filesz == 0)
continue;
if (!image->verbose)
continue;
fprintf(stdout, "%s program-%d: \ttype\t 0x%8.8x\n",
module->elf_file, i, prg[i].p_type);
fprintf(stdout, "%s program-%d: \toffset\t 0x%8.8x\n",
module->elf_file, i, prg[i].p_offset);
fprintf(stdout, "%s program-%d: \tvaddr\t 0x%8.8x\n",
module->elf_file, i, prg[i].p_vaddr);
fprintf(stdout, "%s program-%d: \tpaddr\t 0x%8.8x\n",
module->elf_file, i, prg[i].p_paddr);
fprintf(stdout, "%s program-%d: \tfsize\t 0x%8.8x\n",
module->elf_file, i, prg[i].p_filesz);
fprintf(stdout, "%s program-%d: \tmsize\t 0x%8.8x\n",
module->elf_file, i, prg[i].p_memsz);
fprintf(stdout, "%s program-%d: \tflags\t 0x%8.8x\n\n",
module->elf_file, i, prg[i].p_flags);
}
return 0;
}
static int elf_read_hdr(struct image *image, struct module *module)
{
Elf32_Ehdr *hdr = &module->hdr;
size_t count;
/* read in elf header */
count = fread(hdr, sizeof(*hdr), 1, module->fd);
if (count != 1) {
fprintf(stderr, "error: failed to read %s elf header %d\n",
module->elf_file, -errno);
return -errno;
}
if (!image->verbose)
return 0;
fprintf(stdout, "%s elf: \tentry point\t 0x%8.8x\n",
module->elf_file, hdr->e_entry);
fprintf(stdout, "%s elf: \tprogram offset\t 0x%8.8x\n",
module->elf_file, hdr->e_phoff);
fprintf(stdout, "%s elf: \tsection offset\t 0x%8.8x\n",
module->elf_file, hdr->e_shoff);
fprintf(stdout, "%s elf: \tprogram size\t 0x%8.8x\n",
module->elf_file, hdr->e_phentsize);
fprintf(stdout, "%s elf: \tprogram count\t 0x%8.8x\n",
module->elf_file, hdr->e_phnum);
fprintf(stdout, "%s elf: \tsection size\t 0x%8.8x\n",
module->elf_file, hdr->e_shentsize);
fprintf(stdout, "%s elf: \tsection count\t 0x%8.8x\n",
module->elf_file, hdr->e_shnum);
fprintf(stdout, "%s elf: \tstring index\t 0x%8.8x\n\n",
module->elf_file, hdr->e_shstrndx);
return 0;
}
int elf_is_rom(struct image *image, Elf32_Shdr *section)
{
const struct adsp *adsp = image->adsp;
uint32_t start, end;
start = section->sh_addr;
end = section->sh_addr + section->sh_size;
if (start < image->adsp->rom_base ||
start > image->adsp->rom_base + image->adsp->rom_size)
return 0;
if (end < image->adsp->rom_base ||
end > image->adsp->rom_base + image->adsp->rom_size)
return 0;
return 1;
}
static void elf_module_size(struct image *image, struct module *module,
Elf32_Shdr *section, int index)
{
switch (section->sh_type) {
case SHT_PROGBITS:
/* text or data */
if (section->sh_flags & SHF_EXECINSTR) {
/* text */
if (module->text_start > section->sh_addr)
module->text_start = section->sh_addr;
if (module->text_end < section->sh_addr + section->sh_size)
module->text_end = section->sh_addr + section->sh_size;
fprintf(stdout, "\tTEXT\n");
} else {
/* initialized data, also calc the writable sections */
if (module->data_start > section->sh_addr)
module->data_start = section->sh_addr;
if (module->data_end < section->sh_addr + section->sh_size)
module->data_end = section->sh_addr + section->sh_size;
fprintf(stdout, "\tDATA\n");
}
break;
case SHT_NOBITS:
/* bss */
if (index == module->bss_index) {
/* updated the .bss segment */
module->bss_start = section->sh_addr;
module->bss_end = section->sh_addr + section->sh_size;
fprintf(stdout, "\tBSS\n");
} else {
fprintf(stdout, "\tHEAP\n");
}
break;
default:
break;
}
}
static void elf_module_limits(struct image *image, struct module *module)
{
Elf32_Shdr *section;
uint32_t valid = (SHF_WRITE | SHF_ALLOC | SHF_EXECINSTR);
int i;
module->text_start = module->data_start = module->bss_start = 0xffffffff;
module->text_end = module->data_end = module->bss_end = 0;
fprintf(stdout, " Found %d sections, listing valid sections......\n",
module->hdr.e_shnum);
fprintf(stdout, "\tNo\tStart\t\tEnd\t\tBytes\tType\n");
/* iterate all sections and get size of segments */
for (i = 0; i < module->hdr.e_shnum; i++) {
section = &module->section[i];
/* only check valid sections */
if (!(section->sh_flags & valid))
continue;
if (section->sh_size == 0)
continue;
if (elf_is_rom(image, section))
continue;
fprintf(stdout, "\t%d\t0x%8.8x\t0x%8.8x\t%d", i,
section->sh_addr, section->sh_addr + section->sh_size,
section->sh_size);
/* text or data section */
elf_module_size(image, module, section, i);
}
fprintf(stdout, "\n");
}
/* make sure no section overlap from any modules */
int elf_validate_section(struct image *image, struct module *module,
Elf32_Shdr *section)
{
struct module *m;
Elf32_Shdr *s;
uint32_t valid = (SHF_WRITE | SHF_ALLOC | SHF_EXECINSTR);
int i, j, ret;
/* for each module */
for (i = 0; i < image->num_modules; i++) {
m = &image->module[i];
if (m == module)
continue;
/* for each section */
for (j = 0; j < m->hdr.e_shnum; j++) {
s = &m->section[j];
if (s == section)
continue;
/* only check valid sections */
if (!(section->sh_flags & valid))
continue;
if (section->sh_size == 0)
continue;
/* is section non overlapping ? */
if (section->sh_addr >= s->sh_addr &&
section->sh_addr + section->sh_size <=
s->sh_addr + s->sh_size) {
goto err;
}
}
}
return 0;
err:
fprintf(stderr, "error: section overlap between %s and %s\n",
module->elf_file, m->elf_file);
fprintf(stderr, " [0x%x : 0x%x] overlaps with [0x%x :0x%x]\n",
section->sh_addr, section->sh_addr + section->sh_size,
s->sh_addr, s->sh_addr + s->sh_size);
return -EINVAL;
}
/* make sure no section overlaps from any modules */
int elf_validate_modules(struct image *image)
{
struct module *module;
Elf32_Shdr *section;
uint32_t valid = (SHF_WRITE | SHF_ALLOC | SHF_EXECINSTR);
int i, j, ret;
/* for each module */
for (i = 0; i < image->num_modules; i++) {
module = &image->module[i];
/* for each section */
for (j = 0; j < module->hdr.e_shnum; j++) {
section = &module->section[j];
/* only check valid sections */
if (!(section->sh_flags & valid))
continue;
if (section->sh_size == 0)
continue;
/* is section non overlapping ? */
ret = elf_validate_section(image, module, section);
if (ret < 0)
return ret;
}
}
return 0;
}
int elf_find_section(struct image *image, struct module *module,
const char *name)
{
Elf32_Ehdr *hdr = &module->hdr;
Elf32_Shdr *section, *s;
char *buffer;
size_t count;
int ret, i;
section = &module->section[hdr->e_shstrndx];
/* alloc data data */
buffer = calloc(1, section->sh_size);
if (buffer == NULL)
return -ENOMEM;
/* read in section string data */
ret = fseek(module->fd, section->sh_offset, SEEK_SET);
if (ret < 0) {
fprintf(stderr, "error: cant seek to string section %d\n", ret);
goto out;
}
count = fread(buffer, 1, section->sh_size, module->fd);
if (count != section->sh_size) {
fprintf(stderr, "error: can't read string section %d\n", -errno);
ret = -errno;
goto out;
}
/* find section with name */
for (i = 0; i < hdr->e_shnum; i++) {
s = &module->section[i];
if (!strcmp(name, buffer + s->sh_name)) {
ret = i;
goto out;
}
}
fprintf(stderr, "error: can't find section %s in module %s\n", name,
module->elf_file);
ret = -EINVAL;
out:
free(buffer);
return ret;
}
int elf_parse_module(struct image *image, int module_index, const char *name)
{
const struct adsp *adsp = image->adsp;
struct module *module;
uint32_t rem;
int ret = 0;
/* validate module index */
if (module_index >= MAX_MODULES) {
fprintf(stderr, "error: too any modules\n");
return -EINVAL;
}
module = &image->module[module_index];
/* open the elf input file */
module->fd = fopen(name, "r");
if (module->fd == NULL) {
fprintf(stderr, "error: unable to open %s for reading %d\n",
name, errno);
return -EINVAL;
}
module->elf_file = name;
/* read in elf header */
ret = elf_read_hdr(image, module);
if (ret < 0)
goto hdr_err;
/* read in programs */
ret = elf_read_programs(image, module);
if (ret < 0) {
fprintf(stderr, "error: failed to read program sections %d\n",
ret);
goto hdr_err;
}
/* read sections */
ret = elf_read_sections(image, module);
if (ret < 0) {
fprintf(stderr, "error: failed to read base sections %d\n",
ret);
goto sec_err;
}
/* check limits */
elf_module_limits(image, module);
elf_find_section(image, module, "");
fprintf(stdout, " module: input size %d (0x%x) bytes %d sections\n",
module->fw_size, module->fw_size, module->num_sections);
fprintf(stdout, " module: text %d (0x%x) bytes\n"
" data %d (0x%x) bytes\n"
" bss %d (0x%x) bytes\n\n",
module->text_size, module->text_size,
module->data_size, module->data_size,
module->bss_size, module->bss_size);
/* file sizes round up to nearest page */
module->text_file_size = module->text_end - module->text_start;
rem = module->text_file_size % MAN_PAGE_SIZE;
if (rem)
module->text_file_size += MAN_PAGE_SIZE - rem;
/* apply any base FW fixups */
if (image->adsp->base_fw_text_size_fixup &&
module->text_start == image->adsp->sram_base) {
module->text_file_size += image->adsp->base_fw_text_size_fixup;
}
/* data section */
module->data_file_size = module->data_end - module->data_start;
rem = module->data_file_size % MAN_PAGE_SIZE;
if (rem)
module->data_file_size += MAN_PAGE_SIZE - rem;
/* bss section */
module->bss_file_size = module->bss_end - module->bss_start;
rem = module->bss_file_size % MAN_PAGE_SIZE;
if (rem)
module->bss_file_size += MAN_PAGE_SIZE - rem;
return 0;
sec_err:
free(module->prg);
hdr_err:
fclose(module->fd);
return ret;
}
void elf_free_module(struct image *image, int module_index)
{
struct module *module = &image->module[module_index];
free(module->prg);
free(module->section);
fclose(module->fd);
}

View File

@ -1,117 +0,0 @@
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2017 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* BSD LICENSE
*
* Copyright(c) 2017 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Author: Liam Girdwood <liam.r.girdwood@linux.intel.com>
*/
/*
* Firmware file format .
*/
#ifndef __INCLUDE_UAPI_SOF_FW_H__
#define __INCLUDE_UAPI_SOF_FW_H__
#define SND_SOF_FW_SIG_SIZE 4
#define SND_SOF_FW_ABI 1
#define SND_SOF_FW_SIG "Reef"
/*
* Firmware module is made up of 1 . N blocks of different types. The
* Block header is used to determine where and how block is to be copied in the
* DSP/host memory space.
*/
enum snd_sof_fw_blk_type {
SOF_BLK_IMAGE = 0, /* whole image - parsed by ROMs */
SOF_BLK_TEXT = 1,
SOF_BLK_DATA = 2,
SOF_BLK_CACHE = 3,
SOF_BLK_REGS = 4,
SOF_BLK_SIG = 5,
SOF_BLK_ROM = 6,
/* add new block types here */
};
struct snd_sof_blk_hdr {
enum snd_sof_fw_blk_type type;
uint32_t size; /* bytes minus this header */
uint32_t offset; /* offset from base */
} __attribute__((packed));
/*
* Firmware file is made up of 1 .. N different modules types. The module
* type is used to determine how to load and parse the module.
*/
enum snd_sof_fw_mod_type {
SOF_FW_BASE = 0, /* base firmware image */
SOF_FW_MODULE = 1, /* firmware module */
};
struct snd_sof_mod_hdr {
enum snd_sof_fw_mod_type type;
uint32_t size; /* bytes minus this header */
uint32_t num_blocks; /* number of blocks */
} __attribute__((packed));
/*
* Firmware file header.
*/
struct snd_sof_fw_header {
unsigned char sig[SND_SOF_FW_SIG_SIZE]; /* "Reef" */
uint32_t file_size; /* size of file minus this header */
uint32_t num_modules; /* number of modules */
uint32_t abi; /* version of header format */
} __attribute__((packed));
#endif

View File

@ -1,308 +0,0 @@
/*
* ELF to firmware image creator.
*
* Copyright (c) 2015, Intel Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*/
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include "rimage.h"
#include "file_format.h"
#define BYT_IRAM_BASE 0xff2c0000
#define BYT_IRAM_HOST_OFFSET 0x0C0000
#define BYT_IRAM_SIZE (80 * 1024)
#define BYT_DRAM_BASE 0xff300000
#define BYT_DRAM_HOST_OFFSET 0x100000
#define BYT_DRAM_SIZE (160 * 1024)
#define HSW_IRAM_BASE 0x00000000
#define HSW_IRAM_HOST_OFFSET 0x00080000
#define HSW_IRAM_SIZE (384 * 1024)
#define HSW_DRAM_BASE 0x00400000
#define HSW_DRAM_HOST_OFFSET 0x00000000
#define HSW_DRAM_SIZE (512 * 1024)
#define BDW_IRAM_BASE 0x00000000
#define BDW_IRAM_HOST_OFFSET 0x000A0000
#define BDW_IRAM_SIZE (320 * 1024)
#define BDW_DRAM_BASE 0x00400000
#define BDW_DRAM_HOST_OFFSET 0x00000000
#define BDW_DRAM_SIZE (640 * 1024)
static int is_iram(struct image *image, Elf32_Shdr *section)
{
const struct adsp *adsp = image->adsp;
uint32_t start, end;
start = section->sh_addr;
end = section->sh_addr + section->sh_size;
if (start < adsp->iram_base)
return 0;
if (start >= adsp->iram_base + adsp->iram_size)
return 0;
return 1;
}
static int is_dram(struct image *image, Elf32_Shdr *section)
{
const struct adsp *adsp = image->adsp;
uint32_t start, end;
start = section->sh_addr;
end = section->sh_addr + section->sh_size;
if (start < adsp->dram_base)
return 0;
if (start >= adsp->dram_base + adsp->dram_size)
return 0;
return 1;
}
static int block_idx = 0;
static int write_block(struct image *image, struct module *module,
Elf32_Shdr *section)
{
const struct adsp *adsp = image->adsp;
struct snd_sof_blk_hdr block;
size_t count;
void *buffer;
int ret;
block.size = section->sh_size;
if (is_iram(image, section)) {
block.type = SOF_BLK_TEXT;
block.offset = section->sh_addr - adsp->iram_base
+ adsp->host_iram_offset;
} else if (is_dram(image, section)) {
block.type = SOF_BLK_DATA;
block.offset = section->sh_addr - adsp->dram_base
+ adsp->host_dram_offset;
} else {
fprintf(stderr, "error: invalid block address/size 0x%x/0x%x\n",
section->sh_addr, section->sh_size);
return -EINVAL;
}
/* write header */
count = fwrite(&block, sizeof(block), 1, image->out_fd);
if (count != 1)
return -errno;
/* alloc data data */
buffer = calloc(1, section->sh_size);
if (buffer == NULL)
return -ENOMEM;
/* read in section data */
ret = fseek(module->fd, section->sh_offset, SEEK_SET);
if (ret < 0) {
fprintf(stderr, "error: cant seek to section %d\n", ret);
goto out;
}
count = fread(buffer, 1, section->sh_size, module->fd);
if (count != section->sh_size) {
fprintf(stderr, "error: cant read section %d\n", -errno);
ret = -errno;
goto out;
}
/* write out section data */
count = fwrite(buffer, 1, section->sh_size, image->out_fd);
if (count != section->sh_size) {
fprintf(stderr, "error: cant write section %d\n", -errno);
fprintf(stderr, " foffset %d size 0x%x mem addr 0x%x\n",
section->sh_offset, section->sh_size, section->sh_addr);
ret = -errno;
goto out;
}
fprintf(stdout, "\t%d\t0x%8.8x\t0x%8.8x\t0x%8.8lx\t%s\n", block_idx++,
section->sh_addr, section->sh_size, ftell(image->out_fd),
block.type == SOF_BLK_TEXT ? "TEXT" : "DATA");
out:
free(buffer);
return ret;
}
static int simple_write_module(struct image *image, struct module *module)
{
const struct adsp *adsp = image->adsp;
struct snd_sof_mod_hdr hdr;
Elf32_Shdr *section;
size_t count;
int i, err;
uint32_t valid = (SHF_WRITE | SHF_ALLOC | SHF_EXECINSTR);
hdr.num_blocks = module->num_sections - module->num_bss;
hdr.size = module->text_size + module->data_size +
sizeof(struct snd_sof_blk_hdr) * hdr.num_blocks;
hdr.type = SOF_FW_BASE;
count = fwrite(&hdr, sizeof(hdr), 1, image->out_fd);
if (count != 1) {
fprintf(stderr, "error: failed to write section header %d\n",
-errno);
return -errno ;
}
fprintf(stdout, "\n\tTotals\tStart\t\tEnd\t\tSize");
fprintf(stdout, "\n\tTEXT\t0x%8.8x\t0x%8.8x\t0x%x\n",
module->text_start, module->text_end,
module->text_end - module->text_start);
fprintf(stdout, "\tDATA\t0x%8.8x\t0x%8.8x\t0x%x\n",
module->data_start, module->data_end,
module->data_end - module->data_start);
fprintf(stdout, "\tBSS\t0x%8.8x\t0x%8.8x\t0x%x\n\n ",
module->bss_start, module->bss_end,
module->bss_end - module->bss_start);
fprintf(stdout, "\tNo\tAddress\t\tSize\t\tFile\t\tType\n");
for (i = 0; i < module->hdr.e_shnum; i++) {
section = &module->section[i];
/* only write valid sections */
if (!(module->section[i].sh_flags & valid))
continue;
/* dont write bss */
if (section->sh_type == SHT_NOBITS)
continue;
err = write_block(image, module, section);
if (err < 0) {
fprintf(stderr, "error: failed to write section #%d\n", i);
return err;
}
}
fprintf(stdout, "\n");
return 0;
}
/* used by others */
static int simple_write_firmware(struct image *image)
{
struct snd_sof_fw_header hdr;
struct module *module;
size_t count;
int i, ret;
memcpy(hdr.sig, SND_SOF_FW_SIG, SND_SOF_FW_SIG_SIZE);
hdr.num_modules = image->num_modules;
hdr.abi = SND_SOF_FW_ABI;
hdr.file_size = 0;
for (i = 0; i < image->num_modules; i++) {
module = &image->module[i];
module->fw_size += sizeof(struct snd_sof_blk_hdr) *
(module->num_sections - module->num_bss);
module->fw_size += sizeof(struct snd_sof_mod_hdr) * hdr.num_modules;
hdr.file_size += module->fw_size;
}
count = fwrite(&hdr, sizeof(hdr), 1, image->out_fd);
if (count != 1)
return -errno;
for (i = 0; i < image->num_modules; i++) {
module = &image->module[i];
fprintf(stdout, "writing module %d %s\n", i, module->elf_file);
ret = simple_write_module(image, module);
if (ret < 0) {
fprintf(stderr, "error: failed to write module %d\n",
i);
return ret;
}
}
fprintf(stdout, "firmware: image size %ld (0x%lx) bytes %d modules\n\n",
hdr.file_size + sizeof(hdr), hdr.file_size + sizeof(hdr),
hdr.num_modules);
return 0;
}
const struct adsp machine_byt = {
.name = "byt",
.iram_base = BYT_IRAM_BASE,
.iram_size = BYT_IRAM_SIZE,
.host_iram_offset = BYT_IRAM_HOST_OFFSET,
.dram_base = BYT_DRAM_BASE,
.dram_size = BYT_DRAM_SIZE,
.host_dram_offset = BYT_DRAM_HOST_OFFSET,
.machine_id = MACHINE_BAYTRAIL,
.write_firmware = simple_write_firmware,
};
const struct adsp machine_cht = {
.name = "cht",
.iram_base = BYT_IRAM_BASE,
.iram_size = BYT_IRAM_SIZE,
.host_iram_offset = BYT_IRAM_HOST_OFFSET,
.dram_base = BYT_DRAM_BASE,
.dram_size = BYT_DRAM_SIZE,
.host_dram_offset = BYT_DRAM_HOST_OFFSET,
.machine_id = MACHINE_CHERRYTRAIL,
.write_firmware = simple_write_firmware,
};
const struct adsp machine_bsw = {
.name = "bsw",
.iram_base = BYT_IRAM_BASE,
.iram_size = BYT_IRAM_SIZE,
.host_iram_offset = BYT_IRAM_HOST_OFFSET,
.dram_base = BYT_DRAM_BASE,
.dram_size = BYT_DRAM_SIZE,
.host_dram_offset = BYT_DRAM_HOST_OFFSET,
.machine_id = MACHINE_BRASWELL,
.write_firmware = simple_write_firmware,
};
const struct adsp machine_hsw = {
.name = "hsw",
.iram_base = HSW_IRAM_BASE,
.iram_size = HSW_IRAM_SIZE,
.host_iram_offset = HSW_IRAM_HOST_OFFSET,
.dram_base = HSW_DRAM_BASE,
.dram_size = HSW_DRAM_SIZE,
.host_dram_offset = HSW_DRAM_HOST_OFFSET,
.machine_id = MACHINE_HASWELL,
.write_firmware = simple_write_firmware,
};
const struct adsp machine_bdw = {
.name = "bdw",
.iram_base = BDW_IRAM_BASE,
.iram_size = BDW_IRAM_SIZE,
.host_iram_offset = BDW_IRAM_HOST_OFFSET,
.dram_base = BDW_DRAM_BASE,
.dram_size = BDW_DRAM_SIZE,
.host_dram_offset = BDW_DRAM_HOST_OFFSET,
.machine_id = MACHINE_BROADWELL,
.write_firmware = simple_write_firmware,
};

View File

@ -1,72 +0,0 @@
/*
* Copyright (c) 2017, Intel Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* Author: Liam Girdwood <liam.r.girdwood@linux.intel.com>
* Keyon Jie <yang.jie@linux.intel.com>
*/
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <time.h>
#include <sys/time.h>
#include <openssl/conf.h>
#include <openssl/evp.h>
#include <openssl/err.h>
#include "rimage.h"
#include "file_format.h"
#include "manifest.h"
#define DEBUG_HASH 0
void module_sha256_create(struct image *image)
{
image->md = EVP_sha256();
image->mdctx = EVP_MD_CTX_create();
EVP_DigestInit_ex(image->mdctx, image->md, NULL);
}
void module_sha256_update(struct image *image, uint8_t *data, size_t bytes)
{
EVP_DigestUpdate(image->mdctx, data, bytes);
}
void module_sha256_complete(struct image *image, uint8_t *hash)
{
unsigned char md_value[EVP_MAX_MD_SIZE];
int md_len;
#if DEBUG_HASH
int i;
#endif
EVP_DigestFinal_ex(image->mdctx, md_value, &md_len);
EVP_MD_CTX_destroy(image->mdctx);
memcpy(hash, md_value, md_len);
#if DEBUG_HASH
fprintf(stdout, "Module digest is: ");
for (i = 0; i < md_len; i++)
fprintf(stdout, "%02x", md_value[i]);
fprintf(stdout, "\n");
#endif
}
void ri_hash(struct image *image, unsigned offset, unsigned size, char *hash)
{
module_sha256_create(image);
module_sha256_update(image, image->fw_image + offset, size);
module_sha256_complete(image, hash);
}

View File

@ -1,144 +0,0 @@
/*
* Copyright (c) 2017, Intel Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*/
#include "css.h"
#include "cse.h"
#include "plat_auth.h"
#include "manifest.h"
/* hard coded atm - will pass this in from cmd line and git */
#define MAN_FW_HDR_VERSION_MAJOR 9
#define MAN_FW_HDR_VERSION_MINOR 22
#define MAN_FW_HDR_VERSION_HOTFIX 1
#define MAN_FW_HDR_VERSION_BUILD 0x7da
/* manifest template */
struct fw_image_manifest apl_manifest = {
.cse_partition_dir_header = {
.header_marker = CSE_HEADER_MAKER,
.nb_entries = MAN_CSE_PARTS,
.header_version = 1,
.entry_version = 1,
.header_length = sizeof(struct CsePartitionDirHeader),
.checksum = 0,
.partition_name = "ADSP",
},
.cse_partition_dir_entry = {
{
/* CssHeader + platformFirmwareAuthenticationExtension - padding */
.entry_name = "ADSP.man",
.offset = MAN_CSS_HDR_OFFSET,
.length = sizeof(struct css_header) +
PLAT_AUTH_SIZE,
},
{ /* ADSPMetadataFileExtension */
.entry_name = "cavs0015.met",
.offset = MAN_META_EXT_OFFSET,
.length = sizeof(struct sof_man_adsp_meta_file_ext),
},
{ /* AdspFwBinaryDesc */
.entry_name = "cavs0015",
.offset = MAN_FW_DESC_OFFSET,
.length = 0, /* calculated by rimage - */
},
},
.css = {
.header_type = MAN_CSS_MOD_TYPE,
.header_len = MAN_CSS_HDR_SIZE,
.header_version = MAN_CSS_HDR_VERSION,
.module_vendor = MAN_CSS_MOD_VENDOR,
.size = 222,
.header_id = MAN_CSS_HDR_ID,
.padding = 0,
.version = {
.major_version = MAN_FW_HDR_VERSION_MAJOR,
.minor_version = MAN_FW_HDR_VERSION_MINOR,
.hotfix_version = MAN_FW_HDR_VERSION_HOTFIX,
.build_version = MAN_FW_HDR_VERSION_BUILD,
},
.modulus_size = MAN_CSS_MOD_SIZE,
.exponent_size = MAN_CSS_EXP_SIZE,
},
.signed_pkg = {
.ext_type = SIGN_PKG_EXT_TYPE,
.ext_len = sizeof(struct signed_pkg_info_ext),
.name = "ADSP",
.vcn = 0,
.bitmap = {0, 0, 0, 0, 8},
.module[0] = {
.name = "cavs0015.met",
.meta_size = 96,
.type = 0x03,
.hash_algo = 0x02, /* SHA 256 */
.hash_size = 0x20,
},
},
.partition_info = {
.ext_type = PART_INFO_EXT_TYPE,
.ext_len = sizeof(struct partition_info_ext),
.name = "ADSP",
.length = 0, /* calculated by rimage - rounded up to nearest PAGE */
.part_version = 0x10000000,
.instance_id = 1,
.reserved[0 ... 19] = 0xff,
.module[0] = {
.name = "cavs0015.met",
.meta_size = 96,
.type = 0x03,
.reserved = {0x00, 0xff, 0xff},
},
},
.cse_padding[0 ... 47] = 0xff,
.adsp_file_ext = {
.ext_type = 17,
.ext_len = sizeof(struct sof_man_adsp_meta_file_ext),
.imr_type = 3,
.comp_desc[0] = {
.version = 0,
.base_offset = MAN_DESC_OFFSET,
.limit_offset = 0, /* calculated length + MAN_DESC_OFFSET */
},
},
.reserved[0 ... 31] = 0xff,
.desc = {
.header = {
.header_id = SOF_MAN_FW_HDR_ID,
.header_len = sizeof(struct sof_man_fw_header),
.name = SOF_MAN_FW_HDR_NAME,
.preload_page_count = 0, /* size in pages from $CPD */
.fw_image_flags = SOF_MAN_FW_HDR_FLAGS,
.feature_mask = SOF_MAN_FW_HDR_FEATURES,
.major_version = MAN_FW_HDR_VERSION_MAJOR,
.minor_version = MAN_FW_HDR_VERSION_MINOR,
.hotfix_version = MAN_FW_HDR_VERSION_HOTFIX,
.build_version = MAN_FW_HDR_VERSION_BUILD,
.load_offset = MAN_DESC_OFFSET,
},
},
};

View File

@ -1,143 +0,0 @@
/*
* Copyright (c) 2017, Intel Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*/
#include "css.h"
#include "cse.h"
#include "plat_auth.h"
#include "manifest.h"
/* hard coded atm - will pass this in from cmd line and git */
#define MAN_FW_HDR_VERSION_MAJOR 10
#define MAN_FW_HDR_VERSION_MINOR 23
#define MAN_FW_HDR_VERSION_HOTFIX 0
#define MAN_FW_HDR_VERSION_BUILD 0x2a4
/* manifest template */
struct fw_image_manifest cnl_manifest = {
.cse_partition_dir_header = {
.header_marker = CSE_HEADER_MAKER,
.nb_entries = MAN_CSE_PARTS,
.header_version = 1,
.entry_version = 1,
.header_length = sizeof(struct CsePartitionDirHeader),
.partition_name = "ADSP",
},
.cse_partition_dir_entry = {
{
/* CssHeader + platformFirmwareAuthenticationExtension - padding */
.entry_name = "ADSP.man",
.offset = MAN_CSS_HDR_OFFSET,
.length = sizeof(struct css_header) +
PLAT_AUTH_SIZE,
},
{ /* ADSPMetadataFileExtension */
.entry_name = "cavs0015.met",
.offset = MAN_META_EXT_OFFSET,
.length = sizeof(struct sof_man_adsp_meta_file_ext),
},
{ /* AdspFwBinaryDesc */
.entry_name = "cavs0015",
.offset = MAN_FW_DESC_OFFSET,
.length = 0, /* calculated by rimage - */
},
},
.css = {
.header_type = MAN_CSS_MOD_TYPE,
.header_len = MAN_CSS_HDR_SIZE,
.header_version = MAN_CSS_HDR_VERSION,
.module_vendor = MAN_CSS_MOD_VENDOR,
.size = 222,
.header_id = MAN_CSS_HDR_ID,
.padding = 0,
.version = {
.major_version = MAN_FW_HDR_VERSION_MAJOR,
.minor_version = MAN_FW_HDR_VERSION_MINOR,
.hotfix_version = MAN_FW_HDR_VERSION_HOTFIX,
.build_version = MAN_FW_HDR_VERSION_BUILD,
},
.modulus_size = MAN_CSS_MOD_SIZE,
.exponent_size = MAN_CSS_EXP_SIZE,
},
.signed_pkg = {
.ext_type = SIGN_PKG_EXT_TYPE,
.ext_len = sizeof(struct signed_pkg_info_ext),
.name = "ADSP",
.vcn = 0,
.bitmap = {0, 0, 0, 0, 8},
.module[0] = {
.name = "cavs0015.met",
.meta_size = 96,
.type = 0x03,
.hash_algo = 0x02, /* SHA 256 */
.hash_size = 0x20,
},
},
.partition_info = {
.ext_type = PART_INFO_EXT_TYPE,
.ext_len = sizeof(struct partition_info_ext),
.name = "ADSP",
.length = 0, /* calculated by rimage - rounded up to nearest PAGE */
.part_version = 0x10000000,
.instance_id = 1,
.reserved[0 ... 19] = 0xff,
.module[0] = {
.name = "cavs0015.met",
.meta_size = 96,
.type = 0x03,
.reserved = {0x00, 0xff, 0xff},
},
},
.cse_padding[0 ... 47] = 0xff,
.adsp_file_ext = {
.ext_type = 17,
.ext_len = sizeof(struct sof_man_adsp_meta_file_ext),
.imr_type = 3,
.comp_desc[0] = {
.version = 0,
.base_offset = MAN_DESC_OFFSET,
.limit_offset = 0, /* calculated length + MAN_DESC_OFFSET */
},
},
.reserved[0 ... 31] = 0xff,
.desc = {
.header = {
.header_id = SOF_MAN_FW_HDR_ID,
.header_len = sizeof(struct sof_man_fw_header),
.name = SOF_MAN_FW_HDR_NAME,
.preload_page_count = 0, /* size in pages from $CPD */
.fw_image_flags = SOF_MAN_FW_HDR_FLAGS,
.feature_mask = SOF_MAN_FW_HDR_FEATURES,
.major_version = MAN_FW_HDR_VERSION_MAJOR,
.minor_version = MAN_FW_HDR_VERSION_MINOR,
.hotfix_version = MAN_FW_HDR_VERSION_HOTFIX,
.build_version = MAN_FW_HDR_VERSION_BUILD,
.load_offset = 0x30000,
},
},
};

View File

@ -1,532 +0,0 @@
/*
* Copyright (c) 2017, Intel Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* Author: Liam Girdwood <liam.r.girdwood@linux.intel.com>
* Keyon Jie <yang.jie@linux.intel.com>
*/
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <time.h>
#include <sys/time.h>
#include <sof/uapi/manifest.h>
#include "rimage.h"
#include "file_format.h"
#include "css.h"
#include "cse.h"
#include "plat_auth.h"
#include "manifest.h"
static int man_open_rom_file(struct image *image)
{
sprintf(image->out_rom_file, "%s.rom", image->out_file);
unlink(image->out_rom_file);
/* allocate ROM image */
image->rom_image = calloc(image->adsp->rom_size, 1);
if (image->rom_image == NULL)
return -ENOMEM;
/* open ROM outfile for writing */
image->out_rom_fd = fopen(image->out_rom_file, "w");
if (image->out_rom_fd == NULL) {
fprintf(stderr, "error: unable to open %s for writing %d\n",
image->out_rom_file, errno);
}
return 0;
}
static int man_open_manifest_file(struct image *image)
{
/* open manifest outfile for writing */
sprintf(image->out_man_file, "%s.met", image->out_file);
unlink(image->out_man_file);
image->out_man_fd = fopen(image->out_man_file, "w");
if (image->out_man_fd == NULL) {
fprintf(stderr, "error: unable to open %s for writing %d\n",
image->out_man_file, errno);
}
return 0;
}
static int man_init_image(struct image *image)
{
/* allocate image and copy template manifest */
image->fw_image = calloc(image->adsp->image_size, 1);
if (image->fw_image == NULL)
return -ENOMEM;
memcpy(image->fw_image, image->adsp->man,
sizeof(struct fw_image_manifest));
return 0;
}
/* we should call this after all segments size set up via iterate */
static uint32_t elf_to_file_offset(struct image *image,
struct module *module, struct sof_man_module *man_module,
Elf32_Shdr *section)
{
uint32_t elf_addr = section->sh_addr, file_offset = 0;
if (section->sh_type == SHT_PROGBITS) {
if (section->sh_flags & SHF_EXECINSTR) {
/* text segment */
file_offset = elf_addr - module->text_start +
module->foffset;
}
else {
/* rodata segment, append to text segment */
file_offset = elf_addr - module->data_start +
module->foffset + module->text_file_size;
}
} else if (section->sh_type == SHT_NOBITS) {
/* bss segment */
file_offset = 0;
}
return file_offset;
}
/* write SRAM sections */
static int man_copy_sram(struct image *image, Elf32_Shdr *section,
struct module *module, struct sof_man_module *man_module,
int section_idx)
{
uint32_t offset = elf_to_file_offset(image, module,
man_module, section);
uint32_t end = offset + section->sh_size;
int seg_type = -1;
void *buffer = image->fw_image + offset;
size_t count;
switch (section->sh_type) {
case SHT_PROGBITS:
/* text or data */
if (section->sh_flags & SHF_EXECINSTR)
seg_type = SOF_MAN_SEGMENT_TEXT;
else
seg_type = SOF_MAN_SEGMENT_RODATA;
break;
case SHT_NOBITS:
seg_type = SOF_MAN_SEGMENT_BSS;
default:
return 0;
}
/* file_offset for segment should not be 0s, we set it to
* the smallest offset of its modules ATM.
*/
if (man_module->segment[seg_type].file_offset > offset ||
man_module->segment[seg_type].file_offset == 0)
man_module->segment[seg_type].file_offset = offset;
count = fread(buffer, 1, section->sh_size, module->fd);
if (count != section->sh_size) {
fprintf(stderr, "error: cant read section %d\n", -errno);
return -errno;
}
/* get module end offset ? */
if (end > image->image_end)
image->image_end = end;
fprintf(stdout, "\t%d\t0x%x\t0x%x\t0x%x\t%s\n", section_idx,
section->sh_addr, section->sh_size, offset,
seg_type == SOF_MAN_SEGMENT_TEXT ? "TEXT" : "DATA");
return 0;
}
static int man_copy_elf_section(struct image *image, Elf32_Shdr *section,
struct module *module, struct sof_man_module *man_module, int idx)
{
int ret;
/* seek to ELF section */
ret = fseek(module->fd, section->sh_offset, SEEK_SET);
if (ret < 0) {
fprintf(stderr, "error: can't seek to section %d\n", ret);
return ret;
}
/* write data to DRAM or ROM image */
if (!elf_is_rom(image, section))
return man_copy_sram(image, section, module, man_module, idx);
return 0;
}
static int man_get_module_manifest(struct image *image, struct module *module,
struct sof_man_module *man_module)
{
Elf32_Shdr *section;
struct sof_man_segment_desc *segment;
struct sof_man_module sof_mod;
size_t count;
int ret, man_section_idx;
fprintf(stdout, "Module Write: %s\n", module->elf_file);
/* find manifest module data */
man_section_idx = elf_find_section(image, module, ".module");
if (man_section_idx < 0) {
return -EINVAL;
}
fprintf(stdout, " Manifest module metadata section at index %d\n",
man_section_idx);
section = &module->section[man_section_idx];
/* load in manifest data */
ret = fseek(module->fd, section->sh_offset, SEEK_SET);
if (ret < 0) {
fprintf(stderr, "error: can't seek to section %d\n", ret);
return ret;
}
count = fread(&sof_mod, 1, sizeof(sof_mod), module->fd);
if (count != sizeof(sof_mod)) {
fprintf(stderr, "error: can't read section %d\n", -errno);
return -errno;
}
/* configure man_module with sofmod data */
strncpy(man_module->struct_id, "$AME", 4);
man_module->entry_point = sof_mod.entry_point;
strncpy(man_module->name, sof_mod.name, SOF_MAN_MOD_NAME_LEN);
memcpy(man_module->uuid, sof_mod.uuid, 16);
man_module->affinity_mask = sof_mod.affinity_mask;
man_module->type.auto_start = sof_mod.type.auto_start;
man_module->type.domain_dp = sof_mod.type.domain_dp;
man_module->type.domain_ll = sof_mod.type.domain_ll;
man_module->type.load_type = sof_mod.type.load_type;
/* text segment */
segment = &man_module->segment[SOF_MAN_SEGMENT_TEXT];
segment->flags.r.contents = 1;
segment->flags.r.alloc = 1;
segment->flags.r.load = 1;
segment->flags.r.readonly = 1;
segment->flags.r.code = 1;
/* data segment */
segment = &man_module->segment[SOF_MAN_SEGMENT_RODATA];
segment->flags.r.contents = 1;
segment->flags.r.alloc = 1;
segment->flags.r.load = 1;
segment->flags.r.readonly = 1;
segment->flags.r.data = 1;
segment->flags.r.type = 1;
/* bss segment */
segment = &man_module->segment[SOF_MAN_SEGMENT_BSS];
segment->flags.r.alloc = 1;
segment->flags.r.type = 2;
fprintf(stdout, " Entry point 0x%8.8x\n", man_module->entry_point);
return 0;
}
static int man_module_create(struct image *image, struct module *module,
struct sof_man_module *man_module)
{
/* create module and segments */
uint32_t valid = (SHF_WRITE | SHF_ALLOC | SHF_EXECINSTR);
const struct adsp *adsp = image->adsp;
Elf32_Shdr *section;
size_t count;
int i, err;
unsigned pages;
image->image_end = 0;
err = man_get_module_manifest(image, module, man_module);
if (err < 0)
return err;
/* stack size ??? convert sizes to PAGES */
man_module->instance_bss_size = 1;
/* max number of instances of this module ?? */
man_module->instance_max_count = 1;
fprintf(stdout, "\n\tTotals\tStart\t\tEnd\t\tSize");
fprintf(stdout, "\n\tTEXT\t0x%x\t0x%x\t0x%x\n",
module->text_start, module->text_end,
module->text_end - module->text_start);
fprintf(stdout, "\tDATA\t0x%x\t0x%x\t0x%x\n",
module->data_start, module->data_end,
module->data_end - module->data_start);
fprintf(stdout, "\tBSS\t0x%x\t0x%x\t0x%x\n\n ",
module->bss_start, module->bss_end,
module->bss_end - module->bss_start);
/* main module */
/* text section is first */
man_module->segment[SOF_MAN_SEGMENT_TEXT].file_offset =
module->foffset;
man_module->segment[SOF_MAN_SEGMENT_TEXT].v_base_addr =
module->text_start;
/* calculates those padding 0s by the start of next segment */
pages = module->text_file_size / MAN_PAGE_SIZE;
if (module->text_file_size % MAN_PAGE_SIZE)
pages += 1;
man_module->segment[SOF_MAN_SEGMENT_TEXT].flags.r.length = pages;
/* data section */
man_module->segment[SOF_MAN_SEGMENT_RODATA].v_base_addr =
module->data_start;
man_module->segment[SOF_MAN_SEGMENT_RODATA].file_offset =
module->foffset + module->text_file_size;
pages = module->data_file_size / MAN_PAGE_SIZE;
if (module->data_file_size % MAN_PAGE_SIZE)
pages += 1;
man_module->segment[SOF_MAN_SEGMENT_RODATA].flags.r.length = pages;
/* bss is last */
man_module->segment[SOF_MAN_SEGMENT_BSS].file_offset = 0;
man_module->segment[SOF_MAN_SEGMENT_BSS].v_base_addr = module->bss_start;
pages = (module->bss_end - module->bss_start) / MAN_PAGE_SIZE;
if ((module->bss_end - module->bss_start) % MAN_PAGE_SIZE)
pages += 1;
man_module->segment[SOF_MAN_SEGMENT_BSS].flags.r.length = pages;
fprintf(stdout, "\tNo\tAddress\t\tSize\tFile\tType\n");
/* find all sections and copy to corresponding segments */
for (i = 0; i < module->hdr.e_shnum; i++) {
section = &module->section[i];
/* only check valid sections */
if (!(section->sh_flags & valid))
continue;
if (section->sh_size == 0)
continue;
/* text or data section */
if (!elf_is_rom(image, section))
err = man_copy_elf_section(image, section, module,
man_module, i);
if (err < 0) {
fprintf(stderr, "error: failed to write section #%d\n", i);
return err;
}
}
fprintf(stdout, "\n");
/* round module end upto nearest page */
if (image->image_end % MAN_PAGE_SIZE) {
image->image_end = (image->image_end / MAN_PAGE_SIZE) + 1;
image->image_end *= MAN_PAGE_SIZE;
}
fprintf(stdout, " Total pages text %d data %d bss %d module file limit: 0x%x\n\n",
man_module->segment[SOF_MAN_SEGMENT_TEXT].flags.r.length,
man_module->segment[SOF_MAN_SEGMENT_RODATA].flags.r.length,
man_module->segment[SOF_MAN_SEGMENT_BSS].flags.r.length,
image->image_end);
return 0;
}
static int man_write_fw_mod(struct image *image)
{
int count;
long unsigned int size = 0;
/* write ROM - for VM use only */
count = fwrite(image->rom_image, image->adsp->rom_size, 1,
image->out_rom_fd);
if (count != 1) {
fprintf(stderr, "error: failed to write rom %s %d\n",
image->out_rom_file, -errno);
return -errno;
}
fclose(image->out_rom_fd);
/* write manifest and signed image */
count = fwrite(image->fw_image,
image->image_end,
1, image->out_fd);
/* did the image write succeed ? */
if (count != 1) {
fprintf(stderr, "error: failed to write signed firmware %s %d\n",
image->out_file, -errno);
return -errno;
}
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, count, i, man_section_idx;
/* init image */
ret = man_init_image(image);
if (ret < 0)
goto err;
/* open ROM image */
ret = man_open_rom_file(image);
if (ret < 0)
goto err;
/* create the manifest */
ret = man_open_manifest_file(image);
if (ret < 0)
goto err;
/* create the module */
m = image->fw_image;
desc = image->fw_image + MAN_DESC_OFFSET;
/* 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;
}
ret = man_module_create(image, module, man_module);
if (ret < 0)
goto err;
}
fprintf(stdout, "Firmware completing manifest\n");
/* create structures from end of file to start of file */
ri_adsp_meta_data_create(image);
ri_plat_ext_data_create(image);
ri_css_hdr_create(image);
ri_cse_create(image);
fprintf(stdout, "Firmware file size 0x%x page count %d\n",
FILE_TEXT_OFFSET - MAN_DESC_OFFSET + image->image_end,
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);
}
/* calculate hash for ADSP meta data extension - 0x480 to end */
ri_hash(image, MAN_FW_DESC_OFFSET, image->image_end
- MAN_FW_DESC_OFFSET, m->adsp_file_ext.comp_desc[0].hash);
/* calculate hash for platform auth data - repeated in hash 2 and 4 */
ri_hash(image, MAN_META_EXT_OFFSET,
sizeof(struct sof_man_adsp_meta_file_ext), hash);
/* hash values in reverse order */
for (i = 0; i < SOF_MAN_MOD_SHA256_LEN; i++) {
m->signed_pkg.module[0].hash[i] =
m->partition_info.module[0].hash[i] =
hash[SOF_MAN_MOD_SHA256_LEN - 1 - i];
}
/* sign manifest */
ret = ri_manifest_sign(image);
if (ret < 0)
goto err;
/* write the firmware */
ret = man_write_fw_mod(image);
if (ret < 0)
goto err;
fprintf(stdout, "Firmware manifest and signing completed !\n");
return 0;
err:
free(image->rom_image);
free(image->fw_image);
unlink(image->out_file);
unlink(image->out_rom_file);
return ret;
}
#define ADSP_APL_DSP_ROM_BASE 0xBEFE0000
#define ADSP_APL_DSP_ROM_SIZE 0x00002000
#define APL_DSP_BASE_ENTRY 0xa000a000
#define ADSP_CNL_DSP_ROM_BASE 0xBEFE0000
#define ADSP_CNL_DSP_ROM_SIZE 0x00002000
#define CNL_DSP_IMR_BASE_ENTRY 0xb0038000
#define CNL_DSP_HP_BASE_ENTRY 0xbe040000
/* list of supported adsp */
const struct adsp machine_apl = {
.name = "apl",
.rom_base = ADSP_APL_DSP_ROM_BASE,
.rom_size = ADSP_APL_DSP_ROM_SIZE,
.sram_base = APL_DSP_BASE_ENTRY,
.sram_size = 0x100000,
.image_size = 0x100000,
.dram_offset = 0,
.machine_id = MACHINE_APOLLOLAKE,
.write_firmware = man_write_fw,
.man = &apl_manifest,
.base_fw_text_size_fixup = 0xa000,
};
const struct adsp machine_cnl = {
.name = "cnl",
.rom_base = ADSP_CNL_DSP_ROM_BASE,
.rom_size = ADSP_CNL_DSP_ROM_SIZE,
.imr_base = CNL_DSP_IMR_BASE_ENTRY,
.imr_size = 0x100000,
.sram_base = CNL_DSP_HP_BASE_ENTRY,
.sram_size = 0x100000,
.image_size = 0x100000,
.dram_offset = 0,
.machine_id = MACHINE_CANNONLAKE,
.write_firmware = man_write_fw,
.man = &cnl_manifest,
};

View File

@ -1,90 +0,0 @@
/*
* Copyright (c) 2017, Intel Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*/
#ifndef __MANIFEST_H__
#define __MANIFEST_H__
#include <stdint.h>
#include <sof/uapi/manifest.h>
#include "css.h"
#include "cse.h"
#include "plat_auth.h"
#define MAN_PAGE_SIZE 4096
/* start offset for base FW module */
#define FILE_TEXT_OFFSET 0x8000
/*
* CSE values for CNL
*/
#define MAN_CSE_PARTS 3
#define MAN_CSE_HDR_OFFSET 0
#define MAN_CSE_PADDING_SIZE 0x30
#define MAN_EXT_PADDING 0x20
#define MAN_DESC_OFFSET 0x2000
#define MAN_CSS_HDR_OFFSET \
(MAN_CSE_HDR_OFFSET + \
sizeof(struct CsePartitionDirHeader) + \
MAN_CSE_PARTS * sizeof(struct CsePartitionDirEntry))
#define MAN_SIG_PKG_OFFSET \
(MAN_CSS_HDR_OFFSET + \
sizeof(struct css_header))
#define MAN_PART_INFO_OFFSET \
(MAN_SIG_PKG_OFFSET + \
sizeof(struct signed_pkg_info_ext))
#define MAN_META_EXT_OFFSET \
(MAN_SIG_PKG_OFFSET + \
sizeof(struct signed_pkg_info_ext) + \
sizeof(struct partition_info_ext) + \
MAN_CSE_PADDING_SIZE)
#define MAN_FW_DESC_OFFSET \
(MAN_META_EXT_OFFSET + \
sizeof(struct sof_man_adsp_meta_file_ext) + \
MAN_EXT_PADDING)
#define MAN_DESC_PADDING_SIZE \
(MAN_DESC_OFFSET - MAN_FW_DESC_OFFSET)
/*
* Firmware manifest header.
*/
struct fw_image_manifest {
/* MEU tool needs these sections to be 0s */
struct CsePartitionDirHeader cse_partition_dir_header;
struct CsePartitionDirEntry cse_partition_dir_entry[MAN_CSE_PARTS];
struct css_header css;
struct signed_pkg_info_ext signed_pkg;
struct partition_info_ext partition_info;
uint8_t cse_padding[MAN_CSE_PADDING_SIZE];
struct sof_man_adsp_meta_file_ext adsp_file_ext;
/* reserved / pading at end of ext data - all 0s*/
uint8_t reserved[MAN_EXT_PADDING];
/* start of the unsigned binary for MEU input must start at MAN_DESC_OFFSET */
uint8_t padding[MAN_DESC_PADDING_SIZE];
struct sof_man_fw_desc desc; /* at offset MAN_DESC_OFFSET */
} __attribute__((packed));
extern struct fw_image_manifest apl_manifest;
extern struct fw_image_manifest cnl_manifest;
#endif

View File

@ -1,141 +0,0 @@
/*
* Copyright (c) 2017, Intel Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* Author: Liam Girdwood <liam.r.girdwood@linux.intel.com>
* Keyon Jie <yang.jie@linux.intel.com>
*/
#include <openssl/pem.h>
#include <openssl/ssl.h>
#include <openssl/rsa.h>
#include <openssl/evp.h>
#include <openssl/bio.h>
#include <openssl/sha.h>
#include <openssl/objects.h>
#include <stdio.h>
#include <errno.h>
#include "config.h"
#include "rimage.h"
#include "css.h"
#include "manifest.h"
#define DEBUG_PKCS 0
static void bytes_swap(uint8_t *ptr, uint32_t size)
{
uint8_t tmp;
uint32_t index;
for (index = 0; index < (size / 2); index++) {
tmp = ptr[index];
ptr[index] = ptr[size - 1 - index];
ptr[size - 1 - index] = tmp;
}
}
/*
* RSA signature of manifest. The signature is an PKCS
* #1-v1_5 of the entire manifest structure, including all
* extensions, and excluding the last 3 fields of the
* manifest header (Public Key, Exponent and Signature).
*/
int pkcs_sign(struct image *image, struct fw_image_manifest *man,
void *ptr1, unsigned size1, void *ptr2, unsigned size2)
{
RSA *priv_rsa = NULL;
EVP_PKEY *privkey;
FILE *fp;
unsigned char digest[SHA256_DIGEST_LENGTH], path[256], mod[MAN_RSA_KEY_MODULUS_LEN];
unsigned int siglen = MAN_RSA_SIGNATURE_LEN;
int ret = -EINVAL, i;
#if DEBUG_PKCS
fprintf(stdout, "offsets 0x%lx size 0x%x offset 0x%lx size 0x%x\n",
ptr1 - (void*)man, size1, ptr2 - (void*)man, size2);
#endif
/* create new key */
privkey = EVP_PKEY_new();
if (privkey == NULL)
return -ENOMEM;
/* load in RSA private key from PEM file */
if (image->key_name == NULL) {
sprintf(path, "%s/otc_private_key.pem", PEM_KEY_PREFIX);
image->key_name = path;
}
fprintf(stdout, " pkcs: signing with key %s\n", image->key_name);
fp = fopen(image->key_name, "r");
if (fp == NULL) {
fprintf(stderr, "error: can't open file %s %d\n", path, -errno);
return -errno;
}
PEM_read_PrivateKey(fp, &privkey, NULL, NULL);
fclose(fp);
/* validate RSA private key */
priv_rsa = EVP_PKEY_get1_RSA(privkey);
if (RSA_check_key(priv_rsa)) {
fprintf(stdout, " pkcs: RSA private key is valid.\n");
} else {
fprintf(stderr, "error: validating RSA private key.\n");
return -EINVAL;
}
/* calculate the digest */
module_sha256_create(image);
module_sha256_update(image, ptr1, size1);
module_sha256_update(image, ptr2, size2);
module_sha256_complete(image, digest);
fprintf(stdout, " pkcs: digest for manifest is ");
for (i = 0; i < SHA256_DIGEST_LENGTH; i++)
fprintf(stdout, "%02x", digest[i]);
fprintf(stdout, "\n");
/* sign the manifest */
ret = RSA_sign(NID_sha256, digest, SHA256_DIGEST_LENGTH,
(unsigned char *)man->css.signature,
&siglen, priv_rsa);
if (ret < 0)
fprintf(stderr, "error: failed to sign manifest\n");
/* copy public key modulus and exponent to manifest */
BN_bn2bin(priv_rsa->n, mod);
BN_bn2bin(priv_rsa->e, (unsigned char*)man->css.exponent);
/* modulus is reveresd */
for (i = 0; i < MAN_RSA_KEY_MODULUS_LEN; i++)
man->css.modulus[i] = mod[MAN_RSA_KEY_MODULUS_LEN - (1 + i)];
/* signature is reveresd, swap it */
bytes_swap(man->css.signature, sizeof(man->css.signature));
EVP_PKEY_free(privkey);
return ret;
}
int ri_manifest_sign(struct image *image)
{
struct fw_image_manifest *man = image->fw_image;
pkcs_sign(image, man, (void *)man + MAN_CSS_HDR_OFFSET,
sizeof(struct css_header) -
(MAN_RSA_KEY_MODULUS_LEN + MAN_RSA_KEY_EXPONENT_LEN +
MAN_RSA_SIGNATURE_LEN),
(void *)man + MAN_SIG_PKG_OFFSET,
(man->css.size - man->css.header_len) * sizeof(uint32_t));
return 0;
}

View File

@ -1,50 +0,0 @@
/*
* Copyright (c) 2017, Intel Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* Author: Liam Girdwood <liam.r.girdwood@linux.intel.com>
* Keyon Jie <yang.jie@linux.intel.com>
*/
#include "rimage.h"
#include "manifest.h"
#include "plat_auth.h"
void ri_adsp_meta_data_create(struct image *image)
{
struct sof_man_adsp_meta_file_ext *meta =
image->fw_image + MAN_META_EXT_OFFSET;
fprintf(stdout, " meta: completing ADSP manifest\n");
meta->comp_desc[0].limit_offset = MAN_DESC_OFFSET + image->image_end
- MAN_FW_DESC_OFFSET;
fprintf(stdout, " meta: limit is 0x%x\n",
meta->comp_desc[0].limit_offset);
/* now hash the AdspFwBinaryDesc -> EOF */
}
void ri_plat_ext_data_create(struct image *image)
{
struct partition_info_ext *part = image->fw_image + MAN_PART_INFO_OFFSET;
struct sof_man_adsp_meta_file_ext *meta =
image->fw_image + MAN_META_EXT_OFFSET;
struct sof_man_fw_desc *desc = image->fw_image + MAN_DESC_OFFSET;
fprintf(stdout, " auth: completing authentication manifest\n");
part->length = meta->comp_desc[0].limit_offset - MAN_DESC_OFFSET;
part->length += MAN_PAGE_SIZE - (part->length % MAN_PAGE_SIZE);
/* do this here atm */
desc->header.preload_page_count = part->length / MAN_PAGE_SIZE;
}

View File

@ -1,92 +0,0 @@
/*
* Copyright (c) 2017, Intel Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*/
#ifndef __PLAT_AUTH_H__
#define __PLAT_AUTH_H__
#include <stdint.h>
struct image;
#define PLAT_AUTH_SHA256_LEN 32
#define PLAT_AUTH_NAME_LEN 12
#define PLAT_AUTH_PADDING 48 /* pad at end of struct */
#define SIGN_PKG_EXT_TYPE 15
#define SIGN_PKG_NUM_MODULE 1
struct signed_pkg_info_module {
uint8_t name[PLAT_AUTH_NAME_LEN]; /* must be padded with 0 */
uint8_t type;
uint8_t hash_algo;
uint16_t hash_size;
uint32_t meta_size;
uint8_t hash[PLAT_AUTH_SHA256_LEN];
} __attribute__((packed));
struct signed_pkg_info_ext {
uint32_t ext_type;
uint32_t ext_len;
uint8_t name[4];
uint32_t vcn;
uint8_t bitmap[16];
uint32_t svn;
uint8_t fw_type;
uint8_t fw_sub_type;
uint8_t reserved[14]; /* must be 0 */
/* variable length of modules */
struct signed_pkg_info_module module[SIGN_PKG_NUM_MODULE];
} __attribute__((packed));
#define PART_INFO_EXT_TYPE 3
#define PART_INFO_NUM_MODULE 1
struct partition_info_module {
uint8_t name[PLAT_AUTH_NAME_LEN]; /* must be padded with 0 */
uint8_t type;
uint8_t reserved[3];
uint32_t meta_size;
uint8_t hash[PLAT_AUTH_SHA256_LEN];
} __attribute__((packed));
struct partition_info_ext {
uint32_t ext_type;
uint32_t ext_len;
uint8_t name[4]; /* "ADSP" */
uint32_t length;
uint8_t hash[PLAT_AUTH_SHA256_LEN];
uint32_t vcn;
uint32_t part_version;
uint32_t fmt_version;
uint32_t instance_id;
uint32_t part_flags;
uint8_t reserved[20]; /* must be 0 */
/* variable length of modules */
struct partition_info_module module[PART_INFO_NUM_MODULE];
} __attribute__((packed));
#define PLAT_AUTH_SIZE \
(sizeof(struct partition_info_ext) + \
sizeof(struct signed_pkg_info_ext))
void ri_adsp_meta_data_create(struct image *image);
void ri_plat_ext_data_create(struct image *image);
#endif

View File

@ -1,139 +0,0 @@
/*
* ELF to firmware image creator.
*
* Copyright (c) 2015, Intel Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*/
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include "rimage.h"
#include "file_format.h"
#include "manifest.h"
static const struct adsp *machine[] = {
&machine_byt,
&machine_cht,
&machine_bsw,
&machine_hsw,
&machine_bdw,
&machine_apl,
&machine_cnl,
};
static void usage(char *name)
{
fprintf(stdout, "%s:\t -m machine -o outfile -k [key] ELF files\n", name);
fprintf(stdout, "\t -v enable verbose output\n");
exit(0);
}
int main(int argc, char *argv[])
{
struct image image;
const char *mach = NULL;
int opt, ret, i, binary = 0, elf_argc = 0;
memset(&image, 0, sizeof(image));
while ((opt = getopt(argc, argv, "ho:m:vba:sk:l:")) != -1) {
switch (opt) {
case 'o':
image.out_file = optarg;
break;
case 'm':
mach = optarg;
break;
case 'v':
image.verbose = 1;
break;
case 'b':
binary = 1;
break;
case 's':
image.dump_sections = 1;
break;
case 'a':
image.abi = atoi(optarg);
break;
case 'k':
image.key_name = optarg;
break;
case 'h':
usage(argv[0]);
break;
default:
break;
}
}
elf_argc = optind;
/* make sure we have an outfile and machine */
if (image.out_file == NULL || mach == NULL)
usage(argv[0]);
/* find machine */
for (i = 0; i < ARRAY_SIZE(machine); i++) {
if (!strcmp(mach, machine[i]->name)) {
image.adsp = machine[i];
goto found;
}
}
fprintf(stderr, "error: machine %s not found\n", mach);
fprintf(stderr, "error: available machines ");
for (i = 0; i < ARRAY_SIZE(machine); i++)
fprintf(stderr, "%s, ", machine[i]->name);
fprintf(stderr, "\n");
return -EINVAL;
found:
/* parse input ELF files */
image.num_modules = argc - elf_argc;
for (i = elf_argc; i < argc; i++) {
fprintf(stdout, "\nModule Reading %s\n", argv[i]);
ret = elf_parse_module(&image, i - elf_argc, argv[i]);
if (ret < 0)
goto out;
}
/* validate all modules */
ret = elf_validate_modules(&image);
if (ret < 0)
goto out;
/* open outfile for writing */
unlink(image.out_file);
image.out_fd = fopen(image.out_file, "w");
if (image.out_fd == NULL) {
fprintf(stderr, "error: unable to open %s for writing %d\n",
image.out_file, errno);
ret = -EINVAL;
goto out;
}
/* process and write output */
ret = image.adsp->write_firmware(&image);
out:
/* close files */
if (image.out_fd)
fclose(image.out_fd);
return ret;
}

View File

@ -1,165 +0,0 @@
/*
* ELF to firmware image creator.
*
* Copyright (c) 2015-2018 Intel Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*/
#ifndef __RIMAGE_H__
#define __RIMAGE_H__
#include <stdint.h>
#include <elf.h>
#include <stdio.h>
#include <openssl/conf.h>
#include <openssl/evp.h>
#include <openssl/err.h>
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
#define MAX_MODULES 32
struct adsp;
struct manifest;
struct man_module;
/* list of supported targets */
enum machine_id {
MACHINE_BAYTRAIL = 0,
MACHINE_CHERRYTRAIL,
MACHINE_BRASWELL,
MACHINE_HASWELL,
MACHINE_BROADWELL,
MACHINE_APOLLOLAKE,
MACHINE_CANNONLAKE,
MACHINE_MAX
};
/*
* ELF module data
*/
struct module {
const char *elf_file;
FILE *fd;
Elf32_Ehdr hdr;
Elf32_Shdr *section;
Elf32_Phdr *prg;
uint32_t text_start;
uint32_t text_end;
uint32_t data_start;
uint32_t data_end;
uint32_t bss_start;
uint32_t bss_end;
uint32_t foffset;
int num_sections;
int num_bss;
int fw_size;
int bss_index;
/* sizes do not include any gaps */
int bss_size;
int text_size;
int data_size;
/* sizes do include gaps to nearest page */
int bss_file_size;
int text_file_size;
int data_file_size;
};
/*
* Firmware image context.
*/
struct image {
const char *out_file;
FILE *out_fd;
void *pos;
const struct adsp *adsp;
int abi;
int verbose;
int num_modules;
struct module module[MAX_MODULES];
uint32_t image_end;/* module end, equal to output image size */
int dump_sections;
/* SHA 256 */
const char *key_name;
EVP_MD_CTX *mdctx;
const EVP_MD *md;
/* file IO */
void *fw_image;
void *rom_image;
FILE *out_rom_fd;
FILE *out_man_fd;
FILE *out_unsigned_fd;
char out_rom_file[256];
char out_man_file[256];
char out_unsigned_file[256];
};
/*
* Audio DSP descriptor and operations.
*/
struct adsp {
const char *name;
uint32_t iram_base;
uint32_t iram_size;
uint32_t dram_base;
uint32_t dram_size;
uint32_t sram_base;
uint32_t sram_size;
uint32_t host_iram_offset;
uint32_t host_dram_offset;
uint32_t rom_base;
uint32_t rom_size;
uint32_t imr_base;
uint32_t imr_size;
uint32_t image_size;
uint32_t dram_offset;
enum machine_id machine_id;
int (*write_firmware)(struct image *image);
struct fw_image_manifest *man;
/* fixups */
uint32_t base_fw_text_size_fixup; /* added to BASEFW text size */
};
void module_sha256_create(struct image *image);
void module_sha256_update(struct image *image, uint8_t *data, size_t bytes);
void module_sha256_complete(struct image *image, uint8_t *hash);
int ri_manifest_sign(struct image *image);
void ri_hash(struct image *image, unsigned offset, unsigned size, char *hash);
int elf_parse_module(struct image *image, int module_index, const char *name);
void elf_free_module(struct image *image, int module_index);
int elf_is_rom(struct image *image, Elf32_Shdr *section);
int elf_validate_modules(struct image *image);
int elf_find_section(struct image *image, struct module *module,
const char *name);
/* supported machines */
extern const struct adsp machine_byt;
extern const struct adsp machine_cht;
extern const struct adsp machine_bsw;
extern const struct adsp machine_hsw;
extern const struct adsp machine_bdw;
extern const struct adsp machine_apl;
extern const struct adsp machine_cnl;
#endif