This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] 编译器/TM4C1294NCPDT:闪存存储器读取保护

Guru**** 2330830 points
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/577123/compiler-tm4c1294ncpdt-flash-memory-read-protection

器件型号:TM4C1294NCPDT

工具/软件:TI C/C++编译器

大家好、

我想保护我的二进制文件不被未经授权的重复使用、因此我想锁定器件的闪存。 我很清楚、只能保护.text 段(它是 可执行文件)、但我的.cmd 文件如下所示:

.intvecs:> 0x00000000
.text:> FLASH
.const:> FLASH
.cinit:>闪存
.pinit:> FLASH
init_array:> FLASH


我认为、.text 段应该停留在末尾、并且应该强制链接器与可锁定的页面边界对齐。 有人能建议我、这样做的正确方式/最佳实践是什么?

此致、
Norbert
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好 Norbert

    保护代码的正确方法是使用闪存保护寄存器。 请注意、在执行读取保护时、必须确保不会像从 CPU 创建的那样创建字面量池表、这将导致读取闪存、从而导致总线故障。 这可以通过更改优化设置并避免在 CCS 工程设置中使用字面量池设置来处理。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    添加了一些更多详细信息。 您可以将闪存分区到链接命令文件中的可读部分和仅执行部分。 这里是我做的一个示例。

    /*系统内存映射*/
    
    内存
    {
    /*存储在内部闪存中并从内部闪存执行的应用程序*/
    闪存(RX):origin = APP_BASE,length = 0x00010000
    FLASH2 (X):origin = 0x00010000,length = 0x00030000
    /*应用程序使用内部 RAM 进行数据*/
    SRAM (rwx):origin = 0x20000000,length = 0x00008000
    }//
    
    
    
    段中的段分配
    {
    .intvecs:> app_base
    libtext:
    {
    driverlib.lib<*。obj>(.text)
    rtsv7M4_T_le_v4SPD16_eabi.lib<*。obj>(.text)
    } >闪存
    .text:> FLASH2
    .const:> FLASH
    .cinit:>闪存
    .pinit:> FLASH
    init_array:> FLASH
    
    .vtable:> RAM_base
    .data :> SRAM
    .bss:> SRAM
    .sysmem:> SRAM
    .stack:> SRAM
    }
    
    __stack_top =__stack + 256;
    

    在第6行和第7行中、我将闪存分成了两个存储器块。 我留下的可读部分命名为 FLASH、而我给出的只执行部分命名为 FLASH2。 在 SECTIONS 指令中、我将.text 段更改为指向 FLASH2 (第22行)。 现在、正如 Amit 提到的、您必须编译代码、使其不会在.text 段中嵌入常量。 如果您不想使用该选项重新编译库、则库中的.text 段必须链接到可读闪存中。 我的代码引用了两个库。 我将这两个库中的.text 段重定向到第17行到第21行中的闪存中。

    通过如下所示更改项目设置、禁止在运行时代码中嵌入常量:

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    [报价用户="Norbert Toth"]我想保护我的二进制文件不被未经授权的重复使用...

    好的、很多人都有这种愿望、但你(真的)能建造一座足够高、足够深的墙/护城墙吗?   (大约) 10美元的 MCU?

    如果您的愿望是"真实的"、为什么不要求该供应商(或任何类似的其他供应商)"书面"语言"保证"这些"保护您的代码"措施的成功?

    过去曾在另一个半"巨人"工作过-我可以告诉你、那些想要你的代码的人应该有你的代码-即使-特别是如果-你遵循这些(要求严格)的指示。

    那些寻求您的代码的人可能比您的设备要好得多-拥有卓越的资源-并且(非常)熟练。  (且价格非常合理)

    请注意、此供应商并不是唯一一家针对长期存在的 MCU 漏洞提出(过于乐观)案例的供应商...   "带辅助"是否足以治疗"划伤"动脉?

    再次-要求您的"书面"安全保证-这说明了真实的故事...

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好!

    感谢您的回复。 您能帮我、如何从源获取 FLASH2的地址? 我不想对代码进行硬代码寄存器访问或存储器地址、但我知道、我可以通过某种方式将段的起始地址构建到源代码中。

    此致、
    Norbert
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    存储器区域 FLASH 和 FLASH2的区别在于、对于定义为 FLASH2的范围、您将对 Flash 存储器保护寄存器位进行编程、使该存储器只执行。 由于在代码开发完成之前、您不知道需要多少只执行闪存以及需要多少可读闪存以下链接您的文件的另一种方式:

    #define APP_BASE 0x00000000
    #define RAM_BASE 0x20000000
    
    //系统存储器映射*/
    
    存储
    器{
    /*存储在内部闪存中并从内部闪存执行的应用程序*/
    闪存(RX):origin = APP_BASE,length = 0x00040000
    /*应用程序使用内部 RAM 进行数据*/
    SRAM (rwx):origin = 0x20000000,length = 0x00008000
    }//
    
    
    
    段中的段分配
    {
    .intvecs:> app_base
    libtext:
    {
    driverlib.lib<*。obj>(.text)
    rtsv7M4_T_le_v4SPD16_eabi.lib<*。obj>(.text)
    } >闪存
    .text:>闪存 palign = 2048,fill = 0xffffffff
    .const:> FLASH
    .cinit:>闪存
    .pinit:> FLASH
    init_array:> FLASH
    
    .vtable:> RAM_base
    .data :> SRAM
    .bss:> SRAM
    .sysmem:> SRAM
    .stack:> SRAM
    }
    
    __stack_top =__stack + 256;
    

    在此链接命令文件中、所有1MB 闪存均由闪存表示。 请注意、在第24行中、我添加了" palign "和" fill "这两个关键字。 由于闪存的只执行部分必须包含 在一定数量的2KB 段中、我使用"palign = 2048"将此输出段与2KB 边界对齐、并将 PAD 与2KB 边界的末尾对齐。 "fill"关键字表示使用0xffffffff 作为填充的填充值。 填充功能可防止链接器将可能需要读取访问的任何其他代码打包到我的只执行代码的末尾。

    代码开发完成后、我可以查看由链接器生成的.map 文件、并查看要转换为只执行的闪存的哪个2KB 部分。 如果我想将只执行段放置在特定的位置、例如闪存的顶部、那么我可以像以前那样将闪存存储器指令分解为闪存和 FLASH2、但现在我知道所需的确切大小。