summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAaron Plattner <aplattner@nvidia.com>2015-08-03 10:02:16 -0700
committerAaron Plattner <aplattner@nvidia.com>2015-08-03 10:02:16 -0700
commit34f4c891167075210bba38ea063c771347ca55f6 (patch)
treecee1d74b36498030cd185c4d52505a4fdc54c136
parent93549f66b29cbbc5d88de96ca74e8623d5251899 (diff)
355.06355.06
-rw-r--r--Makefile2
-rw-r--r--backup.c30
-rw-r--r--command-list.c65
-rw-r--r--common-utils/nvgetopt.c35
-rw-r--r--conflicting-kernel-modules.c38
-rw-r--r--conflicting-kernel-modules.h26
-rw-r--r--dist-files.mk2
-rw-r--r--files.c283
-rw-r--r--files.h5
-rw-r--r--install-from-cwd.c337
-rw-r--r--kernel.c1156
-rw-r--r--kernel.h19
-rw-r--r--manifest.c124
-rw-r--r--misc.c4
-rw-r--r--nvidia-installer.c28
-rw-r--r--nvidia-installer.h51
-rw-r--r--option_table.h18
-rwxr-xr-xrtld_test_Linux-armv7l-gnueabibin3892 -> 2808 bytes
-rwxr-xr-xrtld_test_Linux-armv7l-gnueabihfbin5540 -> 2820 bytes
-rwxr-xr-xrtld_test_Linux-x86bin3056 -> 2668 bytes
-rwxr-xr-xrtld_test_Linux-x86_64bin4688 -> 3800 bytes
-rw-r--r--version.mk2
22 files changed, 1164 insertions, 1061 deletions
diff --git a/Makefile b/Makefile
index 2247002..dc6984d 100644
--- a/Makefile
+++ b/Makefile
@@ -308,7 +308,7 @@ tls_test: tls_test.c
# nvidia-installer to simplify x86-64 builds.
rebuild_rtld_test: rtld_test.c $(CONFIG_H)
- $(call quiet_cmd,LINK) $(CFLAGS) $(LDFLAGS) $(BIN_LDFLAGS) -o $(RTLD_TEST) -lGL $<
+ $(call quiet_cmd,LINK) $(CFLAGS) $(LDFLAGS) $(BIN_LDFLAGS) -o $(RTLD_TEST) -lGL -lEGL $<
$(call quiet_cmd,STRIP_CMD) $(RTLD_TEST)
# dummy rule to override implicit rule that builds dls_test from
diff --git a/backup.c b/backup.c
index 60d408f..39e58c3 100644
--- a/backup.c
+++ b/backup.c
@@ -41,13 +41,12 @@
#include "crc.h"
#include "misc.h"
#include "kernel.h"
+#include "conflicting-kernel-modules.h"
#define BACKUP_DIRECTORY "/var/lib/nvidia"
#define BACKUP_LOG (BACKUP_DIRECTORY "/log")
#define BACKUP_MKDIR_LOG (BACKUP_DIRECTORY "/dirs")
-#define RMMOD_MODULE_NAME "nvidia"
-
@@ -623,18 +622,6 @@ static int rmdir_recursive(Options *op)
-/* unload_nvidia_module() - unload nvidia${suffix}.ko, ignoring failures. */
-
-static void unload_nvidia_module(Options *op, const char *suffix)
-{
- char *name;
- name = nvstrcat(RMMOD_MODULE_NAME, suffix, NULL);
- rmmod_kernel_module(op, name);
- nvfree(name);
-}
-
-
-
/*
* do_uninstall() - this function uninstalls a previously installed
* driver, by parsing the BACKUP_LOG file.
@@ -840,20 +827,9 @@ static int do_uninstall(Options *op, const char *version)
* module might not have existed at all.
*/
- unload_nvidia_module(op, "-uvm");
-
- unload_nvidia_module(op, "");
-
- for (i = 0; i < NV_MAX_MODULE_INSTANCES; i++) {
- char num[5];
- memset(num, 0, sizeof(num));
- snprintf(num, sizeof(num), "%d", i);
- num[sizeof(num) - 1] = '\0';
-
- unload_nvidia_module(op, num);
+ for (i = 0; i < num_conflicting_kernel_modules; i++) {
+ rmmod_kernel_module(op, conflicting_kernel_modules[i]);
}
-
- unload_nvidia_module(op, "-frontend");
}
run_distro_hook(op, "post-uninstall");
diff --git a/command-list.c b/command-list.c
index d65440c..7dc5933 100644
--- a/command-list.c
+++ b/command-list.c
@@ -43,13 +43,12 @@
#include "files.h"
#include "kernel.h"
#include "manifest.h"
+#include "conflicting-kernel-modules.h"
static void free_file_list(FileList* l);
-static void find_conflicting_kernel_modules(Options *op,
- Package *p,
- FileList *l);
+static void find_conflicting_kernel_modules(Options *op, FileList *l);
static void find_existing_files(Package *p, FileList *l,
PackageEntryFileTypeList *file_type_list);
@@ -207,8 +206,9 @@ CommandList *build_command_list(Options *op, Package *p)
/* find any possibly conflicting modules and/or libraries */
- if (!op->no_kernel_module || op->dkms)
- find_conflicting_kernel_modules(op, p, l);
+ if (!op->no_kernel_module || op->dkms) {
+ find_conflicting_kernel_modules(op, l);
+ }
/* check the conflicting file list for any installed kernel modules */
@@ -377,14 +377,6 @@ CommandList *build_command_list(Options *op, Package *p)
}
}
- /* find any commands we should run */
-
- for (i = 0; i < p->num_entries; i++) {
- if (p->entries[i].type == FILE_TYPE_KERNEL_MODULE_CMD) {
- add_command(c, RUN_CMD, p->entries[i].file, NULL, 0);
- }
- }
-
/*
* if "--no-abi-note" was requested, scan for any OpenGL
* libraries, and run the following command on them:
@@ -625,13 +617,13 @@ int execute_command_list(Options *op, CommandList *c,
* modules under the kernel module installation prefix.
*/
-static void find_conflicting_kernel_modules(Options *op,
- Package *p, FileList *l)
+static void find_conflicting_kernel_modules(Options *op, FileList *l)
{
- int i = 0, n = 0;
- ConflictingFileInfo files[2];
+ int i = 0;
+ ConflictingFileInfo *files;
char *paths[3];
char *tmp = get_kernel_name(op);
+ char **filenames;
/* Don't descend into the "build" or "source" directories; these won't
* contain modules, and may be symlinks back to an actual source tree. */
@@ -641,9 +633,6 @@ static void find_conflicting_kernel_modules(Options *op,
{ 0, NULL }
};
- memset(files, 0, sizeof(files));
- files[1].name = NULL;
- files[1].len = 0;
if (op->kernel_module_installation_path) {
paths[i++] = op->kernel_module_installation_path;
}
@@ -653,18 +642,25 @@ static void find_conflicting_kernel_modules(Options *op,
}
paths[i] = NULL;
-
+
+ /* Build the list of conflicting kernel modules */
+
+ files = nvalloc((num_conflicting_kernel_modules + 1) * sizeof(files[0]));
+ filenames = nvalloc(num_conflicting_kernel_modules * sizeof(filenames[0]));
+
+ for (i = 0; i < num_conflicting_kernel_modules; i++) {
+ filenames[i] = nvstrcat(conflicting_kernel_modules[i], ".ko", NULL);
+ files[i].name = filenames[i];
+ files[i].len = strlen(filenames[i]);
+ }
+
for (i = 0; paths[i]; i++) {
- for (n = 0; p->bad_module_filenames[n]; n++) {
- /*
- * Recursively search for this conflicting kernel module
- * relative to the current prefix.
- */
- files[0].name = p->bad_module_filenames[n];
- files[0].len = strlen(files[0].name);
+ /*
+ * Recursively search for the conflicting kernel modules
+ * relative to the current prefix.
+ */
- find_conflicting_files(op, paths[i], files, l, skipdirs);
- }
+ find_conflicting_files(op, paths[i], files, l, skipdirs);
}
/* free any paths we nvstrcat()'d above */
@@ -673,7 +669,14 @@ static void find_conflicting_kernel_modules(Options *op,
nvfree(paths[i]);
}
-} /* find_conflicting_kernel_modules() */
+ /* free the kernel module names */
+
+ for (i = 0; i < num_conflicting_kernel_modules; i++) {
+ nvfree(filenames[i]);
+ }
+ nvfree(filenames);
+ nvfree(files);
+}
diff --git a/common-utils/nvgetopt.c b/common-utils/nvgetopt.c
index 1716495..286aee8 100644
--- a/common-utils/nvgetopt.c
+++ b/common-utils/nvgetopt.c
@@ -205,6 +205,41 @@ int nvgetopt(int argc,
}
}
+ /*
+ * If we still didn't find a match, maybe this is a short option
+ * with its argument value concatenated (e.g., "-j8"). For now,
+ * limit this to short options with integer argument values.
+ */
+ if (!o && intval) {
+
+ /* Is the string after the first character an integer? */
+ int appendedInteger = NVGETOPT_FALSE;
+ if ((name[0] != '\0') && (name[1] != '\0')) {
+ char *endptr;
+ strtol(name + 1, &endptr, 0);
+ if (*endptr == '\0') {
+ /*
+ * The only characters after the first character are
+ * parsable by strtol(3).
+ */
+ appendedInteger = NVGETOPT_TRUE;
+ }
+ }
+
+ if (appendedInteger) {
+ for (i = 0; options[i].name; i++) {
+ if ((options[i].flags & NVGETOPT_INTEGER_ARGUMENT) == 0) {
+ continue;
+ }
+ if (options[i].val == name[0]) {
+ o = &options[i];
+ argument = name + 1;
+ break;
+ }
+ }
+ }
+ }
+
/* if we didn't find an option, return */
if (!o) {
diff --git a/conflicting-kernel-modules.c b/conflicting-kernel-modules.c
new file mode 100644
index 0000000..74c33eb
--- /dev/null
+++ b/conflicting-kernel-modules.c
@@ -0,0 +1,38 @@
+/*
+ * nvidia-installer: A tool for installing NVIDIA software packages on
+ * Unix and Linux systems.
+ *
+ * Copyright (C) 2015 NVIDIA Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses>.
+ */
+
+#include "common-utils.h"
+
+/*
+ * A list of kernel modules that will conflict with this driver installation.
+ * The list should be maintained in reverse dependency order; i.e., it should
+ * be possible to unload kernel modules one at a time, in the order that they
+ * appear in this list.
+ */
+
+const char * const conflicting_kernel_modules[] = {
+ "nvidia-uvm",
+ "nvidia-modeset",
+ "nvidia",
+ "nvidia0", "nvidia1", "nvidia2", "nvidia3",
+ "nvidia4", "nvidia5", "nvidia6", "nvidia7",
+ "nvidia-frontend",
+};
+
+const int num_conflicting_kernel_modules = ARRAY_LEN(conflicting_kernel_modules);
diff --git a/conflicting-kernel-modules.h b/conflicting-kernel-modules.h
new file mode 100644
index 0000000..892a5a6
--- /dev/null
+++ b/conflicting-kernel-modules.h
@@ -0,0 +1,26 @@
+/*
+ * nvidia-installer: A tool for installing NVIDIA software packages on
+ * Unix and Linux systems.
+ *
+ * Copyright (C) 2015 NVIDIA Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses>.
+ */
+
+#ifndef __CONFLICTING_KERNEL_MODULES_H__
+#define __CONFLICTING_KERNEL_MODULES_H__
+
+extern const char * const conflicting_kernel_modules[];
+extern const int num_conflicting_kernel_modules;
+
+#endif
diff --git a/dist-files.mk b/dist-files.mk
index c4b104f..3be998b 100644
--- a/dist-files.mk
+++ b/dist-files.mk
@@ -44,6 +44,7 @@ SRC += update.c
SRC += user-interface.c
SRC += sanity.c
SRC += manifest.c
+SRC += conflicting-kernel-modules.c
DIST_FILES := $(SRC)
@@ -63,6 +64,7 @@ DIST_FILES += snarf.h
DIST_FILES += update.h
DIST_FILES += user-interface.h
DIST_FILES += manifest.h
+DIST_FILES += conflicting-kernel-modules.h
DIST_FILES += COPYING
DIST_FILES += README
diff --git a/files.c b/files.c
index c7c3628..c37586e 100644
--- a/files.c
+++ b/files.c
@@ -480,6 +480,116 @@ void select_tls_class(Options *op, Package *p)
#endif /* NV_TLS_TEST */
} /* select_tls_class() */
+/*
+ * check_libGLX_indirect_target() - Helper function for
+ * check_libGLX_indirect_links.
+ *
+ * Checks to see if the installer should install (or overwrite) a
+ * libGLX_indirect.so.0 symlink.
+ *
+ * (path) should be the path to where the symlink would be installed.
+ */
+static int check_libGLX_indirect_target(Options *op, const char *path)
+{
+ char *target = NULL;
+ char *base = NULL;
+ char *ext = NULL;
+ struct stat stat_buf;
+ int ret;
+
+ if (lstat(path, &stat_buf) != 0) {
+ // If the file doesn't exist, then we should create it.
+ return TRUE;
+ }
+
+ if (!S_ISLNK(stat_buf.st_mode)) {
+ // The file is not a symlink. Leave it alone.
+ return FALSE;
+ }
+
+ if (stat(path, &stat_buf) != 0) {
+ // If we can't resolve the link, then overwrite it.
+ return TRUE;
+ }
+
+ // Resolve the symlink.
+ target = get_resolved_symlink_target(op, path);
+ while (target != NULL) {
+ // Follow any more symlinks. The fact that the stat call above
+ // succeeded means that the link is valid.
+ char *nextTarget = NULL;
+ if (lstat(target, &stat_buf) != 0) {
+ free(target);
+ target = NULL;
+ break;
+ }
+
+ if (!S_ISLNK(stat_buf.st_mode)) {
+ break;
+ }
+
+ nextTarget = get_resolved_symlink_target(op, target);
+ free(target);
+ target = nextTarget;
+ }
+ if (target == NULL) {
+ // This should never happen.
+ ui_error(op, "Unable to resolve symbolic link \"%s\"\n", path);
+ return FALSE;
+ }
+
+ // Find the basename of the link target.
+ base = basename(target);
+ // Strip off the extension.
+ ext = strchr(base, '.');
+ if (ext != NULL) {
+ *ext = '\0';
+ }
+
+ // Finally, see if the resulting name is "libGLX_indirect". If it is, then
+ // we'll assume that the existing file is a dedicated indirect rendering
+ // library. Otherwise, we'll assume that it's a link to another vendor
+ // library.
+ if (strcmp(base, "libGLX_indirect") == 0) {
+ ret = FALSE;
+ } else {
+ ret = TRUE;
+ }
+ free(target);
+ return ret;
+}
+
+/*
+ * check_libGLX_indirect_links() - Finds the entries for the
+ * "libGLX_indirect.so.0" symlinks, and figures out whether to install them.
+ */
+static void check_libGLX_indirect_links(Options *op, Package *p)
+{
+ int i;
+
+ if (op->install_libglx_indirect == NV_OPTIONAL_BOOL_TRUE) {
+ // The user specified that we should install the symlink.
+ return;
+ }
+
+ // Find the entries for libGLX_indirect.so.0, and decide whether or not to
+ // keep them.
+ for (i = 0; i < p->num_entries; i++) {
+ if (p->entries[i].dst != NULL && p->entries[i].type == FILE_TYPE_OPENGL_SYMLINK) {
+ if (strcmp(p->entries[i].name, "libGLX_indirect.so.0") == 0) {
+ int overwrite = FALSE;
+ if (op->install_libglx_indirect == NV_OPTIONAL_BOOL_DEFAULT) {
+ if (check_libGLX_indirect_target(op, p->entries[i].dst)) {
+ overwrite = TRUE;
+ }
+ }
+ if (!overwrite) {
+ invalidate_package_entry(&(p->entries[i]));
+ }
+ }
+ }
+ }
+}
/*
* set_destinations() - given the Options and Package structures,
@@ -499,32 +609,20 @@ int set_destinations(Options *op, Package *p)
op->kernel_module_src_dir = nvstrcat("nvidia-", p->version, NULL);
}
- op->uvm_module_src_dir = nvstrcat(op->kernel_module_src_dir, "/" UVM_SUBDIR,
- NULL);
-
for (i = 0; i < p->num_entries; i++) {
switch (p->entries[i].type) {
- case FILE_TYPE_KERNEL_MODULE_CMD:
- /* we don't install kernel module commands */
- p->entries[i].dst = NULL;
- continue;
-
case FILE_TYPE_KERNEL_MODULE_SRC:
- case FILE_TYPE_UVM_MODULE_SRC:
+ case FILE_TYPE_DKMS_CONF:
if (op->no_kernel_module_source) {
/* Don't install kernel module source files if requested. */
p->entries[i].dst = NULL;
continue;
}
prefix = op->kernel_module_src_prefix;
- if (p->entries[i].type == FILE_TYPE_UVM_MODULE_SRC) {
- dir = op->uvm_module_src_dir;
- } else {
- dir = op->kernel_module_src_dir;
- }
- path = "";
+ dir = op->kernel_module_src_dir;
+ path = p->entries[i].path;
break;
case FILE_TYPE_OPENGL_LIB:
@@ -775,6 +873,8 @@ int set_destinations(Options *op, Package *p)
}
#endif /* NV_X86_64 */
}
+
+ check_libGLX_indirect_links(op, p);
return TRUE;
@@ -1031,11 +1131,11 @@ int get_prefixes (Options *op)
*/
static void add_kernel_module_helper(Options *op, Package *p,
- const char *filename, const char *dir)
+ const char *filename)
{
char *file, *name, *dst;
- file = nvstrcat(dir, "/", filename, NULL);
+ file = nvstrcat(p->kernel_module_build_directory, "/", filename, NULL);
name = strrchr(file, '/');
@@ -1066,43 +1166,20 @@ static void add_kernel_module_helper(Options *op, Package *p,
* to the package list for installation.
*/
-int add_kernel_modules_to_package(Options *op, Package *p)
+void add_kernel_modules_to_package(Options *op, Package *p)
{
int i;
- if (op->multiple_kernel_modules) {
- add_kernel_module_helper(op, p, p->kernel_frontend_module_filename,
- p->kernel_module_build_directory);
- }
-
- for (i = 0; i < op->num_kernel_modules; i++) {
-
- char *tmp, *name;
-
- name = nvstrdup(p->kernel_module_filename);
-
- tmp = strrchr(name, '0');
- if (tmp) *tmp = *tmp + i;
-
- add_kernel_module_helper(op, p, name, p->kernel_module_build_directory);
-
- nvfree(name);
+ for (i = 0; i < p->num_kernel_modules; i++) {
+ add_kernel_module_helper(op, p, p->kernel_modules[i].module_filename);
}
-
- if (op->install_uvm) {
- add_kernel_module_helper(op, p, p->uvm_kernel_module_filename,
- p->uvm_module_build_directory);
- }
-
- return TRUE;
-
-} /* add_kernel_module_to_package() */
+}
/*
* Invalidate each package entry that is not type
- * FILE_TYPE_KERNEL_MODULE{,_CMD,_SRC}.
+ * FILE_TYPE_KERNEL_MODULE{,_SRC} or FILE_TYPE_DKMS_CONF.
*/
void remove_non_kernel_module_files_from_package(Options *op, Package *p)
@@ -1111,8 +1188,8 @@ void remove_non_kernel_module_files_from_package(Options *op, Package *p)
for (i = 0; i < p->num_entries; i++) {
if ((p->entries[i].type != FILE_TYPE_KERNEL_MODULE) &&
- (p->entries[i].type != FILE_TYPE_KERNEL_MODULE_CMD) &&
- (p->entries[i].type != FILE_TYPE_KERNEL_MODULE_SRC)) {
+ (p->entries[i].type != FILE_TYPE_KERNEL_MODULE_SRC) &&
+ (p->entries[i].type != FILE_TYPE_DKMS_CONF)) {
invalidate_package_entry(&(p->entries[i]));
}
}
@@ -1592,8 +1669,8 @@ int check_for_existing_rpms(Options *op)
/*
- * copy_directory_contents() - copy the contents of directory src to
- * directory dst. This only copies files; subdirectories are ignored.
+ * copy_directory_contents() - recursively copy the contents of directory src to
+ * directory dst. Special files are ignored.
*/
int copy_directory_contents(Options *op, const char *src, const char *dst)
@@ -1612,22 +1689,24 @@ int copy_directory_contents(Options *op, const char *src, const char *dst)
struct stat stat_buf;
char *srcfile, *dstfile;
int ret;
-
+
if (((strcmp(ent->d_name, ".")) == 0) ||
((strcmp(ent->d_name, "..")) == 0)) continue;
-
+
srcfile = nvstrcat(src, "/", ent->d_name, NULL);
+ dstfile = nvstrcat(dst, "/", ent->d_name, NULL);
- /* only copy regular files */
+ ret = (stat(srcfile, &stat_buf) != -1);
- if ((stat(srcfile, &stat_buf) == -1) || !(S_ISREG(stat_buf.st_mode))) {
- nvfree(srcfile);
- continue;
+ if (ret) {
+ /* recurse into subdirectories */
+ if (S_ISDIR(stat_buf.st_mode)) {
+ ret = mkdir_recursive(op, dstfile, stat_buf.st_mode, FALSE) &&
+ copy_directory_contents(op, srcfile, dstfile);
+ } else if (S_ISREG(stat_buf.st_mode)) {
+ ret = copy_file(op, srcfile, dstfile, stat_buf.st_mode);
+ }
}
-
- dstfile = nvstrcat(dst, "/", ent->d_name, NULL);
-
- ret = copy_file(op, srcfile, dstfile, stat_buf.st_mode);
nvfree(srcfile);
nvfree(dstfile);
@@ -1644,13 +1723,13 @@ int copy_directory_contents(Options *op, const char *src, const char *dst)
if (closedir(dir) != 0) {
ui_error(op, "Failure while closing directory '%s' (%s).",
src, strerror(errno));
-
+
return FALSE;
}
-
+
return status;
-
-} /* copy_directory_contents() */
+
+}
@@ -2098,6 +2177,84 @@ void process_dot_desktop_files(Options *op, Package *p)
} /* process_dot_desktop_files() */
+
+/*
+ * process_dkms_conf() - copy dkms.conf to a temporary file and perform
+ * some substitutions. Then, add the new file to the package list.
+ */
+
+void process_dkms_conf(Options *op, Package *p)
+{
+ int i;
+ char *tmpfile;
+
+ char *tokens[6] = { "__VERSION_STRING", "__DKMS_MODULES", "__JOBS",
+ "__EXCLUDE_MODULES", "will be generated", NULL };
+ char *replacements[6] = { p->version, NULL, NULL,
+ p->excluded_kernel_modules,
+ "was generated", NULL };
+
+ int package_num_entries = p->num_entries;
+
+ replacements[1] = nvstrdup("");
+ replacements[2] = nvasprintf("%d", op->concurrency_level);
+
+ /* Build the list of kernel modules to be installed */
+ for (i = 0; i < p->num_kernel_modules; i++) {
+ char *old_modules = replacements[1];
+ char *index = nvasprintf("%d", i);
+
+ replacements[1] = nvstrcat(old_modules,
+ "BUILT_MODULE_NAME[", index, "]=\"",
+ p->kernel_modules[i].module_name, "\"\n",
+ "DEST_MODULE_LOCATION[", index, "]=",
+ "\"/kernel/drivers/video\"\n", NULL);
+
+ nvfree(index);
+ nvfree(old_modules);
+ }
+
+ for (i = 0; i < package_num_entries; i++) {
+ if ((p->entries[i].type == FILE_TYPE_DKMS_CONF)) {
+
+ /* invalidate the template file */
+
+ invalidate_package_entry(&(p->entries[i]));
+
+ tmpfile = process_template_file(op, &p->entries[i], tokens,
+ replacements);
+ if (tmpfile != NULL) {
+ /* add this new file to the package */
+
+ /*
+ * XXX 'name' is the basename (non-directory part) of
+ * the file to be installed; normally, 'name' just
+ * points into 'file', but in this case 'file' is
+ * mkstemp(3)-generated, so doesn't have the same
+ * basename; instead, we just strdup the name from the
+ * template package entry; yes, 'name' will get leaked
+ */
+
+ add_package_entry(p,
+ tmpfile,
+ nvstrdup(p->entries[i].path),
+ nvstrdup(p->entries[i].name),
+ NULL, /* target */
+ NULL, /* dst */
+ FILE_TYPE_DKMS_CONF,
+ p->entries[i].tls_class,
+ p->entries[i].compat_arch,
+ p->entries[i].mode);
+ }
+ }
+ }
+
+ nvfree(replacements[2]);
+ nvfree(replacements[1]);
+
+}
+
+
/*
* set_security_context() - set the security context of the file to 'shlib_t'
* Returns TRUE on success or if SELinux is disabled, FALSE otherwise
diff --git a/files.h b/files.h
index 1708926..03672b1 100644
--- a/files.h
+++ b/files.h
@@ -23,8 +23,6 @@
#include "nvidia-installer.h"
#include "precompiled.h"
-#define UVM_SUBDIR "uvm"
-
int remove_directory(Options *op, const char *victim);
int touch_directory(Options *op, const char *victim);
int copy_file(Options *op, const char *srcfile,
@@ -35,7 +33,7 @@ void select_tls_class(Options *op, Package *p); /* XXX move? */
int set_destinations(Options *op, Package *p); /* XXX move? */
int get_license_acceptance(Options *op); /* XXX move? */
int get_prefixes(Options *op); /* XXX move? */
-int add_kernel_modules_to_package(Options *op, Package *p);
+void add_kernel_modules_to_package(Options *op, Package *p);
void remove_non_kernel_module_files_from_package(Options *op, Package *p);
void remove_opengl_files_from_package(Options *op, Package *p);
int mode_string_to_mode(Options *op, char *s, mode_t *mode);
@@ -62,6 +60,7 @@ char *process_template_file(Options *op, PackageEntry *pe,
char **tokens, char **replacements);
void process_libGL_la_files(Options *op, Package *p);
void process_dot_desktop_files(Options *op, Package *p);
+void process_dkms_conf(Options *op, Package *p);
int set_security_context(Options *op, const char *filename);
void get_default_prefixes_and_paths(Options *op);
void get_compat32_path(Options *op);
diff --git a/install-from-cwd.c b/install-from-cwd.c
index a6388da..18d7df1 100644
--- a/install-from-cwd.c
+++ b/install-from-cwd.c
@@ -111,7 +111,7 @@ int install_from_cwd(Options *op)
/* make sure the kernel module is unloaded */
- if (!check_for_unloaded_kernel_module(op, p)) goto failed;
+ if (!check_for_unloaded_kernel_module(op)) goto failed;
/* ask the user to accept the license */
@@ -314,7 +314,9 @@ int install_from_cwd(Options *op)
*/
if (!op->no_kernel_module || op->dkms) {
- if (!load_kernel_module(op, p)) goto failed;
+ if (!load_kernel_module(op, p->kernel_modules[0].module_name)) {
+ goto failed;
+ }
}
/* run the distro postinstall script */
@@ -419,49 +421,7 @@ static int install_kernel_modules(Options *op, Package *p)
{
PrecompiledInfo *precompiled_info;
- /* Append the UVM dkms.conf fragment to RM's dkms.conf when installing UVM */
-
- if (op->install_uvm) {
- FILE *dkmsconf, *uvmdkmsconf;
- char *tmppath;
-
- tmppath = nvstrcat(p->kernel_module_build_directory, "/dkms.conf", NULL);
- dkmsconf = fopen(tmppath, "a");
- nvfree(tmppath);
-
- tmppath = nvstrcat(p->uvm_module_build_directory,
- "/dkms.conf.fragment", NULL);
- uvmdkmsconf = fopen(tmppath, "r");
- nvfree (tmppath);
-
- if (dkmsconf && uvmdkmsconf) {
- char byte;
-
- while (fread(&byte, 1, 1, uvmdkmsconf)) {
- if (!fwrite(&byte, 1, 1, dkmsconf)) {
- goto dkmscatfailed;
- }
- }
-
- if (ferror(uvmdkmsconf)) {
- goto dkmscatfailed;
- }
-
- } else {
-dkmscatfailed:
- ui_warn(op, "Failed to add build commands for the NVIDIA Unified "
- "Memory kernel module to the dkms.conf file: DKMS will "
- "not be able to build the NVIDIA Unified Memory kernel "
- "module.");
- }
-
- if (dkmsconf) {
- fclose(dkmsconf);
- }
- if (uvmdkmsconf) {
- fclose(uvmdkmsconf);
- }
- }
+ process_dkms_conf(op,p);
/* Offer the DKMS option if DKMS exists and the kernel module sources
* will be installed somewhere. Don't offer DKMS as an option if module
@@ -528,8 +488,8 @@ dkmscatfailed:
*/
for (i = 0; i < precompiled_info->num_files; i++) {
- if (!link_kernel_module(op, p, p->kernel_module_build_directory,
- &(precompiled_info->files[i]))) {
+ if (!unpack_kernel_modules(op, p, p->kernel_module_build_directory,
+ &(precompiled_info->files[i]))) {
precompiled_success = FALSE;
goto precompiled_done;
}
@@ -579,7 +539,7 @@ precompiled_done:
/* add the kernel modules to the list of things to install */
- if (!add_kernel_modules_to_package(op, p)) return FALSE;
+ add_kernel_modules_to_package(op, p);
return TRUE;
}
@@ -595,7 +555,6 @@ int add_this_kernel(Options *op)
{
Package *p;
PrecompiledFileInfo *fileInfos;
- int num_expected_files = 1;
/* parse the manifest */
@@ -609,22 +568,14 @@ int add_this_kernel(Options *op)
if (!determine_kernel_source_path(op, p)) goto failed;
- if (op->multiple_kernel_modules) {
- num_expected_files += op->num_kernel_modules;
- }
-
- if (op->install_uvm) {
- num_expected_files += 1;
- }
-
/* build the precompiled files */
- if (num_expected_files != build_kernel_interface(op, p, &fileInfos))
+ if (p->num_kernel_modules != build_kernel_interfaces(op, p, &fileInfos))
goto failed;
/* pack the precompiled files */
- if (!pack_precompiled_files(op, p, num_expected_files, fileInfos))
+ if (!pack_precompiled_files(op, p, p->num_kernel_modules, fileInfos))
goto failed;
free_package(p);
@@ -650,6 +601,7 @@ static void add_conflicting_file(Package *p, int *index, const char *file)
p->conflicting_files = nvrealloc(p->conflicting_files,
sizeof(ConflictingFileInfo) * (*index+1));
+ memset(&p->conflicting_files[*index], 0, sizeof(ConflictingFileInfo));
p->conflicting_files[*index].name = file;
@@ -686,6 +638,100 @@ static void add_conflicting_file(Package *p, int *index, const char *file)
}
+/*
+ * Returns TRUE if the given module has a separate interface, FALSE otherwise.
+ */
+static int has_separate_interface_file(char *name) {
+ int i;
+
+ static const char* no_interface_modules[] = {
+ "nvidia-uvm",
+ };
+
+ for (i = 0; i < ARRAY_LEN(no_interface_modules); i++) {
+ if (strcmp(no_interface_modules[i],name) == 0) {
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+};
+
+
+/*
+ * Populate the module info records for optional records with information
+ * that can be used in e.g. error messages.
+ */
+static void populate_optional_module_info(KernelModuleInfo *module)
+{
+ int i;
+
+ static struct {
+ const char *name;
+ char * const dependee;
+ char * const disable_option;
+ } optional_modules[] = {
+ { "nvidia-uvm", "CUDA", "no-unified-memory" },
+ };
+
+ for (i = 0; i < ARRAY_LEN(optional_modules); i++) {
+ if (strcmp(optional_modules[i].name, module->module_name) == 0) {
+ module->is_optional = TRUE;
+ module->optional_module_dependee = optional_modules[i].dependee;
+ module->disable_option = optional_modules[i].disable_option;
+ return;
+ }
+ }
+}
+
+
+/*
+ * Return a string with 'suffix' appended to the original source string, after
+ * replacing "nvidia" with "nv" at the beginning of the original source string.
+ */
+static char *nvidia_to_nv(const char *name, const char *suffix) {
+ if (strncmp("nvidia", name, strlen("nvidia")) != 0) {
+ return NULL;
+ }
+
+ return nvstrcat("nv", name + strlen("nvidia"), suffix, NULL);
+}
+
+
+/*
+ * Iterate over the list of kernel modules from the manifest file; generate
+ * and store module information records for each module in the Package.
+ */
+static int parse_kernel_modules_list(Package *p, char *list) {
+ char *name;
+
+ p->num_kernel_modules = 0; /* in case this gets called more than once */
+
+ for (name = strtok(list, " "); name; name = strtok(NULL, " ")) {
+ KernelModuleInfo *module;
+ p->kernel_modules = nvrealloc(p->kernel_modules,
+ (p->num_kernel_modules + 1) *
+ sizeof(p->kernel_modules[0]));
+ module = p->kernel_modules + p->num_kernel_modules;
+ memset(module, 0, sizeof(*module));
+
+ module->module_name = nvstrdup(name);
+ module->module_filename = nvstrcat(name, ".ko", NULL);
+ module->has_separate_interface_file = has_separate_interface_file(name);
+ if (module->has_separate_interface_file) {
+ char *core_binary = nvidia_to_nv(name, "-kernel.o_binary");
+ module->interface_filename = nvidia_to_nv(name, "-linux.o");
+ module->core_object_name = nvstrcat(name, "/", core_binary, NULL);
+ nvfree(core_binary);
+ }
+ populate_optional_module_info(module);
+
+ p->num_kernel_modules++;
+ }
+
+ return p->num_kernel_modules;
+}
+
/*
* parse_manifest() - open and read the .manifest file in the current
@@ -714,13 +760,14 @@ static void add_conflicting_file(Package *p, int *index, const char *file)
* - certain file types have an architecture
* - certain file types have a second flag
* - certain file types will have a path
+ * - file types which inherit their paths will have a path depth
* - symbolic links will name the target of the link
*/
static Package *parse_manifest (Options *op)
{
- char *buf, *c, *tmpstr, *module_suffix = "", *interface_suffix = "";
- int n, line;
+ char *buf, *c, *tmpstr;
+ int line;
int fd, ret, len = 0;
struct stat stat_buf;
Package *p;
@@ -763,74 +810,32 @@ static Package *parse_manifest (Options *op)
line++;
nvfree(get_next_line(ptr, &ptr, manifest, len));
- /* the fourth line is the kernel module name */
+ /* the fourth line is the list of kernel modules. */
line++;
tmpstr = get_next_line(ptr, &ptr, manifest, len);
- if (!tmpstr) goto invalid_manifest_file;
-
- if (op->multiple_kernel_modules) {
- module_suffix = "0";
- interface_suffix = "-0";
+ if (parse_kernel_modules_list(p, tmpstr) == 0) {
+ goto invalid_manifest_file;
}
-
- p->kernel_module_name = nvstrcat(tmpstr, module_suffix, NULL);
- p->kernel_module_filename = nvstrcat(p->kernel_module_name, ".ko", NULL);
- p->kernel_interface_filename = nvstrcat("nv-linux", interface_suffix, ".o", NULL);
-
- p->kernel_frontend_module_name = nvstrcat(tmpstr, "-frontend", NULL);
- p->kernel_frontend_module_filename = nvstrcat(p->kernel_frontend_module_name,
- ".ko", NULL);
- p->kernel_frontend_interface_filename = "nv-linux-frontend.o";
-
- p->uvm_kernel_module_name = nvstrcat(tmpstr, "-uvm", NULL);
- p->uvm_kernel_module_filename = nvstrcat(p->uvm_kernel_module_name, ".ko",
- NULL);
- p->uvm_interface_filename = "nv-linux-uvm.o";
-
nvfree(tmpstr);
/*
- * the fifth line is a whitespace-separated list of kernel modules
- * to be unloaded before installing the new kernel module
+ * set the default value of excluded_kernel_modules to an empty, heap
+ * allocated string so that it can be freed and won't prematurely end
+ * an nvstrcat()ed string when unset.
*/
- line++;
- tmpstr = get_next_line(ptr, &ptr, manifest, len);
- if (!tmpstr) goto invalid_manifest_file;
+ p->excluded_kernel_modules = nvstrdup("");
- p->bad_modules = NULL;
- c = tmpstr;
- n = 0;
-
- do {
- n++;
- p->bad_modules = (char **)
- nvrealloc(p->bad_modules, n * sizeof(char *));
- p->bad_modules[n-1] = read_next_word(c, &c);
- } while (p->bad_modules[n-1]);
-
/*
- * the sixth line is a whitespace-separated list of kernel module
- * filenames to be uninstalled before installing the new kernel
- * module
+ * ignore the fifth and sixth lines
*/
line++;
- tmpstr = get_next_line(ptr, &ptr, manifest, len);
- if (!tmpstr) goto invalid_manifest_file;
+ nvfree(get_next_line(ptr, &ptr, manifest, len));
+ line++;
+ nvfree(get_next_line(ptr, &ptr, manifest, len));
- p->bad_module_filenames = NULL;
- c = tmpstr;
- n = 0;
-
- do {
- n++;
- p->bad_module_filenames = (char **)
- nvrealloc(p->bad_module_filenames, n * sizeof(char *));
- p->bad_module_filenames[n-1] = read_next_word(c, &c);
- } while (p->bad_module_filenames[n-1]);
-
/* the seventh line is the kernel module build directory */
line++;
@@ -838,9 +843,6 @@ static Package *parse_manifest (Options *op)
if (!p->kernel_module_build_directory) goto invalid_manifest_file;
remove_trailing_slashes(p->kernel_module_build_directory);
- p->uvm_module_build_directory = nvstrcat(p->kernel_module_build_directory,
- "/" UVM_SUBDIR, NULL);
-
/*
* the eigth line is the directory containing precompiled kernel
* interfaces
@@ -907,9 +909,6 @@ static Package *parse_manifest (Options *op)
/* Track whether certain file types were packaged */
switch (entry.type) {
- case FILE_TYPE_UVM_MODULE_SRC:
- op->uvm_files_packaged = TRUE;
- break;
case FILE_TYPE_XMODULE_SHARED_LIB:
op->x_files_packaged = TRUE;
break;
@@ -964,11 +963,45 @@ static Package *parse_manifest (Options *op)
}
}
- /* libs and documentation have a path field */
+ /* some file types have a path field, or inherit their paths */
if (entry.caps.has_path) {
entry.path = read_next_word(c, &c);
if (!entry.path) goto invalid_manifest_file;
+ } else if (entry.caps.inherit_path) {
+ int i;
+ char *path, *depth, *slash;
+ const char * const depth_marker = "INHERIT_PATH_DEPTH:";
+
+ depth = read_next_word(c, &c);
+ if (!depth ||
+ strncmp(depth, depth_marker, strlen(depth_marker)) != 0) {
+ goto invalid_manifest_file;
+ }
+ entry.inherit_path_depth = atoi(depth + strlen(depth_marker));
+ nvfree(depth);
+
+ /* Remove the file component from the packaged filename */
+ path = entry.path = nvstrdup(entry.file);
+ slash = strrchr(path, '/');
+ if (slash == NULL) {
+ goto invalid_manifest_file;
+ }
+ slash[1] = '\0';
+
+ /* Strip leading directory components from the path */
+ for (i = 0; i < entry.inherit_path_depth; i++) {
+ slash = strchr(entry.path, '/');
+
+ if (slash == NULL) {
+ goto invalid_manifest_file;
+ }
+
+ entry.path = slash + 1;
+ }
+
+ entry.path = nvstrdup(entry.path);
+ nvfree(path);
} else {
entry.path = NULL;
}
@@ -1132,29 +1165,18 @@ static void free_package(Package *p)
nvfree(p->description);
nvfree(p->version);
- nvfree(p->kernel_module_filename);
- nvfree(p->kernel_interface_filename);
- nvfree(p->kernel_module_name);
-
- if (p->bad_modules) {
- for (i = 0; p->bad_modules[i]; i++) {
- nvfree(p->bad_modules[i]);
- }
- nvfree((char *) p->bad_modules);
- }
-
- if (p->bad_module_filenames) {
- for (i = 0; p->bad_module_filenames[i]; i++) {
- nvfree(p->bad_module_filenames[i]);
- }
- nvfree((char *) p->bad_module_filenames);
- }
nvfree(p->kernel_module_build_directory);
- nvfree(p->uvm_module_build_directory);
-
+
nvfree(p->precompiled_kernel_interface_directory);
-
+
+ for (i = 0; i < p->num_kernel_modules; i++) {
+ free_kernel_module_info(p->kernel_modules[i]);
+ }
+ nvfree(p->kernel_modules);
+
+ nvfree(p->excluded_kernel_modules);
+
for (i = 0; i < p->num_entries; i++) {
nvfree(p->entries[i].file);
nvfree(p->entries[i].path);
@@ -1169,11 +1191,6 @@ static void free_package(Package *p)
nvfree((char *) p->entries);
- nvfree(p->kernel_frontend_module_filename);
- nvfree(p->kernel_frontend_module_name);
- nvfree(p->uvm_kernel_module_name);
- nvfree(p->uvm_kernel_module_filename);
-
nvfree((char *) p);
} /* free_package() */
@@ -1307,7 +1324,8 @@ static int assisted_module_signing(Options *op, Package *p)
"plan to generate a new key pair with "
"nvidia-installer.";
- guess = guess_module_signing_hash(op, p);
+ guess = guess_module_signing_hash(op,
+ p->kernel_module_build_directory);
if (guess == NULL) {
warn = no_guess;
@@ -1405,30 +1423,9 @@ generate_done:
/* Now that we have keys (user-supplied or installer-generated),
* sign the kernel module/s which we built earlier. */
- for (i = 0; i < op->num_kernel_modules; i++) {
- char module_instance_str[5];
- memset(module_instance_str, 0, sizeof(module_instance_str));
-
- if (op->multiple_kernel_modules) {
- snprintf(module_instance_str, sizeof(module_instance_str), "%d", i);
- }
-
+ for (i = 0; i < p->num_kernel_modules; i++) {
if (!sign_kernel_module(op, p->kernel_module_build_directory,
- module_instance_str, TRUE)) {
- return FALSE;
- }
- }
-
- if (op->multiple_kernel_modules) {
- if (!sign_kernel_module(op, p->kernel_module_build_directory,
- "-frontend", TRUE)) {
- return FALSE;
- }
- }
-
- if (op->install_uvm) {
- if (!sign_kernel_module(op, p->uvm_module_build_directory, "-uvm",
- TRUE)) {
+ p->kernel_modules[i].module_filename, TRUE)) {
return FALSE;
}
}
diff --git a/kernel.c b/kernel.c
index 4751f0b..d1bd4aa 100644
--- a/kernel.c
+++ b/kernel.c
@@ -43,6 +43,7 @@
#include "precompiled.h"
#include "snarf.h"
#include "crc.h"
+#include "conflicting-kernel-modules.h"
/* local prototypes */
@@ -54,9 +55,9 @@ static void check_for_warning_messages(Options *op);
static PrecompiledInfo *download_updated_kernel_interface(Options*, Package*,
const char*,
char* const*);
-static int fbdev_check(Options *op, Package *p);
-static int xen_check(Options *op, Package *p);
-static int preempt_rt_check(Options *op, Package *p);
+static int sanity_check(Options *op, const char *dir,
+ const char *sanity_check_name,
+ const char *conftest_name);
static PrecompiledInfo *scan_dir(Options *op, Package *p,
const char *directory_name,
@@ -68,9 +69,10 @@ static char *convert_include_path_to_source_path(const char *inc);
static char *get_machine_arch(Options *op);
static int init_libkmod(void);
static void close_libkmod(void);
-static int run_conftest(Options *op, Package *p, const char *args,
+static int run_conftest(Options *op, const char *dir, const char *args,
char **result);
-static void replace_zero(char* filename, int i);
+static int run_make(Options *op, Package *p, char *dir, const char *target,
+ char **vars, const char *status, int lines);
static void load_kernel_module_quiet(Options *op, const char *module_name);
static void modprobe_remove_kernel_module_quiet(Options *op, const char *name);
@@ -83,7 +85,6 @@ static int (*lkmod_module_new_from_path)(struct kmod_ctx*, const char*,
struct kmod_module**) = NULL;
static int (*lkmod_module_insert_module)(struct kmod_module*, unsigned int,
const char*) = NULL;
-static void free_search_filelist(char **);
/*
* Message text that is used by several error messages.
@@ -170,28 +171,33 @@ int determine_kernel_module_installation_path(Options *op)
* the result back to the caller. Returns TRUE on success, or FALSE on failure.
*/
-static int run_conftest(Options *op, Package *p, const char *args, char **result)
+static int run_conftest(Options *op, const char *dir, const char *args,
+ char **result)
{
char *cmd, *arch;
int ret;
- if (result)
+ if (result) {
*result = NULL;
+ }
arch = get_machine_arch(op);
- if (!arch)
+ if (!arch) {
return FALSE;
+ }
- cmd = nvstrcat("sh \"", p->kernel_module_build_directory,
- "/conftest.sh\" \"", op->utils[CC], "\" \"", op->utils[CC],
- "\" \"", arch, "\" \"", op->kernel_source_path, "\" \"",
- op->kernel_output_path, "\" ", args, NULL);
+ cmd = nvstrcat("sh \"", dir, "/conftest.sh\" \"",
+ op->utils[CC], "\" \"",
+ op->utils[CC], "\" \"",
+ arch, "\" \"",
+ op->kernel_source_path, "\" \"",
+ op->kernel_output_path, "\" ",
+ args, NULL);
ret = run_command(op, cmd, result, FALSE, 0, TRUE);
nvfree(cmd);
return ret == 0;
-
} /* run_conftest() */
@@ -295,7 +301,8 @@ int determine_kernel_source_path(Options *op, Package *p)
if (!determine_kernel_output_path(op)) return FALSE;
- ret = run_conftest(op, p, "get_uname", &result);
+ ret = run_conftest(op, p->kernel_module_build_directory, "get_uname",
+ &result);
if (!ret) {
ui_error(op, "Unable to determine the version of the kernel "
@@ -501,54 +508,45 @@ static int attach_signature(Options *op, Package *p,
/*
- * Look for the presence of char '0' in filename and replace
- * it with the integer value passed as input. This is used
- * especially for multiple kernel module builds.
- */
-
-static void replace_zero(char *filename, int i)
-{
- char *name;
-
- if (i < 0 || i > 9) return;
-
- name = strrchr(filename, '0');
- if (name) *name = *name + i;
-}
-
-
-/*
- * link_kernel_module() - link the prebuilt kernel interface against
- * the binary-only core of the kernel module. This results in a
- * complete kernel module, ready for installation.
+ * unpack_kernel_modules() - unpack the precompiled file bundle, and link any
+ * prebuilt kernel interface against their respective binary-only core object
+ * files. This results in a complete kernel module, ready for installation.
*
+ * e.g.: ld -r -o nvidia.ko nv-linux.o nvidia/nv-kernel.o_binary
*
- * ld -r -o nvidia.o nv-linux.o nv-kernel.o
+ * If the precompiled file is a complete kernel module instead of an interface
+ * file, no additional action is needed after unpacking.
*/
-int link_kernel_module(Options *op, Package *p, const char *build_directory,
- const PrecompiledFileInfo *fileInfo)
+int unpack_kernel_modules(Options *op, Package *p, const char *build_directory,
+ const PrecompiledFileInfo *fileInfo)
{
char *cmd, *result;
int ret;
uint32 attrmask;
- if (fileInfo->type != PRECOMPILED_FILE_TYPE_INTERFACE) {
+ if (fileInfo->type != PRECOMPILED_FILE_TYPE_INTERFACE &&
+ fileInfo->type != PRECOMPILED_FILE_TYPE_MODULE) {
ui_error(op, "The file does not appear to be a valid precompiled "
- "kernel interface.");
+ "kernel interface or module.");
return FALSE;
}
ret = precompiled_file_unpack(op, fileInfo, build_directory);
if (!ret) {
- ui_error(op, "Failed to unpack the precompiled interface.");
+ ui_error(op, "Failed to unpack the precompiled file.");
return FALSE;
+ } else if (fileInfo->type == PRECOMPILED_FILE_TYPE_MODULE) {
+ ui_log(op, "Kernel module unpacked successfully.");
+ return TRUE;
}
- cmd = nvstrcat("cd ", build_directory, "/", fileInfo->target_directory,
+ cmd = nvstrcat("cd ", build_directory,
"; ", op->utils[LD], " ", LD_OPTIONS, " -o ",
fileInfo->linked_module_name, " ",
- fileInfo->name, " ", fileInfo->core_object_name, NULL);
+ fileInfo->target_directory, "/", fileInfo->name, " ",
+ fileInfo->target_directory, "/", fileInfo->core_object_name,
+ NULL);
ret = run_command(op, cmd, &result, TRUE, 0, TRUE);
@@ -571,215 +569,129 @@ int link_kernel_module(Options *op, Package *p, const char *build_directory,
return TRUE;
-} /* link_kernel_module() */
-
-
-
-static int build_kernel_module_helper(Options *op, const char *dir,
- const char *module, int num_instances)
-{
- int ret;
- char *instances = NULL, *cmd, *tmp, *concurrency;
-
- tmp = op->multiple_kernel_modules && num_instances ?
- nvasprintf("%d", num_instances) : NULL;
- instances = nvstrcat(" NV_BUILD_MODULE_INSTANCES=", tmp, NULL);
- nvfree(tmp);
-
- concurrency = nvasprintf(" -j%d ", op->concurrency_level);
-
- tmp = nvasprintf("Building %s kernel module:", module);
- ui_status_begin(op, tmp, "Building");
- nvfree(tmp);
-
- cmd = nvstrcat("cd ", dir, "; ", op->utils[MAKE], " module",
- " SYSSRC=", op->kernel_source_path,
- " SYSOUT=", op->kernel_output_path, concurrency,
- instances, NULL);
- nvfree(instances);
- nvfree(concurrency);
-
- ret = run_command(op, cmd, NULL, TRUE, 25, TRUE);
-
- nvfree(cmd);
-
- if (ret != 0) {
- ui_status_end(op, "Error.");
- ui_error(op, "Unable to build the %s kernel module.", module);
- /* XXX need more descriptive error message */
-
- return FALSE;
- }
-
- ui_status_end(op, "done.");
-
- return TRUE;
}
-static int check_file(Options *op, const char *dir, const char *filename,
- const char *modname)
+static int check_file(Options *op, const char *dir, const char *modname)
{
int ret;
char *path;
- path = nvstrcat(dir, "/", filename, NULL);
+ path = nvstrcat(dir, "/", modname, ".ko", NULL);
ret = access(path, F_OK);
nvfree(path);
if (ret == -1) {
- ui_error(op, "The NVIDIA %s module was not created.", modname);
+ ui_error(op, "The %s kernel module was not created.", modname);
}
return ret != -1;
}
+
/*
- * Determine the kernel include directory,
- * copy the kernel module source files into a temporary directory, and
- * compile nvidia.o.
+ * Build the kernel modules that part of this package.
*/
int build_kernel_modules(Options *op, Package *p)
{
- char *result, *cmd;
- int ret;
-
- /*
- * touch all the files in the build directory to avoid make time
- * skew messages
- */
-
- touch_directory(op, p->kernel_module_build_directory);
-
- if (!fbdev_check(op, p)) return FALSE;
- if (!xen_check(op, p)) return FALSE;
- if (!preempt_rt_check(op, p)) return FALSE;
-
- ui_log(op, "Cleaning kernel module build directory.");
-
- cmd = nvstrcat("cd ", p->kernel_module_build_directory, "; ",
- op->utils[MAKE], " clean", NULL);
-
- ret = run_command(op, cmd, &result, TRUE, 0, TRUE);
- free(result);
- free(cmd);
-
- ret = build_kernel_module_helper(op, p->kernel_module_build_directory,
- "NVIDIA", op->num_kernel_modules);
-
- if (!ret) {
- return FALSE;
- }
-
- /* check that the frontend file actually exists */
- if (op->multiple_kernel_modules) {
- if (!check_file(op, p->kernel_module_build_directory,
- p->kernel_frontend_module_filename, "frontend")) {
- return FALSE;
- }
- }
-
- /* check that the file actually exists */
- if (!check_file(op, p->kernel_module_build_directory,
- p->kernel_module_filename, "kernel")) {
- return FALSE;
- }
-
- /*
- * Build the UVM kernel module. The build directory from the previous kernel
- * module build must not be cleaned first, as the UVM kernel module will
- * depend on the Module.symvers file produced by that build.
- */
+ return build_kernel_interfaces(op, p, NULL);
+}
- if (op->install_uvm) {
- ret = build_kernel_module_helper(op, p->uvm_module_build_directory,
- "Unified Memory", 0);
- ret = ret && check_file(op, p->uvm_module_build_directory,
- p->uvm_kernel_module_filename, "Unified Memory");
+/*
+ * Run the module_signing_script with three or four arguments.
+ * Return TRUE on success.
+ */
+static int try_sign_file(Options *op, const char *file, int num_args)
+{
+ char *cmd;
+ const char *arg_1;
+ int ret;
- if (!ret) {
- ui_error(op, "The Unified Memory kernel module failed to build. "
- "This kernel module is required for the proper operation "
- "of CUDA. If you do not need to use CUDA, you can try to "
- "install this driver package again with the "
- "'--no-unified-memory' option.");
- return FALSE;
- }
+ switch (num_args) {
+ case 3: arg_1 = ""; break;
+ case 4: arg_1 = op->module_signing_hash; break;
+ default: return FALSE;
}
- ui_log(op, "Kernel module compilation complete.");
+ cmd = nvstrcat("\"", op->module_signing_script, "\" ",
+ arg_1, " \"",
+ op->module_signing_secret_key, "\" \"",
+ op->module_signing_public_key, "\" \"",
+ file, "\"", NULL);
+ ret = run_command(op, cmd, NULL, TRUE, 1, TRUE);
+ nvfree(cmd);
- return TRUE;
+ return ret == 0;
}
-
-
/*
- * sign_kernel_module() - sign the kernel module. The caller is responsible
+ * sign_kernel_module() - sign a kernel module. The caller is responsible
* for ensuring that the kernel module is already built successfully and that
* op->module_signing_{secret,public}_key are set.
*/
int sign_kernel_module(Options *op, const char *build_directory,
- const char *module_suffix, int status) {
- char *cmd, *mod_sign_cmd, *mod_sign_hash;
- int ret, success;
- char *build_module_instances_parameter, *concurrency;
-
- /* if module_signing_script isn't set, then set mod_sign_cmd below to end
- * the nvstrcat() that builds cmd early. */
- mod_sign_cmd = op->module_signing_script ?
- nvstrcat(" mod_sign_cmd=", op->module_signing_script, NULL) :
- NULL;
-
- mod_sign_hash = op->module_signing_hash ?
- nvstrcat(" CONFIG_MODULE_SIG_HASH=",
- op->module_signing_hash, NULL) :
- NULL;
+ const char *module_filename, int status) {
+ char *file;
+ int success;
+ static int num_args = 3;
+
+ /* Lazily set the default value for module_signing_script. */
+
+ if (!op->module_signing_script) {
+ op->module_signing_script = nvstrcat(op->kernel_source_path,
+ "/scripts/sign-file", NULL);
+ }
if (status) {
ui_status_begin(op, "Signing kernel module:", "Signing");
}
- if (op->multiple_kernel_modules) {
- build_module_instances_parameter =
- nvasprintf(" NV_BUILD_MODULE_INSTANCES=%d",
- NV_MAX_MODULE_INSTANCES);
- }
- else {
- build_module_instances_parameter = nvstrdup("");
- }
+ file = nvstrcat(build_directory, "/", module_filename, NULL);
- concurrency = nvasprintf(" -j%d ", op->concurrency_level);
- cmd = nvstrcat("cd ", build_directory, "; ", op->utils[MAKE], " module-sign"
- " SYSSRC=", op->kernel_source_path,
- " SYSOUT=", op->kernel_output_path,
- " MODSECKEY=", op->module_signing_secret_key,
- " MODPUBKEY=", op->module_signing_public_key,
- " BUILD_MODULES_LIST=\"nvidia", module_suffix, "\" ",
- build_module_instances_parameter,
- mod_sign_cmd ? mod_sign_cmd : "",
- mod_sign_hash ? mod_sign_hash : "", concurrency, NULL);
- nvfree(concurrency);
+ try_sign:
- ret = run_command(op, cmd, NULL, TRUE, 20 /* XXX */, TRUE);
- success = ret == 0;
+ success = try_sign_file(op, file, num_args);
- nvfree(mod_sign_hash);
- nvfree(mod_sign_cmd);
- nvfree(cmd);
- nvfree(build_module_instances_parameter);
+ /* If sign-file failed to run with three arguments, try running it with
+ * four arguments on all subsequent signing attempts. */
+
+ if (num_args == 3 && !success) {
+ num_args = 4;
+
+ /* The four-arg version of sign-file needs a hash. */
+
+ if (!op->module_signing_hash) {
+ op->module_signing_hash = guess_module_signing_hash(op,
+ build_directory);
+ }
+
+ if (op->module_signing_hash) {
+ goto try_sign;
+ } else {
+ ui_error(op, "The installer was unable to sign %s without "
+ "specifying a hash algorithm on the command line to %s, "
+ "and was also unable to automatically detect the hash. "
+ "If you need to sign the NVIDIA kernel modules, please "
+ "try again and set the '--module-signing-hash' option on "
+ "the installer's command line.",
+ file, op->module_signing_script);
+ }
+ }
+
+ nvfree(file);
if (status) {
ui_status_end(op, success ? "done." : "Failed to sign kernel module.");
} else {
ui_log(op, success ? "Signed kernel module." : "Module signing failed");
}
+
op->kernel_module_signed = success;
return success;
-} /* sign_kernel_module */
+}
@@ -791,7 +703,6 @@ int sign_kernel_module(Options *op, const char *build_directory,
static int create_detached_signature(Options *op, Package *p,
const char *build_dir,
PrecompiledFileInfo *fileInfo,
- const char *module_suffix,
const char *module_filename)
{
int ret, command_ret;
@@ -801,7 +712,7 @@ static int create_detached_signature(Options *op, Package *p,
ui_status_begin(op, "Creating a detached signature for the linked "
"kernel module:", "Linking module");
- ret = link_kernel_module(op, p, build_dir, fileInfo);
+ ret = unpack_kernel_modules(op, p, build_dir, fileInfo);
if (!ret) {
ui_error(op, "Failed to link a kernel module for signing.");
@@ -825,7 +736,7 @@ static int create_detached_signature(Options *op, Package *p,
ui_status_update(op, .50, "Signing linked module");
- ret = sign_kernel_module(op, target_dir, module_suffix, FALSE);
+ ret = sign_kernel_module(op, target_dir, module_filename, FALSE);
if (!ret) {
error = "Failed to sign the linked kernel module.";
@@ -857,95 +768,34 @@ done:
nvfree(module_path);
nvfree(target_dir);
return ret;
-} /* create_detached_signature() */
-
-
-/*
- * build_kernel_interface_file() - build the kernel interface(s).
- * Returns true if the build was successful, or false on error.
- *
- * This is done by copying the sources to a temporary working
- * directory and building the kernel interface in that directory.
- */
-
-static int build_kernel_interface_file(Options *op, const char *tmpdir,
- PrecompiledFileInfo *fileInfo,
- const char *kernel_interface_filename)
-{
- char *cmd;
- char *kernel_interface, *build_module_instances_parameter = NULL;
- char *concurrency;
- int ret;
-
- if (op->multiple_kernel_modules) {
- build_module_instances_parameter =
- nvasprintf(" NV_BUILD_MODULE_INSTANCES=%d", NV_MAX_MODULE_INSTANCES);
- }
-
- concurrency = nvasprintf(" -j%d ", op->concurrency_level);
-
- cmd = nvstrcat("cd ", tmpdir, "; ", op->utils[MAKE], " ",
- kernel_interface_filename,
- " SYSSRC=", op->kernel_source_path,
- " SYSOUT=", op->kernel_output_path, concurrency,
- build_module_instances_parameter, NULL);
-
- nvfree(build_module_instances_parameter);
- nvfree(concurrency);
-
- ret = run_command(op, cmd, NULL, TRUE, 25 /* XXX */, TRUE);
-
- free(cmd);
-
- if (ret != 0) {
- ui_status_end(op, "Error.");
- ui_error(op, "Unable to build the NVIDIA kernel module interface.");
- /* XXX need more descriptive error message */
- return FALSE;
- }
-
- /* check that the file exists */
-
- kernel_interface = nvstrcat(tmpdir, "/",
- kernel_interface_filename, NULL);
- ret = access(kernel_interface, F_OK);
- nvfree(kernel_interface);
-
- if (ret == -1) {
- ui_status_end(op, "Error.");
- ui_error(op, "The NVIDIA kernel module interface was not created.");
- return FALSE;
- }
-
- return TRUE;
}
+
/*
* pack_kernel_interface() - Store the input built interfaces in the
* PrecompiledFileInfo array.
*
* Returns true if the packing was successful, or false on error.
*/
-
static int pack_kernel_interface(Options *op, Package *p,
const char *build_dir,
PrecompiledFileInfo *fileInfo,
- const char *module_suffix,
const char *kernel_interface,
const char *module_filename,
- const char *core_file,
- const char *target_directory)
+ const char *core_file)
{
int command_ret;
+ char *file_path = nvstrcat(build_dir, "/", kernel_interface, NULL);
- command_ret = precompiled_read_interface(fileInfo, kernel_interface,
+ command_ret = precompiled_read_interface(fileInfo, file_path,
module_filename,
- core_file, target_directory);
+ core_file, ".");
+
+ nvfree(file_path);
if (command_ret) {
if (op->module_signing_secret_key && op->module_signing_public_key) {
if (!create_detached_signature(op, p, build_dir, fileInfo,
- module_suffix,
module_filename)) {
return FALSE;
}
@@ -957,104 +807,110 @@ static int pack_kernel_interface(Options *op, Package *p,
}
+static void handle_optional_module_failure(Options *op,
+ KernelModuleInfo module,
+ ui_message_func msg_func,
+ const char *action) {
+ if (module.is_optional) {
+ msg_func(op, "The %s kernel module failed to %s. This kernel module "
+ "is required for the proper operation of %s. If you do not "
+ "need to use %s, you can try to install this driver package "
+ "again with the '--%s' option.",
+ module.module_name, action, module.optional_module_dependee,
+ module.optional_module_dependee, module.disable_option);
+ }
+}
-static int build_and_pack_interface(Options *op, Package *p, const char *tmpdir,
- const char *subdir,
- PrecompiledFileInfo *fileInfo,
- const char *interface, const char *module,
- const char *suffix, const char *core)
-{
- int ret;
- char *filename = NULL;
- char *dir = NULL;
-
- ui_status_begin(op, "Building kernel module interface: ", "Building %s",
- interface);
- dir = nvstrcat(tmpdir, "/", subdir, NULL);
- ret = build_kernel_interface_file(op, dir, fileInfo, interface);
+static int pack_kernel_module(Options *op,
+ const char *build_dir,
+ PrecompiledFileInfo *fileInfo,
+ const char *module_filename)
+{
+ int command_ret;
+ char *file_path = nvstrcat(build_dir, "/", module_filename, NULL);
- if (!ret) {
- goto done;
+ if (op->module_signing_secret_key && op->module_signing_public_key) {
+ if (sign_kernel_module(op, build_dir, module_filename, FALSE)) {
+ fileInfo->attributes |= PRECOMPILED_ATTR(EMBEDDED_SIGNATURE);
+ } else {
+ ui_error(op, "Failed to sign precompiled kernel module %s!",
+ module_filename);
+ return FALSE;
+ }
}
- ui_status_end(op, "done.");
+ command_ret = precompiled_read_module(fileInfo, file_path, "");
- ui_log(op, "Kernel module interface compilation complete.");
+ nvfree(file_path);
- filename = nvstrcat(dir, "/", interface, NULL);
-
- /* add the kernel interface to the list of files to be packaged */
- ret = pack_kernel_interface(op, p, tmpdir, fileInfo, suffix, filename,
- module, core, subdir);
-
-done:
- nvfree(dir);
- nvfree(filename);
+ if (command_ret) {
+ return TRUE;
+ }
- return ret;
+ return FALSE;
}
+
/*
- * build_kernel_interface() - build the kernel interface(s), and store any
- * built interfaces in a newly allocated PrecompiledFileInfo array. Return
- * the number of packaged interface files, or 0 on error.
+ * build_kernel_interfaces() - build the kernel modules and interfaces, and
+ * store any precompiled files in a newly allocated PrecompiledFileInfo array.
+ * Return the number of packaged files, or 0 on error.
*
- * The tmpdir created to build the kernel interface is removed before exit.
+ * If fileInfos is NULL, stop after building the kernel modules and do not
+ * build the interfaces.
*
- * For multi-RM, the frontend module interface should be compiled and
- * packaged too.
- *
- * XXX this and build_kernel_module() should be merged.
+ * When building interfaces, copy everything into a temporary directory and
+ * work out of the tmpdir. For kernel module only builds, operate within
+ * p->kernel_module_build_directory, as later packaging steps will look for
+ * the built files there. If a tmpdir is created, it is removed before exit.
*/
-int build_kernel_interface(Options *op, Package *p,
- PrecompiledFileInfo ** fileInfos)
+int build_kernel_interfaces(Options *op, Package *p,
+ PrecompiledFileInfo ** fileInfos)
{
- char *tmpdir = NULL;
- int files_packaged = 0, i;
- int num_files = 1, ret = FALSE;
- char *uvmdir = NULL;
-
- *fileInfos = NULL;
-
- /* create a temporary directory */
-
- tmpdir = make_tmpdir(op);
+ char *tmpdir = NULL, *builddir;
+ int ret, files_packaged = 0, i;
+
+ struct {
+ const char *sanity_check_name;
+ const char *conftest_name;
+ } sanity_checks[] = {
+ { "rivafb", "rivafb_sanity_check" },
+ { "nvidiafb", "nvidiafb_sanity_check" },
+ { "Xen", "xen_sanity_check" },
+ { "PREEMPT_RT", "preempt_rt_sanity_check" },
+ };
- if (!tmpdir) {
- ui_error(op, "Unable to create a temporary build directory.");
- return FALSE;
+ if (fileInfos) {
+ *fileInfos = NULL;
}
-
- /* copy the kernel module sources to it */
-
- ui_log(op, "Copying kernel module sources to temporary directory.");
- if (!copy_directory_contents
- (op, p->kernel_module_build_directory, tmpdir)) {
- ui_error(op, "Unable to copy the kernel module sources to temporary "
- "directory '%s'.", tmpdir);
- goto failed;
- }
+ /* create a temporary directory if we will be packing interfaces */
- uvmdir = nvstrcat(tmpdir, "/" UVM_SUBDIR, NULL);
+ if (fileInfos) {
+ tmpdir = make_tmpdir(op);
+ builddir = tmpdir;
- if (op->install_uvm) {
- if (!mkdir_recursive(op, uvmdir, 0655, FALSE)) {
- ui_error(op, "Unable to create a temporary subdirectory for the "
- "Unified Memory kernel module build.");
- goto failed;
+ if (!tmpdir) {
+ ui_error(op, "Unable to create a temporary build directory.");
+ goto done;
}
- if (!copy_directory_contents(op,
- p->uvm_module_build_directory, uvmdir)) {
- ui_error(op, "Unable to copy the Unified Memory kernel module "
- "sources to temporary directory '%s'.", uvmdir);
- goto failed;
+ /* copy the kernel module sources to it */
+
+ ui_log(op, "Copying kernel module sources to temporary directory.");
+
+ if (!copy_directory_contents
+ (op, p->kernel_module_build_directory, tmpdir)) {
+ ui_error(op, "Unable to copy the kernel module sources to temporary "
+ "directory '%s'.", tmpdir);
+ goto done;
}
+ } else {
+ builddir = p->kernel_module_build_directory;
}
/*
@@ -1062,81 +918,76 @@ int build_kernel_interface(Options *op, Package *p,
* skew error messages
*/
- touch_directory(op, p->kernel_module_build_directory);
-
- if (op->multiple_kernel_modules) {
- num_files = op->num_kernel_modules;
- }
-
- *fileInfos = nvalloc(sizeof(PrecompiledFileInfo) * (num_files + 2));
-
- for (i = 0; i < num_files; i++) {
- char *kernel_module_filename;
- char *kernel_interface_filename;
- char *module_instance_str = NULL;
-
- if (op->multiple_kernel_modules) {
- module_instance_str = nvasprintf("%d", i);
- } else {
- module_instance_str = nvstrdup("");
+ /* run sanity checks */
+ for (i = 0; i < ARRAY_LEN(sanity_checks); i++) {
+ if (!sanity_check(op, builddir,
+ sanity_checks[i].sanity_check_name,
+ sanity_checks[i].conftest_name)) {
+ return FALSE;
}
+ }
- kernel_interface_filename = nvstrdup(p->kernel_interface_filename);
- replace_zero(kernel_interface_filename, i);
-
- kernel_module_filename = nvstrdup(p->kernel_module_filename);
- replace_zero(kernel_module_filename, i);
-
- ret = build_and_pack_interface(op, p, tmpdir, "", *fileInfos + i,
- kernel_interface_filename,
- kernel_module_filename,
- module_instance_str, "nv-kernel.o");
-
- if (!ret) {
- goto interface_done;
+ ui_log(op, "Cleaning kernel module build directory.");
+ run_make(op, p, builddir, "clean", NULL, NULL, 0);
+ ret = run_make(op, p, builddir, "", NULL, "Building kernel modules", 25);
+
+ /* Test to make sure that all kernel modules were built. */
+ for (i = 0; i < p->num_kernel_modules; i++) {
+ if (!check_file(op, builddir, p->kernel_modules[i].module_name)) {
+ handle_optional_module_failure(op,
+ p->kernel_modules[i], ui_error,
+ "build");
+ goto done;
}
+ }
-interface_done:
-
- nvfree(kernel_interface_filename);
- nvfree(kernel_module_filename);
- nvfree(module_instance_str);
-
- if (!ret)
- goto failed;
-
- files_packaged++;
+ /*
+ * Now check the status of the overall build: it may have failed, despite
+ * having produced all expected kernel modules.
+ */
+ if (!ret) {
+ goto done;
}
- if (op->multiple_kernel_modules) {
- ret = build_and_pack_interface(op, p, tmpdir, "", *fileInfos + num_files,
- p->kernel_frontend_interface_filename,
- p->kernel_frontend_module_filename,
- "-frontend", "");
- if (!ret) {
- goto failed;
- }
+ ui_log(op, "Kernel module compilation complete.");
- files_packaged++;
+ /*
+ * If we're not building interfaces, return the number of built modules
+ * instead of the number of packaged interfaces.
+ */
+ if (fileInfos == NULL) {
+ /* If we've made it this far, all the modules were built. */
+ files_packaged = p->num_kernel_modules;
+ goto done;
}
- if (op->install_uvm) {
- ret = build_and_pack_interface(op, p, tmpdir, UVM_SUBDIR,
- *fileInfos + files_packaged,
- p->uvm_interface_filename,
- p->uvm_kernel_module_filename, "-uvm", "");
+ *fileInfos = nvalloc(sizeof(PrecompiledFileInfo) *
+ (p->num_kernel_modules + 1));
- if (!ret) {
- goto failed;
- }
+ for (files_packaged = 0;
+ files_packaged < p->num_kernel_modules;
+ files_packaged++) {
+ PrecompiledFileInfo *fileInfo = *fileInfos + files_packaged;
+ KernelModuleInfo *module = p->kernel_modules + files_packaged;
- files_packaged++;
+ if (module->has_separate_interface_file) {
+ if (!(run_make(op, p, tmpdir, module->interface_filename,
+ NULL, NULL, 0) &&
+ pack_kernel_interface(op, p, tmpdir, fileInfo,
+ module->interface_filename,
+ module->module_filename,
+ module->core_object_name))) {
+ goto done;
+ }
+ } else if (!pack_kernel_module(op, tmpdir, fileInfo,
+ module->module_filename)) {
+ goto done;
+ }
}
-failed:
- nvfree(uvmdir);
+done:
- if (files_packaged == 0) {
+ if (files_packaged == 0 && fileInfos) {
nvfree(*fileInfos);
*fileInfos = NULL;
}
@@ -1147,8 +998,7 @@ failed:
}
return files_packaged;
-
-} /* build_kernel_interface() */
+}
@@ -1503,17 +1353,31 @@ static int ignore_load_error(Options *op, Package *p,
/*
+ * attempt to unload all kernel modules, but don't abort if this fails: the
+ * kernel may not have been configured with support for module unloading
+ * (Linux 2.6).
+ */
+
+static void unload_kernel_modules(Options *op, Package *p) {
+ int i;
+
+ for (i = p->num_kernel_modules - 1; i >= 0; i--) {
+ rmmod_kernel_module(op, p->kernel_modules[i].module_name);
+ }
+}
+
+
+/*
* test_kernel_module() - attempt to insmod the kernel modules and then rmmod
* them. Return TRUE if the insmod succeeded, or FALSE otherwise.
*/
int test_kernel_modules(Options *op, Package *p)
{
- char *cmd = NULL, *data = NULL, *module_path;
+ char *cmd = NULL, *data = NULL;
int ret, i;
const char *depmods[] = { "i2c-core", "drm" };
-
/*
* If we're building/installing for a different kernel, then we
* can't test the module now.
@@ -1530,56 +1394,44 @@ int test_kernel_modules(Options *op, Package *p)
load_kernel_module_quiet(op, depmods[i]);
}
- if (op->multiple_kernel_modules) {
- /* Load nvidia-frontend.ko */
-
- module_path = nvstrcat(p->kernel_module_build_directory, "/",
- p->kernel_frontend_module_filename, NULL);
- ret = do_insmod(op, module_path, &data, "");
- nvfree(module_path);
-
- if (ret != 0) {
- ret = ignore_load_error(op, p, p->kernel_frontend_module_filename,
- data, ret);
- goto test_exit;
- }
-
- nvfree(data);
- }
-
- /*
- * Load nvidia0.ko while building multiple kernel modules or
- * load nvidia.ko for non-multiple-kernel-module/simple builds.
+ /*
+ * Attempt to load each kernel module one at a time. The order of the list
+ * in the package manifest is set such that loading modules in that order
+ * should satisfy any dependencies that exist between modules.
*/
- module_path = nvstrcat(p->kernel_module_build_directory, "/",
- p->kernel_module_filename, NULL);
- ret = do_insmod(op, module_path, &data,
- "NVreg_DeviceFileUID=0 NVreg_DeviceFileGID=0 "
- "NVreg_DeviceFileMode=0 NVreg_ModifyDeviceFiles=0");
-
- nvfree(module_path);
+ for (i = 0; i < p->num_kernel_modules; i++) {
+ int module_success = FALSE;
+ char *cmd_output;
+ char *module_path = nvstrcat(p->kernel_module_build_directory, "/",
+ p->kernel_modules[i].module_filename,
+ NULL);
+ const char *module_opts = "";
+
+ if (strcmp(p->kernel_modules[i].module_name, "nvidia") == 0) {
+ module_opts = "NVreg_DeviceFileUID=0 NVreg_DeviceFileGID=0 "
+ "NVreg_DeviceFileMode=0 NVreg_ModifyDeviceFiles=0";
+ }
- if (ret != 0) {
- ret = ignore_load_error(op, p, p->kernel_module_filename, data, ret);
- goto test_exit;
- }
- if (op->install_uvm) {
- module_path = nvstrcat(p->uvm_module_build_directory, "/",
- p->uvm_kernel_module_filename, NULL);
- ret = do_insmod(op, module_path, &data, "");
+ ret = do_insmod(op, module_path, &cmd_output, module_opts);
nvfree(module_path);
- if (ret != 0) {
- ret = ignore_load_error(op, p, p->uvm_kernel_module_filename, data,
- ret);
+ if (ret == 0) {
+ module_success = TRUE;
+ } else {
+ ret = ignore_load_error(op, p, p->kernel_modules[i].module_filename,
+ cmd_output, ret);
if (ret) {
- ui_warn(op, "The NVIDIA Unified Memory module failed to load, "
- "and the load failure was ignored. This module is "
- "required in order for the CUDA driver to function; if "
- "the load failure cannot be resolved, then this system "
- "will be unable to run CUDA applications.");
+ op->load_error_ignored = TRUE;
+ handle_optional_module_failure(op,
+ p->kernel_modules[i], ui_warn,
+ "load");
}
+ }
+
+ nvfree(cmd_output);
+
+ if (!module_success) {
goto test_exit;
}
}
@@ -1592,27 +1444,11 @@ int test_kernel_modules(Options *op, Package *p)
check_for_warning_messages(op);
- /*
- * attempt to unload the kernel modules, but don't abort if this fails:
- * the kernel may not have been configured with support for module unloading
- * (Linux 2.6).
- */
-
- if (op->install_uvm) {
- rmmod_kernel_module(op, p->uvm_kernel_module_name);
- }
-
- rmmod_kernel_module(op, p->kernel_module_name);
-
- if (op->multiple_kernel_modules) {
- rmmod_kernel_module(op, p->kernel_frontend_module_name);
- }
+ unload_kernel_modules(op, p);
ret = TRUE;
test_exit:
- nvfree(data);
-
/*
* display/log the last few lines of the kernel ring buffer
* to provide further details in case of a load failure or
@@ -1652,8 +1488,12 @@ test_exit:
static int modprobe_helper(Options *op, const char *module_name,
int quiet, int unload)
{
+ int ret = 0, old_loglevel, loglevel_set;
char *cmd, *data;
- int ret, old_loglevel, loglevel_set;
+
+ if (op->load_error_ignored) {
+ return TRUE;
+ }
cmd = nvstrcat(op->utils[MODPROBE],
quiet ? " -q" : "",
@@ -1662,37 +1502,31 @@ static int modprobe_helper(Options *op, const char *module_name,
NULL);
loglevel_set = set_loglevel(PRINTK_LOGLEVEL_KERN_ALERT, &old_loglevel);
-
+
ret = run_command(op, cmd, &data, FALSE, 0, TRUE);
if (loglevel_set) {
set_loglevel(old_loglevel, NULL);
}
+ nvfree(cmd);
+
if (!quiet && ret != 0) {
- if (op->expert) {
- ui_error(op, "Unable to %s the kernel module: '%s'",
- unload ? "unload" : "load",
- data);
- } else {
- ui_error(op, "Unable to %s the kernel module.",
- unload ? "unload" : "load");
- }
- ret = FALSE;
- } else {
- ret = TRUE;
+ char *expert_detail = nvstrcat(": '", data, "'", NULL);
+ ui_error(op, "Unable to %s the '%s' kernel module%s",
+ unload ? "unload" : "load", module_name,
+ op->expert? expert_detail : ".");
+ nvfree(expert_detail);
}
- nvfree(cmd);
nvfree(data);
-
- return ret;
-} /* load_kernel_module() */
+ return ret == 0;
+}
-int load_kernel_module(Options *op, Package *p)
+int load_kernel_module(Options *op, const char *module_name)
{
- return modprobe_helper(op, p->kernel_module_name, FALSE, FALSE);
+ return modprobe_helper(op, module_name, FALSE, FALSE);
}
static void load_kernel_module_quiet(Options *op, const char *module_name)
@@ -1705,6 +1539,24 @@ static void modprobe_remove_kernel_module_quiet(Options *op, const char *name)
modprobe_helper(op, name, TRUE, TRUE);
}
+/*
+ * Attempt to load all kernel modules that are part of the Package. Returns
+ * the number of successfully loaded kernel modules.
+ */
+int load_kernel_modules(Options *op, Package *p)
+{
+ int i;
+
+ for (i = 0; i < p->num_kernel_modules; i++) {
+ if (!load_kernel_module(op, p->kernel_modules[i].module_name)) {
+ break;
+ }
+ }
+
+ return i;
+}
+
+
/*
* check_for_unloaded_kernel_module() - test if any of the "bad"
@@ -1712,11 +1564,11 @@ static void modprobe_remove_kernel_module_quiet(Options *op, const char *name)
* we can't unload it, then report an error and return FALSE;
*/
-int check_for_unloaded_kernel_module(Options *op, Package *p)
+int check_for_unloaded_kernel_module(Options *op)
{
- int n = 0;
+ int n;
int loaded = FALSE;
- unsigned int bits = 0;
+ unsigned long long int bits = 0;
/*
* We can skip this check if we are installing for a non-running
@@ -1741,30 +1593,27 @@ int check_for_unloaded_kernel_module(Options *op, Package *p)
return TRUE;
}
- while (p->bad_modules[n]) {
- if (check_for_loaded_kernel_module(op, p->bad_modules[n])) {
+ for (n = 0; n < num_conflicting_kernel_modules; n++) {
+ if (check_for_loaded_kernel_module(op, conflicting_kernel_modules[n])) {
loaded = TRUE;
bits |= (1 << n);
}
- n++;
}
if (!loaded) return TRUE;
/* one or more kernel modules is loaded... try to unload them */
- n = 0;
- while (p->bad_modules[n]) {
+ for (n = 0; n < num_conflicting_kernel_modules; n++) {
if (!(bits & (1 << n))) {
- n++;
continue;
}
- rmmod_kernel_module(op, p->bad_modules[n]);
+ rmmod_kernel_module(op, conflicting_kernel_modules[n]);
/* check again */
- if (check_for_loaded_kernel_module(op, p->bad_modules[n])) {
+ if (check_for_loaded_kernel_module(op, conflicting_kernel_modules[n])) {
ui_error(op, "An NVIDIA kernel module '%s' appears to already "
"be loaded in your kernel. This may be because it is "
"in use (for example, by an X server, a CUDA program, "
@@ -1778,11 +1627,10 @@ int check_for_unloaded_kernel_module(Options *op, Package *p)
"error may have occured that has corrupted an NVIDIA "
"kernel module's usage count, for which the simplest "
"remedy is to reboot your computer.",
- p->bad_modules[n]);
+ conflicting_kernel_modules[n]);
return FALSE;
}
- n++;
}
return TRUE;
@@ -1791,44 +1639,6 @@ int check_for_unloaded_kernel_module(Options *op, Package *p)
/*
- * add_file_to_search_filelist() - Add file to build a list
- * of files expected to be unpacked.
- */
-
-static void add_file_to_search_filelist(char **search_filelist, char *filename)
-{
- int index = 0;
-
- while(search_filelist[index]) {
- index++;
- }
-
- if (index == SEARCH_FILELIST_MAX_ENTRIES)
- return;
-
- search_filelist[index] = nvstrdup(filename);
-
-} /* add_file_to_search_filelist() */
-
-
-/*
- * free_search_filelist() - frees the list of files expected
- * to unpack
- */
-
-static void free_search_filelist(char **search_filelist)
-{
- int index = 0;
-
- while (search_filelist[index]) {
- free(search_filelist[index]);
- index++;
- }
-
-} /*free_search_filelist() */
-
-
-/*
* find_precompiled_kernel_interface() - do assorted black magic to
* determine if the given package contains a precompiled kernel interface
* for the kernel on this system.
@@ -1841,8 +1651,8 @@ PrecompiledInfo *find_precompiled_kernel_interface(Options *op, Package *p)
{
char *proc_version_string, *tmp;
PrecompiledInfo *info = NULL;
- char *search_filelist[SEARCH_FILELIST_MAX_ENTRIES+1];
- int index;
+ char **search_filelist = NULL;
+ int i;
/* allow the user to completely skip this search */
@@ -1862,19 +1672,14 @@ PrecompiledInfo *find_precompiled_kernel_interface(Options *op, Package *p)
if (!mkdir_recursive(op, p->kernel_module_build_directory, 0755, FALSE))
goto done;
- memset(search_filelist, 0, sizeof(search_filelist));
+ search_filelist = nvalloc(p->num_kernel_modules * sizeof(char*));
- if (op->multiple_kernel_modules) {
- add_file_to_search_filelist(search_filelist,
- p->kernel_frontend_interface_filename);
- }
-
- for (index = 0; index < op->num_kernel_modules; index++) {
- char *tmp;
- tmp = nvstrdup(p->kernel_interface_filename);
- replace_zero(tmp, index);
- add_file_to_search_filelist(search_filelist, tmp);
- free(tmp);
+ for (i = 0; i < p->num_kernel_modules; i++) {
+ if (p->kernel_modules[i].has_separate_interface_file) {
+ search_filelist[i] = p->kernel_modules[i].interface_filename;
+ } else {
+ search_filelist[i] = p->kernel_modules[i].module_filename;
+ }
}
/*
@@ -1926,13 +1731,10 @@ PrecompiledInfo *find_precompiled_kernel_interface(Options *op, Package *p)
"found at '%s'; this means that the installer will need "
"to compile a kernel interface for your kernel.",
op->precompiled_kernel_interfaces_url);
- free_search_filelist(search_filelist);
goto done;
}
}
- free_search_filelist(search_filelist);
-
/* If we found one, ask expert users if they really want to use it */
if (info && op->expert) {
@@ -1953,6 +1755,8 @@ PrecompiledInfo *find_precompiled_kernel_interface(Options *op, Package *p)
done:
+ nvfree(search_filelist);
+
nvfree(proc_version_string);
if (!info && op->expert) {
@@ -2006,7 +1810,8 @@ KernelConfigOptionStatus test_kernel_config_option(Options* op, Package *p,
char *conftest_cmd;
conftest_cmd = nvstrcat("test_configuration_option ", option, NULL);
- ret = run_conftest(op, p, conftest_cmd, NULL);
+ ret = run_conftest(op, p->kernel_module_build_directory, conftest_cmd,
+ NULL);
nvfree(conftest_cmd);
return ret ? KERNEL_CONFIG_OPTION_DEFINED :
@@ -2023,11 +1828,12 @@ KernelConfigOptionStatus test_kernel_config_option(Options* op, Package *p,
* signing kernel modules, or NULL if it can't be determined.
*/
-char *guess_module_signing_hash(Options *op, Package *p)
+char *guess_module_signing_hash(Options *op, const char *build_directory)
{
char *ret;
- if (run_conftest(op, p, "guess_module_signing_hash", &ret)) {
+ if (run_conftest(op, build_directory,
+ "guess_module_signing_hash", &ret)) {
return ret;
}
@@ -2525,7 +2331,8 @@ int check_cc_version(Options *op, Package *p)
dummyop.kernel_source_path = "DUMMY_SOURCE_PATH";
dummyop.kernel_output_path = "DUMMY_OUTPUT_PATH";
- ret = run_conftest(&dummyop, p, "cc_version_check just_msg", &result);
+ ret = run_conftest(&dummyop, p->kernel_module_build_directory,
+ "cc_version_check just_msg", &result);
if (ret) return TRUE;
@@ -2546,100 +2353,30 @@ int check_cc_version(Options *op, Package *p)
/*
- * fbdev_check() - run the rivafb_sanity_check and the nvidiafb_sanity_check
- * conftests; if either test fails, print the error message from the test
- * and abort the driver installation.
+ * sanity_check() - run the given sanity check conftest; if the test fails,
+ * print the error message from the test. Return the status from the test.
*/
-static int fbdev_check(Options *op, Package *p)
+static int sanity_check(Options *op, const char *dir,
+ const char *sanity_check_name,
+ const char *conftest_name)
{
- char *result;
+ char *result, *conftest_args;
int ret;
-
- ui_log(op, "Performing rivafb check.");
-
- ret = run_conftest(op, p,"rivafb_sanity_check just_msg", &result);
-
- if (!ret) {
- if (result)
- ui_error(op, "%s", result);
- nvfree(result);
- return FALSE;
- }
+ ui_log(op, "Performing %s check.", sanity_check_name);
- ui_log(op, "Performing nvidiafb check.");
-
- ret = run_conftest(op, p,"nvidiafb_sanity_check just_msg", &result);
-
- if (!ret) {
- if (result)
- ui_error(op, "%s", result);
- nvfree(result);
+ conftest_args = nvstrcat(conftest_name, " just_msg", NULL);
+ ret = run_conftest(op, dir, conftest_args, &result);
+ nvfree(conftest_args);
- return FALSE;
+ if (!ret && result) {
+ ui_error(op, "%s", result);
}
- return TRUE;
-
-} /* fbdev_check() */
-
-
-
-/*
- * xen_check() - run the xen_sanity_check conftest; if this test fails, print
- * the test's error message and abort the driver installation.
- */
-
-static int xen_check(Options *op, Package *p)
-{
- char *result;
- int ret;
-
- ui_log(op, "Performing Xen check.");
-
- ret = run_conftest(op, p,"xen_sanity_check just_msg", &result);
-
- if (!ret) {
- if (result)
- ui_error(op, "%s", result);
- nvfree(result);
-
- return FALSE;
- }
-
- return TRUE;
-
-} /* xen_check() */
-
-
-
-/*
- * preempt_rt_check() - run the preempt_rt_sanity_check conftest; if this
- * test fails, print the test's error message and abort the driver
- * installation.
- */
-
-static int preempt_rt_check(Options *op, Package *p)
-{
- char *result;
- int ret;
-
- ui_log(op, "Performing PREEMPT_RT check.");
-
- ret = run_conftest(op, p, "preempt_rt_sanity_check just_msg", &result);
-
- if (!ret) {
- if (result)
- ui_error(op, "%s", result);
- nvfree(result);
-
- return FALSE;
- }
-
- return TRUE;
-
-} /* preempt_rt_check() */
+ nvfree(result);
+ return ret;
+}
@@ -2786,3 +2523,132 @@ char *get_machine_arch(Options *op)
}
} /* get_machine_arch() */
+
+/*
+ * Run `make` with the specified target and make variables. The variables
+ * are given in the form of a NULL-terminated array of alternating key
+ * and value strings, e.g. { "KEY1", "value1", "KEY2", "value2", NULL }.
+ * If a 'status' string is given, then a ui_status progress bar is shown
+ * using 'status' as the initial message, expecting 'lines' lines of output
+ * from the make command.
+ */
+static int run_make(Options *op, Package *p, char *dir, const char *target,
+ char **vars, const char *status, int lines) {
+ char *cmd, *concurrency, *data = NULL;
+ int i = 0, ret;
+
+ concurrency = nvasprintf(" -j%d ", op->concurrency_level);
+
+ cmd = nvstrcat("cd ", dir, "; ",
+ op->utils[MAKE], " -k", concurrency, target,
+ " NV_EXCLUDE_KERNEL_MODULES=\"",
+ p->excluded_kernel_modules, "\"",
+ " SYSSRC=\"", op->kernel_source_path, "\"",
+ " SYSOUT=\"", op->kernel_output_path, "\"",
+ NULL);
+ nvfree(concurrency);
+
+ if (vars) {
+ while (vars[i] && vars[i+1]) {
+ char *old_cmd = cmd;
+
+ cmd = nvstrcat(old_cmd, " ", vars[i], "=\"", vars[i+1], "\"", NULL);
+ nvfree(old_cmd);
+ i += 2;
+ }
+ }
+
+ if (status) {
+ ui_status_begin(op, status, "");
+ }
+
+ ret = (run_command(op, cmd, &data, TRUE, status ? lines : 0, TRUE) == 0);
+
+ if (status) {
+ if (ret) {
+ ui_status_end(op, "done.");
+ } else {
+ ui_status_end(op, "Error.");
+ }
+ }
+
+ if (!ret) {
+ char *status_extra;
+
+ if (status) {
+ status_extra = nvasprintf(" while performing the step: \"%s\"",
+ status);
+ } else {
+ status_extra = nvstrdup("");
+ }
+
+ ui_error(op, "An error occurred%s. See " DEFAULT_LOG_FILE_NAME
+ " for details.", status_extra);
+ ui_log(op, "The command `%s` failed with the following output:\n\n%s",
+ cmd, data);
+ nvfree(status_extra);
+ }
+
+ nvfree(cmd);
+ nvfree(data);
+
+ return ret;
+}
+
+
+/*
+ * Remove any instances of kernel module 'module' from the kernel modules
+ * list in the package.
+ */
+int remove_kernel_module_from_package(Package *p, const char *module)
+{
+ int i, found = 0;
+
+ for (i = 0; i < p->num_kernel_modules; i++) {
+ if (found) {
+ p->kernel_modules[i - found] = p->kernel_modules[i];
+ }
+
+ if (strcmp(p->kernel_modules[i].module_name, module) == 0) {
+ free_kernel_module_info(p->kernel_modules[i]);
+ found++;
+ }
+ }
+
+ if (found) {
+ char *old_exclude_list;
+
+ p->num_kernel_modules -= found;
+ old_exclude_list = p->excluded_kernel_modules;
+ p->excluded_kernel_modules = nvstrcat(module, " ", old_exclude_list,
+ NULL);
+ nvfree(old_exclude_list);
+ }
+
+ return found;
+}
+
+
+void free_kernel_module_info(KernelModuleInfo info)
+{
+ nvfree(info.module_name);
+ nvfree(info.module_filename);
+ if (info.has_separate_interface_file) {
+ nvfree(info.interface_filename);
+ nvfree(info.core_object_name);
+ }
+}
+
+
+int package_includes_kernel_module(const Package *p, const char *module)
+{
+ int i;
+
+ for (i = 0; i < p->num_kernel_modules; i++) {
+ if (strcmp(p->kernel_modules[i].module_name, module) == 0) {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
diff --git a/kernel.h b/kernel.h
index 1ce4b35..7770323 100644
--- a/kernel.h
+++ b/kernel.h
@@ -32,26 +32,29 @@ typedef enum {
int determine_kernel_module_installation_path (Options*);
int determine_kernel_source_path (Options*, Package*);
int determine_kernel_output_path (Options*);
-int link_kernel_module (Options*, Package*,
+int unpack_kernel_modules (Options*, Package*,
const char *,
const PrecompiledFileInfo *);
int check_cc_version (Options*, Package*);
int build_kernel_modules (Options*, Package*);
-int build_kernel_interface (Options*, Package*,
+int build_kernel_interfaces (Options*, Package*,
PrecompiledFileInfo **);
int test_kernel_modules (Options*, Package*);
-int load_kernel_module (Options*, Package*);
-int check_for_unloaded_kernel_module (Options*, Package*);
+int load_kernel_module (Options*, const char*);
+int load_kernel_modules (Options*, Package*);
+int check_for_unloaded_kernel_module (Options*);
PrecompiledInfo *find_precompiled_kernel_interface (Options*, Package*);
char *get_kernel_name (Options*);
KernelConfigOptionStatus test_kernel_config_option (Options*, Package*,
const char*);
int sign_kernel_module (Options*, const char*,
const char*, int);
-char *guess_module_signing_hash (Options*, Package*);
-int rmmod_kernel_module (Options*, const char*);
-
-#define SEARCH_FILELIST_MAX_ENTRIES 32
+char *guess_module_signing_hash (Options*, const char*);
+int remove_kernel_module_from_package (Package*, const char*);
+void free_kernel_module_info (KernelModuleInfo);
+int package_includes_kernel_module (const Package*,
+ const char *);
+int rmmod_kernel_module (Options*, const char *);
#ifndef ENOKEY
#define ENOKEY 126 /* Required key not available */
diff --git a/manifest.c b/manifest.c
index d1f0e6e..ab9e82c 100644
--- a/manifest.c
+++ b/manifest.c
@@ -33,7 +33,8 @@
_is_shared_lib, \
_is_opengl, \
_is_temporary, \
- _is_wrapper) \
+ _is_wrapper, \
+ _inherit_path) \
#_name , FILE_TYPE_ ## _name , \
{ \
.has_arch = _has_arch, \
@@ -45,6 +46,7 @@
.is_opengl = _is_opengl, \
.is_temporary = _is_temporary, \
.is_wrapper = _is_wrapper, \
+ .inherit_path = _inherit_path, \
}
/*
@@ -58,65 +60,65 @@ static const struct {
} packageEntryFileTypeTable[] = {
/*
- * is_wrapper ---------------------------------------+
- * is_temporary ------------------------------------+ |
- * is_opengl ---------------------------------+ | |
- * is_shared_lib ------------------------------+ | | |
- * is_symlink ---------------------------+ | | | |
- * has_path ------------------------+ | | | | |
- * installable ---------------------+ | | | | | |
- * has_tls_class ------------------+ | | | | | | |
- * has_arch ---------------+ | | | | | | | |
- * | | | | | | | | |
+ * inherit_path ------------------------------------------+
+ * is_wrapper ---------------------------------------+ |
+ * is_temporary ------------------------------------+ | |
+ * is_opengl ---------------------------------+ | | |
+ * is_shared_lib ------------------------------+ | | | |
+ * is_symlink ---------------------------+ | | | | |
+ * has_path ------------------------+ | | | | | |
+ * installable ---------------------+ | | | | | | |
+ * has_tls_class ------------------+ | | | | | | | |
+ * has_arch ---------------+ | | | | | | | | |
+ * | | | | | | | | | |
*/
- { ENTRY(KERNEL_MODULE_SRC, F, F, T, F, F, F, F, F, F) },
- { ENTRY(KERNEL_MODULE_CMD, F, F, F, F, F, F, F, F, F) },
- { ENTRY(KERNEL_MODULE, F, F, T, F, F, F, F, F, F) },
- { ENTRY(OPENGL_HEADER, F, F, T, T, F, F, T, F, F) },
- { ENTRY(CUDA_ICD, F, F, T, F, F, F, F, F, F) },
- { ENTRY(OPENGL_LIB, T, F, T, F, F, T, T, F, F) },
- { ENTRY(CUDA_LIB, T, F, T, T, F, T, F, F, F) },
- { ENTRY(OPENCL_LIB, T, F, T, T, F, T, F, F, F) },
- { ENTRY(OPENCL_WRAPPER_LIB, T, F, T, T, F, T, F, F, T) },
- { ENTRY(OPENCL_LIB_SYMLINK, T, F, F, T, T, F, F, F, F) },
- { ENTRY(OPENCL_WRAPPER_SYMLINK, T, F, F, T, T, F, F, F, T) },
- { ENTRY(LIBGL_LA, T, F, T, F, F, F, T, T, F) },
- { ENTRY(TLS_LIB, T, T, T, T, F, T, T, F, F) },
- { ENTRY(UTILITY_LIB, T, F, T, F, F, T, F, F, F) },
- { ENTRY(DOCUMENTATION, F, F, T, T, F, F, F, F, F) },
- { ENTRY(APPLICATION_PROFILE, F, F, T, T, F, F, F, F, F) },
- { ENTRY(MANPAGE, F, F, T, T, F, F, F, F, F) },
- { ENTRY(EXPLICIT_PATH, F, F, T, T, F, F, F, F, F) },
- { ENTRY(OPENGL_SYMLINK, T, F, F, F, T, F, T, F, F) },
- { ENTRY(CUDA_SYMLINK, T, F, F, T, T, F, F, F, F) },
- { ENTRY(TLS_SYMLINK, T, T, F, T, T, F, T, F, F) },
- { ENTRY(UTILITY_LIB_SYMLINK, T, F, F, F, T, F, F, F, F) },
- { ENTRY(INSTALLER_BINARY, F, F, T, F, F, F, F, F, F) },
- { ENTRY(UTILITY_BINARY, F, F, T, F, F, F, F, F, F) },
- { ENTRY(UTILITY_BIN_SYMLINK, F, F, F, F, T, F, F, F, F) },
- { ENTRY(DOT_DESKTOP, F, F, T, T, F, F, F, T, F) },
- { ENTRY(XMODULE_SHARED_LIB, F, F, T, T, F, T, F, F, F) },
- { ENTRY(XMODULE_SYMLINK, F, F, F, T, T, F, F, F, F) },
- { ENTRY(GLX_MODULE_SHARED_LIB, F, F, T, T, F, T, T, F, F) },
- { ENTRY(GLX_MODULE_SYMLINK, F, F, F, T, T, F, T, F, F) },
- { ENTRY(XMODULE_NEWSYM, F, F, F, T, T, F, F, F, F) },
- { ENTRY(VDPAU_LIB, T, F, T, T, F, T, F, F, F) },
- { ENTRY(VDPAU_WRAPPER_LIB, T, F, T, T, F, T, F, F, T) },
- { ENTRY(VDPAU_SYMLINK, T, F, F, T, T, F, F, F, F) },
- { ENTRY(VDPAU_WRAPPER_SYMLINK, T, F, F, T, T, F, F, F, T) },
- { ENTRY(NVCUVID_LIB, T, F, T, F, F, T, F, F, F) },
- { ENTRY(NVCUVID_LIB_SYMLINK, T, F, F, F, T, F, F, F, F) },
- { ENTRY(ENCODEAPI_LIB, T, F, T, F, F, T, F, F, F) },
- { ENTRY(ENCODEAPI_LIB_SYMLINK, T, F, F, F, T, F, F, F, F) },
- { ENTRY(VGX_LIB, F, F, T, F, F, T, F, F, F) },
- { ENTRY(VGX_LIB_SYMLINK, F, F, F, F, T, F, F, F, F) },
- { ENTRY(NVIDIA_MODPROBE, F, F, T, T, F, F, F, F, F) },
- { ENTRY(NVIDIA_MODPROBE_MANPAGE,F, F, T, T, F, F, F, F, F) },
- { ENTRY(MODULE_SIGNING_KEY, F, F, T, F, F, F, F, T, F) },
- { ENTRY(NVIFR_LIB, T, F, T, F, F, T, F, F, F) },
- { ENTRY(NVIFR_LIB_SYMLINK, T, F, F, F, T, F, F, F, F) },
- { ENTRY(UVM_MODULE_SRC, F, F, T, F, F, F, F, F, F) },
- { ENTRY(XORG_OUTPUTCLASS_CONFIG,F, F, T, F, F, F, F, F, F) },
+ { ENTRY(KERNEL_MODULE_SRC, F, F, T, F, F, F, F, F, F, T) },
+ { ENTRY(KERNEL_MODULE, F, F, T, F, F, F, F, F, F, F) },
+ { ENTRY(OPENGL_HEADER, F, F, T, T, F, F, T, F, F, F) },
+ { ENTRY(CUDA_ICD, F, F, T, F, F, F, F, F, F, F) },
+ { ENTRY(OPENGL_LIB, T, F, T, F, F, T, T, F, F, F) },
+ { ENTRY(CUDA_LIB, T, F, T, T, F, T, F, F, F, F) },
+ { ENTRY(OPENCL_LIB, T, F, T, T, F, T, F, F, F, F) },
+ { ENTRY(OPENCL_WRAPPER_LIB, T, F, T, T, F, T, F, F, T, F) },
+ { ENTRY(OPENCL_LIB_SYMLINK, T, F, F, T, T, F, F, F, F, F) },
+ { ENTRY(OPENCL_WRAPPER_SYMLINK, T, F, F, T, T, F, F, F, T, F) },
+ { ENTRY(LIBGL_LA, T, F, T, F, F, F, T, T, F, F) },
+ { ENTRY(TLS_LIB, T, T, T, T, F, T, T, F, F, F) },
+ { ENTRY(UTILITY_LIB, T, F, T, F, F, T, F, F, F, F) },
+ { ENTRY(DOCUMENTATION, F, F, T, T, F, F, F, F, F, F) },
+ { ENTRY(APPLICATION_PROFILE, F, F, T, T, F, F, F, F, F, F) },
+ { ENTRY(MANPAGE, F, F, T, T, F, F, F, F, F, F) },
+ { ENTRY(EXPLICIT_PATH, F, F, T, T, F, F, F, F, F, F) },
+ { ENTRY(OPENGL_SYMLINK, T, F, F, F, T, F, T, F, F, F) },
+ { ENTRY(CUDA_SYMLINK, T, F, F, T, T, F, F, F, F, F) },
+ { ENTRY(TLS_SYMLINK, T, T, F, T, T, F, T, F, F, F) },
+ { ENTRY(UTILITY_LIB_SYMLINK, T, F, F, F, T, F, F, F, F, F) },
+ { ENTRY(INSTALLER_BINARY, F, F, T, F, F, F, F, F, F, F) },
+ { ENTRY(UTILITY_BINARY, F, F, T, F, F, F, F, F, F, F) },
+ { ENTRY(UTILITY_BIN_SYMLINK, F, F, F, F, T, F, F, F, F, F) },
+ { ENTRY(DOT_DESKTOP, F, F, T, T, F, F, F, T, F, F) },
+ { ENTRY(XMODULE_SHARED_LIB, F, F, T, T, F, T, F, F, F, F) },
+ { ENTRY(XMODULE_SYMLINK, F, F, F, T, T, F, F, F, F, F) },
+ { ENTRY(GLX_MODULE_SHARED_LIB, F, F, T, T, F, T, T, F, F, F) },
+ { ENTRY(GLX_MODULE_SYMLINK, F, F, F, T, T, F, T, F, F, F) },
+ { ENTRY(XMODULE_NEWSYM, F, F, F, T, T, F, F, F, F, F) },
+ { ENTRY(VDPAU_LIB, T, F, T, T, F, T, F, F, F, F) },
+ { ENTRY(VDPAU_WRAPPER_LIB, T, F, T, T, F, T, F, F, T, F) },
+ { ENTRY(VDPAU_SYMLINK, T, F, F, T, T, F, F, F, F, F) },
+ { ENTRY(VDPAU_WRAPPER_SYMLINK, T, F, F, T, T, F, F, F, T, F) },
+ { ENTRY(NVCUVID_LIB, T, F, T, F, F, T, F, F, F, F) },
+ { ENTRY(NVCUVID_LIB_SYMLINK, T, F, F, F, T, F, F, F, F, F) },
+ { ENTRY(ENCODEAPI_LIB, T, F, T, F, F, T, F, F, F, F) },
+ { ENTRY(ENCODEAPI_LIB_SYMLINK, T, F, F, F, T, F, F, F, F, F) },
+ { ENTRY(VGX_LIB, F, F, T, F, F, T, F, F, F, F) },
+ { ENTRY(VGX_LIB_SYMLINK, F, F, F, F, T, F, F, F, F, F) },
+ { ENTRY(NVIDIA_MODPROBE, F, F, T, T, F, F, F, F, F, F) },
+ { ENTRY(NVIDIA_MODPROBE_MANPAGE,F, F, T, T, F, F, F, F, F, F) },
+ { ENTRY(MODULE_SIGNING_KEY, F, F, T, F, F, F, F, T, F, F) },
+ { ENTRY(NVIFR_LIB, T, F, T, F, F, T, F, F, F, F) },
+ { ENTRY(NVIFR_LIB_SYMLINK, T, F, F, F, T, F, F, F, F, F) },
+ { ENTRY(XORG_OUTPUTCLASS_CONFIG,F, F, T, F, F, F, F, F, F, F) },
+ { ENTRY(DKMS_CONF ,F, F, T, F, F, F, F, T, F, T) },
};
/*
@@ -128,7 +130,7 @@ PackageEntryFileCapabilities get_file_type_capabilities(
)
{
int i;
- PackageEntryFileCapabilities nullCaps = { F, F, F, F, F, F, F, F, F };
+ PackageEntryFileCapabilities nullCaps = { F, F, F, F, F, F, F, F, F, F };
for (i = 0; i < ARRAY_LEN(packageEntryFileTypeTable); i++) {
if (type == packageEntryFileTypeTable[i].type) {
@@ -182,7 +184,7 @@ void get_installable_file_type_list(
}
if (((type == FILE_TYPE_KERNEL_MODULE_SRC) ||
- (type == FILE_TYPE_UVM_MODULE_SRC)) &&
+ (type == FILE_TYPE_DKMS_CONF)) &&
op->no_kernel_module_source) {
continue;
}
diff --git a/misc.c b/misc.c
index 2541a8b..83c5d7d 100644
--- a/misc.c
+++ b/misc.c
@@ -1248,7 +1248,7 @@ void should_install_uvm(Options *op, Package *p)
{
/* if the package does not include UVM, it can't be installed. */
- if (!op->uvm_files_packaged) {
+ if (!package_includes_kernel_module(p, "nvidia-uvm")) {
op->install_uvm = FALSE;
return;
}
@@ -1266,6 +1266,8 @@ void should_install_uvm(Options *op, Package *p)
ui_warn(op, "The NVIDIA Unified Memory kernel module will not be "
"installed. As a result, CUDA applications will not be able to "
"run with this installation of the NVIDIA driver.");
+
+ remove_kernel_module_from_package(p, "nvidia-uvm");
}
}
diff --git a/nvidia-installer.c b/nvidia-installer.c
index 94300f1..92176a9 100644
--- a/nvidia-installer.c
+++ b/nvidia-installer.c
@@ -145,9 +145,9 @@ static Options *load_default_options(void)
op->dkms = FALSE;
op->install_vdpau_wrapper = NV_OPTIONAL_BOOL_DEFAULT;
op->check_for_alternate_installs = TRUE;
- op->num_kernel_modules = 1;
op->install_uvm = TRUE;
op->install_compat32_libs = NV_OPTIONAL_BOOL_DEFAULT;
+ op->install_libglx_indirect = NV_OPTIONAL_BOOL_DEFAULT;
return op;
@@ -361,7 +361,7 @@ static void parse_commandline(int argc, char *argv[], Options *op)
case NO_RPMS_OPTION:
op->no_rpms = TRUE;
break;
- case NO_RECURSION_OPTION:
+ case 'r':
op->no_recursion = TRUE;
break;
case FORCE_SELINUX_OPTION:
@@ -430,28 +430,18 @@ static void parse_commandline(int argc, char *argv[], Options *op)
op->install_vdpau_wrapper = boolval ? NV_OPTIONAL_BOOL_TRUE :
NV_OPTIONAL_BOOL_FALSE;
break;
- case MULTIPLE_KERNEL_MODULES_OPTION:
- if (intval < 0) {
- nv_error_msg("Invalid parameter for '--multiple-kernel-modules'");
- goto fail;
- }
- op->multiple_kernel_modules = TRUE;
- /* Unified Memory is incompatible with multiple kernel modules */
- op->install_uvm = FALSE;
-
- if (intval > NV_MAX_MODULE_INSTANCES) {
- op->num_kernel_modules = NV_MAX_MODULE_INSTANCES;
- }
- else {
- op->num_kernel_modules = intval;
- }
- break;
case NO_UVM_OPTION:
op->install_uvm = FALSE;
break;
case NO_CHECK_FOR_ALTERNATE_INSTALLS_OPTION:
op->check_for_alternate_installs = FALSE;
break;
+ case FORCE_LIBGLX_INDIRECT:
+ op->install_libglx_indirect = NV_OPTIONAL_BOOL_TRUE;
+ break;
+ case NO_LIBGLX_INDIRECT:
+ op->install_libglx_indirect = NV_OPTIONAL_BOOL_FALSE;
+ break;
default:
goto fail;
}
@@ -644,7 +634,7 @@ int main(int argc, char *argv[])
done:
ui_close(op);
-
+
nvfree((void*)op);
return (ret ? 0 : 1);
diff --git a/nvidia-installer.h b/nvidia-installer.h
index eed02a7..0252174 100644
--- a/nvidia-installer.h
+++ b/nvidia-installer.h
@@ -151,13 +151,12 @@ typedef struct __options {
int no_kernel_module_source;
int dkms;
int check_for_alternate_installs;
- int multiple_kernel_modules;
- int num_kernel_modules;
int install_uvm;
- int uvm_files_packaged;
int compat32_files_packaged;
int x_files_packaged;
int concurrency_level;
+ int load_error_ignored;
+ int install_libglx_indirect;
NVOptionalBool install_vdpau_wrapper;
NVOptionalBool install_compat32_libs;
@@ -200,8 +199,7 @@ typedef struct __options {
char *kernel_module_src_prefix;
char *kernel_module_src_dir;
char *utils[MAX_UTILS];
- char *uvm_module_src_dir;
-
+
char *proc_mount_point;
char *ui_str;
char *log_file_name;
@@ -238,7 +236,6 @@ typedef struct __options {
typedef enum {
FILE_TYPE_NONE,
FILE_TYPE_KERNEL_MODULE_SRC,
- FILE_TYPE_KERNEL_MODULE_CMD,
FILE_TYPE_OPENGL_HEADER,
FILE_TYPE_OPENGL_LIB,
FILE_TYPE_DOCUMENTATION,
@@ -283,8 +280,8 @@ typedef enum {
FILE_TYPE_MODULE_SIGNING_KEY,
FILE_TYPE_NVIFR_LIB,
FILE_TYPE_NVIFR_LIB_SYMLINK,
- FILE_TYPE_UVM_MODULE_SRC,
FILE_TYPE_XORG_OUTPUTCLASS_CONFIG,
+ FILE_TYPE_DKMS_CONF,
FILE_TYPE_MAX
} PackageEntryFileType;
@@ -310,6 +307,7 @@ typedef struct {
unsigned int is_opengl : 1;
unsigned int is_temporary : 1;
unsigned int is_wrapper : 1;
+ unsigned int inherit_path : 1;
} PackageEntryFileCapabilities;
/*
@@ -320,6 +318,7 @@ typedef struct {
uint8_t types[FILE_TYPE_MAX];
} PackageEntryFileTypeList;
+
typedef struct __package_entry {
char *file; /*
@@ -356,6 +355,7 @@ typedef struct __package_entry {
PackageEntryFileType type;
PackageEntryFileTlsClass tls_class;
PackageEntryFileCompatArch compat_arch;
+ int inherit_path_depth;
mode_t mode;
@@ -389,29 +389,38 @@ typedef struct {
} ConflictingFileInfo;
+/*
+ * KernelModuleInfo: store information about a kernel module that is useful
+ * for building the module or identifying it or its component objects.
+ */
+typedef struct {
+ char *module_name; /* e.g. "nvidia" */
+ char *module_filename; /* e.g. "nvidia.ko" */
+ int has_separate_interface_file; /* e.g. FALSE for "nvidia-uvm" */
+ char *interface_filename; /* e.g. "nv-linux.o" */
+ char *core_object_name; /* e.g. "nv-kernel.o" */
+ int is_optional; /* e.g. TRUE for "nvidia-uvm" */
+ char *optional_module_dependee; /* e.g. "CUDA" for "nvidia-uvm" */
+ char *disable_option; /* e.g. "--no-unified-memory" */
+} KernelModuleInfo;
+
+
typedef struct __package {
char *description;
char *version;
- char *kernel_module_filename;
- char *kernel_interface_filename;
- char *kernel_module_name;
- char **bad_modules;
- char **bad_module_filenames;
char *kernel_module_build_directory;
- char *uvm_module_build_directory;
char *precompiled_kernel_interface_directory;
- char *kernel_frontend_module_filename;
- char *kernel_frontend_module_name;
- char *kernel_frontend_interface_filename;
- char *uvm_kernel_module_name;
- char *uvm_kernel_module_filename;
- char *uvm_interface_filename;
-
+
PackageEntry *entries; /* array of filename/checksum/bytesize entries */
int num_entries;
ConflictingFileInfo *conflicting_files;
+
+ KernelModuleInfo *kernel_modules;
+ int num_kernel_modules;
+ char *excluded_kernel_modules;
+
} Package;
@@ -502,8 +511,6 @@ typedef struct __package {
#define NUM_TIMES_QUESTIONS_ASKED 3
-#define NV_MAX_MODULE_INSTANCES 8
-
#define LD_OPTIONS "-d -r"
#define NVIDIA_VERSION_PROC_FILE "/proc/driver/nvidia/version"
diff --git a/option_table.h b/option_table.h
index c9c5c60..6096697 100644
--- a/option_table.h
+++ b/option_table.h
@@ -65,7 +65,6 @@ enum {
NO_RPMS_OPTION,
X_PREFIX_OPTION,
KERNEL_OUTPUT_PATH_OPTION,
- NO_RECURSION_OPTION,
FORCE_TLS_COMPAT32_OPTION,
COMPAT32_CHROOT_OPTION,
COMPAT32_PREFIX_OPTION,
@@ -95,10 +94,11 @@ enum {
MODULE_SIGNING_X509_HASH_OPTION,
INSTALL_VDPAU_WRAPPER_OPTION,
NO_CHECK_FOR_ALTERNATE_INSTALLS_OPTION,
- MULTIPLE_KERNEL_MODULES_OPTION,
NO_UVM_OPTION,
INSTALL_COMPAT32_LIBS_OPTION,
X_SYSCONFIG_PATH_OPTION,
+ FORCE_LIBGLX_INDIRECT,
+ NO_LIBGLX_INDIRECT,
};
static const NVGetoptOption __options[] = {
@@ -444,7 +444,7 @@ static const NVGetoptOption __options[] = {
"This option instructs the installer to not attempt to access the "
"network." },
- { "no-recursion", NO_RECURSION_OPTION, 0, NULL,
+ { "no-recursion", 'r', 0, NULL,
"Normally, nvidia-installer will recursively search for "
"potentially conflicting libraries under the default OpenGL "
"and X server installation locations. With this option set, "
@@ -640,12 +640,6 @@ static const NVGetoptOption __options[] = {
"nvidia-installer. Setting this option skips the check for alternate "
"driver installations." },
- { "multiple-kernel-modules", MULTIPLE_KERNEL_MODULES_OPTION,
- NVGETOPT_INTEGER_ARGUMENT, NULL,
- "Build and install multiple NVIDIA kernel modules. The maximum number "
- "of NVIDIA kernel modules that may be built is 8. '--multiple-kernel-"
- "modules' implies '--no-unified-memory'." },
-
{ "no-unified-memory", NO_UVM_OPTION, 0, NULL,
"Do not install the NVIDIA Unified Memory kernel module. This kernel "
"module is required for CUDA on 64-bit systems, and if it is not "
@@ -660,6 +654,12 @@ static const NVGetoptOption __options[] = {
"be set to the number of detected CPUs, or to '1', if nvidia-installer "
"fails to detect the number of CPUs." },
+ { "force-libglx-indirect", FORCE_LIBGLX_INDIRECT, 0, NULL,
+ "If the package includes a libglvnd-based OpenGL library, then always "
+ "install a libGLX_indirect.so.0 symlink, overwriting one if it exists." },
+ { "no-libglx-indirect", NO_LIBGLX_INDIRECT, 0, NULL,
+ "Do not install a libGLX_indirect.so.0 symlink." },
+
/* Orphaned options: These options were in the long_options table in
* nvidia-installer.c but not in the help. */
{ "debug", 'd', 0, NULL,NULL },
diff --git a/rtld_test_Linux-armv7l-gnueabi b/rtld_test_Linux-armv7l-gnueabi
index 604a02a..9afef55 100755
--- a/rtld_test_Linux-armv7l-gnueabi
+++ b/rtld_test_Linux-armv7l-gnueabi
Binary files differ
diff --git a/rtld_test_Linux-armv7l-gnueabihf b/rtld_test_Linux-armv7l-gnueabihf
index be0eadb..221965d 100755
--- a/rtld_test_Linux-armv7l-gnueabihf
+++ b/rtld_test_Linux-armv7l-gnueabihf
Binary files differ
diff --git a/rtld_test_Linux-x86 b/rtld_test_Linux-x86
index b60ea47..290b8c0 100755
--- a/rtld_test_Linux-x86
+++ b/rtld_test_Linux-x86
Binary files differ
diff --git a/rtld_test_Linux-x86_64 b/rtld_test_Linux-x86_64
index be5e874..037cf90 100755
--- a/rtld_test_Linux-x86_64
+++ b/rtld_test_Linux-x86_64
Binary files differ
diff --git a/version.mk b/version.mk
index 172316a..82747a7 100644
--- a/version.mk
+++ b/version.mk
@@ -1 +1 @@
-NVIDIA_VERSION = 352.30
+NVIDIA_VERSION = 355.06