serial: Don't use packet buffer for escaped tx data
Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
diff --git a/serial.c b/serial.c
index 7c4e9e3..87524f6 100644
--- a/serial.c
+++ b/serial.c
@@ -38,6 +38,9 @@
STATE_WAIT_FCS2,
STATE_WAIT_SYNC_END,
} rx_state;
+
+ /* temporary transmit buffer */
+ uint8_t txbuf[256];
};
#ifndef container_of
@@ -64,28 +67,29 @@
uint8_t flag;
};
-static void mctp_serial_pkt_escape(struct mctp_pktbuf *pkt)
+static size_t mctp_serial_pkt_escape(struct mctp_pktbuf *pkt, uint8_t *buf)
{
- uint8_t buf[MCTP_MTU + sizeof(struct mctp_hdr)], *p;
uint8_t total_len;
+ uint8_t *p;
int i, j;
total_len = pkt->end - pkt->mctp_hdr_off;
p = (void *)mctp_pktbuf_hdr(pkt);
- memcpy(buf, p, total_len);
-
for (i = 0, j = 0; i < total_len; i++, j++) {
- uint8_t c = buf[i];
+ uint8_t c = p[i];
if (c == 0x7e || c == 0x7d) {
- p[j] = 0x7d;
- mctp_pktbuf_alloc_end(pkt, 1);
+ if (buf)
+ buf[j] = 0x7d;
j++;
c ^= 0x20;
}
- p[j] = c;
+ if (buf)
+ buf[j] = c;
}
+
+ return j;
}
static int mctp_binding_serial_tx(struct mctp_binding *b,
@@ -94,24 +98,35 @@
struct mctp_binding_serial *serial = binding_to_serial(b);
struct mctp_serial_header *hdr;
struct mctp_serial_trailer *tlr;
- uint8_t len;
+ uint8_t *buf;
+ size_t len;
/* the length field in the header excludes serial framing
* and escape sequences */
len = mctp_pktbuf_size(pkt);
- hdr = mctp_pktbuf_alloc_start(pkt, 3);
+ hdr = (void *)serial->txbuf;
hdr->flag = MCTP_SERIAL_FRAMING_FLAG;
hdr->revision = MCTP_SERIAL_REVISION;
hdr->len = len;
- mctp_serial_pkt_escape(pkt);
+ buf = (void *)(hdr + 1);
- tlr = mctp_pktbuf_alloc_end(pkt, 3);
- /* todo: trailer FCS */
+ len = mctp_serial_pkt_escape(pkt, NULL);
+ if (len + sizeof(*hdr) + sizeof(*tlr) > sizeof(serial->txbuf))
+ return -1;
+
+ mctp_serial_pkt_escape(pkt, buf);
+
+ buf += len;
+
+ tlr = (void *)buf;
tlr->flag = MCTP_SERIAL_FRAMING_FLAG;
+ /* todo: trailer FCS */
+ tlr->fcs_msb = 0;
+ tlr->fcs_lsb = 0;
- write(serial->fd, pkt->data + pkt->start, pkt->end - pkt->start);
+ write(serial->fd, serial->txbuf, sizeof(*hdr) + len + sizeof(*tlr));
return 0;
}
@@ -166,7 +181,8 @@
}
break;
case STATE_WAIT_LEN:
- if (c > MCTP_MTU || c < sizeof(struct mctp_hdr)) {
+ if (c > (MCTP_MTU + sizeof(struct mctp_hdr))
+ || c < sizeof(struct mctp_hdr)) {
mctp_prdebug("invalid size %d", c);
serial->rx_state = STATE_WAIT_SYNC_START;
} else {