Skip to content

Commit

Permalink
linker: correct linker script _flash_used calculation
Browse files Browse the repository at this point in the history
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 d85efe0

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 <Torsten.Rasmussen@nordicsemi.no>
  • Loading branch information
tejlmand authored and fabiobaltieri committed Oct 3, 2022
1 parent 11e3344 commit c107827
Show file tree
Hide file tree
Showing 6 changed files with 61 additions and 10 deletions.
26 changes: 26 additions & 0 deletions Kconfig.zephyr
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
9 changes: 7 additions & 2 deletions include/zephyr/arch/arm/aarch32/cortex_a_r/scripts/linker.ld
Original file line number Diff line number Diff line change
Expand Up @@ -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;

}
9 changes: 7 additions & 2 deletions include/zephyr/arch/arm/aarch32/cortex_m/scripts/linker.ld
Original file line number Diff line number Diff line change
Expand Up @@ -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;

}
9 changes: 7 additions & 2 deletions include/zephyr/arch/arm64/scripts/linker.ld
Original file line number Diff line number Diff line change
Expand Up @@ -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;

}
9 changes: 7 additions & 2 deletions include/zephyr/arch/riscv/common/linker.ld
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
9 changes: 7 additions & 2 deletions soc/riscv/riscv-privilege/andes_v5/ae350/linker.ld
Original file line number Diff line number Diff line change
Expand Up @@ -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;

}

0 comments on commit c107827

Please sign in to comment.