Introduced LLC (for TFTP and Console) to the usual networking stack.
authorRick van Rein <vanrein@hwdev.(none)>
Thu, 30 Jun 2011 21:35:14 +0000 (21:35 +0000)
committerRick van Rein <vanrein@hwdev.(none)>
Thu, 30 Jun 2011 21:35:14 +0000 (21:35 +0000)
This introduces a few really useful programming facilities:
 1. To be able to download the Flash (and, in some future, upload)
 2. To access a console over Ethernet, displaying bottom_printf()

24 files changed:
TODO
include/0cpm/netfun.h
include/bottom/blackfin.h
src/driver/Makefile
src/driver/soc/tic55x.c [deleted file]
src/function/Makefile
src/function/bootloader.c
src/function/develtest/echo.c
src/function/develtest/keys2display.c
src/function/develtest/netconsole.c
src/function/develtest/switch2led.c
src/function/develtest/timer2led.c
src/function/netconsole.c
src/function/sip6phone/topmain.c
src/kernel/cpu.c
src/kernel/net.c
src/kernel/timer.c
src/net/Makefile
src/net/core.c
src/net/input.c
src/net/llc.c [new file with mode: 0644]
src/net/llconly.c
src/net/reply.c
src/target/Makefile

diff --git a/TODO b/TODO
index efb9604..a4790ee 100644 (file)
--- a/TODO
+++ b/TODO
@@ -17,10 +17,6 @@ look at:
   (The original idea was to do the entire processing in that style, but
   it turned out not to be sufficiently flexible for that.)
 
-* The replies from netinput.c are functions to be called.  Decide if
-  this is enough, and if it can cover netreply_* as well as netdb_*
-  with the same setup.  Is this all typesafe?
-
 * Must join multicast addresses for local addresses, as described in
   http://tools.ietf.org/html/rfc4291 section 2.7.1, ff02::1:ff00:0/102
   for solicited-node address.  WIDE DHCPv6 server actually needs this.
@@ -33,5 +29,7 @@ look at:
 * tic55x's int.c driver: work out conditions for hibernation sleep.
   In hibernation, also shutdown the codec.
 
+* tic55x should include from separate directory for <stdbool.h>
+
 * Append network stack with LLC1 (for TFTP) and LLC2 (for console).
 
index 67f7f4a..c0c7552 100644 (file)
@@ -63,6 +63,11 @@ enum mem_netinput {
        MEM_VLAN_ID,
        MEM_BINDING6,
        MEM_IP6_DST,
+       MEM_LLC_SSAP,
+       MEM_LLC_DSAP,
+       MEM_LLC_CMD,
+       MEM_LLC_PKTLEN,
+       MEM_LLC_PAYLOAD,
        //
        // The number of entries in this enum
        MEM_NETVAR_COUNT
@@ -104,6 +109,14 @@ uint8_t *netreply_icmp6_ngb_disc (uint8_t *pkt, intptr_t *mem);
 uint8_t *netreply_icmp6_echo_req (uint8_t *pkt, intptr_t *mem);
 uint8_t *netreply_dhcp4_offer (uint8_t *pkt, intptr_t *mem);
 uint8_t *netreply_dhcp6_advertise (uint8_t *pout, intptr_t *mem);
+uint8_t *netllc_reply (uint8_t *pout, intptr_t *mem);
+uint8_t *netllc_tftp (uint8_t *pout, intptr_t *mem);
+uint8_t *netllc_console_sabme (uint8_t *pout, intptr_t *mem);
+uint8_t *netllc_console_disc (uint8_t *pout, intptr_t *mem);
+uint8_t *netllc_console_frmr (uint8_t *pout, intptr_t *mem);
+uint8_t *netllc_console_datasentback (uint8_t *pout, intptr_t *mem);
+uint8_t *netllc_console_receiverfeedback (uint8_t *pout, intptr_t *mem);
+
 
 uint8_t *netsend_icmp6_router_solicit (uint8_t *pout, intptr_t *mem);
 uint8_t *netsend_icmp6_ngb_sol (uint8_t *pout, intptr_t *mem);
index 9fb85b0..85e155c 100644 (file)
  * You should have received a copy of the GNU General Public License
  * along with 0cpm Firmerware.  If not, see <http://www.gnu.org/licenses/>.
  */
+
+
+/* Below:
+ *  - definitions for this architecture to service the top half
+ *  - definitions to bind bottom half files together
+ *
+ * From: Rick van Rein <rick@openfortress.nl>
+ */
+
+
+/* The timer is the top 32-bit half of timer0 */
+typedef uint32_t timing_t;
+#define TIME_BEFORE(x,y)       (((x)-(y)) >> 31)
+#define TIME_BEFOREQ(x,y)      (!(TIME_BEFORE((y),(x))))
+
+#define TIMER_NULL 0
+
+#define TIME_MSEC(x)   (((uint32_t) (x)))
+#define TIME_SEC(x)    (((uint32_t) (x))*1000)
+#define TIME_MIN(x)    (((uint32_t) (x))*1000*60)
+#define TIME_HOUR(x)   (((uint32_t) (x))*1000*60*60)
+#define TIME_DAY(x)    (((uint32_t) (x))*1000*60*60*24)
+
+
+
index d7ef4a3..f7e6d7d 100644 (file)
@@ -5,6 +5,7 @@ objs-bottom-$(CONFIG_TARGET_GRANDSTREAM_BT20x) += src/driver/tic55x/grandstream-
 
 objs-bottom-$(CONFIG_PLATFORM_TIC55x) += src/driver/tic55x/int.o src/driver/tic55x/timer.o src/driver/tic55x/isrmap.o #NOPE# src/driver/tic55x/gpio.o #TODO# 
 
+objs-bottom-$(CONFIG_PLATFORM_BLACKFIN) += src/driver/blackfin/timer.o src/driver/blackfin/imaginary.o
 
 metavars-$(CONFIG_TARGET_GRANDSTREAM_BT20x) += SYSCLK1_TO_MS_DIVIDER=122880
 # metavars-$(CONFIG_TARGET_GRANDSTREAM_BT20x) += SYSCLK1_TO_MS_DIVIDER=61440
diff --git a/src/driver/soc/tic55x.c b/src/driver/soc/tic55x.c
deleted file mode 100644 (file)
index e69de29..0000000
index 3083035..dadb759 100644 (file)
@@ -9,8 +9,7 @@ objs-top-$(CONFIG_MAINFUNCTION_SIP_PHONE) += src/function/sip6phone/topmain.o bi
 
 objs-top-$(CONFIG_MAINFUNCTION_BOOTLOADER) += src/function/bootloader.o src/net/llconly.o src/function/netconsole.o
 
-#TODO# Must replace llconly.o with "real" LLC support in src/net/*
-objs-top-$(CONFIG_FUNCTION_NETCONSOLE) += src/function/netconsole.o src/net/llconly.o
+objs-top-$(CONFIG_FUNCTION_NETCONSOLE) += src/function/netconsole.o
 
 objs-top-$(CONFIG_FUNCTION_FIRMWARE_UPGRADES) += src/function/bootloader.o
 
index deb4738..4774894 100644 (file)
@@ -34,6 +34,8 @@
 
 #include <0cpm/cons.h>
 #include <0cpm/flash.h>
+#include <0cpm/netinet.h>
+#include <0cpm/netfun.h>
 
 
 /* Sanity check */
@@ -49,45 +51,53 @@ static struct flashpart *current = NULL;
 static uint16_t blocknum;
 static bool sending = false, receiving = false;
 
+extern uint8_t ether_mine [6];
 
-/* Handle an incoming TFTP request (over LLC)
+
+/* Handle a TFTP request that came in over LLC1.
  *
  * This code is rather brutal -- it only does binary transfers,
- * and it supports no options at all.
+ * and it supports no options at all.  It is mainly intended for
+ * bootstrapping (bootloading) purposes, offering access to the
+ * flash memory contained in the machine.
  */
-
-void bootloader_datagram (uint8_t *pkt, uint16_t pktlen) {
-       void netreply_llc1 (uint8_t *pkt, uint16_t pktlen);
+uint8_t *netllc_tftp (uint8_t *pkt, intptr_t *mem) {
        uint16_t cmd;
-       uint16_t pktlen2;
+       uint16_t pktlen, pktlen2;
+       uint16_t replylen = 0;
+       uint8_t *llc = (uint8_t *) mem [MEM_ETHER_HEAD];
+       pktlen = mem [MEM_ALL_DONE] - mem [MEM_ETHER_HEAD];
+       memcpy (pkt, llc+6, 6);
+       memcpy (pkt+6, ether_mine, 6);
+       pktlen2 = (llc [12] << 8) | llc [13];
+bottom_printf ("netllc_tftp, pktlen=%d, pktlen2=%d\n", pktlen, pktlen2);
        if (pktlen < 12 + 2 + 3 + 4) {
                return;
        }
-       pktlen2 = (pkt [12] << 8) | pkt [13];
        if (pktlen < pktlen2 + 12 + 2) {
                return;
        }
-       cmd = (pkt [12 + 2 + 3 + 0] << 8) | pkt [12 + 2 + 3 + 1];
+       cmd = (llc [12 + 2 + 3 + 0] << 8) | llc [12 + 2 + 3 + 1];
+bottom_printf ("Processing TFTP command %d\n", (int) cmd);
        if ((cmd == 1) || (cmd == 2)) {         /* 1==RRQ, 2=WRQ, new setup */
-               pkt [pktlen - 1] = 0;
+               llc [pktlen - 1] = 0;
                bottom_printf ("TFTP %s for %s\n",
                        (cmd == 1)? "RRQ": "WRQ",
-                       pkt + 12 + 2 + 3 + 2);
+                       llc + 12 + 2 + 3 + 2);
                current = (struct flashpart *) "TODO"; //TODO// current=flash_find_file(...), return if not found
                sending   = (current != NULL) && (cmd == 1);
                receiving = (current != NULL) && (cmd == 2);
-               pktlen = 12 + 2 + 3;
+               replylen = 12 + 2 + 3;
                blocknum = 0;
                if (sending) {
                        goto sendblock;
                }
                if (receiving) {
-                       pkt [pktlen++] = 0x00;  // send ACK
-                       pkt [pktlen++] = 0x04;
-                       pkt [pktlen++] = 0x00;
-                       pkt [pktlen++] = 0x00;
+                       pkt [replylen++] = 0x00;        // send ACK
+                       pkt [replylen++] = 0x04;
+                       pkt [replylen++] = 0x00;
+                       pkt [replylen++] = 0x00;
                }
-               netreply_llc1 (pkt, pktlen);
        } else if (cmd == 3) {                  /* 3==DATA, store or burn */
                if (!current) {
                        bottom_printf ("TFTP DATA received without connection\n");
@@ -104,7 +114,7 @@ void bootloader_datagram (uint8_t *pkt, uint16_t pktlen) {
                        pkt [12 + 2 + 3 + 1] = 0x04;
                        pkt [12 + 2 + 3 + 2] = blocknum >> 8;
                        pkt [12 + 2 + 3 + 3] = blocknum & 0xff;
-                       netreply_llc1 (pkt, 12 + 2 + 3 + 4);
+                       replylen = 12 + 2 + 3 + 4;
                }
        } else if (cmd == 4) {                  /* 4==ACK, send next if sending  */
                if (!current) {
@@ -126,9 +136,9 @@ sendblock:
                        pkt [12 + 2 + 3 + 2] = blocknum >> 8;
                        pkt [12 + 2 + 3 + 3] = blocknum & 0xff;
                        if (bottom_flash_read (blocknum - 1, pkt + 12 + 2 + 3 + 4)) {
-                               netreply_llc1 (pkt, 12 + 2 + 3 + 4 + 512);
+                               replylen = 12 + 2 + 3 + 4 + 512;
                        } else {
-                               netreply_llc1 (pkt, 12 + 2 + 3 + 4 + 0  );
+                               replylen = 12 + 2 + 3 + 4 +   0;
                        }
                }
        } else if (cmd == 5) {                  /* 5==ERR */
@@ -138,7 +148,21 @@ sendblock:
                        pkt + 12 + 2 + 3 + 4);
                /* no further error handling */
        }
-       
+       if (replylen) {
+bottom_printf ("TFTP reply consists of %d bytes\n", replylen);
+               // netllc_reply (pkt, mem);
+               pkt [12] = (replylen - 12 - 2) >> 8;
+               pkt [13] = (replylen - 12 - 2) & 0xff;
+               pkt [12 + 2 + 0] = mem [MEM_LLC_SSAP];          /* DSAP */
+               pkt [12 + 2 + 1] = 68;                          /* SSAP */
+               pkt [12 + 2 + 2] = 0x03;        /* UI, unnumbered information */
+               mem [MEM_ETHER_HEAD]  = (intptr_t) pkt;
+               mem [MEM_LLC_PAYLOAD] = (intptr_t) pkt + 17;
+               return pkt + replylen;
+       } else {
+bottom_printf ("No TFTP reply package\n");
+               return NULL;
+       }
 }
 
 
index 8b9f308..2014089 100644 (file)
@@ -46,8 +46,9 @@ volatile uint16_t tobeplayed   = 0;
 volatile uint16_t toberecorded = 0;
 
 
-void top_timer_expiration (timing_t timeout) {
+timing_t top_timer_expiration (timing_t timeout) {
         /* Keep the linker happy */ ;
+       return timeout;
 }
 
 void top_hook_update (bool offhook) {
index dbd112b..9920f42 100644 (file)
@@ -30,8 +30,9 @@
 #include <0cpm/show.h>
 
 
-void top_timer_expiration (timing_t timeout) {
+timing_t top_timer_expiration (timing_t timeout) {
        /* Keep the linker happy */ ;
+       return timeout;
 }
 
 void top_hook_update (bool offhook) {
index 4755d3e..93be551 100644 (file)
@@ -52,8 +52,9 @@
 bool online = false;
 
 
-void top_timer_expiration (timing_t timeout) {
+timing_t top_timer_expiration (timing_t timeout) {
        /* Keep the linker happy */ ;
+       return timeout;
 }
 
 void top_hook_update (bool offhook) {
index d5ca7bc..55eb8a2 100644 (file)
@@ -34,8 +34,9 @@
 #define complete_top_main top_main
 
 
-void top_timer_expiration (timing_t timeout) {
+timing_t top_timer_expiration (timing_t timeout) {
        /* Keep the linker happy */ ;
+       return timeout;
 }
 
 void top_hook_update (bool offhook) {
index 3c9909b..a459950 100644 (file)
@@ -105,11 +105,11 @@ void noirq_top_main (void) {
 }
 
 
-void top_timer_expiration (timing_t exptime) {
+timing_t top_timer_expiration (timing_t exptime) {
        uint16_t ctr;
        ledstate ^= LED_STABLE_ON ^ LED_STABLE_OFF;
        nextirq += TIME_MSEC(500);
-       bottom_timer_set (nextirq);
+       return nextirq;
 }
 
 
index 418d982..9f04741 100644 (file)
@@ -44,6 +44,9 @@
 
 #include <config.h>
 #include <0cpm/cons.h>
+#include <0cpm/cpu.h>
+#include <0cpm/irq.h>
+#include <0cpm/timer.h>
 
 
 /*
@@ -97,12 +100,29 @@ static void trysend (void) {
        }
 }
 
+#ifndef CONFIG_MAINFUNCTION_DEVEL_NETWORK
+static irqtimer_t console_timer;
+static void netcons_interval (irq_t *tmr) {
+       trysend ();
+       //TODO:Efficiency// if (rpos != wpos) {
+               irqtimer_restart ((irqtimer_t *) tmr, TIME_MSEC(20));
+       //TODO// }
+}
+#endif
+
 void netcons_connect (struct llc2 *cnx) {
        netcons_connection = cnx;
+#ifdef CONFIG_MAINFUNCTION_DEVEL_NETWORK
        trysend ();
+#else
+       irqtimer_start (&console_timer, 0, netcons_interval, CPU_PRIO_LOW);
+#endif
 }
 
 void netcons_close (void) {
+#ifndef CONFIG_MAINFUNCTION_DEVEL_NETWORK
+       irqtimer_stop (&console_timer);
+#endif
        netcons_connection = NULL;
 }
 
@@ -173,7 +193,7 @@ void bottom_console_vprintf (char *fmt, va_list argh) {
                                minpos += fp [-1] - '0';
                                goto moremeuk;
                        case 'c':
-                               ch = va_arg (argh, char);
+                               ch = (char) va_arg (argh, int);
                                cons_putchar (ch);
                                break;
                        case 's':
@@ -195,7 +215,7 @@ void bottom_console_vprintf (char *fmt, va_list argh) {
                                if (val32bit) {
                                        intval =            va_arg (argh, uint32_t);
                                } else {
-                                       intval = (uint32_t) va_arg (argh, uint16_t);
+                                       intval = (uint32_t) va_arg (argh, int     );
                                }
                                cons_putint (intval, 10, minpos);
                                break;
@@ -207,7 +227,7 @@ void bottom_console_vprintf (char *fmt, va_list argh) {
                                if (val32bit) {
                                        intval =            va_arg (argh, uint32_t);
                                } else {
-                                       intval = (uint32_t) va_arg (argh, uint16_t);
+                                       intval = (uint32_t) va_arg (argh, int     );
                                }
                                cons_putint (intval, 16, minpos);
                                break;
@@ -218,7 +238,9 @@ void bottom_console_vprintf (char *fmt, va_list argh) {
                        }
                }
        }
+#ifdef CONFIG_MAINFUNCTION_DEVEL_NETWORK
        trysend ();
+#endif
 }
 
 void bottom_console_printf (char *fmt, ...) {
index 2fcbd82..cbeaa4e 100644 (file)
@@ -117,7 +117,7 @@ uint8_t bad;
 irqtimer_t disptimer;
 int nibblepos = 0;
 timing_t nextrot = 0;
-void show_info (irqtimer_t *tmr) {
+void show_info (irq_t *tmr) {
        int relpos;
        //TODO:MANUAL_TIMER_AS_REAL_ONE_FAILS://
 #if 0
@@ -150,7 +150,7 @@ bottom_keyboard_scan ();
                nibblepos = 0;
        }
        ht162x_dispdata_notify (3, 14);
-       irqtimer_restart (tmr, TIME_MSEC (1000));
+       irqtimer_restart ((irqtimer_t *) tmr, TIME_MSEC (1000));
 }
 
 /* The main operational loop for the CPU.  Try to run code, and when
index 2a84f10..9a35536 100644 (file)
@@ -80,7 +80,7 @@ void irq_fire (irq_t *irq) {
  */
 void jobhopper (void) {
 void ht162x_putchar (uint8_t idx, uint8_t ch, bool notify);
-       bottom_printf ("Jobhopper starts.\n");
+       //OVERZEALOUSLOGGER// bottom_printf ("Jobhopper starts.\n");
 //TODO:TEST// ht162x_putchar (0, '0', true);
        while (cur_prio > CPU_PRIO_ZERO) {
                closure_t *here;
@@ -109,7 +109,7 @@ void ht162x_putchar (uint8_t idx, uint8_t ch, bool notify);
                                }
                                todo->irq_next = NULL;
                                bottom_critical_region_end ();
-                               bottom_printf ("Jobhopper calls interrupt handler.\n");
+                               //OVERZEALOUSLOGGER// bottom_printf ("Jobhopper calls interrupt handler.\n");
 //TODO:TEST// ht162x_audiolevel (2 << 5);
 //TODO:NAAAHHH// if (this->irq_handler)
                                (*todo->irq_handler) (todo);
@@ -138,6 +138,6 @@ void ht162x_putchar (uint8_t idx, uint8_t ch, bool notify);
                }
        }
 //TODO:TEST// ht162x_putchar (0, '9', true);
-       bottom_printf ("Jobhopper ends.\n");
+       //OVERZEALOUSLOGGER// bottom_printf ("Jobhopper ends.\n");
 }
 
index 69e1816..e2a35f0 100644 (file)
@@ -143,7 +143,7 @@ void ht162x_putchar (uint8_t idx, uint8_t ch, bool notify);
                        goto done;//TODO//break;
                }
 //TODO:TEST// ht162x_putchar (1, '2', true);
-               bottom_printf ("Received a network packet\n");
+               //TODO:OVERZEALOUS// bottom_printf ("Received a network packet\n");
                bzero (mymem, sizeof (mymem));
                rf = (retfn *) netinput (myrbuf.data, rbuflen, mymem);
 //TODO:TEST// ht162x_putchar (1, '3', true);
index 4f16204..d8fc597 100644 (file)
@@ -120,7 +120,7 @@ static void irqtimer_enable (void) {
        irqtimer_interrupt_blocked = false;
        if (irqtimer_interrupt_occurred) {
                timing_t now, next;
-               bottom_printf ("Activating deferred timer interrupt\n");
+               //TODO:OVERZEALOUS// bottom_printf ("Activating deferred timer interrupt\n");
                now = bottom_time ();
                next = top_timer_expiration (now);
                if (next != now) {
index 3560164..74d1ef7 100644 (file)
@@ -1,4 +1,4 @@
 src/net/6bed4.c:
        printf > $@ '#include <stdint.h>\nuint32_t ip4_6bed4 = ( (uint32_t) %d) << 24 | ((uint32_t) %d) << 16 | ((uint32_t) %d) << 8 | ((uint32_t) %d );\n' `echo $(CONFIG_NET_6BED4_SERVER) | sed 's/\./ /g'`
 
-objs-top-net-y += src/net/core.o src/net/input.o src/net/reply.o src/net/send.o src/net/db.o src/net/6bed4.o
+objs-top-net-y += src/net/core.o src/net/input.o src/net/reply.o src/net/send.o src/net/db.o src/net/llc.o src/net/6bed4.o
index e4ecd1c..085f16c 100644 (file)
@@ -124,6 +124,7 @@ void netcore_send_buffer (intptr_t *mem, uint8_t *wbuf) {
        struct ip6_hdr *ip6 = (void *) mem [MEM_IP6_HEAD];
        struct arphdr  *arp = (void *) mem [MEM_ARP_HEAD];
        struct ethhdr  *eth = (void *) mem [MEM_ETHER_HEAD];
+       bool is_llc = (mem [MEM_LLC_DSAP] != 0) || (mem [MEM_LLC_SSAP] != 0);
        uint16_t wlen;
        //
        // Checksum UDPv6 on IPv6
@@ -203,6 +204,8 @@ void netcore_send_buffer (intptr_t *mem, uint8_t *wbuf) {
                netset16 (eth->h_proto, ETH_P_IPV6);
        } else if (arp) {
                netset16 (eth->h_proto, ETH_P_ARP);
+       } else if (is_llc) {
+               ; //TODO// netset16 (eth->h_proto, mem [MEM_ALL_DONE] - mem [MEM_ETHER_HEAD]);
        } else {
                return;
        }
index 06c65a5..5bebd5f 100644 (file)
@@ -1,4 +1,4 @@
-/* netinput.c
+/* netinput.c -- Incoming network packet parser and switch.
  *
  * This file is part of 0cpm Firmerware.
  *
  * along with 0cpm Firmerware.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-
-/* Process networked input and select actions to take.
- *
- * The "assembly language" used below is the BPF pseudo-language,
- * documented in
- *
- *                     The BSD Packet Filter:
- *     A New Architecture for User-Level Packet Capture
- *             by Steven McCanne and Van Jacobson
- *
- *      ftp://ftp.ee.lbl.gov/papers/bpf-usenix93.ps.Z
- *
- * It serves to analyse frames, set aside the juicy details and
- * return a value which in this case is either the address of a
+/*
+ * This code analyses frames, sets aside the juicy details and
+ * returns a value which in this case is either the address of a
  * function to invoke, or NULL if the frame should be dropped.
  *
- * It should not be difficult to interpret the consistent assembly
- * instructions (stored in a fixed structure format) from native
- * code, thus leading to extremely efficient network packet handling
- * with a very high level of flexibility for future extensions.
- *
- * This language is designed for speed, and is used in tcpdump et al.
- *
  * From: Rick van Rein <rick@openfortress.nl>
  */
 
 #include <0cpm/netfun.h>
 
 
+/* Utility functions for packet analyses */
 
-
-/*
- * The following is written in BPF assembler, because that is a proper
- * form for handling this kind of problem.  The language lends itself
- * for optimal translation.  In spite of that, it is very flexible.
- *
- * The labels ending in _sel indicate that a definite selection has been
- * made of the kind of frame, but some validation may still be in order.
- *
- * The code below does not calculate checksums yet.  It also does not
- * take packet length into account.
- *
- * The code collects various bits of data in the M[] scratchpad array:
- * TODO:OLD:USING MEM_INPUT ENUM NOW
- * M[0] is the ethernet payload
- * M[1] is the IP4.src address                 (or 0 for native IP6)
- * M[2] is the IP4.dst address                 (or 0 for native IP6)
- * M[3] is the IP4 payload                     (or 0 for native IP6)
- * M[4] is the UDP4 src.PORT|dst.PORT          (or 0 for native IP6)
- * M[5] is the UDP4 payload                    (or 0 for native IP6)
- * M[6] is the IP6 frame address (+40 is payload)
- * M[7] is the UDP6 src.PORT|dst.PORT
- * M[8] is the UDP6 payload
- * M[9] is the ethernet header
- *
- * These addresses and values can be used in further analyses, based
- * on the functions returned from the analysis.  Note that the first
- * things these functions do is (1) check lengths and (2) check sums.
- *
- * If all that is okay, it can start processing the frame contents.
- */
-
+#define forward(t) here += sizeof (t); fromhere -= sizeof (t);
+#define store(i, t) if (fromhere < sizeof (t)) return NULL; mem [i] = (intptr_t) (t *) here;
+#define store_forward(i, t) store(i,t) forward(t)
+#ifndef get08
+#  define get08(o) ((uint8_t) here [o])
+#endif
+#ifndef get16
+#  define get16(o) ((((uint16_t) here [o]) << 8) | ((uint16_t) here [o+1]))
+#endif
+#ifndef get32
+#  define get32(o) ((((uint32_t) here [o]) << 24) | (((uint32_t) here [o+1]) << 16) | (((uint32_t) here [o+2]) << 8) | ((uint32_t) here [o+3]))
+#endif
 
 
 /* Analyse incoming network packets.
  * for specifically known targets.
  */
 
-#define forward(t) here += sizeof (t); fromhere -= sizeof (t);
-#define store(i, t) if (fromhere < sizeof (t)) return NULL; mem [i] = (intptr_t) (t *) here;
-#define store_forward(i, t) store(i,t) forward(t)
-#ifndef get08
-#  define get08(o) ((uint8_t) here [o])
-#endif
-#ifndef get16
-#  define get16(o) ((((uint16_t) here [o]) << 8) | ((uint16_t) here [o+1]))
-#endif
-#ifndef get32
-#  define get32(o) ((((uint32_t) here [o]) << 24) | (((uint32_t) here [o+1]) << 16) | (((uint32_t) here [o+2]) << 8) | ((uint32_t) here [o+3]))
-#endif
-
 intptr_t netinput (uint8_t *pkt, uint16_t pktlen, intptr_t *mem) {
 
        register uint8_t *here = pkt;
@@ -147,6 +97,8 @@ intptr_t netinput (uint8_t *pkt, uint16_t pktlen, intptr_t *mem) {
        uint16_t udp6_dst;
        uint8_t dhcp6_tag;
        uint16_t dnssd_flags;
+       uint8_t llc_ssap, llc_dsap;
+       uint16_t llc_cmd;
 
        //
        // Store the end of the entire packet
@@ -168,7 +120,14 @@ intptr_t netinput (uint8_t *pkt, uint16_t pktlen, intptr_t *mem) {
        case 0x86dd: goto netin_IP6_sel;
        case 0x0800: goto netin_IP4_sel;
        case 0x0806: goto netin_ARP_sel;
-       default: return NULL;
+       default:
+#if defined(CONFIG_FUNCTION_NETCONSOLE) || defined(CONFIG_FUNCTION_FIRMWARE_UPGRADES)
+               if (ethertp <= 1500) {
+                       mem [MEM_LLC_PKTLEN] = (intptr_t) ethertp;
+                       goto netin_LLC_sel;
+               }
+#endif
+               return NULL;
        }
 
        //
@@ -383,4 +342,66 @@ netin_DNSSD_sel:
 
        // Finally, a catchall that rejects anything that makes it to here
        return NULL;
+
+
+/********** OPTIONAL CODE FOR LLC: NETCONSOLE, FIRMWARE UPGRADES **********/
+
+
+#if defined (CONFIG_FUNCTION_NETCONSOLE) || defined (CONFIG_FUNCTION_FIRMWARE_UPGRADES)
+
+netin_LLC_sel:
+       mem [MEM_LLC_DSAP] = (intptr_t) get08 (0);
+       mem [MEM_LLC_SSAP] = (intptr_t) get08 (1);;
+       mem [MEM_LLC_CMD] =  get08 (2);
+       if ((mem [MEM_LLC_CMD] & 0x03) != 0x03) {
+               mem [MEM_LLC_CMD] |= get08 (3) << 8;
+               goto netin_LLC2_sel;
+       }
+       // else, fallthrough to netin_LLC1_sel
+
+netin_LLC1_sel:
+       mem [MEM_LLC_PAYLOAD] = (intptr_t) (here + 3);
+       switch (mem [MEM_LLC_CMD]) {
+#ifdef CONFIG_FUNCTION_FIRMWARE_UPGRADES
+       case 0x03:
+               if (mem [MEM_LLC_DSAP] == 68) {
+                       return (intptr_t) netllc_tftp;
+               }
+               break;
+#endif // NETCONSOLE
+#ifdef CONFIG_FUNCTION_FIRMWARE_UPGRADES
+       case 0x7f:
+               if (mem [MEM_LLC_DSAP] == 20) {
+                       return (intptr_t) netllc_console_sabme;
+               }
+               break;
+       case 0x53:
+               if (mem [MEM_LLC_DSAP] == 20) {
+                       return (intptr_t) netllc_console_disc;
+               }
+               break;
+       case 0x87:
+               if (mem [MEM_LLC_DSAP] == 20) {
+                       return (intptr_t) netllc_console_frmr;
+               }
+               break;
+#endif // FIRMWARE_UPGRADES
+       default:
+               break;
+       }
+       return NULL;
+
+#ifdef CONFIG_FUNCTION_NETCONSOLE
+netin_LLC2_sel:
+       mem [MEM_LLC_PAYLOAD] = (intptr_t) (here + 4);
+       if ((mem [MEM_LLC_CMD] & 0x0001) == 0x0000) {
+               return (intptr_t) netllc_console_datasentback;
+       } else if ((mem [MEM_LLC_CMD] & 0x0007) == 0x0001) {
+               return (intptr_t) netllc_console_receiverfeedback;
+       }
+       return NULL;
 }
+#endif // NETCONSOLE
+
+#endif // NETCONSOLE || FIRMWARE_UPGRADES
+
diff --git a/src/net/llc.c b/src/net/llc.c
new file mode 100644 (file)
index 0000000..2f8201d
--- /dev/null
@@ -0,0 +1,201 @@
+/* netllc.c -- Optional LLC handling that plugs into the network stack.
+ *
+ * This file is part of 0cpm Firmerware.
+ *
+ * 0cpm Firmerware is Copyright (c)2011 Rick van Rein, OpenFortress.
+ *
+ * 0cpm Firmerware is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 3.
+ *
+ * 0cpm Firmerware 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with 0cpm Firmerware.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdarg.h>
+
+// #include <netinet/ip.h>
+// #include <netinet/udp.h>
+// #include <netinet/ip6.h>
+// #include <netinet/ip_icmp.h>
+// #include <netinet/icmp6.h>
+// #include <netinet/if_ether.h>
+
+#include <config.h>
+
+#include <0cpm/cpu.h>
+#include <0cpm/irq.h>
+#include <0cpm/timer.h>
+#include <0cpm/netinet.h>
+#include <0cpm/netfun.h>
+#include <0cpm/netdb.h>
+#include <0cpm/cons.h>
+
+
+/********** OPTIONAL FIRMWARE ACCESS FUNCTIONS **********/
+
+/*
+ * This functionality is located in src/function/bootloader.c
+ */
+
+
+
+/********** OPTIONAL CONSOLE ACCESS FUNCTIONS **********/
+#ifdef CONFIG_FUNCTION_NETCONSOLE
+
+extern uint8_t ether_mine [6];
+
+static bool console_is_connected = false;
+static uint8_t console_remote_mac [6];
+static uint8_t console_remote_sap;
+
+struct llc2 {
+       uint8_t dummy;
+};
+static struct llc2 llc2_dummy_handle;
+
+uint8_t llc_received = 0;
+uint8_t llc_sent = 0;
+uint8_t llc_input = 0;
+
+
+static bool mismatch_console_connection (intptr_t *mem) {
+       if ((mem [MEM_LLC_SSAP] & 0xfe) != console_remote_sap) {
+               return true;
+       }
+       if (memcmp (((uint8_t *) mem [MEM_ETHER_HEAD]) + 6, console_remote_mac, 6)) {
+               return true;
+       }
+       return false;
+}
+
+
+/* Construct an LLC reply start; fill out ethernet addresses and SSAP/DSAP */
+uint8_t *netllc_reply (uint8_t *pout, intptr_t *mem) {
+       memcpy (pout +  0, ((uint8_t *) mem [MEM_ETHER_HEAD] + 6), 6);
+       memcpy (pout +  6, ether_mine, 6);
+       pout [14] = mem [MEM_LLC_SSAP] | 0x00;  /* Individual */
+       pout [15] = mem [MEM_LLC_DSAP] | 0x01;  /* Response */
+}
+
+/* Construct an LLC1 acknowledgement in reply to an incoming packet */
+uint8_t *netllc_llc1_ack (uint8_t *pout, intptr_t *mem) {
+       netllc_reply (pout, mem);
+       netset16 (*(nint16_t *) (pout + 12), 3);
+       netset8  (*(nint8_t  *) (pout + 16), 0x73);
+       return pout + 17;
+}
+
+/* Dummy LLC2 send routine, ignoring "cnx" as there is just one LLC2 connection.
+ * Before sending, the routine will first establish whether the last send
+ * was successful; if not, it will repeat that.  The return value is true if at
+ * least the new send was done, relying on future calls to resend if need be.
+ * TODO: Possibly improve on this routine.
+ */
+uint8_t llc_pkt [100];
+uint16_t llc_pktlen;
+bool netsend_llc2 (struct llc2 *cnx, uint8_t *data, uint16_t datalen) {
+        bool newpkt;
+        if (datalen > 80) {
+                return false;
+        }
+        if (!console_is_connected) {
+                return false;
+        }
+        newpkt = (llc_sent == llc_received);
+        if (newpkt) {
+                // Sending is complete, construct new packet as requested
+                memcpy (llc_pkt +  0, console_remote_mac, 6);
+                memcpy (llc_pkt +  6, "\x00\x0b\x82\x19\xa0\xf4", 6);
+                llc_pkt [12] = 0x00;
+                llc_pkt [13] = datalen + 4;
+                llc_pkt [14] = console_remote_sap;      // DSAP
+                llc_pkt [15] = 20;                      // SSAP
+                llc_pkt [16] = llc_sent << 1;           // N(S) = 0x00, information frame
+                llc_pkt [17] = llc_input << 1;          // N(R) = sent-up-to-here, low bit reset
+                memcpy (llc_pkt + 18, data, datalen);
+                llc_pktlen = 6 + 6 + 2 + 4 + datalen;
+                llc_sent++;
+                llc_sent &= 0x7f;
+        }
+        bottom_network_send (llc_pkt, llc_pktlen);
+        return newpkt;
+}
+
+
+/* Respond to an LLC SABMA console connection request */
+uint8_t *netllc_console_sabme (uint8_t *pout, intptr_t *mem) {
+#if 0
+       if (console_is_connected) {
+               return NULL;
+       }
+#endif
+       memcpy (console_remote_mac, ((uint8_t *) mem [MEM_ETHER_HEAD]) + 6, 6);
+       console_remote_sap = mem [MEM_LLC_SSAP] & 0xfe;
+       llc_sent = llc_received = llc_input = 0x00;
+//TODO: netcons_connect() overwrites memory buffer with 1st llc cnx pkt
+netllc_llc1_ack (pout, mem);
+bottom_network_send (pout, 6+6+2+3);
+       if (!console_is_connected) {
+               netcons_connect (&llc2_dummy_handle);
+               console_is_connected = true;
+       }
+return NULL;
+       return netllc_llc1_ack (pout, mem);
+}
+
+/* Respond to an LLC DISC console disconnect request */
+uint8_t *netllc_console_disc (uint8_t *pout, intptr_t *mem) {
+       if (mismatch_console_connection (mem)) {
+               return NULL;
+       }
+       console_is_connected = false;
+       netcons_close ();
+       return netllc_llc1_ack (pout, mem);
+}
+
+/* Respond to an LLC FRMR frame rejection */
+uint8_t *netllc_console_frmr (uint8_t *pout, intptr_t *mem) {
+       if (mismatch_console_connection (mem)) {
+               return NULL;
+       }
+       llc_received = llc_sent;
+       return NULL;
+}
+
+/* Respond to an LLC data frame sent to the console.
+ * As the console is output-only, the contents are dropped.
+ */
+uint8_t *netllc_console_datasentback (uint8_t *pout, intptr_t *mem) {
+       if (mismatch_console_connection (mem)) {
+               return NULL;
+       }
+       netllc_reply (pout, mem);
+       netset16 (*(nint16_t *) (pout + 12), 4);
+       netset8  (*(nint8_t  *) (pout + 16), 0x01);
+       netset8  (*(nint8_t  *) (pout + 17), (mem [MEM_LLC_CMD] + 2) & 0xfe);
+       return pout + 18;
+}
+
+/* Respond to an LLC receiver-ready (or receiver-reject) indication for the console */
+uint8_t *netllc_console_receiverfeedback (uint8_t *pout, intptr_t *mem) {
+       if (mismatch_console_connection (mem)) {
+               return NULL;
+       }
+       llc_received = mem [MEM_LLC_CMD] >> 9;
+       return NULL;
+}
+
+
+#endif
+
+
index 743c006..cc72516 100644 (file)
@@ -36,6 +36,7 @@
 #include <stdint.h>
 #include <stdbool.h>
 #include <stdarg.h>
+#include <string.h>
 
 #include <config.h>
 
 
 
 
-/* Send a reply through LLC1.
- * The packet provided have the responded-to MAC/LLC SAPs.
- * The packet size is completed with any reply content.
- * This routine updates MAC addresses and LLC headers.
- */
-void netreply_llc1 (uint8_t *pkt, uint16_t pktlen) {
-       uint8_t tmp;
-       memcpy (pkt +  0, pkt + 6, 6);
-       memcpy (pkt +  6, "\x00\x0b\x82\x19\xa0\xf4", 6);
-       pkt [12] = (pktlen - 12 - 2) >> 8;
-       pkt [13] = (pktlen - 12 - 2) & 0xff;
-       tmp = pkt [14];
-       pkt [14] = pkt [15];
-       pkt [15] = tmp; // Command flag -- LLC1 only uses commands
-       // Send and forget -- LLC1 is not guaranteed delivery
-       bottom_network_send (pkt, pktlen);
+
+/* Construct an LLC reply start; fill out ethernet addresses and SSAP/DSAP */
+uint8_t *netreply_llc (uint8_t *pout, intptr_t *mem) {
+        memcpy (pout +  0, ((uint8_t *) mem [MEM_ETHER_HEAD] + 6), 6);
+        memcpy (pout +  6, ether_mine, 6);
+        pout [14] = mem [MEM_LLC_SSAP];
+        pout [15] = mem [MEM_LLC_DSAP];
 }
 
 
@@ -70,6 +62,13 @@ static uint8_t llc_rr [6 + 6 + 2 + 4];
 static uint8_t llc_sent;
 static uint8_t llc_received;
 static uint8_t llc_input;
+static mem [MEM_NETVAR_COUNT];
+
+
+struct llc2 {
+       uint8_t dummy;
+};
+static struct llc2 llc2_dummy_handle;
 
 
 /* Dummy LLC2 send routine, ignoring "cnx" as there is just one LLC2 connection.
@@ -107,11 +106,6 @@ bool netsend_llc2 (struct llc2 *cnx, uint8_t *data, uint16_t datalen) {
        return newpkt;
 }
 
-struct llc2 {
-       uint8_t dummy;
-};
-static struct llc2 llc2_dummy_handle;
-
 /* LLC-only network packet handling, specifically for:
  *  - LLC2 console at SAP 20
  *  - LLC1 firmware access through TFTP at SAP 68
@@ -168,8 +162,17 @@ void nethandler_llconly (uint8_t *pkt, uint16_t pktlen) {
        if (cmd == 0x03) {                              // UI (llc.datagram)
 #ifdef CONFIG_FUNCTION_FIRMWARE_UPGRADES
                if (pkt [14] == 68) {
-                       void bootloader_datagram (uint8_t *pkt, uint16_t pktlen);
-                       bootloader_datagram (pkt, pktlen);
+                       uint16_t pktlen;
+                       // Setup minimal mem[] array for TFTP over LLC1
+                       bzero (mem, sizeof (mem));
+                       mem [MEM_ETHER_HEAD] = (intptr_t) pkt;
+                       mem [MEM_ALL_DONE] = (intptr_t) &pkt [pktlen];
+                       mem [MEM_LLC_DSAP] = pkt [14];
+                       mem [MEM_LLC_SSAP] = pkt [15];
+                       pkt = netllc_tftp (pkt, pktlen);
+                       pktlen = mem [MEM_ALL_DONE] - (intptr_t) pkt;
+                       // Send and forget -- LLC1 is unconfirmed transmission
+                       bottom_network_send (pkt, pktlen);
                } else {
 #ifdef CONFIG_DEVEL
                        bottom_printf ("LLC1 UA is only used for TFTP, use SAP 68 and not %d\n", pkt [14]);
index a965321..d5fafef 100644 (file)
@@ -207,12 +207,11 @@ uint8_t *netreply_icmp4_echo_req (uint8_t *pout, intptr_t *mem) {
        icmp4in  = (struct icmphdr *) mem [MEM_ICMP4_HEAD];
        netset8  (icmp4out->type, ICMP_ECHOREPLY);
        netset8  (icmp4out->code, 0);
-       icmp4out->un.echo.id = icmp4in->un.echo.id;
-       icmp4out->un.echo.sequence = icmp4in->un.echo.sequence;
+       memcpy (&icmp4out->un.echo, &icmp4in->un.echo, 4);
        pout = pout + sizeof (struct icmphdr);
        alen = mem [MEM_ALL_DONE] - mem [MEM_ICMP4_HEAD] - sizeof (struct icmphdr);
        if ((alen > 0) && (alen < 128)) {
-               memcpy (icmp4out + 1, icmp4in + 1, alen);
+               memcpy (pout, &icmp4in [1], alen);
                pout += alen;
        }
        mem [MEM_ICMP4_HEAD] = (intptr_t) icmp4out;
index 2cbf429..df20062 100644 (file)
@@ -25,3 +25,6 @@ ifdef CONFIG_PLATFORM_TIC55x
 include src/target/Makefile.tic55x
 endif
 
+ifdef CONFIG_PLATFORM_BLACKFIN
+include src/target/Makefile.blackfin
+endif