1 ///////////////////////////////////////////////////////////////////////////////
2 // BOSSA
3 //
4 // Copyright (c) 2011-2018, ShumaTech
5 // All rights reserved.
6 //
7 // Redistribution and use in source and binary forms, with or without
8 // modification, are permitted provided that the following conditions are met:
9 // * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
11 // * Redistributions in binary form must reproduce the above copyright
12 // notice, this list of conditions and the following disclaimer in the
13 // documentation and/or other materials provided with the distribution.
14 // * Neither the name of the <organization> nor the
15 // names of its contributors may be used to endorse or promote products
16 // derived from this software without specific prior written permission.
17 //
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 // DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
22 // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 ///////////////////////////////////////////////////////////////////////////////
29 #define __STDC_LIMIT_MACROS
30 #include <stdio.h>
31 #include <stdarg.h>
32 #include <errno.h>
33 #include <string.h>
34 #include <assert.h>
35 #include <readline/readline.h>
36 #include <readline/history.h>
37
38 #include "Command.h"
39
40 #define min(a, b) ((a) < (b) ? (a) : (b))
41
42 using namespace std;
43
44 Shell* Command::_shell = NULL;
45 Samba Command::_samba;
46 PortFactory Command::_portFactory;
47 Device Command::_device(_samba);
48 Device::FlashPtr& Command::_flash = _device.getFlash();
49 CommandObserver Command::_observer;
50 Flasher Command::_flasher(_samba, _device, _observer);
51 bool Command::_connected = false;
52
Command(const char * name,const char * help,const char * usage)53 Command::Command(const char* name, const char* help, const char* usage) :
54 _name(name), _help(help), _usage(usage)
55 {
56 assert(_shell != NULL);
57 }
58
59 void
onStatus(const char * message,...)60 CommandObserver::onStatus(const char *message, ...)
61 {
62 va_list ap;
63
64 va_start(ap, message);
65 vprintf(message, ap);
66 va_end(ap);
67 }
68
69 void
onProgress(int num,int div)70 CommandObserver::onProgress(int num, int div)
71 {
72 int ticks;
73 int bars = 30;
74
75 ticks = num * bars / div;
76
77 if (ticks == _lastTicks)
78 return;
79
80 printf("\r[");
81 while (ticks-- > 0)
82 {
83 putchar('=');
84 bars--;
85 }
86 while (bars-- > 0)
87 {
88 putchar(' ');
89 }
90 printf("] %d%% (%d/%d pages)", num * 100 / div, num, div);
91 fflush(stdout);
92
93 _lastTicks = 0;
94 }
95
96 bool
error(const char * fmt,...)97 Command::error(const char* fmt, ...)
98 {
99 va_list ap;
100
101 va_start(ap, fmt);
102 vprintf(fmt, ap);
103 va_end(ap);
104 printf(". Try \"help %s\".\n", _name);
105
106 return false;
107 }
108
109 bool
argNum(int argc,int num)110 Command::argNum(int argc, int num)
111 {
112 if (argc != num)
113 return error("Command requires %d argument%s",
114 num - 1, (num > 1) ? "s" : "", _name);
115
116 return true;
117 }
118
119 bool
argRange(int argc,int min,int max)120 Command::argRange(int argc, int min, int max)
121 {
122 if (argc < min || argc > max)
123 return error("Command requires %d to %d arguments", min - 1, max - 1);
124
125 return true;
126 }
127
128 bool
argUint32(const char * arg,uint32_t * value)129 Command::argUint32(const char* arg, uint32_t* value)
130 {
131 long long ll;
132 char *end;
133
134 errno = 0;
135 ll = strtoll(arg, &end, 0);
136 if (errno != 0 || *end != '\0')
137 return error("Invalid number \"%s\"", arg);
138 if (ll < 0 || ll > UINT32_MAX)
139 return error("Number \"%s\" is out of range", arg);
140
141 *value = ll;
142
143 return true;
144 }
145
146 bool
argBool(const char * arg,bool * value)147 Command::argBool(const char* arg, bool* value)
148 {
149 int len = strlen(arg);
150 if (strncasecmp(arg, "true", len) == 0)
151 *value = true;
152 else if (strncasecmp(arg, "false", len) == 0)
153 *value = false;
154 else
155 return error("Invalid boolean \"%s\"", arg);
156
157 return true;
158 }
159
160 bool
argState(const char * arg,bool * value)161 Command::argState(const char* arg, bool* value)
162 {
163 int len = strlen(arg);
164 if (strncasecmp(arg, "enable", len) == 0)
165 *value = true;
166 else if (strncasecmp(arg, "disable", len) == 0)
167 *value = false;
168 else
169 return error("Invalid state \"%s\"", arg);
170
171 return true;
172 }
173
174 bool
connected()175 Command::connected()
176 {
177 if (!_connected)
178 {
179 printf("No device connected. Use \"connect\" first.\n");
180 return false;
181 }
182 return true;
183 }
184
185 bool
flashable()186 Command::flashable()
187 {
188 if (!connected())
189 return false;
190
191 if (_flash.get() == NULL)
192 {
193 printf("Flash on device is not supported.\n");
194 return false;
195 }
196 return true;
197 }
198
199 bool
createDevice()200 Command::createDevice()
201 {
202 try
203 {
204 _device.create();
205 }
206 catch (DeviceUnsupportedError& e)
207 {
208 printf("Device is not supported\n");
209 return false;
210 }
211
212 return true;
213 }
214
215 void
hexdump(uint32_t addr,uint8_t * buf,size_t count)216 Command::hexdump(uint32_t addr, uint8_t *buf, size_t count)
217 {
218 int lpad;
219 int rpad;
220 size_t size;
221 size_t offset;
222 const uint32_t ROW_SIZE = 16;
223 const uint32_t ROW_MASK = ~(ROW_SIZE - 1);
224
225 printf(" 0 1 2 3 4 5 6 7 8 9 a b c d e f\n");
226
227 while (count > 0)
228 {
229 lpad = (addr % ROW_SIZE);
230 rpad = ROW_SIZE - min(lpad + count, ROW_SIZE);
231 size = ROW_SIZE - rpad - lpad;
232
233 printf("%08x | ", addr & ROW_MASK);
234
235 printf("%*s", 3 * lpad, "");
236 for (offset = 0; offset < size; offset++)
237 printf("%02x ", buf[offset]);
238 printf("%*s", 3 * rpad, "");
239
240 printf("| ");
241
242 printf("%*s", lpad, "");
243 for (offset = 0; offset < size; offset++)
244 printf("%c", isprint(buf[offset]) ? buf[offset] : '.');
245 printf("%*s", rpad, "");
246
247 printf("\n");
248
249 buf += size;
250 addr += size;
251 count -= size;
252 }
253 }
254
255 const char*
binstr(uint32_t value,int bits,char low,char high)256 Command::binstr(uint32_t value, int bits, char low, char high)
257 {
258 static char buf[36];
259 char *str = buf;
260
261 assert(bits <= 32 && bits > 0);
262
263 for (int bitnum = bits - 1; bitnum >= 0; bitnum--)
264 {
265 *str++ = (value & (1 << bitnum)) ? high : low;
266 if (bitnum % 8 == 0)
267 *str++ = ' ';
268 }
269 *(str - 1) = '\0';
270
271 return buf;
272 }
273
274 void
disconnect()275 Command::disconnect()
276 {
277 _connected = false;
278 }
279
280 bool
operator <(const Command & rhs)281 Command::operator < (const Command& rhs)
282 {
283 return (strcmp(_name, rhs._name) == -1);
284 }
285
CommandBod()286 CommandBod::CommandBod() :
287 Command("bod",
288 "Change the brownout detect flag.",
289 "bod [BOOL]\n"
290 " BOOL -- boolean value either \"true\" or \"false\"")
291 {}
292
293 void
invoke(char * argv[],int argc)294 CommandBod::invoke(char* argv[], int argc)
295 {
296 bool value;
297
298 if (!argNum(argc, 2) ||
299 !argBool(argv[1], &value) ||
300 !flashable())
301 return;
302
303 if (!_flash->canBod())
304 {
305 printf("Unsupported on this flash device\n");
306 return;
307 }
308
309 _flash->setBod(value);
310 printf("BOD flag set to %s\n", value ? "true" : "false");
311 }
312
CommandBootf()313 CommandBootf::CommandBootf() :
314 Command("bootf",
315 "Change the boot to flash flag.",
316 "bootf [BOOL]\n"
317 " BOOL -- boolean value either \"true\" or \"false\"")
318 {}
319
320 void
invoke(char * argv[],int argc)321 CommandBootf::invoke(char* argv[], int argc)
322 {
323 bool value;
324
325 if (!argNum(argc, 2) ||
326 !argBool(argv[1], &value) ||
327 !flashable())
328 return;
329
330 _flash->setBootFlash(value);
331 printf("Boot to flash flag set to %s\n", value ? "true" : "false");
332 }
333
CommandBor()334 CommandBor::CommandBor() :
335 Command("bor",
336 "Change the brownout reset flag.",
337 "bor [BOOL]\n"
338 " BOOL -- boolean value either \"true\" or \"false\"")
339 {}
340
341 void
invoke(char * argv[],int argc)342 CommandBor::invoke(char* argv[], int argc)
343 {
344 bool value;
345
346 if (!argNum(argc, 2) ||
347 !argBool(argv[1], &value) ||
348 !flashable())
349 return;
350
351 if (!_flash->canBor())
352 {
353 printf("Unsupported on this flash device\n");
354 return;
355 }
356
357 _flash->setBor(value);
358 printf("BOR flag set to %s\n", value ? "true" : "false");
359 }
360
CommandConnect()361 CommandConnect::CommandConnect() :
362 Command("connect",
363 "Connect to device over serial port.",
364 "connect [SERIAL]\n"
365 " SERIAL -- host-specific serial port")
366 {}
367
368 void
invoke(char * argv[],int argc)369 CommandConnect::invoke(char* argv[], int argc)
370 {
371 if (!argNum(argc, 2))
372 return;
373
374 if (!_samba.connect(_portFactory.create(argv[1])))
375 {
376 printf("No device found on %s\n", argv[1]);
377 _connected = false;
378 return;
379 }
380
381 printf("Connected to device on %s\n", argv[1]);
382 _connected = true;
383 createDevice();
384 }
385
CommandDebug()386 CommandDebug::CommandDebug() :
387 Command("debug",
388 "Change the debug state.",
389 "debug [STATE]\n"
390 " STATE - either \"disable\" or \"enable\"")
391 {}
392
393 void
invoke(char * argv[],int argc)394 CommandDebug::invoke(char* argv[], int argc)
395 {
396 bool state;
397
398 if (!argNum(argc, 2) ||
399 !argState(argv[1], &state))
400 return;
401
402 _samba.setDebug(state);
403 }
404
CommandDump()405 CommandDump::CommandDump() :
406 Command("dump",
407 "Dump memory in hexadecimal and ascii.",
408 "dump [ADDRESS] [COUNT]\n"
409 " ADDRESS -- starting memory address\n"
410 " COUNT -- count of bytes to display")
411 {}
412
413 void
invoke(char * argv[],int argc)414 CommandDump::invoke(char* argv[], int argc)
415 {
416 uint32_t addr;
417 uint32_t count;
418
419 if (!argNum(argc, 3) ||
420 !argUint32(argv[1], &addr) ||
421 !argUint32(argv[2], &count) ||
422 !connected())
423 return;
424
425 std::unique_ptr<uint8_t[]> buf(new uint8_t[count]);
426
427 try
428 {
429 _samba.read(addr, buf.get(), count);
430 }
431 catch (...)
432 {
433 throw;
434 }
435
436 hexdump(addr, buf.get(), count);
437 }
438
CommandErase()439 CommandErase::CommandErase() :
440 Command("erase",
441 "Erase the flash to the end.",
442 "erase <offset>"
443 " OFFSET -- (optional) start erase operation at flash OFFSET\n"
444 " OFFSET must be aligned to a flash page boundary")
445 {}
446
447 void
invoke(char * argv[],int argc)448 CommandErase::invoke(char* argv[], int argc)
449 {
450 uint32_t offset = 0;
451
452 if (!argRange(argc, 1, 2) ||
453 (argc >= 2 && !argUint32(argv[1], &offset)) ||
454 !flashable())
455 return;
456
457 _flasher.erase(offset);
458 printf("Flash is erased\n");
459 }
460
CommandExit()461 CommandExit::CommandExit() :
462 Command("exit",
463 "Exit the BOSSA shell.",
464 "exit")
465 {}
466
467 void
invoke(char * argv[],int argc)468 CommandExit::invoke(char* argv[], int argc)
469 {
470 if (!argNum(argc, 1))
471 return;
472
473 _shell->exitFlag() = true;
474 }
475
CommandGo()476 CommandGo::CommandGo() :
477 Command("go",
478 "Execute ARM code at address.",
479 "go [ADDRESS]\n"
480 " ADDRESS -- starting memory address of code to execute")
481 {}
482
483 void
invoke(char * argv[],int argc)484 CommandGo::invoke(char* argv[], int argc)
485 {
486 uint32_t addr;
487
488 if (!argNum(argc, 2) ||
489 !argUint32(argv[1], &addr) ||
490 !connected())
491 return;
492
493 printf("Executing code at %#x\n", addr);
494 _samba.go(addr);
495 }
496
CommandHelp()497 CommandHelp::CommandHelp() :
498 Command("help",
499 "Display help for a command.",
500 "help <COMMAND>\n"
501 " COMMAND -- (optional) display detailed usage for this command,\n"
502 " display summary help for all commands if not given")
503 {}
504
505 void
invoke(char * argv[],int argc)506 CommandHelp::invoke(char* argv[], int argc)
507 {
508 if (!argRange(argc, 1, 2))
509 return;
510
511 if (argc == 1)
512 _shell->help();
513 else
514 _shell->usage(argv[1]);
515 }
516
CommandHistory()517 CommandHistory::CommandHistory() :
518 Command("history",
519 "List the command history.",
520 "history")
521 {}
522
523 void
invoke(char * argv[],int argc)524 CommandHistory::invoke(char* argv[], int argc)
525 {
526 if (!argNum(argc, 1))
527 return;
528 printf("history_base=%d\n", history_base);
529 for (int i = history_base; i < history_base + history_length; i++)
530 {
531 HIST_ENTRY *entry = history_get(i);
532 if (entry)
533 printf (" %d %s\n", i, entry->line);
534 }
535 }
536
CommandInfo()537 CommandInfo::CommandInfo() :
538 Command("info",
539 "Display information about the flash.",
540 "info")
541 {}
542
543 void
invoke(char * argv[],int argc)544 CommandInfo::invoke(char* argv[], int argc)
545 {
546 FlasherInfo info;
547
548 if (!argNum(argc, 1) ||
549 !flashable())
550 return;
551
552 _flasher.info(info);
553
554 info.print();
555 }
556
CommandLock()557 CommandLock::CommandLock() :
558 Command("lock",
559 "Set lock bits in the flash.",
560 "lock <BITS>"
561 " BITS -- (optional) comma separated list of bits,"
562 " all bits if not given\n")
563 {}
564
565 void
invoke(char * argv[],int argc)566 CommandLock::invoke(char* argv[], int argc)
567 {
568 string bits;
569
570 if (!flashable())
571 return;
572
573 for (int argn = 1; argn < argc; argn++)
574 bits += argv[argn];
575
576 _flasher.lock(bits, true);
577 printf("Locked regions %s\n", bits.c_str());
578 }
579
CommandMrb()580 CommandMrb::CommandMrb() :
581 Command("mrb",
582 "Read bytes from memory.",
583 "mrb [ADDRESS] <COUNT>\n"
584 " ADDRESS -- starting memory address\n"
585 " COUNT -- (optional) count of bytes to display, 1 if not given")
586 {}
587
588 void
invoke(char * argv[],int argc)589 CommandMrb::invoke(char* argv[], int argc)
590 {
591 uint32_t addr;
592 uint32_t count = 1;
593 uint8_t value;
594
595 if (!argRange(argc, 2, 3) ||
596 !argUint32(argv[1], &addr) ||
597 (argc >= 3 && !argUint32(argv[2], &count)) ||
598 !connected())
599 return;
600
601 while (count > 0)
602 {
603 value = _samba.readByte(addr);
604 printf("%08x : %02x %s\n", addr, value, binstr(value, 8));
605 addr++;
606 count--;
607 }
608 }
609
CommandMrf()610 CommandMrf::CommandMrf() :
611 Command("mrf",
612 "Read memory to file.",
613 "mrf [ADDRESS] [COUNT] [FILE]\n"
614 " ADDRESS -- memory address to read\n"
615 " COUNT -- count of bytes to read\n"
616 " FILE -- file name on host filesystem to write")
617 {}
618
619 void
invoke(char * argv[],int argc)620 CommandMrf::invoke(char* argv[], int argc)
621 {
622 uint32_t addr;
623 uint32_t count;
624 FILE* infile;
625 uint8_t buf[1024];
626 ssize_t fbytes;
627
628 if (!argNum(argc, 4) ||
629 !argUint32(argv[1], &addr) ||
630 !argUint32(argv[2], &count) ||
631 !connected())
632 return;
633
634 infile = fopen(argv[3], "wb");
635 if (!infile)
636 throw FileOpenError(errno);
637
638 try
639 {
640 while (count > 0)
641 {
642 fbytes = min(count, sizeof(buf));
643 _samba.read(addr, buf, fbytes);
644 fbytes = fwrite(buf, 1, fbytes, infile);
645 if (fbytes < 0)
646 throw FileIoError(errno);
647 if ((size_t) fbytes != min(count, sizeof(buf)))
648 throw FileShortError();
649 count -= fbytes;
650 }
651 }
652 catch (...)
653 {
654 fclose(infile);
655 throw;
656 }
657
658 fclose(infile);
659 }
660
CommandMrw()661 CommandMrw::CommandMrw() :
662 Command("mrw",
663 "Read words from memory.",
664 "mrw [ADDRESS] <COUNT>\n"
665 " ADDRESS -- starting memory address\n"
666 " COUNT -- (optional) count of words to display, 1 if not given")
667 {}
668
669 void
invoke(char * argv[],int argc)670 CommandMrw::invoke(char* argv[], int argc)
671 {
672 uint32_t addr;
673 uint32_t count = 1;
674 uint32_t value;
675
676 if (!argRange(argc, 2, 3) ||
677 !argUint32(argv[1], &addr) ||
678 (argc >= 3 && !argUint32(argv[2], &count)) ||
679 !connected())
680 return;
681
682 while (count > 0)
683 {
684 value = _samba.readWord(addr);
685 printf("%08x : %08x %s\n", addr, value, binstr(value, 32));
686 addr += 4;
687 count--;
688 }
689 }
690
CommandMwb()691 CommandMwb::CommandMwb() :
692 Command("mwb",
693 "Write bytes to memory.",
694 "mwb [ADDRESS] <VALUE>\n"
695 " ADDRESS -- starting memory address\n"
696 " VALUE -- (optional) value of byte to write, if not given"
697 " command will repeatedly prompt for input")
698 {}
699
700 void
invoke(char * argv[],int argc)701 CommandMwb::invoke(char* argv[], int argc)
702 {
703 uint32_t addr;
704 uint32_t value;
705
706 if (!argRange(argc, 2, 3) ||
707 !argUint32(argv[1], &addr) ||
708 (argc >= 3 && !argUint32(argv[2], &value)) ||
709 !connected())
710 return;
711
712 do
713 {
714 if (argc == 2)
715 {
716 char* input = readline("? ");
717 if (!input)
718 return;
719 if (*input == '\0' ||
720 !argUint32(input, &value))
721 {
722 free(input);
723 return;
724 }
725 free(input);
726 }
727
728 if (value > 255)
729 {
730 error("Value out of range");
731 return;
732 }
733
734 _samba.writeByte(addr, value);
735 printf("%08x : %02x\n", addr, value);
736 addr++;
737 } while (argc == 2);
738 }
739
CommandMwf()740 CommandMwf::CommandMwf() :
741 Command("mwf",
742 "Write memory from file.",
743 "mwf [ADDRESS] [FILE]\n"
744 " ADDRESS -- memory address to write\n"
745 " FILE -- file name on host filesystem to read")
746 {}
747
748 void
invoke(char * argv[],int argc)749 CommandMwf::invoke(char* argv[], int argc)
750 {
751 uint32_t addr;
752 FILE* infile;
753 uint8_t buf[1024];
754 ssize_t fsize;
755 ssize_t fbytes;
756 ssize_t fpos;
757
758 if (!argNum(argc, 3) ||
759 !argUint32(argv[1], &addr) ||
760 !connected())
761 return;
762
763 infile = fopen(argv[2], "rb");
764 if (!infile)
765 throw FileOpenError(errno);
766
767 try
768 {
769 if (fseek(infile, 0, SEEK_END) != 0 ||
770 (fsize = ftell(infile)) < 0)
771 throw FileIoError(errno);
772
773 rewind(infile);
774
775 for (fpos = 0; fpos < fsize; fpos += fbytes)
776 {
777 fbytes = fread(buf, 1, min((size_t)fsize, sizeof(buf)), infile);
778 if (fbytes < 0)
779 throw FileIoError(errno);
780 if (fbytes == 0)
781 break;
782 _samba.write(addr, buf, fbytes);
783 }
784 }
785 catch (...)
786 {
787 fclose(infile);
788 throw;
789 }
790 fclose(infile);
791 printf("Wrote %ld bytes to address %08x\n", (long) fsize, addr);
792 }
793
CommandMww()794 CommandMww::CommandMww() :
795 Command("mww",
796 "Write words to memory.",
797 "mww [ADDRESS] <VALUE>\n"
798 " ADDRESS -- starting memory address\n"
799 " VALUE -- (optional) value of word to write, if not given"
800 " command will repeatedly prompt for input")
801 {}
802
803 void
invoke(char * argv[],int argc)804 CommandMww::invoke(char* argv[], int argc)
805 {
806 uint32_t addr;
807 uint32_t value;
808
809 if (!argRange(argc, 2, 3) ||
810 !argUint32(argv[1], &addr) ||
811 (argc >= 3 && !argUint32(argv[2], &value)) ||
812 !connected())
813 return;
814
815 do
816 {
817 if (argc == 2)
818 {
819 char* input = readline("? ");
820 if (!input)
821 return;
822 if (*input == '\0' ||
823 !argUint32(input, &value))
824 {
825 free(input);
826 return;
827 }
828 free(input);
829 }
830
831 _samba.writeWord(addr, value);
832 printf("%08x : %08x\n", addr, value);
833 addr++;
834 } while (argc == 2);
835 }
836
CommandPio()837 CommandPio::CommandPio() :
838 Command("pio",
839 "Parallel input/output operations.",
840 "pio [LINE] [OPERATION]\n"
841 " LINE -- PIO line name (i.e. pa28, pc5, etc.)\n"
842 " All lines if only port given (i.e. pa, pc, etc.)\n"
843 " OPERATION -- operation to perform on the PIO line.\n"
844 " status -- show the line status\n"
845 " high -- drive the output high\n"
846 " low -- drive the output low\n"
847 " read -- read the input level\n"
848 " input -- make the line an input\n"
849 " peripheral [AB] -- set the line to a peripheral\n"
850 " [AB] -- peripheral \"a\" or \"b\"\n"
851 " multidrive [STATE] -- set the multi-drive state\n"
852 " STATE - either \"disable\" or \"enable\"\n"
853 " pullup [STATE] -- set the pull-up state\n"
854 " STATE - either \"disable\" or \"enable\""
855 )
856 {}
857
858 void
invoke(char * argv[],int argc)859 CommandPio::invoke(char* argv[], int argc)
860 {
861 uint32_t line;
862 uint32_t addr = 0;
863 size_t len;
864 char port;
865
866 if (!argRange(argc, 3, 4) ||
867 !connected())
868 return;
869
870 if (strlen(argv[1]) < 2 ||
871 tolower(argv[1][0]) != 'p')
872 {
873 error("Invalid PIO line name");
874 return;
875 }
876
877 if (argv[1][2] == '\0')
878 {
879 line = 0xffffffff;
880 }
881 else
882 {
883 if (!argUint32(&argv[1][2], &line))
884 return;
885
886 if (line >= 32)
887 {
888 error("Invalid PIO line number");
889 return;
890 }
891
892 line = (1 << line);
893 }
894
895 port = tolower(argv[1][1]);
896
897 // Check for Cortex-M3 register set
898 Device::Family family = _device.getFamily();
899 if (family == Device::FAMILY_SAM3U)
900 {
901 // Check for SAM3U special case
902 switch (port)
903 {
904 case 'a': addr = 0x400e0c00; break;
905 case 'b': addr = 0x400e0e00; break;
906 case 'c': addr = 0x400e1000; break;
907 }
908 }
909 else if (family == Device::FAMILY_SAM3N ||
910 family == Device::FAMILY_SAM3S)
911 {
912 switch (port)
913 {
914 case 'a': addr = 0x400e0e00; break;
915 case 'b': addr = 0x400e1000; break;
916 case 'c': addr = 0x400e1200; break;
917 }
918 }
919 else if (family == Device::FAMILY_SAM7S ||
920 family == Device::FAMILY_SAM7SE ||
921 family == Device::FAMILY_SAM7X ||
922 family == Device::FAMILY_SAM7XC ||
923 family == Device::FAMILY_SAM7L)
924 {
925 switch (port)
926 {
927 case 'a': addr = 0xfffff400; break;
928 case 'b': addr = 0xfffff600; break;
929 case 'c': addr = 0xfffff800; break;
930 }
931 }
932 else
933 {
934 printf("Unsupported device\n");
935 return;
936 }
937
938 if (addr == 0)
939 {
940 printf("Invalid PIO line \"%s\"\n", argv[1]);
941 return;
942 }
943
944 static const uint32_t PIO_PER = 0x0;
945 static const uint32_t PIO_PDR = 0x4;
946 static const uint32_t PIO_PSR = 0x8;
947 static const uint32_t PIO_OER = 0x10;
948 static const uint32_t PIO_ODR = 0x14;
949 static const uint32_t PIO_OSR = 0x18;
950 static const uint32_t PIO_SODR = 0x30;
951 static const uint32_t PIO_CODR = 0x34;
952 static const uint32_t PIO_ODSR = 0x38;
953 static const uint32_t PIO_PDSR = 0x3c;
954 static const uint32_t PIO_MDER = 0x50;
955 static const uint32_t PIO_MDDR = 0x54;
956 static const uint32_t PIO_MDSR = 0x58;
957 static const uint32_t PIO_PUDR = 0x60;
958 static const uint32_t PIO_PUER = 0x64;
959 static const uint32_t PIO_PUSR = 0x68;
960 static const uint32_t PIO_ABSR = 0x70;
961
962 len = strlen(argv[2]);
963 if (strncasecmp(argv[2], "status", len) == 0)
964 {
965 if (line != 0xffffffff)
966 {
967 uint32_t reg = _samba.readWord(addr + PIO_PSR);
968 printf("PIO Mode : %s\n", (reg & line) ? "enable" : "disable");
969
970 reg = _samba.readWord(addr + PIO_OSR);
971 printf("Direction : %s\n", (reg & line) ? "output" : "input");
972
973 reg = _samba.readWord(addr + PIO_PDSR);
974 printf("Input Level : %s\n", (reg & line)? "high" : "low");
975
976 reg = _samba.readWord(addr + PIO_ODSR);
977 printf("Output Level : %s\n", (reg & line)? "high" : "low");
978
979 reg = _samba.readWord(addr + PIO_MDSR);
980 printf("Multi-Drive : %s\n", (reg & line)? "enable" : "disable");
981
982 reg = _samba.readWord(addr + PIO_PUSR);
983 printf("Pull-Up : %s\n", (reg & line)? "disable" : "enable");
984
985 reg = _samba.readWord(addr + PIO_ABSR);
986 printf("Peripheral : %s\n", (reg & line) ? "B" : "A");
987 }
988 else
989 {
990 printf(" 3 2 2 1 1\n");
991 printf(" 1 4 3 6 5 8 7 0\n");
992
993 uint32_t reg = _samba.readWord(addr + PIO_PSR);
994 printf("PIO Mode : %s\n", binstr(reg, 32, 'D', 'E'));
995
996 reg = _samba.readWord(addr + PIO_OSR);
997 printf("Direction : %s\n", binstr(reg, 32, 'I', 'O'));
998
999 reg = _samba.readWord(addr + PIO_PDSR);
1000 printf("Input Level : %s\n", binstr(reg, 32, 'L', 'H'));
1001
1002 reg = _samba.readWord(addr + PIO_ODSR);
1003 printf("Output Level : %s\n", binstr(reg, 32, 'L', 'H'));
1004
1005 reg = _samba.readWord(addr + PIO_MDSR);
1006 printf("Multi-Drive : %s\n", binstr(reg, 32, 'D', 'E'));
1007
1008 reg = _samba.readWord(addr + PIO_PUSR);
1009 printf("Pull-Up : %s\n", binstr(reg, 32, 'E', 'D'));
1010
1011 reg = _samba.readWord(addr + PIO_ABSR);
1012 printf("Peripheral : %s\n", binstr(reg, 32, 'A', 'B'));
1013 }
1014 }
1015 else if (strncasecmp(argv[2], "high", len) == 0)
1016 {
1017 _samba.writeWord(addr + PIO_SODR, line);
1018 _samba.writeWord(addr + PIO_OER, line);
1019 _samba.writeWord(addr + PIO_PER, line);
1020 printf("%s is high output\n", argv[1]);
1021 }
1022 else if (strncasecmp(argv[2], "low", len) == 0)
1023 {
1024 _samba.writeWord(addr + PIO_CODR, line);
1025 _samba.writeWord(addr + PIO_OER, line);
1026 _samba.writeWord(addr + PIO_PER, line);
1027 printf("%s is low output\n", argv[1]);
1028 }
1029 else if (strncasecmp(argv[2], "read", len) == 0)
1030 {
1031 uint32_t reg = _samba.readWord(addr + PIO_PDSR);
1032 printf("%s is %s\n", argv[1], (reg & line) ? "high" : "low");
1033 }
1034 else if (strncasecmp(argv[2], "input", len) == 0)
1035 {
1036 _samba.writeWord(addr + PIO_ODR, line);
1037 _samba.writeWord(addr + PIO_PER, line);
1038 printf("%s is an input\n", argv[1]);
1039 }
1040 else if (strncasecmp(argv[2], "peripheral", len) == 0)
1041 {
1042 uint32_t reg;
1043
1044 if (!argNum(argc, 4))
1045 return;
1046
1047 reg = _samba.readWord(addr + PIO_ABSR);
1048 if (strcasecmp(argv[3], "a") == 0)
1049 reg &= ~line;
1050 else if (strcasecmp(argv[3], "b") == 0)
1051 reg |= line;
1052 else
1053 {
1054 error("Peripheral must be \"a\" or \"b\"");
1055 return;
1056 }
1057
1058 _samba.writeWord(addr + PIO_ABSR, reg);
1059 _samba.writeWord(addr + PIO_PDR, line);
1060
1061 printf("%s set to peripheral %s\n", argv[1], argv[3]);
1062 }
1063 else if (strncasecmp(argv[2], "pullup", len) == 0)
1064 {
1065 bool state;
1066 if (!argNum(argc, 4) ||
1067 !argState(argv[3], &state))
1068 return;
1069
1070 if (state)
1071 _samba.writeWord(addr + PIO_PUER, line);
1072 else
1073 _samba.writeWord(addr + PIO_PUDR, line);
1074 printf("%s pullup is %s\n", argv[1], argv[3]);
1075 }
1076 else if (strncasecmp(argv[2], "multidrive", len) == 0)
1077 {
1078 bool state;
1079 if (!argNum(argc, 4) ||
1080 !argState(argv[3], &state))
1081 return;
1082
1083 if (state)
1084 _samba.writeWord(addr + PIO_MDER, line);
1085 else
1086 _samba.writeWord(addr + PIO_MDDR, line);
1087 printf("%s multidrive is %s\n", argv[1], argv[3]);
1088 }
1089 else
1090 {
1091 printf("Invalid PIO operation\n");
1092 return;
1093 }
1094 }
1095
CommandRead()1096 CommandRead::CommandRead() :
1097 Command("read",
1098 "Read flash into a binary file.",
1099 "read [FILE] <COUNT> <OFFSET>\n"
1100 " FILE -- file name on host filesystem\n"
1101 " COUNT -- (optional) count of bytes to read, defaults\n"
1102 " to entire flash if not given\n"
1103 " OFFSET -- (optional) start read operation at flash OFFSET\n"
1104 " OFFSET must be aligned to a flash page boundary")
1105 {}
1106
1107 void
invoke(char * argv[],int argc)1108 CommandRead::invoke(char* argv[], int argc)
1109 {
1110 uint32_t count = 0;
1111 uint32_t offset = 0;
1112
1113 if (!argRange(argc, 2, 4) ||
1114 (argc >= 3 && !argUint32(argv[2], &count)) ||
1115 (argc >= 4 && !argUint32(argv[3], &offset)) ||
1116 !flashable())
1117 return;
1118
1119 printf("count:%d offset:%d\n", count, offset);
1120
1121 _flasher.read(argv[1], count, offset);
1122
1123 printf("\nRead successful\n");
1124 }
1125
CommandSecurity()1126 CommandSecurity::CommandSecurity() :
1127 Command("security",
1128 "Enable the security flag.",
1129 "security")
1130 {}
1131
1132 void
invoke(char * argv[],int argc)1133 CommandSecurity::invoke(char* argv[], int argc)
1134 {
1135 if (!argNum(argc, 1) ||
1136 !flashable())
1137 return;
1138
1139 _flash->setSecurity();
1140 }
1141
CommandUnlock()1142 CommandUnlock::CommandUnlock() :
1143 Command("unlock",
1144 "Clear lock bits in the flash.",
1145 "unlock <BITS>"
1146 " BITS -- (optional) comma separated list of bits,"
1147 " all bits if not given\n")
1148 {}
1149
1150 void
invoke(char * argv[],int argc)1151 CommandUnlock::invoke(char* argv[], int argc)
1152 {
1153 string bits;
1154
1155 if (!flashable())
1156 return;
1157
1158 for (int argn = 1; argn < argc; argn++)
1159 bits += argv[argn];
1160
1161 _flasher.lock(bits, false);
1162 printf("Unlocked regions %s", bits.c_str());
1163 }
1164
CommandVerify()1165 CommandVerify::CommandVerify() :
1166 Command("verify",
1167 "Verify binary file with the flash.",
1168 "verify [FILE] <OFFSET>\n"
1169 " FILE -- file name on host filesystem\n"
1170 " OFFSET -- (optional) start verify operation at flash OFFSET\n"
1171 " OFFSET must be aligned to a flash page boundary")
1172 {}
1173
1174 void
invoke(char * argv[],int argc)1175 CommandVerify::invoke(char* argv[], int argc)
1176 {
1177 uint32_t offset = 0;
1178 uint32_t pageErrors;
1179 uint32_t totalErrors;
1180
1181 if (!argRange(argc, 2, 3) ||
1182 (argc >= 3 && !argUint32(argv[2], &offset)) ||
1183 !flashable())
1184 return;
1185
1186 if (!_flasher.verify(argv[1], pageErrors, totalErrors, offset))
1187 {
1188 printf("\nVerify failed\nPage errors: %d\nByte errors: %d\n",
1189 pageErrors, totalErrors);
1190 return;
1191 }
1192
1193 printf("\nVerify successful\n");
1194 }
1195
CommandWrite()1196 CommandWrite::CommandWrite() :
1197 Command("write",
1198 "Write binary file into flash.",
1199 "write [FILE] <OFFSET>\n"
1200 " FILE -- file name on host filesystem\n"
1201 " OFFSET -- (optional) start write operation at flash OFFSET\n"
1202 " OFFSET must be aligned to a flash page boundary")
1203 {}
1204
1205 void
invoke(char * argv[],int argc)1206 CommandWrite::invoke(char* argv[], int argc)
1207 {
1208 uint32_t offset = 0;
1209
1210 if (!argRange(argc, 2, 3) ||
1211 (argc >= 3 && !argUint32(argv[2], &offset)) ||
1212 !flashable())
1213 return;
1214
1215 _flasher.write(argv[1], offset);
1216
1217 printf("\nWrite successful\n");
1218 }
1219
CommandReset()1220 CommandReset::CommandReset() :
1221 Command("reset",
1222 "Reset the CPU. (only for supported CPU)",
1223 "reset\n")
1224 {}
1225
1226 void
invoke(char * argv[],int argc)1227 CommandReset::invoke(char* argv[], int argc)
1228 {
1229 _device.reset();
1230 }
1231
CommandOptions()1232 CommandOptions::CommandOptions() :
1233 Command("options",
1234 "Write options to flash.",
1235 "options\n")
1236 {}
1237
1238 void
invoke(char * argv[],int argc)1239 CommandOptions::invoke(char* argv[], int argc)
1240 {
1241 _flash->writeOptions();
1242 }
1243
1244