#include <stdint.h> uint32_t volatile * const rccApb2 = (uint32_t *) 0x40021018u; uint32_t volatile * const ioAModerH = (uint32_t *) 0x40010804u; uint32_t volatile * const uart1Ctrl = (uint32_t *) 0x40013800u; void readChar( uint8_t const chr ); void writeByte( uint8_t b ); void writeStr( uint8_t const * const str ); void writeChar( uint8_t const chr ); void writeWordLe( uint32_t const word ); void writeWordBe( uint32_t const word ); void readCmd( uint8_t const * const cmd); uint32_t hexToInt(uint8_t const * const hex); void readMem(uint32_t const addr, uint32_t const len); void writeMem(uint32_t const addr, uint32_t const data); uint8_t const strHelp[] = "Help\r\n-----------\r\n" "ADDR, VAL, LEN: 32-bit Hex encoded:\r\n e.g., 0A1337FF\r\n" "-----------\r\n" "R ADDR LEN - Read 32-bit word\r\n" "W ADDR VAL - Write 32-bit word\r\n" "D - Dump all flash memory\r\n" "P - Jump into chall4 function\r\n" "S - Reboot\r\n" "E - Exit\r\n" "H - Show help \r\n" "---------------\r\n"; int main(void) { /* IOA + USART1 clock enable */ *rccApb2 = (uint32_t) 0x4004u; /* USART1 TX+RX (PA9, PX10) on */ *ioAModerH = (uint32_t) 0x444444B4u; /* config and enable uart */ uart1Ctrl[2] = 0x00000341u; uart1Ctrl[3] = 0x0000200Cu; writeStr("\r\n##############################\r\n" "# Low-Level Shell v.0xRoM #\r\n" "# CPU-ID: 0x"); uint32_t cpuid = *((uint32_t *) 0xe000ed00); writeWordBe(cpuid); writeStr( " #\r\n"); writeStr("##############################\r\n\r\n"); writeStr("> "); while (1) { if ((uart1Ctrl[0] & 0x80u) && (0)) { uart1Ctrl[1] = 0x33u; } if (uart1Ctrl[0] & 0x20u) { uint32_t data = uart1Ctrl[1]; readChar((uint8_t) data); } } } /* hex must have length 8 */ uint32_t hexToInt(uint8_t const * const hex) { uint32_t ind = 0u; uint32_t res = 0u; for (ind = 0; ind < 8; ++ind) { uint8_t chr = hex[ind]; uint32_t val = 0u; res <<= 4u; if ((chr >= '0') && (chr <= '9')) { val = chr - '0'; } else if ((chr >= 'a') && (chr <= 'f')) { val = chr - 'a' + 0x0a; } else if ((chr >= 'A') && (chr <= 'F')) { val = chr - 'A' + 0x0a; } else { val = 0u; } res |= val; } return res; } void readChar( uint8_t const chr ) { #define CMDBUF_LEN (64u) static uint8_t cmdbuf[CMDBUF_LEN] = {0u}; static uint32_t cmdInd = 0u; switch (chr) { case '\n': case '\r': cmdbuf[cmdInd] = 0u; if (cmdInd != 0) { writeStr("\r\n"); } readCmd(cmdbuf); cmdInd = 0u; writeStr("\r\n> "); { uint32_t ind = 0u; for (ind = 0; ind<CMDBUF_LEN; ++ind) { cmdbuf[ind]=0x00u; } } break; case 8: case 255: case 127: /* TODO backspace */ if (cmdInd > 0u) --cmdInd; writeChar(chr); break; default: if (cmdInd < (CMDBUF_LEN - 1)) { cmdbuf[cmdInd] = chr; ++cmdInd; writeChar(chr); } break; } } void readCmd( uint8_t const * const cmd ) { void (*chall4)(void) = (void (*)(void))0x08000ba9; switch (cmd[0]) { case 0: return; break; /* chall4 function */ case 'p': case 'P': writeStr("time to change baudrate to 115200\r\n"); for (volatile uint32_t i = 0; i < 5000000; i++); // Crude delay chall4(); break; /* read 32-bit command */ case 'r': case 'R': /* r 08000000 00000100 */ readMem(hexToInt(&cmd[2]), hexToInt(&cmd[11])); break; /* write 32-bit command */ case 'w': case 'W': /* w 20000000 12345678 */ writeMem(hexToInt(&cmd[2]), hexToInt(&cmd[11])); break; /* Dump all flash */ case 'd': case 'D': writeStr("\r\n\r\n"); { uint32_t const * addr = (uint32_t*) 0x08000000; uint32_t br = 8u; while (((uintptr_t) addr) < (0x08000000 + 64u * 1024u)) { if (br == 8u) { writeStr("\r\n["); writeWordBe((uint32_t) addr); writeStr("]: "); br = 0u; } writeWordBe(*addr); writeChar(' '); ++addr; ++br; } } writeStr("\r\n\r\n"); break; /* Help command */ case 'h': case 'H': writeStr(strHelp); break; /* Reboot */ case 's': case 'S': writeStr("Rebooting...\r\n\r\n"); *((uint32_t *) 0xE000ED0C) = 0x05FA0004u; break; /* exit */ case 'e': case 'E': writeStr("Bye.\r\n"); while (1) { __asm__ volatile("wfi"); } break; default: writeStr("Unknown command: "); writeStr(cmd); writeStr("\r\n"); break; } } const uint8_t txtMap[] = "0123456789ABCDEF"; void writeByte( uint8_t b ) { writeChar(txtMap[b >> 4]); writeChar(txtMap[b & 0x0F]); } void writeStr( uint8_t const * const str ) { uint32_t ind = 0u; while (str[ind]) { writeChar(str[ind]); ++ind; } } void writeChar( uint8_t const chr ) { while (!(uart1Ctrl[0] & 0x80u)) { /* wait */ } uart1Ctrl[1] = chr; } void writeWordLe( uint32_t const word ) { writeByte((word & 0x000000FF)); writeByte((word & 0x0000FF00) >> 8); writeByte((word & 0x00FF0000) >> 16); writeByte((word & 0xFF000000) >> 24); } void writeWordBe( uint32_t const word ) { writeByte((word & 0xFF000000) >> 24); writeByte((word & 0x00FF0000) >> 16); writeByte((word & 0x0000FF00) >> 8); writeByte((word & 0x000000FF)); } void alertCrash( uint32_t crashId ) { writeStr("!!! EXCEPTION !!!\r\nID: "); writeByte(crashId); writeStr("\r\nRestart required!\r\n\r\n"); *((uint32_t *) 0xE000ED0C) = 0x05FA0004u; while (1); } void readMem(uint32_t const addr, uint32_t const len) { uint32_t it = 0u; uint32_t addrx = 0u; uint32_t lenx = 0u; lenx = len; if (lenx == 0u) { lenx = 4u; } for (it = 0u; it < (lenx / 4u); ++it) { addrx = addr + it*4u; writeStr("Read ["); writeWordBe(addrx); writeStr("]: "); writeWordBe(*((uint32_t*)addrx)); writeStr("\r\n"); } } void writeMem(uint32_t const addr, uint32_t const data) { writeStr("Write ["); writeWordBe(addr); writeStr("]: "); writeWordBe(data); *((uint32_t*) addr) = data; writeStr("\r\n"); }