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