Skip to content
Snippets Groups Projects
cmd_boot.c 27.2 KiB
Newer Older
  • Learn to ignore specific revisions
  • Wolfgang Denk's avatar
    Wolfgang Denk committed
    		while (serial_getc () != START_CHAR);
    		/* get length of packet */
    		sum = 0;
    		new_char = serial_getc ();
    		if ((new_char & 0xE0) == 0)
    			goto packet_error;
    		sum += new_char & 0xff;
    		length = untochar (new_char);
    		/* get sequence number */
    		new_char = serial_getc ();
    		if ((new_char & 0xE0) == 0)
    			goto packet_error;
    		sum += new_char & 0xff;
    		n = untochar (new_char);
    		--length;
    
    		/* NEW CODE - check sequence numbers for retried packets */
    		/* Note - this new code assumes that the sequence number is correctly
    		 * received.  Handling an invalid sequence number adds another layer
    		 * of complexity that may not be needed - yet!  At this time, I'm hoping
    		 * that I don't need to buffer the incoming data packets and can write
    		 * the data into memory in real time.
    		 */
    		if (n == last_n) {
    			/* same sequence number, restore the previous state */
    			k_state = k_state_saved;
    			k_data_restore ();
    		} else {
    			/* new sequence number, checkpoint the download */
    			last_n = n;
    			k_state_saved = k_state;
    			k_data_save ();
    		}
    		/* END NEW CODE */
    
    		/* get packet type */
    		new_char = serial_getc ();
    		if ((new_char & 0xE0) == 0)
    			goto packet_error;
    		sum += new_char & 0xff;
    		k_state = new_char;
    		--length;
    		/* check for extended length */
    		if (length == -2) {
    			/* (length byte was 0, decremented twice) */
    			/* get the two length bytes */
    			new_char = serial_getc ();
    			if ((new_char & 0xE0) == 0)
    				goto packet_error;
    			sum += new_char & 0xff;
    			len_hi = untochar (new_char);
    			new_char = serial_getc ();
    			if ((new_char & 0xE0) == 0)
    				goto packet_error;
    			sum += new_char & 0xff;
    			len_lo = untochar (new_char);
    			length = len_hi * 95 + len_lo;
    			/* check header checksum */
    			new_char = serial_getc ();
    			if ((new_char & 0xE0) == 0)
    				goto packet_error;
    			if (new_char != tochar ((sum + ((sum >> 6) & 0x03)) & 0x3f))
    				goto packet_error;
    			sum += new_char & 0xff;
    /* --length; */ /* new length includes only data and block check to come */
    		}
    		/* bring in rest of packet */
    		while (length > 1) {
    			new_char = serial_getc ();
    			if ((new_char & 0xE0) == 0)
    				goto packet_error;
    			sum += new_char & 0xff;
    			--length;
    			if (k_state == DATA_TYPE) {
    				/* pass on the data if this is a data packet */
    				k_data_char (new_char);
    			} else if (k_state == SEND_TYPE) {
    				/* save send pack in buffer as is */
    				*send_ptr++ = new_char;
    				/* if too much data, back off the pointer */
    				if (send_ptr >= &send_parms[SEND_DATA_SIZE])
    					--send_ptr;
    			}
    		}
    		/* get and validate checksum character */
    		new_char = serial_getc ();
    		if ((new_char & 0xE0) == 0)
    			goto packet_error;
    		if (new_char != tochar ((sum + ((sum >> 6) & 0x03)) & 0x3f))
    			goto packet_error;
    		/* get END_CHAR */
    		new_char = serial_getc ();
    		if (new_char != END_CHAR) {
    		  packet_error:
    			/* restore state machines */
    			k_state = k_state_saved;
    			k_data_restore ();
    			/* send a negative acknowledge packet in */
    			send_nack (n);
    		} else if (k_state == SEND_TYPE) {
    			/* crack the protocol parms, build an appropriate ack packet */
    			handle_send_packet (n);
    		} else {
    			/* send simple acknowledge packet in */
    			send_ack (n);
    			/* quit if end of transmission */
    			if (k_state == BREAK_TYPE)
    				done = 1;
    		}
    		++z;
    	}
    	return ((ulong) os_data_addr - (ulong) bin_start_address);
    }
    #endif	/* CFG_CMD_LOADB */
    #if (CONFIG_COMMANDS & CFG_CMD_HWFLOW)
    int do_hwflow (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
    {
    	extern int hwflow_onoff(int);
    
    	if (argc == 2) {
    		if (strcmp(argv[1], "off") == 0)
    			hwflow_onoff(-1);
    		else
    			if (strcmp(argv[1], "on") == 0)
    				hwflow_onoff(1);
    			else
    				printf("Usage: %s\n", cmdtp->usage);
    	}
    	printf("RTS/CTS hardware flow control: %s\n", hwflow_onoff(0) ? "on" : "off");
    	return 0;
    }
    #endif /* CFG_CMD_HWFLOW */