Blame view
tools/img2srec.c
9.73 KB
89752b9b5 Initial revision |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
/************************************************************************* | 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 |*************************************************************************/ |
375660907 compiler.h: unify... |
54 |
#include "os_support.h" |
fd66066ee img2srec: use sta... |
55 |
#include <stdbool.h> |
89752b9b5 Initial revision |
56 57 58 59 60 61 62 63 |
#include <stddef.h> #include <stdio.h> #include <stdlib.h> #include <ctype.h> #include <string.h> #include <elf.h> #include <unistd.h> #include <errno.h> |
89752b9b5 Initial revision |
64 |
/************************************************************************* |
89752b9b5 Initial revision |
65 66 |
| FUNCTIONS |*************************************************************************/ |
fd66066ee img2srec: use sta... |
67 |
static char* ExtractHex (uint32_t* value, char* getPtr) |
89752b9b5 Initial revision |
68 |
{ |
fd66066ee img2srec: use sta... |
69 70 71 |
uint32_t num; uint32_t digit; uint8_t c; |
89752b9b5 Initial revision |
72 73 74 75 76 |
while (*getPtr == ' ') getPtr++; num = 0; for (;;) { c = *getPtr; |
fd66066ee img2srec: use sta... |
77 78 79 |
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); |
89752b9b5 Initial revision |
80 81 82 83 84 85 86 87 |
else break; num <<= 4; num += digit; getPtr++; } /* for */ *value = num; return getPtr; } /* ExtractHex */ |
fd66066ee img2srec: use sta... |
88 |
static char* ExtractDecimal (uint32_t* value, char* getPtr) |
89752b9b5 Initial revision |
89 |
{ |
fd66066ee img2srec: use sta... |
90 91 92 |
uint32_t num; uint32_t digit; uint8_t c; |
89752b9b5 Initial revision |
93 94 95 96 97 |
while (*getPtr == ' ') getPtr++; num = 0; for (;;) { c = *getPtr; |
fd66066ee img2srec: use sta... |
98 |
if ((c >= '0') && (c <= '9')) digit = (uint32_t)(c - '0'); |
89752b9b5 Initial revision |
99 100 101 102 103 104 105 106 |
else break; num *= 10; num += digit; getPtr++; } /* for */ *value = num; return getPtr; } /* ExtractDecimal */ |
fd66066ee img2srec: use sta... |
107 |
static void ExtractNumber (uint32_t* value, char* getPtr) |
89752b9b5 Initial revision |
108 |
{ |
fd66066ee img2srec: use sta... |
109 |
bool neg = false;; |
89752b9b5 Initial revision |
110 111 112 |
while (*getPtr == ' ') getPtr++; if (*getPtr == '-') { |
fd66066ee img2srec: use sta... |
113 |
neg = true; |
89752b9b5 Initial revision |
114 115 116 117 118 119 120 121 122 123 124 |
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 */ |
fd66066ee img2srec: use sta... |
125 |
static uint8_t* ExtractWord(uint16_t* value, uint8_t* buffer) |
89752b9b5 Initial revision |
126 |
{ |
fd66066ee img2srec: use sta... |
127 128 129 |
uint16_t x; x = (uint16_t)*buffer++; x = (x<<8) + (uint16_t)*buffer++; |
89752b9b5 Initial revision |
130 131 132 |
*value = x; return buffer; } /* ExtractWord */ |
fd66066ee img2srec: use sta... |
133 |
static uint8_t* ExtractLong(uint32_t* value, uint8_t* buffer) |
89752b9b5 Initial revision |
134 |
{ |
fd66066ee img2srec: use sta... |
135 136 137 138 139 |
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++; |
89752b9b5 Initial revision |
140 141 142 |
*value = x; return buffer; } /* ExtractLong */ |
fd66066ee img2srec: use sta... |
143 |
static uint8_t* ExtractBlock(uint16_t count, uint8_t* data, uint8_t* buffer) |
89752b9b5 Initial revision |
144 145 146 147 |
{ while (count--) *data++ = *buffer++; return buffer; } /* ExtractBlock */ |
fd66066ee img2srec: use sta... |
148 |
static char* WriteHex(char* pa, uint8_t value, uint16_t* pCheckSum) |
89752b9b5 Initial revision |
149 |
{ |
fd66066ee img2srec: use sta... |
150 |
uint16_t temp; |
89752b9b5 Initial revision |
151 152 153 154 155 156 157 158 159 160 |
static char ByteToHex[] = "0123456789ABCDEF"; *pCheckSum += value; temp = value / 16; *pa++ = ByteToHex[temp]; temp = value % 16; *pa++ = ByteToHex[temp]; return pa; } |
fd66066ee img2srec: use sta... |
161 162 |
static char* BuildSRecord(char* pa, uint16_t sType, uint32_t addr, const uint8_t* data, int nCount) |
89752b9b5 Initial revision |
163 |
{ |
fd66066ee img2srec: use sta... |
164 165 166 167 |
uint16_t addrLen; uint16_t sRLen; uint16_t checkSum; uint16_t i; |
89752b9b5 Initial revision |
168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 |
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; |
fd66066ee img2srec: use sta... |
191 |
pa = WriteHex(pa, (uint8_t)sRLen, &checkSum); |
89752b9b5 Initial revision |
192 193 194 |
/* Write address field */ for (i = 1; i <= addrLen; i++) { |
fd66066ee img2srec: use sta... |
195 |
pa = WriteHex(pa, (uint8_t)(addr >> (8 * (addrLen - i))), &checkSum); |
89752b9b5 Initial revision |
196 197 198 199 200 201 202 203 204 |
} /* for */ /* Write code/data fields */ for (i = 0; i < nCount; i++) { pa = WriteHex(pa, *data++, &checkSum); } /* for */ /* Write checksum field */ checkSum = ~checkSum; |
fd66066ee img2srec: use sta... |
205 |
pa = WriteHex(pa, (uint8_t)checkSum, &checkSum); |
89752b9b5 Initial revision |
206 207 208 |
*pa++ = '\0'; return pa; } |
fd66066ee img2srec: use sta... |
209 |
static void ConvertELF(char* fileName, uint32_t loadOffset) |
89752b9b5 Initial revision |
210 211 212 213 |
{ FILE* file; int i; int rxCount; |
fd66066ee img2srec: use sta... |
214 215 216 217 218 |
uint8_t rxBlock[1024]; uint32_t loadSize; uint32_t firstAddr; uint32_t loadAddr; uint32_t loadDiff = 0; |
89752b9b5 Initial revision |
219 220 |
Elf32_Ehdr elfHeader; Elf32_Shdr sectHeader[32]; |
fd66066ee img2srec: use sta... |
221 |
uint8_t* getPtr; |
89752b9b5 Initial revision |
222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 |
char srecLine[128]; char *hdr_name; /* open file */ if ((file = fopen(fileName,"rb")) == NULL) { fprintf (stderr, "Can't open %s: %s ", 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); |
fd66066ee img2srec: use sta... |
238 239 240 241 242 |
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); |
89752b9b5 Initial revision |
243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 |
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 "); 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); |
fd66066ee img2srec: use sta... |
266 267 268 269 270 271 272 273 274 275 |
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); |
89752b9b5 Initial revision |
276 277 278 279 280 281 282 283 284 285 286 287 288 289 |
if (rxCount != sizeof sectHeader[0]) { fclose(file); fprintf (stderr, "*** illegal file format "); return; } /* if */ } /* for */ if ((hdr_name = strrchr(fileName, '/')) == NULL) { hdr_name = fileName; } else { ++hdr_name; } /* write start record */ |
fd66066ee img2srec: use sta... |
290 |
(void)BuildSRecord(srecLine, 0, 0, (uint8_t *)hdr_name, strlen(hdr_name)); |
89752b9b5 Initial revision |
291 292 293 294 295 296 297 298 |
printf("%s\r ",srecLine); /* write data records */ firstAddr = ~0; loadAddr = 0; for (i = 0; i < elfHeader.e_shnum; i++) { if ( (sectHeader[i].sh_type == SHT_PROGBITS) |
8bde7f776 * Code cleanup: |
299 300 |
&& (sectHeader[i].sh_size != 0) ) { |
89752b9b5 Initial revision |
301 302 |
loadSize = sectHeader[i].sh_size; if (sectHeader[i].sh_flags != 0) { |
8bde7f776 * Code cleanup: |
303 304 |
loadAddr = sectHeader[i].sh_addr; loadDiff = loadAddr - sectHeader[i].sh_offset; |
89752b9b5 Initial revision |
305 306 |
} /* if */ else { |
8bde7f776 * Code cleanup: |
307 |
loadAddr = sectHeader[i].sh_offset + loadDiff; |
89752b9b5 Initial revision |
308 309 310 |
} /* else */ if (loadAddr < firstAddr) |
8bde7f776 * Code cleanup: |
311 |
firstAddr = loadAddr; |
89752b9b5 Initial revision |
312 313 314 315 316 |
/* build s-records */ loadSize = sectHeader[i].sh_size; fseek(file, sectHeader[i].sh_offset, SEEK_SET); while (loadSize) { |
8bde7f776 * Code cleanup: |
317 318 319 320 321 322 323 324 325 326 327 328 |
rxCount = fread(rxBlock, 1, (loadSize > 32) ? 32 : loadSize, file); if (rxCount < 0) { fclose(file); fprintf (stderr, "*** illegal file format "); return; } /* if */ (void)BuildSRecord(srecLine, 3, loadAddr + loadOffset, rxBlock, rxCount); loadSize -= rxCount; loadAddr += rxCount; printf("%s\r ",srecLine); |
89752b9b5 Initial revision |
329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 |
} /* while */ } /* if */ } /* for */ /* add end record */ (void)BuildSRecord(srecLine, 7, firstAddr + loadOffset, 0, 0); printf("%s\r ",srecLine); fclose(file); } /* ConvertELF */ /************************************************************************* | MAIN |*************************************************************************/ int main( int argc, char *argv[ ]) { |
fd66066ee img2srec: use sta... |
347 |
uint32_t offset; |
89752b9b5 Initial revision |
348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 |
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> "); } /* if */ return 0; } /* main */ |