libratp, libratp-barebox and ratp-barebox-cli
Hey, For anyone interested, I ended up preparing a pair of C libraries and a CLI tool that allow controlling barebox remotely using RATP, in the same way as bbremote does it. The libraries would allow easy integration on C applications that may want to remotely control barebox. Repositories: https://github.com/aleksander0m/libratp https://github.com/aleksander0m/libratp-barebox Some initial 0.0.2 tagged versions here: https://aleksander.es/software/libratp-0.0.2.tar.xz https://aleksander.es/software/libratp-barebox-0.0.2.tar.xz APIs: https://aleksander0m.github.io/libratp https://aleksander0m.github.io/libratp-barebox The libratp library provides a generic RATP implementation, much like barebox' lib/ratp.c: * The library currently supports creating ratp_t objects for TTYs or FIFO pairs (e.g. for barebox sandbox testing). * The library launches a background thread running a libevent main loop, which takes care of all the async reading from the TTY (or FIFO). all the timers in the RATP logic and all the link management state machine. * Callbacks may be registered by the user to get reported when new data arrives or when RATP link state changes. Worth noting that these callbacks are called from within the support thread. * The ratp_close() and ratp_establish() operations in barebox' lib/ratp.c are blocking, they will not return until the desired final state has been reached or a timeout happened. In the libratp library the equivalent operations would be ratp_link_active_open_sync() and ratp_link_close_sync(); but the library also includes support for just sending the active open or close requests, without waiting for the final state to be reached, via ratp_link_active_open() and ratp_link_close(). This allows to e.g. request an active open and queue data to be sent, so that the data is directly sent on the ACK finishing the establishment. * The library doesn't make any assumption on the maximum data length chosen by each peer, so a peer may choose a MDL<255 to receive data in shorter chunks or even choose MDL=0 to indicate no data may be received. The libratp-barebox library "extends" the libratp library with barebox specific operations. Right now, these are implemented: * ratp_barebox_link_ping() * ratp_barebox_link_command() * ratp_barebox_link_getenv() The ratp-barebox-cli implements the barebox specific operations in a CLI, just a simple way to exercise the library APIs: $ ratp-barebox-cli -t /dev/ttyUSB3 --ping Sending PING... PONG received... $ ratp-barebox-cli -t /dev/ttyUSB3 --getenv global.boot.default Sending getenv request: global.boot.default global.boot.default: net $ ratp-barebox-cli -t /dev/ttyUSB3 --command "ls /dev" Sending command: ls /dev Received response (errno Success): cs0 eeprom0 eeprom1 full imx-ocotpmem netconsole-1 null prng ram0 ratpconsole-1serial0-1 serial1-1serial2-1zero Cheers! -- Aleksander https://aleksander.es ___ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox
[PATCH 16/16] ratp: user close may happen in SYN-RECEIVED state
The reference says: 5.2.3. SYN-RECEIVED ... Departures - A CLOSE request is made by the user. Create a packet with FIN set. Send it and go to the FIN-WAIT state. Add this missing step. Signed-off-by: Aleksander Morgado --- lib/ratp.c | 2 +- scripts/remote/ratp.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/ratp.c b/lib/ratp.c index 46a82c69a..e7fbf640a 100644 --- a/lib/ratp.c +++ b/lib/ratp.c @@ -1689,7 +1689,7 @@ void ratp_close(struct ratp *ratp) if (!ri) return; - if (ri->state == RATP_STATE_ESTABLISHED) { + if (ri->state == RATP_STATE_ESTABLISHED || ri->state == RATP_STATE_SYN_RECEIVED) { uint64_t start; u8 control; diff --git a/scripts/remote/ratp.py b/scripts/remote/ratp.py index 7972d31f2..44f3e2f40 100644 --- a/scripts/remote/ratp.py +++ b/scripts/remote/ratp.py @@ -721,7 +721,7 @@ class RatpConnection(object): def close(self, timeout=1.0): deadline = monotonic() + timeout logging.info("CLOSE") -if self._state == RatpState.established: +if self._state == RatpState.established or self._state == RatpState.syn_received: fin = RatpPacket(flags='FA') fin.c_sn = (self._s_sn + 1) % 2 fin.c_an = (self._r_sn + 1) % 2 -- 2.13.1 ___ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox
[PATCH 14/16] ratp: don't ignore data that may arrive in behaviour H1
If an input packet arrives H1 that has data in it, we need to: * track sn_received * if we have data pending, send it * if we don't have data pending, send a plain ACK This process, as noted in RFC916, is the same as the I1 procedure, so go and run it: Go to the ESTABLISHED state and execute procedure I1 to process any data which might be in this packet. Signed-off-by: Aleksander Morgado --- lib/ratp.c | 8 +++- scripts/remote/ratp.py | 14 ++ 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/lib/ratp.c b/lib/ratp.c index e810a9e54..2dee41009 100644 --- a/lib/ratp.c +++ b/lib/ratp.c @@ -1042,6 +1042,8 @@ static int ratp_behaviour_g(struct ratp_internal *ri, void *pkt) return 0; } +static int ratp_behaviour_i1(struct ratp_internal *ri, void *pkt); + /* * Our SYN has been acknowledged. At this point we are * technically in the ESTABLISHED state. Send any initial data @@ -1062,7 +1064,11 @@ static int ratp_behaviour_h1(struct ratp_internal *ri, void *pkt) ratp_state_change(ri, RATP_STATE_ESTABLISHED); - return 0; + /* If the input message has data (i.e. it is not just an ACK +* without data) then we need to send back an ACK ourselves, +* or even data if we have it pending. This is the same +* procedure done in i1, so just run it. */ + return ratp_behaviour_i1 (ri, pkt); } /* diff --git a/scripts/remote/ratp.py b/scripts/remote/ratp.py index e6b3e19b6..7972d31f2 100644 --- a/scripts/remote/ratp.py +++ b/scripts/remote/ratp.py @@ -489,12 +489,8 @@ class RatpConnection(object): def _h1(self, r): logging.info("H1") - -# FIXME: initial data? self._state = RatpState.established -self._r_sn = r.c_sn - -return False +return self._common_i1(r) def _h2(self, r): logging.info("H2") @@ -584,9 +580,7 @@ class RatpConnection(object): self._time_wait_deadline = monotonic() + self._get_rto() return False -def _i1(self, r): -logging.info("I1") - +def _common_i1(self, r): if r.c_so: self._r_sn = r.c_sn self._rx_buf.append(chr(r.length)) @@ -608,6 +602,10 @@ class RatpConnection(object): self._write(s) return False +def _i1(self, r): +logging.info("I1") +return self._common_i1(r) + def _machine(self, pkt): logging.info("State: %r", self._state) if self._state == RatpState.listen: -- 2.13.1 ___ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox
[PATCH 15/16] ratp: consolidate setting the next AN or SN flags
Setting the next AN or SN flag was being done in two different ways throughout the code; e.g. here for AN: ratp_set_an(ratp_sn(hdr) + 1); or: ratp_set_an(!ratp_sn(hdr)); We define a pair of new ratp_set_next_sn() and ratp_set_next_an() macros that make it clear that the next value is desired, and also hide the computation of the actual flag value within the macro, so the previous example would now look like: ratp_set_next_an(ratp_sn(hdr)); Signed-off-by: Aleksander Morgado --- lib/ratp.c | 30 -- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/lib/ratp.c b/lib/ratp.c index 2dee41009..46a82c69a 100644 --- a/lib/ratp.c +++ b/lib/ratp.c @@ -139,8 +139,10 @@ static bool ratp_an(struct ratp_header *hdr) return hdr->control & RATP_CONTROL_AN ? 1 : 0; } -#define ratp_set_sn(sn) (((sn) % 2) ? RATP_CONTROL_SN : 0) -#define ratp_set_an(an) (((an) % 2) ? RATP_CONTROL_AN : 0) +#define ratp_set_sn(sn) (sn ? RATP_CONTROL_SN : 0) +#define ratp_set_an(an) (an ? RATP_CONTROL_AN : 0) +#define ratp_set_next_sn(sn) (((sn + 1) % 2) ? RATP_CONTROL_SN : 0) +#define ratp_set_next_an(an) (((an + 1) % 2) ? RATP_CONTROL_AN : 0) static inline int ratp_header_ok(struct ratp_internal *ri, struct ratp_header *h) { @@ -368,7 +370,7 @@ static int ratp_send_ack(struct ratp_internal *ri, struct ratp_header *hdr) int ret; control = ratp_set_sn(ratp_an(hdr)) | - ratp_set_an(ratp_sn(hdr) + 1) | + ratp_set_next_an(ratp_sn(hdr)) | RATP_CONTROL_ACK; ret = ratp_send_hdr(ri, control); @@ -404,8 +406,8 @@ static int ratp_send_next_data(struct ratp_internal *ri) len = msg->len; - control = ratp_set_sn(ri->sn_sent + 1) | - ratp_set_an(ri->sn_received + 1) | + control = ratp_set_next_sn(ri->sn_sent) | + ratp_set_next_an(ri->sn_received) | RATP_CONTROL_ACK; hdr = msg->buf; @@ -630,7 +632,7 @@ static void ratp_behaviour_b(struct ratp_internal *ri, void *pkt) } else { struct ratp_header synack = {}; - control = ratp_set_an(!ratp_sn(hdr)) | + control = ratp_set_next_an(ratp_sn(hdr)) | RATP_CONTROL_SYN | RATP_CONTROL_ACK; @@ -734,7 +736,7 @@ static int ratp_behaviour_c2(struct ratp_internal *ri, void *pkt) pr_debug("Error: Connection reset\n"); control = RATP_CONTROL_RST | RATP_CONTROL_ACK | - ratp_set_sn(ratp_an(hdr)) | ratp_set_an(!ratp_sn(hdr)); + ratp_set_sn(ratp_an(hdr)) | ratp_set_next_an(ratp_sn(hdr)); ratp_send_hdr(ri, control); ratp_state_change(ri, RATP_STATE_CLOSED); @@ -1035,7 +1037,7 @@ static int ratp_behaviour_g(struct ratp_internal *ri, void *pkt) if (hdr->control & RATP_CONTROL_ACK) control |= ratp_set_sn(ratp_an(hdr)); else - control |= ratp_set_an(ratp_sn(hdr) + 1) | RATP_CONTROL_ACK; + control |= ratp_set_next_an(ratp_sn(hdr)) | RATP_CONTROL_ACK; ratp_send_hdr(ri, control); @@ -1099,7 +1101,7 @@ static int ratp_behaviour_h2(struct ratp_internal *ri, void *pkt) ri->status = -ENETDOWN; control = ratp_set_sn(ratp_an(hdr)) | - ratp_set_an(ratp_sn(hdr) + 1) | + ratp_set_next_an(ratp_sn(hdr)) | RATP_CONTROL_FIN | RATP_CONTROL_ACK; @@ -1165,7 +1167,7 @@ static int ratp_behaviour_h3(struct ratp_internal *ri, void *pkt) if (ratp_has_data(hdr)) { control = ratp_set_sn(ratp_an(hdr)) | - ratp_set_an(ratp_sn(hdr) + 1) | + ratp_set_next_an(ratp_sn(hdr)) | RATP_CONTROL_RST | RATP_CONTROL_ACK; ratp_send_hdr(ri, control); @@ -1176,7 +1178,7 @@ static int ratp_behaviour_h3(struct ratp_internal *ri, void *pkt) } control = ratp_set_sn(ratp_an(hdr)) | - ratp_set_an(ratp_sn(hdr) + 1) | + ratp_set_next_an(ratp_sn(hdr)) | RATP_CONTROL_ACK; expected = ratp_an_expected(ri, hdr); @@ -1278,7 +1280,7 @@ static int ratp_behaviour_h6(struct ratp_internal *ri, void *pkt) if (!(hdr->control & RATP_CONTROL_FIN)) return 1; - control = ratp_set_sn(ratp_an(hdr) + 1) | RATP_CONTROL_ACK; + control = ratp_set_next_sn(ratp_an(hdr)) | RATP_CONTROL_ACK; ratp_send_hdr(ri, control); @@ -1695,8 +1697,8 @@ void ratp_close(struct ratp *ratp) ratp_state_change(ri, RATP_STATE_FIN_WAIT); - control = ratp_set_sn(!ri->sn_sent) | - ratp_set_an(ri->sn_received + 1) | + control = ratp_set_next_sn(ri->sn_sent) | +
[PATCH 10/16] ratp: fix sending ACKs without data
All ACKs without data must be built in the same way from the input message: The code was actually doing this instead: Signed-off-by: Aleksander Morgado --- lib/ratp.c | 9 - 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/lib/ratp.c b/lib/ratp.c index 321721ab7..5c52d3b5f 100644 --- a/lib/ratp.c +++ b/lib/ratp.c @@ -364,13 +364,12 @@ static bool ratp_sn_expected(struct ratp_internal *ri, struct ratp_header *hdr) static int ratp_send_ack(struct ratp_internal *ri, struct ratp_header *hdr) { - uint8_t control = RATP_CONTROL_ACK; + uint8_t control; int ret; - if (hdr->control & RATP_CONTROL_SN) - control |= RATP_CONTROL_AN; - else - control |= 0; + control = ratp_set_sn(ratp_an(hdr)) | + ratp_set_an(ratp_sn(hdr) + 1) | + RATP_CONTROL_ACK; ret = ratp_send_hdr(ri, control); if (ret) -- 2.13.1 ___ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox
[PATCH 13/16] ratp: send initial data in behaviour B if any pending
And also, use ratp_send_ack() instead of manually constructing an ACK if no data is pending to be sent. Signed-off-by: Aleksander Morgado --- lib/ratp.c | 8 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/ratp.c b/lib/ratp.c index c7f3f4171..e810a9e54 100644 --- a/lib/ratp.c +++ b/lib/ratp.c @@ -622,11 +622,11 @@ static void ratp_behaviour_b(struct ratp_internal *ri, void *pkt) ri->sn_received = ratp_sn(hdr); if (hdr->control & RATP_CONTROL_ACK) { - control = ratp_set_sn(ratp_an(hdr)) | - ratp_set_an(!ratp_sn(hdr)) | - RATP_CONTROL_ACK; - ratp_send_hdr(ri, control); ratp_state_change(ri, RATP_STATE_ESTABLISHED); + if (list_empty(&ri->sendmsg) || ri->sendmsg_current) + ratp_send_ack(ri, hdr); + else + ratp_send_next_data(ri); } else { struct ratp_header synack = {}; -- 2.13.1 ___ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox
[PATCH 09/16] ratp: remove FIXME comment: FIN always requires ACK
Section 3.4 in the RFC916 shows a packet flow for the connection close where the initial packet sent by the endpoint starting the close has just the FIN flag set, without an ACK: --> <-- --> This may lead to think that it is actually allowed to send the initial packet with just FIN set, without ACK-ing any other packet from the peer. But, this is actually not possible, the packet MUST be ACK-ing a previous packet from the peer, even if this is just a duplicated ACK, because otherwise the packet with the FIN wouldn't get processed in the H2 behavior (FIN processing) of the peer, as the F2 behavior (ACK processing) would filter it out. This is actually the same reasoning why data packets always have ACK set, even if the same ACK has already been sent previously (e.g. with a simple ACK packet without data); if they didn't have it, they would be filtered out in the F2 behavior, never arriving the I1 behavior, which is where the received data is processed. Signed-off-by: Aleksander Morgado --- scripts/remote/ratp.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/remote/ratp.py b/scripts/remote/ratp.py index 0dfc8420c..e6b3e19b6 100644 --- a/scripts/remote/ratp.py +++ b/scripts/remote/ratp.py @@ -724,7 +724,7 @@ class RatpConnection(object): deadline = monotonic() + timeout logging.info("CLOSE") if self._state == RatpState.established: -fin = RatpPacket(flags='FA') # FIXME: only F? +fin = RatpPacket(flags='FA') fin.c_sn = (self._s_sn + 1) % 2 fin.c_an = (self._r_sn + 1) % 2 self._write(fin) -- 2.13.1 ___ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox
[PATCH 12/16] ratp: prefer using ratp_send_ack() in behaviour I1
Instead of manually constructing an ACK, use the ratp_send_ack() method, which already does that properly. Signed-off-by: Aleksander Morgado --- lib/ratp.c | 12 +++- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/lib/ratp.c b/lib/ratp.c index 46a2b645c..c7f3f4171 100644 --- a/lib/ratp.c +++ b/lib/ratp.c @@ -1330,7 +1330,6 @@ static int msg_recv(struct ratp_internal *ri, void *pkt) static int ratp_behaviour_i1(struct ratp_internal *ri, void *pkt) { struct ratp_header *hdr = pkt; - uint8_t control = 0; if (!ratp_has_data (hdr)) return 1; @@ -1341,15 +1340,10 @@ static int ratp_behaviour_i1(struct ratp_internal *ri, void *pkt) msg_recv(ri, pkt); - if (list_empty(&ri->sendmsg) || ri->sendmsg_current) { - control = ratp_set_sn(!ri->sn_sent) | - ratp_set_an(ri->sn_received + 1) | - RATP_CONTROL_ACK; - - ratp_send_hdr(ri, control); - } else { + if (list_empty(&ri->sendmsg) || ri->sendmsg_current) + ratp_send_ack(ri, hdr); + else ratp_send_next_data(ri); - } return 0; } -- 2.13.1 ___ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox
[PATCH 07/16] ratp: fix single byte sending flagged with SO
When a single data byte is sent, it is flagged as SO and the actual data goes in the length byte within the header. Signed-off-by: Aleksander Morgado --- lib/ratp.c | 11 ++- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/lib/ratp.c b/lib/ratp.c index c946bea1a..846f8130c 100644 --- a/lib/ratp.c +++ b/lib/ratp.c @@ -384,6 +384,7 @@ static int ratp_send_next_data(struct ratp_internal *ri) uint16_t crc; uint8_t control; struct ratp_header *hdr; + uint8_t *data; int pktlen; struct ratp_message *msg; int len; @@ -409,19 +410,19 @@ static int ratp_send_next_data(struct ratp_internal *ri) RATP_CONTROL_ACK; hdr = msg->buf; + data = (uint8_t *)(hdr + 1); if (msg->eor) control |= RATP_CONTROL_EOR; + pktlen = sizeof(struct ratp_header); if (len > 1) { - void *data = hdr + 1; - pktlen = sizeof(*hdr) + len + 2; + pktlen += len + 2; crc = cyg_crc16(data, len); put_unaligned_be16(crc, data + len); - } else { - pktlen = sizeof(struct ratp_header); + } else if (len == 1) { control |= RATP_CONTROL_SO; - len = 0; + len = *data; } ratp_create_packet(ri, hdr, control, len); -- 2.13.1 ___ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox
[PATCH 11/16] ratp: consolidate ratp_sn_expected() and ratp_an_expected()
This is no code change in ratp_sn_expected(), it's just rewritten in the same way as ratp_an_expected(), which follows the RFC916 approach. Signed-off-by: Aleksander Morgado --- lib/ratp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ratp.c b/lib/ratp.c index 5c52d3b5f..46a2b645c 100644 --- a/lib/ratp.c +++ b/lib/ratp.c @@ -359,7 +359,7 @@ static bool ratp_an_expected(struct ratp_internal *ri, struct ratp_header *hdr) static bool ratp_sn_expected(struct ratp_internal *ri, struct ratp_header *hdr) { - return ratp_sn(hdr) != ri->sn_received; + return ratp_sn(hdr) == (ri->sn_received + 1) % 2; } static int ratp_send_ack(struct ratp_internal *ri, struct ratp_header *hdr) -- 2.13.1 ___ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox
[PATCH 01/16] ratp: add missing transition to SYN-RECEIVED in behavior B
The reference says: If the SYN flag was set but the ACK was not set then the other end of the connection has executed an active open also. Acknowledge the SYN, choose your MDL, and send: Go to the SYN-RECEIVED state without any further processing. Add this missing step. Signed-off-by: Aleksander Morgado --- lib/ratp.c | 14 +- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/lib/ratp.c b/lib/ratp.c index 22e83636f..0d384aa4e 100644 --- a/lib/ratp.c +++ b/lib/ratp.c @@ -619,21 +619,25 @@ static void ratp_behaviour_b(struct ratp_internal *ri, void *pkt) if (hdr->control & RATP_CONTROL_SYN) { uint8_t control; + ri->sn_received = ratp_sn(hdr); + if (hdr->control & RATP_CONTROL_ACK) { control = ratp_set_sn(ratp_an(hdr)) | ratp_set_an(!ratp_sn(hdr)) | RATP_CONTROL_ACK; + ratp_send_hdr(ri, control); + ratp_state_change(ri, RATP_STATE_ESTABLISHED); } else { + struct ratp_header synack = {}; + control = ratp_set_an(!ratp_sn(hdr)) | RATP_CONTROL_SYN | RATP_CONTROL_ACK; + ratp_create_packet(ri, &synack, control, 255); + ratp_send_pkt(ri, &synack, sizeof(synack)); + ratp_state_change(ri, RATP_STATE_SYN_RECEIVED); } - - ri->sn_received = ratp_sn(hdr); - - ratp_send_hdr(ri, control); - ratp_state_change(ri, RATP_STATE_ESTABLISHED); } } -- 2.13.1 ___ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox
[PATCH 02/16] ratp: avoid unnecessary variable initializations
Signed-off-by: Aleksander Morgado --- lib/ratp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/ratp.c b/lib/ratp.c index 0d384aa4e..e9536499e 100644 --- a/lib/ratp.c +++ b/lib/ratp.c @@ -382,7 +382,7 @@ static int ratp_send_ack(struct ratp_internal *ri, struct ratp_header *hdr) static int ratp_send_next_data(struct ratp_internal *ri) { uint16_t crc; - uint8_t control = RATP_CONTROL_ACK; + uint8_t control; struct ratp_header *hdr; int pktlen; struct ratp_message *msg; @@ -594,7 +594,7 @@ static void ratp_behaviour_b(struct ratp_internal *ri, void *pkt) if ((hdr->control & RATP_CONTROL_ACK) && !ratp_an_expected(ri, hdr)) { if (!(hdr->control & RATP_CONTROL_RST)) { - uint8_t control = RATP_CONTROL_RST; + uint8_t control; control = RATP_CONTROL_RST | ratp_set_sn(ratp_an(hdr)); -- 2.13.1 ___ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox
[PATCH 06/16] ratp: fix data presence check
Looking at the "data length" and SO flag isn't enough to declare a packet with or without data, because SYN flagged packets will also use the "data length" field to define MDL. So, improve the check to match against SYN|RST|FIN flagged packets, which can never have data. Signed-off-by: Aleksander Morgado --- lib/ratp.c | 4 ++-- scripts/remote/ratp.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/ratp.c b/lib/ratp.c index d3c252047..c946bea1a 100644 --- a/lib/ratp.c +++ b/lib/ratp.c @@ -165,7 +165,7 @@ static bool ratp_has_data(struct ratp_header *hdr) { if (hdr->control & RATP_CONTROL_SO) return 1; - if (hdr->data_length) + if (!(hdr->control & (RATP_CONTROL_SYN | RATP_CONTROL_RST | RATP_CONTROL_FIN)) && hdr->data_length) return 1; return 0; } @@ -1338,7 +1338,7 @@ static int ratp_behaviour_i1(struct ratp_internal *ri, void *pkt) struct ratp_header *hdr = pkt; uint8_t control = 0; - if (!hdr->data_length && !(hdr->control & RATP_CONTROL_SO)) + if (!ratp_has_data (hdr)) return 1; pr_vdebug("%s **received** %d\n", __func__, hdr->data_length); diff --git a/scripts/remote/ratp.py b/scripts/remote/ratp.py index 079fb871a..a41d2e8a3 100644 --- a/scripts/remote/ratp.py +++ b/scripts/remote/ratp.py @@ -525,7 +525,7 @@ class RatpConnection(object): # Our fin was lost, rely on retransmission return False -if r.length or r.c_so: +if (r.length and not r.c_syn and not r.c_rst and not r.c_fin) or r.c_so: self._retrans = None s = RatpPacket(flags='RA') s.c_sn = r.c_an @@ -596,7 +596,7 @@ class RatpConnection(object): if r.c_so: self._r_sn = r.c_sn self._rx_buf.append(chr(r.length)) -elif r.length: +elif r.length and not r.c_syn and not r.c_rst and not r.c_fin: self._r_sn = r.c_sn self._rx_buf.append(r.payload) else: -- 2.13.1 ___ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox
[PATCH 03/16] ratp: send missing RST in behavior C2
The reference says: If SYN was set we assume that the other end crashed and has attempted to open a new connection. We respond by sending a legal reset: Add this missing step. Signed-off-by: Aleksander Morgado --- lib/ratp.c | 7 +++ 1 file changed, 7 insertions(+) diff --git a/lib/ratp.c b/lib/ratp.c index e9536499e..a8ac52c75 100644 --- a/lib/ratp.c +++ b/lib/ratp.c @@ -731,8 +731,15 @@ static int ratp_behaviour_c2(struct ratp_internal *ri, void *pkt) return 1; if (hdr->control & RATP_CONTROL_SYN) { + uint8_t control; + ri->status = -ECONNRESET; pr_debug("Error: Connection reset\n"); + + control = RATP_CONTROL_RST | RATP_CONTROL_ACK | + ratp_set_sn(ratp_an(hdr)) | ratp_set_an(!ratp_sn(hdr)); + ratp_send_hdr(ri, control); + ratp_state_change(ri, RATP_STATE_CLOSED); return 1; } -- 2.13.1 ___ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox
[PATCH 08/16] ratp: remove bogus data checks in behavior C2
The SN validation was being completely ignored if the packet had no data (e.g. for RST, FIN or SYN or plain ACKs). This condition is now removed so that the SN check is done. The second check removed was actually never being used, as it was already being tested for not having data in the first one. Signed-off-by: Aleksander Morgado --- lib/ratp.c | 8 +--- scripts/remote/ratp.py | 16 +--- 2 files changed, 6 insertions(+), 18 deletions(-) diff --git a/lib/ratp.c b/lib/ratp.c index 846f8130c..321721ab7 100644 --- a/lib/ratp.c +++ b/lib/ratp.c @@ -721,9 +721,6 @@ static int ratp_behaviour_c2(struct ratp_internal *ri, void *pkt) pr_debug("%s\n", __func__); - if (!ratp_has_data(hdr)) - return 0; - if (ratp_sn_expected(ri, hdr)) return 0; @@ -745,9 +742,6 @@ static int ratp_behaviour_c2(struct ratp_internal *ri, void *pkt) return 1; } - if (!ratp_has_data(hdr)) - return 1; - pr_debug("Sending ack for duplicate message\n"); ret = ratp_send_ack(ri, hdr); if (ret) @@ -1846,4 +1840,4 @@ eor: } return 0; -} \ No newline at end of file +} diff --git a/scripts/remote/ratp.py b/scripts/remote/ratp.py index a41d2e8a3..0dfc8420c 100644 --- a/scripts/remote/ratp.py +++ b/scripts/remote/ratp.py @@ -339,9 +339,6 @@ class RatpConnection(object): def _c2(self, r): logging.info("C2") -if r.length == 0 and r.c_so == 0: -return True - if r.c_sn != self._r_sn: return True @@ -358,14 +355,11 @@ class RatpConnection(object): self._state = RatpState.closed return False -# FIXME: only ack duplicate data packages? -# This is not documented in RFC 916 -if r.length or r.c_so: -logging.info("C2: duplicate data packet, dropping") -s = RatpPacket(flags='A') -s.c_sn = r.c_an -s.c_an = (r.c_sn + 1) % 2 -self._write(s) +logging.info("C2: duplicate packet") +s = RatpPacket(flags='A') +s.c_sn = r.c_an +s.c_an = (r.c_sn + 1) % 2 +self._write(s) return False -- 2.13.1 ___ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox
[PATCH 04/16] ratp: add missing RST flag in behavior G
The reference says: If the ACK flag was set then send: If the ACK flag was not set then send: (i.e. in both cases RST is needed) The RST flag is set initially in the 'control' variable; so instead of completely overwriting it, make sure the additional flags are OR-ed to the current value. Signed-off-by: Aleksander Morgado --- lib/ratp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ratp.c b/lib/ratp.c index a8ac52c75..43b8b04dc 100644 --- a/lib/ratp.c +++ b/lib/ratp.c @@ -1038,7 +1038,7 @@ static int ratp_behaviour_g(struct ratp_internal *ri, void *pkt) if (hdr->control & RATP_CONTROL_ACK) control |= ratp_set_sn(ratp_an(hdr)); else - control = ratp_set_an(ratp_sn(hdr) + 1) | RATP_CONTROL_ACK; + control |= ratp_set_an(ratp_sn(hdr) + 1) | RATP_CONTROL_ACK; ratp_send_hdr(ri, control); -- 2.13.1 ___ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox
[PATCH 00/16] RATP logic fixes and improvements
Hey Sascha, I went through the RFC916 and ended up preparing a set of fixes and improvements for the RATP logic in barebox. Let me know what you think. Cheers! Aleksander Morgado (16): ratp: add missing transition to SYN-RECEIVED in behavior B ratp: avoid unnecessary variable initializations ratp: send missing RST in behavior C2 ratp: add missing RST flag in behavior G ratp: completely ignore RST flagged packets in behavior G ratp: fix data presence check ratp: fix single byte sending flagged with SO ratp: remove bogus data checks in behavior C2 ratp: remove FIXME comment: FIN always requires ACK ratp: fix sending ACKs without data ratp: consolidate ratp_sn_expected() and ratp_an_expected() ratp: prefer using ratp_send_ack() in behaviour I1 ratp: send initial data in behaviour B if any pending ratp: don't ignore data that may arrive in behaviour H1 ratp: consolidate setting the next AN or SN flags ratp: user close may happen in SYN-RECEIVED state lib/ratp.c | 116 +++-- scripts/remote/ratp.py | 38 +++- 2 files changed, 78 insertions(+), 76 deletions(-) -- 2.13.1 ___ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox
[PATCH 05/16] ratp: completely ignore RST flagged packets in behavior G
The reference says: This procedure represents the behavior of the CLOSED state of a connection. All incoming packets are discarded. If the packet had the RST flag set take no action. Otherwise it is necessary to build a RST packet. So, skip building the RST packet if the incoming one had RST set. Signed-off-by: Aleksander Morgado --- lib/ratp.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/ratp.c b/lib/ratp.c index 43b8b04dc..d3c252047 100644 --- a/lib/ratp.c +++ b/lib/ratp.c @@ -1033,6 +1033,9 @@ static int ratp_behaviour_g(struct ratp_internal *ri, void *pkt) pr_debug("%s\n", __func__); + if (hdr->control & RATP_CONTROL_RST) + return 0; + control = RATP_CONTROL_RST; if (hdr->control & RATP_CONTROL_ACK) -- 2.13.1 ___ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox
Re: [PATCH v1 1/1] gpio: of: provide option generic property for initial line states
Hi Oleksij, On 06/15/2017 08:56 AM, Oleksij Rempel wrote: > Hi Vladimir, > > On Sun, Jun 11, 2017 at 10:57:18PM +0300, Vladimir Zapolskiy wrote: >> Hi Oleksij, >> >> On 06/11/2017 09:19 AM, Oleksij Rempel wrote: >>> Hi Rob, >>> >>> On Fri, Jun 09, 2017 at 10:41:30AM -0500, Rob Herring wrote: On Fri, Jun 9, 2017 at 9:16 AM, Oleksij Rempel wrote: > This property is needed for barebox or may be other bootloaders > to set proper gpio configuration as early as possible. > > This example is mainly based on "lines-initial-states" property > from this binding documentation: > Documentation/devicetree/bindings/gpio/gpio-pcf857x.txt Don't we have a binding for this already based on gpio-hogs. >>> >>> Markus Pargmann was working on this topic before and suddenly was not >>> able to finish it. >> >> that's fine, but the proposed extension is supposedly not wanted. > > :( No worries, we're in the discussion and 'supposedly' was a meaningful word :) >>> I found only some not finished discussions and no code or documentation >>> in linux kernel upstream. >>> >>> So far, I was able to find fallowing patches and discussions: >>> patch 23.08.2015, last comment 11.05.2017: >>> https://patchwork.kernel.org/patch/7096721/ >>> >>> patch 23.02.2016, last comment 09.03.2016: >>> https://patchwork.ozlabs.org/patch/586743/ >>> >>> Since there was objections about node-like design for gpio-initval, I >>> provided an array property, which is similar to initval properties already >>> used >>> for different other device nodes. For example: >>> >>> Documentation/devicetree/bindings/net/wireless/qcom,ath10k.txt >>> qcom,ath10k-calibration-data >>> >>> Documentation/devicetree/bindings/gpio/gpio-pcf857x.txt >>> lines-initial-states >> >> It'd rather be better to fix the drivers and remove the properties >> from these found device tree binding descriptions. > > no sure if it is possible. WiFi calibration data is kind of initval too. Sorry, I have no idea about the ath10k calibration data and its connection to the GPIO framework. >>> >>> Please fixme if I miss something. >> >> Why is GPIO hogging mechanism not good enough for your purpose? > > Becouse it should not permanently hog a gpio. The "Hogging" should be > released as soon as some driver will request it. > > Right now, if I define gpio-hog, boot loader will configure it and start > linux. But linux will never let it free. > > If you have other suggestions which fit to this use case, please tell > me. I assume, right now I'm just blind. Ok, I'll meditate on it. > Other way, I can imagine is to create real device nodes which use this > gpios. Compatible for this devices will be like this: > some_gpio_holder: gpio@0 { > compatible = "gpio-for-userspace"; > gpio = <&gpio1 5 GPIO_ACTIVE_HIGH>; > }; Generally it might be a good option, because if GPIOs are essentially needed to be preset, I can conclude there are some ICs to which these GPIOs are connected, thus drivers of these ICs can become GPIO consumers and get a proper description in a board DTB. > > Boot loader will configure it as needed, an linux will do nothing with > it so it can be used over /dev/gpio interface. As I read it from Documentation/gpio/sysfs.txt generic interface(s) to control GPIOs is a last resort, it is not clear if you want a new feature for all possible consumers or just userspace consumers. -- With best wishes, Vladimir ___ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox
[PATCH v2 3/3] ARM: mvebu: Add initial support for Turris Omnia
Up to now only 2nd stage booting is tested and boots up to a prompt. i2c and spi are working, ethernet, usb and sata don't. Signed-off-by: Uwe Kleine-König --- Changes since (implicit) v1: - fix copyright stuff - drop some debug remains - fix kwboot.cfg arch/arm/boards/Makefile| 1 + arch/arm/boards/turris-omnia/Makefile | 2 ++ arch/arm/boards/turris-omnia/board.c| 1 + arch/arm/boards/turris-omnia/kwbimage.cfg | 7 ++ arch/arm/boards/turris-omnia/lowlevel.c | 33 + arch/arm/dts/Makefile | 1 + arch/arm/dts/armada-385-turris-omnia-bb.dts | 7 ++ arch/arm/mach-mvebu/Kconfig | 10 + images/Makefile.mvebu | 8 +++ 9 files changed, 70 insertions(+) create mode 100644 arch/arm/boards/turris-omnia/Makefile create mode 100644 arch/arm/boards/turris-omnia/board.c create mode 100644 arch/arm/boards/turris-omnia/kwbimage.cfg create mode 100644 arch/arm/boards/turris-omnia/lowlevel.c create mode 100644 arch/arm/dts/armada-385-turris-omnia-bb.dts diff --git a/arch/arm/boards/Makefile b/arch/arm/boards/Makefile index 0ecfb3e4b398..896a3f5cbab5 100644 --- a/arch/arm/boards/Makefile +++ b/arch/arm/boards/Makefile @@ -124,6 +124,7 @@ obj-$(CONFIG_MACH_TORADEX_COLIBRI_T20) += toradex-colibri-t20/ obj-$(CONFIG_MACH_TOSHIBA_AC100) += toshiba-ac100/ obj-$(CONFIG_MACH_TQMA53) += tqma53/ obj-$(CONFIG_MACH_TQMA6X) += tqma6x/ +obj-$(CONFIG_MACH_TURRIS_OMNIA)+= turris-omnia/ obj-$(CONFIG_MACH_TX25)+= karo-tx25/ obj-$(CONFIG_MACH_TX28)+= karo-tx28/ obj-$(CONFIG_MACH_TX51)+= karo-tx51/ diff --git a/arch/arm/boards/turris-omnia/Makefile b/arch/arm/boards/turris-omnia/Makefile new file mode 100644 index ..01c7a259e9a5 --- /dev/null +++ b/arch/arm/boards/turris-omnia/Makefile @@ -0,0 +1,2 @@ +obj-y += board.o +lwl-y += lowlevel.o diff --git a/arch/arm/boards/turris-omnia/board.c b/arch/arm/boards/turris-omnia/board.c new file mode 100644 index ..40a8c178f10d --- /dev/null +++ b/arch/arm/boards/turris-omnia/board.c @@ -0,0 +1 @@ +/* empty */ diff --git a/arch/arm/boards/turris-omnia/kwbimage.cfg b/arch/arm/boards/turris-omnia/kwbimage.cfg new file mode 100644 index ..789ee5df17de --- /dev/null +++ b/arch/arm/boards/turris-omnia/kwbimage.cfg @@ -0,0 +1,7 @@ +VERSION 1 +BOOT_FROM spi +DESTADDR 0080 +EXECADDR 0080 +NAND_BLKSZ +NAND_BADBLK_LOCATION 00 +BINARY binary.0 005b 0068 diff --git a/arch/arm/boards/turris-omnia/lowlevel.c b/arch/arm/boards/turris-omnia/lowlevel.c new file mode 100644 index ..3f20908ff7fd --- /dev/null +++ b/arch/arm/boards/turris-omnia/lowlevel.c @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2017 Pengutronix, Uwe Kleine-Koenig + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include + +#include + +extern char __dtb_armada_385_turris_omnia_bb_start[]; + +ENTRY_FUNCTION(start_turris_omnia, r0, r1, r2) +{ + void *fdt; + + arm_cpu_lowlevel_init(); + + fdt = __dtb_armada_385_turris_omnia_bb_start - + get_runtime_offset(); + + armada_370_xp_barebox_entry(fdt); +} diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile index 2342d35a4bd1..c81e6e0e492c 100644 --- a/arch/arm/dts/Makefile +++ b/arch/arm/dts/Makefile @@ -81,6 +81,7 @@ pbl-dtb-$(CONFIG_MACH_TQMA6X) += imx6dl-mba6x.dtb.o imx6q-mba6x.dtb.o pbl-dtb-$(CONFIG_MACH_TX25) += imx25-karo-tx25.dtb.o pbl-dtb-$(CONFIG_MACH_TX6X) += imx6dl-tx6u.dtb.o pbl-dtb-$(CONFIG_MACH_TX6X) += imx6q-tx6q.dtb.o +pbl-dtb-$(CONFIG_MACH_TURRIS_OMNIA) += armada-385-turris-omnia-bb.dtb.o pbl-dtb-$(CONFIG_MACH_UDOO) += imx6q-udoo.dtb.o pbl-dtb-$(CONFIG_MACH_USI_TOPKICK) += kirkwood-topkick-bb.dtb.o pbl-dtb-$(CONFIG_MACH_VARISCITE_MX6) += imx6q-var-custom.dtb.o diff --git a/arch/arm/dts/armada-385-turris-omnia-bb.dts b/arch/arm/dts/armada-385-turris-omnia-bb.dts new file mode 100644 index ..53bef01af758 --- /dev/null +++ b/arch/arm/dts/armada-385-turris-omnia-bb.dts @@ -0,0 +1,7 @@ +#include "arm/armada-385-turris-omnia.dts" + +/ { + chosen { + stdout-path = "/soc/internal-regs/serial@12000"; + }; +}; diff --git a/arch/arm/mach-mvebu/Kconfig b/arch/arm/mach-mvebu/Kconfig index 827967eea380..ad97e83701e7 100644 --- a/arch/arm/mach-mvebu/Kconfig +