diff --git a/librtt/librtt.c b/librtt/librtt.c index 3673a211..42bb9740 100644 --- a/librtt/librtt.c +++ b/librtt/librtt.c @@ -289,37 +289,85 @@ int librtt_txCheckReaderAttached(unsigned int ch) } -int librtt_init(void *addr, librtt_cacheOp_t invalFn, librtt_cacheOp_t cleanFn) +static int librtt_verifyChannel(volatile struct rtt_desc *rtt, unsigned int ch, unsigned char *buffers, size_t buffersSize) { - if ((LIBRTT_DESC_SIZE < sizeof(struct rtt_desc)) || (librtt_common.rtt != NULL)) { + unsigned char *bufEnd = buffers + buffersSize; + size_t sz = rtt->channel[ch].sz; + /* Check buffer size is non-zero and power of 2 */ + if ((sz == 0) || ((sz & (sz - 1)) != 0)) { return -EINVAL; } - librtt_common.invalFn = invalFn; - librtt_common.cleanFn = cleanFn; + if ((rtt->channel[ch].ptr < buffers) || (rtt->channel[ch].ptr >= bufEnd)) { + return -EINVAL; + } - volatile struct rtt_desc *rtt = addr; + if (((rtt->channel[ch].ptr + rtt->channel[ch].sz) <= buffers) || ((rtt->channel[ch].ptr + rtt->channel[ch].sz) > bufEnd)) { + return -EINVAL; + } + + return 0; +} + + +int librtt_verify(void *addr, size_t cbSize, void *buffers, size_t buffersSize, librtt_cacheOp_t invalFn, librtt_cacheOp_t cleanFn) +{ + int n, ret; + if ((cbSize < sizeof(struct rtt_desc))) { + return -EINVAL; + } - int n; + volatile struct rtt_desc *rtt = addr; for (n = 0; n < librtt_tagLength; n++) { if (librtt_tagReversed[n] != rtt->tag[librtt_tagLength - 1 - n]) { break; } } - if (n == librtt_tagLength) { - if ((rtt->txChannels + rtt->rxChannels) <= (LIBRTT_TXCHANNELS + LIBRTT_RXCHANNELS)) { - librtt_common.rtt = rtt; - return 0; + if (n != librtt_tagLength) { + return -EINVAL; + } + + if ((rtt->txChannels > LIBRTT_TXCHANNELS) || (rtt->rxChannels > LIBRTT_RXCHANNELS)) { + return -EINVAL; + } + + int totalChannels = rtt->txChannels + rtt->rxChannels; + for (n = 0; n < totalChannels; n++) { + ret = librtt_verifyChannel(rtt, n, buffers, buffersSize); + if (ret != 0) { + return ret; + } + + if (n < LIBRTT_TXCHANNELS) { + librtt_common.lastRd[n] = rtt->channel[n].rd; } } + librtt_common.invalFn = invalFn; + librtt_common.cleanFn = cleanFn; + librtt_common.rtt = rtt; + return 0; +} + + +int librtt_init(void *addr, librtt_cacheOp_t invalFn, librtt_cacheOp_t cleanFn) +{ + if ((LIBRTT_DESC_SIZE < sizeof(struct rtt_desc)) || (librtt_common.rtt != NULL)) { + return -EINVAL; + } + + librtt_common.invalFn = invalFn; + librtt_common.cleanFn = cleanFn; + + volatile struct rtt_desc *rtt = addr; + memset((void *)rtt, 0, sizeof(*rtt)); rtt->txChannels = LIBRTT_TXCHANNELS; rtt->rxChannels = LIBRTT_RXCHANNELS; - for (n = 0; n < librtt_tagLength; n++) { + for (int n = 0; n < librtt_tagLength; n++) { rtt->tag[librtt_tagLength - 1 - n] = librtt_tagReversed[n]; } diff --git a/librtt/librtt.h b/librtt/librtt.h index d01c821e..000ce520 100644 --- a/librtt/librtt.h +++ b/librtt/librtt.h @@ -22,7 +22,11 @@ typedef int (*librtt_cacheOp_t)(void *addr, unsigned int sz); -/* Initialize rtt descriptor if it is not initialized already */ +/* Verify contents of rtt descriptor and initialize data structure if successful */ +int librtt_verify(void *addr, size_t cbSize, void *buffers, size_t buffersSize, librtt_cacheOp_t invalFn, librtt_cacheOp_t cleanFn); + + +/* Initialize rtt descriptor */ int librtt_init(void *addr, librtt_cacheOp_t invalFn, librtt_cacheOp_t cleanFn); diff --git a/multi/imxrt-multi/rtt.c b/multi/imxrt-multi/rtt.c index d93ffc4c..250d5ab7 100644 --- a/multi/imxrt-multi/rtt.c +++ b/multi/imxrt-multi/rtt.c @@ -27,11 +27,7 @@ #include "rtt.h" -#ifndef RTT_ADDR -/* RTT descriptors location, last 256 bytes of DTCM */ -#define RTT_ADDR (0x20040000 - 0x100) -#endif - +#define RTT_MAP_NAME "rtt" #define RTT_TX_BUF_SIZE 1024 #define RTT_RX_BUF_SIZE 256 #define RTT_POLLING_RATE_MS 20 @@ -147,8 +143,11 @@ static int rtt_initOne(rtt_t *uart, int chn, unsigned char *buf) uart->chn = chn; int ret = 0; - ret = (ret == 0) ? librtt_initChannel(1, chn, buf, RTT_TX_BUF_SIZE) : ret; - ret = (ret == 0) ? librtt_initChannel(0, chn, buf + RTT_TX_BUF_SIZE, RTT_RX_BUF_SIZE) : ret; + if (buf != NULL) { + ret = (ret == 0) ? librtt_initChannel(1, chn, buf, RTT_TX_BUF_SIZE) : ret; + ret = (ret == 0) ? librtt_initChannel(0, chn, buf + RTT_TX_BUF_SIZE, RTT_RX_BUF_SIZE) : ret; + } + ret = (ret == 0) ? mutexCreate(&uart->lock) : ret; /* TODO: calculate approx. baud rate based on buffer size and polling rate */ ret = (ret == 0) ? libtty_init(&uart->tty_common, &callbacks, TTY_BUF_SIZE, libtty_int_to_baudrate(115200)) : ret; @@ -157,49 +156,90 @@ static int rtt_initOne(rtt_t *uart, int chn, unsigned char *buf) } -int rtt_init(void) +static int rtt_getMemInfo(void **rttMemPtr_out, size_t *rttMemSz_out) { - if (RTT_ACTIVE_CNT == 0) { - return EOK; + void *rttMemPtr = NULL; + size_t rttMemSz = 0; + meminfo_t mi; + mi.page.mapsz = -1; + mi.entry.kmapsz = -1; + mi.entry.mapsz = -1; + mi.maps.mapsz = 0; + mi.maps.map = NULL; + meminfo(&mi); + + mi.maps.map = malloc(mi.maps.mapsz * sizeof(mapinfo_t)); + if (mi.maps.map == NULL) { + return -ENOMEM; } - /* Reserve memory for the descriptor and buffers */ - intptr_t startAddr = (RTT_ADDR - (RTT_ACTIVE_CNT * (RTT_TX_BUF_SIZE + RTT_RX_BUF_SIZE))) & ~(_PAGE_SIZE - 1); - size_t mapSize = RTT_ADDR + LIBRTT_DESC_SIZE - startAddr; - unsigned char *rttBuffer = mmap( - NULL, - mapSize, - PROT_WRITE | PROT_READ, - MAP_ANONYMOUS | MAP_UNCACHED | MAP_PHYSMEM, - -1, - startAddr); + meminfo(&mi); + for (int i = 0; i < mi.maps.mapsz; i++) { + if (strcmp(mi.maps.map[i].name, RTT_MAP_NAME) == 0) { + rttMemPtr = (void *)mi.maps.map[i].vstart; + rttMemSz = mi.maps.map[i].vend - mi.maps.map[i].vstart; + break; + } + } - if (rttBuffer == MAP_FAILED) { - return -ENOMEM; + free(mi.maps.map); + if (rttMemPtr == NULL) { + return -ENODEV; } - int ret = librtt_init((void *)RTT_ADDR, NULL, NULL); + *rttMemPtr_out = rttMemPtr; + *rttMemSz_out = rttMemSz; + return EOK; +} + + +int rtt_init(void) +{ + int doInit = 0; + void *rttMemPtr = NULL; + size_t rttMemSz = 0; + int ret = rtt_getMemInfo(&rttMemPtr, &rttMemSz); if (ret != 0) { - librtt_done(); - munmap(rttBuffer, mapSize); return ret; } - unsigned char *buf = rttBuffer; - for (int i = 0, chn = 0; chn < RTT_CHANNEL_CNT; ++chn) { + size_t bufSz = rttMemSz - LIBRTT_DESC_SIZE; + void *cbAddr = rttMemPtr + bufSz; + ret = librtt_verify( + cbAddr, + LIBRTT_DESC_SIZE, + rttMemPtr, + bufSz, + NULL, + NULL); + if (ret != 0) { + doInit = 1; + ret = librtt_init(cbAddr, NULL, NULL); + if (ret != 0) { + return ret; + } + } + + unsigned char *buf = (doInit != 0) ? rttMemPtr : NULL; + unsigned char *nextBuf = buf; + for (int i = 0, chn = 0; chn < RTT_CHANNEL_CNT; chn++, buf = nextBuf) { if (rttConfig[chn] == 0) { continue; } rtt_t *uart = &rtt_common.uarts[i++]; - int ret = rtt_initOne(uart, chn, buf); + if (buf != NULL) { + nextBuf = buf + RTT_TX_BUF_SIZE + RTT_RX_BUF_SIZE; + if ((nextBuf - (unsigned char *)rttMemPtr) > bufSz) { + break; + } + } + + ret = rtt_initOne(uart, chn, buf); if (ret != 0) { librtt_done(); - munmap(rttBuffer, mapSize); return ret; } - - buf += RTT_RX_BUF_SIZE + RTT_TX_BUF_SIZE; } beginthread(rtt_thread, IMXRT_MULTI_PRIO, rtt_common.stack, sizeof(rtt_common.stack), NULL);