blob: b758717b53484353a1afe12b00a06a4ec8779433 [file] [log] [blame]
Liam Girdwood05ef4342018-02-13 20:29:40 +00001/*
2 * Copyright (c) 2017, Intel Corporation.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com>
14 * Keyon Jie <yang.jie@linux.intel.com>
15 */
16
17
18#include <stdlib.h>
19#include <stdio.h>
20#include <unistd.h>
21#include <errno.h>
22#include <string.h>
23#include <time.h>
24#include <sys/time.h>
25
26#include "uapi/manifest.h"
27#include "rimage.h"
28#include "file_format.h"
29#include "css.h"
30#include "cse.h"
31#include "plat_auth.h"
32#include "manifest.h"
33
34static int man_open_rom_file(struct image *image)
35{
36 sprintf(image->out_rom_file, "%s.rom", image->out_file);
37 unlink(image->out_rom_file);
38
39 /* allocate ROM image */
40 image->rom_image = calloc(image->adsp->rom_size, 1);
41 if (image->rom_image == NULL)
42 return -ENOMEM;
43
44 /* open ROM outfile for writing */
45 image->out_rom_fd = fopen(image->out_rom_file, "w");
46 if (image->out_rom_fd == NULL) {
47 fprintf(stderr, "error: unable to open %s for writing %d\n",
48 image->out_rom_file, errno);
49 }
50
51 return 0;
52}
53
Pan Xiulid5b8df42018-02-23 01:40:19 +080054static int man_open_unsigned_file(struct image *image)
55{
56 sprintf(image->out_unsigned_file, "%s.uns", image->out_file);
57 unlink(image->out_unsigned_file);
58
59 /* open unsigned FW outfile for writing */
60 image->out_unsigned_fd = fopen(image->out_unsigned_file, "w");
61 if (image->out_unsigned_fd == NULL) {
62 fprintf(stderr, "error: unable to open %s for writing %d\n",
63 image->out_unsigned_file, errno);
64 }
65
66 return 0;
67}
68
Liam Girdwood05ef4342018-02-13 20:29:40 +000069static int man_open_manifest_file(struct image *image)
70{
71 /* open manifest outfile for writing */
72 sprintf(image->out_man_file, "%s.met", image->out_file);
73 unlink(image->out_man_file);
74
75 image->out_man_fd = fopen(image->out_man_file, "w");
76 if (image->out_man_fd == NULL) {
77 fprintf(stderr, "error: unable to open %s for writing %d\n",
78 image->out_man_file, errno);
79 }
80
81 return 0;
82}
83
84static int man_init_image(struct image *image)
85{
86 /* allocate image and copy template manifest */
87 image->fw_image = calloc(image->adsp->image_size, 1);
88 if (image->fw_image == NULL)
89 return -ENOMEM;
90
91 memcpy(image->fw_image, image->adsp->man,
92 sizeof(struct fw_image_manifest));
93
94 return 0;
95}
96
97/* we should call this after all segments size set up via iterate */
98static uint32_t elf_to_file_offset(struct image *image,
99 struct module *module, struct sof_man_module *man_module,
100 Elf32_Shdr *section)
101{
102 uint32_t elf_addr = section->sh_addr, file_offset = 0;
103
104 if (section->sh_type == SHT_PROGBITS) {
105 if (section->sh_flags & SHF_EXECINSTR) {
106 /* text segment */
107 file_offset = elf_addr - module->text_start +
108 module->foffset;
109 } else {
110 /* rodata segment, append to text segment */
111 file_offset = elf_addr - module->data_start +
Pan Xiuli3943df62018-03-02 15:55:27 +0800112 module->foffset + module->text_fixup_size;
Liam Girdwood05ef4342018-02-13 20:29:40 +0000113
114 }
115 } else if (section->sh_type == SHT_NOBITS) {
116 /* bss segment */
117 file_offset = 0;
118 }
119
120 return file_offset;
121}
122
123/* write SRAM sections */
124static int man_copy_sram(struct image *image, Elf32_Shdr *section,
125 struct module *module, struct sof_man_module *man_module,
126 int section_idx)
127{
128 uint32_t offset = elf_to_file_offset(image, module,
129 man_module, section);
130 uint32_t end = offset + section->sh_size;
131 int seg_type = -1;
132 void *buffer = image->fw_image + offset;
133 size_t count;
134
135 switch (section->sh_type) {
136 case SHT_PROGBITS:
137 /* text or data */
138 if (section->sh_flags & SHF_EXECINSTR)
139 seg_type = SOF_MAN_SEGMENT_TEXT;
140 else
141 seg_type = SOF_MAN_SEGMENT_RODATA;
142 break;
143 case SHT_NOBITS:
144 seg_type = SOF_MAN_SEGMENT_BSS;
145 default:
146 return 0;
147 }
148
149 /* file_offset for segment should not be 0s, we set it to
150 * the smallest offset of its modules ATM.
151 */
152 if (man_module->segment[seg_type].file_offset > offset ||
153 man_module->segment[seg_type].file_offset == 0)
154 man_module->segment[seg_type].file_offset = offset;
155
156 count = fread(buffer, 1, section->sh_size, module->fd);
157 if (count != section->sh_size) {
158 fprintf(stderr, "error: cant read section %d\n", -errno);
159 return -errno;
160 }
161
162 /* get module end offset ? */
163 if (end > image->image_end)
164 image->image_end = end;
165
Liam Girdwood301418d2018-04-08 16:32:57 +0100166 fprintf(stdout, "\t%d\t0x%x\t0x%x\t\t0x%x\t%s\n", section_idx,
Liam Girdwood05ef4342018-02-13 20:29:40 +0000167 section->sh_addr, section->sh_size, offset,
168 seg_type == SOF_MAN_SEGMENT_TEXT ? "TEXT" : "DATA");
169
170 return 0;
171}
172
173static int man_copy_elf_section(struct image *image, Elf32_Shdr *section,
174 struct module *module, struct sof_man_module *man_module, int idx)
175{
176 int ret;
177
178 /* seek to ELF section */
179 ret = fseek(module->fd, section->sh_offset, SEEK_SET);
180 if (ret < 0) {
181 fprintf(stderr, "error: can't seek to section %d\n", ret);
182 return ret;
183 }
184
185 /* write data to DRAM or ROM image */
186 if (!elf_is_rom(image, section))
187 return man_copy_sram(image, section, module, man_module, idx);
188
189 return 0;
190}
191
192static int man_get_module_manifest(struct image *image, struct module *module,
193 struct sof_man_module *man_module)
194{
195 Elf32_Shdr *section;
196 struct sof_man_segment_desc *segment;
Liam Girdwoodf6513162018-03-19 08:34:52 +0000197 struct sof_man_module_manifest sof_mod;
Liam Girdwood05ef4342018-02-13 20:29:40 +0000198 size_t count;
199 int ret, man_section_idx;
200
201 fprintf(stdout, "Module Write: %s\n", module->elf_file);
202
203 /* find manifest module data */
204 man_section_idx = elf_find_section(image, module, ".module");
205 if (man_section_idx < 0) {
206 return -EINVAL;
207 }
208
209 fprintf(stdout, " Manifest module metadata section at index %d\n",
210 man_section_idx);
211 section = &module->section[man_section_idx];
212
213 /* load in manifest data */
Liam Girdwood08f85702018-03-30 14:44:17 +0100214 /* module built using xcc has preceding bytes */
215 if (section->sh_size > sizeof(sof_mod))
216 ret = fseek(module->fd,
217 section->sh_offset + XCC_MOD_OFFSET, SEEK_SET);
218 else
219 ret = fseek(module->fd, section->sh_offset, SEEK_SET);
220
Liam Girdwood05ef4342018-02-13 20:29:40 +0000221 if (ret < 0) {
222 fprintf(stderr, "error: can't seek to section %d\n", ret);
223 return ret;
224 }
Liam Girdwood08f85702018-03-30 14:44:17 +0100225
Liam Girdwood05ef4342018-02-13 20:29:40 +0000226 count = fread(&sof_mod, 1, sizeof(sof_mod), module->fd);
227 if (count != sizeof(sof_mod)) {
228 fprintf(stderr, "error: can't read section %d\n", -errno);
229 return -errno;
230 }
231
232 /* configure man_module with sofmod data */
233 memcpy(man_module->struct_id, "$AME", 4);
Liam Girdwoodf6513162018-03-19 08:34:52 +0000234 man_module->entry_point = sof_mod.module.entry_point;
235 memcpy(man_module->name, sof_mod.module.name, SOF_MAN_MOD_NAME_LEN);
236 memcpy(man_module->uuid, sof_mod.module.uuid, 16);
237 man_module->affinity_mask = sof_mod.module.affinity_mask;
238 man_module->type.auto_start = sof_mod.module.type.auto_start;
239 man_module->type.domain_dp = sof_mod.module.type.domain_dp;
240 man_module->type.domain_ll = sof_mod.module.type.domain_ll;
241 man_module->type.load_type = sof_mod.module.type.load_type;
Liam Girdwood05ef4342018-02-13 20:29:40 +0000242
Pan Xiuli3943df62018-03-02 15:55:27 +0800243 /* read out text_fixup_size from memory mapping */
244 module->text_fixup_size = sof_mod.text_size;
245
Liam Girdwood05ef4342018-02-13 20:29:40 +0000246 /* text segment */
247 segment = &man_module->segment[SOF_MAN_SEGMENT_TEXT];
248 segment->flags.r.contents = 1;
249 segment->flags.r.alloc = 1;
250 segment->flags.r.load = 1;
251 segment->flags.r.readonly = 1;
252 segment->flags.r.code = 1;
253
254 /* data segment */
255 segment = &man_module->segment[SOF_MAN_SEGMENT_RODATA];
256 segment->flags.r.contents = 1;
257 segment->flags.r.alloc = 1;
258 segment->flags.r.load = 1;
259 segment->flags.r.readonly = 1;
260 segment->flags.r.data = 1;
261 segment->flags.r.type = 1;
262
263 /* bss segment */
264 segment = &man_module->segment[SOF_MAN_SEGMENT_BSS];
265 segment->flags.r.alloc = 1;
266 segment->flags.r.type = 2;
267
268 fprintf(stdout, " Entry point 0x%8.8x\n", man_module->entry_point);
269
270 return 0;
271}
272
Liam Girdwood041423b2018-02-27 16:35:10 +0000273static inline const char *segment_name(int i)
274{
275 switch (i) {
276 case SOF_MAN_SEGMENT_TEXT:
277 return "TEXT";
278 case SOF_MAN_SEGMENT_RODATA:
279 return "DATA";
280 case SOF_MAN_SEGMENT_BSS:
281 return "BSS";
282 default:
283 return "NONE";
284 }
285}
286
287/* make sure no segments collide */
288static int man_module_validate(struct sof_man_module *man_module)
289{
290 uint32_t istart, iend;
291 uint32_t jstart, jend;
292 int i, j;
293
294 for (i = 0; i < 3; i++) {
295
296 istart = man_module->segment[i].v_base_addr;
297 iend = istart + man_module->segment[i].flags.r.length *
298 MAN_PAGE_SIZE;
299
300 for (j = 0; j < 3; j++) {
301
302 /* don't validate segment against itself */
303 if (i == j)
304 continue;
305
306 jstart = man_module->segment[j].v_base_addr;
307 jend = jstart + man_module->segment[j].flags.r.length *
308 MAN_PAGE_SIZE;
309
310 if (jstart > istart && jstart < iend)
311 goto err;
312
313 if (jend > istart && jend < iend)
314 goto err;
315 }
316 }
317
318 /* success, no overlapping segments */
319 return 0;
320
321err:
322 fprintf(stderr, "error: segment %s [0x%8.8x:0x%8.8x] overlaps",
323 segment_name(i), istart, iend);
324 fprintf(stderr, " with %s [0x%8.8x:0x%8.8x]\n",
325 segment_name(j), jstart, jend);
326 return -EINVAL;
327}
328
Liam Girdwood05ef4342018-02-13 20:29:40 +0000329static int man_module_create(struct image *image, struct module *module,
330 struct sof_man_module *man_module)
331{
332 /* create module and segments */
333 uint32_t valid = (SHF_WRITE | SHF_ALLOC | SHF_EXECINSTR);
334 Elf32_Shdr *section;
335 int i, err;
336 unsigned int pages;
337
338 image->image_end = 0;
339
340 err = man_get_module_manifest(image, module, man_module);
341 if (err < 0)
342 return err;
343
344 /* stack size ??? convert sizes to PAGES */
345 man_module->instance_bss_size = 1;
346
347 /* max number of instances of this module ?? */
348 man_module->instance_max_count = 1;
349
350 fprintf(stdout, "\n\tTotals\tStart\t\tEnd\t\tSize");
351
Liam Girdwood301418d2018-04-08 16:32:57 +0100352 fprintf(stdout, "\n\tTEXT\t0x%8.8x\t0x%8.8x\t0x%x\n",
353 module->text_start, module->text_end,
354 module->text_end - module->text_start);
355 fprintf(stdout, "\tDATA\t0x%8.8x\t0x%8.8x\t0x%x\n",
356 module->data_start, module->data_end,
357 module->data_end - module->data_start);
358 fprintf(stdout, "\tBSS\t0x%8.8x\t0x%8.8x\t0x%x\n\n ",
359 module->bss_start, module->bss_end,
360 module->bss_end - module->bss_start);
Liam Girdwood05ef4342018-02-13 20:29:40 +0000361
362 /* main module */
363 /* text section is first */
364 man_module->segment[SOF_MAN_SEGMENT_TEXT].file_offset =
365 module->foffset;
366 man_module->segment[SOF_MAN_SEGMENT_TEXT].v_base_addr =
367 module->text_start;
368
369 /* calculates those padding 0s by the start of next segment */
370 pages = module->text_file_size / MAN_PAGE_SIZE;
371 if (module->text_file_size % MAN_PAGE_SIZE)
372 pages += 1;
373
Pan Xiuli3943df62018-03-02 15:55:27 +0800374 if (module->text_fixup_size == 0)
375 module->text_fixup_size = module->text_file_size;
376
377 /* check if text_file_size is bigger then text_fixup_size */
378 if (module->text_file_size > module->text_fixup_size) {
379 fprintf(stderr, "error: too small text size assigned!\n");
380 return -EINVAL;
381 }
382
Liam Girdwood05ef4342018-02-13 20:29:40 +0000383 man_module->segment[SOF_MAN_SEGMENT_TEXT].flags.r.length = pages;
384
385 /* data section */
386 man_module->segment[SOF_MAN_SEGMENT_RODATA].v_base_addr =
387 module->data_start;
388 man_module->segment[SOF_MAN_SEGMENT_RODATA].file_offset =
Pan Xiuli3943df62018-03-02 15:55:27 +0800389 module->foffset + module->text_fixup_size;
Liam Girdwood05ef4342018-02-13 20:29:40 +0000390 pages = module->data_file_size / MAN_PAGE_SIZE;
391 if (module->data_file_size % MAN_PAGE_SIZE)
392 pages += 1;
393
394 man_module->segment[SOF_MAN_SEGMENT_RODATA].flags.r.length = pages;
395
396 /* bss is last */
397 man_module->segment[SOF_MAN_SEGMENT_BSS].file_offset = 0;
398 man_module->segment[SOF_MAN_SEGMENT_BSS].v_base_addr = module->bss_start;
399 pages = (module->bss_end - module->bss_start) / MAN_PAGE_SIZE;
400 if ((module->bss_end - module->bss_start) % MAN_PAGE_SIZE)
401 pages += 1;
402 man_module->segment[SOF_MAN_SEGMENT_BSS].flags.r.length = pages;
Marcin Maka45e9bc42018-05-22 17:07:40 +0100403 if (pages == 0) {
404 man_module->segment[SOF_MAN_SEGMENT_BSS].flags.ul = 0;
405 man_module->segment[SOF_MAN_SEGMENT_BSS].flags.r.type =
406 SOF_MAN_SEGMENT_EMPTY;
407 }
Liam Girdwood05ef4342018-02-13 20:29:40 +0000408
Liam Girdwood301418d2018-04-08 16:32:57 +0100409 fprintf(stdout, "\tNo\tAddress\t\tSize\t\tFile\tType\n");
Liam Girdwood05ef4342018-02-13 20:29:40 +0000410
Liam Girdwood041423b2018-02-27 16:35:10 +0000411 if (man_module_validate(man_module) < 0)
412 return -EINVAL;
413
Liam Girdwood05ef4342018-02-13 20:29:40 +0000414 /* find all sections and copy to corresponding segments */
415 for (i = 0; i < module->hdr.e_shnum; i++) {
416
417 section = &module->section[i];
418
419 /* only check valid sections */
420 if (!(section->sh_flags & valid))
421 continue;
422
423 if (section->sh_size == 0)
424 continue;
425
426 /* text or data section */
427 if (!elf_is_rom(image, section))
428 err = man_copy_elf_section(image, section, module,
429 man_module, i);
430
431 if (err < 0) {
432 fprintf(stderr, "error: failed to write section #%d\n", i);
433 return err;
434 }
435 }
436 fprintf(stdout, "\n");
437
438 /* round module end upto nearest page */
439 if (image->image_end % MAN_PAGE_SIZE) {
440 image->image_end = (image->image_end / MAN_PAGE_SIZE) + 1;
441 image->image_end *= MAN_PAGE_SIZE;
442 }
443
444 fprintf(stdout, " Total pages text %d data %d bss %d module file limit: 0x%x\n\n",
445 man_module->segment[SOF_MAN_SEGMENT_TEXT].flags.r.length,
446 man_module->segment[SOF_MAN_SEGMENT_RODATA].flags.r.length,
447 man_module->segment[SOF_MAN_SEGMENT_BSS].flags.r.length,
448 image->image_end);
449 return 0;
450}
451
Liam Girdwood7db25d82018-04-12 21:07:35 +0100452static int man_module_create_reloc(struct image *image, struct module *module,
453 struct sof_man_module *man_module)
454{
455 /* create module and segments */
456 int err;
457 unsigned int pages;
458 void *buffer = image->fw_image + module->foffset;
459 size_t count;
460
461 image->image_end = 0;
462
463 err = man_get_module_manifest(image, module, man_module);
464 if (err < 0)
465 return err;
466
467 /* stack size ??? convert sizes to PAGES */
468 man_module->instance_bss_size = 1;
469
470 /* max number of instances of this module ?? */
471 man_module->instance_max_count = 1;
472
473 fprintf(stdout, "\n\tTotals\tStart\t\tEnd\t\tSize");
474
475 fprintf(stdout, "\n\tTEXT\t0x%8.8x\t0x%8.8x\t0x%x\n",
476 module->text_start, module->text_end,
477 module->text_end - module->text_start);
478 fprintf(stdout, "\tDATA\t0x%8.8x\t0x%8.8x\t0x%x\n",
479 module->data_start, module->data_end,
480 module->data_end - module->data_start);
481 fprintf(stdout, "\tBSS\t0x%8.8x\t0x%8.8x\t0x%x\n\n ",
482 module->bss_start, module->bss_end,
483 module->bss_end - module->bss_start);
484
485 /* main module */
486 /* text section is first */
487 man_module->segment[SOF_MAN_SEGMENT_TEXT].file_offset =
488 module->foffset;
489 man_module->segment[SOF_MAN_SEGMENT_TEXT].v_base_addr = 0;
490 man_module->segment[SOF_MAN_SEGMENT_TEXT].flags.r.length = 0;
491
492 /* data section */
493 man_module->segment[SOF_MAN_SEGMENT_RODATA].v_base_addr = 0;
494 man_module->segment[SOF_MAN_SEGMENT_RODATA].file_offset =
495 module->foffset;
496 pages = module->data_file_size / MAN_PAGE_SIZE;
497 if (module->data_file_size % MAN_PAGE_SIZE)
498 pages += 1;
499
500 man_module->segment[SOF_MAN_SEGMENT_RODATA].flags.r.length = pages;
501
502 /* bss is last */
503 man_module->segment[SOF_MAN_SEGMENT_BSS].file_offset = 0;
504 man_module->segment[SOF_MAN_SEGMENT_BSS].v_base_addr = 0;
505 man_module->segment[SOF_MAN_SEGMENT_BSS].flags.r.length = 0;
506
507 fprintf(stdout, "\tNo\tAddress\t\tSize\t\tFile\tType\n");
508
509 /* seek to beginning of file */
510 err = fseek(module->fd, 0, SEEK_SET);
511 if (err < 0) {
512 fprintf(stderr, "error: can't seek to section %d\n", err);
513 return err;
514 }
515
516 count = fread(buffer, 1, module->file_size, module->fd);
517 if (count != module->file_size) {
518 fprintf(stderr, "error: can't read section %d\n", -errno);
519 return -errno;
520 }
521
522 fprintf(stdout, "\t%d\t0x%8.8x\t0x%8.8x\t0x%x\t%s\n", 0,
523 0, module->file_size, 0, "DATA");
524
525 fprintf(stdout, "\n");
526 image->image_end = module->foffset + module->file_size;
527
528 /* round module end up to nearest page */
529 if (image->image_end % MAN_PAGE_SIZE) {
530 image->image_end = (image->image_end / MAN_PAGE_SIZE) + 1;
531 image->image_end *= MAN_PAGE_SIZE;
532 }
533
534 fprintf(stdout, " Total pages text %d data %d bss %d module file limit: 0x%x\n\n",
535 man_module->segment[SOF_MAN_SEGMENT_TEXT].flags.r.length,
536 man_module->segment[SOF_MAN_SEGMENT_RODATA].flags.r.length,
537 man_module->segment[SOF_MAN_SEGMENT_BSS].flags.r.length,
538 image->image_end);
539 return 0;
540}
541
Tomasz Laudaac7b0c22018-06-04 12:03:42 +0100542static int man_write_unsigned_mod(struct image *image, int meta_start_offset,
543 int meta_end_offset)
Pan Xiulid5b8df42018-02-23 01:40:19 +0800544{
545 int count;
546
547 /* write metadata file for unsigned FW */
Tomasz Laudaac7b0c22018-06-04 12:03:42 +0100548 count = fwrite(image->fw_image + meta_start_offset,
Pan Xiulid5b8df42018-02-23 01:40:19 +0800549 sizeof(struct sof_man_adsp_meta_file_ext), 1,
550 image->out_man_fd);
551
552 /* did the metadata/manifest write succeed ? */
553 if (count != 1) {
554 fprintf(stderr, "error: failed to write meta %s %d\n",
555 image->out_man_file, -errno);
556 return -errno;
557 }
558 fclose(image->out_man_fd);
559
560 /* now prepare the unsigned rimage */
Tomasz Laudaac7b0c22018-06-04 12:03:42 +0100561 count = fwrite(image->fw_image + meta_end_offset,
562 image->image_end - meta_end_offset,
Pan Xiulid5b8df42018-02-23 01:40:19 +0800563 1, image->out_unsigned_fd);
564
565 /* did the unsigned FW write succeed ? */
566 if (count != 1) {
567 fprintf(stderr, "error: failed to write firmware %s %d\n",
568 image->out_unsigned_file, -errno);
569 return -errno;
570 }
571 fclose(image->out_unsigned_fd);
572
573 return 0;
574}
575
Liam Girdwood05ef4342018-02-13 20:29:40 +0000576static int man_write_fw_mod(struct image *image)
577{
578 int count;
579
580 /* write ROM - for VM use only */
581 count = fwrite(image->rom_image, image->adsp->rom_size, 1,
582 image->out_rom_fd);
583 if (count != 1) {
584 fprintf(stderr, "error: failed to write rom %s %d\n",
585 image->out_rom_file, -errno);
586 return -errno;
587 }
588 fclose(image->out_rom_fd);
589
590 /* write manifest and signed image */
591 count = fwrite(image->fw_image,
592 image->image_end,
593 1, image->out_fd);
594
595 /* did the image write succeed ? */
596 if (count != 1) {
597 fprintf(stderr, "error: failed to write signed firmware %s %d\n",
598 image->out_file, -errno);
599 return -errno;
600 }
601
602 return 0;
603}
604
Tomasz Laudaac7b0c22018-06-04 12:03:42 +0100605static int man_create_modules(struct image *image, struct sof_man_fw_desc *desc)
606{
607 struct module *module;
608 struct sof_man_module *man_module;
609 int err;
610 int i;
611
612 for (i = 0; i < image->num_modules; i++) {
613 man_module = sof_man_get_module(desc, i);
614 module = &image->module[i];
615
616 /* set module file offset */
617 if (i == 0)
618 module->foffset = FILE_TEXT_OFFSET;
619 else
620 module->foffset = image->image_end;
621
622 if (image->reloc)
623 err = man_module_create_reloc(image, module,
624 man_module);
625 else
626 err = man_module_create(image, module, man_module);
627
628 if (err < 0)
629 return err;
630 }
631
632 return 0;
633}
634
635static int man_hash_modules(struct image *image, struct sof_man_fw_desc *desc)
636{
637 struct sof_man_module *man_module;
638 int i;
639
640 for (i = 0; i < image->num_modules; i++) {
641 man_module = sof_man_get_module(desc, i);
642
643 ri_hash(image,
644 man_module->segment[SOF_MAN_SEGMENT_TEXT].file_offset,
645 (man_module->segment[SOF_MAN_SEGMENT_TEXT].flags.r.length +
646 man_module->segment[SOF_MAN_SEGMENT_RODATA].flags.r.length) *
647 MAN_PAGE_SIZE, man_module->hash);
648 }
649
650 return 0;
651}
652
Liam Girdwood05ef4342018-02-13 20:29:40 +0000653/* used by others */
654static int man_write_fw(struct image *image)
655{
656 struct sof_man_fw_desc *desc;
657 struct fw_image_manifest *m;
Liam Girdwood05ef4342018-02-13 20:29:40 +0000658 uint8_t hash[SOF_MAN_MOD_SHA256_LEN];
659 int ret, i;
660
661 /* init image */
662 ret = man_init_image(image);
663 if (ret < 0)
664 goto err;
665
666 /* open ROM image */
667 ret = man_open_rom_file(image);
668 if (ret < 0)
669 goto err;
670
Pan Xiulid5b8df42018-02-23 01:40:19 +0800671 /* open unsigned firmware */
672 ret = man_open_unsigned_file(image);
673 if (ret < 0)
674 goto err;
675
Liam Girdwood05ef4342018-02-13 20:29:40 +0000676 /* create the manifest */
677 ret = man_open_manifest_file(image);
678 if (ret < 0)
679 goto err;
680
681 /* create the module */
682 m = image->fw_image;
683 desc = image->fw_image + MAN_DESC_OFFSET;
684
685 /* create each module */
686 m->desc.header.num_module_entries = image->num_modules;
Tomasz Laudaac7b0c22018-06-04 12:03:42 +0100687 man_create_modules(image, desc);
Liam Girdwood05ef4342018-02-13 20:29:40 +0000688
689 fprintf(stdout, "Firmware completing manifest\n");
690
691 /* create structures from end of file to start of file */
Tomasz Laudaac7b0c22018-06-04 12:03:42 +0100692 ri_adsp_meta_data_create(image, MAN_META_EXT_OFFSET,
693 MAN_FW_DESC_OFFSET);
Liam Girdwood05ef4342018-02-13 20:29:40 +0000694 ri_plat_ext_data_create(image);
695 ri_css_hdr_create(image);
696 ri_cse_create(image);
697
698 fprintf(stdout, "Firmware file size 0x%x page count %d\n",
699 FILE_TEXT_OFFSET - MAN_DESC_OFFSET + image->image_end,
700 desc->header.preload_page_count);
701
702 /* calculate hash for each module */
Tomasz Laudaac7b0c22018-06-04 12:03:42 +0100703 man_hash_modules(image, desc);
Liam Girdwood05ef4342018-02-13 20:29:40 +0000704
705 /* calculate hash for ADSP meta data extension - 0x480 to end */
706 ri_hash(image, MAN_FW_DESC_OFFSET, image->image_end
707 - MAN_FW_DESC_OFFSET, m->adsp_file_ext.comp_desc[0].hash);
708
709 /* calculate hash for platform auth data - repeated in hash 2 and 4 */
710 ri_hash(image, MAN_META_EXT_OFFSET,
711 sizeof(struct sof_man_adsp_meta_file_ext), hash);
712
713 /* hash values in reverse order */
714 for (i = 0; i < SOF_MAN_MOD_SHA256_LEN; i++) {
715 m->signed_pkg.module[0].hash[i] =
716 m->partition_info.module[0].hash[i] =
717 hash[SOF_MAN_MOD_SHA256_LEN - 1 - i];
718 }
719
720 /* sign manifest */
721 ret = ri_manifest_sign(image);
722 if (ret < 0)
723 goto err;
724
725 /* write the firmware */
726 ret = man_write_fw_mod(image);
727 if (ret < 0)
728 goto err;
729
Pan Xiulid5b8df42018-02-23 01:40:19 +0800730 /* write the unsigned files*/
Tomasz Laudaac7b0c22018-06-04 12:03:42 +0100731 ret = man_write_unsigned_mod(image, MAN_META_EXT_OFFSET,
732 MAN_FW_DESC_OFFSET);
Pan Xiulid5b8df42018-02-23 01:40:19 +0800733 if (ret < 0)
734 goto err;
735
Liam Girdwood05ef4342018-02-13 20:29:40 +0000736 fprintf(stdout, "Firmware manifest and signing completed !\n");
737 return 0;
738
739err:
740 free(image->rom_image);
741 free(image->fw_image);
742 unlink(image->out_file);
743 unlink(image->out_rom_file);
744 return ret;
745}
746
Tomasz Laudaac7b0c22018-06-04 12:03:42 +0100747/* used to sign with MEU */
748static int man_write_fw_meu(struct image *image)
749{
750 const int meta_start_offset = image->meu_offset -
751 sizeof(struct sof_man_adsp_meta_file_ext) - MAN_EXT_PADDING;
752 struct sof_man_adsp_meta_file_ext *meta;
753 struct sof_man_fw_desc *desc;
754 uint32_t preload_size;
755 int ret;
756
757 /* allocate image */
758 image->fw_image = calloc(image->adsp->image_size, 1);
759 if (image->fw_image == NULL) {
760 ret = -ENOMEM;
761 goto err;
762 }
763
764 /* open unsigned firmware */
765 ret = man_open_unsigned_file(image);
766 if (ret < 0)
767 goto err;
768
769 /* create the manifest */
770 ret = man_open_manifest_file(image);
771 if (ret < 0)
772 goto err;
773
774 /* create the module */
775 meta = image->fw_image + meta_start_offset;
776 desc = image->fw_image + MAN_DESC_OFFSET;
777
778 /* copy data */
779 memcpy(meta, &image->adsp->man->adsp_file_ext,
780 sizeof(struct sof_man_adsp_meta_file_ext));
781 memcpy(desc, &image->adsp->man->desc,
782 sizeof(struct sof_man_fw_desc));
783
784 /* create each module */
785 desc->header.num_module_entries = image->num_modules;
786 man_create_modules(image, desc);
787
788 fprintf(stdout, "Firmware completing manifest\n");
789
790 /* create structures from end of file to start of file */
791 ri_adsp_meta_data_create(image, meta_start_offset, image->meu_offset);
792
793 /* write preload page count */
794 preload_size = meta->comp_desc[0].limit_offset - MAN_DESC_OFFSET;
795 preload_size += MAN_PAGE_SIZE - (preload_size % MAN_PAGE_SIZE);
796 desc->header.preload_page_count = preload_size / MAN_PAGE_SIZE;
797
798 /* calculate hash for each module */
799 man_hash_modules(image, desc);
800
801 /* calculate hash for ADSP meta data extension */
802 ri_hash(image, image->meu_offset, image->image_end -
803 image->meu_offset, meta->comp_desc[0].hash);
804
805 /* write the unsigned files */
806 ret = man_write_unsigned_mod(image, meta_start_offset,
807 image->meu_offset);
808 if (ret < 0)
809 goto err;
810
811 fprintf(stdout, "Firmware manifest completed!\n");
812 return 0;
813
814err:
815 free(image->fw_image);
816 unlink(image->out_file);
817 return ret;
818}
819
Liam Girdwood05ef4342018-02-13 20:29:40 +0000820#define ADSP_APL_DSP_ROM_BASE 0xBEFE0000
821#define ADSP_APL_DSP_ROM_SIZE 0x00002000
822#define APL_DSP_BASE_ENTRY 0xa000a000
823
824#define ADSP_CNL_DSP_ROM_BASE 0xBEFE0000
825#define ADSP_CNL_DSP_ROM_SIZE 0x00002000
826#define CNL_DSP_IMR_BASE_ENTRY 0xb0038000
827#define CNL_DSP_HP_BASE_ENTRY 0xbe040000
828
829/* list of supported adsp */
830const struct adsp machine_apl = {
831 .name = "apl",
832 .rom_base = ADSP_APL_DSP_ROM_BASE,
833 .rom_size = ADSP_APL_DSP_ROM_SIZE,
834 .sram_base = APL_DSP_BASE_ENTRY,
835 .sram_size = 0x100000,
836 .image_size = 0x100000,
837 .dram_offset = 0,
838 .machine_id = MACHINE_APOLLOLAKE,
839 .write_firmware = man_write_fw,
Tomasz Laudaac7b0c22018-06-04 12:03:42 +0100840 .write_firmware_meu = man_write_fw_meu,
Liam Girdwood05ef4342018-02-13 20:29:40 +0000841 .man = &apl_manifest,
Liam Girdwood05ef4342018-02-13 20:29:40 +0000842};
843
844const struct adsp machine_cnl = {
845 .name = "cnl",
846 .rom_base = ADSP_CNL_DSP_ROM_BASE,
847 .rom_size = ADSP_CNL_DSP_ROM_SIZE,
848 .imr_base = CNL_DSP_IMR_BASE_ENTRY,
849 .imr_size = 0x100000,
850 .sram_base = CNL_DSP_HP_BASE_ENTRY,
851 .sram_size = 0x100000,
852 .image_size = 0x100000,
853 .dram_offset = 0,
854 .machine_id = MACHINE_CANNONLAKE,
855 .write_firmware = man_write_fw,
Tomasz Laudaac7b0c22018-06-04 12:03:42 +0100856 .write_firmware_meu = man_write_fw_meu,
Liam Girdwood05ef4342018-02-13 20:29:40 +0000857 .man = &cnl_manifest,
858};