/* * Receive a file. This is implemented as a state machine using a while loop * and a switch statement. This follow pxe specification pages 32-34. */ int tftp_mtftp_receive_file(struct client_data *data) { int state = S_SEND_REQ; /* current state in the state machine */ int timeout_state = state; /* what state should we go on when timeout */ int result; int block_number = 0; int last_block_number = -1;/* block number of last block for multicast */ int data_size; /* size of data received */ int sockfd = data->sockfd; /* just to simplify calls */ int sock; struct sockaddr_storage sa; /* a copy of data.sa_peer */ struct sockaddr_storage from; char from_str[SOCKADDR_PRINT_ADDR_LEN]; struct tftphdr *tftphdr = (struct tftphdr *)data->data_buffer; FILE *fp = NULL; /* the local file pointer */ int number_of_timeout = 0; int timeout = 0; struct sockaddr_storage sa_mcast_group; int mcast_sockfd = 0; struct sockaddr_storage sa_mcast; union ip_mreq_storage mreq; struct addrinfo hints, *addrinfo; int err; int mode = LISTEN; unsigned int file_bitmap[NB_BLOCK]; char string[MAXLEN]; data->file_size = 0; tftp_cancel = 0; memset(&from, 0, sizeof(from)); memset(&sa_mcast, 0, sizeof(struct sockaddr_storage)); memset(&file_bitmap, 0, sizeof(file_bitmap)); /* make sure the socket is not connected */ sa.ss_family = AF_UNSPEC; connect(sockfd, (struct sockaddr *)&sa, sizeof(sa)); /* copy sa_peer structure */ memcpy(&sa, &data->sa_peer, sizeof(sa)); /* check to see if conversion is requiered */ if (strcasecmp(data->tftp_options[OPT_MODE].value, "netascii") == 0) fprintf(stderr, "netascii convertion ignored\n"); /* make sure the data buffer is SEGSIZE + 4 bytes */ if (data->data_buffer_size != (SEGSIZE + 4)) { data->data_buffer = realloc(data->data_buffer, SEGSIZE + 4); tftphdr = (struct tftphdr *)data->data_buffer; if (data->data_buffer == NULL) { fprintf(stderr, "atftp: memory allocation failure.\n"); exit(1); } data->data_buffer_size = SEGSIZE + 4; } /* open the file for writing */ if ((fp = fopen(data->local_file, "w")) == NULL) { fprintf(stderr, "atftp: can't open %s for writing.\n", data->local_file); return ERR; } /* Configure multicast stuff, look up the host */ /* if valid, update s_inn structure */ memset(&hints, 0, sizeof(hints)); hints.ai_socktype = SOCK_DGRAM; if (!getaddrinfo(data->mtftp_mcast_ip, NULL, &hints, &addrinfo) && !sockaddr_set_addrinfo(&sa_mcast_group, addrinfo)) { freeaddrinfo(addrinfo); if (!sockaddr_is_multicast(&sa_mcast_group)) { fprintf(stderr, "mtftp: bad multicast address %s\n", data->mtftp_mcast_ip); exit(1); } } else { fprintf(stderr, "atftp: bad multicast address %s", data->mtftp_mcast_ip); exit(1); } /* we need to open a new socket for multicast */ if ((mcast_sockfd = socket(AF_INET, SOCK_DGRAM, 0))<0) { perror("atftp: socket"); exit(1); } memset(&sa_mcast, 0, sizeof(sa_mcast)); sa_mcast.ss_family = sa_mcast_group.ss_family; sockaddr_set_port(&sa, data->mtftp_client_port); if (bind(mcast_sockfd, (struct sockaddr *)&sa_mcast, sizeof(sa_mcast)) < 0) { perror("atftp: bind"); exit(1); } sockaddr_get_mreq(&sa_mcast_group, &mreq); if (sa_mcast_group.ss_family == AF_INET) err = setsockopt(mcast_sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq.v4, sizeof(mreq.v4)); else err = setsockopt(mcast_sockfd, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &mreq.v6, sizeof(mreq.v6)); if (err < 0) { perror("atftp: setsockopt"); exit(1); } state = S_LISTEN; while (1) { #ifdef DEBUG if (data->delay) usleep(data->delay*1000); #endif if (tftp_cancel) { if (from.ss_family == 0) state = S_ABORT; else { if (mode == RECEIVE) { tftp_send_error(sockfd, &sa, EUNDEF, data->data_buffer, data->data_buffer_size); if (data->trace) fprintf(stderr, "sent ERROR <code: %d, msg: %s>\n", EUNDEF, tftp_errmsg[EUNDEF]); } state = S_ABORT; } tftp_cancel = 0; } switch (state) { case S_LISTEN: if (data->trace) fprintf(stderr, "mtftp: listening for ongoing transfer on %s port %d\n", data->mtftp_mcast_ip, data->mtftp_client_port); number_of_timeout = 0; mode = LISTEN; if (last_block_number > 0) { timeout = data->mtftp_listen_delay - tftp_mtftp_missed_packet(file_bitmap, last_block_number, 1); if (timeout < 0) timeout = 0; } else timeout = data->mtftp_listen_delay; state = S_WAIT_PACKET; timeout_state = S_OPEN; break; case S_OPEN: if (data->trace) fprintf(stderr, "mtftp: opening new connection\n"); mode = OPEN; block_number = 0; timeout = data->mtftp_timeout_delay; state = S_SEND_REQ; break; case S_RECEIVE: if (data->trace) fprintf(stderr, "mtftp: connected, receiving\n"); mode = RECEIVE; timeout = data->mtftp_timeout_delay; state = S_SEND_ACK; break; case S_SEND_REQ: timeout_state = S_SEND_REQ; if (data->trace) { opt_options_to_string(data->tftp_options, string, MAXLEN); fprintf(stderr, "sent RRQ <file: %s, mode: %s <%s>>\n", data->tftp_options[OPT_FILENAME].value, data->tftp_options[OPT_MODE].value, string); } /* send request packet */ if (tftp_send_request(sockfd, &sa, RRQ, data->data_buffer, data->data_buffer_size, data->tftp_options) == ERR) state = S_ABORT; else state = S_WAIT_PACKET; sockaddr_set_port(&sa, 0); /* must be set to 0 before the fist call to tftp_get_packet, but it was set before the call to tftp_send_request with the server port */ break; case S_SEND_ACK: timeout_state = S_SEND_ACK; /* walk the bitmap to find the next missing block */ //prev_bitmap_hole = //tftp_find_bitmap_hole(prev_bitmap_hole, file_bitmap); //block_number = prev_bitmap_hole; if (data->trace) fprintf(stderr, "sent ACK <block: %d>\n", block_number); tftp_send_ack(sockfd, &sa, block_number); /* if we just ACK the last block we are done */ if (block_number == last_block_number) state = S_END; else state = S_WAIT_PACKET; break; case S_WAIT_PACKET: data_size = data->data_buffer_size; /* receive the data */ result = tftp_get_packet(sockfd, mcast_sockfd, &sock, &sa, &from, NULL, timeout, &data_size, data->data_buffer); switch (result) { case GET_TIMEOUT: number_of_timeout++; if (mode == LISTEN) { fprintf(stderr, "mtftp: timeout while listening\n"); state = S_OPEN; } else { fprintf(stderr, "mtftp: timeout: retrying...\n"); if (number_of_timeout > NB_OF_RETRY) state = S_ABORT; else state = timeout_state; } break; case GET_ERROR: if (mode == LISTEN) { fprintf(stderr, "mtftp: unexpected error received from server, ignoring\n"); break; } /* Can only receive this error from unicast */ if (!sockaddr_equal_addr(&sa, &from)) { fprintf(stderr, "mtftp: error packet discarded from <%s>.\n", sockaddr_print_addr(&from, from_str, sizeof(from_str))); break; } /* packet is for us */ fprintf(stderr, "mtftp: error received from server"); fwrite(tftphdr->th_msg, 1, data_size - 4 - 1, stderr); fprintf(stderr, ">\n"); state = S_ABORT; break; case GET_DATA: /* Specification state that server source IP must matches, but port is not a requierement (anyway we may not know the source port yet) */ if (sockaddr_equal_addr(&sa, &from)) { if (mode != LISTEN) { if (sock == sockfd) { /* This is a unicast packet from the server. This should happend for the first data block only, when current block number is 0 and when in OPEN mode */ if ((block_number > 0) || (mode != OPEN)) fprintf(stderr, "mtftp: unexpected unicast packet from <%s>," " continuing\n", sockaddr_print_addr(&from, from_str, sizeof(from_str))); else mode = RECEIVE; } else { /* We receive data on the multicast socket, it should happend for packets 1 and above */ if (block_number == 0) { mode = LISTEN; fprintf(stderr, "mtftp: got multicast data packet," " falling back to listen mode\n"); } } } else { /* We are in listenning mode, we expect data on multicast socket only */ if (sock == sockfd) { fprintf(stderr, "mtftp: unexpected unicast packet from <%s>.\n", sockaddr_print_addr(&from, from_str, sizeof(from_str))); break; } } } else { fprintf(stderr, "mtftp: unexpected packet from <%s>\n", sockaddr_print_addr(&from, from_str, sizeof(from_str))); break; } number_of_timeout = 0; state = S_DATA_RECEIVED; break; case GET_DISCARD: /* consider discarded packet as timeout to make sure when don't lock up when doing multicast transfer and routing is broken or when using wrong mcast IP or port */ number_of_timeout++; fprintf(stderr, "mtftp: packet discard <%s>.\n", sockaddr_print_addr(&from, from_str, sizeof(from_str))); if (number_of_timeout > NB_OF_RETRY) state = S_ABORT; break; case ERR: fprintf(stderr, "mtftp: unknown error.\n"); state = S_ABORT; break; default: fprintf(stderr, "mtftp: abnormal return value %d.\n", result); } break; case S_DATA_RECEIVED: block_number = ntohs(tftphdr->th_block); if (data->trace) fprintf(stderr, "received DATA <block: %d, size: %d>\n", ntohs(tftphdr->th_block), data_size - 4); fseek(fp, (block_number - 1) * (data->data_buffer_size - 4), SEEK_SET); if (fwrite(tftphdr->th_data, 1, data_size - 4, fp) != (data_size - 4)) { fprintf(stderr, "mtftp: error writing to file %s\n", data->local_file); if (mode == RECEIVE) tftp_send_error(sockfd, &sa, ENOSPACE, data->data_buffer, data->data_buffer_size); state = S_END; break; } data->file_size += data_size; /* FIXME: not usefull */ /* Record the block number of the last block. The last block is the one with less data than the transfer block size */ if (data_size < data->data_buffer_size) last_block_number = block_number; /* Mark the received block in the bitmap */ file_bitmap[(block_number - 1)/32] |= (1 << ((block_number - 1) % 32)); /* if we are the master client we ack, else we just wait for data */ if (mode == LISTEN) { /* If we've not received all packets, continue listen. In the case we've not seen the last packet yet, no choice but continuing listen phase and eventually fall back to the open mode and download the whole file again. If we've seen the last packet, we also continue listen, but if we've got all the file we are done */ if (last_block_number < 0) state = S_WAIT_PACKET; else { if (tftp_mtftp_missed_packet(file_bitmap, last_block_number, 0)) state = S_WAIT_PACKET; else { fprintf(stderr, "mtftp: got all packets\n"); state = S_END; } } } else state = S_SEND_ACK; break; case S_END: case S_ABORT: /* close file */ if (fp) fclose(fp); /* drop multicast membership */ if (sa_mcast_group.ss_family == AF_INET) err = setsockopt(mcast_sockfd, IPPROTO_IP, IP_DROP_MEMBERSHIP, &mreq.v4, sizeof(mreq.v4)); else err = setsockopt(mcast_sockfd, IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP, &mreq.v6, sizeof(mreq.v6)); if (err < 0) { perror("setsockopt"); exit(1); } /* close socket */ if (mcast_sockfd) close(mcast_sockfd); /* return proper error code */ if (state == S_END) return OK; else fprintf(stderr, "mtftp: aborting\n"); default: return ERR; } } }
int My_boot_main() { //unsigned char buff[2048]; int num; #ifdef MMU_ON mmu_init(); #endif led_init(); button_init(); init_irq(); uart_init(); ts_init(); //lcd_init(); //lcd_test(); dm9000_init(); while(1) { printf("\n**********************************************\n\r"); printf("\n*******************My-boot********************\n\r"); printf("[1], Download Linux Kernel from TFTP Server!\n\r"); printf("[2], Boot Linux from RAM!\n\r"); printf("[3], Boot Linux from Nand Flash\n\r"); printf("\n Please Select:"); int num; scanf("%d", &num); switch (num) { case 1: //tftp_load(); tftp_send_request("start.o"); break; case 2: //boot_linux_ram(); //arp_request(); boot_linux(); break; case 3: //boot_linux_nand(); arp_request(); break; default: printf("Error: wrong selection!\n\r"); break; } return 0; } }
int gboot_main() { int num; //unsigned char buf[1024*4]; #ifdef MMU_ON mmu_init(); #endif uart_init(); led_init(); button_init(); init_irq(); led_off(); dma_init(); dma_start(); dm9000_init(); while(1) { printf("\n***************************************\n\r"); printf("\n****************MYBOOT*****************\n\r"); printf("1:Set Out a Arp Package to Get Host Ip and MAC!\n\r"); printf("2:Download Linux Kernel from TFTP Server!\n\r"); printf("3:Boot Linux from RAM!\n\r"); printf("\n Plese Select:"); scanf("%d",&num); switch (num) { case 1: arp_progress(); break; case 2: tftp_send_request("tftp.c"); while(FLAG_TFTP); break; case 3: boot_linux(); //boot_linux_nand(); break; default: printf("Error: wrong selection!\n\r"); break; } } return 0; }
int main() { unsigned int num; unsigned char ret = 0; #ifdef MMU_ON mmu_init(); #endif led_init(); key_init(); irq_init(); uart0_init(); lcd_init(); i2c0_init(); lcd_clear_screen(0x000000); dm9000_init(); printf("First write address of 0x0,"); at24cxx_write(0x0, 0xAA); //往设备内存0地址写入0xAA ret = at24cxx_read(0x0); //读设备内存0地址里面的数据 printf("the value in address 0x0 = %x\r\n",ret); printf("Second write address of 0x1,"); at24cxx_write(0x1,0x33); ret = at24cxx_read(0x1); printf("the value in address 0x1 = %x\r\n",ret); // dm9000_arp(); while(1) { printf("\r\n"); printf("========= Boot for S5pv210 Main Menu =========\r\n"); printf("========= designed by KungfuMonkey =========\r\n"); printf("\r\n"); printf("1.ARP Request for PC MAC\r\n"); printf("2.Download Linux Kernel to SDRAM\r\n"); printf("3.Run the linux\r\n"); scanf("%d\r\n",&num); printf("%d\r\n",num); switch(num) { case 1: arp_request(); break; case 2: tftp_send_request("zImage"); break; case 3: boot_linux(); break; default: printf("Error: wrong selection!\r\n"); break; } } return 0; }