555.42.02

This commit is contained in:
Aaron Plattner
2024-05-20 19:09:48 -07:00
parent ca6a568e83
commit b85cf6c52a
13 changed files with 825 additions and 227 deletions

View File

@@ -26,47 +26,46 @@
#include "conflicting-kernel-modules.h"
/*
* get_initramfs_path() - Test well-known locations for the existence of
* candidate initramfs files. If there is more than one candidate, prompt the
* user to select one of them. Returns the found (if one) or selected (if more
* than one found) file, or NULL if no file is found or the user declines to
* select one.
* find_initramfs_images() - Locate initramfs image files whose names conform
* to well-known patterns. Returns the number of located image files. If the
* caller supplies a pointer to an array of strings, the list of found images
* will be returned in a heap-allocated NULL-terminated list via that pointer.
*/
static char *get_initramfs_path(Options *op)
static int find_initramfs_images(Options *op, char ***found_paths)
{
static char *path_ret;
static int attempted;
char *kernel_name;
char *kernel_name = get_kernel_name(op);
int num_found_paths = 0;
if (attempted) {
/* This function has already been called: return the cached path value
* (which may be NULL if no path was found previously). */
return path_ret;
if (found_paths) {
*found_paths = NULL;
}
kernel_name = get_kernel_name(op);
if (kernel_name) {
int num_found_paths = 0, found_paths_size = 8;
int i;
char **found_paths = nvalloc(found_paths_size * sizeof(char*));
/* This must be at least two more than the number of times the
* __TEST_INITRAMFS_FILE macro is invoked below. One for a NULL
* terminator, and another for a "none of the above" option that
* may be added by a caller. */
const int found_paths_size = 8;
char *tmp;
if (found_paths) {
*found_paths = nvalloc(found_paths_size * sizeof(char*));
}
#define __TEST_INITRAMFS_FILE(format, str) { \
char *path = nvasprintf("/boot/" format, str); \
if (access(path, F_OK) == 0) { \
if (num_found_paths + 2 > found_paths_size) { \
found_paths_size *= 2; \
found_paths = nvrealloc(found_paths, \
found_paths_size * sizeof(char*)); \
if (found_paths && num_found_paths < found_paths_size - 2) { \
(*found_paths)[num_found_paths] = path; \
} \
found_paths[num_found_paths++] = path; \
num_found_paths++; \
} else { \
nvfree(path); \
} \
}
/* Don't forget to increase found_paths_size, if necessary, when
* adding additional templates. */
__TEST_INITRAMFS_FILE("initramfs-%s.img", kernel_name);
__TEST_INITRAMFS_FILE("initramfs-%s.img", "linux");
__TEST_INITRAMFS_FILE("initramfs-%s.img", "linux-lts");
@@ -95,35 +94,67 @@ static char *get_initramfs_path(Options *op)
nvfree(kernel_name_copy);
}
if (num_found_paths == 1) {
path_ret = found_paths[0];
} else if (num_found_paths > 1) {
int answer;
/* We ensured we have enough space in __TEST_INITRAMFS_FILE() */
found_paths[num_found_paths] = "Use none of these";
answer = ui_multiple_choice(op, (const char * const*)found_paths,
num_found_paths + 1, num_found_paths,
"More than one initramfs file found. "
"Which file would you like to use?");
if (answer < num_found_paths) {
/* answer == found_paths means the user opted out */
path_ret = found_paths[answer];
}
}
/* Clean up the paths that we're not returning */
for (i = 0; i < num_found_paths; i++) {
if (found_paths[i] != path_ret) {
nvfree(found_paths[i]);
}
}
nvfree(found_paths);
}
attempted = TRUE;
return num_found_paths;
}
/*
* get_initramfs_path() - Test well-known locations for the existence of
* candidate initramfs files. If there is more than one candidate, optionally
* prompt the user to select one of them. Returns the found (if one) or
* selected (if more than one found, and function is run interactively) file,
* or NULL if no file is found or multiple candidates exist and the user does
* not select one (either because the function is run non-interactively or the
* user declines to select one when prompted.
*/
static char *get_initramfs_path(Options *op, int interactive)
{
static char *path_ret = NULL;
static int attempted = FALSE;
int num_found_paths;
char **found_paths;
int i;
if (attempted) {
/* This function has already been called: return the cached path value
* (which may be NULL if no path was found previously). */
return path_ret;
}
num_found_paths = find_initramfs_images(op, &found_paths);
if (num_found_paths == 1) {
path_ret = found_paths[0];
} else if (num_found_paths > 1 && interactive) {
int answer;
/* We ensured we have enough space in find_initramfs_images() */
found_paths[num_found_paths] = "Use none of these";
answer = ui_multiple_choice(op, (const char * const*)found_paths,
num_found_paths + 1, num_found_paths,
"More than one initramfs file found. "
"Which file would you like to use?");
if (answer < num_found_paths) {
/* answer == found_paths means the user opted out */
path_ret = found_paths[answer];
}
}
/* Clean up the paths that we're not returning */
for (i = 0; i < num_found_paths; i++) {
if (found_paths[i] != path_ret) {
nvfree(found_paths[i]);
}
}
nvfree(found_paths);
/* If a path is not found in non-interactive mode, allow trying again in
* interactive mode later. */
attempted = path_ret || interactive;
return path_ret;
}
@@ -224,7 +255,7 @@ static int get_tool_index(Options *op, const InitramfsTool *tool)
return -1;
}
if (tool->requires_path && get_initramfs_path(op) == NULL) {
if (tool->requires_path && find_initramfs_images(op, NULL) == 0) {
return -1;
}
@@ -416,10 +447,12 @@ static int run_initramfs_tool(Options *op, int tool, char **data,
/* Run with only the initramfs path, if a kernel is not required. */
if (ret != 0 && !kernel_required) {
char *initramfs_path = get_initramfs_path(op, interactive);
if (data) {
nvfree(*data);
}
ret = initramfs_tool_helper(op, tool, NULL, get_initramfs_path(op),
ret = initramfs_tool_helper(op, tool, NULL, initramfs_path,
data, interactive);
}
@@ -434,11 +467,13 @@ static int run_initramfs_tool(Options *op, int tool, char **data,
/* Run with both the kernel and initramfs path. */
if (ret != 0) {
char *initramfs_path = get_initramfs_path(op, interactive);
if (data) {
nvfree(*data);
}
ret = initramfs_tool_helper(op, tool, get_kernel_name(op),
get_initramfs_path(op), data, interactive);
initramfs_path, data, interactive);
}
return ret;
@@ -447,18 +482,31 @@ static int run_initramfs_tool(Options *op, int tool, char **data,
static pthread_t scan_thread;
typedef struct {
/* Index into initramfs_tools[] for the initramfs scanning tool. A negative
* index indicates that no suitable tool was found. The index should be
* initialized with either the return value of find_initramfs_tool() or a
* negative value. */
int tool;
/* Flags to indicate the reults of an attempted initramfs scan. These flags
* should all be zero-initialized before the first scan attempt. */
/* Initramfs scan detected Nouveau in the initramfs */
int nouveau_ko_detected;
/* Initramfs scan detected NVIDIA kernel modules in the initramfs */
int nvidia_ko_detected;
int scan_attempted;
int scan_succeeded;
/* A non-interactive scan was attempted, but interaction is required to
* complete the scan (e.g. because the user needs to make a choice between
* more than one available candidate tool). */
int try_scan_again;
/* The initramfs was successfully scanned and the *_ko_detected flags can
* be trusted to accurately reflect the contents of the initramfs. */
int scan_complete;
} ScanThreadData;
static void scan_initramfs(Options *op, ScanThreadData *data, int interactive)
{
if (data->tool < 0) {
ui_log(op, "Unable to scan initramfs: no tool found");
} else {
if (data->tool >= 0) {
char *listing;
int ret;
@@ -466,8 +514,7 @@ static void scan_initramfs(Options *op, ScanThreadData *data, int interactive)
initramfs_tools[data->tool].name);
ret = run_initramfs_tool(op, data->tool, &listing, interactive);
data->scan_attempted = TRUE;
data->scan_succeeded = FALSE;
data->scan_complete = FALSE;
if (ret == 0) {
int i;
@@ -494,17 +541,22 @@ static void scan_initramfs(Options *op, ScanThreadData *data, int interactive)
}
}
data->scan_succeeded = TRUE;
data->scan_complete = TRUE;
}
nvfree(listing);
/* If the scan failed in non-interactive mode, we'll want to try again
* in interactive mode later. */
data->try_scan_again = !interactive && !data->scan_complete;
ui_log(op, "Initramfs scan %s.", ret == 0 ? "complete" : "failed");
} else {
ui_log(op, "Unable to scan initramfs: no tool found");
}
}
static void *initramfs_scan_worker(void *arg)
{
static ScanThreadData data;
static ScanThreadData data = {};
Options *op = arg;
data.tool = find_initramfs_tool(op, INITRAMFS_LIST_TOOL, NON_INTERACTIVE);
@@ -577,7 +629,7 @@ int update_initramfs(Options *op)
data_pointer = &data;
}
if (!data_pointer->scan_attempted) {
if (data_pointer->try_scan_again) {
data_pointer->tool = find_initramfs_tool(op, INITRAMFS_LIST_TOOL,
INTERACTIVE);
@@ -611,13 +663,13 @@ int update_initramfs(Options *op)
"condition(s):\n%s\n"
"Would you like to rebuild the "
"initramfs?", reason);
} else if (data_pointer->tool < 0 || !data_pointer->scan_succeeded) {
} else if (data_pointer->scan_complete) {
ui_log(op, "No NVIDIA modules detected in the initramfs.");
ret = TRUE;
} else {
rebuild = ui_multiple_choice(op, choices, 2, 0,
"%s Would you like to rebuild "
"the initramfs?", no_listing);
} else {
ui_log(op, "No NVIDIA modules detected in the initramfs.");
ret = TRUE;
}
if (rebuild) {
@@ -638,10 +690,10 @@ int update_initramfs(Options *op)
"due to the following condition(s):\n%s\n"
"Please consult your distribution's documentation for "
"instructions on how to rebuild the initramfs.", reason);
ret = TRUE;
} else if (data_pointer->tool < 0 || !data_pointer->scan_succeeded) {
ret = TRUE;
} else if (!data_pointer->scan_complete) {
ui_message(op, "%s", no_listing);
ret = TRUE;
ret = TRUE;
}
nvfree(reason);

View File

@@ -805,9 +805,31 @@ static Package *parse_manifest (Options *op)
if (op->kernel_module_build_directory_override) {
p->kernel_module_build_directory =
nvstrdup(op->kernel_module_build_directory_override);
op->kernel_module_build_directory_override;
op->kernel_module_build_directory_override = NULL;
} else {
p->kernel_module_build_directory = nvstrdup("kernel");
struct module_type_info types;
int num_types;
num_types = valid_kernel_module_types(op, &types);
if (num_types > 0) {
int selection;
if (num_types == 1) {
selection = 0;
} else {
selection = ui_multiple_choice(op, types.licenses, num_types,
types.default_entry,
"Multiple kernel module types are available for this "
"system. Which would you like to use?"
);
}
p->kernel_module_build_directory = nvstrdup(types.dirs[selection]);
} else {
p->kernel_module_build_directory = nvstrdup("kernel");
}
}
remove_trailing_slashes(p->kernel_module_build_directory);

206
kernel.c
View File

@@ -334,7 +334,6 @@ int determine_kernel_source_path(Options *op, Package *p)
int determine_kernel_output_path(Options *op)
{
char *str, *tmp;
int len;
/* check --kernel-output-path */
@@ -376,11 +375,19 @@ int determine_kernel_output_path(Options *op)
tmp = get_kernel_name(op);
if (tmp) {
str = nvstrcat("/lib/modules/", tmp, "/source", NULL);
len = strlen(str);
char *source_path, *build_source_path;
int len_source_path, len_build_source_path;
if (!strncmp(op->kernel_source_path, str, len)) {
nvfree(str);
source_path = nvstrcat("/lib/modules/", tmp, "/source", NULL);
len_source_path = strlen(source_path);
build_source_path = nvstrcat("/lib/modules/", tmp, "/build/source", NULL);
len_build_source_path = strlen(build_source_path);
if ((!strncmp(op->kernel_source_path, source_path, len_source_path)) ||
(!strncmp(op->kernel_source_path, build_source_path, len_build_source_path))) {
nvfree(source_path);
nvfree(build_source_path);
str = nvstrcat("/lib/modules/", tmp, "/build", NULL);
if (directory_exists(str)) {
@@ -388,7 +395,10 @@ int determine_kernel_output_path(Options *op)
return TRUE;
}
}
else {
nvfree(source_path);
nvfree(build_source_path);
}
nvfree(str);
}
@@ -2058,6 +2068,14 @@ static char *default_kernel_source_path(Options *op)
nvfree(str);
str = nvstrcat("/lib/modules/", tmp, "/build/source", NULL);
if (directory_exists(str)) {
return str;
}
nvfree(str);
str = nvstrcat("/lib/modules/", tmp, "/build", NULL);
if (directory_exists(str)) {
@@ -2646,3 +2664,179 @@ static int kernel_configuration_conflict(Options *op, Package *p,
return FALSE;
}
/* These values correspond to the initial letter which will be matched using the
* --kernel-module-type command line option. */
enum {
PROPRIETARY = 'p',
OPEN = 'o',
};
static struct {
char type;
char * const dir;
char * const license;
} kernel_module_types[NUM_KERNEL_MODULE_TYPES] = {
{ .type = PROPRIETARY, .dir = "kernel", .license = "NVIDIA Proprietary" },
{ .type = OPEN, .dir = "kernel-open", .license = "MIT/GPL" },
};
int valid_kernel_module_types(Options *op, struct module_type_info *info)
{
int num_valid_types = 0, i;
memset(info, 0, sizeof(*info));
for (i = 0; i < NUM_KERNEL_MODULE_TYPES; i++) {
if (op->open_modules.required) {
/* If at least one GPU requires the open modules, don't allow
* the proprietary ones. */
if (kernel_module_types[i].type == PROPRIETARY) {
continue;
}
if (op->open_modules.unsupported_gpu_present) {
ui_warn(op, "This system requires the open GPU kernel "
"modules, but contains GPUs which are not "
"supported by the open GPU kernel modules. "
"The unsupported GPUs will be ignored.");
}
} else if (!op->open_modules.supported_gpu_present ||
op->open_modules.unsupported_gpu_present) {
/* If GPUs do not support the open modules, mark them invalid:
* users can still forcibly install them via the command line */
if (kernel_module_types[i].type == OPEN) {
continue;
}
}
if (directory_exists(kernel_module_types[i].dir)) {
info->types[num_valid_types] = kernel_module_types[i].type;
info->dirs[num_valid_types] = kernel_module_types[i].dir;
info->licenses[num_valid_types] = kernel_module_types[i].license;
num_valid_types++;
}
}
if (num_valid_types == 0) {
ui_error(op, "This system requires a kernel module type which is "
"not present in this installer package.");
}
/* Return a default selection to the caller if multiple types are valid. */
if (num_valid_types > 1) {
char default_type = PROPRIETARY;
for (i = 0; i < num_valid_types; i++) {
if (info->types[i] == default_type) {
info->default_entry = i;
break;
}
}
if (i == num_valid_types) {
ui_warn(op, "An error occurred while selecting the default kernel "
"module type; using \"%s\" as the default.",
info->licenses[info->default_entry]);
}
}
return num_valid_types;
}
int override_kernel_module_build_directory(Options *op, const char *directory)
{
int i, num_types, ret = FALSE;
struct module_type_info types;
if (!directory_exists(directory)) {
ui_error(op, "The kernel module build directory '%s' is not present in "
"this installer package.", directory);
return FALSE;
}
num_types = valid_kernel_module_types(op, &types);
for (i = 0; i < num_types; i++) {
if (strcmp(directory, types.dirs[i]) == 0) {
ret = TRUE;
break;
}
}
if (ret) {
if (op->kernel_module_build_directory_override) {
/* If the override has already been set, make sure the value doesn't
* conflict with the one being set now. */
if (strcmp(op->kernel_module_build_directory_override, directory)) {
ui_error(op, "Conflicting options set the kernel module build "
"directory to both '%s' and '%s'. Please use only one.",
op->kernel_module_build_directory_override, directory);
ret = FALSE;
}
}
} else {
/* If we failed to match, check the full kernel module type list
* to see if there is a matching kernel module type that happens
* to be invalid for this package/system. */
for (i = 0; i < NUM_KERNEL_MODULE_TYPES; i++) {
if (strcmp(directory, kernel_module_types[i].dir) == 0) {
if (directory_exists(directory)) {
if (kernel_module_types[i].type == OPEN &&
op->open_modules.supported_gpu_present &&
op->open_modules.unsupported_gpu_present) {
ui_warn(op, "The open GPU kernel modules are supported "
"on some GPUs in this system, and unsupported "
"on others. The unsupported GPUs will be "
"ignored.");
} else {
ui_warn(op, "The '%s' kernel modules are incompatible "
"with the GPU(s) detected on this system. They "
"will be installed anyway, but are not "
"expected to work.",
kernel_module_types[i].license);
}
ret = TRUE;
} else {
ui_error(op, "The '%s' kernel modules are not "
"present in this installer package.",
kernel_module_types[i].license);
}
break;
}
}
if (i >= NUM_KERNEL_MODULE_TYPES) {
ui_error(op, "'%s' is not a valid kernel module directory.",
directory);
}
}
if (ret) {
op->kernel_module_build_directory_override = nvstrdup(directory);
}
return ret;
}
int override_kernel_module_type(Options *op, const char *type)
{
const char *directory = NULL;
int i;
for (i = 0; i < NUM_KERNEL_MODULE_TYPES; i++) {
if (tolower(type[0]) == kernel_module_types[i].type) {
directory = kernel_module_types[i].dir;
break;
}
}
if (!directory) {
ui_error(op, "'%s' is not a valid kernel module type.", type);
return FALSE;
}
return override_kernel_module_build_directory(op, directory);
}

View File

@@ -29,6 +29,15 @@ typedef enum {
KERNEL_CONFIG_OPTION_UNKNOWN
} KernelConfigOptionStatus;
#define NUM_KERNEL_MODULE_TYPES 2
struct module_type_info {
int default_entry;
char types[NUM_KERNEL_MODULE_TYPES];
const char *dirs[NUM_KERNEL_MODULE_TYPES];
const char *licenses[NUM_KERNEL_MODULE_TYPES];
};
int determine_kernel_module_installation_path (Options*);
int determine_kernel_source_path (Options*, Package*);
int determine_kernel_output_path (Options*);
@@ -57,6 +66,10 @@ int rmmod_kernel_module (Options*, const char *);
int conftest_sanity_check (Options*, const char *,
const char *, const char *);
char *precompiled_kernel_interface_path (const Package*);
int valid_kernel_module_types (Options*,
struct module_type_info*);
int override_kernel_module_build_directory (Options*, const char*);
int override_kernel_module_type (Options*, const char*);
#ifndef ENOKEY
#define ENOKEY 126 /* Required key not available */

231
misc.c
View File

@@ -45,7 +45,7 @@
#include "files.h"
#include "misc.h"
#include "crc.h"
#include "nvLegacy.h"
#include "nvGpus.h"
#include "manifest.h"
#include "nvpci-utils.h"
#include "conflicting-kernel-modules.h"
@@ -1671,7 +1671,7 @@ int check_for_running_x(Options *op)
* If device_id is present in the list of devIDs of pGPUs that don't support GSP
* on vGPU then return FALSE, else return TRUE.
*/
static int nvpci_dev_is_vgpu_gsp(Package *p, unsigned int device_id)
static int nvpci_dev_is_vgpu_gsp(unsigned int device_id)
{
unsigned short vgpu_non_gsp_dev_ids[] = {
0x13bd, // Tesla M10,
@@ -1729,7 +1729,6 @@ static int nvpci_dev_is_vgpu_gsp(Package *p, unsigned int device_id)
/* Check if this is vGPU host package */
if ((access("./is_vgpu_host_package.txt", F_OK) == 0) || (is_vgx_build == 1) ||
(is_vgx_kvm_build == 1)) {
/* If device_id is present in the non-gsp devId list, return FALSE */
for (i = 0; i < ARRAY_LEN(vgpu_non_gsp_dev_ids); i++) {
if (device_id == vgpu_non_gsp_dev_ids[i]) {
@@ -1741,6 +1740,118 @@ static int nvpci_dev_is_vgpu_gsp(Package *p, unsigned int device_id)
return FALSE;
}
/*
* pci_device_scan() - Use libpciaccess to iterate over all of the PCI devices
* on the system to look for legacy and feature-flagged devices. The results
* are stored in the pci_devices sub-struct of the Options structure to inform
* policy decisions and targeted messages later on in the installation process.
*/
void pci_device_scan(Options *op)
{
struct pci_device_iterator *iter;
struct pci_device *dev;
if (pci_system_init()) {
return;
}
iter = nvpci_find_gpu_by_vendor(NV_PCI_VENDOR_ID);
for (dev = pci_device_next(iter); dev; dev = pci_device_next(iter)) {
if (dev->device_id >= 0x0020 /* TNT or later */) {
int match = -1;
int i;
/*
* First check if this GPU is a "legacy" GPU; if it is, add it to
* the list of detected legacy devices.
*
* LegacyList only contains a row with a full 4-part ID (including
* subdevice and subvendor IDs) if its name differs from other
* devices with the same devid. For all other devices with the same
* devid and name, there is only one row, with subdevice and
* subvendor IDs set to 0.
*
* This loop finds the LegacyList entry for a matching 2-part devid,
* but continues searching for a matching 4-part ID (which would
* have a different name), and adds the list entry index to the
* running list of matched legacy devices.
*/
for (i = 0; i < ARRAY_LEN(LegacyList); i++) {
if (dev->device_id == LegacyList[i].uiDevId) {
int found_specific =
(dev->subvendor_id == LegacyList[i].uiSubVendorId &&
dev->subdevice_id == LegacyList[i].uiSubDevId);
if (found_specific || LegacyList[i].uiSubDevId == 0) {
match = i;
}
if (found_specific) {
break;
}
}
}
/* A non-negative index indicates a match found in the LegacyList
* table; otherwise, this GPU is a non-legacy device. */
if (match >= 0) {
int already_matched = FALSE;
if (op->pci_devices.num_legacy >=
ARRAY_LEN(op->pci_devices.legacy)) {
continue;
}
for (i = 0; i < op->pci_devices.num_legacy; i++) {
if (match == op->pci_devices.legacy[i]) {
already_matched = TRUE;
break;
}
}
if (!already_matched) {
op->pci_devices.legacy[op->pci_devices.num_legacy] = match;
op->pci_devices.num_legacy++;
}
} else {
op->pci_devices.found_supported = TRUE;
if (nvpci_dev_is_vga(dev)) {
op->pci_devices.found_vga = TRUE;
}
if (pci_devid_is_self_hosted(dev->device_id) ||
nvpci_dev_is_vgpu_gsp(dev->device_id)) {
op->open_modules.required = TRUE;
op->open_modules.supported_gpu_present = TRUE;
} else {
/* Assume the device has GSP unless flags say otherwise */
int device_has_gsp = TRUE;
for (i = 0; i < ARRAY_LEN(GpuFlagList); i++) {
if (dev->device_id == GpuFlagList[i].devId) {
if (GpuFlagList[i].flags & GPU_FLAGS_NO_GSP) {
device_has_gsp = FALSE;
}
break;
}
}
if (device_has_gsp) {
op->open_modules.supported_gpu_present = TRUE;
} else {
op->open_modules.unsupported_gpu_present = TRUE;
}
}
}
}
}
pci_system_cleanup();
}
/*
* check_for_nvidia_graphics_devices() - check if there are supported
* NVIDIA graphics devices installed in this system. If no supported devices
@@ -1752,97 +1863,38 @@ static int nvpci_dev_is_vgpu_gsp(Package *p, unsigned int device_id)
void check_for_nvidia_graphics_devices(Options *op, Package *p)
{
struct pci_device_iterator *iter;
struct pci_device *dev;
int i, found_supported_device = FALSE, found_self_hosted = FALSE;
int found_vga_device = FALSE, found_vgpu_gsp = FALSE, count = 0;
if (op->pci_devices.num_legacy > 0) {
char *list = nvstrdup("\n");
int i;
if (pci_system_init()) {
return;
}
for (i = 0; i < op->pci_devices.num_legacy; i++) {
const LEGACY_INFO *info = &LegacyList[op->pci_devices.legacy[i]];
char *old_list = list;
int j;
iter = nvpci_find_gpu_by_vendor(NV_PCI_VENDOR_ID);
for (dev = pci_device_next(iter); dev; dev = pci_device_next(iter), count++) {
if (dev->device_id >= 0x0020 /* TNT or later */) {
/*
* First check if this GPU is a "legacy" GPU; if it is, print a
* warning message and point the user to the NVIDIA Linux
* driver download page for.
*
* LegacyList only contains a row with a full 4-part ID (including
* subdevice and subvendor IDs) if its name differs from other
* devices with the same devid. For all other devices with the same
* devid and name, there is only one row, with subdevice and
* subvendor IDs set to 0.
*
* This loop finds the name for the matching devid, but continues
* searching for a matching 4-part ID with a different name, and
* breaks if it finds one.
*/
int found_legacy_device = FALSE;
unsigned int branch = 0;
const char *dev_name = NULL;
for (i = 0; i < sizeof(LegacyList) / sizeof(LEGACY_INFO); i++) {
if (dev->device_id == LegacyList[i].uiDevId) {
int found_specific =
(dev->subvendor_id == LegacyList[i].uiSubVendorId &&
dev->subdevice_id == LegacyList[i].uiSubDevId);
if (found_specific || LegacyList[i].uiSubDevId == 0) {
branch = LegacyList[i].branch;
dev_name = LegacyList[i].AdapterString;
found_legacy_device = TRUE;
}
if (found_specific) {
break;
}
for (j = 0; j < ARRAY_LEN(LegacyStrings); j++) {
if (LegacyStrings[j].branch == info->branch) {
break;
}
}
if (found_legacy_device) {
int j, nstrings;
const char *branch_string = "";
nstrings = sizeof(LegacyStrings) / sizeof(LEGACY_STRINGS);
for (j = 0; j < nstrings; j++) {
if (LegacyStrings[j].branch == branch) {
branch_string = LegacyStrings[j].description;
break;
}
}
if (j >= ARRAY_LEN(LegacyStrings)) continue;
ui_warn(op, "The NVIDIA %s GPU installed in this system is supported "
"through the NVIDIA %s legacy Linux graphics drivers. Please "
"visit http://www.nvidia.com/object/unix.html for more "
"information. The %s NVIDIA Linux graphics driver will "
"ignore this GPU.",
dev_name,
branch_string,
p->version);
} else {
found_supported_device = TRUE;
if (nvpci_dev_is_vga(dev)) {
found_vga_device = TRUE;
}
if (pci_devid_is_self_hosted(dev->device_id)) {
found_self_hosted = TRUE;
}
/* Check the first device in the system is vGPU GSP supported device */
if ((count == 0) && nvpci_dev_is_vgpu_gsp(p, dev->device_id)) {
found_vgpu_gsp = TRUE;
}
}
list = nvstrcat(list, info->AdapterString, " requires ",
LegacyStrings[j].description, "\n", NULL);
nvfree(old_list);
}
ui_warn(op, "The following NVIDIA GPUs are supported through NVIDIA "
"legacy Linux graphics drivers and will be ignored by the "
"NVIDIA %s Linux graphics driver:\n%s\nPlease visit "
"https://www.nvidia.com/object/unix.html for more "
"information.", p->version, list);
nvfree(list);
}
pci_system_cleanup();
if (!found_supported_device) {
if (!op->pci_devices.found_supported) {
/* Don't test-load the modules on a system with no supported devices */
op->skip_module_load = TRUE;
@@ -1853,15 +1905,8 @@ void check_for_nvidia_graphics_devices(Options *op, Package *p)
"driver download page at www.nvidia.com.", p->version);
}
if (!found_vga_device)
if (!op->pci_devices.found_vga)
op->no_nvidia_xconfig_question = TRUE;
if ((found_self_hosted || found_vgpu_gsp) && !op->kernel_module_build_directory_override) {
ui_log(op, "This system requires use of the NVIDIA open kernel "
"modules; these will be selected by default.");
nvfree(p->kernel_module_build_directory);
p->kernel_module_build_directory = nvstrdup("kernel-open");
}
} /* check_for_nvidia_graphics_devices() */

1
misc.h
View File

@@ -93,6 +93,7 @@ int check_installed_file(Options*, const char*, const mode_t, const uint32,
ui_message_func *logwarn);
int check_for_running_x(Options *op);
void query_xorg_version(Options *op);
void pci_device_scan(Options *op);
void check_for_nvidia_graphics_devices(Options *op, Package *p);
int run_nvidia_xconfig(Options *op, int restore, const char *question, int answer);
HookScriptStatus run_distro_hook(Options *op, const char *hook);

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2006, 2012, 2014 NVIDIA Corporation
* Copyright (c) 2005, 2006, 2012, 2014, 2023 NVIDIA Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -21,8 +21,8 @@
* SOFTWARE.
*/
#ifndef __NV_LEGACY_H
#define __NV_LEGACY_H
#ifndef __NV_GPUS_H
#define __NV_GPUS_H
typedef struct _LEGACY_INFO {
unsigned int uiDevId;
@@ -32,6 +32,13 @@ typedef struct _LEGACY_INFO {
char* AdapterString;
} LEGACY_INFO;
enum { GPU_FLAGS_NO_GSP = 1 << 0, };
typedef struct _GPU_FLAGS {
unsigned short devId;
unsigned short flags;
} GPU_FLAGS;
typedef struct _LEGACY_STRINGS {
unsigned int branch;
char* description;
@@ -1243,4 +1250,169 @@ static const LEGACY_INFO LegacyList[] = {
{ 0x12BA, 0x0000, 0x0000, 8, "Quadro K510M" }
};
#endif /* __NV_LEGACY_H */
// This is the list of feature flags for current GPUs
// Only two-part IDs for GPUs with non-zero flags are tracked
static const GPU_FLAGS GpuFlagList[] = {
// PCI-ID Flags
{ 0x1340, GPU_FLAGS_NO_GSP },
{ 0x1341, GPU_FLAGS_NO_GSP },
{ 0x1344, GPU_FLAGS_NO_GSP },
{ 0x1346, GPU_FLAGS_NO_GSP },
{ 0x1347, GPU_FLAGS_NO_GSP },
{ 0x1348, GPU_FLAGS_NO_GSP },
{ 0x1349, GPU_FLAGS_NO_GSP },
{ 0x134b, GPU_FLAGS_NO_GSP },
{ 0x134d, GPU_FLAGS_NO_GSP },
{ 0x134e, GPU_FLAGS_NO_GSP },
{ 0x134f, GPU_FLAGS_NO_GSP },
{ 0x137a, GPU_FLAGS_NO_GSP },
{ 0x137b, GPU_FLAGS_NO_GSP },
{ 0x1380, GPU_FLAGS_NO_GSP },
{ 0x1381, GPU_FLAGS_NO_GSP },
{ 0x1382, GPU_FLAGS_NO_GSP },
{ 0x1390, GPU_FLAGS_NO_GSP },
{ 0x1391, GPU_FLAGS_NO_GSP },
{ 0x1392, GPU_FLAGS_NO_GSP },
{ 0x1393, GPU_FLAGS_NO_GSP },
{ 0x1398, GPU_FLAGS_NO_GSP },
{ 0x1399, GPU_FLAGS_NO_GSP },
{ 0x139a, GPU_FLAGS_NO_GSP },
{ 0x139b, GPU_FLAGS_NO_GSP },
{ 0x139c, GPU_FLAGS_NO_GSP },
{ 0x139d, GPU_FLAGS_NO_GSP },
{ 0x13b0, GPU_FLAGS_NO_GSP },
{ 0x13b1, GPU_FLAGS_NO_GSP },
{ 0x13b2, GPU_FLAGS_NO_GSP },
{ 0x13b3, GPU_FLAGS_NO_GSP },
{ 0x13b4, GPU_FLAGS_NO_GSP },
{ 0x13b6, GPU_FLAGS_NO_GSP },
{ 0x13b9, GPU_FLAGS_NO_GSP },
{ 0x13ba, GPU_FLAGS_NO_GSP },
{ 0x13bb, GPU_FLAGS_NO_GSP },
{ 0x13bc, GPU_FLAGS_NO_GSP },
{ 0x13c0, GPU_FLAGS_NO_GSP },
{ 0x13c2, GPU_FLAGS_NO_GSP },
{ 0x13d7, GPU_FLAGS_NO_GSP },
{ 0x13d8, GPU_FLAGS_NO_GSP },
{ 0x13d9, GPU_FLAGS_NO_GSP },
{ 0x13da, GPU_FLAGS_NO_GSP },
{ 0x13f0, GPU_FLAGS_NO_GSP },
{ 0x13f1, GPU_FLAGS_NO_GSP },
{ 0x13f2, GPU_FLAGS_NO_GSP },
{ 0x13f3, GPU_FLAGS_NO_GSP },
{ 0x13f8, GPU_FLAGS_NO_GSP },
{ 0x13f9, GPU_FLAGS_NO_GSP },
{ 0x13fa, GPU_FLAGS_NO_GSP },
{ 0x13fb, GPU_FLAGS_NO_GSP },
{ 0x1401, GPU_FLAGS_NO_GSP },
{ 0x1402, GPU_FLAGS_NO_GSP },
{ 0x1406, GPU_FLAGS_NO_GSP },
{ 0x1407, GPU_FLAGS_NO_GSP },
{ 0x1427, GPU_FLAGS_NO_GSP },
{ 0x1430, GPU_FLAGS_NO_GSP },
{ 0x1431, GPU_FLAGS_NO_GSP },
{ 0x1436, GPU_FLAGS_NO_GSP },
{ 0x15f0, GPU_FLAGS_NO_GSP },
{ 0x15f7, GPU_FLAGS_NO_GSP },
{ 0x15f8, GPU_FLAGS_NO_GSP },
{ 0x15f9, GPU_FLAGS_NO_GSP },
{ 0x1617, GPU_FLAGS_NO_GSP },
{ 0x1618, GPU_FLAGS_NO_GSP },
{ 0x1619, GPU_FLAGS_NO_GSP },
{ 0x161a, GPU_FLAGS_NO_GSP },
{ 0x1667, GPU_FLAGS_NO_GSP },
{ 0x174d, GPU_FLAGS_NO_GSP },
{ 0x174e, GPU_FLAGS_NO_GSP },
{ 0x179c, GPU_FLAGS_NO_GSP },
{ 0x17c2, GPU_FLAGS_NO_GSP },
{ 0x17c8, GPU_FLAGS_NO_GSP },
{ 0x17f0, GPU_FLAGS_NO_GSP },
{ 0x17f1, GPU_FLAGS_NO_GSP },
{ 0x17fd, GPU_FLAGS_NO_GSP },
{ 0x1b00, GPU_FLAGS_NO_GSP },
{ 0x1b02, GPU_FLAGS_NO_GSP },
{ 0x1b06, GPU_FLAGS_NO_GSP },
{ 0x1b30, GPU_FLAGS_NO_GSP },
{ 0x1b38, GPU_FLAGS_NO_GSP },
{ 0x1b80, GPU_FLAGS_NO_GSP },
{ 0x1b81, GPU_FLAGS_NO_GSP },
{ 0x1b82, GPU_FLAGS_NO_GSP },
{ 0x1b83, GPU_FLAGS_NO_GSP },
{ 0x1b84, GPU_FLAGS_NO_GSP },
{ 0x1b87, GPU_FLAGS_NO_GSP },
{ 0x1ba0, GPU_FLAGS_NO_GSP },
{ 0x1ba1, GPU_FLAGS_NO_GSP },
{ 0x1ba2, GPU_FLAGS_NO_GSP },
{ 0x1bb0, GPU_FLAGS_NO_GSP },
{ 0x1bb1, GPU_FLAGS_NO_GSP },
{ 0x1bb4, GPU_FLAGS_NO_GSP },
{ 0x1bb5, GPU_FLAGS_NO_GSP },
{ 0x1bb6, GPU_FLAGS_NO_GSP },
{ 0x1bb7, GPU_FLAGS_NO_GSP },
{ 0x1bb8, GPU_FLAGS_NO_GSP },
{ 0x1bb9, GPU_FLAGS_NO_GSP },
{ 0x1bbb, GPU_FLAGS_NO_GSP },
{ 0x1bc7, GPU_FLAGS_NO_GSP },
{ 0x1be0, GPU_FLAGS_NO_GSP },
{ 0x1be1, GPU_FLAGS_NO_GSP },
{ 0x1c02, GPU_FLAGS_NO_GSP },
{ 0x1c03, GPU_FLAGS_NO_GSP },
{ 0x1c04, GPU_FLAGS_NO_GSP },
{ 0x1c06, GPU_FLAGS_NO_GSP },
{ 0x1c07, GPU_FLAGS_NO_GSP },
{ 0x1c09, GPU_FLAGS_NO_GSP },
{ 0x1c20, GPU_FLAGS_NO_GSP },
{ 0x1c21, GPU_FLAGS_NO_GSP },
{ 0x1c22, GPU_FLAGS_NO_GSP },
{ 0x1c23, GPU_FLAGS_NO_GSP },
{ 0x1c30, GPU_FLAGS_NO_GSP },
{ 0x1c31, GPU_FLAGS_NO_GSP },
{ 0x1c60, GPU_FLAGS_NO_GSP },
{ 0x1c61, GPU_FLAGS_NO_GSP },
{ 0x1c62, GPU_FLAGS_NO_GSP },
{ 0x1c81, GPU_FLAGS_NO_GSP },
{ 0x1c82, GPU_FLAGS_NO_GSP },
{ 0x1c83, GPU_FLAGS_NO_GSP },
{ 0x1c8c, GPU_FLAGS_NO_GSP },
{ 0x1c8d, GPU_FLAGS_NO_GSP },
{ 0x1c8f, GPU_FLAGS_NO_GSP },
{ 0x1c90, GPU_FLAGS_NO_GSP },
{ 0x1c91, GPU_FLAGS_NO_GSP },
{ 0x1c92, GPU_FLAGS_NO_GSP },
{ 0x1c94, GPU_FLAGS_NO_GSP },
{ 0x1c96, GPU_FLAGS_NO_GSP },
{ 0x1cb1, GPU_FLAGS_NO_GSP },
{ 0x1cb2, GPU_FLAGS_NO_GSP },
{ 0x1cb3, GPU_FLAGS_NO_GSP },
{ 0x1cb6, GPU_FLAGS_NO_GSP },
{ 0x1cba, GPU_FLAGS_NO_GSP },
{ 0x1cbb, GPU_FLAGS_NO_GSP },
{ 0x1cbc, GPU_FLAGS_NO_GSP },
{ 0x1cbd, GPU_FLAGS_NO_GSP },
{ 0x1cfa, GPU_FLAGS_NO_GSP },
{ 0x1cfb, GPU_FLAGS_NO_GSP },
{ 0x1d01, GPU_FLAGS_NO_GSP },
{ 0x1d02, GPU_FLAGS_NO_GSP },
{ 0x1d10, GPU_FLAGS_NO_GSP },
{ 0x1d11, GPU_FLAGS_NO_GSP },
{ 0x1d12, GPU_FLAGS_NO_GSP },
{ 0x1d13, GPU_FLAGS_NO_GSP },
{ 0x1d16, GPU_FLAGS_NO_GSP },
{ 0x1d33, GPU_FLAGS_NO_GSP },
{ 0x1d34, GPU_FLAGS_NO_GSP },
{ 0x1d52, GPU_FLAGS_NO_GSP },
{ 0x1d81, GPU_FLAGS_NO_GSP },
{ 0x1db1, GPU_FLAGS_NO_GSP },
{ 0x1db3, GPU_FLAGS_NO_GSP },
{ 0x1db4, GPU_FLAGS_NO_GSP },
{ 0x1db5, GPU_FLAGS_NO_GSP },
{ 0x1db6, GPU_FLAGS_NO_GSP },
{ 0x1db7, GPU_FLAGS_NO_GSP },
{ 0x1db8, GPU_FLAGS_NO_GSP },
{ 0x1dba, GPU_FLAGS_NO_GSP },
{ 0x1df0, GPU_FLAGS_NO_GSP },
{ 0x1df2, GPU_FLAGS_NO_GSP },
{ 0x1df6, GPU_FLAGS_NO_GSP },
};
#endif /* __NV_GPUS_H */

View File

@@ -46,6 +46,7 @@
#include "manifest.h"
#include "initramfs.h"
static void print_version(void);
static void print_help(const char* name, int is_uninstall, int advanced);
@@ -258,7 +259,7 @@ static void parse_commandline(int argc, char *argv[], Options *op)
break;
case 'j':
if (intval < 1) {
nv_error_msg("Invalid concurrency level %d: nvidia-installer "
ui_error(op, "Invalid concurrency level %d: nvidia-installer "
"will attempt to autodetect the number of CPUs.",
intval);
intval = 0;
@@ -336,13 +337,13 @@ static void parse_commandline(int argc, char *argv[], Options *op)
op->nvidia_modprobe = FALSE; break;
case FORCE_TLS_OPTION:
/* This option is no longer used; ignore it. */
nv_warning_msg("The '--force-tls' option is deprecated: "
"nvidia-installer will ignore this option.");
ui_warn(op, "The '--force-tls' option is deprecated: "
"nvidia-installer will ignore this option.");
break;
case FORCE_TLS_COMPAT32_OPTION:
/* This option is no longer used; ignore it. */
nv_warning_msg("The '--force-tls-compat32' option is deprecated: "
"nvidia-installer will ignore this option.");
ui_warn(op, "The '--force-tls-compat32' option is deprecated: "
"nvidia-installer will ignore this option.");
break;
case SANITY_OPTION:
op->sanity = TRUE;
@@ -359,13 +360,13 @@ static void parse_commandline(int argc, char *argv[], Options *op)
break;
case NO_RUNLEVEL_CHECK_OPTION:
/* This option is no longer used; ignore it. */
nv_warning_msg("The '--no-runlevel-check' option is deprecated: "
"nvidia-installer will ignore this option.");
ui_warn(op, "The '--no-runlevel-check' option is deprecated: "
"nvidia-installer will ignore this option.");
break;
case 'N':
/* This option is no longer used; ignore it. */
nv_warning_msg("The '--no-network' option is deprecated: "
"nvidia-installer will ignore this option.");
ui_warn(op, "The '--no-network' option is deprecated: "
"nvidia-installer will ignore this option.");
break;
case PRECOMPILED_KERNEL_INTERFACES_PATH_OPTION:
op->precompiled_kernel_interfaces_path = strval;
@@ -385,7 +386,7 @@ static void parse_commandline(int argc, char *argv[], Options *op)
else if (strcasecmp(strval, "no") == 0)
op->selinux_option = SELINUX_FORCE_NO;
else if (strcasecmp(strval, "default")) {
nv_error_msg("Invalid parameter for '--force-selinux'");
ui_error(op, "Invalid parameter for '--force-selinux'");
goto fail;
}
break;
@@ -446,7 +447,7 @@ static void parse_commandline(int argc, char *argv[], Options *op)
break;
case INSTALL_VDPAU_WRAPPER_OPTION:
if (boolval) {
nv_error_msg("This driver package does not contain a "
ui_error(op, "This driver package does not contain a "
"pre-compiled copy of libvdpau. Please see the "
"README for instructions on how to install "
"libvdpau.");
@@ -478,12 +479,12 @@ static void parse_commandline(int argc, char *argv[], Options *op)
case GLVND_GLX_CLIENT_OPTION:
/* This option is no longer used */
if (!boolval) {
nv_error_msg("The --no-glvnd-glx-client option is no longer supported");
ui_error(op, "The --no-glvnd-glx-client option is no longer supported");
goto fail;
}
nv_warning_msg("The '--glvnd-glx-client' option is deprecated: "
"nvidia-installer will ignore this option.");
ui_warn(op, "The '--glvnd-glx-client' option is deprecated: "
"nvidia-installer will ignore this option.");
break;
case GLVND_EGL_CONFIG_FILE_PATH_OPTION:
op->libglvnd_json_path = strval;
@@ -491,12 +492,12 @@ static void parse_commandline(int argc, char *argv[], Options *op)
case GLVND_EGL_CLIENT_OPTION:
/* This option is no longer used */
if (!boolval) {
nv_error_msg("The --no-glvnd-egl-client option is no longer supported");
ui_error(op, "The --no-glvnd-egl-client option is no longer supported");
goto fail;
}
nv_warning_msg("The '--glvnd-egl-client' option is deprecated: "
"nvidia-installer will ignore this option.");
ui_warn(op, "The '--glvnd-egl-client' option is deprecated: "
"nvidia-installer will ignore this option.");
break;
case EGL_EXTERNAL_PLATFORM_CONFIG_FILE_PATH_OPTION:
op->external_platform_json_path = strval;
@@ -523,7 +524,14 @@ static void parse_commandline(int argc, char *argv[], Options *op)
op->systemd_sysconf_prefix = strval;
break;
case 'm':
op->kernel_module_build_directory_override = strval;
if (!override_kernel_module_build_directory(op, strval)) {
goto fail;
}
break;
case 'M':
if (!override_kernel_module_type(op, strval)) {
goto fail;
}
break;
case ALLOW_INSTALLATION_WITH_RUNNING_DRIVER_OPTION:
op->allow_installation_with_running_driver = boolval;
@@ -584,7 +592,7 @@ static void parse_commandline(int argc, char *argv[], Options *op)
return;
fail:
nv_error_msg("Invalid commandline, please run `%s --help` "
ui_error(op, "Invalid commandline, please run `%s --help` "
"for usage information.", argv[0]);
nvfree((void*)op);
exit(1);
@@ -611,7 +619,10 @@ int main(int argc, char *argv[])
fprintf(stderr, "\nOut of memory error.\n\n");
return 1;
}
/* check for supported PCI devices */
pci_device_scan(op);
/* parse the commandline options */
parse_commandline(argc, argv, op);

View File

@@ -315,6 +315,26 @@ typedef struct __options {
int status_active;
IndeterminateData *indeterminate_data;
} ui;
struct {
unsigned int found_supported :1;
unsigned int found_vga :1;
int num_legacy;
int legacy[16];
} pci_devices;
struct {
unsigned int required :1;
unsigned int supported_gpu_present :1;
unsigned int unsupported_gpu_present :1;
} open_modules;
int num_ui_deferred_messages;
struct {
int level;
char *message;
} *ui_deferred_messages;
} Options;
typedef enum {

View File

@@ -715,11 +715,18 @@ static const NVGetoptOption __options[] = {
"install these symlinks, or '/etc/systemd/system' if pkg-config is not "
"available. Ignored if --no-systemd is specified." },
{ "kernel-module-type", 'M',
NVGETOPT_STRING_ARGUMENT, NULL,
"The type of kernel modules to build and install. Valid values are "
"\"open\" and \"proprietary\"."
},
{ "kernel-module-build-directory", 'm',
NVGETOPT_STRING_ARGUMENT, NULL,
"The path within the driver package that contains the kernel module "
"build files is normally 'kernel/'. This option can be used to "
"override this value." },
"Directly set the directory within the package from which to build the "
"kernel modules. This option is deprecated; use \"--kernel-module-type\" "
"instead."
},
{ "allow-installation-with-running-driver",
ALLOW_INSTALLATION_WITH_RUNNING_DRIVER_OPTION, NVGETOPT_IS_BOOLEAN, NULL,

View File

@@ -88,6 +88,23 @@ const char * const CONTINUE_ABORT_CHOICES[] = {
[ABORT_CHOICE] = "Abort installation"
};
static const char *level_str(int level)
{
switch (level) {
case NV_MSG_LEVEL_ERROR: return "ERROR: ";
case NV_MSG_LEVEL_WARNING: return "WARNING: ";
default: return NV_BULLET_STR;
}
}
static void do_print_message(Options *op, int level, const char *msg)
{
/* Print all warnings/errors; only print normal messages when not silent */
if (level != NV_MSG_LEVEL_MESSAGE || !op->silent) {
__ui->message(op, level, msg);
}
}
/*
* ui_init() - initialize the user interface; we start by looping over
* each of the possible ui shared libs (gtk, ncurses) until we find
@@ -196,6 +213,25 @@ int ui_init(Options *op)
signal(SIGILL, ui_signal_handler);
signal(SIGBUS, ui_signal_handler);
for (i = 0; i < op->num_ui_deferred_messages; i++) {
/* Deferred message was already printed to stdout/stderr; don't print
* it again if we're using the stream UI. */
if (__ui != &stream_ui_dispatch_table) {
do_print_message(op, op->ui_deferred_messages[i].level,
op->ui_deferred_messages[i].message);
}
/* Message was deferred before the log was initialized; log it now. */
log_printf(op, level_str(op->ui_deferred_messages[i].level), "%s",
op->ui_deferred_messages[i].message);
nvfree(op->ui_deferred_messages[i].message);
}
nvfree(op->ui_deferred_messages);
op->ui_deferred_messages = NULL;
op->num_ui_deferred_messages = 0;
/* so far, so good */
return TRUE;
@@ -251,55 +287,77 @@ char *ui_get_input(Options *op, const char *def, const char *fmt, ...)
} /* ui_get_input() */
static void defer_message(Options *op, int level, const char *message)
{
int i = op->num_ui_deferred_messages;
op->num_ui_deferred_messages++;
op->ui_deferred_messages = nvrealloc(op->ui_deferred_messages,
op->num_ui_deferred_messages *
sizeof(op->ui_deferred_messages[0]));
op->ui_deferred_messages[i].level = level;
op->ui_deferred_messages[i].message = nvstrdup(message);
/* Print the message to stdout/stderr right away, so it can be displayed
* even if ui_init() is never called. */
switch (level) {
case NV_MSG_LEVEL_ERROR:
nv_error_msg("%s", message);
break;
case NV_MSG_LEVEL_WARNING:
nv_warning_msg("%s", message);
break;
default:
if (!op->silent) {
nv_info_msg(NULL, "%s", message);
}
break;
}
}
static void message_helper(Options *op, int level, const char *msg)
{
if (__ui) {
do_print_message(op, level, msg);
log_printf(op, level_str(level), "%s", msg);
} else {
defer_message(op, level, msg);
}
}
/*
* ui_error() - have the ui display an error message
* ui_{error,warn,message}() - have the ui display a message
*/
void ui_error(Options *op, const char *fmt, ...)
{
char *msg;
NV_VSNPRINTF(msg, fmt);
__ui->message(op, NV_MSG_LEVEL_ERROR, msg);
log_printf(op, "ERROR: ", "%s", msg);
message_helper(op, NV_MSG_LEVEL_ERROR, msg);
free(msg);
} /* ui_error() */
}
void ui_warn(Options *op, const char *fmt, ...)
{
char *msg;
NV_VSNPRINTF(msg, fmt);
__ui->message(op, NV_MSG_LEVEL_WARNING, msg);
log_printf(op, "WARNING: ", "%s", msg);
message_helper(op, NV_MSG_LEVEL_WARNING, msg);
free(msg);
} /* ui_error() */
}
void ui_message(Options *op, const char *fmt, ...)
{
char *msg;
NV_VSNPRINTF(msg, fmt);
if (!op->silent) __ui->message(op, NV_MSG_LEVEL_MESSAGE, msg);
log_printf(op, NV_BULLET_STR, "%s", msg);
message_helper(op, NV_MSG_LEVEL_MESSAGE, msg);
free(msg);
} /* ui_message() */
}
void ui_log(Options *op, const char *fmt, ...)
@@ -308,7 +366,7 @@ void ui_log(Options *op, const char *fmt, ...)
NV_VSNPRINTF(msg, fmt);
if (!op->silent) __ui->message(op, NV_MSG_LEVEL_LOG, msg);
if (__ui && !op->silent) __ui->message(op, NV_MSG_LEVEL_LOG, msg);
log_printf(op, NV_BULLET_STR, "%s", msg);
free(msg);

View File

@@ -49,6 +49,9 @@ EXTRA_CFLAGS ?=
STACK_USAGE_WARNING ?=
CFLAGS += $(if $(STACK_USAGE_WARNING),-Wstack-usage=$(STACK_USAGE_WARNING))
IMPLICIT_FALLTHROUGH_WARNING ?=
CFLAGS += $(if $(IMPLICIT_FALLTHROUGH_WARNING),-Wimplicit-fallthrough=$(IMPLICIT_FALLTHROUGH_WARNING))
HOST_CC ?= $(CC)
HOST_LD ?= $(LD)
HOST_CFLAGS ?= $(CFLAGS)

View File

@@ -1,4 +1,4 @@
NVIDIA_VERSION = 550.78
NVIDIA_VERSION = 555.42.02
# This file.
VERSION_MK_FILE := $(lastword $(MAKEFILE_LIST))