查看: 2254|回复: 2

KW3x Flash Security和Protection配置

[复制链接]
  • TA的每日心情
    开心
    2024-3-26 15:16
  • 签到天数: 266 天

    [LV.8]以坛为家I

    3298

    主题

    6545

    帖子

    0

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    32012
    最后登录
    2024-4-9
    发表于 2020-9-24 13:50:48 | 显示全部楼层 |阅读模式
    KW3x Flash Security和Protection配置
    一、概述
    KW3x系列芯片提供了Flash Security和Protection机制,限制外部对芯片内存数据的访问和程序运行过程中的修改。
    Flash里定义了专门的一块区域(Flash Configuration Field,后文简称Flash_Config)来存放默认配置,与应用程序一起编译成固件一同烧录进芯片中。芯片里设计了一组相关寄存器(FTFE寄存器),在上电时会读取Flash_Config对应的值,作用于程序运行周期中。
    本文将介绍这种机制并提供配置方法。

    二、Security和Protection机
    1 Security特性
    当使能Security特性后,外部调试接口将无法访问芯片内存模块,但编程接口仍可执行全擦除(Mass Erase)动作。内部应用程序对Flash的读写权限不受影响。

    2 Protection特性
    Protection特性是防止Flash内容被意外改写。我们将Flash分为多个片区,按片区来进行保护。当某个片区受保护后,它的内容将无法被改写,但其他未受保护的片区不受影响。

    3 Flash_Config
    Flash里定义了专门的一块区域Flash_Config来存放安全与保护相关的默认配置。这块区域位于Program Flash(P-Flash)的0x400偏移位置,共16字节,即0x400~0x40F。

    芯片中Flash内存模块(FTFE)定义了相关的安全保护寄存器,上电时自动读取Flash_Config对应字节的值。其中读写寄存器如FTFE->FPROT0-3、FTFE->FEPROT和FTFE->FDPROT等在程序运行过程当中可被改写,但复位后会重新加载Flash_Config的值,改写这类寄存器不会影响Flash_Config的值。FTFE->FSEC、FTFE->FOPT等为只读寄存器。Flash_Config、FSEC和PROT定义如下述表格,其他部分定义请参考芯片用户手册。
    表1: Flash_Config定义
    11.png
    表2:FSEC定义
    12.png
    表3:PROT定义
    13.png
    PROT每1位代表一个片区,每个片区大小=P-Flash大小/32。比如KW36含256K P-Flash,每个片区大小则为256K/32=8K,而KW35每片区大小为512K/32=16K。

    KW3x系列芯片中有些带有FlexNVM。FlexNVM可配置成D-Flash或者EEPROM或者两者的结合。当D-Flash大小为2n时,DPORT[7:0]每1位所代表的片区大小为2n/8;否则每1位所代表的片区大小为某个固定值(根据具体芯片来定),DPROT部分位生效。EPORT [7:0]每1位所代表片区大小为EEPROM大小/8。

    比如KW36含256KFlexNVM,当配置成128K D-Flash和128K EEPROM时,DPROT每位表示片区大小为128K/8=16K,EPORT每位表示片区大小为128K/8=16K;当配置成192KD-Flash和64K EEPROM时,DPORT每位表示片区大小固定为32K,DPORT[5:0]共6位生效,共32K*6=192K,DPORT[7:6]无效置1,而EPORT [7:0]每位表示64K/8=8K。

    三、Security配
    1 初始使能
    在恩智浦官网http://mcuxpresso.nxp.com/下载KW36最新SDK,准备1块FRDM-KW36开发板,基于SDK\boards\frdmkw36\driver_examples\flash\pflash\iar工程来进行配置演示。默认代码演示P-Flash为非安全模式下的扇区擦写操作。
    在工程startup_MKW36Z4.s中,有以下默认定义:
    __FlashConfig
        DCD 0xFFFFFFFF
        DCD 0xFFFFFFFF
        DCD 0xFFFFFFFF
        DCD 0xFFFFFFFE
    __FlashConfig_End

    表示64位预设BackdoorKey为0xFFFFFFFFFFFFFFFF(无效值);PROT [31:0]为0xFFFFFFFF,P-Flash所有片区均未设保护;FSEC为0xFE,表示非安全、使能原厂访问接口、使能全擦除接口、禁止Backdoor Key。FOPT、DPROT、EPORT均为0xFF。调试信息如下图:
    14.png
    若要设置安全模式,其实设置保持不变,需将SEC置成非0b10的值,如0b00,即FSEC=0xFC。在startup_MKW36Z4.s修改如下:

    __FlashConfig
        DCD 0xFFFFFFFF
        DCD 0xFFFFFFFF
        DCD 0xFFFFFFFF
        DCD 0xFFFFFFFC
    __FlashConfig_End

    IAR工程下在默认配置下会阻止使能安全模式,虽然代码修改且编译成功,但最终下载到芯片中依然会保持非安全设置。要使之生效,需要在工程里做以下修改:

    1)打开工程Options >Debugger > Download,勾选Overridedefault .board file,点击Edit…按钮:
    15.png
    使能改写.board文件选项
    2)在跳出来的Flash LoaderOverview窗口,选择CODE:0-0x3ffff这一栏,点击Edit…按钮:
    16.png
    Flash LoaderOverview窗口
    3)在新的Flash Loader Configuration窗口,在Extra parameters添加--enable_config_write,点击OK按钮:
    8.png
    Flash LoaderConfiguration窗口

    4)此时Flash Loader Overview窗口CODE: 0x0-0x3ffff会显示设置的ExtraParameters,点击OK按钮:
    9.png
    Flash LoaderOverview新窗口


    5)此时会弹出保存新.board文件的窗口,命名保存;
    保存新.board文件


    6)回到Options窗口,点击OK即可。
    18.png
    新.board文件设置生效


    此时下载再运行,调试信息提示芯片已置安全模式,如下图:
    19.png
    调试信息-Security使能


    2 Security解锁
    2.1 全擦除解锁
    当Security使能后,外部调试接口访问芯片通道受限。若想恢复正常访问,需先对芯片Flash执行全擦除进行解锁。若使用IAR IDE,可选择菜单Project > Download > Erase memory执行全擦除。当然前提条件是FSEC中的MMEN为使能状态,若MMEN禁止,则无法执行全擦除操作。

    2.2 Backdoor Key解锁
    当Security使能后,也可以用Backdoor Key来进行解锁。前提条件是FSEC的KEYEN为使能状态,并且Flash_Config中的0x400~0x407已设置有效BackdoorKey。设置KEYEN为0b10,BackdoorKey为0x0506070801020304,在startup_MKW36Z4.s修改如下:

    __FlashConfig
        DCD 0x01020304
        DCD 0x05060708
        DCD 0xFFFFFFFF
        DCD 0xFFFFFFBC
    __FlashConfig_End

    解锁Backdoor Key一般可以通过串口、无线等方式输入,输入后和预设Backdoor Key进行比对,比对成功则解锁,比对失败则保持锁住状态。一旦比对失败,只能等复位后再次比对,一个上电周期只有一次比对解锁机会。

    为方便演示,在代码中定义与预设Backdoor Key相同的解锁BackdoorKey。通过FLASH_GetSecurityState()得知芯片状态是kFLASH_SecurityStateBackdoorEnabled时,调用FLASH_SecurityBypass()传入解锁BackdoorKey进行比对解锁,执行后再用FLASH_GetSecurityState()获取芯片状态。若状态为kFLASH_SecurityStateNotSecure则表示已解锁。
    1. const uint8_t backdoorkey[8] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
    2. static flash_config_t s_flashDriver;
    3. flash_security_state_t securityStatus = kFLASH_SecurityStateNotSecure;
    4. memset(&s_flashDriver, 0, sizeof(flash_config_t));
    5. FLASH_Init(&s_flashDriver);
    6. FLASH_GetSecurityState(&s_flashDriver, &securityStatus);
    7. if (kFLASH_SecurityStateNotSecure == securityStatus)
    8. {
    9.         …
    10. }
    11. else if (kFLASH_SecurityStateBackdoorEnabled == securityStatus)
    12. {
    13.         FLASH_SecurityBypass(&s_flashDriver, backdoorkey);
    14.         FLASH_GetSecurityState(&s_flashDriver, &securityStatus);
    15.         PRINTF("Input backdoor key, check security status...");
    16.      switch (securityStatus)
    17.      {
    18.         case kFLASH_SecurityStateNotSecure:
    19.             PRINTF("\r\nFlash is UNSECURE!\r\n");
    20.             break;
    21.         case kFLASH_SecurityStateBackdoorEnabled:
    22.             PRINTF("\r\nFlash is SECURE, BACKDOOR is ENABLED! \r\n ");
    23.             break;
    24.         case kFLASH_SecurityStateBackdoorDisabled:
    25.             PRINTF("\r\nFlash is SECURE, BACKDOOR is DISABLED! \r\n ");
    26.             break;
    27.         default:
    28.             break;
    29.     }
    30. }
    复制代码
    20.png
    调试信息-Backdoor Key解锁


    用BackdoorKey解锁后,FTFE->FSEC的SEC会强制置为0b10,所以FLASH_GetSecurityState()获取到的状态为kFLASH_SecurityStateNotSecure。但是需要注意的是用BackdoorKey解锁只是临时作用在此次上电周期,并不会改变Flash_Config的SEC值,一旦复位,FTFE->FSEC会重新加载Flash_Config的SEC值。解锁后,外部调试接口恢复对芯片的访问权限,但需要注意此时不能复位芯片,否则芯片会恢复到安全模式。

    2.3 擦写解锁
    若芯片已设为安全模式,但Flash_Config所在片区未设保护,程序运行当中自身仍可用FLASH_Erase()和FLASH_Program()对所在扇区擦除改写,将其置回非安全模式。但由于所在扇区为P-Flash第1个扇区,如果运行程序起始为第1扇区,自身尝试擦写这个扇区会引发错误。所以此方法需将运行程序起始执行在后续扇区或者其他内存比如RAM里才可以实现。改写完Flash_Config后,FTFE->FSEC的值仍为原来的值即安全模式,只有复位后FTFE->FSEC重新加载Flash_Config的新设置值,解锁才能生效。

    在修改时由于需要将整个扇区先擦除,所以需先将该扇区内容读出保存,改完后同时将整个扇区的数据写回。必要时在操作Flash前后禁止/使能全局中断。另外芯片初始为非安全模式时,也可用这种方法在程序运行中置为安全模式。

    读者可用SDK\boards\frdmkw36\wireless_examples\framework\bootloader_otap和SDK\boards\frdmkw36\wireless_examples\bluetooth\otac_att一起配合做这个测试,bootloader_otap起始执行地址为Flash 0x0偏移地址,而otac_att起始地址为Flash 0x2000偏移地址,所以otac_att在运行时尝试擦写Flash_Config所在扇区时是可行的。在otap_client_att.c中增加以下测试代码:
    1. #include "fsl_flash.h"
    2. void BleApp_Init(void)
    3. {
    4.         …
    5.         PRINTF("FSEC: 0x%02X\r\n", FTFE->FSEC);
    6.         static flash_config_t s_flashDriver;
    7.             memset(&s_flashDriver, 0, sizeof(flash_config_t));
    8.             FLASH_Init(&s_flashDriver);
    9.    
    10.             uint32_t value[512] = {0};
    11.             for (uint32_t i = 0; i < 512; i++)
    12.             {
    13.                        value[i] = *(volatile uint32_t *)(i * 4); //save current contents
    14.         }

    15.         value[259] = 0xFFFFFFFC; //set FSEC=0xFC to enable security
    16.         OSA_InterruptDisable();
    17.         FLASH_Erase(&s_flashDriver, 0, 2048, kFLASH_ApiEraseKey);
    18.         OSA_InterruptEnable();
    19.         FLASH_Program(&s_flashDriver, 0, value, 512);
    20. }
    复制代码
    需要注意在freertos工程里进行Flash擦除前一定要用OSA_InterruptDisable()关闭全局中断,否则会触发异常导致芯片复位;而在bm工程里是非必要的。
    四、Protection配置
    1 初始使能
    Flash_Config的PROT[31:0]用于配置P-Flash不同片区的Protection选项。KW36含256K P-Flash,每1位代表8K,默认为1,表示未设保护。在SDK\boards\frdmkw36\driver_examples\flash\pflash原有代码中,在未设安全模式下会对最后一个扇区(0x3f800~0x40000,2K字节)进行擦写操作。我们尝试将最后一个片区进行保护(0x3e000~0x40000,8K字节,共4个扇区),即PROT[31]设为0。在startup_MKW36Z4.s修改如下:

    __FlashConfig
        DCD 0xFFFFFFFF
        DCD 0xFFFFFFFF
        DCD 0x7FFFFFFF
        DCD 0xFFFFFFFE
    __FlashConfig_End

    编译烧录运行后,在尝试对受保护扇区进行FLASH_Erase()时返回了kStatus_FLASH_ProtectionViolation,也就是所操作扇区已设保护,禁止擦写操作。
    21.png
    调试信息-操作受保护扇区

    2 修改配置
    在初始使能Protection后,还可以在程序运行当中进行修改。但只能将未保护片区设成保护,而不能将已受保护的片区取消保护,且程序中所修改配置只在本上电周期有效。复位后,FTFE->FPROTn仍将重新加载Flash_Config里PROT里的值。

    基于原先的配置,PROT [31]为0,其他位为1。我们尝试用FLASH_PflashSetProtection()将PROT [30]所代表片区升级成保护,再将PROT [31]片区降级成未受保护,用FLASH_PflashGetProtection()分别获取操作前后状态。
    22.png
    调试信息-修改Protection配置

    上图显示在第一次Protection升级时FTFE->FPROTn时设置生效,而第二次Protection降级返回kStatus_FLASH_CommandFailure错误,导致设置失败。
    四、Protection配
    配置Flash Security和Protection时需谨慎,否则可能造成不可撤销的后果。

    当使能Security时,若同时禁止全擦除解锁位,在程序内部无预留擦写解锁和Backdoor Key解锁的情况下,外部调试接口访问芯片资源的权限会被永久禁止(也就无法再更新固件)。擦写解锁的使用场景受限,而Backdoor Key解锁只能在本次上电周期,外部调试接口访问时必须保证不复位芯片。

    当使能Security时,若同时禁止全擦除解锁位,Flash_Config初始设置保护的片区将永久受保护,不能被擦写。

    当使能Security时,由于存在程序擦写解锁的可能性,若想Security设置永久保持,可对Flash_Config所在片区进行Protection设置并禁止全擦除。

    其他更多信息还可参考官网MKW36/35/34 Reference Manual和应用笔记AN 4507 Using the Kinetis Security and Flash Protection Features.

    文章出处:恩智浦MCU加油站

    签到签到
    回复

    使用道具 举报

  • TA的每日心情
    慵懒
    2024-1-21 12:18
  • 签到天数: 1081 天

    [LV.10]以坛为家III

    16

    主题

    1903

    帖子

    0

    金牌会员

    Rank: 6Rank: 6

    积分
    5035
    最后登录
    2024-4-23
    发表于 2020-9-24 13:55:21 | 显示全部楼层
    感谢分享!
    回复

    使用道具 举报

  • TA的每日心情
    开心
    2021-11-4 13:30
  • 签到天数: 47 天

    [LV.5]常住居民I

    3

    主题

    167

    帖子

    0

    版主

    Rank: 7Rank: 7Rank: 7

    积分
    379
    最后登录
    2024-4-16
    发表于 2020-9-28 15:41:11 | 显示全部楼层
    支持一下
    该会员没有填写今日想说内容.
    回复

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /4 下一条

    Archiver|手机版|小黑屋|恩智浦技术社区

    GMT+8, 2024-4-23 21:03 , Processed in 0.137682 second(s), 24 queries , MemCache On.

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.

    快速回复 返回顶部 返回列表