ltib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Ltib] [PATCH] Add BOOTP support to Apex


From: Jean-Christian de Rivaz
Subject: [Ltib] [PATCH] Add BOOTP support to Apex
Date: Tue, 15 Sep 2009 15:34:53 +0200
User-agent: Mozilla-Thunderbird 2.0.0.22 (X11/20090707)

Hi all,

The attached files are my first try to add BOOTP support to the Apex
boot loader. It seem that the Apex web site is gone. So I think it's
better to share this with LTIB as it seem to be the only option for the
NXP LPC3131 processor. Or is there anyone working on a u-boot support
for the LPC3131 ?

Anyway, Apex lack the BOOTP and DHCP support. It already have the
configuration options for them, but not the related code. Since any RFC
compliant DHCP server should be compatible with BOOTP, I only added the
BOOTP support, as it is far enough for the Apex operation. If you have
configured a DHCP server to provides the parameters for a kernel booted
with the "ip=dhcp" options, then it should work transparently with this
BOOTP support.

Aside of the BOOTP support, I have also fixed the ethernet_receive() to not verify the IP address of incoming packet if the interface is not configured with an IP address. Without that, all BOOTP responses from the server are dropped.

The first file is the actual patch to the LTIB. The two remainings files
must be added to your /opt/ltib/pkgs/ folder.

While configuring Apex, take car to enable the BOOTP support. It could
be useful to change the default command to have "ipconfig bootp" in it.

Best regards,

Jean-Christian de Rivaz
commit d12ef921ace6461a595523a67e0016cac8d101ea
Author: Jean-Christian de Rivaz <address@hidden>
Date:   Tue Sep 15 15:15:29 2009 +0200

    Add BOOTP support to APEX

diff --git a/dist/lfs-5.1/apex/apex-1.6.8-ea3131.spec.in 
b/dist/lfs-5.1/apex/apex-1.6.8-ea3131.spec.in
index bbf0d84..42b0c83 100644
--- a/dist/lfs-5.1/apex/apex-1.6.8-ea3131.spec.in
+++ b/dist/lfs-5.1/apex/apex-1.6.8-ea3131.spec.in
@@ -10,11 +10,12 @@ Vendor          : NXP
 Packager        : Kevin Wells
 Group           : Applications/System
 Source          : %{name}-%{version}.tar.bz2
-Patch0         : apex-1.6.8_lpc313x.patch
-patch1         : apex-1.6.8_lpc313x_nand.patch
-patch2         : apex-1.6.8_lpc313x_r1a_to_r2.patch
-patch3         : apex-1.6.8_lpc313x_r2_to_r2a.patch
-patch4         : apex-1.6.8_lpc313x_r2a_to_r2c.patch
+Patch0         : apex-1.6.8-add-bootp.patch
+Patch1         : apex-1.6.8_lpc313x.patch
+patch2         : apex-1.6.8_lpc313x_nand.patch
+patch3         : apex-1.6.8_lpc313x_r1a_to_r2.patch
+patch4         : apex-1.6.8_lpc313x_r2_to_r2a.patch
+patch5         : apex-1.6.8_lpc313x_r2a_to_r2c.patch
 BuildRoot       : %{_tmppath}/%{name}
 Prefix          : %{pfx}
 
@@ -31,4 +32,5 @@ needed for the Embedded Artists 3131 board.
 %patch2 -p1
 %patch3 -p1
 %patch4 -p1
+%patch5 -p1
 
commit 382fa95d38badb453f0ec3f8f283e990ed817efa
Author: Jean-Christian de Rivaz <address@hidden>
Date:   Tue Sep 15 15:00:58 2009 +0200

    Add support for BOOTP

diff --git a/include/network.h b/include/network.h
index 614657c..6ddb079 100644
--- a/include/network.h
+++ b/include/network.h
@@ -55,6 +55,24 @@ struct header_arp {
   u8 target_protocol_address[4];
 } __attribute__((packed));
 
+struct header_bootp {
+  u8 op;
+  u8 htype;
+  u8 hlen;
+  u8 hops;
+  u32 xid;
+  u16 secs;
+  u16 flags;
+  u8 ciaddr[4];
+  u8 yiaddr[4];
+  u8 siaddr[4];
+  u8 giaddr[4];
+  u8 chaddr[16];
+  u8 sname[64];
+  u8 file[128];
+  u8 vend[64]; /* This field is not part of DHCP */
+}  __attribute__((packed));
+
 struct header_ipv4 {
   u8  version_ihl;             /* version (4 lsb) and header length (4 msb) */
   u8  tos;                     /* type of service */
@@ -148,6 +166,9 @@ struct addrinfo {
 #define ARP_REVERSEREPLY       4
 #define ARP_NAK                        10
 
+#define PORT_BOOTP_SERVER      67
+#define PORT_BOOTP_CLIENT      68
+
 #define ICMP_TYPE_ECHO         8
 #define ICMP_TYPE_ECHO_REPLY   0
 
@@ -185,6 +206,12 @@ struct addrinfo {
                          + sizeof (struct header_ethernet)\
                          + sizeof (struct header_ipv4)))
 
+#define BOOTP_F(f)     ((struct header_bootp*)\
+                        (f->rgb\
+                         + sizeof (struct header_ethernet)\
+                         + sizeof (struct header_ipv4)\
+                         + sizeof (struct header_udp)))
+
 #define ICMP_F(f)      ((struct header_icmp*)\
                         (f->rgb\
                          + sizeof (struct header_ethernet)\
diff --git a/src/net/ethernet.c b/src/net/ethernet.c
index 726394c..3b40423 100644
--- a/src/net/ethernet.c
+++ b/src/net/ethernet.c
@@ -420,15 +420,15 @@ void ethernet_receive (struct descriptor_d* d, struct 
ethernet_frame* frame)
     return;                    /* Not for us. */
 #endif
 
-  /* Check for a valid IP address.  At present, this isn't strictly
-     correct since we don't check for broadcast addresses.  Adding
-     support for such shouldn't be difficult.  It just requires some
-     bookkeeping. */
-
-  if (ETH_F (frame)->protocol == HTONS (ETH_PROTO_IP)
-      && memcmp (IPV4_F (frame)->destination_ip, host_ip_address, 4))
-    return;                    /* Not for us */
-
+  if (!UNCONFIGURED_IP) {
+    /* Check for a valid IP address.  At present, this isn't strictly
+       correct since we don't check for broadcast addresses.  Adding
+       support for such shouldn't be difficult.  It just requires some
+       bookkeeping. */
+    if (ETH_F (frame)->protocol == HTONS (ETH_PROTO_IP)
+        && memcmp (IPV4_F (frame)->destination_ip, host_ip_address, 4))
+      return;                  /* Not for us */
+  }
        /* Invoke receivers */
   {
     int i;
diff --git a/src/net/ipconfig.c b/src/net/ipconfig.c
index 0480d85..8dbaec5 100644
--- a/src/net/ipconfig.c
+++ b/src/net/ipconfig.c
@@ -251,6 +251,173 @@ int cmd_ipconfig_rarp (int argc, const char** argv)
 
 #endif
 
+#if defined CONFIG_CMD_IPCONFIG_BOOTP
+
+static u16 _checksum (u32* sum, void* pv, int cb)
+{
+  u16* p = (u16*) pv;
+  for (; cb > 0; cb -= 2) {
+    unsigned short s = *p++;
+    *sum += HTONS (s);
+  }
+
+  return ~ ((*sum & 0xffff) + (*sum >> 16));
+}
+
+static int bootp_receiver (struct descriptor_d* d,
+                         struct ethernet_frame* frame,
+                         void* context)
+{
+  /* Vet the frame */
+  if (frame->cb
+      < (sizeof (struct header_ethernet) + sizeof (struct header_ipv4)
+        + sizeof (struct header_udp) + sizeof (struct header_bootp)))
+    return 0;                  /* runt */
+
+  if (ETH_F (frame)->protocol != HTONS (ETH_PROTO_IP))
+    return 0;
+
+  if (IPV4_F (frame)->protocol != IP_PROTO_UDP)
+    return 0;
+
+  if (UDP_F (frame)->source_port != HTONS (PORT_BOOTP_SERVER))
+    return 0;
+
+  if (UDP_F (frame)->destination_port != HTONS (PORT_BOOTP_CLIENT))
+    return 0;
+
+  if (BOOTP_F (frame)->op != 0x02)
+    return 0;
+
+  memcpy (host_ip_address, BOOTP_F (frame)->yiaddr, 4);
+       /* Add ARP entry for the server */
+  arp_cache_update ((char*) ETH_F (frame)->source_address,
+                   (char*) IPV4_F (frame)->source_ip,
+                   1);
+  memcpy (server_ip_address, BOOTP_F (frame)->siaddr, 4);
+  memcpy (gw_ip_address, BOOTP_F (frame)->giaddr, 4);
+  set_aliases ();
+
+  return 1;
+}
+
+int cmd_ipconfig_bootp (int argc, const char** argv)
+{
+  struct descriptor_d d;
+  int result;
+  struct ethernet_frame* frame;
+  int tries = 0;
+
+  if (   (result = parse_descriptor (szNetDriver, &d))
+      || (result = open_descriptor (&d)))
+    return result;
+
+  DBG (2,"%s: open %s -> %d\n", __FUNCTION__, szNetDriver, result);
+
+  frame = ethernet_frame_allocate ();
+
+  DBG (2,"%s: setup ethernet header %p\n", __FUNCTION__, frame);
+
+  memset (ETH_F (frame)->destination_address, 0xff, 6);
+  memcpy (ETH_F (frame)->source_address, host_mac_address, 6);
+  ETH_F (frame)->protocol = HTONS (ETH_PROTO_IP);
+
+  DBG (2,"%s: setup ipv4 header\n", __FUNCTION__);
+
+  IPV4_F (frame)->version_ihl = 4<<4 | 5;
+  IPV4_F (frame)->length
+    = htons (  sizeof (struct header_ipv4)
+            + sizeof (struct header_udp)
+            + sizeof (struct header_bootp));
+  IPV4_F (frame)->ttl = 64;
+  IPV4_F (frame)->protocol = IP_PROTO_UDP;
+  memset (IPV4_F (frame)->source_ip, 0xff, 4);
+  memset (IPV4_F (frame)->destination_ip, 0xff, 4);
+  IPV4_F (frame)->checksum
+    = htons (checksum (IPV4_F (frame), sizeof (struct header_ipv4)));
+
+  DBG (2,"%s: setup bootp header\n", __FUNCTION__);
+
+  BOOTP_F (frame)->op = 0x01;
+  BOOTP_F (frame)->htype = 0x01;
+  BOOTP_F (frame)->hlen = 0x06;
+  BOOTP_F (frame)->hops = 0x00;
+  BOOTP_F (frame)->xid = HTONS (0x3903F326);
+  BOOTP_F (frame)->secs = HTONS (0x0000);
+  BOOTP_F (frame)->flags = HTONS (0x0000);
+  memset (BOOTP_F (frame)->ciaddr, 0x00, 4);
+  memset (BOOTP_F (frame)->yiaddr, 0x00, 4);
+  memset (BOOTP_F (frame)->siaddr, 0x00, 4);
+  memset (BOOTP_F (frame)->giaddr, 0x00, 4);
+  memset (BOOTP_F (frame)->chaddr, 0x00, 16);
+  memcpy (BOOTP_F (frame)->chaddr, host_mac_address, 6);
+  memset (BOOTP_F (frame)->sname, 0x00, 64);
+  memset (BOOTP_F (frame)->file, 0x00, 128);
+
+  /* This must be at the end because the UDP checksum includs the data */
+  DBG (2,"%s: setup udp header\n", __FUNCTION__);
+
+  UDP_F (frame)->source_port = HTONS (PORT_BOOTP_CLIENT);
+  UDP_F (frame)->destination_port = HTONS (PORT_BOOTP_SERVER);
+  UDP_F (frame)->length = htons (sizeof (struct header_udp) + sizeof (struct 
header_bootp));
+  {
+    /* UDP Checksum use part of IPv4 header*/
+    u32 sum = 0;
+    u16 length = htons (sizeof (struct header_udp) + sizeof (struct 
header_bootp));
+    u8 rgb[2] = { 0, IPV4_F (frame)->protocol };
+    _checksum (&sum, IPV4_F (frame)->source_ip, 8);
+    _checksum (&sum, rgb, 2);
+    _checksum (&sum, &length, 2);
+    UDP_F (frame)->checksum
+      = htons (_checksum (&sum, UDP_F (frame),
+                         sizeof (struct header_udp) + sizeof (struct 
header_bootp)));
+  }
+
+  frame->cb = sizeof (struct header_ethernet)
+           + sizeof (struct header_ipv4)
+           + sizeof (struct header_udp)
+           + sizeof (struct header_bootp);
+//  dump (frame->rgb, frame->cb, 0);
+
+  register_ethernet_receiver (100, bootp_receiver, NULL);
+
+  goto flush;          /* Receive pending packets before first transmit  */
+  do {
+    struct ethernet_timeout_context timeout;
+
+    DBG (1,"%s: send frame\n", __FUNCTION__);
+    d.driver->write (&d, frame->rgb,
+                    sizeof (struct header_ethernet)
+                    + sizeof (struct header_ipv4)
+                    + sizeof (struct header_udp)
+                    + sizeof (struct header_bootp));
+    ++tries;
+
+  flush:
+    memset (&timeout, 0, sizeof (timeout));
+    timeout.ms_timeout = MS_TIMEOUT;
+    result = ethernet_service (&d, ipconfig_terminate, &timeout);
+
+    /* result == 1 on success, -1 on timeout, -2 on user abort  */
+  } while (result != ERROR_BREAK && result <= 0 && tries < TRIES_MAX);
+
+  unregister_ethernet_receiver (bootp_receiver, NULL);
+
+  printf ("\r");
+  if (UNCONFIGURED_IP)
+    printf ("BOOTP failed\n");
+  else
+    show_ip_config ();
+
+  ethernet_frame_release (frame);
+
+  close_descriptor (&d);
+
+  return result < 0 ? result : 0;
+}
+
+#endif
+
 int cmd_ipconfig (int argc, const char** argv)
 {
   int result;
a923ff32d2d29f46fe8edcf6acd2a083  apex-1.6.8-add-bootp.patch

reply via email to

[Prev in Thread] Current Thread [Next in Thread]