読者です 読者をやめる 読者になる 読者になる

φ(.. )メモシテオコウ Linux:firmwareの読み込み処理めも

kernel linux

jailhouseのmain.cを見ていてファームウェアの読み込みrequest_firmware()のところでこれってどうやってんだろ?と思ったので調べてみるなど。見たカーネルのバージョンは3.12です。
この関数がどんなことをしているのかというのはLinux Kernel Watchにありました。こちらによるとrequest_firmware()自体がファームウェアを読み込むのではなく、ユーザー空間側のプログラムと連動してファームウェアの読み込みが行われるのですね。
では実際に見ていくと。。。

jailhouse側はこのような呼び出し。

        const struct firmware *hypervisor;
        ~ 中略 ~
        err = request_firmware(&hypervisor, JAILHOUSE_FW_NAME, jailhouse_dev);

JAILHOUSE_FW_NAMEはjailhouse.bin、jailhouse_devはmodule_initの関数で設定したデバイス。


request_firmware()はこうなってます。。

1129 int
1130 request_firmware(const struct firmware **firmware_p, const char *name,
1131                  struct device *device)
1132 {
1133         int ret;
1134 
1135         /* Need to pin this module until return */
1136         __module_get(THIS_MODULE);
1137         ret = _request_firmware(firmware_p, name, device, true, false);
1138         module_put(THIS_MODULE);
1139         return ret;
1140 }

関数の実質的な内容は_request_firmware()ですね。
request_firmware()に渡す引数についてはコメントに内容が書かれています。

1111  * @firmware_p: pointer to firmware image
1112  * @name: name of firmware file
1113  * @device: device for which firmware is being loaded

firmware_pには変数hypervisorのポインタのポインタを渡しているのでイメージがここに入るはず。nameはjailhouse.bin、デバイスはjailhouseが使うstruct device。

_request_firmware()はこちら。

1056 _request_firmware(const struct firmware **firmware_p, const char *name,
1057                   struct device *device, bool uevent, bool nowait)
1058 {
1059         struct firmware *fw;
1060         long timeout;
1061         int ret;
1062 
1063         if (!firmware_p)
1064                 return -EINVAL;
1065 
1066         ret = _request_firmware_prepare(&fw, name, device);
1067         if (ret <= 0) /* error or already assigned */
1068                 goto out;
1069 
1070         ret = 0;
1071         timeout = firmware_loading_timeout();
1072         if (nowait) {
1073                 timeout = usermodehelper_read_lock_wait(timeout);
1074                 if (!timeout) {
1075                         dev_dbg(device, "firmware: %s loading timed out\n",
1076                                 name);
1077                         ret = -EBUSY;
1078                         goto out;
1079                 }
1080         } else {
1081                 ret = usermodehelper_read_trylock();
1082                 if (WARN_ON(ret)) {
1083                         dev_err(device, "firmware: %s will not be loaded\n",
1084                                 name);
1085                         goto out;
1086                 }
1087         }
1088 
1089         if (!fw_get_filesystem_firmware(device, fw->priv))
1090                 ret = fw_load_from_user_helper(fw, name, device,
1091                                                uevent, nowait, timeout);
1092 
1093         /* don't cache firmware handled without uevent */
1094         if (!ret)
1095                 ret = assign_firmware_buf(fw, device, !uevent);
1096 
1097         usermodehelper_read_unlock();
1098 
1099  out:
1100         if (ret < 0) {
1101                 release_firmware(fw);
1102                 fw = NULL;
1103         }
1104 
1105         *firmware_p = fw;
1106         return ret;
1107 }

この間数の内容を大雑把にまとめるとこのような形。

  • _request_firmware_prepare()で読み込み準備
  • 1071~1088行目でユーザー空間側のプログラムがファームウェアを読み込むのを待つ
  • fw_get_filesystem_firmware()でファームウェアを読み込んでfw->privに保存

では、_request_firmware_prepare()を見てみます。

977 static int
978 _request_firmware_prepare(struct firmware **firmware_p, const char *name,
979                           struct device *device)
980 {
981         struct firmware *firmware;
982         struct firmware_buf *buf;
983         int ret;
984 
985         *firmware_p = firmware = kzalloc(sizeof(*firmware), GFP_KERNEL);
986         if (!firmware) {
987                 dev_err(device, "%s: kmalloc(struct firmware) failed\n",
988                         __func__);
989                 return -ENOMEM;
990         }
991 
992         if (fw_get_builtin_firmware(firmware, name)) {
993                 dev_dbg(device, "firmware: using built-in firmware %s\n", name);
994                 return 0; /* assigned */
995         }
996 
997         ret = fw_lookup_and_allocate_buf(name, &fw_cache, &buf);
998 
999         /*
1000          * bind with 'buf' now to avoid warning in failure path
1001          * of requesting firmware.
1002          */
1003         firmware->priv = buf;
1004 
1005         if (ret > 0) {
1006                 ret = sync_cached_firmware_buf(buf);
1007                 if (!ret) {
1008                         fw_set_page_data(buf, firmware);
1009                         return 0; /* assigned */
1010                 }
1011         }
1012 
1013         if (ret < 0)
1014                 return ret;
1015         return 1; /* need to load */
1016 }

この関数はロードしようしているファームウェアがカーネルビルトインのものかチェック(fw_get_builtin_firmware())してビルトインファームウェアの場合は0、違う場合は1を返す。
ビルトインファームウェアだった場合は_request_firmware()に戻ってそのまま終了。

対象のファームウェアがビルトインかどうかはfw_get_builtin_firmware()でチェック。調べ方は__start_builtin_fw~__end_builtin_fwの範囲でnameが有るか調べて有ったらtrueをかえすというもの。

 44 extern struct builtin_fw __start_builtin_fw[];
 45 extern struct builtin_fw __end_builtin_fw[];
 46 
 47 static bool fw_get_builtin_firmware(struct firmware *fw, const char *name)
 48 {
 49         struct builtin_fw *b_fw;
 50 
 51         for (b_fw = __start_builtin_fw; b_fw != __end_builtin_fw; b_fw++) {
 52                 if (strcmp(name, b_fw->name) == 0) {
 53                         fw->size = b_fw->size;
 54                         fw->data = b_fw->data;
 55                         return true;
 56                 }
 57         }
 58 
 59         return false;
 60 }

もしここからファームウェアが見つからなければfw_lookup_and_allocate_buf()を使う。

197 static int fw_lookup_and_allocate_buf(const char *fw_name,
198                                       struct firmware_cache *fwc,
199                                       struct firmware_buf **buf)
200 {
201         struct firmware_buf *tmp;
202 
203         spin_lock(&fwc->lock);
204         tmp = __fw_lookup_buf(fw_name);
205         if (tmp) {
206                 kref_get(&tmp->ref);
207                 spin_unlock(&fwc->lock);
208                 *buf = tmp;
209                 return 1;
210         }
211         tmp = __allocate_fw_buf(fw_name, fwc);
212         if (tmp)
213                 list_add(&tmp->list, &fwc->head);
214         spin_unlock(&fwc->lock);
215 
216         *buf = tmp;
217 
218         return tmp ? 0 : -ENOMEM;
219 }

この関数はファームウェアバッファのキャッシュを検索してファームウェアが読み込まれている場合はそのバッファを返す。
キャッシュから検索しているのは__fw_lookup_buf()で以下のような内容。

186 static struct firmware_buf *__fw_lookup_buf(const char *fw_name)
187 {
188         struct firmware_buf *tmp;
189         struct firmware_cache *fwc = &fw_cache;
190 
191         list_for_each_entry(tmp, &fwc->head, list)
192                 if (!strcmp(tmp->fw_id, fw_name))
193                         return tmp;
194         return NULL;
195 }

キャッシュから見つからなかった場合は__allocate_fw_buf()でバッファを確保する。

163 static struct firmware_buf *__allocate_fw_buf(const char *fw_name,
164                                               struct firmware_cache *fwc)
165 {
166         struct firmware_buf *buf;
167 
168         buf = kzalloc(sizeof(*buf) + strlen(fw_name) + 1 , GFP_ATOMIC);
169 
170         if (!buf)
171                 return buf;
172 
173         kref_init(&buf->ref);
174         strcpy(buf->fw_id, fw_name);
175         buf->fwc = fwc;
176         init_completion(&buf->completion);
177 #ifdef CONFIG_FW_LOADER_USER_HELPER
178         INIT_LIST_HEAD(&buf->pending_list);
179 #endif
180 
181         pr_debug("%s: fw-%s buf=%p\n", __func__, fw_name, buf);
182 
183         return buf;
184 }

kzalloc()で構造体サイズの他にファームウェア名を付けているのはfirmware_buf構造体の最後のメンバ(fw_id)がchar[]で可変長になっているため。

121 struct firmware_buf {
122         struct kref ref;
123         struct list_head list;
124         struct completion completion;
     ~中略~
137         char fw_id[];
138 };

ここまででキャッシュからファームウェアのバッファが見つかった、もしくはアローケート完了です。そして_request_firmware()に戻ってファームウェアの読み込み部分で、読み込みを行うのはfw_get_filesystem_firmware()

305 static bool fw_get_filesystem_firmware(struct device *device,
306                                        struct firmware_buf *buf)
307 {
308         int i;
309         bool success = false;
310         char *path = __getname();
311 
312         for (i = 0; i < ARRAY_SIZE(fw_path); i++) {
313                 struct file *file;
314 
315                 /* skip the unset customized path */
316                 if (!fw_path[i][0])
317                         continue;
318 
319                 snprintf(path, PATH_MAX, "%s/%s", fw_path[i], buf->fw_id);
320 
321                 file = filp_open(path, O_RDONLY, 0);
322                 if (IS_ERR(file))
323                         continue;
324                 success = fw_read_file_contents(file, buf);
325                 fput(file);
326                 if (success)
327                         break;
328         }
329         __putname(path);
330 
331         if (success) {
332                 dev_dbg(device, "firmware: direct-loading firmware %s\n",
333                         buf->fw_id);
334                 mutex_lock(&fw_lock);
335                 set_bit(FW_STATUS_DONE, &buf->status);
336                 complete_all(&buf->completion);
337                 mutex_unlock(&fw_lock);
338         }
339 
340         return success;
341 }

最初の__getname()は何だ?と思ったらスラブキャッシュからメモリを取得するためのマクロでした。

2048 #define __getname()             kmem_cache_alloc(names_cachep, GFP_KERNEL)
2049 #define __putname(name)         kmem_cache_free(names_cachep, (void *)(name))

そして、ファイルの読み込みですがファイル名は分かっているけどパスが分からないのでそのためのループですね。
パスの配列分ループしていますがこの配列はfirmware_class.cに定義されています。

254 /* direct firmware loading support */
255 static char fw_path_para[256];
256 static const char * const fw_path[] = {
257         fw_path_para,
258         "/lib/firmware/updates/" UTS_RELEASE,
259         "/lib/firmware/updates",
260         "/lib/firmware/" UTS_RELEASE,
261         "/lib/firmware"
262 };

あとはファイルを開いてみてオープンに成功すればfw_read_file_contents()で読み込むという流れですね。
一応、fw_read_file_contents()がどんなことをしているか見てます。 

285 static bool fw_read_file_contents(struct file *file, struct firmware_buf *fw_buf)
286 {
287         long size;
288         char *buf;
289 
290         size = fw_file_size(file);
291         if (size <= 0)
292                 return false;
293         buf = vmalloc(size);
294         if (!buf)
295                 return false;
296         if (kernel_read(file, 0, buf, size) != size) {
297                 vfree(buf);
298                 return false;
299         }
300         fw_buf->data = buf;
301         fw_buf->size = size;
302         return true;
303 }

ファイルの読み込みを行っているのはkernel_read()で関数のプロトタイプは以下の通り。

792 int kernel_read(struct file *file, loff_t offset,
793                 char *addr, unsigned long count)

ファイルオフセット0からsize分読み出しているだけですね。

もしfw_get_filesystem_firmware()でファームウェアの読み込みに失敗した場合はfw_load_from_user_helper()が呼ばれる。

1089         if (!fw_get_filesystem_firmware(device, fw->priv))
1090                 ret = fw_load_from_user_helper(fw, name, device,
1091                                                uevent, nowait, timeout);

fw_load_from_user_helper()はこのような関数。

905 static int fw_load_from_user_helper(struct firmware *firmware,
906                                     const char *name, struct device *device,
907                                     bool uevent, bool nowait, long timeout)
908 {
909         struct firmware_priv *fw_priv;
910 
911         fw_priv = fw_create_instance(firmware, name, device, uevent, nowait);
912         if (IS_ERR(fw_priv))
913                 return PTR_ERR(fw_priv);
914 
915         fw_priv->buf = firmware->priv;
916         return _request_firmware_load(fw_priv, uevent, timeout);
917 }
918 

fw_create_instance()と_request_firmware_load()の呼び出しが主な処理。

fw_create_instance()の処理としてはfirmware_priv構造体の設定とファームウェア名のデバイスファイルの作成ってところですかね。

814 static struct firmware_priv *
815 fw_create_instance(struct firmware *firmware, const char *fw_name,
816                    struct device *device, bool uevent, bool nowait)
817 {
818         struct firmware_priv *fw_priv;
819         struct device *f_dev;
820 
821         fw_priv = kzalloc(sizeof(*fw_priv), GFP_KERNEL);
822         if (!fw_priv) {
823                 dev_err(device, "%s: kmalloc failed\n", __func__);
824                 fw_priv = ERR_PTR(-ENOMEM);
825                 goto exit;
826         }
827 
828         fw_priv->nowait = nowait;
829         fw_priv->fw = firmware;
830         INIT_DELAYED_WORK(&fw_priv->timeout_work,
831                 firmware_class_timeout_work);
832 
833         f_dev = &fw_priv->dev;
834 
835         device_initialize(f_dev);
836         dev_set_name(f_dev, "%s", fw_name);
837         f_dev->parent = device;
838         f_dev->class = &firmware_class;
839 exit:
840         return fw_priv;
841 }

firmware_priv構造体はこのように定義されています。CONFIG_FW_LOADER_USER_HELPERがyじゃないとダメですね。

426 /*
427  * user-mode helper code
428  */
429 #ifdef CONFIG_FW_LOADER_USER_HELPER
430 struct firmware_priv {
431         struct delayed_work timeout_work;
432         bool nowait;
433         struct device dev;
434         struct firmware_buf *buf;
435         struct firmware *fw;
436 };
437 

_request_firmware_load()ユーザーモードと連動してファームウェアを読み込むメインの処理っぽいですね。

842 
843 /* load a firmware via user helper */
844 static int _request_firmware_load(struct firmware_priv *fw_priv, bool uevent,
845                                   long timeout)
846 {
847         int retval = 0;
848         struct device *f_dev = &fw_priv->dev;
849         struct firmware_buf *buf = fw_priv->buf;
850 
851         /* fall back on userspace loading */
852         buf->is_paged_buf = true;
853 
854         dev_set_uevent_suppress(f_dev, true);
855 
856         retval = device_add(f_dev);
857         if (retval) {
858                 dev_err(f_dev, "%s: device_register failed\n", __func__);
859                 goto err_put_dev;
860         }
861 
862         retval = device_create_bin_file(f_dev, &firmware_attr_data);
863         if (retval) {
864                 dev_err(f_dev, "%s: sysfs_create_bin_file failed\n", __func__);
865                 goto err_del_dev;
866         }
867 
868         mutex_lock(&fw_lock);
869         list_add(&buf->pending_list, &pending_fw_head);
870         mutex_unlock(&fw_lock);
871 
872         retval = device_create_file(f_dev, &dev_attr_loading);
873         if (retval) {
874                 mutex_lock(&fw_lock);
875                 list_del_init(&buf->pending_list);
876                 mutex_unlock(&fw_lock);
877                 dev_err(f_dev, "%s: device_create_file failed\n", __func__);
878                 goto err_del_bin_attr;
879         }
880 
881         if (uevent) {
882                 buf->need_uevent = true;
883                 dev_set_uevent_suppress(f_dev, false);
884                 dev_dbg(f_dev, "firmware: requesting %s\n", buf->fw_id);
885                 if (timeout != MAX_SCHEDULE_TIMEOUT)
886                         schedule_delayed_work(&fw_priv->timeout_work, timeout);
887 
888                 kobject_uevent(&fw_priv->dev.kobj, KOBJ_ADD);
889         }
890 
891         wait_for_completion(&buf->completion);
892 
893         cancel_delayed_work_sync(&fw_priv->timeout_work);
894 
895         device_remove_file(f_dev, &dev_attr_loading);
896 err_del_bin_attr:
897         device_remove_bin_file(f_dev, &firmware_attr_data);
898 err_del_dev:
899         device_del(f_dev);
900 err_put_dev:
901         put_device(f_dev);
902         return retval;
903 }

読み込んだデータの保存先になるファイルを作り、読み込みが終わるのを待つ。そして最後に作ったファイルを削除して終了。

そしてまた_request_firmware()に戻ってきて、retが0だった場合のみassign_firmware_buf()が呼ばれる。retが0とは例えば、 fw_load_from_user_helper()が成功したときとか。

1093         /* don't cache firmware handled without uevent */
1094         if (!ret)
1095                 ret = assign_firmware_buf(fw, device, !uevent);
1096 

assign_firmware_buf()はコメントが書かれていて良いですね( ´∀`)bグッ!

1018 static int assign_firmware_buf(struct firmware *fw, struct device *device,
1019                                 bool skip_cache)
1020 {
1021         struct firmware_buf *buf = fw->priv;
1022 
1023         mutex_lock(&fw_lock);
1024         if (!buf->size || is_fw_load_aborted(buf)) {
1025                 mutex_unlock(&fw_lock);
1026                 return -ENOENT;
1027         }
1028 
1029         /*
1030          * add firmware name into devres list so that we can auto cache
1031          * and uncache firmware for device.
1032          *
1033          * device may has been deleted already, but the problem
1034          * should be fixed in devres or driver core.
1035          */
1036         if (device && !skip_cache)
1037                 fw_add_devm_name(device, buf->fw_id);
1038 
1039         /*
1040          * After caching firmware image is started, let it piggyback
1041          * on request firmware.
1042          */
1043         if (buf->fwc->state == FW_LOADER_START_CACHE) {
1044                 if (fw_cache_piggyback_on_request(buf->fw_id))
1045                         kref_get(&buf->ref);
1046         }
1047 
1048         /* pass the pages buffer to driver at the last minute */
1049         fw_set_page_data(buf, fw);
1050         mutex_unlock(&fw_lock);
1051         return 0;
1052 }

( ´ー`)フゥー...
適当にまとめると

  • request_firmware()はファームウェア名を受け取ってそのファイルを読み込む
  • ファームウェアはカーネルビルトインのものとそれ以外の2種類
  • ファームウェアの読み込みはカーネル内部で行える場合と、ユーザー空間のプログラムに読んでもらう場合の2通りある
  • 読み込んだファームウェアのデータはキャッシュされる