drivers/base/firmware_loader/main.c | 209 +++++++++++++++++++++++------------- 1 file changed, 133 insertions(+), 76 deletions(-)
Refactor fw_get_filesystem_firmware() by extracting the per-path
firmware loading logic into a new fw_try_firmware_path() helper.
Use this helper to parse fw_path_para for ':'-separated paths,
trying each one before falling through to the default firmware
search paths. This allows users to specify multiple custom firmware
directories via firmware_class.path, e.g.:
firmware_class.path=/custom/path1:/custom/path2
A backslash can be used as an escape character, allowing a literal
':' ("\:") or literal '\' ("\\") to be embedded in a pathname.
Suggested-by: Michal Grzedzicki <mge@meta.com>
Signed-off-by: Jeff Layton <jlayton@kernel.org>
---
Michal privately pointed out that this didn't have provision to handle
an embedded ':' in the filename. This version adds support for escaping
':' and '\' in the filename via backslash characters.
---
Changes in v3:
- Allow '\' to escape a literal ':' or '\' in the string
- Link to v2: https://lore.kernel.org/r/20260318-fw-path-v2-1-8a106eb91eb4@kernel.org
Changes in v2:
- switch to using ':' as path delimiter
- Link to v1: https://lore.kernel.org/r/20260318-fw-path-v1-1-7884d9bf618f@kernel.org
---
drivers/base/firmware_loader/main.c | 209 +++++++++++++++++++++++-------------
1 file changed, 133 insertions(+), 76 deletions(-)
diff --git a/drivers/base/firmware_loader/main.c b/drivers/base/firmware_loader/main.c
index a11b30dda23be563bd55f25474ceff2153ddd667..7f35100ae1a7575deed57bdf9b5823f87ce5d115 100644
--- a/drivers/base/firmware_loader/main.c
+++ b/drivers/base/firmware_loader/main.c
@@ -470,7 +470,6 @@ static int fw_decompress_xz(struct device *dev, struct fw_priv *fw_priv,
/* direct firmware loading support */
static char fw_path_para[256];
static const char * const fw_path[] = {
- fw_path_para,
"/lib/firmware/updates/" UTS_RELEASE,
"/lib/firmware/updates",
"/lib/firmware/" UTS_RELEASE,
@@ -480,10 +479,83 @@ static const char * const fw_path[] = {
/*
* Typical usage is that passing 'firmware_class.path=$CUSTOMIZED_PATH'
* from kernel command line because firmware_class is generally built in
- * kernel instead of module.
+ * kernel instead of module. Multiple paths can be separated by ':'.
*/
module_param_string(path, fw_path_para, sizeof(fw_path_para), 0644);
-MODULE_PARM_DESC(path, "customized firmware image search path with a higher priority than default path");
+MODULE_PARM_DESC(path, "customized firmware image search path with a higher priority than default path, multiple paths can be separated by ':' (use '\\:' for literal ':', '\\\\' for literal '\\')");
+
+static int
+fw_try_firmware_path(struct device *device, struct fw_priv *fw_priv,
+ const char *suffix,
+ int (*decompress)(struct device *dev,
+ struct fw_priv *fw_priv,
+ size_t in_size,
+ const void *in_buffer),
+ const char *dir, int dirlen,
+ char *path, void **bufp, size_t msize)
+{
+ size_t file_size = 0;
+ size_t *file_size_ptr = NULL;
+ size_t size;
+ int len, rc;
+
+ len = snprintf(path, PATH_MAX, "%.*s/%s%s",
+ dirlen, dir, fw_priv->fw_name, suffix);
+ if (len >= PATH_MAX)
+ return -ENAMETOOLONG;
+
+ fw_priv->size = 0;
+
+ /*
+ * The total file size is only examined when doing a partial
+ * read; the "full read" case needs to fail if the whole
+ * firmware was not completely loaded.
+ */
+ if ((fw_priv->opt_flags & FW_OPT_PARTIAL) && *bufp)
+ file_size_ptr = &file_size;
+
+ /* load firmware files from the mount namespace of init */
+ rc = kernel_read_file_from_path_initns(path, fw_priv->offset,
+ bufp, msize,
+ file_size_ptr,
+ READING_FIRMWARE);
+ if (rc < 0) {
+ if (!(fw_priv->opt_flags & FW_OPT_NO_WARN)) {
+ if (rc != -ENOENT)
+ dev_warn(device,
+ "loading %s failed with error %d\n",
+ path, rc);
+ else
+ dev_dbg(device,
+ "loading %s failed for no such file or directory.\n",
+ path);
+ }
+ return rc;
+ }
+ size = rc;
+
+ dev_dbg(device, "Loading firmware from %s\n", path);
+ if (decompress) {
+ dev_dbg(device, "f/w decompressing %s\n",
+ fw_priv->fw_name);
+ rc = decompress(device, fw_priv, size, *bufp);
+ /* discard the superfluous original content */
+ vfree(*bufp);
+ *bufp = NULL;
+ if (rc) {
+ fw_free_paged_buf(fw_priv);
+ return rc;
+ }
+ } else {
+ dev_dbg(device, "direct-loading %s\n",
+ fw_priv->fw_name);
+ if (!fw_priv->data)
+ fw_priv->data = *bufp;
+ fw_priv->size = size;
+ }
+ fw_state_done(fw_priv);
+ return 0;
+}
static int
fw_get_filesystem_firmware(struct device *device, struct fw_priv *fw_priv,
@@ -493,10 +565,9 @@ fw_get_filesystem_firmware(struct device *device, struct fw_priv *fw_priv,
size_t in_size,
const void *in_buffer))
{
- size_t size;
- int i, len, maxlen = 0;
+ int i;
int rc = -ENOENT;
- char *path, *nt = NULL;
+ char *path;
size_t msize = INT_MAX;
void *buffer = NULL;
@@ -511,83 +582,69 @@ fw_get_filesystem_firmware(struct device *device, struct fw_priv *fw_priv,
return -ENOMEM;
wait_for_initramfs();
- for (i = 0; i < ARRAY_SIZE(fw_path); i++) {
- size_t file_size = 0;
- size_t *file_size_ptr = NULL;
-
- /* skip the unset customized path */
- if (!fw_path[i][0])
- continue;
-
- /* strip off \n from customized path */
- maxlen = strlen(fw_path[i]);
- if (i == 0) {
- nt = strchr(fw_path[i], '\n');
- if (nt)
- maxlen = nt - fw_path[i];
- }
- len = snprintf(path, PATH_MAX, "%.*s/%s%s",
- maxlen, fw_path[i],
- fw_priv->fw_name, suffix);
- if (len >= PATH_MAX) {
- rc = -ENAMETOOLONG;
- break;
- }
+ /* Try each ':'-separated path in fw_path_para first */
+ if (fw_path_para[0]) {
+ const char *start = fw_path_para;
+ const char *p;
+ char *dir;
- fw_priv->size = 0;
+ dir = __getname();
+ if (!dir) {
+ rc = -ENOMEM;
+ goto done;
+ }
- /*
- * The total file size is only examined when doing a partial
- * read; the "full read" case needs to fail if the whole
- * firmware was not completely loaded.
- */
- if ((fw_priv->opt_flags & FW_OPT_PARTIAL) && buffer)
- file_size_ptr = &file_size;
-
- /* load firmware files from the mount namespace of init */
- rc = kernel_read_file_from_path_initns(path, fw_priv->offset,
- &buffer, msize,
- file_size_ptr,
- READING_FIRMWARE);
- if (rc < 0) {
- if (!(fw_priv->opt_flags & FW_OPT_NO_WARN)) {
- if (rc != -ENOENT)
- dev_warn(device,
- "loading %s failed with error %d\n",
- path, rc);
- else
- dev_dbg(device,
- "loading %s failed for no such file or directory.\n",
- path);
+ while (*start) {
+ int dirlen = 0;
+
+ /*
+ * Parse the next path component. A backslash
+ * escapes the following character, allowing
+ * literal ':' ('\:') and literal '\' ('\\')
+ * to be embedded in a path.
+ */
+ for (p = start; *p && *p != ':'; p++) {
+ if (p[0] == '\\' && (p[1] == ':' || p[1] == '\\'))
+ p++;
+ if (dirlen < PATH_MAX - 1)
+ dir[dirlen++] = *p;
}
- continue;
- }
- size = rc;
- rc = 0;
-
- dev_dbg(device, "Loading firmware from %s\n", path);
- if (decompress) {
- dev_dbg(device, "f/w decompressing %s\n",
- fw_priv->fw_name);
- rc = decompress(device, fw_priv, size, buffer);
- /* discard the superfluous original content */
- vfree(buffer);
- buffer = NULL;
- if (rc) {
- fw_free_paged_buf(fw_priv);
- continue;
+
+ /* strip trailing newline */
+ if (dirlen > 0 && dir[dirlen - 1] == '\n')
+ dirlen--;
+
+ if (dirlen > 0) {
+ dir[dirlen] = '\0';
+ rc = fw_try_firmware_path(device, fw_priv,
+ suffix, decompress,
+ dir, dirlen,
+ path, &buffer,
+ msize);
+ if (!rc) {
+ __putname(dir);
+ goto done;
+ }
}
- } else {
- dev_dbg(device, "direct-loading %s\n",
- fw_priv->fw_name);
- if (!fw_priv->data)
- fw_priv->data = buffer;
- fw_priv->size = size;
+
+ if (!*p)
+ break;
+ start = p + 1;
}
- fw_state_done(fw_priv);
- break;
+ __putname(dir);
}
+
+ /* Try default firmware paths */
+ for (i = 0; i < ARRAY_SIZE(fw_path); i++) {
+ rc = fw_try_firmware_path(device, fw_priv, suffix, decompress,
+ fw_path[i], strlen(fw_path[i]),
+ path, &buffer, msize);
+ if (!rc)
+ break;
+ }
+
+done:
__putname(path);
return rc;
---
base-commit: 2d1373e4246da3b58e1df058374ed6b101804e07
change-id: 20260317-fw-path-a094c30259a5
Best regards,
--
Jeff Layton <jlayton@kernel.org>
On Wed, Mar 18, 2026 at 03:54:02PM -0400, Jeff Layton wrote:
> Refactor fw_get_filesystem_firmware() by extracting the per-path
> firmware loading logic into a new fw_try_firmware_path() helper.
>
> Use this helper to parse fw_path_para for ':'-separated paths,
> trying each one before falling through to the default firmware
> search paths. This allows users to specify multiple custom firmware
> directories via firmware_class.path, e.g.:
>
> firmware_class.path=/custom/path1:/custom/path2
>
> A backslash can be used as an escape character, allowing a literal
> ':' ("\:") or literal '\' ("\\") to be embedded in a pathname.
This is a mess, what could go wrong embedding another parser in the
kernel :)
Let's step back, why is this needed at all? The kernel already supports
multiple standard locations for firmware paths, and one custom location.
Why do we now need more than that? What changed to require this and who
is going to use it (and support it, and actually test it?)
We really want to make the number of firmware paths less, not more. But
if we _really_ need multiple paths, isn't it simpler to just have an
array of paths here, not be forced to parse escape codes like you are
now doing?
thanks,
greg k-h
On Thu, 2026-03-19 at 07:23 +0100, Greg Kroah-Hartman wrote:
> On Wed, Mar 18, 2026 at 03:54:02PM -0400, Jeff Layton wrote:
> > Refactor fw_get_filesystem_firmware() by extracting the per-path
> > firmware loading logic into a new fw_try_firmware_path() helper.
> >
> > Use this helper to parse fw_path_para for ':'-separated paths,
> > trying each one before falling through to the default firmware
> > search paths. This allows users to specify multiple custom firmware
> > directories via firmware_class.path, e.g.:
> >
> > firmware_class.path=/custom/path1:/custom/path2
> >
> > A backslash can be used as an escape character, allowing a literal
> > ':' ("\:") or literal '\' ("\\") to be embedded in a pathname.
>
> This is a mess, what could go wrong embedding another parser in the
> kernel :)
>
> Let's step back, why is this needed at all? The kernel already supports
> multiple standard locations for firmware paths, and one custom location.
> Why do we now need more than that? What changed to require this and who
> is going to use it (and support it, and actually test it?)
>
We have at least one internal user that requested the ability to do
this. I'll see if they can articulate their use-case better.
> We really want to make the number of firmware paths less, not more. But
> if we _really_ need multiple paths, isn't it simpler to just have an
> array of paths here, not be forced to parse escape codes like you are
> now doing?
>
How would one feed an array of paths to the module without delimiting
them in some fashion?
--
Jeff Layton <jlayton@kernel.org>
On Thu, Mar 19, 2026 at 07:34:46AM -0400, Jeff Layton wrote:
> On Thu, 2026-03-19 at 07:23 +0100, Greg Kroah-Hartman wrote:
> > On Wed, Mar 18, 2026 at 03:54:02PM -0400, Jeff Layton wrote:
> > > Refactor fw_get_filesystem_firmware() by extracting the per-path
> > > firmware loading logic into a new fw_try_firmware_path() helper.
> > >
> > > Use this helper to parse fw_path_para for ':'-separated paths,
> > > trying each one before falling through to the default firmware
> > > search paths. This allows users to specify multiple custom firmware
> > > directories via firmware_class.path, e.g.:
> > >
> > > firmware_class.path=/custom/path1:/custom/path2
> > >
> > > A backslash can be used as an escape character, allowing a literal
> > > ':' ("\:") or literal '\' ("\\") to be embedded in a pathname.
> >
> > This is a mess, what could go wrong embedding another parser in the
> > kernel :)
> >
> > Let's step back, why is this needed at all? The kernel already supports
> > multiple standard locations for firmware paths, and one custom location.
> > Why do we now need more than that? What changed to require this and who
> > is going to use it (and support it, and actually test it?)
> >
>
> We have at least one internal user that requested the ability to do
> this. I'll see if they can articulate their use-case better.
Please do.
> > We really want to make the number of firmware paths less, not more. But
> > if we _really_ need multiple paths, isn't it simpler to just have an
> > array of paths here, not be forced to parse escape codes like you are
> > now doing?
> >
>
> How would one feed an array of paths to the module without delimiting
> them in some fashion?
I don't know, but once you start attempting to "escape" things, the
complexity goes up a lot and makes me think that this all isn't a good
idea :)
thanks,
greg k-h
On Thu, 2026-03-19 at 12:39 +0100, Greg Kroah-Hartman wrote:
> On Thu, Mar 19, 2026 at 07:34:46AM -0400, Jeff Layton wrote:
> > On Thu, 2026-03-19 at 07:23 +0100, Greg Kroah-Hartman wrote:
> > > On Wed, Mar 18, 2026 at 03:54:02PM -0400, Jeff Layton wrote:
> > > > Refactor fw_get_filesystem_firmware() by extracting the per-path
> > > > firmware loading logic into a new fw_try_firmware_path() helper.
> > > >
> > > > Use this helper to parse fw_path_para for ':'-separated paths,
> > > > trying each one before falling through to the default firmware
> > > > search paths. This allows users to specify multiple custom firmware
> > > > directories via firmware_class.path, e.g.:
> > > >
> > > > firmware_class.path=/custom/path1:/custom/path2
> > > >
> > > > A backslash can be used as an escape character, allowing a literal
> > > > ':' ("\:") or literal '\' ("\\") to be embedded in a pathname.
> > >
> > > This is a mess, what could go wrong embedding another parser in the
> > > kernel :)
> > >
> > > Let's step back, why is this needed at all? The kernel already supports
> > > multiple standard locations for firmware paths, and one custom location.
> > > Why do we now need more than that? What changed to require this and who
> > > is going to use it (and support it, and actually test it?)
> > >
> >
> > We have at least one internal user that requested the ability to do
> > this. I'll see if they can articulate their use-case better.
>
> Please do.
>
Michal said he'll outline his use-case.
> > > We really want to make the number of firmware paths less, not more. But
> > > if we _really_ need multiple paths, isn't it simpler to just have an
> > > array of paths here, not be forced to parse escape codes like you are
> > > now doing?
> > >
> >
> > How would one feed an array of paths to the module without delimiting
> > them in some fashion?
>
> I don't know, but once you start attempting to "escape" things, the
> complexity goes up a lot and makes me think that this all isn't a good
> idea :)
>
Fair point, but the escaping here is pretty tame -- It's only escaping
':' and '\'. For better or worse, UNIX has very few characters that are
not allowed to be embedded in filenames, so our options for doing this
are somewhat limited.
If we really don't want to deal with escaping, then another option
might be to add a fixed number of path strings "slots" as parameters
(i.e. path1=/foo,path2=/bar,path3=...).
That seems uglier and more limiting than dealing with escapes though.
--
Jeff Layton <jlayton@kernel.org>
> On 19 Mar 2026, at 11:47, Jeff Layton <jlayton@kernel.org> wrote:
>
> On Thu, 2026-03-19 at 12:39 +0100, Greg Kroah-Hartman wrote:
>> On Thu, Mar 19, 2026 at 07:34:46AM -0400, Jeff Layton wrote:
>>> On Thu, 2026-03-19 at 07:23 +0100, Greg Kroah-Hartman wrote:
>>>> On Wed, Mar 18, 2026 at 03:54:02PM -0400, Jeff Layton wrote:
>>>>> Refactor fw_get_filesystem_firmware() by extracting the per-path
>>>>> firmware loading logic into a new fw_try_firmware_path() helper.
>>>>>
>>>>> Use this helper to parse fw_path_para for ':'-separated paths,
>>>>> trying each one before falling through to the default firmware
>>>>> search paths. This allows users to specify multiple custom firmware
>>>>> directories via firmware_class.path, e.g.:
>>>>>
>>>>> firmware_class.path=/custom/path1:/custom/path2
>>>>>
>>>>> A backslash can be used as an escape character, allowing a literal
>>>>> ':' ("\:") or literal '\' ("\\") to be embedded in a pathname.
>>>>
>>>> This is a mess, what could go wrong embedding another parser in the
>>>> kernel :)
>>>>
>>>> Let's step back, why is this needed at all? The kernel already supports
>>>> multiple standard locations for firmware paths, and one custom location.
>>>> Why do we now need more than that? What changed to require this and who
>>>> is going to use it (and support it, and actually test it?)
>>>>
>>>
>>> We have at least one internal user that requested the ability to do
>>> this. I'll see if they can articulate their use-case better.
>>
>> Please do.
>>
>
> Michal said he'll outline his use-case.
Internally, we distribute firmware binaries as read-only snapshots, and a system may have more than one. Without this feature, we must maintain a symlink farm to merge multiple snapshots into a single path. We would love to remove this workaround and switch to just passing multiple paths.
Also a common pattern I seen in vendor shell scripts is temporarily setting firmware_class.path to the current working directory, loading the module, and then restoring firmware_class.path to its previous value, with this feature it could be made safer.
Thanks,
Michal Grzedzicki
On Thu, Mar 19, 2026 at 02:13:09PM +0000, Michal Grzedzicki wrote:
>
> > On 19 Mar 2026, at 11:47, Jeff Layton <jlayton@kernel.org> wrote:
> >
> > On Thu, 2026-03-19 at 12:39 +0100, Greg Kroah-Hartman wrote:
> >> On Thu, Mar 19, 2026 at 07:34:46AM -0400, Jeff Layton wrote:
> >>> On Thu, 2026-03-19 at 07:23 +0100, Greg Kroah-Hartman wrote:
> >>>> On Wed, Mar 18, 2026 at 03:54:02PM -0400, Jeff Layton wrote:
> >>>>> Refactor fw_get_filesystem_firmware() by extracting the per-path
> >>>>> firmware loading logic into a new fw_try_firmware_path() helper.
> >>>>>
> >>>>> Use this helper to parse fw_path_para for ':'-separated paths,
> >>>>> trying each one before falling through to the default firmware
> >>>>> search paths. This allows users to specify multiple custom firmware
> >>>>> directories via firmware_class.path, e.g.:
> >>>>>
> >>>>> firmware_class.path=/custom/path1:/custom/path2
> >>>>>
> >>>>> A backslash can be used as an escape character, allowing a literal
> >>>>> ':' ("\:") or literal '\' ("\\") to be embedded in a pathname.
> >>>>
> >>>> This is a mess, what could go wrong embedding another parser in the
> >>>> kernel :)
> >>>>
> >>>> Let's step back, why is this needed at all? The kernel already supports
> >>>> multiple standard locations for firmware paths, and one custom location.
> >>>> Why do we now need more than that? What changed to require this and who
> >>>> is going to use it (and support it, and actually test it?)
> >>>>
> >>>
> >>> We have at least one internal user that requested the ability to do
> >>> this. I'll see if they can articulate their use-case better.
> >>
> >> Please do.
> >>
> >
> > Michal said he'll outline his use-case.
>
>
> Internally, we distribute firmware binaries as read-only snapshots, and a system may have more than one. Without this feature, we must maintain a symlink farm to merge multiple snapshots into a single path. We would love to remove this workaround and switch to just passing multiple paths.
>
> Also a common pattern I seen in vendor shell scripts is temporarily setting firmware_class.path to the current working directory, loading the module, and then restoring firmware_class.path to its previous value, with this feature it could be made safer.
How would putting a bunch of different filepaths be "safer"? A shell
script will have to read the value, append their path to it, and then
write it back? And how will that ever work given that they will not
know if this is a kernel version that can support multiple paths in a
single value?
I think if you are going to change the way the option works, it needs to
be renamed so that everyone "knows" they can rely on it, otherwise no
one will use it.
thanks,
greg k-h
On Thu, 2026-03-19 at 16:30 +0100, Greg Kroah-Hartman wrote:
> On Thu, Mar 19, 2026 at 02:13:09PM +0000, Michal Grzedzicki wrote:
> >
> > > On 19 Mar 2026, at 11:47, Jeff Layton <jlayton@kernel.org> wrote:
> > >
> > > On Thu, 2026-03-19 at 12:39 +0100, Greg Kroah-Hartman wrote:
> > > > On Thu, Mar 19, 2026 at 07:34:46AM -0400, Jeff Layton wrote:
> > > > > On Thu, 2026-03-19 at 07:23 +0100, Greg Kroah-Hartman wrote:
> > > > > > On Wed, Mar 18, 2026 at 03:54:02PM -0400, Jeff Layton wrote:
> > > > > > > Refactor fw_get_filesystem_firmware() by extracting the per-path
> > > > > > > firmware loading logic into a new fw_try_firmware_path() helper.
> > > > > > >
> > > > > > > Use this helper to parse fw_path_para for ':'-separated paths,
> > > > > > > trying each one before falling through to the default firmware
> > > > > > > search paths. This allows users to specify multiple custom firmware
> > > > > > > directories via firmware_class.path, e.g.:
> > > > > > >
> > > > > > > firmware_class.path=/custom/path1:/custom/path2
> > > > > > >
> > > > > > > A backslash can be used as an escape character, allowing a literal
> > > > > > > ':' ("\:") or literal '\' ("\\") to be embedded in a pathname.
> > > > > >
> > > > > > This is a mess, what could go wrong embedding another parser in the
> > > > > > kernel :)
> > > > > >
> > > > > > Let's step back, why is this needed at all? The kernel already supports
> > > > > > multiple standard locations for firmware paths, and one custom location.
> > > > > > Why do we now need more than that? What changed to require this and who
> > > > > > is going to use it (and support it, and actually test it?)
> > > > > >
> > > > >
> > > > > We have at least one internal user that requested the ability to do
> > > > > this. I'll see if they can articulate their use-case better.
> > > >
> > > > Please do.
> > > >
> > >
> > > Michal said he'll outline his use-case.
> >
> >
> > Internally, we distribute firmware binaries as read-only snapshots, and a system may have more than one. Without this feature, we must maintain a symlink farm to merge multiple snapshots into a single path. We would love to remove this workaround and switch to just passing multiple paths.
> >
> > Also a common pattern I seen in vendor shell scripts is temporarily setting firmware_class.path to the current working directory, loading the module, and then restoring firmware_class.path to its previous value, with this feature it could be made safer.
>
> How would putting a bunch of different filepaths be "safer"? A shell
> script will have to read the value, append their path to it, and then
> write it back?
>
It's safer in that you don't have to have a shell script monkeying with
the path string.
> And how will that ever work given that they will not
> know if this is a kernel version that can support multiple paths in a
> single value?
>
> I think if you are going to change the way the option works, it needs to
> be renamed so that everyone "knows" they can rely on it, otherwise no
> one will use it.
>
That is a valid point though. I'd be open to adding a separate module
option for this. Some name ideas:
paths=
searchpath=
search=
Anyone have opinions?
--
Jeff Layton <jlayton@kernel.org>
On Thu, Mar 19, 2026 at 07:47:31AM -0400, Jeff Layton wrote:
> On Thu, 2026-03-19 at 12:39 +0100, Greg Kroah-Hartman wrote:
> > On Thu, Mar 19, 2026 at 07:34:46AM -0400, Jeff Layton wrote:
> > > On Thu, 2026-03-19 at 07:23 +0100, Greg Kroah-Hartman wrote:
> > > > On Wed, Mar 18, 2026 at 03:54:02PM -0400, Jeff Layton wrote:
> > > > > Refactor fw_get_filesystem_firmware() by extracting the per-path
> > > > > firmware loading logic into a new fw_try_firmware_path() helper.
> > > > >
> > > > > Use this helper to parse fw_path_para for ':'-separated paths,
> > > > > trying each one before falling through to the default firmware
> > > > > search paths. This allows users to specify multiple custom firmware
> > > > > directories via firmware_class.path, e.g.:
> > > > >
> > > > > firmware_class.path=/custom/path1:/custom/path2
> > > > >
> > > > > A backslash can be used as an escape character, allowing a literal
> > > > > ':' ("\:") or literal '\' ("\\") to be embedded in a pathname.
> > > >
> > > > This is a mess, what could go wrong embedding another parser in the
> > > > kernel :)
> > > >
> > > > Let's step back, why is this needed at all? The kernel already supports
> > > > multiple standard locations for firmware paths, and one custom location.
> > > > Why do we now need more than that? What changed to require this and who
> > > > is going to use it (and support it, and actually test it?)
> > > >
> > >
> > > We have at least one internal user that requested the ability to do
> > > this. I'll see if they can articulate their use-case better.
> >
> > Please do.
> >
>
> Michal said he'll outline his use-case.
>
> > > > We really want to make the number of firmware paths less, not more. But
> > > > if we _really_ need multiple paths, isn't it simpler to just have an
> > > > array of paths here, not be forced to parse escape codes like you are
> > > > now doing?
> > > >
> > >
> > > How would one feed an array of paths to the module without delimiting
> > > them in some fashion?
> >
> > I don't know, but once you start attempting to "escape" things, the
> > complexity goes up a lot and makes me think that this all isn't a good
> > idea :)
> >
>
> Fair point, but the escaping here is pretty tame -- It's only escaping
> ':' and '\'. For better or worse, UNIX has very few characters that are
> not allowed to be embedded in filenames, so our options for doing this
> are somewhat limited.
>
> If we really don't want to deal with escaping, then another option
> might be to add a fixed number of path strings "slots" as parameters
> (i.e. path1=/foo,path2=/bar,path3=...).
>
> That seems uglier and more limiting than dealing with escapes though.
For some reason, I thought we used to have more than one "path" that
userspace could pick for this, but we got rid of them all to just use
one. So you might want to dig through the past history of this feature
to see why we did that?
thanks,
greg k-h
© 2016 - 2026 Red Hat, Inc.