]> git.karo-electronics.de Git - karo-tx-redboot.git/blob - packages/redboot/v2_0/src/wince.c
1afa5558b1588abe7509ca26b15ee06270eb4a75
[karo-tx-redboot.git] / packages / redboot / v2_0 / src / wince.c
1 #include <redboot.h>
2 #include <net/net.h>
3 #include CYGHWR_MEMORY_LAYOUT_H
4 #include <wince.h>
5 #include <winceinc.h>
6
7 cmd_fun do_go;
8
9 ///////////////////////////////////////////////////////////////////////////////////////////////
10 // Local macro
11
12 // Memory macro
13 #define CE_RAM_BASE                     CYGMEM_REGION_ram
14 #define CE_RAM_SIZE                     CYGMEM_REGION_ram_SIZE
15 #define CE_RAM_END                      (CE_RAM_BASE + CE_RAM_SIZE)
16 #define CE_WINCE_VRAM_BASE              0x80000000
17 #define CE_FIX_ADDRESS(a)               (((a) - CE_WINCE_VRAM_BASE) + CE_RAM_BASE)
18
19 // Bin image parse states
20 #define CE_PS_RTI_ADDR                  0
21 #define CE_PS_RTI_LEN                   1
22 #define CE_PS_E_ADDR                    2
23 #define CE_PS_E_LEN                     3
24 #define CE_PS_E_CHKSUM                  4
25 #define CE_PS_E_DATA                    5
26
27 // Min/max
28 #define CE_MIN(a, b)                    (((a) < (b)) ? (a) : (b))
29 #define CE_MAX(a, b)                    (((a) > (b)) ? (a) : (b))
30
31 // Macro string
32 #define _STRMAC(s)                      #s
33 #define STRMAC(s)                       _STRMAC(s)
34
35 ///////////////////////////////////////////////////////////////////////////////////////////////
36 // Local types
37 typedef struct {
38         unsigned int rtiPhysAddr;
39         unsigned int rtiPhysLen;
40         unsigned int ePhysAddr;
41         unsigned int ePhysLen;
42         unsigned int eChkSum;
43
44         unsigned int eEntryPoint;
45         unsigned int eRamStart;
46         unsigned int eRamLen;
47         unsigned int eDrvGlb;
48
49         unsigned char parseState;
50         unsigned int parseChkSum;
51         int parseLen;
52         unsigned char *parsePtr;
53         int secion;
54
55         int dataLen;
56         unsigned char *data;
57
58         int binLen;
59         int endOfBin;
60
61         edbg_os_config_data edbgConfig;
62 } ce_bin;
63
64 typedef struct {
65         bool verbose;
66         bool link;
67         struct sockaddr_in locAddr;
68         struct sockaddr_in srvAddrSend;
69         struct sockaddr_in srvAddrRecv;
70         bool gotJumpingRequest;
71         unsigned char secNum;
72         unsigned short blockNum;
73         int dataLen;
74         unsigned char data[516];
75 } ce_net;
76
77 ///////////////////////////////////////////////////////////////////////////////////////////////
78 // Global data
79 #ifdef CYGPKG_REDBOOT_NETWORKING
80 static ce_net g_net;
81 #endif
82 static ce_bin g_bin;
83
84 // Equotip3 specific
85 #ifdef CYGPKG_HAL_ARM_XSCALE_TRITON270_EQT32
86 #include <cyg/hal/hal_triton270.h>
87 extern EEDAT eedat;
88 #endif
89
90 ///////////////////////////////////////////////////////////////////////////////////////////////
91 // Local proto
92
93 void ce_init_bin(ce_bin *bin, unsigned char *dataBuffer);
94 int ce_parse_bin(ce_bin *bin);
95 bool ce_lookup_ep_bin(ce_bin *bin);
96 void ce_prepare_run_bin(ce_bin *bin);
97 void ce_run_bin(ce_bin *bin);
98 void ce_redboot_version(unsigned int *vhigh, unsigned int *vlow);
99
100 #ifdef CYGPKG_REDBOOT_NETWORKING
101 // Redboot network based routines
102 void ce_shell(int argc, char *argv[]);
103 void ce_init_download_link(ce_net *net, ce_bin *bin, struct sockaddr_in *host_addr, bool verbose);
104 void ce_init_edbg_link(ce_net *net);
105 int ce_send_frame(ce_net *net);
106 int ce_recv_frame(ce_net *net, int timeout);
107 int ce_send_bootme(ce_net *net);
108 int ce_send_write_ack(ce_net *net);
109 int ce_process_download(ce_net *net, ce_bin *bin);
110 void ce_process_edbg(ce_net *net, ce_bin *bin);
111
112 #endif
113
114 ///////////////////////////////////////////////////////////////////////////////////////////////
115 // RedBoot commands
116
117 #ifdef CYGPKG_REDBOOT_NETWORKING
118 // Redboot network based commands
119 RedBoot_cmd(
120             "ceconnect",
121             "Set up a connection to the CE host PC over TCP/IP and download the run-time image",
122             "[-v] [-t <timeout>] [-h <host>]",
123             ce_load
124             );
125 #endif
126
127 ///////////////////////////////////////////////////////////////////////////////////////////////
128 // Implementation
129
130 bool ce_bin_load(void *image, int imglen)
131 {
132         ce_init_bin(&g_bin, image);
133
134         g_bin.dataLen = imglen;
135
136         if (ce_parse_bin(&g_bin) == CE_PR_EOF) {
137                 ce_prepare_run_bin(&g_bin);
138                 return true;
139         }
140
141         return false;
142 }
143
144 bool ce_is_bin_image(void *image, int imglen)
145 {
146         if (imglen < CE_BIN_SIGN_LEN) {
147                 return 0;
148         }
149
150         return (memcmp(image, CE_BIN_SIGN, CE_BIN_SIGN_LEN) == 0);
151 }
152
153 void ce_bin_init_parser()
154 {
155         // No buffer address by now, will be specified
156         // latter by the ce_bin_parse_next routine
157
158         ce_init_bin(&g_bin, NULL);
159 }
160
161 int ce_bin_parse_next(void *parseBuffer, int len)
162 {
163         int rc;
164
165         g_bin.data = (unsigned char*)parseBuffer;
166         g_bin.dataLen = len;
167         rc = ce_parse_bin(&g_bin);
168
169         if (rc == CE_PR_EOF) {
170                 ce_prepare_run_bin(&g_bin);
171         }
172
173         return rc;
174 }
175
176 void ce_init_bin(ce_bin *bin, unsigned char *dataBuffer)
177 {
178         memset(bin, 0, sizeof(ce_bin));
179
180         bin->data = dataBuffer;
181         bin->parseState = CE_PS_RTI_ADDR;
182         bin->parsePtr = (unsigned char*)&bin->rtiPhysAddr;
183 }
184
185 int ce_parse_bin(ce_bin *bin)
186 {
187         unsigned char *pbData = bin->data;
188         int pbLen = bin->dataLen;
189         int copyLen;
190
191         if (pbLen) {
192                 if (bin->binLen == 0) {
193                         // Check for the .BIN signature first
194
195                         if (!ce_is_bin_image(pbData, pbLen)) {
196                                 diag_printf("Error: Invalid or corrupted .BIN image!\n");
197
198                                 return CE_PR_ERROR;
199                         }
200
201                         diag_printf("Loading Windows CE .BIN image ...\n");
202
203                         // Skip signature
204
205                         pbLen -= CE_BIN_SIGN_LEN;
206                         pbData += CE_BIN_SIGN_LEN;
207                 }
208
209                 while (pbLen) {
210                         switch (bin->parseState) {
211                         case CE_PS_RTI_ADDR:
212                         case CE_PS_RTI_LEN:
213                         case CE_PS_E_ADDR:
214                         case CE_PS_E_LEN:
215                         case CE_PS_E_CHKSUM:
216
217                                 copyLen = CE_MIN(sizeof(unsigned int) - bin->parseLen, pbLen);
218
219                                 memcpy(&bin->parsePtr[ bin->parseLen ], pbData, copyLen);
220
221                                 bin->parseLen += copyLen;
222                                 pbLen -= copyLen;
223                                 pbData += copyLen;
224
225                                 if (bin->parseLen == sizeof(unsigned int)) {
226                                         if (bin->parseState == CE_PS_RTI_ADDR) {
227                                                 bin->rtiPhysAddr = CE_FIX_ADDRESS(bin->rtiPhysAddr);
228                                         } else if (bin->parseState == CE_PS_E_ADDR) {
229                                                 if (bin->ePhysAddr) {
230                                                         bin->ePhysAddr = CE_FIX_ADDRESS(bin->ePhysAddr);
231                                                 }
232                                         }
233
234                                         bin->parseState ++;
235                                         bin->parseLen = 0;
236                                         bin->parsePtr += sizeof(unsigned int);
237
238                                         if (bin->parseState == CE_PS_E_DATA) {
239                                                 if (bin->ePhysAddr) {
240                                                         bin->parsePtr = (unsigned char*)(bin->ePhysAddr);
241                                                         bin->parseChkSum = 0;
242                                                 } else {
243                                                         // EOF
244
245                                                         pbLen = 0;
246                                                         bin->endOfBin = 1;
247                                                 }
248                                         }
249                                 }
250
251                                 break;
252
253                         case CE_PS_E_DATA:
254
255                                 if (bin->ePhysAddr) {
256                                         copyLen = CE_MIN(bin->ePhysLen - bin->parseLen, pbLen);
257                                         bin->parseLen += copyLen;
258                                         pbLen -= copyLen;
259
260                                         while (copyLen --) {
261                                                 bin->parseChkSum += *pbData;
262                                                 *bin->parsePtr ++ = *pbData ++;
263                                         }
264
265                                         if (bin->parseLen == bin->ePhysLen) {
266                                                 diag_printf("Section [%02d]: address 0x%08X, size 0x%08X, checksum %s\n",
267                                                         bin->secion,
268                                                         bin->ePhysAddr,
269                                                         bin->ePhysLen,
270                                                         (bin->eChkSum == bin->parseChkSum) ? "ok" : "fail");
271
272                                                 if (bin->eChkSum != bin->parseChkSum) {
273                                                         // Checksum error!
274
275                                                         diag_printf("Error: Checksum error, corrupted .BIN file!\n");
276
277                                                         bin->binLen = 0;
278
279                                                         return CE_PR_ERROR;
280                                                 }
281
282                                                 bin->secion ++;
283                                                 bin->parseState = CE_PS_E_ADDR;
284                                                 bin->parseLen = 0;
285                                                 bin->parsePtr = (unsigned char*)(&bin->ePhysAddr);
286                                         }
287                                 } else {
288                                         bin->parseLen = 0;
289                                         bin->endOfBin = 1;
290                                         pbLen = 0;
291                                 }
292
293                                 break;
294                         }
295                 }
296         }
297
298         if (bin->endOfBin) {
299                 // Find entry point
300
301                 if (!ce_lookup_ep_bin(bin)) {
302                         diag_printf("Error: entry point not found!\n");
303
304                         bin->binLen = 0;
305
306                         return CE_PR_ERROR;
307                 }
308
309                 diag_printf("Entry point: 0x%08X, address range: 0x%08X-0x%08X\n",
310                         bin->eEntryPoint,
311                         bin->rtiPhysAddr,
312                         bin->rtiPhysAddr + bin->rtiPhysLen);
313
314                 return CE_PR_EOF;
315         }
316
317         // Need more data
318
319         bin->binLen += bin->dataLen;
320
321         return CE_PR_MORE;
322 }
323
324 bool ce_lookup_ep_bin(ce_bin *bin)
325 {
326         ce_rom_hdr *header;
327         ce_toc_entry *tentry;
328         e32_rom *e32;
329         unsigned int i;
330
331         // Check image Table Of Contents (TOC) signature
332
333         if (*(unsigned int*)(bin->rtiPhysAddr + ROM_SIGNATURE_OFFSET) != ROM_SIGNATURE) {
334                 // Error: Did not find image TOC signature!
335
336                 return 0;
337         }
338
339
340         // Lookup entry point
341
342         header = (ce_rom_hdr*)CE_FIX_ADDRESS(*(unsigned int*)(bin->rtiPhysAddr +
343                                                               ROM_SIGNATURE_OFFSET +
344                                                               sizeof(unsigned int)));
345         tentry = (ce_toc_entry*)(header + 1);
346
347         for (i = 0; i < header->nummods; i ++) {
348                 // Look for 'nk.exe' module
349
350                 if (strcmp((char*)CE_FIX_ADDRESS(tentry[ i ].fileName), "nk.exe") == 0) {
351                         // Save entry point and RAM addresses
352
353                         e32 = (e32_rom*)CE_FIX_ADDRESS(tentry[ i ].e32Offset);
354
355                         bin->eEntryPoint = CE_FIX_ADDRESS(tentry[ i ].loadOffset) + e32->e32_entryrva;
356                         bin->eRamStart = CE_FIX_ADDRESS(header->ramStart);
357                         bin->eRamLen = header->ramEnd - header->ramStart;
358
359                         // Save driver_globals address
360                         // Must follow RAM section in CE config.bib file
361                         //
362                         // eg.
363                         //
364                         // RAM          80900000        03200000        RAM
365                         // DRV_GLB      83B00000        00001000        RESERVED
366                         //
367
368                         bin->eDrvGlb = CE_FIX_ADDRESS(header->ramEnd);
369
370                         return 1;
371                 }
372         }
373
374         // Error: Did not find 'nk.exe' module
375
376         return 0;
377 }
378
379 void ce_prepare_run_bin(ce_bin *bin)
380 {
381         ce_driver_globals *drv_glb;
382
383         // Clear os RAM area (if needed)
384
385         if (1 || bin->edbgConfig.flags & EDBG_FL_CLEANBOOT) {
386                 diag_printf("Preparing clean boot ... ");
387                 memset((void*)bin->eRamStart, 0, bin->eRamLen);
388                 diag_printf("ok\n");
389         }
390
391         // Prepare driver globals (if needed)
392
393         if (bin->eDrvGlb) {
394                 drv_glb = (ce_driver_globals*)bin->eDrvGlb;
395
396                 // Fill out driver globals
397                 memset(drv_glb, 0, sizeof(ce_driver_globals));
398
399                 // Signature
400                 drv_glb->signature = DRV_GLB_SIGNATURE;
401
402                 // No flags by now
403                 drv_glb->flags = 0;
404
405 #ifdef CYGPKG_REDBOOT_NETWORKING
406                 // Local ethernet MAC address
407                 memcpy(drv_glb->macAddr, __local_enet_addr, sizeof(__local_enet_addr));
408
409                 // Local IP address
410                 memcpy(&drv_glb->ipAddr, __local_ip_addr, sizeof(__local_ip_addr));
411
412                 // Subnet mask
413                 memcpy(&drv_glb->ipMask, __local_ip_mask, sizeof(__local_ip_mask));
414
415                 // Gateway config
416 #ifdef CYGSEM_REDBOOT_NETWORKING_USE_GATEWAY
417                 // Getway IP address
418                 memcpy(&drv_glb->ipGate, __local_ip_gate, sizeof(__local_ip_gate));
419 #endif
420 #else
421                 // Local ethernet MAC address
422                 memset(drv_glb->macAddr, 0, sizeof(drv_glb->macAddr));
423
424                 // Local IP address
425                 memset(&drv_glb->ipAddr, 0, sizeof(drv_glb->ipAddr));
426
427                 // Subnet mask
428                 memset(&drv_glb->ipMask, 0, sizeof(drv_glb->ipMask));
429
430                 // Getway IP address
431                 memset(&drv_glb->ipGate, 0, sizeof(drv_glb->ipGate));
432 #endif // CYGPKG_REDBOOT_NETWORKING
433                 // EDBG services config
434                 memcpy(&drv_glb->edbgConfig, &bin->edbgConfig, sizeof(bin->edbgConfig));
435
436                 // Equotip specific
437 #ifdef CYGPKG_HAL_ARM_XSCALE_TRITON270_EQT32
438                 // Copy configuration
439
440                 drv_glb->contrastDefault = eedat.lcd_contrast;
441                 drv_glb->contrastBand = eedat.lcd_contrast_band;
442                 drv_glb->backlight = eedat.lcd_backlight;
443                 drv_glb->backlightOffset = eedat.lcd_backlight_offset;
444
445                 memcpy(drv_glb->macAddr, eedat.mac_address, sizeof(drv_glb->macAddr));
446 #endif
447         }
448
449         // Update global RedBoot entry point address
450         // to use with go/run commands
451         entry_address = bin->eEntryPoint;
452 }
453
454 void ce_run_bin(ce_bin *bin)
455 {
456         char *argv[] = { "go" };
457
458         diag_printf("Launching Windows CE ...\n");
459
460         // Call GO command direcly
461         do_go(1, argv);
462 }
463
464 // Extract version from CYGDAT_REDBOOT_CUSTOM_VERSION macro
465 // Works with versions like 'v2', 'v2.1', '2', '2.1', '2a', '2.1a'
466
467 void ce_redboot_version(unsigned int *vhigh, unsigned int *vlow)
468 {
469         char *pver = ""STRMAC(CYGDAT_REDBOOT_CUSTOM_VERSION);
470         char *p;
471         unsigned int *ver;
472         int len, pow;
473
474         *vhigh = *vlow = 0;
475         len = strlen(pver);
476         ver = vhigh;
477         pow = 1;
478         p = pver + strlen(pver) - 1;
479
480         while (len --) {
481                 if (*p >= '0' && *p <= '9') {
482                         *ver += ((*p - '0') * pow);
483                         pow *= 10;
484                 } else if (*p == '.') {
485                         if (ver == vhigh) {
486                                 *vlow = *vhigh;
487                                 *ver = 0;
488                                 pow = 1;
489                         } else {
490                                 break;
491                         }
492                 }
493                 p --;
494         }
495 }
496
497 ///////////////////////////////////////////////////////////////////////////////////////////////
498 // Redboot network based routines
499
500 #ifdef CYGPKG_REDBOOT_NETWORKING
501 void ce_load(int argc, char *argv[])
502 {
503         struct option_info opts[3];
504         bool verbose, use_timeout;
505         int timeout, recv_timeout, ret;
506         char *host_name;
507         char ctemp;
508         struct sockaddr_in host_ip_addr;
509
510         // Prepare for command line scan
511
512         verbose = false;
513         init_opts(&opts[0], 'v', false, OPTION_ARG_TYPE_FLG, (void *)&verbose, NULL,
514                   "verbose operation");
515
516         timeout = 0;
517         init_opts(&opts[1], 't', true, OPTION_ARG_TYPE_NUM, (void *)&timeout, &use_timeout,
518                   "<timeout> - max wait time (#sec) for the connection");
519
520         host_name = NULL;
521         init_opts(&opts[2], 'h', true, OPTION_ARG_TYPE_STR, (void *)&host_name, NULL,
522                   "<host> - host name or IP address");
523
524         if (!scan_opts(argc, argv, 1, opts, 3, NULL, 0, "")) {
525                 diag_printf("CELOAD - Invalid option specified\n");
526                 return;
527         }
528
529         // Check host IP address (if specified)
530         memset(&host_ip_addr, 0, sizeof(host_ip_addr));
531         if (host_name) {
532                 if (!_gethostbyname(host_name, (in_addr_t*)&host_ip_addr)) {
533                         diag_printf("CELOAD - Invalid host name: %s\n", host_name);
534                         return;
535                 }
536         }
537
538         // Initialize download link
539
540         ce_init_download_link(&g_net, &g_bin, &host_ip_addr, verbose);
541
542         // Download loop
543
544         while (1) {
545                 if (g_net.link) {
546                         recv_timeout = 3;
547                 } else {
548                         recv_timeout = 1;
549
550                         if (use_timeout) {
551                                 if (timeout <= 0) {
552                                         diag_printf("CELOAD - Canceled, timeout\n");
553                                         return;
554                                 }
555                         } else {
556                                 // Try to catch ^C
557                                 if (_rb_gets(&ctemp, 1, 1) == _GETS_CTRLC) {
558                                         diag_printf("CELOAD - canceled by user\n");
559                                         return;
560                                 }
561                         }
562
563                         if (ce_send_bootme(&g_net)) {
564                                 diag_printf("CELOAD - error while sending BOOTME request\n");
565                                 return;
566                         }
567
568                         if (verbose) {
569                                 if (use_timeout) {
570                                         diag_printf("Waiting for connection, timeout %d sec\n",
571                                                     timeout);
572                                 } else {
573                                         diag_printf("Waiting for connection, enter ^C to abort\n");
574                                 }
575                         }
576                 }
577
578                 // Try to receive frame
579
580                 if (ce_recv_frame(&g_net, recv_timeout)) {
581                         // Process received data
582
583                         ret = ce_process_download(&g_net, &g_bin);
584
585                         if (ret != CE_PR_MORE) {
586                                 break;
587                         }
588                 } else if (use_timeout) {
589                         timeout -= recv_timeout;
590                 }
591         }
592
593         if (g_bin.binLen) {
594                 // Try to receive edbg commands from host
595
596                 ce_init_edbg_link(&g_net);
597
598                 if (verbose) {
599                         diag_printf("Waiting for EDBG commands ...\n");
600                 }
601
602                 while (ce_recv_frame(&g_net, 3)) {
603                         ce_process_edbg(&g_net, &g_bin);
604                 }
605
606                 // Prepare WinCE image for execution
607
608                 ce_prepare_run_bin(&g_bin);
609
610                 // Launch WinCE, if necessary
611
612                 if (g_net.gotJumpingRequest) {
613                         ce_run_bin(&g_bin);
614                 }
615         }
616 }
617
618 void ce_init_download_link(ce_net *net, ce_bin *bin, struct sockaddr_in *host_addr, bool verbose)
619 {
620         // Initialize EDBG link for download
621
622         memset(net, 0, sizeof(ce_net));
623
624         net->locAddr.sin_family = AF_INET;
625         memcpy(&net->locAddr.sin_addr, __local_ip_addr, sizeof(__local_ip_addr));
626         net->locAddr.sin_port = htons(EDBG_DOWNLOAD_PORT);
627
628         net->srvAddrSend.sin_family = AF_INET;
629         net->srvAddrSend.sin_port = htons(EDBG_DOWNLOAD_PORT);
630
631         net->srvAddrRecv.sin_family = AF_INET;
632         net->srvAddrRecv.sin_port = 0;
633
634         if (host_addr->sin_addr.s_addr) {
635                 // Use specified host address ...
636
637                 net->srvAddrSend.sin_addr = host_addr->sin_addr;
638                 net->srvAddrRecv.sin_addr = host_addr->sin_addr;
639         } else {
640                 // ... or use default server address
641
642                 net->srvAddrSend.sin_addr = my_bootp_info.bp_siaddr;
643                 net->srvAddrRecv.sin_addr = my_bootp_info.bp_siaddr;
644         }
645
646         net->verbose = verbose;
647
648         // Initialize .BIN parser
649
650         // net->data + 0 -> Command
651         // net->data + 2 -> Block number
652         // net->data + 4 -> Block data
653
654         ce_init_bin(bin, net->data + 4);
655 }
656
657 void ce_init_edbg_link(ce_net *net)
658 {
659         // Initialize EDBG link for commands
660
661         net->locAddr.sin_port = htons(EDBG_DOWNLOAD_PORT);
662         net->srvAddrSend.sin_port = htons(EDBG_DOWNLOAD_PORT);
663         net->srvAddrRecv.sin_port = 0;
664         net->link = false;
665 }
666
667 int ce_send_frame(ce_net *net)
668 {
669         // Send UDP packet
670
671         return __udp_sendto(net->data, net->dataLen, &net->srvAddrSend, &net->locAddr);
672 }
673
674 int ce_recv_frame(ce_net *net, int timeout)
675 {
676         struct timeval timeo;
677
678         // Setup timeout
679
680         timeo.tv_sec = timeout;
681         timeo.tv_usec = 0;
682
683         // Receive UDP packet
684
685         net->dataLen = __udp_recvfrom(net->data, sizeof(net->data), &net->srvAddrRecv,
686                                       &net->locAddr, &timeo);
687
688         if (net->dataLen < 0) {
689                 // Error! No data available
690
691                 net->dataLen = 0;
692         }
693         return net->dataLen;
694 }
695
696 int ce_send_bootme(ce_net *net)
697 {
698         eth_dbg_hdr *header;
699         edbg_bootme_data *data;
700         int verHigh, verLow;
701
702         // Fill out BOOTME packet
703         memset(net->data, 0, BOOTME_PKT_SIZE);
704
705         header = (eth_dbg_hdr*)net->data;
706         data = (edbg_bootme_data*)header->data;
707
708         header->id = EDBG_ID;
709         header->service = EDBG_SVC_ADMIN;
710         header->flags = EDBG_FL_FROM_DEV;
711         header->seqNum = net->secNum ++;
712         header->cmd = EDBG_CMD_BOOTME;
713
714         // Get RedBoot version
715         ce_redboot_version(&verHigh, &verLow);
716
717         data->versionMajor = verHigh;
718         data->versionMinor = verLow;
719         data->cpuId = EDBG_CPU_TYPE_ARM;
720         data->bootmeVer = EDBG_CURRENT_BOOTME_VERSION;
721         data->bootFlags = 0;
722         data->downloadPort = 0;
723         data->svcPort = 0;
724
725         memcpy(data->macAddr, __local_enet_addr, sizeof(__local_enet_addr));
726         memcpy(&data->ipAddr, __local_ip_addr, sizeof(__local_ip_addr));
727
728         // Device name string (NULL terminated). Should include
729         // platform and number based on Ether address (e.g. Odo42, CEPCLS2346, etc)
730
731         // We will use lower MAC address segment to create device name
732         // eg. MAC '00-0C-C6-69-09-05', device name 'Triton05'
733
734         strcpy(data->platformId, "Triton");
735         diag_sprintf(data->deviceName, "%s%02X", data->platformId, __local_enet_addr[5]);
736 #if 0
737         diag_printf("header->id: %08X\r\n", header->id);
738         diag_printf("header->service: %08X\r\n", header->service);
739         diag_printf("header->flags: %08X\r\n", header->flags);
740         diag_printf("header->seqNum: %08X\r\n", header->seqNum);
741         diag_printf("header->cmd: %08X\r\n\r\n", header->cmd);
742
743         diag_printf("data->versionMajor: %08X\r\n", data->versionMajor);
744         diag_printf("data->versionMinor: %08X\r\n", data->versionMinor);
745         diag_printf("data->cpuId: %08X\r\n", data->cpuId);
746         diag_printf("data->bootmeVer: %08X\r\n", data->bootmeVer);
747         diag_printf("data->bootFlags: %08X\r\n", data->bootFlags);
748         diag_printf("data->svcPort: %08X\r\n\r\n", data->svcPort);
749
750         diag_printf("data->macAddr: %02X-%02X-%02X-%02X-%02X-%02X-%02X\r\n",
751                 (data->macAddr[0] >> 0) & 0xFF,
752                 (data->macAddr[0] >> 8) & 0xFF,
753                 (data->macAddr[1] >> 0) & 0xFF,
754                 (data->macAddr[1] >> 8) & 0xFF,
755                 (data->macAddr[2] >> 0) & 0xFF,
756                 (data->macAddr[2] >> 8) & 0xFF);
757
758         diag_printf("data->ipAddr: %d.%d.%d.%d\r\n",
759                 (data->ipAddr >> 0) & 0xFF,
760                 (data->ipAddr >> 8) & 0xFF,
761                 (data->ipAddr >> 16) & 0xFF,
762                 (data->ipAddr >> 24) & 0xFF);
763
764         diag_printf("data->platformId: %s\r\n", data->platformId);
765         diag_printf("data->deviceName: %s\r\n", data->deviceName);
766 #endif
767         // Some diag output ...
768         if (net->verbose) {
769                 diag_printf("Sending BOOTME request [%d] to %s\n",
770                         (int)net->secNum,
771                         inet_ntoa((in_addr_t *)&net->srvAddrSend));
772         }
773
774         // Send packet
775         net->dataLen = BOOTME_PKT_SIZE;
776
777         return ce_send_frame(net);
778 }
779
780 int ce_send_write_ack(ce_net *net)
781 {
782         unsigned short *wdata = (unsigned short*)net->data;
783
784         wdata[ 0 ] = htons(EDBG_CMD_WRITE_ACK);
785         wdata[ 1 ] = htons(net->blockNum);
786
787         net->dataLen = 4;
788
789         return ce_send_frame(net);
790 }
791
792 int ce_process_download(ce_net *net, ce_bin *bin)
793 {
794         int ret = CE_PR_MORE;
795
796         if (net->dataLen >= 2) {
797                 switch (ntohs(*(unsigned short*)net->data)) {
798                 case EDBG_CMD_WRITE_REQ:
799                         if (!net->link) {
800                                 // Check file name for WRITE request
801                                 // CE EShell uses "boot.bin" file name
802
803                                 /*diag_printf(">>>>>>>> First Frame, IP: %s, port: %d\n",
804                                                         inet_ntoa((in_addr_t *)&net->srvAddrRecv),
805                                                         net->srvAddrRecv.sin_port);*/
806                                 if (strncmp((char*)(net->data + 2), "boot.bin", 8) == 0) {
807                                         // Some diag output
808                                         if (net->verbose) {
809                                                 diag_printf("Locked Down download link, IP: %s, port: %d\n",
810                                                             inet_ntoa((in_addr_t *)&net->srvAddrRecv),
811                                                             net->srvAddrRecv.sin_port);
812                                         }
813
814                                         // Lock down EShell download link
815                                         net->locAddr.sin_port = htons(EDBG_DOWNLOAD_PORT + 1);
816                                         net->srvAddrSend.sin_port = net->srvAddrRecv.sin_port;
817                                         net->srvAddrSend.sin_addr = net->srvAddrRecv.sin_addr;
818                                         net->link = true;
819                                 } else {
820                                         // Unknown link
821                                         net->srvAddrRecv.sin_port = 0;
822                                 }
823
824                                 // Return write ack
825                                 if (net->link) {
826                                         ce_send_write_ack(net);
827                                 }
828                                 break;
829                         }
830                         // LW: is it really intended to fall thru in case of net->link != 0 ?
831                 case EDBG_CMD_WRITE:
832                         // Fix data len
833                         bin->dataLen = net->dataLen - 4;
834
835                         // Parse next block of .bin file
836                         ret = ce_parse_bin(bin);
837
838                         // Request next block
839                         if (ret != CE_PR_ERROR) {
840                                 net->blockNum ++;
841
842                                 ce_send_write_ack(net);
843                         }
844                         break;
845                 case EDBG_CMD_READ_REQ:
846                         // Read requests are not supported
847                         // Do nothing ...
848                         break;
849                 case EDBG_CMD_ERROR:
850                         // Error condition on the host side
851                         diag_printf("Error: unknown error on the host side\n");
852
853                         bin->binLen = 0;
854                         ret = CE_PR_ERROR;
855                         break;
856                 }
857         }
858
859         return ret;
860 }
861
862 void ce_process_edbg(ce_net *net, ce_bin *bin)
863 {
864         eth_dbg_hdr *header;
865
866         if (net->dataLen < sizeof(eth_dbg_hdr)) {
867                 // Bad packet
868
869                 net->srvAddrRecv.sin_port = 0;
870                 return;
871         }
872
873         header = (eth_dbg_hdr*)net->data;
874
875         if (header->id != EDBG_ID) {
876                 // Bad packet
877
878                 net->srvAddrRecv.sin_port = 0;
879                 return;
880         }
881
882         if (header->service != EDBG_SVC_ADMIN) {
883                 // Unknown service
884
885                 return;
886         }
887
888         if (!net->link) {
889                 // Some diag output
890
891                 if (net->verbose) {
892                         diag_printf("Locked Down EDBG service link, IP: %s, port: %d\n",
893                                 inet_ntoa((in_addr_t *)&net->srvAddrRecv),
894                                 net->srvAddrRecv.sin_port);
895                 }
896
897                 // Lock down EDBG link
898
899                 net->srvAddrSend.sin_port = net->srvAddrRecv.sin_port;
900                 net->link = true;
901         }
902
903         switch (header->cmd) {
904         case EDBG_CMD_JUMPIMG:
905                 net->gotJumpingRequest = true;
906
907                 if (net->verbose) {
908                         diag_printf("Received JUMPING command\n");
909                 }
910                 // Just pass through and copy CONFIG structure
911         case EDBG_CMD_OS_CONFIG:
912                 // Copy config structure
913                 memcpy(&bin->edbgConfig, header->data, sizeof(edbg_os_config_data));
914                 if (net->verbose) {
915                         diag_printf("Received CONFIG command\n");
916                         if (bin->edbgConfig.flags & EDBG_FL_DBGMSG) {
917                                 diag_printf("--> Enabling DBGMSG service, IP: %d.%d.%d.%d, port: %d\n",
918                                         (bin->edbgConfig.dbgMsgIPAddr >> 0) & 0xFF,
919                                         (bin->edbgConfig.dbgMsgIPAddr >> 8) & 0xFF,
920                                         (bin->edbgConfig.dbgMsgIPAddr >> 16) & 0xFF,
921                                         (bin->edbgConfig.dbgMsgIPAddr >> 24) & 0xFF,
922                                         (int)bin->edbgConfig.dbgMsgPort);
923                         }
924                         if (bin->edbgConfig.flags & EDBG_FL_PPSH) {
925                                 diag_printf("--> Enabling PPSH service, IP: %d.%d.%d.%d, port: %d\n",
926                                         (bin->edbgConfig.ppshIPAddr >> 0) & 0xFF,
927                                         (bin->edbgConfig.ppshIPAddr >> 8) & 0xFF,
928                                         (bin->edbgConfig.ppshIPAddr >> 16) & 0xFF,
929                                         (bin->edbgConfig.ppshIPAddr >> 24) & 0xFF,
930                                         (int)bin->edbgConfig.ppshPort);
931                         }
932                         if (bin->edbgConfig.flags & EDBG_FL_KDBG) {
933                                 diag_printf("--> Enabling KDBG service, IP: %d.%d.%d.%d, port: %d\n",
934                                         (bin->edbgConfig.kdbgIPAddr >> 0) & 0xFF,
935                                         (bin->edbgConfig.kdbgIPAddr >> 8) & 0xFF,
936                                         (bin->edbgConfig.kdbgIPAddr >> 16) & 0xFF,
937                                         (bin->edbgConfig.kdbgIPAddr >> 24) & 0xFF,
938                                         (int)bin->edbgConfig.kdbgPort);
939                         }
940                         if (bin->edbgConfig.flags & EDBG_FL_CLEANBOOT) {
941                                 diag_printf("--> Force clean boot\n");
942                         }
943                 }
944                 break;
945         default:
946                 if (net->verbose) {
947                         diag_printf("Received unknown command: %08X\n", header->cmd);
948                 }
949                 return;
950         }
951
952         // Respond with ack
953         header->flags = EDBG_FL_FROM_DEV | EDBG_FL_ACK;
954         net->dataLen = EDBG_DATA_OFFSET;
955
956         ce_send_frame(net);
957 }
958 #endif
959