diff --git a/librtt/librtt.c b/librtt/librtt.c index 247b0e7f..d1f74340 100644 --- a/librtt/librtt.c +++ b/librtt/librtt.c @@ -77,7 +77,7 @@ struct rtt_desc { char tag[16]; unsigned int txChannels; unsigned int rxChannels; - struct rtt_pipe channel[LIBRTT_TXCHANNELS + LIBRTT_RXCHANNELS]; + struct rtt_pipe channel[]; }; @@ -113,7 +113,7 @@ static void performCacheOp(librtt_cacheOp_t op, volatile unsigned char *buf, uns int librtt_checkTx(unsigned int ch) { - if ((librtt_common.rtt == NULL) || (ch >= librtt_common.rtt->txChannels)) { + if ((librtt_common.rtt == NULL) || (ch >= librtt_common.rtt->txChannels) || (ch >= LIBRTT_TXCHANNELS)) { return -ENODEV; } @@ -123,7 +123,7 @@ int librtt_checkTx(unsigned int ch) int librtt_checkRx(unsigned int ch) { - if ((librtt_common.rtt == NULL) || (ch >= librtt_common.rtt->rxChannels)) { + if ((librtt_common.rtt == NULL) || (ch >= librtt_common.rtt->rxChannels) || (ch >= LIBRTT_RXCHANNELS)) { return -ENODEV; } @@ -290,37 +290,87 @@ 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; + } + + if (((rtt->channel[ch].ptr + rtt->channel[ch].sz) <= buffers) || ((rtt->channel[ch].ptr + rtt->channel[ch].sz) > bufEnd)) { + return -EINVAL; + } + + return 0; +} - volatile struct rtt_desc *rtt = addr; - int n; +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; + } + + 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; + } + + size_t realCbSize = sizeof(struct rtt_desc) + ((rtt->txChannels + rtt->rxChannels) * sizeof(struct rtt_pipe)); + if (cbSize < realCbSize) { + 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; } } - memset((void *)rtt, 0, sizeof(*rtt)); + 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) +{ + const size_t cbSize = sizeof(struct rtt_desc) + (LIBRTT_TXCHANNELS + LIBRTT_RXCHANNELS) * sizeof(struct rtt_pipe); + if ((LIBRTT_DESC_SIZE < cbSize) || (librtt_common.rtt != NULL)) { + return -EINVAL; + } + + librtt_common.invalFn = invalFn; + librtt_common.cleanFn = cleanFn; + + volatile struct rtt_desc *rtt = addr; + + memset((void *)rtt, 0, cbSize); 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]; } @@ -336,11 +386,6 @@ int librtt_initChannel(int isTx, unsigned int ch, unsigned char *buf, size_t sz) return -EINVAL; } - unsigned int chMax = (isTx != 0) ? rtt->txChannels : rtt->rxChannels; - if ((ch >= chMax)) { - return -EINVAL; - } - /* Check buffer size is non-zero and power of 2 */ if ((sz == 0) || ((sz & (sz - 1)) != 0)) { return -EINVAL; @@ -348,20 +393,19 @@ int librtt_initChannel(int isTx, unsigned int ch, unsigned char *buf, size_t sz) const char *name = NULL; if (isTx != 0) { - if (ch < LIBRTT_TXCHANNELS) { - name = librtt_txName[ch]; + if ((ch >= LIBRTT_TXCHANNELS) || (ch >= rtt->txChannels)) { + return -EINVAL; } - } - else { - if (ch < LIBRTT_RXCHANNELS) { - name = librtt_rxName[ch]; - } - } - if (isTx != 0) { + name = librtt_txName[ch]; librtt_common.lastRd[ch] = 0; } else { + if ((ch >= LIBRTT_RXCHANNELS) || (ch >= rtt->rxChannels)) { + return -EINVAL; + } + + name = librtt_rxName[ch]; ch += rtt->txChannels; } 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..32f58897 100644 --- a/multi/imxrt-multi/rtt.c +++ b/multi/imxrt-multi/rtt.c @@ -27,9 +27,8 @@ #include "rtt.h" -#ifndef RTT_ADDR -/* RTT descriptors location, last 256 bytes of DTCM */ -#define RTT_ADDR (0x20040000 - 0x100) +#ifndef RTT_SYSPAGE_MAP_NAME +#define RTT_SYSPAGE_MAP_NAME "rtt" #endif #define RTT_TX_BUF_SIZE 1024 @@ -147,8 +146,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,52 +159,97 @@ 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_SYSPAGE_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) +{ + if (RTT_CHANNEL_CNT == 0) { + return EOK; + } + + 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); + ret = beginthread(rtt_thread, IMXRT_MULTI_PRIO, rtt_common.stack, sizeof(rtt_common.stack), NULL); return ret; }