生活随笔
收集整理的這篇文章主要介紹了
简谈高通Trustzone的实现
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
從trust zone之我見知道,支持trustzone的芯片會跑在兩個世界。
普通世界、安全世界,對應高通這邊是HLOS,QSEE。
如下圖:
如下是HLOS與QSEE的軟件架構圖
HLOS這兩分為kernel層,user層。user層的通過qseecom提供的API起動trustzone那邊的app。
qseecom driver 除了提供API,還調用scm函數做世界切換。
scm driver 那邊接到qseecom的調用后,會把HLOS相關數據(包括指令參數)放入指它buffer,然后執行scm調用。
qsapp通過qsee提供的api接受來自HLOS那邊的請求,并把執行結果返回HLOS。
qsee除了提供API,還與從monitor把來自HLOS的數據傳給qsapp,然后把qsapp的數據返回給HLOS。
monitor就不用說了,切換世界用的,還處理shared buffer的內容。
是大概的架構圖,細節比較復雜,沒有開元。
下面通過一個簡單的qseecom_security_test代碼來說明整個調用流程。
如下圖:
qseecom_security_test.c
view plaincopy to clipboardprint?
int?main(?int?argc,?char?*argv[]?){....????memset(?g_qseeCommHandles,?0,?sizeof(g_qseeCommHandles)?);??memset(?g_xors,?0,?sizeof(g_xors)?);??
先初始化全局變量g_qseeCommHandles
view plaincopy to clipboardprint?
for(?j?=?0;?j?<?NUM_CLIENTS;?j++?)?{????????????ret?=?sem_init(?&barrier[j],?0,?0?);??
初始化一個barrier信號變量,用于線程創建時的同步
然后調用pthread_create()函數創建test_thread線程,該線程將會起動QSApp。
view plaincopy to clipboardprint?
void?*test_thread(?void*?threadid?){??...??do?{.....????LOGD(?"T%#X:?Starting?QSApp...",?(uint32_t)threadid?);????ret?=?QSEECom_start_app(?&g_qseeCommHandles[tid][0],?"/firmware/image",??
跟著來到test_thread線程
調用QSEECom_start_app()函數起動QSApp。
這個函數在kernel實現 如下:
qseecom.c
view plaincopy to clipboardprint?
static?int?qseecom_load_app(struct?qseecom_dev_handle?*data,?void?__user?*argp){...????????ihandle?=?ion_import_dma_buf(qseecom.ion_clnt,??????????????????load_img_req.ifd_data_fd);...???????ret?=?scm_call(SCM_SVC_TZSCHEDULER,?1,??&load_req,??????????sizeof(struct?qseecom_load_app_ireq),???????????&resp,?sizeof(resp));??
Get shared buf fd,用于與安全世界通信
調用scm_call()來陷入安全世界。
scm_call()實現如下:
arch/arm/mach-msm/scm.c
view plaincopy to clipboardprint?
int?scm_call(u32?svc_id,?u32?cmd_id,?const?void?*cmd_buf,?size_t?cmd_len,???????void?*resp_buf,?size_t?resp_len){???...?ret?=?scm_call_common(svc_id,?cmd_id,?cmd_buf,?cmd_len,?resp_buf,???????????????resp_len,?cmd,?len);????kfree(cmd);?return?ret;}??
scm_call_common的實現如下:
view plaincopy to clipboardprint?
static?int?scm_call_common(u32?svc_id,?u32?cmd_id,?const?void?*cmd_buf,?????????????size_t?cmd_len,?void?*resp_buf,?size_t?resp_len,????????????????struct?scm_command?*scm_buf,????????????????size_t?scm_buf_length){?....????mutex_lock(&scm_lock);??ret?=?__scm_call(scm_buf);??
調用__scm_call()陷入安全世界,回來后調用scm_get_response_buffer()獲取安全世界返回的信息供上面QSApp client用
__scm_call實現如下:
view plaincopy to clipboardprint?
static?int?__scm_call(const?struct?scm_command?*cmd){...????ret?=?smc(cmd_addr);...?return?ret;}??
smc實現如下:
view plaincopy to clipboardprint?
static?u32?smc(u32?cmd_addr){???int?context_id;?register?u32?r0?asm("r0")?=?1;??register?u32?r1?asm("r1")?=?(u32)&context_id;???register?u32?r2?asm("r2")?=?cmd_addr;???do?{????????asm?volatile(???????????__asmeq("%0",?"r0")?????????__asmeq("%1",?"r0")?????????__asmeq("%2",?"r1")?????????__asmeq("%3",?"r2")#ifdef?REQUIRES_SEC??????????".arch_extension?sec\n"#endif???????????"smc????#0??@?switch?to?secure?world\n"?????????:?"=r"?(r0)?????????:?"r"?(r0),?"r"?(r1),?"r"?(r2)??????????:?"r3");????}?while?(r0?==?SCM_INTERRUPTED);????return?r0;}??
是一段匯編程序,好吧,安全世界的QSApp已經運行起來了,當QSApp完成相應服務后就會返回數據。這個函數就會返回。
Starting QSApp已經完成,下面就注冊listener,這個listener用于監聽QSApp那邊的請求。因為有時QSApp也需要HLOS這邊做一些事。
實現如下:
view plaincopy to clipboardprint?
void?*listener_thread(?void*?threadid?){....??do?{...????????LOGD(?"L%#X:?Registering?as?listener?with?QSApp...",?(uint32_t)threadid?);????ret?=?QSEECom_register_listener(?&g_qseeCommHandles[parent_tid][tid],?GET_LSTNR_SVC_ID(parent_tid,?tid),????????????sizeof(qseecom_req_res_t),?0?);....????for(?;;?)?{????????????ret?=?QSEECom_receive_req(?g_qseeCommHandles[parent_tid][tid],?req_res,?sizeof(qseecom_req_res_t)?);??????if(?ret?)?break;?????....????????????ret?=?QSEECom_send_resp(?g_qseeCommHandles[parent_tid][tid],?req_res,?sizeof(qseecom_req_res_t)?);??????CHECK_RETURN(?ret,?__LINE__?);????}??}?while(?0?);...}??
這個函數比較長,簡化一下,分步來看
首先調用QSEECom_register_listener()函數來注冊監聽,告訴QSApp,我可以接收你的申請。
再次看到for循環沒有,這就是一直等待QSApp那邊的消息,一但有消息QSEECom_reveive_req就返回,這邊處理完之后。
再調用qSEECom_send_resp()發送response給QSApp。
無論是起動QSApp,還是注冊listener都是線程中執行,一但所有線程都退出后就會調用QSEECom_shutdown_app()函數停止QSApp。
整個過程執行完畢。如下:
view plaincopy to clipboardprint?
void?*test_thread(?void*?threadid?){...if?(?g_qseeCommHandles[tid][0]?!=?NULL?)?{??????QSEECom_shutdown_app(?&g_qseeCommHandles[tid][0]?);????}??}?while(?0?);??pthread_exit(?NULL?);??return?NULL;}??
注:QSEECom _XX開頭的函數都在kernel中的qseecom.c里實現,scm系統調用,都在scm.c中實現。
HLOS user層把握QSEEComAPI.h文件
HLOS kernel層把握qseecom.c 和 scm.c兩文件
《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀
總結
以上是生活随笔為你收集整理的简谈高通Trustzone的实现的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。