I have a microcontroller with lots of flash divided in 1k flash sectors. I want to flash prime numbers to a specific memory region during flashing, then during the first boot a crypto key will be generated, then the prime numbers will be erased and overwritten.
I would prefer to hide the prime numbers inside the m_text and not create a Read/Write memory area for the primes with the linker script.
The Firmware, prime numbers and bootloader are compiled separately, resulting in 3 .hex files that are used to flash.
Say that the FW code to start at 0x2000 and it is 0x2000 long, inside that region i want to allocate a 1024 byte sector that later can be erased and overwritten without bricking the FW.
With the following code i can read, erase and write data to the flash, but i have some questions:
- With the following code will gcc allocate sector at 0x3000? if not, how?
- Do you know any better way to do this?
Code:
...
typedef uint8_t sector[1024];
uint32_t* prime = (sector*)0x3000;
uint32_t data = *prime;
uint32_t dataToWrite = 0xdeadbeef;
flash_init();
flash_sector_erase(0x3000);
flash_block(0x3000,(uint8_t*)&dataToWrite,4);
data = *prime;
...
Linker script
MEMORY {
...
m_text(rx): ORIGIN = 0x00002000, LENGTH = 0x2000
...
}
UPDATE: I have to reserve space at a given flash address with GCC, it seams that other compilers have a solution for this but with GCC i have to use linker scripts.
from here i read this:
The special linker variable dot `.' always contains the current output location counter. Since the . always refers to a location in an output section, it may only appear in an expression within a SECTIONS command. The . symbol may appear anywhere that an ordinary symbol is allowed in an expression.
Assigning a value to . will cause the location counter to be moved. This may be used to create holes in the output section. The location counter may never be moved backwards.
SECTIONS
{
output :
{
file1(.text)
. = . + 1000;
file2(.text)
. += 1000;
file3(.text)
} = 0x1234;
}
In the previous example, the
.text' section from
file1' is located at the beginning of the output sectionoutput'. It is followed by a 1000 byte gap. Then the
.text' section fromfile2' appears, also with a 1000 byte gap following before the
.text' section fromfile3'. The notation
= 0x1234' specifies what data to write in the gaps (see section Output section fill).
My m_text section looks like this:
.text :
{
. = ALIGN(4);
*(.text) /* .text sections (code) */
*(.text*) /* .text* sections (code) */
*(.rodata) /* .rodata sections (constants, strings, etc.) */
*(.rodata*) /* .rodata* sections (constants, strings, etc.) */
*(.glue_7) /* glue arm to thumb code */
*(.glue_7t) /* glue thumb to arm code */
*(.eh_frame)
KEEP (*(.init))
KEEP (*(.fini))
. = ALIGN(4);
} > m_text
So what i can do is to change it to:
.text :
{
. = ALIGN(4);
*(.text) /* .text sections (code) */
. = NEXT(0x400); /* move to start of next 1kb section*/
. += 0x400; /* jump 1k forward */
*(.text*) /* .text* sections (code) */
*(.rodata) /* .rodata sections (constants, strings, etc.) */
*(.rodata*) /* .rodata* sections (constants, strings, etc.) */
*(.glue_7) /* glue arm to thumb code */
*(.glue_7t) /* glue thumb to arm code */
*(.eh_frame)
KEEP (*(.init))
KEEP (*(.fini))
. = ALIGN(4);
} > m_text
Now we have reserved data on the flash, but the address will be dependent on the size of .text with is not ideal, but it might work if we change from direct addressing in the FW code to a section name and then take the size of .text from the FW project and padd to the next 1024 bytes sector to get the address that we will import to the Prime number project.
I am also not too happy about the padding before the sector, in an ideal world we would fill it with "junk code" or random data, i have seen that you can specify a pattern to fill with, but any consistent pattern will shine up as much as 0xffffff or 0x00000 to a reverse engineer ;)
any better ideas?
Not sure what compiler you are using but with GCC you can specify the section with a
section
attribute details here.