2 * Copyright (C) 2012 Lothar Waßmann <LW@KARO-electronics.de>
3 * based on: code from RedBoot (C) Uwe Steinkohl <US@KARO-electronics.de>
5 * See file CREDITS for list of people who contributed to this
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of
11 * the License, or (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
28 #include <asm/errno.h>
30 DECLARE_GLOBAL_DATA_PTR;
32 #define WINCE_VRAM_BASE 0x80000000
33 #define CE_FIX_ADDRESS(a) ((void *)((a) - WINCE_VRAM_BASE + CONFIG_SYS_SDRAM_BASE))
36 #define INT_MAX ((1U << (sizeof(int) * 8 - 1)) - 1)
39 /* Bin image parse states */
40 #define CE_PS_RTI_ADDR 0
41 #define CE_PS_RTI_LEN 1
42 #define CE_PS_E_ADDR 2
44 #define CE_PS_E_CHKSUM 4
45 #define CE_PS_E_DATA 5
47 #define CE_MIN(a, b) (((a) < (b)) ? (a) : (b))
48 #define CE_MAX(a, b) (((a) > (b)) ? (a) : (b))
51 #define STRMAC(s) _STRMAC(s)
53 static ce_bin __attribute__ ((aligned (32))) g_bin;
54 static ce_net __attribute__ ((aligned (32))) g_net;
56 static inline void print_IPaddr(IPaddr_t ip)
65 static void ce_init_bin(ce_bin *bin, unsigned char *dataBuffer)
67 memset(bin, 0, sizeof(*bin));
69 bin->data = dataBuffer;
70 bin->parseState = CE_PS_RTI_ADDR;
71 bin->parsePtr = (unsigned char *)bin;
74 static int ce_is_bin_image(void *image, int imglen)
76 if (imglen < CE_BIN_SIGN_LEN) {
80 return memcmp(image, CE_BIN_SIGN, CE_BIN_SIGN_LEN) == 0;
83 static const struct ce_magic {
86 ce_std_driver_globals drv_glb;
87 } ce_magic_template = {
89 .size = sizeof(ce_std_driver_globals),
92 .signature = STD_DRV_GLB_SIGNATURE,
100 static void __attribute__((unused)) ce_dump_block(void *ptr, int length)
106 for (i = 0; i < length; i++) {
108 printf("\n%p: ", ptr + i);
111 printf("%02x ", p[i]);
112 if (!((i + 1) % 16)){
114 for (j = i - 15; j <= i; j++){
115 if((p[j] > 0x1f) && (p[j] < 0x7f)) {
126 static inline void ce_dump_block(void *ptr, int length)
131 static void ce_setup_std_drv_globals(ce_std_driver_globals *std_drv_glb,
134 char *mtdparts = getenv("mtdparts");
135 size_t max_len = ALIGN((unsigned long)std_drv_glb, SZ_4K) -
136 (unsigned long)&std_drv_glb->mtdparts;
139 memcpy(&std_drv_glb->kitl.mac, eth_get_dev()->enetaddr,
140 sizeof(std_drv_glb->kitl.mac));
142 snprintf(std_drv_glb->deviceId, sizeof(std_drv_glb->deviceId),
143 "Triton%02X", eth_get_dev()->enetaddr[5]);
145 std_drv_glb->kitl.ipAddress = gd->bd->bi_ip_addr;
146 std_drv_glb->kitl.ipMask = getenv_IPaddr("netmask");
147 std_drv_glb->kitl.ipRoute = getenv_IPaddr("gatewayip");
150 strncpy(std_drv_glb->mtdparts, mtdparts, max_len);
151 std_drv_glb->mtdparts[max_len - 1] = '\0';
153 printf("Failed to get mtdparts environment variable\n");
157 static void ce_prepare_run_bin(ce_bin *bin)
159 ce_driver_globals *drv_glb;
160 struct ce_magic *ce_magic = (void *)CONFIG_SYS_SDRAM_BASE + 0x160;
161 ce_std_driver_globals *std_drv_glb = &ce_magic->drv_glb;
163 /* Clear os RAM area (if needed) */
164 if (bin->edbgConfig.flags & EDBG_FL_CLEANBOOT) {
165 debug("cleaning memory from %p to %p\n",
166 bin->eRamStart, bin->eRamStart + bin->eRamLen);
168 printf("Preparing clean boot ... ");
169 memset(bin->eRamStart, 0, bin->eRamLen);
173 /* Prepare driver globals (if needed) */
175 debug("Copying CE MAGIC from %p to %p..%p\n",
176 &ce_magic_template, ce_magic,
177 (void *)ce_magic + sizeof(*ce_magic) - 1);
178 memcpy(ce_magic, &ce_magic_template, sizeof(*ce_magic));
180 ce_setup_std_drv_globals(std_drv_glb, bin);
181 ce_magic->size = sizeof(*std_drv_glb) +
182 strlen(std_drv_glb->mtdparts) + 1;
183 ce_dump_block(ce_magic, offsetof(struct ce_magic, drv_glb) +
186 drv_glb = bin->eDrvGlb;
187 memset(drv_glb, 0, sizeof(*drv_glb));
189 drv_glb->signature = DRV_GLB_SIGNATURE;
191 /* Local ethernet MAC address */
192 memcpy(drv_glb->macAddr, std_drv_glb->kitl.mac,
193 sizeof(drv_glb->macAddr));
194 debug("got MAC address %02x:%02x:%02x:%02x:%02x:%02x from environment\n",
195 drv_glb->macAddr[0], drv_glb->macAddr[1],
196 drv_glb->macAddr[2], drv_glb->macAddr[3],
197 drv_glb->macAddr[4], drv_glb->macAddr[5]);
199 /* Local IP address */
200 drv_glb->ipAddr = getenv_IPaddr("ipaddr");
203 drv_glb->ipMask = getenv_IPaddr("netmask");
206 drv_glb->ipGate = getenv_IPaddr("gatewayip");
208 debug("got IP address ");
209 print_IPaddr(drv_glb->ipAddr);
210 debug(" from environment\n");
211 debug("got IP mask ");
212 print_IPaddr(drv_glb->ipMask);
213 debug(" from environment\n");
214 debug("got gateway address ");
215 print_IPaddr(drv_glb->ipGate);
216 debug(" from environment\n");
218 /* EDBG services config */
219 memcpy(&drv_glb->edbgConfig, &bin->edbgConfig,
220 sizeof(bin->edbgConfig));
224 * Make sure, all the above makes it into SDRAM because
225 * WinCE switches the cache & MMU off, obviously without
231 static int ce_lookup_ep_bin(ce_bin *bin)
234 ce_toc_entry *tentry;
237 uint32_t *sig = (uint32_t *)(bin->rtiPhysAddr + ROM_SIGNATURE_OFFSET);
239 debug("Looking for TOC signature at %p\n", sig);
241 /* Check image Table Of Contents (TOC) signature */
242 if (*sig != ROM_SIGNATURE) {
243 printf("Error: Did not find image TOC signature!\n");
244 printf("Expected %08x at address %p; found %08x instead\n",
245 ROM_SIGNATURE, sig, *sig);
249 /* Lookup entry point */
250 header = CE_FIX_ADDRESS(*(unsigned int *)(bin->rtiPhysAddr +
251 ROM_SIGNATURE_OFFSET +
252 sizeof(unsigned int)));
253 tentry = (ce_toc_entry *)(header + 1);
255 for (i = 0; i < header->nummods; i++) {
256 // Look for 'nk.exe' module
257 if (strcmp(CE_FIX_ADDRESS(tentry[i].fileName), "nk.exe") == 0) {
258 // Save entry point and RAM addresses
260 e32 = CE_FIX_ADDRESS(tentry[i].e32Offset);
262 bin->eEntryPoint = CE_FIX_ADDRESS(tentry[i].loadOffset) +
264 bin->eRamStart = CE_FIX_ADDRESS(header->ramStart);
265 bin->eRamLen = header->ramEnd - header->ramStart;
266 // Save driver_globals address
267 // Must follow RAM section in CE config.bib file
271 // RAM 80900000 03200000 RAM
272 // DRV_GLB 83B00000 00001000 RESERVED
274 bin->eDrvGlb = CE_FIX_ADDRESS(header->ramEnd);
279 // Error: Did not find 'nk.exe' module
283 static int ce_parse_bin(ce_bin *bin)
285 unsigned char *pbData = bin->data;
286 int len = bin->dataLen;
289 debug("starting ce image parsing:\n\tbin->binLen: 0x%08X\n", bin->binLen);
292 if (bin->binLen == 0) {
293 // Check for the .BIN signature first
294 if (!ce_is_bin_image(pbData, len)) {
295 printf("Error: Invalid or corrupted .BIN image!\n");
299 printf("Loading Windows CE .BIN image ...\n");
301 len -= CE_BIN_SIGN_LEN;
302 pbData += CE_BIN_SIGN_LEN;
306 switch (bin->parseState) {
312 copyLen = CE_MIN(sizeof(unsigned int) - bin->parseLen, len);
313 memcpy(&bin->parsePtr[bin->parseLen], pbData, copyLen);
315 bin->parseLen += copyLen;
319 if (bin->parseLen == sizeof(unsigned int)) {
320 if (bin->parseState == CE_PS_RTI_ADDR)
321 bin->rtiPhysAddr = CE_FIX_ADDRESS(bin->rtiPhysAddr);
322 else if (bin->parseState == CE_PS_E_ADDR &&
324 bin->ePhysAddr = CE_FIX_ADDRESS(bin->ePhysAddr);
328 bin->parsePtr += sizeof(unsigned int);
330 if (bin->parseState == CE_PS_E_DATA) {
331 if (bin->ePhysAddr) {
332 bin->parsePtr = bin->ePhysAddr;
333 bin->parseChkSum = 0;
344 if (bin->ePhysAddr) {
345 copyLen = CE_MIN(bin->ePhysLen - bin->parseLen, len);
346 bin->parseLen += copyLen;
350 bin->parseChkSum += *pbData;
351 *bin->parsePtr++ = *pbData++;
354 if (bin->parseLen == bin->ePhysLen) {
355 printf("Section [%02d]: address %p, size 0x%08X, checksum %s\n",
359 (bin->eChkSum == bin->parseChkSum) ? "ok" : "fail");
361 if (bin->eChkSum != bin->parseChkSum) {
362 printf("Error: Checksum error, corrupted .BIN file!\n");
363 printf("checksum calculated: 0x%08x from file: 0x%08x\n",
364 bin->parseChkSum, bin->eChkSum);
370 bin->parseState = CE_PS_E_ADDR;
372 bin->parsePtr = (unsigned char *)&bin->ePhysAddr;
385 if (!ce_lookup_ep_bin(bin)) {
386 printf("Error: entry point not found!\n");
391 printf("Entry point: %p, address range: %p-%p\n",
394 bin->rtiPhysAddr + bin->rtiPhysLen);
400 bin->binLen += bin->dataLen;
404 static int ce_bin_load(void *image, int imglen)
406 ce_init_bin(&g_bin, image);
407 g_bin.dataLen = imglen;
408 if (ce_parse_bin(&g_bin) == CE_PR_EOF) {
409 ce_prepare_run_bin(&g_bin);
416 static void ce_run_bin(void (*entry)(void))
418 printf("Launching Windows CE ...\n");
422 static int do_bootce(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
429 addr = (void *)simple_strtoul(argv[1], NULL, 16);
430 image_size = INT_MAX; /* actually we do not know the image size */
431 } else if (getenv("fileaddr") != NULL) {
432 addr = (void *)getenv_ulong("fileaddr", 16, 0);
433 image_size = getenv_ulong("filesize", 16, INT_MAX);
435 printf ("Usage:\n%s\n", cmdtp->usage);
439 printf ("## Booting Windows CE Image from address %p ...\n", addr);
441 /* check if there is a valid windows CE image */
442 if (ce_is_bin_image(addr, image_size)) {
443 if (!ce_bin_load(addr, image_size)) {
444 /* Ops! Corrupted .BIN image! */
445 /* Handle error here ... */
446 printf("corrupted .BIN image !!!\n");
449 if ((s = getenv("autostart")) != NULL) {
452 * just use bootce to load the image to SDRAM;
453 * Do not start it automatically.
455 setenv_addr("fileaddr",
460 ce_run_bin(g_bin.eEntryPoint); /* start the image */
462 printf("Image does not seem to be a valid Windows CE image!\n");
465 return 1; /* never reached - just to keep compiler happy */
469 bootce, 2, 0, do_bootce,
470 "bootce\t- Boot a Windows CE image from memory \n",
472 "\taddr\t\t-boot image from address addr\n"
475 static void wince_handler(uchar *pkt, unsigned dport, IPaddr_t sip,
476 unsigned sport, unsigned len)
478 void *eth_pkt = pkt - IP_HDR_SIZE - ETHER_HDR_SIZE;
479 unsigned eth_len = len + IP_HDR_SIZE + ETHER_HDR_SIZE;
481 NetState = NETLOOP_SUCCESS; /* got input - quit net loop */
483 if (memcmp(eth_pkt, eth_get_dev()->enetaddr, ETH_ALEN) != 0) {
484 g_net.got_packet_4me = 0;
487 memcpy(&g_net.data[g_net.align_offset],
491 g_net.got_packet_4me = 1;
493 g_net.srvAddrRecv.sin_port = *((unsigned short *)(&g_net.data[
494 ETHER_HDR_SIZE + IP_HDR_SIZE_NO_UDP + g_net.align_offset]));
495 NetCopyIP(&g_net.srvAddrRecv.sin_addr, &g_net.data[ETHER_HDR_SIZE +
496 g_net.align_offset + 12]);
497 memcpy(NetServerEther, &g_net.data[g_net.align_offset + 6], ETH_ALEN);
499 printf("received packet: buffer %p Laenge %d \n", pkt, len);
501 print_IPaddr(g_net.srvAddrRecv.sin_addr);
502 printf(", port: %d\n", ntohs(g_net.srvAddrRecv.sin_port));
504 ce_dump_block(pkt, len);
506 printf("Headers:\n");
507 ce_dump_block(eth_pkt, ETHER_HDR_SIZE + IP_HDR_SIZE);
508 printf("my port should be: %d\n",
509 ntohs(*((unsigned short *)(&g_net.data[ETHER_HDR_SIZE +
511 g_net.align_offset + 2]))));
515 /* returns packet length if successfull */
516 static int ce_recv_packet(uchar *buf, int len, struct sockaddr_in *from,
517 struct sockaddr_in *local, struct timeval *timeout)
522 g_net.got_packet_4me = 0;
523 time_started = get_timer(0);
524 NetSetHandler(wince_handler);
528 if (g_net.got_packet_4me)
529 return g_net.dataLen;
530 /* check for timeout */
531 if (get_timer(time_started) > timeout->tv_sec * CONFIG_SYS_HZ) {
537 static int ce_recv_frame(ce_net *net, int timeout)
539 struct timeval timeo;
541 timeo.tv_sec = timeout;
544 net->dataLen = ce_recv_packet(&net->data[net->align_offset],
545 sizeof(net->data) - net->align_offset,
546 &net->srvAddrRecv, &net->locAddr, &timeo);
548 if (net->dataLen < 0 || net->dataLen > sizeof(net->data)) {
549 /* Error! No data available */
556 static int ce_send_frame(ce_net *net)
558 uchar *pkt = (uchar *)NetTxPacket + ETHER_HDR_SIZE + IP_HDR_SIZE;
560 memcpy(pkt, &net->data[net->align_offset + ETHER_HDR_SIZE + IP_HDR_SIZE],
562 return NetSendUDPPacket(NetServerEther, net->srvAddrSend.sin_addr,
563 ntohs(net->srvAddrSend.sin_port),
564 ntohs(net->locAddr.sin_port), net->dataLen);
567 static int ce_send_write_ack(ce_net *net)
569 unsigned short *wdata;
570 unsigned long aligned_address;
572 aligned_address = (unsigned long)&net->data[ETHER_HDR_SIZE + IP_HDR_SIZE + net->align_offset];
574 wdata = (unsigned short *)aligned_address;
575 wdata[0] = htons(EDBG_CMD_WRITE_ACK);
576 wdata[1] = htons(net->blockNum);
580 return ce_send_frame(net);
583 static int ce_process_download(ce_net *net, ce_bin *bin)
585 int ret = CE_PR_MORE;
587 if (net->dataLen >= 2) {
588 unsigned short command;
590 command = ntohs(*(unsigned short *)&net->data[CE_DOFFSET]);
591 debug("command found: 0x%04X\n", command);
594 case EDBG_CMD_WRITE_REQ:
596 // Check file name for WRITE request
597 // CE EShell uses "boot.bin" file name
599 printf(">>>>>>>> First Frame, IP: %s, port: %d\n",
600 inet_ntoa((in_addr_t *)&net->srvAddrRecv),
601 ntohs(net->srvAddrRecv.sin_port));
603 if (strncmp((char *)&net->data[CE_DOFFSET + 2],
604 "boot.bin", 8) == 0) {
607 printf("Locked Down download link, IP: ");
608 print_IPaddr(net->srvAddrRecv.sin_addr);
609 printf(", port: %d\n", ntohs(net->srvAddrRecv.sin_port));
611 printf("Sending BOOTME request [%d] to ",
613 print_IPaddr(net->srvAddrSend.sin_addr);
617 // Lock down EShell download link
618 net->locAddr.sin_port = htons(EDBG_DOWNLOAD_PORT + 1);
619 net->srvAddrSend.sin_port = net->srvAddrRecv.sin_port;
620 net->srvAddrSend.sin_addr = net->srvAddrRecv.sin_addr;
624 net->srvAddrRecv.sin_port = 0;
628 ce_send_write_ack(net);
635 bin->dataLen = net->dataLen - 4;
637 ret = ce_parse_bin(bin);
638 if (ret != CE_PR_ERROR) {
640 ce_send_write_ack(net);
644 case EDBG_CMD_READ_REQ:
645 /* Read requests are not supported
651 printf("Error: unknown error on the host side\n");
658 printf("unknown command 0x%04X\n", command);
665 static void ce_init_edbg_link(ce_net *net)
667 /* Initialize EDBG link for commands */
669 net->locAddr.sin_port = htons(EDBG_DOWNLOAD_PORT);
670 net->srvAddrSend.sin_port = htons(EDBG_DOWNLOAD_PORT);
671 net->srvAddrRecv.sin_port = 0;
675 static void ce_process_edbg(ce_net *net, ce_bin *bin)
679 if (net->dataLen < sizeof(eth_dbg_hdr)) {
682 net->srvAddrRecv.sin_port = 0;
686 header = (eth_dbg_hdr *)&net->data[net->align_offset + ETHER_HDR_SIZE + IP_HDR_SIZE];
688 if (header->id != EDBG_ID) {
691 net->srvAddrRecv.sin_port = 0;
695 if (header->service != EDBG_SVC_ADMIN) {
696 /* Unknown service */
701 /* Some diag output */
703 printf("Locked Down EDBG service link, IP: ");
704 print_IPaddr(net->srvAddrRecv.sin_addr);
705 printf(", port: %d\n", ntohs(net->srvAddrRecv.sin_port));
708 /* Lock down EDBG link */
709 net->srvAddrSend.sin_port = net->srvAddrRecv.sin_port;
713 switch (header->cmd) {
714 case EDBG_CMD_JUMPIMG:
715 net->gotJumpingRequest = 1;
718 printf("Received JUMPING command\n");
720 /* Just pass through and copy CONFIG structure */
721 case EDBG_CMD_OS_CONFIG:
722 /* Copy config structure */
723 memcpy(&bin->edbgConfig, header->data,
724 sizeof(edbg_os_config_data));
726 printf("Received CONFIG command\n");
727 if (bin->edbgConfig.flags & EDBG_FL_DBGMSG) {
728 printf("--> Enabling DBGMSG service, IP: %d.%d.%d.%d, port: %d\n",
729 (bin->edbgConfig.dbgMsgIPAddr >> 0) & 0xFF,
730 (bin->edbgConfig.dbgMsgIPAddr >> 8) & 0xFF,
731 (bin->edbgConfig.dbgMsgIPAddr >> 16) & 0xFF,
732 (bin->edbgConfig.dbgMsgIPAddr >> 24) & 0xFF,
733 ntohs(bin->edbgConfig.dbgMsgPort));
736 if (bin->edbgConfig.flags & EDBG_FL_PPSH) {
737 printf("--> Enabling PPSH service, IP: %d.%d.%d.%d, port: %d\n",
738 (bin->edbgConfig.ppshIPAddr >> 0) & 0xFF,
739 (bin->edbgConfig.ppshIPAddr >> 8) & 0xFF,
740 (bin->edbgConfig.ppshIPAddr >> 16) & 0xFF,
741 (bin->edbgConfig.ppshIPAddr >> 24) & 0xFF,
742 ntohs(bin->edbgConfig.ppshPort));
745 if (bin->edbgConfig.flags & EDBG_FL_KDBG) {
746 printf("--> Enabling KDBG service, IP: %d.%d.%d.%d, port: %d\n",
747 (bin->edbgConfig.kdbgIPAddr >> 0) & 0xFF,
748 (bin->edbgConfig.kdbgIPAddr >> 8) & 0xFF,
749 (bin->edbgConfig.kdbgIPAddr >> 16) & 0xFF,
750 (bin->edbgConfig.kdbgIPAddr >> 24) & 0xFF,
751 ntohs(bin->edbgConfig.kdbgPort));
754 if (bin->edbgConfig.flags & EDBG_FL_CLEANBOOT) {
755 printf("--> Force clean boot\n");
762 printf("Received unknown command: %08X\n", header->cmd);
767 /* Respond with ack */
768 header->flags = EDBG_FL_FROM_DEV | EDBG_FL_ACK;
769 net->dataLen = EDBG_DATA_OFFSET;
773 static int ce_send_bootme(ce_net *net)
776 edbg_bootme_data *data;
781 /* Fill out BOOTME packet */
782 memset(net->data, 0, PKTSIZE);
783 header = (eth_dbg_hdr *)&net->data[CE_DOFFSET];
784 data = (edbg_bootme_data *)header->data;
786 header->id = EDBG_ID;
787 header->service = EDBG_SVC_ADMIN;
788 header->flags = EDBG_FL_FROM_DEV;
789 header->seqNum = net->seqNum++;
790 header->cmd = EDBG_CMD_BOOTME;
792 data->versionMajor = 0;
793 data->versionMinor = 0;
794 data->cpuId = EDBG_CPU_TYPE_ARM;
795 data->bootmeVer = EDBG_CURRENT_BOOTME_VERSION;
797 data->downloadPort = 0;
800 /* MAC address from environment*/
801 if (!eth_getenv_enetaddr("ethaddr", data->macAddr)) {
802 printf("'ethaddr' is not set or invalid\n");
803 memset(data->macAddr, 0, sizeof(data->macAddr));
806 /* IP address from environment */
807 data->ipAddr = getenv_IPaddr("ipaddr");
809 // Device name string (NULL terminated). Should include
810 // platform and number based on Ether address (e.g. Odo42, CEPCLS2346, etc)
812 // We will use lower MAC address segment to create device name
813 // eg. MAC '00-0C-C6-69-09-05', device name 'Triton05'
815 strncpy(data->platformId, "Triton", sizeof(data->platformId));
816 snprintf(data->deviceName, sizeof(data->deviceName), "%s%02X",
817 data->platformId, data->macAddr[5]);
820 printf("header->id: %08X\r\n", header->id);
821 printf("header->service: %08X\r\n", header->service);
822 printf("header->flags: %08X\r\n", header->flags);
823 printf("header->seqNum: %08X\r\n", header->seqNum);
824 printf("header->cmd: %08X\r\n\r\n", header->cmd);
826 printf("data->versionMajor: %08X\r\n", data->versionMajor);
827 printf("data->versionMinor: %08X\r\n", data->versionMinor);
828 printf("data->cpuId: %08X\r\n", data->cpuId);
829 printf("data->bootmeVer: %08X\r\n", data->bootmeVer);
830 printf("data->bootFlags: %08X\r\n", data->bootFlags);
831 printf("data->svcPort: %08X\r\n\r\n", ntohs(data->svcPort));
833 printf("data->macAddr: %02X-%02X-%02X-%02X-%02X-%02X\r\n",
834 data->macAddr[0], data->macAddr[1],
835 data->macAddr[2], data->macAddr[3],
836 data->macAddr[4], data->macAddr[5]);
838 printf("data->ipAddr: %d.%d.%d.%d\r\n",
839 (data->ipAddr >> 0) & 0xFF,
840 (data->ipAddr >> 8) & 0xFF,
841 (data->ipAddr >> 16) & 0xFF,
842 (data->ipAddr >> 24) & 0xFF);
844 printf("data->platformId: %s\r\n", data->platformId);
846 printf("data->deviceName: %s\r\n", data->deviceName);
848 // Some diag output ...
850 printf("Sending BOOTME request [%d] to ", net->seqNum);
851 print_IPaddr(net->srvAddrSend.sin_addr);
855 net->dataLen = BOOTME_PKT_SIZE;
857 debug("Start of buffer: %p\n", net->data);
858 debug("Start of ethernet buffer: %p\n", &net->data[net->align_offset]);
859 debug("Start of CE header: %p\n", header);
860 debug("Start of CE data: %p\n", data);
862 pkt = &net->data[net->align_offset];
863 debug("packet to send (ceconnect): \n");
864 for (i = 0; i < net->dataLen + ETHER_HDR_SIZE + IP_HDR_SIZE; i++) {
865 debug("0x%02X ", pkt[i]);
871 memcpy(NetServerEther, NetBcastAddr, 6);
872 return ce_send_frame(net);
875 static int ce_init_download_link(ce_net *net, ce_bin *bin,
876 struct sockaddr_in *host_addr, int verbose)
879 unsigned long aligned_address;
881 if (!eth_get_dev()) {
882 printf("No network interface available\n");
885 printf("Usinge device '%s'\n", eth_get_name());
887 /* Initialize EDBG link for download */
888 memset(net, 0, sizeof(*net));
890 /* our buffer contains space for ethernet- ip- and udp- headers */
891 /* calculate an offset so that our ce field is aligned to 4 bytes */
892 aligned_address = (unsigned long)net->data;
893 /* we need 42 bytes room for headers (14 Ethernet , 20 IPv4, 8 UDP) */
894 aligned_address += ETHER_HDR_SIZE + IP_HDR_SIZE;
895 /* want CE header aligned to 4 Byte boundary */
896 net->align_offset = (4 - (aligned_address % 4)) % 4;
898 net->locAddr.sin_family = AF_INET;
899 net->locAddr.sin_addr = getenv_IPaddr("ipaddr");
900 net->locAddr.sin_port = htons(EDBG_DOWNLOAD_PORT);
902 net->srvAddrSend.sin_family = AF_INET;
903 net->srvAddrSend.sin_port = htons(EDBG_DOWNLOAD_PORT);
905 net->srvAddrRecv.sin_family = AF_INET;
906 net->srvAddrRecv.sin_port = 0;
908 if (host_addr->sin_addr) {
909 /* Use specified host address ... */
910 net->srvAddrSend.sin_addr = host_addr->sin_addr;
911 net->srvAddrRecv.sin_addr = host_addr->sin_addr;
913 /* ... or default server address */
914 net->srvAddrSend.sin_addr = getenv_IPaddr("serverip");
915 net->srvAddrRecv.sin_addr = getenv_IPaddr("serverip");
918 net->verbose = verbose;
920 ce_init_bin(bin, &net->data[CE_DOFFSET + 4]);
924 #ifdef CONFIG_NET_MULTI
927 ret = eth_init(gd->bd);
929 printf("ceconnect: failed to init ethernet: %d\n", ret);
934 puts("ceconnect: init ethernet done!\n");
936 memcpy(NetOurEther, eth_get_dev()->enetaddr, ETH_ALEN);
937 NetCopyIP(&NetOurIP, &gd->bd->bi_ip_addr);
938 NetOurGatewayIP = getenv_IPaddr("gatewayip");
939 NetOurSubnetMask = getenv_IPaddr("netmask");
940 NetServerIP = getenv_IPaddr("serverip");
944 static int do_ceconnect(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
947 int verbose = 0, use_timeout = 0;
948 int timeout = 0, recv_timeout, ret;
949 struct sockaddr_in host_ip_addr;
951 for (i = 1; i < argc; i++){
954 if (argv[i][1] == 'v') {
956 } else if (argv[i][1] == 't') {
959 timeout = simple_strtoul(argv[i],
963 printf("Option requires an argument - t\n");
969 memset(&host_ip_addr, 0xff, sizeof(host_ip_addr));
971 if (ce_init_download_link(&g_net, &g_bin, &host_ip_addr, verbose) != 0)
980 if (use_timeout && timeout <= 0) {
981 printf("CELOAD - Canceled, timeout\n");
986 printf("CELOAD - canceled by user\n");
991 debug("sending broadcast frame bootme\n");
993 if (ce_send_bootme(&g_net)) {
994 printf("CELOAD - error while sending BOOTME request\n");
998 debug("net state is: %d\n", NetState);
1001 printf("Waiting for connection, timeout %d sec\n", timeout);
1003 printf("Waiting for connection, enter ^C to abort\n");
1008 if (ce_recv_frame(&g_net, recv_timeout)) {
1009 ret = ce_process_download(&g_net, &g_bin);
1010 if (ret != CE_PR_MORE)
1012 } else if (use_timeout) {
1013 timeout -= recv_timeout;
1018 // Try to receive edbg commands from host
1019 ce_init_edbg_link(&g_net);
1021 printf("Waiting for EDBG commands ...\n");
1023 while (ce_recv_frame(&g_net, 3))
1024 ce_process_edbg(&g_net, &g_bin);
1026 // Prepare WinCE image for execution
1027 ce_prepare_run_bin(&g_bin);
1029 // Launch WinCE, if necessary
1030 if (g_net.gotJumpingRequest)
1031 ce_run_bin(g_bin.eEntryPoint);
1038 ceconnect, 4, 1, do_ceconnect,
1039 "ceconnect - Set up a connection to the CE host PC over TCP/IP and download the run-time image\n",
1040 "ceconnect [-v] [-t <timeout>]\n"
1041 " -v verbose operation\n"
1042 " -t <timeout> - max wait time (#sec) for the connection\n"