韌體上傳 API

向韌體載入器註冊的裝置驅動程式將公開持久的 sysfs 節點,以使使用者能夠啟動該裝置的韌體更新。裝置驅動程式和/或裝置本身有責任對接收到的資料執行任何驗證。韌體上傳使用韌體回退文件中描述的相同loadingdata sysfs 檔案。它還添加了額外的 sysfs 檔案,以提供韌體映像傳輸到裝置的狀態。

註冊韌體上傳

裝置驅動程式透過呼叫 firmware_upload_register() 註冊韌體上傳。引數列表中有一個名稱來標識 /sys/class/firmware 下的裝置。使用者可以透過將 1 回顯到目標裝置的 loading sysfs 檔案來啟動韌體上傳。接下來,使用者將韌體映像寫入 data sysfs 檔案。寫入韌體資料後,使用者將 0 回顯到 loading sysfs 檔案以表示完成。將 0 回顯到 loading 也會觸發韌體在核心工作執行緒上下文中傳輸到較低級別的裝置驅動程式。

要使用韌體上傳 API,請編寫一個實現一組 ops 的驅動程式。探針函式呼叫 firmware_upload_register(),刪除函式呼叫 firmware_upload_unregister(),例如

static const struct fw_upload_ops m10bmc_ops = {
        .prepare = m10bmc_sec_prepare,
        .write = m10bmc_sec_write,
        .poll_complete = m10bmc_sec_poll_complete,
        .cancel = m10bmc_sec_cancel,
        .cleanup = m10bmc_sec_cleanup,
};

static int m10bmc_sec_probe(struct platform_device *pdev)
{
        const char *fw_name, *truncate;
        struct m10bmc_sec *sec;
        struct fw_upload *fwl;
        unsigned int len;

        sec = devm_kzalloc(&pdev->dev, sizeof(*sec), GFP_KERNEL);
        if (!sec)
                return -ENOMEM;

        sec->dev = &pdev->dev;
        sec->m10bmc = dev_get_drvdata(pdev->dev.parent);
        dev_set_drvdata(&pdev->dev, sec);

        fw_name = dev_name(sec->dev);
        truncate = strstr(fw_name, ".auto");
        len = (truncate) ? truncate - fw_name : strlen(fw_name);
        sec->fw_name = kmemdup_nul(fw_name, len, GFP_KERNEL);

        fwl = firmware_upload_register(THIS_MODULE, sec->dev, sec->fw_name,
                                       &m10bmc_ops, sec);
        if (IS_ERR(fwl)) {
                dev_err(sec->dev, "Firmware Upload driver failed to start\n");
                kfree(sec->fw_name);
                return PTR_ERR(fwl);
        }

        sec->fwl = fwl;
        return 0;
}

static int m10bmc_sec_remove(struct platform_device *pdev)
{
        struct m10bmc_sec *sec = dev_get_drvdata(&pdev->dev);

        firmware_upload_unregister(sec->fwl);
        kfree(sec->fw_name);
        return 0;
}

firmware_upload_register

struct fw_upload *firmware_upload_register(struct module *module, struct device *parent, const char *name, const struct fw_upload_ops *ops, void *dd_handle)

註冊韌體上傳 sysfs API

引數

struct module *module

此裝置的核心模組

struct device *parent

例項化韌體上傳的父裝置

const char *name

要與此裝置關聯的韌體名稱

const struct fw_upload_ops *ops

指向韌體上傳 ops 結構的指標

void *dd_handle

指向父驅動程式私有資料的指標

name 在所有韌體上傳使用者中必須是唯一的。此裝置的韌體 sysfs 檔案將在 /sys/class/firmware/name 中找到。

返回值

struct fw_upload 指標或 ERR_PTR()

firmware_upload_unregister

void firmware_upload_unregister(struct fw_upload *fw_upload)

取消註冊韌體上傳介面

引數

struct fw_upload *fw_upload

指向 struct fw_upload 的指標

韌體上傳 Ops

struct fw_upload_ops

裝置特定操作以支援韌體上傳

定義:

struct fw_upload_ops {
    enum fw_upload_err (*prepare)(struct fw_upload *fw_upload, const u8 *data, u32 size);
    enum fw_upload_err (*write)(struct fw_upload *fw_upload,const u8 *data, u32 offset, u32 size, u32 *written);
    enum fw_upload_err (*poll_complete)(struct fw_upload *fw_upload);
    void (*cancel)(struct fw_upload *fw_upload);
    void (*cleanup)(struct fw_upload *fw_upload);
};

成員

prepare

必需:準備安全更新

write

必需:write() op 接收要寫入的剩餘大小,並且必須返回實際寫入的大小或負錯誤程式碼。write() op 將被重複呼叫,直到寫入所有資料。

poll_complete

必需:檢查硬體身份驗證/程式設計過程的完成情況。

cancel

必需:請求取消更新。此 op 從不同的核心執行緒上下文中呼叫,因此需要考慮競爭條件。

cleanup

可選:補充 prepare() 函式,並在更新完成時(成功或失敗)呼叫,如果 prepare 函式成功。

韌體上傳進度程式碼

以下進度程式碼由韌體載入器內部使用。相應的字串透過下面描述的狀態 sysfs 節點報告,並在 ABI 文件中進行了記錄。

enum fw_upload_prog

韌體上傳進度程式碼

常量

FW_UPLOAD_PROG_IDLE

沒有正在進行的韌體上傳

FW_UPLOAD_PROG_RECEIVING

工作執行緒正在接收韌體資料

FW_UPLOAD_PROG_PREPARING

目標裝置正在準備韌體上傳

FW_UPLOAD_PROG_TRANSFERRING

資料正在複製到裝置

FW_UPLOAD_PROG_PROGRAMMING

裝置正在執行韌體更新

FW_UPLOAD_PROG_MAX

最大進度程式碼標記

韌體上傳錯誤程式碼

如果發生故障,驅動程式 ops 可能會返回以下錯誤程式碼

enum fw_upload_err

韌體上傳錯誤程式碼

常量

FW_UPLOAD_ERR_NONE

返回以指示成功

FW_UPLOAD_ERR_HW_ERROR

硬體發出的錯誤訊號,請參閱核心日誌

FW_UPLOAD_ERR_TIMEOUT

軟體與硬體/韌體握手超時

FW_UPLOAD_ERR_CANCELED

上傳被使用者取消

FW_UPLOAD_ERR_BUSY

已經有一個上傳操作正在進行中

FW_UPLOAD_ERR_INVALID_SIZE

韌體映像大小無效

FW_UPLOAD_ERR_RW_ERROR

讀取或寫入硬體失敗,請參閱核心日誌

FW_UPLOAD_ERR_WEAROUT

快閃記憶體裝置即將耗盡,請等待並重試

FW_UPLOAD_ERR_FW_INVALID

韌體檔案無效

FW_UPLOAD_ERR_MAX

最大錯誤程式碼標記

Sysfs 屬性

除了 loadingdata sysfs 檔案之外,還有額外的 sysfs 檔案來監視資料傳輸到目標裝置的狀態,並確定傳輸的最終透過/失敗狀態。根據裝置和韌體映像的大小,韌體更新可能需要幾毫秒或幾分鐘。

額外的 sysfs 檔案是

  • status - 提供韌體更新進度的指示

  • error - 為失敗的韌體更新提供錯誤資訊

  • remaining_size - 跟蹤更新的資料傳輸部分

  • cancel - 將 1 回顯到此檔案以取消更新