GD32W51x 為國內領先的半導體廠商兆易創新最新發布的一款基于Cotrex-M33內核的MCU,Cortex-M33內核基于Armv8-M指令集架構,集成了TrustZone硬體安全機制,支持獨立的存盤訪問空間,提供了系統開發所必需的安全性和靈活性,本文主要基于GD32W51x MCU 介紹TrustZone安全機制的內容及具體工程應用方法,
1.1 Trust Zone介紹
TrustZone的本質是在一顆CPU上隔出兩個世界,即安全和非安全世界,我們可以將系統安全相關的硬體底層驅動代碼、外設模塊、資料放在安全世界中,可以防止非法的訪問和資料篡改,將用戶邏輯層代碼放在非安全區,框圖如下所示,

每個外設模塊、sram、flash都有自己的安全和非安全訪問地址,外設模塊的安全/非安全屬性由TZPCU_TZSPC_SAM_CFG0~CFG3暫存器配置,sram的安全/非安全屬性由TZBMPC0 ~TZBMPC3暫存器配置,flash 的安全/非安全地址范圍由FMC_SECMCFG0暫存器配置,MCU記憶體地址的安全屬性由SAU(安全屬性單元)和IDAU(實施定義屬性單元)來定義,記憶體映射安全屬性與 SAU 配置區域的示例如下圖所示,

IDAU 預定義了一個固定的非安全(NS)和非安全可呼叫(NSC)安全屬性劃分,IDAU 通過硬體實作了不可配置的固定記憶體映射磁區,即上電后默認不可更改的,而 SAU 可以通過軟體更改記憶體的安全屬性,一個記憶體地址的安全性屬性由 IDAU 和 SAU 一起決定,如果一個記憶體地址的安全屬性在這兩者的設定不一樣,則會采用較高安全等級的屬性(S>NSC>NS),SAU共有8個region區域可以配置,上圖由下到上分別為region0 ~ region7 區域可配置的屬性,NSC為安全區域非安全可調區域,為了開發的方便性,兩個世界之間是可以任意切換的,安全世界可以訪問非安全世界的資源,而非安全世界是不能隨意呼叫安全世界的資源,那該如何呢?所以NSC區域的作用就體現了,NSC為安全地址范圍內定義的一段非安全可調區域,如果安全世界的某些資源想讓非安全世界呼叫,則可以將這些資源定義在NSC區域,
簡單理解NSC區域就是從非安全區域訪問安全區域某些資源的唯一 通道,S、NSC、NS三者之間呼叫關系框圖如下所示,

TrustZone安全機制在MCU的軟體開發模型如下圖所示,

兩個工程分別為安全工程和非安全工程,下載時首先將非安全工程的代碼下載到MCU非安全區域,然后再將安全工程的代碼下載到MCU安全區域,因為在TrustZone安全機制使能的情況下,MCU總是先從安全地址啟動,所以如果先下載安全程式時,在安全區跳轉到非安全區,PC指標跳轉的非安全區域flash地址并無代碼,可能會造成程式跑飛,故建議下載時首先下載非安全區的工程代碼,
1.2 TrustZone 具體專案應用
GD32W515x MCU默認TZEN=0,即TrustZone安全機制失能,此時的MCU上電后總是從非安全地址啟動,和不帶TrustZone安全機制的MCU的使用方法并無區別,如果我們要讓TrustZone安全機制使能,首先得讓TZEN=1,查閱GD的官方手冊可知,要使TZEN=1,有2種方法,一是通過操作選項位元組,二是通過操作EFUSE暫存器,個人建議采用第一種選項位元組的方法,因為EFUSE暫存器只可寫入一次,后面無法更改,一旦寫入后,這顆芯片后面只能作為TrustZone安全機制芯片使用,上電從安全地址啟動,不能再回到從非安全地址啟動狀態了,選項位元組的編程方法可以參考GD官方用戶手冊FMC章節,具體的代碼實作如下所示:
void TZEN_Enable(void)
{
fmc_unlock();//首先FMC暫存器解鎖
while(fmc_flag_get(FMC_FLAG_BUSY)==SET);//等待FMC busy flag清0
ob_unlock();//解鎖FMC_CTL暫存器中的選項位元組操作位
while(((FMC_CTL & FMC_CTL_OBWEN)==RESET));//等待OBWEN置1
while(ob_trustzone_enable()!=FMC_READY);//等待TZEN=1操作完成
ob_lock();//選項位元組上鎖
fmc_lock();//FMC暫存器上鎖
}
本文使用的是GD 官方提供的TrustZone安全工程,后面的分析也是基于這個工程,當將上述代碼下載到mcu中即可將TZEN=1,我們首先要確認TZEN是否已置1,將非安全和安全工程的代碼下載到MCU中,通過JTAG進入Debug模式,看PC指標和SP指標的初始位置是否在安全地址,如果為安全地址則TZEN置1成功,
將TZEN置1后,下面通過SAU來配置MCU記憶體地址的安全屬性,因為SAU配置與ARMv8架構下內核操作相關,為了方便開發,GD官方提供了一個組態檔partition_gd32w51x.h,我們將它拉進keil工程,就可以很方便的對SAU進行配置了,配置界面如下圖所示:

TZEN=1時,MCU上電所有的外設、flash、sram都是默認安全的,所以我們需要在安全工程中配置非安全工程中的flash、sram屬性為非安全,通過上圖SAU配置可知,region0被配置為NSC區域,region1被配置為非安全區flash地址范圍,region2被配置為非安全區sram地址范圍,region3被配置為所有外設屬性非安全可尋址范圍,將SAU配置完成后,我們還需要修改安全工程和非安全工程的分散加載檔案,使代碼的加載和運行地址與我們配置的相同,
安全工程的分散加載檔案如下:
LR_IROM1 0x0C000000 0x00040000 { ; load region size_region
ER_IROM1 0x0C000000 0x0003E000 { ; load address = execution address
*.o (RESET, +First)
*(InRootKaTeX parse error: Expected 'EOF', got '}' at position 41: … .ANY (+XO) }? RW_IRAM2 0x3…CMSE) ; check with partition.h
}
}
LR_IROM2 為NSC的地址范圍,0x0C03E000為NSC 記憶體的起始地址,0x00002000為NSC區域的大小,RW_IRAM2 為安全地址sram的記憶體地址范圍,通過查看GD官方手冊存盤器地址映射表可知為sram0,通過SAU配置可知非安全地址的flash空間0x08040000~0x081FFFFF,
起始地址相對于0x08000000地址偏移了40000,故可知安全地址的flash空間范圍大小為64k(0x40000),
非安全工程的分散加載檔案如下所示:
LR_IROM1 0x08040000 0x001C0000 { ; load region size_region
ER_IROM1 0x08040000 0x001C0000 { ; load address = execution address
*.o (RESET, +First)
*(InRoot$$Sections)
.ANY (+RO)
.ANY (+XO)
}
RW_IRAM1 0x20010000 0x00010000 { ; RW data
.ANY (+RW +ZI)
}
}
LR_IROM1 為NS的地址范圍,0x08040000為NS記憶體的起始地址,0x001C0000 為NS區域的大小,RW_IRAM1 為非安全地址sram的記憶體地址范圍,通過查看GD官方手冊存盤器地址映射表可知為sram1,大小為64k,
修改完分散加載檔案后,就要通過fmc暫存器安全標記功能配置flash的安全地址范圍,呼叫函式如下:
void ob_secmark_config(0x00, 0x3F, SECM_INDEX0);//安全地址的起始頁為0x00,結束頁為0x3F,每頁的大小為1k,故安全flash地址的大小為64k
通過TZBMPC0暫存器配置sram1的所有地址空間屬性為非安全,配置代碼如下:
uint16_t block_number = 0U;
/* enable TZPCU clock */
rcu_periph_clock_enable(RCU_TZPCU);
/* SRAM1 is used to nonsecure code, so all blocks of SRAM1 should set to nonsecure */
for(block_number = 0U; block_number <= TZBMPC1_BLOCK_NUMBER; block_number++){
tzpcu_tzbmpc_block_secure_access_mode_config(TZBMPC1, block_number, BLOCK_SECURE_ACCESS_MODE_NSEC);
}
以上TrustZone的基本配置已完成,下面是在安全工程中實作非安全區域的跳轉函式,主要是PC指標指向非安全地址的PC指標起始地址,SP指標指向非安全地址的堆疊頂位置,具體函式分析可參考我上一篇IAP設計思想實作博客,代碼實作如下:
uint32_t nonsecure_stackpointer = (*((uint32_t *)(NONSECURE_START)));
ns_fptr nonsecure_reset_handler = (ns_fptr)(*((uint32_t *)(NONSECURE_START + 4U)));
/* set non-secure vector table location */
SCB_NS->VTOR = NONSECURE_START;
/* set non-secure stack pointer */
__TZ_set_MSP_NS(nonsecure_stackpointer);
/* start non-secure application */
nonsecure_reset_handler();
綜上所述,基于基于GD32W51x MCU Trust Zone安全機制專案應用基本完成,進入Debug后,我們在非安全工程的main函式起始部分打斷點,然后全速運行,可以看到程式可以運行到非安全工程且PC指標和SP指標的位置均指向非安全地址,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/394159.html
標籤:其他
上一篇:docker安裝kali
