kmodloader: support loadable module parameters in modinfo
authorTony Ambardar <itugrok@yahoo.com>
Fri, 1 Dec 2023 09:40:17 +0000 (01:40 -0800)
committerTony Ambardar <itugrok@yahoo.com>
Tue, 16 Jan 2024 01:54:35 +0000 (17:54 -0800)
Current OpenWrt loadable modules embed details of parameters accepted on
loading, but these aren't shown to users. Enable modinfo to print this
information like most other distros. For example:

  root@OpenWrt:/# modinfo mac80211
  filename:       /lib/modules/6.1.65/mac80211.ko
  license:        GPL
  depends:        cfg80211,compat
  name:           mac80211
  vermagic:       6.1.65 SMP mod_unload MIPS32_R2 32BIT
  parm:           minstrel_vht_only (bool)
  parm:           max_nullfunc_tries (int)
  parm:           max_probe_tries (int)
  parm:           beacon_loss_count (int)
  parm:           probe_wait_ms (int)
  parm:           ieee80211_default_rc_algo (charp)

Signed-off-by: Tony Ambardar <itugrok@yahoo.com>
kmodloader.c

index 0afc79560693e9a67bf0ca74a0dfd934b5387e75..8d06ff15a5fa2dadda8fcda3ea69b6e7350f9f18 100644 (file)
 #include <libubox/utils.h>
 #include <libubox/ulog.h>
 #include <libubox/kvlist.h>
+#include <libubox/list.h>
 
 #define DEF_MOD_PATH "/modules/%s/"
 /* duplicated from in-kernel include/linux/module.h */
 #define MODULE_NAME_LEN (64 - sizeof(unsigned long))
 
+struct param {
+       char *name;
+       char *desc;
+       char *type;
+       struct list_head list;
+};
+
 enum {
        SCANNED,
        PROBE,
@@ -495,10 +503,13 @@ static int print_modinfo(char *module)
 {
        int fd = open(module, O_RDONLY);
        unsigned int offset, size;
+       struct param *p;
        struct stat s;
        char *map = MAP_FAILED, *strings;
        int rv = -1;
 
+       LIST_HEAD(params);
+
        if (fd < 0) {
                ULOG_ERR("failed to open %s\n", module);
                goto out;
@@ -523,8 +534,9 @@ static int print_modinfo(char *module)
        strings = map + offset;
        printf("module:\t\t%s\n", module);
        while (true) {
+               char *pname, *pdata;
                char *dup = NULL;
-               char *sep;
+               char *sep, *sep2;
 
                while (!strings[0])
                        strings++;
@@ -540,12 +552,49 @@ static int print_modinfo(char *module)
                                printf("%s:\t\t%s\n",  dup, sep);
                        else
                                printf("%s:\t%s\n",  dup, sep);
+               } else {
+                       sep2 = strstr(sep, ":");
+                       if (!sep2)
+                               break;
+                       pname = strndup(sep, sep2 - sep);
+                       sep2++;
+                       pdata = strdup(sep2);
+
+                       list_for_each_entry(p, &params, list)
+                               if (!strcmp(pname, p->name))
+                                       break;
+
+                       if (list_entry_is_h(p, &params, list)) {
+                               p = alloca(sizeof(*p));
+                               p->name = pname;
+                               p->desc = p->type = NULL;
+                               list_add(&p->list, &params);
+                       } else {
+                               free(pname);
+                       }
+
+                       if (!strcmp(dup, "parmtype"))
+                               p->type = pdata;
+                       else
+                               p->desc = pdata;
                }
                strings = &sep[strlen(sep)];
                if (dup)
                        free(dup);
        }
 
+       list_for_each_entry(p, &params, list) {
+               printf("parm:\t\t%s",  p->name);
+               if (p->desc)
+                       printf(":%s", p->desc);
+               if (p->type)
+                       printf(" (%s)", p->type);
+               printf("\n");
+               free(p->name);
+               free(p->desc);
+               free(p->type);
+       }
+
        rv = 0;
 
 out: