我有一个微 Controller ,其中有许多闪存,分为 1k 闪存扇区。 我想在闪存期间将素数闪存到特定的内存区域,然后在第一次启动期间将生成加密 key ,然后素数将被删除并覆盖。
我更愿意将素数隐藏在 m_text 中,而不是使用链接器脚本为素数创建读/写内存区域。
固件、质数和引导加载程序分别编译,生成 3 个用于闪存的 .hex 文件。
假设固件代码从 0x2000 开始,长度为 0x2000,在该区域内我想分配一个 1024 字节的扇区,以后可以在不破坏固件的情况下删除和覆盖该扇区。
使用以下代码,我可以读取、删除数据并将数据写入闪存,但我有一些问题:
- 使用以下代码,gcc 会在 0x3000 处分配扇区吗?如果没有,怎么办?
- 您知道有更好的方法吗?
代码:
...
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;
...
链接描述文件
MEMORY {
...
m_text(rx): ORIGIN = 0x00002000, LENGTH = 0x2000
...
}
更新: 我必须使用 GCC 在给定的闪存地址处保留空间,这似乎其他编译器对此有解决方案,但使用 GCC 我必须使用链接器脚本。
来自here我读到了这个:
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).
我的 m_text 部分如下所示:
.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
所以我能做的就是将其更改为:
.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
现在我们已经在闪存上保留了数据,但地址将取决于.text的大小,这并不理想,但如果我们将固件代码中的直接寻址更改为节名称,然后采用,它可能会起作用FW 项目中的 .text 的大小并填充到下一个 1024 字节扇区,以获得我们将导入到素数项目的地址。
我对扇区之前的填充也不太满意,在理想的情况下,我们会用“垃圾代码”或随机数据填充它,我已经看到你可以指定一个模式来填充,但任何一致的模式对于逆向工程师来说,会亮出 0xffffff 或 0x00000 ;)
还有更好的想法吗?
最佳答案
不确定您使用的是什么编译器,但使用 GCC,您可以使用 section
属性指定该部分 details here .
关于c - 在嵌入式目标上FLASH的m_text内存区域中保留内存空间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30711729/