diff --git a/ks.c b/ks.c index 4a18fc4..a39c528 100644 --- a/ks.c +++ b/ks.c @@ -54,6 +54,8 @@ static void print_usage(FILE *out) 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; @@ -101,8 +103,12 @@ int main(int argc, char **argv) print_usage(stderr); return 1; } - qdl.mappings[file_id] = &optarg[colon - optarg + 1]; - printf("Created mapping ID:%ld File:%s\n", file_id, qdl.mappings[file_id]); + filename = &optarg[colon - optarg + 1]; + ret = load_sahara_image(filename, &mappings[file_id]); + if (ret < 0) + exit(1); + + printf("Created mapping ID:%ld File:%s\n", file_id, filename); break; case 'h': print_usage(stdout); @@ -128,7 +134,7 @@ int main(int argc, char **argv) return 1; } - ret = sahara_run(&qdl, qdl.mappings, false, NULL, NULL); + ret = sahara_run(&qdl, mappings, false, NULL, NULL); if (ret < 0) return 1; diff --git a/qdl.c b/qdl.c index 79a809f..b7e733e 100644 --- a/qdl.c +++ b/qdl.c @@ -141,7 +141,8 @@ static void print_usage(FILE *out) int main(int argc, char **argv) { enum qdl_storage_type storage_type = QDL_STORAGE_UFS; - char *prog_mbn; + struct sahara_image sahara_images[MAPPING_SZ] = {}; + bool single_image = true; char *incdir = NULL; char *serial = NULL; const char *vip_generate_dir = NULL; @@ -256,9 +257,9 @@ int main(int argc, char **argv) if (qdl_debug) print_version(); - prog_mbn = argv[optind++]; - if (access(prog_mbn, F_OK)) - errx(1, "unable to load programmer \"%s\"", prog_mbn); + ret = load_sahara_image(argv[optind++], &sahara_images[0]); + if (ret < 0) + exit(1); do { type = detect_type(argv[optind]); @@ -321,8 +322,7 @@ int main(int argc, char **argv) qdl->storage_type = storage_type; - qdl->mappings[0] = prog_mbn; - ret = sahara_run(qdl, qdl->mappings, true, NULL, NULL); + ret = sahara_run(qdl, sahara_images, single_image, NULL, NULL); if (ret < 0) goto out_cleanup; diff --git a/qdl.h b/qdl.h index 002a161..806c90a 100644 --- a/qdl.h +++ b/qdl.h @@ -61,11 +61,15 @@ struct qdl_device { void (*set_vip_transfer)(struct qdl_device *qdl, const char *signed_table, const char *chained_table); - char *mappings[MAPPING_SZ]; // array index is the id from the device - struct vip_transfer_data vip_data; }; +struct sahara_image { + const char *name; + void *ptr; + size_t len; +}; + struct libusb_device_handle; struct qdl_device *qdl_init(enum QDL_DEVICE_TYPE type); @@ -83,8 +87,10 @@ struct qdl_device *sim_init(void); int firehose_run(struct qdl_device *qdl); int firehose_provision(struct qdl_device *qdl); int firehose_read_buf(struct qdl_device *qdl, struct read_op *read_op, void *out_buf, size_t out_size); -int sahara_run(struct qdl_device *qdl, char *img_arr[], bool single_image, - const char *ramdump_path, const char *ramdump_filter); +int sahara_run(struct qdl_device *qdl, const struct sahara_image *images, + bool single_image, const char *ramdump_path, + const char *ramdump_filter); +int load_sahara_image(const char *filename, struct sahara_image *image); void print_hex_dump(const char *prefix, const void *buf, size_t len); unsigned int attr_as_unsigned(xmlNode *node, const char *attr, int *errors); const char *attr_as_string(xmlNode *node, const char *attr, int *errors); diff --git a/sahara.c b/sahara.c index f431c95..501316b 100644 --- a/sahara.c +++ b/sahara.c @@ -144,38 +144,15 @@ static void sahara_hello(struct qdl_device *qdl, struct sahara_pkt *pkt) qdl_write(qdl, &resp, resp.length, SAHARA_CMD_TIMEOUT_MS); } -static int sahara_read_common(struct qdl_device *qdl, int progfd, off_t offset, size_t len) +static void sahara_read(struct qdl_device *qdl, struct sahara_pkt *pkt, + const struct sahara_image *images, + bool single_image) { - ssize_t n; - void *buf; - int ret = 0; - - buf = malloc(len); - if (!buf) - return -ENOMEM; - - lseek(progfd, offset, SEEK_SET); - n = read(progfd, buf, len); - if (n != len) { - ret = -errno; - goto out; - } - - n = qdl_write(qdl, buf, n, SAHARA_CMD_TIMEOUT_MS); - if (n != len) - err(1, "failed to write %zu bytes to sahara", len); - - free(buf); - -out: - return ret; -} - -static void sahara_read(struct qdl_device *qdl, struct sahara_pkt *pkt, char *img_arr[], bool single_image) -{ - unsigned int image; + const struct sahara_image *image; + unsigned int image_idx; + size_t offset; + size_t len; int ret; - int fd; assert(pkt->length == SAHARA_READ_DATA_LENGTH); @@ -183,37 +160,39 @@ static void sahara_read(struct qdl_device *qdl, struct sahara_pkt *pkt, char *im pkt->read_req.image, pkt->read_req.offset, pkt->read_req.length); if (single_image) - image = 0; + image_idx = 0; else - image = pkt->read_req.image; + image_idx = pkt->read_req.image; - if (image >= MAPPING_SZ || !img_arr[image]) { - ux_err("device requested invalid image: %u\n", image); + if (image_idx >= MAPPING_SZ || !images[image_idx].ptr) { + ux_err("device requested invalid image: %u\n", image_idx); sahara_send_reset(qdl); return; } - fd = open(img_arr[image], O_RDONLY | O_BINARY); - if (fd < 0) { - ux_err("Can not open \"%s\": %s\n", img_arr[image], strerror(errno)); - // Maybe this read was optional. Notify device of error and let - // it decide how to proceed. - sahara_send_reset(qdl); + offset = pkt->read_req.offset; + len = pkt->read_req.length; + + image = &images[image_idx]; + if (offset > image->len || offset + len > image->len) { + ux_err("device requested invalid range of image %d\n", image_idx); return; } - ret = sahara_read_common(qdl, fd, pkt->read_req.offset, pkt->read_req.length); - if (ret < 0) - errx(1, "failed to read image chunk to sahara"); - - close(fd); + ret = qdl_write(qdl, image->ptr + offset, len, SAHARA_CMD_TIMEOUT_MS); + if (ret != len) + err(1, "failed to write %zu bytes to sahara", len); } -static void sahara_read64(struct qdl_device *qdl, struct sahara_pkt *pkt, char *img_arr[], bool single_image) +static void sahara_read64(struct qdl_device *qdl, struct sahara_pkt *pkt, + const struct sahara_image *images, + bool single_image) { - unsigned int image; + const struct sahara_image *image; + unsigned int image_idx; + size_t offset; + size_t len; int ret; - int fd; assert(pkt->length == SAHARA_READ_DATA64_LENGTH); @@ -221,29 +200,28 @@ static void sahara_read64(struct qdl_device *qdl, struct sahara_pkt *pkt, char * pkt->read64_req.image, pkt->read64_req.offset, pkt->read64_req.length); if (single_image) - image = 0; + image_idx = 0; else - image = pkt->read64_req.image; + image_idx = pkt->read64_req.image; - if (image >= MAPPING_SZ || !img_arr[image]) { - ux_err("device requested invalid image: %u\n", image); - sahara_send_reset(qdl); - return; - } - fd = open(img_arr[image], O_RDONLY | O_BINARY); - if (fd < 0) { - ux_err("Can not open \"%s\": %s\n", img_arr[image], strerror(errno)); - // Maybe this read was optional. Notify device of error and let - // it decide how to proceed. + if (image_idx >= MAPPING_SZ || !images[image_idx].ptr) { + ux_err("device requested invalid image: %u\n", image_idx); sahara_send_reset(qdl); return; } - ret = sahara_read_common(qdl, fd, pkt->read64_req.offset, pkt->read64_req.length); - if (ret < 0) - errx(1, "failed to read image chunk to sahara"); + offset = pkt->read64_req.offset; + len = pkt->read64_req.length; - close(fd); + image = &images[image_idx]; + if (offset > image->len || offset + len > image->len) { + ux_err("device requested invalid range of image %d\n", image_idx); + return; + } + + ret = qdl_write(qdl, image->ptr + offset, len, SAHARA_CMD_TIMEOUT_MS); + if (ret != len) + err(1, "failed to write %zu bytes to sahara", len); } static void sahara_eoi(struct qdl_device *qdl, struct sahara_pkt *pkt) @@ -436,8 +414,23 @@ static void sahara_debug64(struct qdl_device *qdl, struct sahara_pkt *pkt, sahara_send_reset(qdl); } -int sahara_run(struct qdl_device *qdl, char *img_arr[], bool single_image, - const char *ramdump_path, const char *ramdump_filter) +static void sahara_debug_list_images(const struct sahara_image *images, bool single_image) +{ + int i; + + if (single_image) + ux_debug("Sahara image id in read requests will be ignored\n"); + + ux_debug("Sahara images:\n"); + for (i = 0; i < MAPPING_SZ; i++) { + if (images[i].ptr) + ux_debug(" %2d: %s\n", i, images[i].name ? : "(unknown)"); + } +} + +int sahara_run(struct qdl_device *qdl, const struct sahara_image *images, + bool single_image, const char *ramdump_path, + const char *ramdump_filter) { struct sahara_pkt *pkt; char buf[4096]; @@ -445,6 +438,8 @@ int sahara_run(struct qdl_device *qdl, char *img_arr[], bool single_image, bool done = false; int n; + sahara_debug_list_images(images, single_image); + /* * Don't need to do anything in simulation mode with Sahara, * we care only about Firehose protocol @@ -470,7 +465,7 @@ int sahara_run(struct qdl_device *qdl, char *img_arr[], bool single_image, sahara_hello(qdl, pkt); break; case SAHARA_READ_DATA_CMD: - sahara_read(qdl, pkt, img_arr, single_image); + sahara_read(qdl, pkt, images, single_image); break; case SAHARA_END_OF_IMAGE_CMD: sahara_eoi(qdl, pkt); @@ -486,7 +481,7 @@ int sahara_run(struct qdl_device *qdl, char *img_arr[], bool single_image, sahara_debug64(qdl, pkt, ramdump_path, ramdump_filter); break; case SAHARA_READ_DATA64_CMD: - sahara_read64(qdl, pkt, img_arr, single_image); + sahara_read64(qdl, pkt, images, single_image); break; case SAHARA_RESET_RESP_CMD: assert(pkt->length == SAHARA_RESET_LENGTH); diff --git a/util.c b/util.c index 412e488..36b0bcc 100644 --- a/util.c +++ b/util.c @@ -5,6 +5,7 @@ */ #include #include +#include #include #include #include @@ -12,7 +13,9 @@ #include #include #include +#include +#include "oscompat.h" #include "qdl.h" #include "version.h" @@ -207,3 +210,55 @@ done: return 0; } + +/** + * load_sahara_image() - Load the content of the given file into the image + * @filename: file to be loaded + * @image: Sahara image object to be populated + * + * Read the content of the given @filename into the given @image, update the + * @image->len, and then populate the @image->name for debugging purposes. + * + * Returns: 0 on success, -1 on error + */ +int load_sahara_image(const char *filename, struct sahara_image *image) +{ + ssize_t n; + off_t len; + void *ptr; + int fd; + + fd = open(filename, O_RDONLY | O_BINARY); + if (fd < 0) { + ux_err("failed to read \"%s\"\n", filename); + return -1; + } + + len = lseek(fd, 0, SEEK_END); + if (len < 0) { + ux_err("failed to find end of \"%s\"\n", filename); + goto err_close; + } + lseek(fd, 0, SEEK_SET); + + ptr = malloc(len); + + n = read(fd, ptr, len); + if (n != len) { + ux_err("failed to read content of \"%s\"\n", filename); + free(ptr); + goto err_close; + } + + close(fd); + + image->name = strdup(filename); + image->ptr = ptr; + image->len = len; + + return 0; + +err_close: + close(fd); + return -1; +}