您好,登錄后才能下訂單哦!
這篇文章主要介紹“linux firmware的含義是什么”的相關知識,小編通過實際案例向大家展示操作過程,操作方法簡單快捷,實用性強,希望這篇“linux firmware的含義是什么”文章能幫助大家解決問題。
在linux中,firmware是指“固件”,是硬件設備自身執行的一段程序,一般存放在設備flash內。在Linux系統中,設備驅動程序處于內核態,而固件文件處于用戶態,因此需要一個安全穩定可靠的機制,用來確保設備驅動程序成功加載固件文件。
linux firmware是什么
固件(firmware)是硬件設備自身執行的一段程序。固件一般存放在設備flash內。而出于成本和便利性的考慮,通常是先將硬件設備的運行程序打包為一個特定格式的固件文件,存儲到終端系統內,通過終端系統給硬件設備進行升級。
Linux內核開發過程中,開發人員調試外設驅動設備,比如觸控,充電,線性馬達,存儲,WIFI設備等,同樣存在需要更新固件的情況。在Linux系統中,設備驅動程序處于內核態,而固件文件處于用戶態,因此需要一個安全穩定可靠的機制,用來確保設備驅動程序成功加載固件文件。
為了解決設備驅動程序從內核態穩定加載用戶態固件文件的問題,Linux系統提供了固件子系統。
Linux固件子系統流程簡介
Linux固件子系統基于sysfs 和uevent機制實現。
驅動程序調用固件系統函數接口申請固件之后,固件子系統使用固件編譯內核的方式去獲取固件;如果獲取失敗,就使用固件緩存的方式去獲取固件;如果仍然獲取失敗,就使用默認路徑內核直接查找的方式去獲取固件。如果還是獲取失敗,就通過上報uevent消息給init進程。init進程則接收到uevent消息,過濾出subsystem類型為firmware的消息。init進程根據uevent消息內指向的固件信息去查找固件,通過sysfs提供的文件節點接口,把獲取的固件內容從用戶態寫入內核態,從而使驅動程序,獲取到固件文件的數據。
Linux固件系統提供了多種在不同場景下獲取固件文件的方法。
1)直接編譯到內核的方式;
2)固件緩存的方式;
3)直接根據內核指定路徑的方式:
4)通過init進程來協助處理的方式;
Linux固件子系統流程框圖
Linux固件子系統主要函數接口
主要函數接口:
申請固件接口主要類型分為同步和異步。
通常申請固件的過程比較耗時,以及處理固件升級的過程比較耗時,因此可以采用異步函數接口實現,或者在驅動程序內先創建工作隊列調用同步函數接口實現。
其中:
內核申請固件文件調用 request_firmware函數實現。
內核獲取固件文件后調用release_firmware釋放相關的內存。
其中:
request_firmware_direct接口只在內核指定的路徑內查找固件,不使用uevent機制來獲取固件。
request_firmware_nowait接口是通過異步的工作隊列去獲取固件,可以起到不阻塞驅動probe時間的作用。
Linux固件子系統實現過程
request_firmware實現流程
request_firmware函數通過調用_request_firmware_prepare函數,設置不同的標志位,實現不同的差異功能。
_request_firmware_prepare函數:
在打開CONFIG_FW_LOADER宏開關基礎上,首先通過調用fw_get_builtin_firmware函數的方式,判斷固件文件是否編譯到內核。
接著調用fw_lookup_and_allocate_buf函數,判斷全局fw_cache結構內鏈表是否記錄過當前請求firmware的name。如果不存在當前請求firmware的name,則動態分配對應的內存空間并且添加當前請求firmware的name到全局的fw_cache結構內的鏈表。
fw_get_filesystem_firmware函數
主要是通過內核提供的默認路徑去查找固件文件,調用kernel_read_file_from_path函數。如果沒有查找到固件文件,則通過標志位FW_OPT_USERHELPER判斷,是否啟用USER_HELPER模式實現。
其中:
Firmware系統內默認路徑如下:
默認路徑可以通過kernel command line的方式來增加一個路徑,通過module_param_string接口傳遞給變量path來客制化新增路徑。
USER_HELPER模式
在內核打開CONFIG_FW_LOADER_USER_HELPER之后,才支持該功能。主要功能就是通過kernel上報uevent消息給到init進程,通過init進程獲取固件信息寫入底層sysfs節點。
fw_load_from_user_helper函數:
先調用fw_create_instance函數創建device設備,class文件和屬性文件,以及分配firmware_priv結構體。
接著在 /sys/class/firmware 下將創建一個目錄,該目錄使用設備名作為它的目錄名。
該目錄包含三個屬性:
loading:
設置為 1:該屬性由負責裝載固件的用戶空間設置1開始;
設置為 0:當裝載過程完畢;
設置為 -1:將終止固件裝載過程。
data:
用來接收固件數據,在設置完 loading 后,用戶空間進程把固件寫入該屬性。
device:
/sys/devices 下相應入口的符號鏈接。
timeout:
默認申請firmware通過uevent方式最大超時時間為60S,支持上層寫入超時時間。
_request_firmware_load函數:
首先先禁用uevent上報,通過調用device_add函數添加設備,觸發調用firmware_uevent函數。其中,填充uevent上報的信息格式,包括固件的名稱,超時時間,是否異步。
下一步則啟用uevent上報功能,同時調用kobject_uevent函數,上報add動作類型給到上層ueventd。
接著調用fw_state_wait_timeout函數,在預設的超時時間內等待上層ueventd的處理。
若超時時間達到或者收到完成量喚醒,則釋放之前申請的內存,釋放device,class等內存信息。
ueventd相關firmware處理流程
Ueventd是init進程內重要的模塊,它主要處理selinux,dev設備創建,監聽kernel上報uevent消息,firmware固件加載等內容。
FirmwareHandler處理流程:
FirmwareHandler內的HandleUevent方法主要是處理firmware固件加載和底層節點的交互流程。
首先先判斷uevent消息的subsystem類型是firmware字段才進行處理,這個類型只有kernel內firmware模塊才會上報。
HandleUevent主要是通過一個主線程創建不同的子線程,并行分別處理來自kernel的不同驅動的firmware請求。
ProcessFirmwareEvent函數
首先是循環判斷ueventd支持的路徑內檢索固件文件是否存在;若存在,則寫入底層loading屬性文件為1,同時拷貝獲取的固件文件,寫入到底層data文件。完成之后則寫入底層loading屬性文件為0。
至此,kernel就獲取到了用戶空間寫入的固件文件信息。
其中:
ueventd 默認支持搜索固件的路徑:
來自 ueventd.rc文件內指定的firmware_directory。
關于“linux firmware的含義是什么”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識,可以關注億速云行業資訊頻道,小編每天都會為大家更新不同的知識點。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。