From 091cd24f8888e3fdf40a747aae4d05d6f005af02 Mon Sep 17 00:00:00 2001 From: Karol Trzcinski Date: Wed, 19 Feb 2020 13:00:03 +0100 Subject: [PATCH 1/7] sof: Add fw_metadata section This section will be used to store information about firmware known during compilation time. Signed-off-by: Karol Trzcinski --- src/platform/apollolake/apollolake.x.in | 13 +++++++++++++ .../apollolake/include/platform/lib/memory.h | 3 +++ src/platform/baytrail/baytrail.x.in | 13 +++++++++++++ src/platform/baytrail/include/platform/lib/memory.h | 3 +++ src/platform/cannonlake/cannonlake.x.in | 13 +++++++++++++ .../cannonlake/include/platform/lib/memory.h | 3 +++ src/platform/haswell/haswell.x.in | 13 +++++++++++++ src/platform/haswell/include/platform/lib/memory.h | 3 +++ src/platform/icelake/icelake.x.in | 13 +++++++++++++ src/platform/icelake/include/platform/lib/memory.h | 3 +++ src/platform/imx8/imx8.x.in | 13 +++++++++++++ src/platform/imx8/include/platform/lib/memory.h | 3 +++ src/platform/imx8m/imx8m.x.in | 13 +++++++++++++ src/platform/imx8m/include/platform/lib/memory.h | 3 +++ src/platform/suecreek/include/platform/lib/memory.h | 3 +++ src/platform/suecreek/suecreek.x.in | 13 +++++++++++++ .../tigerlake/include/platform/lib/memory.h | 3 +++ src/platform/tigerlake/tigerlake.x.in | 12 ++++++++++++ 18 files changed, 143 insertions(+) diff --git a/src/platform/apollolake/apollolake.x.in b/src/platform/apollolake/apollolake.x.in index e7ebbd14b613..1e67806ee737 100644 --- a/src/platform/apollolake/apollolake.x.in +++ b/src/platform/apollolake/apollolake.x.in @@ -107,6 +107,9 @@ MEMORY static_log_entries_seg (!ari) : org = LOG_ENTRY_ELF_BASE, len = LOG_ENTRY_ELF_SIZE + fw_metadata_seg (!ari) : + org = EXT_MANIFEST_ELF_BASE, + len = EXT_MANIFEST_ELF_SIZE } PHDRS @@ -142,6 +145,7 @@ PHDRS static_uuid_entries_phdr PT_NOTE; static_log_entries_phdr PT_NOTE; + metadata_entries_phdr PT_NOTE; } /* Default entry point: */ @@ -157,6 +161,9 @@ PROVIDE(_memmap_vecbase_reset = SOF_MEM_VECBASE); _memmap_cacheattr_wbna_trapnull = 0xFF42FFF2; PROVIDE(_memmap_cacheattr_reset = _memmap_cacheattr_wbna_trapnull); +_EXT_MAN_ALIGN_ = 16; +EXTERN(ext_man_fw_ver) + SECTIONS { .MemoryExceptionVector.literal : ALIGN(4) @@ -590,4 +597,10 @@ SECTIONS { *(*.static_log*) } > static_log_entries_seg :static_log_entries_phdr + + .fw_metadata (COPY) : ALIGN(1024) + { + KEEP (*(.fw_metadata)) + . = ALIGN(_EXT_MAN_ALIGN_); + } >fw_metadata_seg :metadata_entries_phdr } diff --git a/src/platform/apollolake/include/platform/lib/memory.h b/src/platform/apollolake/include/platform/lib/memory.h index fb55d9bcb3b3..b82ba41f2c00 100644 --- a/src/platform/apollolake/include/platform/lib/memory.h +++ b/src/platform/apollolake/include/platform/lib/memory.h @@ -122,6 +122,9 @@ #define LOG_ENTRY_ELF_BASE 0x20000000 #define LOG_ENTRY_ELF_SIZE 0x2000000 +#define EXT_MANIFEST_ELF_BASE (LOG_ENTRY_ELF_BASE + LOG_ENTRY_ELF_SIZE) +#define EXT_MANIFEST_ELF_SIZE 0x2000000 + /* * The HP SRAM Region Apollolake is organised like this :- * +--------------------------------------------------------------------------+ diff --git a/src/platform/baytrail/baytrail.x.in b/src/platform/baytrail/baytrail.x.in index 996b739114bd..7dafc3abf2dc 100644 --- a/src/platform/baytrail/baytrail.x.in +++ b/src/platform/baytrail/baytrail.x.in @@ -108,6 +108,9 @@ MEMORY static_log_entries_seg (!ari) : org = LOG_ENTRY_ELF_BASE, len = LOG_ENTRY_ELF_SIZE + fw_metadata_seg (!ari) : + org = EXT_MANIFEST_ELF_BASE, + len = EXT_MANIFEST_ELF_SIZE } PHDRS @@ -145,6 +148,7 @@ PHDRS sof_stack_phdr PT_LOAD; static_uuid_entries_phdr PT_NOTE; static_log_entries_phdr PT_NOTE; + metadata_entries_phdr PT_NOTE; } /* Default entry point: */ @@ -172,6 +176,9 @@ _memmap_cacheattr_wt_allvalid = 0x11221222; _memmap_cacheattr_bp_allvalid = 0x22222222; PROVIDE(_memmap_cacheattr_reset = _memmap_cacheattr_wbna_trapnull); +_EXT_MAN_ALIGN_ = 16; +EXTERN(ext_man_fw_ver) + SECTIONS { .ResetVector.text : ALIGN(4) @@ -548,4 +555,10 @@ SECTIONS KEEP (*(.fw_ready)) KEEP (*(.fw_ready_metadata)) } >sof_data :sof_data_phdr + + .fw_metadata (COPY) : ALIGN(1024) + { + KEEP (*(.fw_metadata)) + . = ALIGN(_EXT_MAN_ALIGN_); + } >fw_metadata_seg :metadata_entries_phdr } diff --git a/src/platform/baytrail/include/platform/lib/memory.h b/src/platform/baytrail/include/platform/lib/memory.h index 1905b2edf553..2b90751f3359 100644 --- a/src/platform/baytrail/include/platform/lib/memory.h +++ b/src/platform/baytrail/include/platform/lib/memory.h @@ -98,6 +98,9 @@ static inline void *platform_rfree_prepare(void *ptr) #define LOG_ENTRY_ELF_BASE 0x20000000 #define LOG_ENTRY_ELF_SIZE 0x2000000 +#define EXT_MANIFEST_ELF_BASE (LOG_ENTRY_ELF_BASE + LOG_ENTRY_ELF_SIZE) +#define EXT_MANIFEST_ELF_SIZE 0x2000000 + /* * The Heap and Stack on Baytrail are organised like this :- * diff --git a/src/platform/cannonlake/cannonlake.x.in b/src/platform/cannonlake/cannonlake.x.in index 54a9e3bc81b7..3359a2575ec7 100644 --- a/src/platform/cannonlake/cannonlake.x.in +++ b/src/platform/cannonlake/cannonlake.x.in @@ -99,6 +99,9 @@ MEMORY static_log_entries_seg (!ari) : org = LOG_ENTRY_ELF_BASE, len = LOG_ENTRY_ELF_SIZE + fw_metadata_seg (!ari) : + org = EXT_MANIFEST_ELF_BASE, + len = EXT_MANIFEST_ELF_SIZE } PHDRS @@ -131,6 +134,7 @@ PHDRS wnd3_phdr PT_LOAD; static_uuid_entries_phdr PT_NOTE; static_log_entries_phdr PT_NOTE; + metadata_entries_phdr PT_NOTE; } /* Default entry point: */ @@ -144,6 +148,9 @@ PROVIDE(_memmap_vecbase_reset = HP_SRAM_VECBASE_RESET); _memmap_cacheattr_wbna_trapnull = 0xFF42FFF2; PROVIDE(_memmap_cacheattr_reset = _memmap_cacheattr_wbna_trapnull); +_EXT_MAN_ALIGN_ = 16; +EXTERN(ext_man_fw_ver) + SECTIONS { .MemoryExceptionVector.text : ALIGN(4) @@ -555,4 +562,10 @@ SECTIONS { *(*.static_log*) } > static_log_entries_seg :static_log_entries_phdr + + .fw_metadata (COPY) : ALIGN(1024) + { + KEEP (*(.fw_metadata)) + . = ALIGN(_EXT_MAN_ALIGN_); + } >fw_metadata_seg :metadata_entries_phdr } diff --git a/src/platform/cannonlake/include/platform/lib/memory.h b/src/platform/cannonlake/include/platform/lib/memory.h index 3400c4fcccb1..9755f72b1d72 100644 --- a/src/platform/cannonlake/include/platform/lib/memory.h +++ b/src/platform/cannonlake/include/platform/lib/memory.h @@ -130,6 +130,9 @@ #define LOG_ENTRY_ELF_BASE 0x20000000 #define LOG_ENTRY_ELF_SIZE 0x2000000 +#define EXT_MANIFEST_ELF_BASE (LOG_ENTRY_ELF_BASE + LOG_ENTRY_ELF_SIZE) +#define EXT_MANIFEST_ELF_SIZE 0x2000000 + /* * The HP SRAM Region on Cannonlake is organised like this :- * +--------------------------------------------------------------------------+ diff --git a/src/platform/haswell/haswell.x.in b/src/platform/haswell/haswell.x.in index 3f9adaea9c95..cca86c0bc1d6 100644 --- a/src/platform/haswell/haswell.x.in +++ b/src/platform/haswell/haswell.x.in @@ -114,6 +114,9 @@ MEMORY static_log_entries_seg (!ari) : org = LOG_ENTRY_ELF_BASE, len = LOG_ENTRY_ELF_SIZE + fw_metadata_seg (!ari) : + org = EXT_MANIFEST_ELF_BASE, + len = EXT_MANIFEST_ELF_SIZE } PHDRS @@ -153,6 +156,7 @@ PHDRS sof_stack_phdr PT_LOAD; static_uuid_entries_phdr PT_NOTE; static_log_entries_phdr PT_NOTE; + metadata_entries_phdr PT_NOTE; } /* Default entry point: */ @@ -180,6 +184,9 @@ _memmap_cacheattr_wt_allvalid = 0x11221222; _memmap_cacheattr_bp_allvalid = 0x22222222; PROVIDE(_memmap_cacheattr_reset = _memmap_cacheattr_wbna_trapnull); +_EXT_MAN_ALIGN_ = 16; +EXTERN(ext_man_fw_ver) + SECTIONS { .ResetVector.text : ALIGN(4) @@ -573,4 +580,10 @@ SECTIONS KEEP (*(.fw_ready)) KEEP (*(.fw_ready_metadata)) } >sof_data :sof_data_phdr + + .fw_metadata (COPY) : ALIGN(1024) + { + KEEP (*(.fw_metadata)) + . = ALIGN(_EXT_MAN_ALIGN_); + } >fw_metadata_seg :metadata_entries_phdr } diff --git a/src/platform/haswell/include/platform/lib/memory.h b/src/platform/haswell/include/platform/lib/memory.h index ec8a02d708e2..8545da99ad12 100644 --- a/src/platform/haswell/include/platform/lib/memory.h +++ b/src/platform/haswell/include/platform/lib/memory.h @@ -91,6 +91,9 @@ static inline void *platform_rfree_prepare(void *ptr) #define LOG_ENTRY_ELF_BASE 0x20000000 #define LOG_ENTRY_ELF_SIZE 0x2000000 +#define EXT_MANIFEST_ELF_BASE (LOG_ENTRY_ELF_BASE + LOG_ENTRY_ELF_SIZE) +#define EXT_MANIFEST_ELF_SIZE 0x2000000 + /* * The Heap and Stack on Haswell/Broadwell are organised like this :- * diff --git a/src/platform/icelake/icelake.x.in b/src/platform/icelake/icelake.x.in index bcf2243ae255..6e7bc494142f 100644 --- a/src/platform/icelake/icelake.x.in +++ b/src/platform/icelake/icelake.x.in @@ -99,11 +99,17 @@ MEMORY static_log_entries_seg (!ari) : org = LOG_ENTRY_ELF_BASE, len = LOG_ENTRY_ELF_SIZE + fw_metadata_seg (!ari) : + org = EXT_MANIFEST_ELF_BASE, + len = EXT_MANIFEST_ELF_SIZE lpsram_mem : org = LP_SRAM_BASE, len = LP_SRAM_SIZE } +_EXT_MAN_ALIGN_ = 16; +EXTERN(ext_man_fw_ver) + PHDRS { vector_memory_lit_phdr PT_LOAD; @@ -134,6 +140,7 @@ PHDRS wnd3_phdr PT_LOAD; static_uuid_entries_phdr PT_NOTE; static_log_entries_phdr PT_NOTE; + metadata_entries_phdr PT_NOTE; lpsram_mem_phdr PT_LOAD; } @@ -559,6 +566,12 @@ SECTIONS *(*.static_log*) } > static_log_entries_seg :static_log_entries_phdr + .fw_metadata (COPY) : ALIGN(1024) + { + KEEP (*(.fw_metadata)) + . = ALIGN(_EXT_MAN_ALIGN_); + } >fw_metadata_seg :metadata_entries_phdr + .lpsram(NOLOAD) : ALIGN(8) { _lpsram_start = ABSOLUTE(.); diff --git a/src/platform/icelake/include/platform/lib/memory.h b/src/platform/icelake/include/platform/lib/memory.h index bce24be9a4c8..d6419a5fa646 100644 --- a/src/platform/icelake/include/platform/lib/memory.h +++ b/src/platform/icelake/include/platform/lib/memory.h @@ -130,6 +130,9 @@ #define LOG_ENTRY_ELF_BASE 0x20000000 #define LOG_ENTRY_ELF_SIZE 0x2000000 +#define EXT_MANIFEST_ELF_BASE (LOG_ENTRY_ELF_BASE + LOG_ENTRY_ELF_SIZE) +#define EXT_MANIFEST_ELF_SIZE 0x2000000 + /* * The HP SRAM Region on Icelake is organised like this :- * +--------------------------------------------------------------------------+ diff --git a/src/platform/imx8/imx8.x.in b/src/platform/imx8/imx8.x.in index b8ae0bd21ec0..609794b02d1f 100644 --- a/src/platform/imx8/imx8.x.in +++ b/src/platform/imx8/imx8.x.in @@ -96,6 +96,9 @@ MEMORY static_log_entries_seg (!ari) : org = LOG_ENTRY_ELF_BASE, len = LOG_ENTRY_ELF_SIZE + fw_metadata_seg (!ari) : + org = EXT_MANIFEST_ELF_BASE, + len = EXT_MANIFEST_ELF_SIZE } PHDRS @@ -127,6 +130,7 @@ PHDRS sof_stack_phdr PT_LOAD; static_uuid_entries_phdr PT_NOTE; static_log_entries_phdr PT_NOTE; + metadata_entries_phdr PT_NOTE; } /* Default entry point: */ @@ -155,6 +159,9 @@ _memmap_cacheattr_bp_allvalid = 0x22222222; _memmap_cacheattr_imx8_wt_allvalid = 0x22212222; PROVIDE(_memmap_cacheattr_reset = _memmap_cacheattr_imx8_wt_allvalid); +_EXT_MAN_ALIGN_ = 16; +EXTERN(ext_man_fw_ver) + SECTIONS { .ResetVector.text : ALIGN(4) @@ -512,4 +519,10 @@ SECTIONS KEEP (*(.fw_ready)) KEEP (*(.fw_ready_metadata)) } >sof_sdram0 :sof_sdram0_phdr + + .fw_metadata (COPY) : ALIGN(1024) + { + KEEP (*(.fw_metadata)) + . = ALIGN(_EXT_MAN_ALIGN_); + } >fw_metadata_seg :metadata_entries_phdr } diff --git a/src/platform/imx8/include/platform/lib/memory.h b/src/platform/imx8/include/platform/lib/memory.h index 2169130766e9..d5dafe805ca1 100644 --- a/src/platform/imx8/include/platform/lib/memory.h +++ b/src/platform/imx8/include/platform/lib/memory.h @@ -51,6 +51,9 @@ #define LOG_ENTRY_ELF_BASE 0x20000000 #define LOG_ENTRY_ELF_SIZE 0x2000000 +#define EXT_MANIFEST_ELF_BASE (LOG_ENTRY_ELF_BASE + LOG_ENTRY_ELF_SIZE) +#define EXT_MANIFEST_ELF_SIZE 0x2000000 + /* * The Heap and Stack on i.MX8 are organised like this :- * diff --git a/src/platform/imx8m/imx8m.x.in b/src/platform/imx8m/imx8m.x.in index 5652d28bb637..3b5ebf40eb4f 100644 --- a/src/platform/imx8m/imx8m.x.in +++ b/src/platform/imx8m/imx8m.x.in @@ -96,6 +96,9 @@ MEMORY static_log_entries_seg (!ari) : org = LOG_ENTRY_ELF_BASE, len = LOG_ENTRY_ELF_SIZE + fw_metadata_seg (!ari) : + org = EXT_MANIFEST_ELF_BASE, + len = EXT_MANIFEST_ELF_SIZE } PHDRS @@ -127,6 +130,7 @@ PHDRS sof_stack_phdr PT_LOAD; static_uuid_entries_phdr PT_NOTE; static_log_entries_phdr PT_NOTE; + metadata_entries_phdr PT_NOTE; } /* Default entry point: */ @@ -155,6 +159,9 @@ _memmap_cacheattr_bp_allvalid = 0x22222222; _memmap_cacheattr_imx8_wt_allvalid = 0x22212222; PROVIDE(_memmap_cacheattr_reset = _memmap_cacheattr_imx8_wt_allvalid); +_EXT_MAN_ALIGN_ = 16; +EXTERN(ext_man_fw_ver) + SECTIONS { .ResetVector.text : ALIGN(4) @@ -512,4 +519,10 @@ SECTIONS KEEP (*(.fw_ready)) KEEP (*(.fw_ready_metadata)) } >sof_sdram0 :sof_sdram0_phdr + + .fw_metadata (COPY) : ALIGN(1024) + { + KEEP (*(.fw_metadata)) + . = ALIGN(_EXT_MAN_ALIGN_); + } >fw_metadata_seg :metadata_entries_phdr } diff --git a/src/platform/imx8m/include/platform/lib/memory.h b/src/platform/imx8m/include/platform/lib/memory.h index d216836b0196..d1535b956246 100644 --- a/src/platform/imx8m/include/platform/lib/memory.h +++ b/src/platform/imx8m/include/platform/lib/memory.h @@ -51,6 +51,9 @@ #define LOG_ENTRY_ELF_BASE 0x20000000 #define LOG_ENTRY_ELF_SIZE 0x2000000 +#define EXT_MANIFEST_ELF_BASE (LOG_ENTRY_ELF_BASE + LOG_ENTRY_ELF_SIZE) +#define EXT_MANIFEST_ELF_SIZE 0x2000000 + /* * The Heap and Stack on i.MX8M are organised like this :- * diff --git a/src/platform/suecreek/include/platform/lib/memory.h b/src/platform/suecreek/include/platform/lib/memory.h index eedd76166b44..00e24dcf8da9 100644 --- a/src/platform/suecreek/include/platform/lib/memory.h +++ b/src/platform/suecreek/include/platform/lib/memory.h @@ -154,6 +154,9 @@ #define LOG_ENTRY_ELF_BASE 0x20000000 #define LOG_ENTRY_ELF_SIZE 0x2000000 +#define EXT_MANIFEST_ELF_BASE (LOG_ENTRY_ELF_BASE + LOG_ENTRY_ELF_SIZE) +#define EXT_MANIFEST_ELF_SIZE 0x2000000 + /* * The HP SRAM Region on Sue Creek is organised like this :- * +--------------------------------------------------------------------------+ diff --git a/src/platform/suecreek/suecreek.x.in b/src/platform/suecreek/suecreek.x.in index 4dc70396f48d..24ca2e9722f5 100644 --- a/src/platform/suecreek/suecreek.x.in +++ b/src/platform/suecreek/suecreek.x.in @@ -93,6 +93,9 @@ MEMORY static_log_entries_seg (!ari) : org = LOG_ENTRY_ELF_BASE, len = LOG_ENTRY_ELF_SIZE + fw_metadata_seg (!ari) : + org = EXT_MANIFEST_ELF_BASE, + len = EXT_MANIFEST_ELF_SIZE } PHDRS @@ -123,6 +126,7 @@ PHDRS sof_fw_phdr PT_LOAD; static_uuid_entries_phdr PT_NOTE; static_log_entries_phdr PT_NOTE; + metadata_entries_phdr PT_NOTE; } /* Default entry point: */ @@ -151,6 +155,9 @@ _memmap_cacheattr_bp_allvalid = 0x22222222; _memmap_cacheattr_sue_creek = 0xf2ff4242; PROVIDE(_memmap_cacheattr_reset = _memmap_cacheattr_sue_creek); +_EXT_MAN_ALIGN_ = 16; +EXTERN(ext_man_fw_ver) + SECTIONS { .ResetVector.text : ALIGN(4) @@ -557,4 +564,10 @@ SECTIONS { *(*.static_log*) } > static_log_entries_seg :static_log_entries_phdr + + .fw_metadata (COPY) : ALIGN(1024) + { + KEEP (*(.fw_metadata)) + . = ALIGN(_EXT_MAN_ALIGN_); + } >fw_metadata_seg :metadata_entries_phdr } diff --git a/src/platform/tigerlake/include/platform/lib/memory.h b/src/platform/tigerlake/include/platform/lib/memory.h index 15234e359aab..dc893d280333 100644 --- a/src/platform/tigerlake/include/platform/lib/memory.h +++ b/src/platform/tigerlake/include/platform/lib/memory.h @@ -130,6 +130,9 @@ #define LOG_ENTRY_ELF_BASE 0x20000000 #define LOG_ENTRY_ELF_SIZE 0x2000000 +#define EXT_MANIFEST_ELF_BASE (LOG_ENTRY_ELF_BASE + LOG_ENTRY_ELF_SIZE) +#define EXT_MANIFEST_ELF_SIZE 0x2000000 + /* * The HP SRAM Region on Tigerlake is organised like this :- * +--------------------------------------------------------------------------+ diff --git a/src/platform/tigerlake/tigerlake.x.in b/src/platform/tigerlake/tigerlake.x.in index 59b1b719786e..449f7004b3e8 100644 --- a/src/platform/tigerlake/tigerlake.x.in +++ b/src/platform/tigerlake/tigerlake.x.in @@ -102,6 +102,9 @@ MEMORY static_log_entries_seg (!ari) : org = LOG_ENTRY_ELF_BASE, len = LOG_ENTRY_ELF_SIZE + fw_metadata_seg (!ari) : + org = EXT_MANIFEST_ELF_BASE, + len = EXT_MANIFEST_ELF_SIZE lpsram_alt_reset_vec_seg : org = LP_SRAM_ALT_RESET_VEC_BASE, len = LP_SRAM_ALT_RESET_VEC_SIZE @@ -147,6 +150,7 @@ PHDRS wnd3_phdr PT_LOAD; static_uuid_entries_phdr PT_NOTE; static_log_entries_phdr PT_NOTE; + metadata_entries_phdr PT_NOTE; lpsram_mem_phdr PT_LOAD; sram_alt_fw_reset_vec_phdr PT_LOAD; sram_alt_fw_reset_vec_int_phdr PT_LOAD; @@ -164,6 +168,8 @@ PROVIDE(_memmap_vecbase_reset = HP_SRAM_VECBASE_RESET); _memmap_cacheattr_wbna_trapnull = 0xFF42FFF2; PROVIDE(_memmap_cacheattr_reset = _memmap_cacheattr_wbna_trapnull); +_EXT_MAN_ALIGN_ = 16; +EXTERN(ext_man_fw_ver) EXTERN(_LpsramHeader) EXTERN(_AltResetVector) @@ -634,6 +640,12 @@ SECTIONS *(*.static_log*) } > static_log_entries_seg :static_log_entries_phdr + .fw_metadata (COPY) : ALIGN(1024) + { + KEEP (*(.fw_metadata)) + . = ALIGN(_EXT_MAN_ALIGN_); + } >fw_metadata_seg :metadata_entries_phdr + .lpsram(NOLOAD) : ALIGN(8) { _lpsram_start = ABSOLUTE(.); From af1d000d4fd3f5c27b60d1989c2b85efd5240b2a Mon Sep 17 00:00:00 2001 From: Karol Trzcinski Date: Mon, 24 Feb 2020 13:30:07 +0100 Subject: [PATCH 2/7] ext_manifest: Define extended manifest structures in firmware Extended manifest is a place to store build time known firmware metadata, for example firmware version or used compiler description. Given information is read on host side before firmware startup. This part of output binary is located as a first structure in binary file. Extended manifest should be skipped in firmware loading routine. Signed-off-by: Karol Trzcinski --- src/include/kernel/ext_manifest.h | 78 +++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 src/include/kernel/ext_manifest.h diff --git a/src/include/kernel/ext_manifest.h b/src/include/kernel/ext_manifest.h new file mode 100644 index 000000000000..f889436311ea --- /dev/null +++ b/src/include/kernel/ext_manifest.h @@ -0,0 +1,78 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2020 Intel Corporation. All rights reserved. + * + * Author: Karol Trzcinski + */ + +/* + * Extended manifest is a place to store metadata about firmware, known during + * compilation time - for example firmware version or used compiler. + * Given information are read on host side before firmware startup. + * This part of output binary is not signed. + * + * To add new content to ext_man, in firmware code define struct which starts + * with ext_man_elem_head followed by usage dependent content and place whole + * struct in "fw_metadata" section. Moreover kernel code should be modified to + * properly read new packet. + * + * Extended manifest is designed to be extensible. In header there is a field + * which describe header length, so after appending some data to header then it + * can be easily skipped by device with older version of this header. + * Unknown ext_man elements should be just skipped by host, + * to be backward compatible. Field `ext_man_elem_header.elem_size` should be + * used in such a situation. + */ + +#ifndef __KERNEL_EXT_MANIFEST_H__ +#define __KERNEL_EXT_MANIFEST_H__ + +#include +#include + +/* In ASCII `XMan` */ +#define EXT_MAN_MAGIC_NUMBER 0x6e614d58 + +/* Build u32 number in format MMmmmppp */ +#define EXT_MAN_BUILD_VERSION(MAJOR, MINOR, PATH) ( \ + ((uint32_t)(MAJOR) << 24) | \ + ((uint32_t)(MINOR) << 12) | \ + (uint32_t)(PATH)) + +/* check extended manifest version consistency */ +#define EXT_MAN_VERSION_INCOMPATIBLE(host_ver, cli_ver) ( \ + ((host_ver) & GENMASK(31, 24)) != \ + ((cli_ver) & GENMASK(31, 24))) + +/* used extended manifest header version */ +#define EXT_MAN_VERSION EXT_MAN_BUILD_VERSION(1, 0, 0) + +/* struct size alignment for ext_man elements */ +#define EXT_MAN_ALIGN 16 + +/* extended manifest header, deleting any field breaks backward compatibility */ +struct ext_man_header { + uint32_t magic; /**< identification number, */ + /**< EXT_MAN_MAGIC_NUMBER */ + uint32_t full_size; /**< [bytes] full size of ext_man, */ + /**< (header + content + padding) */ + uint32_t header_size; /**< [bytes] makes header extensionable, */ + /**< after append new field to ext_man header */ + /**< then backward compatible won't be lost */ + uint32_t header_version; /**< value of EXT_MAN_VERSION */ + /**< not related with following content */ + + /* just after this header should be list of ext_man_elem_* elements */ +} __packed; + +/* Now define extended manifest elements */ + +/* extended manifest element header */ +struct ext_man_elem_header { + uint32_t type; /**< EXT_MAN_ELEM_* */ + uint32_t elem_size; /**< in bytes, including header size */ + + /* just after this header should be type dependent content */ +} __packed; + +#endif /* __KERNEL_EXT_MANIFEST_H__ */ From 6bb6c12a0b2264b03cf76ddfbe22056c5d2e1cc9 Mon Sep 17 00:00:00 2001 From: Karol Trzcinski Date: Thu, 16 Apr 2020 09:18:34 +0200 Subject: [PATCH 3/7] rimage: Mark const args in elf_find_section() Read only pointers should be explicit marked with const keyword to add more restrictions to code and make this function usable with arguments already marked as cost. Signed-off-by: Karol Trzcinski --- rimage/elf.c | 6 +++--- rimage/rimage.h | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/rimage/elf.c b/rimage/elf.c index a00ab7452efb..589fc09a0cf2 100644 --- a/rimage/elf.c +++ b/rimage/elf.c @@ -470,11 +470,11 @@ int elf_validate_modules(struct image *image) return 0; } -int elf_find_section(struct image *image, struct module *module, +int elf_find_section(const struct image *image, const struct module *module, const char *name) { - Elf32_Ehdr *hdr = &module->hdr; - Elf32_Shdr *section, *s; + const Elf32_Ehdr *hdr = &module->hdr; + const Elf32_Shdr *section, *s; char *buffer; size_t count; int ret, i; diff --git a/rimage/rimage.h b/rimage/rimage.h index c65d116b5526..6323707b0d00 100644 --- a/rimage/rimage.h +++ b/rimage/rimage.h @@ -171,8 +171,8 @@ 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); +int elf_find_section(const struct image *image, const struct module *module, + const char *name); int elf_validate_section(struct image *image, struct module *module, Elf32_Shdr *section, int index); From 6248bb9dd62584660a498bbf5331a0680b3fb679 Mon Sep 17 00:00:00 2001 From: Karol Trzcinski Date: Wed, 19 Feb 2020 13:15:12 +0100 Subject: [PATCH 4/7] rimage: Create extended manifest Extended manifest is a place to store metadata about firmware, known during compilation time - for example firmware version or used compiler. Given information are read on host side before firmware startup. This part of output binary is not signed. Signed-off-by: Karol Trzcinski --- rimage/CMakeLists.txt | 1 + rimage/ext_manifest.c | 195 +++++++++++++++++++++++++++++++++ rimage/ext_manifest.h | 34 ++++++ rimage/rimage.c | 7 ++ rimage/rimage.h | 2 + src/arch/xtensa/CMakeLists.txt | 18 ++- 6 files changed, 256 insertions(+), 1 deletion(-) create mode 100644 rimage/ext_manifest.c create mode 100644 rimage/ext_manifest.h diff --git a/rimage/CMakeLists.txt b/rimage/CMakeLists.txt index dc5d3ac794f8..abc32f69c25f 100644 --- a/rimage/CMakeLists.txt +++ b/rimage/CMakeLists.txt @@ -32,6 +32,7 @@ add_executable(rimage hash.c pkcs1_5.c manifest.c + ext_manifest.c elf.c rimage.c ) diff --git a/rimage/ext_manifest.c b/rimage/ext_manifest.c new file mode 100644 index 000000000000..329a25f90e1f --- /dev/null +++ b/rimage/ext_manifest.c @@ -0,0 +1,195 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2020 Intel Corporation. All rights reserved. +// +// Author: Karol Trzcinski + +#include +#include +#include +#include + +#include "kernel/ext_manifest.h" +#include "ext_manifest.h" +#include "ipc/info.h" +#include "rimage.h" + +const struct ext_man_header ext_man_template = { + .magic = EXT_MAN_MAGIC_NUMBER, + .header_version = EXT_MAN_VERSION, + .header_size = sizeof(struct ext_man_header), + .full_size = 0, /* runtime variable */ +}; + +static int ext_man_open_file(struct image *image) +{ + /* open extended manifest outfile for writing */ + sprintf(image->out_ext_man_file, "%s.xman", image->out_file); + unlink(image->out_ext_man_file); + + image->out_ext_man_fd = fopen(image->out_ext_man_file, "wb"); + if (!image->out_ext_man_fd) { + fprintf(stderr, "error: unable to open %s for writing %d\n", + image->out_ext_man_file, errno); + return errno; + } + + return 0; +} + +static struct module *ext_man_get_module(struct image *image) +{ + struct module *module; + int i; + + for (i = image->num_modules > 1 ? 1 : 0; i < image->num_modules; i++) { + module = &image->module[i]; + + if (elf_find_section(image, module, ".fw_metadata") > 0) + return module; + } + + return NULL; +} + +static int ext_man_validate(uint32_t section_size, const void *section_data) +{ + uint8_t *sbuf = (uint8_t *)section_data; + struct ext_man_elem_header head; + uint32_t offset = 0; + + /* copy each head to local struct to omit memory align issues */ + while (offset < section_size) { + memcpy(&head, &sbuf[offset], sizeof(head)); + fprintf(stdout, "Extended manifest found module, type: 0x%04X size: 0x%04X (%4d) offset: 0x%04X\n", + head.type, head.elem_size, head.elem_size, offset); + if (head.elem_size == 0 || head.elem_size % EXT_MAN_ALIGN) { + fprintf(stderr, + "error: invalid extended manifest element size\n"); + return -EINVAL; + } + offset += head.elem_size; + } + + /* sum of packets size != section size */ + if (offset != section_size) { + fprintf(stderr, + "error: fw_metadata section is inconsistent, section size: 0x%04X != 0x%04X sum of packets size\n", + section_size, offset); + return -EINVAL; + } else { + return 0; + } +} + +static int ext_man_build(const struct image *image, const struct module *module, + struct ext_man_header **dst_buff) +{ + struct ext_man_header ext_man; + const Elf32_Shdr *section; + uint8_t *buffer = NULL; + int fw_metadata_index; + size_t offset; + size_t read; + int ret = 0; + + /* find .fw_metadata section */ + fw_metadata_index = elf_find_section(image, module, ".fw_metadata"); + if (fw_metadata_index < 0) { + fprintf(stderr, "error: unable to find .fw_metadata section: %d\n", + fw_metadata_index); + ret = fw_metadata_index; + goto out; + } + section = &module->section[fw_metadata_index]; + + /* fill ext_man, size aligned to 4 to avoid unaligned accesses */ + memcpy(&ext_man, &ext_man_template, sizeof(struct ext_man_header)); + ext_man.full_size = ext_man.header_size; + ext_man.full_size += section->size; + if (ext_man.full_size % 4) { + fprintf(stderr, + "error: extended manifest size must be aligned to 4\n"); + ret = -EINVAL; + goto out; + } + + /* alloc buffer for ext_man */ + buffer = calloc(1, ext_man.full_size); + if (!buffer) { + ret = -ENOMEM; + goto out; + } + + /* fill buffer with ext_man header and section content */ + memcpy(buffer, &ext_man, ext_man.header_size); + offset = ext_man.header_size; + + fseek(module->fd, section->off, SEEK_SET); + read = fread(buffer + offset, 1, section->size, module->fd); + if (read != section->size) { + fprintf(stderr, + "error: can't read fw_metadata section %d\n", + -errno); + free(buffer); + ret = -errno; + } + + *dst_buff = (struct ext_man_header *)buffer; + +out: + return ret; +} + +int ext_man_write(struct image *image) +{ + struct ext_man_header *ext_man = NULL; + struct module *module; + int count; + int ret; + + module = ext_man_get_module(image); + if (!module) { + fprintf(stderr, "error: firmware metadata section not found\n"); + ret = -EINVAL; + goto out; + } + + ret = ext_man_open_file(image); + if (ret) + goto out; + + ret = ext_man_build(image, module, &ext_man); + if (ret) + goto out; + + /* validate metadata section */ + ret = ext_man_validate(ext_man->full_size - ext_man->header_size, + (char *)ext_man + ext_man->header_size); + if (ret) { + ret = -errno; + goto out; + } + + /* write extended metadata to file */ + count = fwrite(ext_man, 1, ext_man->full_size, image->out_ext_man_fd); + + if (count != ext_man->full_size) { + fprintf(stderr, + "error: can't write extended manifest to file %d\n", + -errno); + ret = -errno; + goto out; + } + + fprintf(stdout, "Extended manifest saved to file %s size 0x%04X (%d) bytes\n\n", + image->out_ext_man_file, ext_man->full_size, + ext_man->full_size); + +out: + if (ext_man) + free(ext_man); + if (image->out_ext_man_fd) + fclose(image->out_ext_man_fd); + return ret; +} diff --git a/rimage/ext_manifest.h b/rimage/ext_manifest.h new file mode 100644 index 000000000000..16bebcf87f69 --- /dev/null +++ b/rimage/ext_manifest.h @@ -0,0 +1,34 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2020 Intel Corporation. All rights reserved. + * + * Author: Karol Trzcinski + */ + +/* + * Extended manifest is a place to store metadata about firmware, known during + * compilation time - for example firmware version or used compiler. + * Given information are read on host side before firmware startup. + * This part of output binary is not signed. + * + * To add new content to ext_man, in firmware code define struct which starts + * with ext_man_elem_head followed by usage dependent content and place whole + * struct in "fw_metadata" section. Moreover kernel code should be modified to + * properly read new packet. + * + * Extended manifest designed to be extensible. In header there is a field which + * describe header length, so after appending some data to header then it can be + * easily skipped by device with older version of this header. + * From other side, unknown ext_man elements should be just skipped by host, + * to be backward compatible. Field ext_man_elem_header.elem_size should be + * used in such a situation. + */ + +#ifndef __EXT_MAN_H__ +#define __EXT_MAN_H__ + +#include "rimage.h" + +int ext_man_write(struct image *image); + +#endif /* __EXT_MAN_H__ */ diff --git a/rimage/rimage.c b/rimage/rimage.c index f5997fd1d750..628ca88440d6 100644 --- a/rimage/rimage.c +++ b/rimage/rimage.c @@ -8,6 +8,7 @@ #include #include +#include "ext_manifest.h" #include "rimage.h" #include "file_format.h" #include "manifest.h" @@ -150,7 +151,13 @@ int main(int argc, char *argv[]) ret = image.adsp->write_firmware_meu(&image); else ret = image.adsp->write_firmware(&image); + if (ret) { + fprintf(stderr, "error: unable to write firmware, %d\n", + errno); + goto out; + } + ext_man_write(&image); out: /* close files */ if (image.out_fd) diff --git a/rimage/rimage.h b/rimage/rimage.h index 6323707b0d00..78a9a3134a43 100644 --- a/rimage/rimage.h +++ b/rimage/rimage.h @@ -115,9 +115,11 @@ struct image { void *rom_image; FILE *out_rom_fd; FILE *out_man_fd; + FILE *out_ext_man_fd; FILE *out_unsigned_fd; char out_rom_file[256]; char out_man_file[256]; + char out_ext_man_file[256]; char out_unsigned_file[256]; }; diff --git a/src/arch/xtensa/CMakeLists.txt b/src/arch/xtensa/CMakeLists.txt index e68146a8ea8b..4913d1bf3dde 100644 --- a/src/arch/xtensa/CMakeLists.txt +++ b/src/arch/xtensa/CMakeLists.txt @@ -441,11 +441,27 @@ else() add_custom_target(run_meu DEPENDS run_rimage) endif() +if(CMAKE_HOST_WIN32) + set(GLUE_CMD copy /b sof-${fw_name}.ri.xman + sof-${fw_name}.ri sof-${fw_name}.ri.temp) +else() + set(GLUE_CMD cat sof-${fw_name}.ri.xman sof-${fw_name}.ri > sof-${fw_name}.ri.temp) +endif() + +add_custom_target( + ext_man_glue ALL + COMMAND ${GLUE_CMD} + COMMAND ${CMAKE_COMMAND} -E copy sof-${fw_name}.ri.temp sof-${fw_name}.ri + COMMAND ${CMAKE_COMMAND} -E remove sof-${fw_name}.ri.temp + DEPENDS run_meu + VERBATIM + USES_TERMINAL +) + add_custom_target( bin ALL COMMAND ${CMAKE_COMMAND} -E copy sof-${fw_name}.ri ${PROJECT_BINARY_DIR}/sof-${fw_name}.ri COMMAND ${CMAKE_COMMAND} -E copy sof-${fw_name}.ldc ${PROJECT_BINARY_DIR}/sof-${fw_name}.ldc - DEPENDS run_meu bin_extras + DEPENDS ext_man_glue bin_extras VERBATIM USES_TERMINAL ) From c0b09918807e89509aeea33f9b01b5a7936be864 Mon Sep 17 00:00:00 2001 From: Karol Trzcinski Date: Mon, 24 Feb 2020 14:09:50 +0100 Subject: [PATCH 5/7] ext_manifest: Include firmware version Include such an information in extended manifest, to make it accessible from host side before firmware load and run. Signed-off-by: Karol Trzcinski --- rimage/rimage.c | 8 ++++++- src/include/kernel/ext_manifest.h | 14 ++++++++++++ src/init/CMakeLists.txt | 9 ++++++++ src/init/ext_manifest.c | 36 +++++++++++++++++++++++++++++++ 4 files changed, 66 insertions(+), 1 deletion(-) create mode 100644 src/init/ext_manifest.c diff --git a/rimage/rimage.c b/rimage/rimage.c index 628ca88440d6..0144132fc781 100644 --- a/rimage/rimage.c +++ b/rimage/rimage.c @@ -157,7 +157,13 @@ int main(int argc, char *argv[]) goto out; } - ext_man_write(&image); + ret = ext_man_write(&image); + if (ret) { + fprintf(stderr, "error: unable to write extended manifest, %d\n", + errno); + goto out; + } + out: /* close files */ if (image.out_fd) diff --git a/src/include/kernel/ext_manifest.h b/src/include/kernel/ext_manifest.h index f889436311ea..fb2425ae9312 100644 --- a/src/include/kernel/ext_manifest.h +++ b/src/include/kernel/ext_manifest.h @@ -27,6 +27,7 @@ #ifndef __KERNEL_EXT_MANIFEST_H__ #define __KERNEL_EXT_MANIFEST_H__ +#include #include #include @@ -67,6 +68,11 @@ struct ext_man_header { /* Now define extended manifest elements */ +/* Extended manifest elements identificators */ +enum ext_man_elem_type { + EXT_MAN_ELEM_FW_VERSION = 0, +}; + /* extended manifest element header */ struct ext_man_elem_header { uint32_t type; /**< EXT_MAN_ELEM_* */ @@ -75,4 +81,12 @@ struct ext_man_elem_header { /* just after this header should be type dependent content */ } __packed; +/* FW version */ +struct ext_man_fw_version { + struct ext_man_elem_header hdr; + /* use sof_ipc struct because of code re-use */ + struct sof_ipc_fw_version version; + uint32_t flags; +} __packed; + #endif /* __KERNEL_EXT_MANIFEST_H__ */ diff --git a/src/init/CMakeLists.txt b/src/init/CMakeLists.txt index 17dab5792dd9..31fc44276210 100644 --- a/src/init/CMakeLists.txt +++ b/src/init/CMakeLists.txt @@ -1,3 +1,12 @@ # SPDX-License-Identifier: BSD-3-Clause add_local_sources(sof init.c) + +add_library(ext_manifest STATIC "") + +add_local_sources(ext_manifest + ext_manifest.c) +sof_append_relative_path_definitions(ext_manifest) + +target_link_libraries(ext_manifest sof_options) +target_link_libraries(sof_static_libraries INTERFACE ext_manifest) diff --git a/src/init/ext_manifest.c b/src/init/ext_manifest.c new file mode 100644 index 000000000000..f91424cc7eed --- /dev/null +++ b/src/init/ext_manifest.c @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2020 Intel Corporation. All rights reserved. +// +// Author: Karol Trzcinski +// + +#include +#include +#include +#include +#include +#include +#include + +const struct ext_man_fw_version ext_man_fw_ver + __aligned(EXT_MAN_ALIGN) __section(".fw_metadata") = { + .hdr.type = EXT_MAN_ELEM_FW_VERSION, + .hdr.elem_size = ALIGN_UP(sizeof(struct ext_man_fw_version), + EXT_MAN_ALIGN), + .version = { + .hdr.size = sizeof(struct sof_ipc_fw_version), + .micro = SOF_MICRO, + .minor = SOF_MINOR, + .major = SOF_MAJOR, +#if CONFIG_DEBUG + /* only added in debug for reproducibility in releases */ + .build = SOF_BUILD, + .date = __DATE__, + .time = __TIME__, +#endif + .tag = SOF_TAG, + .abi_version = SOF_ABI_VERSION, + }, + .flags = DEBUG_SET_FW_READY_FLAGS, +}; From e8ddac8ab06bbac7885aa4d3a9c03a0077022f59 Mon Sep 17 00:00:00 2001 From: Karol Trzcinski Date: Mon, 20 Apr 2020 14:14:05 +0200 Subject: [PATCH 6/7] file_simple Signed-off-by: Karol Trzcinski --- rimage/file_simple.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/rimage/file_simple.c b/rimage/file_simple.c index 06ce7732e5f4..46f52b09fbd2 100644 --- a/rimage/file_simple.c +++ b/rimage/file_simple.c @@ -194,10 +194,16 @@ static int simple_write_module(struct image *image, struct module *module) if (!(module->section[i].flags & valid)) continue; + if (section->vaddr == 0) + continue; + /* dont write bss */ if (section->type == SHT_NOBITS) continue; + if (section->type == SHT_NOBITS) + continue; + err = write_block(image, module, section); if (err < 0) { fprintf(stderr, "error: failed to write section #%d\n", From ce0c0a56b717a88917f8b5f08306e6fac63027e9 Mon Sep 17 00:00:00 2001 From: Karol Trzcinski Date: Fri, 17 Apr 2020 12:28:35 +0200 Subject: [PATCH 7/7] fixup! sof: Add fw_metadata section Signed-off-by: Karol Trzcinski --- src/platform/baytrail/baytrail.x.in | 12 ++++++------ src/platform/baytrail/include/platform/lib/memory.h | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/platform/baytrail/baytrail.x.in b/src/platform/baytrail/baytrail.x.in index 7dafc3abf2dc..fd29a93a4b79 100644 --- a/src/platform/baytrail/baytrail.x.in +++ b/src/platform/baytrail/baytrail.x.in @@ -550,15 +550,15 @@ SECTIONS *(*.static_log*) } > static_log_entries_seg :static_log_entries_phdr + .fw_metadata : ALIGN(1024) + { + KEEP (*(.fw_metadata)) + . = ALIGN(_EXT_MAN_ALIGN_); + } >fw_metadata_seg :metadata_entries_phdr + .fw_ready : ALIGN(4) { KEEP (*(.fw_ready)) KEEP (*(.fw_ready_metadata)) } >sof_data :sof_data_phdr - - .fw_metadata (COPY) : ALIGN(1024) - { - KEEP (*(.fw_metadata)) - . = ALIGN(_EXT_MAN_ALIGN_); - } >fw_metadata_seg :metadata_entries_phdr } diff --git a/src/platform/baytrail/include/platform/lib/memory.h b/src/platform/baytrail/include/platform/lib/memory.h index 2b90751f3359..db890f64b975 100644 --- a/src/platform/baytrail/include/platform/lib/memory.h +++ b/src/platform/baytrail/include/platform/lib/memory.h @@ -98,8 +98,8 @@ static inline void *platform_rfree_prepare(void *ptr) #define LOG_ENTRY_ELF_BASE 0x20000000 #define LOG_ENTRY_ELF_SIZE 0x2000000 -#define EXT_MANIFEST_ELF_BASE (LOG_ENTRY_ELF_BASE + LOG_ENTRY_ELF_SIZE) -#define EXT_MANIFEST_ELF_SIZE 0x2000000 +#define EXT_MANIFEST_ELF_BASE 0x22000000 +#define EXT_MANIFEST_ELF_SIZE 0x8000 /* * The Heap and Stack on Baytrail are organised like this :-