int tftp_mkdatapacket(int fd, off_t offset, uint8_t *packet, uint16_t blockno) { off_t tmp; int nbytesread; /* Format the DATA message header */ packet[0] = TFTP_DATA >> 8; packet[1] = TFTP_DATA & 0xff; packet[2] = blockno >> 8; packet[3] = blockno & 0xff; /* Seek to the correct offset in the file */ tmp = lseek(fd, offset, SEEK_SET); if (tmp == (off_t)-1) { ndbg("lseek failed: %d\n", errno); return ERROR; } /* Read the file data into the packet buffer */ nbytesread = tftp_read(fd, &packet[TFTP_DATAHEADERSIZE], TFTP_DATASIZE); if (nbytesread < 0) { return ERROR; } return nbytesread + TFTP_DATAHEADERSIZE; }
int main(void) { NetbootParam *param; // Initialize some consoles. serial_console_init(); cbmem_console_init(); video_console_init(); input_init(); printf("\n\nStarting netboot on " CONFIG_BOARD "...\n"); timestamp_init(); if (run_init_funcs()) halt(); // Make sure graphics are available if they aren't already. enable_graphics(); dc_usb_initialize(); srand(timer_raw_value()); printf("Looking for network device... "); while (!net_get_device()) usb_poll(); printf("done.\n"); printf("Waiting for link... "); int ready = 0; while (!ready) { if (net_ready(&ready)) halt(); } mdelay(200); // some dongles need more time than they think printf("done.\n"); // Start up the network stack. uip_init(); // Plug in the MAC address. const uip_eth_addr *mac_addr = net_get_mac(); if (!mac_addr) halt(); printf("MAC: "); print_mac_addr(mac_addr); printf("\n"); uip_setethaddr(*mac_addr); // Find out who we are. uip_ipaddr_t my_ip, next_ip, server_ip; const char *dhcp_bootfile; while (dhcp_request(&next_ip, &server_ip, &dhcp_bootfile)) printf("Dhcp failed, retrying.\n"); printf("My ip is "); uip_gethostaddr(&my_ip); print_ip_addr(&my_ip); printf("\nThe DHCP server ip is "); print_ip_addr(&server_ip); printf("\n"); // Retrieve settings from the shared data area. FmapArea shared_data; if (fmap_find_area("SHARED_DATA", &shared_data)) { printf("Couldn't find the shared data area.\n"); halt(); } void *data = flash_read(shared_data.offset, shared_data.size); netboot_params_init(data, shared_data.size); // Get TFTP server IP and file name from params with DHCP as fallback uip_ipaddr_t *tftp_ip = NULL; param = netboot_params_val(NetbootParamIdTftpServerIp); if (param->data && param->size >= sizeof(uip_ipaddr_t)) { tftp_ip = (uip_ipaddr_t *)param->data; printf("TFTP server IP set from firmware parameters: "); } else { tftp_ip = &next_ip; printf("TFTP server IP supplied by DHCP server: "); } print_ip_addr(tftp_ip); printf("\n"); const char *bootfile = NULL; param = netboot_params_val(NetbootParamIdBootfile); if (param->data && param->size > 0 && strnlen((const char *)param->data, param->size) < param->size) { bootfile = (const char *)param->data; printf("Bootfile set from firmware parameters: %s\n", bootfile); } else { bootfile = dhcp_bootfile; printf("Bootfile supplied by DHCP server: %s\n", bootfile); } // Download the bootfile. uint32_t size; if (tftp_read(payload, tftp_ip, bootfile, &size, MaxPayloadSize)) { printf("Tftp failed.\n"); if (dhcp_release(server_ip)) printf("Dhcp release failed.\n"); halt(); } printf("The bootfile was %d bytes long.\n", size); // Use command line from params when present (added to the default). param = netboot_params_val(NetbootParamIdKernelArgs); if (param->data && param->size > 0 && *(char *)param->data != '\0') { cmd_line[sizeof(def_cmd_line) - 1] = ' '; strncpy(&cmd_line[sizeof(def_cmd_line)], param->data, sizeof(cmd_line) - sizeof(def_cmd_line)); printf("Command line set from firmware parameters.\n"); // Otherwise, try to fetch it dynamically as a TFTP file. } else if (!(tftp_read(cmd_line, tftp_ip, "cmdline." CONFIG_BOARD, &size, sizeof(cmd_line) - 1))) { while (cmd_line[size - 1] <= ' ') // strip trailing whitespace if (!--size) break; // and control chars (\n, \r) cmd_line[size] = '\0'; while (size--) // replace inline control if (cmd_line[size] < ' ') // chars with spaces cmd_line[size] = ' '; printf("Command line loaded dynamically from TFTP server.\n"); // If the file doesn't exist, finally fall back to built-in default. } else { printf("No command line from TFTP, falling back to default.\n"); } cmd_line[sizeof(cmd_line) - 1] = '\0'; // We're done on the network, so release our IP. if (dhcp_release(server_ip)) { printf("Dhcp release failed.\n"); halt(); } // Add tftp server IP into command line. static const char def_tftp_cmdline[] = " tftpserverip=xxx.xxx.xxx.xxx"; const int tftp_cmdline_def_size = sizeof(def_tftp_cmdline) - 1; int cmd_line_size = strlen(cmd_line); if (cmd_line_size + tftp_cmdline_def_size >= sizeof(cmd_line)) { printf("Out of space adding TFTP server IP to the command line.\n"); return 1; } sprintf(&cmd_line[cmd_line_size], " tftpserverip=%d.%d.%d.%d", uip_ipaddr1(tftp_ip), uip_ipaddr2(tftp_ip), uip_ipaddr3(tftp_ip), uip_ipaddr4(tftp_ip)); printf("The command line is: %s\n", cmd_line); // Boot. boot(payload, cmd_line, NULL, NULL); // We should never get here. printf("Got to the end!\n"); halt(); return 0; }