"Das U-Boot" Source Tree
at master 177 lines 3.6 kB view raw
1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * (C) Copyright 2000 4 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. 5 */ 6 7#include <s_record.h> 8 9static int hex1_bin (char c); 10static int hex2_bin (char *s); 11 12int srec_decode (char *input, int *count, ulong *addr, char *data) 13{ 14 int i; 15 int v; /* conversion buffer */ 16 int srec_type; /* S-Record type */ 17 unsigned char chksum; /* buffer for checksum */ 18 19 chksum = 0; 20 21 /* skip anything before 'S', and the 'S' itself. 22 * Return error if not found 23 */ 24 25 for (; *input; ++input) { 26 if (*input == 'S') { /* skip 'S' */ 27 ++input; 28 break; 29 } 30 } 31 if (*input == '\0') { /* no more data? */ 32 return (SREC_EMPTY); 33 } 34 35 v = *input++; /* record type */ 36 37 if ((*count = hex2_bin(input)) < 0) { 38 return (SREC_E_NOSREC); 39 } 40 41 chksum += *count; 42 input += 2; 43 44 switch (v) { /* record type */ 45 46 case '0': /* start record */ 47 srec_type = SREC_START; /* 2 byte addr field */ 48 *count -= 3; /* - checksum and addr */ 49 break; 50 case '1': 51 srec_type = SREC_DATA2; /* 2 byte addr field */ 52 *count -= 3; /* - checksum and addr */ 53 break; 54 case '2': 55 srec_type = SREC_DATA3; /* 3 byte addr field */ 56 *count -= 4; /* - checksum and addr */ 57 break; 58 case '3': /* data record with a */ 59 srec_type = SREC_DATA4; /* 4 byte addr field */ 60 *count -= 5; /* - checksum and addr */ 61 break; 62/*** case '4' ***/ 63 case '5': /* count record, addr field contains */ 64 srec_type = SREC_COUNT; /* a 2 byte record counter */ 65 *count = 0; /* no data */ 66 break; 67/*** case '6' -- not used ***/ 68 case '7': /* end record with a */ 69 srec_type = SREC_END4; /* 4 byte addr field */ 70 *count -= 5; /* - checksum and addr */ 71 break; 72 case '8': /* end record with a */ 73 srec_type = SREC_END3; /* 3 byte addr field */ 74 *count -= 4; /* - checksum and addr */ 75 break; 76 case '9': /* end record with a */ 77 srec_type = SREC_END2; /* 2 byte addr field */ 78 *count -= 3; /* - checksum and addr */ 79 break; 80 default: 81 return (SREC_E_BADTYPE); 82 } 83 84 /* read address field */ 85 *addr = 0; 86 87 switch (v) { 88 case '3': /* 4 byte addr field */ 89 case '7': 90 if ((v = hex2_bin(input)) < 0) { 91 return (SREC_E_NOSREC); 92 } 93 *addr += v; 94 chksum += v; 95 input += 2; 96 /* FALL THRU */ 97 case '2': /* 3 byte addr field */ 98 case '8': 99 if ((v = hex2_bin(input)) < 0) { 100 return (SREC_E_NOSREC); 101 } 102 *addr <<= 8; 103 *addr += v; 104 chksum += v; 105 input += 2; 106 /* FALL THRU */ 107 case '0': /* 2 byte addr field */ 108 case '1': 109 case '5': 110 case '9': 111 if ((v = hex2_bin(input)) < 0) { 112 return (SREC_E_NOSREC); 113 } 114 *addr <<= 8; 115 *addr += v; 116 chksum += v; 117 input += 2; 118 119 if ((v = hex2_bin(input)) < 0) { 120 return (SREC_E_NOSREC); 121 } 122 *addr <<= 8; 123 *addr += v; 124 chksum += v; 125 input += 2; 126 127 break; 128 default: 129 return (SREC_E_BADTYPE); 130 } 131 132 /* convert data and calculate checksum */ 133 for (i=0; i < *count; ++i) { 134 if ((v = hex2_bin(input)) < 0) { 135 return (SREC_E_NOSREC); 136 } 137 data[i] = v; 138 chksum += v; 139 input += 2; 140 } 141 142 /* read anc check checksum */ 143 if ((v = hex2_bin(input)) < 0) { 144 return (SREC_E_NOSREC); 145 } 146 147 if ((unsigned char)v != (unsigned char)~chksum) { 148 return (SREC_E_BADCHKS); 149 } 150 151 return (srec_type); 152} 153 154static int hex1_bin (char c) 155{ 156 if (c >= '0' && c <= '9') 157 return (c - '0'); 158 if (c >= 'a' && c <= 'f') 159 return (c + 10 - 'a'); 160 if (c >= 'A' && c <= 'F') 161 return (c + 10 - 'A'); 162 return (-1); 163} 164 165static int hex2_bin (char *s) 166{ 167 int i, j; 168 169 if ((i = hex1_bin(*s++)) < 0) { 170 return (-1); 171 } 172 if ((j = hex1_bin(*s)) < 0) { 173 return (-1); 174 } 175 176 return ((i<<4) + j); 177}