1 /* control utility for the Calypso bootloader */
3 /* (C) 2010 by Ingo Albrecht <prom@berlin.ccc.de>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
31 #include <arpa/inet.h>
35 #include <sys/socket.h>
38 #include <osmocore/msgb.h>
39 #include <osmocore/select.h>
40 #include <osmocore/timer.h>
41 #include <osmocore/crc16.h>
43 #include <loader/protocol.h>
47 #define MEM_MSG_MAX (MSGB_MAX - 16)
49 #define DEFAULT_SOCKET "/tmp/osmocom_loader"
51 static struct bsc_fd connection;
56 STATE_DUMP_IN_PROGRESS,
57 STATE_LOAD_IN_PROGRESS,
58 STATE_FLASHRANGE_GET_INFO,
59 STATE_FLASHRANGE_IN_PROGRESS,
60 STATE_PROGRAM_GET_INFO,
61 STATE_PROGRAM_IN_PROGRESS,
74 unsigned char print_requests;
75 unsigned char print_replies;
77 /* quit flag for main loop */
80 /* main state machine */
83 /* pending query command */
87 struct timer_list timeout;
89 /* binary i/o for firmware images */
91 /* buffer containing binfile data */
94 /* memory operation state */
95 uint8_t memchip; /* target chip (for flashes) */
96 uint32_t membase; /* target base address of operation */
97 uint32_t memlen; /* length of entire operation */
98 uint32_t memoff; /* offset for next request */
99 uint16_t memcrc; /* crc for current request */
100 uint16_t memreq; /* length of current request */
102 /* array of all flash blocks */
103 uint8_t flashcommand;
105 struct flashblock blocks[512];
108 static int usage(const char *name)
110 printf("Usage: %s [ -v | -h ] [ -d tr ] [ -m {c123,c155} ] [ -l /tmp/osmocom_loader ] COMMAND ...\n", name);
112 puts("\n Memory commands:");
113 puts(" memget <hex-address> <hex-length> - Peek at memory");
114 puts(" memput <hex-address> <hex-bytes> - Poke at memory");
115 puts(" memdump <hex-address> <hex-length> <file>- Dump memory to file");
116 puts(" memload <hex-address> <file> - Load file into memory");
118 puts("\n Flash commands:");
119 puts(" finfo - Information about flash chips");
120 puts(" funlock <address> <length> - Unlock flash block");
121 puts(" flock <address> <length> - Lock flash block");
122 puts(" flockdown <address> <length> - Lock down flash block");
123 puts(" fgetlock <address> <length> - Get locking state of block");
124 puts(" ferase <address> <length> - Erase flash range");
125 puts(" fprogram <chip> <address> <file> - Program file into flash");
127 puts("\n Execution commands:");
128 puts(" jump <hex-address> - Jump to address");
129 puts(" jumpflash - Jump to flash loader");
130 puts(" jumprom - Jump to rom loader");
132 puts("\n Device lifecycle:");
133 puts(" ping - Ping the loader");
134 puts(" reset - Reset device");
135 puts(" off - Power off device");
138 puts(" dump - Dump loader traffic to console");
143 static int version(const char *name)
145 //printf("\n%s version %s\n", name, VERSION);
149 static void hexdump(const uint8_t *data, unsigned int len)
151 const uint8_t *bufptr = data;
152 const uint8_t const *endptr = bufptr + len;
155 for (n=0; n < len; n+=32, bufptr += 32) {
157 for(m = 0; m < 32 && bufptr < endptr; m++, bufptr++) {
162 printf("%02x", *bufptr);
167 for(i = 0; i < n; i++) {
173 for(m = 0; m < 32 && bufptr < endptr; m++, bufptr++) {
174 if(isgraph(*bufptr)) {
187 loader_send_request(struct msgb *msg) {
189 u_int16_t len = htons(msg->len);
191 if(osmoload.print_requests) {
192 printf("Sending %d bytes:\n", msg->len);
193 hexdump(msg->data, msg->len);
196 rc = write(connection.fd, &len, sizeof(len));
197 if(rc != sizeof(len)) {
198 fprintf(stderr, "Error writing.\n");
202 rc = write(connection.fd, msg->data, msg->len);
204 fprintf(stderr, "Error writing.\n");
209 static void loader_do_memdump(uint16_t crc, void *address, size_t length);
210 static void loader_do_memload();
211 static void loader_do_fprogram();
212 static void loader_do_flashrange(uint8_t cmd, struct msgb *msg, uint8_t chip, uint32_t address, uint32_t status);
214 static void memop_timeout(void *dummy) {
215 switch(osmoload.state) {
216 case STATE_LOAD_IN_PROGRESS:
217 printf("Timeout. Repeating.");
218 osmoload.memoff -= osmoload.memreq;
228 loader_parse_flash_info(struct msgb *msg) {
231 nchips = msgb_get_u8(msg);
233 osmoload.numblocks = 0;
236 for(chip = 0; chip < nchips; chip++) {
239 address = msgb_get_u32(msg);
242 chipsize = msgb_get_u32(msg);
245 nregions = msgb_get_u8(msg);
247 printf(" chip %d at 0x%8.8x of %d bytes in %d regions\n", chip, address, chipsize, nregions);
249 uint32_t curoffset = 0;
251 for(region = 0; region < nregions; region++) {
252 uint16_t blockcount = msgb_get_u32(msg);
253 uint32_t blocksize = msgb_get_u32(msg);
255 printf(" region %d with %d blocks of %d bytes each\n", region, blockcount, blocksize);
258 for(block = 0; block < blockcount; block++) {
259 osmoload.blocks[osmoload.numblocks].fb_chip = chip;
260 osmoload.blocks[osmoload.numblocks].fb_offset = curoffset;
261 osmoload.blocks[osmoload.numblocks].fb_addr = address + curoffset;
262 osmoload.blocks[osmoload.numblocks].fb_size = blocksize;
264 printf(" block %d with %d bytes at 0x%8.8x on chip %d\n",
265 osmoload.numblocks, blocksize, address + curoffset, chip);
267 curoffset += blocksize;
269 osmoload.numblocks++;
277 loader_handle_reply(struct msgb *msg) {
278 if(osmoload.print_replies) {
279 printf("Received %d bytes:\n", msg->len);
280 hexdump(msg->data, msg->len);
283 uint8_t cmd = msgb_get_u8(msg);
296 address = msgb_get_u32(msg);
297 entrypoint = msgb_get_u32(msg);
298 printf("Loader at entry %x has been started, requesting load to %x\n", entrypoint, address);
302 case LOADER_POWEROFF:
303 case LOADER_ENTER_ROM_LOADER:
304 case LOADER_ENTER_FLASH_LOADER:
306 case LOADER_MEM_READ:
307 length = msgb_get_u8(msg);
308 crc = msgb_get_u16(msg);
309 address = msgb_get_u32(msg);
310 data = msgb_get(msg, length);
312 case LOADER_MEM_WRITE:
313 length = msgb_get_u8(msg);
314 crc = msgb_get_u16(msg);
315 address = msgb_get_u32(msg);
318 address = msgb_get_u32(msg);
320 case LOADER_FLASH_INFO:
322 case LOADER_FLASH_GETLOCK:
323 case LOADER_FLASH_ERASE:
324 case LOADER_FLASH_UNLOCK:
325 case LOADER_FLASH_LOCK:
326 case LOADER_FLASH_LOCKDOWN:
327 chip = msgb_get_u8(msg);
328 address = msgb_get_u32(msg);
329 status = msgb_get_u32(msg);
331 case LOADER_FLASH_PROGRAM:
332 length = msgb_get_u8(msg);
333 crc = msgb_get_u16(msg);
334 msgb_get_u8(msg); // XXX align
335 chip = msgb_get_u8(msg);
336 address = msgb_get_u32(msg);
337 status = msgb_get_u32(msg);
340 printf("Received unknown reply %d:\n", cmd);
341 hexdump(msg->data, msg->len);
346 switch(osmoload.state) {
347 case STATE_QUERY_PENDING:
351 printf("Received pong.\n");
354 printf("Reset confirmed.\n");
356 case LOADER_POWEROFF:
357 printf("Poweroff confirmed.\n");
359 case LOADER_ENTER_ROM_LOADER:
360 printf("Jump to ROM loader confirmed.\n");
362 case LOADER_ENTER_FLASH_LOADER:
363 printf("Jump to flash loader confirmed.\n");
365 case LOADER_MEM_READ:
366 printf("Received memory dump of %d bytes at 0x%x:\n", length, address);
367 hexdump(data, length);
369 case LOADER_MEM_WRITE:
370 printf("Confirmed memory write of %d bytes at 0x%x.\n", length, address);
373 printf("Confirmed jump to 0x%x.\n", address);
375 case LOADER_FLASH_ERASE:
376 printf("Confirmed flash erase of chip %d address 0x%8.8x, status %s\n",
377 chip, address, status ? "FAILED" : "ok");
379 case LOADER_FLASH_GETLOCK:
380 printf("Lock state of chip %d address 0x%8.8x is %s\n",
381 chip, address, (status == LOADER_FLASH_LOCKED ? "locked"
382 : (status == LOADER_FLASH_LOCKED_DOWN ? "locked down"
383 : (status == LOADER_FLASH_UNLOCKED ? "unlocked"
386 case LOADER_FLASH_UNLOCK:
387 printf("Confirmed flash unlock of chip %d address 0x%8.8x, status %s\n",
388 chip, address, status ? "FAILED" : "ok");
390 case LOADER_FLASH_LOCK:
391 printf("Confirmed flash lock of chip %d address 0x%8.8x, status %s\n",
392 chip, address, status ? "FAILED" : "ok");
394 case LOADER_FLASH_LOCKDOWN:
395 printf("Confirmed flash lockdown of chip %d address 0x%8.8x, status %s\n",
396 chip, address, status ? "FAILED" : "ok");
398 case LOADER_FLASH_INFO:
399 loader_parse_flash_info(msg);
404 if(osmoload.state == STATE_QUERY_PENDING) {
405 if(osmoload.command == cmd) {
410 case STATE_DUMP_IN_PROGRESS:
411 if(cmd == LOADER_MEM_READ) {
412 loader_do_memdump(crc, data, length);
415 case STATE_LOAD_IN_PROGRESS:
416 if(cmd == LOADER_MEM_WRITE) {
417 if(osmoload.memcrc != crc) {
418 osmoload.memoff -= osmoload.memreq;
419 printf("\nbad crc %4.4x (not %4.4x) at offset 0x%8.8x", crc, osmoload.memcrc, osmoload.memoff);
426 case STATE_PROGRAM_GET_INFO:
427 case STATE_PROGRAM_IN_PROGRESS:
428 if(cmd == LOADER_FLASH_PROGRAM) {
429 if(osmoload.memcrc != crc) {
430 osmoload.memoff -= osmoload.memreq;
431 printf("\nbad crc %4.4x (not %4.4x) at offset 0x%8.8x", crc, osmoload.memcrc, osmoload.memoff);
435 if(((int)status) != 0) {
436 printf("\nstatus %d, aborting\n", status);
439 loader_do_fprogram();
442 case STATE_FLASHRANGE_GET_INFO:
443 case STATE_FLASHRANGE_IN_PROGRESS:
444 loader_do_flashrange(cmd, msg, chip, address, status);
454 loader_read_cb(struct bsc_fd *fd, unsigned int flags) {
459 msg = msgb_alloc(MSGB_MAX, "loader");
461 fprintf(stderr, "Failed to allocate msg.\n");
465 rc = read(fd->fd, &len, sizeof(len));
466 if (rc < sizeof(len)) {
467 fprintf(stderr, "Short read. Error.\n");
471 if (ntohs(len) > MSGB_MAX) {
472 fprintf(stderr, "Length is too big: %u\n", ntohs(len));
477 /* blocking read for the poor... we can starve in here... */
478 msg->l2h = msgb_put(msg, ntohs(len));
479 rc = read(fd->fd, msg->l2h, msgb_l2len(msg));
480 if (rc != msgb_l2len(msg)) {
481 fprintf(stderr, "Can not read data: rc: %d errno: %d\n", rc, errno);
486 loader_handle_reply(msg);
494 loader_connect(const char *socket_path) {
496 struct sockaddr_un local;
497 struct bsc_fd *conn = &connection;
499 local.sun_family = AF_UNIX;
500 strncpy(local.sun_path, socket_path, sizeof(local.sun_path));
501 local.sun_path[sizeof(local.sun_path) - 1] = '\0';
503 conn->fd = socket(AF_UNIX, SOCK_STREAM, 0);
505 fprintf(stderr, "Failed to create unix domain socket.\n");
509 rc = connect(conn->fd, (struct sockaddr *) &local,
510 sizeof(local.sun_family) + strlen(local.sun_path));
512 fprintf(stderr, "Failed to connect to '%s'.\n", local.sun_path);
516 conn->when = BSC_FD_READ;
517 conn->cb = loader_read_cb;
520 if (bsc_register_fd(conn) != 0) {
521 fprintf(stderr, "Failed to register fd.\n");
527 loader_send_simple(uint8_t command) {
528 struct msgb *msg = msgb_alloc(MSGB_MAX, "loader");
529 msgb_put_u8(msg, command);
530 loader_send_request(msg);
533 osmoload.command = command;
537 loader_start_query(uint8_t command) {
538 loader_send_simple(command);
539 osmoload.state = STATE_QUERY_PENDING;
543 loader_send_flash_query(uint8_t command, uint8_t chip, uint32_t address) {
544 struct msgb *msg = msgb_alloc(MSGB_MAX, "loader");
545 msgb_put_u8(msg, command);
546 msgb_put_u8(msg, chip);
547 msgb_put_u32(msg, address);
548 loader_send_request(msg);
551 osmoload.command = command;
555 loader_start_flash_query(uint8_t command, uint8_t chip, uint32_t address) {
556 loader_send_flash_query(command, chip, address);
557 osmoload.state = STATE_QUERY_PENDING;
561 loader_start_memget(uint8_t length, uint32_t address) {
562 struct msgb *msg = msgb_alloc(MSGB_MAX, "loader");
563 msgb_put_u8(msg, LOADER_MEM_READ);
564 msgb_put_u8(msg, length);
565 msgb_put_u32(msg, address);
566 loader_send_request(msg);
569 osmoload.state = STATE_QUERY_PENDING;
570 osmoload.command = LOADER_MEM_READ;
574 loader_start_memput(uint8_t length, uint32_t address, void *data) {
575 struct msgb *msg = msgb_alloc(MSGB_MAX, "loader");
576 msgb_put_u8(msg, LOADER_MEM_WRITE);
577 msgb_put_u8(msg, length);
578 msgb_put_u16(msg, crc16(0, data, length));
579 msgb_put_u32(msg, address);
580 memcpy(msgb_put(msg, length), data, length);
581 loader_send_request(msg);
584 osmoload.state = STATE_QUERY_PENDING;
585 osmoload.command = LOADER_MEM_WRITE;
589 loader_start_jump(uint32_t address) {
590 struct msgb *msg = msgb_alloc(MSGB_MAX, "loader");
591 msgb_put_u8(msg, LOADER_JUMP);
592 msgb_put_u32(msg, address);
593 loader_send_request(msg);
596 osmoload.state = STATE_QUERY_PENDING;
597 osmoload.command = LOADER_JUMP;
602 loader_do_memdump(uint16_t crc, void *data, size_t length) {
606 osmoload.memcrc = crc16(0, data, length);
607 if(osmoload.memcrc != crc) {
608 osmoload.memoff -= osmoload.memreq;
609 printf("\nbad crc %4.4x (not %4.4x) at offset 0x%8.8x", crc, osmoload.memcrc, osmoload.memoff);
614 memcpy(osmoload.binbuf + osmoload.memoff, data, length);
615 osmoload.memoff += length;
618 uint32_t rembytes = osmoload.memlen - osmoload.memoff;
624 unsigned c = osmoload.memlen;
625 char *p = osmoload.binbuf;
627 rc = fwrite(p, 1, c, osmoload.binfile);
628 if(ferror(osmoload.binfile)) {
629 printf("Could not read from file: %s\n", strerror(errno));
635 fclose(osmoload.binfile);
636 osmoload.binfile = NULL;
638 free(osmoload.binbuf);
643 uint8_t reqbytes = (rembytes < MEM_MSG_MAX) ? rembytes : MEM_MSG_MAX;
645 struct msgb *msg = msgb_alloc(MSGB_MAX, "loader");
647 msgb_put_u8(msg, LOADER_MEM_READ);
648 msgb_put_u8(msg, reqbytes);
649 msgb_put_u32(msg, osmoload.membase + osmoload.memoff);
650 loader_send_request(msg);
655 loader_do_memload() {
656 uint32_t rembytes = osmoload.memlen - osmoload.memoff;
664 bsc_schedule_timer(&osmoload.timeout, 0, 500000);
666 uint8_t reqbytes = (rembytes < MEM_MSG_MAX) ? rembytes : MEM_MSG_MAX;
668 osmoload.memcrc = crc16(0, (uint8_t *) osmoload.binbuf + osmoload.memoff, reqbytes);
669 osmoload.memreq = reqbytes;
671 struct msgb *msg = msgb_alloc(MSGB_MAX, "loader");
673 msgb_put_u8(msg, LOADER_MEM_WRITE);
674 msgb_put_u8(msg, reqbytes);
675 msgb_put_u16(msg, osmoload.memcrc);
676 msgb_put_u32(msg, osmoload.membase + osmoload.memoff);
678 unsigned char *p = msgb_put(msg, reqbytes);
679 memcpy(p, osmoload.binbuf + osmoload.memoff, reqbytes);
682 printf("Sending %u bytes at offset %u to address %x with crc %x\n",
683 reqbytes, osmoload.memoff, osmoload.membase + osmoload.memoff,
687 loader_send_request(msg);
691 osmoload.memoff += reqbytes;
695 loader_do_fprogram() {
696 uint32_t rembytes = osmoload.memlen - osmoload.memoff;
704 bsc_schedule_timer(&osmoload.timeout, 0, 10000000);
706 uint8_t reqbytes = (rembytes < MEM_MSG_MAX) ? rembytes : MEM_MSG_MAX;
708 osmoload.memcrc = crc16(0, (uint8_t *) osmoload.binbuf + osmoload.memoff, reqbytes);
709 osmoload.memreq = reqbytes;
711 struct msgb *msg = msgb_alloc(MSGB_MAX, "loader");
713 msgb_put_u8(msg, LOADER_FLASH_PROGRAM);
714 msgb_put_u8(msg, reqbytes);
715 msgb_put_u16(msg, osmoload.memcrc);
716 msgb_put_u8(msg, 0); // XXX: align data to 16bit
717 msgb_put_u8(msg, osmoload.memchip);
718 msgb_put_u32(msg, osmoload.membase + osmoload.memoff);
720 unsigned char *p = msgb_put(msg, reqbytes);
721 memcpy(p, osmoload.binbuf + osmoload.memoff, reqbytes);
724 printf("Sending %u bytes at offset %u to address %x with crc %x\n",
725 reqbytes, osmoload.memoff, osmoload.membase + osmoload.memoff,
729 loader_send_request(msg);
733 osmoload.memoff += reqbytes;
737 loader_start_memdump(uint32_t length, uint32_t address, char *file) {
738 printf("Dumping %u bytes of memory at 0x%x to file %s\n", length, address, file);
740 osmoload.binbuf = malloc(length);
741 if(!osmoload.binbuf) {
742 printf("Could not allocate %u bytes for %s.\n", length, file);
746 osmoload.binfile = fopen(file, "wb");
747 if(!osmoload.binfile) {
748 printf("Could not open %s: %s\n", file, strerror(errno));
752 osmoload.membase = address;
753 osmoload.memlen = length;
756 osmoload.state = STATE_DUMP_IN_PROGRESS;
757 loader_do_memdump(0, NULL, 0);
761 loader_start_memload(uint32_t address, char *file) {
765 rc = stat(file, &st);
767 printf("Could not stat %s: %s\n", file, strerror(errno));
771 uint32_t length = st.st_size;
773 printf("Loading %u bytes of memory to address 0x%x from file %s\n", length, address, file);
775 osmoload.binbuf = malloc(length);
776 if(!osmoload.binbuf) {
777 printf("Could not allocate %u bytes for %s.\n", length, file);
781 osmoload.binfile = fopen(file, "rb");
782 if(!osmoload.binfile) {
783 printf("Could not open %s: %s\n", file, strerror(errno));
788 char *p = osmoload.binbuf;
790 rc = fread(p, 1, c, osmoload.binfile);
791 if(ferror(osmoload.binfile)) {
792 printf("Could not read from file: %s\n", strerror(errno));
798 fclose(osmoload.binfile);
799 osmoload.binfile = NULL;
801 osmoload.membase = address;
802 osmoload.memlen = length;
805 osmoload.state = STATE_LOAD_IN_PROGRESS;
810 loader_start_flashrange(uint8_t command, uint32_t address, uint32_t length) {
812 case LOADER_FLASH_ERASE:
813 printf("Erasing %u bytes of flash at 0x%x\n", length, address);
815 case LOADER_FLASH_LOCK:
816 printf("Locking %u bytes of flash at 0x%x\n", length, address);
818 case LOADER_FLASH_LOCKDOWN:
819 printf("Locking down %u bytes of flash at 0x%x\n", length, address);
821 case LOADER_FLASH_UNLOCK:
822 printf("Unlocking %u bytes of flash at 0x%x\n", length, address);
824 case LOADER_FLASH_GETLOCK:
825 printf("Getlocking %u bytes of flash at 0x%x\n", length, address);
828 puts("Unknown range command");
833 osmoload.flashcommand = command;
835 osmoload.membase = address;
836 osmoload.memlen = length;
839 printf(" requesting flash info to determine block layout\n");
841 osmoload.state = STATE_FLASHRANGE_GET_INFO;
843 loader_send_simple(LOADER_FLASH_INFO);
847 loader_do_flashrange(uint8_t cmd, struct msgb *msg, uint8_t chip, uint32_t address, uint32_t status) {
848 switch(osmoload.state) {
849 case STATE_FLASHRANGE_GET_INFO:
850 if(cmd == LOADER_FLASH_INFO) {
851 loader_parse_flash_info(msg);
852 osmoload.state = STATE_FLASHRANGE_IN_PROGRESS;
853 loader_do_flashrange(0, NULL, 0, 0, 0);
856 case STATE_FLASHRANGE_IN_PROGRESS:
859 if(cmd == osmoload.flashcommand) {
860 if(cmd == LOADER_FLASH_GETLOCK) {
861 printf(" lock state of chip %d address 0x%8.8x is %s\n",
862 chip, address, (status == LOADER_FLASH_LOCKED ? "locked"
863 : (status == LOADER_FLASH_LOCKED_DOWN ? "locked down"
864 : (status == LOADER_FLASH_UNLOCKED ? "unlocked"
867 printf(" confirmed operation on chip %d address 0x%8.8x, status %s\n",
868 chip, address, status ? "FAILED" : "ok");
875 uint32_t addr = osmoload.membase + osmoload.memoff;
877 if(osmoload.memoff >= osmoload.memlen) {
878 puts(" operation done");
885 for(i = 0; i < osmoload.numblocks; i++) {
886 struct flashblock *b = &osmoload.blocks[i];
887 if(b->fb_addr == addr) {
888 loader_send_flash_query(osmoload.flashcommand, b->fb_chip, b->fb_offset);
889 osmoload.memoff += b->fb_size;
895 puts("Oops!? Block not found?"); // XXX message
904 loader_start_fprogram(uint8_t chip, uint32_t address, char *file) {
908 rc = stat(file, &st);
910 printf("Could not stat %s: %s\n", file, strerror(errno));
914 uint32_t length = st.st_size;
916 printf("Loading %u bytes of memory at 0x%x in chip %d from file %s\n", length, address, chip, file);
918 osmoload.binbuf = malloc(length);
919 if(!osmoload.binbuf) {
920 printf("Could not allocate %u bytes for %s.\n", length, file);
924 osmoload.binfile = fopen(file, "rb");
925 if(!osmoload.binfile) {
926 printf("Could not open %s: %s\n", file, strerror(errno));
931 char *p = osmoload.binbuf;
933 rc = fread(p, 1, c, osmoload.binfile);
934 if(ferror(osmoload.binfile)) {
935 printf("Could not read from file: %s\n", strerror(errno));
941 fclose(osmoload.binfile);
942 osmoload.binfile = NULL;
944 osmoload.memchip = chip;
945 osmoload.membase = address;
946 osmoload.memlen = length;
949 osmoload.state = STATE_PROGRAM_IN_PROGRESS;
951 loader_do_fprogram();
955 query_timeout(void *dummy) {
956 puts("Query timed out.");
961 loader_command(char *name, int cmdc, char **cmdv) {
968 char buf[MEM_MSG_MAX];
969 memset(buf, 23, sizeof(buf));
971 if(!strcmp(cmd, "dump")) {
972 osmoload.state = STATE_DUMPING;
973 } else if(!strcmp(cmd, "ping")) {
974 loader_start_query(LOADER_PING);
975 } else if(!strcmp(cmd, "off")) {
976 loader_start_query(LOADER_POWEROFF);
977 } else if(!strcmp(cmd, "reset")) {
978 loader_start_query(LOADER_RESET);
979 } else if(!strcmp(cmd, "jumprom")) {
980 loader_start_query(LOADER_ENTER_ROM_LOADER);
981 } else if(!strcmp(cmd, "jumpflash")) {
982 loader_start_query(LOADER_ENTER_FLASH_LOADER);
983 } else if(!strcmp(cmd, "finfo")) {
984 puts("Requesting flash layout info");
985 loader_start_query(LOADER_FLASH_INFO);
986 } else if(!strcmp(cmd, "memput")) {
993 address = strtoul(cmdv[1], NULL, 16);
998 puts("Invalid hex string.");
1001 for(i = 0; i <= sizeof(buf) && i < strlen(hex)/2; i++) {
1002 if(i >= sizeof(buf)) {
1003 puts("Value too long for single message");
1007 int count = sscanf(hex + i * 2, "%02x", &byte);
1009 puts("Invalid hex string.");
1012 buf[i] = byte & 0xFF;
1015 loader_start_memput(i & 0xFF, address, buf);
1016 } else if(!strcmp(cmd, "memget")) {
1024 address = strtoul(cmdv[1], NULL, 16);
1025 length = strtoul(cmdv[2], NULL, 16);
1027 if(length > MEM_MSG_MAX) {
1028 puts("Too many bytes");
1032 loader_start_memget(length, address);
1033 } else if(!strcmp(cmd, "jump")) {
1040 address = strtoul(cmdv[1], NULL, 16);
1042 loader_start_jump(address);
1043 } else if(!strcmp(cmd, "memdump")) {
1051 address = strtoul(cmdv[1], NULL, 16);
1052 length = strtoul(cmdv[2], NULL, 16);
1054 loader_start_memdump(length, address, cmdv[3]);
1055 } else if(!strcmp(cmd, "memload")) {
1062 address = strtoul(cmdv[1], NULL, 16);
1064 loader_start_memload(address, cmdv[2]);
1065 } else if(!strcmp(cmd, "fprogram")) {
1073 chip = strtoul(cmdv[1], NULL, 10);
1074 address = strtoul(cmdv[2], NULL, 16);
1076 loader_start_fprogram(chip, address, cmdv[3]);
1077 } else if(!strcmp(cmd, "ferase")) {
1085 address = strtoul(cmdv[1], NULL, 16);
1086 length = strtoul(cmdv[2], NULL, 16);
1088 loader_start_flashrange(LOADER_FLASH_ERASE, address, length);
1089 } else if(!strcmp(cmd, "flock")) {
1097 address = strtoul(cmdv[1], NULL, 16);
1098 length = strtoul(cmdv[2], NULL, 16);
1100 loader_start_flashrange(LOADER_FLASH_LOCK, address, length);
1101 } else if(!strcmp(cmd, "flockdown")) {
1109 address = strtoul(cmdv[1], NULL, 16);
1110 length = strtoul(cmdv[2], NULL, 16);
1112 loader_start_flashrange(LOADER_FLASH_LOCKDOWN, address, length);
1113 } else if(!strcmp(cmd, "funlock")) {
1121 address = strtoul(cmdv[1], NULL, 16);
1122 length = strtoul(cmdv[2], NULL, 16);
1124 loader_start_flashrange(LOADER_FLASH_UNLOCK, address, length);
1125 } else if(!strcmp(cmd, "fgetlock")) {
1133 address = strtoul(cmdv[1], NULL, 16);
1134 length = strtoul(cmdv[2], NULL, 16);
1136 loader_start_flashrange(LOADER_FLASH_GETLOCK, address, length);
1137 } else if(!strcmp(cmd, "help")) {
1140 printf("Unknown command '%s'\n", cmd);
1144 if(osmoload.state == STATE_QUERY_PENDING) {
1145 osmoload.timeout.cb = &query_timeout;
1146 bsc_schedule_timer(&osmoload.timeout, 0, 5000000);
1148 if(osmoload.state == STATE_LOAD_IN_PROGRESS) {
1149 osmoload.timeout.cb = &memop_timeout;
1155 setdebug(const char *name, char c) {
1158 osmoload.print_requests = 1;
1161 osmoload.print_replies = 1;
1170 main(int argc, char **argv) {
1172 char *loader_un_path = "/tmp/osmocom_loader";
1173 const char *debugopt;
1175 while((opt = getopt(argc, argv, "d:hl:m:v")) != -1) {
1180 setdebug(argv[0], *debugopt);
1185 loader_un_path = optarg;
1188 puts("model selection not implemented");
1203 loader_connect(loader_un_path);
1205 loader_command(argv[0], argc - optind, argv + optind);
1207 while(!osmoload.quit) {
1211 if(osmoload.binfile) {
1212 fclose(osmoload.binfile);