安全引導功能及ATF的啟動過程(四)

安全引導功能及ATF的啟動過程(四)

ATF中bl31的啟動

在bl2中觸發安全監控模式調用后會跳轉到bl31中執行,bl31最主要的作用是建立EL3運行態的軟件配置,在該階段會完成各種類型的安全監控模式調用ID的注冊和對應的ARM核狀態的切換,bl31運行在EL3。bl31的執行流程如圖所示。

在這里插入圖片描述

bl31_entrypoint函數

通過bl31.ld.S文件可知,bl31的入口函數是bl31_entrypoint。該函數的內容如下:

/root/optee/trusted-firmware-a/bl31/bl31.ld.S

OUTPUT_FORMAT(PLATFORM_LINKER_FORMAT)
OUTPUT_ARCH(PLATFORM_LINKER_ARCH)
ENTRY(bl31_entrypoint)

/root/optee/trusted-firmware-a/bl31/aarch64/bl31_entrypoint.S

func bl31_entrypoint/* ---------------------------------------------------------------* Stash the previous bootloader arguments x0 - x3 for later use.* ---------------------------------------------------------------*///保存x0/x1/x2/x3寄存器中的值 mov     x20, x0mov     x21, x1mov     x22, x2mov     x23, x3#if !RESET_TO_BL31//根據是否啟用了RESET_TO_BL31參數為el3_entrypoint_common傳入不同參數// RESET_TO_BL31=y 系統復位后直接進入 BL31// RESET_TO_BL31=n BL31 是由前一級(如 BL2)加載并跳轉進來的/* ---------------------------------------------------------------------* For !RESET_TO_BL31 systems, only the primary CPU ever reaches* bl31_entrypoint() during the cold boot flow, so the cold/warm boot* and primary/secondary CPU logic should not be executed in this case.** Also, assume that the previous bootloader has already initialised the* SCTLR_EL3, including the endianness, and has initialised the memory.* ---------------------------------------------------------------------*///  不進行初始化類操作el3_entrypoint_common                                   \_init_sctlr=0                                   \_warm_boot_mailbox=0                            \_secondary_cold_boot=0                          \_init_memory=0                                  \_init_c_runtime=1                               \//設置 EL3 異常向量               _exception_vectors=runtime_exceptions           \_pie_fixup_size=BL31_LIMIT - BL31_BASE
#else/* ---------------------------------------------------------------------* For RESET_TO_BL31 systems which have a programmable reset address,* bl31_entrypoint() is executed only on the cold boot path so we can* skip the warm boot mailbox mechanism.* ---------------------------------------------------------------------*///進行初始化類操作el3_entrypoint_common                                   \_init_sctlr=1                                   \_warm_boot_mailbox=!PROGRAMMABLE_RESET_ADDRESS  \_secondary_cold_boot=!COLD_BOOT_SINGLE_CPU      \_init_memory=1                                  \_init_c_runtime=1                               \_exception_vectors=runtime_exceptions           \_pie_fixup_size=BL31_LIMIT - BL31_BASE
#endif /* RESET_TO_BL31 *//* --------------------------------------------------------------------* Perform BL31 setup* --------------------------------------------------------------------*///恢復x0/x1/x2/x3數據,配置bl31mov     x0, x20mov     x1, x21mov     x2, x22mov     x3, x23bl      bl31_setup#if ENABLE_PAUTH/* --------------------------------------------------------------------* Program APIAKey_EL1 and enable pointer authentication* --------------------------------------------------------------------*///執行指針認證初始化 bl      pauth_init_enable_el3
#endif /* ENABLE_PAUTH *//* --------------------------------------------------------------------* Jump to main function* --------------------------------------------------------------------*/// 執行bl31_mainbl      bl31_main   /* --------------------------------------------------------------------* Clean the .data & .bss sections to main memory. This ensures* that any global data which was initialised by the primary CPU* is visible to secondary CPUs before they enable their data* caches and participate in coherency.* --------------------------------------------------------------------*///清理數據段和 未初始化的全局變量和靜態變量段adrp    x0, __DATA_START__add     x0, x0, :lo12:__DATA_START__adrp    x1, __DATA_END__add     x1, x1, :lo12:__DATA_END__sub     x1, x1, x0bl      clean_dcache_rangeadrp    x0, __BSS_START__add     x0, x0, :lo12:__BSS_START__adrp    x1, __BSS_END__add     x1, x1, :lo12:__BSS_END__sub     x1, x1, x0bl      clean_dcache_rangeb       el3_exit
endfunc bl31_entrypoint         

bl31_main函數

該函數主要完成必要的初始化操作,注冊EL3中各種安全監控模式調用的處理函數,以便在啟動完成后響應在REE側和TEE側產生的安全監控模式調用。該函數的內容如下:

/root/optee/trusted-firmware-a/bl31/bl31_main.c

//BL31 負責為啟動 CPU 設置運行時服務,然后將控制權移交給引導加載程序或操作系統。
//該函數調用 runtime_svc_init(),該函數會初始化所有已注冊的運行時服務。
//這些運行時服務會為處理器核心切換到下一個異常級別建立足夠的上下文環境。
//當該函數返回后,核心將通過 ERET 指令切換到已設定的異常級別。
void bl31_main(void)
{/* Init registers that never change for the lifetime of TF-A *///初始化在 TF-A 生命周期內永不更改的寄存器。cm_manage_extensions_el3(plat_my_core_pos());/* Init per-world context registers for non-secure world */// 設置那些會在 安全世界(Secure)與非安全世界之間切換時需要恢復的寄存器manage_extensions_nonsecure_per_world();NOTICE("BL31: %s\n", build_version_string);NOTICE("BL31: %s\n", build_message);#if FEATURE_DETECTION/* Detect if features enabled during compilation are supported by PE. *///檢測在編譯期間啟用的功能是否被處理器單元(PE)所支持detect_arch_features();
#endif /* FEATURE_DETECTION */#if ENABLE_RUNTIME_INSTRUMENTATION//運行時性能檢測PMF_CAPTURE_TIMESTAMP(bl_svc, BL31_ENTRY, PMF_CACHE_MAINT);
#endif#ifdef SUPPORT_UNKNOWN_MPID//處理未知的 MPID(多核標識)if (unsupported_mpid_flag == 0) {NOTICE("Unsupported MPID detected!\n");}
#endif/* Perform platform setup in BL31 *///平臺相關設置bl31_platform_setup();#if USE_GIC_DRIVER/** Initialize the GIC driver as well as per-cpu and global interfaces.* Platform has had an opportunity to initialise specifics.*///初始化 GIC unsigned int core_pos = plat_my_core_pos();gic_init(core_pos);   //初始化 GIC 分發器gic_pcpu_init(core_pos);   //初始化當前 CPU 的中斷接口gic_cpuif_enable(core_pos);     //使能當前 CPU 的中斷接收
#endif /* USE_GIC_DRIVER *//* Initialise helper libraries *///初始化輔助庫bl31_lib_init();#if EL3_EXCEPTION_HANDLING//初始化異常處理框架(EXCEPTION_HANDLING_FRAMEWORK) INFO("BL31: Initialising Exception Handling Framework\n");ehf_init();
#endif/* Initialize the runtime services e.g. psci. *///初始化運行時服務,如PSCI// PSCI(Power State Coordination Interface):負責 CPU 啟動、關閉、掛起等// SPD(Secure Payload Dispatcher):調度 OP-TEE(BL32)// SPMC(Secure Partition Manager Component):用于 FF-A 架構// RMM(Realm Management Monitor):用于 CCA(Confidential Compute Architecture)INFO("BL31: Initializing runtime services\n");runtime_svc_init();/** All the cold boot actions on the primary cpu are done. We now need to* decide which is the next image and how to execute it.* If the SPD runtime service is present, it would want to pass control* to BL32 first in S-EL1. In that case, SPD would have registered a* function to initialize bl32 where it takes responsibility of entering* S-EL1 and returning control back to bl31_main. Similarly, if RME is* enabled and a function is registered to initialize RMM, control is* transferred to RMM in R-EL2. After RMM initialization, control is* returned back to bl31_main. Once this is done we can prepare entry* into BL33 as normal.*///所有在主 CPU 上的冷啟動操作已經完成。//我們現在需要決定下一個要運行的鏡像以及如何執行它。//如果存在 SPD(Secure Payload Dispatcher)運行時服務,//它會希望先將控制權交給運行在 S-EL1 的 BL32。//在這種情況下,SPD 會注冊一個用于初始化 BL32 的函數,//該函數負責進入 S-EL1 并在完成后將控制權交還給 bl31_main。//同樣地,如果啟用了 RME(Realm Management Extension)//并注冊了用于初始化 RMM(Realm Management Monitor)的函數,//則會將控制權轉移到運行在 R-EL2 的 RMM。RMM 初始化完成后,//控制權也會返回到 bl31_main。完成這些步驟后,我們就可以像往常一樣準備進入 BL33。// S-EL安全世界 中運行的異常等級。// R-EL普通世界 中運行的異常等級。/** If SPD had registered an init hook, invoke it.*/if (bl32_init != NULL) {INFO("BL31: Initializing BL32\n");console_flush();int32_t rc = (*bl32_init)();if (rc == 0) {WARN("BL31: BL32 initialization failed\n");}}/** If RME is enabled and init hook is registered, initialize RMM* in R-EL2.*/
#if ENABLE_RMEif (rmm_init != NULL) {INFO("BL31: Initializing RMM\n");console_flush();int32_t rc = (*rmm_init)();if (rc == 0) {WARN("BL31: RMM initialization failed\n");}}
#endif/** We are ready to enter the next EL. Prepare entry into the image* corresponding to the desired security state after the next ERET.*///我們已經準備好進入下一個異常級別。//請準備在下一次 ERET 指令后,進入對應目標安全狀態的鏡像 bl31_prepare_next_image_entry();/** Perform any platform specific runtime setup prior to cold boot exit* from BL31*/// 在從 BL31 冷啟動退出之前,執行任何必要的平臺特定運行時設置bl31_plat_runtime_setup();#if ENABLE_RUNTIME_INSTRUMENTATIONconsole_flush();  //運行時性能檢測PMF_CAPTURE_TIMESTAMP(bl_svc, BL31_EXIT, PMF_CACHE_MAINT);
#endif//切換控制臺狀態并刷新輸出console_flush();console_switch_state(CONSOLE_FLAG_RUNTIME);  //將控制臺切換到“運行時”模式
}

runtime_svc_init函數會將各種安全監控模式調用的處理函數的指針注冊到EL3中,并通過service init函數來進行初始化,將TEE OS鏡像的入口函數賦值給bl32_init,通過執行bl32_init指向的函數進入到TEE OS的啟動過程。待TEE OS啟動完成之后就會去查找bl33的鏡像文件,即REE側的鏡像文件,開始進入REE側鏡像的啟動。

runtime_svc_init函數

該函數主要用來建立安全監控模式調用處理函數的索引表,并執行EL3中提供的服務項的初始化操作,獲取TEE OS的入口地址并賦值給bl32_init變量,以備啟動TEE OS。而這些處理函數是通過DECLARE_RT_SVC宏定義被編譯到鏡像文件的rt_svc_descs段中的。

/root/optee/trusted-firmware-a/common/runtime_svc.c

void __init runtime_svc_init(void)
{int rc = 0;uint8_t index, start_idx, end_idx;rt_svc_desc_t *rt_svc_descs;/* Assert the number of descriptors detected are less than maximum indices *///檢查是否描述符的結束地址 ≥ 開始地址//檢查是否注冊的服務數量 < MAX_RT_SVCS(防止數組越界)assert((RT_SVC_DESCS_END >= RT_SVC_DESCS_START) &&(RT_SVC_DECS_NUM < MAX_RT_SVCS));/* If no runtime services are implemented then simply bail out *///如果沒有實現運行時服務,則直接退出if (RT_SVC_DECS_NUM == 0U) {return;}/* Initialise internal variables to invalid state *///初始化內部變量為無效狀態(void)memset(rt_svc_descs_indices, -1, sizeof(rt_svc_descs_indices));//獲取服務描述符數組指針rt_svc_descs = (rt_svc_desc_t *) RT_SVC_DESCS_START;for (index = 0U; index < RT_SVC_DECS_NUM; index++) {rt_svc_desc_t *service = &rt_svc_descs[index];/** An invalid descriptor is an error condition since it is* difficult to predict the system behaviour in the absence* of this service.*///檢查描述符是否合法rc = validate_rt_svc_desc(service);if (rc != 0) {ERROR("Invalid runtime service descriptor %p\n",(void *) service);panic();}/** The runtime service may have separate rt_svc_desc_t* for its fast smc and yielding smc. Since the service itself* need to be initialized only once, only one of them will have* an initialisation routine defined. Call the initialisation* routine for this runtime service, if it is defined.*///調用服務初始化函數(如果存在) if (service->init != NULL) {rc = service->init();if (rc != 0) {ERROR("Error initializing runtime service %s\n",service->name);continue;}}/** Fill the indices corresponding to the start and end* owning entity numbers with the index of the* descriptor which will handle the SMCs for this owning* entity range.*/// 為每個服務分配一個OEN范圍,用來處理所有的SMC調用start_idx = (uint8_t)get_unique_oen(service->start_oen,service->call_type);end_idx = (uint8_t)get_unique_oen(service->end_oen,service->call_type);assert(start_idx <= end_idx);assert(end_idx < MAX_RT_SVCS);//填充查找表for (; start_idx <= end_idx; start_idx++) {rt_svc_descs_indices[start_idx] = index;}}
}                

DECLARE_RT_SVC

該宏用來在編譯時將EL3中的service編譯進rt_svc_descs段中。該宏定義如下:

/root/optee/trusted-firmware-a/include/common/runtime_svc.h

/** Convenience macros to declare a service descriptor*/
// ##:將 __svc_desc_ 和 _name 拼接成一個唯一變量名。
// #:將 __svc_desc_ 和 _name 拼接成一個唯一變量名。 
// .rt_svc_descs: 將該變量放入名為 .rt_svc_descs 的自定義鏈接段(section)中。
// __used:告訴編譯器“這個變量雖然可能沒被顯式引用,但也別優化掉”
#define DECLARE_RT_SVC(_name, _start, _end, _type, _setup, _smch)       \static const rt_svc_desc_t __svc_desc_ ## _name                 \__section(".rt_svc_descs") __used = {                   \.start_oen = (_start),                          \.end_oen = (_end),                              \.call_type = (_type),                           \.name = #_name,                                 \.init = (_setup),                               \.handle = (_smch)                               \}

該宏中的各種參數說明如下:

  • start_oen:該service的起始內部編號
  • end.oen:該service的末尾編號
  • call_type:調用的smc的類型
  • name:該service的名字
  • init:該service在執行之前需要被執行的初始化操作
  • handle:當觸發了call type的調用時調用的處理該請求的函數

REE側鏡像文件的啟動

在bl31_main中啟動完TEE OS之后通過調用bl31_prepare_next_image_entry函數來獲取下一個階段需要被加載的鏡像文件,即REE側的鏡像文件,并配置好REE側鏡像的運行環境。bl31_main執行完成之后會跳轉到bl31_entrypoint中繼續執行,計算出需要被加載的鏡像文件的數據段大小和起始地址并清空BSS端中的數據,從EL3進入到EL1-NS開始執行REE側的代碼。

TEE側的加載在bl31_prepare_next_image_entry前,通過runtime_svc_init初始化的函數進行加載,將在下一節進行介紹。

參考資料:

  • 《手機安全和可信應用開發指南:TrustZone與OP-TEE技術詳解》

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/92584.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/92584.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/92584.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

從手工到智能決策,ERP讓制造外貿企業告別“數據孤島“降本增效

在全球化競爭加劇的當下&#xff0c;制造型外貿企業正面臨訂單碎片化、供應鏈復雜化、合規風險上升等多重挑戰。數字化轉型已成為企業突破增長瓶頸、構建核心競爭力的必選項。然而&#xff0c;許多企業在推進過程中因選型不當陷入“系統孤島”“數據失真”“流程低效”等困境。…

DMETL簡單介紹、安裝部署和入門嘗試

一、DMETL的介紹1.1 概述我們先來簡單了解一下DMETL。DMETL是什么&#xff1f;說的簡單一點&#xff0c;DMETL一款數據處理與集成平臺&#xff1b;從功能來說&#xff0c;那DMETL就是對數據同步、數據處理以及數據交換共享提供一站式支持的平臺&#xff1b;從它的意義來說&…

NLP 人工智能 Seq2Seq、K-means應用實踐

基于Java和人工智能的Web應用 以下是基于Java和人工智能的Web應用實例,涵蓋自然語言處理、計算機視覺、數據分析等領域。這些案例結合了沈七星AI或其他開源框架(如TensorFlow、Deeplearning4j)的實現思路,供開發參考: 自然語言處理(NLP) 1. 智能客服系統 使用Java的Op…

Docker 從入門到實戰(一):全面解析容器化革命 | 2025 終極指南

2025 年,全球容器市場規模突破 200 億美元,超過 80% 的企業生產環境運行在容器之上。掌握 Docker 已成為開發、運維乃至架構師的核心競爭力。本文帶你徹底搞懂 Docker 的底層邏輯與核心價值! 一、Docker 是什么?為什么它能改變世界? 想象一下:你開發時運行完美的 Pytho…

Lazada東南亞矩陣營銷破局:指紋手機如何以“批量智控+數據中樞”重構運營生態

在Lazada以“超級APP”戰略滲透東南亞6國市場的進程中&#xff0c;商家正陷入一個結構性矛盾&#xff1a;如何用有限人力高效管理10個國家賬號&#xff0c;卻不被數據孤島拖垮營銷效率&#xff0c;更不因賬號關聯風險引發平臺封禁&#xff1f;傳統多賬號運營依賴“人手一臺設備…

操作系統: 線程(Thread)

目錄 什么是線程&#xff08;Thread&#xff09;&#xff1f; 線程與進程之間的關系 線程調度與并發執行 并發&#xff08;Concurrency&#xff09;與并行&#xff08;Parallelism&#xff09; 多線程編程的四大核心優勢&#xff08;benefits of multithreaded programmin…

Uber的MySQL實踐(一)——學習筆記

MySQL 是Uber數據基礎設施的核心支柱&#xff0c;支撐著平臺上大量關鍵操作。Uber 擁有一套龐大的 MySQL 集群&#xff0c;如何構建一個控制平面來管理如此大規模的 MySQL 集群&#xff0c;并同時確保零宕機、零數據丟失是一個十分有挑戰性的問題。下面重點介紹 Uber 的 MySQL …

騰訊云EdgeOne產品深度分析報告

一、產品概述騰訊云EdgeOne是騰訊云推出的新一代邊緣安全加速平臺&#xff0c;集成內容分發網絡&#xff08;CDN&#xff09;、Web應用防火墻&#xff08;WAF&#xff09;、DDoS防護、Bot管理、API安全及邊緣計算能力&#xff0c;致力于為企業提供一站式安全加速解決方案。該平…

Spring Boot 優雅配置InfluxDB3客戶端指南:@Configuration + @Bean + yml實戰

前言 想用Java玩轉InfluxDB 3?要是還靠寫main函數硬編碼配置,那就像穿著睡衣開正式會議,實在有點不靠譜。現代Spring開發套路講究配置和代碼分離,講究優雅和靈活。用@Configuration配合@Bean注解,再加上yml配置文件集中管理連接信息,簡直是為代碼打扮一身西裝,既整潔又…

記錄:rk3568適配開源GPU驅動(panfrost)

rk3568采用的GPU是Mali-G52&#xff0c;該型號的GPU已在5.10內核的panfrost驅動中被支持。下面記錄下移植過程。 1.內核dts修改&#xff1a; kernel 5.10: arch/arm64/boot/dts/rockchip/rk3568.dtsigpu: gpufde60000 {compatible "rockchip,rk3568-mali", "ar…

SMBIOS詳解:系統管理BIOS的工作原理與實現

1. SMBIOS概述 SMBIOS&#xff08;System Management BIOS&#xff09;是由DMTF&#xff08;分布式管理任務組&#xff09;制定的行業標準&#xff0c;旨在為計算機系統提供統一的硬件信息描述框架。它定義了計算機硬件組件&#xff08;如處理器、內存、主板等&#xff09;的標…

8.5 CSS3多列布局

多列布局 CSS3之多列布局columns CSS3中新出現的多列布局(multi-column)是傳統HTML網頁中塊狀布局模式的有力擴充。這種新語法能夠讓WEB開發人員輕松的讓文本呈現多列顯示。 設置列寬 column-width&#xff1a; | auto 設置對象的寬度&#xff1b;使用像素表示。 auto&#…

Chrome插件快速上手

目錄 前言 一、瀏覽器插件的主要功能 二、插件的工作原理 插件結構 manifest.json icons background.js content-scripts 三、插件例子 popup popup.html popup.js styles.css background.js content-script.js manifest.json 四、其它 前言 本文不做特殊說明…

moment和dayjs

一&#xff1a;moment和dayjs 區別moment 大且可變、維護模式&#xff1b;dayjs 小且不可變、插件化、tree?shaking 友好。antd v4 用 moment&#xff1b;antd v5 用 dayjs。請在同一項目中統一其一&#xff0c;避免混用導致組件報錯。二&#xff1a; antd 4.24.16&#xff08…

Flutter Packge - 組件應用

一、組件創建1. 在工程根目錄創建 packages 目錄。mkdir packages #創建文件夾 cd packages 2. 創建純 Dart Package&#xff08;適合工具類/UI組件&#xff09;。flutter create --templatepackage common_network二、組件配置1. 在 common_network 的 pubspec.yaml 中添加…

基于雙塊輕量級神經網絡的無人機拍攝的風力渦輪機圖像去霧方法

基于雙塊輕量級神經網絡的無人機拍攝的風力渦輪機圖像去霧方法 UAV-Taken Wind Turbine Image Dehazing With a Double-Patch Lightweight Neural Network 我是菜雞&#xff01;我是菜雞&#xff01;我是菜雞&#xff01; 如果老師及學姐學長對該文有任何意見&#xff0c;請…

Spring AI Alibaba 項目接入阿里云百煉平臺大模型

1 依賴jdk 21 springboot 3.4.5 spring-ai-alibaba-starter-dashscope 1.0.0.2<properties><java.version>21</java.version><spring-ai.version>1.0.0</spring-ai.version><spring-ai-alibaba.version>1.0.0.2</spring-ai-alibaba.v…

電腦和手機訪問網站,自動檢測跳轉不同網站

自動檢測跳轉不同網站 自動檢測設備手機或電腦來跳轉不同網頁 開箱即用&#xff0c;不過需要自己修改一下跳轉鏈接 源碼截圖&#xff1a; 下載地址&#xff1a;電腦和手機訪問網站&#xff0c;自動檢測跳轉不同網站.zip - 藍奏云

Spring Boot 集成 ShardingSphere 實現讀寫分離實踐

Spring Boot 集成 ShardingSphere 實現讀寫分離實踐 在高并發的業務場景中,數據庫往往是系統性能的瓶頸。為了提高系統的吞吐量和穩定性,讀寫分離是一種常見的優化方案。本文將詳細介紹如何使用 Spring Boot 結合 ShardingSphere 實現數據庫的讀寫分離,并提供完整的配置和實…

以rabbitmq為例演示podman導出導入鏡像文件

1. 導出鏡像為 tar 文件 將鏡像保存為壓縮包&#xff08;默認格式為 docker-archive&#xff09;&#xff1a; podman save -o rabbitmq_management.tar docker.io/rabbitmq:management-o&#xff1a;指定輸出文件名&#xff08;如 rabbitmq_management.tar&#xff09;。鏡像名…