diff options
-rw-r--r-- | src/host/osmocon/Makefile.am | 6 | ||||
-rw-r--r-- | src/host/osmocon/osmoload.c | 198 | ||||
-rw-r--r-- | src/target/firmware/Makefile | 3 | ||||
-rw-r--r-- | src/target/firmware/apps/loader/main.c | 229 | ||||
-rw-r--r-- | src/target/firmware/apps/loader/protocol.h | 6 | ||||
-rw-r--r-- | src/target/firmware/include/comm/sercomm.h | 1 |
6 files changed, 439 insertions, 4 deletions
diff --git a/src/host/osmocon/Makefile.am b/src/host/osmocon/Makefile.am index eef09628..925a2ffc 100644 --- a/src/host/osmocon/Makefile.am +++ b/src/host/osmocon/Makefile.am @@ -3,10 +3,12 @@ AUTOMAKE_OPTIONS = foreign dist-bzip2 1.6 INCLUDES = $(all_includes) -I$(top_srcdir)/include AM_CFLAGS=-Wall $(LIBOSMOCORE_CFLAGS) -sbin_PROGRAMS = osmocon +sbin_PROGRAMS = osmocon osmoload # FIXME: sercomm needs to move into libosmocore or another shared lib -INCLUDES += -I../../target/firmware/include/comm -DHOST_BUILD +INCLUDES += -I../../target/firmware/include/comm -I../../target/firmware/apps -DHOST_BUILD osmocon_SOURCES = osmocon.c tpu_debug.c ../../target/firmware/comm/sercomm.c osmocon_LDADD = $(LIBOSMOCORE_LIBS) +osmoload_SOURCE = osmoload.c ../../target/firmware/comm/sercomm.c +osmoload_LDADD = $(LIBOSMOCORE_LIBS) diff --git a/src/host/osmocon/osmoload.c b/src/host/osmocon/osmoload.c new file mode 100644 index 00000000..2ee01249 --- /dev/null +++ b/src/host/osmocon/osmoload.c @@ -0,0 +1,198 @@ + +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <getopt.h> + +#include <arpa/inet.h> + +#include <sys/socket.h> +#include <sys/un.h> + +#include <osmocore/msgb.h> +#include <osmocore/select.h> + +#include <loader/protocol.h> + +#define MSGB_MAX 256 + +#define DEFAULT_SOCKET "/tmp/osmocom_loader" + +static struct bsc_fd connection; + +static int usage(const char *name) +{ + printf("\nUsage: %s [ -v | -h ] [ -m {c123,c155} ] [ -l /tmp/osmocom_loader ] COMMAND\n", name); + exit(2); +} + +static int version(const char *name) +{ + //printf("\n%s version %s\n", name, VERSION); + exit(2); +} + +static void hexdump(const uint8_t *data, unsigned int len) +{ + const uint8_t *bufptr = data; + int n; + + for (n=0; bufptr, n < len; n++, bufptr++) + printf("%02x ", *bufptr); + printf("\n"); +} + +static void +loader_send_request(struct msgb *msg) { + int rc; + u_int16_t len = htons(msg->len); + + printf("Sending %d bytes ", msg->len); + hexdump(msg->data, msg->len); + + rc = write(connection.fd, &len, sizeof(len)); + if(rc != sizeof(len)) { + fprintf(stderr, "Error writing.\n"); + exit(2); + } + + rc = write(connection.fd, msg->data, msg->len); + if(rc != msg->len) { + fprintf(stderr, "Error writing.\n"); + exit(2); + } +} + +static void +loader_handle_reply(struct msgb *msg) { + printf("Received "); + hexdump(msg->data, msg->len); +} + +static int +loader_read_cb(struct bsc_fd *fd, unsigned int flags) { + struct msgb *msg; + u_int16_t len; + int rc; + + msg = msgb_alloc(MSGB_MAX, "loader"); + if (!msg) { + fprintf(stderr, "Failed to allocate msg.\n"); + return -1; + } + + rc = read(fd->fd, &len, sizeof(len)); + if (rc < sizeof(len)) { + fprintf(stderr, "Short read. Error.\n"); + exit(2); + } + + if (ntohs(len) > MSGB_MAX) { + fprintf(stderr, "Length is too big: %u\n", ntohs(len)); + msgb_free(msg); + return -1; + } + + /* blocking read for the poor... we can starve in here... */ + msg->l2h = msgb_put(msg, ntohs(len)); + rc = read(fd->fd, msg->l2h, msgb_l2len(msg)); + if (rc != msgb_l2len(msg)) { + fprintf(stderr, "Can not read data: rc: %d errno: %d\n", rc, errno); + msgb_free(msg); + return -1; + } + + loader_handle_reply(msg); + + msgb_free(msg); + + return 0; +} + +static void +loader_connect(const char *socket_path) { + int rc; + struct sockaddr_un local; + struct bsc_fd *conn = &connection; + + local.sun_family = AF_UNIX; + strncpy(local.sun_path, socket_path, sizeof(local.sun_path)); + local.sun_path[sizeof(local.sun_path) - 1] = '\0'; + + conn->fd = socket(AF_UNIX, SOCK_STREAM, 0); + if (conn->fd < 0) { + fprintf(stderr, "Failed to create unix domain socket.\n"); + exit(1); + } + + rc = connect(conn->fd, (struct sockaddr *) &local, + sizeof(local.sun_family) + strlen(local.sun_path)); + if (rc < 0) { + fprintf(stderr, "Failed to connect to '%s'.\n", local.sun_path); + exit(1); + } + + conn->when = BSC_FD_READ; + conn->cb = loader_read_cb; + conn->data = NULL; + + if (bsc_register_fd(conn) != 0) { + fprintf(stderr, "Failed to register fd.\n"); + exit(1); + } +} + +static void +loader_command(char *name, int cmdc, char **cmdv) { + if(!cmdc) { + usage(name); + } + + char *cmd = cmdv[0]; + + 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); + } else { + printf("Unknown command '%s'\n", cmd); + usage(name); + } +} + +int +main(int argc, char **argv) { + int opt; + char *loader_un_path = "/tmp/osmocom_loader"; + + while((opt = getopt(argc, argv, "hl:m:v")) != -1) { + switch(opt) { + case 'l': + loader_un_path = optarg; + break; + case 'm': + puts("model selection not implemented"); + exit(2); + break; + case 'v': + version(argv[0]); + break; + case 'h': + default: + usage(argv[0]); + break; + } + } + + loader_connect(loader_un_path); + + loader_command(argv[0], argc - optind, argv + optind); + + return 0; +} diff --git a/src/target/firmware/Makefile b/src/target/firmware/Makefile index 06c4df40..d02d9404 100644 --- a/src/target/firmware/Makefile +++ b/src/target/firmware/Makefile @@ -13,8 +13,7 @@ BOARD_C123_OBJS=board/common/rffe_compal_dualband.o board/compal_e88/init.o START=board/common/compal_ramload_start.S LDS=board/common/compal_ramload.lds -# The objects that we want to link with every application -APPLICATIONS=hello_world l1test compal_dump compal_dsp_dump layer1 +APPLICATIONS=hello_world l1test compal_dump compal_dsp_dump layer1 loader # Things that go in all applications ANY_APP_OBJS+=$(START:.S=.o) $(ABB_OBJS) $(RF_OBJS) $(DISPLAY_OBJS) $(FLASH_OBJS) $(BOARD_C123_OBJS) diff --git a/src/target/firmware/apps/loader/main.c b/src/target/firmware/apps/loader/main.c new file mode 100644 index 00000000..777a1df8 --- /dev/null +++ b/src/target/firmware/apps/loader/main.c @@ -0,0 +1,229 @@ +/* boot loader for Calypso phones */ + +/* (C) 2010 by Ingo Albrecht <prom@berlin.ccc.de> + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include <stdint.h> +#include <stdio.h> +#include <string.h> + +#include <gsm.h> +#include <debug.h> +#include <memory.h> +#include <rffe.h> +#include <keypad.h> +#include <board.h> +#include <console.h> + +#include <abb/twl3025.h> +#include <display/st7558.h> +#include <rf/trf6151.h> + +#include <comm/sercomm.h> + +#include <calypso/clock.h> +#include <calypso/tpu.h> +#include <calypso/tsp.h> +#include <calypso/irq.h> +#include <calypso/misc.h> +#include <calypso/uart.h> +#include <calypso/timer.h> + +#include <layer1/sync.h> +#include <layer1/tpu_window.h> + +#include <machine/endian.h> + +#include "protocol.h" + +struct loader_mem_read { + uint8_t cmd; + uint8_t nbytes; + uint32_t address; + 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 + +/* FIXME: We need proper calibrated delay loops at some point! */ +void delay_us(unsigned int us) +{ + volatile unsigned int i; + + for (i= 0; i < us*4; i++) { i; } +} + +void delay_ms(unsigned int ms) +{ + volatile unsigned int i; + + for (i= 0; i < ms*1300; i++) { i; } +} + +/* Main Program */ +const char *hr = "======================================================================\n"; + +static void key_handler(enum key_codes code, enum key_states state); +static void cmd_handler(uint8_t dlci, struct msgb *msg); + +int flag = 0; + +void poweroff(void) { + unsigned i; + for(i = 0; i < 10; i++) { + uart_poll(SERCOMM_UART_NR); + delay_ms(10); + } + twl3025_power_off(); +} + +int main(void) +{ + /* Always disable wdt (some platforms enable it on boot) */ + wdog_enable(0); + + /* Initialize TWL3025 for power control */ + twl3025_init(); + + /* Initialize UART without interrupts */ + uart_init(SERCOMM_UART_NR, 0); + uart_baudrate(SERCOMM_UART_NR, UART_115200); + + /* Initialize HDLC subsystem */ + sercomm_init(); + + /* Say hi */ + puts("\n\nOSMOCOM Calypso loader\n"); + puts(hr); + + /* Set up a key handler for powering off */ + keypad_set_handler(&key_handler); + + /* Set up loader communications */ + sercomm_register_rx_cb(SC_DLCI_LOADER, &cmd_handler); + + /* Wait for events */ + while (1) { + keypad_poll(); + uart_poll(SERCOMM_UART_NR); + } + + /* NOT REACHED */ + + twl3025_power_off(); +} + +static void cmd_handler(uint8_t dlci, struct msgb *msg) { + if(msg->data_len < 1) { + return; + } + + uint8_t command = 0; //= msgb_get_u8(msg); + + printf("command %u\n", command); + + msgb_free(msg); + + return; + + uint8_t nbytes; + uint32_t address; + + struct msgb *reply; + + switch(command) { + + case LOADER_PING: + + printf("ping\n"); + + //sercomm_sendmsg(dlci, msg); + //msg = NULL; + + break; + + case LOADER_MEM_READ: + + nbytes = msgb_get_u8(msg); + address = msgb_get_u32(msg); + + printf("mem read %u @ %p\n", nbytes, (void*)address); + + reply = sercomm_alloc_msgb(6 + nbytes); + + msgb_put_u8(reply, LOADER_MEM_READ); + msgb_put_u8(reply, nbytes); + msgb_put_u32(reply, address); + + memcpy(msgb_put(reply, nbytes), (void*)address, nbytes); + + sercomm_sendmsg(dlci, reply); + + break; + + } + + if(msg) { + msgb_free(msg); + } +} + +static void key_handler(enum key_codes code, enum key_states state) +{ + if (state != PRESSED) + return; + + switch (code) { + case KEY_POWER: + poweroff(); + break; + default: + break; + } +} diff --git a/src/target/firmware/apps/loader/protocol.h b/src/target/firmware/apps/loader/protocol.h new file mode 100644 index 00000000..afbd2390 --- /dev/null +++ b/src/target/firmware/apps/loader/protocol.h @@ -0,0 +1,6 @@ + +enum loader_command { + LOADER_PING, + LOADER_MEM_READ, + LOADER_MEM_WRITE, +}; diff --git a/src/target/firmware/include/comm/sercomm.h b/src/target/firmware/include/comm/sercomm.h index 7ef964f4..e9f560e2 100644 --- a/src/target/firmware/include/comm/sercomm.h +++ b/src/target/firmware/include/comm/sercomm.h @@ -22,6 +22,7 @@ enum sercomm_dlci { SC_DLCI_HIGHEST = 0, SC_DLCI_DEBUG = 4, SC_DLCI_L1A_L23 = 5, + SC_DLCI_LOADER = 9, SC_DLCI_CONSOLE = 10, _SC_DLCI_MAX }; |