Loader with memory read/write and various lifecycle operations.
authorIngo Albrecht <prom@berlin.ccc.de>
Sun, 7 Mar 2010 08:52:28 +0000 (09:52 +0100)
committerIngo Albrecht <prom@berlin.ccc.de>
Tue, 20 Jul 2010 12:41:19 +0000 (14:41 +0200)
src/host/osmocon/osmoload.c
src/target/firmware/apps/loader/main.c
src/target/firmware/apps/loader/protocol.h

index ecee8b3..9b0f0ec 100644 (file)
 
 static struct bsc_fd connection;
 
+static struct {
+       unsigned char quit;
+} osmoload;
+
 static int usage(const char *name)
 {
        printf("\nUsage: %s [ -v | -h ] [ -m {c123,c155} ] [ -l /tmp/osmocom_loader ] COMMAND\n", name);
@@ -67,8 +71,51 @@ loader_send_request(struct msgb *msg) {
 
 static void
 loader_handle_reply(struct msgb *msg) {
-       printf("Received ");
-       hexdump(msg->data, msg->len);
+       uint8_t cmd = msgb_get_u8(msg);
+
+       uint8_t length;
+       uint32_t address;
+
+       switch(cmd) {
+       case LOADER_PING:
+               printf("Received pong.\n");
+               osmoload.quit = 1;
+               break;
+       case LOADER_RESET:
+               printf("Reset confirmed.\n");
+               osmoload.quit = 1;
+               break;
+       case LOADER_POWEROFF:
+               printf("Poweroff confirmed.\n");
+               osmoload.quit = 1;
+               break;
+       case LOADER_ENTER_ROM_LOADER:
+               printf("Jump to ROM loader confirmed.\n");
+               osmoload.quit = 1;
+               break;
+       case LOADER_ENTER_FLASH_LOADER:
+               printf("Jump to flash loader confirmed.\n");
+               osmoload.quit = 1;
+               break;
+       case LOADER_MEM_READ:
+               length = msgb_get_u8(msg);
+               address = msgb_get_u32(msg);
+               printf("Received memory dump of %d bytes at 0x%x:\n", length, address);
+               hexdump(msgb_get(msg, length), length);
+               osmoload.quit = 1;
+               break;
+       case LOADER_MEM_WRITE:
+               length = msgb_get_u8(msg);
+               address = msgb_get_u32(msg);
+               printf("Confirmed memory write of %d bytes at 0x%x.\n", length, address);
+               osmoload.quit = 1;
+               break;
+       default:
+               printf("Received unknown reply for command %d:\n");
+               hexdump(msg->data, msg->len);
+               osmoload.quit = 1;
+               break;
+       }
 }
 
 static int
@@ -144,22 +191,63 @@ loader_connect(const char *socket_path) {
        }
 }
 
+static void
+loader_send_simple(uint8_t command) {
+       struct msgb *msg = msgb_alloc(MSGB_MAX, "loader");
+       msgb_put_u8(msg, command);
+       loader_send_request(msg);
+       msgb_free(msg);
+}
+
+static void
+loader_send_memread(uint8_t length, uint32_t address) {
+       struct msgb *msg = msgb_alloc(MSGB_MAX, "loader");
+       msgb_put_u8(msg, LOADER_MEM_READ);
+       msgb_put_u8(msg, 128);
+       msgb_put_u32(msg, 0x00810000);
+       loader_send_request(msg);
+       msgb_free(msg);
+}
+
+static void
+loader_send_memwrite(uint8_t length, uint32_t address, void *data) {
+       struct msgb *msg = msgb_alloc(MSGB_MAX, "loader");
+       msgb_put_u8(msg, LOADER_MEM_WRITE);
+       msgb_put_u8(msg, length);
+       msgb_put_u32(msg, address);
+       memcpy(msgb_put(msg, 128), data, length);
+       loader_send_request(msg);
+       msgb_free(msg);
+}
+
 static void
 loader_command(char *name, int cmdc, char **cmdv) {
        if(!cmdc) {
                usage(name);
        }
 
+       struct msgb *msg;
        char *cmd = cmdv[0];
 
+       char buf[256];
+       memset(buf, 23, sizeof(buf));
+
        printf("Command %s\n", cmd);
 
        if(!strcmp(cmd, "ping")) {
-               struct msgb *msg = msgb_alloc(MSGB_MAX, "loader");
-               msgb_put_u8(msg, LOADER_PING);
-               msgb_put_u8(msg, 0);
-               loader_send_request(msg);
-               msgb_free(msg);
+               loader_send_simple(LOADER_PING);
+       } else if(!strcmp(cmd, "memread")) {
+               loader_send_memread(128, 0x810000);
+       } else if(!strcmp(cmd, "memwrite")) {
+               loader_send_memwrite(128, 0x810000, buf);
+       } else if(!strcmp(cmd, "off")) {
+               loader_send_simple(LOADER_POWEROFF);
+       } else if(!strcmp(cmd, "reset")) {
+               loader_send_simple(LOADER_RESET);
+       } else if(!strcmp(cmd, "romload")) {
+               loader_send_simple(LOADER_ENTER_ROM_LOADER);
+       } else if(!strcmp(cmd, "flashload")) {
+               loader_send_simple(LOADER_ENTER_FLASH_LOADER);
        } else {
                printf("Unknown command '%s'\n", cmd);
                usage(name);
@@ -190,9 +278,15 @@ main(int argc, char **argv) {
                }
        }
 
+       osmoload.quit = 0;
+
        loader_connect(loader_un_path);
 
        loader_command(argv[0], argc - optind, argv + optind);
 
+       while(!osmoload.quit) {
+               bsc_select_main(0);
+       }
+
        return 0;
 }
index 794b05f..c1498a2 100644 (file)
@@ -57,37 +57,6 @@ struct loader_mem_read {
        uint8_t  data[0];
 } __attribute__((__packed__));
 
-uint32_t htonl(uint32_t hostlong) {
-#if BYTE_ORDER==LITTLE_ENDIAN
-  return (hostlong>>24) | ((hostlong&0xff0000)>>8) |
-          ((hostlong&0xff00)<<8) | (hostlong<<24);
-#else
-  return hostlong;
-#endif
-}
-
-uint32_t ntohl(uint32_t hostlong) __attribute__((weak,alias("htonl")));
-
-uint16_t htons(uint16_t hostshort) {
-#if BYTE_ORDER==LITTLE_ENDIAN
-  return ((hostshort>>8)&0xff) | (hostshort<<8);
-#else
-  return hostshort;
-#endif
-}
-
-uint16_t ntohs(uint16_t hostshort) __attribute__((weak,alias("htons")));
-
-#define SCAN
-
-#ifdef SCAN
-/* if scanning is enabled, scan from 0 ... 124 */
-#define BASE_ARFCN     0
-#else
-/* fixed ARFCN in GSM1800 at which Harald has his GSM test license */
-#define BASE_ARFCN     871
-#endif
-
 /* Main Program */
 const char *hr = "======================================================================\n";
 
@@ -96,15 +65,45 @@ static void cmd_handler(uint8_t dlci, struct msgb *msg);
 
 int flag = 0;
 
-void poweroff(void) {
+static void flush_uart(void) {
        unsigned i;
-       for(i = 0; i < 10; i++) {
+       for(i = 0; i < 500; i++) {
                uart_poll(SERCOMM_UART_NR);
-               delay_ms(10);
+               delay_ms(1);
        }
+}
+
+static void device_poweroff(void) {
+       flush_uart();
        twl3025_power_off();
 }
 
+static void device_reset(void) {
+       flush_uart();
+       wdog_reset();
+}
+
+static void device_enter_loader(unsigned char bootrom) {
+       flush_uart();
+       puts("XXX: loader entry is broken\n");
+       return;
+
+       /* XXX: this is not working (with or without bootrom) */
+       calypso_bootrom(bootrom);
+       void (*entry)( void ) = (void (*)(void))0;
+       entry();
+}
+
+static void
+loader_send_simple(uint8_t dlci, uint8_t command) {
+       struct msgb *msg = sercomm_alloc_msgb(1);
+       if(!msg) {
+               puts("Failed to allocate message buffer!\n");
+       }
+       msgb_put_u8(msg, command);
+       sercomm_sendmsg(dlci, msg);
+}
+
 int main(void)
 {
        /* Always disable wdt (some platforms enable it on boot) */
@@ -121,7 +120,7 @@ int main(void)
        sercomm_init();
 
        /* Say hi */
-       puts("\n\nOSMOCOM Calypso loader\n");
+       puts("\n\nOSMOCOM Calypso loader (revision " GIT_REVISION ")\n");
        puts(hr);
 
        /* Set up a key handler for powering off */
@@ -130,6 +129,9 @@ int main(void)
        /* Set up loader communications */
        sercomm_register_rx_cb(SC_DLCI_LOADER, &cmd_handler);
 
+       /* Notify any running osmoload about our startup */
+       loader_send_simple(SC_DLCI_LOADER, LOADER_INIT);
+
        /* Wait for events */
        while (1) {
                keypad_poll();
@@ -146,13 +148,9 @@ static void cmd_handler(uint8_t dlci, struct msgb *msg) {
                return;
        }
 
-       uint8_t command = 0; //= msgb_get_u8(msg);
-
-       printf("command %u\n", command);
+       uint8_t command = msgb_get_u8(msg);
 
-       msgb_free(msg);
-
-       return;
+       printf("command %u: ", command);
 
        uint8_t  nbytes;
        uint32_t address;
@@ -162,12 +160,32 @@ static void cmd_handler(uint8_t dlci, struct msgb *msg) {
        switch(command) {
 
        case LOADER_PING:
+               puts("ping\n");
+               loader_send_simple(dlci, LOADER_PING);
+               break;
+
+       case LOADER_RESET:
+               puts("reset\n");
+               loader_send_simple(dlci, LOADER_RESET);
+               device_reset();
+               break;
 
-               printf("ping\n");
+       case LOADER_POWEROFF:
+               puts("poweroff\n");
+               loader_send_simple(dlci, LOADER_POWEROFF);
+               device_poweroff();
+               break;
 
-               //sercomm_sendmsg(dlci, msg);
-               //msg = NULL;
+       case LOADER_ENTER_ROM_LOADER:
+               puts("jump to rom loader\n");
+               loader_send_simple(dlci, LOADER_ENTER_ROM_LOADER);
+               device_enter_loader(1);
+               break;
 
+       case LOADER_ENTER_FLASH_LOADER:
+               puts("jump to flash loader\n");
+               loader_send_simple(dlci, LOADER_ENTER_FLASH_LOADER);
+               device_enter_loader(0);
                break;
 
        case LOADER_MEM_READ:
@@ -179,6 +197,10 @@ static void cmd_handler(uint8_t dlci, struct msgb *msg) {
 
                reply = sercomm_alloc_msgb(6 + nbytes);
 
+               if(!reply) {
+                       printf("Failed to allocate reply buffer!\n");
+               }
+
                msgb_put_u8(reply, LOADER_MEM_READ);
                msgb_put_u8(reply, nbytes);
                msgb_put_u32(reply, address);
@@ -189,11 +211,32 @@ static void cmd_handler(uint8_t dlci, struct msgb *msg) {
 
                break;
 
-       }
+       case LOADER_MEM_WRITE:
+
+               nbytes = msgb_get_u8(msg);
+               address = msgb_get_u32(msg);
+
+               printf("mem write %u @ %p\n", nbytes, (void*)address);
+
+               memcpy((void*)address, msgb_get(msg, nbytes), nbytes);
+
+               reply = sercomm_alloc_msgb(6);
+
+               if(!reply) {
+                       printf("Failed to allocate reply buffer!\n");
+               }
+
+               msgb_put_u8(reply, LOADER_MEM_WRITE);
+               msgb_put_u8(reply, nbytes);
+               msgb_put_u32(reply, address);
+
+               sercomm_sendmsg(dlci, reply);
+
+               break;
 
-       if(msg) {
-               msgb_free(msg);
        }
+
+       msgb_free(msg);
 }
 
 static void key_handler(enum key_codes code, enum key_states state)
@@ -203,7 +246,12 @@ static void key_handler(enum key_codes code, enum key_states state)
 
        switch (code) {
        case KEY_POWER:
-               poweroff();
+               puts("Powering off due to keypress.\n");
+               device_poweroff();
+               break;
+       case KEY_OK:
+               puts("Resetting due to keypress.\n");
+               device_reset();
                break;
        default:
                break;
index afbd239..f1cc4f4 100644 (file)
@@ -1,6 +1,11 @@
 
 enum loader_command {
+       LOADER_INIT,
        LOADER_PING,
+       LOADER_RESET,
+       LOADER_POWEROFF,
+       LOADER_ENTER_ROM_LOADER,
+       LOADER_ENTER_FLASH_LOADER,
        LOADER_MEM_READ,
        LOADER_MEM_WRITE,
 };