Page MenuHomeFreeBSD

D43522.id133304.diff
No OneTemporary

D43522.id133304.diff

diff --git a/sys/kern/subr_firmware.c b/sys/kern/subr_firmware.c
--- a/sys/kern/subr_firmware.c
+++ b/sys/kern/subr_firmware.c
@@ -150,6 +150,19 @@
LIST_FOREACH(fp, &firmware_table, link) {
if (fp->fw.name != NULL && strcasecmp(name, fp->fw.name) == 0)
break;
+
+ /*
+ * If the name looks like an absolute path, also try to match
+ * the last part of the string to the requested firmware if it
+ * matches the trailing components. This allows us to load
+ * /boot/firmware/abc/bca2233_fw.bin and match it against
+ * requests for bca2233_fw.bin or abc/bca2233_fw.bin.
+ */
+ if (*fp->fw.name == '/' && strlen(fp->fw.name) > strlen(name)) {
+ const char *p = fp->fw.name + strlen(fp->fw.name) - strlen(name);
+ if (p[-1] == '/' && strcasecmp(name, p) == 0)
+ break;
+ }
}
return (fp);
}
@@ -412,9 +425,9 @@
mtx_lock(&firmware_mtx);
restart:
- LIST_FOREACH(fp, &firmware_table, link) {
- if (fp->file == NULL || fp->refcnt != 0 ||
- (fp->flags & FW_UNLOAD) == 0)
+ LIST_FOREACH_SAFE(fp, &firmware_table, link, tmp) {
+ if (((fp->flags & FW_DIRECT) == 0 && fp->file == NULL) ||
+ fp->refcnt != 0 || (fp->flags & FW_UNLOAD) == 0)
continue;
/*
@@ -442,6 +455,42 @@
mtx_unlock(&firmware_mtx);
}
+/*
+ * Find all the firmware that was loaded in the boot loader via load -t firmware
+ * foo. There is only one firmware per file, it's the whole file, and there's
+ * no meaningful version passed in, so pass 0 for that. If version is needed by
+ * the consumer (and not just arbitrarily defined), the .ko version must be used
+ * instead.
+ */
+static void
+firmware_raw_files(void)
+{
+ caddr_t file;
+ char *name;
+ const char *type;
+ const void *addr;
+ size_t size;
+ unsigned int version = 0;
+ const struct firmware *fw;
+ struct priv_fw *fp;
+
+ file = 0;
+ for (;;) {
+ file = preload_search_next_name(file);
+ if (file == 0)
+ break;
+ type = (const char *)preload_search_info(file, MODINFO_TYPE);
+ if (type == NULL || strcmp(type, "firmware") != 0)
+ continue;
+ name = preload_search_info(file, MODINFO_NAME);
+ addr = preload_fetch_addr(file);
+ size = preload_fetch_size(file);
+ fw = firmware_register(name, addr, size, version, NULL);
+ fp = PRIV_FW(fw);
+ fp->refcnt++; /* Hold an extra reference so we never unload */
+ }
+}
+
/*
* Module glue.
*/
@@ -460,6 +509,7 @@
/* NB: use our own loop routine that sets up context */
(void) taskqueue_start_threads(&firmware_tq, 1, PWAIT,
"firmware taskq");
+ firmware_raw_files();
if (rootvnode != NULL) {
/*
* Root is already mounted so we won't get an event;

File Metadata

Mime Type
text/plain
Expires
Fri, Jun 19, 12:00 AM (6 h, 48 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
34063059
Default Alt Text
D43522.id133304.diff (2 KB)

Event Timeline