Merge pull request #68 from logicog/dhcp

Add a DHCP client implementation and validate BANKS code size.
This commit is contained in:
René van Dorst
2026-01-18 11:08:17 +00:00
committed by GitHub
13 changed files with 738 additions and 105 deletions
+4 -7
View File
@@ -6,7 +6,7 @@ CONFIG_LOCATION = 458752
HTML_LOCATION = 262144
CC = sdcc
CC_FLAGS = -mmcs51 -Ihttpd -Iuip
CC_FLAGS = -mmcs51 -I. -Ihttpd -Iuip
ASM = sdas8051
AFLAGS= -plosgff
@@ -21,7 +21,7 @@ all: create_build_dir $(VERSION_HEADER) $(SUBDIRS) $(BUILDDIR)rtlplayground.bin
create_build_dir:
mkdir -p $(BUILDDIR)
SRCS = rtlplayground.c rtl837x_flash.c rtl837x_phy.c rtl837x_port.c cmd_parser.c html_data.c rtl837x_igmp.c rtl837x_stp.c machine.c
SRCS = rtlplayground.c rtl837x_flash.c rtl837x_phy.c rtl837x_port.c cmd_parser.c html_data.c rtl837x_igmp.c rtl837x_stp.c dhcp.c machine.c
OBJS = ${SRCS:%.c=$(BUILDDIR)%.rel}
OBJS += uip/$(BUILDDIR)/timer.rel uip/$(BUILDDIR)/uip-fw.rel uip/$(BUILDDIR)/uip-neighbor.rel uip/$(BUILDDIR)/uip-split.rel uip/$(BUILDDIR)/uip.rel uip/$(BUILDDIR)/uip_arp.rel uip/$(BUILDDIR)/uiplib.rel httpd/$(BUILDDIR)/httpd.rel httpd/$(BUILDDIR)/page_impl.rel
@@ -59,17 +59,14 @@ $(BUILDDIR)%.rel: $(BUILDDIR)%.asm
# mv -f $(addprefix $(basename $^), .lst .rel .sym) .
$(BUILDDIR)rtlplayground.ihx: $(BUILDDIR)crtstart.rel $(OBJS) $(BUILDDIR)crc16.rel
$(CC) $(CC_FLAGS) -Wl-bHOME=${BOOTLOADER_ADDRESS} -Wl-bBANK1=0x14000 -Wl-r -o $@ $^
$(CC) $(CC_FLAGS) -Wl-bHOME=${BOOTLOADER_ADDRESS} -Wl-bBANK1=0x14000 -Wl-bBANK2=0x24000 -Wl-r -o $@ $^
$(BUILDDIR)rtlplayground.img: $(BUILDDIR)rtlplayground.ihx
objcopy --input-target=ihex -O binary $< $@
$(BUILDDIR)rtlplayground.bin: $(BUILDDIR)rtlplayground.img
if [ -e $@ ]; then rm $@; fi
echo "0000000: 00 40" | xxd -r - $@
cat $< >> $@
truncate --size=16K $@
dd if=$< skip=80 bs=1024 >>$@
tools/$(BUILDDIR)imagebuilder -i $^ $@
tools/$(BUILDDIR)fileadder -a $(CONFIG_LOCATION) -s $(IMAGESIZE) -d config.txt $@
tools/$(BUILDDIR)fileadder -a $(HTML_LOCATION) -s $(IMAGESIZE) -d html -p html_data $@
tools/$(BUILDDIR)crc_calculator -u $@
+59 -19
View File
@@ -13,6 +13,7 @@
#include "rtl837x_sfr.h"
#include "rtl837x_stp.h"
#include "rtl837x_igmp.h"
#include "dhcp.h"
#include "uip/uip.h"
#include "version.h"
@@ -37,6 +38,8 @@ extern __xdata struct flash_region_t flash_region;
extern __xdata char passwd[21];
extern __xdata struct dhcp_state dhcp_state;
__xdata uint8_t vlan_names[VLAN_NAMES_SIZE];
__xdata uint16_t vlan_ptr;
__xdata uint8_t gpio_last_value[8] = { 0 };
@@ -149,6 +152,7 @@ uint8_t atoi_hex(uint8_t idx)
return ((h_idx + 1) >> 1);
}
uint8_t atoi_short(register uint16_t *vlan, register uint8_t idx)
{
uint8_t err = 1;
@@ -774,28 +778,64 @@ void cmd_parser(void) __banked
} else if (cmd_compare(0, "mtu") && cmd_words_b[1] > 0) {
parse_mtu();
} else if (cmd_compare(0, "ip")) {
print_string("Got ip command: ");
if (!parse_ip(cmd_words_b[1]))
uip_ipaddr(&uip_hostaddr, ip[0], ip[1], ip[2], ip[3]);
else
print_string("Invalid IP address\n");
print_byte(ip[0]); print_byte(ip[1]); print_byte(ip[2]); print_byte(ip[3]);
write_char('\n');
if (cmd_words_b[2] > 0 && cmd_compare(1, "dhcp")) {
dhcp_start();
} else if (cmd_words_b[2] < 0) {
print_string("Current IP: ");
itoa(uip_hostaddr[0]); write_char('.'); itoa(uip_hostaddr[0] >> 8); write_char('.');
itoa(uip_hostaddr[1]); write_char('.'); itoa(uip_hostaddr[1] >> 8);
if (dhcp_state.state == DHCP_LEASING) {
print_string(" (dhcp, renewal in sec: ");
print_short(dhcp_state.dhcp_timer);
write_char(')');
} else {
print_string(" (static)");
}
write_char('\n');
} else {
if (dhcp_state.state)
dhcp_stop();
if (!parse_ip(cmd_words_b[1])) {
uip_ipaddr(&uip_hostaddr, ip[0], ip[1], ip[2], ip[3]);
print_string("Setting ip: ");
itoa(ip[0]); write_char('.'); itoa(ip[1]); write_char('.');
itoa(ip[2]); write_char('.'); itoa(ip[3]); write_char('\n');
} else {
print_string("Invalid IP address\n");
print_string("Error: ip [<ip-address>|dhcp]\n");
print_string(" The dhcp option enables the dhcp client, calling ip without options prints the current IP\n");
print_string(" Calling with a valid IP address will stop any ongoing dhcp client and set the IP address\n");
}
}
} else if (cmd_compare(0, "gw")) {
print_string("Got gw command: ");
if (!parse_ip(cmd_words_b[1]))
uip_ipaddr(&uip_draddr, ip[0], ip[1], ip[2], ip[3]);
else
print_string("Invalid IP address\n");
print_byte(ip[0]); print_byte(ip[1]); print_byte(ip[2]); print_byte(ip[3]);
if (cmd_words_b[2] < 0) {
print_string("Current gw: ");
itoa(uip_draddr[0]); write_char('.'); itoa(uip_draddr[0] >> 8); write_char('.');
itoa(uip_draddr[1]); write_char('.'); itoa(uip_draddr[1] >> 8);
} else {
if (!parse_ip(cmd_words_b[1]))
uip_ipaddr(&uip_draddr, ip[0], ip[1], ip[2], ip[3]);
else
print_string("Invalid IP address\n");
print_string("Setting gw: ");
itoa(ip[0]); write_char('.'); itoa(ip[1]); write_char('.');
itoa(ip[2]); write_char('.'); itoa(ip[3]);
}
write_char('\n');
} else if (cmd_compare(0, "netmask")) {
print_string("Got netmask command: ");
if (!parse_ip(cmd_words_b[1]))
uip_ipaddr(&uip_netmask, ip[0], ip[1], ip[2], ip[3]);
else
print_string("Invalid IP address\n");
print_byte(ip[0]);print_byte(ip[1]);print_byte(ip[2]);print_byte(ip[3]);
if (cmd_words_b[2] < 0) {
print_string("Current netmask: ");
itoa(uip_netmask[0]); write_char('.'); itoa(uip_netmask[0] >> 8); write_char('.');
itoa(uip_netmask[1]); write_char('.'); itoa(uip_netmask[1] >> 8);
} else {
if (!parse_ip(cmd_words_b[1]))
uip_ipaddr(&uip_netmask, ip[0], ip[1], ip[2], ip[3]);
else
print_string("Invalid IP address\n");
print_string("Setting netmask: ");
itoa(ip[0]); write_char('.'); itoa(ip[1]); write_char('.');
itoa(ip[2]); write_char('.'); itoa(ip[3]);
}
write_char('\n');
} else if (cmd_compare(0, "l2")) {
if (cmd_words_b[1] > 0 && cmd_compare(1, "forget"))
+391
View File
@@ -0,0 +1,391 @@
/*
* This is a DHCP client implementation for the RTL837x-based switches
*/
// #define REGDBG
// #define DEBUG
#include <stdint.h>
#include "rtl837x_sfr.h"
#include "rtl837x_common.h"
#include "dhcp.h"
#include "uip.h"
#include "uip/uip.h"
extern __code struct uip_eth_addr uip_ethaddr;
__xdata struct dhcp_state dhcp_state;
__xdata uip_ipaddr_t server;
#define DHCP_HW_TYPE_ETH 1
#define DHCP_SUBNET_MASK 1
#define DHCP_SUBNET_MASK_LEN 4
#define DHCP_ROUTER 3
#define DHCP_ROUTER_LEN 4
#define DHCP_DNS 6
#define DHCP_DNS_LEN 4
#define DHCP_BROADCAST 28
#define DHCP_BROADCAST_LEN 4
#define DHCP_SERVER_ID 54
#define DHCP_SERVER_ID_LEN 4
#define DHCP_MESSAGE_TYPE 53
#define DHCP_MESSAGE_TYPE_LEN 1
#define DHCP_MESSAGE_DISCOVER 1
#define DHCP_MESSAGE_OFFER 2
#define DHCP_MESSAGE_REQUEST 3
#define DHCP_MESSAGE_ACK 5
#define DHCP_LEASE 51
#define DHCP_LEASE_LEN 4
#define DHCP_RENEWAL 58
#define DHCP_RENEWAL_LEN 4
#define DHCP_REBIND 59
#define DHCP_REBIND_LEN 4
#define DHCP_CLIENT_ID 61
#define DHCP_CLIENT_ID_LEN 7
#define DHCP_REQUEST_IP 50
#define DHCP_REQUEST_IP_LEN 4
#define DHCP_PARAMS 55
#define DHCP_PARAM_SUBNET 1
#define DHCP_PARAM_ROUTER 3
#define DHCP_PARAM_DNS 6
#define DHCP_END 255
#pragma codeseg BANK2
#pragma constseg BANK2
struct dhcp_pkt {
uint8_t type;
uint8_t hw;
uint8_t hw_len;
uint8_t hops;
uint32_t tid;
uint16_t delay;
uint16_t flags;
uint8_t client_ip[4];
uint8_t your_ip[4];
uint8_t next_server_ip[4];
uint8_t relay_ip[4];
uint8_t client_addr[6];
uint8_t client_pad[10];
uint8_t server_name[64];
uint8_t file[128];
uint8_t cookie[4];
};
/*
#define DHCP_P ((__xdata struct dhcp_pkt *)&uip_buf[RTL_TAG_SIZE + VLAN_TAG_SIZE])
#define DHCP_OPT ((__xdata uint8_t *)&uip_buf[RTL_TAG_SIZE + VLAN_TAG_SIZE + sizeof (struct dhcp_pkt)])
*/
#define DHCP_P ((__xdata struct dhcp_pkt *)uip_appdata)
#define DHCP_OPT ((__xdata uint8_t *)(uip_appdata) + sizeof (struct dhcp_pkt))
__xdata uint32_t long_value;
void dhcp_print_ip(uint8_t *a)
{
itoa(a[0]); write_char('.');
itoa(a[1]); write_char('.');
itoa(a[2]); write_char('.');
itoa(a[3]);
}
void dhcp_prepare_request(void)
{
DHCP_P->type = 1;
DHCP_P->hw = DHCP_HW_TYPE_ETH;
DHCP_P->hw_len = 6;
DHCP_P->hops = 0;
DHCP_P->tid = HTONS(dhcp_state.transaction_id);
DHCP_P->delay = HTONS(0);
DHCP_P->flags = 0;
// Clear fields client_ip to bootp_file
memset(DHCP_P->client_ip, 0, 224);
memcpyc(DHCP_P->client_addr, uip_ethaddr.addr, 6);
DHCP_P->cookie[0] = 0x63;
DHCP_P->cookie[1] = 0x82;
DHCP_P->cookie[2] = 0x53;
DHCP_P->cookie[3] = 0x63;
}
void dhcp_addopt_client_id(void)
{
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_CLIENT_ID;
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_CLIENT_ID_LEN;
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_HW_TYPE_ETH;
memcpyc(&DHCP_OPT[dhcp_state.opt_ptr], uip_ethaddr.addr, 6);
dhcp_state.opt_ptr += 6;
}
void dhcp_addopt_request_ip(void)
{
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_REQUEST_IP;
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_REQUEST_IP_LEN;
DHCP_OPT[dhcp_state.opt_ptr++] = dhcp_state.current_ip[0];
DHCP_OPT[dhcp_state.opt_ptr++] = dhcp_state.current_ip[1];
DHCP_OPT[dhcp_state.opt_ptr++] = dhcp_state.current_ip[2];
DHCP_OPT[dhcp_state.opt_ptr++] = dhcp_state.current_ip[3];
memcpyc(&DHCP_OPT[dhcp_state.opt_ptr], uip_ethaddr.addr, 4);
}
void dhcp_addopt_server_id(void)
{
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_SERVER_ID;
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_SERVER_ID_LEN;
DHCP_OPT[dhcp_state.opt_ptr++] = dhcp_state.server[0];
DHCP_OPT[dhcp_state.opt_ptr++] = dhcp_state.server[1];
DHCP_OPT[dhcp_state.opt_ptr++] = dhcp_state.server[2];
DHCP_OPT[dhcp_state.opt_ptr++] = dhcp_state.server[3];
memcpyc(&DHCP_OPT[dhcp_state.opt_ptr], uip_ethaddr.addr, 4);
}
void dhcp_send_discover(void)
{
print_string("dhcp_send_discover called\n");
dhcp_prepare_request();
dhcp_state.opt_ptr = 0;
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_MESSAGE_TYPE;
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_MESSAGE_TYPE_LEN;
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_MESSAGE_DISCOVER;
dhcp_addopt_client_id();
dhcp_addopt_request_ip();
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_PARAMS;
DHCP_OPT[dhcp_state.opt_ptr++] = 3;
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_PARAM_SUBNET;
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_PARAM_ROUTER;
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_PARAM_DNS;
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_END;
// Padding to 300 bytes
DHCP_OPT[dhcp_state.opt_ptr++] = 0;
DHCP_OPT[dhcp_state.opt_ptr++] = 0;
DHCP_OPT[dhcp_state.opt_ptr++] = 0;
DHCP_OPT[dhcp_state.opt_ptr++] = 0;
DHCP_OPT[dhcp_state.opt_ptr++] = 0;
DHCP_OPT[dhcp_state.opt_ptr++] = 0;
uip_udp_send(sizeof(struct dhcp_pkt) + dhcp_state.opt_ptr);
dhcp_state.state = DHCP_DISCOVER_SENT;
dhcp_state.ticks = SYS_TICK_HZ;
dhcp_state.dhcp_timer = 30; // Timeout for discover
}
void dhcp_send_request(void)
{
print_string("dhcp_send_request called\n");
dhcp_prepare_request();
dhcp_state.opt_ptr = 0;
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_MESSAGE_TYPE;
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_MESSAGE_TYPE_LEN;
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_MESSAGE_REQUEST;
dhcp_addopt_client_id();
dhcp_addopt_request_ip();
dhcp_addopt_server_id();
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_PARAMS;
DHCP_OPT[dhcp_state.opt_ptr++] = 3;
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_PARAM_SUBNET;
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_PARAM_ROUTER;
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_PARAM_DNS;
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_END;
// Padding to 300 bytes
DHCP_OPT[dhcp_state.opt_ptr++] = 0;
DHCP_OPT[dhcp_state.opt_ptr++] = 0;
DHCP_OPT[dhcp_state.opt_ptr++] = 0;
DHCP_OPT[dhcp_state.opt_ptr++] = 0;
DHCP_OPT[dhcp_state.opt_ptr++] = 0;
DHCP_OPT[dhcp_state.opt_ptr++] = 0;
uip_udp_send(sizeof(struct dhcp_pkt) + dhcp_state.opt_ptr);
dhcp_state.state = DHCP_REQUEST_SENT;
dhcp_state.ticks = SYS_TICK_HZ;
dhcp_state.dhcp_timer = 30; // Timeout for request
}
void ip_opt(uint8_t * __xdata ip)
{
dhcp_state.opt_ptr++;
uint8_t len = DHCP_OPT[dhcp_state.opt_ptr++];
*ip++ = DHCP_OPT[dhcp_state.opt_ptr++];
*ip++ = DHCP_OPT[dhcp_state.opt_ptr++];
*ip++ = DHCP_OPT[dhcp_state.opt_ptr++];
*ip++ = DHCP_OPT[dhcp_state.opt_ptr++];
// There may be more than one IP option, such as 2 DNS servers advertised
dhcp_state.opt_ptr += len - 4;
}
void long_opt(void)
{
dhcp_state.opt_ptr++;
dhcp_state.opt_ptr++;
long_value = DHCP_OPT[dhcp_state.opt_ptr++];
long_value <<= 8;
long_value |= DHCP_OPT[dhcp_state.opt_ptr++];
long_value <<= 8;
long_value |= DHCP_OPT[dhcp_state.opt_ptr++];
long_value <<= 8;
long_value |= DHCP_OPT[dhcp_state.opt_ptr++];
}
void parse_opts(void)
{
while (DHCP_OPT[dhcp_state.opt_ptr] && DHCP_OPT[dhcp_state.opt_ptr] != DHCP_END) {
switch(DHCP_OPT[dhcp_state.opt_ptr]) {
case DHCP_SUBNET_MASK:
ip_opt(&dhcp_state.subnet[0]);
break;
case DHCP_ROUTER:
ip_opt(&dhcp_state.router[0]);
break;
case DHCP_DNS:
ip_opt(&dhcp_state.dns[0]);
break;
case DHCP_SERVER_ID:
ip_opt(&dhcp_state.server[0]);
break;
case DHCP_BROADCAST:
ip_opt(&dhcp_state.broadcast[0]);
break;
case DHCP_LEASE:
long_opt();
dhcp_state.lease = long_value;
break;
case DHCP_REBIND:
long_opt();
dhcp_state.rebind = long_value;
break;
case DHCP_RENEWAL:
long_opt();
dhcp_state.renewal = long_value;
break;
case DHCP_END:
break;
default:
print_string("Unknown DHCP option: "); print_byte(DHCP_OPT[dhcp_state.opt_ptr]); write_char('\n');
dhcp_state.opt_ptr++;
dhcp_state.opt_ptr += DHCP_OPT[dhcp_state.opt_ptr];
dhcp_state.opt_ptr++;
}
}
}
void parse_dhcp(void)
{
if (!DHCP_P->tid == HTONS(dhcp_state.transaction_id))
return;
if (DHCP_P->cookie[0] != 0x63 || DHCP_P->cookie[1] != 0x82 || DHCP_P->cookie[2] != 0x53 || DHCP_P->cookie[3] != 0x63)
return;
dhcp_state.opt_ptr = 0;
if (DHCP_OPT[dhcp_state.opt_ptr++] != DHCP_MESSAGE_TYPE || DHCP_OPT[dhcp_state.opt_ptr++] != DHCP_MESSAGE_TYPE_LEN)
return;
if (DHCP_OPT[dhcp_state.opt_ptr] == DHCP_MESSAGE_OFFER) {
dhcp_state.opt_ptr++;
dhcp_state.current_ip[0] = DHCP_P->your_ip[0];
dhcp_state.current_ip[1] = DHCP_P->your_ip[1];
dhcp_state.current_ip[2] = DHCP_P->your_ip[2];
dhcp_state.current_ip[3] = DHCP_P->your_ip[3];
parse_opts();
print_string("DHCP offer received for IP "); dhcp_print_ip(dhcp_state.current_ip);
write_char('\n');
dhcp_send_request();
} else if (DHCP_OPT[dhcp_state.opt_ptr++] == DHCP_MESSAGE_ACK) {
parse_opts();
print_string("DHCP ACK, our IP is "); dhcp_print_ip(dhcp_state.current_ip);
write_char('\n');
print_string("DHCP netmask "); dhcp_print_ip(dhcp_state.subnet);
write_char('\n');
print_string("DHCP gateway "); dhcp_print_ip(dhcp_state.router);
write_char('\n');
print_string("DHCP lease-time ");
print_long(dhcp_state.lease);
write_char('\n');
uip_ipaddr(&uip_hostaddr, dhcp_state.current_ip[0], dhcp_state.current_ip[1], dhcp_state.current_ip[2], dhcp_state.current_ip[3]);
uip_ipaddr(&uip_draddr, dhcp_state.router[0], dhcp_state.router[1], dhcp_state.router[2], dhcp_state.router[3]);
uip_ipaddr(&uip_netmask, dhcp_state.subnet[0], dhcp_state.subnet[1], dhcp_state.subnet[2], dhcp_state.subnet[3]);
dhcp_state.state = DHCP_LEASING;
dhcp_state.ticks = SYS_TICK_HZ;
dhcp_state.dhcp_timer = dhcp_state.renewal > 0xffff ? 0xffff : dhcp_state.renewal;
}
}
void dhcp_start(void) __banked
{
uip_ipaddr(server, 255,255,255,255);
dhcp_state.conn = uip_udp_new(&server, HTONS(DHCPC_SERVER_PORT));
dhcp_state.current_ip[0] = dhcp_state.current_ip[1] = dhcp_state.current_ip[2] = dhcp_state.current_ip[3] = 0;
if(dhcp_state.conn) {
uip_udp_bind(dhcp_state.conn, HTONS(DHCPC_CLIENT_PORT));
} else {
print_string("dhcp_start failed to set up socket\n");
return;
}
get_random_32();
dhcp_state.transaction_id = SFR_DATA_U32;
dhcp_state.state = DHCP_START;
print_string("dhcp_start done\n");
}
void dhcp_stop(void) __banked
{
print_string("dhcp_stop called\n");
uip_udp_remove(dhcp_state.conn);
dhcp_state.state = DHCP_OFF;
}
void dhcp_callback(void) __banked
{
if (!dhcp_state.state)
return;
if (uip_closed()) {
print_string("Closed\n");
return;
} else if (uip_newdata()) {
parse_dhcp();
} else {
if (dhcp_state.state == DHCP_START) {
dhcp_send_discover();
} else if (!--dhcp_state.ticks) {
// print_string("Timer: "); print_short(dhcp_state.ticks); write_char(' '); print_short(dhcp_state.dhcp_timer);
dhcp_state.dhcp_timer--;
dhcp_state.ticks = SYS_TICK_HZ;
}
if (!dhcp_state.dhcp_timer) {
switch (dhcp_state.state) {
case DHCP_DISCOVER_SENT:
dhcp_send_discover();
break;
case DHCP_LEASING:
case DHCP_REQUEST_SENT:
dhcp_send_request();
break;
default:
print_string("UNKNOWN STATE\n");
}
}
}
// By default we do not send anything out
uip_len = 0;
}
+48
View File
@@ -0,0 +1,48 @@
#ifndef _DHCP_H_
#define _DHCP_H_
#include "uipopt.h"
#include <stdint.h>
#define DHCPC_SERVER_PORT 67
#define DHCPC_CLIENT_PORT 68
#define DHCP_OFF 0
#define DHCP_START 1
#define DHCP_DISCOVER_SENT 2
#define DHCP_REQUEST_SENT 3
#define DHCP_LEASING 4
void dhcp_start(void) __banked;
void dhcp_stop(void) __banked;
// void dhcp_periodic(void) __banked;
void dhcp_callback(void) __banked;
struct dhcp_state {
uint8_t state;
uint32_t transaction_id;
uint16_t dhcp_timer;
uint8_t ticks;
uint16_t opt_ptr;
uint8_t current_ip[4];
uint8_t server[4];
uint8_t router[4];
uint8_t subnet[4];
uint8_t dns[4];
uint8_t broadcast[4];
uint32_t lease;
uint32_t rebind;
uint32_t renewal;
struct uip_udp_conn *conn;
};
typedef struct dhcp_state uip_udp_appstate_t;
/* Finally we define the application function to be called by uIP. */
#ifndef UIP_UDP_APPCALL
#define UIP_UDP_APPCALL dhcp_callback
#endif /* UIP_APPCALL */
#endif
-1
View File
@@ -11,7 +11,6 @@
// #define DEBUG
#include "debug.h"
#define SESSION_ID_LENGTH 12
#define SESSION_TIMEOUT 200
+3
View File
@@ -5,6 +5,8 @@
#include <stdint.h>
#include <stdbool.h>
#define SYS_TICK_HZ 200
// SCL and SDA pin numbers for SFP cage 0 and SFP cage 1
#define SCL_PIN 3
#define SDA_PIN_0 4
@@ -88,6 +90,7 @@ void print_string(__code char *p);
void print_long(__xdata uint32_t a);
void print_short(uint16_t a);
void print_byte(uint8_t a);
void itoa(uint8_t v);
void print_sfr_data(void);
void print_phy_data(void);
void phy_write_mask(uint16_t phy_mask, uint8_t dev_id, uint16_t reg, uint16_t v);
+2 -2
View File
@@ -16,8 +16,8 @@
#include "rtl837x_phy.h"
#include "phy.h"
#pragma codeseg BANK1
#pragma constseg BANK1
#pragma codeseg BANK2
#pragma constseg BANK2
extern __code uint16_t bit_mask[16];
+30
View File
@@ -12,6 +12,7 @@
#include "rtl837x_port.h"
#include "rtl837x_stp.h"
#include "rtl837x_igmp.h"
#include "dhcp.h"
#include "cmd_parser.h"
#include "uip/uipopt.h"
#include "uip/uip.h"
@@ -80,6 +81,7 @@ volatile __xdata uint32_t ticks;
volatile __xdata uint8_t sec_counter;
volatile __xdata uint16_t sleep_ticks;
__xdata uint8_t stp_clock;
extern __xdata struct dhcp_state dhcp_state;
#define STP_TICK_DIVIDER 3
@@ -172,6 +174,22 @@ void write_char(char c)
}
void itoa(uint8_t v)
{
uint8_t t = (v / 100);
// when print_zeros is not zero, we know that a non-zero number has printed.
// That have to print all the next numbers.
uint8_t print_zeros = t;
if (print_zeros)
write_char('0' + t);
t = (v / 10) % 10;
print_zeros |= t;
if (print_zeros)
write_char('0' + t);
write_char('0' + (v % 10));
}
void print_string(__code char *p)
{
while (*p)
@@ -910,6 +928,10 @@ void handle_rx(void)
uip_arp_out();
tcpip_output();
}
} else {
#ifdef RXTXDBG
print_string("Unknown RX on port "); print_byte(rx_headers[3] & 0xf); write_char('\n');
#endif
}
}
}
@@ -927,6 +949,13 @@ void handle_tx(void)
tcpip_output();
}
}
for(uint8_t i = 0; i < UIP_UDP_CONNS; i++) {
uip_udp_periodic(i);
if(uip_len > 0) {
uip_arp_out();
tcpip_output();
}
}
}
@@ -1739,6 +1768,7 @@ void bootloader(void)
{
ticks = 0;
stp_clock = STP_TICK_DIVIDER;
dhcp_state.state = DHCP_OFF;
sbuf_ptr = 0;
CKCON = 0; // Initial Clock configuration
+5 -1
View File
@@ -2,7 +2,8 @@ CC = gcc
CCFLAGS = -Wall -o
BUILDDIR = output/
all: create_build_dir $(BUILDDIR)injector $(BUILDDIR)fileadder $(BUILDDIR)httpd_sim $(BUILDDIR)crc_calculator
all: create_build_dir $(BUILDDIR)injector $(BUILDDIR)fileadder $(BUILDDIR)httpd_sim\
$(BUILDDIR)crc_calculator $(BUILDDIR)imagebuilder
create_build_dir:
mkdir -p $(BUILDDIR)
@@ -21,3 +22,6 @@ $(BUILDDIR)crc_calculator: crc_calculator.c
$(BUILDDIR)httpd_sim: httpd_sim.c httpd_sim.h
gcc $< $(CCFLAGS) $@ -I/usr/include/json-c -ljson-c
$(BUILDDIR)imagebuilder: imagebuilder.c
gcc $^ $(CCFLAGS) $@
+166
View File
@@ -0,0 +1,166 @@
/*
* Adds data files into specified locations of an image, optionally creates
* an index in the form of a header file
*/
#include <stdint.h>
#include <fcntl.h>
#include <arpa/inet.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <argp.h>
#include <stdbool.h>
#define OFFSET 2
#define BANK0_SIZE 0x4000
#define BANK_SIZE 0xc000
#define BANK_STRIDE 0x10000
// Use a 4MB buffer, the maximum flash rom size
#define BUFFER_SIZE 0x400000
uint8_t buffer[BUFFER_SIZE];
FILE *inptr;
int outptr;
const char *argp_program_version = "imagebuilder 0.1";
const char *argp_program_bug_address = "<git@logicog.de>";
static char doc[] = "Create an image with multiple banks for RTL837X-based switches";
static char args_doc[] = "INPUT_IMAGE";
static struct argp_option options[] = {
{ "input", 'i', "FILE", 0, "Input file"},
{ 0 }
};
struct arguments {
char *input_file;
};
static error_t parse_opt(int key, char *arg, struct argp_state *state)
{
struct arguments *arguments = state->input;
switch (key) {
case 'i':
arguments->input_file = arg;
break;
case ARGP_KEY_END:
if (state->arg_num < 1) // Expect 1 command line argument at end
argp_usage(state);
break;
default:
return ARGP_ERR_UNKNOWN;
}
return 0;
}
static struct argp argp = {
options, parse_opt, args_doc, doc, 0, 0, 0
};
int main(int argc, char **argv)
{
struct arguments arguments;
int arg_index;
arguments.input_file = NULL;
argp_parse(&argp, argc, argv, 0, &arg_index, &arguments);
memset(buffer, 0, BUFFER_SIZE);
size_t filesize = 0;
inptr = fopen(arguments.input_file, "rb");
if (inptr == NULL) {
printf("Cannot open input file %s\n", arguments.input_file);
return 5;
}
fseek(inptr, 0L, SEEK_END);
filesize = ftell(inptr);
rewind(inptr);
printf("Input file size: %ld\n", filesize);
if (filesize > BUFFER_SIZE) {
printf("File too large.\n");
return 5;
}
int nbanks = (filesize - BANK0_SIZE) / BANK_STRIDE;
printf("Input file contains %d banks\n", nbanks);
/* Verify the size of banks in input file:
* Bank 0: 0x00002 - 0x04000 <- 0x00000 - 0x03ffe
* Bank 1: 0x04000 - 0x10000 <- 0x14000 - 0x20000
* Bank 2: 0x10000 - 0x1c000 <- 0x24000 - 0x33000
* [...]
* by verifying whether other than 0-bytes are found in the input
* file after these ranges.
*/
size_t bytes_read = fread(buffer, 1, filesize, inptr);
if (bytes_read != filesize) {
printf("Error reading input file.\n");
return 5;
}
for (int b = BANK0_SIZE; b < BANK_STRIDE + BANK0_SIZE; b ++) {
if (buffer[b]) {
printf("WARNING: Bank 0: code segment too large at 0x%x!\n", b);
break;
}
}
for (int bank = 1; bank <= nbanks; bank++) {
for (int b = (bank + 1) * BANK_STRIDE; b < (bank + 1) * BANK_STRIDE + BANK0_SIZE; b ++) {
if (buffer[b]) {
printf("WARNING: Bank %d: code segment too large at 0x%x!\n", bank, b);
break;
}
}
}
rewind(inptr);
memset(buffer, 0, BUFFER_SIZE);
// BANK0-Size
buffer[0] = 0x00;
buffer[1] = 0x40;
// Read bank 0
bytes_read = fread(buffer + OFFSET, 1, BANK0_SIZE, inptr);
printf("Bank 0: Bytes read: %ld\n", bytes_read);
if (bytes_read != BANK0_SIZE) {
printf("Error reading input file.\n");
return 5;
}
fseek(inptr, BANK_STRIDE, SEEK_CUR);
for (int bank = 1; bank <= nbanks; bank++) {
bytes_read = fread(buffer + (bank - 1) * BANK_SIZE + BANK0_SIZE, 1, BANK_SIZE, inptr);
printf("Bank %d: bytes read: %ld\n", bank, bytes_read);
if (bank != nbanks)
fseek(inptr, BANK0_SIZE, SEEK_CUR);
}
fclose(inptr);
outptr = creat(argv[arg_index], S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
if (!outptr) {
printf("Cannot open %s\n", argv[arg_index]);
return 5;
}
size_t written = write(outptr, buffer, (nbanks + 1) * BANK_STRIDE);
if (written != (nbanks + 1) * BANK_STRIDE) {
printf("Error writing output file.\n");
return 5;
}
close(outptr);
return 0;
}
+7 -2
View File
@@ -129,14 +129,18 @@ typedef unsigned short uip_stats_t;
*
* \hideinitializer
*/
#define UIP_CONF_UDP 0
#define UIP_CONF_UDP 1
/**
* UDP checksums on or off
* The RTL8372/3 are able to calculate and verify all L2 and L3 checksums
* in hardware. The TX checksums are configured in the CPU-tag of outgoing
* packets, while the RTL837X_NIC_RX_CTRL register configures the verification
* of the checksum of inbound packets and subsequent possible drop.
*
* \hideinitializer
*/
#define UIP_CONF_UDP_CHECKSUMS 1
#define UIP_CONF_UDP_CHECKSUMS 0
/**
* uIP statistics on or off
@@ -149,6 +153,7 @@ typedef unsigned short uip_stats_t;
our project. */
/*#include "smtp.h"*/
#include "httpd.h"
#include "dhcp.h"
/*#include "telnetd.h"*/
/*#include "webserver.h" */
/*#include "dhcpc.h"*/
+16 -14
View File
@@ -85,6 +85,7 @@
#include "uip.h"
#include "uipopt.h"
#include "uip_arch.h"
#include <stddef.h>
#pragma codeseg BANK1
#pragma constseg BANK1
@@ -168,8 +169,8 @@ __xdata u16_t uip_listenports[UIP_LISTENPORTS];
/* The uip_listenports list all currently
listning ports. */
#if UIP_UDP
struct uip_udp_conn *uip_udp_conn;
struct uip_udp_conn uip_udp_conns[UIP_UDP_CONNS];
__xdata struct uip_udp_conn *uip_udp_conn;
__xdata struct uip_udp_conn uip_udp_conns[UIP_UDP_CONNS];
#endif /* UIP_UDP */
__xdata static u16_t ipid; /* Ths ipid variable is an increasing
@@ -401,7 +402,7 @@ uip_init(void) __banked
/*---------------------------------------------------------------------------*/
#if UIP_ACTIVE_OPEN
__xdata struct uip_conn *
uip_connect(register __xdata uip_ipaddr_t *ripaddr, __xdata u16_t rport)
uip_connect(register __xdata uip_ipaddr_t *ripaddr, __xdata u16_t rport) __banked
{
__xdata struct uip_conn *conn, *cconn;
@@ -467,9 +468,9 @@ uip_connect(register __xdata uip_ipaddr_t *ripaddr, __xdata u16_t rport)
/*---------------------------------------------------------------------------*/
#if UIP_UDP
struct uip_udp_conn *
uip_udp_new(uip_ipaddr_t *ripaddr, u16_t rport)
uip_udp_new(uip_ipaddr_t *ripaddr, u16_t rport) __banked
{
register struct uip_udp_conn *conn;
__xdata struct uip_udp_conn *conn;
/* Find an unused local port. */
again:
@@ -512,7 +513,7 @@ uip_udp_new(uip_ipaddr_t *ripaddr, u16_t rport)
#endif /* UIP_UDP */
/*---------------------------------------------------------------------------*/
void
uip_unlisten(u16_t port)
uip_unlisten(u16_t port) __banked
{
for(c = 0; c < UIP_LISTENPORTS; ++c) {
if(uip_listenports[c] == port) {
@@ -523,7 +524,7 @@ uip_unlisten(u16_t port)
}
/*---------------------------------------------------------------------------*/
void
uip_listen(u16_t port)
uip_listen(u16_t port) __banked
{
for(c = 0; c < UIP_LISTENPORTS; ++c) {
if(uip_listenports[c] == 0) {
@@ -721,7 +722,6 @@ uip_process(u8_t flag) __banked
/* Reset the length variables. */
uip_len = 0;
uip_slen = 0;
/* Check if the connection is in a state in which we simply wait
for the connection to time out. If so, we increase the
connection's timer and remove the connection if it times
@@ -919,12 +919,14 @@ uip_process(u8_t flag) __banked
}
#endif /* UIP_BROADCAST */
/* Check if the packet is destined for our IP address. */
/* Check if we have a DHCP packet, otherwise check if the packet is destined for our IP address. */
#if !UIP_CONF_IPV6
if(!uip_ipaddr_cmpx(BUF->destipaddr, uip_hostaddr)) {
UIP_STAT(++uip_stat.ip.drop);
goto drop;
}
if(!(BUF->proto == UIP_PROTO_UDP && UDPBUF->destport == HTONS(DHCPC_CLIENT_PORT))) {
if(!uip_ipaddr_cmpx(BUF->destipaddr, uip_hostaddr)) {
UIP_STAT(++uip_stat.ip.drop);
goto drop;
}
}
#else /* UIP_CONF_IPV6 */
/* For IPv6, packet reception is a little trickier as we need to
make sure that we listen to certain multicast addresses (all
@@ -1901,7 +1903,7 @@ htons(u16_t val)
}
/*---------------------------------------------------------------------------*/
void
uip_send(register __xdata const void *data, register uint16_t len)
uip_send(register __xdata const void *data, register uint16_t len) __banked
{
if(len > 0) {
uip_slen = len;
+7 -59
View File
@@ -447,7 +447,7 @@ void uip_setipid(u16_t id);
*
* \param port A 16-bit port number in network byte order.
*/
void uip_listen(u16_t port);
void uip_listen(u16_t port) __banked;
/**
* Stop listening to the specified port.
@@ -461,7 +461,7 @@ void uip_listen(u16_t port);
*
* \param port A 16-bit port number in network byte order.
*/
void uip_unlisten(u16_t port);
void uip_unlisten(u16_t port) __banked;
/**
* Connect to a remote host using TCP.
@@ -495,7 +495,7 @@ void uip_unlisten(u16_t port);
* or NULL if no connection could be allocated.
*
*/
__xdata struct uip_conn *uip_connect(register __xdata uip_ipaddr_t *ripaddr, __xdata u16_t port);
__xdata struct uip_conn *uip_connect(register __xdata uip_ipaddr_t *ripaddr, __xdata u16_t port) __banked;
@@ -535,7 +535,7 @@ __xdata struct uip_conn *uip_connect(register __xdata uip_ipaddr_t *ripaddr, __x
*
* \hideinitializer
*/
void uip_send(register __xdata const void *data, register uint16_t len);
void uip_send(register __xdata const void *data, register uint16_t len) __banked;
/**
* The length of any incoming data that is currently avaliable (if avaliable)
@@ -763,7 +763,7 @@ void uip_send(register __xdata const void *data, register uint16_t len);
* \return The uip_udp_conn structure for the new connection or NULL
* if no connection could be allocated.
*/
struct uip_udp_conn *uip_udp_new(uip_ipaddr_t *ripaddr, u16_t rport);
struct uip_udp_conn *uip_udp_new(uip_ipaddr_t *ripaddr, u16_t rport) __banked;
/**
* Removed a UDP connection.
@@ -1224,8 +1224,8 @@ struct uip_udp_conn {
/**
* The current UDP connection.
*/
extern struct uip_udp_conn *uip_udp_conn;
extern struct uip_udp_conn uip_udp_conns[UIP_UDP_CONNS];
extern __xdata struct uip_udp_conn *uip_udp_conn;
extern __xdata struct uip_udp_conn uip_udp_conns[UIP_UDP_CONNS];
#endif /* UIP_UDP */
/**
@@ -1538,58 +1538,6 @@ extern __xdata uip_ipaddr_t uip_hostaddr, uip_netmask, uip_draddr;
extern __xdata uip_ipaddr_t uip_hostaddr, uip_netmask, uip_draddr;
#endif /* UIP_FIXEDADDR */
/**
* Calculate the Internet checksum over a buffer.
*
* The Internet checksum is the one's complement of the one's
* complement sum of all 16-bit words in the buffer.
*
* See RFC1071.
*
* \param buf A pointer to the buffer over which the checksum is to be
* computed.
*
* \param len The length of the buffer over which the checksum is to
* be computed.
*
* \return The Internet checksum of the buffer.
*/
u16_t uip_chksum(u16_t *buf, u16_t len);
/**
* Calculate the IP header checksum of the packet header in uip_buf.
*
* The IP header checksum is the Internet checksum of the 20 bytes of
* the IP header.
*
* \return The IP header checksum of the IP header in the uip_buf
* buffer.
*/
u16_t uip_ipchksum(void);
/**
* Calculate the TCP checksum of the packet in uip_buf and uip_appdata.
*
* The TCP checksum is the Internet checksum of data contents of the
* TCP segment, and a pseudo-header as defined in RFC793.
*
* \return The TCP checksum of the TCP segment in uip_buf and pointed
* to by uip_appdata.
*/
u16_t uip_tcpchksum(void);
/**
* Calculate the UDP checksum of the packet in uip_buf and uip_appdata.
*
* The UDP checksum is the Internet checksum of data contents of the
* UDP segment, and a pseudo-header as defined in RFC768.
*
* \return The UDP checksum of the UDP segment in uip_buf and pointed
* to by uip_appdata.
*/
u16_t uip_udpchksum(void);
#endif /* __UIP_H__ */