img2srec.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413
  1. /*************************************************************************
  2. | COPYRIGHT (c) 2000 BY ABATRON AG
  3. |*************************************************************************
  4. |
  5. | PROJECT NAME: Linux Image to S-record Conversion Utility
  6. | FILENAME : img2srec.c
  7. |
  8. | COMPILER : GCC
  9. |
  10. | TARGET OS : LINUX / UNIX
  11. | TARGET HW : -
  12. |
  13. | PROGRAMMER : Abatron / RD
  14. | CREATION : 07.07.00
  15. |
  16. |*************************************************************************
  17. |
  18. | DESCRIPTION :
  19. |
  20. | Utility to convert a Linux Boot Image to S-record:
  21. | ==================================================
  22. |
  23. | This command line utility can be used to convert a Linux boot image
  24. | (zimage.initrd) to S-Record format used for flash programming.
  25. | This conversion takes care of the special sections "IMAGE" and INITRD".
  26. |
  27. | img2srec [-o offset] image > image.srec
  28. |
  29. |
  30. | Build the utility:
  31. | ==================
  32. |
  33. | To build the utility use GCC as follows:
  34. |
  35. | gcc img2srec.c -o img2srec
  36. |
  37. |
  38. |*************************************************************************
  39. |
  40. |
  41. | UPDATES :
  42. |
  43. | DATE NAME CHANGES
  44. | -----------------------------------------------------------
  45. | Latest update
  46. |
  47. | 07.07.00 aba Initial release
  48. |
  49. |*************************************************************************/
  50. /*************************************************************************
  51. | INCLUDES
  52. |*************************************************************************/
  53. #include <stddef.h>
  54. #include <stdio.h>
  55. #include <stdlib.h>
  56. #include <ctype.h>
  57. #include <string.h>
  58. #include <elf.h>
  59. #include <unistd.h>
  60. #include <errno.h>
  61. extern int errno;
  62. /*************************************************************************
  63. | DEFINES
  64. |*************************************************************************/
  65. #define FALSE 0
  66. #define TRUE 1
  67. /*************************************************************************
  68. | MACROS
  69. |*************************************************************************/
  70. /*************************************************************************
  71. | TYPEDEFS
  72. |*************************************************************************/
  73. typedef uint8_t CHAR;
  74. typedef uint8_t BYTE;
  75. typedef uint16_t WORD;
  76. typedef uint32_t DWORD;
  77. typedef int BOOL;
  78. /*************************************************************************
  79. | LOCALS
  80. |*************************************************************************/
  81. /*************************************************************************
  82. | PROTOTYPES
  83. |*************************************************************************/
  84. static char *ExtractHex(DWORD *value, char *getPtr);
  85. static char *ExtractDecimal(DWORD *value, char *getPtr);
  86. static void ExtractNumber(DWORD *value, char *getPtr);
  87. static BYTE *ExtractWord(WORD *value, BYTE *buffer);
  88. static BYTE *ExtractLong(DWORD *value, BYTE *buffer);
  89. static BYTE *ExtractBlock(WORD count, BYTE *data, BYTE *buffer);
  90. static char *WriteHex(char *pa, BYTE value, WORD *pCheckSum);
  91. static char *BuildSRecord(char *pa, WORD sType, DWORD addr,
  92. const BYTE *data, int nCount);
  93. static void ConvertELF(char *fileName, DWORD loadOffset);
  94. int main(int argc, char *argv[]);
  95. /*************************************************************************
  96. | FUNCTIONS
  97. |*************************************************************************/
  98. static char* ExtractHex (DWORD* value, char* getPtr)
  99. {
  100. DWORD num;
  101. DWORD digit;
  102. BYTE c;
  103. while (*getPtr == ' ') getPtr++;
  104. num = 0;
  105. for (;;) {
  106. c = *getPtr;
  107. if ((c >= '0') && (c <= '9')) digit = (DWORD)(c - '0');
  108. else if ((c >= 'A') && (c <= 'F')) digit = (DWORD)(c - 'A' + 10);
  109. else if ((c >= 'a') && (c <= 'f')) digit = (DWORD)(c - 'a' + 10);
  110. else break;
  111. num <<= 4;
  112. num += digit;
  113. getPtr++;
  114. } /* for */
  115. *value = num;
  116. return getPtr;
  117. } /* ExtractHex */
  118. static char* ExtractDecimal (DWORD* value, char* getPtr)
  119. {
  120. DWORD num;
  121. DWORD digit;
  122. BYTE c;
  123. while (*getPtr == ' ') getPtr++;
  124. num = 0;
  125. for (;;) {
  126. c = *getPtr;
  127. if ((c >= '0') && (c <= '9')) digit = (DWORD)(c - '0');
  128. else break;
  129. num *= 10;
  130. num += digit;
  131. getPtr++;
  132. } /* for */
  133. *value = num;
  134. return getPtr;
  135. } /* ExtractDecimal */
  136. static void ExtractNumber (DWORD* value, char* getPtr)
  137. {
  138. BOOL neg = FALSE;;
  139. while (*getPtr == ' ') getPtr++;
  140. if (*getPtr == '-') {
  141. neg = TRUE;
  142. getPtr++;
  143. } /* if */
  144. if ((*getPtr == '0') && ((*(getPtr+1) == 'x') || (*(getPtr+1) == 'X'))) {
  145. getPtr +=2;
  146. (void)ExtractHex(value, getPtr);
  147. } /* if */
  148. else {
  149. (void)ExtractDecimal(value, getPtr);
  150. } /* else */
  151. if (neg) *value = -(*value);
  152. } /* ExtractNumber */
  153. static BYTE* ExtractWord(WORD* value, BYTE* buffer)
  154. {
  155. WORD x;
  156. x = (WORD)*buffer++;
  157. x = (x<<8) + (WORD)*buffer++;
  158. *value = x;
  159. return buffer;
  160. } /* ExtractWord */
  161. static BYTE* ExtractLong(DWORD* value, BYTE* buffer)
  162. {
  163. DWORD x;
  164. x = (DWORD)*buffer++;
  165. x = (x<<8) + (DWORD)*buffer++;
  166. x = (x<<8) + (DWORD)*buffer++;
  167. x = (x<<8) + (DWORD)*buffer++;
  168. *value = x;
  169. return buffer;
  170. } /* ExtractLong */
  171. static BYTE* ExtractBlock(WORD count, BYTE* data, BYTE* buffer)
  172. {
  173. while (count--) *data++ = *buffer++;
  174. return buffer;
  175. } /* ExtractBlock */
  176. static char* WriteHex(char* pa, BYTE value, WORD* pCheckSum)
  177. {
  178. WORD temp;
  179. static char ByteToHex[] = "0123456789ABCDEF";
  180. *pCheckSum += value;
  181. temp = value / 16;
  182. *pa++ = ByteToHex[temp];
  183. temp = value % 16;
  184. *pa++ = ByteToHex[temp];
  185. return pa;
  186. }
  187. static char* BuildSRecord(char* pa, WORD sType, DWORD addr,
  188. const BYTE* data, int nCount)
  189. {
  190. WORD addrLen;
  191. WORD sRLen;
  192. WORD checkSum;
  193. WORD i;
  194. switch (sType) {
  195. case 0:
  196. case 1:
  197. case 9:
  198. addrLen = 2;
  199. break;
  200. case 2:
  201. case 8:
  202. addrLen = 3;
  203. break;
  204. case 3:
  205. case 7:
  206. addrLen = 4;
  207. break;
  208. default:
  209. return pa;
  210. } /* switch */
  211. *pa++ = 'S';
  212. *pa++ = (char)(sType + '0');
  213. sRLen = addrLen + nCount + 1;
  214. checkSum = 0;
  215. pa = WriteHex(pa, (BYTE)sRLen, &checkSum);
  216. /* Write address field */
  217. for (i = 1; i <= addrLen; i++) {
  218. pa = WriteHex(pa, (BYTE)(addr >> (8 * (addrLen - i))), &checkSum);
  219. } /* for */
  220. /* Write code/data fields */
  221. for (i = 0; i < nCount; i++) {
  222. pa = WriteHex(pa, *data++, &checkSum);
  223. } /* for */
  224. /* Write checksum field */
  225. checkSum = ~checkSum;
  226. pa = WriteHex(pa, (BYTE)checkSum, &checkSum);
  227. *pa++ = '\0';
  228. return pa;
  229. }
  230. static void ConvertELF(char* fileName, DWORD loadOffset)
  231. {
  232. FILE* file;
  233. int i;
  234. int rxCount;
  235. BYTE rxBlock[1024];
  236. DWORD loadSize;
  237. DWORD firstAddr;
  238. DWORD loadAddr;
  239. DWORD loadDiff = 0;
  240. Elf32_Ehdr elfHeader;
  241. Elf32_Shdr sectHeader[32];
  242. BYTE* getPtr;
  243. char srecLine[128];
  244. char *hdr_name;
  245. /* open file */
  246. if ((file = fopen(fileName,"rb")) == NULL) {
  247. fprintf (stderr, "Can't open %s: %s\n", fileName, strerror(errno));
  248. return;
  249. } /* if */
  250. /* read ELF header */
  251. rxCount = fread(rxBlock, 1, sizeof elfHeader, file);
  252. getPtr = ExtractBlock(sizeof elfHeader.e_ident, elfHeader.e_ident, rxBlock);
  253. getPtr = ExtractWord(&elfHeader.e_type, getPtr);
  254. getPtr = ExtractWord(&elfHeader.e_machine, getPtr);
  255. getPtr = ExtractLong((DWORD *)&elfHeader.e_version, getPtr);
  256. getPtr = ExtractLong((DWORD *)&elfHeader.e_entry, getPtr);
  257. getPtr = ExtractLong((DWORD *)&elfHeader.e_phoff, getPtr);
  258. getPtr = ExtractLong((DWORD *)&elfHeader.e_shoff, getPtr);
  259. getPtr = ExtractLong((DWORD *)&elfHeader.e_flags, getPtr);
  260. getPtr = ExtractWord(&elfHeader.e_ehsize, getPtr);
  261. getPtr = ExtractWord(&elfHeader.e_phentsize, getPtr);
  262. getPtr = ExtractWord(&elfHeader.e_phnum, getPtr);
  263. getPtr = ExtractWord(&elfHeader.e_shentsize, getPtr);
  264. getPtr = ExtractWord(&elfHeader.e_shnum, getPtr);
  265. getPtr = ExtractWord(&elfHeader.e_shstrndx, getPtr);
  266. if ( (rxCount != sizeof elfHeader)
  267. || (elfHeader.e_ident[0] != ELFMAG0)
  268. || (elfHeader.e_ident[1] != ELFMAG1)
  269. || (elfHeader.e_ident[2] != ELFMAG2)
  270. || (elfHeader.e_ident[3] != ELFMAG3)
  271. || (elfHeader.e_type != ET_EXEC)
  272. ) {
  273. fclose(file);
  274. fprintf (stderr, "*** illegal file format\n");
  275. return;
  276. } /* if */
  277. /* read all section headers */
  278. fseek(file, elfHeader.e_shoff, SEEK_SET);
  279. for (i = 0; i < elfHeader.e_shnum; i++) {
  280. rxCount = fread(rxBlock, 1, sizeof sectHeader[0], file);
  281. getPtr = ExtractLong((DWORD *)&sectHeader[i].sh_name, rxBlock);
  282. getPtr = ExtractLong((DWORD *)&sectHeader[i].sh_type, getPtr);
  283. getPtr = ExtractLong((DWORD *)&sectHeader[i].sh_flags, getPtr);
  284. getPtr = ExtractLong((DWORD *)&sectHeader[i].sh_addr, getPtr);
  285. getPtr = ExtractLong((DWORD *)&sectHeader[i].sh_offset, getPtr);
  286. getPtr = ExtractLong((DWORD *)&sectHeader[i].sh_size, getPtr);
  287. getPtr = ExtractLong((DWORD *)&sectHeader[i].sh_link, getPtr);
  288. getPtr = ExtractLong((DWORD *)&sectHeader[i].sh_info, getPtr);
  289. getPtr = ExtractLong((DWORD *)&sectHeader[i].sh_addralign, getPtr);
  290. getPtr = ExtractLong((DWORD *)&sectHeader[i].sh_entsize, getPtr);
  291. if (rxCount != sizeof sectHeader[0]) {
  292. fclose(file);
  293. fprintf (stderr, "*** illegal file format\n");
  294. return;
  295. } /* if */
  296. } /* for */
  297. if ((hdr_name = strrchr(fileName, '/')) == NULL) {
  298. hdr_name = fileName;
  299. } else {
  300. ++hdr_name;
  301. }
  302. /* write start record */
  303. (void)BuildSRecord(srecLine, 0, 0, (BYTE *)hdr_name, strlen(hdr_name));
  304. printf("%s\r\n",srecLine);
  305. /* write data records */
  306. firstAddr = ~0;
  307. loadAddr = 0;
  308. for (i = 0; i < elfHeader.e_shnum; i++) {
  309. if ( (sectHeader[i].sh_type == SHT_PROGBITS)
  310. && (sectHeader[i].sh_size != 0)
  311. ) {
  312. loadSize = sectHeader[i].sh_size;
  313. if (sectHeader[i].sh_flags != 0) {
  314. loadAddr = sectHeader[i].sh_addr;
  315. loadDiff = loadAddr - sectHeader[i].sh_offset;
  316. } /* if */
  317. else {
  318. loadAddr = sectHeader[i].sh_offset + loadDiff;
  319. } /* else */
  320. if (loadAddr < firstAddr)
  321. firstAddr = loadAddr;
  322. /* build s-records */
  323. loadSize = sectHeader[i].sh_size;
  324. fseek(file, sectHeader[i].sh_offset, SEEK_SET);
  325. while (loadSize) {
  326. rxCount = fread(rxBlock, 1, (loadSize > 32) ? 32 : loadSize, file);
  327. if (rxCount < 0) {
  328. fclose(file);
  329. fprintf (stderr, "*** illegal file format\n");
  330. return;
  331. } /* if */
  332. (void)BuildSRecord(srecLine, 3, loadAddr + loadOffset, rxBlock, rxCount);
  333. loadSize -= rxCount;
  334. loadAddr += rxCount;
  335. printf("%s\r\n",srecLine);
  336. } /* while */
  337. } /* if */
  338. } /* for */
  339. /* add end record */
  340. (void)BuildSRecord(srecLine, 7, firstAddr + loadOffset, 0, 0);
  341. printf("%s\r\n",srecLine);
  342. fclose(file);
  343. } /* ConvertELF */
  344. /*************************************************************************
  345. | MAIN
  346. |*************************************************************************/
  347. int main( int argc, char *argv[ ])
  348. {
  349. DWORD offset;
  350. if (argc == 2) {
  351. ConvertELF(argv[1], 0);
  352. } /* if */
  353. else if ((argc == 4) && (strcmp(argv[1], "-o") == 0)) {
  354. ExtractNumber(&offset, argv[2]);
  355. ConvertELF(argv[3], offset);
  356. } /* if */
  357. else {
  358. fprintf (stderr, "Usage: img2srec [-o offset] <image>\n");
  359. } /* if */
  360. return 0;
  361. } /* main */