diff --git a/litex/soc/software/bios/Makefile b/litex/soc/software/bios/Makefile index 6fd21dd27..25217e11e 100644 --- a/litex/soc/software/bios/Makefile +++ b/litex/soc/software/bios/Makefile @@ -1,6 +1,11 @@ include ../include/generated/variables.mak include $(SOC_DIRECTORY)/software/common.mak +# Permit TFTP_SERVER_PORT override from shell environment / command line +ifdef TFTP_SERVER_PORT +CFLAGS += -DTFTP_SERVER_PORT=$(TFTP_SERVER_PORT) +endif + OBJECTS=isr.o sdram.o main.o boot-helper-$(CPU).o boot.o all: bios.bin diff --git a/litex/soc/software/bios/boot.c b/litex/soc/software/bios/boot.c index 91da5b177..edf4216a5 100644 --- a/litex/soc/software/bios/boot.c +++ b/litex/soc/software/bios/boot.c @@ -213,11 +213,17 @@ int serialboot(void) #define REMOTEIP4 100 #endif -static int tftp_get_v(unsigned int ip, const char *filename, char *buffer) +#define DEFAULT_TFTP_SERVER_PORT 69 /* IANA well known port: UDP/69 */ +#ifndef TFTP_SERVER_PORT +#define TFTP_SERVER_PORT DEFAULT_TFTP_SERVER_PORT +#endif + +static int tftp_get_v(unsigned int ip, unsigned short server_port, + const char *filename, char *buffer) { int r; - r = tftp_get(ip, filename, buffer); + r = tftp_get(ip, server_port, filename, buffer); if(r > 0) printf("Successfully downloaded %d bytes from %s over TFTP\n", r, filename); else @@ -232,6 +238,7 @@ void netboot(void) int size; unsigned int cmdline_adr, initrdstart_adr, initrdend_adr; unsigned int ip; + unsigned short tftp_port; printf("Booting from network...\n"); printf("Local IP : %d.%d.%d.%d\n", LOCALIP1, LOCALIP2, LOCALIP3, LOCALIP4); @@ -241,13 +248,27 @@ void netboot(void) microudp_start(macadr, IPTOINT(LOCALIP1, LOCALIP2, LOCALIP3, LOCALIP4)); - if(tftp_get_v(ip, "boot.bin", (void *)MAIN_RAM_BASE) <= 0) { + tftp_port = TFTP_SERVER_PORT; + printf("Fetching from: UDP/%d\n", tftp_port); + + size = tftp_get_v(ip, tftp_port, "boot.bin", (void *)MAIN_RAM_BASE); + + if ((size <= 0) && (tftp_port != DEFAULT_TFTP_SERVER_PORT)) { + /* Try default TFTP port if timed out on non-standard port */ + tftp_port = DEFAULT_TFTP_SERVER_PORT; + printf("Fetching from: UDP/%d\n", tftp_port); + + size = tftp_get_v(ip, tftp_port, "boot.bin", + (void *)MAIN_RAM_BASE); + } + + if (size <= 0) { printf("Network boot failed\n"); return; } cmdline_adr = MAIN_RAM_BASE+0x1000000; - size = tftp_get_v(ip, "cmdline.txt", (void *)cmdline_adr); + size = tftp_get_v(ip, tftp_port, "cmdline.txt", (void *)cmdline_adr); if(size <= 0) { printf("No command line parameters found\n"); cmdline_adr = 0; @@ -255,7 +276,7 @@ void netboot(void) *((char *)(cmdline_adr+size)) = 0x00; initrdstart_adr = MAIN_RAM_BASE+0x1002000; - size = tftp_get_v(ip, "initrd.bin", (void *)initrdstart_adr); + size = tftp_get_v(ip, tftp_port, "initrd.bin", (void *)initrdstart_adr); if(size <= 0) { printf("No initial ramdisk found\n"); initrdstart_adr = 0; diff --git a/litex/soc/software/include/net/tftp.h b/litex/soc/software/include/net/tftp.h index 7babb2d77..788731ba0 100644 --- a/litex/soc/software/include/net/tftp.h +++ b/litex/soc/software/include/net/tftp.h @@ -3,8 +3,10 @@ #include -int tftp_get(uint32_t ip, const char *filename, void *buffer); -int tftp_put(uint32_t ip, const char *filename, const void *buffer, int size); +int tftp_get(uint32_t ip, uint16_t server_port, const char *filename, + void *buffer); +int tftp_put(uint32_t ip, uint16_t server_port, const char *filename, + const void *buffer, int size); #endif /* __TFTP_H */ diff --git a/litex/soc/software/libnet/tftp.c b/litex/soc/software/libnet/tftp.c index 8a9ecf219..3cbcec3a4 100644 --- a/litex/soc/software/libnet/tftp.c +++ b/litex/soc/software/libnet/tftp.c @@ -4,7 +4,7 @@ #include #include -#define PORT_OUT 69 +/* Local TFTP client port (arbitrary) */ #define PORT_IN 7642 enum { @@ -100,7 +100,8 @@ static void rx_callback(uint32_t src_ip, uint16_t src_port, } } -int tftp_get(uint32_t ip, const char *filename, void *buffer) +int tftp_get(uint32_t ip, uint16_t server_port, const char *filename, + void *buffer) { int len; int tries; @@ -120,7 +121,7 @@ int tftp_get(uint32_t ip, const char *filename, void *buffer) while(1) { packet_data = microudp_get_tx_buffer(); len = format_request(packet_data, TFTP_RRQ, filename); - microudp_send(PORT_IN, PORT_OUT, len); + microudp_send(PORT_IN, server_port, len); for(i=0;i<2000000;i++) { microudp_service(); if((total_length > 0) || transfer_finished) break; @@ -152,7 +153,8 @@ int tftp_get(uint32_t ip, const char *filename, void *buffer) return total_length; } -int tftp_put(uint32_t ip, const char *filename, const void *buffer, int size) +int tftp_put(uint32_t ip, uint16_t server_port, const char *filename, + const void *buffer, int size) { int len, send; int tries; @@ -172,7 +174,7 @@ int tftp_put(uint32_t ip, const char *filename, const void *buffer, int size) while(1) { packet_data = microudp_get_tx_buffer(); len = format_request(packet_data, TFTP_WRQ, filename); - microudp_send(PORT_IN, PORT_OUT, len); + microudp_send(PORT_IN, server_port, len); for(i=0;i<2000000;i++) { last_ack = -1; microudp_service();