/* // ALL RIGHTS RESERVED // // You are hereby granted a copyright license to use, modify, and // distribute the SOFTWARE so long as this entire notice is retained // without alteration in any modified and/or redistributed versions, // and that such modified versions are clearly identified as such. // No licenses are granted by implication, estoppel or otherwise under // any patents or trademarks of Motorola, Inc. // // The SOFTWARE is provided on an "AS IS" basis and without warranty. // To the maximum extent permitted by applicable law, MOTOROLA DISCLAIMS // ALL WARRANTIES WHETHER EXPRESS OR IMPLIED, INCLUDING IMPLIED // WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR // PURPOSE AND ANY WARRANTY AGAINST INFRINGEMENT WITH // REGARD TO THE SOFTWARE (INCLUDING ANY MODIFIED VERSIONS // THEREOF) AND ANY ACCOMPANYING WRITTEN MATERIALS. // // To the maximum extent permitted by applicable law, IN NO EVENT SHALL // MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER // (INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF // BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS // INFORMATION, OR OTHER PECUNIARY LOSS) ARISING OF THE USE OR // INABILITY TO USE THE SOFTWARE. Motorola assumes no responsibility // for the maintenance and support of the SOFTWARE. */ /* // NAME // srec2bin // // DESCRIPTION // srec2bin converts an SRecord file to straight binary. // It handles gaps by filling with 0xFF. // // BUGS // If the Srecord file is not relatively contiguous, then // either: // 1. the binary file will be larger than the Srecord file. // 2. srec2bin will explode. // // REVISION // 2000Jun01 -- GMilliorn -- Written */ #include #include int bin_len; char fill_char; unsigned long dl_addr; unsigned long next_addr; get_two_char( line, data ) char *line; int *data; { char ch1; char ch2; ch1 = *line++; ch2 = *line++; if (ch1 >= '0' && ch1 <= '9') ch1 = ch1 - '0'; else if (ch1 >= 'A' && ch1 <= 'F') ch1 = ch1 - 'A' + 10; else if (ch1 >= 'a' && ch1 <= 'f') ch1 = ch1 - 'a' + 10; if (ch2 >= '0' && ch2 <= '9') ch2 = ch2 - '0'; else if (ch2 >= 'A' && ch2 <= 'F') ch2 = ch2 - 'A' + 10; else if (ch2 >= 'a' && ch2 <= 'f') ch2 = ch2 - 'a' + 10; *data = ((ch1 << 4) | ch2) & 0x0ff; } int process_line(line) char *line; { int i; int length; int addr_length; int data_byte; char type; unsigned long address; char *iline; /* Step 0: Ignore whitespace. */ iline = line; while (*line == ' ' || *line == '\t') line++; /* Step 1: All SRecords start with 'S'. If not, return an error. // Compressed lines should have been converted by now. // // S3 11 000089AC 030405060708091011121314 FE // ^ */ if (*line++ != 'S') { fprintf(stderr, "srec2bin: `%s' does not start with S\n", iline); return( 0 ); } /* Step 2: Get the S-record type, a digit from 0..9. This is used // to process the data as well as determine the length. // // S3 11 000089AC 030405060708091011121314 FE // ^ */ type = *line++; /* Step 3: Get the length of the remainder of the S-record, including the // trailing checksum. // // S3 11 000089AC 030405060708091011121314 FE // ^^ */ get_two_char( line, &length ); line += 2; /* Step 4: Get the address of the Srecord data. The size is dependent // on the type of Srecord we're reading. This example shows a // typical 32-bit address. // // S3 11 000089AC 030405060708091011121314 FE // ^^^^^^^^ */ switch (type) { case '0': case '1': case '5': case '9': addr_length = 4; break; case '2': case '8': addr_length = 6; break; case '3': case '7': addr_length = 8; break; default: fprintf(stderr, "srec2bin: unknown type `%c'\n", type); return( 0 ); } /* Now we know how many characters need to be converted to an address. */ if (type == '0' || type >= '5') return( 1 ); address = 0; length -= (addr_length >> 1); while (addr_length > 0) { get_two_char( line, &i ); address = (address << 8) | i; line += 2; addr_length -= 2; } /* // If address != next_addr /* If 'dl_addr' is unset, and type is [1-3], then this is the first // address record. */ if ((dl_addr == 0x77777777) && ('3' >= type && type >= '1')) dl_addr = address; /* // If, on continuing, we find a gap in the addresses, it must be // filled. */ else if (address != next_addr) { i = address - next_addr; fprintf(stderr, "GAP: from %08lx <=> %08lx (%d)\n", next_addr, address-1, i); while (i) { putchar( fill_char ); bin_len++; i--; } } /* Step 5: The remainder of the Srecord line is the data in bytes, // with the exception of the last two hex digits (the checksum). // // S3 11 000089AC 030405060708091011121314 FE // ^^^^^^^^^^^^^^^^^^^^^^^^ */ length--; /* ignore checksum */ next_addr = address; while (length > 0) { get_two_char( line, &data_byte ); line += 2; length--; next_addr++; putchar( data_byte ); bin_len++; } /* fprintf(stderr, "last store was %x to %x\n", data_byte, next_addr-1); */ /* All that's left is the checksum, which we ignore. */ return( 1 ); } /*--------------------------------------------------------------------------- // main -- convert SRecord file to binary. //-------------------------------------------------------------------------*/ int main() { int lines; int srec_len; char buf[BUFSIZ]; lines = 0; srec_len = 0; bin_len = 0; dl_addr = 0x77777777; fill_char = 0xff; while (1) { if (!gets(buf)) break; srec_len += strlen( buf ); if (!process_line( buf )) break; lines++; } fprintf(stderr, "srec2bin: SRecord lines = %d\n", lines); fprintf(stderr, " SRecord length = %d\n", srec_len); fprintf(stderr, " Binary length = %d\n", bin_len); fprintf(stderr, " Compression = %d%%\n", 100 - ((bin_len * 100)/srec_len)); fprintf(stderr, " Recommended offset = 0x%08lx\n", dl_addr); return( 0 ); }