Callisto4Bootloader: lib/c4_tftp.c Source File

Callisto4Bootloader

c4_tftp.c
Go to the documentation of this file.
1
28 /*******************************************************************************
29 * Includes
30 ******************************************************************************/
31 #include "c4_tftp.h"
32
33 #include "lwip/tcpip.h"
34 //#include "lwip/init.h"
35 #include "lwip/netif.h"
36 #include "lwip/sockets.h"
37 #include "enet_ethernetif.h"
38
39 /*******************************************************************************
40 * External Definitions
41 ******************************************************************************/
42
43 /*******************************************************************************
44 * Defines
45 ******************************************************************************/
53 #ifndef max
54 #define max(a,b) \
55 ({ \
56 __typeof__ (a) _a = (a); \
57 __typeof__ (b) _b = (b); \
58 _a > _b ? _a : _b; \
59 })
60 #endif
61
68 #ifndef min
69 #define min(a,b) \
70 ({ \
71 __typeof__ (a) _a = (a); \
72 __typeof__ (b) _b = (b); \
73 _a < _b ? _a : _b; \
74 })
75 #endif
76
78 #define EXAMPLE_CLOCK_NAME kCLOCK_CoreSysClk
79 static const uint32_t TFTP_PORT = 69;
80 static const uint16_t TFTP_DATA_MAX = 1020;
81 static const uint16_t TFTP_PACKET_MAX = (TFTP_DATA_MAX + 4);
82
83 /*******************************************************************************
84 * Structures
85 ******************************************************************************/
86
87
88
90 typedef enum
91 {
92 E_TFTP_OP_RRQ = 1,
93 E_TFTP_OP_WRQ = 2,
94 E_TFTP_OP_DATA = 3,
95 E_TFTP_OP_ACK = 4,
96 E_TFTP_OP_ERROR = 5,
97 E_TFTP_OP_OACK = 6,
98 E_TFTP_OP_NUM
99 } tftp_opcode_t;
100
102 typedef enum
103 {
104 E_TFTP_MODE_TEXT,
105 E_TFTP_MODE_BINARY,
106 E_TFTP_MODE_MAIL,
107 E_TFTP_MODE_NUM
108 } tftp_mode_t;
109
111 typedef enum
112 {
113 E_TFTP_ERR_UNDEF = 0,
114 E_TFTP_ERR_NOT_FOUND = 1,
115 E_TFTP_ERR_ACCESS = 2,
116 E_TFTP_ERR_ALLOC = 3,
117 E_TFTP_ERR_ILLEGAL = 4,
118 E_TFTP_ERR_BAD_TRANSFER = 5,
119 E_TFTP_ERR_EXISTS = 6,
120 E_TFTP_ERR_USER = 7,
121 E_TFTP_ERR_OPT = 8,
122 E_TFTP_ERR_NUM
123 } tftp_err_t;
124
126 typedef enum
127 {
128 E_TFTP_OPT_BLKSIZE,
129 E_TFTP_OPT_TIMEOUT,
130 E_TFTP_OPT_TSIZE,
131 E_TFTP_OPT_NUM
132 } tftp_opt_t;
133
135 const char *TFTP_MODE[E_TFTP_MODE_NUM] = {"netascii", "octet", "mail"};
137 const char *TFTP_OPT[E_TFTP_OPT_NUM] = {"blksize", "timeout", "tsize"};
138
139 /*******************************************************************************
140 * Prototypes
141 ******************************************************************************/
142
145 static void ipaddress_show(void);
146
155 static int TFTP_makePacketAck(uint16_t block, uint8_t *packet, size_t max_pkt);
156
167 static int TFTP_makePacketData(uint16_t block, const uint8_t *data, size_t len, uint8_t *packet, size_t max_pkt);
168
178 static int TFTP_makePacketErr(tftp_err_t code, const char *msg, uint8_t *packet, size_t max_pkt);
179
190 static int TFTP_makePacketRQ(const char *name, tftp_opcode_t op, tftp_mode_t mode, uint8_t *packet, size_t max_pkt);
191
200 static int TFTP_parsePacketAck(const uint8_t *packet, size_t len, uint16_t *block);
201
222 static int TFTP_parsePacketData(const uint8_t *packet, size_t len, uint16_t *block, uint8_t **pData);
223
233 static int TFTP_parsePacketError(const uint8_t *packet, size_t len, tftp_err_t *errcode, char **pMsg);
234
245 static int TFTP_parsePacketOptAck(const uint8_t *packet, size_t len, int *blocksize, int *timeout, int *totalsize);
246
247 /*******************************************************************************
248 * Variables
249 ******************************************************************************/
250
251 static struct netif fsl_netif1;
252 static ip4_addr_t fsl_netif1_ipaddr;
253 static ip4_addr_t fsl_netif1_netmask;
254 static ip4_addr_t fsl_netif1_gw;
255
256 /*******************************************************************************
257 * Code
258 ******************************************************************************/
259
260 /*******************************************************************************
261 * Interface Implementation
262 ******************************************************************************/
263
274 exit_code_t c4_tftpDownloadText(const uint8_t server[4], const char *name, char *file, uint32_t max_file)
275 {
276 exit_code_t rc = C4_ERR_OK;
277 bool qspi_addr = ((file >= FlexSPI_AMBA_BASE) && ((file + max_file) < (FlexSPI_AMBA_BASE + QSPI_FLASH_SIZE)));
278
279 int sockfd;
280 struct sockaddr_in servaddr, cliaddr;
281
282
283 if (qspi_addr)
284 {
285 C4_QSPI_erase(file, max_file);
286 }
287
288 // create socket to connect to TFTP server
289
290 if (-1 == (sockfd = lwip_socket(PF_INET, SOCK_DGRAM, 0)))
291 rc = C4_ERR_SOCKET;
292 if (C4_ERR_OK == rc)
293 {
294 // Set up structure for local client address
295 memset(&cliaddr, 0, sizeof(cliaddr));
296 cliaddr.sin_family = AF_INET;
297 inet_pton(AF_INET, "169.254.154.150", &cliaddr.sin_addr);
298 cliaddr.sin_port = 0;
299 if (-1 == lwip_bind(sockfd, (struct sockaddr *)&cliaddr, sizeof(cliaddr)))
300 rc = C4_ERR_SOCKET;
301
302 // Set up structure for remote server address
303 memset(&servaddr, 0, sizeof(servaddr));
304 servaddr.sin_family = AF_INET;
305 inet_pton(AF_INET, "169.254.154.157", &servaddr.sin_addr);
306 servaddr.sin_port = htons(TFTP_PORT);
307
308 }
309
310 uint8_t tftp_msg[TFTP_PACKET_MAX];
311 int tx_len, rx_len;
312 if (C4_ERR_OK == rc)
313 {
314 // Send request
315 tx_len = TFTP_makePacketRQ(name, E_TFTP_OP_RRQ, E_TFTP_MODE_TEXT, tftp_msg, TFTP_PACKET_MAX);
316 if (-1 == lwip_sendto(sockfd, tftp_msg, tx_len, 0, (struct sockaddr *)&servaddr, sizeof(servaddr)))
317 rc = C4_ERR_SOCKET;
318
319 // Clear port in structure for receive server address
320 servaddr.sin_port = 0;
321 }
322 socklen_t len = sizeof(servaddr);
323 int offset = 0;
324 uint16_t block = 0;
325 bool data_left = true;
326 // Loop to retrieve packets
327 do
328 {
329 rx_len = lwip_recvfrom(sockfd, tftp_msg, 1024, 0, (struct sockaddr *)&servaddr, &len);
330
331 switch(ntohs(*(uint16_t *)tftp_msg))
332 {
333 case E_TFTP_OP_DATA:
334 rx_len = TFTP_parsePacketData(tftp_msg, rx_len, &block, (uint8_t *)(file+offset), max_file - offset);
335 // Send Ack
336 tx_len = TFTP_makePacketAck(block, tftp_msg, TFTP_PACKET_MAX);
337 if (-1 == lwip_sendto(sockfd, tftp_msg, tx_len, 0, (struct sockaddr *)&servaddr, sizeof(servaddr)))
338 rc = C4_ERR_SOCKET;
339
340 if (TFTP_DATA_MAX > rx_len)
341 {
342 data_left = false;
343 }
344 break;
345 case E_TFTP_OP_OACK:
346 {
347 int timeout = -1;
348 int blocksize = - 1;
349 int totalsize = -1;
350 TFTP_parsePacketOptAck(tftp_msg, rx_len, &blocksize, &timeout, &totalsize);
351 /* We have specified a timeout and the server has responded.
352 * Not Implemented
353 */
354 /* We have specified a blocksize and the server has responded.
355 * The specification says that this value is no larger than our request.
356 */
357 /* We requested the total file size and the server has responded. */
358 if (totalsize > max_file)
359 {
360 /* The file is too big for our buffer.
361 * Send an error.
362 */
363 TFTP_makePacketErr(E_TFTP_ERR_ALLOC, "File exceeds allocation", tftp_msg, TFTP_PACKET_MAX);
364 }
365 /* Send a block 0 ack. */
366 tx_len = TFTP_makePacketAck(0, tftp_msg, TFTP_PACKET_MAX);
367 if (-1 == lwip_sendto(sockfd, tftp_msg, tx_len, 0, (struct sockaddr *)&servaddr, sizeof(servaddr)))
368 rc = C4_ERR_SOCKET;
369
370 break;
371 }
372 case E_TFTP_OP_ERROR:
373 case E_TFTP_OP_ACK:
374 case E_TFTP_OP_RRQ:
375 case E_TFTP_OP_WRQ:
376 default:
377 rc = C4_ERR_NOT_IMPLEMENTED;
378 }
379 } while (data_left);
380 return rc;
381 }
382
383 /* ========================================================================= */
384
385 exit_code_t c4_stack_init(const uint8_t au8MACAddress[6],
386 const uint8_t au8StaticIPAddress[4],
387 const uint8_t au8StaticNetMask[4],
388 const uint8_t au8StaticGateway[4])
389 {
390 exit_code_t rc = C4_ERR_OK;
391
392 ethernetif_config_t fsl_enet_config1 = {
393 .clockName = EXAMPLE_CLOCK_NAME,
394 .macAddress =
395 {
396 au8MACAddress[0],
397 au8MACAddress[1],
398 au8MACAddress[2],
399 au8MACAddress[3],
400 au8MACAddress[4],
401 au8MACAddress[5]
402 }
403 };
404 #if LWIP_DHCP
405 int err;
406 #endif
407
408 // Start tcpip_thread (lwIP) task. (Also calls lwip_init() etc.)
409 tcpip_init(NULL, NULL);
410
411 // if (u8UseDHCP == 0)
412 {
413 IP4_ADDR(&fsl_netif1_ipaddr,
414 au8StaticIPAddress[0],
415 au8StaticIPAddress[1],
416 au8StaticIPAddress[2],
417 au8StaticIPAddress[3]);
418 IP4_ADDR(&fsl_netif1_netmask,
419 au8StaticNetMask[0],
420 au8StaticNetMask[1],
421 au8StaticNetMask[2],
422 au8StaticNetMask[3]);
423 IP4_ADDR(&fsl_netif1_gw,
424 au8StaticGateway[0],
425 au8StaticGateway[1],
426 au8StaticGateway[2],
427 au8StaticGateway[3]);
428 }
429
430 netif_add(&fsl_netif1, &fsl_netif1_ipaddr, &fsl_netif1_netmask, &fsl_netif1_gw,
431 &fsl_enet_config1, ethernetif1_init, tcpip_input);
432 /*
433 #if LWIP_NETIF_HOSTNAME
434 netif_set_hostname(&fsl_netif1, (const char *) achHostName);
435 #endif
436 */
437 #if LWIP_IPV6
438 netif_create_ip6_linklocal_address(&fsl_netif1, 1); // LWIP_IPV6
439 // netif_ip6_addr_set_state((&EMAC_if), 0, IP6_ADDR_TENTATIVE); LWIP_IPV6 Don't think I need to do this...
440 #endif
441
442 netif_set_default(&fsl_netif1);
443
444 // Note: according to https://www.nongnu.org/lwip/2_1_x/sys_init.html ...
445 // ...we should add the following call in here: (NickP)
446 // netif_set_link_up(&fsl_netif1);
447
448 netif_set_up(&fsl_netif1);
449 /*
450 if (u8UseDHCP != 0)
451 {
452 #if LWIP_DHCP
453 err = dhcp_start(&fsl_netif1);
454 LWIP_PLATFORM_DIAG(( "dhcp_start...........[result=%d]\r\n", err ));
455 #else
456 LWIP_PLATFORM_DIAG(( "Error: DHCP enabled but not compiled in\r\n" ));
457 #endif
458 }
459 */
460 printf("\r\n************************************************\r\n");
461
462 printf(" MAC Address : %02X:%02X:%02X:%02X:%02X:%02X\r\n",
463 (int) fsl_enet_config1.macAddress[0],
464 (int) fsl_enet_config1.macAddress[1],
465 (int) fsl_enet_config1.macAddress[2],
466 (int) fsl_enet_config1.macAddress[3],
467 (int) fsl_enet_config1.macAddress[4],
468 (int) fsl_enet_config1.macAddress[5]);
469
470 // if (u8UseDHCP == 0)
471 {
472 // No DHCP, so display static IP address
473 ipaddress_show();
474 }
475
476 #if LWIP_IPV6
477 printf(" IPv6 Link Local Address : %s\r\n", ip6addr_ntoa(&(fsl_netif1.ip6_addr[0].u_addr.ip6)) );
478 #endif
479 printf("************************************************\r\n");
480
481 #if STACK_INIT_USE_TASK
482 vTaskDelete(NULL);
483 #endif
484
485 return rc;
486 }
487
488 /*******************************************************************************
489 * Local Functions
490 ******************************************************************************/
491
492 static int TFTP_makePacketAck(uint16_t block, uint8_t *packet, size_t max_pkt)
493 {
494 // check that the packet is long enough
495 if ((4) > max_pkt)
496 return 0;
497 *(uint32_t *)packet = htons((uint16_t)E_TFTP_OP_ACK) | (htons(block)<<16);
498 return 4;
499 }
500
501 /*****************************************************************************/
502
503 static int TFTP_makePacketData(uint16_t block, const uint8_t *data, size_t len, uint8_t *packet, size_t max_pkt)
504 {
505
506 return -1;
507 }
508
509 /*****************************************************************************/
510
511 static int TFTP_makePacketErr(tftp_err_t code, const char *msg, uint8_t *packet, size_t max_pkt)
512 {
513 // check that the packet is long enough - allow extra 6 for maximum blocksize (65535) and 2 to send
514 // tsize request (0)
515 if ((5 + strlen(msg)) > max_pkt)
516 return 0;
517
518
519 char *ptr = (char *)packet;
520 *(uint16_t *)ptr = htons((uint16_t)E_TFTP_OP_ERROR);
521 ptr +=2;
522 *(uint16_t *)ptr = htons((uint16_t)code);
523 ptr +=2;
524 ptr += sprintf(ptr, "%s", msg) + 1;
525
526 return ((uint8_t *)ptr - packet) + 1;
527 }
528
529 /*****************************************************************************/
530
531 static int TFTP_makePacketRQ(const char *name, tftp_opcode_t op, tftp_mode_t mode, uint8_t *packet, size_t max_pkt)
532 {
533
534
535 // check that the packet is long enough
536 // Add one to the lengths to allow for the terminating null for each string
537 // - allow extra 6 for maximum blocksize (65535) and 2 to send
538 // tsize request (0)
539 if ((2 + strlen(name) + 1 +
540 strlen(TFTP_MODE[mode]) + 1 +
541 strlen(TFTP_OPT[E_TFTP_OPT_BLKSIZE]) + 7 +
542 strlen(TFTP_OPT[E_TFTP_OPT_TSIZE]) + 3) > max_pkt)
543 return 0;
544
545 char *ptr = (char *)packet;
546 *(uint16_t *)ptr = htons((uint16_t)(op));
547 ptr +=2;
548 ptr += sprintf(ptr, "%s", name) + 1;
549 ptr += sprintf(ptr, "%s", TFTP_MODE[mode]) + 1;
550 ptr += sprintf(ptr, "%s", TFTP_OPT[E_TFTP_OPT_BLKSIZE]) + 1;
551 ptr += sprintf(ptr, "%d", TFTP_DATA_MAX) + 1 ;
552 ptr += sprintf(ptr, "%s", TFTP_OPT[E_TFTP_OPT_TSIZE]) + 1;
553 ptr += sprintf(ptr, "0") + 1;
554
555 return ((uint8_t *)ptr - packet) + 1;
556 }
557
558 /*****************************************************************************/
559
560 static int TFTP_parsePacketAck(const uint8_t *data, size_t len, uint16_t *block)
561 {
562 if (4 == len)
563 {
564 *block = ntohs(*(uint16_t *)(data+2));
565 return 0;
566 }
567 return -1;
568 }
569
570 /*****************************************************************************/
571
572 static int TFTP_parsePacketData(const uint8_t *packet, size_t len, uint16_t *block, uint8_t **pDest)
573 {
574 if (4 <= len)
575 {
576 uint16_t rx_block = ntohs(*(uint16_t *)(packet+2));
577 if(rx_block == *block + 1)
578 {
579 ++*block;
580 memcpy(dest, packet+4, min(max_dest, len-4));
581 return (len - 4);
582 }
583 else if (rx_block == *block)
584 /* Don't copy duplicate block but return length of data. */
585 return (len - 4);
586
587 }
588 return -1;
589 }
590
591 /*****************************************************************************/
592
593 static int TFTP_parsePacketError(const uint8_t *packet, size_t len, tftp_err_t *errcode, char **pMsg)
594 {
595
596 if (5 <= len)
597 {
598 *errcode = ntohs(*(uint16_t *)(packet+2));
599 strncpy(msg, (char *)(packet + 4), min(max_msg, len - 4));
600 return min(max_msg, len - 4);
601 }
602 return -1;
603 }
604
605 /*****************************************************************************/
606
607 static int TFTP_parsePacketOptAck(const uint8_t *packet, size_t len, int *blocksize, int *timeout, int *totalsize)
608 {
609 if (4 <= len)
610 {
611 const char *ptr = (char *)packet+2;
612 while (ptr < (char *)(packet + len - 1))
613 {
614 int opt_len = strlen(ptr) + 1;
615 int opt_val;
616 int val_len = strlen(ptr + opt_len) + 1;
617 sscanf((ptr + opt_len), "%d", &opt_val);
618 if (0 == strcmp(ptr, TFTP_OPT[E_TFTP_OPT_BLKSIZE]))
619 {
620 *blocksize = opt_val;
621 }
622 else if (0 == strcmp(ptr, TFTP_OPT[E_TFTP_OPT_TIMEOUT]))
623 {
624 *timeout = opt_val;
625 }
626 else if (0 == strcmp(ptr, TFTP_OPT[E_TFTP_OPT_TSIZE]))
627 {
628 *totalsize = opt_val;
629 }
630 ptr += opt_len + val_len;
631 }
632 return 0;
633 }
634 return -1;
635 }
NULL
#define NULL
Definition: bootloader_common.h:26
E_TFTP_OP_NUM
Number of supported TFTP op codes.
Definition: c4_tftp.c:95
fsl_netif1_gw
static ip4_addr_t fsl_netif1_gw
Definition: c4_tftp.c:248
TFTP_DATA_MAX
static const uint16_t TFTP_DATA_MAX
Maximum TFTP packet size.
Definition: c4_tftp.c:77
TFTP_parsePacketData
static int TFTP_parsePacketData(const uint8_t *packet, size_t len, uint16_t *block, uint8_t **pData)
Parse TFTP data packet.
Definition: c4_tftp.c:563
TFTP_makePacketAck
static int TFTP_makePacketAck(uint16_t block, uint8_t *packet, size_t max_pkt)
Construct TFTP acknowledge packet.
Definition: c4_tftp.c:483
E_TFTP_ERR_NUM
Number of supported TFTP error codes.
Definition: c4_tftp.c:118
E_TFTP_MODE_TEXT
Text mode.
Definition: c4_tftp.c:100
E_TFTP_ERR_UNDEF
Not defined, see error message (if any).
Definition: c4_tftp.c:109
c4_tftpDownloadText
exit_code_t c4_tftpDownloadText(const uint8_t server[4], const char *name, char *file, uint32_t max_file)
Use TFTP to download the configuration file.
Definition: c4_tftp.c:266
E_TFTP_OP_WRQ
TFTP Write request.
Definition: c4_tftp.c:90
E_TFTP_OPT_BLKSIZE
Negotiate blocksize.
Definition: c4_tftp.c:124
E_TFTP_OP_DATA
TFTP Data packet.
Definition: c4_tftp.c:91
fsl_netif1
static struct netif fsl_netif1
Definition: c4_tftp.c:245
min
#define min(a, b)
Minimum.
Definition: c4_tftp.c:66
TFTP_parsePacketAck
static int TFTP_parsePacketAck(const uint8_t *packet, size_t len, uint16_t *block)
Parse TFTP Acknowledge packet.
Definition: c4_tftp.c:551
E_TFTP_ERR_ACCESS
Access violation.
Definition: c4_tftp.c:111
E_TFTP_ERR_USER
No such user.
Definition: c4_tftp.c:116
TFTP_OPT
const char * TFTP_OPT[E_TFTP_OPT_NUM]
TFTP option strings.
Definition: c4_tftp.c:133
TFTP_makePacketRQ
static int TFTP_makePacketRQ(const char *name, tftp_opcode_t op, tftp_mode_t mode, uint8_t *packet, size_t max_pkt)
Construct TFTP read or write request packet.
Definition: c4_tftp.c:522
E_TFTP_MODE_MAIL
Mail mode.
Definition: c4_tftp.c:102
fsl_netif1_ipaddr
static ip4_addr_t fsl_netif1_ipaddr
Definition: c4_tftp.c:246
c4_stack_init
exit_code_t c4_stack_init(const uint8_t au8MACAddress[6], const uint8_t au8StaticIPAddress[4], const uint8_t au8StaticNetMask[4], const uint8_t au8StaticGateway[4])
Initialise the IP stack.
Definition: c4_tftp.c:377
exit_code_t
exit_code_t
Enumeration of error codes.
Definition: c4_error_codes.h:96
C4_QSPI_erase
exit_code_t C4_QSPI_erase(uintptr_t addr, size_t len)
Erase region in QSPI flash memory.
Definition: c4_qspi.c:123
fsl_netif1_netmask
static ip4_addr_t fsl_netif1_netmask
Definition: c4_tftp.c:247
E_TFTP_OP_ACK
TFTP Acknowledge packet.
Definition: c4_tftp.c:92
E_TFTP_MODE_NUM
Number of supported TFTP modes.
Definition: c4_tftp.c:103
E_TFTP_OP_RRQ
TFTP Read request.
Definition: c4_tftp.c:89
E_TFTP_OPT_TIMEOUT
Negotiate timeout.
Definition: c4_tftp.c:125
E_TFTP_OP_OACK
TFTP Optiona Acknowledge packet.
Definition: c4_tftp.c:94
FlexSPI_AMBA_BASE
#define FlexSPI_AMBA_BASE
Definition: MIMXRT1062.h:20168
tftp_mode_t
tftp_mode_t
enumeration of supported TFTP modes
Definition: c4_tftp.c:98
E_TFTP_ERR_EXISTS
File already exists.
Definition: c4_tftp.c:115
E_TFTP_OPT_NUM
Total number of TFTP options.
Definition: c4_tftp.c:127
tftp_err_t
tftp_err_t
TFTP error codes.
Definition: c4_tftp.c:107
EXAMPLE_CLOCK_NAME
#define EXAMPLE_CLOCK_NAME
Definition: c4_tftp.c:75
ipaddress_show
static void ipaddress_show(void)
Display the current IP address, subnet mask, and gateway address.
TFTP_PORT
static const uint32_t TFTP_PORT
Well known TFTP port.
Definition: c4_tftp.c:76
tftp_opcode_t
tftp_opcode_t
TFTP opcodes.
Definition: c4_tftp.c:86
E_TFTP_OPT_TSIZE
Negotiate transfer size total.
Definition: c4_tftp.c:126
tftp_opt_t
tftp_opt_t
TFTP Options.
Definition: c4_tftp.c:122
E_TFTP_ERR_BAD_TRANSFER
Unknown transfer ID.
Definition: c4_tftp.c:114
TFTP_parsePacketError
static int TFTP_parsePacketError(const uint8_t *packet, size_t len, tftp_err_t *errcode, char **pMsg)
Parse TFTP error request packet.
Definition: c4_tftp.c:584
TFTP_makePacketErr
static int TFTP_makePacketErr(tftp_err_t code, const char *msg, uint8_t *packet, size_t max_pkt)
Construct TFTP error packet.
Definition: c4_tftp.c:502
TFTP_makePacketData
static int TFTP_makePacketData(uint16_t block, const uint8_t *data, size_t len, uint8_t *packet, size_t max_pkt)
Construct TFTP data packet.
Definition: c4_tftp.c:494
E_TFTP_MODE_BINARY
Binary mode.
Definition: c4_tftp.c:101
E_TFTP_ERR_NOT_FOUND
File not found.
Definition: c4_tftp.c:110
c4_tftp.h
Functions to connect to an TFTP server and download application files and configurations.
TFTP_parsePacketOptAck
static int TFTP_parsePacketOptAck(const uint8_t *packet, size_t len, int *blocksize, int *timeout, int *totalsize)
Parse TFTP Option acknowledgement packet.
Definition: c4_tftp.c:598
TFTP_PACKET_MAX
static const uint16_t TFTP_PACKET_MAX
Maximum TFTP packet size.
Definition: c4_tftp.c:78
E_TFTP_OP_ERROR
TFTP Error packet.
Definition: c4_tftp.c:93
E_TFTP_ERR_OPT
Option error.
Definition: c4_tftp.c:117
E_TFTP_ERR_ILLEGAL
Illegal TFTP operation.
Definition: c4_tftp.c:113
TFTP_MODE
const char * TFTP_MODE[E_TFTP_MODE_NUM]
TFTP mode strings.
Definition: c4_tftp.c:131
E_TFTP_ERR_ALLOC
Disk full or allocation exceeded.
Definition: c4_tftp.c:112