EDK2 doxygen online documents - Firmware Encoding Index 1
EDK2 doxygen online documents - Firmware Encoding Index

S3C24xxPkg/vivi/drivers/serial/xmodem.c

Go to the documentation of this file.
00001 /*
00002  * vivi/deriver/serialxmodem.c:
00003  *     - an implementation of the xmodem protocol from the spec.
00004  *
00005  * Based on bootldr/xmodem.c (C) 2000 Compaq Computer Coporation.
00006  *
00007  * Copyright (C) 2001 MIZI Research, Inc.
00008  *
00009  *
00010  * 1999-01-xx: Edwin Foo <efoo@crl.dec.com>
00011  *    - Initial code
00012  *
00013  * 2001-10-04: Janghoon Lyu <nandy@mizi.com>
00014  *    - Modified a little bit.
00015  *
00016  * 2002-07-04: Janghoon Lyu <nandy@mizi.com>
00017  */
00018 
00019 #include "config.h"
00020 #include "machine.h"
00021 #include "serial.h"
00022 #include "priv_data.h"
00023 #include <types.h>
00024 
00025 /* XMODEM parameters */
00026 #define BLOCK_SIZE      128     /* size of transmit blocks */
00027 #define RETRIES         20      /* maximum number of RETRIES */
00028 
00029 /* Line control codes */
00030 #define SOH             0x01    /* start of header */
00031 #define ACK             0x06    /* Acknowledge */
00032 #define NAK             0x15    /* Negative acknowledge */
00033 #define CAN             0x18    /* Cancel */
00034 #define EOT             0x04    /* end of text */
00035 
00036 #define GET_BYTE_TIMEOUT 10000000
00037 
00038 /* global error variable */
00039 char *xmodem_errtxt = NULL;
00040 int get_byte_err = 0;
00041 __u8 volatile rbuffer[BLOCK_SIZE];
00042 
00043 /* prototypes of helper functions */
00044 int get_record(void);
00045 __u8 get_byte(void);
00046 
00047 enum
00048 {
00049         SAC_SEND_NAK = 0,
00050         SAC_SENT_NAK = 1,
00051         SAC_PAST_START_NAK = 2
00052 };
00053 
00054 static volatile int seen_a_char = SAC_SEND_NAK;
00055 
00056 static int one_nak = 0;
00057 static unsigned long xmodem_timeout = GET_BYTE_TIMEOUT;
00058 
00059 char debugbuf[4096];
00060 int db_idx = 0;
00061 
00062 void bufputs(char *s)
00063 {
00064         size_t len = strlen(s) + 1;
00065 
00066         if (len + db_idx > sizeof(debugbuf))
00067                 len = sizeof(debugbuf) - db_idx;
00068 
00069         if (len) {
00070                 memcpy(&debugbuf[db_idx], s, len);
00071                 db_idx += len;
00072         }
00073 }
00074 
00075 void reset_debugbuf(void)
00076 {
00077         memset(debugbuf, 0x2a, sizeof(debugbuf));
00078         db_idx = 0;
00079 }
00080 
00081 __u32 xmodem_receive(char *dldaddr, size_t len)
00082 {
00083         char ochr;
00084         int r = 0, rx_block_num = 0, error_count = 0;
00085         __u32 foffset = 0;
00086         int i;
00087         int ret;
00088 
00089         xmodem_errtxt = NULL;
00090         seen_a_char = 0;
00091 
00092         one_nak = get_param_value("xmodem_one_nak", &ret);
00093         if (ret) one_nak = 0;
00094 
00095         xmodem_timeout = get_param_value("xmodem_initial_timeout", &ret);
00096         if (ret) xmodem_timeout = GET_BYTE_TIMEOUT;
00097 
00098         rx_block_num = 1;
00099         error_count = RETRIES;
00100 
00101         do {
00102                 if ((r = get_record()) == (rx_block_num & 255)) {
00103                         error_count = RETRIES;
00104                         for (i = 0; i <BLOCK_SIZE; i++)
00105                                 *(__u8 *)(dldaddr+foffset+i) = rbuffer[i];
00106                         xmodem_errtxt = "RX PACKET";
00107                         rx_block_num++;
00108                         ochr = ACK;
00109                         foffset += BLOCK_SIZE;
00110                 } else {
00111                         switch (r) {
00112                         case -1: /* TIMEOUT */
00113                                 xmodem_errtxt = "TIMEOUT";
00114                                 ochr = NAK;
00115                                 break;
00116                         case -2: /* Bad block */
00117                                 xmodem_errtxt = "BAD BLOCK#";
00118                                 /* eat teh rest of the block */
00119                                 get_byte_err = 0;
00120                                 while (get_byte_err != -1) get_byte();
00121                                 ochr = NAK;
00122                                 break;
00123                         case -3: /* Bad checksum */
00124                                 xmodem_errtxt = "BAD CHKSUM";
00125                                 ochr = NAK;
00126                                 break;
00127                         case -4: /* End of file */
00128                                 xmodem_errtxt = "DONE";
00129                                 ochr = ACK;
00130                                 break;
00131                         case -5: /* Cancel */
00132                                 xmodem_errtxt = "ABORTED";
00133                                 ochr = ACK;
00134                                 break;
00135                         default: /* Block out of sequence */
00136                                 xmodem_errtxt = "WRONG BLK";
00137                                 ochr = NAK;
00138                         }
00139                         error_count--;
00140                 }
00141                 putc(ochr);
00142         } while ((r > -3) && error_count);
00143 
00144         if ((!error_count) || (r != -4)) {
00145                 foffset = 0;    /* indicate failure to caller */
00146                 /*printk("x-modem error: %s\n", xmodem_errtxt); */
00147         }
00148 
00149         return foffset;
00150 }
00151 
00152 /*
00153  * Read a record in the XMODEM protocol, return the block number
00154  * (0-255) if successful, or one of the following return codes:
00155  *      -1 = Bad byte
00156  *      -2 = Bad block number
00157  *      -3 = Bad block checksum
00158  *      -4 = End of file
00159  *      -5 = Canceled by remote
00160  */
00161 int get_record(void)
00162 {
00163         int c, block_num = 0;
00164         int i;
00165         __u32 check_sum;
00166 
00167         /* clear the buffer */
00168         for (i = 0; i < BLOCK_SIZE; i++)
00169                 rbuffer[i] = 0x00;
00170 
00171         check_sum = 0;
00172         i = -2;
00173         c = get_byte();
00174         if (get_byte_err)
00175                 return -1;
00176 
00177         switch (c) {
00178         case SOH:       /* Receive packet */
00179                 for (;;) {
00180                         c = get_byte();
00181                         if (get_byte_err)
00182                                 return -1;
00183 
00184                         switch (i) {
00185                         case -2: 
00186                                 block_num = c;
00187                                 break;
00188                         case -1:
00189 #if 0
00190 #ifdef CHECK_NEGATED_SECTNUM
00191                                 if (c != (-block_num -1))
00192                                         return -2;
00193 #endif
00194 #endif
00195                                 break;
00196                         case BLOCK_SIZE:
00197                                 if ((check_sum & 0xff) != c)
00198                                         return -3;
00199                                 else
00200                                         return block_num;
00201                                 break;
00202                         default:
00203                                 rbuffer[i] = c;
00204                                 check_sum += c;
00205                         }
00206                         i++;
00207                 }
00208         case EOT:       /* end of file encountered */
00209                 return -4;
00210         case CAN:       /* cancel protocol */
00211                 return -5;
00212         default:
00213                 return -5;
00214         }
00215 }
00216 
00217 /* get_byte should use one of the timer's for a CPU clock independent timeout */
00218 __u8 get_byte()
00219 {
00220         int c, ret;
00221 
00222 again:
00223         c = 0;
00224         get_byte_err = 0; /* reset errno */
00225         c = awaitkey(xmodem_timeout, &get_byte_err);
00226 
00227         if (get_byte_err) {
00228                 if (seen_a_char == SAC_SEND_NAK || !one_nak) {
00229                         bufputs("timeout nak");
00230                         putc(NAK);      /* make the sender go */
00231                 }
00232 
00233                 if (seen_a_char < SAC_PAST_START_NAK) {
00234                         bufputs("goto again");
00235                         seen_a_char = SAC_SENT_NAK;
00236 
00237                         xmodem_timeout = get_param_value("xmodem_timeout", &ret);
00238                         if (ret) xmodem_timeout = GET_BYTE_TIMEOUT;
00239                         goto again;
00240                 }
00241         }
00242 
00243         if (get_byte_err == 0)
00244                 seen_a_char = SAC_PAST_START_NAK;
00245 
00246         return (c);
00247 }
00248 
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Defines