Firmware 加載原理分析

前言       node

              前段時間移植 wifi 驅動到 android 的內核上,發現 firmware 的加載始終出錯,問了幾我的,都不是很瞭解,沒辦法,只好本身研究一下。 linux

原理分析

    從本質上來講, firmware 須要作的事情包括兩件: android

1,  通知用戶態程序,我須要下載 firmware 了; socket

2,  用戶態程序把用戶態的數據 copy 到內核層; 函數

3,  內核把內核態的數據寫到設備上,好比 wifi 模塊裏; spa

其中第三步應該不難,關鍵是看看, linux 裏面是如何實現第1、二步的; 設計

實現機制

              簡單的說,它的機制分紅如下幾部分: it

1,  經過必定的方式,通知用戶態程序,好比 init 程序,如圖所示 io



 

顯然是經過 kobject_uevent 的方式通知的應用層,它的機制我有空再詳細解釋,簡單的說,就是往一個 socket 廣播一個消息,只須要在應用層打開 socket 監聽 NETLINK_KOBJECT_UEVENT 組的消息,就能夠收到了。

          用戶態的 init 是如何作的? event


       能夠看到 init 程序打開了一個 socket ,而後綁定它,最後經過 select 來監聽 socket 上來的數據,最後調用 handle_device_fd 來處理收到的消息;當內核發送一個 KOBJ_ADD 的消息上來的時候,通過過濾,判斷是不是 firmware 要被加載的消息,而後調用

              handle_firmware_event 來處理;

2,  用戶態的數據如何下載到內核;

       本質上它是內核建立了兩個文件,一個文件 A 用來標誌下載的開始和結束,另一個文件 B 用來接收用戶層傳下來的數據,當用戶態的程序往 A 文件寫入 1 的時候,標誌用戶態程序已經往裏面寫程序來,而往裏面寫入 0 的時候,就標誌下載成功結束,若是寫入 -1 就表示下載失敗了;下面看看這兩個文件是如何被建立的 , 以及數據是如何寫到內核的,請看圖:






 

這個圖基本上就是兩個文件被創立的過程,以及當這兩個文件被用戶態程序訪問的時候將要被調用的函數,好比對於標誌文件,若是往裏面寫入數據,將會觸發函數 firmware_loading_store 函數,若是往 bin 文件裏面寫入數據將會觸發 bin 文件類型的 write 函數;

       用戶態寫數據的過程大約是這樣的:當用戶態收到 KOBJ_ADD 消息的時候最終將會調用 handle_firmware_event 的函數;



它的過程就是:

a, 先往標誌文件裏面寫 1

b, 從用戶空間讀取數據;

c, 往內核建立的文件裏面寫數據;

d, 若是成功寫入 0 ,不然寫入 -1

下面看看內核是如何接受這些文件的,前面提到內核建立了一個 bin 文件,用來接收用戶態的數據,下面看看這個過程:



對於 SYSFS_KOBJ_BIN_ATTR 屬性的文件,在 inode 初始化的時候,將會被賦予 bin_fops 的文件操做函數集,因而當上層調用 write 的時候,將會走到內核的 bin_fops.write 函數;這個函數乾的事情很簡單,就是把用戶態的數據 copyright bb->buffer ,而 bb->buffer 實際上是在 open 的時候分配的空間,這樣的話,就實現了用戶態的數據到內核的 copy ;過程是否是完了?

還有一個步驟,這個 bb->buffer 自己是如何與 wifi 驅動交互的呢?這只是一箇中間層,它的數據必需要寫到 wifi 的驅動才應該算完整,而這一步其實就是經過 flush_write 來完成的,下面看看這個過程:



 

這裏能夠清楚的看到, flush_write 作的事情就是把 bb->buffer 的內容 copy wifi driver 分配的空間 fw->data 裏面去了,至此,用戶態的數據已經完整的寫到了 wifi driver 空間了;

 

3,  內核態的數據到 wifi 模塊

                                                         這個就比較簡單了,經過函數 sdio_writesb 利用 sdio 總線把數據寫到模塊裏面去了;

 

 

總結

                  Firmware 的加載主要是利用了 uevent 的通信機制實現用戶態和內核態的交互,另外還涉及了 sys 文件系統裏的文件建立 , 我加載 wifi firmware 始終出錯的緣由是 android 的文件系統要求把 wifi firmware helper 放到 /etc/firmware 裏面,而把真正的 firmware sd8686.bin 放到 /etc/firmware/mrvl 裏面,估計是 marvel 修改後的結果,結論就是,這個設計真醜;

相關文章
相關標籤/搜索