Reserve memory space in m_text memory region of FLASH on embedded target

4.7k views Asked by At

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:

  1. With the following code will gcc allocate sector at 0x3000? if not, how?
  2. 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 fromfile1' is located at the beginning of the output section output'. It is followed by a 1000 byte gap. Then the.text' section from file2' appears, also with a 1000 byte gap following before the.text' section from file3'. 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?

2

There are 2 answers

0
doron On

Not sure what compiler you are using but with GCC you can specify the section with a section attribute details here.

5
too honest for this site On

You could locate the array into the m_text section using gcc __attribute__((section("m_text") )).

A memory region is not a section. So you need to add this section to the linker script, placing it into this memory region (not sure, if both use different namespaces, but it would be better style to have different names for region and section). If that is not loaded with the programm, it has to be NOLOAD (much like .bss).

Or you only use C constucts and no linker facilities at all. However, this will prevent the data to load with the program, so it only works if you intend to program that area seperately from the program.