1 /*************************************************************************
2 | COPYRIGHT (c) 2000 BY ABATRON AG
3 |*************************************************************************
5 | PROJECT NAME: Linux Image to S-record Conversion Utility
6 | FILENAME : img2srec.c
10 | TARGET OS : LINUX / UNIX
13 | PROGRAMMER : Abatron / RD
16 |*************************************************************************
20 | Utility to convert a Linux Boot Image to S-record:
21 | ==================================================
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".
27 | img2srec [-o offset] image > image.srec
33 | To build the utility use GCC as follows:
35 | gcc img2srec.c -o img2srec
38 |*************************************************************************
44 | -----------------------------------------------------------
47 | 07.07.00 aba Initial release
49 |*************************************************************************/
51 /*************************************************************************
53 |*************************************************************************/
66 /*************************************************************************
68 |*************************************************************************/
73 /*************************************************************************
75 |*************************************************************************/
77 /*************************************************************************
79 |*************************************************************************/
83 typedef uint16_t WORD
;
84 typedef uint32_t DWORD
;
87 /*************************************************************************
89 |*************************************************************************/
91 /*************************************************************************
93 |*************************************************************************/
95 static char *ExtractHex(DWORD
*value
, char *getPtr
);
96 static char *ExtractDecimal(DWORD
*value
, char *getPtr
);
97 static void ExtractNumber(DWORD
*value
, char *getPtr
);
98 static BYTE
*ExtractWord(WORD
*value
, BYTE
*buffer
);
99 static BYTE
*ExtractLong(DWORD
*value
, BYTE
*buffer
);
100 static BYTE
*ExtractBlock(WORD count
, BYTE
*data
, BYTE
*buffer
);
101 static char *WriteHex(char *pa
, BYTE value
, WORD
*pCheckSum
);
102 static char *BuildSRecord(char *pa
, WORD sType
, DWORD addr
,
103 const BYTE
*data
, int nCount
);
104 static void ConvertELF(char *fileName
, DWORD loadOffset
);
105 int main(int argc
, char *argv
[]);
107 /*************************************************************************
109 |*************************************************************************/
111 static char* ExtractHex (DWORD
* value
, char* getPtr
)
117 while (*getPtr
== ' ') getPtr
++;
121 if ((c
>= '0') && (c
<= '9')) digit
= (DWORD
)(c
- '0');
122 else if ((c
>= 'A') && (c
<= 'F')) digit
= (DWORD
)(c
- 'A' + 10);
123 else if ((c
>= 'a') && (c
<= 'f')) digit
= (DWORD
)(c
- 'a' + 10);
133 static char* ExtractDecimal (DWORD
* value
, char* getPtr
)
139 while (*getPtr
== ' ') getPtr
++;
143 if ((c
>= '0') && (c
<= '9')) digit
= (DWORD
)(c
- '0');
151 } /* ExtractDecimal */
154 static void ExtractNumber (DWORD
* value
, char* getPtr
)
158 while (*getPtr
== ' ') getPtr
++;
159 if (*getPtr
== '-') {
163 if ((*getPtr
== '0') && ((*(getPtr
+1) == 'x') || (*(getPtr
+1) == 'X'))) {
165 (void)ExtractHex(value
, getPtr
);
168 (void)ExtractDecimal(value
, getPtr
);
170 if (neg
) *value
= -(*value
);
171 } /* ExtractNumber */
174 static BYTE
* ExtractWord(WORD
* value
, BYTE
* buffer
)
178 x
= (x
<<8) + (WORD
)*buffer
++;
184 static BYTE
* ExtractLong(DWORD
* value
, BYTE
* buffer
)
187 x
= (DWORD
)*buffer
++;
188 x
= (x
<<8) + (DWORD
)*buffer
++;
189 x
= (x
<<8) + (DWORD
)*buffer
++;
190 x
= (x
<<8) + (DWORD
)*buffer
++;
196 static BYTE
* ExtractBlock(WORD count
, BYTE
* data
, BYTE
* buffer
)
198 while (count
--) *data
++ = *buffer
++;
203 static char* WriteHex(char* pa
, BYTE value
, WORD
* pCheckSum
)
207 static char ByteToHex
[] = "0123456789ABCDEF";
211 *pa
++ = ByteToHex
[temp
];
213 *pa
++ = ByteToHex
[temp
];
218 static char* BuildSRecord(char* pa
, WORD sType
, DWORD addr
,
219 const BYTE
* data
, int nCount
)
245 *pa
++ = (char)(sType
+ '0');
246 sRLen
= addrLen
+ nCount
+ 1;
248 pa
= WriteHex(pa
, (BYTE
)sRLen
, &checkSum
);
250 /* Write address field */
251 for (i
= 1; i
<= addrLen
; i
++) {
252 pa
= WriteHex(pa
, (BYTE
)(addr
>> (8 * (addrLen
- i
))), &checkSum
);
255 /* Write code/data fields */
256 for (i
= 0; i
< nCount
; i
++) {
257 pa
= WriteHex(pa
, *data
++, &checkSum
);
260 /* Write checksum field */
261 checkSum
= ~checkSum
;
262 pa
= WriteHex(pa
, (BYTE
)checkSum
, &checkSum
);
268 static void ConvertELF(char* fileName
, DWORD loadOffset
)
278 Elf32_Ehdr elfHeader
;
279 Elf32_Shdr sectHeader
[32];
286 if ((file
= fopen(fileName
,"rb")) == NULL
) {
287 fprintf (stderr
, "Can't open %s: %s\n", fileName
, strerror(errno
));
291 /* read ELF header */
292 rxCount
= fread(rxBlock
, 1, sizeof elfHeader
, file
);
293 getPtr
= ExtractBlock(sizeof elfHeader
.e_ident
, elfHeader
.e_ident
, rxBlock
);
294 getPtr
= ExtractWord(&elfHeader
.e_type
, getPtr
);
295 getPtr
= ExtractWord(&elfHeader
.e_machine
, getPtr
);
296 getPtr
= ExtractLong((DWORD
*)&elfHeader
.e_version
, getPtr
);
297 getPtr
= ExtractLong((DWORD
*)&elfHeader
.e_entry
, getPtr
);
298 getPtr
= ExtractLong((DWORD
*)&elfHeader
.e_phoff
, getPtr
);
299 getPtr
= ExtractLong((DWORD
*)&elfHeader
.e_shoff
, getPtr
);
300 getPtr
= ExtractLong((DWORD
*)&elfHeader
.e_flags
, getPtr
);
301 getPtr
= ExtractWord(&elfHeader
.e_ehsize
, getPtr
);
302 getPtr
= ExtractWord(&elfHeader
.e_phentsize
, getPtr
);
303 getPtr
= ExtractWord(&elfHeader
.e_phnum
, getPtr
);
304 getPtr
= ExtractWord(&elfHeader
.e_shentsize
, getPtr
);
305 getPtr
= ExtractWord(&elfHeader
.e_shnum
, getPtr
);
306 getPtr
= ExtractWord(&elfHeader
.e_shstrndx
, getPtr
);
307 if ( (rxCount
!= sizeof elfHeader
)
308 || (elfHeader
.e_ident
[0] != ELFMAG0
)
309 || (elfHeader
.e_ident
[1] != ELFMAG1
)
310 || (elfHeader
.e_ident
[2] != ELFMAG2
)
311 || (elfHeader
.e_ident
[3] != ELFMAG3
)
312 || (elfHeader
.e_type
!= ET_EXEC
)
315 fprintf (stderr
, "*** illegal file format\n");
319 /* read all section headers */
320 fseek(file
, elfHeader
.e_shoff
, SEEK_SET
);
321 for (i
= 0; i
< elfHeader
.e_shnum
; i
++) {
322 rxCount
= fread(rxBlock
, 1, sizeof sectHeader
[0], file
);
323 getPtr
= ExtractLong((DWORD
*)§Header
[i
].sh_name
, rxBlock
);
324 getPtr
= ExtractLong((DWORD
*)§Header
[i
].sh_type
, getPtr
);
325 getPtr
= ExtractLong((DWORD
*)§Header
[i
].sh_flags
, getPtr
);
326 getPtr
= ExtractLong((DWORD
*)§Header
[i
].sh_addr
, getPtr
);
327 getPtr
= ExtractLong((DWORD
*)§Header
[i
].sh_offset
, getPtr
);
328 getPtr
= ExtractLong((DWORD
*)§Header
[i
].sh_size
, getPtr
);
329 getPtr
= ExtractLong((DWORD
*)§Header
[i
].sh_link
, getPtr
);
330 getPtr
= ExtractLong((DWORD
*)§Header
[i
].sh_info
, getPtr
);
331 getPtr
= ExtractLong((DWORD
*)§Header
[i
].sh_addralign
, getPtr
);
332 getPtr
= ExtractLong((DWORD
*)§Header
[i
].sh_entsize
, getPtr
);
333 if (rxCount
!= sizeof sectHeader
[0]) {
335 fprintf (stderr
, "*** illegal file format\n");
340 if ((hdr_name
= strrchr(fileName
, '/')) == NULL
) {
345 /* write start record */
346 (void)BuildSRecord(srecLine
, 0, 0, (BYTE
*)hdr_name
, strlen(hdr_name
));
347 printf("%s\r\n",srecLine
);
349 /* write data records */
352 for (i
= 0; i
< elfHeader
.e_shnum
; i
++) {
353 if ( (sectHeader
[i
].sh_type
== SHT_PROGBITS
)
354 && (sectHeader
[i
].sh_size
!= 0)
356 loadSize
= sectHeader
[i
].sh_size
;
357 if (sectHeader
[i
].sh_flags
!= 0) {
358 loadAddr
= sectHeader
[i
].sh_addr
;
359 loadDiff
= loadAddr
- sectHeader
[i
].sh_offset
;
362 loadAddr
= sectHeader
[i
].sh_offset
+ loadDiff
;
365 if (loadAddr
< firstAddr
)
366 firstAddr
= loadAddr
;
368 /* build s-records */
369 loadSize
= sectHeader
[i
].sh_size
;
370 fseek(file
, sectHeader
[i
].sh_offset
, SEEK_SET
);
372 rxCount
= fread(rxBlock
, 1, (loadSize
> 32) ? 32 : loadSize
, file
);
375 fprintf (stderr
, "*** illegal file format\n");
378 (void)BuildSRecord(srecLine
, 3, loadAddr
+ loadOffset
, rxBlock
, rxCount
);
381 printf("%s\r\n",srecLine
);
387 (void)BuildSRecord(srecLine
, 7, firstAddr
+ loadOffset
, 0, 0);
388 printf("%s\r\n",srecLine
);
393 /*************************************************************************
395 |*************************************************************************/
397 int main( int argc
, char *argv
[ ])
402 ConvertELF(argv
[1], 0);
404 else if ((argc
== 4) && (strcmp(argv
[1], "-o") == 0)) {
405 ExtractNumber(&offset
, argv
[2]);
406 ConvertELF(argv
[3], offset
);
409 fprintf (stderr
, "Usage: img2srec [-o offset] <image>\n");