/* XXX: recvmsg is overwritten when multiple msg arrive! */ static ssize_t sc_console_read(file_t *filep, FAR char *buffer, size_t buflen) { size_t len; struct msgb *tmp; /* Wait until data is received */ while(recvmsg == NULL) { sem_wait(&readdev->recvsem); } len = recvmsg->len > buflen ? buflen : recvmsg->len; memcpy(buffer, msgb_get(recvmsg, len), len); if(recvmsg->len == 0) { /* prevent inconsistent msg by first invalidating it, then free it */ tmp = recvmsg; recvmsg = NULL; msgb_free(tmp); } return len; }
static void cmd_handler(uint8_t dlci, struct msgb *msg) { if (msg->data_len < 1) { return; } uint8_t command = msgb_get_u8(msg); int res; flash_lock_t lock; void *data; uint8_t chip; uint8_t nbytes; uint16_t crc, mycrc; uint32_t address; struct msgb *reply = sercomm_alloc_msgb(256); // XXX if (!reply) { printf("Failed to allocate reply buffer!\n"); goto out; } switch (command) { case LOADER_PING: loader_send_simple(reply, dlci, LOADER_PING); break; case LOADER_RESET: loader_send_simple(reply, dlci, LOADER_RESET); device_reset(); break; case LOADER_POWEROFF: loader_send_simple(reply, dlci, LOADER_POWEROFF); device_poweroff(); break; case LOADER_ENTER_ROM_LOADER: loader_send_simple(reply, dlci, LOADER_ENTER_ROM_LOADER); device_enter_loader(1); break; case LOADER_ENTER_FLASH_LOADER: loader_send_simple(reply, dlci, LOADER_ENTER_FLASH_LOADER); device_enter_loader(0); break; case LOADER_MEM_READ: nbytes = msgb_get_u8(msg); address = msgb_get_u32(msg); crc = osmo_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); sercomm_sendmsg(dlci, reply); break; case LOADER_MEM_WRITE: nbytes = msgb_get_u8(msg); crc = msgb_get_u16(msg); address = msgb_get_u32(msg); data = msgb_get(msg, nbytes); mycrc = osmo_crc16(0, data, nbytes); 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); break; case LOADER_JUMP: address = msgb_get_u32(msg); msgb_put_u8(reply, LOADER_JUMP); msgb_put_u32(reply, address); sercomm_sendmsg(dlci, reply); device_jump((void *)address); break; case LOADER_FLASH_INFO: 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); } 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); 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; 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 = osmo_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); }