From c107827bb7456d7ead8af0b1febe932e1b2c4423 Mon Sep 17 00:00:00 2001 From: Torsten Rasmussen Date: Tue, 27 Sep 2022 12:34:36 +0200 Subject: [PATCH] linker: correct linker script _flash_used calculation Linker scripts contains a `.last_section` section that is placed in rom region as NOLOAD for the purpose of retrieve the actual number of bytes contained in the image. See d85efe0b10f1f8ed4b854717f994062a4bbffe26 However, a previous section may cause the location counter to be incremented for alignment purposes. This can result in the size of the image to be 0x10FA but location counter to be 0x1100 because it has been aligned for next section placement. Therefore, two new Kconfig settings are introduced. Those settings request the linker to will write a pattern in `.last_section`. Together with removing NOLOAD and writing a patten to the section then we ensure that data is written after alignment of location counter, and thereby forces the image size to be in sync with the location counter. The default pattern used will be 0xE015 (end of last section). Some systems may fill up the flash completely, or simply write data at the end of the flash, which in both cases can result in overflow. Therefore, the new settings can be disabled. Signed-off-by: Torsten Rasmussen --- Kconfig.zephyr | 26 +++++++++++++++++++ .../arm/aarch32/cortex_a_r/scripts/linker.ld | 9 +++++-- .../arm/aarch32/cortex_m/scripts/linker.ld | 9 +++++-- include/zephyr/arch/arm64/scripts/linker.ld | 9 +++++-- include/zephyr/arch/riscv/common/linker.ld | 9 +++++-- .../riscv-privilege/andes_v5/ae350/linker.ld | 9 +++++-- 6 files changed, 61 insertions(+), 10 deletions(-) diff --git a/Kconfig.zephyr b/Kconfig.zephyr index b623b2892c0b44..289abc2194c614 100644 --- a/Kconfig.zephyr +++ b/Kconfig.zephyr @@ -266,6 +266,32 @@ config LINKER_GENERIC_SECTIONS_PRESENT_AT_BOOT If unsure, say Y. +config LINKER_LAST_SECTION_ID + bool "Last section identifier" + default y + depends on ARM || ARM64 || RISCV + help + If enabled, the last section will contain an identifier. + This ensures that the '_flash_used' linker symbol will always be + correctly calculated, even in cases where the location counter may + have been incremented for alignment purposes but no data is placed + after alignment. + + Note: in cases where the flash is fully used, for example application + specific data is written at the end of the flash area, then writing a + last section identifier may cause rom region overflow. + In such cases this setting should be disabled. + +config LINKER_LAST_SECTION_ID_PATTERN + hex "Last section identifier pattern" + default "0xE015E015" + depends on LINKER_LAST_SECTION_ID + help + Pattern to fill into last section as identifier. + Default pattern is 0xE015 (end of last section), but any pattern can + be used. + The size of the pattern must not exceed 4 bytes. + endmenu # "Linker Sections" endmenu diff --git a/include/zephyr/arch/arm/aarch32/cortex_a_r/scripts/linker.ld b/include/zephyr/arch/arm/aarch32/cortex_a_r/scripts/linker.ld index f56548f3bca54a..2a3d7a2d39ebad 100644 --- a/include/zephyr/arch/arm/aarch32/cortex_a_r/scripts/linker.ld +++ b/include/zephyr/arch/arm/aarch32/cortex_a_r/scripts/linker.ld @@ -385,12 +385,17 @@ GROUP_END(OCM) LINKER_DT_SECTIONS() /* Must be last in romable region */ - SECTION_PROLOGUE(.last_section,(NOLOAD),) + SECTION_PROLOGUE(.last_section,,) { +#ifdef CONFIG_LINKER_LAST_SECTION_ID + /* Fill last section with a word to ensure location counter and actual rom + * region data usage match. */ + LONG(CONFIG_LINKER_LAST_SECTION_ID_PATTERN) +#endif } GROUP_LINK_IN(ROMABLE_REGION) /* To provide the image size as a const expression, * calculate this value here. */ - _flash_used = LOADADDR(.last_section) - __rom_region_start; + _flash_used = LOADADDR(.last_section) + SIZEOF(.last_section) - __rom_region_start; } diff --git a/include/zephyr/arch/arm/aarch32/cortex_m/scripts/linker.ld b/include/zephyr/arch/arm/aarch32/cortex_m/scripts/linker.ld index e6341d587b612d..9620f96f40647f 100644 --- a/include/zephyr/arch/arm/aarch32/cortex_m/scripts/linker.ld +++ b/include/zephyr/arch/arm/aarch32/cortex_m/scripts/linker.ld @@ -440,12 +440,17 @@ GROUP_END(DTCM) LINKER_DT_SECTIONS() /* Must be last in romable region */ -SECTION_PROLOGUE(.last_section,(NOLOAD),) +SECTION_PROLOGUE(.last_section,,) { +#ifdef CONFIG_LINKER_LAST_SECTION_ID + /* Fill last section with a word to ensure location counter and actual rom + * region data usage match. */ + LONG(CONFIG_LINKER_LAST_SECTION_ID_PATTERN) +#endif } GROUP_LINK_IN(ROMABLE_REGION) /* To provide the image size as a const expression, * calculate this value here. */ -_flash_used = LOADADDR(.last_section) - __rom_region_start; +_flash_used = LOADADDR(.last_section) + SIZEOF(.last_section) - __rom_region_start; } diff --git a/include/zephyr/arch/arm64/scripts/linker.ld b/include/zephyr/arch/arm64/scripts/linker.ld index 05ae9464fe625e..1a608150ef5de9 100644 --- a/include/zephyr/arch/arm64/scripts/linker.ld +++ b/include/zephyr/arch/arm64/scripts/linker.ld @@ -322,12 +322,17 @@ SECTIONS /* Must be last in romable region */ - SECTION_PROLOGUE(.last_section,(NOLOAD),) + SECTION_PROLOGUE(.last_section,,) { +#ifdef CONFIG_LINKER_LAST_SECTION_ID + /* Fill last section with a word to ensure location counter and actual rom + * region data usage match. */ + LONG(CONFIG_LINKER_LAST_SECTION_ID_PATTERN) +#endif } GROUP_ROM_LINK_IN(RAMABLE_REGION, ROMABLE_REGION) /* To provide the image size as a const expression, * calculate this value here. */ - _flash_used = LOADADDR(.last_section) - __rom_region_start; + _flash_used = LOADADDR(.last_section) + SIZEOF(.last_section) - __rom_region_start; } diff --git a/include/zephyr/arch/riscv/common/linker.ld b/include/zephyr/arch/riscv/common/linker.ld index e5b623e0506dcf..52f0a2b97e8d50 100644 --- a/include/zephyr/arch/riscv/common/linker.ld +++ b/include/zephyr/arch/riscv/common/linker.ld @@ -399,13 +399,18 @@ GROUP_END(DTCM) */ #ifdef CONFIG_XIP /* Must be last in romable region */ -SECTION_PROLOGUE(.last_section,(NOLOAD),) +SECTION_PROLOGUE(.last_section,,) { +#ifdef CONFIG_LINKER_LAST_SECTION_ID + /* Fill last section with a word to ensure location counter and actual rom + * region data usage match. */ + LONG(CONFIG_LINKER_LAST_SECTION_ID_PATTERN) +#endif } GROUP_LINK_IN(ROMABLE_REGION) /* To provide the image size as a const expression, * calculate this value here. */ -__rom_region_end = LOADADDR(.last_section); +__rom_region_end = LOADADDR(.last_section) + SIZEOF(.last_section); __rom_region_size = __rom_region_end - __rom_region_start; #endif diff --git a/soc/riscv/riscv-privilege/andes_v5/ae350/linker.ld b/soc/riscv/riscv-privilege/andes_v5/ae350/linker.ld index 9245971c6d384b..0db410ca997ec1 100644 --- a/soc/riscv/riscv-privilege/andes_v5/ae350/linker.ld +++ b/soc/riscv/riscv-privilege/andes_v5/ae350/linker.ld @@ -360,13 +360,18 @@ GROUP_END(DTCM) } /* Must be last in romable region */ -SECTION_PROLOGUE(.last_section,(NOLOAD),) +SECTION_PROLOGUE(.last_section,,) { +#ifdef CONFIG_LINKER_LAST_SECTION_ID + /* Fill last section with a word to ensure location counter and actual rom + * region data usage match. */ + LONG(CONFIG_LINKER_LAST_SECTION_ID_PATTERN) +#endif } GROUP_LINK_IN(ROMABLE_REGION) /* To provide the image size as a const expression, * calculate this value here. */ -__rom_region_end = LOADADDR(.last_section); +__rom_region_end = LOADADDR(.last_section) + SIZEOF(.last_section); __rom_region_size = __rom_region_end - __rom_region_start; }