mirror of
https://github.com/linux-msm/qdl.git
synced 2026-10-07 06:29:17 -07:00
Calls to assert() on packet fields derived from device-controlled input crash the process on malformed data, giving no useful diagnostic and leaving the USB session in an undefined state. Replace every such assert with an explicit length check that logs the unexpected value, sends a SAHARA_RESET to the device to cleanly terminate the session, and returns -1 so the caller can propagate the error. Functions that were void and sent no response on assertion failure (sahara_hello, sahara_eoi, sahara_done) are changed to return int. All call sites in sahara_run() now check the return value. Since no assert() calls remain anywhere in the tree, drop the unused assert.h include. Signed-off-by: Igor Opaniuk <igor.opaniuk@oss.qualcomm.com>
142 lines
3.0 KiB
C
142 lines
3.0 KiB
C
// SPDX-License-Identifier: BSD-3-Clause
|
|
#include <sys/types.h>
|
|
#include <ctype.h>
|
|
#include <dirent.h>
|
|
#include <errno.h>
|
|
#include <fcntl.h>
|
|
#include <getopt.h>
|
|
#include <stdbool.h>
|
|
#include <stdint.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
|
|
#include "qdl.h"
|
|
#include "oscompat.h"
|
|
|
|
#ifdef _WIN32
|
|
const char *__progname = "ks";
|
|
#endif
|
|
|
|
static struct qdl_device qdl;
|
|
|
|
bool qdl_debug;
|
|
|
|
int qdl_read(struct qdl_device *qdl, void *buf, size_t len, unsigned int timeout __unused)
|
|
{
|
|
return read(qdl->fd, buf, len);
|
|
}
|
|
|
|
int qdl_write(struct qdl_device *qdl, const void *buf, size_t len, unsigned int timeout __unused)
|
|
{
|
|
return write(qdl->fd, buf, len);
|
|
}
|
|
|
|
static void print_usage(FILE *out)
|
|
{
|
|
extern const char *__progname;
|
|
|
|
fprintf(out,
|
|
"%s -p <sahara dev_node> -s <id:file path> ...\n",
|
|
__progname);
|
|
fprintf(out,
|
|
" -h --help Print this usage info\n"
|
|
" -p --port Sahara device node to use\n"
|
|
" -s <id:file path> --sahara <id:file path> Sahara protocol file mapping\n"
|
|
"\n"
|
|
"One -p instance is required. One or more -s instances are required.\n"
|
|
"\n"
|
|
"Example:\n"
|
|
"ks -p /dev/mhi0_QAIC_SAHARA -s 1:/opt/qti-aic/firmware/fw1.bin -s 2:/opt/qti-aic/firmware/fw2.bin\n");
|
|
}
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
struct sahara_image mappings[MAPPING_SZ] = {};
|
|
const char *filename;
|
|
bool found_mapping = false;
|
|
char *dev_node = NULL;
|
|
long file_id;
|
|
char *colon;
|
|
int opt;
|
|
int ret;
|
|
|
|
static struct option options[] = {
|
|
{"debug", no_argument, 0, 'd'},
|
|
{"help", no_argument, 0, 'h'},
|
|
{"version", no_argument, 0, 'v'},
|
|
{"port", required_argument, 0, 'p'},
|
|
{"sahara", required_argument, 0, 's'},
|
|
{0, 0, 0, 0}
|
|
};
|
|
|
|
while ((opt = getopt_long(argc, argv, "dvp:s:h", options, NULL)) != -1) {
|
|
switch (opt) {
|
|
case 'd':
|
|
qdl_debug = true;
|
|
break;
|
|
case 'v':
|
|
print_version();
|
|
return 0;
|
|
case 'p':
|
|
dev_node = optarg;
|
|
printf("Using port - %s\n", dev_node);
|
|
break;
|
|
case 's':
|
|
found_mapping = true;
|
|
file_id = strtol(optarg, NULL, 10);
|
|
if (file_id < 0) {
|
|
print_usage(stderr);
|
|
return 1;
|
|
}
|
|
if (file_id >= MAPPING_SZ) {
|
|
fprintf(stderr,
|
|
"ID:%ld exceeds the max value of %d\n",
|
|
file_id,
|
|
MAPPING_SZ - 1);
|
|
return 1;
|
|
}
|
|
colon = strchr(optarg, ':');
|
|
if (!colon) {
|
|
print_usage(stderr);
|
|
return 1;
|
|
}
|
|
filename = &optarg[colon - optarg + 1];
|
|
ret = load_sahara_image(filename, &mappings[file_id]);
|
|
if (ret < 0)
|
|
return 1;
|
|
|
|
printf("Created mapping ID:%ld File:%s\n", file_id, filename);
|
|
break;
|
|
case 'h':
|
|
print_usage(stdout);
|
|
return 0;
|
|
default:
|
|
print_usage(stderr);
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
// -p and -s is required
|
|
if (!dev_node || !found_mapping) {
|
|
print_usage(stderr);
|
|
return 1;
|
|
}
|
|
|
|
if (qdl_debug)
|
|
print_version();
|
|
|
|
qdl.fd = open(dev_node, O_RDWR);
|
|
if (qdl.fd < 0) {
|
|
fprintf(stderr, "Unable to open %s\n", dev_node);
|
|
return 1;
|
|
}
|
|
|
|
ret = sahara_run(&qdl, mappings, NULL, NULL);
|
|
if (ret < 0)
|
|
return 1;
|
|
|
|
return 0;
|
|
}
|