diff --git a/internal/nvsandboxutils/gen/generate-bindings.sh b/internal/nvsandboxutils/gen/generate-bindings.sh new file mode 100755 index 00000000..e32641a3 --- /dev/null +++ b/internal/nvsandboxutils/gen/generate-bindings.sh @@ -0,0 +1,50 @@ +#!/bin/bash +# Copyright 2024 NVIDIA CORPORATION +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# This file generates bindings for nvsandboxutils by calling c-for-go. + +set -x -e + +PWD=$(pwd) +GEN_DIR="$PWD/gen" +PKG_DIR="$PWD" +GEN_BINDINGS_DIR="$GEN_DIR/nvsandboxutils" +PKG_BINDINGS_DIR="$PKG_DIR" + +SOURCES=$(find "$GEN_BINDINGS_DIR" -type f) + +mkdir -p "$PKG_BINDINGS_DIR" + +cp "$GEN_BINDINGS_DIR/nvsandboxutils.h" "$PKG_BINDINGS_DIR/nvsandboxutils.h" +spatch --in-place --very-quiet --sp-file "$GEN_BINDINGS_DIR/anonymous_structs.cocci" "$PKG_BINDINGS_DIR/nvsandboxutils.h" > /dev/null + +echo "Generating the bindings..." +c-for-go -out "$PKG_DIR/.." "$GEN_BINDINGS_DIR/nvsandboxutils.yml" +cd "$PKG_BINDINGS_DIR" +go tool cgo -godefs types.go > types_gen.go +go fmt types_gen.go +cd - > /dev/null +rm -rf "$PKG_BINDINGS_DIR/cgo_helpers.go" "$PKG_BINDINGS_DIR/types.go" "$PKG_BINDINGS_DIR/_obj" +go run "$GEN_BINDINGS_DIR/generateapi.go" --sourceDir "$PKG_BINDINGS_DIR" --output "$PKG_BINDINGS_DIR/zz_generated.api.go" +# go fmt "$PKG_BINDINGS_DIR" + +SED_SEARCH_STRING='// WARNING: This file has automatically been generated on' +SED_REPLACE_STRING='// WARNING: THIS FILE WAS AUTOMATICALLY GENERATED.' +grep -l -R "$SED_SEARCH_STRING" "$PKG_DIR" | grep -v "/gen/" | xargs sed -i -E "s#$SED_SEARCH_STRING.*\$#$SED_REPLACE_STRING#g" + +SED_SEARCH_STRING='// (.*) nvsandboxutils/nvsandboxutils.h:[0-9]+' +SED_REPLACE_STRING='// \1 nvsandboxutils/nvsandboxutils.h' +grep -l -RE "$SED_SEARCH_STRING" "$PKG_DIR" | grep -v "/gen/" | xargs sed -i -E "s#$SED_SEARCH_STRING\$#$SED_REPLACE_STRING#g" + diff --git a/internal/nvsandboxutils/gen/nvsandboxutils/anonymous_structs.cocci b/internal/nvsandboxutils/gen/nvsandboxutils/anonymous_structs.cocci new file mode 100644 index 00000000..c8028fb5 --- /dev/null +++ b/internal/nvsandboxutils/gen/nvsandboxutils/anonymous_structs.cocci @@ -0,0 +1,100 @@ +@patch@ +type WRAPPER_TYPE; +field list FIELDS; +identifier V; +expression E; +fresh identifier ST = "nvSandboxUtilsGenerated_struct___"; +fresh identifier TEMP_VAR = "nvSandboxUtilsGenerated_variable___" ## V; +@@ + +++ struct ST { +++ WRAPPER_TYPE TEMP_VAR; +++ FIELDS +++ }; ++ + +WRAPPER_TYPE +{ + ... +( +- struct { +- FIELDS +- } V[E]; ++ struct ST V[E]; + +| + +- struct { +- FIELDS +- } V; ++ struct ST V; +) + ... +}; + +@capture@ +type WRAPPER_TYPE; +identifier TEMP_VAR; +identifier ST =~ "^nvSandboxUtilsGenerated_struct___"; +@@ + +struct ST { + WRAPPER_TYPE TEMP_VAR; + ... +}; + +@script:python concat@ +WRAPPER_TYPE << capture.WRAPPER_TYPE; +TEMP_VAR << capture.TEMP_VAR; +ST << capture.ST; +T; +@@ + +def removePrefix(string, prefix): + if string.startswith(prefix): + return string[len(prefix):] + return string + +def removeSuffix(string, suffix): + if string.endswith(suffix): + return string[:-len(suffix)] + return string + +WRAPPER_TYPE = removeSuffix(WRAPPER_TYPE, "_t") +TEMP_VAR = removePrefix(TEMP_VAR, "nvSandboxUtilsGenerated_variable___") +coccinelle.T = cocci.make_type(WRAPPER_TYPE + TEMP_VAR[0].upper() + TEMP_VAR[1:] + "_t") + +@add_typedef@ +identifier capture.ST; +type concat.T; +type WRAPPER_TYPE; +identifier TEMP_VAR; +@@ + +- struct ST { ++ typedef struct { +- WRAPPER_TYPE TEMP_VAR; + ... +- }; ++ } T; + +@update@ +identifier capture.ST; +type concat.T; +identifier V; +expression E; +type WRAPPER_TYPE; +@@ + +WRAPPER_TYPE +{ + ... +( +- struct ST V[E]; ++ T V[E]; +| +- struct ST V; ++ T V; +) + ... +}; diff --git a/internal/nvsandboxutils/gen/nvsandboxutils/generateapi.go b/internal/nvsandboxutils/gen/nvsandboxutils/generateapi.go new file mode 100644 index 00000000..104b824b --- /dev/null +++ b/internal/nvsandboxutils/gen/nvsandboxutils/generateapi.go @@ -0,0 +1,389 @@ +/** +# Copyright 2024 NVIDIA CORPORATION +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +**/ + +package main + +import ( + "flag" + "fmt" + "go/ast" + "go/parser" + "go/token" + "io" + "io/fs" + "os" + "path/filepath" + "slices" + "sort" + "strings" + "unicode" +) + +type GeneratableInterfacePoperties struct { + Type string + Interface string + Exclude []string + PackageMethodsAliasedFrom string +} + +var GeneratableInterfaces = []GeneratableInterfacePoperties{ + { + Type: "library", + Interface: "Interface", + PackageMethodsAliasedFrom: "libnvsandboxutils", + }, +} + +func main() { + sourceDir := flag.String("sourceDir", "", "Path to the source directory for all go files") + output := flag.String("output", "", "Path to the output file (default: stdout)") + flag.Parse() + + // Check if required flags are provided + if *sourceDir == "" { + flag.Usage() + return + } + + writer, closer, err := getWriter(*output) + if err != nil { + fmt.Printf("Error: %v", err) + return + } + defer func() { + _ = closer() + }() + + header, err := generateHeader() + if err != nil { + fmt.Printf("Error: %v", err) + return + } + fmt.Fprint(writer, header) + + for i, p := range GeneratableInterfaces { + if p.PackageMethodsAliasedFrom != "" { + comment, err := generatePackageMethodsComment(p) + if err != nil { + fmt.Printf("Error: %v", err) + return + } + fmt.Fprint(writer, comment) + + output, err := generatePackageMethods(*sourceDir, p) + if err != nil { + fmt.Printf("Error: %v", err) + return + } + fmt.Fprintf(writer, "%s\n", output) + } + + comment, err := generateInterfaceComment(p) + if err != nil { + fmt.Printf("Error: %v", err) + return + } + fmt.Fprint(writer, comment) + + output, err := generateInterface(*sourceDir, p) + if err != nil { + fmt.Printf("Error: %v", err) + return + } + fmt.Fprint(writer, output) + + if i < (len(GeneratableInterfaces) - 1) { + fmt.Fprint(writer, "\n") + } + } +} + +func getWriter(outputFile string) (io.Writer, func() error, error) { + if outputFile == "" { + return os.Stdout, func() error { return nil }, nil + } + + file, err := os.Create(outputFile) + if err != nil { + return nil, nil, err + } + + return file, file.Close, nil +} + +func generateHeader() (string, error) { + lines := []string{ + "/**", + "# Copyright 2024 NVIDIA CORPORATION", + "#", + "# Licensed under the Apache License, Version 2.0 (the \"License\");", + "# you may not use this file except in compliance with the License.", + "# You may obtain a copy of the License at", + "#", + "# http://www.apache.org/licenses/LICENSE-2.0", + "#", + "# Unless required by applicable law or agreed to in writing, software", + "# distributed under the License is distributed on an \"AS IS\" BASIS,", + "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", + "# See the License for the specific language governing permissions and", + "# limitations under the License.", + "**/", + "", + "// Generated Code; DO NOT EDIT.", + "", + "package nvsandboxutils", + "", + "", + } + return strings.Join(lines, "\n"), nil +} + +func generatePackageMethodsComment(input GeneratableInterfacePoperties) (string, error) { + commentFmt := []string{ + "// The variables below represent package level methods from the %s type.", + } + + var signature strings.Builder + comment := strings.Join(commentFmt, "\n") + comment = fmt.Sprintf(comment, input.Type) + signature.WriteString(fmt.Sprintf("%s\n", comment)) + return signature.String(), nil +} + +func generateInterfaceComment(input GeneratableInterfacePoperties) (string, error) { + commentFmt := []string{ + "// %s represents the interface for the %s type.", + "//", + "//go:generate moq -out mock/%s.go -pkg mock . %s:%s", + } + + var signature strings.Builder + comment := strings.Join(commentFmt, "\n") + comment = fmt.Sprintf(comment, input.Interface, input.Type, strings.ToLower(input.Interface), input.Interface, input.Interface) + signature.WriteString(fmt.Sprintf("%s\n", comment)) + return signature.String(), nil +} + +func generatePackageMethods(sourceDir string, input GeneratableInterfacePoperties) (string, error) { + var signature strings.Builder + + signature.WriteString("var (\n") + + methods, err := extractMethodsFromPackage(sourceDir, input) + if err != nil { + return "", err + } + + for _, method := range methods { + name := method.Name.Name + formatted := fmt.Sprintf("\t%s = %s.%s\n", name, input.PackageMethodsAliasedFrom, name) + signature.WriteString(formatted) + } + + signature.WriteString(")\n") + + return signature.String(), nil +} + +func generateInterface(sourceDir string, input GeneratableInterfacePoperties) (string, error) { + var signature strings.Builder + + signature.WriteString(fmt.Sprintf("type %s interface {\n", input.Interface)) + + methods, err := extractMethodsFromPackage(sourceDir, input) + if err != nil { + return "", err + } + + for _, method := range methods { + formatted := fmt.Sprintf("\t%s\n", formatMethodSignature(method)) + signature.WriteString(formatted) + } + + signature.WriteString("}\n") + + return signature.String(), nil +} + +func getGoFiles(sourceDir string) (map[string][]byte, error) { + gofiles := make(map[string][]byte) + + err := filepath.WalkDir(sourceDir, func(path string, d fs.DirEntry, err error) error { + if err != nil { + return err + } + if d.IsDir() || filepath.Ext(path) != ".go" { + return nil + } + + content, err := os.ReadFile(path) + if err != nil { + return err + } + + gofiles[path] = content + + return nil + }) + if err != nil { + return nil, fmt.Errorf("walking %s: %w", sourceDir, err) + } + + return gofiles, nil +} + +func extractMethodsFromPackage(sourceDir string, input GeneratableInterfacePoperties) ([]*ast.FuncDecl, error) { + gofiles, err := getGoFiles(sourceDir) + if err != nil { + return nil, err + } + + var methods []*ast.FuncDecl + for file, content := range gofiles { + m, err := extractMethods(file, content, input) + if err != nil { + return nil, err + } + methods = append(methods, m...) + } + + sort.Slice(methods, func(i, j int) bool { + return methods[i].Name.Name < methods[j].Name.Name + }) + + return methods, nil +} + +func extractMethods(sourceFile string, sourceContent []byte, input GeneratableInterfacePoperties) ([]*ast.FuncDecl, error) { + // Parse source file + fset := token.NewFileSet() + node, err := parser.ParseFile(fset, sourceFile, sourceContent, parser.ParseComments) + if err != nil { + return nil, err + } + + // Traverse AST to find type declarations and associated methods + var methods []*ast.FuncDecl + for _, decl := range node.Decls { + funcDecl, ok := decl.(*ast.FuncDecl) + if !ok { + continue + } + + // Check if the function is a method associated with the specified type + if receiverType := funcDecl.Recv; receiverType != nil { + var ident *ast.Ident + + for _, field := range receiverType.List { + switch fieldType := field.Type.(type) { + case *ast.Ident: + ident = fieldType + case *ast.StarExpr: + // Update ident if it's a *ast.StarExpr + if newIdent, ok := fieldType.X.(*ast.Ident); ok { + // If the inner type is an *ast.Ident, update ident + ident = newIdent + } + } + + // No identifier found + if ident == nil { + continue + } + + // Identifier is not the one we are looking for + if ident.Name != input.Type { + continue + } + + // Ignore non-public methods + if !isPublic(funcDecl.Name.Name) { + continue + } + + // Ignore method in the exclude list + if slices.Contains(input.Exclude, funcDecl.Name.Name) { + continue + } + + methods = append(methods, funcDecl) + } + } + } + + return methods, nil +} + +func formatMethodSignature(decl *ast.FuncDecl) string { + var signature strings.Builder + + // Write method name + signature.WriteString(decl.Name.Name) + signature.WriteString("(") + + // Write parameters + if decl.Type.Params != nil { + for i, param := range decl.Type.Params.List { + if i > 0 { + signature.WriteString(", ") + } + signature.WriteString(formatFieldList(param)) + } + } + + signature.WriteString(")") + + // Write return types + if decl.Type.Results != nil { + signature.WriteString(" ") + if len(decl.Type.Results.List) > 1 { + signature.WriteString("(") + } + for i, result := range decl.Type.Results.List { + if i > 0 { + signature.WriteString(", ") + } + signature.WriteString(formatFieldList(result)) + } + if len(decl.Type.Results.List) > 1 { + signature.WriteString(")") + } + } + + return signature.String() +} + +func formatFieldList(field *ast.Field) string { + var builder strings.Builder + switch fieldType := field.Type.(type) { + case *ast.Ident: + builder.WriteString(fieldType.Name) + case *ast.ArrayType: + builder.WriteString("[]") + builder.WriteString(formatFieldList(&ast.Field{Type: fieldType.Elt})) + case *ast.StarExpr: + builder.WriteString("*") + builder.WriteString(formatFieldList(&ast.Field{Type: fieldType.X})) + } + return builder.String() +} + +func isPublic(name string) bool { + if len(name) == 0 { + return false + } + return unicode.IsUpper([]rune(name)[0]) +} diff --git a/internal/nvsandboxutils/gen/nvsandboxutils/nvsandboxutils.h b/internal/nvsandboxutils/gen/nvsandboxutils/nvsandboxutils.h new file mode 100644 index 00000000..eb087156 --- /dev/null +++ b/internal/nvsandboxutils/gen/nvsandboxutils/nvsandboxutils.h @@ -0,0 +1,298 @@ +/* + * SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __NVSANDBOXUTILS_H__ +#define __NVSANDBOXUTILS_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#define INPUT_LENGTH 256 +#define MAX_FILE_PATH 256 +#define MAX_NAME_LENGTH 256 + +/***************************************************************************************************/ +/** @defgroup enums Enumerations + * @{ + */ +/***************************************************************************************************/ + +/** + * Return types + */ +typedef enum +{ + NVSANDBOXUTILS_SUCCESS = 0, //!< The operation was successful + NVSANDBOXUTILS_ERROR_UNINITIALIZED = 1, //!< The library wasn't successfully initialized + NVSANDBOXUTILS_ERROR_NOT_SUPPORTED = 2, //!< The requested operation is not supported on target device + NVSANDBOXUTILS_ERROR_INVALID_ARG = 3, //!< A supplied argument is invalid + NVSANDBOXUTILS_ERROR_INSUFFICIENT_SIZE = 4, //!< A supplied argument is not large enough + NVSANDBOXUTILS_ERROR_VERSION_NOT_SUPPORTED = 5, //!< Requested library version is not supported + NVSANDBOXUTILS_ERROR_LIBRARY_LOAD = 6, //!< The library load failed + NVSANDBOXUTILS_ERROR_FUNCTION_NOT_FOUND = 7, //!< Called function was not found + NVSANDBOXUTILS_ERROR_DEVICE_NOT_FOUND = 8, //!< Target device was not found + NVSANDBOXUTILS_ERROR_NVML_LIB_CALL = 9, //!< NVML library call failed + NVSANDBOXUTILS_ERROR_OUT_OF_MEMORY = 10, //!< There is insufficient memory + NVSANDBOXUTILS_ERROR_FILEPATH_NOT_FOUND = 11, //!< A supplied file path was not found + NVSANDBOXUTILS_ERROR_UNKNOWN = 0xFFFF, //!< Unknown error occurred +} nvSandboxUtilsRet_t; + +/** + * Return if there is an error + */ +#define RETURN_ON_SANDBOX_ERROR(result) \ + if ((result) != NVSANDBOXUTILS_SUCCESS) { \ + NVSANDBOXUTILS_ERROR_MSG("%s %d result=%d", __func__, __LINE__, result); \ + return result; \ + } + +/** + * Log levels + */ +typedef enum +{ + NVSANDBOXUTILS_LOG_LEVEL_FATAL = 0, //!< Log fatal errors + NVSANDBOXUTILS_LOG_LEVEL_ERROR = 1, //!< Log all errors + NVSANDBOXUTILS_LOG_LEVEL_WARN = 2, //!< Log all warnings + NVSANDBOXUTILS_LOG_LEVEL_DEBUG = 3, //!< Log all debug messages + NVSANDBOXUTILS_LOG_LEVEL_INFO = 4, //!< Log all info messages + NVSANDBOXUTILS_LOG_LEVEL_NONE = 0xFFFF, //!< Log none +} nvSandboxUtilsLogLevel_t; + +/** + * Input rootfs to help access files inside the driver container + */ +typedef enum +{ + NV_ROOTFS_DEFAULT, //!< Default no rootfs + NV_ROOTFS_PATH, //!< /run/nvidia/driver + NV_ROOTFS_PID, //!< /proc/PID/mountinfo +} nvSandboxUtilsRootfsInputType_t; + +/** + * File type + */ +typedef enum +{ + NV_DEV, //!< /dev file system + NV_PROC, //!< /proc file system + NV_SYS, //!< /sys file system +} nvSandboxUtilsFileType_t; + +/** + * File subtype + */ +typedef enum +{ + NV_DEV_NVIDIA, //!< /dev/nvidia0 + NV_DEV_DRI_CARD, //!< /dev/dri/card1 + NV_DEV_DRI_RENDERD, //!< /dev/dri/renderD128 + NV_DEV_DRI_CARD_SYMLINK, //!< /dev/dri/by-path/pci-0000:41:00.0-card + NV_DEV_DRI_RENDERD_SYMLINK, //!< /dev/dri/by-path/pci-0000:41:00.0-render + NV_DEV_NVIDIA_UVM, //!< /dev/nvidia-uvm + NV_DEV_NVIDIA_UVM_TOOLS, //!< /dev/nvidia-uvm-tools + NV_DEV_NVIDIA_MODESET, //!< /dev/nvidia-uvm-modeset + NV_DEV_NVIDIA_CTL, //!< /dev/nvidiactl + NV_DEV_GDRDRV, //!< /dev/gdrdrv + NV_DEV_NVIDIA_CAPS_NVIDIA_CAP, //!< /dev/nvidia-caps/nvidia-cap22 + NV_PROC_DRIVER_NVIDIA_GPUS_PCIBUSID, //!< /proc/driver/nvidia/gpus/0000:2d:00.0 + NV_PROC_DRIVER_NVIDIA_GPUS, //!< /proc/driver/nvidia/gpus (for mask out) + NV_PROC_NVIDIA_PARAMS, //!< /proc/driver/nvidia/params + NV_PROC_NVIDIA_CAPS_MIG_MINORS, //!< /proc/driver/nvidia-caps/mig-minors + NV_PROC_DRIVER_NVIDIA_CAPABILITIES_GPU, //!< /proc/driver/nvidia/capabilities/gpu0 + NV_PROC_DRIVER_NVIDIA_CAPABILITIES, //!< /proc/driver/nvidia/capabilities (for mask out) + NV_PROC_DRIVER_NVIDIA_CAPABILITIIES_GPU_MIG_CI_ACCESS, //!< proc/driver/nvidia/capabilities/gpu0/mig/gi2/ci0/access + NV_SYS_MODULE_NVIDIA_DRIVER_PCIBUSID, //!< /sys/module/nvidia/drivers/pci:nvidia/0000:2d:00.0 + NV_SYS_MODULE_NVIDIA_DRIVER, //!< /sys/module/nvidia/drivers/pci:nvidia (for mask out) + NV_NUM_SUBTYPE, // always at the end. +} nvSandboxUtilsFileSystemSubType_t; + +/** + * File module + */ +typedef enum +{ + NV_GPU, //!< Target device + NV_MIG, //!< Target device- MIG + NV_DRIVER_NVIDIA, //!< NVIDIA kernel driver + NV_DRIVER_NVIDIA_UVM, //!< NVIDIA kernel driver-UVM + NV_DRIVER_NVIDIA_MODESET, //!< NVIDIA kernel driver-modeset + NV_DRIVER_GDRDRV, //!< GDRDRV driver + NV_SYSTEM, //!< System module +} nvSandboxUtilsFileModule_t; + +/** + * Flag to provide additional details about the file + */ +typedef enum +{ + NV_FILE_FLAG_HINT = (1 << 0), //!< Default no hint + NV_FILE_FLAG_MASKOUT = (1 << 1), //!< For /proc/driver/nvidia/gpus + NV_FILE_FLAG_CONTENT = (1 << 2), //!< For /proc/driver/nvidia/params + //!< For SYMLINK + //!< Use \p nvSandboxUtilsGetFileContent to get name of the linked file + NV_FILE_FLAG_DEPRECTATED = (1 << 3), //!< For all the FIRMWARE GSP file + NV_FILE_FLAG_CANDIDATES = (1 << 4), //!< For libcuda.so +} nvSandboxUtilsFileFlag_t; + +/** + * Input type of the target device + */ +typedef enum +{ + NV_GPU_INPUT_GPU_UUID, //!< GPU UUID + NV_GPU_INPUT_MIG_UUID, //!< MIG UUID + NV_GPU_INPUT_PCI_ID, //!< PCIe DBDF ID + NV_GPU_INPUT_PCI_INDEX, //!< PCIe bus order (0 points to the GPU that has lowest PCIe BDF) +} nvSandboxUtilsGpuInputType_t; + +/** @} */ + +/***************************************************************************************************/ +/** @defgroup dataTypes Structures and Unions + * @{ + */ +/***************************************************************************************************/ + +/** + * Initalization input v1 + */ +typedef struct +{ + unsigned int version; //!< Version for the structure + nvSandboxUtilsRootfsInputType_t type; //!< One of \p nvSandboxUtilsRootfsInputType_t + char value[INPUT_LENGTH]; //!< String representation of input +} nvSandboxUtilsInitInput_v1_t; + +typedef nvSandboxUtilsInitInput_v1_t nvSandboxUtilsInitInput_t; + +/** + * File system information + */ +typedef struct nvSandboxUtilsGpuFileInfo_v1_t +{ + struct nvSandboxUtilsGpuFileInfo_v1_t *next; //!< Pointer to the next node in the linked list + nvSandboxUtilsFileType_t fileType; //!< One of \p nvSandboxUtilsFileType_t + nvSandboxUtilsFileSystemSubType_t fileSubType; //!< One of \p nvSandboxUtilsFileSystemSubType_t + nvSandboxUtilsFileModule_t module; //!< One of \p nvSandboxUtilsFileModule_t + nvSandboxUtilsFileFlag_t flags; //!< One of \p nvSandboxUtilsFileFlag_t + char *filePath; //!< Relative file path to rootfs +}nvSandboxUtilsGpuFileInfo_v1_t; + +/** + * GPU resource request v1 + */ +typedef struct +{ + unsigned int version; //!< Version for the structure + nvSandboxUtilsGpuInputType_t inputType; //!< One of \p nvSandboxUtilsGpuInputType_t + char input[INPUT_LENGTH]; //!< String representation of input + nvSandboxUtilsGpuFileInfo_v1_t *files; //!< Linked list of \ref nvSandboxUtilsGpuFileInfo_v1_t +} nvSandboxUtilsGpuRes_v1_t; + +typedef nvSandboxUtilsGpuRes_v1_t nvSandboxUtilsGpuRes_t; + +/** @} */ + +/***************************************************************************************************/ +/** @defgroup funcs Functions + * @{ + */ +/***************************************************************************************************/ + +/* ************************************************* + * Initialize library + * ************************************************* + */ +/** + * Prepare library resources before library API can be used. + * This initialization will not fail if one of the initialization prerequisites fails. + * @param input Reference to the called-supplied input struct that has initialization fields + * + * @returns @ref NVSANDBOXUTILS_SUCCESS on success + * @returns @ref NVSANDBOXUTILS_ERROR_INVALID_ARG if \p input->value isn't a valid rootfs path + * @returns @ref NVSANDBOXUTILS_ERROR_VERSION_NOT_SUPPORTED if \p input->version isn't supported by the library + * @returns @ref NVSANDBOXUTILS_ERROR_FILEPATH_NOT_FOUND if any of the required file paths are not found during initialization + * @returns @ref NVSANDBOXUTILS_ERROR_OUT_OF_MEMORY if there is insufficient system memory during initialization + * @returns @ref NVSANDBOXUTILS_ERROR_LIBRARY_LOAD on any error during loading the library + */ +nvSandboxUtilsRet_t nvSandboxUtilsInit(nvSandboxUtilsInitInput_t *input); + +/* ************************************************* + * Shutdown library + * ************************************************* + */ +/** + * Clean up library resources created by init call + * + * @returns @ref NVSANDBOXUTILS_SUCCESS on success + */ +nvSandboxUtilsRet_t nvSandboxUtilsShutdown(void); + +/* ************************************************* + * Get NVIDIA RM driver version + * ************************************************* + */ +/** + * Get NVIDIA RM driver version + * @param version Reference to caller-supplied buffer to return driver version string + * @param length The maximum allowed length of the string returned in \p version + * + * @returns @ref NVSANDBOXUTILS_SUCCESS on success + * @returns @ref NVSANDBOXUTILS_ERROR_INVALID_ARG if \p version is NULL + * @returns @ref NVSANDBOXUTILS_ERROR_NVML_LIB_CALL on any error during driver version query from NVML + */ +nvSandboxUtilsRet_t nvSandboxUtilsGetDriverVersion(char *version, unsigned int length); + +/* ************************************************* + * Get /dev, /proc, /sys file system information + * ************************************************* + */ +/** + * Get /dev, /proc, /sys file system information + * @param request Reference to caller-supplied request struct to return the file system information + * + * @returns @ref NVSANDBOXUTILS_SUCCESS on success + * @returns @ref NVSANDBOXUTILS_ERROR_INVALID_ARG if \p request->input doesn't match any device + * @returns @ref NVSANDBOXUTILS_ERROR_VERSION_NOT_SUPPORTED if \p request->version isn't supported by the library + */ +nvSandboxUtilsRet_t nvSandboxUtilsGetGpuResource(nvSandboxUtilsGpuRes_t *request); + +/* ************************************************* + * Get content of given file path + * ************************************************* + */ +/** + * Get file content of input file path + * @param filePath Reference to the file path + * @param content Reference to the caller-supplied buffer to return the file content + * @param contentSize Reference to the maximum allowed size of content. It is updated to the actual size of the content on return + * + * @returns @ref NVSANDBOXUTILS_SUCCESS on success + * @returns @ref NVSANDBOXUTILS_ERROR_INVALID_ARG if \p filePath or \p content is NULL + * @returns @ref NVSANDBOXUTILS_ERROR_INSUFFICIENT_SIZE if \p contentSize is too small + * @returns @ref NVSANDBOXUTILS_ERROR_FILEPATH_NOT_FOUND on an error while obtaining the content for the file path + */ +nvSandboxUtilsRet_t nvSandboxUtilsGetFileContent(char *filePath, char *content, unsigned int *contentSize); + +/** @} */ + +#ifdef __cplusplus +} +#endif +#endif // __NVSANDBOXUTILS_H__ diff --git a/internal/nvsandboxutils/gen/nvsandboxutils/nvsandboxutils.yml b/internal/nvsandboxutils/gen/nvsandboxutils/nvsandboxutils.yml new file mode 100644 index 00000000..851db743 --- /dev/null +++ b/internal/nvsandboxutils/gen/nvsandboxutils/nvsandboxutils.yml @@ -0,0 +1,66 @@ +# Copyright (c) 2024, NVIDIA CORPORATION +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +--- +GENERATOR: + PackageName: nvsandboxutils + PackageDescription: "Package NVSANDBOXUTILS bindings" + PackageLicense: |- + Copyright (c) 2024, NVIDIA CORPORATION + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + Includes: ["nvsandboxutils.h"] + FlagGroups: + - {name: "LDFLAGS", traits: ["linux"], flags: ["-Wl,--export-dynamic","-Wl,--unresolved-symbols=ignore-in-object-files"]} + - {name: "LDFLAGS", traits: ["darwin"], flags: ["-Wl,-undefined,dynamic_lookup"]} +PARSER: + SourcesPaths: ["nvsandboxutils.h"] +TRANSLATOR: + ConstRules: + defines: eval + enum: eval + PtrTips: + function: + - {target: "^nvSandboxUtils", default: "sref"} + MemTips: + - {target: "^nvSandboxUtils", default: "raw"} + Rules: + const: + - {action: accept, from: "^NVSANDBOXUTILS_"} + - {action: accept, from: "^nvSandboxUtils"} + - {action: replace, from: "^NVSANDBOXUTILS_"} + - {action: replace, from: "^nvSandboxUtils"} + - {action: accept, from: "^NV"} + - {action: accept, from: "^MAX"} + - {action: accept, from: "^INPUT"} + - {action: replace, from: "_t$"} + - {transform: export} + type: + - {action: accept, from: "^nvSandboxUtils"} + - {action: replace, from: "^nvSandboxUtils"} + - {action: replace, from: "_t$"} + - {transform: export} + function: + - {action: accept, from: "^nvSandboxUtils"} + - {transform: unexport} diff --git a/internal/nvsandboxutils/gen/update-bindings.sh b/internal/nvsandboxutils/gen/update-bindings.sh new file mode 100755 index 00000000..5ac472ea --- /dev/null +++ b/internal/nvsandboxutils/gen/update-bindings.sh @@ -0,0 +1,41 @@ +#!/bin/bash +# Copyright 2024 NVIDIA CORPORATION +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# This file allows for the nvsandboxutils bindings to be updated using the tooling +# implemented in https://github.com/NVIDIA/go-nvml. +# To run this: +# cd internal/nvsandboxutils +# ./update-bindings.sh + +set -e + +BUILDIMAGE=bindings + +docker build \ + --build-arg GOLANG_VERSION=1.22.1 \ + --build-arg C_FOR_GO_TAG=8eeee8c3b71f9c3c90c4a73db54ed08b0bba971d \ + -t ${BUILDIMAGE} \ + -f docker/Dockerfile.devel \ + https://github.com/NVIDIA/go-nvml.git + + +docker run --rm -ti \ + -e GOCACHE=/tmp/.cache/go \ + -e GOMODCACHE=/tmp/.cache/gomod \ + -v $(pwd):/nvsandboxutils \ + -w /nvsandboxutils \ + -u $(id -u):$(id -g) \ + ${BUILDIMAGE} \ + ./gen/generate-bindings.sh