Use firmware path from sysfs

Some linux distributions adjust path fro kernel to load
firmware from using /sys/module/firmware_class/parameters/path.
Kernel supports it, teach tqftpserv to respect it too.

Signed-off-by: Alexey Minnekhanov <alexeymin@postmarketos.org>
This commit is contained in:
Alexey Minnekhanov
2024-01-08 05:58:40 +03:00
committed by Alexey Minnekhanov
parent 289214a5d1
commit a4c755db17

View File

@@ -53,6 +53,20 @@
#define TQFTPSERV_TMP "/data/vendor/tmp/tqftpserv" #define TQFTPSERV_TMP "/data/vendor/tmp/tqftpserv"
#endif #endif
static void read_fw_path_from_sysfs(char *outbuffer, size_t bufsize)
{
size_t pathsize;
FILE *f = fopen("/sys/module/firmware_class/parameters/path", "rt");
if (!f)
return;
pathsize = fread(outbuffer, sizeof(char), bufsize, f);
fclose(f);
if (pathsize == 0)
return;
/* truncate newline */
outbuffer[pathsize - 1] = '\0';
}
/** /**
* translate_readonly() - open "file" residing with remoteproc firmware * translate_readonly() - open "file" residing with remoteproc firmware
* @file: file requested, stripped of "/readonly/image/" prefix * @file: file requested, stripped of "/readonly/image/" prefix
@@ -72,6 +86,7 @@ static int translate_readonly(const char *file)
char firmware_value[PATH_MAX]; char firmware_value[PATH_MAX];
char firmware_attr[32]; char firmware_attr[32];
char path[PATH_MAX]; char path[PATH_MAX];
char fw_sysfs_path[PATH_MAX];
struct dirent *de; struct dirent *de;
int firmware_fd; int firmware_fd;
DIR *class_dir; DIR *class_dir;
@@ -79,6 +94,8 @@ static int translate_readonly(const char *file)
ssize_t n; ssize_t n;
int fd = -1; int fd = -1;
read_fw_path_from_sysfs(fw_sysfs_path, sizeof(fw_sysfs_path));
class_fd = open("/sys/class/remoteproc", O_RDONLY | O_DIRECTORY); class_fd = open("/sys/class/remoteproc", O_RDONLY | O_DIRECTORY);
if (class_fd < 0) { if (class_fd < 0) {
warn("failed to open remoteproc class"); warn("failed to open remoteproc class");
@@ -112,6 +129,23 @@ static int translate_readonly(const char *file)
} }
firmware_value[n] = '\0'; firmware_value[n] = '\0';
/* first try path from sysfs */
if ((strlen(fw_sysfs_path) > 0) &&
(strlen(fw_sysfs_path) + 1 + strlen(firmware_value) + 1 + strlen(file) + 1 < sizeof(path))) {
strcpy(path, fw_sysfs_path);
strcat(path, "/");
strcat(path, dirname(firmware_value));
strcat(path, "/");
strcat(path, file);
fd = open(path, O_RDONLY);
if (fd >= 0)
break;
if (errno != ENOENT)
warn("failed to open %s", path);
}
/* now try with base path */
if (strlen(FIRMWARE_BASE) + strlen(firmware_value) + 1 + if (strlen(FIRMWARE_BASE) + strlen(firmware_value) + 1 +
strlen(file) + 1 > sizeof(path)) strlen(file) + 1 > sizeof(path))
continue; continue;