diff options
| author | wdenk <wdenk> | 2001-10-23 11:55:05 +0000 | 
|---|---|---|
| committer | wdenk <wdenk> | 2001-10-23 11:55:05 +0000 | 
| commit | 89752b9b544c05048efe49c6ec9ab982057b988f (patch) | |
| tree | c349dc902386ea2933b9bf37a96f6e62ad3e00b1 /tools/img2srec.c | |
| parent | c74078f8dc7acc8ab85e9eb07afe85ef1bca84bc (diff) | |
| download | olio-uboot-2014.01-89752b9b544c05048efe49c6ec9ab982057b988f.tar.xz olio-uboot-2014.01-89752b9b544c05048efe49c6ec9ab982057b988f.zip | |
Initial revision
Diffstat (limited to 'tools/img2srec.c')
| -rw-r--r-- | tools/img2srec.c | 413 | 
1 files changed, 413 insertions, 0 deletions
| diff --git a/tools/img2srec.c b/tools/img2srec.c new file mode 100644 index 000000000..330ae02ec --- /dev/null +++ b/tools/img2srec.c @@ -0,0 +1,413 @@ +/************************************************************************* +|  COPYRIGHT (c) 2000 BY ABATRON AG +|************************************************************************* +| +|  PROJECT NAME: Linux Image to S-record Conversion Utility +|  FILENAME    : img2srec.c +| +|  COMPILER    : GCC +| +|  TARGET OS   : LINUX / UNIX +|  TARGET HW   : - +| +|  PROGRAMMER  : Abatron / RD +|  CREATION    : 07.07.00 +| +|************************************************************************* +| +|  DESCRIPTION : +| +|  Utility to convert a Linux Boot Image to S-record: +|  ================================================== +| +|  This command line utility can be used to convert a Linux boot image +|  (zimage.initrd) to S-Record format used for flash programming. +|  This conversion takes care of the special sections "IMAGE" and INITRD". +| +|  img2srec [-o offset] image > image.srec +| +| +|  Build the utility: +|  ================== +| +|  To build the utility use GCC as follows: +| +|  gcc img2srec.c -o img2srec +| +| +|************************************************************************* +| +| +|  UPDATES     : +| +|  DATE      NAME  CHANGES +|  ----------------------------------------------------------- +|  Latest update +| +|  07.07.00  aba   Initial release +| +|*************************************************************************/ + +/************************************************************************* +|  INCLUDES +|*************************************************************************/ + +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <ctype.h> +#include <string.h> +#include <elf.h> +#include <unistd.h> +#include <errno.h> + +extern int errno; + +/************************************************************************* +|  DEFINES +|*************************************************************************/ + +#define FALSE           0 +#define TRUE            1 + +/************************************************************************* +|  MACROS +|*************************************************************************/ + +/************************************************************************* +|  TYPEDEFS +|*************************************************************************/ + +typedef uint8_t   CHAR; +typedef uint8_t   BYTE; +typedef uint16_t  WORD; +typedef uint32_t  DWORD; +typedef int       BOOL; + +/************************************************************************* +|  LOCALS +|*************************************************************************/ + +/************************************************************************* +|  PROTOTYPES +|*************************************************************************/ + +static char *ExtractHex(DWORD *value, char *getPtr); +static char *ExtractDecimal(DWORD *value, char *getPtr); +static void ExtractNumber(DWORD *value, char *getPtr); +static BYTE *ExtractWord(WORD *value, BYTE *buffer); +static BYTE *ExtractLong(DWORD *value, BYTE *buffer); +static BYTE *ExtractBlock(WORD count, BYTE *data, BYTE *buffer); +static char *WriteHex(char *pa, BYTE value, WORD *pCheckSum); +static char *BuildSRecord(char *pa, WORD sType, DWORD addr, +			  const BYTE *data, int nCount); +static void ConvertELF(char *fileName, DWORD loadOffset); +int main(int argc, char *argv[]); + +/************************************************************************* +|  FUNCTIONS +|*************************************************************************/ + +static char* ExtractHex (DWORD* value,  char* getPtr) +{ +  DWORD num; +  DWORD digit; +  BYTE  c; + +  while (*getPtr == ' ') getPtr++; +  num = 0; +  for (;;) { +    c = *getPtr; +    if      ((c >= '0') && (c <= '9')) digit = (DWORD)(c - '0'); +    else if ((c >= 'A') && (c <= 'F')) digit = (DWORD)(c - 'A' + 10); +    else if ((c >= 'a') && (c <= 'f')) digit = (DWORD)(c - 'a' + 10); +    else break; +    num <<= 4; +    num += digit; +    getPtr++; +  } /* for */ +  *value = num; +  return getPtr; +} /* ExtractHex */ + +static char* ExtractDecimal (DWORD* value,  char* getPtr) +{ +  DWORD num; +  DWORD digit; +  BYTE  c; + +  while (*getPtr == ' ') getPtr++; +  num = 0; +  for (;;) { +    c = *getPtr; +    if      ((c >= '0') && (c <= '9')) digit = (DWORD)(c - '0'); +    else break; +    num *= 10; +    num += digit; +    getPtr++; +  } /* for */ +  *value = num; +  return getPtr; +} /* ExtractDecimal */ + + +static void ExtractNumber (DWORD* value,  char* getPtr) +{ +  BOOL  neg = FALSE;; + +  while (*getPtr == ' ') getPtr++; +  if (*getPtr == '-') { +    neg = TRUE; +    getPtr++; +  } /* if */ +  if ((*getPtr == '0') && ((*(getPtr+1) == 'x') || (*(getPtr+1) == 'X'))) { +    getPtr +=2; +    (void)ExtractHex(value, getPtr); +  } /* if */ +  else { +    (void)ExtractDecimal(value, getPtr); +  } /* else */ +  if (neg) *value = -(*value); +} /* ExtractNumber */ + + +static BYTE* ExtractWord(WORD* value, BYTE* buffer) +{ +  WORD x; +  x = (WORD)*buffer++; +  x = (x<<8) + (WORD)*buffer++; +  *value = x; +  return buffer; +} /* ExtractWord */ + + +static BYTE* ExtractLong(DWORD* value, BYTE* buffer) +{ +  DWORD x; +  x = (DWORD)*buffer++; +  x = (x<<8) + (DWORD)*buffer++; +  x = (x<<8) + (DWORD)*buffer++; +  x = (x<<8) + (DWORD)*buffer++; +  *value = x; +  return buffer; +} /* ExtractLong */ + + +static BYTE* ExtractBlock(WORD count, BYTE* data, BYTE* buffer) +{ +  while (count--) *data++ = *buffer++; +  return buffer; +} /* ExtractBlock */ + + +static char* WriteHex(char* pa, BYTE value, WORD* pCheckSum) +{ +  WORD  temp; + +  static  char ByteToHex[] = "0123456789ABCDEF"; + +  *pCheckSum += value; +  temp  = value / 16; +  *pa++ = ByteToHex[temp]; +  temp  = value % 16; +  *pa++ = ByteToHex[temp]; +  return pa; +} + + +static char* BuildSRecord(char* pa, WORD sType, DWORD addr, +			  const BYTE* data, int nCount) +{ +  WORD  addrLen; +  WORD  sRLen; +  WORD  checkSum; +  WORD  i; + +  switch (sType) { +  case 0: +  case 1: +  case 9: +    addrLen = 2; +    break; +  case 2: +  case 8: +    addrLen = 3; +    break; +  case 3: +  case 7: +    addrLen = 4; +    break; +  default: +    return pa; +  } /* switch */ + +  *pa++ = 'S'; +  *pa++ = (char)(sType + '0'); +  sRLen = addrLen + nCount + 1; +  checkSum = 0; +  pa = WriteHex(pa, (BYTE)sRLen, &checkSum); + +  /* Write address field */ +  for (i = 1; i <= addrLen; i++) { +    pa = WriteHex(pa, (BYTE)(addr >> (8 * (addrLen - i))), &checkSum); +  } /* for */ + +  /* Write code/data fields */ +  for (i = 0; i < nCount; i++) { +    pa = WriteHex(pa, *data++, &checkSum); +  } /* for */ + +  /* Write checksum field */ +  checkSum = ~checkSum; +  pa = WriteHex(pa, (BYTE)checkSum, &checkSum); +  *pa++ = '\0'; +  return pa; +} + + +static void ConvertELF(char* fileName, DWORD loadOffset) +{ +  FILE*         file; +  int           i; +  int           rxCount; +  BYTE          rxBlock[1024]; +  DWORD         loadSize; +  DWORD         firstAddr; +  DWORD         loadAddr; +  DWORD         loadDiff = 0; +  Elf32_Ehdr    elfHeader; +  Elf32_Shdr    sectHeader[32]; +  BYTE*         getPtr; +  char          srecLine[128]; +  char		*hdr_name; + + +  /* open file */ +  if ((file = fopen(fileName,"rb")) == NULL) { +    fprintf (stderr, "Can't open %s: %s\n", fileName, strerror(errno)); +    return; +  } /* if */ + +  /* read ELF header */ +  rxCount = fread(rxBlock, 1, sizeof elfHeader, file); +  getPtr = ExtractBlock(sizeof elfHeader.e_ident, elfHeader.e_ident, rxBlock); +  getPtr = ExtractWord(&elfHeader.e_type, getPtr); +  getPtr = ExtractWord(&elfHeader.e_machine, getPtr); +  getPtr = ExtractLong((DWORD *)&elfHeader.e_version, getPtr); +  getPtr = ExtractLong((DWORD *)&elfHeader.e_entry, getPtr); +  getPtr = ExtractLong((DWORD *)&elfHeader.e_phoff, getPtr); +  getPtr = ExtractLong((DWORD *)&elfHeader.e_shoff, getPtr); +  getPtr = ExtractLong((DWORD *)&elfHeader.e_flags, getPtr); +  getPtr = ExtractWord(&elfHeader.e_ehsize, getPtr); +  getPtr = ExtractWord(&elfHeader.e_phentsize, getPtr); +  getPtr = ExtractWord(&elfHeader.e_phnum, getPtr); +  getPtr = ExtractWord(&elfHeader.e_shentsize, getPtr); +  getPtr = ExtractWord(&elfHeader.e_shnum, getPtr); +  getPtr = ExtractWord(&elfHeader.e_shstrndx, getPtr); +  if (    (rxCount              != sizeof elfHeader) +       || (elfHeader.e_ident[0] != ELFMAG0) +       || (elfHeader.e_ident[1] != ELFMAG1) +       || (elfHeader.e_ident[2] != ELFMAG2) +       || (elfHeader.e_ident[3] != ELFMAG3) +       || (elfHeader.e_type     != ET_EXEC) +     ) { +    fclose(file); +    fprintf (stderr, "*** illegal file format\n"); +    return; +  } /* if */ + +  /* read all section headers */ +  fseek(file, elfHeader.e_shoff, SEEK_SET); +  for (i = 0; i < elfHeader.e_shnum; i++) { +    rxCount = fread(rxBlock, 1, sizeof sectHeader[0], file); +    getPtr = ExtractLong((DWORD *)§Header[i].sh_name, rxBlock); +    getPtr = ExtractLong((DWORD *)§Header[i].sh_type, getPtr); +    getPtr = ExtractLong((DWORD *)§Header[i].sh_flags, getPtr); +    getPtr = ExtractLong((DWORD *)§Header[i].sh_addr, getPtr); +    getPtr = ExtractLong((DWORD *)§Header[i].sh_offset, getPtr); +    getPtr = ExtractLong((DWORD *)§Header[i].sh_size, getPtr); +    getPtr = ExtractLong((DWORD *)§Header[i].sh_link, getPtr); +    getPtr = ExtractLong((DWORD *)§Header[i].sh_info, getPtr); +    getPtr = ExtractLong((DWORD *)§Header[i].sh_addralign, getPtr); +    getPtr = ExtractLong((DWORD *)§Header[i].sh_entsize, getPtr); +    if (rxCount != sizeof sectHeader[0]) { +      fclose(file); +      fprintf (stderr, "*** illegal file format\n"); +      return; +    } /* if */ +  } /* for */ + +  if ((hdr_name = strrchr(fileName, '/')) == NULL) { +    hdr_name = fileName; +  } else { +    ++hdr_name; +  } +  /* write start record */ +  (void)BuildSRecord(srecLine, 0, 0, (BYTE *)hdr_name, strlen(hdr_name)); +  printf("%s\r\n",srecLine); + +  /* write data records */ +  firstAddr = ~0; +  loadAddr  =  0; +  for (i = 0; i < elfHeader.e_shnum; i++) { +    if (    (sectHeader[i].sh_type == SHT_PROGBITS) +         && (sectHeader[i].sh_size != 0) +         ) { +      loadSize = sectHeader[i].sh_size; +      if (sectHeader[i].sh_flags != 0) { +        loadAddr = sectHeader[i].sh_addr; +        loadDiff = loadAddr - sectHeader[i].sh_offset; +      } /* if */ +      else { +        loadAddr = sectHeader[i].sh_offset + loadDiff; +      } /* else */ + +      if (loadAddr < firstAddr) +        firstAddr = loadAddr; + +      /* build s-records */ +      loadSize = sectHeader[i].sh_size; +      fseek(file, sectHeader[i].sh_offset, SEEK_SET); +      while (loadSize) { +        rxCount = fread(rxBlock, 1, (loadSize > 32) ? 32 : loadSize, file); +        if (rxCount < 0) { +          fclose(file); +          fprintf (stderr, "*** illegal file format\n"); +        return; +        } /* if */ +        (void)BuildSRecord(srecLine, 3, loadAddr + loadOffset, rxBlock, rxCount); +        loadSize -= rxCount; +        loadAddr += rxCount; +        printf("%s\r\n",srecLine); +      } /* while */ +    } /* if */ +  } /* for */ + +  /* add end record */ +  (void)BuildSRecord(srecLine, 7, firstAddr + loadOffset, 0, 0); +  printf("%s\r\n",srecLine); +  fclose(file); +} /* ConvertELF */ + + +/************************************************************************* +|  MAIN +|*************************************************************************/ + +int main( int argc, char *argv[ ]) +{ +  DWORD offset; + +  if (argc == 2) { +    ConvertELF(argv[1], 0); +  } /* if */ +  else if ((argc == 4) && (strcmp(argv[1], "-o") == 0)) { +    ExtractNumber(&offset, argv[2]); +    ConvertELF(argv[3], offset); +  } /* if */ +  else { +    fprintf (stderr, "Usage: img2srec [-o offset] <image>\n"); +  } /* if */ + +  return 0; +} /* main */ |