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,
36 #include <asm/errno.h>
38 DECLARE_GLOBAL_DATA_PTR;
40 #define WINCE_VRAM_BASE 0x80000000
41 #define CE_FIX_ADDRESS(a) ((void *)((a) - WINCE_VRAM_BASE + CONFIG_SYS_SDRAM_BASE))
44 #define INT_MAX ((int)(~0 >> 1))
47 /* Bin image parse states */
48 #define CE_PS_RTI_ADDR 0
49 #define CE_PS_RTI_LEN 1
50 #define CE_PS_E_ADDR 2
52 #define CE_PS_E_CHKSUM 4
53 #define CE_PS_E_DATA 5
55 #define CE_MIN(a, b) (((a) < (b)) ? (a) : (b))
56 #define CE_MAX(a, b) (((a) > (b)) ? (a) : (b))
59 #define STRMAC(s) _STRMAC(s)
61 static ce_bin __attribute__ ((aligned (32))) g_bin;
62 static ce_net __attribute__ ((aligned (32))) g_net;
63 static IPaddr_t server_ip;
65 static void ce_init_bin(ce_bin *bin, unsigned char *dataBuffer)
67 memset(bin, 0, sizeof(*bin));
69 debug("%s@%d: \n", __func__, __LINE__);
70 bin->data = dataBuffer;
71 bin->parseState = CE_PS_RTI_ADDR;
72 bin->parsePtr = (unsigned char *)bin;
73 debug("%s@%d: \n", __func__, __LINE__);
76 static int ce_is_bin_image(void *image, int imglen)
78 if (imglen < CE_BIN_SIGN_LEN) {
82 return memcmp(image, CE_BIN_SIGN, CE_BIN_SIGN_LEN) == 0;
85 static const struct ce_magic {
88 ce_std_driver_globals drv_glb;
89 } ce_magic_template = {
91 .size = sizeof(ce_std_driver_globals),
94 .signature = STD_DRV_GLB_SIGNATURE,
102 static void __attribute__((unused)) ce_dump_block(void *ptr, int length)
108 for (i = 0; i < length; i++) {
110 printf("\n%p: ", ptr + i);
113 printf("%02x ", p[i]);
114 if (!((i + 1) % 16)){
116 for (j = i - 15; j <= i; j++){
117 if((p[j] > 0x1f) && (p[j] < 0x7f)) {
128 static inline void ce_dump_block(void *ptr, int length)
133 static void ce_setup_std_drv_globals(ce_std_driver_globals *std_drv_glb)
135 char *mtdparts = getenv("mtdparts");
136 size_t max_len = ALIGN((unsigned long)std_drv_glb, SZ_4K) -
137 (unsigned long)&std_drv_glb->mtdparts;
140 memcpy(&std_drv_glb->kitl.mac, eth_get_dev()->enetaddr,
141 sizeof(std_drv_glb->kitl.mac));
143 snprintf(std_drv_glb->deviceId, sizeof(std_drv_glb->deviceId),
144 "Triton%02X", eth_get_dev()->enetaddr[5]);
146 NetCopyIP(&std_drv_glb->kitl.ipAddress, &NetOurIP);
147 std_drv_glb->kitl.ipMask = getenv_IPaddr("netmask");
148 std_drv_glb->kitl.ipRoute = getenv_IPaddr("gatewayip");
151 strncpy(std_drv_glb->mtdparts, mtdparts, max_len);
152 std_drv_glb->mtdparts[max_len - 1] = '\0';
154 printf("Failed to get mtdparts environment variable\n");
158 static void ce_prepare_run_bin(ce_bin *bin)
160 ce_driver_globals *drv_glb;
161 struct ce_magic *ce_magic = (void *)CONFIG_SYS_SDRAM_BASE + 0x160;
162 ce_std_driver_globals *std_drv_glb = &ce_magic->drv_glb;
164 /* Clear os RAM area (if needed) */
165 if (bin->edbgConfig.flags & EDBG_FL_CLEANBOOT) {
166 debug("cleaning memory from %p to %p\n",
167 bin->eRamStart, bin->eRamStart + bin->eRamLen);
169 printf("Preparing clean boot ... ");
170 memset(bin->eRamStart, 0, bin->eRamLen);
174 /* Prepare driver globals (if needed) */
176 debug("Copying CE MAGIC from %p to %p..%p\n",
177 &ce_magic_template, ce_magic,
178 (void *)ce_magic + sizeof(*ce_magic) - 1);
179 memcpy(ce_magic, &ce_magic_template, sizeof(*ce_magic));
181 ce_setup_std_drv_globals(std_drv_glb);
182 ce_magic->size = sizeof(*std_drv_glb) +
183 strlen(std_drv_glb->mtdparts) + 1;
184 ce_dump_block(ce_magic, offsetof(struct ce_magic, drv_glb) +
187 drv_glb = bin->eDrvGlb;
188 memset(drv_glb, 0, sizeof(*drv_glb));
190 drv_glb->signature = DRV_GLB_SIGNATURE;
192 /* Local ethernet MAC address */
193 memcpy(drv_glb->macAddr, std_drv_glb->kitl.mac,
194 sizeof(drv_glb->macAddr));
195 debug("got MAC address %02x:%02x:%02x:%02x:%02x:%02x from environment\n",
196 drv_glb->macAddr[0], drv_glb->macAddr[1],
197 drv_glb->macAddr[2], drv_glb->macAddr[3],
198 drv_glb->macAddr[4], drv_glb->macAddr[5]);
200 /* Local IP address */
201 drv_glb->ipAddr = getenv_IPaddr("ipaddr");
204 drv_glb->ipMask = getenv_IPaddr("netmask");
207 drv_glb->ipGate = getenv_IPaddr("gatewayip");
209 debug("got IP address %pI4 from environment\n", &drv_glb->ipAddr);
210 debug("got IP mask %pI4 from environment\n", &drv_glb->ipMask);
211 debug("got gateway address %pI4 from environment\n", &drv_glb->ipGate);
213 /* EDBG services config */
214 memcpy(&drv_glb->edbgConfig, &bin->edbgConfig,
215 sizeof(bin->edbgConfig));
219 * Make sure, all the above makes it into SDRAM because
220 * WinCE switches the cache & MMU off, obviously without
226 static int ce_lookup_ep_bin(ce_bin *bin)
229 ce_toc_entry *tentry;
232 uint32_t *sig = (uint32_t *)(bin->rtiPhysAddr + ROM_SIGNATURE_OFFSET);
234 debug("Looking for TOC signature at %p\n", sig);
236 /* Check image Table Of Contents (TOC) signature */
237 if (*sig != ROM_SIGNATURE) {
238 printf("Error: Did not find image TOC signature!\n");
239 printf("Expected %08x at address %p; found %08x instead\n",
240 ROM_SIGNATURE, sig, *sig);
244 /* Lookup entry point */
245 header = CE_FIX_ADDRESS(*(unsigned int *)(bin->rtiPhysAddr +
246 ROM_SIGNATURE_OFFSET +
247 sizeof(unsigned int)));
248 tentry = (ce_toc_entry *)(header + 1);
250 for (i = 0; i < header->nummods; i++) {
251 // Look for 'nk.exe' module
252 if (strcmp(CE_FIX_ADDRESS(tentry[i].fileName), "nk.exe") == 0) {
253 // Save entry point and RAM addresses
255 e32 = CE_FIX_ADDRESS(tentry[i].e32Offset);
257 bin->eEntryPoint = CE_FIX_ADDRESS(tentry[i].loadOffset) +
259 bin->eRamStart = CE_FIX_ADDRESS(header->ramStart);
260 bin->eRamLen = header->ramEnd - header->ramStart;
261 // Save driver_globals address
262 // Must follow RAM section in CE config.bib file
266 // RAM 80900000 03200000 RAM
267 // DRV_GLB 83B00000 00001000 RESERVED
269 bin->eDrvGlb = CE_FIX_ADDRESS(header->ramEnd);
274 // Error: Did not find 'nk.exe' module
278 static int ce_parse_bin(ce_bin *bin)
280 unsigned char *pbData = g_net.data + 4;//bin->data;
281 int len = bin->dataLen;
284 debug("starting ce image parsing:\n\tbin->binLen: 0x%08X\n", bin->binLen);
285 debug("\tlen=%d\n", len);
286 debug("\tparse_state=%d\n", bin->parseState);
289 ce_dump_block(pbData, len);
291 if (bin->binLen > 1024)
294 if (bin->binLen == 0) {
295 // Check for the .BIN signature first
296 if (!ce_is_bin_image(pbData, len)) {
297 printf("Error: Invalid or corrupted .BIN image!\n");
301 printf("Loading Windows CE .BIN image ...\n");
303 len -= CE_BIN_SIGN_LEN;
304 pbData += CE_BIN_SIGN_LEN;
308 switch (bin->parseState) {
314 copyLen = CE_MIN(sizeof(unsigned int) - bin->parseLen, len);
315 memcpy(&bin->parsePtr[bin->parseLen], pbData, copyLen);
317 bin->parseLen += copyLen;
321 if (bin->parseLen == sizeof(unsigned int)) {
322 if (bin->parseState == CE_PS_RTI_ADDR)
323 bin->rtiPhysAddr = CE_FIX_ADDRESS(bin->rtiPhysAddr);
324 else if (bin->parseState == CE_PS_E_ADDR &&
326 bin->ePhysAddr = CE_FIX_ADDRESS(bin->ePhysAddr);
330 bin->parsePtr += sizeof(unsigned int);
332 if (bin->parseState == CE_PS_E_DATA) {
333 if (bin->ePhysAddr) {
334 bin->parsePtr = bin->ePhysAddr;
335 bin->parseChkSum = 0;
346 debug("ePhysAddr=%p physlen=%08x parselen=%08x\n",
347 bin->ePhysAddr, bin->ePhysLen, bin->parseLen);
348 if (bin->ePhysAddr) {
349 copyLen = CE_MIN(bin->ePhysLen - bin->parseLen, len);
350 bin->parseLen += copyLen;
354 bin->parseChkSum += *pbData;
355 *bin->parsePtr++ = *pbData++;
358 if (bin->parseLen == bin->ePhysLen) {
359 printf("Section [%02d]: address %p, size 0x%08X, checksum %s\n",
363 (bin->eChkSum == bin->parseChkSum) ? "ok" : "fail");
365 if (bin->eChkSum != bin->parseChkSum) {
366 printf("Error: Checksum error, corrupted .BIN file!\n");
367 printf("checksum calculated: 0x%08x from file: 0x%08x\n",
368 bin->parseChkSum, bin->eChkSum);
374 bin->parseState = CE_PS_E_ADDR;
376 bin->parsePtr = (unsigned char *)&bin->ePhysAddr;
389 if (!ce_lookup_ep_bin(bin)) {
390 printf("Error: entry point not found!\n");
395 printf("Entry point: %p, address range: %p-%p\n",
398 bin->rtiPhysAddr + bin->rtiPhysLen);
404 bin->binLen += bin->dataLen;
408 static int ce_bin_load(void *image, int imglen)
410 ce_init_bin(&g_bin, image);
411 g_bin.dataLen = imglen;
412 if (ce_parse_bin(&g_bin) == CE_PR_EOF) {
413 ce_prepare_run_bin(&g_bin);
420 static void ce_run_bin(void (*entry)(void))
422 printf("Launching Windows CE ...\n");
429 static int do_bootce(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
436 addr = (void *)simple_strtoul(argv[1], NULL, 16);
437 image_size = INT_MAX; /* actually we do not know the image size */
438 } else if (getenv("fileaddr") != NULL) {
439 addr = (void *)getenv_ulong("fileaddr", 16, 0);
440 image_size = getenv_ulong("filesize", 16, INT_MAX);
442 printf ("Usage:\n%s\n", cmdtp->usage);
446 printf ("## Booting Windows CE Image from address %p ...\n", addr);
448 /* check if there is a valid windows CE image */
449 if (ce_is_bin_image(addr, image_size)) {
450 if (!ce_bin_load(addr, image_size)) {
451 /* Ops! Corrupted .BIN image! */
452 /* Handle error here ... */
453 printf("corrupted .BIN image !!!\n");
456 if ((s = getenv("autostart")) != NULL) {
459 * just use bootce to load the image to SDRAM;
460 * Do not start it automatically.
462 setenv_addr("fileaddr",
467 ce_run_bin(g_bin.eEntryPoint); /* start the image */
469 printf("Image does not seem to be a valid Windows CE image!\n");
472 return 1; /* never reached - just to keep compiler happy */
476 bootce, 2, 0, do_bootce,
477 "bootce\t- Boot a Windows CE image from memory \n",
479 "\taddr\t\t-boot image from address addr\n"
482 static int ce_send_write_ack(ce_net *net)
485 unsigned short wdata[2];
488 wdata[0] = htons(EDBG_CMD_WRITE_ACK);
489 wdata[1] = htons(net->blockNum);
490 net->dataLen = sizeof(wdata);
491 memcpy(net->data, wdata, net->dataLen);
494 ret = bootme_send_frame(net->data, net->dataLen);
496 printf("Failed to send write ack %d; retries=%d\n",
500 } while (ret != 0 && retries-- > 0);
504 static enum bootme_state ce_process_download(ce_net *net, ce_bin *bin)
506 int ret = net->state;
508 if (net->dataLen >= 4) {
509 unsigned short command;
510 unsigned short blknum;
512 memcpy(&command, net->data, sizeof(command));
513 command = ntohs(command);
514 debug("command found: 0x%04X\n", command);
516 if (net->state == BOOTME_DOWNLOAD) {
517 unsigned short nxt = net->blockNum + 1;
519 memcpy(&blknum, &net->data[2], sizeof(blknum));
520 blknum = ntohs(blknum);
522 net->blockNum = blknum;
525 int rc = ce_send_write_ack(net);
527 printf("Dropping out of sequence packet with ID %d (expected %d)\n",
537 case EDBG_CMD_WRITE_REQ:
538 if (net->state == BOOTME_INIT) {
539 // Check file name for WRITE request
540 // CE EShell uses "boot.bin" file name
542 printf(">>>>>>>> First Frame, IP: %s, port: %d\n",
543 inet_ntoa((in_addr_t *)&net->srvAddrRecv),
544 ntohs(net->srvAddrRecv.sin_port));
546 if (strncmp((char *)&net->data[2],
547 "boot.bin", 8) == 0) {
550 printf("Locked Down download link, IP: %pI4\n",
552 printf("Sending BOOTME request [%d] to %pI4\n",
553 net->seqNum, &NetServerIP);
556 // Lock down EShell download link
558 ret = BOOTME_DOWNLOAD;
561 printf("Unknown link\n");
564 if (ret == BOOTME_DOWNLOAD) {
565 int rc = ce_send_write_ack(net);
574 bin->dataLen = net->dataLen - 4;
575 ret = ce_parse_bin(bin);
576 if (ret != CE_PR_ERROR) {
577 int rc = ce_send_write_ack(net);
580 if (ret == CE_PR_EOF)
587 case EDBG_CMD_READ_REQ:
588 printf("Ignoring EDBG_CMD_READ_REQ\n");
589 /* Read requests are not supported
595 printf("Error: unknown error on the host side\n");
602 printf("unknown command 0x%04X\n", command);
603 net->state = BOOTME_ERROR;
609 static enum bootme_state ce_process_edbg(ce_net *net, ce_bin *bin)
611 enum bootme_state ret = net->state;
614 debug("%s: received packet of %u byte @ %p\n", __func__, net->dataLen, net->data);
615 if (net->dataLen < sizeof(header)) {
617 printf("Invalid packet size %u\n", net->dataLen);
621 debug("%s@%d: Copying header from %p..%p to %p\n", __func__, __LINE__,
622 net->data, net->data + sizeof(header) - 1, &header);
623 memcpy(&header, net->data, sizeof(header));
624 if (header.id != EDBG_ID) {
626 printf("Bad EDBG ID %08x\n", header.id);
631 debug("%s@%d\n", __func__, __LINE__);
632 if (header.service != EDBG_SVC_ADMIN) {
633 /* Unknown service */
634 printf("Bad EDBG service %02x\n", header.service);
639 debug("%s@%d\n", __func__, __LINE__);
640 if (net->state == BOOTME_INIT) {
641 /* Some diag output */
643 printf("Locked Down EDBG service link, IP: %pI4\n",
647 /* Lock down EDBG link */
649 net->state = BOOTME_DEBUG;
652 debug("%s@%d\n", __func__, __LINE__);
653 switch (header.cmd) {
654 case EDBG_CMD_JUMPIMG:
655 debug("%s@%d\n", __func__, __LINE__);
656 net->gotJumpingRequest = 1;
659 printf("Received JUMPING command\n");
661 /* Just pass through and copy CONFIG structure */
662 case EDBG_CMD_OS_CONFIG:
663 debug("%s@%d\n", __func__, __LINE__);
664 /* Copy config structure */
665 memcpy(&bin->edbgConfig, header.data,
666 sizeof(edbg_os_config_data));
668 printf("Received CONFIG command\n");
669 if (bin->edbgConfig.flags & EDBG_FL_DBGMSG) {
670 printf("--> Enabling DBGMSG service, IP: %d.%d.%d.%d, port: %d\n",
671 (bin->edbgConfig.dbgMsgIPAddr >> 0) & 0xFF,
672 (bin->edbgConfig.dbgMsgIPAddr >> 8) & 0xFF,
673 (bin->edbgConfig.dbgMsgIPAddr >> 16) & 0xFF,
674 (bin->edbgConfig.dbgMsgIPAddr >> 24) & 0xFF,
675 ntohs(bin->edbgConfig.dbgMsgPort));
678 if (bin->edbgConfig.flags & EDBG_FL_PPSH) {
679 printf("--> Enabling PPSH service, IP: %d.%d.%d.%d, port: %d\n",
680 (bin->edbgConfig.ppshIPAddr >> 0) & 0xFF,
681 (bin->edbgConfig.ppshIPAddr >> 8) & 0xFF,
682 (bin->edbgConfig.ppshIPAddr >> 16) & 0xFF,
683 (bin->edbgConfig.ppshIPAddr >> 24) & 0xFF,
684 ntohs(bin->edbgConfig.ppshPort));
687 if (bin->edbgConfig.flags & EDBG_FL_KDBG) {
688 printf("--> Enabling KDBG service, IP: %d.%d.%d.%d, port: %d\n",
689 (bin->edbgConfig.kdbgIPAddr >> 0) & 0xFF,
690 (bin->edbgConfig.kdbgIPAddr >> 8) & 0xFF,
691 (bin->edbgConfig.kdbgIPAddr >> 16) & 0xFF,
692 (bin->edbgConfig.kdbgIPAddr >> 24) & 0xFF,
693 ntohs(bin->edbgConfig.kdbgPort));
696 if (bin->edbgConfig.flags & EDBG_FL_CLEANBOOT) {
697 printf("--> Force clean boot\n");
705 printf("Received unknown command: %08X\n", header.cmd);
710 /* Respond with ack */
711 header.flags = EDBG_FL_FROM_DEV | EDBG_FL_ACK;
712 net->dataLen = EDBG_DATA_OFFSET;
713 debug("%s@%d: sending packet %p len %u\n", __func__, __LINE__,
714 net->data, net->dataLen);
715 bootme_send_frame(net->data, net->dataLen);
719 static enum bootme_state ce_edbg_handler(const void *buf, size_t len)
721 enum bootme_state ret;
724 _debug("%s: EOF\n", __func__);
728 if (len > sizeof(g_net.data)) {
729 debug("Dropping oversized packet of %u bytes (max. size %u)\n",
730 len, sizeof(g_net.data));
733 debug("Copying network packet of %u bytes from %p to %p\n",
734 len, buf, g_net.data);
735 memcpy(g_net.data, buf, len);
738 g_net.data = (void *)buf;
741 ret = ce_process_edbg(&g_net, &g_bin);
745 static void ce_init_edbg_link(ce_net *net)
747 /* Initialize EDBG link for commands */
748 net->state = BOOTME_INIT;
751 static enum bootme_state ce_download_handler(const void *buf, size_t len)
754 if (len > sizeof(g_net.data)) {
755 debug("Dropping oversized packet of %u bytes (max. size %u)\n",
756 len, sizeof(g_net.data));
759 debug("Copying network packet of %u bytes from %p to %p\n",
760 len, buf, g_net.data);
761 memcpy(g_net.data, buf, len);
764 g_net.data = (void *)buf;
767 g_net.state = ce_process_download(&g_net, &g_bin);
771 static int ce_send_bootme(ce_net *net)
774 edbg_bootme_data *data;
775 unsigned char txbuf[PKTSIZE_ALIGN];
780 /* Fill out BOOTME packet */
782 assert(net->data != NULL);
783 memset(net->data, 0, PKTSIZE);
784 header = (eth_dbg_hdr *)net->data;
785 data = (edbg_bootme_data *)header->data;
787 header->id = EDBG_ID;
788 header->service = EDBG_SVC_ADMIN;
789 header->flags = EDBG_FL_FROM_DEV;
790 header->seqNum = net->seqNum++;
791 header->cmd = EDBG_CMD_BOOTME;
793 data->versionMajor = 0;
794 data->versionMinor = 0;
795 data->cpuId = EDBG_CPU_TYPE_ARM;
796 data->bootmeVer = EDBG_CURRENT_BOOTME_VERSION;
798 data->downloadPort = 0;
801 /* MAC address from environment*/
802 if (!eth_getenv_enetaddr("ethaddr", data->macAddr)) {
803 printf("'ethaddr' is not set or invalid\n");
804 memset(data->macAddr, 0, sizeof(data->macAddr));
807 /* IP address from active config */
808 NetCopyIP(&data->ipAddr, &NetOurIP);
810 // Device name string (NULL terminated). Should include
811 // platform and number based on Ether address (e.g. Odo42, CEPCLS2346, etc)
813 // We will use lower MAC address segment to create device name
814 // eg. MAC '00-0C-C6-69-09-05', device name 'Triton05'
816 strncpy(data->platformId, "Triton", sizeof(data->platformId));
817 snprintf(data->deviceName, sizeof(data->deviceName), "%s%02X",
818 data->platformId, data->macAddr[5]);
821 printf("header->id: %08X\r\n", header->id);
822 printf("header->service: %08X\r\n", header->service);
823 printf("header->flags: %08X\r\n", header->flags);
824 printf("header->seqNum: %08X\r\n", header->seqNum);
825 printf("header->cmd: %08X\r\n\r\n", header->cmd);
827 printf("data->versionMajor: %08X\r\n", data->versionMajor);
828 printf("data->versionMinor: %08X\r\n", data->versionMinor);
829 printf("data->cpuId: %08X\r\n", data->cpuId);
830 printf("data->bootmeVer: %08X\r\n", data->bootmeVer);
831 printf("data->bootFlags: %08X\r\n", data->bootFlags);
832 printf("data->svcPort: %08X\r\n\r\n", ntohs(data->svcPort));
834 printf("data->macAddr: %02X-%02X-%02X-%02X-%02X-%02X\r\n",
835 data->macAddr[0], data->macAddr[1],
836 data->macAddr[2], data->macAddr[3],
837 data->macAddr[4], data->macAddr[5]);
839 printf("data->ipAddr: %d.%d.%d.%d\r\n",
840 (data->ipAddr >> 0) & 0xFF,
841 (data->ipAddr >> 8) & 0xFF,
842 (data->ipAddr >> 16) & 0xFF,
843 (data->ipAddr >> 24) & 0xFF);
845 printf("data->platformId: %s\r\n", data->platformId);
847 printf("data->deviceName: %s\r\n", data->deviceName);
849 // Some diag output ...
851 printf("Sending BOOTME request [%d] to %pI4\n", net->seqNum,
855 net->dataLen = BOOTME_PKT_SIZE;
856 // net->status = CE_PR_MORE;
857 net->state = BOOTME_INIT;
859 debug("Start of buffer: %p\n", net->data);
860 debug("Start of ethernet buffer: %p\n", net->data);
861 debug("Start of CE header: %p\n", header);
862 debug("Start of CE data: %p\n", data);
865 debug("packet to send (ceconnect): \n");
866 for (i = 0; i < net->dataLen; i++) {
867 debug("0x%02X ", pkt[i]);
873 return BootMeRequest(server_ip, net->data, net->dataLen, 1);
876 static inline int ce_init_download_link(ce_net *net, ce_bin *bin, int verbose)
878 if (!eth_get_dev()) {
879 printf("No network interface available\n");
882 printf("Using device '%s'\n", eth_get_name());
884 /* Initialize EDBG link for download */
885 memset(net, 0, sizeof(*net));
887 net->verbose = verbose;
889 ce_init_bin(bin, NULL);//&net->data[4]);
893 #define UINT_MAX ~0UL
895 static inline int ce_download_file(ce_net *net, ulong timeout)
897 ulong start = get_timer_masked();
899 while (net->state == BOOTME_INIT) {
902 if (timeout && get_timer(start) > timeout) {
903 printf("CELOAD - Canceled, timeout\n");
908 printf("CELOAD - canceled by user\n");
912 if (ce_send_bootme(&g_net)) {
913 printf("CELOAD - error while sending BOOTME request\n");
918 printf("Waiting for connection, timeout %lu sec\n",
919 DIV_ROUND_UP(timeout - get_timer(start),
922 printf("Waiting for connection, enter ^C to abort\n");
926 ret = BootMeDownload(ce_download_handler);
927 printf("BootMeDownload() returned %d\n", ret);
928 if (ret == BOOTME_ERROR) {
929 printf("CELOAD - aborted\n");
936 static void ce_disconnect(void)
938 net_set_udp_handler(NULL);
942 static int do_ceconnect(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
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],
961 if (timeout >= UINT_MAX / CONFIG_SYS_HZ) {
962 printf("Timeout value %lu out of range (max.: %lu)\n",
963 timeout, UINT_MAX / CONFIG_SYS_HZ - 1);
966 timeout *= CONFIG_SYS_HZ;
968 printf("Option requires an argument - t\n");
971 } else if (argv[i][1] == 'h') {
974 server_ip = string_to_ip(argv[i]);
975 printf("Using server %pI4\n", &server_ip);
977 printf("Option requires an argument - t\n");
983 if (ce_init_download_link(&g_net, &g_bin, verbose) != 0)
986 if (ce_download_file(&g_net, timeout))
992 // Try to receive edbg commands from host
993 _debug("%s@%d: \n", __func__, __LINE__);
994 ce_init_edbg_link(&g_net);
995 _debug("%s@%d: \n", __func__, __LINE__);
997 printf("Waiting for EDBG commands ...\n");
999 _debug("%s@%d: \n", __func__, __LINE__);
1000 ret = BootMeDebugStart(ce_edbg_handler);
1001 _debug("%s@%d: ret=%d\n", __func__, __LINE__, ret);
1002 if (ret != BOOTME_DONE)
1004 _debug("%s@%d: \n", __func__, __LINE__);
1006 // Prepare WinCE image for execution
1007 ce_prepare_run_bin(&g_bin);
1008 _debug("%s@%d: \n", __func__, __LINE__);
1010 // Launch WinCE, if necessary
1011 if (g_net.gotJumpingRequest)
1012 ce_run_bin(g_bin.eEntryPoint);
1013 _debug("%s@%d: \n", __func__, __LINE__);
1022 ceconnect, 4, 1, do_ceconnect,
1023 "ceconnect - Set up a connection to the CE host PC over TCP/IP and download the run-time image\n",
1024 "ceconnect [-v] [-t <timeout>]\n"
1025 " -v verbose operation\n"
1026 " -t <timeout> - max wait time (#sec) for the connection\n"