diff --git a/Makefile b/Makefile index 12a67a7..203cb04 100644 --- a/Makefile +++ b/Makefile @@ -6,10 +6,10 @@ CFLAGS += -O2 -Wall -g `pkg-config --cflags libxml-2.0 libusb-1.0` LDFLAGS += `pkg-config --libs libxml-2.0 libusb-1.0` prefix := /usr/local -QDL_SRCS := firehose.c io.c qdl.c sahara.c util.c patch.c program.c read.c ufs.c usb.c ux.c oscompat.c +QDL_SRCS := firehose.c io.c qdl.c sahara.c util.c patch.c program.c read.c sim.c ufs.c usb.c ux.c oscompat.c QDL_OBJS := $(QDL_SRCS:.c=.o) -RAMDUMP_SRCS := ramdump.c sahara.c io.c usb.c util.c ux.c oscompat.c +RAMDUMP_SRCS := ramdump.c sahara.c io.c sim.c usb.c util.c ux.c oscompat.c RAMDUMP_OBJS := $(RAMDUMP_SRCS:.c=.o) KS_OUT := ks diff --git a/firehose.c b/firehose.c index 3e6b13f..97c0856 100644 --- a/firehose.c +++ b/firehose.c @@ -146,6 +146,10 @@ static int firehose_read(struct qdl_device *qdl, int timeout_ms, gettimeofday(&now, NULL); timeradd(&now, &delta, &timeout); + /* In simulation mode we don't expent to read and parse any responses */ + if (qdl->dev_type == QDL_DEVICE_SIM) + return 0; + do { n = qdl_read(qdl, buf, sizeof(buf), 100); if (n <= 0) { @@ -298,7 +302,12 @@ static int firehose_configure(struct qdl_device *qdl, bool skip_storage_init, co return -1; } - max_payload_size = size; + /* + * Simulated target doesn't provide any valid payload size, so + * for QDL_DEVICE_SIM dev type we keep old max_payload_size value + */ + if (qdl->dev_type != QDL_DEVICE_SIM) + max_payload_size = size; } ux_debug("accepted max payload size: %zu\n", max_payload_size); diff --git a/io.c b/io.c index 11c6b7c..6d1e6e6 100644 --- a/io.c +++ b/io.c @@ -36,6 +36,9 @@ struct qdl_device *qdl_init(enum QDL_DEVICE_TYPE type) if (type == QDL_DEVICE_USB) return usb_init(); + if (type == QDL_DEVICE_SIM) + return sim_init(); + return NULL; } diff --git a/qdl.c b/qdl.c index 329d0ec..06145f0 100644 --- a/qdl.c +++ b/qdl.c @@ -107,7 +107,7 @@ static void print_usage(void) { extern const char *__progname; fprintf(stderr, - "%s [--debug] [--version] [--allow-missing] [--storage ] [--finalize-provisioning] [--include ] [--serial ] [--out-chunk-size ] [ ...]\n", + "%s [--debug] [--dry-run] [--version] [--allow-missing] [--storage ] [--finalize-provisioning] [--include ] [--serial ] [--out-chunk-size ] [ ...]\n", __progname); } @@ -140,6 +140,7 @@ int main(int argc, char **argv) {"storage", required_argument, 0, 's'}, {"allow-missing", no_argument, 0, 'f'}, {"allow-fusing", no_argument, 0, 'c'}, + {"dry-run", no_argument, 0, 'n'}, {0, 0, 0, 0} }; @@ -148,6 +149,9 @@ int main(int argc, char **argv) case 'd': qdl_debug = true; break; + case 'n': + qdl_dev_type = QDL_DEVICE_SIM; + break; case 'v': print_version(); return 0; diff --git a/qdl.h b/qdl.h index ed243b3..756a79e 100644 --- a/qdl.h +++ b/qdl.h @@ -13,6 +13,7 @@ enum QDL_DEVICE_TYPE { QDL_DEVICE_USB, + QDL_DEVICE_SIM, }; struct qdl_device @@ -40,6 +41,7 @@ int qdl_write(struct qdl_device *qdl, const void *buf, size_t len); void qdl_set_out_chunk_size(struct qdl_device *qdl, long size); struct qdl_device *usb_init(void); +struct qdl_device *sim_init(void); int firehose_run(struct qdl_device *qdl, const char *incdir, const char *storage, bool allow_missing); int sahara_run(struct qdl_device *qdl, char *img_arr[], bool single_image, diff --git a/sahara.c b/sahara.c index 4ef1a94..259f433 100644 --- a/sahara.c +++ b/sahara.c @@ -469,6 +469,13 @@ int sahara_run(struct qdl_device *qdl, char *img_arr[], bool single_image, bool done = false; int n; + /* + * Don't need to do anything in simulation mode with Sahara, + * we care only about Firehose protocol + */ + if (qdl->dev_type == QDL_DEVICE_SIM) + return 0; + while (!done) { n = qdl_read(qdl, buf, sizeof(buf), 1000); if (n < 0) diff --git a/sim.c b/sim.c new file mode 100644 index 0000000..350779a --- /dev/null +++ b/sim.c @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2025, Qualcomm Innovation Center, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include +#include + +#include "qdl.h" + +struct qdl_device_sim +{ + struct qdl_device base; +}; + +static int sim_open(struct qdl_device *qdl, const char *serial) +{ + ux_info("This is a dry-run execution of QDL. No actual flashing has been performed\n"); + + return 0; +} + +static void sim_close(struct qdl_device *qdl) +{ + return; +} + +static int sim_read(struct qdl_device *qdl, void *buf, size_t len, unsigned int timeout) +{ + return len; +} + +static int sim_write(struct qdl_device *qdl, const void *buf, size_t len) +{ + return len; +} + +static void sim_set_out_chunk_size(struct qdl_device *qdl, long size) +{ + return; +} + +struct qdl_device *sim_init(void) +{ + struct qdl_device *qdl = malloc(sizeof(struct qdl_device_sim)); + if (!qdl) + return NULL; + + memset(qdl, 0, sizeof(struct qdl_device_sim)); + + qdl->dev_type = QDL_DEVICE_SIM; + qdl->open = sim_open; + qdl->read = sim_read; + qdl->write = sim_write; + qdl->close = sim_close; + qdl->set_out_chunk_size = sim_set_out_chunk_size; + + return qdl; +} \ No newline at end of file