summaryrefslogtreecommitdiff
path: root/rbutil/jztool/jztool.c
diff options
context:
space:
mode:
authorAidan MacDonald <amachronic@protonmail.com>2021-05-11 13:25:26 +0100
committerAidan MacDonald <amachronic@protonmail.com>2021-05-12 10:35:20 +0000
commitcc22df198d0ccb64dfdfe0c2f247f7d86b7fd750 (patch)
treee6cd8aaa33c161bc0f72a9b35e763372b20f910d /rbutil/jztool/jztool.c
parent3748117ee3623437d63ba2016637fd532dbdd4b9 (diff)
downloadrockbox-cc22df198d0ccb64dfdfe0c2f247f7d86b7fd750.tar.gz
rockbox-cc22df198d0ccb64dfdfe0c2f247f7d86b7fd750.zip
jztool: Support new M3K bootloader
Change-Id: Ia2d96893a9a5c77deb71c1fe32ae5a0585093f5b
Diffstat (limited to 'rbutil/jztool/jztool.c')
-rw-r--r--rbutil/jztool/jztool.c162
1 files changed, 65 insertions, 97 deletions
diff --git a/rbutil/jztool/jztool.c b/rbutil/jztool/jztool.c
index 5aae8d7457..5fb6dc173f 100644
--- a/rbutil/jztool/jztool.c
+++ b/rbutil/jztool/jztool.c
@@ -26,21 +26,68 @@
26#include <stdbool.h> 26#include <stdbool.h>
27 27
28jz_context* jz = NULL; 28jz_context* jz = NULL;
29jz_usbdev* usbdev = NULL;
29const jz_device_info* dev_info = NULL; 30const jz_device_info* dev_info = NULL;
30int dev_action = -1; 31
31jz_paramlist* action_params = NULL; 32void usage_fiiom3k(void)
33{
34 printf("Usage:\n"
35 " jztool fiiom3k load <bootloader.m3k>\n"
36 "\n"
37 "The 'load' command is used to boot the Rockbox bootloader in\n"
38 "recovery mode, which allows you to install the Rockbox bootloader\n"
39 "and backup or restore bootloader images. You need to connect the\n"
40 "M3K in USB boot mode in order to use this tool.\n"
41 "\n"
42 "On Windows, you will need to install the WinUSB driver for the M3K\n"
43 "using a 3rd-party tool such as Zadig <https://zadig.akeo.ie>. For\n"
44 "more details check the jztool README.md file or the Rockbox wiki at\n"
45 "<https://rockbox.org/wiki/FiioM3K>.\n"
46 "\n"
47 "To connect the M3K in USB boot mode, plug the microUSB into the\n"
48 "M3K, and hold the VOL- button while plugging the USB into your\n"
49 "computer. If successful, the button light will turn on and the\n"
50 "LCD will remain black. If you encounter any errors and need to\n"
51 "reconnect the device, you must force a power off by holding POWER\n"
52 "for more than 10 seconds.\n"
53 "\n"
54 "Once the Rockbox bootloader is installed on your M3K, you can\n"
55 "access the recovery menu by holding VOL+ while powering on the\n"
56 "device.\n");
57 exit(4);
58}
59
60int cmdline_fiiom3k(int argc, char** argv)
61{
62 if(argc < 2 || strcmp(argv[0], "load")) {
63 usage_fiiom3k();
64 return 2;
65 }
66
67 int rc = jz_usb_open(jz, &usbdev, dev_info->vendor_id, dev_info->product_id);
68 if(rc < 0) {
69 jz_log(jz, JZ_LOG_ERROR, "Cannot open USB device: %d", rc);
70 return 1;
71 }
72
73 rc = jz_fiiom3k_boot(usbdev, argv[1]);
74 if(rc < 0) {
75 jz_log(jz, JZ_LOG_ERROR, "Boot failed: %d", rc);
76 return 1;
77 }
78
79 return 0;
80}
32 81
33void usage(void) 82void usage(void)
34{ 83{
35 printf("Usage:\n" 84 printf("Usage:\n"
36 " jztool [global options] <device> <action> [action options]\n" 85 " jztool [global options] <device> <command> [command arguments]\n"
37 "\n" 86 "\n"
38 "Global options:\n" 87 "Global options:\n"
39 "\n"
40 " -h, --help Display this help\n" 88 " -h, --help Display this help\n"
41 " -q, --quiet Don't log anything except errors\n" 89 " -q, --quiet Don't log anything except errors\n"
42 " -v, --verbose Display detailed logging output\n" 90 " -v, --verbose Display detailed logging output\n\n");
43 " -l, --loglevel LEVEL Set log level\n");
44 91
45 printf("Supported devices:\n\n"); 92 printf("Supported devices:\n\n");
46 int n = jz_get_num_device_info(); 93 int n = jz_get_num_device_info();
@@ -49,39 +96,17 @@ void usage(void)
49 printf(" %s - %s\n", info->name, info->description); 96 printf(" %s - %s\n", info->name, info->description);
50 } 97 }
51 98
52 printf( 99 printf("\n"
53"\n" 100 "For device-specific help run 'jztool DEVICE' without arguments,\n"
54"Available actions for fiiom3k:\n" 101 "eg. 'jztool fiiom3k' will display help for the FiiO M3K.\n");
55"\n"
56" install --spl <spl.m3k> --bootloader <bootloader.m3k>\n"
57" [--without-backup yes] [--backup IMAGE]\n"
58" Install or update the Rockbox bootloader on a device.\n"
59"\n"
60" If --backup is given, back up the current bootloader to IMAGE before\n"
61" installing the new bootloader. The installer will normally refuse to\n"
62" overwrite your current bootloader; pass '--without-backup yes' if you\n"
63" really want to proceed without taking a backup.\n"
64"\n"
65" WARNING: it is NOT RECOMMENDED to install the Rockbox bootloader\n"
66" without taking a backup of the original firmware bootloader. It may\n"
67" be very difficult or impossible to recover your player without one.\n"
68" At least one M3Ks is known to not to work with the Rockbox bootloader,\n"
69" so it is very important to take a backup.\n"
70"\n"
71" backup --image IMAGE\n"
72" Backup the current bootloader to the file IMAGE\n"
73"\n"
74" restore --image IMAGE\n"
75" Restore a bootloader image backup from the file IMAGE\n"
76"\n");
77 102
78 exit(4); 103 exit(4);
79} 104}
80 105
81void cleanup(void) 106void cleanup(void)
82{ 107{
83 if(action_params) 108 if(usbdev)
84 jz_paramlist_free(action_params); 109 jz_usb_close(usbdev);
85 if(jz) 110 if(jz)
86 jz_context_destroy(jz); 111 jz_context_destroy(jz);
87} 112}
@@ -157,71 +182,14 @@ int main(int argc, char** argv)
157 exit(2); 182 exit(2);
158 } 183 }
159 184
160 /* Read the action */ 185 /* Dispatch to device handler */
161 --argc, ++argv;
162 if(argc == 0) {
163 jz_log(jz, JZ_LOG_ERROR, "No action specified (try jztool --help)");
164 exit(2);
165 }
166
167 for(dev_action = 0; dev_action < dev_info->num_actions; ++dev_action)
168 if(!strcmp(*argv, dev_info->action_names[dev_action]))
169 break;
170
171 if(dev_action == dev_info->num_actions) {
172 jz_log(jz, JZ_LOG_ERROR, "Unknown action '%s' (try jztool --help)", *argv);
173 exit(2);
174 }
175
176 /* Parse the action options */
177 action_params = jz_paramlist_new();
178 if(!action_params) {
179 jz_log(jz, JZ_LOG_ERROR, "Out of memory: can't create paramlist");
180 exit(1);
181 }
182
183 const char* const* allowed_params = dev_info->action_params[dev_action];
184
185 --argc, ++argv; 186 --argc, ++argv;
186 while(argc > 0 && argv[0][0] == '-') { 187 switch(dev_info->device_type) {
187 if(argv[0][1] != '-') { 188 case JZ_DEVICE_FIIOM3K:
188 jz_log(jz, JZ_LOG_ERROR, "Invalid option '%s' for action", *argv); 189 return cmdline_fiiom3k(argc, argv);
189 exit(2);
190 }
191 190
192 bool bad_option = true; 191 default:
193 for(int i = 0; allowed_params[i] != NULL; ++i) { 192 jz_log(jz, JZ_LOG_ERROR, "INTERNAL ERROR: unhandled device type");
194 if(!strcmp(&argv[0][2], allowed_params[i])) { 193 return 1;
195 ++argv;
196 if(--argc == 0) {
197 jz_log(jz, JZ_LOG_ERROR, "Missing argument for parameter '%s'", *argv);
198 exit(2);
199 }
200
201 int rc = jz_paramlist_set(action_params, allowed_params[i], *argv);
202 if(rc < 0) {
203 jz_log(jz, JZ_LOG_ERROR, "Out of memory");
204 exit(1);
205 }
206
207 bad_option = false;
208 }
209 }
210
211 if(bad_option) {
212 jz_log(jz, JZ_LOG_ERROR, "Invalid option '%s' for action", *argv);
213 exit(2);
214 }
215
216 --argc, ++argv;
217 }
218
219 if(argc != 0) {
220 jz_log(jz, JZ_LOG_ERROR, "Excess arguments on command line");
221 exit(2);
222 } 194 }
223
224 /* Invoke action handler */
225 int rc = dev_info->action_funcs[dev_action](jz, action_params);
226 return (rc < 0) ? 1 : 0;
227} 195}