diff --git a/armsrc/BigBuf.c b/armsrc/BigBuf.c index 07f32239f..20e2e3e2d 100644 --- a/armsrc/BigBuf.c +++ b/armsrc/BigBuf.c @@ -14,34 +14,48 @@ #include "dbprint.h" #include "pm3_cmd.h" +extern uint8_t _stack_start, __bss_end__; + // BigBuf is the large multi-purpose buffer, typically used to hold A/D samples or traces. // Also used to hold various smaller buffers and the Mifare Emulator Memory. -// declare it as uint32_t to achieve alignment to 4 Byte boundary -static uint32_t BigBuf[BIGBUF_SIZE / sizeof(uint32_t)]; +// We know that bss is aligned to 4 bytes. +static uint8_t* BigBuf = &__bss_end__; /* BigBuf memory layout: Pointer to highest available memory: BigBuf_hi - - high BIGBUF_SIZE + high BigBuf_size reserved = BigBuf_malloc() subtracts amount from BigBuf_hi, low 0x00 */ +static uint32_t BigBuf_size = 0; + // High memory mark -static uint16_t BigBuf_hi = BIGBUF_SIZE; +static uint32_t BigBuf_hi = 0; // pointer to the emulator memory. static uint8_t *emulator_memory = NULL; // trace related variables static uint32_t traceLen = 0; -static bool tracing = true; //todo static? +static bool tracing = true; + +// compute the available size for BigBuf +void BigBuf_initialize(void) { + BigBuf_size = (uint32_t)&_stack_start - (uint32_t)&__bss_end__; + BigBuf_hi = BigBuf_size; + traceLen = 0; +} // get the address of BigBuf uint8_t *BigBuf_get_addr(void) { return (uint8_t *)BigBuf; } +uint32_t BigBuf_get_size(void) { + return BigBuf_size; +} + // get the address of the emulator memory. Allocate part of Bigbuf for it, if not yet done uint8_t *BigBuf_get_EM_addr(void) { // not yet allocated @@ -58,9 +72,9 @@ void BigBuf_Clear(void) { // clear ALL of BigBuf void BigBuf_Clear_ext(bool verbose) { - memset(BigBuf, 0, BIGBUF_SIZE); + memset(BigBuf, 0, BigBuf_size); if (verbose) - Dbprintf("Buffer cleared (%i bytes)", BIGBUF_SIZE); + Dbprintf("Buffer cleared (%i bytes)", BigBuf_size); } void BigBuf_Clear_EM(void) { @@ -74,7 +88,7 @@ void BigBuf_Clear_keep_EM(void) { // allocate a chunk of memory from BigBuf. We allocate high memory first. The unallocated memory // at the beginning of BigBuf is always for traces/samples uint8_t *BigBuf_malloc(uint16_t chunksize) { - if (BigBuf_hi - chunksize < 0) + if (BigBuf_hi < chunksize) return NULL; // no memory left chunksize = (chunksize + 3) & 0xfffc; // round to next multiple of 4 @@ -84,7 +98,7 @@ uint8_t *BigBuf_malloc(uint16_t chunksize) { // free ALL allocated chunks. The whole BigBuf is available for traces or samples again. void BigBuf_free(void) { - BigBuf_hi = BIGBUF_SIZE; + BigBuf_hi = BigBuf_size; emulator_memory = NULL; // shouldn't this empty BigBuf also? } @@ -94,14 +108,14 @@ void BigBuf_free_keep_EM(void) { if (emulator_memory != NULL) BigBuf_hi = emulator_memory - (uint8_t *)BigBuf; else - BigBuf_hi = BIGBUF_SIZE; + BigBuf_hi = BigBuf_size; // shouldn't this empty BigBuf also? } void BigBuf_print_status(void) { DbpString(_BLUE_("Memory")); - Dbprintf(" BIGBUF_SIZE.............%d", BIGBUF_SIZE); + Dbprintf(" BigBuf_size.............%d", BigBuf_size); Dbprintf(" Available memory........%d", BigBuf_hi); DbpString(_BLUE_("Tracing")); Dbprintf(" tracing ................%d", tracing); diff --git a/armsrc/BigBuf.h b/armsrc/BigBuf.h index ad967c4c7..60857e82a 100644 --- a/armsrc/BigBuf.h +++ b/armsrc/BigBuf.h @@ -14,7 +14,6 @@ #include "common.h" -#define BIGBUF_SIZE 40000 #define MAX_FRAME_SIZE 256 // maximum allowed ISO14443 frame #define MAX_PARITY_SIZE ((MAX_FRAME_SIZE + 7) / 8) #define MAX_MIFARE_FRAME_SIZE 18 // biggest Mifare frame is answer to a read (one block = 16 Bytes) + 2 Bytes CRC @@ -23,8 +22,10 @@ #define DMA_BUFFER_SIZE 256 //128 (how big is the dma?!? uint8_t *BigBuf_get_addr(void); +uint32_t BigBuf_get_size(void); uint8_t *BigBuf_get_EM_addr(void); uint16_t BigBuf_max_traceLen(void); +void BigBuf_initialize(void); void BigBuf_Clear(void); void BigBuf_Clear_ext(bool verbose); void BigBuf_Clear_keep_EM(void); diff --git a/armsrc/appmain.c b/armsrc/appmain.c index fd5b4853c..28e2d9625 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -71,6 +71,8 @@ uint8_t ToSend[TOSEND_BUFFER_SIZE]; int ToSendMax = -1; +extern uint32_t _stack_start, _stack_end; + static int ToSendBit; struct common_area common_area __attribute__((section(".commonarea"))); @@ -359,6 +361,12 @@ static void SendStatus(void) { #endif printConnSpeed(); DbpString(_BLUE_("Various")); + for (uint32_t *p = &_stack_start; ; ++p) { + if (*p != 0xdeadbeef) { + Dbprintf(" Max stack usage.........%d", (&_stack_end - p)*4); + break; + } + } Dbprintf(" DBGLEVEL................%d", DBGLEVEL); Dbprintf(" ToSendMax...............%d", ToSendMax); Dbprintf(" ToSendBit...............%d", ToSendBit); @@ -392,6 +400,7 @@ static void SendCapabilities(void) { capabilities.version = CAPABILITIES_VERSION; capabilities.via_fpc = g_reply_via_fpc; capabilities.via_usb = g_reply_via_usb; + capabilities.bigbuf_size = BigBuf_get_size(); capabilities.baudrate = 0; // no real baudrate for USB-CDC #ifdef WITH_FPC_USART if (g_reply_via_fpc) @@ -1659,12 +1668,12 @@ static void PacketReceived(PacketCommandNG *packet) { } // offset should not be over buffer - if (payload->offset >= BIGBUF_SIZE) { + if (payload->offset >= BigBuf_get_size()) { reply_ng(CMD_LF_UPLOAD_SIM_SAMPLES, PM3_EOVFLOW, NULL, 0); break; } // ensure len bytes copied wont go past end of bigbuf - uint16_t len = MIN(BIGBUF_SIZE - payload->offset, sizeof(payload->data)); + uint16_t len = MIN(BigBuf_get_size() - payload->offset, sizeof(payload->data)); uint8_t *mem = BigBuf_get_addr(); @@ -2054,8 +2063,12 @@ static void PacketReceived(PacketCommandNG *packet) { void __attribute__((noreturn)) AppMain(void) { SpinDelay(100); - clear_trace(); + BigBuf_initialize(); + for (uint32_t * p = &_stack_start; p < (uint32_t *)((uintptr_t)&_stack_end - 0x200); ++p) { + *p = 0xdeadbeef; + } + if (common_area.magic != COMMON_AREA_MAGIC || common_area.version != 1) { /* Initialize common area */ memset(&common_area, 0, sizeof(common_area)); @@ -2121,6 +2134,10 @@ void __attribute__((noreturn)) AppMain(void) { for (;;) { WDT_HIT(); + if (_stack_start != 0xdeadbeef) { + Dbprintf("Stack overflow detected! Please increase stack size."); + } + // Check if there is a packet available PacketCommandNG rx; memset(&rx.data, 0, sizeof(rx.data)); diff --git a/armsrc/mifarecmd.c b/armsrc/mifarecmd.c index ef1a15864..9e19cbc53 100644 --- a/armsrc/mifarecmd.c +++ b/armsrc/mifarecmd.c @@ -1392,7 +1392,7 @@ void MifareChkKeys_fast(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *da // limit size of availlable for keys in bigbuff // a key is 6bytes - uint16_t key_mem_available = MIN(BIGBUF_SIZE, keyCount * 6); + uint16_t key_mem_available = MIN(BigBuf_get_size(), keyCount * 6); keyCount = key_mem_available / 6; diff --git a/client/src/cmddata.c b/client/src/cmddata.c index 326e0d457..007c32c8a 100644 --- a/client/src/cmddata.c +++ b/client/src/cmddata.c @@ -567,7 +567,7 @@ int ASKDemod_ext(const char *Cmd, bool verbose, bool emSearch, uint8_t askType, sscanf(Cmd, "%i %i %i %zu %c", &clk, &invert, &maxErr, &maxLen, &); - if (!maxLen) maxLen = BIGBUF_SIZE; + if (!maxLen) maxLen = pm3_capabilities.bigbuf_size; if (invert != 0 && invert != 1) { PrintAndLogEx(WARNING, "Invalid argument: %s", Cmd); @@ -1517,16 +1517,18 @@ static int CmdHexsamples(const char *Cmd) { uint32_t offset = 0; char string_buf[25]; char *string_ptr = string_buf; - uint8_t got[BIGBUF_SIZE]; + uint8_t got[pm3_capabilities.bigbuf_size]; sscanf(Cmd, "%u %u", &requested, &offset); /* if no args send something */ if (requested == 0) requested = 8; + if (requested > pm3_capabilities.bigbuf_size) + requested = pm3_capabilities.bigbuf_size; if (offset + requested > sizeof(got)) { - PrintAndLogEx(NORMAL, "Tried to read past end of buffer, + > %d", BIGBUF_SIZE); + PrintAndLogEx(NORMAL, "Tried to read past end of buffer, + > %d", pm3_capabilities.bigbuf_size); return PM3_EINVARG; } @@ -1595,10 +1597,11 @@ int getSamples(uint32_t n, bool verbose) { // we don't have to worry about remaining trash // in the last byte in case the bits-per-sample // does not line up on byte boundaries - uint8_t got[BIGBUF_SIZE - 1] = { 0 }; + uint8_t got[pm3_capabilities.bigbuf_size - 1]; + memset(got, 0x00, sizeof(got)); - if (n == 0 || n > sizeof(got)) - n = sizeof(got); + if (n == 0 || n > pm3_capabilities.bigbuf_size - 1) + n = pm3_capabilities.bigbuf_size - 1; if (verbose) PrintAndLogEx(INFO, "Reading " _YELLOW_("%u") " bytes from device memory", n); diff --git a/client/src/cmddata.h b/client/src/cmddata.h index a7a69e430..abef8fde8 100644 --- a/client/src/cmddata.h +++ b/client/src/cmddata.h @@ -79,7 +79,6 @@ int AskEdgeDetect(const int *in, int *out, int len, int threshold); int demodIdteck(void); #define MAX_DEMOD_BUF_LEN (1024*128) -#define BIGBUF_SIZE 40000 extern uint8_t DemodBuffer[MAX_DEMOD_BUF_LEN]; extern size_t DemodBufferLen; diff --git a/client/src/cmdlft55xx.c b/client/src/cmdlft55xx.c index 6294ffef6..b2f048665 100644 --- a/client/src/cmdlft55xx.c +++ b/client/src/cmdlft55xx.c @@ -2837,7 +2837,7 @@ static int CmdResetRead(const char *Cmd) { if (resp.status == PM3_SUCCESS) { - uint16_t gotsize = BIGBUF_SIZE - 1; + uint16_t gotsize = pm3_capabilities.bigbuf_size - 1; uint8_t *got = calloc(gotsize, sizeof(uint8_t)); if (got == NULL) { PrintAndLogEx(WARNING, "failed to allocate memory"); diff --git a/common_arm/ldscript.common b/common_arm/ldscript.common index 1be33df95..9e53d8436 100644 --- a/common_arm/ldscript.common +++ b/common_arm/ldscript.common @@ -9,17 +9,21 @@ ms of the GNU GPL, version 2 or, ----------------------------------------------------------------------------- */ +stacksize = DEFINED(stacksize) ? stacksize : 5K; +commonareasize = 0x20; + /* AT91SAM7S256 has 256k Flash and 64k RAM */ /* AT91SAM7S512 has 512k Flash and 64k RAM */ /* boot space = 8192bytes (0x2000) */ /* osimage space = (512k - 0x2000 == 524288 - 8192 == 516096bytes == 0x7E000 ) */ MEMORY { - bootphase1 : ORIGIN = 0x00100000, LENGTH = 0x200 /* Phase 1 bootloader: Copies real bootloader to RAM */ - bootphase2 : ORIGIN = 0x00100200, LENGTH = 0x2000 - 0x200 /* Main bootloader code, stored in Flash, executed from RAM */ - osimage : ORIGIN = 0x00102000, LENGTH = 512K - 0x2000 /* Place where the main OS will end up */ - ram : ORIGIN = 0x00200000, LENGTH = 64K - 0x20 /* RAM, minus small common area */ - commonarea : ORIGIN = 0x00200000 + 64K - 0x20, LENGTH = 0x20 /* Communication between bootloader and main OS */ + bootphase1 : ORIGIN = 0x00100000, LENGTH = 0x200 /* Phase 1 bootloader: Copies real bootloader to RAM */ + bootphase2 : ORIGIN = 0x00100200, LENGTH = 0x2000 - 0x200 /* Main bootloader code, stored in Flash, executed from RAM */ + osimage : ORIGIN = 0x00102000, LENGTH = 512K - 0x2000 /* Place where the main OS will end up */ + ram : ORIGIN = 0x00200000, LENGTH = 64K - commonareasize /* RAM, minus small common area */ + stack : ORIGIN = 0x00200000 + 64K - stacksize - commonareasize, LENGTH = stacksize /* Stack */ + commonarea : ORIGIN = 0x00200000 + 64K - commonareasize, LENGTH = commonareasize /* Communication between bootloader and main OS */ } /* Export some information that can be used from within the firmware */ @@ -29,4 +33,5 @@ _bootrom_start = ORIGIN(bootphase1); _bootrom_end = ORIGIN(bootphase2) + LENGTH(bootphase2); _flash_start = ORIGIN(bootphase1); _flash_end = ORIGIN(osimage) + LENGTH(osimage); +_stack_start = ORIGIN(stack); _stack_end = ORIGIN(ram) + LENGTH(ram) - 8; diff --git a/include/pm3_cmd.h b/include/pm3_cmd.h index b6de6f292..3cafb9df1 100644 --- a/include/pm3_cmd.h +++ b/include/pm3_cmd.h @@ -175,6 +175,7 @@ typedef struct { typedef struct { uint8_t version; uint32_t baudrate; + uint32_t bigbuf_size; bool via_fpc : 1; bool via_usb : 1; // rdv4 @@ -203,7 +204,7 @@ typedef struct { bool hw_available_flash : 1; bool hw_available_smartcard : 1; } PACKED capabilities_t; -#define CAPABILITIES_VERSION 4 +#define CAPABILITIES_VERSION 5 extern capabilities_t pm3_capabilities; // For CMD_LF_T55XX_WRITEBL