├── version.mk ├── COPYING ├── gen-manpage-opts.c ├── README ├── common-utils ├── gen-manpage-opts-helper.h ├── nvpci-utils.h ├── src.mk ├── nvpci-utils.c ├── common-utils.h ├── msg.h ├── gen-manpage-opts-helper.c ├── nvgetopt.h ├── msg.c ├── nvgetopt.c └── common-utils.c ├── init ├── systemd │ └── nvidia-persistenced.service.template ├── upstart │ └── nvidia-persistenced.conf.template ├── README └── sysv │ └── nvidia-persistenced.template ├── nvidia-numa.h ├── nvpd_defs.h ├── nvidia-syslog-utils.h ├── nv-ioctl-numbers.h ├── nvpd_rpc_xdr.c ├── dist-files.mk ├── nvidia-syslog-utils.c ├── nvidia-persistenced.h ├── nv-ioctl-numa.h ├── nvpd_rpc_server.c ├── nvidia-persistenced.1.m4 ├── nvstatus.h ├── nvpd_rpc.h ├── command_server.c ├── option-table.h ├── options.c ├── Makefile ├── cpuopsys.h ├── nvstatuscodes.h └── nvidia-cfg.h /version.mk: -------------------------------------------------------------------------------- 1 | NVIDIA_VERSION = 590.48.01 2 | NVIDIA_NVID_VERSION = 590.48.01 3 | NVIDIA_NVID_EXTRA = 4 | 5 | # This file. 6 | VERSION_MK_FILE := $(lastword $(MAKEFILE_LIST)) 7 | $(OUTPUTDIR)/version.h: $(VERSION_MK_FILE) 8 | @$(MKDIR) $(OUTPUTDIR) 9 | @$(ECHO) '#define NVIDIA_VERSION "$(NVIDIA_VERSION)"' > $@ 10 | 11 | NV_GENERATED_HEADERS += $(OUTPUTDIR)/version.h 12 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013-2018, NVIDIA CORPORATION. All rights reserved. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a 4 | copy of this software and associated documentation files (the "Software"), 5 | to deal in the Software without restriction, including without limitation 6 | the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | and/or sell copies of the Software, and to permit persons to whom the 8 | Software is furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | DEALINGS IN THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /gen-manpage-opts.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 NVIDIA Corporation 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | #include 24 | 25 | #include "gen-manpage-opts-helper.h" 26 | #include "option-table.h" 27 | 28 | int main(int argc, char* argv[]) 29 | { 30 | gen_manpage_opts_helper(__options); 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | ______________________________________________________________________________ 2 | 3 | NVIDIA-PERSISTENCED SOURCE DOCUMENTATION 4 | ______________________________________________________________________________ 5 | 6 | This document outlines the source code and build instructions for the NVIDIA 7 | Persistence Daemon, nvidia-persistenced. Information on how to use 8 | nvidia-persistenced is available in the driver README and via the manpage that 9 | is installed along with the driver or installed from this source package. 10 | 11 | The daemon is controlled by an RPC interface that is generated by rpcgen. The 12 | files have been pre-generated for this source package to remove any dependency 13 | on rpcgen on the target system. The build otherwise only relies on the command 14 | line utility m4 to generate the manpage documentation, aside from the standard 15 | build tools. 16 | 17 | To build nvidia-persistenced and its manpage, you can simply run: 18 | 19 | make 20 | 21 | This will generate all output files within a system-specific subdirectory of 22 | the '_out' directory. 23 | 24 | To install nvidia-persistenced and its manpage, you can simply run: 25 | 26 | make install 27 | 28 | There are also a few init files included in the source distribution that may 29 | be used to start the NVIDIA Persistence Daemon on system startup. These files 30 | are provided as examples and may not install correctly out of the box. Please 31 | see init/README for more information. 32 | 33 | -------------------------------------------------------------------------------- /common-utils/gen-manpage-opts-helper.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | #if !defined(__GEN_MANPAGE_OPTS_HELPER_H__) 24 | #define __GEN_MANPAGE_OPTS_HELPER_H__ 25 | 26 | #include "nvgetopt.h" 27 | 28 | void gen_manpage_opts_helper(const NVGetoptOption *options); 29 | 30 | #endif /* __GEN_MANPAGE_OPTS_HELPER_H__ */ 31 | -------------------------------------------------------------------------------- /common-utils/nvpci-utils.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 NVIDIA Corporation 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | #ifndef __NVPCI_UTILS_H__ 24 | #define __NVPCI_UTILS_H__ 25 | 26 | #include 27 | 28 | #define NV_PCI_VENDOR_ID 0x10de 29 | 30 | struct pci_device_iterator *nvpci_find_gpu_by_vendor(uint32_t vendor_id); 31 | int nvpci_dev_is_vga(struct pci_device *dev); 32 | 33 | #endif /* __NVPCI_UTILS_H__ */ 34 | -------------------------------------------------------------------------------- /common-utils/src.mk: -------------------------------------------------------------------------------- 1 | # makefile fragment included by nvidia-xconfig, nvidia-settings, and nvidia-installer 2 | 3 | # the including makefile should set this if the relevant program uses pciaccess 4 | COMMON_UTILS_PCIACCESS ?= 5 | 6 | COMMON_UTILS_SRC += nvgetopt.c 7 | COMMON_UTILS_SRC += common-utils.c 8 | COMMON_UTILS_SRC += msg.c 9 | 10 | COMMON_UTILS_EXTRA_DIST += nvgetopt.h 11 | COMMON_UTILS_EXTRA_DIST += common-utils.h 12 | COMMON_UTILS_EXTRA_DIST += msg.h 13 | COMMON_UTILS_EXTRA_DIST += src.mk 14 | 15 | # only build nvpci-utils.c for programs that actually use libpciaccess, to 16 | # prevent other programs from needing to set the right CFLAGS/LDFLAGS for code 17 | # they won't use. Otherwise, just package it in the source tarball. 18 | ifneq ($(COMMON_UTILS_PCIACCESS),) 19 | COMMON_UTILS_SRC += nvpci-utils.c 20 | 21 | ifndef PCIACCESS_CFLAGS 22 | PCIACCESS_CFLAGS := $(shell $(PKG_CONFIG) --cflags pciaccess) 23 | endif 24 | 25 | ifndef PCIACCESS_LDFLAGS 26 | PCIACCESS_LDFLAGS := $(shell $(PKG_CONFIG) --libs pciaccess) 27 | endif 28 | 29 | $(call BUILD_OBJECT_LIST,nvpci-utils.c): CFLAGS += $(PCIACCESS_CFLAGS) 30 | else 31 | COMMON_UTILS_EXTRA_DIST += nvpci-utils.c 32 | endif 33 | COMMON_UTILS_EXTRA_DIST += nvpci-utils.h 34 | 35 | # gen-manpage-opts-helper.c is listed in EXTRA_DIST, rather than SRC, 36 | # because it is not compiled into the utilities themselves, but used 37 | # when building the utility's gen-manpage-opts 38 | COMMON_UTILS_EXTRA_DIST += gen-manpage-opts-helper.c 39 | COMMON_UTILS_EXTRA_DIST += gen-manpage-opts-helper.h 40 | 41 | -------------------------------------------------------------------------------- /init/systemd/nvidia-persistenced.service.template: -------------------------------------------------------------------------------- 1 | # NVIDIA Persistence Daemon Init Script 2 | # 3 | # Copyright (c) 2013 NVIDIA Corporation 4 | # 5 | # Permission is hereby granted, free of charge, to any person obtaining a 6 | # copy of this software and associated documentation files (the "Software"), 7 | # to deal in the Software without restriction, including without limitation 8 | # the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 | # and/or sell copies of the Software, and to permit persons to whom the 10 | # Software is furnished to do so, subject to the following conditions: 11 | # 12 | # The above copyright notice and this permission notice shall be included in 13 | # all copies or substantial portions of the Software. 14 | # 15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 | # DEALINGS IN THE SOFTWARE. 22 | # 23 | # This is a sample systemd service file, designed to show how the NVIDIA 24 | # Persistence Daemon can be started. 25 | # 26 | 27 | [Unit] 28 | Description=NVIDIA Persistence Daemon 29 | Wants=syslog.target 30 | 31 | [Service] 32 | Type=forking 33 | ExecStart=/usr/bin/nvidia-persistenced --user __USER__ 34 | ExecStopPost=/bin/rm -rf /var/run/nvidia-persistenced 35 | 36 | [Install] 37 | WantedBy=multi-user.target 38 | -------------------------------------------------------------------------------- /init/upstart/nvidia-persistenced.conf.template: -------------------------------------------------------------------------------- 1 | # NVIDIA Persistence Daemon Init Script 2 | # 3 | # Copyright (c) 2013 NVIDIA Corporation 4 | # 5 | # Permission is hereby granted, free of charge, to any person obtaining a 6 | # copy of this software and associated documentation files (the "Software"), 7 | # to deal in the Software without restriction, including without limitation 8 | # the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 | # and/or sell copies of the Software, and to permit persons to whom the 10 | # Software is furnished to do so, subject to the following conditions: 11 | # 12 | # The above copyright notice and this permission notice shall be included in 13 | # all copies or substantial portions of the Software. 14 | # 15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 | # DEALINGS IN THE SOFTWARE. 22 | # 23 | # This is a sample Upstart init script, designed to show how the NVIDIA 24 | # Persistence Daemon can be started. 25 | # 26 | 27 | description "NVIDIA Persistence Daemon" 28 | 29 | start on runlevel [2345] 30 | stop on runlevel [016] 31 | 32 | env NVPD_BIN=/usr/bin/nvidia-persistenced 33 | env NVPD_RUNTIME=/var/run/nvidia-persistenced 34 | env NVPD_USER=__USER__ 35 | 36 | expect fork 37 | 38 | exec $NVPD_BIN --user $NVPD_USER 39 | 40 | post-stop script 41 | rm -rf $NVPD_RUNTIME 42 | end script 43 | -------------------------------------------------------------------------------- /nvidia-numa.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | Copyright (c) 2015-2024 NVIDIA Corporation 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to 6 | deal in the Software without restriction, including without limitation the 7 | rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 | sell copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | DEALINGS IN THE SOFTWARE. 21 | 22 | *******************************************************************************/ 23 | #ifndef _NV_GPU_NUMA_H_ 24 | #define _NV_GPU_NUMA_H_ 25 | 26 | #include "nvpd_rpc.h" 27 | #include "nvidia-syslog-utils.h" 28 | 29 | /* per-device NUMA context */ 30 | typedef struct 31 | { 32 | int fd; 33 | NvCfgPciDevice *pci_info; 34 | uint8_t use_auto_online; 35 | } NvNumaDevice; 36 | 37 | NvPdStatus nvNumaOnlineMemory(NvNumaDevice *numa_info); 38 | 39 | NvPdStatus nvNumaOfflineMemory(NvNumaDevice *numa_info); 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /nvpd_defs.h: -------------------------------------------------------------------------------- 1 | /* 2 | * nvidia-persistenced: A daemon for maintaining persistent driver state, 3 | * specifically for use by the NVIDIA Linux driver. 4 | * 5 | * Copyright (C) 2013 NVIDIA Corporation 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a 8 | * copy of this software and associated documentation files (the "Software"), 9 | * to deal in the Software without restriction, including without limitation 10 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 | * and/or sell copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | * DEALINGS IN THE SOFTWARE. 24 | * 25 | * nvpd_defs.h 26 | */ 27 | 28 | #ifndef _NVPD_DEFS_H_ 29 | #define _NVPD_DEFS_H_ 30 | 31 | #include "nvpd_rpc.h" 32 | 33 | #define NVPD_DAEMON_NAME "nvidia-persistenced" 34 | 35 | #define NVPD_VAR_RUNTIME_DATA_PATH "/var/run/" NVPD_DAEMON_NAME 36 | #define NVPD_SOCKET_NAME "socket" 37 | #define NVPD_SOCKET_PATH NVPD_VAR_RUNTIME_DATA_PATH "/" \ 38 | NVPD_SOCKET_NAME 39 | #define NVPD_MAX_STRLEN 255 40 | 41 | /* 42 | * Useful format for printing PCI devices 43 | */ 44 | #define PCI_DEVICE_FMT "%04d:%02x:%02x:%x" 45 | 46 | #endif /* _NVPD_DEFS_H_ */ 47 | -------------------------------------------------------------------------------- /nvidia-syslog-utils.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017, NVIDIA CORPORATION. 3 | * 4 | * Permission is hereby granted, free of charge, to any person 5 | * obtaining a copy of this software and associated documentation 6 | * files (the "Software"), to deal in the Software without 7 | * restriction, including without limitation the rights to use, copy, 8 | * modify, merge, publish, distribute, sublicense, and/or sell copies 9 | * of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be 13 | * included in all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | * 24 | * This file provides utility functions for logging messages through 25 | * syslog 26 | */ 27 | 28 | #ifndef _NVIDIA_SYSLOG_UTILS_H_ 29 | #define _NVIDIA_SYSLOG_UTILS_H_ 30 | 31 | #include 32 | 33 | #include "common-utils.h" 34 | #include "nvidia-cfg.h" 35 | 36 | extern int verbose; 37 | extern int log_mask; 38 | 39 | void syslog_device(NvCfgPciDevice *device_pci_info, int priority, 40 | const char *format, ...); 41 | 42 | #define SYSLOG_DEVICE_VERBOSE(device, priority, format, ...) do { \ 43 | if (verbose) \ 44 | syslog_device(device, priority, format, ##__VA_ARGS__); \ 45 | } while(0) 46 | 47 | #define SYSLOG_VERBOSE(priority, format, ...) do { \ 48 | if (verbose) \ 49 | syslog(priority, format, ##__VA_ARGS__); \ 50 | } while(0) 51 | 52 | #endif /* _NVIDIA_SYSLOG_UTILS_H_ */ 53 | -------------------------------------------------------------------------------- /nv-ioctl-numbers.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: Copyright (c) 2020-2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 3 | * SPDX-License-Identifier: MIT 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a 6 | * copy of this software and associated documentation files (the "Software"), 7 | * to deal in the Software without restriction, including without limitation 8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 | * and/or sell copies of the Software, and to permit persons to whom the 10 | * Software is furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 | * DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | 25 | #ifndef NV_IOCTL_NUMBERS_H 26 | #define NV_IOCTL_NUMBERS_H 27 | 28 | /* NOTE: using an ioctl() number > 55 will overflow! */ 29 | #define NV_IOCTL_MAGIC 'F' 30 | #define NV_IOCTL_BASE 200 31 | #define NV_ESC_CARD_INFO (NV_IOCTL_BASE + 0) 32 | #define NV_ESC_REGISTER_FD (NV_IOCTL_BASE + 1) 33 | #define NV_ESC_ALLOC_OS_EVENT (NV_IOCTL_BASE + 6) 34 | #define NV_ESC_FREE_OS_EVENT (NV_IOCTL_BASE + 7) 35 | #define NV_ESC_STATUS_CODE (NV_IOCTL_BASE + 9) 36 | #define NV_ESC_CHECK_VERSION_STR (NV_IOCTL_BASE + 10) 37 | #define NV_ESC_IOCTL_XFER_CMD (NV_IOCTL_BASE + 11) 38 | #define NV_ESC_ATTACH_GPUS_TO_FD (NV_IOCTL_BASE + 12) 39 | #define NV_ESC_QUERY_DEVICE_INTR (NV_IOCTL_BASE + 13) 40 | #define NV_ESC_SYS_PARAMS (NV_IOCTL_BASE + 14) 41 | #define NV_ESC_EXPORT_TO_DMABUF_FD (NV_IOCTL_BASE + 17) 42 | #define NV_ESC_WAIT_OPEN_COMPLETE (NV_IOCTL_BASE + 18) 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /nvpd_rpc_xdr.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Please do not edit this file. 3 | * It was generated using rpcgen. 4 | */ 5 | 6 | #include "nvpd_rpc.h" 7 | 8 | bool_t 9 | xdr_NvPdStatus (XDR *xdrs, NvPdStatus *objp) 10 | { 11 | if (!xdr_enum (xdrs, (enum_t *) objp)) 12 | return FALSE; 13 | return TRUE; 14 | } 15 | 16 | bool_t 17 | xdr_NvPciDevice (XDR *xdrs, NvPciDevice *objp) 18 | { 19 | if (!xdr_int (xdrs, &objp->domain)) 20 | return FALSE; 21 | if (!xdr_int (xdrs, &objp->bus)) 22 | return FALSE; 23 | if (!xdr_int (xdrs, &objp->slot)) 24 | return FALSE; 25 | if (!xdr_int (xdrs, &objp->function)) 26 | return FALSE; 27 | return TRUE; 28 | } 29 | 30 | bool_t 31 | xdr_NvPersistenceMode (XDR *xdrs, NvPersistenceMode *objp) 32 | { 33 | if (!xdr_enum (xdrs, (enum_t *) objp)) 34 | return FALSE; 35 | return TRUE; 36 | } 37 | 38 | bool_t 39 | xdr_NvUVMPersistenceMode (XDR *xdrs, NvUVMPersistenceMode *objp) 40 | { 41 | if (!xdr_enum (xdrs, (enum_t *) objp)) 42 | return FALSE; 43 | return TRUE; 44 | } 45 | 46 | bool_t 47 | xdr_SetPersistenceModeArgs (XDR *xdrs, SetPersistenceModeArgs *objp) 48 | { 49 | if (!xdr_NvPciDevice (xdrs, &objp->device)) 50 | return FALSE; 51 | if (!xdr_NvPersistenceMode (xdrs, &objp->mode)) 52 | return FALSE; 53 | return TRUE; 54 | } 55 | 56 | bool_t 57 | xdr_GetPersistenceModeArgs (XDR *xdrs, GetPersistenceModeArgs *objp) 58 | { 59 | if (!xdr_NvPciDevice (xdrs, &objp->device)) 60 | return FALSE; 61 | return TRUE; 62 | } 63 | 64 | bool_t 65 | xdr_GetPersistenceModeRes (XDR *xdrs, GetPersistenceModeRes *objp) 66 | { 67 | if (!xdr_NvPdStatus (xdrs, &objp->status)) 68 | return FALSE; 69 | switch (objp->status) { 70 | case NVPD_SUCCESS: 71 | if (!xdr_NvPersistenceMode (xdrs, &objp->GetPersistenceModeRes_u.mode)) 72 | return FALSE; 73 | break; 74 | default: 75 | break; 76 | } 77 | return TRUE; 78 | } 79 | 80 | bool_t 81 | xdr_NvNumaStatus (XDR *xdrs, NvNumaStatus *objp) 82 | { 83 | if (!xdr_enum (xdrs, (enum_t *) objp)) 84 | return FALSE; 85 | return TRUE; 86 | } 87 | 88 | bool_t 89 | xdr_SetNumaStatusArgs (XDR *xdrs, SetNumaStatusArgs *objp) 90 | { 91 | if (!xdr_NvPciDevice (xdrs, &objp->device)) 92 | return FALSE; 93 | if (!xdr_NvNumaStatus (xdrs, &objp->status)) 94 | return FALSE; 95 | return TRUE; 96 | } 97 | -------------------------------------------------------------------------------- /init/README: -------------------------------------------------------------------------------- 1 | The scripts in this directory and its subdirectories provide examples of how 2 | to install the NVIDIA Persistence Daemon to run during the system startup 3 | sequence. 4 | 5 | The install.sh script attempts to find an init system it understands, and if 6 | it does, will attempt to install the daemon for that init system. While this 7 | script understands a few of the major init systems, it is not guaranteed to 8 | support all systems that the NVIDIA GPU driver can be installed on, and 9 | is not guaranteed to correctly install the NVIDIA Persistence Daemon for those 10 | systems that it thinks it understands. 11 | 12 | End users or package maintainers may use the scripts in the following ways: 13 | 14 | (1) Invoke install.sh to install the proper init script for the target system, 15 | if supported. 16 | (2) Tailor the install.sh script to correctly install the proper init script 17 | for the target system, if not supported by the original install.sh script. 18 | (3) Tailor the init system-specific configuration files or scripts found in 19 | the subdirectories of this directory, and install them via either the 20 | install.sh script or another mechanism. 21 | 22 | The files found in the subdirectories of this directory are template files, 23 | which are processed by the install.sh script to fill in the user under which 24 | the daemon should run (see install.sh -h for more details) prior to 25 | installation. The final installable configuration files and scripts are 26 | created from these template files for every init system (in their respective 27 | subdirectories) when install.sh is run with correct arguments, regardless of 28 | whether or not a supported init system is detected. 29 | 30 | The final installable configuration files and scripts are simply copies of 31 | the template files with the "__USER__" string replaced with the actual 32 | username. 33 | 34 | The install.sh script will check for init systems in the following order: 35 | 36 | (1) systemd 37 | (2) Upstart 38 | (3) System V 39 | 40 | Since Upstart provides backwards compatibility with System V init, if the 41 | install.sh script fails to install for Upstart, try installing instead with 42 | the 'sysv' argument. This will force the install.sh script to only attempt 43 | installation of the System V init script. 44 | 45 | Finally, the install.sh script provides some other convenience functions, 46 | such as: 47 | 48 | (1) Install the daemon to run as a specific user 49 | (2) Install the config file/script to a non-standard directory 50 | (3) Uninstallation 51 | 52 | -------------------------------------------------------------------------------- /dist-files.mk: -------------------------------------------------------------------------------- 1 | # nvidia-persistenced: A daemon for maintaining persistent driver state, 2 | # specifically for use by the NVIDIA Linux driver. 3 | # 4 | # Copyright (C) 2013 NVIDIA Corporation 5 | # 6 | # Permission is hereby granted, free of charge, to any person obtaining a 7 | # copy of this software and associated documentation files (the "Software"), 8 | # to deal in the Software without restriction, including without limitation 9 | # the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 | # and/or sell copies of the Software, and to permit persons to whom the 11 | # Software is furnished to do so, subject to the following conditions: 12 | # 13 | # The above copyright notice and this permission notice shall be included in 14 | # all copies or substantial portions of the Software. 15 | # 16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 22 | # DEALINGS IN THE SOFTWARE. 23 | # 24 | 25 | ############################################################################## 26 | # define the list of files that should be distributed in the 27 | # nvidia-persistenced tarball 28 | ############################################################################## 29 | 30 | RPC_DIR ?= . 31 | 32 | RPC_SRC := $(RPC_DIR)/nvpd_rpc_server.c 33 | RPC_SRC += $(RPC_DIR)/nvpd_rpc_xdr.c 34 | 35 | # Sources 36 | SRC += command_server.c 37 | SRC += nvidia-persistenced.c 38 | SRC += options.c 39 | SRC += nvidia-syslog-utils.c 40 | SRC += $(RPC_SRC) 41 | SRC += $(NVIDIA_NUMA_DIR)/nvidia-numa.c 42 | 43 | # Sample files included in the distribution 44 | SAMPLE_FILES := init/README 45 | SAMPLE_FILES += init/install.sh 46 | SAMPLE_FILES += init/systemd/nvidia-persistenced.service.template 47 | SAMPLE_FILES += init/sysv/nvidia-persistenced.template 48 | SAMPLE_FILES += init/upstart/nvidia-persistenced.conf.template 49 | 50 | # Other distributed files 51 | DIST_FILES := $(SRC) 52 | DIST_FILES += COPYING 53 | DIST_FILES += README 54 | DIST_FILES += dist-files.mk 55 | DIST_FILES += nvpd_defs.h 56 | DIST_FILES += nvidia-persistenced.h 57 | DIST_FILES += nvidia-syslog-utils.h 58 | DIST_FILES += option-table.h 59 | DIST_FILES += nvidia-persistenced.1.m4 60 | DIST_FILES += gen-manpage-opts.c 61 | DIST_FILES += $(RPC_DIR)/nvpd_rpc.h 62 | DIST_FILES += $(NVIDIA_NUMA_DIR)/nvidia-numa.h 63 | -------------------------------------------------------------------------------- /nvidia-syslog-utils.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017, NVIDIA CORPORATION. 3 | * 4 | * Permission is hereby granted, free of charge, to any person 5 | * obtaining a copy of this software and associated documentation 6 | * files (the "Software"), to deal in the Software without 7 | * restriction, including without limitation the rights to use, copy, 8 | * modify, merge, publish, distribute, sublicense, and/or sell copies 9 | * of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be 13 | * included in all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | * 24 | * This file provides utility functions for logging messages through 25 | * syslog 26 | */ 27 | 28 | #include "nvidia-syslog-utils.h" 29 | 30 | int verbose = 0; 31 | int log_mask = 0; 32 | 33 | /* 34 | * syslog_device() - This function prints the device info along with the 35 | * specified message to syslog. If there is a failure to allocate memory along 36 | * the way, it will simply fail with an error to syslog(). 37 | */ 38 | void syslog_device(NvCfgPciDevice *device_pci_info, int priority, 39 | const char *format, ...) 40 | { 41 | char *device_str = NULL; 42 | char *str = NULL; 43 | 44 | /* First check if this message will even show up. */ 45 | if ((log_mask & priority) == 0) { 46 | return; 47 | } 48 | 49 | /* First fill in the format string as usual. */ 50 | NV_VSNPRINTF(str, format); 51 | if (str == NULL) { 52 | syslog(LOG_ERR, "Failed to create formatted message."); 53 | return; 54 | } 55 | 56 | /* Then prefix it with the device info. */ 57 | device_str = nvasprintf("device %04x:%02x:%02x.%x - %s", 58 | device_pci_info->domain, device_pci_info->bus, 59 | device_pci_info->slot, device_pci_info->function, 60 | str); 61 | nvfree(str); 62 | if (device_str == NULL) { 63 | syslog(LOG_ERR, "Failed to create device message."); 64 | return; 65 | } 66 | 67 | syslog(priority, "%s", device_str); 68 | 69 | nvfree(device_str); 70 | } 71 | -------------------------------------------------------------------------------- /common-utils/nvpci-utils.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 NVIDIA Corporation 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | #include "nvpci-utils.h" 24 | 25 | /* 26 | * libpciaccess stores the device class in bits 16-23, subclass in 8-15, and 27 | * interface in bits 0-7 of dev->device_class. We care only about the class 28 | * and subclass. 29 | */ 30 | const uint32_t PCI_CLASS_DISPLAY_VGA = 0x30000; 31 | const uint32_t PCI_CLASS_SUBCLASS_MASK = 0xffff00; 32 | 33 | /* 34 | * nvpci_find_gpu_by_vendor() - use libpciaccess to find all VGA and 3D PCI 35 | * devices matching the passed-in vendor_id (which may be set to PCI_MATCH_ANY). 36 | * The caller is responsible for calling pci_system_init() before using this 37 | * function, and pci_system_cleanup() when libpciaccess is no longer needed. 38 | */ 39 | struct pci_device_iterator *nvpci_find_gpu_by_vendor(uint32_t vendor_id) 40 | { 41 | const struct pci_id_match match = { 42 | .vendor_id = vendor_id, 43 | .device_id = PCI_MATCH_ANY, 44 | .subvendor_id = PCI_MATCH_ANY, 45 | .subdevice_id = PCI_MATCH_ANY, 46 | .device_class = PCI_CLASS_DISPLAY_VGA, 47 | /* 48 | * Ignore bit 1 of the subclass, to allow both 0x30000 (VGA controller) 49 | * and 0x30200 (3D controller). 50 | */ 51 | .device_class_mask = PCI_CLASS_SUBCLASS_MASK & ~0x200, 52 | }; 53 | 54 | return pci_id_match_iterator_create(&match); 55 | } 56 | 57 | /* 58 | * nvpci_dev_is_vga() - test whether the passed-in struct pci_device* has the 59 | * VGA device class 0x0300 (and not 3D class 0x0302). 60 | */ 61 | int nvpci_dev_is_vga(struct pci_device *dev) 62 | { 63 | return (dev->device_class & PCI_CLASS_SUBCLASS_MASK) == 64 | PCI_CLASS_DISPLAY_VGA; 65 | } 66 | -------------------------------------------------------------------------------- /nvidia-persistenced.h: -------------------------------------------------------------------------------- 1 | /* 2 | * nvidia-persistenced: A daemon for maintaining persistent driver state, 3 | * specifically for use by the NVIDIA Linux driver. 4 | * 5 | * Copyright (C) 2013 NVIDIA Corporation 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a 8 | * copy of this software and associated documentation files (the "Software"), 9 | * to deal in the Software without restriction, including without limitation 10 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 | * and/or sell copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | * DEALINGS IN THE SOFTWARE. 24 | * 25 | * nvidia-persistenced.h 26 | */ 27 | 28 | #ifndef _NVIDIA_PERSISTENCED_H_ 29 | #define _NVIDIA_PERSISTENCED_H_ 30 | 31 | #include 32 | 33 | #include "nvpd_rpc.h" 34 | 35 | /* Daemon Options */ 36 | typedef struct { 37 | NvPersistenceMode persistence_mode; 38 | NvUVMPersistenceMode uvm_persistence_mode; 39 | char *nvidia_cfg_path; 40 | int verbose; 41 | uid_t uid; 42 | gid_t gid; 43 | } NvPdOptions; 44 | 45 | /* Command Implementations */ 46 | NvPdStatus nvPdSetDevicePersistenceMode(int domain, int bus, int slot, 47 | int function, NvPersistenceMode mode); 48 | NvPdStatus nvPdGetDevicePersistenceMode(int domain, int bus, int slot, 49 | int function, 50 | NvPersistenceMode *mode); 51 | NvPdStatus nvPdSetDevicePersistenceModeOnly(int domain, int bus, int slot, 52 | int function, 53 | NvPersistenceMode mode); 54 | NvPdStatus nvPdSetDeviceNumaStatus(int domain, int bus, int slot, 55 | int function, NvNumaStatus status); 56 | 57 | /* RPC Service Routines */ 58 | extern void nvpd_prog_1(struct svc_req *rqstp, register SVCXPRT *transp); 59 | extern void nvpd_prog_2(struct svc_req *rqstp, register SVCXPRT *transp); 60 | 61 | /* Commandline Parsing */ 62 | extern void parse_options(int argc, char *argv[], NvPdOptions *); 63 | 64 | #endif /* _NVIDIA_PERSISTENCED_H_ */ 65 | -------------------------------------------------------------------------------- /init/sysv/nvidia-persistenced.template: -------------------------------------------------------------------------------- 1 | #!/bin/sh -e 2 | # 3 | # NVIDIA Persistence Daemon Init Script 4 | # 5 | # Copyright (c) 2013 NVIDIA Corporation 6 | # 7 | # Permission is hereby granted, free of charge, to any person obtaining a 8 | # copy of this software and associated documentation files (the "Software"), 9 | # to deal in the Software without restriction, including without limitation 10 | # the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 | # and/or sell copies of the Software, and to permit persons to whom the 12 | # Software is furnished to do so, subject to the following conditions: 13 | # 14 | # The above copyright notice and this permission notice shall be included in 15 | # all copies or substantial portions of the Software. 16 | # 17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | # DEALINGS IN THE SOFTWARE. 24 | # 25 | # This is a sample System V init script, designed to show how the NVIDIA 26 | # Persistence Daemon can be started. 27 | # 28 | # This sample does not rely on any init system functions, to ensure the 29 | # widest portability possible. 30 | # 31 | # chkconfig: 2345 99 01 32 | # description: Starts and stops the NVIDIA Persistence Daemon 33 | # processname: nvidia-persistenced 34 | # 35 | ### BEGIN INIT INFO 36 | # Provides: nvidia-persistenced 37 | # Required-Start: $ALL 38 | # Required-Stop: $ALL 39 | # Default-Start: 2 3 4 5 40 | # Default-Stop: 0 1 6 41 | # Description: Starts and stops the NVIDIA Persistence Daemon 42 | ### END INIT INFO 43 | 44 | 45 | NVPD=nvidia-persistenced 46 | NVPD_BIN=/usr/bin/${NVPD} 47 | NVPD_RUNTIME=/var/run/${NVPD} 48 | NVPD_PIDFILE=${NVPD_RUNTIME}/${NVPD}.pid 49 | NVPD_USER=__USER__ 50 | 51 | if [ -f ${NVPD_PIDFILE} ]; then 52 | read -r NVPD_PID < "${NVPD_PIDFILE}" 53 | # Remove stale runtime files 54 | if [ "${NVPD_PID}" ] && [ ! -d /proc/${NVPD_PID} ]; then 55 | unset NVPD_PID 56 | rm -rf "${NVPD_RUNTIME}" 57 | fi 58 | fi 59 | 60 | case "${1}" in 61 | start) 62 | echo "Starting NVIDIA Persistence Daemon" 63 | 64 | # Execute the daemon as the intended user 65 | ${NVPD_BIN} --user ${NVPD_USER} 66 | ;; 67 | stop) 68 | echo "Stopping NVIDIA Persistence Daemon" 69 | 70 | # Stop the daemon - its PID should have been read in 71 | [ ! -z "${NVPD_PID}" ] && kill ${NVPD_PID} &> /dev/null 72 | ;; 73 | restart) 74 | $0 stop 75 | sleep 2 76 | $0 start 77 | ;; 78 | *) echo "usage: $0 {start|stop|restart}" 79 | esac 80 | exit 0 81 | -------------------------------------------------------------------------------- /nv-ioctl-numa.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: Copyright (c) 2020 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 3 | * SPDX-License-Identifier: MIT 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a 6 | * copy of this software and associated documentation files (the "Software"), 7 | * to deal in the Software without restriction, including without limitation 8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 | * and/or sell copies of the Software, and to permit persons to whom the 10 | * Software is furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 | * DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | 25 | #ifndef NV_IOCTL_NUMA_H 26 | #define NV_IOCTL_NUMA_H 27 | 28 | #include 29 | 30 | #if defined(NV_KERNEL_INTERFACE_LAYER) && defined(NV_LINUX) 31 | #include 32 | #elif defined (NV_KERNEL_INTERFACE_LAYER) && defined(NV_BSD) 33 | #include 34 | #else 35 | 36 | #include 37 | 38 | #if !defined(__aligned) 39 | #define __aligned(n) __attribute__((aligned(n))) 40 | #endif 41 | 42 | #endif 43 | 44 | #define NV_ESC_NUMA_INFO (NV_IOCTL_BASE + 15) 45 | #define NV_ESC_SET_NUMA_STATUS (NV_IOCTL_BASE + 16) 46 | 47 | #define NV_IOCTL_NUMA_INFO_MAX_OFFLINE_ADDRESSES 64 48 | typedef struct offline_addresses 49 | { 50 | uint64_t addresses[NV_IOCTL_NUMA_INFO_MAX_OFFLINE_ADDRESSES] __aligned(8); 51 | uint32_t numEntries; 52 | } nv_offline_addresses_t; 53 | 54 | 55 | /* per-device NUMA memory info as assigned by the system */ 56 | typedef struct nv_ioctl_numa_info 57 | { 58 | int32_t nid; 59 | int32_t status; 60 | uint64_t memblock_size __aligned(8); 61 | uint64_t numa_mem_addr __aligned(8); 62 | uint64_t numa_mem_size __aligned(8); 63 | uint8_t use_auto_online; 64 | nv_offline_addresses_t offline_addresses __aligned(8); 65 | } nv_ioctl_numa_info_t; 66 | 67 | /* set the status of the device NUMA memory */ 68 | typedef struct nv_ioctl_set_numa_status 69 | { 70 | int32_t status; 71 | } nv_ioctl_set_numa_status_t; 72 | 73 | #define NV_IOCTL_NUMA_STATUS_DISABLED 0 74 | #define NV_IOCTL_NUMA_STATUS_OFFLINE 1 75 | #define NV_IOCTL_NUMA_STATUS_ONLINE_IN_PROGRESS 2 76 | #define NV_IOCTL_NUMA_STATUS_ONLINE 3 77 | #define NV_IOCTL_NUMA_STATUS_ONLINE_FAILED 4 78 | #define NV_IOCTL_NUMA_STATUS_OFFLINE_IN_PROGRESS 5 79 | #define NV_IOCTL_NUMA_STATUS_OFFLINE_FAILED 6 80 | 81 | #endif 82 | -------------------------------------------------------------------------------- /nvpd_rpc_server.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Please do not edit this file. 3 | * It was generated using rpcgen. 4 | */ 5 | 6 | #include "nvpd_rpc.h" 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #ifndef SIG_PF 17 | #define SIG_PF void(*)(int) 18 | #endif 19 | 20 | #include "nvidia-persistenced.h" 21 | 22 | void 23 | nvpd_prog_1(struct svc_req *rqstp, register SVCXPRT *transp) 24 | { 25 | union { 26 | SetPersistenceModeArgs nvpdsetpersistencemode_1_arg; 27 | GetPersistenceModeArgs nvpdgetpersistencemode_1_arg; 28 | } argument; 29 | char *result; 30 | xdrproc_t _xdr_argument, _xdr_result; 31 | char *(*local)(char *, struct svc_req *); 32 | 33 | switch (rqstp->rq_proc) { 34 | case NULLPROC: 35 | (void) svc_sendreply (transp, (xdrproc_t) xdr_void, (char *)NULL); 36 | return; 37 | 38 | case nvPdSetPersistenceMode: 39 | _xdr_argument = (xdrproc_t) xdr_SetPersistenceModeArgs; 40 | _xdr_result = (xdrproc_t) xdr_NvPdStatus; 41 | local = (char *(*)(char *, struct svc_req *)) nvpdsetpersistencemode_1_svc; 42 | break; 43 | 44 | case nvPdGetPersistenceMode: 45 | _xdr_argument = (xdrproc_t) xdr_GetPersistenceModeArgs; 46 | _xdr_result = (xdrproc_t) xdr_GetPersistenceModeRes; 47 | local = (char *(*)(char *, struct svc_req *)) nvpdgetpersistencemode_1_svc; 48 | break; 49 | 50 | default: 51 | svcerr_noproc (transp); 52 | return; 53 | } 54 | memset ((char *)&argument, 0, sizeof (argument)); 55 | if (!svc_getargs (transp, (xdrproc_t) _xdr_argument, (caddr_t) &argument)) { 56 | svcerr_decode (transp); 57 | return; 58 | } 59 | result = (*local)((char *)&argument, rqstp); 60 | if (result != NULL && !svc_sendreply(transp, (xdrproc_t) _xdr_result, result)) { 61 | svcerr_systemerr (transp); 62 | } 63 | if (!svc_freeargs (transp, (xdrproc_t) _xdr_argument, (caddr_t) &argument)) { 64 | syslog (LOG_ERR, "%s", "unable to free arguments"); 65 | exit (1); 66 | } 67 | return; 68 | } 69 | 70 | void 71 | nvpd_prog_2(struct svc_req *rqstp, register SVCXPRT *transp) 72 | { 73 | union { 74 | SetPersistenceModeArgs nvpdsetpersistencemodeonly_2_arg; 75 | SetNumaStatusArgs nvpdsetnumastatus_2_arg; 76 | } argument; 77 | char *result; 78 | xdrproc_t _xdr_argument, _xdr_result; 79 | char *(*local)(char *, struct svc_req *); 80 | 81 | switch (rqstp->rq_proc) { 82 | case NULLPROC: 83 | (void) svc_sendreply (transp, (xdrproc_t) xdr_void, (char *)NULL); 84 | return; 85 | 86 | case nvPdSetPersistenceModeOnly: 87 | _xdr_argument = (xdrproc_t) xdr_SetPersistenceModeArgs; 88 | _xdr_result = (xdrproc_t) xdr_NvPdStatus; 89 | local = (char *(*)(char *, struct svc_req *)) nvpdsetpersistencemodeonly_2_svc; 90 | break; 91 | 92 | case nvPdSetNumaStatus: 93 | _xdr_argument = (xdrproc_t) xdr_SetNumaStatusArgs; 94 | _xdr_result = (xdrproc_t) xdr_NvPdStatus; 95 | local = (char *(*)(char *, struct svc_req *)) nvpdsetnumastatus_2_svc; 96 | break; 97 | 98 | default: 99 | svcerr_noproc (transp); 100 | return; 101 | } 102 | memset ((char *)&argument, 0, sizeof (argument)); 103 | if (!svc_getargs (transp, (xdrproc_t) _xdr_argument, (caddr_t) &argument)) { 104 | svcerr_decode (transp); 105 | return; 106 | } 107 | result = (*local)((char *)&argument, rqstp); 108 | if (result != NULL && !svc_sendreply(transp, (xdrproc_t) _xdr_result, result)) { 109 | svcerr_systemerr (transp); 110 | } 111 | if (!svc_freeargs (transp, (xdrproc_t) _xdr_argument, (caddr_t) &argument)) { 112 | syslog (LOG_ERR, "%s", "unable to free arguments"); 113 | exit (1); 114 | } 115 | return; 116 | } 117 | -------------------------------------------------------------------------------- /nvidia-persistenced.1.m4: -------------------------------------------------------------------------------- 1 | dnl This file is to be preprocessed by m4. 2 | changequote([[[, ]]])dnl 3 | define(__OPTIONS__, [[[include([[[options.1.inc]]])dnl]]])dnl 4 | dnl Solaris man chokes on three-letter macros. 5 | ifelse(__BUILD_OS__,SunOS,[[[define(__URL__,UR)]]],[[[define(__URL__,URL)]]])dnl 6 | .\" Copyright (C) 2013 NVIDIA Corporation. 7 | .\" 8 | __HEADER__ 9 | .\" Define the .__URL__ macro and then override it with the www.tmac package if it 10 | .\" exists. 11 | .de __URL__ 12 | \\$2 \(la \\$1 \(ra\\$3 13 | .. 14 | .if \n[.g] .mso www.tmac 15 | .TH nvidia\-persistenced 1 "__DATE__" "nvidia\-persistenced __VERSION__" 16 | 17 | .SH NAME 18 | nvidia\-persistenced \- A daemon to maintain persistent software state in the NVIDIA driver. 19 | 20 | .SH SYNOPSIS 21 | .BI "nvidia\-persistenced" 22 | .br 23 | 24 | .SH DESCRIPTION 25 | The 26 | .B nvidia\-persistenced 27 | utility is used to enable persistent software state in the NVIDIA driver. 28 | When persistence mode is enabled, the daemon prevents the driver from releasing device state when the device is not in use. 29 | This can improve the startup time of new clients in this scenario. 30 | .PP 31 | 32 | __OPTIONS__ 33 | 34 | .SH INSTALLATION 35 | When installed by 36 | .B nvidia\-installer 37 | , sample init scripts to start the daemon for some of the more prevalent init systems are installed as the compressed tarball /usr/share/doc/NVIDIA_GLX-1.0/sample/nvidia-persistenced-init.tar.bz2. 38 | These init scripts should be customized to the user's distribution and installed in the proper location by the user to run 39 | .B nvidia\-persistenced 40 | on system initialization. 41 | .PP 42 | Once the init script is installed so that the daemon is running, users should not normally need to manually interact with 43 | .B nvidia\-persistenced: 44 | the NVIDIA management utilities, such as 45 | .B nvidia\-smi, 46 | can communicate with it automatically as necessary to manage persistence mode. 47 | .PP 48 | See the "Using the nvidia-persistenced Utility" section of the NVIDIA Linux Graphics Driver README for more background, information about installing the 49 | .B nvidia\-persistenced 50 | utility to run on system initialization, and troubleshooting tips. 51 | .PP 52 | 53 | .SH PRIVILEGES 54 | The daemon does not require root privileges to run, and may safely be run as an unprivileged user, given that its runtime directory, /var/run/nvidia-persistenced, is created for and owned by that user prior to starting the daemon. 55 | .B nvidia\-persistenced 56 | also requires read and write access to the NVIDIA character device files. 57 | If the permissions of the device files have been altered through any of the NVreg_DeviceFileUID, NVreg_DeviceFile_GID, or NVreg_DeviceFileMode NVIDIA kernel module options, 58 | .B nvidia\-persistenced 59 | will need to run as a suitable user. 60 | .PP 61 | If the daemon is started with root privileges, the 62 | .B \-\-user 63 | option may be used instead to indicate that the daemon should drop its privileges and run as the specified user after setting up its runtime directory. 64 | Using this option may cause the daemon to be unable to remove the /var/run/nvidia-persistenced directory when it is killed, if the specified user does not have write permissions to /var/run. 65 | In this case, directory removal should be handled by a post-execution script. 66 | See the sample init scripts provided in /usr/share/doc/NVIDIA_GLX-1.0/sample/nvidia-persistenced-init.tar.bz2 for examples of this behavior. 67 | .PP 68 | The daemon indirectly utilizes 69 | .B nvidia\-modprobe 70 | via the nvidia-cfg library to load the NVIDIA kernel module and create the NVIDIA character device files after the daemon has dropped its root privileges, if it had any to begin with. 71 | If 72 | .B nvidia\-modprobe 73 | is not installed, the daemon may not be able to start properly if it is not run with root privileges. 74 | .PP 75 | 76 | .SH OTHER 77 | The source code to 78 | .B nvidia\-persistenced 79 | is available here: 80 | .__URL__ https://download.nvidia.com/XFree86/nvidia-persistenced/ 81 | .PP 82 | 83 | .SH EXAMPLES 84 | .TP 85 | .B nvidia\-persistenced 86 | Starts the NVIDIA Persistence Daemon with persistence mode enabled for all NVIDIA devices. 87 | .TP 88 | .B nvidia\-persistenced \-\-no\-persistence\-mode 89 | Starts the NVIDIA Persistence Daemon with persistence mode disabled for all NVIDIA devices. 90 | .TP 91 | .B nvidia\-persistenced \-\-user=foo 92 | Starts the NVIDIA Persistence Daemon so that it will run as user 'foo'. 93 | 94 | .SH AUTHOR 95 | Will Davis 96 | .br 97 | NVIDIA Corporation 98 | 99 | .SH SEE ALSO 100 | .BR nvidia\-smi (1), 101 | .BR nvidia\-modprobe (1) 102 | 103 | .SH COPYRIGHT 104 | Copyright \(co 2013-2016 NVIDIA Corporation. 105 | -------------------------------------------------------------------------------- /nvstatus.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: Copyright (c) 2014-2019 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 3 | * SPDX-License-Identifier: MIT 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a 6 | * copy of this software and associated documentation files (the "Software"), 7 | * to deal in the Software without restriction, including without limitation 8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 | * and/or sell copies of the Software, and to permit persons to whom the 10 | * Software is furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 | * DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | #ifndef SDK_NVSTATUS_H 25 | #define SDK_NVSTATUS_H 26 | 27 | #ifdef __cplusplus 28 | extern "C" { 29 | #endif 30 | 31 | #include "nvtypes.h" 32 | 33 | typedef NvU32 NV_STATUS; 34 | 35 | #define NV_STATUS_CODE( name, code, string ) name = (code), 36 | 37 | enum 38 | { 39 | #include "nvstatuscodes.h" 40 | }; 41 | 42 | #undef NV_STATUS_CODE 43 | 44 | /*! 45 | * @def NV_STATUS_LEVEL_OK 46 | * @see NV_STATUS_LEVEL 47 | * @brief Success: No error or special condition 48 | */ 49 | #define NV_STATUS_LEVEL_OK 0 50 | 51 | /*! 52 | * @def NV_STATUS_LEVEL_WARN 53 | * @see NV_STATUS_LEVEL 54 | * @brief Success, but there is an special condition 55 | * 56 | * @details In general, NV_STATUS_LEVEL_WARN status codes are handled the 57 | * same as NV_STATUS_LEVEL_OK, but are usefil to indicate that 58 | * there is a condition that may be specially handled. 59 | * 60 | * Therefore, in most cases, client function should test for 61 | * status <= NV_STATUS_LEVEL_WARN or status > NV_STATUS_LEVEL_WARN 62 | * to determine success v. failure of a call. 63 | */ 64 | #define NV_STATUS_LEVEL_WARN 1 65 | 66 | /*! 67 | * @def NV_STATUS_LEVEL_ERR 68 | * @see NV_STATUS_LEVEL 69 | * @brief Unrecoverable error condition 70 | */ 71 | #define NV_STATUS_LEVEL_ERR 3 72 | 73 | /*! 74 | * @def NV_STATUS_LEVEL 75 | * @see NV_STATUS_LEVEL_OK 76 | * @see NV_STATUS_LEVEL_WARN 77 | * @see NV_STATUS_LEVEL_ERR 78 | * @brief Level of the status code 79 | * 80 | * @warning IMPORTANT: When comparing NV_STATUS_LEVEL(_S) against one of 81 | * these constants, it is important to use '<=' or '>' (rather 82 | * than '<' or '>='). 83 | * 84 | * For example. do: 85 | * if (NV_STATUS_LEVEL(status) <= NV_STATUS_LEVEL_WARN) 86 | * rather than: 87 | * if (NV_STATUS_LEVEL(status) < NV_STATUS_LEVEL_ERR) 88 | * 89 | * By being consistent in this manner, it is easier to systematically 90 | * add additional level constants. New levels are likely to lower 91 | * (rather than raise) the severity of _ERR codes. For example, 92 | * if we were to add NV_STATUS_LEVEL_RETRY to indicate hardware 93 | * failures that may be recoverable (e.g. RM_ERR_TIMEOUT_RETRY 94 | * or RM_ERR_BUSY_RETRY), it would be less severe than 95 | * NV_STATUS_LEVEL_ERR the level to which these status codes now 96 | * belong. Using '<=' and '>' ensures your code is not broken in 97 | * cases like this. 98 | */ 99 | #define NV_STATUS_LEVEL(_S) \ 100 | ((_S) == NV_OK? NV_STATUS_LEVEL_OK: \ 101 | ((_S) != NV_ERR_GENERIC && (_S) & 0x00010000? NV_STATUS_LEVEL_WARN: \ 102 | NV_STATUS_LEVEL_ERR)) 103 | 104 | /*! 105 | * @def NV_STATUS_LEVEL 106 | * @see NV_STATUS_LEVEL_OK 107 | * @see NV_STATUS_LEVEL_WARN 108 | * @see NV_STATUS_LEVEL_ERR 109 | * @brief Character representing status code level 110 | */ 111 | #define NV_STATUS_LEVEL_CHAR(_S) \ 112 | ((_S) == NV_OK? '0': \ 113 | ((_S) != NV_ERR_GENERIC && (_S) & 0x00010000? 'W': \ 114 | 'E')) 115 | 116 | // Function definitions 117 | const char *nvstatusToString(NV_STATUS nvStatusIn); 118 | 119 | #ifdef __cplusplus 120 | } 121 | #endif 122 | 123 | #endif /* SDK_NVSTATUS_H */ 124 | -------------------------------------------------------------------------------- /nvpd_rpc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Please do not edit this file. 3 | * It was generated using rpcgen. 4 | */ 5 | 6 | #ifndef _NVPD_RPC_H_RPCGEN 7 | #define _NVPD_RPC_H_RPCGEN 8 | 9 | #include 10 | 11 | 12 | #ifdef __cplusplus 13 | extern "C" { 14 | #endif 15 | 16 | 17 | enum NvPdStatus { 18 | NVPD_SUCCESS = 0, 19 | NVPD_ERR_DAEMON_NOT_PRESENT = 1, 20 | NVPD_ERR_DEVICE_NOT_FOUND = 2, 21 | NVPD_ERR_DRIVER = 3, 22 | NVPD_ERR_INSUFFICIENT_RESOURCES = 4, 23 | NVPD_ERR_INVALID_ARGUMENT = 5, 24 | NVPD_ERR_IO = 6, 25 | NVPD_ERR_PERMISSIONS = 7, 26 | NVPD_ERR_RPC = 8, 27 | NVPD_ERR_USER_NOT_FOUND = 9, 28 | NVPD_ERR_NUMA_FAILURE = 10, 29 | NVPD_ERR_UNKNOWN = 11, 30 | }; 31 | typedef enum NvPdStatus NvPdStatus; 32 | 33 | struct NvPciDevice { 34 | int domain; 35 | int bus; 36 | int slot; 37 | int function; 38 | }; 39 | typedef struct NvPciDevice NvPciDevice; 40 | 41 | enum NvPersistenceMode { 42 | NV_PERSISTENCE_MODE_DISABLED = 0, 43 | NV_PERSISTENCE_MODE_ENABLED = 1, 44 | }; 45 | typedef enum NvPersistenceMode NvPersistenceMode; 46 | 47 | enum NvUVMPersistenceMode { 48 | NV_UVM_PERSISTENCE_MODE_DISABLED = 0, 49 | NV_UVM_PERSISTENCE_MODE_ENABLED = 1, 50 | }; 51 | typedef enum NvUVMPersistenceMode NvUVMPersistenceMode; 52 | 53 | struct SetPersistenceModeArgs { 54 | NvPciDevice device; 55 | NvPersistenceMode mode; 56 | }; 57 | typedef struct SetPersistenceModeArgs SetPersistenceModeArgs; 58 | 59 | struct GetPersistenceModeArgs { 60 | NvPciDevice device; 61 | }; 62 | typedef struct GetPersistenceModeArgs GetPersistenceModeArgs; 63 | 64 | struct GetPersistenceModeRes { 65 | NvPdStatus status; 66 | union { 67 | NvPersistenceMode mode; 68 | } GetPersistenceModeRes_u; 69 | }; 70 | typedef struct GetPersistenceModeRes GetPersistenceModeRes; 71 | 72 | enum NvNumaStatus { 73 | NV_NUMA_STATUS_OFFLINE = 0, 74 | NV_NUMA_STATUS_ONLINE = 1, 75 | }; 76 | typedef enum NvNumaStatus NvNumaStatus; 77 | 78 | struct SetNumaStatusArgs { 79 | NvPciDevice device; 80 | NvNumaStatus status; 81 | }; 82 | typedef struct SetNumaStatusArgs SetNumaStatusArgs; 83 | 84 | #define NVPD_PROG 35006 85 | #define VersionOne 1 86 | 87 | #if defined(__STDC__) || defined(__cplusplus) 88 | #define nvPdSetPersistenceMode 1 89 | extern NvPdStatus * nvpdsetpersistencemode_1(SetPersistenceModeArgs *, CLIENT *); 90 | extern NvPdStatus * nvpdsetpersistencemode_1_svc(SetPersistenceModeArgs *, struct svc_req *); 91 | #define nvPdGetPersistenceMode 2 92 | extern GetPersistenceModeRes * nvpdgetpersistencemode_1(GetPersistenceModeArgs *, CLIENT *); 93 | extern GetPersistenceModeRes * nvpdgetpersistencemode_1_svc(GetPersistenceModeArgs *, struct svc_req *); 94 | extern int nvpd_prog_1_freeresult (SVCXPRT *, xdrproc_t, caddr_t); 95 | 96 | #else /* K&R C */ 97 | #define nvPdSetPersistenceMode 1 98 | extern NvPdStatus * nvpdsetpersistencemode_1(); 99 | extern NvPdStatus * nvpdsetpersistencemode_1_svc(); 100 | #define nvPdGetPersistenceMode 2 101 | extern GetPersistenceModeRes * nvpdgetpersistencemode_1(); 102 | extern GetPersistenceModeRes * nvpdgetpersistencemode_1_svc(); 103 | extern int nvpd_prog_1_freeresult (); 104 | #endif /* K&R C */ 105 | #define VersionTwo 2 106 | 107 | #if defined(__STDC__) || defined(__cplusplus) 108 | #define nvPdSetPersistenceModeOnly 1 109 | extern NvPdStatus * nvpdsetpersistencemodeonly_2(SetPersistenceModeArgs *, CLIENT *); 110 | extern NvPdStatus * nvpdsetpersistencemodeonly_2_svc(SetPersistenceModeArgs *, struct svc_req *); 111 | #define nvPdSetNumaStatus 2 112 | extern NvPdStatus * nvpdsetnumastatus_2(SetNumaStatusArgs *, CLIENT *); 113 | extern NvPdStatus * nvpdsetnumastatus_2_svc(SetNumaStatusArgs *, struct svc_req *); 114 | extern int nvpd_prog_2_freeresult (SVCXPRT *, xdrproc_t, caddr_t); 115 | 116 | #else /* K&R C */ 117 | #define nvPdSetPersistenceModeOnly 1 118 | extern NvPdStatus * nvpdsetpersistencemodeonly_2(); 119 | extern NvPdStatus * nvpdsetpersistencemodeonly_2_svc(); 120 | #define nvPdSetNumaStatus 2 121 | extern NvPdStatus * nvpdsetnumastatus_2(); 122 | extern NvPdStatus * nvpdsetnumastatus_2_svc(); 123 | extern int nvpd_prog_2_freeresult (); 124 | #endif /* K&R C */ 125 | 126 | /* the xdr functions */ 127 | 128 | #if defined(__STDC__) || defined(__cplusplus) 129 | extern bool_t xdr_NvPdStatus (XDR *, NvPdStatus*); 130 | extern bool_t xdr_NvPciDevice (XDR *, NvPciDevice*); 131 | extern bool_t xdr_NvPersistenceMode (XDR *, NvPersistenceMode*); 132 | extern bool_t xdr_NvUVMPersistenceMode (XDR *, NvUVMPersistenceMode*); 133 | extern bool_t xdr_SetPersistenceModeArgs (XDR *, SetPersistenceModeArgs*); 134 | extern bool_t xdr_GetPersistenceModeArgs (XDR *, GetPersistenceModeArgs*); 135 | extern bool_t xdr_GetPersistenceModeRes (XDR *, GetPersistenceModeRes*); 136 | extern bool_t xdr_NvNumaStatus (XDR *, NvNumaStatus*); 137 | extern bool_t xdr_SetNumaStatusArgs (XDR *, SetNumaStatusArgs*); 138 | 139 | #else /* K&R C */ 140 | extern bool_t xdr_NvPdStatus (); 141 | extern bool_t xdr_NvPciDevice (); 142 | extern bool_t xdr_NvPersistenceMode (); 143 | extern bool_t xdr_NvUVMPersistenceMode (); 144 | extern bool_t xdr_SetPersistenceModeArgs (); 145 | extern bool_t xdr_GetPersistenceModeArgs (); 146 | extern bool_t xdr_GetPersistenceModeRes (); 147 | extern bool_t xdr_NvNumaStatus (); 148 | extern bool_t xdr_SetNumaStatusArgs (); 149 | 150 | #endif /* K&R C */ 151 | 152 | #ifdef __cplusplus 153 | } 154 | #endif 155 | 156 | #endif /* !_NVPD_RPC_H_RPCGEN */ 157 | -------------------------------------------------------------------------------- /command_server.c: -------------------------------------------------------------------------------- 1 | /* 2 | * nvidia-persistenced: A daemon for maintaining persistent driver state, 3 | * specifically for use by the NVIDIA Linux driver. 4 | * 5 | * Copyright (C) 2013 NVIDIA Corporation 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a 8 | * copy of this software and associated documentation files (the "Software"), 9 | * to deal in the Software without restriction, including without limitation 10 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 | * and/or sell copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | * DEALINGS IN THE SOFTWARE. 24 | * 25 | * command_server.c 26 | */ 27 | 28 | #define _GNU_SOURCE 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | #include "nvidia-persistenced.h" 35 | #include "nvpd_rpc.h" 36 | 37 | static NvPdStatus _nvpdIsClientRoot(struct svc_req *req) 38 | { 39 | struct ucred ucred = { -1, -1, -1 }; 40 | socklen_t ucred_len = sizeof(struct ucred); 41 | 42 | if (getsockopt(req->rq_xprt->xp_sock, 43 | SOL_SOCKET, SO_PEERCRED, 44 | &ucred, &ucred_len) < 0) { 45 | return NVPD_ERR_UNKNOWN; 46 | } 47 | 48 | if (ucred.uid != 0) { 49 | return NVPD_ERR_PERMISSIONS; 50 | } 51 | 52 | return NVPD_SUCCESS; 53 | } 54 | 55 | /*! 56 | * nvpdsetpersistencemode_1_svc() - This service is an RPC function 57 | * implementation to set the persistence mode of a specific device. 58 | */ 59 | NvPdStatus* nvpdsetpersistencemode_1_svc(SetPersistenceModeArgs *args, 60 | struct svc_req *req) 61 | { 62 | static NvPdStatus result; 63 | 64 | result = _nvpdIsClientRoot(req); 65 | if (result != NVPD_SUCCESS) { 66 | return &result; 67 | } 68 | 69 | result = nvPdSetDevicePersistenceMode(args->device.domain, 70 | args->device.bus, 71 | args->device.slot, 72 | args->device.function, 73 | args->mode); 74 | 75 | return &result; 76 | } 77 | 78 | /*! 79 | * nvpdsetpersistencemode_1_svc() - This service is an RPC function 80 | * implementation to get the persistence mode of a specific device. 81 | */ 82 | GetPersistenceModeRes* nvpdgetpersistencemode_1_svc(GetPersistenceModeArgs *args, 83 | struct svc_req *req) 84 | { 85 | static GetPersistenceModeRes result; 86 | NvPersistenceMode *mode = &result.GetPersistenceModeRes_u.mode; 87 | 88 | result.status = nvPdGetDevicePersistenceMode(args->device.domain, 89 | args->device.bus, 90 | args->device.slot, 91 | args->device.function, 92 | mode); 93 | 94 | return &result; 95 | } 96 | 97 | 98 | /*! 99 | * nvpdsetpersistencemodeonly_2_svc() - This service is an RPC function 100 | * implementation to set the persistence mode of a specific device 101 | * without affecting the NUMA status of the device. 102 | */ 103 | NvPdStatus* nvpdsetpersistencemodeonly_2_svc(SetPersistenceModeArgs *args, 104 | struct svc_req *req) 105 | { 106 | static NvPdStatus result; 107 | 108 | result = _nvpdIsClientRoot(req); 109 | if (result != NVPD_SUCCESS) { 110 | return &result; 111 | } 112 | 113 | result = nvPdSetDevicePersistenceModeOnly(args->device.domain, 114 | args->device.bus, 115 | args->device.slot, 116 | args->device.function, 117 | args->mode); 118 | 119 | return &result; 120 | } 121 | 122 | /*! 123 | * nvpdsetnumastatus_2_svc() - This service is an RPC function 124 | * implementation to set the NUMA status of the device. 125 | */ 126 | NvPdStatus* nvpdsetnumastatus_2_svc(SetNumaStatusArgs *args, 127 | struct svc_req *req) 128 | { 129 | static NvPdStatus result; 130 | 131 | result = _nvpdIsClientRoot(req); 132 | if (result != NVPD_SUCCESS) { 133 | return &result; 134 | } 135 | 136 | result = nvPdSetDeviceNumaStatus(args->device.domain, 137 | args->device.bus, 138 | args->device.slot, 139 | args->device.function, 140 | args->status); 141 | 142 | return &result; 143 | } 144 | -------------------------------------------------------------------------------- /option-table.h: -------------------------------------------------------------------------------- 1 | /* 2 | * nvidia-persistenced: A daemon for maintaining persistent driver state, 3 | * specifically for use by the NVIDIA Linux driver. 4 | * 5 | * Copyright (C) 2013-2025 NVIDIA Corporation 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a 8 | * copy of this software and associated documentation files (the "Software"), 9 | * to deal in the Software without restriction, including without limitation 10 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 | * and/or sell copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | * DEALINGS IN THE SOFTWARE. 24 | * 25 | * option-table.h 26 | */ 27 | 28 | #include "nvgetopt.h" 29 | 30 | enum { 31 | PERSISTENCE_MODE_OPTION = 1024, 32 | NVIDIA_CFG_PATH_OPTION, 33 | UVM_PERSISTENCE_MODE_OPTION, 34 | }; 35 | 36 | static const NVGetoptOption __options[] = { 37 | 38 | { "version", 39 | 'v', 40 | NVGETOPT_HELP_ALWAYS, 41 | NULL, 42 | "Print the utility version and exit." }, 43 | 44 | { "help", 45 | 'h', 46 | NVGETOPT_HELP_ALWAYS, 47 | NULL, 48 | "Print usage information for the command line options and exit." }, 49 | 50 | { "verbose", 51 | 'V', 52 | NVGETOPT_HELP_ALWAYS, 53 | NULL, 54 | "Controls how much information is printed. By default, " 55 | "nvidia-persistenced will only print errors and warnings to syslog for " 56 | "unexpected events, as well as startup and shutdown notices. " 57 | "Specifying this flag will cause nvidia-persistenced to also print " 58 | "notices to syslog on state transitions, such as when persistence mode " 59 | "is enabled or disabled, and informational messages on startup and " 60 | "exit." }, 61 | 62 | { "user", 63 | 'u', 64 | NVGETOPT_STRING_ARGUMENT | NVGETOPT_HELP_ALWAYS, 65 | "USERNAME", 66 | "Runs nvidia-persistenced with the user permissions of the user " 67 | "specified by the &USERNAME& argument. This user must have write access " 68 | "to the /var/run/nvidia-persistenced directory. If this directory does " 69 | "not exist, nvidia-persistenced will attempt to create it prior to " 70 | "changing the process user and group IDs. " 71 | "If this option is not given, nvidia-persistenced will not attempt " 72 | "to change the process user ID." }, 73 | 74 | { "group", 75 | 'g', 76 | NVGETOPT_STRING_ARGUMENT | NVGETOPT_HELP_ALWAYS, 77 | "GROUPNAME", 78 | "Runs nvidia-persistenced with the group permissions of the group " 79 | "specified by the &GROUPNAME& argument. " 80 | "If both this option and the --user option are given, this option " 81 | "will take precedence when determining the group ID to use. " 82 | "If this option is not given, nvidia-persistenced will use the " 83 | "primary group ID of the user specified by the --user option argument. " 84 | "If the --user option is also not given, nvidia-persistenced will not " 85 | "attempt to change the process group ID." }, 86 | 87 | { "persistence-mode", 88 | PERSISTENCE_MODE_OPTION, 89 | NVGETOPT_IS_BOOLEAN | NVGETOPT_HELP_ALWAYS, 90 | NULL, 91 | "By default, nvidia-persistenced starts with persistence mode enabled " 92 | "for all devices. Use '--no-persistence-mode' to force persistence mode " 93 | "off for all devices on startup." }, 94 | 95 | { "uvm-persistence-mode", 96 | UVM_PERSISTENCE_MODE_OPTION, 97 | NVGETOPT_IS_BOOLEAN | NVGETOPT_HELP_ALWAYS, 98 | NULL, 99 | "By default, nvidia-persistenced starts with UVM " 100 | "persistence mode disabled for all devices. Use '--uvm-persistence-mode' " 101 | "to force UVM persistence mode for supported devices on startup. " 102 | "When UVM persistence mode is enabled, a GPU cannot enter the " 103 | "PCI-Express Runtime D3 low-power state. Refer to the " 104 | "NVIDIA Accelerated Linux Graphics Driver README chapter on " 105 | "PCI-Express Runtime D3 (RTD3) Power Management. " 106 | "Enabling UVM persistence mode may result in additional GPU memory " 107 | "usage being reported, even when no applications are running."}, 108 | 109 | { "nvidia-cfg-path", 110 | NVIDIA_CFG_PATH_OPTION, 111 | NVGETOPT_STRING_ARGUMENT | NVGETOPT_HELP_ALWAYS, 112 | "PATH", 113 | "The nvidia-cfg library is used to communicate with the NVIDIA kernel " 114 | "module to query and manage GPUs in the system. This library is " 115 | "required by nvidia-persistenced. This option tells " 116 | "nvidia-persistenced where to look for this library (in case it cannot " 117 | "find it on its own). This option should normally not be needed." }, 118 | 119 | { NULL, 0, 0, NULL, NULL }, 120 | }; 121 | -------------------------------------------------------------------------------- /common-utils/common-utils.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010-2015 NVIDIA Corporation 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | #ifndef __COMMON_UTILS_H__ 24 | #define __COMMON_UTILS_H__ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #include "msg.h" 33 | 34 | #if !defined(TRUE) 35 | #define TRUE 1 36 | #endif 37 | 38 | #if !defined(FALSE) 39 | #define FALSE 0 40 | #endif 41 | 42 | #define ARRAY_LEN(_arr) (sizeof(_arr) / sizeof(_arr[0])) 43 | 44 | #ifndef NV_MIN 45 | #define NV_MIN(x,y) ((x) < (y) ? (x) : (y)) 46 | #endif 47 | #ifndef NV_MAX 48 | #define NV_MAX(x,y) ((x) > (y) ? (x) : (y)) 49 | #endif 50 | 51 | #define TAB " " 52 | #define BIGTAB " " 53 | 54 | void *nvalloc(size_t size); 55 | char *nvstrcat(const char *str, ...); 56 | char *nvvstrcat(const char *str, va_list ap); 57 | void *nvrealloc(void *ptr, size_t size); 58 | char *nvstrdup(const char *s); 59 | char *nvstrndup(const char *s, size_t n); 60 | char *nvstrtolower(char *s); 61 | char *nvstrtoupper(char *s); 62 | char *nvstrchrnul(char *s, int c); 63 | char *nvasprintf(const char *fmt, ...) NV_ATTRIBUTE_PRINTF(1, 2); 64 | void nv_append_sprintf(char **buf, const char *fmt, ...) NV_ATTRIBUTE_PRINTF(2, 3); 65 | void nvfree(void *s); 66 | 67 | char *tilde_expansion(const char *str); 68 | char *nv_prepend_to_string_list(char *list, const char *item, const char *delim); 69 | 70 | char *fget_next_line(FILE *fp, int *eof); 71 | 72 | int nv_open(const char *pathname, int flags, mode_t mode); 73 | int nv_get_file_length(const char *filename); 74 | void nv_set_file_length(const char *filename, int fd, int len); 75 | void *nv_mmap(const char *filename, size_t len, int prot, int flags, int fd); 76 | char *nv_basename(const char *path); 77 | int nv_mkdir_recursive(const char *path, const mode_t mode, 78 | char **error_str, char **log_str); 79 | char *nvdircat(const char *str, ...); 80 | char *nv_dirname(const char *path); 81 | int nv_string_to_file(const char *, const char *); 82 | 83 | char *nv_trim_space(char *string); 84 | char *nv_trim_char(char *string, char trim); 85 | char *nv_trim_char_strict(char *string, char trim); 86 | void remove_trailing_slashes(char *string); 87 | void collapse_multiple_slashes(char *s); 88 | 89 | int directory_exists(const char *dir); 90 | 91 | #if defined(__GNUC__) 92 | # define NV_INLINE __inline__ 93 | #else 94 | # define NV_INLINE 95 | #endif 96 | 97 | /* 98 | * Simple function which encodes a version number, given as major, minor, micro, 99 | * and nano, as a 64-bit unsigned integer. This is defined in an inline function 100 | * rather than as a macro for convenience so it can be examined by the debugger. 101 | * Encoded version numbers can be compared directly in version checks. 102 | */ 103 | static NV_INLINE uint64_t nv_encode_version(unsigned int major, 104 | unsigned int minor, 105 | unsigned int micro, 106 | unsigned int nano) 107 | { 108 | return (((uint64_t)(nano & 0xFFFF)) | 109 | (((uint64_t)(micro & 0xFFFF)) << 16) | 110 | (((uint64_t)(minor & 0xFFFF)) << 32) | 111 | (((uint64_t)(major & 0xFFFF)) << 48)); 112 | } 113 | 114 | /* 115 | * Wrapper macros for nv_encode_version(). For K in {2,3,4}, NV_VERSIONK() takes 116 | * a K-part version number. 117 | */ 118 | #define NV_VERSION2(major, minor) \ 119 | nv_encode_version(major, minor, 0, 0) 120 | #define NV_VERSION3(major, minor, micro) \ 121 | nv_encode_version(major, minor, micro, 0) 122 | #define NV_VERSION4(major, minor, micro, nano) \ 123 | nv_encode_version(major, minor, micro, nano) 124 | 125 | /* 126 | * Helper enum that can be used for boolean values that might or might not be 127 | * set. Care should be taken to avoid simple boolean testing, as a value of 128 | * NV_OPTIONAL_BOOL_DEFAULT would evaluate as true. 129 | * 130 | * The user is responsible for unconditionally initializing the default value of 131 | * any such booleans to NV_OPTIONAL_BOOL_DEFAULT, before any code path that 132 | * might optionally set their values is executed. 133 | */ 134 | 135 | typedef enum { 136 | NV_OPTIONAL_BOOL_DEFAULT = -1, 137 | NV_OPTIONAL_BOOL_FALSE = FALSE, 138 | NV_OPTIONAL_BOOL_TRUE = TRUE 139 | } NVOptionalBool; 140 | 141 | #define NV_ID_STRING PROGRAM_NAME ": version " NVIDIA_VERSION 142 | 143 | #endif /* __COMMON_UTILS_H__ */ 144 | -------------------------------------------------------------------------------- /common-utils/msg.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2004 NVIDIA Corporation. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | #ifndef __MSG_H__ 24 | #define __MSG_H__ 25 | 26 | #include 27 | #include 28 | 29 | 30 | /* 31 | * Define a printf format attribute macro. This definition is based on the one 32 | * from Xfuncproto.h, available in the 'xproto' package at 33 | * http://xorg.freedesktop.org/releases/individual/proto/ 34 | */ 35 | 36 | #if defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 203) 37 | # define NV_ATTRIBUTE_PRINTF(x,y) __attribute__((__format__(__printf__,x,y))) 38 | #else /* not gcc >= 2.3 */ 39 | # define NV_ATTRIBUTE_PRINTF(x,y) 40 | #endif 41 | 42 | 43 | /* 44 | * NV_VSNPRINTF(): macro that assigns buf using vsnprintf(). This is 45 | * correct for differing semantics of the vsnprintf() return value: 46 | * 47 | * -1 when the buffer is not long enough (glibc < 2.1) 48 | * 49 | * or 50 | * 51 | * the length the string would have been if the buffer had been large 52 | * enough (glibc >= 2.1) 53 | * 54 | * This macro allocates memory for buf; the caller should free it when 55 | * done. 56 | */ 57 | 58 | #define NV_FMT_BUF_LEN 256 59 | 60 | #define NV_VSNPRINTF(buf, fmt) \ 61 | do { \ 62 | if (!fmt) { \ 63 | (buf) = NULL; \ 64 | } else { \ 65 | va_list ap; \ 66 | int len, current_len = NV_FMT_BUF_LEN; \ 67 | \ 68 | while (1) { \ 69 | (buf) = nvalloc(current_len); \ 70 | \ 71 | va_start(ap, fmt); \ 72 | len = vsnprintf((buf), current_len, (fmt), ap); \ 73 | va_end(ap); \ 74 | \ 75 | if ((len > -1) && (len < current_len)) { \ 76 | break; \ 77 | } else if (len > -1) { \ 78 | current_len = len + 1; \ 79 | } else { \ 80 | current_len += NV_FMT_BUF_LEN; \ 81 | } \ 82 | \ 83 | nvfree(buf); \ 84 | } \ 85 | } \ 86 | } while (0) 87 | 88 | 89 | /* 90 | * verbosity, controls output of errors, warnings and other 91 | * information. 92 | */ 93 | 94 | typedef enum { 95 | NV_VERBOSITY_NONE = 0, /* no errors, warnings or info */ 96 | NV_VERBOSITY_ERROR, /* errors only */ 97 | NV_VERBOSITY_DEPRECATED, /* errors and deprecation messages */ 98 | NV_VERBOSITY_WARNING, /* errors and all warnings */ 99 | NV_VERBOSITY_ALL, /* errors, all warnings and other info */ 100 | NV_VERBOSITY_DEFAULT = NV_VERBOSITY_ALL 101 | } NvVerbosity; 102 | 103 | NvVerbosity nv_get_verbosity(void); 104 | void nv_set_verbosity(NvVerbosity level); 105 | 106 | 107 | /* 108 | * Formatted I/O functions 109 | */ 110 | 111 | void reset_current_terminal_width(unsigned short new_val); 112 | 113 | void nv_error_msg(const char *fmt, ...) NV_ATTRIBUTE_PRINTF(1, 2); 114 | void nv_deprecated_msg(const char *fmt, ...) NV_ATTRIBUTE_PRINTF(1, 2); 115 | void nv_warning_msg(const char *fmt, ...) NV_ATTRIBUTE_PRINTF(1, 2); 116 | void nv_info_msg(const char *prefix, 117 | const char *fmt, ...) NV_ATTRIBUTE_PRINTF(2, 3); 118 | void nv_info_msg_to_file(FILE *stream, 119 | const char *prefix, 120 | const char *fmt, ...) NV_ATTRIBUTE_PRINTF(3, 4); 121 | void nv_msg(const char *prefix, const char *fmt, ...) NV_ATTRIBUTE_PRINTF(2, 3); 122 | void nv_msg_preserve_whitespace(const char *prefix, 123 | const char *fmt, ...) NV_ATTRIBUTE_PRINTF(2, 3); 124 | 125 | 126 | /* 127 | * TextRows structure and helper functions 128 | */ 129 | 130 | typedef struct { 131 | char **t; /* the text rows */ 132 | int n; /* number of rows */ 133 | int m; /* maximum row length */ 134 | } TextRows; 135 | 136 | TextRows *nv_format_text_rows(const char *prefix, const char *str, int width, 137 | int word_boundary); 138 | void nv_text_rows_append(TextRows *t, const char *msg); 139 | void nv_concat_text_rows(TextRows *t0, TextRows *t1); 140 | void nv_free_text_rows(TextRows *t); 141 | 142 | 143 | #endif /* __MSG_H__ */ 144 | -------------------------------------------------------------------------------- /options.c: -------------------------------------------------------------------------------- 1 | /* 2 | * nvidia-persistenced: A daemon for maintaining persistent driver state, 3 | * specifically for use by the NVIDIA Linux driver. 4 | * 5 | * Copyright (C) 2013-2025 NVIDIA Corporation 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a 8 | * copy of this software and associated documentation files (the "Software"), 9 | * to deal in the Software without restriction, including without limitation 10 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 | * and/or sell copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | * DEALINGS IN THE SOFTWARE. 24 | * 25 | * options.c 26 | */ 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | 36 | #include "common-utils.h" 37 | #include "msg.h" 38 | #include "nvgetopt.h" 39 | #include "nvidia-persistenced.h" 40 | #include "nvpd_defs.h" 41 | #include "option-table.h" 42 | 43 | #define TAB " " 44 | #define BIGTAB " " 45 | 46 | /* 47 | * print_version() - print basic version information about the utility. 48 | */ 49 | static void print_version(void) 50 | { 51 | nv_info_msg(NULL, ""); 52 | nv_info_msg(NULL, "%s", NV_ID_STRING); 53 | nv_info_msg(NULL, ""); 54 | nv_info_msg(TAB, "The NVIDIA Persistence Daemon."); 55 | nv_info_msg(NULL, ""); 56 | nv_info_msg(TAB, "A tool for maintaining persistent driver state, " 57 | "specifically for use by the NVIDIA Linux driver."); 58 | nv_info_msg(NULL, ""); 59 | nv_info_msg(TAB, "Copyright (C) 2013-2025 NVIDIA Corporation."); 60 | nv_info_msg(NULL, ""); 61 | } 62 | 63 | /* 64 | * print_help_callback() - used by nvgetopt to format help output. 65 | */ 66 | static void print_help_callback(const char *name, const char *description) 67 | { 68 | nv_info_msg(TAB, "%s", name); 69 | nv_info_msg(BIGTAB, "%s", description); 70 | nv_info_msg(NULL, ""); 71 | } 72 | 73 | /* 74 | * print_help() - loop through the __options, and print the description of 75 | * each option. 76 | */ 77 | static void print_help(void) 78 | { 79 | print_version(); 80 | 81 | nv_info_msg(NULL, ""); 82 | nv_info_msg(NULL, NVPD_DAEMON_NAME " [options]"); 83 | nv_info_msg(NULL, ""); 84 | 85 | nvgetopt_print_help(__options, 0, print_help_callback); 86 | 87 | nv_info_msg(NULL, "For more detailed usage information, please see the " 88 | "nvidia-persistenced manpage and the \"Using the " 89 | "nvidia-persistenced Utility\" section of the NVIDIA " 90 | "Linux Graphics Driver README."); 91 | nv_info_msg(NULL, ""); 92 | } 93 | 94 | /* 95 | * setup_option_defaults() - loads sensible defaults for the commandline 96 | * options. 97 | */ 98 | static void setup_option_defaults(NvPdOptions *options) 99 | { 100 | options->persistence_mode = NV_PERSISTENCE_MODE_ENABLED; 101 | options->uvm_persistence_mode = NV_UVM_PERSISTENCE_MODE_DISABLED; 102 | options->nvidia_cfg_path = NULL; 103 | options->verbose = 0; 104 | options->uid = getuid(); 105 | options->gid = getgid(); 106 | } 107 | 108 | /* 109 | * parse_options() - fill in an NvPdOptions structure with any pertinent data 110 | * from the commandline arguments. 111 | */ 112 | void parse_options(int argc, char *argv[], NvPdOptions *options) 113 | { 114 | int short_name; 115 | int boolval; 116 | char *strval; 117 | struct passwd *pw_entry; 118 | struct group *gr_entry; 119 | int group_specified = 0; 120 | 121 | setup_option_defaults(options); 122 | 123 | while (1) 124 | { 125 | short_name = nvgetopt(argc, argv, __options, &strval, &boolval, 126 | NULL, /* intval */ 127 | NULL, /* doubleval */ 128 | NULL); /* disable */ 129 | if (short_name == -1) 130 | { 131 | break; 132 | } 133 | 134 | switch (short_name) 135 | { 136 | case 'v': 137 | print_version(); 138 | exit(EXIT_SUCCESS); 139 | break; 140 | case 'h': 141 | print_help(); 142 | exit(EXIT_SUCCESS); 143 | break; 144 | case 'V': 145 | options->verbose = 1; 146 | break; 147 | case 'u': 148 | pw_entry = getpwnam(strval); 149 | if (pw_entry == NULL) { 150 | nv_error_msg("Failed to find user ID of user '%s': %s", 151 | strval, strerror(errno)); 152 | exit(EXIT_FAILURE); 153 | } 154 | options->uid = pw_entry->pw_uid; 155 | if (!group_specified) { 156 | options->gid = pw_entry->pw_gid; 157 | } 158 | break; 159 | case 'g': 160 | gr_entry = getgrnam(strval); 161 | if (gr_entry == NULL) { 162 | nv_error_msg("Failed to find group ID of group '%s': %s", 163 | strval, strerror(errno)); 164 | exit(EXIT_FAILURE); 165 | } 166 | /* overrides the gid from the -u option, if already given */ 167 | options->gid = gr_entry->gr_gid; 168 | group_specified = 1; 169 | break; 170 | case PERSISTENCE_MODE_OPTION: 171 | if (boolval) { 172 | options->persistence_mode = NV_PERSISTENCE_MODE_ENABLED; 173 | } else { 174 | options->persistence_mode = NV_PERSISTENCE_MODE_DISABLED; 175 | } 176 | break; 177 | case UVM_PERSISTENCE_MODE_OPTION: 178 | if (boolval) { 179 | options->uvm_persistence_mode = NV_UVM_PERSISTENCE_MODE_ENABLED; 180 | } else { 181 | options->uvm_persistence_mode = NV_UVM_PERSISTENCE_MODE_DISABLED; 182 | } 183 | break; 184 | case NVIDIA_CFG_PATH_OPTION: 185 | options->nvidia_cfg_path = strval; 186 | break; 187 | default: 188 | nv_error_msg("Invalid commandline, please run `%s --help` for " 189 | "usage information.", argv[0]); 190 | exit(EXIT_SUCCESS); 191 | } 192 | } 193 | } 194 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # nvidia-persistenced: A daemon for maintaining persistent driver state, 3 | # specifically for use by the NVIDIA Linux driver. 4 | # 5 | # Copyright (C) 2013 NVIDIA Corporation 6 | # 7 | # Permission is hereby granted, free of charge, to any person obtaining a 8 | # copy of this software and associated documentation files (the "Software"), 9 | # to deal in the Software without restriction, including without limitation 10 | # the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 | # and/or sell copies of the Software, and to permit persons to whom the 12 | # Software is furnished to do so, subject to the following conditions: 13 | # 14 | # The above copyright notice and this permission notice shall be included in 15 | # all copies or substantial portions of the Software. 16 | # 17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | # DEALINGS IN THE SOFTWARE. 24 | # 25 | 26 | ############################################################################## 27 | # include common variables and functions 28 | ############################################################################## 29 | 30 | include utils.mk 31 | 32 | ############################################################################## 33 | # assign variables 34 | ############################################################################## 35 | 36 | NVIDIA_PERSISTENCED = $(OUTPUTDIR)/nvidia-persistenced 37 | 38 | NVIDIA_PERSISTENCED_PROGRAM_NAME = "nvidia-persistenced" 39 | 40 | MANPAGE_GZIP ?= 1 41 | 42 | MANPAGE_not_gzipped = $(OUTPUTDIR)/nvidia-persistenced.1 43 | MANPAGE_gzipped = $(OUTPUTDIR)/nvidia-persistenced.1.gz 44 | 45 | ifeq ($(MANPAGE_GZIP),1) 46 | MANPAGE = $(MANPAGE_gzipped) 47 | else 48 | MANPAGE = $(MANPAGE_not_gzipped) 49 | endif 50 | GEN_MANPAGE_OPTS = $(OUTPUTDIR_ABSOLUTE)/gen-manpage-opts 51 | OPTIONS_1_INC = $(OUTPUTDIR)/options.1.inc 52 | 53 | ############################################################################## 54 | # The calling Makefile may export any of the following variables; we assign 55 | # default values if they are not exported by the caller 56 | ############################################################################## 57 | 58 | RPC_DIR ?= . 59 | NVIDIA_CFG_DIR ?= . 60 | NVIDIA_NUMA_DIR ?= . 61 | NV_IOCTL_INC_DIR ?= . 62 | 63 | ############################################################################## 64 | # The common-utils directory may be in one of two places: either elsewhere in 65 | # the driver source tree when building nvidia-persistenced as part of the 66 | # NVIDIA driver build (in which case, COMMON_UTILS_DIR should be defined by 67 | # the calling makefile), or directly in the source directory when building 68 | # from the nvidia-persistenced source tarball (in which case, the below 69 | # conditional assignment should be used) 70 | ############################################################################## 71 | 72 | COMMON_UTILS_DIR ?= common-utils 73 | 74 | # include the list of source files; defines SRC 75 | include dist-files.mk 76 | 77 | include $(COMMON_UTILS_DIR)/src.mk 78 | SRC += $(addprefix $(COMMON_UTILS_DIR)/,$(COMMON_UTILS_SRC)) 79 | 80 | # rpcgen generates code that emits unused variable warnings and suspicious 81 | # function type casts 82 | $(call BUILD_OBJECT_LIST,$(RPC_SRC)): CFLAGS += -Wno-unused-variable 83 | suppress_cast_func_type_warning := $(call TEST_CC_ARG,-Wno-cast-function-type) 84 | $(call BUILD_OBJECT_LIST,$(RPC_SRC)): CFLAGS += $(suppress_cast_func_type_warning) 85 | 86 | OBJS = $(call BUILD_OBJECT_LIST,$(SRC)) 87 | 88 | common_cflags += -I $(COMMON_UTILS_DIR) 89 | common_cflags += -I $(NVIDIA_CFG_DIR) 90 | common_cflags += -I $(NVIDIA_NUMA_DIR) 91 | common_cflags += -I $(NV_IOCTL_INC_DIR) 92 | common_cflags += -I $(RPC_DIR) 93 | common_cflags += -I $(OUTPUTDIR) 94 | common_cflags += -I . 95 | 96 | common_cflags += -DPROGRAM_NAME=\"$(NVIDIA_PERSISTENCED_PROGRAM_NAME)\" 97 | common_cflags += -D_BSD_SOURCE 98 | common_cflags += -D_XOPEN_SOURCE=500 99 | common_cflags += -std=c99 100 | 101 | CFLAGS += $(common_cflags) 102 | HOST_CFLAGS += $(common_cflags) 103 | 104 | ifneq ($(TARGET_OS),FreeBSD) 105 | LIBS += -ldl 106 | endif 107 | 108 | USE_TIRPC ?= $(shell $(PKG_CONFIG) --atleast-version=1.0.1 libtirpc && echo 1) 109 | 110 | ifeq ($(USE_TIRPC),1) 111 | TIRPC_LDFLAGS ?= $(shell $(PKG_CONFIG) --libs libtirpc) 112 | TIRPC_CFLAGS ?= $(shell $(PKG_CONFIG) --cflags libtirpc) 113 | $(call BUILD_OBJECT_LIST,$(SRC)): CFLAGS += $(TIRPC_CFLAGS) 114 | LIBS += $(TIRPC_LDFLAGS) 115 | endif 116 | 117 | ############################################################################## 118 | # build rules 119 | ############################################################################## 120 | 121 | .PHONY: all 122 | all: $(NVIDIA_PERSISTENCED) $(MANPAGE) 123 | 124 | .PHONY: install 125 | install: NVIDIA_PERSISTENCED_install MANPAGE_install 126 | 127 | .PHONY: NVIDIA_PERSISTENCED_install 128 | NVIDIA_PERSISTENCED_install: $(NVIDIA_PERSISTENCED) 129 | $(MKDIR) $(BINDIR) 130 | $(INSTALL) $(INSTALL_BIN_ARGS) $< $(BINDIR)/$(notdir $<) 131 | 132 | .PHONY: MANPAGE_install 133 | MANPAGE_install: $(MANPAGE) 134 | $(MKDIR) $(MANDIR) 135 | $(INSTALL) $(INSTALL_BIN_ARGS) $< $(MANDIR)/$(notdir $<) 136 | 137 | $(eval $(call DEBUG_INFO_RULES, $(NVIDIA_PERSISTENCED))) 138 | $(NVIDIA_PERSISTENCED).unstripped: $(OBJS) 139 | $(call quiet_cmd,LINK) $(CFLAGS) $(LDFLAGS) $(BIN_LDFLAGS) \ 140 | -o $@ $(OBJS) $(LIBS) 141 | 142 | # define the rule to build each object file 143 | $(foreach src, $(SRC), $(eval $(call DEFINE_OBJECT_RULE,TARGET,$(src)))) 144 | 145 | .PHONY: clean clobber 146 | clean clobber: 147 | $(RM) -rf $(NVIDIA_PERSISTENCED) $(MANPAGE) *~ \ 148 | $(OUTPUTDIR)/*.o $(OUTPUTDIR)/*.d \ 149 | $(GEN_MANPAGE_OPTS) $(OPTIONS_1_INC) 150 | 151 | ############################################################################## 152 | # documentation 153 | ############################################################################## 154 | 155 | AUTO_TEXT = ".\\\" WARNING: THIS FILE IS AUTO_GENERATED! Edit $< instead." 156 | 157 | .PHONY: doc 158 | doc: $(MANPAGE) 159 | 160 | GEN_MANPAGE_OPTS_SRC = gen-manpage-opts.c 161 | GEN_MANPAGE_OPTS_SRC += $(COMMON_UTILS_DIR)/gen-manpage-opts-helper.c 162 | 163 | GEN_MANPAGE_OPTS_OBJS = $(call BUILD_OBJECT_LIST,$(GEN_MANPAGE_OPTS_SRC)) 164 | 165 | $(foreach src,$(GEN_MANPAGE_OPTS_SRC), \ 166 | $(eval $(call DEFINE_OBJECT_RULE,HOST,$(src)))) 167 | 168 | $(GEN_MANPAGE_OPTS): $(GEN_MANPAGE_OPTS_OBJS) 169 | $(call quiet_cmd,HOST_LINK) \ 170 | $(HOST_CFLAGS) $(HOST_LDFLAGS) $(HOST_BIN_LDFLAGS) $^ -o $@ 171 | 172 | $(OPTIONS_1_INC): $(GEN_MANPAGE_OPTS) 173 | @$< > $@ 174 | 175 | $(MANPAGE_not_gzipped): nvidia-persistenced.1.m4 $(OPTIONS_1_INC) $(VERSION_MK) 176 | $(call quiet_cmd,M4) -D__HEADER__=$(AUTO_TEXT) -I $(OUTPUTDIR) \ 177 | -D__VERSION__=$(NVIDIA_VERSION) \ 178 | -D__DATE__="`$(DATE) +%F`" \ 179 | -D__BUILD_OS__=$(TARGET_OS) \ 180 | $< > $@ 181 | 182 | $(MANPAGE_gzipped): $(MANPAGE_not_gzipped) 183 | $(GZIP_CMD) -9nf < $< > $@ 184 | -------------------------------------------------------------------------------- /common-utils/gen-manpage-opts-helper.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #include "nvgetopt.h" 29 | #include "gen-manpage-opts-helper.h" 30 | #include "common-utils.h" 31 | 32 | static void print_option(const NVGetoptOption *o) 33 | { 34 | char scratch[64]; 35 | const char *s; 36 | int j, len; 37 | 38 | int italics, bold, omitWhiteSpace, firstchar; 39 | 40 | /* if we are going to need the argument, process it now */ 41 | if (o->flags & NVGETOPT_HAS_ARGUMENT) { 42 | if (o->arg_name) { 43 | strcpy(scratch, o->arg_name); 44 | } else { 45 | len = strlen(o->name); 46 | for (j = 0; j < len; j++) scratch[j] = toupper(o->name[j]); 47 | scratch[len] = '\0'; 48 | } 49 | } 50 | 51 | printf(".TP\n.BI \""); 52 | /* Print the name of the option */ 53 | /* XXX We should backslashify the '-' characters in o->name. */ 54 | 55 | if (isalpha(o->val)) { 56 | /* '\-c' */ 57 | printf("\\-%c", o->val); 58 | 59 | if (o->flags & NVGETOPT_HAS_ARGUMENT) { 60 | /* ' " "ARG" "' */ 61 | printf(" \" \"%s\" \"", scratch); 62 | } 63 | /* ', ' */ 64 | printf(", "); 65 | } 66 | 67 | /* '\-\-name' */ 68 | printf("\\-\\-%s", o->name); 69 | 70 | /* '=" "ARG' */ 71 | if (o->flags & NVGETOPT_HAS_ARGUMENT) { 72 | printf("=\" \"%s", scratch); 73 | 74 | /* '" "' */ 75 | if ((o->flags & NVGETOPT_IS_BOOLEAN) || 76 | (o->flags & NVGETOPT_ALLOW_DISABLE)) { 77 | printf("\" \""); 78 | } 79 | } 80 | 81 | /* ', \-\-no\-name' */ 82 | if (((o->flags & NVGETOPT_IS_BOOLEAN) && 83 | !(o->flags & NVGETOPT_HAS_ARGUMENT)) || 84 | (o->flags & NVGETOPT_ALLOW_DISABLE)) { 85 | printf(", \\-\\-no\\-%s", o->name); 86 | } 87 | 88 | printf("\"\n"); 89 | 90 | /* Print the option description */ 91 | /* XXX Each sentence should be on its own line! */ 92 | 93 | /* 94 | * Print the option description: write each character one at a 95 | * time (ugh) so that we can special-case a few characters: 96 | * 97 | * '&' : toggles italics on and off 98 | * '^' : toggles bold on and off 99 | * '-' : is backslashified: "\-" 100 | * '\n': resets the first character flag 101 | * '.' : must not be the first character of a line 102 | * '\'': must not be the first character of a line 103 | * 104 | * Trailing whitespace is omitted when italics or bold is on 105 | */ 106 | 107 | italics = FALSE; 108 | bold = FALSE; 109 | omitWhiteSpace = FALSE; 110 | firstchar = TRUE; 111 | 112 | for (s = o->description; s && *s; s++) { 113 | 114 | switch (*s) { 115 | case '&': 116 | if (italics) { 117 | printf("\n"); 118 | } else { 119 | printf("\n.I "); 120 | } 121 | omitWhiteSpace = italics; 122 | firstchar = italics; 123 | italics = !italics; 124 | break; 125 | case '^': 126 | if (bold) { 127 | printf("\n"); 128 | } else { 129 | printf("\n.B "); 130 | } 131 | omitWhiteSpace = bold; 132 | firstchar = bold; 133 | bold = !bold; 134 | break; 135 | case '-': 136 | printf("\\-"); 137 | omitWhiteSpace = FALSE; 138 | firstchar = FALSE; 139 | break; 140 | case ' ': 141 | if (!omitWhiteSpace) { 142 | printf(" "); 143 | firstchar = FALSE; 144 | } 145 | break; 146 | case '\n': 147 | printf("\n"); 148 | omitWhiteSpace = FALSE; 149 | firstchar = TRUE; 150 | break; 151 | case '.': 152 | if (firstchar) { 153 | fprintf(stderr, "Error: *roff can't start a line with '.' " 154 | "If you used '&' or '^' to format text in the " 155 | "description of the '%s' option, please add some " 156 | "text before the end of the sentence, so that a " 157 | "valid manpage can be generated.\n", o->name); 158 | exit(1); 159 | } 160 | /* fall through */ 161 | case '\'': 162 | if (firstchar) { 163 | fprintf(stderr, "Error: *roff can't start a line with '\''. " 164 | "If you started a line with '\'' in the description " 165 | "of the '%s' option, please add some text at the " 166 | "beginning of the sentence, so that a valid manpage " 167 | "can be generated.\n", o->name); 168 | exit(1); 169 | } 170 | /* fall through */ 171 | default: 172 | printf("%c", *s); 173 | omitWhiteSpace = FALSE; 174 | firstchar = FALSE; 175 | break; 176 | } 177 | } 178 | 179 | printf("\n"); 180 | } 181 | 182 | void gen_manpage_opts_helper(const NVGetoptOption *options) 183 | { 184 | int i; 185 | int has_advanced_options = 0; 186 | 187 | /* Print the "simple" options; i.e. the ones you get with --help. */ 188 | printf(".SH OPTIONS\n"); 189 | for (i = 0; options[i].name; i++) { 190 | const NVGetoptOption *o = &options[i]; 191 | 192 | if (!o->description) { 193 | continue; 194 | } 195 | 196 | if (!(o->flags & NVGETOPT_HELP_ALWAYS)) { 197 | has_advanced_options = 1; 198 | continue; 199 | } 200 | 201 | print_option(o); 202 | } 203 | 204 | if (has_advanced_options) { 205 | /* 206 | * If any exist, print the advanced options; i.e., the ones 207 | * you get with --advanced-help 208 | */ 209 | printf(".SH \"ADVANCED OPTIONS\"\n"); 210 | for (i = 0; options[i].name; i++) { 211 | const NVGetoptOption *o = &options[i]; 212 | 213 | if (!o->description) { 214 | continue; 215 | } 216 | 217 | if (o->flags & NVGETOPT_HELP_ALWAYS) { 218 | continue; 219 | } 220 | 221 | print_option(o); 222 | } 223 | } 224 | } 225 | -------------------------------------------------------------------------------- /common-utils/nvgetopt.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2004-2010 NVIDIA Corporation 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | #ifndef __NVGETOPT_H__ 24 | #define __NVGETOPT_H__ 25 | 26 | #define NVGETOPT_FALSE 0 27 | #define NVGETOPT_TRUE 1 28 | 29 | 30 | /* 31 | * mask of bits not used by nvgetopt in NVGetoptOption::flags; 32 | * these bits are available for use within specific users of 33 | * nvgetopt 34 | */ 35 | 36 | #define NVGETOPT_UNUSED_FLAG_RANGE 0xffff0000 37 | 38 | /* 39 | * indicates that the option is a boolean value; the presence of the 40 | * option will be interpreted as a TRUE value; if the option is 41 | * prepended with '--no-', the option will be interpreted as a FALSE 42 | * value. On success, nvgetopt will return the parsed boolean value 43 | * through 'boolval'. 44 | */ 45 | 46 | #define NVGETOPT_IS_BOOLEAN 0x0001 47 | 48 | 49 | /* 50 | * indicates that the option takes an argument to be interpreted as a 51 | * string; on success, nvgetopt will return the parsed string argument 52 | * through 'strval'. 53 | */ 54 | 55 | #define NVGETOPT_STRING_ARGUMENT 0x0002 56 | 57 | 58 | /* 59 | * indicates that the option takes an argument to be interpreted as an 60 | * integer; on success, nvgetopt will return the parsed integer 61 | * argument through 'intval'. 62 | */ 63 | 64 | #define NVGETOPT_INTEGER_ARGUMENT 0x0004 65 | 66 | 67 | /* 68 | * indicates that the option takes an argument to be interpreted as 69 | * an double; on success, nvgetopt will return the parsed double 70 | * argument through 'doubleval'. 71 | */ 72 | 73 | #define NVGETOPT_DOUBLE_ARGUMENT 0x0008 74 | 75 | 76 | /* helper macro */ 77 | 78 | #define NVGETOPT_HAS_ARGUMENT (NVGETOPT_STRING_ARGUMENT | \ 79 | NVGETOPT_INTEGER_ARGUMENT | \ 80 | NVGETOPT_DOUBLE_ARGUMENT) 81 | 82 | /* 83 | * indicates that the option, which normally takes an argument, can be 84 | * disabled if the option is prepended with '--no-', in which case, 85 | * the option does not take an argument. If the option is disabled, 86 | * nvgetopt will return TRUE through 'disable_val'. 87 | * 88 | * Note that NVGETOPT_ALLOW_DISABLE can only be used with options that 89 | * take arguments. 90 | */ 91 | 92 | #define NVGETOPT_ALLOW_DISABLE 0x0010 93 | 94 | 95 | /* 96 | * indicates that the argument for this option is optional; if no 97 | * argument is present (either the option is already at the end of the 98 | * argv array, or the next option in argv starts with '-'), then the 99 | * option is returned without an argument. 100 | */ 101 | 102 | #define NVGETOPT_ARGUMENT_IS_OPTIONAL 0x0020 103 | 104 | 105 | /* 106 | * The NVGETOPT_HELP_ALWAYS flag is not used by nvgetopt() itself, but 107 | * is often used by other users of NVGetoptOption tables, who print 108 | * out basic and advanced help. In such cases, OPTION_HELP_ALWAYS is 109 | * used to indicate that the help for the option should always be 110 | * printed. 111 | */ 112 | 113 | #define NVGETOPT_HELP_ALWAYS 0x0040 114 | 115 | 116 | /* 117 | * Indicates that an option is deprecated. The description field of the 118 | * NVGetoptOption, if set, may be used to store text explaining why the 119 | * option is no longer used. 120 | */ 121 | 122 | #define NVGETOPT_IS_DEPRECATED 0x0080 123 | 124 | /* 125 | * These flags indicate that a particular boolean or disableable value is no 126 | * longer supported. They can be used together with NVGETOPT_DEPRECATED in 127 | * order to differentiate between deprecated boolean values or enable/disable 128 | * states that will be ignored, and unsupported boolean values or enable/disable 129 | * states that are invalid. 130 | */ 131 | 132 | #define NVGETOPT_DISABLE_IS_INVALID 0x0100 133 | #define NVGETOPT_ENABLE_IS_INVALID 0x0200 134 | 135 | typedef struct { 136 | const char *name; 137 | int val; 138 | unsigned int flags; 139 | const char *arg_name; /* not used by nvgetopt() */ 140 | const char *description; /* not used by nvgetopt() */ 141 | } NVGetoptOption; 142 | 143 | 144 | /* 145 | * nvgetopt() - see the glibc getopt_long(3) manpage for usage 146 | * description. Options can be prepended with "--", "-", or "--no-". 147 | * 148 | * A global variable stores the current index into the argv array, so 149 | * subsequent calls to nvgetopt() will advance through argv[]. 150 | * 151 | * On success, the matching NVGetoptOption.val is returned. 152 | * 153 | * If the NVGETOPT_IS_BOOLEAN flag is set, boolval will be set to TRUE 154 | * (or FALSE, if the option string was prepended with "--no-"). 155 | * 156 | * disable_val will be assigned TRUE if the option string was 157 | * prepended with "--no-", otherwise it will be assigned FALSE. 158 | * 159 | * If an argument is successfully parsed, one of strval, intval, or 160 | * doubleval will be assigned, based on which of 161 | * NVGETOPT_STRING_ARGUMENT, NVGETOPT_INTEGER_ARGUMENT, or 162 | * NVGETOPT_DOUBLE_ARGUMENT is set in the option's flags. If strval 163 | * is assigned to a non-NULL value by nvgetopt, then it is the 164 | * caller's responsibility to free the string when done with it. 165 | * 166 | * On failure, an error is printed to stderr, and 0 is returned. 167 | * 168 | * When there are no more options to parse, -1 is returned. 169 | */ 170 | 171 | int nvgetopt(int argc, 172 | char *argv[], 173 | const NVGetoptOption *options, 174 | char **strval, 175 | int *boolval, 176 | int *intval, 177 | double *doubleval, 178 | int *disable_val); 179 | 180 | /* 181 | * nvgetopt_print_help() - print a help message for each option in the 182 | * provided NVGetoptOption array. This is useful for a utility's 183 | * "--help" output. 184 | * 185 | * Options will only be printed if they have every bit set that 186 | * include_mask includes. 187 | * 188 | * For each option, the provided callback function will be called with 189 | * two strings: a name string that lists the option's name, and a 190 | * description string for the option. The callback function is 191 | * responsible for actually printing these strings. Examples: 192 | * 193 | * name = "-v, --version"; 194 | * description = "Print usage information for the common commandline " 195 | * "options and exit."; 196 | */ 197 | 198 | typedef void nvgetopt_print_help_callback_ptr(const char *name, 199 | const char *description); 200 | 201 | void nvgetopt_print_help(const NVGetoptOption *options, 202 | unsigned int include_mask, 203 | nvgetopt_print_help_callback_ptr callback); 204 | 205 | #endif /* __NVGETOPT_H__ */ 206 | -------------------------------------------------------------------------------- /common-utils/msg.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2004 NVIDIA Corporation. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | #define _GNU_SOURCE // needed for fileno 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #if defined(__sun) 33 | #include 34 | #endif 35 | 36 | #include "msg.h" 37 | #include "common-utils.h" 38 | 39 | 40 | /* 41 | * verbosity, controls output of errors, warnings and other 42 | * information. 43 | */ 44 | 45 | static NvVerbosity __verbosity = NV_VERBOSITY_DEFAULT; 46 | 47 | NvVerbosity nv_get_verbosity(void) 48 | { 49 | return __verbosity; 50 | } 51 | 52 | void nv_set_verbosity(NvVerbosity level) 53 | { 54 | __verbosity = level; 55 | } 56 | 57 | 58 | /****************************************************************************/ 59 | /* Formatted I/O functions */ 60 | /****************************************************************************/ 61 | 62 | #define DEFAULT_WIDTH 75 63 | 64 | static unsigned short __terminal_width = 0; 65 | 66 | /* 67 | * reset_current_terminal_width() - if new_val is zero, then use the 68 | * TIOCGWINSZ ioctl to get the current width of the terminal, and 69 | * assign it the value to __terminal_width. If the ioctl fails, use a 70 | * hardcoded constant. If new_val is non-zero, then use new_val. 71 | */ 72 | 73 | void reset_current_terminal_width(unsigned short new_val) 74 | { 75 | struct winsize ws; 76 | 77 | if (new_val) { 78 | __terminal_width = new_val; 79 | return; 80 | } 81 | 82 | if (ioctl(STDERR_FILENO, TIOCGWINSZ, &ws) == -1 || ws.ws_col == 0) { 83 | __terminal_width = DEFAULT_WIDTH; 84 | } else { 85 | __terminal_width = ws.ws_col - 1; 86 | } 87 | } 88 | 89 | 90 | static void format(FILE *stream, const char *prefix, const char *buf, 91 | const int whitespace) 92 | { 93 | if (isatty(fileno(stream))) { 94 | int i; 95 | TextRows *t; 96 | 97 | if (!__terminal_width) reset_current_terminal_width(0); 98 | 99 | t = nv_format_text_rows(prefix, buf, __terminal_width, whitespace); 100 | 101 | for (i = 0; i < t->n; i++) fprintf(stream, "%s\n", t->t[i]); 102 | 103 | nv_free_text_rows(t); 104 | } else { 105 | fprintf(stream, "%s%s\n", prefix ? prefix : "", buf); 106 | } 107 | } 108 | 109 | 110 | #define NV_FORMAT(stream, prefix, fmt, whitespace) \ 111 | do { \ 112 | char *buf; \ 113 | NV_VSNPRINTF(buf, fmt); \ 114 | format(stream, prefix, buf, whitespace); \ 115 | free (buf); \ 116 | } while (0) 117 | 118 | 119 | /* 120 | * nv_error_msg() - print an error message, nicely formatted using the 121 | * format() function. 122 | * 123 | * This function should be used for all errors. 124 | */ 125 | 126 | void nv_error_msg(const char *fmt, ...) 127 | { 128 | if (__verbosity < NV_VERBOSITY_ERROR) return; 129 | 130 | format(stderr, NULL, "", TRUE); 131 | NV_FORMAT(stderr, "ERROR: ", fmt, TRUE); 132 | format(stderr, NULL, "", TRUE); 133 | } /* nv_error_msg() */ 134 | 135 | 136 | /* 137 | * nv_deprecated_msg() - print a deprecation message, nicely formatted using 138 | * the format() function. 139 | * 140 | * This function should be used for all deprecation messages. 141 | */ 142 | 143 | void nv_deprecated_msg(const char *fmt, ...) 144 | { 145 | if (__verbosity < NV_VERBOSITY_DEPRECATED) return; 146 | 147 | format(stderr, NULL, "", TRUE); 148 | NV_FORMAT(stderr, "DEPRECATED: ", fmt, TRUE); 149 | format(stderr, NULL, "", TRUE); 150 | } 151 | 152 | 153 | /* 154 | * nv_warning_msg() - print a warning message, nicely formatted using 155 | * the format() function. 156 | * 157 | * This function should be used for all warnings. 158 | */ 159 | 160 | void nv_warning_msg(const char *fmt, ...) 161 | { 162 | if (__verbosity < NV_VERBOSITY_WARNING) return; 163 | 164 | format(stderr, NULL, "", TRUE); 165 | NV_FORMAT(stderr, "WARNING: ", fmt, TRUE); 166 | format(stderr, NULL, "", TRUE); 167 | } /* nv_warning_msg() */ 168 | 169 | 170 | /* 171 | * nv_info_msg() - print an info message, nicely formatted using 172 | * the format() function. 173 | * 174 | * This function should be used to display verbose information. 175 | */ 176 | 177 | void nv_info_msg(const char *prefix, const char *fmt, ...) 178 | { 179 | if (__verbosity < NV_VERBOSITY_ALL) return; 180 | 181 | NV_FORMAT(stdout, prefix, fmt, TRUE); 182 | } /* nv_info_msg() */ 183 | 184 | 185 | /* 186 | * nv_info_msg_to_file() - Prints the message, just like nv_info_msg() 187 | * using format() the difference is, it prints to any stream defined by 188 | * the corresponding argument. 189 | */ 190 | 191 | void nv_info_msg_to_file(FILE *stream, const char *prefix, const char *fmt, ...) 192 | { 193 | if (__verbosity < NV_VERBOSITY_ALL) return; 194 | 195 | NV_FORMAT(stream, prefix, fmt, TRUE); 196 | } /* nv_info_msg_to_file() */ 197 | 198 | 199 | /* 200 | * nv_msg() - print a message, nicely formatted using the format() 201 | * function. 202 | * 203 | * This function should be used to display messages independent 204 | * of the verbosity level. 205 | */ 206 | 207 | void nv_msg(const char *prefix, const char *fmt, ...) 208 | { 209 | NV_FORMAT(stdout, prefix, fmt, TRUE); 210 | } /* nv_msg() */ 211 | 212 | 213 | /* 214 | * nv_msg_preserve_whitespace() - Prints the message, just like nv_msg() 215 | * using format(), the difference is, whitespace characters are not 216 | * skipped during the text processing. 217 | */ 218 | 219 | void nv_msg_preserve_whitespace(const char *prefix, const char *fmt, ...) 220 | { 221 | NV_FORMAT(stdout, prefix, fmt, FALSE); 222 | } /* nv_msg_preserve_whitespace() */ 223 | 224 | 225 | /* 226 | * XXX gcc's '-ansi' option causes vsnprintf to not be defined, so 227 | * declare the prototype here. 228 | */ 229 | 230 | #if defined(__STRICT_ANSI__) 231 | int vsnprintf(char *str, size_t size, const char *format, 232 | va_list ap); 233 | #endif 234 | 235 | 236 | /****************************************************************************/ 237 | /* TextRows helper functions */ 238 | /****************************************************************************/ 239 | 240 | /* 241 | * nv_format_text_rows() - this function breaks the given string str 242 | * into some number of rows, where each row is not longer than the 243 | * specified width. 244 | * 245 | * If prefix is non-NULL, the first line is prepended with the prefix, 246 | * and subsequent lines are indented to line up with the prefix. 247 | * 248 | * If word_boundary is TRUE, then attempt to only break lines on 249 | * boundaries between words. 250 | */ 251 | 252 | TextRows *nv_format_text_rows(const char *prefix, const char *str, int width, 253 | int word_boundary) 254 | { 255 | int len, prefix_len, z, w, i; 256 | char *line, *buf, *local_prefix, *a, *b, *c; 257 | TextRows *t; 258 | 259 | /* initialize the TextRows structure */ 260 | 261 | t = (TextRows *) malloc(sizeof(TextRows)); 262 | 263 | if (!t) return NULL; 264 | 265 | t->t = NULL; 266 | t->n = 0; 267 | t->m = 0; 268 | 269 | if (!str) return t; 270 | 271 | buf = strdup(str); 272 | 273 | if (!buf) return t; 274 | 275 | z = strlen(buf); /* length of entire string */ 276 | a = buf; /* pointer to the start of the string */ 277 | 278 | /* initialize the prefix fields */ 279 | 280 | if (prefix) { 281 | prefix_len = strlen(prefix); 282 | local_prefix = strdup(prefix); 283 | } else { 284 | prefix_len = 0; 285 | local_prefix = NULL; 286 | } 287 | 288 | /* adjust the max width for any prefix */ 289 | 290 | w = width - prefix_len; 291 | 292 | do { 293 | /* 294 | * if the string will fit on one line, point b to the end of the 295 | * string 296 | */ 297 | 298 | if (z < w) b = a + z; 299 | 300 | /* 301 | * if the string won't fit on one line, move b to where the 302 | * end of the line should be, and then move b back until we 303 | * find a space; if we don't find a space before we back b all 304 | * the way up to a, just assign b to where the line should end. 305 | */ 306 | 307 | else { 308 | b = a + w; 309 | 310 | if (word_boundary) { 311 | while ((b >= a) && (!isspace(*b))) b--; 312 | if (b <= a) b = a + w; 313 | } 314 | } 315 | 316 | /* look for any newline between a and b, and move b to it */ 317 | 318 | for (c = a; c < b; c++) if (*c == '\n') { b = c; break; } 319 | 320 | /* 321 | * copy the string that starts at a and ends at b, prepending 322 | * with a prefix, if present 323 | */ 324 | 325 | len = b-a; 326 | len += prefix_len; 327 | line = (char *) malloc(len+1); 328 | if (local_prefix) strncpy(line, local_prefix, prefix_len); 329 | strncpy(line + prefix_len, a, len - prefix_len); 330 | line[len] = '\0'; 331 | 332 | /* append the new line to the array of text rows */ 333 | 334 | t->t = (char **) realloc(t->t, sizeof(char *) * (t->n + 1)); 335 | t->t[t->n] = line; 336 | t->n++; 337 | 338 | if (t->m < len) t->m = len; 339 | 340 | /* 341 | * adjust the length of the string and move the pointer to the 342 | * beginning of the new line 343 | */ 344 | 345 | z -= (b - a + 1); 346 | a = b + 1; 347 | 348 | /* move to the first non whitespace character (excluding newlines) */ 349 | 350 | if (word_boundary && isspace(*b)) { 351 | while ((z) && (isspace(*a)) && (*a != '\n')) a++, z--; 352 | } else { 353 | if (!isspace(*b)) z++, a--; 354 | } 355 | 356 | if (local_prefix) { 357 | for (i = 0; i < prefix_len; i++) local_prefix[i] = ' '; 358 | } 359 | 360 | } while (z > 0); 361 | 362 | if (local_prefix) free(local_prefix); 363 | free(buf); 364 | 365 | return t; 366 | } 367 | 368 | 369 | /* 370 | * nv_text_rows_append() - append the given msg to the existing TextRows 371 | */ 372 | 373 | void nv_text_rows_append(TextRows *t, const char *msg) 374 | { 375 | int len; 376 | 377 | t->t = realloc(t->t, sizeof(char *) * (t->n + 1)); 378 | 379 | if (msg) { 380 | t->t[t->n] = strdup(msg); 381 | len = strlen(msg); 382 | if (t->m < len) t->m = len; 383 | } else { 384 | t->t[t->n] = NULL; 385 | } 386 | 387 | t->n++; 388 | } 389 | 390 | /* 391 | * nv_concat_text_rows() - concatenate two text rows, storing the 392 | * result in t0 393 | */ 394 | 395 | void nv_concat_text_rows(TextRows *t0, TextRows *t1) 396 | { 397 | int n, i; 398 | 399 | n = t0->n + t1->n; 400 | 401 | t0->t = realloc(t0->t, sizeof(char *) * n); 402 | 403 | for (i = 0; i < t1->n; i++) { 404 | t0->t[i + t0->n] = strdup(t1->t[i]); 405 | } 406 | 407 | t0->m = NV_MAX(t0->m, t1->m); 408 | t0->n = n; 409 | 410 | } /* nv_concat_text_rows() */ 411 | 412 | 413 | /* 414 | * nv_free_text_rows() - free the TextRows data structure allocated by 415 | * nv_format_text_rows() 416 | */ 417 | 418 | void nv_free_text_rows(TextRows *t) 419 | { 420 | int i; 421 | 422 | if (!t) return; 423 | for (i = 0; i < t->n; i++) free(t->t[i]); 424 | if (t->t) free(t->t); 425 | free(t); 426 | 427 | } /* nv_free_text_rows() */ 428 | 429 | -------------------------------------------------------------------------------- /cpuopsys.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: Copyright (c) 2018-2018 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 3 | * SPDX-License-Identifier: MIT 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a 6 | * copy of this software and associated documentation files (the "Software"), 7 | * to deal in the Software without restriction, including without limitation 8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 | * and/or sell copies of the Software, and to permit persons to whom the 10 | * Software is furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 | * DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | /*! \brief 25 | * Define compile time symbols for CPU type and operating system type. 26 | * This file should only contain preprocessor commands so that 27 | * there are no dependencies on other files. 28 | * 29 | * cpuopsys.h 30 | * 31 | * Copyright (c) 2001, Nvidia Corporation. All rights reserved. 32 | */ 33 | 34 | /*! 35 | * Uniform names are defined for compile time options to distinguish 36 | * CPU types and Operating systems. 37 | * Distinctions between CPU and OpSys should be orthogonal. 38 | * 39 | * These uniform names have initially been defined by keying off the 40 | * makefile/build names defined for builds in the OpenGL group. 41 | * Getting the uniform names defined for other builds may require 42 | * different qualifications. 43 | * 44 | * The file is placed here to allow for the possibility of all driver 45 | * components using the same naming convention for conditional compilation. 46 | */ 47 | 48 | #ifndef CPUOPSYS_H 49 | #define CPUOPSYS_H 50 | 51 | /*****************************************************************************/ 52 | /* Define all OS/CPU-Chip related symbols */ 53 | 54 | /* ***** WINDOWS variations */ 55 | #if defined(_WIN32) || defined(_WIN16) 56 | # define NV_WINDOWS 57 | 58 | # if defined(_WIN32_WINNT) 59 | # define NV_WINDOWS_NT 60 | # elif defined(_WIN32_WCE) 61 | # define NV_WINDOWS_CE 62 | # elif !defined(NV_MODS) 63 | # define NV_WINDOWS_9X 64 | # endif 65 | #endif /* _WIN32 || defined(_WIN16) */ 66 | 67 | /* ***** Unix variations */ 68 | #if defined(__linux__) && !defined(NV_LINUX) && !defined(NV_VMWARE) 69 | # define NV_LINUX 70 | #endif /* defined(__linux__) */ 71 | 72 | #if defined(__VMWARE__) && !defined(NV_VMWARE) 73 | # define NV_VMWARE 74 | #endif /* defined(__VMWARE__) */ 75 | 76 | /* SunOS + gcc */ 77 | #if defined(__sun__) && defined(__svr4__) && !defined(NV_SUNOS) 78 | # define NV_SUNOS 79 | #endif /* defined(__sun__) && defined(__svr4__) */ 80 | 81 | /* SunOS + Sun Compiler (named SunPro, Studio or Forte) */ 82 | #if defined(__SUNPRO_C) || defined(__SUNPRO_CC) 83 | # define NV_SUNPRO_C 84 | # define NV_SUNOS 85 | #endif /* defined(_SUNPRO_C) || defined(__SUNPRO_CC) */ 86 | 87 | #if defined(__FreeBSD__) && !defined(NV_BSD) 88 | # define NV_BSD 89 | #endif /* defined(__FreeBSD__) */ 90 | 91 | /* XXXar don't define NV_UNIX on MacOSX or vxworks or QNX */ 92 | #if (defined(__unix__) || defined(__unix) || defined(__INTEGRITY) ) && !defined(nvmacosx) && !defined(vxworks) && !defined(NV_UNIX) && !defined(__QNX__) && !defined(__QNXNTO__)/* XXX until removed from Makefiles */ 93 | # define NV_UNIX 94 | #endif /* defined(__unix__) */ 95 | 96 | #if (defined(__QNX__) || defined(__QNXNTO__)) && !defined(NV_QNX) 97 | # define NV_QNX 98 | #endif 99 | 100 | #if (defined(__ANDROID__) || defined(ANDROID)) && !defined(NV_ANDROID) 101 | # define NV_ANDROID 102 | #endif 103 | 104 | #if defined(DceCore) && !defined(NV_DCECORE) 105 | # define NV_DCECORE 106 | #endif 107 | 108 | /* ***** Apple variations */ 109 | #if defined(macintosh) || defined(__APPLE__) 110 | # define NV_MACINTOSH 111 | # if defined(__MACH__) 112 | # define NV_MACINTOSH_OSX 113 | # else 114 | # define NV_MACINTOSH_OS9 115 | # endif 116 | # if defined(__LP64__) 117 | # define NV_MACINTOSH_64 118 | # endif 119 | #endif /* defined(macintosh) */ 120 | 121 | /* ***** VxWorks */ 122 | /* Tornado 2.21 is gcc 2.96 and #defines __vxworks. */ 123 | /* Tornado 2.02 is gcc 2.7.2 and doesn't define any OS symbol, so we rely on */ 124 | /* the build system #defining vxworks. */ 125 | #if defined(__vxworks) || defined(vxworks) 126 | # define NV_VXWORKS 127 | #endif 128 | 129 | /* ***** Integrity OS */ 130 | #if defined(__INTEGRITY) 131 | # if !defined(NV_INTEGRITY) 132 | # define NV_INTEGRITY 133 | # endif 134 | #endif 135 | 136 | /* ***** Processor type variations */ 137 | /* Note: The prefix NV_CPU_* is taken by Nvcm.h */ 138 | 139 | #if ((defined(_M_IX86) || defined(__i386__) || defined(__i386)) && !defined(NVCPU_X86)) /* XXX until removed from Makefiles */ 140 | /* _M_IX86 for windows, __i386__ for Linux (or any x86 using gcc) */ 141 | /* __i386 for Studio compiler on Solaris x86 */ 142 | # define NVCPU_X86 /* any IA32 machine (not x86-64) */ 143 | # define NVCPU_MIN_PAGE_SHIFT 12 144 | #endif 145 | 146 | #if defined(_WIN32) && defined(_M_IA64) 147 | # define NVCPU_IA64_WINDOWS /* any IA64 for Windows opsys */ 148 | #endif 149 | #if defined(NV_LINUX) && defined(__ia64__) 150 | # define NVCPU_IA64_LINUX /* any IA64 for Linux opsys */ 151 | #endif 152 | #if defined(NVCPU_IA64_WINDOWS) || defined(NVCPU_IA64_LINUX) || defined(IA64) 153 | # define NVCPU_IA64 /* any IA64 for any opsys */ 154 | #endif 155 | 156 | #if (defined(NV_MACINTOSH) && !(defined(__i386__) || defined(__x86_64__))) || defined(__PPC__) || defined(__ppc) 157 | # if defined(__powerpc64__) && defined(__LITTLE_ENDIAN__) 158 | # ifndef NVCPU_PPC64LE 159 | # define NVCPU_PPC64LE /* PPC 64-bit little endian */ 160 | # endif 161 | # else 162 | # ifndef NVCPU_PPC 163 | # define NVCPU_PPC /* any non-PPC64LE PowerPC architecture */ 164 | # endif 165 | # ifndef NV_BIG_ENDIAN 166 | # define NV_BIG_ENDIAN 167 | # endif 168 | # endif 169 | # define NVCPU_FAMILY_PPC 170 | #endif 171 | 172 | #if defined(__x86_64) || defined(AMD64) || defined(_M_AMD64) 173 | # define NVCPU_X86_64 /* any x86-64 for any opsys */ 174 | #endif 175 | 176 | #if defined(NVCPU_X86) || defined(NVCPU_X86_64) 177 | # define NVCPU_FAMILY_X86 178 | #endif 179 | 180 | #if defined(__riscv) && (__riscv_xlen==64) 181 | # define NVCPU_RISCV64 182 | # if defined(__nvriscv) 183 | # define NVCPU_NVRISCV64 184 | # endif 185 | #endif 186 | 187 | #if defined(__arm__) || defined(_M_ARM) 188 | /* 189 | * 32-bit instruction set on, e.g., ARMv7 or AArch32 execution state 190 | * on ARMv8 191 | */ 192 | # define NVCPU_ARM 193 | # define NVCPU_MIN_PAGE_SHIFT 12 194 | #endif 195 | 196 | #if defined(__aarch64__) || defined(__ARM64__) || defined(_M_ARM64) 197 | # define NVCPU_AARCH64 /* 64-bit A64 instruction set on ARMv8 */ 198 | # define NVCPU_MIN_PAGE_SHIFT 12 199 | #endif 200 | 201 | #if defined(NVCPU_ARM) || defined(NVCPU_AARCH64) 202 | # define NVCPU_FAMILY_ARM 203 | #endif 204 | 205 | #if defined(__SH4__) 206 | # ifndef NVCPU_SH4 207 | # define NVCPU_SH4 /* Renesas (formerly Hitachi) SH4 */ 208 | # endif 209 | # if defined NV_WINDOWS_CE 210 | # define NVCPU_MIN_PAGE_SHIFT 12 211 | # endif 212 | #endif 213 | 214 | /* For Xtensa processors */ 215 | #if defined(__XTENSA__) 216 | # define NVCPU_XTENSA 217 | # if defined(__XTENSA_EB__) 218 | # define NV_BIG_ENDIAN 219 | # endif 220 | #endif 221 | 222 | 223 | /* 224 | * Other flavors of CPU type should be determined at run-time. 225 | * For example, an x86 architecture with/without SSE. 226 | * If it can compile, then there's no need for a compile time option. 227 | * For some current GCC limitations, these may be fixed by using the Intel 228 | * compiler for certain files in a Linux build. 229 | */ 230 | 231 | /* The minimum page size can be determined from the minimum page shift */ 232 | #if defined(NVCPU_MIN_PAGE_SHIFT) 233 | #define NVCPU_MIN_PAGE_SIZE (1 << NVCPU_MIN_PAGE_SHIFT) 234 | #endif 235 | 236 | #if defined(NVCPU_IA64) || defined(NVCPU_X86_64) || \ 237 | defined(NV_MACINTOSH_64) || defined(NVCPU_AARCH64) || \ 238 | defined(NVCPU_PPC64LE) || defined(NVCPU_RISCV64) 239 | # define NV_64_BITS /* all architectures where pointers are 64 bits */ 240 | #else 241 | /* we assume 32 bits. I don't see a need for NV_16_BITS. */ 242 | #endif 243 | 244 | /* For verification-only features not intended to be included in normal drivers */ 245 | #if defined(ENABLE_VERIF_FEATURES) 246 | #define NV_VERIF_FEATURES 247 | #endif 248 | 249 | /* 250 | * New, safer family of #define's -- these ones use 0 vs. 1 rather than 251 | * defined/!defined. This is advantageous because if you make a typo, 252 | * say misspelled ENDIAN: 253 | * 254 | * #if NVCPU_IS_BIG_ENDAIN 255 | * 256 | * ...some compilers can give you a warning telling you that you screwed up. 257 | * The compiler can also give you a warning if you forget to #include 258 | * "cpuopsys.h" in your code before the point where you try to use these 259 | * conditionals. 260 | * 261 | * Also, the names have been prefixed in more cases with "CPU" or "OS" for 262 | * increased clarity. You can tell the names apart from the old ones because 263 | * they all use "_IS_" in the name. 264 | * 265 | * Finally, these can be used in "if" statements and not just in #if's. For 266 | * example: 267 | * 268 | * if (NVCPU_IS_BIG_ENDIAN) x = Swap32(x); 269 | * 270 | * Maybe some day in the far-off future these can replace the old #define's. 271 | */ 272 | 273 | #if defined(NV_MODS) 274 | #define NV_IS_MODS 1 275 | #else 276 | #define NV_IS_MODS 0 277 | #endif 278 | 279 | #if defined(NV_WINDOWS) 280 | #define NVOS_IS_WINDOWS 1 281 | #else 282 | #define NVOS_IS_WINDOWS 0 283 | #endif 284 | #if defined(NV_WINDOWS_CE) 285 | #define NVOS_IS_WINDOWS_CE 1 286 | #else 287 | #define NVOS_IS_WINDOWS_CE 0 288 | #endif 289 | #if defined(NV_LINUX) 290 | #define NVOS_IS_LINUX 1 291 | #else 292 | #define NVOS_IS_LINUX 0 293 | #endif 294 | #if defined(NV_UNIX) 295 | #define NVOS_IS_UNIX 1 296 | #else 297 | #define NVOS_IS_UNIX 0 298 | #endif 299 | #if defined(NV_BSD) 300 | #define NVOS_IS_FREEBSD 1 301 | #else 302 | #define NVOS_IS_FREEBSD 0 303 | #endif 304 | #if defined(NV_SUNOS) 305 | #define NVOS_IS_SOLARIS 1 306 | #else 307 | #define NVOS_IS_SOLARIS 0 308 | #endif 309 | #if defined(NV_VMWARE) 310 | #define NVOS_IS_VMWARE 1 311 | #else 312 | #define NVOS_IS_VMWARE 0 313 | #endif 314 | #if defined(NV_QNX) 315 | #define NVOS_IS_QNX 1 316 | #else 317 | #define NVOS_IS_QNX 0 318 | #endif 319 | #if defined(NV_ANDROID) 320 | #define NVOS_IS_ANDROID 1 321 | #else 322 | #define NVOS_IS_ANDROID 0 323 | #endif 324 | #if defined(NV_MACINTOSH) 325 | #define NVOS_IS_MACINTOSH 1 326 | #else 327 | #define NVOS_IS_MACINTOSH 0 328 | #endif 329 | #if defined(NV_VXWORKS) 330 | #define NVOS_IS_VXWORKS 1 331 | #else 332 | #define NVOS_IS_VXWORKS 0 333 | #endif 334 | #if defined(NV_LIBOS) 335 | #define NVOS_IS_LIBOS 1 336 | #else 337 | #define NVOS_IS_LIBOS 0 338 | #endif 339 | #if defined(NV_INTEGRITY) 340 | #define NVOS_IS_INTEGRITY 1 341 | #else 342 | #define NVOS_IS_INTEGRITY 0 343 | #endif 344 | 345 | #if defined(NVCPU_X86) 346 | #define NVCPU_IS_X86 1 347 | #else 348 | #define NVCPU_IS_X86 0 349 | #endif 350 | #if defined(NVCPU_RISCV64) 351 | #define NVCPU_IS_RISCV64 1 352 | #else 353 | #define NVCPU_IS_RISCV64 0 354 | #endif 355 | #if defined(NVCPU_NVRISCV64) 356 | #define NVCPU_IS_NVRISCV64 1 357 | #else 358 | #define NVCPU_IS_NVRISCV64 0 359 | #endif 360 | #if defined(NVCPU_IA64) 361 | #define NVCPU_IS_IA64 1 362 | #else 363 | #define NVCPU_IS_IA64 0 364 | #endif 365 | #if defined(NVCPU_X86_64) 366 | #define NVCPU_IS_X86_64 1 367 | #else 368 | #define NVCPU_IS_X86_64 0 369 | #endif 370 | #if defined(NVCPU_FAMILY_X86) 371 | #define NVCPU_IS_FAMILY_X86 1 372 | #else 373 | #define NVCPU_IS_FAMILY_X86 0 374 | #endif 375 | #if defined(NVCPU_PPC) 376 | #define NVCPU_IS_PPC 1 377 | #else 378 | #define NVCPU_IS_PPC 0 379 | #endif 380 | #if defined(NVCPU_PPC64LE) 381 | #define NVCPU_IS_PPC64LE 1 382 | #else 383 | #define NVCPU_IS_PPC64LE 0 384 | #endif 385 | #if defined(NVCPU_FAMILY_PPC) 386 | #define NVCPU_IS_FAMILY_PPC 1 387 | #else 388 | #define NVCPU_IS_FAMILY_PPC 0 389 | #endif 390 | #if defined(NVCPU_ARM) 391 | #define NVCPU_IS_ARM 1 392 | #else 393 | #define NVCPU_IS_ARM 0 394 | #endif 395 | #if defined(NVCPU_AARCH64) 396 | #define NVCPU_IS_AARCH64 1 397 | #else 398 | #define NVCPU_IS_AARCH64 0 399 | #endif 400 | #if defined(NVCPU_FAMILY_ARM) 401 | #define NVCPU_IS_FAMILY_ARM 1 402 | #else 403 | #define NVCPU_IS_FAMILY_ARM 0 404 | #endif 405 | #if defined(NVCPU_SH4) 406 | #define NVCPU_IS_SH4 1 407 | #else 408 | #define NVCPU_IS_SH4 0 409 | #endif 410 | #if defined(NVCPU_XTENSA) 411 | #define NVCPU_IS_XTENSA 1 412 | #else 413 | #define NVCPU_IS_XTENSA 0 414 | #endif 415 | #if defined(NV_BIG_ENDIAN) 416 | #define NVCPU_IS_BIG_ENDIAN 1 417 | #else 418 | #define NVCPU_IS_BIG_ENDIAN 0 419 | #endif 420 | #if defined(NV_64_BITS) 421 | #define NVCPU_IS_64_BITS 1 422 | #else 423 | #define NVCPU_IS_64_BITS 0 424 | #endif 425 | #if defined(NVCPU_FAMILY_ARM) 426 | #define NVCPU_IS_PCIE_CACHE_COHERENT 0 427 | #else 428 | #define NVCPU_IS_PCIE_CACHE_COHERENT 1 429 | #endif 430 | #if defined(NV_DCECORE) 431 | #define NVOS_IS_DCECORE 1 432 | #else 433 | #define NVOS_IS_DCECORE 0 434 | #endif 435 | /*****************************************************************************/ 436 | 437 | #endif /* CPUOPSYS_H */ 438 | -------------------------------------------------------------------------------- /common-utils/nvgetopt.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2004-2010 NVIDIA Corporation 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | * 22 | * 23 | * nvgetopt.c - portable getopt_long() replacement; removes the need 24 | * for the stupid optstring argument. 25 | */ 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | #include "nvgetopt.h" 34 | #include "common-utils.h" 35 | 36 | 37 | int nvgetopt(int argc, 38 | char *argv[], 39 | const NVGetoptOption *options, 40 | char **strval, 41 | int *boolval, 42 | int *intval, 43 | double *doubleval, 44 | int *disable_val) 45 | { 46 | char *c, *a, *arg, *name = NULL, *argument=NULL; 47 | int i, found = NVGETOPT_FALSE; 48 | int ret = 0; 49 | int negate = NVGETOPT_FALSE; 50 | int disable = NVGETOPT_FALSE; 51 | int double_dash = NVGETOPT_FALSE; 52 | const NVGetoptOption *o = NULL; 53 | static int argv_index = 0; 54 | 55 | if (strval) *strval = NULL; 56 | if (boolval) *boolval = NVGETOPT_FALSE; 57 | if (intval) *intval = 0; 58 | if (doubleval) *doubleval = 0.0; 59 | if (disable_val) *disable_val = NVGETOPT_FALSE; 60 | 61 | argv_index++; 62 | 63 | /* if no more options, return -1 */ 64 | 65 | if (argv_index >= argc) return -1; 66 | 67 | /* get the argument in question */ 68 | 69 | arg = strdup(argv[argv_index]); 70 | 71 | /* look for "--" or "-" */ 72 | 73 | if ((arg[0] == '-') && (arg[1] == '-')) { 74 | name = arg + 2; 75 | double_dash = NVGETOPT_TRUE; 76 | } else if (arg[0] == '-') { 77 | name = arg + 1; 78 | } else { 79 | fprintf(stderr, "%s: invalid option: \"%s\"\n", argv[0], arg); 80 | goto done; 81 | } 82 | 83 | /* 84 | * if there is an "=" in the string, then assign argument and zero 85 | * out the equal sign so that name will match what is in the 86 | * option table. 87 | */ 88 | 89 | c = name; 90 | while (*c) { 91 | if (*c == '=') { 92 | argument = c + 1; 93 | *c = '\0'; 94 | break; 95 | } 96 | c++; 97 | } 98 | 99 | /* 100 | * if there is no character after '--' then stop processing options. 101 | * if the string is terminated after one character, interpret it 102 | * as a short option. Otherwise, interpret it as a long option. 103 | */ 104 | 105 | if (name[0] == '\0') { 106 | if (double_dash && argument == NULL) { /* option list terminator */ 107 | ret = -1; 108 | goto done; 109 | } 110 | } else if (name[1] == '\0') { /* short option */ 111 | for (i = 0; options[i].name; i++) { 112 | if (options[i].val == name[0]) { 113 | o = &options[i]; 114 | break; 115 | } 116 | } 117 | } else { /* long option */ 118 | for (i = 0; options[i].name; i++) { 119 | const char *tmpname; 120 | int tmp_negate; 121 | 122 | /* 123 | * if this option allows negation by prepending with 124 | * "--no-" (true for IS_BOOLEAN and ALLOW_DISABLE), then 125 | * skip any leading "no-" in the argument 126 | */ 127 | 128 | if ((options[i].flags & (NVGETOPT_IS_BOOLEAN | 129 | NVGETOPT_ALLOW_DISABLE)) && 130 | (name[0] == 'n') && 131 | (name[1] == 'o') && 132 | (name[2] == '-')) { 133 | tmpname = name + 3; 134 | tmp_negate = NVGETOPT_TRUE; 135 | } else { 136 | tmpname = name; 137 | tmp_negate = NVGETOPT_FALSE; 138 | } 139 | 140 | if (strcmp(tmpname, options[i].name) == 0) { 141 | o = &options[i]; 142 | negate = tmp_negate; 143 | break; 144 | } 145 | } 146 | } 147 | 148 | /* 149 | * if we didn't find a match, maybe this is multiple short options 150 | * stored together; is each character a short option? 151 | */ 152 | 153 | if (!o) { 154 | for (c = name; *c; c++) { 155 | found = NVGETOPT_FALSE; 156 | for (i = 0; options[i].name; i++) { 157 | if (options[i].val == *c) { 158 | found = NVGETOPT_TRUE; 159 | break; 160 | } 161 | } 162 | if (!found) break; 163 | } 164 | 165 | if (found) { 166 | 167 | /* 168 | * all characters individually are short options, so 169 | * interpret them that way 170 | */ 171 | 172 | for (i = 0; options[i].name; i++) { 173 | if (options[i].val == name[0]) { 174 | 175 | /* 176 | * don't allow options with arguments to be 177 | * processed in this way 178 | */ 179 | 180 | if (options[i].flags & NVGETOPT_HAS_ARGUMENT) break; 181 | 182 | /* 183 | * remove the first short option from 184 | * argv[argv_index] 185 | */ 186 | 187 | a = argv[argv_index]; 188 | if (a[0] == '-') a++; 189 | if (a[0] == '-') a++; 190 | if (a[0] == '+') a++; 191 | 192 | while (a[0]) { a[0] = a[1]; a++; } 193 | 194 | /* 195 | * decrement argv_index so that we process this 196 | * entry again 197 | */ 198 | 199 | argv_index--; 200 | 201 | o = &options[i]; 202 | break; 203 | } 204 | } 205 | } 206 | } 207 | 208 | /* 209 | * If we still didn't find a match, maybe this is a short option 210 | * with its argument value concatenated (e.g., "-j8"). For now, 211 | * limit this to short options with integer argument values. 212 | */ 213 | if (!o && intval) { 214 | 215 | /* Is the string after the first character an integer? */ 216 | int appendedInteger = NVGETOPT_FALSE; 217 | if ((name[0] != '\0') && (name[1] != '\0')) { 218 | char *endptr; 219 | strtol(name + 1, &endptr, 0); 220 | if (*endptr == '\0') { 221 | /* 222 | * The only characters after the first character are 223 | * parsable by strtol(3). 224 | */ 225 | appendedInteger = NVGETOPT_TRUE; 226 | } 227 | } 228 | 229 | if (appendedInteger) { 230 | for (i = 0; options[i].name; i++) { 231 | if ((options[i].flags & NVGETOPT_INTEGER_ARGUMENT) == 0) { 232 | continue; 233 | } 234 | if (options[i].val == name[0]) { 235 | o = &options[i]; 236 | argument = name + 1; 237 | break; 238 | } 239 | } 240 | } 241 | } 242 | 243 | /* if we didn't find an option, return */ 244 | 245 | if (!o) { 246 | fprintf(stderr, "%s: unrecognized option: \"%s\"\n", argv[0], arg); 247 | goto done; 248 | } 249 | 250 | 251 | /* if the option is boolean, record !negate as the boolean value */ 252 | 253 | if (o->flags & NVGETOPT_IS_BOOLEAN) { 254 | if (boolval) *boolval = !negate; 255 | } 256 | 257 | 258 | /* 259 | * if this option is flagged as "disable-able", then let the 260 | * "--no-" prefix get interpreted to mean that the option should 261 | * be disabled 262 | */ 263 | 264 | if ((o->flags & NVGETOPT_ALLOW_DISABLE) && (negate == NVGETOPT_TRUE)) { 265 | disable = NVGETOPT_TRUE; 266 | } 267 | 268 | 269 | /* 270 | * if the option takes an argument (either string or integer), and 271 | * we haven't already decided to disable the option, then we 272 | * either need to use what was after the "=" in this argv[] entry, 273 | * or we need to pull the next entry off of argv[] 274 | */ 275 | 276 | if ((o->flags & NVGETOPT_HAS_ARGUMENT) && !disable) { 277 | if (argument) { 278 | if (!argument[0]) { 279 | fprintf(stderr, "%s: option \"%s\" requires an " 280 | "argument.\n", argv[0], arg); 281 | goto done; 282 | } 283 | } else { 284 | 285 | /* 286 | * if the argument is optional, and we're either at the 287 | * end of the argv list, or the next argv starts with '-', 288 | * then assume there is no argument for this option 289 | */ 290 | 291 | if ((o->flags & NVGETOPT_ARGUMENT_IS_OPTIONAL) && 292 | ((argv_index == (argc - 1)) || 293 | (argv[argv_index + 1][0] == '-'))) { 294 | argument = NULL; 295 | goto argument_processing_done; 296 | } else { 297 | argv_index++; 298 | if (argv_index >= argc) { 299 | fprintf(stderr, "%s: option \"%s\" requires an " 300 | "argument.\n", argv[0], arg); 301 | goto done; 302 | } 303 | argument = argv[argv_index]; 304 | } 305 | } 306 | 307 | /* argument is now a valid string: parse it */ 308 | 309 | if ((o->flags & NVGETOPT_INTEGER_ARGUMENT) && (intval)) { 310 | 311 | /* parse the argument as an integer */ 312 | 313 | char *endptr; 314 | *intval = (int) strtol(argument, &endptr, 0); 315 | if (*endptr) { 316 | fprintf(stderr, "%s: \"%s\" is not a valid argument for " 317 | "option \"%s\".\n", argv[0], argument, arg); 318 | goto done; 319 | } 320 | } else if ((o->flags & NVGETOPT_STRING_ARGUMENT) && (strval)) { 321 | 322 | /* treat the argument as a string */ 323 | 324 | *strval = strdup(argument); 325 | } else if ((o->flags & NVGETOPT_DOUBLE_ARGUMENT) && (doubleval)) { 326 | 327 | /* parse the argument as a double */ 328 | 329 | char *endptr; 330 | *doubleval = (double) strtod(argument, &endptr); 331 | if (*endptr) { 332 | fprintf(stderr, "%s: \"%s\" is not a valid argument for " 333 | "option \"%s\".\n", argv[0], argument, arg); 334 | goto done; 335 | } 336 | } else { 337 | fprintf(stderr, "%s: error while assigning argument for " 338 | "option \"%s\".\n", argv[0], arg); 339 | goto done; 340 | } 341 | 342 | } else { 343 | 344 | /* if we have an argument when we shouldn't; complain */ 345 | 346 | if (argument) { 347 | fprintf(stderr, "%s: option \"%s\" does not take an argument, but " 348 | "was given an argument of \"%s\".\n", 349 | argv[0], arg, argument); 350 | goto done; 351 | } 352 | } 353 | 354 | argument_processing_done: 355 | 356 | ret = o->val; 357 | 358 | /* fall through */ 359 | 360 | done: 361 | 362 | if (disable_val) *disable_val = disable; 363 | 364 | free(arg); 365 | return ret; 366 | 367 | } /* nvgetopt() */ 368 | 369 | 370 | /* 371 | * cook_description() - the description string may contain text within 372 | * special characters which are interpreted by the manpage generator. 373 | * We want to omit those characters here. 374 | */ 375 | 376 | static char *cook_description(const char *description) 377 | { 378 | const char *src; 379 | char *s, *dst; 380 | 381 | if (!description) { 382 | return NULL; 383 | } 384 | 385 | s = strdup(description); 386 | 387 | if (!s) { 388 | return NULL; 389 | } 390 | 391 | for (src = description, dst = s; *src; src++) { 392 | if ((*src == '&') || (*src == '^')) { 393 | continue; 394 | } 395 | *dst = *src; 396 | dst++; 397 | } 398 | 399 | *dst = '\0'; 400 | 401 | return s; 402 | } 403 | 404 | 405 | void nvgetopt_print_help(const NVGetoptOption *options, 406 | unsigned int include_mask, 407 | nvgetopt_print_help_callback_ptr callback) 408 | { 409 | const NVGetoptOption *o; 410 | int i; 411 | 412 | for (i = 0; options[i].name; i++) { 413 | 414 | char *msg = NULL, *arg = NULL, *description = NULL; 415 | 416 | o = &options[i]; 417 | 418 | /* Skip options with no help text */ 419 | if (!o->description) { 420 | continue; 421 | } 422 | 423 | /* skip options who don't have all the bits of include_mask */ 424 | if ((o->flags & include_mask) != include_mask) { 425 | continue; 426 | } 427 | 428 | /* if we are going to need the argument, process it now */ 429 | arg = NULL; 430 | if (o->flags & NVGETOPT_HAS_ARGUMENT) { 431 | if (o->arg_name) { 432 | arg = strdup(o->arg_name); 433 | } else { 434 | char *tmp; 435 | arg = strdup(o->name); 436 | for (tmp = arg; tmp && *tmp; tmp++) { 437 | *tmp = toupper(*tmp); 438 | } 439 | } 440 | } 441 | 442 | msg = NULL; 443 | 444 | /* 445 | * create the long version of the option, possibly with an 446 | * argument; e.g., "--foo" or "--foo=BAR" 447 | */ 448 | if (arg) { 449 | msg = nvstrcat("--", o->name, "=", arg, NULL); 450 | } else { 451 | msg = nvstrcat("--", o->name, NULL); 452 | } 453 | 454 | /* 455 | * prepend the single character version of the option, 456 | * possibly with an argument; e.g., "-f" or "-f BAR" 457 | */ 458 | if (o->val <= UCHAR_MAX && o->val >= 0 && isalpha(o->val)) { 459 | char scratch[16]; 460 | char *tmp; 461 | snprintf(scratch, sizeof(scratch), "%c", o->val); 462 | if (arg) { 463 | tmp = nvstrcat("-", scratch, " ", arg, ", ", msg, NULL); 464 | } else { 465 | tmp = nvstrcat("-", scratch, ", ", msg, NULL); 466 | } 467 | free(msg); 468 | msg = tmp; 469 | } 470 | 471 | /* append the boolean version of the option; e.g., "--no-foo" */ 472 | if (((o->flags & NVGETOPT_IS_BOOLEAN) && 473 | !(o->flags & NVGETOPT_HAS_ARGUMENT)) || 474 | (o->flags & NVGETOPT_ALLOW_DISABLE)) { 475 | char *tmp = nvstrcat(msg, ", --no-", o->name, NULL); 476 | free(msg); 477 | msg = tmp; 478 | } 479 | 480 | /* process the description text */ 481 | description = cook_description(o->description); 482 | 483 | /* give the strings to the caller to format and print */ 484 | callback(msg, description); 485 | 486 | free(msg); 487 | free(arg); 488 | free(description); 489 | } 490 | } 491 | -------------------------------------------------------------------------------- /nvstatuscodes.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: Copyright (c) 2014-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 3 | * SPDX-License-Identifier: MIT 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a 6 | * copy of this software and associated documentation files (the "Software"), 7 | * to deal in the Software without restriction, including without limitation 8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 | * and/or sell copies of the Software, and to permit persons to whom the 10 | * Software is furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 | * DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | #ifndef SDK_NVSTATUSCODES_H 25 | #define SDK_NVSTATUSCODES_H 26 | 27 | NV_STATUS_CODE(NV_OK, 0x00000000, "Success") 28 | NV_STATUS_CODE(NV_ERR_GENERIC, 0x0000FFFF, "Failure: Generic Error") 29 | 30 | NV_STATUS_CODE(NV_ERR_BROKEN_FB, 0x00000001, "Frame-Buffer broken") 31 | NV_STATUS_CODE(NV_ERR_BUFFER_TOO_SMALL, 0x00000002, "Buffer passed in is too small") 32 | NV_STATUS_CODE(NV_ERR_BUSY_RETRY, 0x00000003, "System is busy, retry later") 33 | NV_STATUS_CODE(NV_ERR_CALLBACK_NOT_SCHEDULED, 0x00000004, "The requested callback API not scheduled") 34 | NV_STATUS_CODE(NV_ERR_CARD_NOT_PRESENT, 0x00000005, "Card not detected") 35 | NV_STATUS_CODE(NV_ERR_CYCLE_DETECTED, 0x00000006, "Call cycle detected") 36 | NV_STATUS_CODE(NV_ERR_DMA_IN_USE, 0x00000007, "Requested DMA is in use") 37 | NV_STATUS_CODE(NV_ERR_DMA_MEM_NOT_LOCKED, 0x00000008, "Requested DMA memory is not locked") 38 | NV_STATUS_CODE(NV_ERR_DMA_MEM_NOT_UNLOCKED, 0x00000009, "Requested DMA memory is not unlocked") 39 | NV_STATUS_CODE(NV_ERR_DUAL_LINK_INUSE, 0x0000000A, "Dual-Link is in use") 40 | NV_STATUS_CODE(NV_ERR_ECC_ERROR, 0x0000000B, "Generic ECC error") 41 | NV_STATUS_CODE(NV_ERR_FIFO_BAD_ACCESS, 0x0000000C, "FIFO: Invalid access") 42 | NV_STATUS_CODE(NV_ERR_FREQ_NOT_SUPPORTED, 0x0000000D, "Requested frequency is not supported") 43 | NV_STATUS_CODE(NV_ERR_GPU_DMA_NOT_INITIALIZED, 0x0000000E, "Requested DMA not initialized") 44 | NV_STATUS_CODE(NV_ERR_GPU_IS_LOST, 0x0000000F, "GPU lost from the bus") 45 | NV_STATUS_CODE(NV_ERR_GPU_IN_FULLCHIP_RESET, 0x00000010, "GPU currently in full-chip reset") 46 | NV_STATUS_CODE(NV_ERR_GPU_NOT_FULL_POWER, 0x00000011, "GPU not in full power") 47 | NV_STATUS_CODE(NV_ERR_GPU_UUID_NOT_FOUND, 0x00000012, "GPU UUID not found") 48 | NV_STATUS_CODE(NV_ERR_HOT_SWITCH, 0x00000013, "System in hot switch") 49 | NV_STATUS_CODE(NV_ERR_I2C_ERROR, 0x00000014, "I2C Error") 50 | NV_STATUS_CODE(NV_ERR_I2C_SPEED_TOO_HIGH, 0x00000015, "I2C Error: Speed too high") 51 | NV_STATUS_CODE(NV_ERR_ILLEGAL_ACTION, 0x00000016, "Current action is not allowed") 52 | NV_STATUS_CODE(NV_ERR_IN_USE, 0x00000017, "Generic busy error") 53 | NV_STATUS_CODE(NV_ERR_INFLATE_COMPRESSED_DATA_FAILED, 0x00000018, "Failed to inflate compressed data") 54 | NV_STATUS_CODE(NV_ERR_INSERT_DUPLICATE_NAME, 0x00000019, "Found a duplicate entry in the requested btree") 55 | NV_STATUS_CODE(NV_ERR_INSUFFICIENT_RESOURCES, 0x0000001A, "Ran out of a critical resource, other than memory") 56 | NV_STATUS_CODE(NV_ERR_INSUFFICIENT_PERMISSIONS, 0x0000001B, "The requester does not have sufficient permissions") 57 | NV_STATUS_CODE(NV_ERR_INSUFFICIENT_POWER, 0x0000001C, "Generic Error: Low power") 58 | NV_STATUS_CODE(NV_ERR_INVALID_ACCESS_TYPE, 0x0000001D, "This type of access is not allowed") 59 | NV_STATUS_CODE(NV_ERR_INVALID_ADDRESS, 0x0000001E, "Address not valid") 60 | NV_STATUS_CODE(NV_ERR_INVALID_ARGUMENT, 0x0000001F, "Invalid argument to call") 61 | NV_STATUS_CODE(NV_ERR_INVALID_BASE, 0x00000020, "Invalid base") 62 | NV_STATUS_CODE(NV_ERR_INVALID_CHANNEL, 0x00000021, "Given channel-id not valid") 63 | NV_STATUS_CODE(NV_ERR_INVALID_CLASS, 0x00000022, "Given class-id not valid") 64 | NV_STATUS_CODE(NV_ERR_INVALID_CLIENT, 0x00000023, "Given client not valid") 65 | NV_STATUS_CODE(NV_ERR_INVALID_COMMAND, 0x00000024, "Command passed is not valid") 66 | NV_STATUS_CODE(NV_ERR_INVALID_DATA, 0x00000025, "Invalid data passed") 67 | NV_STATUS_CODE(NV_ERR_INVALID_DEVICE, 0x00000026, "Current device is not valid") 68 | NV_STATUS_CODE(NV_ERR_INVALID_DMA_SPECIFIER, 0x00000027, "The requested DMA specifier is not valid") 69 | NV_STATUS_CODE(NV_ERR_INVALID_EVENT, 0x00000028, "Invalid event occurred") 70 | NV_STATUS_CODE(NV_ERR_INVALID_FLAGS, 0x00000029, "Invalid flags passed") 71 | NV_STATUS_CODE(NV_ERR_INVALID_FUNCTION, 0x0000002A, "Called function is not valid") 72 | NV_STATUS_CODE(NV_ERR_INVALID_HEAP, 0x0000002B, "Heap corrupted") 73 | NV_STATUS_CODE(NV_ERR_INVALID_INDEX, 0x0000002C, "Index invalid") 74 | NV_STATUS_CODE(NV_ERR_INVALID_IRQ_LEVEL, 0x0000002D, "Requested IRQ level is not valid") 75 | NV_STATUS_CODE(NV_ERR_INVALID_LIMIT, 0x0000002E, "Generic Error: Invalid limit") 76 | NV_STATUS_CODE(NV_ERR_INVALID_LOCK_STATE, 0x0000002F, "Requested lock state not valid") 77 | NV_STATUS_CODE(NV_ERR_INVALID_METHOD, 0x00000030, "Requested method not valid") 78 | NV_STATUS_CODE(NV_ERR_INVALID_OBJECT, 0x00000031, "Object not valid") 79 | NV_STATUS_CODE(NV_ERR_INVALID_OBJECT_BUFFER, 0x00000032, "Object buffer passed is not valid") 80 | NV_STATUS_CODE(NV_ERR_INVALID_OBJECT_HANDLE, 0x00000033, "Object handle is not valid") 81 | NV_STATUS_CODE(NV_ERR_INVALID_OBJECT_NEW, 0x00000034, "New object is not valid") 82 | NV_STATUS_CODE(NV_ERR_INVALID_OBJECT_OLD, 0x00000035, "Old object is not valid") 83 | NV_STATUS_CODE(NV_ERR_INVALID_OBJECT_PARENT, 0x00000036, "Object parent is not valid") 84 | NV_STATUS_CODE(NV_ERR_INVALID_OFFSET, 0x00000037, "The offset passed is not valid") 85 | NV_STATUS_CODE(NV_ERR_INVALID_OPERATION, 0x00000038, "Requested operation is not valid") 86 | NV_STATUS_CODE(NV_ERR_INVALID_OWNER, 0x00000039, "Owner not valid") 87 | NV_STATUS_CODE(NV_ERR_INVALID_PARAM_STRUCT, 0x0000003A, "Invalid structure parameter") 88 | NV_STATUS_CODE(NV_ERR_INVALID_PARAMETER, 0x0000003B, "At least one of the parameters passed is not valid") 89 | NV_STATUS_CODE(NV_ERR_INVALID_PATH, 0x0000003C, "The requested path is not valid") 90 | NV_STATUS_CODE(NV_ERR_INVALID_POINTER, 0x0000003D, "Pointer not valid") 91 | NV_STATUS_CODE(NV_ERR_INVALID_REGISTRY_KEY, 0x0000003E, "Found an invalid registry key") 92 | NV_STATUS_CODE(NV_ERR_INVALID_REQUEST, 0x0000003F, "Generic Error: Invalid request") 93 | NV_STATUS_CODE(NV_ERR_INVALID_STATE, 0x00000040, "Generic Error: Invalid state") 94 | NV_STATUS_CODE(NV_ERR_INVALID_STRING_LENGTH, 0x00000041, "The string length is not valid") 95 | NV_STATUS_CODE(NV_ERR_INVALID_READ, 0x00000042, "The requested read operation is not valid") 96 | NV_STATUS_CODE(NV_ERR_INVALID_WRITE, 0x00000043, "The requested write operation is not valid") 97 | NV_STATUS_CODE(NV_ERR_INVALID_XLATE, 0x00000044, "The requested translate operation is not valid") 98 | NV_STATUS_CODE(NV_ERR_IRQ_NOT_FIRING, 0x00000045, "Requested IRQ is not firing") 99 | NV_STATUS_CODE(NV_ERR_IRQ_EDGE_TRIGGERED, 0x00000046, "IRQ is edge triggered") 100 | NV_STATUS_CODE(NV_ERR_MEMORY_TRAINING_FAILED, 0x00000047, "Failed memory training sequence") 101 | NV_STATUS_CODE(NV_ERR_MISMATCHED_SLAVE, 0x00000048, "Slave mismatch") 102 | NV_STATUS_CODE(NV_ERR_MISMATCHED_TARGET, 0x00000049, "Target mismatch") 103 | NV_STATUS_CODE(NV_ERR_MISSING_TABLE_ENTRY, 0x0000004A, "Requested entry missing not found in the table") 104 | NV_STATUS_CODE(NV_ERR_MODULE_LOAD_FAILED, 0x0000004B, "Failed to load the requested module") 105 | NV_STATUS_CODE(NV_ERR_MORE_DATA_AVAILABLE, 0x0000004C, "There is more data available") 106 | NV_STATUS_CODE(NV_ERR_MORE_PROCESSING_REQUIRED, 0x0000004D, "More processing required for the given call") 107 | NV_STATUS_CODE(NV_ERR_MULTIPLE_MEMORY_TYPES, 0x0000004E, "Multiple memory types found") 108 | NV_STATUS_CODE(NV_ERR_NO_FREE_FIFOS, 0x0000004F, "No more free FIFOs found") 109 | NV_STATUS_CODE(NV_ERR_NO_INTR_PENDING, 0x00000050, "No interrupt pending") 110 | NV_STATUS_CODE(NV_ERR_NO_MEMORY, 0x00000051, "Out of memory") 111 | NV_STATUS_CODE(NV_ERR_NO_SUCH_DOMAIN, 0x00000052, "Requested domain does not exist") 112 | NV_STATUS_CODE(NV_ERR_NO_VALID_PATH, 0x00000053, "Caller did not specify a valid path") 113 | NV_STATUS_CODE(NV_ERR_NOT_COMPATIBLE, 0x00000054, "Generic Error: Incompatible types") 114 | NV_STATUS_CODE(NV_ERR_NOT_READY, 0x00000055, "Generic Error: Not ready") 115 | NV_STATUS_CODE(NV_ERR_NOT_SUPPORTED, 0x00000056, "Call not supported") 116 | NV_STATUS_CODE(NV_ERR_OBJECT_NOT_FOUND, 0x00000057, "Requested object not found") 117 | NV_STATUS_CODE(NV_ERR_OBJECT_TYPE_MISMATCH, 0x00000058, "Specified objects do not match") 118 | NV_STATUS_CODE(NV_ERR_OPERATING_SYSTEM, 0x00000059, "Generic operating system error") 119 | NV_STATUS_CODE(NV_ERR_OTHER_DEVICE_FOUND, 0x0000005A, "Found other device instead of the requested one") 120 | NV_STATUS_CODE(NV_ERR_OUT_OF_RANGE, 0x0000005B, "The specified value is out of bounds") 121 | NV_STATUS_CODE(NV_ERR_OVERLAPPING_UVM_COMMIT, 0x0000005C, "Overlapping unified virtual memory commit") 122 | NV_STATUS_CODE(NV_ERR_PAGE_TABLE_NOT_AVAIL, 0x0000005D, "Requested page table not available") 123 | NV_STATUS_CODE(NV_ERR_PID_NOT_FOUND, 0x0000005E, "Process-Id not found") 124 | NV_STATUS_CODE(NV_ERR_PROTECTION_FAULT, 0x0000005F, "Protection fault") 125 | NV_STATUS_CODE(NV_ERR_RC_ERROR, 0x00000060, "Generic RC error") 126 | NV_STATUS_CODE(NV_ERR_REJECTED_VBIOS, 0x00000061, "Given Video BIOS rejected/invalid") 127 | NV_STATUS_CODE(NV_ERR_RESET_REQUIRED, 0x00000062, "Reset required") 128 | NV_STATUS_CODE(NV_ERR_STATE_IN_USE, 0x00000063, "State in use") 129 | NV_STATUS_CODE(NV_ERR_SIGNAL_PENDING, 0x00000064, "Signal pending") 130 | NV_STATUS_CODE(NV_ERR_TIMEOUT, 0x00000065, "Call timed out") 131 | NV_STATUS_CODE(NV_ERR_TIMEOUT_RETRY, 0x00000066, "Call timed out, please retry later") 132 | NV_STATUS_CODE(NV_ERR_TOO_MANY_PRIMARIES, 0x00000067, "Too many primaries") 133 | NV_STATUS_CODE(NV_ERR_UVM_ADDRESS_IN_USE, 0x00000068, "Unified virtual memory requested address already in use") 134 | NV_STATUS_CODE(NV_ERR_MAX_SESSION_LIMIT_REACHED, 0x00000069, "Maximum number of sessions reached") 135 | NV_STATUS_CODE(NV_ERR_LIB_RM_VERSION_MISMATCH, 0x0000006A, "Library version doesn't match driver version") //Contained within the RMAPI library 136 | NV_STATUS_CODE(NV_ERR_PRIV_SEC_VIOLATION, 0x0000006B, "Priv security violation") 137 | NV_STATUS_CODE(NV_ERR_GPU_IN_DEBUG_MODE, 0x0000006C, "GPU currently in debug mode") 138 | NV_STATUS_CODE(NV_ERR_FEATURE_NOT_ENABLED, 0x0000006D, "Requested Feature functionality is not enabled") 139 | NV_STATUS_CODE(NV_ERR_RESOURCE_LOST, 0x0000006E, "Requested resource has been destroyed") 140 | NV_STATUS_CODE(NV_ERR_PMU_NOT_READY, 0x0000006F, "PMU is not ready or has not yet been initialized") 141 | NV_STATUS_CODE(NV_ERR_FLCN_ERROR, 0x00000070, "Generic falcon assert or halt") 142 | NV_STATUS_CODE(NV_ERR_FATAL_ERROR, 0x00000071, "Fatal/unrecoverable error") 143 | NV_STATUS_CODE(NV_ERR_MEMORY_ERROR, 0x00000072, "Generic memory error") 144 | NV_STATUS_CODE(NV_ERR_INVALID_LICENSE, 0x00000073, "License provided is rejected or invalid") 145 | NV_STATUS_CODE(NV_ERR_NVLINK_INIT_ERROR, 0x00000074, "Nvlink Init Error") 146 | NV_STATUS_CODE(NV_ERR_NVLINK_MINION_ERROR, 0x00000075, "Nvlink Minion Error") 147 | NV_STATUS_CODE(NV_ERR_NVLINK_CLOCK_ERROR, 0x00000076, "Nvlink Clock Error") 148 | NV_STATUS_CODE(NV_ERR_NVLINK_TRAINING_ERROR, 0x00000077, "Nvlink Training Error") 149 | NV_STATUS_CODE(NV_ERR_NVLINK_CONFIGURATION_ERROR, 0x00000078, "Nvlink Configuration Error") 150 | NV_STATUS_CODE(NV_ERR_RISCV_ERROR, 0x00000079, "Generic RISC-V assert or halt") 151 | NV_STATUS_CODE(NV_ERR_FABRIC_MANAGER_NOT_PRESENT, 0x0000007A, "Fabric Manager is not loaded") 152 | NV_STATUS_CODE(NV_ERR_ALREADY_SIGNALLED, 0x0000007B, "Semaphore Surface value already >= requested wait value") 153 | NV_STATUS_CODE(NV_ERR_QUEUE_TASK_SLOT_NOT_AVAILABLE, 0x0000007C, "PMU RPC error due to no queue slot available for this event") 154 | NV_STATUS_CODE(NV_ERR_KEY_ROTATION_IN_PROGRESS, 0x0000007D, "Operation not allowed as key rotation is in progress") 155 | NV_STATUS_CODE(NV_ERR_TEST_ONLY_CODE_NOT_ENABLED, 0x0000007E, "Test-only code path not enabled") 156 | NV_STATUS_CODE(NV_ERR_SECURE_BOOT_FAILED, 0x0000007F, "GFW secure boot failed") 157 | NV_STATUS_CODE(NV_ERR_INSUFFICIENT_ZBC_ENTRY, 0x00000080, "No more ZBC entry for the client") 158 | NV_STATUS_CODE(NV_ERR_NVLINK_FABRIC_NOT_READY, 0x00000081, "Nvlink Fabric Status or Fabric Probe is not yet complete, caller needs to retry") 159 | NV_STATUS_CODE(NV_ERR_NVLINK_FABRIC_FAILURE, 0x00000082, "Nvlink Fabric Probe failed") 160 | NV_STATUS_CODE(NV_ERR_GPU_MEMORY_ONLINING_FAILURE, 0x00000083, "GPU Memory Onlining failed") 161 | NV_STATUS_CODE(NV_ERR_REDUCTION_MANAGER_NOT_AVAILABLE, 0x00000084, "Reduction Manager is not available") 162 | NV_STATUS_CODE(NV_ERR_THRESHOLD_CROSSED, 0x00000085, "A fatal threshold has been crossed") 163 | NV_STATUS_CODE(NV_ERR_RESOURCE_RETIREMENT_ERROR, 0x00000086, "An error occurred while trying to retire a resource") 164 | NV_STATUS_CODE(NV_ERR_FABRIC_STATE_OUT_OF_SYNC, 0x00000087, "NVLink fabric state cached by the driver is out of sync") 165 | NV_STATUS_CODE(NV_ERR_BUFFER_FULL, 0x00000088, "Buffer is full") 166 | NV_STATUS_CODE(NV_ERR_BUFFER_EMPTY, 0x00000089, "Buffer is empty") 167 | NV_STATUS_CODE(NV_ERR_MC_FLA_OFFSET_TABLE_FULL, 0x0000008A, "Multicast FLA offset table has no available slots") 168 | NV_STATUS_CODE(NV_ERR_DMA_XFER_FAILED, 0x0000008B, "DMA transfer failed") 169 | 170 | // Warnings: 171 | NV_STATUS_CODE(NV_WARN_HOT_SWITCH, 0x00010001, "WARNING Hot switch") 172 | NV_STATUS_CODE(NV_WARN_INCORRECT_PERFMON_DATA, 0x00010002, "WARNING Incorrect performance monitor data") 173 | NV_STATUS_CODE(NV_WARN_MISMATCHED_SLAVE, 0x00010003, "WARNING Slave mismatch") 174 | NV_STATUS_CODE(NV_WARN_MISMATCHED_TARGET, 0x00010004, "WARNING Target mismatch") 175 | NV_STATUS_CODE(NV_WARN_MORE_PROCESSING_REQUIRED, 0x00010005, "WARNING More processing required for the call") 176 | NV_STATUS_CODE(NV_WARN_NOTHING_TO_DO, 0x00010006, "WARNING Nothing to do") 177 | NV_STATUS_CODE(NV_WARN_NULL_OBJECT, 0x00010007, "WARNING NULL object found") 178 | NV_STATUS_CODE(NV_WARN_OUT_OF_RANGE, 0x00010008, "WARNING value out of range") 179 | NV_STATUS_CODE(NV_WARN_THRESHOLD_CROSSED, 0x00010009, "WARNING Threshold has been crossed") 180 | 181 | #endif /* SDK_NVSTATUSCODES_H */ 182 | -------------------------------------------------------------------------------- /nvidia-cfg.h: -------------------------------------------------------------------------------- 1 | /* 2 | * nvidia-cfg 3 | * 4 | * Copyright (c) 2004-2025 NVIDIA Corp. All rights reserved. 5 | * 6 | * NOTICE TO USER: The source code is copyrighted under U.S. and 7 | * international laws. NVIDIA, Corp. of Santa Clara, California owns 8 | * the copyright and as design patents pending on the design and 9 | * interface of the NV chips. Users and possessors of this source 10 | * code are hereby granted a nonexclusive, royalty-free copyright 11 | * and design patent license to use this code in individual and 12 | * commercial software. 13 | * 14 | * Any use of this source code must include, in the user documenta- 15 | * tion and internal comments to the code, notices to the end user 16 | * as follows: 17 | * 18 | * Copyright (c) 2004-2025 NVIDIA Corp. NVIDIA design patents pending in 19 | * the U.S. and foreign countries. 20 | * 21 | * NVIDIA CORP. MAKES NO REPRESENTATION ABOUT THE SUITABILITY OF 22 | * THIS SOURCE CODE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" WITHOUT 23 | * EXPRESS OR IMPLIED WARRANTY OF ANY KIND. NVIDIA, CORP. DISCLAIMS 24 | * ALL WARRANTIES WITH REGARD TO THIS SOURCE CODE, INCLUDING ALL 25 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 26 | * PARTICULAR PURPOSE. IN NO EVENT SHALL NVIDIA, CORP. BE LIABLE 27 | * FOR ANY SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, 28 | * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 29 | * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 30 | * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 31 | * PERFORMANCE OF THIS SOURCE CODE. 32 | * 33 | * 34 | * This header file defines the public interface to the 35 | * libnvidia-cfg.so library. 36 | */ 37 | 38 | #ifndef __NVIDIA_CFG_H__ 39 | #define __NVIDIA_CFG_H__ 40 | 41 | 42 | 43 | /* 44 | * NvCfgDevice - data structure containing bus:slot pairs 45 | * 46 | * This is deprecated; please use NvCfgPciDevice instead 47 | */ 48 | 49 | typedef struct { 50 | int bus; 51 | int slot; 52 | } NvCfgDevice; 53 | 54 | 55 | /* 56 | * NvCfgPciDevice - data structure identifying a device on the PCI bus 57 | */ 58 | 59 | typedef struct { 60 | int domain; 61 | int bus; 62 | int slot; 63 | int function; 64 | } NvCfgPciDevice; 65 | 66 | 67 | /* 68 | * NvCfgGSyncDeviceType - type of the GSync device 69 | */ 70 | 71 | typedef enum { 72 | NVCFG_TYPE_GSYNC2 = 1, 73 | NVCFG_TYPE_GSYNC3, 74 | NVCFG_TYPE_GSYNC4 75 | } NvCfgGSyncDeviceType; 76 | 77 | 78 | 79 | #define NV_CFG_GSYNC_DEVICE_FIRMWARE_FORMAT_1 1 80 | 81 | 82 | 83 | /* 84 | * NvCfgDisplayDeviceInformation - this data structure contains 85 | * various limits and other useful data parsed from the EDID. 86 | */ 87 | 88 | typedef struct { 89 | 90 | /* 91 | * The monitor name is the name of the monitor as specified by an 92 | * EDID 1.x Monitor Descriptors, or an EDID 2.x 93 | * Manufacturer/Product ID string. 94 | */ 95 | 96 | char monitor_name[64]; 97 | 98 | /* 99 | * The horiz_sync and vert_refresh ranges are retrieved from an 100 | * EDID 1.x Monitor Descriptor, or an EDID 2.x Range Limit. 101 | */ 102 | 103 | unsigned int min_horiz_sync; /* in Hz */ 104 | unsigned int max_horiz_sync; /* in Hz */ 105 | unsigned int min_vert_refresh; /* in Hz */ 106 | unsigned int max_vert_refresh; /* in Hz */ 107 | 108 | unsigned int max_pixel_clock; /* in kHz */ 109 | 110 | /* 111 | * The max xres, yres, and refresh, if not 0, are taken from the 112 | * largest mode in the EDID. 113 | */ 114 | 115 | unsigned int max_xres; /* in pixels */ 116 | unsigned int max_yres; /* in pixels */ 117 | unsigned int max_refresh; /* in Hz */ 118 | 119 | /* 120 | * the preferred xres, yres, and refresh, if not 0, are the values 121 | * specified by the EDID as the preferred timing mode of the 122 | * display device. 123 | */ 124 | 125 | unsigned int preferred_xres; /* in pixels */ 126 | unsigned int preferred_yres; /* in pixels */ 127 | unsigned int preferred_refresh; /* in Hz */ 128 | 129 | /* 130 | * the physical width and height, if not 0, are the physical 131 | * dimensions of the display device. 132 | */ 133 | 134 | unsigned int physical_width; /* in mm */ 135 | unsigned int physical_height; /* in mm */ 136 | 137 | } NvCfgDisplayDeviceInformation; 138 | 139 | 140 | 141 | /* 142 | * NvCfgDeviceHandle - this is an opaque handle identifying a 143 | * connection to an NVIDIA VGA adapter. 144 | */ 145 | 146 | typedef void * NvCfgDeviceHandle; 147 | 148 | 149 | 150 | /* 151 | * NvCfgGSyncHandle - this is an opaque handle identifying a 152 | * GSync device. 153 | */ 154 | 155 | typedef void * NvCfgGSyncHandle; 156 | 157 | 158 | 159 | /* 160 | * NvCfg Boolean values 161 | */ 162 | 163 | typedef enum { 164 | NVCFG_TRUE = 1, 165 | NVCFG_FALSE = 0, 166 | } NvCfgBool; 167 | 168 | 169 | 170 | /* 171 | * NvCfgProgressTickCallbackProc - callback function type for reporting 172 | * progress on firmware flashing. progress is a float value between 0.0 173 | * and 1.0. reset is a NvCfgBool that is NVCFG_TRUE if the flash operation 174 | * is being reset. 175 | */ 176 | typedef void (*NvCfgProgressTickCallbackProc)(float progress, NvCfgBool reset); 177 | 178 | 179 | 180 | /* 181 | * nvCfgGetDevices() - retrieve an array of NvCfgDevice's indicating 182 | * what PCI devices are present on the system. On success, NVCFG_TRUE 183 | * will be returned, n will contain the number of NVIDIA PCI VGA 184 | * adapters present in the system, and devs will be an allocated array 185 | * containing the bus address of each NVIDIA PCI VGA adapter. When 186 | * the caller is done, it should free the devs array. On failure, 187 | * NVCFG_FALSE will be returned. 188 | * 189 | * This is deprecated; please use nvCfgGetPciDevices() instead. 190 | */ 191 | 192 | NvCfgBool nvCfgGetDevices(int *n, NvCfgDevice **devs); 193 | 194 | 195 | 196 | /* 197 | * nvCfgGetPciDevices() - retrieve an array of NvCfgPciDevice's 198 | * indicating what PCI devices are present on the system. On success, 199 | * NVCFG_TRUE will be returned, n will contain the number of NVIDIA 200 | * PCI graphics devices present in the system, and devs will be an 201 | * allocated array containing the PCI domain:bus:slot:function 202 | * address of each NVIDIA PCI graphics device. When the caller is 203 | * done, it should free the devs array. On failure, NVCFG_FALSE will 204 | * be returned. 205 | */ 206 | 207 | NvCfgBool nvCfgGetPciDevices(int *n, NvCfgPciDevice **devs); 208 | 209 | 210 | 211 | /* 212 | * nvCfgOpenDevice() - open a connection to the NVIDIA device 213 | * identified by the bus:slot PCI address. On success, NVCFG_TRUE 214 | * will be returned and handle be assigned. On failure, NVCFG_FALSE 215 | * will be returned. 216 | * 217 | * This is deprecated; please use nvCfgOpenPciDevice() instead. 218 | */ 219 | 220 | NvCfgBool nvCfgOpenDevice(int bus, int slot, NvCfgDeviceHandle *handle); 221 | 222 | 223 | 224 | /* 225 | * nvCfgAttachPciDevice() - open a limited, display-less connection to 226 | * the NVIDIA device identified by the domain:bus:slot:function PCI 227 | * address. On success, NVCFG_TRUE will be returned and handle will be 228 | * assigned. On failure, NVCFG_FALSE will be returned. 229 | */ 230 | NvCfgBool nvCfgAttachPciDevice(int domain, int bus, int device, int function, 231 | NvCfgDeviceHandle *handle); 232 | 233 | 234 | 235 | /* 236 | * nvCfgOpenPciDevice() - open a connection to the NVIDIA device 237 | * identified by the domain:bus:slot:function PCI address. On 238 | * success, NVCFG_TRUE will be returned and handle will be assigned. 239 | * On failure, NVCFG_FALSE will be returned. 240 | */ 241 | 242 | NvCfgBool nvCfgOpenPciDevice(int domain, int bus, int device, int function, 243 | NvCfgDeviceHandle *handle); 244 | 245 | 246 | 247 | /* 248 | * nvCfgOpenAllPciDevices() - open a connection to each NVIDIA device 249 | * in the system. On success, NVCFG_TRUE will be returned, n will be 250 | * assigned the number of NVIDIA devices in the system, and handles 251 | * will be assigned with an allocated array of NvCfgDeviceHandles; 252 | * each element in the array is a handle to one of the NVIDIA devices 253 | * in the system. The caller should free the handles array when no 254 | * longer needed. On failure, NVCFG_FALSE will be returned. 255 | */ 256 | 257 | NvCfgBool nvCfgOpenAllPciDevices(int *n, NvCfgDeviceHandle **handles); 258 | 259 | 260 | 261 | /* 262 | * nvCfgDetachDevice() - close the previously opened limited, display-less 263 | * connection to an NVIDIA device created by nvCfgAttachPciDevice(). 264 | */ 265 | NvCfgBool nvCfgDetachDevice(NvCfgDeviceHandle handle); 266 | 267 | 268 | 269 | /* 270 | * nvCfgCloseDevice() - close the previously opened connection to an 271 | * NVIDIA device created by nvCfgOpenPciDevice(). 272 | */ 273 | 274 | NvCfgBool nvCfgCloseDevice(NvCfgDeviceHandle handle); 275 | 276 | 277 | 278 | /* 279 | * nvCfgCloseAllPciDevices() - close all the NVIDIA device connections 280 | * opened by a previous call to nvCfgOpenAllPciDevices(). 281 | */ 282 | 283 | NvCfgBool nvCfgCloseAllPciDevices(void); 284 | 285 | 286 | 287 | /* 288 | * nvCfgGetNumCRTCs() - return the number of CRTCs (aka "heads") 289 | * present on the specified NVIDIA device. On success, NVCFG_TRUE 290 | * will be returned and crtcs will be assigned. On failure, 291 | * NVCFG_FALSE will be returned. 292 | */ 293 | 294 | NvCfgBool nvCfgGetNumCRTCs(NvCfgDeviceHandle handle, int *crtcs); 295 | 296 | 297 | 298 | /* 299 | * nvCfgGetProductName() - return an allocated string containing the 300 | * product name of the specified NVIDIA device. It is the caller's 301 | * responsibility to free the returned string. On success, NVCFG_TRUE 302 | * will be returned and name will be assigned. On failure, 303 | * NVCFG_FALSE will be returned. 304 | */ 305 | 306 | NvCfgBool nvCfgGetProductName(NvCfgDeviceHandle handle, char **name); 307 | 308 | 309 | 310 | /* 311 | * nvCfgGetDeviceUUID() - return an allocated string containing the 312 | * global unique identifier of the specified NVIDIA device. It is the caller's 313 | * responsibility to free the returned string. On success, NVCFG_TRUE 314 | * will be returned and uuid will be assigned. On failure, 315 | * NVCFG_FALSE will be returned. 316 | */ 317 | 318 | NvCfgBool nvCfgGetDeviceUUID(NvCfgDeviceHandle handle, char **uuid); 319 | 320 | 321 | 322 | /* 323 | * nvCfgGetDisplayDevices() - retrieve a bitmask describing the 324 | * currently connected display devices: this "display device mask" is 325 | * an unsigned 32 bit value that identifies one or more display 326 | * devices. The first 8 bits each identify a CRT, the next 8 bits 327 | * each identify a TV, and the next 8 each identify a DFP. For 328 | * example, 0x1 refers to CRT-0, 0x3 refers to CRT-0 and CRT-1, 329 | * 0x10001 refers to CRT-0 and DFP-0, etc. On success, NVCFG_TRUE 330 | * will be returned and display_device_mask will be assigned. On 331 | * failure, NVCFG_FALSE will be returned. 332 | */ 333 | 334 | NvCfgBool nvCfgGetDisplayDevices(NvCfgDeviceHandle handle, 335 | unsigned int *display_device_mask); 336 | 337 | 338 | 339 | /* nvCfgGetSupportedDisplayDevices() - get all supported display devices, 340 | * not only connected ones. Interpretation of display_device_mask 341 | * parameter is the same as for nvCfgGetDisplayDevices() call. 342 | * On success, NVCFG_TRUE will be returned and display_device_mask will be 343 | * assigned. On failure, NVCFG_FALSE will be returned. 344 | */ 345 | 346 | NvCfgBool nvCfgGetSupportedDisplayDevices(NvCfgDeviceHandle handle, 347 | unsigned int *display_device_mask); 348 | 349 | 350 | /* 351 | * nvCfgGetEDIDData() - return an allocated byte array containing the 352 | * EDID for the specified display device, if any. On success, 353 | * NVCFG_TRUE will be returned and edidSize and edid will be assigned. 354 | * On failure, NVCFG_FALSE will be returned. It is the caller's 355 | * responsibility to free the allocated EDID. 356 | */ 357 | 358 | NvCfgBool nvCfgGetEDIDData(NvCfgDeviceHandle handle, 359 | unsigned int display_device, 360 | int *edidSize, void **edid); 361 | 362 | 363 | /* 364 | * nvCfgGetEDIDMonitorData() - Initialize the fields in the 365 | * NvCfgDisplayDeviceInformation data structure, using data from the 366 | * EDID. On success, NVCFG_TRUE will be returned and info will be 367 | * assigned. On failure, NVCFG_FALSE will be returned. 368 | */ 369 | 370 | NvCfgBool nvCfgGetEDID(NvCfgDeviceHandle handle, 371 | unsigned int display_device, 372 | NvCfgDisplayDeviceInformation *info); 373 | 374 | 375 | /* 376 | * nvCfgIsPrimaryDevice() - determines whether the specified NVIDIA 377 | * device is the primary device. On success, NVCFG_TRUE will be 378 | * returned and is_primary_device set to indicate whether the 379 | * device is the primary device. On failure, NVCFG_FALSE will be 380 | * returned. 381 | */ 382 | 383 | NvCfgBool nvCfgIsPrimaryDevice(NvCfgDeviceHandle handle, 384 | NvCfgBool *is_primary_device); 385 | 386 | /* 387 | * nvCfgGetTeslaSerialNumbers() - returns an allocated array of strings 388 | * containing the serial numbers of all NVIDIA Tesla/QuadroPlex devices 389 | * connected to the host, followed by a NULL character. It is the caller's 390 | * responsibility to free the returned array of strings. On success, 391 | * NVCFG_TRUE will be returned and serials will be assigned. On failure, 392 | * NVCFG_FALSE will be returned. 393 | * 394 | * Note that this function is deprecated and will always return an empty array 395 | * on recent drivers, since QuadroPlex devices are no longer supported. 396 | */ 397 | 398 | NvCfgBool nvCfgGetTeslaSerialNumbers(char ***serials); 399 | 400 | 401 | /* 402 | * nvCfgOpenAllGSyncDevices() - returns an array of NvCfgGSyncHandle's 403 | * indicating what GSync devices are present in the system. On success, 404 | * NVCFG_TRUE will be returned, n will contain the number of GSync devices 405 | * present in the system, and handles will be an allocated array containing 406 | * a handle for each of the GSync devices.The caller should free the 407 | * handles array when no longer needed. On failure, NVCFG_FALSE will be 408 | * returned. 409 | */ 410 | 411 | NvCfgBool nvCfgOpenAllGSyncDevices(int *n, NvCfgGSyncHandle **handles); 412 | 413 | 414 | /* 415 | * nvCfgCloseAllGSyncDevices() - close all the GSync device connections 416 | * opened by a previous call to nvCfgOpenAllGSyncDevices(). 417 | */ 418 | 419 | NvCfgBool nvCfgCloseAllGSyncDevices(void); 420 | 421 | 422 | /* 423 | * nvCfgGetGSyncDeviceType() - returns the type of GSync device referenced 424 | * by handle. 425 | */ 426 | 427 | NvCfgGSyncDeviceType nvCfgGetGSyncDeviceType(NvCfgGSyncHandle handle); 428 | 429 | 430 | /* 431 | * nvCfgGetGSyncDeviceFirmwareVersion() - returns the firmware major version of 432 | * the GSync device referenced by handle. 433 | */ 434 | 435 | int nvCfgGetGSyncDeviceFirmwareVersion(NvCfgGSyncHandle handle); 436 | 437 | 438 | /* 439 | * nvCfgGetGSyncDeviceFirmwareMinorVersion() - returns the firmware minor 440 | * version of the GSync device referenced by handle. 441 | */ 442 | 443 | int nvCfgGetGSyncDeviceFirmwareMinorVersion(NvCfgGSyncHandle handle); 444 | 445 | 446 | /* 447 | * nvCfgFlashGSyncDevice() - flashes the GSync device referenced by handle. 448 | * format contains the firmware format, newFirmwareImage contains the 449 | * new firmware image to be flashed, and size contains the size of 450 | * newFirmwareImage. On success, NVCFG_TRUE will be returned. 451 | * On failure, NVCFG_FALSE will be returned. 452 | */ 453 | 454 | NvCfgBool nvCfgFlashGSyncDevice(NvCfgGSyncHandle handle, int format, 455 | const unsigned char *newFirmwareImage, 456 | int size); 457 | 458 | 459 | /* 460 | * nvCfgFlashGSyncDeviceWithProgress() - extended version of nvCfgFlashGSyncDevice() 461 | * that allows for progress callback during firmware flashing. The progressCallback 462 | * function is called periodically during the flash operation to report 463 | * progress. 464 | */ 465 | 466 | NvCfgBool nvCfgFlashGSyncDeviceWithProgress(NvCfgGSyncHandle handle, int format, 467 | const unsigned char *newFirmwareImage, int size, 468 | NvCfgProgressTickCallbackProc progressCallback); 469 | 470 | 471 | /* 472 | * nvCfgDumpDisplayPortAuxLog() - dump the DisplayPort AUX channel log to the 473 | * system log. On success, NVCFG_TRUE will be returned. On failure, NVCFG_FALSE 474 | * will be returned. 475 | */ 476 | NvCfgBool nvCfgDumpDisplayPortAuxLog(NvCfgDeviceHandle handle); 477 | 478 | /* 479 | * nvCfgEnableUvmPersistence() - Enable UVM Persistence mode. 480 | * On success, zero will be returned. On failure, non zero 481 | * value will be returned. 482 | * This API is for internal use only and will be removed 483 | * in a future release. 484 | */ 485 | unsigned int nvCfgEnableUVMPersistence(NvCfgDeviceHandle handle); 486 | 487 | /* 488 | * nvCfgDisableUVMPersistence() - Disable UVM Persistence mode. 489 | * On success, zero will be returned. On failure, non-zero 490 | * value will be returned. 491 | * This API is for internal use only and will be removed 492 | * in a future release. 493 | */ 494 | unsigned int nvCfgDisableUVMPersistence(NvCfgDeviceHandle handle); 495 | 496 | #endif /* __NVIDIA_CFG__ */ 497 | -------------------------------------------------------------------------------- /common-utils/common-utils.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010-2012 NVIDIA Corporation 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | 24 | #include 25 | #include 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | #include 36 | #include 37 | #include 38 | 39 | #include "common-utils.h" 40 | 41 | 42 | /****************************************************************************/ 43 | /* Memory allocation helper functions */ 44 | /****************************************************************************/ 45 | 46 | /* 47 | * nvalloc() - calloc wrapper that checks for errors; if an error 48 | * occurs, an error is printed to stderr and exit is called -- this 49 | * function will only return on success. 50 | */ 51 | 52 | void *nvalloc(size_t size) 53 | { 54 | void *m = calloc(1, size); 55 | 56 | if (!m) { 57 | fprintf(stderr, "%s: memory allocation failure (%s)! \n", 58 | PROGRAM_NAME, strerror(errno)); 59 | exit(1); 60 | } 61 | return m; 62 | 63 | } /* nvalloc() */ 64 | 65 | 66 | 67 | /* 68 | * nvvstrcat() - allocate a new string, copying all given strings 69 | * into it. 70 | */ 71 | 72 | char *nvvstrcat(const char *str, va_list ap) 73 | { 74 | const char *s; 75 | char *result; 76 | size_t len; 77 | va_list ap2; 78 | 79 | /* walk the varargs to compute the length of the result string */ 80 | 81 | va_copy(ap2, ap); 82 | 83 | for (s = str, len = 1; s; s = va_arg(ap2, char *)) { 84 | len += strlen(s); 85 | } 86 | 87 | va_end(ap2); 88 | 89 | /* allocate the result string */ 90 | 91 | result = nvalloc(len); 92 | if (!result) { 93 | return result; 94 | } 95 | result[0] = '\0'; 96 | 97 | /* concatenate the input strings, writing into the result string */ 98 | 99 | for (s = str; s; s = va_arg(ap, char *)) { 100 | strcat(result, s); 101 | } 102 | 103 | return result; 104 | } /* nvstrcat() */ 105 | 106 | 107 | /* 108 | * nvstrcat() - allocate a new string, copying all given strings 109 | * into it. 110 | */ 111 | 112 | char *nvstrcat(const char *str, ...) 113 | { 114 | va_list ap; 115 | char *ret; 116 | 117 | va_start(ap, str); 118 | ret = nvvstrcat(str, ap); 119 | va_end(ap); 120 | 121 | return ret; 122 | } 123 | 124 | /* 125 | * nvrealloc() - realloc wrapper that checks for errors; if an error 126 | * occurs, an error is printed to stderr and exit is called -- this 127 | * function will only return on success. 128 | */ 129 | 130 | void *nvrealloc(void *ptr, size_t size) 131 | { 132 | void *m; 133 | 134 | if (ptr == NULL) return nvalloc(size); 135 | 136 | m = realloc(ptr, size); 137 | if (!m) { 138 | fprintf(stderr, "%s: memory re-allocation failure (%s)! \n", 139 | PROGRAM_NAME, strerror(errno)); 140 | exit(1); 141 | } 142 | return m; 143 | 144 | } /* nvrealloc() */ 145 | 146 | 147 | 148 | /* 149 | * nvstrdup() - wrapper for strdup() that checks the return value; if 150 | * an error occurs, an error is printed to stderr and exit is called 151 | * -- this function will only return on success. 152 | */ 153 | 154 | char *nvstrdup(const char *s) 155 | { 156 | char *m; 157 | 158 | if (!s) return NULL; 159 | 160 | m = strdup(s); 161 | 162 | if (!m) { 163 | fprintf(stderr, "%s: memory allocation failure during strdup (%s)! \n", 164 | PROGRAM_NAME, strerror(errno)); 165 | exit(1); 166 | } 167 | return m; 168 | 169 | } /* nvstrdup() */ 170 | 171 | 172 | 173 | /* 174 | * nvstrndup() - implementation of strndup() that checks return values; if 175 | * an error occurs, an error is printed to stderr and exit is called 176 | * -- this function will only return on success. 177 | */ 178 | 179 | char *nvstrndup(const char *s, size_t n) 180 | { 181 | char *m; 182 | 183 | if (!s) return NULL; 184 | 185 | m = malloc(n + 1); 186 | 187 | if (!m) { 188 | fprintf(stderr, "%s: memory allocation failure during malloc (%s)! \n", 189 | PROGRAM_NAME, strerror(errno)); 190 | exit(1); 191 | } 192 | 193 | strncpy (m, s, n); 194 | m[n] = '\0'; 195 | 196 | return m; 197 | 198 | } /* nvstrndup() */ 199 | 200 | 201 | 202 | /* 203 | * nvstrtolower() - convert the given string to lowercase. 204 | */ 205 | 206 | char *nvstrtolower(char *s) 207 | { 208 | char *start = s; 209 | 210 | if (s == NULL) return NULL; 211 | 212 | while (*s) { 213 | *s = tolower(*s); 214 | s++; 215 | } 216 | 217 | return start; 218 | 219 | } /* nvstrtolower() */ 220 | 221 | 222 | 223 | /* 224 | * nvstrtoupper() - convert the given string to uppercase. 225 | */ 226 | 227 | char *nvstrtoupper(char *s) 228 | { 229 | char *start = s; 230 | 231 | if (s == NULL) return NULL; 232 | 233 | while (*s) { 234 | *s = toupper(*s); 235 | s++; 236 | } 237 | 238 | return start; 239 | 240 | } /* nvstrtoupper() */ 241 | 242 | 243 | 244 | /* 245 | * nvasprintf() - implementation of asprintf() that checks return values; if an 246 | * error occurs, an error is printed to stderr and exit is called. 247 | * -- this function will only return on success. 248 | */ 249 | char *nvasprintf(const char *fmt, ...) 250 | { 251 | char *str; 252 | 253 | NV_VSNPRINTF(str, fmt); 254 | 255 | return str; 256 | 257 | } /* nvasprintf() */ 258 | 259 | /* 260 | * nv_append_sprintf() - similar to glib's g_string_append_printf(), except 261 | * instead of operating on a GString it operates on a (char **). Appends a 262 | * formatted string to the end of the dynamically-allocated string pointed to by 263 | * *buf (or the empty string if *buf is NULL), potentially reallocating the 264 | * string in the process. This function only returns on success. 265 | */ 266 | void nv_append_sprintf(char **buf, const char *fmt, ...) 267 | { 268 | char *prefix, *suffix; 269 | 270 | prefix = *buf; 271 | NV_VSNPRINTF(suffix, fmt); 272 | 273 | if (!prefix) { 274 | *buf = suffix; 275 | } else { 276 | *buf = nvstrcat(prefix, suffix, NULL); 277 | free(prefix); 278 | free(suffix); 279 | } 280 | } 281 | 282 | 283 | /* 284 | * nvfree() - frees memory allocated with nvalloc(), provided 285 | * a non-NULL pointer is provided. 286 | */ 287 | void nvfree(void *s) 288 | { 289 | if (s) free(s); 290 | 291 | } /* nvfree() */ 292 | 293 | 294 | 295 | /****************************************************************************/ 296 | /* misc */ 297 | /****************************************************************************/ 298 | 299 | /* 300 | * tilde_expansion() - do tilde expansion on the given path name; 301 | * based loosely on code snippets found in the comp.unix.programmer 302 | * FAQ. The tilde expansion rule is: if a tilde ('~') is alone or 303 | * followed by a '/', then substitute the current user's home 304 | * directory; if followed by the name of a user, then substitute that 305 | * user's home directory. 306 | * 307 | * Returns NULL if its argument is NULL; otherwise, returns a malloced 308 | * and tilde-expanded string. 309 | */ 310 | 311 | char *tilde_expansion(const char *str) 312 | { 313 | char *prefix = NULL; 314 | const char *replace; 315 | char *user, *ret; 316 | struct passwd *pw; 317 | int len; 318 | 319 | if (!str) return NULL; 320 | 321 | if (str[0] != '~') return strdup(str); 322 | 323 | if ((str[1] == '/') || (str[1] == '\0')) { 324 | 325 | /* expand to the current user's home directory */ 326 | 327 | prefix = getenv("HOME"); 328 | if (!prefix) { 329 | 330 | /* $HOME isn't set; get the home directory from /etc/passwd */ 331 | 332 | pw = getpwuid(getuid()); 333 | if (pw) prefix = pw->pw_dir; 334 | } 335 | 336 | replace = str + 1; 337 | 338 | } else { 339 | 340 | /* expand to the specified user's home directory */ 341 | 342 | replace = strchr(str, '/'); 343 | if (!replace) replace = str + strlen(str); 344 | 345 | len = replace - str; 346 | user = malloc(len + 1); 347 | strncpy(user, str+1, len-1); 348 | user[len] = '\0'; 349 | pw = getpwnam(user); 350 | if (pw) prefix = pw->pw_dir; 351 | free (user); 352 | } 353 | 354 | if (!prefix) return strdup(str); 355 | 356 | ret = malloc(strlen(prefix) + strlen(replace) + 1); 357 | strcpy(ret, prefix); 358 | strcat(ret, replace); 359 | 360 | return ret; 361 | 362 | } /* tilde_expansion() */ 363 | 364 | 365 | /* 366 | * nv_prepend_to_string_list() - add a new string to a string list, delimited 367 | * by the given string delimiter. The original list is freed. 368 | */ 369 | 370 | char *nv_prepend_to_string_list(char *list, const char *item, const char *delim) 371 | { 372 | char *new_list = nvstrcat(item, list ? delim : NULL, list, NULL); 373 | nvfree(list); 374 | return new_list; 375 | } 376 | 377 | 378 | /* 379 | * Read from the given FILE stream until a newline, EOF, or nul 380 | * terminator is encountered, writing data into a growable buffer. 381 | * The eof parameter is set to TRUE when EOF is encountered. In all 382 | * cases, the returned string is null-terminated. 383 | * 384 | * XXX this function will be rather slow because it uses fgetc() to 385 | * pull each character off the stream one at a time; this is done so 386 | * that each character can be examined as it's read so that we can 387 | * appropriately deal with EOFs and newlines. A better implementation 388 | * would use fgets(), but that would still require us to parse each 389 | * read line, checking for newlines or guessing if we hit an EOF. 390 | */ 391 | char *fget_next_line(FILE *fp, int *eof) 392 | { 393 | char *buf = NULL, *tmpbuf; 394 | char *c = NULL; 395 | int len = 0, buflen = 0; 396 | int ret; 397 | 398 | const int __fget_next_line_len = 32; 399 | 400 | if (eof) { 401 | *eof = FALSE; 402 | } 403 | 404 | while (1) { 405 | if (buflen == len) { /* buffer isn't big enough -- grow it */ 406 | buflen += __fget_next_line_len; 407 | tmpbuf = nvalloc(buflen); 408 | if (buf) { 409 | memcpy(tmpbuf, buf, len); 410 | nvfree(buf); 411 | } 412 | buf = tmpbuf; 413 | c = buf + len; 414 | } 415 | 416 | ret = fgetc(fp); 417 | 418 | if ((ret == EOF) && (eof)) { 419 | *eof = TRUE; 420 | } 421 | 422 | if ((ret == EOF) || (ret == '\n') || (ret == '\0')) { 423 | *c = '\0'; 424 | return buf; 425 | } 426 | 427 | *c = (char) ret; 428 | 429 | len++; 430 | c++; 431 | 432 | } /* while (1) */ 433 | 434 | return NULL; /* should never get here */ 435 | } 436 | 437 | char *nvstrchrnul(char *s, int c) 438 | { 439 | char *result = strchr(s, c); 440 | if (!result) { 441 | return (s + strlen(s)); 442 | } 443 | return result; 444 | } 445 | 446 | /****************************************************************************/ 447 | /* file helper functions */ 448 | /****************************************************************************/ 449 | 450 | /* 451 | * nv_open() - open(2) wrapper; prints an error message if open(2) 452 | * fails and calls exit(). This function only returns on success. 453 | */ 454 | 455 | int nv_open(const char *pathname, int flags, mode_t mode) 456 | { 457 | int fd; 458 | fd = open(pathname, flags, mode); 459 | if (fd == -1) { 460 | fprintf(stderr, "Failure opening %s (%s).\n", 461 | pathname, strerror(errno)); 462 | exit(1); 463 | } 464 | return fd; 465 | 466 | } /* nv_name() */ 467 | 468 | 469 | 470 | /* 471 | * nv_get_file_length() - stat(2) wrapper; prints an error message if 472 | * the system call fails and calls exit(). This function only returns 473 | * on success. 474 | */ 475 | 476 | int nv_get_file_length(const char *filename) 477 | { 478 | struct stat stat_buf; 479 | int ret; 480 | 481 | ret = stat(filename, &stat_buf); 482 | if (ret == -1) { 483 | fprintf(stderr, "Unable to determine '%s' file length (%s).\n", 484 | filename, strerror(errno)); 485 | exit(1); 486 | } 487 | return stat_buf.st_size; 488 | 489 | } /* nv_get_file_length() */ 490 | 491 | 492 | 493 | /* 494 | * nv_set_file_length() - wrapper for lseek() and write(); prints an 495 | * error message if the system calls fail and calls exit(). This 496 | * function only returns on success. 497 | */ 498 | 499 | void nv_set_file_length(const char *filename, int fd, int len) 500 | { 501 | if ((lseek(fd, len - 1, SEEK_SET) == -1) || 502 | (write(fd, "", 1) == -1)) { 503 | fprintf(stderr, "Unable to set file '%s' length %d (%s).\n", 504 | filename, fd, strerror(errno)); 505 | exit(1); 506 | } 507 | } /* nv_set_file_length() */ 508 | 509 | 510 | 511 | /* 512 | * nv_mmap() - mmap(2) wrapper; prints an error message if mmap(2) 513 | * fails and calls exit(). This function only returns on success. 514 | */ 515 | 516 | void *nv_mmap(const char *filename, size_t len, int prot, int flags, int fd) 517 | { 518 | void *ret; 519 | 520 | ret = mmap(0, len, prot, flags, fd, 0); 521 | if (ret == (void *) -1) { 522 | fprintf(stderr, "Unable to mmap file %s (%s).\n", 523 | filename, strerror(errno)); 524 | exit(1); 525 | } 526 | return ret; 527 | 528 | } /* nv_mmap() */ 529 | 530 | 531 | /* 532 | * nv_basename() - alternative to basename(3) which avoids differences in 533 | * behavior from different implementations: this implementation never modifies 534 | * the original string, and the return value can always be passed to free(3). 535 | */ 536 | 537 | char *nv_basename(const char *path) 538 | { 539 | char *last_slash = strrchr(path, '/'); 540 | if (last_slash) { 541 | return strdup(last_slash+1); 542 | } else { 543 | return strdup(path); 544 | } 545 | } 546 | 547 | 548 | /* 549 | * nv_mkdir_recursive() - make a directory and all parent directories as needed. 550 | * dir_list is an optional arguments that if not empty, will be set to a string 551 | * containing a newline separated list of all directories created. 552 | */ 553 | int nv_mkdir_recursive(const char *path, const mode_t mode, 554 | char **error_str, char **dir_list) 555 | { 556 | char *c, *tmp, ch, *list; 557 | int success = FALSE; 558 | 559 | if (!path || !path[0]) { 560 | return FALSE; 561 | } 562 | 563 | tmp = nvstrdup(path); 564 | remove_trailing_slashes(tmp); 565 | 566 | list = NULL; 567 | 568 | c = tmp; 569 | do { 570 | c++; 571 | if ((*c == '/') || (*c == '\0')) { 572 | ch = *c; 573 | *c = '\0'; 574 | if (!directory_exists(tmp)) { 575 | char *tmplist; 576 | if (mkdir(tmp, mode) != 0) { 577 | *error_str = 578 | nvasprintf("Failure creating directory '%s' : (%s)", 579 | tmp, strerror(errno)); 580 | goto done; 581 | } 582 | /* Prepend the created directory path to a running list */ 583 | if (dir_list) { 584 | tmplist = list; 585 | list = nvstrcat(tmp, "\n", tmplist, NULL); 586 | free(tmplist); 587 | } 588 | } 589 | *c = ch; 590 | } 591 | } while (*c); 592 | 593 | /* Log any created directories */ 594 | if (dir_list && list) { 595 | *dir_list = list; 596 | } 597 | 598 | success = TRUE; 599 | 600 | done: 601 | 602 | if (!dir_list) { 603 | free(list); 604 | } 605 | free(tmp); 606 | return success; 607 | } 608 | 609 | 610 | 611 | /* 612 | * nvdircat() - concatenate path elements, inserting a '/' path separator 613 | * character between each element. 614 | */ 615 | 616 | char *nvdircat(const char *str, ...) 617 | { 618 | const char *s; 619 | char *result = nvstrdup(""); 620 | va_list ap; 621 | 622 | va_start(ap, str); 623 | 624 | for (s = str; s; s = va_arg(ap, char *)) { 625 | char *oldresult = result; 626 | 627 | result = nvstrcat(result, s == str ? "" : "/", s, NULL); 628 | nvfree(oldresult); 629 | } 630 | 631 | va_end(ap); 632 | 633 | collapse_multiple_slashes(result); 634 | 635 | return result; 636 | } 637 | 638 | 639 | /* 640 | * dirname(3) workalike that abstracts away implementation-specific behavior: 641 | * this function always returns a heap-allocated string that can be passed to 642 | * free(3), and never modifies the contents of the original string. 643 | */ 644 | char *nv_dirname(const char *path) 645 | { 646 | char *last_slash = strrchr(path, '/'); 647 | if (last_slash) { 648 | return nvstrndup(path, last_slash - path); 649 | } else { 650 | return nvstrdup("."); 651 | } 652 | } 653 | 654 | 655 | /* 656 | * Simple helper function to write the contents of a NUL-terminated string to 657 | * a file. A trailing newline is appended if not already present. 658 | * Returns TRUE on success; FALSE if an error occurred. 659 | */ 660 | int nv_string_to_file(const char *destination, const char *data) 661 | { 662 | char *dname = nv_dirname(destination); 663 | int written, newline_success = TRUE; 664 | char *error = NULL; 665 | int len, ret; 666 | FILE *fp; 667 | 668 | ret = nv_mkdir_recursive(dname, 0755, &error, NULL); 669 | nvfree(dname); 670 | nvfree(error); 671 | 672 | if (!ret) return FALSE; 673 | 674 | fp = fopen(destination, "w"); 675 | if (!fp) return FALSE; 676 | 677 | len = strlen(data); 678 | written = fwrite(data, 1, len, fp); 679 | if (data[len-1] != '\n') { 680 | if (fwrite("\n", 1, 1, fp) != 1) { 681 | newline_success = FALSE; 682 | } 683 | } 684 | 685 | if (fclose(fp)) return FALSE; 686 | if (chmod(destination, 0644)) return FALSE; 687 | 688 | return written == len && newline_success; 689 | } 690 | 691 | 692 | 693 | /****************************************************************************/ 694 | /* string helper functions */ 695 | /****************************************************************************/ 696 | 697 | /* 698 | * nv_trim_space() - remove any leading and trailing whitespace from a string 699 | * and return a pointer to the modified string. The original string may be 700 | * modified; the returned value should *NOT* be deallocated with free(), since 701 | * it may point somewhere other than the beginning of the original string. If 702 | * the original string was a malloc()ed buffer, that string should be stored 703 | * separately from the returned value of nv_strip_space, and freed. 704 | */ 705 | 706 | char *nv_trim_space(char *string) { 707 | char *ret, *end; 708 | 709 | for (ret = string; *ret && isspace(*ret); ret++); 710 | for (end = ret + strlen(ret) - 1; end >= ret && isspace(*end); end--) { 711 | *end = '\0'; 712 | } 713 | 714 | return ret; 715 | } 716 | 717 | /* 718 | * trim_char() - helper function to remove a character from the initial and 719 | * final positions of a string, and optionally report how many replacements 720 | * were made. The returned value should not be free()d (see nv_trim_space()). 721 | */ 722 | 723 | static char *trim_char(char *string, char trim, int *count) { 724 | int len, replaced = 0; 725 | 726 | if (count) { 727 | *count = 0; 728 | } 729 | 730 | if (string == NULL || trim == '\0') { 731 | return string; 732 | } 733 | 734 | if (string[0] == trim) { 735 | string++; 736 | replaced++; 737 | } 738 | 739 | len = strlen(string); 740 | 741 | if (string[len - 1] == trim) { 742 | string[len - 1] = '\0'; 743 | replaced++; 744 | } 745 | 746 | if (count) { 747 | *count = replaced; 748 | } 749 | 750 | return string; 751 | } 752 | 753 | /* 754 | * nv_trim_char() - remove a character from the initial and final positions of 755 | * a string. The returned value should not be free()d (see nv_trim_space()). 756 | */ 757 | 758 | char *nv_trim_char(char *string, char trim) { 759 | return trim_char(string, trim, NULL); 760 | } 761 | 762 | /* 763 | * nv_trim_char_strict() - remove a character from the initial and final 764 | * positions of a string. If no replacements were made, or if replacements were 765 | * made at both positions, return the modified string. Otherwise, return NULL. 766 | * The returned value should not be free()d (see nv_trim_space()). 767 | */ 768 | 769 | char *nv_trim_char_strict(char *string, char trim) { 770 | int count; 771 | char *trimmed; 772 | 773 | trimmed = trim_char(string, trim, &count); 774 | 775 | if (count == 0 || count == 2) { 776 | return trimmed; 777 | } 778 | 779 | return NULL; 780 | } 781 | 782 | /* 783 | * directory_exists() - test whether the given directory exists 784 | */ 785 | 786 | int directory_exists(const char *dir) 787 | { 788 | struct stat stat_buf; 789 | 790 | if ((stat (dir, &stat_buf) == -1) || (!S_ISDIR(stat_buf.st_mode))) { 791 | return FALSE; 792 | } else { 793 | return TRUE; 794 | } 795 | } 796 | 797 | /* 798 | * remove_trailing_slashes() - begin at the end of the given string, 799 | * and overwrite slashes with NULL as long as we find slashes. 800 | */ 801 | 802 | void remove_trailing_slashes(char *string) 803 | { 804 | int len; 805 | 806 | if (string == NULL) { 807 | return; 808 | } 809 | 810 | len = strlen(string); 811 | 812 | while (string[len-1] == '/') { 813 | string[--len] = '\0'; 814 | } 815 | 816 | } 817 | 818 | 819 | 820 | /* 821 | * collapse_multiple_slashes() - remove any/all occurrences of "//" from the 822 | * argument string. 823 | */ 824 | 825 | void collapse_multiple_slashes(char *s) 826 | { 827 | char *p; 828 | 829 | while ((p = strstr(s, "//")) != NULL) { 830 | p++; /* advance to second '/' */ 831 | while (*p == '/') { 832 | unsigned int i, len; 833 | 834 | len = strlen(p); 835 | for (i = 0; i < len; i++) p[i] = p[i+1]; 836 | } 837 | } 838 | } 839 | --------------------------------------------------------------------------------