From ff1a3bb1d376b96e50dc85fcc191b87e09b25a2e Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Mon, 2 Feb 2026 08:34:57 -0600 Subject: [PATCH] ramdump: Make ramdump a qdl subcommand Providing qdl-ramdump as a separate executable has resulted in it not being part of several of the distributions that include qdl. Also, users that knows that qdl supports ramdumps are looking for it "in" qdl, not a related tool. Make "ramdump" a subcommand, just like "qdl list", to improve the ergonomics of the tool. The implementation is a (almost) verbatim copy of ramdump.c. The existing executable is kept in order to not break those distributions that explicitly do package said executable. At some point we should figure out how to drop this. Signed-off-by: Bjorn Andersson --- qdl.c | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 86 insertions(+), 6 deletions(-) diff --git a/qdl.c b/qdl.c index b145835..d42f0db 100644 --- a/qdl.c +++ b/qdl.c @@ -415,6 +415,7 @@ static void print_usage(FILE *out) fprintf(out, "Usage: %s [options] ( | | )...\n", __progname); fprintf(out, " %s [options] ((read | write)
)...\n", __progname); fprintf(out, " %s list\n", __progname); + fprintf(out, " %s ramdump [--debug] [-o ] [,...]\n", __progname); fprintf(out, " -d, --debug\t\t\tPrint detailed debug info\n"); fprintf(out, " -v, --version\t\t\tPrint the current version and exit\n"); fprintf(out, " -n, --dry-run\t\t\tDry run execution, no device reading or flashing\n"); @@ -428,12 +429,14 @@ static void print_usage(FILE *out) fprintf(out, " -T, --slot=T\t\t\tSet slot number T for multiple storage devices\n"); fprintf(out, " -D, --vip-table-path=T\t\tUse digest tables in the T folder for VIP\n"); fprintf(out, " -h, --help\t\t\tPrint this usage info\n"); - fprintf(out, " \txml file containing or directives\n"); - fprintf(out, " \txml file containing directives\n"); - fprintf(out, " \txml file containing directives\n"); - fprintf(out, "
\tdisk address specifier, can be one of

,

,

, , or\n"); - fprintf(out, " \t

, to specify a physical partition number P, a starting sector\n"); - fprintf(out, " \tnumber S, the number of sectors to follow L, or partition by \"name\"\n"); + fprintf(out, " \t\txml file containing or directives\n"); + fprintf(out, " \t\txml file containing directives\n"); + fprintf(out, " \t\txml file containing directives\n"); + fprintf(out, "

\t\tdisk address specifier, can be one of

,

,

, , or\n"); + fprintf(out, " \t\t

, to specify a physical partition number P, a starting sector\n"); + fprintf(out, " \t\tnumber S, the number of sectors to follow L, or partition by \"name\"\n"); + fprintf(out, " \t\tpath where ramdump should stored\n"); + fprintf(out, " \toptional glob-pattern to select which segments to ramdump\n"); fprintf(out, "\n"); fprintf(out, "Example: %s prog_firehose_ddr.elf rawprogram*.xml patch*.xml\n", __progname); } @@ -461,6 +464,81 @@ static int qdl_list(FILE *out) return 0; } +static int qdl_ramdump(int argc, char **argv) +{ + struct qdl_device *qdl; + char *ramdump_path = "."; + char *filter = NULL; + char *serial = NULL; + int ret = 0; + int opt; + + static struct option options[] = { + {"debug", no_argument, 0, 'd'}, + {"version", no_argument, 0, 'v'}, + {"output", required_argument, 0, 'o'}, + {"serial", required_argument, 0, 'S'}, + {"help", no_argument, 0, 'h'}, + {0, 0, 0, 0} + }; + + while ((opt = getopt_long(argc, argv, "dvo:S:h", options, NULL)) != -1) { + switch (opt) { + case 'd': + qdl_debug = true; + break; + case 'v': + print_version(); + return 0; + case 'o': + ramdump_path = optarg; + break; + case 'S': + serial = optarg; + break; + case 'h': + print_usage(stdout); + return 0; + default: + print_usage(stderr); + return 1; + } + } + + if (optind < argc) + filter = argv[optind++]; + + if (optind != argc) { + print_usage(stderr); + return 1; + } + + qdl = qdl_init(QDL_DEVICE_USB); + if (!qdl) + return 1; + + if (qdl_debug) + print_version(); + + ret = qdl_open(qdl, serial); + if (ret) { + ret = 1; + goto out_cleanup; + } + + ret = sahara_run(qdl, NULL, ramdump_path, filter); + if (ret < 0) { + ret = 1; + goto out_cleanup; + } + +out_cleanup: + qdl_close(qdl); + qdl_deinit(qdl); + + return ret; +} + int main(int argc, char **argv) { enum qdl_storage_type storage_type = QDL_STORAGE_UFS; @@ -500,6 +578,8 @@ int main(int argc, char **argv) if (argc == 2 && !strcmp(argv[1], "list")) return qdl_list(stdout); + if (argc >= 2 && !strcmp(argv[1], "ramdump")) + return qdl_ramdump(argc - 1, argv + 1); while ((opt = getopt_long(argc, argv, "dvi:lu:S:D:s:fcnt:T:h", options, NULL)) != -1) { switch (opt) {