Updated changes for GA RC1
[keystone-rtos/mcsdk-tools.git] / boot_loader / examples / ethernet / Utilities / bootpacket.c
1 /******************************************************************************
2  * Copyright (c) 2011 Texas Instruments Incorporated - http://www.ti.com
3  *
4  *  Redistribution and use in source and binary forms, with or without
5  *  modification, are permitted provided that the following conditions
6  *  are met:
7  *
8  *    Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  *
11  *    Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the
14  *    distribution.
15  *
16  *    Neither the name of Texas Instruments Incorporated nor the names of
17  *    its contributors may be used to endorse or promote products derived
18  *    from this software without specific prior written permission.
19  *
20  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23  *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24  *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25  *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26  *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  *
32  *****************************************************************************/
34 /* A simple utility program to convert a boot table to Ethernet boot format */
35 /* Version: 0.3 */
38 #include <stdio.h>
39 #include <string.h>
40 #include <malloc.h>
41 #include "bootpacket.h"
43 unsigned int line=0;
47 void writeheader(FILE *s, INT16* pdata)
48 {
49         int i;
51         for (i = 0; i < TOTAL_HEADER_LEN/2; i++)
52                 fprintf (s, "0x%04X\n",(unsigned short int)(*pdata++));
53 }
56 void writeboottable(FILE *s, INT16* pdata, int size)
57 {
58         int i;
60         for (i = 0; i < size; i++)
61                 fprintf (s, "0x%04X\n",(unsigned short int)(*pdata++));
62 }
65 void  stripLine (FILE *s)
66 {
67   char iline[132];
69   fgets (iline, 131, s);
71 }
74 int asciiByte (unsigned char c)
75 {
76   if ((c >= '0') && (c <= '9'))
77     return (1);
79   if ((c >= 'A') && (c <= 'F'))
80     return (1);
82   return (0);
83 }
86 int toNum (unsigned char c)
87 {
88   if ((c >= '0') && (c <= '9'))
89     return (c - '0');
91   return (c - 'A' + 10);
93 }
95 int toNumMAC (unsigned char c)
96 {
97   if ((c >= '0') && (c <= '9'))
98      return(c - '0');
100   else  if ((c >= 'A') && (c <= 'F'))
101           return(c -'A' + 10);
103   else  if ((c >= 'a') && (c <= 'f'))
104           return(c - 'a' + 10);
106   else if(c == ':')
107           return(100);
109   return(200);
114 /* Read the file size in bytes*/
115 int getFileSize (FILE *s)
117   unsigned char x, y;
118   unsigned int byteCount = 0;
120   /* Strip the 1st two lines */
121   stripLine (s);
122   stripLine (s);
124   for (;;) {
126     /* read the 1st ascii char */
127     do  {
128       x = fgetc (s);
129       if (x == (unsigned char)EOF)
130         return (byteCount);
132     } while (!asciiByte(x));
134     /* Read the next ascii char */
135     y = fgetc (s);
136     if (y == (unsigned char)EOF)
137       return (byteCount);
138     if (asciiByte(y))
139                 byteCount++;
140   }
145 int getDataIn(FILE *s, int size_bytes, unsigned short int *output)
147   int i;
148   unsigned char x, y;
149   unsigned char c[2];
151   for(i= 0; i< size_bytes/2; i++) {
152           c[0] = 0;
153           c[1] = 0;
155              /* read the 1st ascii char */
156             do  {
157                   x = fgetc (s);
158                   if (x == (unsigned char)EOF) {
159                         printf("file parsing error\n");
160                         return(-1);
161                   }
162             } while (!asciiByte(x));
165                 /* Read the next ascii char */
166                 y = fgetc (s);
167                 if (y == (unsigned char)EOF) {
168                         printf("file parsing error\n");
169                         return(-1);
170                 }
172         if (asciiByte(y)) {
173                         c[0] =  (toNum(x) << 4) | toNum (y);
174                 }
176             do  {
177                   x = fgetc (s);
178                   if (x == (unsigned char)EOF) {
179                         printf("file parsing error\n");
180                         return(-1);
181                   }
182             } while (!asciiByte(x));
185                 /* Read the next ascii char */
186                 y = fgetc (s);
187                 if (y == (unsigned char)EOF) {
188                         printf("file parsing error\n");
189                         return(-1);
190                 }
192         if (asciiByte(y)) {
193                         c[1] =  (toNum(x) << 4) | toNum (y);
194                 }
196                 *output++ = (c[0] << 8) | c[1] ;
197                 line++;
198   }
199    return(0);
204 UINT16 bootmiscOnesComplementAdd (UINT16 value1, UINT16 value2)
206   UINT32 result;
208   result = (UINT32)value1 + (UINT32)value2;
210   result = (result >> 16) + (result & 0xFFFF); /* add in carry   */
211   result += (result >> 16);                    /* maybe one more */
212   return (UINT16)result;
217 /*  Description: Calculate an Internet style one's complement checksum */
218  UINT16 bootmiscOnesComplementChksum (UINT16 base, UINT16 *p_data, UINT16 len)
220   UINT16 chksum = base;
222   while (len > 0)
223   {
224     chksum = bootmiscOnesComplementAdd(chksum,*p_data);
225     p_data++;
226     len--;
227   }
228   return ((unsigned short) ~chksum);
233 /*
234   Input file format: boot table in big endian format
236   Output file format:
238         1st line: CCS data format
239         2nd line: 0x0000
240         3rd line: length of first packet in bytes, length counts not include itself
241         .......
242         first packet
243         .......
245         0xEA00
246         0x0000
247         length of the second packet in bytes, length counts not include itself
248         .......
249         second packet
250         .......
253         0xEA00
254         0x0000
255         length of the other packet in bytes, length counts not include itself
256         .......
257         other packets
258         .......
260         0xEA00
261         0X0000
262         0X0000: end of the file
263 */
265 struct BootPacket data;
268 void main (int argc, char *argv[])
270         UINT32 j;
271         UINT32 inSize;
272         UINT32 counter;
273         UINT16 UDPchecksum;
274         FILE *strin, *strout;
275         UINT32 temp;
276         unsigned int MACaddr[6];
278          /* Arg check */
279         if (argc <3 || argc> 5)  {
280                 fprintf (stderr, "usage: %s infile outfile\n\n", argv[0]);
281                 fprintf (stderr, "To generates the same result as bt-pkt.exe\n");
282                 fprintf (stderr, "usage: %s infile outfile btpkt\n\n", argv[0]);
283                 fprintf (stderr, "To use your own MAC address\n");
284                 fprintf (stderr, "usage: %s infile outfile dstMAC srcMAC\n", argv[0]);
285                 return;
286         }
288         strin = fopen(argv[1],"rb");
289         if(strin == NULL){
290             fprintf (stderr, "%s: Could not open file %s for reading\n", argv[0], argv[1]);
291                 return;
292         }
294         /* Get the file size of data file */
295         inSize = getFileSize (strin);
296         printf("File size = %d bytes.\n",inSize);
297         fclose (strin);
298         strin = fopen(argv[1],"rb");
299     /* Strip the 1st two lines */
300     stripLine (strin);
301     stripLine (strin);
303         strout = fopen(argv[2],"w");
304         if(strout == NULL) {
305             fprintf (stderr, "%s error: Could not open output file %s\n", argv[0], argv[2]);
306                 return;
307         }
310         // MAC header, 14 bytes
311         if(argc == 5) {
313                 /* get destination MAC address */
314         if((sscanf(argv[3],"%02x-%02x-%02x-%02x-%02x-%02x",&MACaddr[0],&MACaddr[1], \
315                         &MACaddr[2],&MACaddr[3],&MACaddr[4],&MACaddr[5])!=6) || \
316                         (MACaddr[0] < 0 || MACaddr[0] > 255 || \
317                         MACaddr[1] < 0 || MACaddr[1] > 255 || \
318                         MACaddr[2] < 0 || MACaddr[2] > 255 || \
319                         MACaddr[3] < 0 || MACaddr[3] > 255 || \
320                         MACaddr[4] < 0 || MACaddr[4] > 255 || \
321                         MACaddr[5] < 0 || MACaddr[5] > 255) ) {
323                         printf("Error in dstMAC address\n");
324                         fclose(strin);
325                         fclose(strout);
326                         return;
327                 }
329                 data.dstMAC_H = (unsigned short)(MACaddr[0]<<8 | MACaddr[1]);
330                 data.dstMAC_M = (unsigned short)(MACaddr[2]<<8 | MACaddr[3]);
331                 data.dstMAC_L = (unsigned short)(MACaddr[4]<<8 | MACaddr[5]);
333                 /* get source MAC address */
334        if((sscanf(argv[4],"%02x-%02x-%02x-%02x-%02x-%02x",&MACaddr[0],&MACaddr[1], \
335                         &MACaddr[2],&MACaddr[3],&MACaddr[4],&MACaddr[5])!=6) || \
336                         (MACaddr[0] < 0 || MACaddr[0] > 255 || \
337                         MACaddr[1] < 0 || MACaddr[1] > 255 || \
338                         MACaddr[2] < 0 || MACaddr[2] > 255 || \
339                         MACaddr[3] < 0 || MACaddr[3] > 255 || \
340                         MACaddr[4] < 0 || MACaddr[4] > 255 || \
341                         MACaddr[5] < 0 || MACaddr[5] > 255) ) {
343                         printf("Error in srcMAC address\n");
344                         fclose(strin);
345                         fclose(strout);
346                         return;
347                 }
349                 data.srcMAC_H = (unsigned short)(MACaddr[0]<<8 | MACaddr[1]);
350                 data.srcMAC_M = (unsigned short)(MACaddr[2]<<8 | MACaddr[3]);
351                 data.srcMAC_L = (unsigned short)(MACaddr[4]<<8 | MACaddr[5]);
353         } else {  /* use default MAC address */
354                 data.dstMAC_H = (unsigned short)DST_MAC_H;
355                 data.dstMAC_M = (unsigned short)DST_MAC_M;
356                 data.dstMAC_L = (unsigned short)DST_MAC_L;
357                 data.srcMAC_H = (unsigned short)SRC_MAC_H;
358                 data.srcMAC_M = (unsigned short)SRC_MAC_M;
359                 data.srcMAC_L = (unsigned short)SRC_MAC_L;
360         }
361         data.EtherType = ETHER_TYPE_IP;
363         // IP header, 20 bytes
364         data.VerTOS = 0x4500;
365         data.IPlength = 0x0000;
366         data.ID = 0x4567;
367         data.FlagsFrag = 0x0000;
368         data.TTLProtocol = 0x1000 | IP_TYPE_UDP;
369         data.IPchecksum = 0x0000;
370         data.srcIPAddr_H = (unsigned short)SRC_IP_ADDR_H;
371         data.srcIPAddr_L = (unsigned short)SRC_IP_ADDR_L;
372         data.dstIPAddr_H = (unsigned short)DST_IP_ADDR_H;
373         data.dstIPAddr_L = (unsigned short)DST_IP_ADDR_L;
375         // UDP header, 8 bytes
376         if(argc != 4) {
377                 data.srcPort = (unsigned short)UDP_SRC_PORT;
378         } else {
379                 data.srcPort = (unsigned short)UDP_SRC_PORT_BTPKT;
380         }
381         data.dstPort = (unsigned short)UDP_DST_PORT;
382         data.UDPlength = 0x0000;
383         data.UDPchecksum = 0x0000;
385         // Payload header, 4 bytes
386         data.MagicNo = MAGICNO;
387         data.SeqNo = 0x100;
389         memset(&data.BootTable,0, sizeof(data.BootTable));
391         counter = inSize / MAX_BOOTTBL_LEN;  // calculate how many packets
393         // If there is only one packet
394         if(counter <=1) {
395                 data.UDPlength = UDP_HEADER_LEN + BOOTTBL_HEADER_LEN + inSize;
397                 data.IPlength = data.UDPlength + IP_HEADER_LEN;
398                 data.IPchecksum=bootmiscOnesComplementChksum(0,&data.VerTOS,IP_HEADER_LEN/2);
400                 if(getDataIn(strin, inSize, data.BootTable)!=0) {
401                         fclose(strin);
402                         fclose(strout);
403                         return;
404                 }
406                 UDPchecksum = bootmiscOnesComplementAdd(IP_TYPE_UDP, data.UDPlength);
407                 data.UDPchecksum=bootmiscOnesComplementChksum(UDPchecksum, &data.srcIPAddr_H,\
408                                                    (UINT16)((4+4+UDP_HEADER_LEN+BOOTTBL_HEADER_LEN+inSize)/2));
410                 temp = BGN_BYTE_LEN+TOTAL_HEADER_LEN+inSize+END_BYTE_LEN;
412                 if(argc != 4) {
413                         fprintf(strout,"1651 1 890000 1 %x\n",temp/2); // CCS format
414                 } else {
415                         fprintf(strout,"1651 1 10000 1 %x\n",temp/2); // CCS format
416                 }
418                 fprintf (strout, "0x%04X\n",0x0000);
419                 fprintf (strout, "0x%04X\n",TOTAL_HEADER_LEN+inSize); /* length in bytes */
421                 writeheader(strout, &data.dstMAC_H);
423                 writeboottable(strout,&data.BootTable[0],inSize/2);
425                 fprintf (strout, "0x%04X\n",(unsigned short)(SYMBOL));
426                 fprintf (strout, "0x%04X\n",0x0000);
427                 fprintf (strout, "0x%04X\n",0x0000);
429         } else { // If there are many packets
431                 temp = BGN_BYTE_LEN + (counter+1)*(TOTAL_HEADER_LEN + END_BYTE_LEN) + inSize;
433                 if(argc != 4) {
434                         fprintf(strout,"1651 1 890000 1 %x\n",temp/2); // CCS format
435                 } else {
436                         fprintf(strout,"1651 1 10000 1 %x\n",temp/2); // CCS format
437                 }
439                 fprintf (strout, "0x%04X\n",0x0000);
440                 fprintf (strout, "0x%04X\n",TOTAL_HEADER_LEN+MAX_BOOTTBL_LEN); /* length in bytes */
442                 data.UDPlength = UDP_HEADER_LEN + BOOTTBL_HEADER_LEN + MAX_BOOTTBL_LEN;
443                 data.IPlength = data.UDPlength + IP_HEADER_LEN;
444                 UDPchecksum = bootmiscOnesComplementAdd(IP_TYPE_UDP, data.UDPlength);
446                 for(j=0; j<counter; j++) { // For first and middle packets
448                                 data.IPchecksum=bootmiscOnesComplementChksum(0,&data.VerTOS,IP_HEADER_LEN/2);
450                                 if(getDataIn(strin, MAX_BOOTTBL_LEN, data.BootTable)!=0) {
451                                         fclose(strin);
452                                         fclose(strout);
453                                         return;
454                                 };
456                                 data.UDPchecksum=bootmiscOnesComplementChksum(UDPchecksum, &data.srcIPAddr_H,\
457                                                          (UINT16)((4+4+UDP_HEADER_LEN+BOOTTBL_HEADER_LEN+MAX_BOOTTBL_LEN)/2));
459                                 writeheader(strout, &data.dstMAC_H);
460                                 writeboottable(strout,&data.BootTable[0],MAX_BOOTTBL_LEN/2);
462                                 fprintf (strout, "0x%04X\n",(unsigned short)(SYMBOL));
463                                 fprintf (strout, "0x%04X\n",0x0000);
465                                 if(j != counter-1) fprintf (strout,"0x%04X\n",TOTAL_HEADER_LEN+MAX_BOOTTBL_LEN);
467                                 // make ready for the next packet
468                                 data.ID++;
469                                 data.SeqNo++;
471                                 if(data.SeqNo >= 0x200) {
472                                         data.SeqNo = 0x100;
473                                 }
475                                 data.IPchecksum = 0x0000;
476                                 data.UDPchecksum = 0x0000;
478                 }
480                 // For the last packet
481                 temp = counter*MAX_BOOTTBL_LEN;
482                 counter = inSize - temp; // how many bytes remained
483                 fprintf (strout,"0x%04X\n",TOTAL_HEADER_LEN+counter);
485                 data.UDPlength = UDP_HEADER_LEN + BOOTTBL_HEADER_LEN + counter;
487                 data.IPlength = data.UDPlength + IP_HEADER_LEN;
488                 data.IPchecksum = bootmiscOnesComplementChksum(0,&data.VerTOS,IP_HEADER_LEN/2);
490                 if(getDataIn(strin, counter, data.BootTable)!=0) {
491                         fclose(strin);
492                         fclose(strout);
493                         return;
494                 }
496                 UDPchecksum = bootmiscOnesComplementAdd(IP_TYPE_UDP, data.UDPlength);
497                 data.UDPchecksum=bootmiscOnesComplementChksum(UDPchecksum, &data.srcIPAddr_H,\
498                                                          (UINT16)((4+4+UDP_HEADER_LEN+BOOTTBL_HEADER_LEN+counter)/2));
499                 writeheader(strout, &data.dstMAC_H);
500                 writeboottable(strout,&data.BootTable[0],counter/2);
502                 fprintf (strout, "0x%04X\n",(unsigned short)(SYMBOL));
503                 fprintf (strout, "0x%04X\n",0x0000);
504                 fprintf (strout, "0x%04X\n",0x0000);
505         }
507         fclose(strin);
508         fclose(strout);