📄 cmd_boot.c
字号:
int count = his_pad_count; while (count-- > 0) serial_putc(his_pad_char);}/* converts escaped kermit char to binary char */char ktrans(char in){ if ((in & 0x60) == 0x40) { return (char) (in & ~0x40); } else if ((in & 0x7f) == 0x3f) { return (char) (in | 0x40); } else return in;}int chk1(char *buffer){ int total = 0; while (*buffer) { total += *buffer++; } return (int) ((total + ((total >> 6) & 0x03)) & 0x3f);}void s1_sendpacket(char *packet){ send_pad(); while (*packet) { serial_putc(*packet++); }}static char a_b[24];void send_ack(int n){ a_b[0] = START_CHAR; a_b[1] = tochar(3); a_b[2] = tochar(n); a_b[3] = ACK_TYPE; a_b[4] = '\0'; a_b[4] = tochar(chk1(&a_b[1])); a_b[5] = his_eol; a_b[6] = '\0'; s1_sendpacket(a_b);}void send_nack(int n){ a_b[0] = START_CHAR; a_b[1] = tochar(3); a_b[2] = tochar(n); a_b[3] = NACK_TYPE; a_b[4] = '\0'; a_b[4] = tochar(chk1(&a_b[1])); a_b[5] = his_eol; a_b[6] = '\0'; s1_sendpacket(a_b);}/* os_data_* takes an OS Open image and puts it into memory, and puts the boot header in an array named os_data_header if image is binary, no header is stored in os_data_header.*/void (*os_data_init)(void);void (*os_data_char)(char new_char);static int os_data_state, os_data_state_saved;int os_data_count;static int os_data_count_saved;static char *os_data_addr, *os_data_addr_saved;static char *bin_start_address;int os_data_header[8];void image_data_init(void){ os_data_state = 0; os_data_count = 32; os_data_addr = (char *) os_data_header;}void bin_data_init(void){ os_data_state = 0; os_data_count = 0; os_data_addr = bin_start_address;}void os_data_save(void){ os_data_state_saved = os_data_state; os_data_count_saved = os_data_count; os_data_addr_saved = os_data_addr;}void os_data_restore(void){ os_data_state = os_data_state_saved; os_data_count = os_data_count_saved; os_data_addr = os_data_addr_saved;}void bin_data_char(char new_char){ switch (os_data_state) { case 0: /* data */ *os_data_addr++ = new_char; --os_data_count; break; }}void set_kerm_bin_mode(unsigned long *addr){ bin_start_address = (char *) addr; os_data_init = bin_data_init; os_data_char = bin_data_char;}/* k_data_* simply handles the kermit escape translations */static int k_data_escape, k_data_escape_saved;void k_data_init(void){ k_data_escape = 0; os_data_init();}void k_data_save(void){ k_data_escape_saved = k_data_escape; os_data_save();}void k_data_restore(void){ k_data_escape = k_data_escape_saved; os_data_restore();}void k_data_char(char new_char){ if (k_data_escape) { /* last char was escape - translate this character */ os_data_char(ktrans(new_char)); k_data_escape = 0; } else { if (new_char == his_quote) { /* this char is escape - remember */ k_data_escape = 1; } else { /* otherwise send this char as-is */ os_data_char(new_char); } }}#define SEND_DATA_SIZE 20char send_parms[SEND_DATA_SIZE];char *send_ptr;/* handle_send_packet interprits the protocol info and builds and sends an appropriate ack for what we can do */void handle_send_packet(int n){ int length = 3; int bytes; /* initialize some protocol parameters */ his_eol = END_CHAR; /* default end of line character */ his_pad_count = 0; his_pad_char = '\0'; his_quote = K_ESCAPE; /* ignore last character if it filled the buffer */ if (send_ptr == &send_parms[SEND_DATA_SIZE - 1]) --send_ptr; bytes = send_ptr - send_parms; /* how many bytes we'll process */ do { if (bytes-- <= 0) break; /* handle MAXL - max length */ /* ignore what he says - most I'll take (here) is 94 */ a_b[++length] = tochar(94); if (bytes-- <= 0) break; /* handle TIME - time you should wait for my packets */ /* ignore what he says - don't wait for my ack longer than 1 second */ a_b[++length] = tochar(1); if (bytes-- <= 0) break; /* handle NPAD - number of pad chars I need */ /* remember what he says - I need none */ his_pad_count = untochar(send_parms[2]); a_b[++length] = tochar(0); if (bytes-- <= 0) break; /* handle PADC - pad chars I need */ /* remember what he says - I need none */ his_pad_char = ktrans(send_parms[3]); a_b[++length] = 0x40; /* He should ignore this */ if (bytes-- <= 0) break; /* handle EOL - end of line he needs */ /* remember what he says - I need CR */ his_eol = untochar(send_parms[4]); a_b[++length] = tochar(END_CHAR); if (bytes-- <= 0) break; /* handle QCTL - quote control char he'll use */ /* remember what he says - I'll use '#' */ his_quote = send_parms[5]; a_b[++length] = '#'; if (bytes-- <= 0) break; /* handle QBIN - 8-th bit prefixing */ /* ignore what he says - I refuse */ a_b[++length] = 'N'; if (bytes-- <= 0) break; /* handle CHKT - the clock check type */ /* ignore what he says - I do type 1 (for now) */ a_b[++length] = '1'; if (bytes-- <= 0) break; /* handle REPT - the repeat prefix */ /* ignore what he says - I refuse (for now) */ a_b[++length] = 'N'; if (bytes-- <= 0) break; /* handle CAPAS - the capabilities mask */ /* ignore what he says - I only do long packets - I don't do windows */ a_b[++length] = tochar(2); /* only long packets */ a_b[++length] = tochar(0); /* no windows */ a_b[++length] = tochar(94); /* large packet msb */ a_b[++length] = tochar(94); /* large packet lsb */ } while (0); a_b[0] = START_CHAR; a_b[1] = tochar(length); a_b[2] = tochar(n); a_b[3] = ACK_TYPE; a_b[++length] = '\0'; a_b[length] = tochar(chk1(&a_b[1])); a_b[++length] = his_eol; a_b[++length] = '\0'; s1_sendpacket(a_b);}/* k_recv receives a OS Open image file over kermit line */int k_recv(void){ char new_char; char k_state, k_state_saved; int sum; int done; int length; int n, last_n; int z = 0; int len_lo, len_hi; /* initialize some protocol parameters */ his_eol = END_CHAR; /* default end of line character */ his_pad_count = 0; his_pad_char = '\0'; his_quote = K_ESCAPE; /* initialize the k_recv and k_data state machine */ done = 0; k_state = 0; k_data_init(); k_state_saved = k_state; k_data_save(); n = 0; /* just to get rid of a warning */ last_n = -1; /* expect this "type" sequence (but don't check): S: send initiate F: file header D: data (multiple) Z: end of file B: break transmission */ /* enter main loop */ while (!done) { /* set the send packet pointer to begining of send packet parms */ send_ptr = send_parms; /* With each packet, start summing the bytes starting with the length. Save the current sequence number. Note the type of the packet. If a character less than SPACE (0x20) is received - error. */#if 0 /* OLD CODE, Prior to checking sequence numbers */ /* first have all state machines save current states */ k_state_saved = k_state; k_data_save();#endif /* get a packet */ /* wait for the starting character */ 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 0;}#endif /* CFG_CMD_LOADB */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -