comparison fluid-mnf/machine.c @ 311:9cecc930d78f

fluid-mnf: original source from TI, defenestrated line endings and rearranged directory structure, but no *.[ch] source file content changes yet
author Mychaela Falconia <falcon@freecalypso.org>
date Sat, 29 Feb 2020 05:36:07 +0000
parents
children 435e041897f2
comparison
equal deleted inserted replaced
310:ae39d76d5b7a 311:9cecc930d78f
1 /******************************************************************************
2 * FLUID (Flash Loader Utility Independent of Device)
3 *
4 * Copyright Texas Instruments, 2001.
5 * Mads Meisner-Jensen, mmj@ti.com.
6 * Original state-machine logic by Delta Technologies, Copyright, 2001.
7 *
8 * Core functionality. State machines and support functions.
9 *
10 * $Id: machine.c 1.35.1.37 Mon, 28 Apr 2003 08:49:16 +0200 tsj $
11 *
12 ******************************************************************************/
13
14 #include "fluid.h"
15 #include "flash.h"
16 #include "target.h"
17 #include "fileio.h"
18 #include "../target/protocol.h"
19 #include "misc.h"
20 #include "lz.h"
21 #include "trace.h"
22 // Secure Calypso Plus
23 #include "../inc/ram_load.h"
24 #include "../inc/secure_types.h"
25
26 #include <stdio.h>
27 #include <malloc.h>
28 #include <stdlib.h>
29 #include <string.h>
30
31 /******************************************************************************
32 * Constants and typedefs
33 ******************************************************************************/
34
35 // Due to memory wrap/mirror used in flash_read_machine(), IMAGE_SIZE_MAX
36 // *must* be a power of two.
37 #define IMAGE_SIZE_MAX (8 * 1024 * 1024)
38
39 #define IMAGE_CHUNK_SIZE 8192
40
41 #define ERASE_LIST_SIZE_MAX 256
42 #define SECTOR_MAP_SIZE_MAX 256
43
44 #define TARGET_PROGRAM_SIZE_MAX (8 * 1024)
45
46 #define READ_LIST_SIZE_MAX 40
47
48 #define RETRIES_MAX 30
49
50 // Default target receive delay in milli-seconds.
51 #define TARGET_RECV_DELAY 250
52 #define TARGET_RECV_LONG_DELAY 1000
53
54 // Default target reset delay in milli-seconds.
55 #define TARGET_RESET_DELAY 200
56
57 // CS_MODE 0: Flash at 0x04000000 @ CS5 on E-Sample
58 #define CALP_OFFSET 0x04000000
59
60 /******************************************************************************
61 * Globals
62 ******************************************************************************/
63
64 // Secure Calypso Plus
65 T_RAM_LOADER d_ram_loader;
66 T_FRAME d_frame;
67 UWORD16 d_certificate_length = 0;
68 char a_certified_cmd_file_name[] = "cmdp_cert.m0";
69
70 struct target_s {
71 uint32 cmd_load_addr;
72 uint32 method_load_addr;
73 const char type;
74 const char *name;
75 const char *prefix;
76 };
77 // Note that the ROM bootloader of Calypso rev. A devices are unable to
78 // write the bottom 128kB of internal RAM. Therefore the address have been
79 // changed from 0x804000 to 0x0820000
80 const struct target_s target[] =
81 {
82 { 0x0000000, 0x0000000, 'u', "Unknown", "oops" },
83 { 0x0000000, 0x0000000, 'u', "Unknown1", "oops1" },
84 { 0x0000000, 0x0000000, 'G', "Gemini?", "gem?" },
85 { 0x3004000, 0x3000000, 'U', "Ulysses", "uly" },
86 { 0x0820000, 0x0800000, 'C', "Calypso", "cal" },
87 { 0x0804000, 0x0800000, 'c', "Calypso Lite", "cal_l" },
88 { 0x8020000, 0x8000100, 'P', "Calypso Plus", "cal_p" }
89 };
90 int target_type;
91 int target_clk; // 13000000 or 14745600
92
93 struct device_s *device;
94
95 uint8 target_program[TARGET_PROGRAM_SIZE_MAX];
96 int target_program_size;
97 int target_fifo_size;
98
99 uint8 image[IMAGE_SIZE_MAX];
100 int image_size; // size of image buffer
101 int image_chunk_size; // number of bytes in each chunk
102 int image_size_in_chunks; // size of image buffer in chunks
103
104 // Each byte in the image_map represents one chunk of the image. Each byte
105 // can have one of the following values:
106 // '\0' = no data in this chunk
107 // 's' = skip this chunk when programming
108 // 'c' = chunk checksum ok, skip this chunk when programming
109 // 'x' = used
110 uint8 image_map[IMAGE_SIZE_MAX / IMAGE_CHUNK_SIZE];
111 int image_map_size; // number of entries in image_map
112
113 // Each byte in the sector_map represents one sector. Each byte can have one
114 // of the following values:
115 // '\0' = sector unused (don't erase)
116 // 'c' = sector already empty/erased (don't erase) (not used)
117 // 's' = skip this sector when erasing (due to erase override)
118 // 'X' = force erase this sector (due to erase override)
119 // 'x' = erase this sector (normal case --- sector is covered by image)
120 int sector_map[SECTOR_MAP_SIZE_MAX];
121 int sector_map_size;
122
123 int erase_list[ERASE_LIST_SIZE_MAX];
124 int erase_list_size;
125
126 struct image_part_s read_list[READ_LIST_SIZE_MAX];
127 int read_list_size;
128 int read_total_size;
129
130 int image_map_count_used_chunks(void);
131 int image_map_update(void);
132 int sector_map_init(void);
133
134 void image_map_show(void);
135 void sector_map_show(void);
136 void target_timers_show(void);
137
138 void parse_arg_erase_override(char *p);
139 void parse_arg_read(char *p);
140 void parse_arg_write(char *p);
141
142 void error_proto(char ch, char ch_expected);
143
144 int target_type_set(uint16 code);
145
146 // Secure Calypso Plus
147 void f_print_signalling_response(int level);
148 void f_print_certificate_platform_data(int level, T_MANUFACTURER_CERTIFICATE_PLATFORM_DATA *p_certificate);
149 void f_print_certificate(int level, T_MANUFACTURER_CERTIFICATE_FLASH_PROGRAMMER *p_certificate);
150 void f_print_parameter_nack_status(int level, UWORD8 d_parameter_nack_sts);
151 void f_print_write_nack_status(int level, UWORD8 d_write_nack_sts);
152 UWORD8 f_convert_uart_baud_rate(UWORD32 d_baud_rate);
153 void target_imei_protection(void);
154
155 /******************************************************************************
156 * Main
157 ******************************************************************************/
158
159 void bootloader_machine(void);
160 void cmd_machine(void);
161 void flash_checksum_machine(void);
162 void flash_detect_machine(void);
163 void method_download_machine(void);
164 void flash_program_machine(void);
165 void flash_read_machine(void);
166 void target_reset_machine(void);
167
168 void fluid_machine(void)
169 {
170 int error;
171
172 // If user has specifically asked fluid just to reset the target, we do
173 // that and only that! This way, we can use fluid just to reset the
174 // target without doing anything else!
175 if (arg_target_reset == 2 && arg_dry_run) {
176 flowf(VERBOSE, "Resetting target: ");
177 target_reset(0);
178 target_wait(0, TARGET_RESET_DELAY);
179 target_reset(1);
180 flowf(VERBOSE, "ok\n");
181 }
182
183 file_read_devices("devices.txt");
184
185 if (arg_list_devices) {
186 devices_list();
187 exit(0);
188 }
189
190 image_size = IMAGE_SIZE_MAX;
191 image_chunk_size = IMAGE_CHUNK_SIZE;
192 image_map_size = IMAGE_SIZE_MAX / image_chunk_size;
193 image_size_in_chunks =
194 (image_size + image_chunk_size - 1) / image_chunk_size;
195
196 // Read the flash image file(s) unless user wants to read from the flash
197 if (*arg_read == 0) {
198 file_read_image(image, IMAGE_SIZE_MAX, image_map, image_chunk_size);
199
200 // Optionally overwrite image with values given on the command-line
201 parse_arg_write(arg_write);
202
203 if (arg_image_map_show)
204 image_map_show();
205 }
206
207 if ((error = target_driver_init(arg_uart_port, 115200,
208 arg_uart_flowcontrol)) < 0)
209 main_fatal(error);
210
211 if (target_type_set(arg_target_type) != 0)
212 flowf(VERBOSE, "Target type '%s' selected.\n", target[target_type].name);
213
214 // Conditionally disable tracing
215 if (arg_debug_trace_pe)
216 tr_enable(0);
217
218 if (arg_debug_resume) {
219 // If resuming in command interpreter, we should set the baudrate
220 // because we do not pass through the code that normally sets it.
221 if ((error = target_driver_baudrate(arg_uart_baudrate)) < 0)
222 main_fatal(error);
223 }
224 else {
225 bootloader_machine();
226 cmd_machine();
227 }
228 if (*arg_read != 0) {
229 parse_arg_read(arg_read);
230 flash_read_machine();
231 file_write_image(image, image_size, read_list);
232 }
233 else {
234 if (arg_checksum)
235 flash_checksum_machine();
236 flash_detect_machine();
237 if (!arg_debug_resume) {
238 method_download_machine();
239 }
240 tr_enable(1); // Ensure full tracing is on
241 flash_program_machine();
242 if (*arg_imeisv && *arg_platform_certificate_addr)
243 target_imei_protection();
244 if (arg_timers_show)
245 target_timers_show();
246 if (arg_target_reset == 1)
247 target_reset_machine();
248 }
249 }
250
251
252 /******************************************************************************
253 * Bootloader (TI Target Monitor) Access
254 ******************************************************************************/
255
256 // Invoke the Fluid bootloader embedded in the TI bootloader/target-monitor
257 // code. The command to enter the loader is 0xAA 0x01 0xDD, which must be
258 // received by the phone within 50ms from reset.
259
260 int bootloader_is_rom;
261 int bootloader_is_secure_rom; // Secure Calypso Plus
262 int bootloader_blocksize_max;
263
264 void bootloader_fluid_init(void);
265 void bootloader_rom_init(void);
266 void bootloader_secure_rom_init(void); // Secure Calypso Plus
267
268 void bootloader_machine(void)
269 {
270 // FIXME: why do we have to send an additional char (0) ?
271 uint8 sendbuf_rom[3] = { '<', 'i', 0x0 };
272 uint8 sendbuf_fluid[3] = { 0xAA, 0x01, 0xDD };
273 int i, error;
274 char ch1, ch2;
275 // Secure Calypso Plus
276 UWORD16 d_j;
277
278 target_trace_enable(0);
279
280 flowf(NORMAL, "Bootloader: ");
281
282 // Wait a short while with power removed, then flush receive buffer.
283 target_power(1);
284 target_reset(0);
285 target_wait(0, TARGET_RESET_DELAY);
286 target_reset(1);
287 target_recv_reset();
288
289 // Continuously send Fluid Bootloader escape sequence until we get an
290 // acknowledgement. Note that we have to establish contact within 50ms
291 // from reset, otherwise we lose our chance! Note that we actually wait
292 // up to 500ms because the target may take some time to reset.
293 i = 0;
294 flowf(DEBUG, "(ROM/fluid-delay = %d/%d, ",
295 arg_boot_delay_rom, arg_boot_delay_fluid);
296
297 switch (arg_rom_bootloader) {
298 case -1:
299 if ((error = target_driver_baudrate(115200)) < 0)
300 main_fatal(error);
301 break;
302 case +1:
303 if ((error = target_driver_baudrate(19200)) < 0)
304 main_fatal(error);
305 break;
306 }
307 while (1)
308 {
309 target_recv_reset();
310
311 // If we are allowed to try fluid bootloader...
312 if (arg_rom_bootloader != +1) {
313 // If we should ONLY try fluid bootloader...
314 flowf(DEBUG, "F");
315 if (arg_rom_bootloader == 0)
316 if ((error = target_driver_baudrate(115200)) < 0)
317 main_fatal(error);
318 target_send(sendbuf_fluid, 3);
319 if (target_wait(1, arg_boot_delay_fluid) > 0 &&
320 target_getchar() == PROTO_HELLO) {
321 bootloader_is_rom = 0;
322 bootloader_is_secure_rom = 0; // Secure Calypso Plus
323 break;
324 }
325 }
326 // If we are allowed to try ROM bootloader...
327 if (arg_rom_bootloader != -1) {
328 flowf(DEBUG, "R");
329 if (arg_rom_bootloader == 0)
330 if ((error = target_driver_baudrate(19200)) < 0)
331 main_fatal(error);
332 target_send(sendbuf_rom, 3);
333
334 if (target_wait(1, arg_boot_delay_rom) >= 1) {
335 ch1 = target_getchar();
336 if (ch1 == '>') {
337 if (target_wait(1, arg_boot_delay_rom) >= 1) {
338 ch2 = target_getchar();
339 if (ch2 == 'i') {
340 bootloader_is_rom = 1;
341
342 // Secure Calypso Plus
343 if (target_wait(2, arg_boot_delay_rom) < 2)
344 flowf(DEBUG, ", Non-secure boot ROM code");
345 else {
346 flowf(DEBUG, ", Secure Calypso Plus ROM)");
347 ch1 = target_getchar();
348 ch2 = target_getchar();
349 d_ram_loader.d_romcode_version = (UWORD16)(ch1) & 0xFF;
350 d_ram_loader.d_romcode_version |= ((UWORD16)(ch2 & 0xFF)) << 8;
351 //d_ram_loader.d_romcode_version |= (((UWORD16)ch2) << 8) & 0xFF00;
352
353 if (d_ram_loader.d_romcode_version == 0x0410 || d_ram_loader.d_romcode_version == 0x0411) {
354 bootloader_is_secure_rom = 1;
355
356 if (target_wait((C_WORD32LGB * C_MD5HASHLG), TARGET_RECV_DELAY) < (C_WORD32LGB * C_MD5HASHLG))
357 main_fatal(E_RECV_TIMEOUT);
358
359 for (d_j = 0 ; d_j < (C_WORD32LGB * C_MD5HASHLG) ; d_j++)
360 d_ram_loader.a_hash_man_pub_key[d_j] = target_getchar();
361
362 if (target_wait((C_WORD32LGB * C_DIE_ID_SIZE), TARGET_RECV_DELAY) < (C_WORD32LGB * C_DIE_ID_SIZE))
363 main_fatal(E_RECV_TIMEOUT);
364
365 for (d_j = 0 ; d_j < (C_WORD32LGB * C_DIE_ID_SIZE) ; d_j++)
366 d_ram_loader.a_die_id[d_j] = target_getchar();
367
368 // SIGNALLING RESPONSE
369 f_print_signalling_response(VERBOSE);
370
371 if (*arg_die_id_file_name != 0) {
372 if ((error = file_write_die_id(&d_ram_loader.a_die_id[0], arg_die_id_file_name)) < 0) {
373 flowf(NORMAL, "\n");
374 main_fatal(error);
375 }
376
377 flowf(NORMAL, "\nDie id retrieved and written to %s.\n", arg_die_id_file_name);
378 exit(0);
379 }
380 }
381 else {
382 flowf(NORMAL, "\nSecure Calypso Plus ROM Code Version 0x%4.4x is not supported by FLUID.\n", d_ram_loader.d_romcode_version);
383 main_fatal(E_BOOTLOADER);
384 }
385 }
386 // End Secure Calypso Plus
387
388 break;
389 }
390 else
391 flowf(DEBUG, "?");
392 }
393 }
394 }
395 }
396 // If target is still not responding, we could not control the reset
397 // line, so we ask the user to reset the target
398 if (i++ == RETRIES_MAX)
399 flowf (NORMAL, "(reset target) ");
400 }
401 if (!bootloader_is_secure_rom)
402 flowf(DEBUG, ") ");
403
404 // Read the command interpreter image file.
405 if (bootloader_is_secure_rom)
406 target_program_size = file_read_cmd(target_program, TARGET_PROGRAM_SIZE_MAX, a_certified_cmd_file_name);
407 else
408 target_program_size = file_read_cmd(target_program, TARGET_PROGRAM_SIZE_MAX, "cmd.m0");
409
410 if (target_program_size == 0)
411 main_error(E_FILE_EMPTY);
412
413 if (bootloader_is_secure_rom)
414 bootloader_secure_rom_init();
415 else if (bootloader_is_rom)
416 bootloader_rom_init();
417 else
418 bootloader_fluid_init();
419
420 flowf(NORMAL, ") ok\n");
421 }
422
423 void bootloader_fluid_init(void)
424 {
425 int divider;
426 char version;
427 uint8 data[4];
428 uint16 chip_id_code;
429
430 flowf(NORMAL, "(fluid");
431
432 target_clk = 13000000;
433
434 // Now send baudrate to make the target stop sending 'H'ello.
435 divider = target_uart_baudrate_divider_get(target_clk, 115200);
436 flowf(DEBUG, ", baudrate = ");
437 target_putchar(0);
438 target_putchar((char) divider);
439 flowf(DEBUG, "%d, ", 115200);
440
441 // Wait a short while before flushing receive buffer. Then make sure
442 // that the target is indeed silent
443 target_wait(0, 10);
444 target_recv_reset();
445 if (target_wait(1, 50) > 0)
446 main_fatal(E_RECV_ANTITIMEOUT);
447
448 // NOTEME: The sequence below to query the Bootloader VERSION *has* to
449 // have 100ms + 100ms delays. It seems as unnecessarily large delays but
450 // practice shows that they cannot be shorter. To be investigated...
451
452 // Get version of bootloader
453 target_putchar(PROTO_VERSION);
454 if (target_wait(1, TARGET_RECV_DELAY) < 1)
455 main_fatal(E_RECV_TIMEOUT);
456 version = target_getchar();
457 flowf(NORMAL, ", version %c", version);
458
459 // Bootloader revision 3 and upwards supports generic query
460 if (version < '3') {
461 main_fatal(E_BOOTLOADER);
462 }
463
464 target_trace_enable(1);
465 target_putchar(PROTO_QUERY);
466 target_putchar(PROTO_QUERY_CHIP);
467 if (target_wait(4, TARGET_RECV_DELAY) < 4)
468 main_fatal(E_RECV_TIMEOUT);
469 target_recv(data, 4);
470 chip_id_code = data[0] + (data[1] << 8);
471 if (target_type_set(chip_id_code) == 0 || arg_verbose >= VERBOSE) {
472 flowf(VERBOSE, ", chipid = 0x%04X", chip_id_code);
473 if (target_type_set(chip_id_code) == 0)
474 main_fatal(E_TARGET_TYPE);
475 }
476 flowf(VERBOSE, ", %s", target[target_type].name);
477 }
478
479 void bootloader_rom_init(void)
480 {
481 int error;
482 char ch, version = '?';
483
484 // Initialization: 115200 bps, 39 MHz DPLL, no timeout
485 uint8 sendbuf[11] = { '<', 'p', 0x00, 0x0D, 0x14, 0x25,
486 0x22, 0x00, 0x00, 0x00, 0x00};
487 // Initialization: 115200 bps, 13 MHz DPLL, no timeout.
488 //uint8 sendbuf[11] = { '<', 'p', 0x00, 0x00, 0x1C, 0xE7,
489 // 0x22, 0x00, 0x00, 0x00, 0x00 };
490
491 flowf(NORMAL, "(ROM");
492
493 // Configure/init the ROM bootloader
494 flowf(VERBOSE, ", baudrate = %d", 115200);
495 target_send(sendbuf, 11);
496
497 // Wait until DPLL is settled and target responds
498 if (target_wait(4, 300) < 4)
499 main_fatal(E_RECV_TIMEOUT);
500 if ((ch = target_getchar ()) != '>')
501 error_proto(ch, '>');
502 if ((ch = target_getchar ()) != 'p')
503 error_proto(ch, 'p');
504
505 // Receive maximum blocksize
506 bootloader_blocksize_max = target_getchar();
507 bootloader_blocksize_max += target_getchar() << 8;
508 bootloader_blocksize_max -= 10; // Subtract the block header
509 flowf(DEBUG, ", blocksize = %iB", bootloader_blocksize_max);
510
511 if ((error = target_driver_baudrate (115200)) < 0)
512 main_fatal(error);
513
514 flowf(NORMAL, ", version %c", version);
515
516 // NOTEME: Can we be sure that it is always a Calypso type?
517 target_type_set('c');
518 }
519
520 // Secure Calypso Plus
521 void bootloader_secure_rom_init(void)
522 {
523 int error;
524 UWORD8 d_char;
525 UWORD16 d_j;
526
527 // cmdp_cert.m0 has been 16 bit aligned using hex470, so the memory width
528 // parameter is set to 2 bytes.
529 buffer_endian_convert(target_program, target_program_size, 2);
530
531 // Check if firmware manufacturer certificate stored in flash is requested
532 if (arg_request_certificate) {
533 // Clear the request
534 arg_request_certificate = 0;
535 d_ram_loader.b_certificate_request = C_FALSE;
536
537 // Certificate Request
538 d_frame.a_data[0] = '<';
539 d_frame.a_data[1] = 'c';
540 d_frame.d_max_byte = 2;
541
542 target_send(&d_frame.a_data[0], d_frame.d_max_byte);
543
544 // Certificate Response
545 target_expect_char('>', arg_boot_delay_rom);
546 target_expect_char('c', arg_boot_delay_rom);
547
548 if (target_wait(2, TARGET_RECV_DELAY) < 2)
549 main_fatal(E_RECV_TIMEOUT);
550
551 d_ram_loader.u_firm_cert.a_firm_cert[0] = target_getchar ();
552 d_ram_loader.u_firm_cert.a_firm_cert[1] = target_getchar ();
553
554 d_certificate_length = (UWORD16)(d_ram_loader.u_firm_cert.a_firm_cert[0]) & 0xFF;
555 d_certificate_length |= ((UWORD16)(d_ram_loader.u_firm_cert.a_firm_cert[1]) << 8) & 0xFF00;
556
557 // We have already read two bytes of the certificate for the CERT_SIZE
558 // and the certificate signature is handled later.
559 for (d_j = 2 ; d_j < d_certificate_length - (C_WORD32LGB * C_MANUF_SIG_SIZE); d_j++) {
560 if (target_wait(1, arg_boot_delay_rom * 4) > 0)
561 d_ram_loader.u_firm_cert.a_firm_cert[d_j] = target_getchar ();
562 else
563 main_fatal(E_RECV_TIMEOUT);
564 }
565
566 for (d_j = 0; d_j < (C_WORD32LGB * C_MANUF_SIG_SIZE); d_j++) {
567 if (target_wait(1, arg_boot_delay_rom * 4) > 0)
568 d_ram_loader.a_Certsig[d_j] = target_getchar ();
569 else
570 main_fatal(E_RECV_TIMEOUT);
571
572 d_ram_loader.u_firm_cert.a_firm_cert[d_j + sizeof(T_MANUFACTURER_CERTIFICATE_PLATFORM_DATA) - (C_WORD32LGB * C_MANUF_SIG_SIZE)] = d_ram_loader.a_Certsig[d_j];
573 }
574
575 f_print_certificate_platform_data(NORMAL, &d_ram_loader.u_firm_cert.d_firm_cert);
576 }
577
578 // Parameter Request
579 d_ram_loader.d_baud_rate = f_convert_uart_baud_rate(arg_uart_baudrate_during_cmd_download);
580 d_ram_loader.d_uart_timeout = arg_uart_timeout_configuration; // TODO: Verify that MSB byte is sent in first position.
581
582 d_frame.a_data[0] = '<';
583 d_frame.a_data[1] = 'p';
584 d_frame.a_data[2] = d_ram_loader.d_baud_rate;
585 memcpy(&d_frame.a_data[3], &d_ram_loader.d_uart_timeout, sizeof(UWORD32));
586
587 d_frame.d_max_byte = 3 + sizeof(UWORD32);
588
589 d_certificate_length = (UWORD16)(target_program[0]) & 0xFF;
590 d_certificate_length |= ((UWORD16)(target_program[1]) & 0xFF) << 8;
591
592 for (d_j = 0 ; d_j < d_certificate_length; d_j++)
593 d_ram_loader.u_code_certificate.a_code_certificate[d_j] = target_program[d_j];
594
595 f_print_certificate(DEBUG, &d_ram_loader.u_code_certificate.d_code_certificate);
596
597 // Send the data
598 target_send(&d_frame.a_data[0], d_frame.d_max_byte);
599 target_send(&target_program[0], d_certificate_length);
600
601 // Parameter Response
602 if (target_wait(2, TARGET_RECV_DELAY) < 2)
603 main_fatal(E_RECV_TIMEOUT);
604
605 if ((d_char = target_getchar ()) != '>')
606 error_proto(d_char, '>');
607
608 if ((d_char = target_getchar ()) != 'p') {
609 if (d_char == 'P') {
610 // PARAMETER_NACK_RESPONSE
611 if (target_wait(1, arg_boot_delay_rom) >= 1) {
612 d_ram_loader.d_param_req_sts = target_getchar();
613 f_print_parameter_nack_status(NORMAL, d_ram_loader.d_param_req_sts);
614 }
615 }
616 error_proto(d_char, 'p');
617 }
618
619 // PARAMETER_ACK_RESPONSE
620
621 flowf(NORMAL, "\n(Secure ROM");
622
623 if ((error = target_driver_baudrate (arg_uart_baudrate_during_cmd_download)) < 0)
624 main_fatal(error);
625
626 // Configure/init the ROM bootloader
627 flowf(VERBOSE, ", UART baud rate during download of flash programmer, %s = %d Kbps", a_certified_cmd_file_name, arg_uart_baudrate_during_cmd_download);
628 }
629 // End Secure Calypso Plus
630
631 /******************************************************************************
632 * Command Interpreter Download
633 ******************************************************************************/
634
635 int cmd_baudrate(int baudrate);
636 void cmd_machine_fluid(void);
637 void cmd_machine_rom(void);
638 void cmd_machine_secure_rom(void); // Secure Calypso Plus
639
640 void cmd_machine(void)
641 {
642 char ramcs0, ch;
643 uint8 count = 0;
644 uint16 chip_id;
645
646 flowf(VERBOSE, "Command Interpreter: (");
647
648 target_trace_enable(0);
649
650 // Secure Calypso Plus
651 if (bootloader_is_secure_rom)
652 cmd_machine_secure_rom();
653 else if (bootloader_is_rom)
654 cmd_machine_rom();
655 else
656 cmd_machine_fluid();
657
658 // Now send 'H'ello command to target and get the response, such as
659 // hardware type etc.
660 while (count < RETRIES_MAX) {
661 target_putchar(PROTO_HELLO);
662 if (target_wait(1, TARGET_RECV_DELAY) >= 1) {
663 ch = target_getchar();
664 flowf(DEBUG, ", received %c (0x%2.2x)", ch, ch);
665 if (ch == PROTO_READY)
666 break;
667 }
668 count++;
669 }
670
671 if (count == RETRIES_MAX)
672 main_fatal(E_RECV_TIMEOUT);
673
674 if (target_wait(5, TARGET_RECV_DELAY) < 4)
675 main_fatal(E_RECV_TIMEOUT);
676
677 chip_id = (target_getchar() & 0xFF);
678 chip_id |= (target_getchar() & 0xFF) << 8;
679 ramcs0 = (target_getchar() == 'R');
680 ch = target_getchar();
681 flowf(BLABBER, ", SRAM = %dk", (1 << ch) / 1024);
682 target_fifo_size = target_getchar();
683 flowf(DEBUG, ", fifo = %d", target_fifo_size);
684
685 if (target_type_set(chip_id) == 0 || arg_verbose >= VERBOSE) {
686 flowf(BLABBER, ", ");
687 flowf(VERBOSE, "chipid = 0x%04X", chip_id);
688 if (target_type_set(chip_id) == 0)
689 main_fatal(E_TARGET_TYPE);
690 }
691 flowf(VERBOSE, ", %s", target[target_type].name);
692
693 if (ramcs0)
694 flowf(VERBOSE, ", RAM");
695
696 // Configure target
697 target_putchar(PROTO_INIT);
698 target_putchar(target[target_type].type);
699 target_expect_char(PROTO_READY, TARGET_RECV_DELAY);
700
701 // Change baudrate. First try to change to new baudrate. If this fails,
702 // try 115.2 Kbps. If this also fails, panic and bail out.
703 if (arg_uart_baudrate != 115200) {
704 flowf(VERBOSE, ", baudrate = ");
705 flowf(VERBOSE, "%d", arg_uart_baudrate);
706 if (!cmd_baudrate(arg_uart_baudrate)) {
707 arg_uart_baudrate = 115200;
708 flowf(VERBOSE, " %d", arg_uart_baudrate);
709 if (!cmd_baudrate(arg_uart_baudrate))
710 main_fatal(E_RECV_TIMEOUT);
711 }
712 }
713 flowf(VERBOSE, ") ");
714 flowf(VERBOSE, "ok\n");
715
716 // Secure Calypso Plus
717
718 // There is a bug in ROM code 0x0410 which means that the secure boot
719 // loader cannot boot if the firmware certificate size is greater than the
720 // max size of 0xFFF8. A workaround is to change the memory mapping on CS5
721 // by initially setting DIP switches 9 and 10 to ON and thereby exchanging
722 // the mapping of RAM and flash. While waiting, set the DIP switches back
723 // to OFF. See SECURITY.txt and BUG03314 in CALPLUS228.
724 if (arg_delay_for_changing_cs5 != 0) {
725 flowf(NORMAL, "\nWaiting %d seconds for changing memory mapping on CS5 or connecting via JTAG...\n", arg_delay_for_changing_cs5);
726 target_wait(0, arg_delay_for_changing_cs5 * 1000);
727 }
728 }
729
730 int cmd_baudrate(int baudrate)
731 {
732 int error;
733 int divider;
734 char xxo;
735
736 target_putchar(PROTO_BAUDRATE);
737 if (baudrate == 230400 || baudrate == 460800 || baudrate == 921600) {
738 // Changing the target clock frequency to 14 MHz
739 target_clk = 14745600;
740 // If we are using a 14 MHz compatible baud rate, we should enable the
741 // eXternal Xtal Oscillator of the target
742 xxo = PROTO_BAUDRATE_XXO;
743 }
744 else {
745 target_clk = 13000000;
746 xxo = 0;
747 }
748
749 divider = target_uart_baudrate_divider_get(target_clk, baudrate);
750 target_putchar(xxo);
751 target_putchar((char) divider);
752
753 if ((error = target_driver_baudrate(baudrate)) < 0)
754 main_fatal(error);
755
756 // Wait for acknowledgement
757 if (target_wait(1, 2 * TARGET_RECV_DELAY) >= 1 &&
758 target_getchar() == PROTO_READY) {
759 return 1;
760 }
761 else {
762 if ((error = target_driver_baudrate(115200)) < 0)
763 main_fatal(error);
764 return 0;
765 }
766 }
767
768 void cmd_machine_fluid(void)
769 {
770 uint8 sendbuf[1+4+2];
771 int error;
772
773 // Send 'Download' command header. Then wait for acknowledgement.
774 buf_put1(&sendbuf[0], PROTO_DOWNLOAD);
775 buf_put4(&sendbuf[1], target[target_type].cmd_load_addr);
776 buf_put2(&sendbuf[1+4], (uint16) target_program_size / 2);
777 target_send(sendbuf, 1+4+2);
778 flowf(BLABBER, "0x%X", target[target_type].cmd_load_addr);
779 if ((error = target_expect_char(PROTO_READY, TARGET_RECV_DELAY)) < 0)
780 main_fatal(error);
781
782 // Send data. Then wait for acknowledgement.
783 target_trace_enable(1);
784 target_send(target_program, target_program_size);
785 flowf(BLABBER, ", %d", target_program_size);
786 }
787
788 void cmd_machine_rom(void)
789 {
790 uint8 sendbuf[10], *buf;
791 int error, i;
792 int block_addr;
793 int block_offset = 0;
794 int block_size;
795 uint8 ch, blksum, cksum = 0;
796
797 // NOTEME: Can we be sure that it is always a Calypso type?
798 target_type_set('c');
799
800 block_addr = target[target_type].cmd_load_addr;
801
802 buffer_endian_convert(target_program, target_program_size, 2);
803
804 flowf(BLABBER, "0x%X, ", target[target_type].cmd_load_addr);
805
806 // Transfer the target program as blocks
807 while (block_offset < target_program_size)
808 {
809 block_size = target_program_size - block_offset;
810 if (block_size > bootloader_blocksize_max)
811 block_size = bootloader_blocksize_max;
812
813 // Initialize block transfer
814 buf = sendbuf;
815 buf += buf_put1(buf, '<');
816 buf += buf_put1(buf, 'w');
817 buf += buf_put1(buf, 0x01); // block index - just use #1 - not important
818 buf += buf_put1(buf, 0x01); // block number - just use #1 - not important
819 buf += buf_put2no(buf, (uint16) block_size);
820 buf += buf_put4no(buf, block_addr + block_offset);
821 target_send(sendbuf, 10);
822
823 // Send the data
824 target_send(&target_program[block_offset], block_size);
825
826 // Calculate block check-sum
827 blksum = 5;
828 blksum += block_size & 0x00ff;
829 blksum += (((block_addr + block_offset) & 0xff000000) >> 24);
830 blksum += (((block_addr + block_offset) & 0x00ff0000) >> 16);
831 blksum += (((block_addr + block_offset) & 0x0000ff00) >> 8);
832 blksum += ( (block_addr + block_offset) & 0x000000ff);
833 for (i = block_offset; i < (block_offset + block_size); i++)
834 blksum += target_program[i];
835 cksum += ~blksum;
836
837 block_offset = block_offset + block_size;
838
839 if ((error = target_expect_char ('>', TARGET_RECV_DELAY)) < 0)
840 main_fatal (error);
841 if ((error = target_expect_char ('w', TARGET_RECV_DELAY)) < 0)
842 main_fatal (error);
843
844 flowf(BLABBER, ".");
845 }
846 flowf(BLABBER, ", %d", target_program_size);
847 target_wait(0, 100);
848
849 // Request compare of checksum
850 target_putchar('<');
851 target_putchar('c');
852 target_putchar((char) ~cksum);
853
854 if ((error = target_expect_char('>', TARGET_RECV_DELAY)) < 0)
855 main_fatal(error);
856 if ((error = target_expect_char('c', TARGET_RECV_DELAY)) < 0)
857 main_fatal(error);
858 if ((error = target_wait(1, TARGET_RECV_DELAY)) < 1)
859 main_fatal(error);
860 ch = target_getchar();
861 flowf(DEBUG, ", cksum = 0x%x (0x%x)", ch, cksum);
862 if (ch != cksum)
863 main_fatal(E_SEND_CHECKSUM);
864
865 // Branch to code
866 buf = sendbuf;
867 buf += buf_put1(buf, '<');
868 buf += buf_put1(buf, 'b');
869 buf += buf_put4no(buf, target[target_type].cmd_load_addr);
870 target_send(sendbuf, 6);
871
872 if (target_wait(2, TARGET_RECV_DELAY) < 2)
873 main_fatal(E_RECV_TIMEOUT);
874 if ((ch = target_getchar()) != '>')
875 error_proto(ch, '>');
876 if ((ch = target_getchar()) != 'b')
877 error_proto(ch, 'b');
878
879 target_wait(0, 100);
880 }
881
882 // Secure Calypso Plus
883 void cmd_machine_secure_rom(void)
884 {
885 UWORD8 d_char;
886 UWORD16 d_i;
887
888 target_type_set('p');
889 flowf(BLABBER, "0x%X", d_ram_loader.u_code_certificate.d_code_certificate.d_Addcode);
890 flowf(DEBUG, ")");
891
892 // Prepare the write command
893 d_ram_loader.d_nb_byte_in_block = (UWORD32) arg_block_size;
894 d_ram_loader.d_nb_byte_sent = 0;
895 d_ram_loader.d_block_address = d_ram_loader.u_code_certificate.d_code_certificate.d_Addcode;
896
897 while (d_ram_loader.d_nb_byte_sent < d_ram_loader.u_code_certificate.d_code_certificate.d_Codesize) {
898 flowf(DEBUG, "\nCurrent write parameters:\n");
899 flowf(DEBUG, " Max Number of Bytes in Block: %ld\n", d_ram_loader.d_nb_byte_in_block);
900 flowf(DEBUG, " Block Address : 0x%8.8lx\n", d_ram_loader.d_block_address);
901 flowf(DEBUG, " Code Size : %ld\n", d_ram_loader.u_code_certificate.d_code_certificate.d_Codesize);
902 flowf(DEBUG, " Bytes sent : %ld\n", d_ram_loader.d_nb_byte_sent);
903
904 // Set block size
905 d_ram_loader.d_block_size = d_ram_loader.u_code_certificate.d_code_certificate.d_Codesize - d_ram_loader.d_nb_byte_sent;
906 if (d_ram_loader.d_block_size > d_ram_loader.d_nb_byte_in_block)
907 d_ram_loader.d_block_size = d_ram_loader.d_nb_byte_in_block;
908
909 flowf(DEBUG, " Block Size : %ld\n", d_ram_loader.d_block_size);
910
911 // Write Request
912 d_frame.a_data[0] = '<';
913 d_frame.a_data[1] = 'w';
914
915 // Send block size
916 for (d_i = 0; d_i < 32; d_i += 8)
917 d_frame.a_data[2 + d_i / 8] = (UWORD8)(d_ram_loader.d_block_size >> (24 - d_i));
918
919 // Send block address
920 for (d_i = 0; d_i < 32; d_i += 8)
921 d_frame.a_data[2 + sizeof(UWORD32) + d_i / 8] = (UWORD8)(d_ram_loader.d_block_address >> (24 - d_i));
922
923 d_frame.d_max_byte = 2 + sizeof(UWORD32) + sizeof(UWORD32);
924
925 // Send the data
926 target_send(&d_frame.a_data[0], d_frame.d_max_byte);
927 target_send(&target_program[d_certificate_length + d_ram_loader.d_nb_byte_sent], d_ram_loader.d_block_size);
928
929 // Update next block address
930 d_ram_loader.d_block_address += d_ram_loader.d_block_size;
931 d_ram_loader.d_nb_byte_sent += d_ram_loader.d_block_size;
932
933 // Write Response
934 if (target_wait(2, TARGET_RECV_DELAY) < 2)
935 main_fatal(E_RECV_TIMEOUT);
936
937 if ((d_char = target_getchar ()) != '>')
938 error_proto(d_char, '>');
939
940 if ((d_char = target_getchar ()) != 'w') {
941 if (d_char == 'W') {
942 // WRITE_NACK_RESPONSE
943 if (target_wait(1, arg_boot_delay_rom) >= 1) {
944 d_ram_loader.d_write_status = target_getchar();
945 f_print_write_nack_status(NORMAL, d_ram_loader.d_write_status);
946 }
947 }
948 error_proto(d_char, 'w');
949 }
950
951 // WRITE_ACK_RESPONSE
952 } // End while
953 if (arg_verbose == BLABBER)
954 flowf(BLABBER, ", ");
955 else
956 flowf(DEBUG, "(");
957
958 flowf(BLABBER, "%d", d_ram_loader.d_nb_byte_sent);
959 target_wait(0, 100);
960
961 // Abort Request
962 d_frame.a_data[0] = '<';
963 d_frame.a_data[1] = 'a';
964 d_frame.d_max_byte = 2;
965
966 target_send(&d_frame.a_data[0], d_frame.d_max_byte);
967 target_wait(0, 100);
968 }
969
970 void f_print_signalling_response(int level) {
971 UWORD16 d_i;
972
973 flowf(level, "\nSignalling Response:\n");
974
975 flowf(level, " ROM Code Version: 0x%4.4x\n", d_ram_loader.d_romcode_version);
976
977 flowf(level, " Hash (ManPubKey): ");
978 for (d_i = 0; d_i < (C_WORD32LGB * C_MD5HASHLG); d_i++) {
979 if (d_i == (C_WORD32LGB * C_MD5HASHLG) / 2)
980 flowf(level, "\n ");
981 flowf(level, "0x%2.2x ", d_ram_loader.a_hash_man_pub_key[d_i]);
982 }
983 flowf(level, "\n");
984
985 flowf(level, " Die Id : ");
986 for (d_i = 0; d_i < (C_WORD32LGB * C_DIE_ID_SIZE); d_i++)
987 flowf(level, "0x%2.2x ", d_ram_loader.a_die_id[d_i]);
988 flowf(level, "\n");
989 } /* f_print_signalling_response() */
990
991 void f_print_certificate_platform_data(int level, T_MANUFACTURER_CERTIFICATE_PLATFORM_DATA *p_certificate) {
992 UWORD16 d_i, d_j, d_max = 4;
993
994 flowf(level, "\nFirmware Manufacturer Certificate:\n");
995 flowf(level, "----------------------------------\n");
996
997 flowf(level, " Size of Certificate: %d bytes\n", p_certificate->d_manufacturer_certificate.d_Certsize);
998 flowf(level, " Type of Certificate: 0x%2.2x\n", p_certificate->d_manufacturer_certificate.d_Certtype);
999 flowf(level, " Emulation Request : 0x%2.2x\n", p_certificate->d_manufacturer_certificate.d_Debugrequest);
1000 flowf(level, " Address of Code : 0x%8.8lx\n", p_certificate->d_manufacturer_certificate.d_Addcode);
1001 flowf(level, " Size of Code : %ld bytes\n", p_certificate->d_manufacturer_certificate.d_Codesize);
1002 flowf(level, " Entry Point Address: 0x%8.8lx\n", p_certificate->d_manufacturer_certificate.d_CodeStartAdd);
1003
1004 flowf(level, " Manufacturer Public Key:\n");
1005 flowf(level, " Public Modulus:");
1006 d_j = d_max;
1007 for (d_i = 0; d_i < (C_RSAKEYLG); d_i++) {
1008 if (d_j++ == d_max) {
1009 flowf(level, "\n ");
1010 d_j = 1;
1011 }
1012 flowf(level, "0x%8.8lx ", p_certificate->d_manufacturer_certificate.d_Manpubkey.a_Modulus[d_i]);
1013 }
1014 flowf(level, "\n");
1015 flowf(level, " Public Modulus Length:\n");
1016 flowf(level, " 0x%8.8lx\n", p_certificate->d_manufacturer_certificate.d_Manpubkey.d_ModulusLength);
1017 flowf(level, " Public Exponent:\n");
1018 flowf(level, " 0x%8.8lx\n", p_certificate->d_manufacturer_certificate.d_Manpubkey.d_Exponent);
1019
1020 flowf(level, " Originator Public Key:\n");
1021 flowf(level, " Public Modulus:");
1022 d_j = d_max;
1023 for (d_i = 0; d_i < (C_RSAKEYLG); d_i++) {
1024 if (d_j++ == d_max) {
1025 flowf(level, "\n ");
1026 d_j = 1;
1027 }
1028 flowf(level, "0x%8.8lx ", p_certificate->d_manufacturer_certificate.d_Origpubkey.a_Modulus[d_i]);
1029 }
1030 flowf(level, "\n");
1031 flowf(level, " Public Modulus Length:\n");
1032 flowf(level, " 0x%8.8lx\n", p_certificate->d_manufacturer_certificate.d_Origpubkey.d_ModulusLength);
1033 flowf(level, " Public Exponent:\n");
1034 flowf(level, " 0x%8.8lx\n", p_certificate->d_manufacturer_certificate.d_Origpubkey.d_Exponent);
1035
1036 flowf(level, " Originator Public Key Signature:");
1037 d_j = d_max;
1038 for (d_i = 0; d_i < (C_RSASIGLG); d_i++) {
1039 if (d_j++ == d_max) {
1040 flowf(level, "\n ");
1041 d_j = 1;
1042 }
1043 flowf(level, "0x%8.8lx ", p_certificate->d_manufacturer_certificate.a_Origpubkeysig[d_i]);
1044 }
1045 flowf(level, "\n");
1046
1047 flowf(level, " Software Signature:");
1048 d_j = d_max;
1049 for (d_i = 0; d_i < (C_RSASIGLG); d_i++) {
1050 if (d_j++ == d_max) {
1051 flowf(level, "\n ");
1052 d_j = 1;
1053 }
1054 flowf(level, "0x%8.8lx ", p_certificate->d_manufacturer_certificate.a_Swsig[d_i]);
1055 }
1056 flowf(level, "\n");
1057
1058 flowf(level, " Configuration Parameters:\n");
1059 flowf(level, " CONF_CS5 register: %4.4x\n",p_certificate->d_manufacturer_certificate.d_Confparam.d_conf_cs5);
1060 flowf(level, " EXWS_CS5 register: %4.4x\n",p_certificate->d_manufacturer_certificate.d_Confparam.d_exws_cs5);
1061 flowf(level, " EX_CTRL register : %4.4x\n",p_certificate->d_manufacturer_certificate.d_Confparam.d_ex_ctrl);
1062 flowf(level, " CS image request : %4.4x\n",p_certificate->d_manufacturer_certificate.d_Confparam.d_cs_img_req);
1063 flowf(level, " Flash size : %ld bytes\n",p_certificate->d_manufacturer_certificate.d_Confparam.d_flash_size);
1064 flowf(level, " Granularity : %ld words\n",p_certificate->d_manufacturer_certificate.d_Confparam.d_granularity);
1065
1066 flowf(level, " Die Id: ");
1067 for(d_i = 0; d_i < (C_DIE_ID_SIZE); d_i++) {
1068 flowf(level, "0x%8.8lx ", p_certificate->d_manufacturer_certificate.a_die_id[d_i]);
1069 }
1070 flowf(level, "\n");
1071
1072 if (p_certificate->d_manufacturer_certificate.d_Certsize > (sizeof(T_MANUFACTURER_CERTIFICATE) + (C_WORD32LGB * C_MANUF_SIG_SIZE))) {
1073 flowf(level, " Platform Data:");
1074 d_j = d_max;
1075 for(d_i = 0; d_i < (p_certificate->d_manufacturer_certificate.d_Certsize - sizeof(T_MANUFACTURER_CERTIFICATE) - (C_WORD32LGB * C_MANUF_SIG_SIZE)) / sizeof(UWORD32); d_i++) {
1076 if (d_j++ == d_max) {
1077 flowf(level, "\n ");
1078 d_j = 1;
1079 }
1080 flowf(level, "0x%8.8lx ", p_certificate->a_platform_data[d_i]);
1081 }
1082 flowf(level, "\n");
1083 }
1084
1085 flowf(level, " Certificate Signature:");
1086 d_j = d_max;
1087 for (d_i = 0; d_i < (C_MANUF_SIG_SIZE); d_i++) {
1088 if (d_j++ == d_max) {
1089 flowf(level, "\n ");
1090 d_j = 1;
1091 }
1092 flowf(level, "0x%8.8lx ", p_certificate->a_Certsig[d_i]);
1093 }
1094 flowf(level, "\n");
1095 } /* f_print_certificate_platform_data() */
1096
1097 void f_print_certificate(int level, T_MANUFACTURER_CERTIFICATE_FLASH_PROGRAMMER *p_certificate) {
1098 UWORD16 d_i, d_j, d_max = 4;
1099
1100 flowf(level, "\nFlash Programmer Manufacturer Certificate:\n");
1101 flowf(level, "------------------------------------------\n");
1102
1103 flowf(level, " Size of Certificate: %d bytes\n", p_certificate->d_Certsize);
1104 flowf(level, " Type of Certificate: 0x%2.2x\n", p_certificate->d_Certtype);
1105 flowf(level, " Emulation Request : 0x%2.2x\n", p_certificate->d_Debugrequest);
1106 flowf(level, " Address of Code : 0x%8.8lx\n", p_certificate->d_Addcode);
1107 flowf(level, " Size of Code : %ld bytes\n", p_certificate->d_Codesize);
1108 flowf(level, " Entry Point Address: 0x%8.8lx\n", p_certificate->d_CodeStartAdd);
1109
1110 flowf(level, " Manufacturer Public key:\n");
1111 flowf(level, " Public Modulus:");
1112 d_j = d_max;
1113 for (d_i = 0; d_i < (C_RSAKEYLG); d_i++) {
1114 if (d_j++ == d_max) {
1115 flowf(level, "\n ");
1116 d_j = 1;
1117 }
1118 flowf(level, "0x%8.8lx ", p_certificate->d_Manpubkey.a_Modulus[d_i]);
1119 }
1120 flowf(level, "\n");
1121 flowf(level, " Public Modulus Length:\n");
1122 flowf(level, " 0x%8.8lx\n", p_certificate->d_Manpubkey.d_ModulusLength);
1123 flowf(level, " Public Exponent:\n");
1124 flowf(level, " 0x%8.8lx\n", p_certificate->d_Manpubkey.d_Exponent);
1125
1126 flowf(level, " Originator Public key:\n");
1127 flowf(level, " Public Modulus:");
1128 d_j = d_max;
1129 for (d_i = 0; d_i < (C_RSAKEYLG); d_i++) {
1130 if (d_j++ == d_max) {
1131 flowf(level, "\n ");
1132 d_j = 1;
1133 }
1134 flowf(level, "0x%8.8lx ", p_certificate->d_Origpubkey.a_Modulus[d_i]);
1135 }
1136 flowf(level, "\n");
1137 flowf(level, " Public Modulus Length:\n");
1138 flowf(level, " 0x%8.8lx\n", p_certificate->d_Origpubkey.d_ModulusLength);
1139 flowf(level, " Public Exponent:\n");
1140 flowf(level, " 0x%8.8lx\n", p_certificate->d_Origpubkey.d_Exponent);
1141
1142 flowf(level, " Originator Public Key Signature:");
1143 d_j = d_max;
1144 for (d_i = 0; d_i < (C_RSASIGLG); d_i++) {
1145 if (d_j++ == d_max) {
1146 flowf(level, "\n ");
1147 d_j = 1;
1148 }
1149 flowf(level, "0x%8.8lx ", p_certificate->a_Origpubkeysig[d_i]);
1150 }
1151 flowf(level, "\n");
1152
1153 flowf(level, " Software Signature:");
1154 d_j = d_max;
1155 for (d_i = 0; d_i < (C_RSASIGLG); d_i++) {
1156 if (d_j++ == d_max) {
1157 flowf(level, "\n ");
1158 d_j = 1;
1159 }
1160 flowf(level, "0x%8.8lx ", p_certificate->a_Swsig[d_i]);
1161 }
1162 flowf(level, "\n");
1163
1164 flowf(level, " Configuration Parameters:\n");
1165 flowf(level, " CONF_CS5 register: %4.4x\n",p_certificate->d_Confparam.d_conf_cs5);
1166 flowf(level, " EXWS_CS5 register: %4.4x\n",p_certificate->d_Confparam.d_exws_cs5);
1167 flowf(level, " EX_CTRL register : %4.4x\n",p_certificate->d_Confparam.d_ex_ctrl);
1168 flowf(level, " CS image request : %4.4x\n",p_certificate->d_Confparam.d_cs_img_req);
1169 flowf(level, " Flash size : %ld bytes\n",p_certificate->d_Confparam.d_flash_size);
1170 flowf(level, " Granularity : %ld words\n",p_certificate->d_Confparam.d_granularity);
1171
1172 flowf(level, " Die Id: ");
1173 for(d_i = 0; d_i < (C_DIE_ID_SIZE); d_i++) {
1174 flowf(level, "0x%8.8lx ", p_certificate->a_die_id[d_i]);
1175 }
1176 flowf(level, "\n");
1177
1178 flowf(level, " Certificate Signature:");
1179 d_j = d_max;
1180 for (d_i = 0; d_i < (C_MANUF_SIG_SIZE); d_i++) {
1181 if (d_j++ == d_max) {
1182 flowf(level, "\n ");
1183 d_j = 1;
1184 }
1185 flowf(level, "0x%8.8lx ", p_certificate->a_Certsig[d_i]);
1186 }
1187 flowf(level, "\n");
1188 } /* f_print_certificate() */
1189
1190 void f_print_parameter_nack_status(int level, UWORD8 d_parameter_nack_sts) {
1191 flowf(level, "\nParameter NAck Response Status:\n");
1192 flowf(level, " 0x%2.2x", d_parameter_nack_sts);
1193
1194 switch(d_parameter_nack_sts) {
1195 case 0x01 : { flowf(level, " Incorrect baud rate\n"); break; }
1196 case 0x02 : { flowf(level, " Incorrect certificate\n"); break; }
1197 case 0x03 : { flowf(level, " Incorrect code address\n"); break; }
1198 }
1199
1200 flowf(level, "\n");
1201 } /* f_print_parameter_nack_status() */
1202
1203 void f_print_write_nack_status(int level, UWORD8 d_write_nack_sts) {
1204 flowf(level, "\nWrite NAck Response Status:\n");
1205 flowf(level, " 0x%2.2x", d_write_nack_sts);
1206
1207 switch(d_write_nack_sts) {
1208 case 0x01 : { flowf(level, " Incorrect block address\n"); break; }
1209 case 0x02 : { flowf(level, " Non-64 bytes block size\n"); break; }
1210 case 0x03 : { flowf(level, " First block is not code address\n"); break; }
1211 case 0x04 : { flowf(level, " Error in firmware signature check\n"); break; }
1212 case 0x05 : { flowf(level, " Received code size does not match the code size in certificate\n"); break; }
1213 case 0x06 : { flowf(level, " Error during block hashing\n"); break; }
1214 }
1215
1216 flowf(level, "\n");
1217 } /* f_print_write_nack_status() */
1218
1219 UWORD8 f_convert_uart_baud_rate(UWORD32 d_baud_rate) {
1220 UWORD8 d_converted_baud_rate;
1221
1222 switch (d_baud_rate) {
1223 case 0:
1224 case 812:
1225 case 812500: {
1226 d_converted_baud_rate = 0x00;
1227 arg_uart_baudrate_during_cmd_download = 812500;
1228 break;
1229 }
1230 case 1:
1231 case 406:
1232 case 406250: {
1233 d_converted_baud_rate = 0x01;
1234 arg_uart_baudrate_during_cmd_download = 406250;
1235 break;
1236 }
1237 case 2:
1238 case 203:
1239 case 203125: {
1240 d_converted_baud_rate = 0x02;
1241 arg_uart_baudrate_during_cmd_download = 203125;
1242 break;
1243 }
1244 case 3:
1245 case 115:
1246 case 115200: {
1247 d_converted_baud_rate = 0x03;
1248 arg_uart_baudrate_during_cmd_download = 115200;
1249 break;
1250 }
1251 case 4:
1252 case 57:
1253 case 57600: {
1254 d_converted_baud_rate = 0x04;
1255 arg_uart_baudrate_during_cmd_download = 57600;
1256 break;
1257 }
1258 case 5:
1259 case 38:
1260 case 38400: {
1261 d_converted_baud_rate = 0x05;
1262 arg_uart_baudrate_during_cmd_download = 38400;
1263 break;
1264 }
1265 case 6:
1266 case 28:
1267 case 28800: {
1268 d_converted_baud_rate = 0x06;
1269 arg_uart_baudrate_during_cmd_download = 28800;
1270 break;
1271 }
1272 case 7:
1273 case 19:
1274 case 19200: {
1275 d_converted_baud_rate = 0x07;
1276 arg_uart_baudrate_during_cmd_download = 19200;
1277 break;
1278 }
1279 default: {
1280 d_converted_baud_rate = 0x03;
1281 arg_uart_baudrate_during_cmd_download = 115200;
1282 break;
1283 }
1284 }
1285
1286 return d_converted_baud_rate;
1287 } /* f_convert_uart_baud_rate() */
1288
1289 void target_imei_protection(void)
1290 {
1291 uint8 a_imeisv[C_IMEISV_BYTES];
1292 uint8 a_platform_cert_addr[C_PLATFORM_CERT_ADDR_BYTES];
1293 uint8 d_i, d_digit, d_temp;
1294 uint8 d_error;
1295
1296 flowf(NORMAL, "\nIMEI protection: ");
1297
1298 if (arg_dry_run) {
1299 flowf(NORMAL, "(dry-run) ok\n");
1300 return;
1301 }
1302
1303 target_putchar(PROTO_IMEI_PROTECT);
1304
1305 // Send IMEI-SV
1306 for (d_i = 0; d_i < C_IMEISV_DIGITS; d_i++) {
1307 sscanf(arg_imeisv++, "%1d", &d_digit);
1308 if (!(d_i & 1))
1309 d_temp = d_digit << 4;
1310 else {
1311 d_temp |= d_digit;
1312 a_imeisv[d_i / 2] = d_temp;
1313 }
1314 }
1315
1316 target_send(a_imeisv, C_IMEISV_BYTES);
1317 target_expect_char(PROTO_READY, TARGET_RECV_DELAY);
1318
1319 // Send platform certificate address
1320 for (d_i = 0; d_i < C_PLATFORM_CERT_ADDR_DIGITS; d_i++) {
1321 sscanf(arg_platform_certificate_addr++, "%1x", &d_digit);
1322 if (!(d_i & 1))
1323 d_temp = d_digit << 4;
1324 else {
1325 d_temp |= d_digit;
1326 a_platform_cert_addr[d_i / 2] = d_temp;
1327 }
1328 }
1329
1330 target_send(a_platform_cert_addr, C_PLATFORM_CERT_ADDR_BYTES);
1331 target_expect_char(PROTO_READY, TARGET_RECV_DELAY);
1332
1333 // Check if address range is erased
1334 if (target_wait(1, TARGET_RECV_DELAY) < 1)
1335 main_fatal(E_RECV_TIMEOUT);
1336
1337 d_error = target_getchar();
1338 if (d_error == PROTO_ERROR_VERIFY) {
1339 flowf(NORMAL, "\n The address range for platform certificate and IMEI-SV is not erased.\n");
1340 main_fatal(E_FLASH_VERIFY);
1341 }
1342
1343 if (d_error != PROTO_READY)
1344 error_proto(d_error, PROTO_READY);
1345
1346 // Verify that the binding service call in target has succeeded
1347 if (target_wait(1, TARGET_RECV_DELAY) < 1)
1348 main_fatal(E_RECV_TIMEOUT);
1349
1350 d_error = target_getchar();
1351 if (d_error == PROTO_ERROR_ROM_SSERVICE) {
1352 flowf(NORMAL, "\n The Run-Time Loader (Binding) Service failed.\n");
1353 main_fatal(E_ROM_SSERVICE);
1354 }
1355
1356 if (d_error != PROTO_FLASH_START)
1357 error_proto(d_error, PROTO_FLASH_START);
1358
1359 // Receive acknowledgement for programming the platform certificate
1360 if (target_wait(1, TARGET_RECV_DELAY) < 1)
1361 main_fatal(E_RECV_TIMEOUT);
1362
1363 d_error = target_getchar();
1364 if (d_error != PROTO_PROGRAM) {
1365 flowf(NORMAL, "\n Platform certificate was not stored correctly in flash.\n");
1366 error_proto(d_error, PROTO_PROGRAM);
1367 }
1368
1369 // Receive acknowledgement for programming the IMEI-SV
1370 if (target_wait(1, TARGET_RECV_DELAY) < 1)
1371 main_fatal(E_RECV_TIMEOUT);
1372
1373 d_error = target_getchar();
1374 if (d_error != PROTO_PROGRAM) {
1375 flowf(NORMAL, "\n IMEI-SV was not stored correctly in flash.\n");
1376 error_proto(d_error, PROTO_PROGRAM);
1377 }
1378
1379 flowf(NORMAL, "Platform certificate and IMEI-SV stored in flash.\n");
1380 }
1381
1382 // End Secure Calypso Plus
1383
1384 /******************************************************************************
1385 * Flash Detect
1386 ******************************************************************************/
1387
1388 void flash_detect_machine(void)
1389 {
1390 uint8 data[12];
1391 uint16 m0, d0, m1, d1, d1ex1, d1ex2;
1392
1393 flowf(NORMAL, "Flash Detect: ");
1394 target_trace_enable(0);
1395
1396 if (arg_device_id0 != -1 || arg_device_id1 != -1) {
1397 // Device auto-detection is disabled
1398 m0 = m1 = arg_device_id0;
1399 d0 = d1 = arg_device_id1;
1400 flowf(VERBOSE, "(ID override) ");
1401 }
1402 else {
1403 target_putchar(PROTO_DETECT);
1404 if (target_wait(12, TARGET_RECV_DELAY) < 12)
1405 main_fatal(E_RECV_TIMEOUT);
1406
1407 target_recv(data, 12);
1408 m0 = data[0] + (data[1] << 8); // Intel manufacturer id
1409 d0 = data[2] + (data[3] << 8); // Intel device id
1410 m1 = data[4] + (data[5] << 8); // AMD manufacturer id
1411 d1 = data[6] + (data[7] << 8); // AMD device di
1412 d1ex1 = data[8] + (data[9] << 8); // AMD extended device id
1413 d1ex2 = data[10] + (data[11] << 8); // AMD extended device id
1414 }
1415
1416 // Lookup multi-id device
1417 if ((m1 == MANUFACT_AMD || m1 == MANUFACT_FUJITSU) && d1 == 0x227E) {
1418 flowf(NORMAL, "Multi-id device detected: (0x%04X, 0x%04X, 0x%04X)\n"
1419 , d1, d1ex1, d1ex2);
1420 d1 = (d1ex1 << 8) | (d1ex2 & 0xFF);
1421 flowf(DEBUG, "Multi-id converted to: 0x%04X\n", d1);
1422
1423 if ((device = device_lookup_by_id(m1, d1)) == NULL) {
1424 flowf(NORMAL, "Id not found, lookup default multi-id conf.\n");
1425 // Backward compatible/keep default multi-id configuration
1426 device = device_lookup_by_id(m1, 0x227E);
1427 }
1428 }
1429
1430 // Lookup device with AMD and Intel ids
1431 else if ((device = device_lookup_by_id(m1, d1)) == NULL)
1432 device = device_lookup_by_id(m0, d0);
1433
1434 if (device == NULL || arg_verbose >= DEBUG) {
1435 flowf(NORMAL, "(0x%02X, 0x%04X, 0x%02X, 0x%04X) ", m0, d0, m1, d1);
1436 if (device == NULL)
1437 main_fatal(E_FLASH_UNKNOWN);
1438 }
1439
1440 if (arg_verbose >= NORMAL) {
1441 device_print(device, 's');
1442 flowf(NORMAL, " ok\n");
1443 }
1444
1445 // Note that device_id is only 0x227E if the Multi-id configuration not
1446 // is found in device.txt (else device_id will be the 'converted' id)
1447 if (arg_device_id0 == -1 && arg_device_id1 == -1 &&
1448 (device->manufacturer_id == MANUFACT_FUJITSU ||
1449 device->manufacturer_id == MANUFACT_AMD )
1450 && device->device_id == 0x227E) {
1451 flowf(NORMAL, "Warning: Extended device codes are supported when detecting flash devices,\n");
1452 flowf(NORMAL, " but the detected multi-id configuration is not found in device.txt. \n");
1453 flowf(NORMAL, " Update the device.txt manually if the default flash device is invalid.\n");
1454 flowf(NORMAL, " Currently, %s %s is used as default.\n\n",
1455 manufacturer_name_lookup_by_id(device->manufacturer_id), device->name);
1456 }
1457 }
1458
1459
1460 /******************************************************************************
1461 * Method Load
1462 ******************************************************************************/
1463
1464 void method_download_machine(void)
1465 {
1466 char sendbuf[1+2+4];
1467 int error;
1468
1469 target_program_size = file_read_method(target_program,
1470 TARGET_PROGRAM_SIZE_MAX,
1471 device);
1472
1473 flowf(BLABBER, "Method Download: ");
1474 target_trace_enable(0);
1475
1476 // Send 'Download' command header. Then wait for acknowledgement.
1477 buf_put1(&sendbuf[0], PROTO_DOWNLOAD);
1478 buf_put4(&sendbuf[1], target[target_type].method_load_addr);
1479 buf_put2(&sendbuf[1+4], (uint16) target_program_size / 2);
1480 target_send(sendbuf, 1+4+2);
1481 flowf(BLABBER, "(0x%X", target[target_type].method_load_addr);
1482 if ((error = target_expect_char(PROTO_READY, TARGET_RECV_DELAY)) < 0)
1483 main_fatal(error);
1484
1485 // Send data. Then wait for acknowledgement.
1486 target_trace_enable(1);
1487 target_send(target_program, target_program_size);
1488 flowf(BLABBER, ", %d) ", target_program_size);
1489 if ((error = target_expect_char(PROTO_READY, TARGET_RECV_DELAY)) < 0)
1490 main_fatal(error);
1491
1492 flowf(BLABBER, "ok\n");
1493 }
1494
1495
1496 /******************************************************************************
1497 * Flash Checksum
1498 ******************************************************************************/
1499
1500 int time_checksum;
1501
1502 #define CHECKSUMS 8
1503
1504 void flash_checksum_machine(void)
1505 {
1506 unsigned char sendbuf[1+1+4+4*CHECKSUMS], *buf;
1507 uint32 addr, cksum, mycksum;
1508 uint16 word;
1509 uint8 data[4];
1510 int index = 0, chunks, n, i, j;
1511 int line = -1;
1512 struct {
1513 uint32 index;
1514 uint32 addr;
1515 uint32 mycksum;
1516 } block[CHECKSUMS];
1517
1518 chunks = image_map_count_used_chunks();
1519 flowf(NORMAL, "Checksumming (%d * %dkB = %dkB): ",
1520 chunks, image_chunk_size / 1024,
1521 chunks * image_chunk_size / 1024);
1522 target_trace_enable(0);
1523
1524 time_checksum = stopwatch_start();
1525 while (chunks > 0)
1526 {
1527 n = (chunks > CHECKSUMS ? CHECKSUMS : chunks);
1528
1529 buf = sendbuf;
1530 buf += buf_put1(buf, PROTO_CHECKSUM);
1531 buf += buf_put1(buf, (unsigned char) n);
1532 buf += buf_put4(buf, image_chunk_size);
1533
1534 for (i = 0; i < n; i++) {
1535 // Find next used entry in image_map
1536 while (image_map[index] != 'x' && index < image_map_size)
1537 index++;
1538
1539 if (index == image_map_size)
1540 break;
1541
1542 addr = index * image_chunk_size;
1543 block[i].index = index;
1544 block[i].addr = addr;
1545
1546 buf += buf_put4(buf, addr);
1547
1548 index++;
1549 }
1550 target_send(sendbuf, buf - sendbuf);
1551
1552 // Compute checksums while we wait for reply
1553 for (i = 0; i < n; i++) {
1554 index = block[i].index;
1555 addr = block[i].addr;
1556 for (j = 0, mycksum = 0; j < image_chunk_size; j += 2) {
1557 word = (image[addr + j + 1] << 8) | image[addr + j + 0];
1558 mycksum += word * ((addr + j) & 0xFFFF);
1559 }
1560 block[i].mycksum = mycksum;
1561 }
1562
1563 if (target_wait(4 * n, TARGET_RECV_LONG_DELAY) <= 0)
1564 main_fatal(E_RECV_TIMEOUT);
1565
1566 for (i = 0; i < n; i++) {
1567 target_recv(data, 4);
1568 cksum = data[0] + (data[1] << 8) + (data[2] << 16) + (data[3] << 24);
1569 mycksum = block[i].mycksum;
1570 index = block[i].index;
1571
1572 if (cksum == mycksum)
1573 image_map[index] = 'c';
1574
1575 if (arg_checksum_show) {
1576 // This is a far from perfect dump of checksums... We don't know
1577 // the exact block number of each checksum in a line.
1578 if (line != (int) index / 4) {
1579 flowf(NORMAL, "\n%4d:", index);
1580 line = index / 4;
1581 }
1582 if (cksum == mycksum)
1583 flowf(NORMAL, "%08X ", cksum);
1584 else
1585 flowf(NORMAL, "%08X/%08X ", cksum, mycksum);
1586
1587 }
1588 else if (arg_verbose >= VERBOSE) {
1589 flowf(VERBOSE, "%c", (image_map[index] == 'c' ? 'c' : '.'));
1590 }
1591 }
1592 index++;
1593 chunks -= n;
1594 }
1595 time_checksum = (stopwatch_stop(time_checksum) + 50) / 100;
1596 flowf(BLABBER, " (%d.%ds)", time_checksum / 10, time_checksum % 10);
1597 flowf(NORMAL, " ok\n");
1598 }
1599
1600
1601 /******************************************************************************
1602 * Flash Program
1603 ******************************************************************************/
1604
1605 int time_program;
1606 int programs_recv, programs_send, erasures;
1607 int index, src_size;
1608 uint32 dst;
1609 char *src;
1610
1611 void flash_erase_machine(void);
1612 int flash_operation_wait(int delay);
1613 int flash_program_next(void);
1614
1615 void flash_program_machine(void)
1616 {
1617 uint8 cksum, sendbuf[1+4+4];
1618 int i, te, tp, tt;
1619 int expected, chunks, total_size, sectors;
1620 int image_chunk_size_old = image_chunk_size;
1621 char ch;
1622
1623 programs_recv = programs_send = erasures = 0;
1624 index = 0;
1625
1626 // Prepare erase
1627 erase_list_size = sectors = sector_map_init();
1628 i = image_map_count_used_chunks();
1629
1630 if (arg_skip_erase)
1631 erase_list_size = 0;
1632
1633 time_compute(device, erase_list_size,
1634 i * image_chunk_size, i, &te, &tp, &tt);
1635
1636 flowf(BLABBER, "Estimated time (uncompressed) ");
1637 if (te + tp > tt)
1638 flowf(BLABBER, "(erase + program = total): %ds + %ds = %ds\n",
1639 te/1000, tp/1000, te/1000 + tp/1000);
1640 else
1641 flowf(BLABBER, "transfer: %ds\n", tt/1000);
1642
1643 chunks = image_map_count_used_chunks();
1644 flowf(NORMAL, "Program: (%d sectors, %d*%dk=%dk) ",
1645 sectors,
1646 chunks, image_chunk_size / 1024,
1647 chunks * image_chunk_size / 1024);
1648 target_trace_enable(1);
1649
1650 // Expected total number of acknowledgements
1651 expected = erase_list_size + chunks;
1652
1653 if (arg_dry_run) {
1654 flowf(NORMAL, "(dry-run) ");
1655 if (arg_dry_run == 2)
1656 image_chunk_size = 0;
1657 }
1658
1659 if (arg_skip_erase)
1660 flowf(NORMAL, "(skip erase) ");
1661
1662 // Start erase
1663 flash_erase_machine();
1664
1665 if (arg_dry_run == 0 || arg_dry_run == 2)
1666 progress_begin(expected);
1667
1668 // Start the flash state machine in the target
1669 target_putchar(PROTO_FLASH_START);
1670 target_putchar(arg_compress ? PROTO_COMPRESS : 0);
1671 ch = flash_operation_wait(TARGET_RECV_DELAY);
1672 if (ch != PROTO_READY)
1673 error_proto(ch, PROTO_READY);
1674 if (arg_compress) {
1675 compress_init();
1676 total_size = 0;
1677 // Worst case "compressed" buffer is 9/8 of original data size.
1678 if ((src = malloc(9 * image_chunk_size / 8)) == NULL)
1679 main_fatal(E_MEMORY);
1680 }
1681
1682 time_program = stopwatch_start();
1683
1684 if (flash_program_next() && *arg_erase_override == 0) {
1685 //Nothing to program
1686 target_putchar(PROTO_FLASH_END);
1687 if ((ch = target_expect_char(PROTO_FLASH_END, TARGET_RECV_DELAY)) < 0)
1688 main_fatal(ch);
1689 }
1690 else {
1691 while (programs_recv + erasures < expected) {
1692 total_size += src_size;
1693
1694 if (arg_progress == 'x')
1695 flowf(NORMAL, "(0x%06X, %d) ", dst, src_size);
1696
1697 if (src_size > 0 &&
1698 (arg_dry_run == 0 || arg_dry_run == 2))
1699 {
1700 buf_put1(&sendbuf[0], PROTO_PROGRAM);
1701 buf_put4(&sendbuf[1], src_size);
1702 buf_put4(&sendbuf[1+4], dst);
1703 target_send(sendbuf, 1+4+4);
1704
1705 for (i = 0, cksum = 0; i < src_size; i++)
1706 cksum += src[i];
1707 cksum = (0x100 - cksum) & 0xFF;
1708
1709 // Wait for acknowledgement of command start
1710 //while ((ch = flash_operation_wait(4000)) != PROTO_READY)
1711 // ;
1712
1713 // Make sure that the target FIFO not is full
1714 while (programs_send - programs_recv >= target_fifo_size)
1715 flash_operation_wait(4000);
1716
1717 // Send data bytes and checksum.
1718 target_send(src, src_size);
1719 target_putchar(cksum);
1720 programs_send++;
1721
1722 if (arg_verbose >= DEBUG)
1723 progress_update_simple('T');
1724 }
1725
1726 // We compress and send next block while sending
1727 // current block to target
1728 if (arg_dry_run == 0 || arg_dry_run == 2) {
1729 if (flash_program_next()) {
1730 // Wait for remaining acknowledgements
1731 flowf(DEBUG, "W%d", expected - (programs_recv + erasures));
1732 while (programs_recv + erasures < expected)
1733 flash_operation_wait(4000);
1734 target_putchar(PROTO_FLASH_END);
1735 if ((ch = target_expect_char(PROTO_FLASH_END, TARGET_RECV_DELAY)) < 0)
1736 main_fatal(ch);
1737 break;
1738 }
1739 else {
1740 // Wait for acknowledgement of data transfer
1741 while ((ch = flash_operation_wait(4000)) != PROTO_READY)
1742 ;
1743 }
1744 }
1745 else {
1746 if (flash_program_next())
1747 break;
1748 }
1749 }
1750 }
1751
1752 if (arg_dry_run == 0 || arg_dry_run == 2)
1753 progress_end(programs_recv + erasures);
1754 flowf(NORMAL, "ok\n");
1755
1756 time_program = stopwatch_stop(time_program);
1757 flowf(VERBOSE, "Used time: ");
1758 if (arg_compress && chunks) {
1759 image_chunk_size = image_chunk_size_old;
1760 flowf(VERBOSE, "(compressed to %d%%) ",
1761 100 * total_size / (chunks * image_chunk_size));
1762 }
1763 flowf(VERBOSE, "%.1fs ok\n", (double) time_program / 1000);
1764 }
1765
1766
1767 /******************************************************************************
1768 * Flash Program sub functions
1769 ******************************************************************************/
1770
1771 void flash_erase_machine(void)
1772 {
1773 uint8 sendbuf[1+2+4*256]; // NOTEME: static limit!
1774 int i;
1775 char ch;
1776
1777 if (arg_dry_run)
1778 erase_list_size = 0;
1779
1780 if (erase_list_size > 0) {
1781 buf_put1(&sendbuf[0], PROTO_ERASE);
1782 buf_put2(&sendbuf[1], (uint16) erase_list_size);
1783 for (i = 0; i < erase_list_size; i++)
1784 buf_put4(&sendbuf[1+2+4*i], erase_list[i]);
1785 target_send(sendbuf, 1+2+4*erase_list_size);
1786
1787 if ((ch = target_expect_char(PROTO_READY, TARGET_RECV_DELAY)) < 0)
1788 main_fatal(ch);
1789 }
1790 }
1791
1792 // Setup address and size of next block to transfer. Also compress the
1793 // block. Return non-zero if this was the last block. Otherwise return zero.
1794 int flash_program_next(void)
1795 {
1796 int oldindex;
1797
1798 // Find next used entry in image_map
1799 while (index < image_map_size && image_map[index] != 'x')
1800 index++;
1801
1802 oldindex = index;
1803
1804 if (index < image_map_size) {
1805 dst = index * image_chunk_size;
1806 if (arg_compress) {
1807 src_size = compress(src, &image[dst], image_chunk_size);
1808 }
1809 else {
1810 src = &image[dst];
1811 src_size = image_chunk_size;
1812 }
1813 index++;
1814 }
1815 else {
1816 dst = 0xFFFFFFFF;
1817 src_size = 0;
1818 }
1819
1820 return (oldindex >= image_map_size);
1821 }
1822
1823 int flash_operation_wait(int delay)
1824 {
1825 int n;
1826 char ch;
1827
1828 tr(TrMachines, "fow() ");
1829
1830 if ((n = target_wait(1, delay)) < 1)
1831 main_fatal(E_RECV_TIMEOUT);
1832
1833 // Minor optimization to avoid waiting for every char...
1834 while (n--) {
1835 ch = target_getchar();
1836
1837 if (ch == PROTO_READY) {
1838 if (arg_verbose >= DEBUG)
1839 progress_update_simple('R');
1840 if (programs_send - programs_recv >= target_fifo_size)
1841 progress_update_simple('W'); // Wait target FIFO is full
1842 break;
1843 }
1844
1845 switch (ch) {
1846 case PROTO_READY:
1847 break; // just return the char
1848 case PROTO_PROGRAM:
1849 programs_recv++;
1850 progress_update_simple('P');
1851 progress_update(programs_recv + erasures);
1852 break; // just return the char
1853 case PROTO_ERASE:
1854 erasures++;
1855 progress_update_simple('E');
1856 progress_update(programs_recv + erasures);
1857 if (arg_progress == 'x')
1858 flowf(NORMAL, "E ");
1859 break; // just return the char
1860 case PROTO_FLASH_END:
1861 progress_update_simple('Z');
1862 break;
1863 case PROTO_ERROR_CKSUM:
1864 main_fatal(E_SEND_CHECKSUM);
1865 case PROTO_ERROR_MEMORY:
1866 main_fatal(E_MEMORY);
1867 case PROTO_ERROR_VERIFY:
1868 main_fatal(E_FLASH_VERIFY);
1869 case PROTO_ERROR_FLASH_TIMEOUT:
1870 main_fatal(E_FLASH_TIMEOUT);
1871 case PROTO_ERROR_FLASH_COMMAND:
1872 main_fatal(E_FLASH_COMMAND);
1873 case PROTO_ERROR_FLASH_VPP:
1874 main_fatal(E_FLASH_VPPRANGE);
1875 case PROTO_ERROR_FLASH_LOCKED:
1876 main_fatal(E_FLASH_LOCKED);
1877 case PROTO_ERROR_FLASH_UNKNOWN:
1878 main_fatal(E_FLASH_ERROR);
1879 case PROTO_ERROR_INVALID:
1880 main_fatal(E_INVALID);
1881 case PROTO_ERROR_FIFO_OVERFLOW:
1882 main_fatal(E_FIFO_OVERFLOW);
1883 case PROTO_ERROR:
1884 default:
1885 flowf(NORMAL, "flash_operation_wait() got unexpected char '%c' 0x%02X (%d chars waiting)\n", (' ' <= ch && ch < 127 ? ch : '.'), ch, n);
1886 // main_fatal(E_PROTO_ERROR);
1887 }
1888 }
1889
1890 return ch;
1891 }
1892
1893 void target_timers_show(void)
1894 {
1895 int data[8], i;
1896 struct {
1897 double erase;
1898 double program;
1899 double recvonly;
1900 double recv;
1901 double comm;
1902 double setup;
1903 double overhead;
1904 double dezip;
1905 double erase_sector;
1906 double program_word;
1907 } timer;
1908 double tmp, total, resolution = (double) (16 * 32 * 1000 / 13e6);
1909
1910 // Use only 14 MHz for D-/E-Sample specific rates (not for e.g. 812.5K).
1911 if ((arg_uart_baudrate == 230400) || (arg_uart_baudrate == 460800) || (arg_uart_baudrate == 921600))
1912 resolution = resolution * 13 / 14.746;
1913
1914 flowf(NORMAL,
1915 "Target Timers:\n"
1916 " (erase + program + recvonly + recv + comm + setup + overhead + dezip)\n");
1917
1918 if (arg_dry_run)
1919 for (i = 0; i < 8; i++) data[i] = 0;
1920 else {
1921 target_putchar(PROTO_TIMERS);
1922 if (target_wait(sizeof(data), TARGET_RECV_DELAY) <= 0)
1923 main_fatal(E_RECV_TIMEOUT);
1924 target_recv(&data, sizeof(data));
1925 }
1926
1927 // Convert all timers to milliseconds
1928 timer.erase = resolution * data[0];
1929 timer.program = resolution * data[1];
1930 timer.recvonly = resolution * data[2];
1931 timer.recv = resolution * data[3];
1932 timer.comm = resolution * data[4];
1933 timer.setup = resolution * data[5];
1934 timer.overhead = resolution * data[6];
1935 timer.dezip = resolution * data[7];
1936
1937 // Because we do erase-while-transfer in the target the reported erase
1938 // time has some inherent tolerance, especially at low baudrates. It
1939 // might make sense to adjust the sector erase time by half the chunk
1940 // transfer time, although this is just another approximation!?
1941
1942 // total = timer.erase + timer.program + timer.recvonly + timer.recv + timer.comm + timer.setup;
1943 flowf(NORMAL, "%8.0f + %7.0f + %8.0f + %6.0f + %5.0f + %5.0f + %8.0f + %5.0f\n",
1944 timer.erase, timer.program, timer.recvonly, timer.recv,
1945 timer.comm, timer.setup, timer.overhead, timer.dezip);
1946
1947 flowf(DEBUG, "resolution = %f, %d, %d, %d, %d, %d, %d, %d, %d\n",
1948 resolution, data[0], data[1], data[2], data[3], data[4],
1949 data[5], data[6], data[7]);
1950
1951 if (arg_timers_extended_show) {
1952 int chunks, size_total, not_zero = 1;
1953 flowf(NORMAL, "Target Timers Extended:\n");
1954
1955 if (erase_list_size == 0 || arg_dry_run)
1956 flowf(NORMAL, " Erase time = 0.0ms/sector\n");
1957 else {
1958 timer.erase_sector = timer.erase / erase_list_size / 1000;
1959 flowf(NORMAL, " Erase time = %.1fs / %d sectors = %.0fms/sector\n",
1960 timer.erase / 1000, erase_list_size, timer.erase_sector * 1000);
1961 }
1962
1963 chunks = image_map_count_used_chunks();
1964 size_total = chunks * image_chunk_size;
1965 if (size_total == 0 || arg_dry_run) {
1966 size_total = 1;
1967 not_zero = 0;
1968 flowf(NORMAL, " Program time = 0.0us/word = 0ms/MB\n");
1969 }
1970 else {
1971 timer.program_word = timer.program / 1000 / (size_total / 2);
1972 flowf(NORMAL, " Program time = %.1fs / %dkwords = %.2fus/word = %.0fms/MB\n",
1973 timer.program / 1000, size_total / 1024 / 2,
1974 timer.program_word * 1000000,
1975 timer.program_word * 1000 * 512 * 1024);
1976 }
1977
1978 flowf(NORMAL, " Receive-only time = %.1fs = %.0fms/MB\n",
1979 timer.recvonly / 1000,
1980 not_zero * timer.recvonly * 1024 * 1024 / size_total);
1981
1982 flowf(NORMAL, " Overhead time = %.1fs = %.0fms/MB\n",
1983 timer.overhead / 1000,
1984 not_zero * timer.overhead * 1024 * 1024 / size_total);
1985
1986 flowf(NORMAL, " Setup time = %.1fs = %.0fms/MB\n",
1987 timer.setup / 1000,
1988 not_zero * timer.setup * 1024 * 1024 / size_total);
1989
1990 total = timer.erase + timer.program + timer.recvonly + timer.overhead +
1991 timer.setup;
1992 flowf(NORMAL,
1993 "Total time: (erase + prog + recvonly + overhead + setup) = %.1fs\n",
1994 total / 1000);
1995
1996 flowf(NORMAL, " Receive time = %.1fs = %.0fms/MB\n",
1997 timer.recv / 1000, timer.recv * 1024 * 1024 / size_total);
1998
1999 flowf(NORMAL, " Communication time = %.1fs = %.0fms/MB\n",
2000 timer.comm / 1000, timer.comm * 1024 * 1024 / size_total);
2001
2002 flowf(NORMAL, " Dezip time = %.1fs = %.0fms/MB\n",
2003 timer.dezip / 1000, timer.dezip * 1024 * 1024 / size_total);
2004
2005 // Now compute the overall performance. Note that the theoretical
2006 // limit compuation is somewhat flawed in that it assumes 64kB
2007 // sector sizes.
2008
2009 tmp = (double) not_zero * total / 1000 * 1024 * 1024 / size_total;
2010 flowf(NORMAL, " Performance = %.0fs/MB\n", tmp);
2011 #if 0
2012 flowf(BLABBER, " (%.1f * min possible, %.1f * theoretical limit)",
2013 time_program / (timer.program + timer.erase),
2014 tmp / (16 * timer.erase_sector + 512 * 1024 * timer.program_word));
2015 flowf(NORMAL, "\n");
2016 #endif
2017 }
2018 }
2019
2020
2021 /******************************************************************************
2022 * Flash Read
2023 ******************************************************************************/
2024
2025 int time_read;
2026
2027 void flash_read_machine(void)
2028 {
2029 int i;
2030 unsigned char sendbuf[1+4+4];
2031 int size, read_size, done_size = 0;
2032 int read_size_max = image_chunk_size;
2033 uint32 addr, index = 0;
2034 uint8 cksum, mycksum;
2035
2036 flowf(NORMAL, "Reading Flash: (%dkB) ", read_total_size / 1024);
2037 target_trace_enable(0);
2038
2039 //read_size_max = 256;
2040 time_read = stopwatch_start();
2041 progress_begin(read_total_size / read_size_max);
2042
2043 while (read_list[index].size > 0)
2044 {
2045 // Find next range to read
2046 size = read_list[index].size;
2047 addr = read_list[index].addr;
2048 index++;
2049
2050 while (size > 0)
2051 {
2052 read_size = (size > read_size_max ? read_size_max : size);
2053
2054 // Read address interval is [MIN..MAX[
2055 // If odd MAX address was specified round up to next even
2056 if ((read_size % 2 == 1) && (read_size < read_size_max)) read_size++;
2057
2058 if (arg_progress == 'x')
2059 flowf(DEBUG, "(0x%06X, %d) ", addr, read_size);
2060
2061 if (!arg_dry_run)
2062 {
2063 buf_put1(&sendbuf[0], PROTO_READ);
2064 buf_put4(&sendbuf[1] , read_size);
2065 buf_put4(&sendbuf[1+4], addr);
2066 target_send(sendbuf, 1+4+4);
2067
2068 if (target_wait(read_size, TARGET_RECV_LONG_DELAY) <= 0)
2069 main_fatal(E_RECV_TIMEOUT);
2070 // Note that we wrap/mirror memory each 'image_size' bytes
2071 target_recv(&image[addr & (image_size - 1)], read_size);
2072 for (i = 0, mycksum = 0; i < read_size; i++)
2073 mycksum ^= image[(addr + i) & (image_size - 1)];
2074
2075 if (target_wait(1, TARGET_RECV_DELAY) <= 0)
2076 main_fatal(E_RECV_TIMEOUT);
2077 cksum = target_getchar();
2078
2079 if (cksum != mycksum)
2080 main_fatal(E_RECV_CHECKSUM);
2081 }
2082 done_size += read_size;
2083 size -= read_size;
2084 addr += read_size;
2085
2086 progress_update(done_size / read_size_max);
2087 progress_update_simple('0' + read_size / 1024);
2088 }
2089 }
2090 progress_end(done_size / read_size_max);
2091 flowf(NORMAL, " ok\n");
2092
2093 time_read = stopwatch_stop(time_read);
2094 flowf(VERBOSE, "Used time: %ds ok\n", time_read);
2095 }
2096
2097
2098 /******************************************************************************
2099 * Flash Reset
2100 ******************************************************************************/
2101
2102 void target_reset_machine(void)
2103 {
2104 int error;
2105
2106 flowf(VERBOSE, "Resetting target: ");
2107
2108 if (arg_dry_run) {
2109 flowf(VERBOSE, "(dry-run) ");
2110 }
2111 else {
2112 target_putchar(PROTO_RESET);
2113 target_expect_char(PROTO_READY, TARGET_RECV_DELAY);
2114 }
2115 flowf(VERBOSE, "ok\n");
2116 }
2117
2118
2119 /******************************************************************************
2120 * Show Functions (dump internal data structures)
2121 ******************************************************************************/
2122
2123 void image_map_show(void)
2124 {
2125 uint32 addr;
2126 int i;
2127
2128 flowf(ALWAYS, "image map of %d * %dkB chunks (x = used, s = skip, c = checksum ok):",
2129 image_size_in_chunks, image_chunk_size / 1024);
2130
2131 // For each chunk of the image usage map...
2132 for (i = 0, addr = 0; i < image_size_in_chunks; i++)
2133 {
2134 if ((i % 64) == 0) {
2135 flowf(ALWAYS, "\n%4dkB: ", (int) addr >> 10);
2136 }
2137 putchar(image_map[i] != 0 ? image_map[i] : '.');
2138 addr += image_chunk_size;
2139 }
2140 putchar('\n');
2141 }
2142
2143 void sector_map_show(void)
2144 {
2145 struct sector_s *sectors = device->memmap->sectors;
2146 int i;
2147
2148 char n;
2149 uint32 addr = 0;
2150
2151 flowf(ALWAYS, "sector map (x = used, s = skip, X = force erase):");
2152
2153 // For each sector of the device definition...
2154 for (i = 0; i < device->memmap->size; i++)
2155 {
2156 if ((addr & 0xFFFFF) == 0) {
2157 flowf(ALWAYS, "\n%2dMB: ", (int) addr >> 20);
2158 }
2159 n = (sector_map[i] ? sector_map[i] : '.');
2160 putchar(n);
2161
2162 addr += sectors[i].size;
2163 }
2164 putchar('\n');
2165 }
2166
2167
2168 /******************************************************************************
2169 * Utility Functions
2170 ******************************************************************************/
2171
2172 int image_is_within(int start, int end)
2173 {
2174 return !(start < 0 || image_size <= start ||
2175 end < 0 || image_size < end ||
2176 end < start);
2177 }
2178
2179 // Set the image usage map in the range [start..end[ as used
2180 int image_map_set(int start, int end)
2181 {
2182 if (!image_is_within(start, end))
2183 return -1;
2184
2185 do {
2186 image_map[start / image_chunk_size] = 'x';
2187 start += image_chunk_size;
2188 } while (start < end);
2189
2190 return 0;
2191 }
2192
2193 int target_type_set(uint16 code)
2194 {
2195 // If there is an override from the command-line, use that
2196 if (arg_target_type != 0)
2197 code = arg_target_type;
2198
2199 switch (code)
2200 {
2201 case 'h': // Hercules
2202 case 'u': // Ulysses
2203 case '3': // Chipset 3
2204 case CHIP_ID_ULYSSES_0:
2205 case CHIP_ID_ULYSSES_A:
2206 case CHIP_ID_HERCULES_A:
2207 case CHIP_ID_HERCULES_B:
2208 target_type = 3;
2209 break;
2210
2211 case 'c': // Calypso
2212 case '4': // Chipset 4
2213 // case 's': // Samson
2214 case CHIP_ID_CALYPSO_A:
2215 case CHIP_ID_CALYPSO_B:
2216 case CHIP_ID_CALYPSO_C:
2217 target_type = 4;
2218 break;
2219
2220 case 'l': // Calypso Lite
2221 case CHIP_ID_CALYPSO_L:
2222 target_type = 5;
2223 break;
2224
2225 case 'p': // Calypso Plus
2226 case CHIP_ID_CALYPSO_PLUS:
2227 case CHIP_ID_CALYPSO_PLUS_A:
2228 target_type = 6;
2229 break;
2230
2231 default:
2232 target_type = 0;
2233 }
2234
2235 return target_type;
2236 }
2237
2238 int image_map_count_used_chunks(void)
2239 {
2240 int used, i;
2241
2242 // For each image chunk
2243 for (i = 0, used = 0; i < image_size_in_chunks; i++) {
2244 if (image_map[i] == 'x')
2245 used++;
2246 }
2247 return used;
2248 }
2249
2250 // When the sector_map have been changed, we have to update the image_map
2251 // such that we don't attempt to program within sectors that are not going
2252 // to be programmed anyway (due to the erase override). We also have to
2253 // program chunks contained in sectors that *are* going to be erased, even
2254 // though the chunks have been check-summed ok.
2255 int image_map_update(void)
2256 {
2257 struct sector_s *sectors = device->memmap->sectors;
2258 int changed, chunks, i, j;
2259 int map_index;
2260
2261 map_index = 0;
2262 changed = 0;
2263
2264 // For each sector of the device definition...
2265 for (i = 0; i < device->memmap->size; i++) {
2266 chunks = sectors[i].size / image_chunk_size;
2267 // For each image--map-chunk contained in current sector...
2268 for (j = 0; j < chunks; j++) {
2269 if (!(sector_map[i] == 'x' || sector_map[i] == 'X') &&
2270 image_map[map_index + j] == 'x') {
2271 image_map[map_index + j] = 's'; // skip
2272 changed++;
2273 }
2274 else if ((sector_map[i] == 'x' || sector_map[i] == 'X')
2275 && image_map[map_index + j] == 'c') {
2276 image_map[map_index + j] = 'x'; // include!
2277 changed++;
2278 }
2279 }
2280 map_index += chunks;
2281 }
2282 return changed;
2283 }
2284
2285 int sector_map_init(void)
2286 {
2287 struct sector_s *sectors = device->memmap->sectors;
2288 int map_index;
2289 int used_list_index;
2290 int used, chunks, i, j;
2291
2292 sector_map_size = SECTOR_MAP_SIZE_MAX;
2293
2294 memset(sector_map, 0, sector_map_size);
2295
2296 // Generate the sector_map from the image_map
2297 map_index = 0;
2298
2299 // For each sector of the device definition...
2300 for (i = 0; i < device->memmap->size; i++) {
2301
2302 chunks = sectors[i].size / image_chunk_size;
2303
2304 // For each image-usage-map-chunk contained in current sector...
2305 for (j = 0, used = 0; j < chunks; j++)
2306 if (image_map[map_index + j] == 'x')
2307 used++;
2308
2309 sector_map[i] = (used ? 'x' : 0);
2310 map_index += chunks;
2311 }
2312
2313 parse_arg_erase_override(arg_erase_override);
2314
2315 // Generate the erase_list
2316 // For each sector of the device definition...
2317 used_list_index = 0;
2318 for (i = 0; i < device->memmap->size; i++) {
2319 if (sector_map[i] == 'x' || sector_map[i] == 'X')
2320 erase_list[used_list_index++] = sectors[i].addr;
2321 }
2322
2323 if (arg_sector_map_show)
2324 sector_map_show();
2325
2326 if (arg_sector_list_show) {
2327 flowf(ALWAYS, "sector used list: ");
2328 for (i = 0; i < used_list_index; i++)
2329 flowf(ALWAYS, "0x%06X ", erase_list[i]);
2330 putchar('\n');
2331 }
2332
2333 return used_list_index;
2334 }
2335
2336 int parse_range(char *p, char **p_end, int *n1, int *n2)
2337 {
2338 char *my_end;
2339 int read_offset_calp = (*arg_read != 0 && target[target_type].type == 'P');
2340
2341 *n2 = 0;
2342
2343 *n1 = strtol(p, &my_end, 0);
2344 if (p == my_end)
2345 return 0; // error: no chars converted
2346
2347 if (*my_end == 'k' || *my_end == 'K') {
2348 *n1 <<= 10;
2349 if (read_offset_calp) *n1 += CALP_OFFSET;
2350 my_end++;
2351 }
2352 else if (*my_end == 'M') {
2353 *n1 <<= 20;
2354 if (read_offset_calp) *n1 += CALP_OFFSET;
2355 my_end++;
2356 }
2357
2358 *p_end = my_end;
2359 if (my_end[0] != '.' || my_end[1] != '.')
2360 return 1;
2361 p = my_end + 2;
2362
2363 *n2 = strtol(p, &my_end, 0);
2364 if (p == my_end)
2365 return 0; // error: no chars converted
2366
2367 if (*my_end == 'k' || *my_end == 'K') {
2368 *n2 <<= 10;
2369 if (read_offset_calp) *n2 += CALP_OFFSET;
2370 my_end++;
2371 }
2372 else if (*my_end == 'M') {
2373 *n2 <<= 20;
2374 if (read_offset_calp) *n2 += CALP_OFFSET;
2375 my_end++;
2376 }
2377
2378 *p_end = my_end;
2379 return 2;
2380 }
2381
2382 // Parse and decode the erase override command line option string. The
2383 // sector_map is updated accordingly.
2384 void parse_arg_erase_override(char *p)
2385 {
2386 struct sector_s *sectors = device->memmap->sectors;
2387 int sector_bottom, sector_top;
2388 int changed, i;
2389
2390 tr(TrBegin| TrArgParser, "erase_override:\n");
2391 while (*p)
2392 {
2393 char *p_end;
2394 int num, sign, n1 = 0, n2 = 0;
2395
2396 if (*p != '-' && *p != '+')
2397 main_error(E_ERASE_SPEC);
2398
2399 sign = (*p == '-' ? -1 : +1);
2400 p++;
2401
2402 if (*p == '*') {
2403 sign = sign * 2;
2404 p++;
2405 }
2406 else {
2407 num = parse_range(p, &p_end, &n1, &n2);
2408 if (num == 0)
2409 main_error(E_ERASE_SPEC);
2410 p = p_end;
2411 }
2412
2413 switch (sign) {
2414 case -1:
2415 case +1:
2416 if (num == 1) {
2417 // Support for absolute addresses on Calypso Plus
2418 if (n1 >= CALP_OFFSET) n1 -= CALP_OFFSET;
2419
2420 if (n1 > sector_map_size) {
2421 // For all sectors...
2422 for (i = 0; i < device->memmap->size; i++) {
2423 sector_bottom = sectors[i].addr;
2424 sector_top = sector_bottom + sectors[i].size - 1;
2425
2426 if (n1 >= sector_bottom && n1 < sector_top) {
2427 sector_map[i] = (sign > 0 ? 'X' : 's');
2428 break;
2429 }
2430 }
2431 }
2432 else
2433 sector_map[n1] = (sign > 0 ? 'X' : 's');
2434 tr(TrArgParser, "%c%d\n", sign > 0 ? '+' : '-', n1);
2435 }
2436 else {
2437 // Support for absolute addresses on Calypso Plus
2438 if (n1 >= CALP_OFFSET && n2 >= CALP_OFFSET) {
2439 n1 -= CALP_OFFSET;
2440 n2 -= CALP_OFFSET;
2441 }
2442
2443 if (n1 > sector_map_size || n2 > sector_map_size) {
2444 // n1 and n2 must respresent an address range
2445 if (n1 >= n2)
2446 main_error(E_ERASE_SPEC);
2447
2448 // For all sectors...
2449 for (i = 0; i < device->memmap->size; i++)
2450 {
2451 sector_bottom = sectors[i].addr;
2452 sector_top = sector_bottom + sectors[i].size - 1;
2453
2454 // If either sector bottom or top is contained in
2455 // [n1..n2[
2456 if ((n1 <= sector_bottom && sector_bottom < n2) ||
2457 (n1 <= sector_top && sector_top < n2)) {
2458 sector_map[i] = (sign > 0 ? 'X' : 's');
2459 }
2460 }
2461 }
2462 else {
2463 // n1 and n2 must respresent a sector range
2464 for (i = n1; i < n2; i++)
2465 sector_map[i] = (sign > 0 ? 'X' : 's');
2466 }
2467 tr(TrArgParser,
2468 "%c%d..%d\n", sign > 0 ? '+' : '-', n1, n2);
2469 }
2470 break;
2471 case -2:
2472 case +2:
2473 // Fill whole sector_map...
2474 for (i = 0; i < device->memmap->size; i++)
2475 sector_map[i] = (sign > 0 ? 'X' : 's');
2476 tr(TrArgParser, "%c*\n", sign > 0 ? '+' : '-');
2477 break;
2478 }
2479 // skip optional comma
2480 if (*p == ',')
2481 p++;
2482 }
2483 tr(TrEnd| TrArgParser, "");
2484
2485 changed = image_map_update();
2486
2487 // If image map was changed, we trace it again.
2488 if (changed && arg_image_map_show)
2489 image_map_show();
2490 }
2491
2492 void parse_arg_read(char *p)
2493 {
2494 read_total_size = 0;
2495 read_list_size = 0;
2496
2497 tr(TrArgParser, "parse_arg_read() {\n");
2498 while (*p)
2499 {
2500 char *p_end;
2501 int num, n1, n2;
2502
2503 if (*p == '*') {
2504 n1 = 0;
2505 n2 = 0x1000000; // sufficiently large (16MB)
2506 p++;
2507 }
2508 else {
2509 num = parse_range(p, &p_end, &n1, &n2);
2510 tr(TrArgParser, "parse_range('%s', ...)\n"
2511 " { #%d, p_end = '%s', n1 = 0x%x, n2 = 0x%x } %d\n",
2512 p, read_list_size, p_end, n1, n2, num);
2513 if (num != 2 || n1 > n2)
2514 main_error(E_ADDR_RANGE);
2515 p = p_end;
2516 }
2517 read_list[read_list_size].addr = n1;
2518 read_list[read_list_size].size = n2 - n1;
2519 read_total_size += n2 - n1;
2520 read_list_size++;
2521 if (read_list_size >= READ_LIST_SIZE_MAX)
2522 main_error(E_ARG_TOOMANY);
2523
2524 if (*p == 0)
2525 break;
2526
2527 if (*p == ',')
2528 p++;
2529 else
2530 main_error(E_READ_SPEC);
2531 }
2532 // Terminate the read_list with zeroes.
2533 read_list[read_list_size].addr = 0;
2534 read_list[read_list_size].size = 0;
2535
2536 tr(TrArgParser, "}\n");
2537 }
2538
2539 void parse_arg_write(char *p)
2540 {
2541 tr(TrArgParser, "parse_arg_write() {\n");
2542
2543 while (*p)
2544 {
2545 char bytes[1024];
2546 char *p_end;
2547 int num, n1, n2;
2548 int index, value, size, i;
2549
2550 num = parse_range(p, &p_end, &n1, &n2);
2551 tr(TrArgParser, "parse_range('%s', ...)\n"
2552 " { p_end = '%s', n1 = 0x%x, n2 = 0x%x } %d\n",
2553 p, p_end, n1, n2, num);
2554
2555 if (num < 1 || num > 2)
2556 main_error(E_ADDR_RANGE);
2557
2558 p = p_end;
2559
2560 if (*p++ != '=')
2561 main_error(E_WRITE_SPEC);
2562
2563 tr(TrArgParser, " { ");
2564 if (*p == 0)
2565 main_error(E_WRITE_SPEC);
2566
2567 index = 0;
2568 while (*p) {
2569 if (*p == '\"') {
2570 // Collect text string
2571 p++;
2572 tr(TrCont|TrArgParser, "'");
2573 while (*p) {
2574 if (*p == '\"')
2575 break;
2576 if (p[0] == '\\' && p[1] == '\"')
2577 p++; // skip leading backslash
2578 if (p[0] == '\\' && p[1] == '\\')
2579 p++; // skip leading backslash
2580 tr(TrCont|TrArgParser, "%c", *p);
2581 bytes[index] = *p++;
2582 if (index++ >= sizeof(bytes))
2583 main_error(E_WRITE_SPEC);
2584 }
2585 if (*p++ != '\"')
2586 main_error(E_WRITE_SPEC);
2587 tr(TrCont|TrArgParser, "' ");
2588 }
2589 else {
2590 // Collect byte string
2591 value = strtol(p, &p_end, 0);
2592 if (p == p_end)
2593 main_error(E_WRITE_SPEC);
2594 if (value < 0 || 255 < value)
2595 main_error(E_WRITE_SPEC);
2596 bytes[index] = value;
2597 if (index++ >= sizeof(bytes))
2598 main_error(E_WRITE_SPEC);
2599 p = p_end;
2600
2601 tr(TrCont|TrArgParser, "0x%x ", value);
2602 }
2603 if (*p == ':' || *p == 0)
2604 break;
2605 if (*p == ',')
2606 p++;
2607 }
2608 size = index;
2609 tr(TrArgParser, "} %d\n", size);
2610
2611 if (num == 1) {
2612 // Support for absolute addresses on Calypso Plus
2613 if (n1 >= CALP_OFFSET) n1 -= CALP_OFFSET;
2614
2615 n2 = n1 + size;
2616 }
2617 else if (n1 >= CALP_OFFSET && n2 >= CALP_OFFSET) {
2618 n1 -= CALP_OFFSET;
2619 n2 -= CALP_OFFSET;
2620 }
2621
2622 if (image_map_set(n1, n2) < 0)
2623 main_error(E_ADDR_RANGE);
2624
2625 index = 0;
2626 for (i = n1; i < n2; i++) {
2627 image[i] = bytes[index++];
2628 if (index >= size)
2629 index = 0;
2630 }
2631 if (*p == ':')
2632 p++;
2633 }
2634 tr(TrArgParser, "}\n");
2635 }