Add firmware search paths when generating CDI specifications

Path to locate the GSP firmware is explicitly set to /lib/firmware/nvidia.
Users may chose to install the GSP firmware in alternate locations where
the kernel would look for firmware on the root filesystem.

Add locate functionality which looks for the GSP firmware files in the
same location as the kernel would
(https://docs.kernel.org/driver-api/firmware/fw_search_path.html).

The paths searched in order are:
- path described in /sys/module/firmware_class/parameters/path
- /lib/firmware/updates/UTS_RELEASE/
- /lib/firmware/updates/
- /lib/firmware/UTS_RELEASE/
- /lib/firmware/

Signed-off-by: Evan Lezar <elezar@nvidia.com>
This commit is contained in:
Evan Lezar 2023-07-07 15:09:12 +02:00
parent 4f89b60ab9
commit 0a37f8798a

View File

@ -18,6 +18,7 @@ package nvcdi
import ( import (
"fmt" "fmt"
"os"
"path/filepath" "path/filepath"
"strings" "strings"
@ -26,6 +27,7 @@ import (
"github.com/NVIDIA/nvidia-container-toolkit/internal/lookup" "github.com/NVIDIA/nvidia-container-toolkit/internal/lookup"
"github.com/NVIDIA/nvidia-container-toolkit/internal/lookup/cuda" "github.com/NVIDIA/nvidia-container-toolkit/internal/lookup/cuda"
"gitlab.com/nvidia/cloud-native/go-nvlib/pkg/nvml" "gitlab.com/nvidia/cloud-native/go-nvlib/pkg/nvml"
"golang.org/x/sys/unix"
) )
// NewDriverDiscoverer creates a discoverer for the libraries and binaries associated with a driver installation. // NewDriverDiscoverer creates a discoverer for the libraries and binaries associated with a driver installation.
@ -55,7 +57,10 @@ func newDriverVersionDiscoverer(logger logger.Interface, driverRoot string, nvid
return nil, fmt.Errorf("failed to create discoverer for IPC sockets: %v", err) return nil, fmt.Errorf("failed to create discoverer for IPC sockets: %v", err)
} }
firmwares := NewDriverFirmwareDiscoverer(logger, driverRoot, version) firmwares, err := NewDriverFirmwareDiscoverer(logger, driverRoot, version)
if err != nil {
return nil, fmt.Errorf("failed to create discoverer for GSP firmware: %v", err)
}
binaries := NewDriverBinariesDiscoverer(logger, driverRoot) binaries := NewDriverBinariesDiscoverer(logger, driverRoot)
@ -96,18 +101,54 @@ func NewDriverLibraryDiscoverer(logger logger.Interface, driverRoot string, nvid
return d, nil return d, nil
} }
func getUTSRelease(logger logger.Interface) (string, error) {
utsname := &unix.Utsname{}
if err := unix.Uname(utsname); err != nil {
return "", err
}
return unix.ByteSliceToString(utsname.Release[:]), nil
}
func getFirmwareSearchPaths(logger logger.Interface) ([]string, error) {
utsRelease, err := getUTSRelease(logger)
if err != nil {
return nil, fmt.Errorf("failed to get UTS_RELEASE: %v", err)
}
firmwarePaths := []string{
filepath.Join("/lib/firmware/updates/", utsRelease),
filepath.Join("/lib/firmware/updates/"),
filepath.Join("/lib/firmware/", utsRelease),
filepath.Join("/lib/firmware/"),
}
customFirmwareClassPath, err := os.ReadFile("/sys/module/firmware_class/parameters/path")
if err != nil {
return nil, fmt.Errorf("failed to get custom firmware class path for driver version: %v", err)
}
if !(len(customFirmwareClassPath) == 1 && customFirmwareClassPath[0] == byte(10)) {
firmwarePaths = append(firmwarePaths, string(customFirmwareClassPath))
}
return firmwarePaths, nil
}
// NewDriverFirmwareDiscoverer creates a discoverer for GSP firmware associated with the specified driver version. // NewDriverFirmwareDiscoverer creates a discoverer for GSP firmware associated with the specified driver version.
func NewDriverFirmwareDiscoverer(logger logger.Interface, driverRoot string, version string) discover.Discover { func NewDriverFirmwareDiscoverer(logger logger.Interface, driverRoot string, version string) (discover.Discover, error) {
gspFirmwarePath := filepath.Join("/lib/firmware/nvidia", version, "gsp*.bin") gspFirmwareSearchPaths, err := getFirmwareSearchPaths(logger)
if err != nil {
return nil, fmt.Errorf("failed to get libraries for driver version: %v", err)
}
gspFirmwarePaths := filepath.Join("nvidia", version, "gsp*.bin")
return discover.NewMounts( return discover.NewMounts(
logger, logger,
lookup.NewFileLocator( lookup.NewFileLocator(
lookup.WithLogger(logger), lookup.WithLogger(logger),
lookup.WithRoot(driverRoot), lookup.WithRoot(driverRoot),
lookup.WithSearchPaths(gspFirmwareSearchPaths...),
), ),
driverRoot, driverRoot,
[]string{gspFirmwarePath}, []string{gspFirmwarePaths},
) ), nil
} }
// NewDriverBinariesDiscoverer creates a discoverer for GSP firmware associated with the GPU driver. // NewDriverBinariesDiscoverer creates a discoverer for GSP firmware associated with the GPU driver.