#include <console.h>
#include <manifest.h>
+#include <osmocore/crc16.h>
+
#include <abb/twl3025.h>
#include <rf/trf6151.h>
#include <calypso/uart.h>
#include <calypso/timer.h>
-#include <layer1/sync.h>
-#include <layer1/tpu_window.h>
+#include <cfi_flash.h>
#include "protocol.h"
-struct loader_mem_read {
- uint8_t cmd;
- uint8_t nbytes;
- uint32_t address;
- uint8_t data[0];
-} __attribute__((__packed__));
-
/* Main Program */
const char *hr = "======================================================================\n";
}
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");
- }
+loader_send_simple(struct msgb *msg, uint8_t dlci, uint8_t command) {
msgb_put_u8(msg, command);
sercomm_sendmsg(dlci, msg);
}
static void
loader_send_init(uint8_t dlci) {
- struct msgb *msg = sercomm_alloc_msgb(1);
- if(!msg) {
- puts("Failed to allocate message buffer!\n");
- }
+ struct msgb *msg = sercomm_alloc_msgb(9);
msgb_put_u8(msg, LOADER_INIT);
msgb_put_u32(msg, 0);
msgb_put_u32(msg, &_start);
sercomm_sendmsg(dlci, msg);
}
+flash_t the_flash;
+
+extern void puts_asm(char *s);
+extern void putchar_asm(uint32_t c);
+
+static const uint8_t phone_ack[] = { 0x1b, 0xf6, 0x02, 0x00, 0x41, 0x03, 0x42 };
+
int main(void)
{
+ int i = 0;
+ for(i = 0; i < sizeof(phone_ack); i++) {
+ putchar_asm(phone_ack[i]);
+ }
+
/* Always disable wdt (some platforms enable it on boot) */
wdog_enable(0);
/* Initialize TWL3025 for power control */
twl3025_init();
+ /* Backlight */
+ bl_mode_pwl(1);
+ bl_level(50);
+
/* Initialize UART without interrupts */
uart_init(SERCOMM_UART_NR, 0);
uart_baudrate(SERCOMM_UART_NR, UART_115200);
puts("\n\nOSMOCOM Calypso loader (revision " GIT_REVISION ")\n");
puts(hr);
+ /* Initialize flash driver */
+ if(flash_init(&the_flash, 0)) {
+ puts("Failed to initialize flash!\n");
+ }
+
/* Identify environment */
- printf("Running on %s in environment %s\n", target_board, target_environment);
+ printf("Running on %s in environment %s\n", manifest_board, manifest_environment);
/* Set up a key handler for powering off */
keypad_set_handler(&key_handler);
uint8_t command = msgb_get_u8(msg);
- printf("command %u: ", command);
+ int res;
+
+ flash_lock_t lock;
+
+ void *data;
+ uint8_t chip;
uint8_t nbytes;
+ uint16_t crc, mycrc;
uint32_t address;
- struct msgb *reply;
+ struct msgb *reply = sercomm_alloc_msgb(256); // XXX
+
+ if(!reply) {
+ printf("Failed to allocate reply buffer!\n");
+ goto out;
+ }
switch(command) {
case LOADER_PING:
- puts("ping\n");
- loader_send_simple(dlci, LOADER_PING);
+ loader_send_simple(reply, dlci, LOADER_PING);
break;
case LOADER_RESET:
- puts("reset\n");
- loader_send_simple(dlci, LOADER_RESET);
+ loader_send_simple(reply, dlci, LOADER_RESET);
device_reset();
break;
case LOADER_POWEROFF:
- puts("poweroff\n");
- loader_send_simple(dlci, LOADER_POWEROFF);
+ loader_send_simple(reply, dlci, LOADER_POWEROFF);
device_poweroff();
break;
case LOADER_ENTER_ROM_LOADER:
- puts("jump to rom loader\n");
- loader_send_simple(dlci, LOADER_ENTER_ROM_LOADER);
+ loader_send_simple(reply, 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);
+ loader_send_simple(reply, dlci, LOADER_ENTER_FLASH_LOADER);
device_enter_loader(0);
break;
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);
-
- if(!reply) {
- printf("Failed to allocate reply buffer!\n");
- }
+ crc = crc16(0, (void*)address, nbytes);
msgb_put_u8(reply, LOADER_MEM_READ);
msgb_put_u8(reply, nbytes);
+ msgb_put_u16(reply, crc);
msgb_put_u32(reply, address);
memcpy(msgb_put(reply, nbytes), (void*)address, nbytes);
case LOADER_MEM_WRITE:
nbytes = msgb_get_u8(msg);
+ crc = msgb_get_u16(msg);
address = msgb_get_u32(msg);
- printf("mem write %u @ %p\n", nbytes, (void*)address);
-
- memcpy((void*)address, msgb_get(msg, nbytes), nbytes);
+ data = msgb_get(msg, nbytes);
- reply = sercomm_alloc_msgb(6);
+ mycrc = crc16(0, data, nbytes);
- if(!reply) {
- printf("Failed to allocate reply buffer!\n");
+ if(mycrc == crc) {
+ memcpy((void*)address, data, nbytes);
}
msgb_put_u8(reply, LOADER_MEM_WRITE);
msgb_put_u8(reply, nbytes);
+ msgb_put_u16(reply, mycrc);
msgb_put_u32(reply, address);
sercomm_sendmsg(dlci, reply);
address = msgb_get_u32(msg);
- printf("jump to 0x%x\n", address);
+ msgb_put_u8(reply, LOADER_JUMP);
+ msgb_put_u32(reply, address);
+
+ sercomm_sendmsg(dlci, reply);
+
+ device_jump((void*)address);
+
+ break;
- reply = sercomm_alloc_msgb(5);
+ case LOADER_FLASH_INFO:
- if(!reply) {
- printf("Failed to allocate reply buffer!\n");
+ msgb_put_u8(reply, LOADER_FLASH_INFO);
+ msgb_put_u8(reply, 1); // nchips
+
+ // chip 1
+ msgb_put_u32(reply, the_flash.f_base);
+ msgb_put_u32(reply, the_flash.f_size);
+ msgb_put_u8(reply, the_flash.f_nregions);
+
+ int i;
+ for(i = 0; i < the_flash.f_nregions; i++) {
+ msgb_put_u32(reply, the_flash.f_regions[i].fr_bnum);
+ msgb_put_u32(reply, the_flash.f_regions[i].fr_bsize);
}
- msgb_put_u8(reply, LOADER_JUMP);
+ sercomm_sendmsg(dlci, reply);
+
+ break;
+
+ case LOADER_FLASH_ERASE:
+ case LOADER_FLASH_UNLOCK:
+ case LOADER_FLASH_LOCK:
+ case LOADER_FLASH_LOCKDOWN:
+
+ chip = msgb_get_u8(msg);
+ address = msgb_get_u32(msg);
+
+ if(command == LOADER_FLASH_ERASE) {
+ res = flash_block_erase(&the_flash, address);
+ }
+ if(command == LOADER_FLASH_UNLOCK) {
+ res = flash_block_unlock(&the_flash, address);
+ }
+ if(command == LOADER_FLASH_LOCK) {
+ res = flash_block_lock(&the_flash, address);
+ }
+ if(command == LOADER_FLASH_LOCKDOWN) {
+ res = flash_block_lockdown(&the_flash, address);
+ }
+
+ msgb_put_u8(reply, command);
+ msgb_put_u8(reply, chip);
msgb_put_u32(reply, address);
+ msgb_put_u32(reply, (res != 0));
sercomm_sendmsg(dlci, reply);
- device_jump((void*)address);
+ break;
+
+ case LOADER_FLASH_GETLOCK:
+
+ chip = msgb_get_u8(msg);
+ address = msgb_get_u32(msg);
+
+ lock = flash_block_getlock(&the_flash, address);
+
+ msgb_put_u8(reply, command);
+ msgb_put_u8(reply, chip);
+ msgb_put_u32(reply, address);
+
+ switch(lock) {
+ case FLASH_UNLOCKED:
+ msgb_put_u32(reply, LOADER_FLASH_UNLOCKED);
+ break;
+ case FLASH_LOCKED:
+ msgb_put_u32(reply, LOADER_FLASH_LOCKED);
+ break;
+ case FLASH_LOCKED_DOWN:
+ msgb_put_u32(reply, LOADER_FLASH_LOCKED_DOWN);
+ break;
+ default:
+ msgb_put_u32(reply, 0xFFFFFFFF);
+ break;
+ }
+
+ sercomm_sendmsg(dlci, reply);
break;
- default:
- printf("unknown command\n", command);
+ case LOADER_FLASH_PROGRAM:
+
+ nbytes = msgb_get_u8(msg);
+ crc = msgb_get_u16(msg);
+ msgb_get_u8(msg); // XXX align
+ chip = msgb_get_u8(msg);
+ address = msgb_get_u32(msg);
+
+ data = msgb_get(msg, nbytes);
+
+ mycrc = crc16(0, data, nbytes);
+
+ if(mycrc == crc) {
+ res = flash_program(&the_flash, address, data, nbytes);
+ }
+
+ msgb_put_u8(reply, LOADER_FLASH_PROGRAM);
+ msgb_put_u8(reply, nbytes);
+ msgb_put_u16(reply, mycrc);
+ msgb_put_u8(reply, 0); // XXX align
+ msgb_put_u8(reply, chip);
+ msgb_put_u32(reply, address);
+
+ msgb_put_u32(reply, (uint32_t)res); // XXX
+
+ sercomm_sendmsg(dlci, reply);
+
break;
+ default:
+ printf("unknown command %d\n", command);
+
+ msgb_free(reply);
+
+ break;
}
+ out:
+
msgb_free(msg);
}