[Feature]add MT2731_MP2_MR2_SVN388 baseline version
Change-Id: Ief04314834b31e27effab435d3ca8ba33b499059
diff --git a/src/bsp/lk/lib/minip/dhcp.c b/src/bsp/lk/lib/minip/dhcp.c
new file mode 100644
index 0000000..170691d
--- /dev/null
+++ b/src/bsp/lk/lib/minip/dhcp.c
@@ -0,0 +1,296 @@
+/*
+ * Copyright (c) 2014 Brian Swetland
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "minip-internal.h"
+
+#include <err.h>
+#include <platform.h>
+#include <stdio.h>
+#include <debug.h>
+#include <malloc.h>
+
+#include <kernel/thread.h>
+#include <sys/types.h>
+#include <endian.h>
+#include <string.h>
+
+#define TRACE_DHCP 0
+
+typedef struct dhcp_msg {
+ u8 opcode;
+ u8 hwtype; // hw addr type
+ u8 hwalen; // hw addr length
+ u8 hops;
+ u32 xid; // txn id
+ u16 secs; // seconds since dhcp process start
+ u16 flags;
+ u32 ciaddr; // Client IP Address
+ u32 yiaddr; // Your IP Address
+ u32 siaddr; // Server IP Address
+ u32 giaddr; // Gateway IP Address
+ u8 chaddr[16]; // Client HW Address
+ u8 sname[64]; // Server Hostname, AsciiZ
+ u8 file[128]; // Boot File Name, AsciiZ
+ u32 cookie;
+ u8 options[0];
+} dhcp_msg_t;
+
+udp_socket_t *dhcp_udp_handle;
+
+#define DHCP_FLAG_BROADCAST 0x8000
+
+#define DHCP_REQUEST 1
+#define DHCP_REPLY 2
+
+#define OP_DHCPDISCOVER 1 // Client: Broadcast to find Server
+#define OP_DHCPOFFER 2 // Server response to Discover
+#define OP_DHCPREQUEST 3 // Client accepts offer
+#define OP_DHCPDECLINE 4 // Client notifies address already in use
+#define OP_DHCPACK 5 // Server confirms accept
+#define OP_DHCPNAK 6 // Server disconfirms or lease expires
+#define OP_DHCPRELEASE 7 // Client releases address
+
+#define OPT_NET_MASK 1 // len 4, mask
+#define OPT_ROUTERS 3 // len 4n, gateway0, ...
+#define OPT_DNS 6 // len 4n, nameserver0, ...
+#define OPT_HOSTNAME 12
+#define OPT_REQUEST_IP 50 // len 4
+#define OPT_MSG_TYPE 53 // len 1, type same as op
+#define OPT_SERVER_ID 54 // len 4, server ident ipaddr
+#define OPT_DONE 255
+
+#define DHCP_CLIENT_PORT 68
+#define DHCP_SERVER_PORT 67
+
+#define HW_ETHERNET 1
+
+static u8 mac[6];
+
+static void printip(const char *name, u32 x) {
+ union {
+ u32 u;
+ u8 b[4];
+ } ip;
+ ip.u = x;
+ printf("%s %d.%d.%d.%d\n", name, ip.b[0], ip.b[1], ip.b[2], ip.b[3]);
+}
+
+static volatile int configured = 0;
+static int cfgstate = 0;
+
+static void dhcp_discover(u32 xid) {
+ struct {
+ dhcp_msg_t msg;
+ u8 opt[128];
+ } s;
+ u8 *opt = s.opt;
+ const char *hostname = minip_get_hostname();
+ memset(&s, 0, sizeof(s));
+ s.msg.opcode = DHCP_REQUEST;
+ s.msg.hwtype = HW_ETHERNET;
+ s.msg.hwalen = 6;
+ s.msg.xid = xid;
+ s.msg.cookie = 0x63538263;
+ minip_get_macaddr(s.msg.chaddr);
+
+ *opt++ = OPT_MSG_TYPE;
+ *opt++ = 1;
+ *opt++ = OP_DHCPDISCOVER;
+
+ if (hostname && hostname[0]) {
+ size_t len = strlen(hostname);
+ *opt++ = OPT_HOSTNAME;
+ *opt++ = len;
+ memcpy(opt, hostname, len);
+ opt += len;
+ }
+
+ *opt++ = OPT_DONE;
+
+ udp_send(&s.msg, sizeof(dhcp_msg_t) + (opt - s.opt), dhcp_udp_handle);
+ status_t ret = udp_send(&s.msg, sizeof(dhcp_msg_t) + (opt - s.opt), dhcp_udp_handle);
+ if (ret != NO_ERROR) {
+ printf("DHCP_DISCOVER failed: %d\n", ret);
+ }
+}
+
+static void dhcp_request(u32 xid, u32 server, u32 reqip) {
+ struct {
+ dhcp_msg_t msg;
+ u8 opt[128];
+ } s;
+ u8 *opt = s.opt;
+ const char *hostname = minip_get_hostname();
+ memset(&s, 0, sizeof(s));
+ s.msg.opcode = DHCP_REQUEST;
+ s.msg.hwtype = HW_ETHERNET;
+ s.msg.hwalen = 6;
+ s.msg.xid = xid;
+ s.msg.cookie = 0x63538263;
+ minip_get_macaddr(s.msg.chaddr);
+
+ *opt++ = OPT_MSG_TYPE;
+ *opt++ = 1;
+ *opt++ = OP_DHCPREQUEST;
+
+ *opt++ = OPT_SERVER_ID;
+ *opt++ = 4;
+ memcpy(opt, &server, 4);
+ opt += 4;
+
+ *opt++ = OPT_REQUEST_IP;
+ *opt++ = 4;
+ memcpy(opt, &reqip, 4);
+ opt += 4;
+
+ if (hostname && hostname[0]) {
+ size_t len = strlen(hostname);
+ *opt++ = OPT_HOSTNAME;
+ *opt++ = len;
+ memcpy(opt, hostname, len);
+ opt += len;
+ }
+
+ *opt++ = OPT_DONE;
+
+ status_t ret = udp_send(&s.msg, sizeof(dhcp_msg_t) + (opt - s.opt), dhcp_udp_handle);
+ if (ret != NO_ERROR) {
+ printf("DHCP_REQUEST failed: %d\n", ret);
+ }
+}
+
+static void dhcp_cb(void *data, size_t sz, uint32_t srcip, uint16_t srcport, void *arg) {
+ dhcp_msg_t *msg = data;
+ u8 *opt;
+ u32 netmask = 0;
+ u32 gateway = 0;
+ u32 dns = 0;
+ u32 server = 0;
+ int op = -1;
+
+ if (sz < sizeof(dhcp_msg_t)) return;
+
+ if (memcmp(msg->chaddr, mac, 6)) return;
+
+#if TRACE_DHCP
+ printf("dhcp op=%d len=%d from p=%d ip=", msg->opcode, sz, srcport);
+ printip("", srcip);
+#endif
+
+ if (configured) {
+ printf("already configured\n");
+ return;
+ }
+#if TRACE_DHCP
+ printip("ciaddr", msg->ciaddr);
+ printip("yiaddr", msg->yiaddr);
+ printip("siaddr", msg->siaddr);
+ printip("giaddr", msg->giaddr);
+ printf("chaddr %02x:%02x:%02x:%02x:%02x:%02x\n",
+ msg->chaddr[0], msg->chaddr[1], msg->chaddr[2],
+ msg->chaddr[3], msg->chaddr[4], msg->chaddr[5]);
+#endif
+ sz -= sizeof(dhcp_msg_t);
+ opt = msg->options;
+ while (sz >= 2) {
+ sz -= 2;
+ if (opt[1] > sz) {
+ break;
+ }
+#if TRACE_DHCP
+ printf("#%d (%d), ", opt[0], opt[1]);
+#endif
+ switch (opt[0]) {
+ case OPT_MSG_TYPE:
+ if (opt[1] == 1) op = opt[2];
+ break;
+ case OPT_NET_MASK:
+ if (opt[1] == 4) memcpy(&netmask, opt + 2, 4);
+ break;
+ case OPT_ROUTERS:
+ if (opt[1] >= 4) memcpy(&gateway, opt + 2, 4);
+ break;
+ case OPT_DNS:
+ if (opt[1] >= 4) memcpy(&dns, opt + 2, 4);
+ break;
+ case OPT_SERVER_ID:
+ if (opt[1] == 4) memcpy(&server, opt + 2, 4);
+ break;
+ case OPT_DONE:
+ goto done;
+ }
+ opt += opt[1] + 2;
+ sz -= opt[1];
+ }
+done:
+#if TRACE_DHCP
+ printf("\n");
+ if (server) printip("server", server);
+ if (netmask) printip("netmask", netmask);
+ if (gateway) printip("gateway", gateway);
+ if (dns) printip("dns", dns);
+#endif
+ if (cfgstate == 0) {
+ if (op == OP_DHCPOFFER) {
+ printip("dhcp: offer:", msg->yiaddr);
+ if (server) {
+ dhcp_request(0xaabbccdd, server, msg->yiaddr);
+ cfgstate = 1;
+ }
+ }
+ } else if (cfgstate == 1) {
+ if (op == OP_DHCPACK) {
+ printip("dhcp: ack:", msg->yiaddr);
+ minip_set_ipaddr(msg->yiaddr);
+ configured = 1;
+ }
+ }
+}
+
+static int dhcp_thread(void *arg) {
+ for (;;) {
+ if (configured) break;
+ thread_sleep(500);
+ if (configured) break;
+ dhcp_discover(0xaabbccdd);
+ }
+ return 0;
+}
+
+static thread_t *dhcp_thr;
+
+void minip_init_dhcp(tx_func_t tx_func, void *tx_arg) {
+ minip_get_macaddr(mac);
+
+ minip_init(tx_func, tx_arg, IPV4_NONE, IPV4_NONE, IPV4_NONE);
+
+ int ret = udp_open(IPV4_BCAST, DHCP_CLIENT_PORT, DHCP_SERVER_PORT, &dhcp_udp_handle);
+ printf("dhcp opened udp: %d\n", ret);
+
+ udp_listen(DHCP_CLIENT_PORT, dhcp_cb, NULL);
+
+ dhcp_thr = thread_create("dhcp", dhcp_thread, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE);
+ thread_detach_and_resume(dhcp_thr);
+}
+
+// vim: set noexpandtab: