From 5bf8d0efa7e02f26dfa08ac68b2d62021bfc3fda Mon Sep 17 00:00:00 2001
From: ryang <decatf@gmail.com>
Date: Thu, 28 Jun 2018 13:22:50 -0400
Subject: [PATCH] module: Use QEMU_MODULE_PATH as a search path

The current paths for modules are CONFIG_QEMU_MODDIR and paths relative
to the executable. Qemu and its modules can be installed / executed in
paths that are different from the current search paths. This change allows
a search path to be specified by environment variable.

An example usage for this is postmarketOS. This is a build environment for
Alpine Linux. It sets up an Alpine Linux chroot environment. Alpine's Qemu
packages are installed in the chroot. The Alpine Linux Qemu package is used
to test compiled Alpine Linux system images. This way there isn't a
reliance on the which ever version of Qemu the host system / distro
might provide.

postmarketOS executes Qemu on host system outside of the chroot
The Qemu module search path needs to point to the location of the
chroot relative to the host system.

e.g.
The root of the Alpine Linux chroot is:
~/.local/var/pmbootstrap/chroot_native/
The Qemu module search path needs to be:
QEMU_MODULE_PATH=~/.local/var/pmbootstrap/chroot_native/usr/lib/qemu/

Signed-off-by: ryang <decatf@gmail.com>
---
 util/module.c | 21 +++++++++++++--------
 1 file changed, 13 insertions(+), 8 deletions(-)

diff --git a/util/module.c b/util/module.c
index c909737..f9088a5 100644
--- a/util/module.c
+++ b/util/module.c
@@ -162,9 +162,10 @@ void module_load_one(const char *prefix, const char *lib_name)
 #ifdef CONFIG_MODULES
     char *fname = NULL;
     char *exec_dir;
-    char *dirs[3];
+    char *search_path;
+    char *dirs[4];
     char *module_name;
-    int i = 0;
+    int i = 0, n_dirs;
     int ret;
     static GHashTable *loaded_modules;
 
@@ -186,14 +187,18 @@ void module_load_one(const char *prefix, const char *lib_name)
     g_hash_table_insert(loaded_modules, module_name, module_name);
 
     exec_dir = qemu_get_exec_dir();
-    dirs[i++] = g_strdup_printf("%s", CONFIG_QEMU_MODDIR);
-    dirs[i++] = g_strdup_printf("%s/..", exec_dir ? : "");
-    dirs[i++] = g_strdup_printf("%s", exec_dir ? : "");
-    assert(i == ARRAY_SIZE(dirs));
+    search_path = getenv("QEMU_MODULE_PATH");
+    if (search_path != NULL)
+        dirs[n_dirs++] = g_strdup_printf("%s", search_path);
+    dirs[n_dirs++] = g_strdup_printf("%s", CONFIG_QEMU_MODDIR);
+    dirs[n_dirs++] = g_strdup_printf("%s/..", exec_dir ? : "");
+    dirs[n_dirs++] = g_strdup_printf("%s", exec_dir ? : "");
+    assert(n_dirs <= ARRAY_SIZE(dirs));
+
     g_free(exec_dir);
     exec_dir = NULL;
 
-    for (i = 0; i < ARRAY_SIZE(dirs); i++) {
+    for (i = 0; i < n_dirs; i++) {
         fname = g_strdup_printf("%s/%s%s",
                 dirs[i], module_name, HOST_DSOSUF);
         ret = module_load_file(fname);
@@ -205,7 +210,7 @@ void module_load_one(const char *prefix, const char *lib_name)
         }
     }
 
-    for (i = 0; i < ARRAY_SIZE(dirs); i++) {
+    for (i = 0; i < n_dirs; i++) {
         g_free(dirs[i]);
     }
 
-- 
2.7.4

