mirror of
https://github.com/NVIDIA/nvidia-installer.git
synced 2025-07-23 02:13:00 +02:00
325.08
This commit is contained in:
3
Makefile
3
Makefile
@@ -151,7 +151,8 @@ HOST_CFLAGS += $(common_cflags)
|
||||
LDFLAGS += -L.
|
||||
LIBS += -ldl
|
||||
|
||||
MKPRECOMPILED_SRC = crc.c mkprecompiled.c
|
||||
MKPRECOMPILED_SRC = crc.c mkprecompiled.c $(COMMON_UTILS_DIR)/common-utils.c \
|
||||
precompiled.c $(COMMON_UTILS_DIR)/nvgetopt.c
|
||||
MKPRECOMPILED_OBJS = $(call BUILD_OBJECT_LIST,$(MKPRECOMPILED_SRC))
|
||||
|
||||
MAKESELF_HELP_SCRIPT_SRC = makeself-help-script.c
|
||||
|
@@ -599,6 +599,7 @@ static ConflictingFileInfo __xfree86_non_opengl_libs[] = {
|
||||
{ "libnvidia-ml.", 13, /* strlen("libnvidia-ml.") */ NULL },
|
||||
{ "libnvidia-encode.", 17, /* strlen("libnvidia-encode.") */ NULL },
|
||||
{ "libnvidia-vgx.", 14, /* strlen("libnvidia-vgx.") */ NULL },
|
||||
{ "libnvidia-vgxcfg.", 17, /* strlen("libnvidia-vgxcfg.") */ NULL },
|
||||
{ NULL, 0, NULL }
|
||||
};
|
||||
|
||||
|
@@ -492,8 +492,6 @@ void nv_text_rows_append(TextRows *t, const char *msg)
|
||||
* result in t0
|
||||
*/
|
||||
|
||||
#define NV_MAX(x,y) ((x) > (y) ? (x) : (y))
|
||||
|
||||
void nv_concat_text_rows(TextRows *t0, TextRows *t1)
|
||||
{
|
||||
int n, i;
|
||||
@@ -707,6 +705,107 @@ char *nvstrchrnul(char *s, int c)
|
||||
return result;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
/* file helper functions */
|
||||
/****************************************************************************/
|
||||
|
||||
/*
|
||||
* nv_open() - open(2) wrapper; prints an error message if open(2)
|
||||
* fails and calls exit(). This function only returns on success.
|
||||
*/
|
||||
|
||||
int nv_open(const char *pathname, int flags, mode_t mode)
|
||||
{
|
||||
int fd;
|
||||
fd = open(pathname, flags, mode);
|
||||
if (fd == -1) {
|
||||
fprintf(stderr, "Failure opening %s (%s).\n",
|
||||
pathname, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
return fd;
|
||||
|
||||
} /* nv_name() */
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* nv_get_file_length() - stat(2) wrapper; prints an error message if
|
||||
* the system call fails and calls exit(). This function only returns
|
||||
* on success.
|
||||
*/
|
||||
|
||||
int nv_get_file_length(const char *filename)
|
||||
{
|
||||
struct stat stat_buf;
|
||||
int ret;
|
||||
|
||||
ret = stat(filename, &stat_buf);
|
||||
if (ret == -1) {
|
||||
fprintf(stderr, "Unable to determine '%s' file length (%s).\n",
|
||||
filename, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
return stat_buf.st_size;
|
||||
|
||||
} /* nv_get_file_length() */
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* nv_set_file_length() - wrapper for lseek() and write(); prints an
|
||||
* error message if the system calls fail and calls exit(). This
|
||||
* function only returns on success.
|
||||
*/
|
||||
|
||||
void nv_set_file_length(const char *filename, int fd, int len)
|
||||
{
|
||||
if ((lseek(fd, len - 1, SEEK_SET) == -1) ||
|
||||
(write(fd, "", 1) == -1)) {
|
||||
fprintf(stderr, "Unable to set file '%s' length %d (%s).\n",
|
||||
filename, fd, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
} /* nv_set_file_length() */
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* nv_mmap() - mmap(2) wrapper; prints an error message if mmap(2)
|
||||
* fails and calls exit(). This function only returns on success.
|
||||
*/
|
||||
|
||||
void *nv_mmap(const char *filename, size_t len, int prot, int flags, int fd)
|
||||
{
|
||||
void *ret;
|
||||
|
||||
ret = mmap(0, len, prot, flags, fd, 0);
|
||||
if (ret == (void *) -1) {
|
||||
fprintf(stderr, "Unable to mmap file %s (%s).\n",
|
||||
filename, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
return ret;
|
||||
|
||||
} /* nv_mmap() */
|
||||
|
||||
|
||||
/*
|
||||
* nv_basename() - alternative to basename(3) which avoids differences in
|
||||
* behavior from different implementations: this implementation never modifies
|
||||
* the original string, and the return value can always be passed to free(3).
|
||||
*/
|
||||
|
||||
char *nv_basename(const char *path)
|
||||
{
|
||||
char *last_slash = strrchr(path, '/');
|
||||
if (last_slash) {
|
||||
return strdup(last_slash+1);
|
||||
} else {
|
||||
return strdup(path);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
/* string helper functions */
|
||||
@@ -741,8 +840,12 @@ char *nv_trim_space(char *string) {
|
||||
static char *trim_char(char *string, char trim, int *count) {
|
||||
int len, replaced = 0;
|
||||
|
||||
if (!string || trim == '\0') {
|
||||
return NULL;
|
||||
if (count) {
|
||||
*count = 0;
|
||||
}
|
||||
|
||||
if (string == NULL || trim == '\0') {
|
||||
return string;
|
||||
}
|
||||
|
||||
if (string[0] == trim) {
|
||||
@@ -781,7 +884,7 @@ char *nv_trim_char(char *string, char trim) {
|
||||
*/
|
||||
|
||||
char *nv_trim_char_strict(char *string, char trim) {
|
||||
int count = 0;
|
||||
int count;
|
||||
char *trimmed;
|
||||
|
||||
trimmed = trim_char(string, trim, &count);
|
||||
@@ -792,3 +895,4 @@ char *nv_trim_char_strict(char *string, char trim) {
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@@ -19,6 +19,8 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <sys/types.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#if !defined(TRUE)
|
||||
#define TRUE 1
|
||||
@@ -30,6 +32,9 @@
|
||||
|
||||
#define ARRAY_LEN(_arr) (sizeof(_arr) / sizeof(_arr[0]))
|
||||
|
||||
#define NV_MIN(x,y) ((x) < (y) ? (x) : (y))
|
||||
#define NV_MAX(x,y) ((x) > (y) ? (x) : (y))
|
||||
|
||||
#define TAB " "
|
||||
#define BIGTAB " "
|
||||
|
||||
@@ -90,6 +95,12 @@ void fmt(FILE *stream, const char *prefix, const char *fmt, ...) NV_ATTRIBUTE_PR
|
||||
|
||||
char *fget_next_line(FILE *fp, int *eof);
|
||||
|
||||
int nv_open(const char *pathname, int flags, mode_t mode);
|
||||
int nv_get_file_length(const char *filename);
|
||||
void nv_set_file_length(const char *filename, int fd, int len);
|
||||
void *nv_mmap(const char *filename, size_t len, int prot, int flags, int fd);
|
||||
char *nv_basename(const char *path);
|
||||
|
||||
char *nv_trim_space(char *string);
|
||||
char *nv_trim_char(char *string, char trim);
|
||||
char *nv_trim_char_strict(char *string, char trim);
|
||||
@@ -139,4 +150,38 @@ do { \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#if defined(__GNUC__)
|
||||
# define NV_INLINE __inline__
|
||||
#else
|
||||
# define NV_INLINE
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Simple function which encodes a version number, given as major, minor, micro,
|
||||
* and nano, as a 64-bit unsigned integer. This is defined in an inline function
|
||||
* rather than as a macro for convenience so it can be examined by the debugger.
|
||||
* Encoded version numbers can be compared directly in version checks.
|
||||
*/
|
||||
static NV_INLINE uint64_t nv_encode_version(unsigned int major,
|
||||
unsigned int minor,
|
||||
unsigned int micro,
|
||||
unsigned int nano)
|
||||
{
|
||||
return (((uint64_t)(nano & 0xFFFF)) |
|
||||
(((uint64_t)(micro & 0xFFFF)) << 16) |
|
||||
(((uint64_t)(minor & 0xFFFF)) << 32) |
|
||||
(((uint64_t)(major & 0xFFFF)) << 48));
|
||||
}
|
||||
|
||||
/*
|
||||
* Wrapper macros for nv_encode_version(). For K in {2,3,4}, NV_VERSIONK() takes
|
||||
* a K-part version number.
|
||||
*/
|
||||
#define NV_VERSION2(major, minor) \
|
||||
nv_encode_version(major, minor, 0, 0)
|
||||
#define NV_VERSION3(major, minor, micro) \
|
||||
nv_encode_version(major, minor, micro, 0)
|
||||
#define NV_VERSION4(major, minor, micro, nano) \
|
||||
nv_encode_version(major, minor, micro, nano)
|
||||
|
||||
#endif /* __COMMON_UTILS_H__ */
|
||||
|
30
crc.c
30
crc.c
@@ -69,15 +69,12 @@ static uint32 crc_init(uint32 crc)
|
||||
|
||||
|
||||
|
||||
uint32 compute_crc(Options *op, const char *filename)
|
||||
uint32 compute_crc_from_buffer(const uint8 *buf, int len)
|
||||
{
|
||||
uint32 cword = ~0;
|
||||
static uint32 *crctab = NULL;
|
||||
uint8 *buf;
|
||||
int i, fd;
|
||||
struct stat stat_buf;
|
||||
size_t len;
|
||||
|
||||
int i;
|
||||
|
||||
if (!crctab) {
|
||||
crctab = (uint32 *) nvalloc(sizeof(uint32) * 256);
|
||||
for (i=0; i < 256; i++) {
|
||||
@@ -85,6 +82,23 @@ uint32 compute_crc(Options *op, const char *filename)
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
cword = crctab[buf[i] ^ (cword >> 24)] ^ (cword << 8);
|
||||
}
|
||||
|
||||
return cword;
|
||||
}
|
||||
|
||||
|
||||
|
||||
uint32 compute_crc(Options *op, const char *filename)
|
||||
{
|
||||
uint32 cword = ~0;
|
||||
uint8 *buf;
|
||||
int fd;
|
||||
struct stat stat_buf;
|
||||
size_t len;
|
||||
|
||||
if ((fd = open(filename, O_RDONLY)) == -1) goto fail;
|
||||
if (fstat(fd, &stat_buf) == -1) goto fail;
|
||||
|
||||
@@ -94,9 +108,7 @@ uint32 compute_crc(Options *op, const char *filename)
|
||||
buf = mmap(0, len, PROT_READ, MAP_FILE | MAP_SHARED, fd, 0);
|
||||
if (buf == (void *) -1) goto fail;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
cword = crctab[buf[i] ^ (cword >> 24)] ^ (cword << 8);
|
||||
}
|
||||
cword = compute_crc_from_buffer(buf, len);
|
||||
|
||||
if (munmap(buf, len) == -1) goto fail;
|
||||
if (close(fd) == -1) goto fail;
|
||||
|
1
crc.h
1
crc.h
@@ -21,6 +21,7 @@
|
||||
#ifndef __NVIDIA_INSTALLER_CRC_H__
|
||||
#define __NVIDIA_INSTALLER_CRC_H__
|
||||
|
||||
uint32 compute_crc_from_buffer(const uint8 *buf, int len);
|
||||
uint32 compute_crc(Options *op, const char *filename);
|
||||
|
||||
#endif /* __NVIDIA_INSTALLER_CRC_H__ */
|
||||
|
105
files.c
105
files.c
@@ -1592,16 +1592,19 @@ int copy_directory_contents(Options *op, const char *src, const char *dst)
|
||||
|
||||
|
||||
/*
|
||||
* pack_precompiled_kernel_interface() -
|
||||
* pack_precompiled_files() - Create a new precompiled files package for the
|
||||
* given PrecompiledFileInfo array and save it to disk.
|
||||
*/
|
||||
|
||||
int pack_precompiled_kernel_interface(Options *op, Package *p)
|
||||
int pack_precompiled_files(Options *op, Package *p, int num_files,
|
||||
PrecompiledFileInfo *files)
|
||||
{
|
||||
char *cmd, time_str[256], *proc_version_string, *suffix, *file, *newfile;
|
||||
char *result, *descr;
|
||||
char time_str[256], *proc_version_string;
|
||||
char *outfile, *descr;
|
||||
time_t t;
|
||||
struct utsname buf;
|
||||
int ret;
|
||||
PrecompiledInfo *info;
|
||||
|
||||
ui_log(op, "Packaging precompiled kernel interface.");
|
||||
|
||||
@@ -1616,7 +1619,7 @@ int pack_precompiled_kernel_interface(Options *op, Package *p)
|
||||
|
||||
/* read the proc version string */
|
||||
|
||||
proc_version_string = read_proc_version(op);
|
||||
proc_version_string = read_proc_version(op, op->proc_mount_point);
|
||||
|
||||
/* use the uname string as the description */
|
||||
|
||||
@@ -1625,74 +1628,36 @@ int pack_precompiled_kernel_interface(Options *op, Package *p)
|
||||
buf.release, " ",
|
||||
buf.version, " ",
|
||||
buf.machine, NULL);
|
||||
|
||||
/* build the PrecompiledInfo struct */
|
||||
|
||||
info = nvalloc(sizeof(PrecompiledInfo));
|
||||
|
||||
outfile = nvstrcat(p->precompiled_kernel_interface_directory, "/",
|
||||
PRECOMPILED_PACKAGE_FILENAME, "-", p->version,
|
||||
".", time_str, NULL);
|
||||
|
||||
info->version = nvstrdup(p->version);
|
||||
info->proc_version_string = proc_version_string;
|
||||
info->description = descr;
|
||||
info->num_files = num_files;
|
||||
info->files = files;
|
||||
|
||||
ret = precompiled_pack(info, outfile);
|
||||
|
||||
nvfree(outfile);
|
||||
free_precompiled(info);
|
||||
|
||||
/* build the mkprecompiled command */
|
||||
|
||||
suffix = nvstrcat("-", p->version, ".", time_str, NULL);
|
||||
|
||||
cmd = nvstrcat("./mkprecompiled --interface=",
|
||||
p->kernel_module_build_directory, "/",
|
||||
PRECOMPILED_KERNEL_INTERFACE_FILENAME,
|
||||
" --output=", p->precompiled_kernel_interface_directory,
|
||||
"/", PRECOMPILED_KERNEL_INTERFACE_FILENAME, suffix,
|
||||
" --description=\"", descr, "\"",
|
||||
" --proc-version=\"", proc_version_string, "\"",
|
||||
" --version=", p->version, NULL);
|
||||
|
||||
/* execute the command */
|
||||
|
||||
ret = run_command(op, cmd, &result, FALSE, 0, TRUE);
|
||||
|
||||
nvfree(cmd);
|
||||
nvfree(proc_version_string);
|
||||
nvfree(descr);
|
||||
|
||||
/* pack the detached signature and checksum, if they exist */
|
||||
|
||||
file = nvstrcat(p->kernel_module_build_directory, "/",
|
||||
DETACHED_SIGNATURE_FILENAME, NULL);
|
||||
|
||||
if (access(file, R_OK) == 0) {
|
||||
newfile = nvstrcat(p->precompiled_kernel_interface_directory, "/",
|
||||
DETACHED_SIGNATURE_FILENAME, suffix, NULL);
|
||||
rename(file, newfile);
|
||||
nvfree(newfile);
|
||||
if (ret) {
|
||||
return TRUE;
|
||||
}
|
||||
else {
|
||||
/* XXX precompiled_pack() never fails */
|
||||
ui_error(op, "Unable to package precompiled kernel interface.");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
nvfree(file);
|
||||
|
||||
file = nvstrcat(p->kernel_module_build_directory, "/",
|
||||
KERNEL_MODULE_CHECKSUM_FILENAME, NULL);
|
||||
|
||||
if (access(file, R_OK) == 0) {
|
||||
newfile = nvstrcat(p->precompiled_kernel_interface_directory, "/",
|
||||
KERNEL_MODULE_CHECKSUM_FILENAME, suffix, NULL);
|
||||
rename(file, newfile);
|
||||
nvfree(newfile);
|
||||
}
|
||||
|
||||
nvfree(file);
|
||||
|
||||
/* remove the old kernel interface file */
|
||||
|
||||
file = nvstrcat(p->kernel_module_build_directory, "/",
|
||||
PRECOMPILED_KERNEL_INTERFACE_FILENAME, NULL);
|
||||
|
||||
unlink(file); /* XXX what to do if this fails? */
|
||||
|
||||
nvfree(file);
|
||||
|
||||
if (ret != 0) {
|
||||
ui_error(op, "Unable to package precompiled kernel interface: %s",
|
||||
result);
|
||||
}
|
||||
|
||||
nvfree(result);
|
||||
|
||||
if (ret == 0) return TRUE;
|
||||
else return FALSE;
|
||||
|
||||
} /* pack_kernel_interface() */
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
4
files.h
4
files.h
@@ -21,6 +21,7 @@
|
||||
#define __NVIDIA_INSTALLER_FILES_H__
|
||||
|
||||
#include "nvidia-installer.h"
|
||||
#include "precompiled.h"
|
||||
|
||||
int remove_directory(Options *op, const char *victim);
|
||||
int touch_directory(Options *op, const char *victim);
|
||||
@@ -54,7 +55,8 @@ char *make_tmpdir(Options *op);
|
||||
int nvrename(Options *op, const char *src, const char *dst);
|
||||
int check_for_existing_rpms(Options *op);
|
||||
int copy_directory_contents(Options *op, const char *src, const char *dst);
|
||||
int pack_precompiled_kernel_interface(Options *op, Package *p);
|
||||
int pack_precompiled_files(Options *op, Package *p, int num_files,
|
||||
PrecompiledFileInfo *files);
|
||||
|
||||
char *process_template_file(Options *op, PackageEntry *pe,
|
||||
char **tokens, char **replacements);
|
||||
|
@@ -127,6 +127,14 @@ int install_from_cwd(Options *op)
|
||||
|
||||
if (!check_for_existing_driver(op, p)) goto exit_install;
|
||||
|
||||
/*
|
||||
* check to see if an alternate method of installation is already installed
|
||||
* or is available, but not installed; ask the user if they really want to
|
||||
* install anyway despite the presence/availability of an alternate install.
|
||||
*/
|
||||
|
||||
if (!check_for_alternate_install(op)) goto exit_install;
|
||||
|
||||
/* run the distro preinstall hook */
|
||||
|
||||
if (!run_distro_hook(op, "pre-install")) {
|
||||
@@ -421,9 +429,15 @@ static int install_kernel_module(Options *op, Package *p)
|
||||
* then there is something pretty seriously wrong... better to
|
||||
* abort.
|
||||
*/
|
||||
|
||||
if (!link_kernel_module(op, p, p->kernel_module_build_directory,
|
||||
precompiled_info)) return FALSE;
|
||||
|
||||
int i;
|
||||
|
||||
for (i = 0; i < precompiled_info->num_files; i++) {
|
||||
if (!link_kernel_module(op, p, p->kernel_module_build_directory,
|
||||
&(precompiled_info->files[i]))) {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
/*
|
||||
@@ -480,6 +494,8 @@ static int install_kernel_module(Options *op, Package *p)
|
||||
int add_this_kernel(Options *op)
|
||||
{
|
||||
Package *p;
|
||||
PrecompiledFileInfo *fileInfos;
|
||||
int num_files;
|
||||
|
||||
/* parse the manifest */
|
||||
|
||||
@@ -489,13 +505,15 @@ int add_this_kernel(Options *op)
|
||||
|
||||
if (!determine_kernel_source_path(op, p)) goto failed;
|
||||
|
||||
/* build the precompiled kernel interface */
|
||||
/* build the precompiled files */
|
||||
|
||||
if (!build_kernel_interface(op, p)) goto failed;
|
||||
num_files = build_kernel_interface(op, p, &fileInfos);
|
||||
if (!num_files) goto failed;
|
||||
|
||||
/* pack the precompiled kernel interface */
|
||||
/* pack the precompiled files */
|
||||
|
||||
if (!pack_precompiled_kernel_interface(op, p)) goto failed;
|
||||
if (!pack_precompiled_files(op, p, num_files, fileInfos))
|
||||
goto failed;
|
||||
|
||||
free_package(p);
|
||||
|
||||
@@ -1096,7 +1114,7 @@ guess_fail:
|
||||
|
||||
cmdline = nvstrcat("cd ", p->kernel_module_build_directory, "; ",
|
||||
op->utils[OPENSSL], " req -new -x509 -newkey "
|
||||
"rsa:2048 -days 7300 -nodes -sha256 -subj "
|
||||
"rsa:2048 -days 7300 -nodes -subj "
|
||||
"\"/CN=nvidia-installer generated signing key/\""
|
||||
" -keyout " SECKEY_NAME " -outform DER -out "
|
||||
PUBKEY_NAME, " -", x509_hash, NULL);
|
||||
|
527
kernel.c
527
kernel.c
@@ -48,6 +48,7 @@
|
||||
|
||||
static char *default_kernel_module_installation_path(Options *op);
|
||||
static char *default_kernel_source_path(Options *op);
|
||||
static char *find_module_substring(char *string, const char *substring);
|
||||
static int check_for_loaded_kernel_module(Options *op, const char *);
|
||||
static void check_for_warning_messages(Options *op);
|
||||
static int rmmod_kernel_module(Options *op, const char *);
|
||||
@@ -55,10 +56,10 @@ static PrecompiledInfo *download_updated_kernel_interface(Options*, Package*,
|
||||
const char*);
|
||||
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 PrecompiledInfo *scan_dir(Options *op, Package *p,
|
||||
const char *directory_name,
|
||||
const char *output_filename,
|
||||
const char *proc_version_string);
|
||||
|
||||
static char *build_distro_precompiled_kernel_interface_dir(Options *op);
|
||||
@@ -170,6 +171,9 @@ static int run_conftest(Options *op, Package *p, const char *args, char **result
|
||||
char *CC, *cmd, *arch;
|
||||
int ret;
|
||||
|
||||
if (result)
|
||||
*result = NULL;
|
||||
|
||||
arch = get_machine_arch(op);
|
||||
if (!arch)
|
||||
return FALSE;
|
||||
@@ -186,6 +190,7 @@ static int run_conftest(Options *op, Package *p, const char *args, char **result
|
||||
nvfree(cmd);
|
||||
|
||||
return ret == 0;
|
||||
|
||||
} /* run_conftest() */
|
||||
|
||||
|
||||
@@ -418,7 +423,7 @@ int determine_kernel_output_path(Options *op)
|
||||
* the linked module and append the signature.
|
||||
*/
|
||||
static int attach_signature(Options *op, Package *p,
|
||||
const PrecompiledInfo *info) {
|
||||
const PrecompiledFileInfo *fileInfo) {
|
||||
uint32 actual_crc;
|
||||
char *module_filename;
|
||||
int ret = FALSE, command_ret;
|
||||
@@ -428,33 +433,24 @@ static int attach_signature(Options *op, Package *p,
|
||||
module_filename = nvstrcat(p->kernel_module_build_directory, "/",
|
||||
p->kernel_module_filename, NULL);
|
||||
|
||||
command_ret = verify_crc(op, module_filename, info->linked_module_crc,
|
||||
&actual_crc);
|
||||
command_ret = verify_crc(op, module_filename, fileInfo->linked_module_crc,
|
||||
&actual_crc);
|
||||
|
||||
if (command_ret) {
|
||||
FILE *module_file, *signature_file;
|
||||
FILE *module_file;
|
||||
|
||||
module_file = fopen(module_filename, "a+");
|
||||
signature_file = fopen(info->detached_signature, "r");
|
||||
|
||||
if (module_file && signature_file) {
|
||||
char buf;
|
||||
|
||||
while(fread(&buf, 1, 1, signature_file)) {
|
||||
command_ret = fwrite(&buf, 1, 1, module_file);
|
||||
if (command_ret != 1) {
|
||||
goto attach_done;
|
||||
}
|
||||
if (module_file && fileInfo->signature_size) {
|
||||
command_ret = fwrite(fileInfo->signature, 1,
|
||||
fileInfo->signature_size, module_file);
|
||||
if (command_ret != fileInfo->signature_size) {
|
||||
goto attach_done;
|
||||
}
|
||||
|
||||
ret = feof(signature_file) &&
|
||||
!ferror(signature_file) &&
|
||||
!ferror(module_file);
|
||||
|
||||
op->kernel_module_signed = ret;
|
||||
op->kernel_module_signed = ret = !ferror(module_file);
|
||||
attach_done:
|
||||
fclose(module_file);
|
||||
fclose(signature_file);
|
||||
} else {
|
||||
ret = ui_yes_no(op, FALSE,
|
||||
"A detached signature was included with the "
|
||||
@@ -475,7 +471,8 @@ attach_done:
|
||||
"the linker on the system that built the precompiled "
|
||||
"interface.\n\nThe detached signature will not be "
|
||||
"added; would you still like to install the unsigned "
|
||||
"kernel module?", actual_crc, info->linked_module_crc);
|
||||
"kernel module?", actual_crc,
|
||||
fileInfo->linked_module_crc);
|
||||
}
|
||||
|
||||
if (ret) {
|
||||
@@ -504,18 +501,29 @@ attach_done:
|
||||
*/
|
||||
|
||||
int link_kernel_module(Options *op, Package *p, const char *build_directory,
|
||||
const PrecompiledInfo *info)
|
||||
const PrecompiledFileInfo *fileInfo)
|
||||
{
|
||||
char *cmd, *result;
|
||||
int ret;
|
||||
|
||||
uint32 attrmask;
|
||||
|
||||
if (fileInfo->type != PRECOMPILED_FILE_TYPE_INTERFACE) {
|
||||
ui_error(op, "The file does not appear to be a valid precompiled "
|
||||
"kernel interface.");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
ret = precompiled_file_unpack(op, fileInfo, build_directory);
|
||||
if (!ret) {
|
||||
ui_error(op, "Failed to unpack the precompiled interface.");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
p->kernel_module_filename = guess_kernel_module_filename(op);
|
||||
|
||||
cmd = nvstrcat("cd ", build_directory, "; ", op->utils[LD],
|
||||
" ", LD_OPTIONS,
|
||||
" -o ", p->kernel_module_filename,
|
||||
" ", PRECOMPILED_KERNEL_INTERFACE_FILENAME,
|
||||
" nv-kernel.o", NULL);
|
||||
cmd = nvstrcat("cd ", build_directory, "; ", op->utils[LD], " ",
|
||||
LD_OPTIONS, " -o ", fileInfo->linked_module_name, " ",
|
||||
fileInfo->name, " ", fileInfo->core_object_name, NULL);
|
||||
|
||||
ret = run_command(op, cmd, &result, TRUE, 0, TRUE);
|
||||
|
||||
@@ -528,8 +536,11 @@ int link_kernel_module(Options *op, Package *p, const char *build_directory,
|
||||
|
||||
ui_log(op, "Kernel module linked successfully.");
|
||||
|
||||
if (info && info->detached_signature) {
|
||||
return attach_signature(op, p, info);
|
||||
attrmask = PRECOMPILED_ATTR(DETACHED_SIGNATURE) |
|
||||
PRECOMPILED_ATTR(LINKED_MODULE_CRC);
|
||||
|
||||
if ((fileInfo->attributes & attrmask) == attrmask) {
|
||||
return attach_signature(op, p, fileInfo);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
@@ -562,13 +573,15 @@ int build_kernel_module(Options *op, Package *p)
|
||||
ret = run_conftest(op, p, "select_makefile just_msg", &result);
|
||||
|
||||
if (!ret) {
|
||||
ui_error(op, "%s", result); /* display conftest.sh's error message */
|
||||
if (result)
|
||||
ui_error(op, "%s", result); /* display conftest.sh's error message */
|
||||
nvfree(result);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!fbdev_check(op, p)) return FALSE;
|
||||
if (!xen_check(op, p)) return FALSE;
|
||||
if (!preempt_rt_check(op, p)) return FALSE;
|
||||
|
||||
cmd = nvstrcat("cd ", p->kernel_module_build_directory,
|
||||
"; make print-module-filename",
|
||||
@@ -687,67 +700,22 @@ int sign_kernel_module(Options *op, const char *build_directory, int status) {
|
||||
|
||||
|
||||
/*
|
||||
* byte_tail() - write to outfile from infile, starting at the specified byte
|
||||
* offset, and going until the end of infile. This is needed because `tail -c`
|
||||
* is unreliable in some implementations.
|
||||
*/
|
||||
static int byte_tail(const char *infile, const char *outfile, int start)
|
||||
{
|
||||
FILE *in = NULL, *out = NULL;
|
||||
int success = FALSE, ret;
|
||||
char buf;
|
||||
|
||||
in = fopen(infile, "r");
|
||||
out = fopen(outfile, "w");
|
||||
|
||||
if (!in || !out) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
ret = fseek(in, start, SEEK_SET);
|
||||
if (ret != 0) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
while(fread(&buf, 1, 1, in)) {
|
||||
ret = fwrite(&buf, 1, 1, out);
|
||||
if (ret != 1) {
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
success = feof(in) && !ferror(in) && !ferror(out);
|
||||
|
||||
done:
|
||||
fclose(in);
|
||||
fclose(out);
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* create_detached_signature() - Link the precompiled interface with nv-kernel.o,
|
||||
* sign the resulting linked nvidia.ko, and split the signature off into a separate
|
||||
* file. Copy a checksum and detached signature for the linked module to the kernel
|
||||
* module build directory on success.
|
||||
* create_detached_signature() - Link a precompiled interface into a module,
|
||||
* sign the resulting linked module, and store a CRC for the linked, unsigned
|
||||
* module and the detached signature in the provided PrecompiledFileInfo record.
|
||||
*/
|
||||
static int create_detached_signature(Options *op, Package *p,
|
||||
const char *build_dir)
|
||||
const char *build_dir,
|
||||
PrecompiledFileInfo *fileInfo)
|
||||
{
|
||||
int ret, command_ret;
|
||||
struct stat st;
|
||||
FILE *checksum_file;
|
||||
char *module_path = NULL, *tmp_path = NULL, *error = NULL, *dstfile = NULL;
|
||||
char *module_path = NULL, *error = NULL;
|
||||
|
||||
ui_status_begin(op, "Creating a detached signature for the linked "
|
||||
"kernel module:", "Linking module");
|
||||
|
||||
tmp_path = nvstrcat(build_dir, "/", PRECOMPILED_KERNEL_INTERFACE_FILENAME,
|
||||
NULL);
|
||||
symlink(p->kernel_interface_filename, tmp_path);
|
||||
|
||||
ret = link_kernel_module(op, p, build_dir, NULL);
|
||||
ret = link_kernel_module(op, p, build_dir, fileInfo);
|
||||
|
||||
if (!ret) {
|
||||
ui_error(op, "Failed to link a kernel module for signing.");
|
||||
@@ -765,33 +733,8 @@ static int create_detached_signature(Options *op, Package *p,
|
||||
|
||||
ui_status_update(op, .25, "Generating module checksum");
|
||||
|
||||
nvfree(tmp_path);
|
||||
tmp_path = nvstrcat(build_dir, "/", KERNEL_MODULE_CHECKSUM_FILENAME, NULL);
|
||||
checksum_file = fopen(tmp_path, "w");
|
||||
|
||||
if(checksum_file) {
|
||||
uint32 crc = compute_crc(op, module_path);
|
||||
command_ret = fwrite(&crc, sizeof(crc), 1, checksum_file);
|
||||
fclose(checksum_file);
|
||||
if (command_ret != 1) {
|
||||
ret = FALSE;
|
||||
error = "Failed to write the module checksum.";
|
||||
goto done;
|
||||
}
|
||||
} else {
|
||||
ret = FALSE;
|
||||
error = "Failed to open the checksum file for writing.";
|
||||
goto done;
|
||||
}
|
||||
|
||||
dstfile = nvstrcat(p->kernel_module_build_directory, "/",
|
||||
KERNEL_MODULE_CHECKSUM_FILENAME, NULL);
|
||||
|
||||
if (!copy_file(op, tmp_path, dstfile, 0644)) {
|
||||
ret = FALSE;
|
||||
error = "Failed to copy the kernel module checksum file.";
|
||||
goto done;
|
||||
}
|
||||
fileInfo->linked_module_crc = compute_crc(op, module_path);
|
||||
fileInfo->attributes |= PRECOMPILED_ATTR(LINKED_MODULE_CRC);
|
||||
|
||||
ui_status_update(op, .50, "Signing linked module");
|
||||
|
||||
@@ -804,24 +747,15 @@ static int create_detached_signature(Options *op, Package *p,
|
||||
|
||||
ui_status_update(op, .75, "Detaching module signature");
|
||||
|
||||
nvfree(tmp_path);
|
||||
tmp_path = nvstrcat(build_dir, "/", DETACHED_SIGNATURE_FILENAME, NULL);
|
||||
ret = byte_tail(module_path, tmp_path, st.st_size);
|
||||
fileInfo->signature_size = byte_tail(module_path, st.st_size,
|
||||
&(fileInfo->signature));
|
||||
|
||||
if (!ret) {
|
||||
if (!(fileInfo->signature) || fileInfo->signature_size == 0) {
|
||||
error = "Failed to detach the module signature";
|
||||
goto done;
|
||||
}
|
||||
|
||||
nvfree(dstfile);
|
||||
dstfile = nvstrcat(p->kernel_module_build_directory, "/",
|
||||
DETACHED_SIGNATURE_FILENAME, NULL);
|
||||
|
||||
if (!copy_file(op, tmp_path, dstfile, 0644)) {
|
||||
ret = FALSE;
|
||||
error = "Failed to copy the detached signature file.";
|
||||
goto done;
|
||||
}
|
||||
fileInfo->attributes |= PRECOMPILED_ATTR(DETACHED_SIGNATURE);
|
||||
|
||||
done:
|
||||
if (ret) {
|
||||
@@ -833,8 +767,6 @@ done:
|
||||
}
|
||||
}
|
||||
|
||||
nvfree(dstfile);
|
||||
nvfree(tmp_path);
|
||||
nvfree(module_path);
|
||||
return ret;
|
||||
} /* create_detached_signature() */
|
||||
@@ -842,28 +774,30 @@ done:
|
||||
|
||||
|
||||
/*
|
||||
* build_kernel_interface() - build the kernel interface, and place it
|
||||
* here:
|
||||
*
|
||||
* "%s/%s", p->kernel_module_build_directory,
|
||||
* PRECOMPILED_KERNEL_INTERFACE_FILENAME
|
||||
* build_kernel_interface() - build the kernel interface(s), and store any
|
||||
* built interfaces in a newly allocated PrecompiledFileInfo array, a pointer
|
||||
* to which is passed back to the caller. Return the number of packaged
|
||||
* interface files, or 0 on error.
|
||||
*
|
||||
* This is done by copying the sources to a temporary working
|
||||
* directory, building, and copying the kernel interface back to the
|
||||
* kernel module source directory. The tmpdir is removed when
|
||||
* complete.
|
||||
* directory and building the kernel interface in that directory.
|
||||
* The tmpdir is removed when complete.
|
||||
*
|
||||
* XXX this and build_kernel_module() should be merged.
|
||||
* XXX for multi-RM the dispatch module should be compiled separately, then
|
||||
* packaged whole with file type PRECOMPILED_FILE_TYPE_MODULE.
|
||||
*/
|
||||
|
||||
int build_kernel_interface(Options *op, Package *p)
|
||||
int build_kernel_interface(Options *op, Package *p,
|
||||
PrecompiledFileInfo ** fileInfos)
|
||||
{
|
||||
char *tmpdir = NULL;
|
||||
char *cmd = NULL;
|
||||
char *kernel_interface = NULL;
|
||||
char *dstfile = NULL;
|
||||
int ret = FALSE;
|
||||
int command_ret;
|
||||
int files_packaged = 0, command_ret, i;
|
||||
const int num_files = 1; /* XXX multi-RM */
|
||||
|
||||
*fileInfos = NULL;
|
||||
|
||||
/* create a temporary directory */
|
||||
|
||||
@@ -892,60 +826,81 @@ int build_kernel_interface(Options *op, Package *p)
|
||||
|
||||
touch_directory(op, p->kernel_module_build_directory);
|
||||
|
||||
/* build the kernel interface */
|
||||
*fileInfos = nvalloc(sizeof(PrecompiledFileInfo) * num_files);
|
||||
|
||||
ui_status_begin(op, "Building kernel interface:", "Building");
|
||||
|
||||
cmd = nvstrcat("cd ", tmpdir, "; make ", p->kernel_interface_filename,
|
||||
" SYSSRC=", op->kernel_source_path, NULL);
|
||||
|
||||
command_ret = run_command(op, cmd, NULL, TRUE, 25 /* XXX */, TRUE);
|
||||
for (i = 0; i < num_files; i++) {
|
||||
char *kernel_interface, *kernel_module_filename;
|
||||
PrecompiledFileInfo *fileInfo = *fileInfos + i;
|
||||
|
||||
if (command_ret != 0) {
|
||||
ui_status_end(op, "Error.");
|
||||
ui_error(op, "Unable to build the NVIDIA kernel module interface.");
|
||||
/* XXX need more descriptive error message */
|
||||
goto failed;
|
||||
}
|
||||
|
||||
/* check that the file exists */
|
||||
/* build the kernel interface */
|
||||
|
||||
kernel_interface = nvstrcat(tmpdir, "/",
|
||||
p->kernel_interface_filename, NULL);
|
||||
|
||||
if (access(kernel_interface, F_OK) == -1) {
|
||||
ui_status_end(op, "Error.");
|
||||
ui_error(op, "The NVIDIA kernel module interface was not created.");
|
||||
goto failed;
|
||||
ui_status_begin(op, "Building kernel interface:", "Building (%d/%d)",
|
||||
i + 1, num_files);
|
||||
|
||||
cmd = nvstrcat("cd ", tmpdir, "; make ", p->kernel_interface_filename,
|
||||
" SYSSRC=", op->kernel_source_path, NULL);
|
||||
|
||||
command_ret = run_command(op, cmd, NULL, TRUE, 25 /* XXX */, TRUE);
|
||||
|
||||
if (command_ret != 0) {
|
||||
ui_status_end(op, "Error.");
|
||||
ui_error(op, "Unable to build the NVIDIA kernel module interface.");
|
||||
/* XXX need more descriptive error message */
|
||||
goto failed;
|
||||
}
|
||||
|
||||
/* check that the file exists */
|
||||
|
||||
kernel_interface = nvstrcat(tmpdir, "/",
|
||||
p->kernel_interface_filename, NULL);
|
||||
|
||||
if (access(kernel_interface, F_OK) == -1) {
|
||||
ui_status_end(op, "Error.");
|
||||
ui_error(op, "The NVIDIA kernel module interface was not created.");
|
||||
nvfree(kernel_interface);
|
||||
goto failed;
|
||||
}
|
||||
|
||||
ui_status_end(op, "done.");
|
||||
|
||||
ui_log(op, "Kernel module interface compilation complete.");
|
||||
|
||||
/* add the kernel interface to the list of files to be packaged */
|
||||
|
||||
kernel_module_filename = guess_kernel_module_filename(op);
|
||||
command_ret = precompiled_read_interface(fileInfo, kernel_interface,
|
||||
kernel_module_filename,
|
||||
"nv-kernel.o");
|
||||
nvfree(kernel_interface);
|
||||
nvfree(kernel_module_filename);
|
||||
|
||||
if (command_ret) {
|
||||
if (op->module_signing_secret_key && op->module_signing_public_key) {
|
||||
if (!create_detached_signature(op, p, tmpdir, fileInfo)) {
|
||||
goto failed;
|
||||
}
|
||||
}
|
||||
files_packaged++;
|
||||
} else {
|
||||
goto failed;
|
||||
}
|
||||
}
|
||||
|
||||
ui_status_end(op, "done.");
|
||||
failed:
|
||||
|
||||
ui_log(op, "Kernel module interface compilation complete.");
|
||||
|
||||
/* copy the kernel interface from the tmpdir back to the srcdir */
|
||||
|
||||
dstfile = nvstrcat(p->kernel_module_build_directory, "/",
|
||||
PRECOMPILED_KERNEL_INTERFACE_FILENAME, NULL);
|
||||
|
||||
if (!copy_file(op, kernel_interface, dstfile, 0644)) goto failed;
|
||||
|
||||
if (op->module_signing_secret_key && op->module_signing_public_key) {
|
||||
ret = create_detached_signature(op, p, tmpdir);
|
||||
} else {
|
||||
ret = TRUE;
|
||||
if (files_packaged == 0) {
|
||||
nvfree(*fileInfos);
|
||||
*fileInfos = NULL;
|
||||
}
|
||||
|
||||
failed:
|
||||
|
||||
remove_directory(op, tmpdir);
|
||||
|
||||
if (tmpdir) nvfree(tmpdir);
|
||||
if (tmpdir) {
|
||||
remove_directory(op, tmpdir);
|
||||
nvfree(tmpdir);
|
||||
}
|
||||
if (cmd) nvfree(cmd);
|
||||
if (kernel_interface) nvfree(kernel_interface);
|
||||
if (dstfile) nvfree(dstfile);
|
||||
|
||||
return ret;
|
||||
return files_packaged;
|
||||
|
||||
} /* build_kernel_interface() */
|
||||
|
||||
@@ -1470,7 +1425,7 @@ int check_for_unloaded_kernel_module(Options *op, Package *p)
|
||||
|
||||
PrecompiledInfo *find_precompiled_kernel_interface(Options *op, Package *p)
|
||||
{
|
||||
char *proc_version_string, *output_filename, *tmp;
|
||||
char *proc_version_string, *tmp;
|
||||
PrecompiledInfo *info = NULL;
|
||||
|
||||
/* allow the user to completely skip this search */
|
||||
@@ -1482,7 +1437,7 @@ PrecompiledInfo *find_precompiled_kernel_interface(Options *op, Package *p)
|
||||
|
||||
/* retrieve the proc version string for the running kernel */
|
||||
|
||||
proc_version_string = read_proc_version(op);
|
||||
proc_version_string = read_proc_version(op, op->proc_mount_point);
|
||||
|
||||
if (!proc_version_string) goto failed;
|
||||
|
||||
@@ -1491,11 +1446,6 @@ PrecompiledInfo *find_precompiled_kernel_interface(Options *op, Package *p)
|
||||
if (!mkdir_recursive(op, p->kernel_module_build_directory, 0755))
|
||||
goto failed;
|
||||
|
||||
/* build the output filename */
|
||||
|
||||
output_filename = nvstrcat(p->kernel_module_build_directory, "/",
|
||||
PRECOMPILED_KERNEL_INTERFACE_FILENAME, NULL);
|
||||
|
||||
/*
|
||||
* if the --precompiled-kernel-interfaces-path option was
|
||||
* specified, search that directory, first
|
||||
@@ -1503,7 +1453,7 @@ PrecompiledInfo *find_precompiled_kernel_interface(Options *op, Package *p)
|
||||
|
||||
if (op->precompiled_kernel_interfaces_path) {
|
||||
info = scan_dir(op, p, op->precompiled_kernel_interfaces_path,
|
||||
output_filename, proc_version_string);
|
||||
proc_version_string);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1514,7 +1464,7 @@ PrecompiledInfo *find_precompiled_kernel_interface(Options *op, Package *p)
|
||||
if (!info) {
|
||||
tmp = build_distro_precompiled_kernel_interface_dir(op);
|
||||
if (tmp) {
|
||||
info = scan_dir(op, p, tmp, output_filename, proc_version_string);
|
||||
info = scan_dir(op, p, tmp, proc_version_string);
|
||||
nvfree(tmp);
|
||||
}
|
||||
}
|
||||
@@ -1528,7 +1478,7 @@ PrecompiledInfo *find_precompiled_kernel_interface(Options *op, Package *p)
|
||||
|
||||
if (!info) {
|
||||
info = scan_dir(op, p, p->precompiled_kernel_interface_directory,
|
||||
output_filename, proc_version_string);
|
||||
proc_version_string);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1806,6 +1756,74 @@ static char *default_kernel_source_path(Options *op)
|
||||
} /* default_kernel_source_path() */
|
||||
|
||||
|
||||
/*
|
||||
* find_module_substring() - find substring in a given string where differences
|
||||
* between hyphens and underscores are ignored. Returns a pointer to the
|
||||
* beginning of the substring, or NULL if the string/substring is NULL, or if
|
||||
* length of substring is greater than length of string, or substring is not
|
||||
* found.
|
||||
*/
|
||||
|
||||
static char *find_module_substring(char *string, const char *substring)
|
||||
{
|
||||
int string_len, substring_len, len;
|
||||
char *tstr;
|
||||
const char *tsubstr;
|
||||
|
||||
if ((string == NULL) || (substring == NULL))
|
||||
return NULL;
|
||||
|
||||
string_len = strlen(string);
|
||||
substring_len = strlen(substring);
|
||||
|
||||
for (len = 0; len <= string_len - substring_len; len++, string++) {
|
||||
if (*string != *substring) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (tstr = string, tsubstr = substring;
|
||||
*tsubstr != '\0';
|
||||
tstr++, tsubstr++) {
|
||||
if (*tstr != *tsubstr) {
|
||||
if (((*tstr == '-') || (*tstr == '_')) &&
|
||||
((*tsubstr == '-') || (*tsubstr == '_')))
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (*tsubstr == '\0')
|
||||
return string;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
} /* find_module_substring */
|
||||
|
||||
|
||||
/*
|
||||
* substring_is_isolated() - given the string 'substring' with length 'len',
|
||||
* which points to a location inside the string 'string', check to see if
|
||||
* 'substring' is surrounded by either whitespace or the start/end of 'string'
|
||||
* on both ends.
|
||||
*/
|
||||
|
||||
static int substring_is_isolated(const char *substring, const char *string,
|
||||
int len)
|
||||
{
|
||||
if (substring != string) {
|
||||
if (!isspace(substring[-1])) {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (substring[len] && !isspace(substring[len])) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* check_for_loaded_kernel_module() - check if the specified kernel
|
||||
* module is currently loaded using `lsmod`. Returns TRUE if the
|
||||
@@ -1818,24 +1836,28 @@ static char *default_kernel_source_path(Options *op)
|
||||
|
||||
static int check_for_loaded_kernel_module(Options *op, const char *module_name)
|
||||
{
|
||||
char *ptr, *result = NULL;
|
||||
int ret;
|
||||
char *result = NULL;
|
||||
int ret, found = FALSE;
|
||||
|
||||
ret = run_command(op, op->utils[LSMOD], &result, FALSE, 0, TRUE);
|
||||
|
||||
if ((ret == 0) && (result) && (result[0] != '\0')) {
|
||||
ptr = strstr(result, module_name);
|
||||
if (ptr) {
|
||||
ptr += strlen(module_name);
|
||||
if(!isspace(*ptr)) ret = 1;
|
||||
} else {
|
||||
ret = 1;
|
||||
char *ptr;
|
||||
int len = strlen(module_name);
|
||||
|
||||
for (ptr = result;
|
||||
(ptr = find_module_substring(ptr, module_name));
|
||||
ptr += len) {
|
||||
if (substring_is_isolated(ptr, result, len)) {
|
||||
found = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (result) free(result);
|
||||
|
||||
return ret ? FALSE : TRUE;
|
||||
return found;
|
||||
|
||||
} /* check_for_loaded_kernel_module() */
|
||||
|
||||
@@ -1875,17 +1897,15 @@ download_updated_kernel_interface(Options *op, Package *p,
|
||||
{
|
||||
int fd = -1;
|
||||
int dst_fd = -1;
|
||||
int length;
|
||||
int length, i;
|
||||
char *url = NULL;
|
||||
char *tmpfile = NULL;
|
||||
char *dstfile = NULL;
|
||||
char *buf = NULL;
|
||||
char *output_filename = NULL;
|
||||
char *str = (void *) -1;
|
||||
char *ptr, *s;
|
||||
struct stat stat_buf;
|
||||
PrecompiledInfo *info = NULL;
|
||||
uint32 crc;
|
||||
|
||||
/* initialize the tmpfile and url strings */
|
||||
|
||||
@@ -1939,7 +1959,7 @@ download_updated_kernel_interface(Options *op, Package *p,
|
||||
s += 3; /* skip past the ":::" separator */
|
||||
|
||||
if (strcmp(proc_version_string, s) == 0) {
|
||||
|
||||
|
||||
/* proc versions strings match */
|
||||
|
||||
/*
|
||||
@@ -1978,33 +1998,34 @@ download_updated_kernel_interface(Options *op, Package *p,
|
||||
|
||||
/* XXX once we have gpg setup, should check the file here */
|
||||
|
||||
/* build the output filename string */
|
||||
|
||||
output_filename = nvstrcat(p->kernel_module_build_directory, "/",
|
||||
PRECOMPILED_KERNEL_INTERFACE_FILENAME,
|
||||
NULL);
|
||||
|
||||
/* unpack the downloaded file */
|
||||
|
||||
info = precompiled_unpack(op, dstfile, output_filename,
|
||||
proc_version_string,
|
||||
p->version);
|
||||
|
||||
/* compare checksums */
|
||||
|
||||
crc = compute_crc(op, output_filename);
|
||||
|
||||
if (info && (info->crc != crc)) {
|
||||
ui_error(op, "The embedded checksum of the downloaded file "
|
||||
"'%s' (%" PRIu32 ") does not match the computed "
|
||||
"checksum (%" PRIu32 "); not using.", buf, info->crc,
|
||||
crc);
|
||||
unlink(dstfile);
|
||||
info = get_precompiled_info(op, dstfile, proc_version_string,
|
||||
p->version);
|
||||
|
||||
if (!info) {
|
||||
ui_error(op, "The format of the downloaded precompiled package "
|
||||
"is invalid!");
|
||||
free_precompiled(info);
|
||||
info = NULL;
|
||||
}
|
||||
|
||||
/* compare checksums */
|
||||
|
||||
for (i = 0; info && i < info->num_files; i++) {
|
||||
uint32 crc = compute_crc_from_buffer(info->files[i].data,
|
||||
info->files[i].size);
|
||||
if (info->files[i].crc != crc) {
|
||||
ui_error(op, "The embedded checksum of the file %s in the "
|
||||
"downloaded precompiled pacakge '%s' (%" PRIu32
|
||||
") does not match the computed checksum (%"
|
||||
PRIu32 "); not using.", info->files[i].name,
|
||||
buf, info->files[i].crc, crc);
|
||||
free_precompiled(info);
|
||||
info = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
goto done;
|
||||
|
||||
}
|
||||
|
||||
nvfree(buf);
|
||||
@@ -2097,7 +2118,8 @@ static int fbdev_check(Options *op, Package *p)
|
||||
ret = run_conftest(op, p,"rivafb_sanity_check just_msg", &result);
|
||||
|
||||
if (!ret) {
|
||||
ui_error(op, "%s", result);
|
||||
if (result)
|
||||
ui_error(op, "%s", result);
|
||||
nvfree(result);
|
||||
|
||||
return FALSE;
|
||||
@@ -2108,7 +2130,8 @@ static int fbdev_check(Options *op, Package *p)
|
||||
ret = run_conftest(op, p,"nvidiafb_sanity_check just_msg", &result);
|
||||
|
||||
if (!ret) {
|
||||
ui_error(op, "%s", result);
|
||||
if (result)
|
||||
ui_error(op, "%s", result);
|
||||
nvfree(result);
|
||||
|
||||
return FALSE;
|
||||
@@ -2135,7 +2158,8 @@ static int xen_check(Options *op, Package *p)
|
||||
ret = run_conftest(op, p,"xen_sanity_check just_msg", &result);
|
||||
|
||||
if (!ret) {
|
||||
ui_error(op, "%s", result);
|
||||
if (result)
|
||||
ui_error(op, "%s", result);
|
||||
nvfree(result);
|
||||
|
||||
return FALSE;
|
||||
@@ -2147,6 +2171,35 @@ static int xen_check(Options *op, Package *p)
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* 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() */
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* scan_dir() - scan through the specified directory for a matching
|
||||
* precompiled kernel interface.
|
||||
@@ -2154,7 +2207,6 @@ static int xen_check(Options *op, Package *p)
|
||||
|
||||
static PrecompiledInfo *scan_dir(Options *op, Package *p,
|
||||
const char *directory_name,
|
||||
const char *output_filename,
|
||||
const char *proc_version_string)
|
||||
{
|
||||
DIR *dir;
|
||||
@@ -2173,21 +2225,18 @@ static PrecompiledInfo *scan_dir(Options *op, Package *p,
|
||||
*/
|
||||
|
||||
while ((ent = readdir(dir)) != NULL) {
|
||||
|
||||
|
||||
if (((strcmp(ent->d_name, ".")) == 0) ||
|
||||
((strcmp(ent->d_name, "..")) == 0) ||
|
||||
strstr(ent->d_name, DETACHED_SIGNATURE_FILENAME)) continue;
|
||||
((strcmp(ent->d_name, "..")) == 0)) continue;
|
||||
|
||||
filename = nvstrcat(directory_name, "/", ent->d_name, NULL);
|
||||
|
||||
info = precompiled_unpack(op, filename, output_filename,
|
||||
proc_version_string,
|
||||
p->version);
|
||||
|
||||
if (info) break;
|
||||
|
||||
info = get_precompiled_info(op, filename, proc_version_string,
|
||||
p->version);
|
||||
|
||||
free(filename);
|
||||
filename = NULL;
|
||||
|
||||
if (info) break;
|
||||
}
|
||||
|
||||
if (closedir(dir) != 0) {
|
||||
|
7
kernel.h
7
kernel.h
@@ -33,11 +33,12 @@ 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*,
|
||||
const char*,
|
||||
const PrecompiledInfo *);
|
||||
const char *,
|
||||
const PrecompiledFileInfo *);
|
||||
int check_cc_version (Options*, Package*);
|
||||
int build_kernel_module (Options*, Package*);
|
||||
int build_kernel_interface (Options*, Package*);
|
||||
int build_kernel_interface (Options*, Package*,
|
||||
PrecompiledFileInfo **);
|
||||
int test_kernel_module (Options*, Package*);
|
||||
int load_kernel_module (Options*, Package*);
|
||||
int check_for_unloaded_kernel_module (Options*, Package*);
|
||||
|
98
misc.c
98
misc.c
@@ -447,8 +447,7 @@ int read_text_file(const char *filename, char **buf)
|
||||
if (!fp)
|
||||
return FALSE;
|
||||
|
||||
while (((line = fget_next_line(fp, &eof))
|
||||
!= NULL) && !eof) {
|
||||
while (((line = fget_next_line(fp, &eof)) != NULL)) {
|
||||
if ((index + strlen(line) + 1) > buflen) {
|
||||
buflen += 2 * strlen(line);
|
||||
tmpbuf = (char *)nvalloc(buflen);
|
||||
@@ -466,6 +465,10 @@ int read_text_file(const char *filename, char **buf)
|
||||
|
||||
index += sprintf(*buf + index, "%s\n", line);
|
||||
nvfree(line);
|
||||
|
||||
if (eof) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
@@ -2391,6 +2394,9 @@ int run_nvidia_xconfig(Options *op, int restore)
|
||||
} /* run_nvidia_xconfig() */
|
||||
|
||||
|
||||
|
||||
#define DISTRO_HOOK_DIRECTORY "/usr/lib/nvidia/"
|
||||
|
||||
/*
|
||||
* run_distro_hook() - run a distribution-provided hook script
|
||||
*/
|
||||
@@ -2398,7 +2404,7 @@ int run_nvidia_xconfig(Options *op, int restore)
|
||||
int run_distro_hook(Options *op, const char *hook)
|
||||
{
|
||||
int ret, status, shouldrun = op->run_distro_scripts;
|
||||
char *cmd = nvstrcat("/usr/lib/nvidia/", hook, NULL);
|
||||
char *cmd = nvstrcat(DISTRO_HOOK_DIRECTORY, hook, NULL);
|
||||
|
||||
if (op->kernel_module_only) {
|
||||
ui_expert(op,
|
||||
@@ -2443,6 +2449,92 @@ done:
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* prompt_for_user_cancel() - print a caller-supplied message and ask the
|
||||
* user whether to cancel the installation. If the file at the caller-supplied
|
||||
* path is readable, include any text from that file as additional detail for
|
||||
* the message. Returns TRUE if the user decides to cancel the installation;
|
||||
* returns FALSE if the user decides not to cancel.
|
||||
*/
|
||||
static int prompt_for_user_cancel(Options *op, const char *file,
|
||||
int default_cancel, const char *text)
|
||||
{
|
||||
int ret, file_read;
|
||||
char *message = NULL;
|
||||
|
||||
file_read = read_text_file(file, &message);
|
||||
|
||||
if (!file_read || !message) {
|
||||
message = nvstrdup("");
|
||||
}
|
||||
|
||||
ret = ui_yes_no(op, default_cancel,
|
||||
"%s\n\n%s\nWould you like to cancel this installation?",
|
||||
text, message);
|
||||
nvfree(message);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define INSTALL_PRESENT_FILE "alternate-install-present"
|
||||
#define INSTALL_AVAILABLE_FILE "alternate-install-available"
|
||||
|
||||
/*
|
||||
* check_for_alternate_install() - check to see if an alternate install is
|
||||
* available or present. If present, recommend updating via the alternate
|
||||
* mechanism or uninstalling first before proceeding with an nvidia-installer
|
||||
* installation; if available, but not present, inform the user about it.
|
||||
* Returns TRUE if no alternate installation is available or present, or if
|
||||
* checking for alternate installs is skipped, or if the user decides not to
|
||||
* cancel the installation. Returns FALSE if the user decides to cancel the
|
||||
* installation.
|
||||
*/
|
||||
|
||||
int check_for_alternate_install(Options *op)
|
||||
{
|
||||
int shouldcheck = op->check_for_alternate_installs;
|
||||
const char *alt_inst_present = DISTRO_HOOK_DIRECTORY INSTALL_PRESENT_FILE;
|
||||
const char *alt_inst_avail = DISTRO_HOOK_DIRECTORY INSTALL_AVAILABLE_FILE;
|
||||
|
||||
if (op->expert) {
|
||||
shouldcheck = ui_yes_no(op, shouldcheck,
|
||||
"Check for the availability or presence of "
|
||||
"alternate driver installs?");
|
||||
}
|
||||
|
||||
if (!shouldcheck) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (access(alt_inst_present, F_OK) == 0) {
|
||||
const char *msg;
|
||||
|
||||
msg = "The NVIDIA driver appears to have been installed previously "
|
||||
"using a different installer. To prevent potential conflicts, it "
|
||||
"is recommended either to update the existing installation using "
|
||||
"the same mechanism by which it was originally installed, or to "
|
||||
"uninstall the existing installation before installing this "
|
||||
"driver.";
|
||||
|
||||
return !prompt_for_user_cancel(op, alt_inst_present, TRUE, msg);
|
||||
}
|
||||
|
||||
if (access(alt_inst_avail, F_OK) == 0) {
|
||||
const char *msg;
|
||||
|
||||
msg = "An alternate method of installing the NVIDIA driver was "
|
||||
"detected. (This is usually a package provided by your "
|
||||
"distributor.) A driver installed via that method may integrate "
|
||||
"better with your system than a driver installed by "
|
||||
"nvidia-installer.";
|
||||
|
||||
return !prompt_for_user_cancel(op, alt_inst_avail, FALSE, msg);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Determine if the nouveau driver is currently in use. We do the
|
||||
|
1
misc.h
1
misc.h
@@ -61,6 +61,7 @@ int check_for_modular_xorg(Options *op);
|
||||
int check_for_nvidia_graphics_devices(Options *op, Package *p);
|
||||
int run_nvidia_xconfig(Options *op, int restore);
|
||||
int run_distro_hook(Options *op, const char *hook);
|
||||
int check_for_alternate_install(Options *op);
|
||||
int check_for_nouveau(Options *op);
|
||||
int dkms_module_installed(Options *op, const char *version);
|
||||
int dkms_install_module(Options *op, const char *version, const char *kernel);
|
||||
|
1077
mkprecompiled.c
1077
mkprecompiled.c
File diff suppressed because it is too large
Load Diff
@@ -122,6 +122,16 @@ These scripts should not require user interaction.
|
||||
Use the
|
||||
.B \-\-no\-distro\-scripts
|
||||
option to disable execution of these scripts.
|
||||
.PP
|
||||
In addition to the distribution hook scripts, distributors or other producers of driver packages may report the presence an already installed driver, or the availability of driver packages. Installing a text file to
|
||||
.B /usr/lib/nvidia/alternate-install-present
|
||||
will alert nvidia-installer that an existing driver is already installed. Installing a text file to
|
||||
.B /usr/lib/nvidia/alternate-install-available
|
||||
will alert nvidia-installer that an alternate installation option is available. The contents of
|
||||
.B /usr/lib/nvidia/alternate-install-present
|
||||
or
|
||||
.B /usr/lib/nvidia/alternate-install-available
|
||||
will be printed in a message informing the user of the presence/availability of the alternate driver installation, and asking the user whether to continue with the installation.
|
||||
.SH EXAMPLES
|
||||
.TP
|
||||
.B nvidia\-installer \-\-latest
|
||||
|
@@ -146,6 +146,7 @@ static Options *load_default_options(void)
|
||||
op->run_distro_scripts = TRUE;
|
||||
op->no_kernel_module_source = FALSE;
|
||||
op->dkms = FALSE;
|
||||
op->check_for_alternate_installs = TRUE;
|
||||
|
||||
return op;
|
||||
|
||||
|
@@ -145,6 +145,7 @@ typedef struct __options {
|
||||
int no_opengl_files;
|
||||
int no_kernel_module_source;
|
||||
int dkms;
|
||||
int check_for_alternate_installs;
|
||||
|
||||
char *opengl_prefix;
|
||||
char *opengl_libdir;
|
||||
@@ -385,10 +386,7 @@ typedef struct __package {
|
||||
|
||||
#define PERM_MASK (S_IRWXU|S_IRWXG|S_IRWXO)
|
||||
|
||||
#define PRECOMPILED_KERNEL_INTERFACE_FILENAME "precompiled-nv-linux.o"
|
||||
#define KERNEL_MODULE_CHECKSUM_FILENAME "nvidia-module-checksum"
|
||||
#define DETACHED_SIGNATURE_FILENAME "nvidia-detached-module-signature"
|
||||
|
||||
#define PRECOMPILED_PACKAGE_FILENAME "nvidia-precompiled"
|
||||
|
||||
/*
|
||||
* These are the default installation prefixes and the default
|
||||
|
@@ -92,6 +92,7 @@ enum {
|
||||
MODULE_SIGNING_KEY_PATH_OPTION,
|
||||
MODULE_SIGNING_HASH_OPTION,
|
||||
MODULE_SIGNING_X509_HASH_OPTION,
|
||||
NO_CHECK_FOR_ALTERNATE_INSTALLS_OPTION,
|
||||
};
|
||||
|
||||
static const NVGetoptOption __options[] = {
|
||||
@@ -604,6 +605,13 @@ static const NVGetoptOption __options[] = {
|
||||
"name must be one of the message digest algorithms recognized by "
|
||||
"the x509(1) command." },
|
||||
|
||||
{ "no-check-for-alternate-installs", NO_CHECK_FOR_ALTERNATE_INSTALLS_OPTION,
|
||||
0, NULL,
|
||||
"Maintainers of alternate driver installation methods can report the "
|
||||
"presence and/or availability of an alternate driver installation to "
|
||||
"nvidia-installer. Setting this option skips the check for alternate "
|
||||
"driver installations." },
|
||||
|
||||
/* Orphaned options: These options were in the long_options table in
|
||||
* nvidia-installer.c but not in the help. */
|
||||
{ "debug", 'd', 0, NULL,NULL },
|
||||
|
826
precompiled.c
826
precompiled.c
@@ -19,10 +19,6 @@
|
||||
*
|
||||
* precompiled.c - this source file contains functions for dealing
|
||||
* with precompiled kernel interfaces.
|
||||
*
|
||||
* XXX portions of these functions are lifted from mkprecompiled (it
|
||||
* was much easier to duplicate them than to finesse the code to be
|
||||
* shared between the installer and mkprecompiled).
|
||||
*/
|
||||
|
||||
|
||||
@@ -42,32 +38,37 @@
|
||||
#include "misc.h"
|
||||
#include "crc.h"
|
||||
|
||||
#define PRECOMPILED_CONSTANT_LENGTH (8 + 4 + 4 + 4 + 4)
|
||||
|
||||
|
||||
static int precompiled_read_fileinfo(Options *op, PrecompiledFileInfo *fileInfos,
|
||||
int index, char *buf, int offset, int size);
|
||||
|
||||
/*
|
||||
* decode_uint32() - given an index into a buffer, read the next 4
|
||||
* bytes, and build a uint32.
|
||||
* read_uint32() - given a buffer and an offset, read the next 4 bytes from
|
||||
* the buffer at the given offset, build a uint32, and advance the offset.
|
||||
*/
|
||||
|
||||
static uint32 decode_uint32(char *buf)
|
||||
static uint32 read_uint32(const char *buf, int *offset)
|
||||
{
|
||||
uint32 ret = 0;
|
||||
|
||||
ret += (((uint32) buf[3]) & 0xff);
|
||||
ret += (((uint32) buf[*offset + 3]) & 0xff);
|
||||
ret <<= 8;
|
||||
|
||||
ret += (((uint32) buf[2]) & 0xff);
|
||||
ret += (((uint32) buf[*offset + 2]) & 0xff);
|
||||
ret <<= 8;
|
||||
|
||||
ret += (((uint32) buf[1]) & 0xff);
|
||||
ret += (((uint32) buf[*offset + 1]) & 0xff);
|
||||
ret <<= 8;
|
||||
|
||||
ret += (((uint32) buf[0]) & 0xff);
|
||||
ret += (((uint32) buf[*offset]) & 0xff);
|
||||
ret <<= 0;
|
||||
|
||||
*offset += sizeof(uint32);
|
||||
|
||||
return ret;
|
||||
|
||||
} /* decode_uint32() */
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -78,15 +79,15 @@ static uint32 decode_uint32(char *buf)
|
||||
* mounted.
|
||||
*/
|
||||
|
||||
char *read_proc_version(Options *op)
|
||||
char *read_proc_version(Options *op, const char *proc_mount_point)
|
||||
{
|
||||
int fd, ret, len, version_len;
|
||||
char *version, *c = NULL;
|
||||
char *proc_verson_filename;
|
||||
|
||||
len = strlen(op->proc_mount_point) + 9; /* strlen("/version") + 1 */
|
||||
len = strlen(proc_mount_point) + 9; /* strlen("/version") + 1 */
|
||||
proc_verson_filename = (char *) nvalloc(len);
|
||||
snprintf(proc_verson_filename, len, "%s/version", op->proc_mount_point);
|
||||
snprintf(proc_verson_filename, len, "%s/version", proc_mount_point);
|
||||
|
||||
if ((fd = open(proc_verson_filename, O_RDONLY)) == -1) {
|
||||
ui_warn(op, "Unable to open the file '%s' (%s).",
|
||||
@@ -139,27 +140,26 @@ char *read_proc_version(Options *op)
|
||||
|
||||
|
||||
/*
|
||||
* precompiled_unpack() - unpack the specified package. It's not
|
||||
* really an error if we can't open the file or if it's not the right
|
||||
* format, so just throw an expert-only log message.
|
||||
* get_precompiled_info() - load the the specified package into a
|
||||
* PrecompiledInfo record. It's not really an error if we can't open the file
|
||||
* or if it's not the right format, so just throw an expert-only log message.
|
||||
*/
|
||||
|
||||
PrecompiledInfo *precompiled_unpack(Options *op,
|
||||
const char *filename,
|
||||
const char *output_filename,
|
||||
const char *real_proc_version_string,
|
||||
const char *package_version)
|
||||
PrecompiledInfo *get_precompiled_info(Options *op,
|
||||
const char *filename,
|
||||
const char *real_proc_version_string,
|
||||
const char *package_version)
|
||||
{
|
||||
int dst_fd, fd, offset, len = 0;
|
||||
char *buf, *dst;
|
||||
uint32 crc, val, size, linked_module_crc;
|
||||
char *version, *description, *proc_version_string,
|
||||
*detached_signature = NULL;
|
||||
int fd, offset, num_files, i;
|
||||
char *buf;
|
||||
uint32 val, size;
|
||||
char *version, *description, *proc_version_string;
|
||||
struct stat stat_buf;
|
||||
PrecompiledInfo *info = NULL;
|
||||
PrecompiledFileInfo *fileInfos = NULL;
|
||||
|
||||
fd = dst_fd = size = 0;
|
||||
buf = dst = description = proc_version_string = NULL;
|
||||
fd = size = 0;
|
||||
buf = description = proc_version_string = NULL;
|
||||
|
||||
/* open the file to be unpacked */
|
||||
|
||||
@@ -180,7 +180,7 @@ PrecompiledInfo *precompiled_unpack(Options *op,
|
||||
|
||||
/* check for a minimum length */
|
||||
|
||||
if (size < PRECOMPILED_CONSTANT_LENGTH) {
|
||||
if (size < PRECOMPILED_PKG_CONSTANT_LENGTH) {
|
||||
ui_expert(op, "File '%s' appears to be too short.", filename);
|
||||
goto done;
|
||||
}
|
||||
@@ -197,22 +197,25 @@ PrecompiledInfo *precompiled_unpack(Options *op,
|
||||
|
||||
/* check for the header */
|
||||
|
||||
if (strncmp(buf + offset, "NVIDIA ", 8) != 0) {
|
||||
if (strncmp(buf + offset, PRECOMPILED_PKG_HEADER, 8) != 0) {
|
||||
ui_expert(op, "File '%s': unrecognized file format.", filename);
|
||||
goto done;
|
||||
}
|
||||
offset += 8;
|
||||
|
||||
/* read the crc */
|
||||
/* check the package format version */
|
||||
|
||||
crc = decode_uint32(buf + offset);
|
||||
offset += 4;
|
||||
val = read_uint32(buf, &offset);
|
||||
if (val != PRECOMPILED_PKG_VERSION) {
|
||||
ui_expert(op, "Incompatible package format version %d: expected %d.",
|
||||
val, PRECOMPILED_PKG_VERSION);
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* read the version */
|
||||
|
||||
val = decode_uint32(buf + offset);
|
||||
offset += 4;
|
||||
if ((val + PRECOMPILED_CONSTANT_LENGTH) > size) {
|
||||
val = read_uint32(buf, &offset);
|
||||
if ((val + PRECOMPILED_PKG_CONSTANT_LENGTH) > size) {
|
||||
ui_expert(op, "Invalid file '%s' (bad version string length %d).",
|
||||
filename, val);
|
||||
goto done;
|
||||
@@ -229,34 +232,28 @@ PrecompiledInfo *precompiled_unpack(Options *op,
|
||||
/* check if this precompiled kernel interface is the right driver
|
||||
version */
|
||||
|
||||
if (strcmp(version, package_version) != 0) {
|
||||
if (package_version && (strcmp(version, package_version) != 0)) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
|
||||
/* read the description */
|
||||
|
||||
val = decode_uint32(buf + offset);
|
||||
offset += 4;
|
||||
if ((val + PRECOMPILED_CONSTANT_LENGTH) > size) {
|
||||
val = read_uint32(buf, &offset);
|
||||
if ((val + PRECOMPILED_PKG_CONSTANT_LENGTH) > size) {
|
||||
ui_expert(op, "Invalid file '%s' (bad description string length %d).",
|
||||
filename, val);
|
||||
goto done;
|
||||
}
|
||||
if (val > 0) {
|
||||
description = nvalloc(val+1);
|
||||
memcpy(description, buf + offset, val);
|
||||
description[val] = '\0';
|
||||
} else {
|
||||
description = NULL;
|
||||
}
|
||||
description = nvalloc(val+1);
|
||||
memcpy(description, buf + offset, val);
|
||||
description[val] = '\0';
|
||||
offset += val;
|
||||
|
||||
/* read the proc version string */
|
||||
|
||||
val = decode_uint32(buf + offset);
|
||||
offset += 4;
|
||||
if ((val + PRECOMPILED_CONSTANT_LENGTH) > size) {
|
||||
val = read_uint32(buf, &offset);
|
||||
if ((val + PRECOMPILED_PKG_CONSTANT_LENGTH) > size) {
|
||||
ui_expert(op, "Invalid file '%s' (bad version string length %d).",
|
||||
filename, val);
|
||||
goto done;
|
||||
@@ -266,131 +263,686 @@ PrecompiledInfo *precompiled_unpack(Options *op,
|
||||
offset += val;
|
||||
proc_version_string[val] = '\0';
|
||||
|
||||
/* if this interface appears to have been packaged by nvidia-installer,
|
||||
* get the linked module crc and path to the detached signature. */
|
||||
|
||||
if (strstr(filename, PRECOMPILED_KERNEL_INTERFACE_FILENAME) ==
|
||||
strrchr(filename, '/') + 1) {
|
||||
char *suffix, *dirname, *tmp, *crc_file_path;
|
||||
|
||||
dirname = nvstrdup(filename);
|
||||
tmp = strrchr(dirname, '/');
|
||||
*tmp = '\0';
|
||||
|
||||
suffix = nvstrdup(strrchr(filename, '/') + 1 +
|
||||
strlen(PRECOMPILED_KERNEL_INTERFACE_FILENAME));
|
||||
|
||||
detached_signature = nvstrcat(dirname, "/", DETACHED_SIGNATURE_FILENAME,
|
||||
suffix, NULL);
|
||||
crc_file_path = nvstrcat(dirname, "/", KERNEL_MODULE_CHECKSUM_FILENAME,
|
||||
suffix, NULL);
|
||||
|
||||
if (access(detached_signature, F_OK | R_OK) == 0 &&
|
||||
access(crc_file_path, F_OK | R_OK) == 0) {
|
||||
FILE *crc_file;
|
||||
|
||||
crc_file = fopen(crc_file_path, "r");
|
||||
if (crc_file) {
|
||||
int items_read = fread(&linked_module_crc,
|
||||
sizeof(linked_module_crc), 1, crc_file);
|
||||
if (items_read != 1) {
|
||||
ui_warn(op, "A checksum file for a linked kernel module "
|
||||
"was found, but reading the checksum failed.");
|
||||
detached_signature = NULL;
|
||||
}
|
||||
fclose(crc_file);
|
||||
}
|
||||
} else {
|
||||
detached_signature = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* check if the running kernel matches */
|
||||
|
||||
if (strcmp(real_proc_version_string, proc_version_string) != 0) {
|
||||
if (real_proc_version_string &&
|
||||
(strcmp(real_proc_version_string, proc_version_string) != 0)) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
ui_log(op, "A precompiled kernel interface for kernel '%s' has been "
|
||||
"found here: %s.", description, filename);
|
||||
|
||||
/* extract kernel interface module */
|
||||
|
||||
len = size - offset;
|
||||
|
||||
if ((dst_fd = open(output_filename, O_CREAT | O_RDWR | O_TRUNC,
|
||||
S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) == -1) {
|
||||
ui_error(op, "Unable to open output file '%s' (%s).", output_filename,
|
||||
strerror(errno));
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* set the output file length */
|
||||
num_files = read_uint32(buf, &offset);
|
||||
fileInfos = nvalloc(num_files * sizeof(PrecompiledFileInfo));
|
||||
for (i = 0; i < num_files; i++) {
|
||||
int ret;
|
||||
ret = precompiled_read_fileinfo(op, fileInfos, i, buf, offset, size);
|
||||
|
||||
if ((lseek(dst_fd, len - 1, SEEK_SET) == -1) ||
|
||||
(write(dst_fd, "", 1) == -1)) {
|
||||
ui_error(op, "Unable to set output file '%s' length %d (%s).\n",
|
||||
output_filename, len, strerror(errno));
|
||||
goto done;
|
||||
if (ret > 0) {
|
||||
offset += ret;
|
||||
} else {
|
||||
ui_log(op, "An error occurred while trying to parse '%s'.",
|
||||
filename);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
/* mmap the dst */
|
||||
|
||||
dst = mmap(0, len, PROT_READ|PROT_WRITE, MAP_FILE|MAP_SHARED, dst_fd, 0);
|
||||
if (dst == (void *) -1) {
|
||||
ui_error(op, "Unable to mmap output file %s (%s).\n",
|
||||
output_filename, strerror(errno));
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* copy */
|
||||
|
||||
memcpy(dst, buf + offset, len);
|
||||
|
||||
/*
|
||||
* now that we can no longer fail, allocate and initialize the
|
||||
* PrecompiledInfo structure
|
||||
*/
|
||||
|
||||
info = (PrecompiledInfo *) nvalloc(sizeof(PrecompiledInfo));
|
||||
info->crc = crc;
|
||||
info->package_size = size;
|
||||
info->version = version;
|
||||
info->proc_version_string = proc_version_string;
|
||||
info->description = description;
|
||||
info->detached_signature = detached_signature;
|
||||
info->linked_module_crc = linked_module_crc;
|
||||
info->num_files = num_files;
|
||||
info->files = fileInfos;
|
||||
|
||||
/*
|
||||
* XXX so that the proc version, description, and detached_signature strings
|
||||
* aren't freed below
|
||||
* XXX so that the proc version and description strings, and the
|
||||
* PrecompiledFileInfo array aren't freed below
|
||||
*/
|
||||
|
||||
proc_version_string = description = detached_signature = NULL;
|
||||
|
||||
proc_version_string = description = NULL;
|
||||
fileInfos = NULL;
|
||||
|
||||
done:
|
||||
|
||||
|
||||
/* cleanup whatever needs cleaning up */
|
||||
|
||||
if (dst) munmap(dst, len);
|
||||
if (buf) munmap(buf, size);
|
||||
if (fd > 0) close(fd);
|
||||
if (dst_fd > 0) close(dst_fd);
|
||||
if (description) free(description);
|
||||
if (proc_version_string) free(proc_version_string);
|
||||
if (detached_signature) free(detached_signature);
|
||||
if (fileInfos) free(fileInfos);
|
||||
|
||||
return info;
|
||||
|
||||
} /* mkprecompiled_unpack() */
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* precompiled_file_unpack() - Unpack an individual precompiled file to the
|
||||
* specified output directory.
|
||||
*/
|
||||
|
||||
int precompiled_file_unpack(Options *op, const PrecompiledFileInfo *fileInfo,
|
||||
const char *output_directory)
|
||||
{
|
||||
int ret = FALSE, dst_fd = 0;
|
||||
char *dst_path, *dst = NULL;
|
||||
|
||||
dst_path = nvstrcat(output_directory, "/", fileInfo->name, NULL);
|
||||
|
||||
/* extract file */
|
||||
|
||||
if ((dst_fd = open(dst_path, O_CREAT | O_RDWR | O_TRUNC,
|
||||
S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) == -1) {
|
||||
ui_error(op, "Unable to open output file '%s' (%s).", dst_path,
|
||||
strerror(errno));
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* set the output file length */
|
||||
|
||||
if ((lseek(dst_fd, fileInfo->size - 1, SEEK_SET) == -1) ||
|
||||
(write(dst_fd, "", 1) == -1)) {
|
||||
ui_error(op, "Unable to set output file '%s' length %d (%s).\n",
|
||||
dst_path, fileInfo->size, strerror(errno));
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* mmap the dst */
|
||||
|
||||
dst = mmap(0, fileInfo->size, PROT_READ|PROT_WRITE, MAP_FILE|MAP_SHARED, dst_fd, 0);
|
||||
if (dst == (void *) -1) {
|
||||
ui_error(op, "Unable to mmap output file %s (%s).\n",
|
||||
dst_path, strerror(errno));
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* copy */
|
||||
|
||||
memcpy(dst, fileInfo->data, fileInfo->size);
|
||||
|
||||
ret = TRUE;
|
||||
|
||||
done:
|
||||
|
||||
/* cleanup whatever needs cleaning up */
|
||||
|
||||
nvfree(dst_path);
|
||||
if (dst) munmap(dst, fileInfo->size);
|
||||
if (dst_fd > 0) close(dst_fd);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* precompiled_unpack() - unpack all of the files in a PrecompiledInfo into
|
||||
* the given destination directory */
|
||||
int precompiled_unpack(Options *op, const PrecompiledInfo *info,
|
||||
const char *output_directory)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!info) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
for (i = 0; i < info->num_files; i++) {
|
||||
if (!precompiled_file_unpack(op, &(info->files[i]), output_directory)) {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* encode_uint32() - given a uint32, a data buffer, and an offset into the data
|
||||
* buffer, write the integer to the data buffer and advance the offset by the
|
||||
* number of bytes written.
|
||||
*/
|
||||
|
||||
static void encode_uint32(uint32 val, uint8 *data, int *offset)
|
||||
{
|
||||
data[*offset + 0] = ((val >> 0) & 0xff);
|
||||
data[*offset + 1] = ((val >> 8) & 0xff);
|
||||
data[*offset + 2] = ((val >> 16) & 0xff);
|
||||
data[*offset + 3] = ((val >> 24) & 0xff);
|
||||
|
||||
*offset += sizeof(uint32);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* precompiled_pack() - pack the specified precompiled kernel interface
|
||||
* file, prepended with a header, the CRC the driver version, a description
|
||||
* string, and the proc version string.
|
||||
*/
|
||||
|
||||
int precompiled_pack(const PrecompiledInfo *info, const char *package_filename)
|
||||
{
|
||||
int fd, offset;
|
||||
uint8 *out;
|
||||
int version_len, description_len, proc_version_len;
|
||||
int total_len, files_len, i;
|
||||
|
||||
/*
|
||||
* get the lengths of the description, the proc version string,
|
||||
* and the files to be packaged along with the associated metadata.
|
||||
*/
|
||||
|
||||
version_len = strlen(info->version);
|
||||
description_len = strlen(info->description);
|
||||
proc_version_len = strlen(info->proc_version_string);
|
||||
|
||||
for (files_len = i = 0; i < info->num_files; i++) {
|
||||
files_len += PRECOMPILED_FILE_CONSTANT_LENGTH +
|
||||
strlen(info->files[i].name) +
|
||||
strlen(info->files[i].linked_module_name) +
|
||||
strlen(info->files[i].core_object_name) +
|
||||
info->files[i].size +
|
||||
info->files[i].signature_size;
|
||||
}
|
||||
|
||||
total_len = PRECOMPILED_PKG_CONSTANT_LENGTH +
|
||||
version_len + description_len + proc_version_len + files_len;
|
||||
|
||||
/* open the output file for writing */
|
||||
|
||||
fd = nv_open(package_filename, O_CREAT|O_RDWR|O_TRUNC,
|
||||
S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
|
||||
|
||||
/* set the output file length */
|
||||
|
||||
nv_set_file_length(package_filename, fd, total_len);
|
||||
|
||||
/* map the output file */
|
||||
|
||||
out = nv_mmap(package_filename, total_len, PROT_READ|PROT_WRITE,
|
||||
MAP_FILE|MAP_SHARED, fd);
|
||||
offset = 0;
|
||||
|
||||
/* write the header */
|
||||
|
||||
memcpy(&(out[0]), PRECOMPILED_PKG_HEADER, 8);
|
||||
offset += 8;
|
||||
|
||||
/* write the package version */
|
||||
|
||||
encode_uint32(PRECOMPILED_PKG_VERSION, out, &offset);
|
||||
|
||||
/* write the version */
|
||||
|
||||
encode_uint32(version_len, out, &offset);
|
||||
|
||||
if (version_len) {
|
||||
memcpy(&(out[offset]), info->version, version_len);
|
||||
offset += version_len;
|
||||
}
|
||||
|
||||
/* write the description */
|
||||
|
||||
encode_uint32(description_len, out, &offset);
|
||||
|
||||
if (description_len) {
|
||||
memcpy(&(out[offset]), info->description, description_len);
|
||||
offset += description_len;
|
||||
}
|
||||
|
||||
/* write the proc version string */
|
||||
|
||||
encode_uint32(proc_version_len, out, &offset);
|
||||
|
||||
memcpy(&(out[offset]), info->proc_version_string, proc_version_len);
|
||||
offset += proc_version_len;
|
||||
|
||||
/* write the number of files */
|
||||
|
||||
encode_uint32(info->num_files, out, &offset);
|
||||
|
||||
/* write the files */
|
||||
for (i = 0; i < info->num_files; i++) {
|
||||
PrecompiledFileInfo *file = &(info->files[i]);
|
||||
uint32 name_len = strlen(file->name);
|
||||
uint32 linked_module_name_len = strlen(file->linked_module_name);
|
||||
uint32 core_object_name_len = strlen(file->core_object_name);
|
||||
|
||||
/* file header */
|
||||
memcpy(&(out[offset]), PRECOMPILED_FILE_HEADER, 4);
|
||||
offset += 4;
|
||||
|
||||
/* file sequence number */
|
||||
encode_uint32(i, out, &offset);
|
||||
|
||||
/* file type and attributes*/
|
||||
encode_uint32(file->type, out, &offset);
|
||||
encode_uint32(file->attributes, out, &offset);
|
||||
|
||||
/* file name */
|
||||
encode_uint32(name_len, out, &offset);
|
||||
memcpy(&(out[offset]), file->name, name_len);
|
||||
offset += name_len;
|
||||
|
||||
/* linked module name */
|
||||
encode_uint32(linked_module_name_len, out, &offset);
|
||||
memcpy(&(out[offset]), file->linked_module_name, linked_module_name_len);
|
||||
offset += linked_module_name_len;
|
||||
|
||||
/* core object name */
|
||||
encode_uint32(core_object_name_len, out, &offset);
|
||||
memcpy(&(out[offset]), file->core_object_name, core_object_name_len);
|
||||
offset += core_object_name_len;
|
||||
|
||||
/* crc */
|
||||
encode_uint32(file->crc, out, &offset);
|
||||
|
||||
/* file */
|
||||
encode_uint32(file->size, out, &offset);
|
||||
memcpy(&(out[offset]), file->data, file->size);
|
||||
offset += file->size;
|
||||
|
||||
/* redundant crc */
|
||||
encode_uint32(file->crc, out, &offset);
|
||||
|
||||
/* linked module crc */
|
||||
encode_uint32(file->linked_module_crc, out, &offset);
|
||||
|
||||
/* detached signature */
|
||||
encode_uint32(file->signature_size, out, &offset);
|
||||
if (file->signature_size) {
|
||||
memcpy(&(out[offset]), file->signature, file->signature_size);
|
||||
offset += file->signature_size;
|
||||
}
|
||||
|
||||
/* redundant file sequence number */
|
||||
encode_uint32(i, out, &offset);
|
||||
|
||||
/* file footer */
|
||||
memcpy(&(out[offset]), PRECOMPILED_FILE_FOOTER, 4);
|
||||
offset += 4;
|
||||
}
|
||||
|
||||
/* unmap package */
|
||||
|
||||
munmap(out, total_len);
|
||||
|
||||
close(fd);
|
||||
|
||||
return TRUE;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* free_precompiled() - free any malloced strings stored in a PrecompiledInfo,
|
||||
* then free the PrecompiledInfo.
|
||||
*/
|
||||
void free_precompiled(PrecompiledInfo *info)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!info) {
|
||||
return;
|
||||
}
|
||||
|
||||
nvfree(info->description);
|
||||
nvfree(info->proc_version_string);
|
||||
nvfree(info->detached_signature);
|
||||
nvfree(info->version);
|
||||
|
||||
for (i = 0; i < info->num_files; i++) {
|
||||
free_precompiled_file_data(info->files[i]);
|
||||
}
|
||||
nvfree(info->files);
|
||||
|
||||
nvfree(info);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void free_precompiled_file_data(PrecompiledFileInfo fileInfo)
|
||||
{
|
||||
nvfree(fileInfo.name);
|
||||
nvfree(fileInfo.linked_module_name);
|
||||
nvfree(fileInfo.data);
|
||||
nvfree(fileInfo.signature);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* precompiled_read_file() - attempt to open the file at the specified path and
|
||||
* populate a PrecompiledFileInfo record with its contents and the appropriate
|
||||
* metadata. Return a pointer to a newly allocated PrecompiledFile record on
|
||||
* success, or NULL on failure.
|
||||
*/
|
||||
|
||||
static int precompiled_read_file(PrecompiledFileInfo *fileInfo,
|
||||
const char *filename,
|
||||
const char *linked_module_name,
|
||||
const char *core_object_name, uint32 type)
|
||||
{
|
||||
int fd;
|
||||
struct stat st;
|
||||
int success = FALSE, ret;
|
||||
|
||||
fd = open(filename, O_RDONLY);
|
||||
if (fd == -1) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (fstat(fd, &st) != 0) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
fileInfo->size = st.st_size;
|
||||
fileInfo->data = nvalloc(fileInfo->size);
|
||||
|
||||
ret = read(fd, fileInfo->data, fileInfo->size);
|
||||
|
||||
if (ret != fileInfo->size) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
fileInfo->type = type;
|
||||
fileInfo->name = nv_basename(filename);
|
||||
fileInfo->linked_module_name = nvstrdup(linked_module_name);
|
||||
fileInfo->core_object_name = nvstrdup(core_object_name);
|
||||
fileInfo->crc = compute_crc(NULL, filename);
|
||||
|
||||
success = TRUE;
|
||||
|
||||
done:
|
||||
close(fd);
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
int precompiled_read_interface(PrecompiledFileInfo *fileInfo,
|
||||
const char *filename,
|
||||
const char *linked_module_name,
|
||||
const char *core_object_name)
|
||||
{
|
||||
return precompiled_read_file(fileInfo, filename, linked_module_name,
|
||||
core_object_name,
|
||||
PRECOMPILED_FILE_TYPE_INTERFACE);
|
||||
}
|
||||
|
||||
int precompiled_read_module(PrecompiledFileInfo *fileInfo, const char *filename)
|
||||
{
|
||||
return precompiled_read_file(fileInfo, filename, "", "",
|
||||
PRECOMPILED_FILE_TYPE_MODULE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* precompiled_read_fileinfo() - Read a PrecompiledFileInfo record from a binary
|
||||
* precompiled file package.
|
||||
*
|
||||
* Parameters:
|
||||
* op: A pointer to the options structure, used for ui_* functions
|
||||
* fileInfos: A PrecompiledFileInfo array, where the decoded file data from
|
||||
* the binary package will be stored
|
||||
* index: The index into fileInfos where the decoded file data will be
|
||||
* stored. Used to verify that the file number recorded in the
|
||||
* package is valid.
|
||||
* buf: The raw buffer containing the binary package data. This should
|
||||
* point to the beginning of the package file.
|
||||
* offset: The offset into buf where the file data to be read begins.
|
||||
* size: The size of the package data buffer. This is used for bounds
|
||||
* checking, to make sure that a reading a length specified in the
|
||||
* won't go past the end of the package file.
|
||||
*
|
||||
* Return value:
|
||||
* The number of bytes read from the package file on success, or -1 on error.
|
||||
*/
|
||||
|
||||
static int precompiled_read_fileinfo(Options *op, PrecompiledFileInfo *fileInfos,
|
||||
int index, char *buf, int offset, int size)
|
||||
{
|
||||
PrecompiledFileInfo *fileInfo = fileInfos + index;
|
||||
uint32 val;
|
||||
int oldoffset = offset;
|
||||
|
||||
if (size - offset < PRECOMPILED_FILE_CONSTANT_LENGTH) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (strncmp(buf + offset, PRECOMPILED_FILE_HEADER, 4) != 0) {
|
||||
ui_log(op, "Unrecognized header for packaged file.");
|
||||
return -1;
|
||||
}
|
||||
offset += 4;
|
||||
|
||||
val = read_uint32(buf, &offset);
|
||||
if (val != index) {
|
||||
ui_log(op, "Invalid file index %d; expected %d.", val, index);
|
||||
return -1;
|
||||
}
|
||||
|
||||
fileInfo->type = read_uint32(buf, &offset);
|
||||
fileInfo->attributes = read_uint32(buf, &offset);
|
||||
|
||||
val = read_uint32(buf, &offset);
|
||||
if (offset + val > size) {
|
||||
ui_log(op, "Bad filename length.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
fileInfo->name = nvalloc(val + 1);
|
||||
memcpy(fileInfo->name, buf + offset, val);
|
||||
offset += val;
|
||||
|
||||
val = read_uint32(buf, &offset);
|
||||
if (offset + val > size) {
|
||||
ui_log(op, "Bad linked module name length.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
fileInfo->linked_module_name = nvalloc(val + 1);
|
||||
memcpy(fileInfo->linked_module_name, buf + offset, val);
|
||||
offset += val;
|
||||
|
||||
val = read_uint32(buf, &offset);
|
||||
if (offset + val > size) {
|
||||
ui_log(op, "Bad core object file name length.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
fileInfo->core_object_name = nvalloc(val + 1);
|
||||
memcpy(fileInfo->core_object_name, buf + offset, val);
|
||||
offset += val;
|
||||
|
||||
fileInfo->crc = read_uint32(buf, &offset);
|
||||
|
||||
fileInfo->size = read_uint32(buf, &offset);
|
||||
if (offset + fileInfo->size > size) {
|
||||
ui_log(op, "Bad file length.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
fileInfo->data = nvalloc(fileInfo->size);
|
||||
memcpy(fileInfo->data, buf + offset, fileInfo->size);
|
||||
offset += fileInfo->size;
|
||||
|
||||
val = read_uint32(buf, &offset);
|
||||
if (val != fileInfo->crc) {
|
||||
ui_log(op, "The redundant stored CRC values %" PRIu32 " and %" PRIu32
|
||||
" disagree with each other; the file may be corrupted.",
|
||||
fileInfo->crc, val);
|
||||
return -1;
|
||||
}
|
||||
|
||||
val = compute_crc_from_buffer(fileInfo->data, fileInfo->size);
|
||||
if (val != fileInfo->crc) {
|
||||
ui_log(op, "The CRC for the file '%s' (%" PRIu32 ") does not match the "
|
||||
"expected value (%" PRIu32 ").", fileInfo->name, val,
|
||||
fileInfo->crc);
|
||||
}
|
||||
|
||||
fileInfo->linked_module_crc = read_uint32(buf, &offset);
|
||||
|
||||
fileInfo->signature_size = read_uint32(buf, &offset);
|
||||
if(fileInfo->signature_size) {
|
||||
if (offset + fileInfo->signature_size > size) {
|
||||
ui_log(op, "Bad signature size");
|
||||
return -1;
|
||||
}
|
||||
fileInfo->signature = nvalloc(fileInfo->signature_size);
|
||||
memcpy(fileInfo->signature, buf + offset, fileInfo->signature_size);
|
||||
offset += fileInfo->signature_size;
|
||||
}
|
||||
|
||||
val = read_uint32(buf, &offset);
|
||||
if (val != index) {
|
||||
ui_log(op, "Invalid file index %d; expected %d.", val, index);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (strncmp(buf + offset, PRECOMPILED_FILE_FOOTER, 4) != 0) {
|
||||
ui_log(op, "Unrecognized footer for packaged file.");
|
||||
return -1;
|
||||
}
|
||||
offset += 4;
|
||||
|
||||
return offset - oldoffset;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* precompiled_find_file() - search for a file with the given name within the
|
||||
* given PrecompiledInfo record, and return a pointer to it if found, or NULL
|
||||
* if not found.
|
||||
*/
|
||||
|
||||
PrecompiledFileInfo *precompiled_find_file(const PrecompiledInfo *info,
|
||||
const char *file)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < info->num_files; i++) {
|
||||
if (strcmp(file, info->files[i].name) == 0) {
|
||||
return info->files + i;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* precompiled_append_files() - append the given PrecompiledFileInfo array to
|
||||
* the already existing files in the given PrecompiledInfo.
|
||||
*/
|
||||
|
||||
void precompiled_append_files(PrecompiledInfo *info, PrecompiledFileInfo *files,
|
||||
int num_files)
|
||||
{
|
||||
info->files = nvrealloc(info->files, (info->num_files + num_files) *
|
||||
sizeof(PrecompiledFileInfo));
|
||||
memcpy(info->files + info->num_files, files,
|
||||
num_files * sizeof(PrecompiledFileInfo));
|
||||
info->num_files += num_files;
|
||||
}
|
||||
|
||||
/*
|
||||
* precompiled_file_type_name() - return a pointer to a human-readable string
|
||||
* naming a file type. The string should not be freed.
|
||||
*/
|
||||
const char *precompiled_file_type_name(uint32 file_type)
|
||||
{
|
||||
static const char *file_type_names[] = {
|
||||
"precompiled kernel interface",
|
||||
"precompiled kernel module",
|
||||
};
|
||||
|
||||
if (file_type >= ARRAY_LEN(file_type_names)) {
|
||||
return "unknown file type";
|
||||
}
|
||||
|
||||
return file_type_names[file_type];
|
||||
}
|
||||
|
||||
/*
|
||||
* precompiled_file_attribute_names() - return a NULL-terminated list of
|
||||
* human-readable strings naming the attributes in the given file attribute
|
||||
* mask. The list should be freed when no longer used, but the constituent
|
||||
* strings should not be freed.
|
||||
*/
|
||||
const char **precompiled_file_attribute_names(uint32 attribute_mask)
|
||||
{
|
||||
const char **ret;
|
||||
int i, attr = 0;
|
||||
|
||||
static const char *file_attribute_names[] = {
|
||||
"detached signature",
|
||||
"linked module crc",
|
||||
"embedded signature",
|
||||
};
|
||||
|
||||
ret = nvalloc((ARRAY_LEN(file_attribute_names) + 1) * sizeof(char *));
|
||||
|
||||
for (i = 0; i < 32; i++) {
|
||||
if (attribute_mask & (1 << i)) {
|
||||
ret[attr++] = file_attribute_names[i];
|
||||
}
|
||||
}
|
||||
ret[attr] = NULL;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* byte_tail() - copy from infile, starting at the specified byte offset, and
|
||||
* going until the end of infile to a newly allocated buffer, a pointer to
|
||||
* which is stored at location given by the caller. Returns the size of the new
|
||||
* buffer on success; returns 0 and sets the caller pointer to NULL on failure.
|
||||
* This is needed because `tail -c` is unreliable in some implementations.
|
||||
*/
|
||||
int byte_tail(const char *infile, int start, char **buf)
|
||||
{
|
||||
FILE *in = NULL;
|
||||
int ret, end, size = 0;
|
||||
|
||||
in = fopen(infile, "r");
|
||||
|
||||
if (!in) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
ret = fseek(in, 0, SEEK_END);
|
||||
if (ret != 0) {
|
||||
goto done;
|
||||
}
|
||||
end = ftell(in);
|
||||
|
||||
ret = fseek(in, start, SEEK_SET);
|
||||
if (ret != 0) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
size = end - start;
|
||||
*buf = nvalloc(size);
|
||||
|
||||
ret = (fread(*buf, 1, size + 1, in));
|
||||
if (ret != size || ferror(in) || !feof(in)) {
|
||||
nvfree(*buf);
|
||||
*buf = NULL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
done:
|
||||
fclose(in);
|
||||
return size;
|
||||
}
|
||||
|
169
precompiled.h
169
precompiled.h
@@ -2,7 +2,7 @@
|
||||
* nvidia-installer: A tool for installing NVIDIA software packages on
|
||||
* Unix and Linux systems.
|
||||
*
|
||||
* Copyright (C) 2003 NVIDIA Corporation
|
||||
* Copyright (C) 2003-2013 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,
|
||||
@@ -16,35 +16,178 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses>.
|
||||
*
|
||||
* precompiled.h: common definitions for mkprecompiled and nvidia-installer's
|
||||
* precompiled kernel interface/module package format
|
||||
*
|
||||
* precompiled.h
|
||||
* The format of a precompiled kernel interface package is:
|
||||
*
|
||||
* the first 8 bytes are: "\aNVIDIA\a"
|
||||
*
|
||||
* the next 4 bytes (unsigned) are: version number of the package format
|
||||
*
|
||||
* the next 4 bytes (unsigned) are: the length of the version string (v)
|
||||
*
|
||||
* the next v bytes are the version string
|
||||
*
|
||||
* the next 4 bytes (unsigned) are: the length of the description (d)
|
||||
*
|
||||
* the next d bytes are the description
|
||||
*
|
||||
* the next 4 bytes (unsigned) are: the length of the proc version string (p)
|
||||
*
|
||||
* the next p bytes are the proc version string
|
||||
*
|
||||
* the next 4 bytes (unsigned) are: the number of files in this package (f)
|
||||
*
|
||||
* for each of the f packaged files:
|
||||
*
|
||||
* the first 4 bytes are: "FILE"
|
||||
*
|
||||
* the next 4 bytes (unsigned) are: the 0-indexed sequence number of this file
|
||||
*
|
||||
* the next 4 bytes (unsigned) are the file type:
|
||||
* 0: precompiled interface
|
||||
* 1: precompiled kernel module
|
||||
*
|
||||
* the next 4 bytes are an attribute mask:
|
||||
* 1: has detached signature
|
||||
* 2: has linked module CRC
|
||||
* 4: has embedded signature
|
||||
*
|
||||
* the next 4 bytes (unsigned) are: length of the file name (n)
|
||||
*
|
||||
* the next n bytes are the file name
|
||||
*
|
||||
* the next 4 bytes (unsigned) are: length of the linked module name (m)
|
||||
*
|
||||
* the next m bytes are the linked module name (for kernel interfaces only)
|
||||
*
|
||||
* the next 4 bytes (unsigned) are: length of the core object file name (o)
|
||||
*
|
||||
* the next o bytes are the core object file name (for kernel interfaces only)
|
||||
*
|
||||
* the next 4 bytes (unsigned) are: CRC of the packaged file
|
||||
*
|
||||
* the next 4 bytes (unsigned) are: size of the packaged file (l)
|
||||
*
|
||||
* the next l bytes is the packaged file
|
||||
*
|
||||
* the next 4 bytes (unsigned) are: CRC of the packaged file, again
|
||||
*
|
||||
* the next 4 bytes (unsigned) are: CRC of linked module, when appropriate;
|
||||
* undefined if "has linked module CRC" attribute is not set
|
||||
*
|
||||
* the next 4 bytes (unsigned) are: length of detached signature (s), when
|
||||
* appropriate; 0 if "has detached signature" attribute is not set
|
||||
*
|
||||
* the next (s) bytes are: detached signature
|
||||
*
|
||||
* the next 4 bytes (unsigned) are: the 0-indexed sequence number of this file
|
||||
*
|
||||
* the next 4 bytes are: "END."
|
||||
*/
|
||||
|
||||
#ifndef __NVIDIA_INSTALLER_PRECOMPILED_H__
|
||||
#define __NVIDIA_INSTALLER_PRECOMPILED_H__
|
||||
|
||||
#define OUTPUT_FILENAME "nv-linux.o"
|
||||
#define PRECOMPILED_PKG_CONSTANT_LENGTH (8 + /* precompiled package header */ \
|
||||
4 + /* package format version */ \
|
||||
4 + /* driver version string length */ \
|
||||
4 + /* description string length */ \
|
||||
4 + /* proc version string length */ \
|
||||
4) /* number of files */
|
||||
|
||||
typedef struct {
|
||||
|
||||
#define PRECOMPILED_PKG_HEADER "\aNVIDIA\a"
|
||||
|
||||
#define PRECOMPILED_PKG_VERSION 1
|
||||
|
||||
#define PRECOMPILED_FILE_CONSTANT_LENGTH (4 + /* precompiled file header */ \
|
||||
4 + /* file serial number */ \
|
||||
4 + /* file type */ \
|
||||
4 + /* attributes mask */ \
|
||||
4 + /* file name length */ \
|
||||
4 + /* linked module name length */ \
|
||||
4 + /* core object name length */ \
|
||||
4 + /* file crc */ \
|
||||
4 + /* file size */ \
|
||||
4 + /* redundant file crc */ \
|
||||
4 + /* linked module crc */ \
|
||||
4 + /* detached signature length */ \
|
||||
4 + /* redundant file serial number */ \
|
||||
4) /* precompiled file footer*/
|
||||
|
||||
#define PRECOMPILED_FILE_HEADER "FILE"
|
||||
#define PRECOMPILED_FILE_FOOTER "END."
|
||||
|
||||
enum {
|
||||
PRECOMPILED_FILE_TYPE_INTERFACE = 0,
|
||||
PRECOMPILED_FILE_TYPE_MODULE,
|
||||
};
|
||||
|
||||
enum {
|
||||
PRECOMPILED_FILE_HAS_DETACHED_SIGNATURE = 0,
|
||||
PRECOMPILED_FILE_HAS_LINKED_MODULE_CRC,
|
||||
PRECOMPILED_FILE_HAS_EMBEDDED_SIGNATURE,
|
||||
};
|
||||
|
||||
#define PRECOMPILED_ATTR(attr) (1 << PRECOMPILED_FILE_HAS_##attr)
|
||||
|
||||
typedef struct __precompiled_file_info {
|
||||
uint32 type;
|
||||
uint32 attributes;
|
||||
char *name;
|
||||
char *linked_module_name;
|
||||
char *core_object_name;
|
||||
uint32 crc;
|
||||
uint32 size;
|
||||
uint8 *data;
|
||||
uint32 linked_module_crc;
|
||||
uint32 signature_size;
|
||||
char *signature;
|
||||
} PrecompiledFileInfo;
|
||||
|
||||
typedef struct __precompiled_info {
|
||||
|
||||
uint32 package_size;
|
||||
char *version;
|
||||
char *proc_version_string;
|
||||
char *description;
|
||||
char *detached_signature;
|
||||
uint32 linked_module_crc;
|
||||
int num_files;
|
||||
PrecompiledFileInfo *files;
|
||||
|
||||
} PrecompiledInfo;
|
||||
|
||||
|
||||
char *read_proc_version(Options *op);
|
||||
char *read_proc_version(Options *op, const char *proc_mount_point);
|
||||
|
||||
PrecompiledInfo *get_precompiled_info(Options *op,
|
||||
const char *filename,
|
||||
const char *real_proc_version_string,
|
||||
const char *package_version);
|
||||
|
||||
PrecompiledFileInfo *precompiled_find_file(const PrecompiledInfo *info,
|
||||
const char *file);
|
||||
|
||||
int precompiled_file_unpack(Options *op, const PrecompiledFileInfo *fileInfo,
|
||||
const char *output_directory);
|
||||
int precompiled_unpack(Options *op, const PrecompiledInfo *info,
|
||||
const char *output_filename);
|
||||
|
||||
int precompiled_pack(const PrecompiledInfo *info, const char *package_filename);
|
||||
|
||||
PrecompiledInfo *precompiled_unpack(Options *op,
|
||||
const char *filename,
|
||||
const char *output_filename,
|
||||
const char *real_proc_version_string,
|
||||
const char *package_version);
|
||||
void free_precompiled(PrecompiledInfo *info);
|
||||
void free_precompiled_file_data(PrecompiledFileInfo fileInfo);
|
||||
int precompiled_read_interface(PrecompiledFileInfo *fileInfo,
|
||||
const char *filename,
|
||||
const char *linked_module_name,
|
||||
const char *core_object_name);
|
||||
int precompiled_read_module(PrecompiledFileInfo *fileInfo, const char *filename);
|
||||
void precompiled_append_files(PrecompiledInfo *info, PrecompiledFileInfo *files,
|
||||
int num_files);
|
||||
|
||||
const char *precompiled_file_type_name(uint32 file_type);
|
||||
const char **precompiled_file_attribute_names(uint32 attribute_mask);
|
||||
|
||||
int byte_tail(const char *infile, int start, char **buf);
|
||||
|
||||
#endif /* __NVIDIA_INSTALLER_PRECOMPILED_H__ */
|
||||
|
@@ -1 +1 @@
|
||||
NVIDIA_VERSION = 319.32
|
||||
NVIDIA_VERSION = 325.08
|
||||
|
Reference in New Issue
Block a user