diff options
author | Yang Zhang <yang.z.zhang@intel.com> | 2015-08-28 09:58:54 +0800 |
---|---|---|
committer | Yang Zhang <yang.z.zhang@intel.com> | 2015-09-01 12:44:00 +0800 |
commit | e44e3482bdb4d0ebde2d8b41830ac2cdb07948fb (patch) | |
tree | 66b09f592c55df2878107a468a91d21506104d3f /qemu/roms/u-boot/tools/img2srec.c | |
parent | 9ca8dbcc65cfc63d6f5ef3312a33184e1d726e00 (diff) |
Add qemu 2.4.0
Change-Id: Ic99cbad4b61f8b127b7dc74d04576c0bcbaaf4f5
Signed-off-by: Yang Zhang <yang.z.zhang@intel.com>
Diffstat (limited to 'qemu/roms/u-boot/tools/img2srec.c')
-rw-r--r-- | qemu/roms/u-boot/tools/img2srec.c | 372 |
1 files changed, 372 insertions, 0 deletions
diff --git a/qemu/roms/u-boot/tools/img2srec.c b/qemu/roms/u-boot/tools/img2srec.c new file mode 100644 index 000000000..ec7696402 --- /dev/null +++ b/qemu/roms/u-boot/tools/img2srec.c @@ -0,0 +1,372 @@ +/************************************************************************* +| 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 "os_support.h" +#include <stdbool.h> +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <ctype.h> +#include <string.h> +#include <elf.h> +#include <unistd.h> +#include <errno.h> + +/************************************************************************* +| FUNCTIONS +|*************************************************************************/ + +static char* ExtractHex (uint32_t* value, char* getPtr) +{ + uint32_t num; + uint32_t digit; + uint8_t c; + + while (*getPtr == ' ') getPtr++; + num = 0; + for (;;) { + c = *getPtr; + if ((c >= '0') && (c <= '9')) digit = (uint32_t)(c - '0'); + else if ((c >= 'A') && (c <= 'F')) digit = (uint32_t)(c - 'A' + 10); + else if ((c >= 'a') && (c <= 'f')) digit = (uint32_t)(c - 'a' + 10); + else break; + num <<= 4; + num += digit; + getPtr++; + } /* for */ + *value = num; + return getPtr; +} /* ExtractHex */ + +static char* ExtractDecimal (uint32_t* value, char* getPtr) +{ + uint32_t num; + uint32_t digit; + uint8_t c; + + while (*getPtr == ' ') getPtr++; + num = 0; + for (;;) { + c = *getPtr; + if ((c >= '0') && (c <= '9')) digit = (uint32_t)(c - '0'); + else break; + num *= 10; + num += digit; + getPtr++; + } /* for */ + *value = num; + return getPtr; +} /* ExtractDecimal */ + + +static void ExtractNumber (uint32_t* 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 uint8_t* ExtractWord(uint16_t* value, uint8_t* buffer) +{ + uint16_t x; + x = (uint16_t)*buffer++; + x = (x<<8) + (uint16_t)*buffer++; + *value = x; + return buffer; +} /* ExtractWord */ + + +static uint8_t* ExtractLong(uint32_t* value, uint8_t* buffer) +{ + uint32_t x; + x = (uint32_t)*buffer++; + x = (x<<8) + (uint32_t)*buffer++; + x = (x<<8) + (uint32_t)*buffer++; + x = (x<<8) + (uint32_t)*buffer++; + *value = x; + return buffer; +} /* ExtractLong */ + + +static uint8_t* ExtractBlock(uint16_t count, uint8_t* data, uint8_t* buffer) +{ + while (count--) *data++ = *buffer++; + return buffer; +} /* ExtractBlock */ + + +static char* WriteHex(char* pa, uint8_t value, uint16_t* pCheckSum) +{ + uint16_t 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, uint16_t sType, uint32_t addr, + const uint8_t* data, int nCount) +{ + uint16_t addrLen; + uint16_t sRLen; + uint16_t checkSum; + uint16_t 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, (uint8_t)sRLen, &checkSum); + + /* Write address field */ + for (i = 1; i <= addrLen; i++) { + pa = WriteHex(pa, (uint8_t)(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, (uint8_t)checkSum, &checkSum); + *pa++ = '\0'; + return pa; +} + + +static void ConvertELF(char* fileName, uint32_t loadOffset) +{ + FILE* file; + int i; + int rxCount; + uint8_t rxBlock[1024]; + uint32_t loadSize; + uint32_t firstAddr; + uint32_t loadAddr; + uint32_t loadDiff = 0; + Elf32_Ehdr elfHeader; + Elf32_Shdr sectHeader[32]; + uint8_t* 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((uint32_t *)&elfHeader.e_version, getPtr); + getPtr = ExtractLong((uint32_t *)&elfHeader.e_entry, getPtr); + getPtr = ExtractLong((uint32_t *)&elfHeader.e_phoff, getPtr); + getPtr = ExtractLong((uint32_t *)&elfHeader.e_shoff, getPtr); + getPtr = ExtractLong((uint32_t *)&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((uint32_t *)§Header[i].sh_name, rxBlock); + getPtr = ExtractLong((uint32_t *)§Header[i].sh_type, getPtr); + getPtr = ExtractLong((uint32_t *)§Header[i].sh_flags, getPtr); + getPtr = ExtractLong((uint32_t *)§Header[i].sh_addr, getPtr); + getPtr = ExtractLong((uint32_t *)§Header[i].sh_offset, getPtr); + getPtr = ExtractLong((uint32_t *)§Header[i].sh_size, getPtr); + getPtr = ExtractLong((uint32_t *)§Header[i].sh_link, getPtr); + getPtr = ExtractLong((uint32_t *)§Header[i].sh_info, getPtr); + getPtr = ExtractLong((uint32_t *)§Header[i].sh_addralign, getPtr); + getPtr = ExtractLong((uint32_t *)§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, (uint8_t *)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[ ]) +{ + uint32_t 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 */ |