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,
30 #include <asm/errno.h>
31 #include <jffs2/load_kernel.h>
33 DECLARE_GLOBAL_DATA_PTR;
35 #define WINCE_VRAM_BASE 0x80000000
36 #define CE_FIX_ADDRESS(a) ((void *)((a) - WINCE_VRAM_BASE + CONFIG_SYS_SDRAM_BASE))
39 #define INT_MAX ((int)(~0U >> 1))
42 /* Bin image parse states */
43 #define CE_PS_RTI_ADDR 0
44 #define CE_PS_RTI_LEN 1
45 #define CE_PS_E_ADDR 2
47 #define CE_PS_E_CHKSUM 4
48 #define CE_PS_E_DATA 5
50 #define CE_MIN(a, b) (((a) < (b)) ? (a) : (b))
51 #define CE_MAX(a, b) (((a) > (b)) ? (a) : (b))
53 static ce_bin __attribute__ ((aligned (32))) g_bin;
54 static ce_net __attribute__ ((aligned (32))) g_net;
55 static IPaddr_t server_ip;
57 static void ce_init_bin(ce_bin *bin, unsigned char *dataBuffer)
59 memset(bin, 0, sizeof(*bin));
61 bin->data = dataBuffer;
62 bin->parseState = CE_PS_RTI_ADDR;
63 bin->parsePtr = (unsigned char *)bin;
66 static int ce_is_bin_image(void *image, int imglen)
68 if (imglen < CE_BIN_SIGN_LEN) {
72 return memcmp(image, CE_BIN_SIGN, CE_BIN_SIGN_LEN) == 0;
75 static const struct ce_magic {
78 ce_std_driver_globals drv_glb;
79 } ce_magic_template = {
81 .size = sizeof(ce_std_driver_globals),
84 .signature = STD_DRV_GLB_SIGNATURE,
92 static void __attribute__((unused)) ce_dump_block(void *ptr, int length)
98 for (i = 0; i < length; i++) {
100 printf("\n%p: ", ptr + i);
103 printf("%02x ", p[i]);
104 if (!((i + 1) % 16)){
106 for (j = i - 15; j <= i; j++){
107 if((p[j] > 0x1f) && (p[j] < 0x7f)) {
118 static inline void ce_dump_block(void *ptr, int length)
123 static void ce_setup_std_drv_globals(ce_std_driver_globals *std_drv_glb)
125 char *mtdparts = getenv("mtdparts");
126 size_t max_len = ALIGN((unsigned long)std_drv_glb, SZ_4K) -
127 (unsigned long)&std_drv_glb->mtdparts;
130 memcpy(&std_drv_glb->kitl.mac, eth_get_dev()->enetaddr,
131 sizeof(std_drv_glb->kitl.mac));
133 snprintf(std_drv_glb->deviceId, sizeof(std_drv_glb->deviceId),
134 "Triton%02X", eth_get_dev()->enetaddr[5]);
136 NetCopyIP(&std_drv_glb->kitl.ipAddress, &NetOurIP);
137 std_drv_glb->kitl.ipMask = getenv_IPaddr("netmask");
138 std_drv_glb->kitl.ipRoute = getenv_IPaddr("gatewayip");
141 strncpy(std_drv_glb->mtdparts, mtdparts, max_len);
142 std_drv_glb->mtdparts[max_len - 1] = '\0';
144 printf("Failed to get mtdparts environment variable\n");
148 static void ce_prepare_run_bin(ce_bin *bin)
150 ce_driver_globals *drv_glb;
151 struct ce_magic *ce_magic = (void *)CONFIG_SYS_SDRAM_BASE + 0x160;
152 ce_std_driver_globals *std_drv_glb = &ce_magic->drv_glb;
154 /* Clear os RAM area (if needed) */
155 if (bin->edbgConfig.flags & EDBG_FL_CLEANBOOT) {
156 debug("cleaning memory from %p to %p\n",
157 bin->eRamStart, bin->eRamStart + bin->eRamLen);
159 printf("Preparing clean boot ... ");
160 memset(bin->eRamStart, 0, bin->eRamLen);
164 /* Prepare driver globals (if needed) */
166 debug("Copying CE MAGIC from %p to %p..%p\n",
167 &ce_magic_template, ce_magic,
168 (void *)ce_magic + sizeof(*ce_magic) - 1);
169 memcpy(ce_magic, &ce_magic_template, sizeof(*ce_magic));
171 ce_setup_std_drv_globals(std_drv_glb);
172 ce_magic->size = sizeof(*std_drv_glb) +
173 strlen(std_drv_glb->mtdparts) + 1;
174 ce_dump_block(ce_magic, offsetof(struct ce_magic, drv_glb) +
177 drv_glb = bin->eDrvGlb;
178 memset(drv_glb, 0, sizeof(*drv_glb));
180 drv_glb->signature = DRV_GLB_SIGNATURE;
182 /* Local ethernet MAC address */
183 memcpy(drv_glb->macAddr, std_drv_glb->kitl.mac,
184 sizeof(drv_glb->macAddr));
185 debug("got MAC address %pM from environment\n",
188 /* Local IP address */
189 drv_glb->ipAddr = getenv_IPaddr("ipaddr");
192 drv_glb->ipMask = getenv_IPaddr("netmask");
195 drv_glb->ipGate = getenv_IPaddr("gatewayip");
197 debug("got IP address %pI4 from environment\n",
199 debug("got IP mask %pI4 from environment\n",
201 debug("got gateway address %pI4 from environment\n",
204 /* EDBG services config */
205 memcpy(&drv_glb->edbgConfig, &bin->edbgConfig,
206 sizeof(bin->edbgConfig));
210 * Make sure, all the above makes it into SDRAM because
211 * WinCE switches the cache & MMU off, obviously without
217 static int ce_lookup_ep_bin(ce_bin *bin)
220 ce_toc_entry *tentry;
223 uint32_t *sig = (uint32_t *)(bin->rtiPhysAddr + ROM_SIGNATURE_OFFSET);
225 debug("Looking for TOC signature at %p\n", sig);
227 /* Check image Table Of Contents (TOC) signature */
228 if (*sig != ROM_SIGNATURE) {
229 printf("Error: Did not find image TOC signature!\n");
230 printf("Expected %08x at address %p; found %08x instead\n",
231 ROM_SIGNATURE, sig, *sig);
235 /* Lookup entry point */
236 header = CE_FIX_ADDRESS(*(unsigned int *)(bin->rtiPhysAddr +
237 ROM_SIGNATURE_OFFSET +
238 sizeof(unsigned int)));
239 tentry = (ce_toc_entry *)(header + 1);
241 for (i = 0; i < header->nummods; i++) {
242 // Look for 'nk.exe' module
243 if (strcmp(CE_FIX_ADDRESS(tentry[i].fileName), "nk.exe") == 0) {
244 // Save entry point and RAM addresses
246 e32 = CE_FIX_ADDRESS(tentry[i].e32Offset);
248 bin->eEntryPoint = CE_FIX_ADDRESS(tentry[i].loadOffset) +
250 bin->eRamStart = CE_FIX_ADDRESS(header->ramStart);
251 bin->eRamLen = header->ramEnd - header->ramStart;
252 // Save driver_globals address
253 // Must follow RAM section in CE config.bib file
257 // RAM 80900000 03200000 RAM
258 // DRV_GLB 83B00000 00001000 RESERVED
260 bin->eDrvGlb = CE_FIX_ADDRESS(header->ramEnd);
265 // Error: Did not find 'nk.exe' module
269 static int ce_parse_bin(ce_bin *bin)
271 unsigned char *pbData = bin->data;
272 int len = bin->dataLen;
275 debug("starting ce image parsing:\n\tbin->binLen: 0x%08X\n", bin->binLen);
278 if (bin->binLen == 0) {
279 // Check for the .BIN signature first
280 if (!ce_is_bin_image(pbData, len)) {
281 printf("Error: Invalid or corrupted .BIN image!\n");
285 printf("Loading Windows CE .BIN image ...\n");
287 len -= CE_BIN_SIGN_LEN;
288 pbData += CE_BIN_SIGN_LEN;
292 switch (bin->parseState) {
298 copyLen = CE_MIN(sizeof(unsigned int) - bin->parseLen, len);
299 memcpy(&bin->parsePtr[bin->parseLen], pbData, copyLen);
301 bin->parseLen += copyLen;
305 if (bin->parseLen == sizeof(unsigned int)) {
306 if (bin->parseState == CE_PS_RTI_ADDR)
307 bin->rtiPhysAddr = CE_FIX_ADDRESS(bin->rtiPhysAddr);
308 else if (bin->parseState == CE_PS_E_ADDR &&
310 bin->ePhysAddr = CE_FIX_ADDRESS(bin->ePhysAddr);
314 bin->parsePtr += sizeof(unsigned int);
316 if (bin->parseState == CE_PS_E_DATA) {
317 if (bin->ePhysAddr) {
318 bin->parsePtr = bin->ePhysAddr;
319 bin->parseChkSum = 0;
330 debug("ePhysAddr=%p physlen=%08x parselen=%08x\n",
331 bin->ePhysAddr, bin->ePhysLen, bin->parseLen);
332 if (bin->ePhysAddr) {
333 copyLen = CE_MIN(bin->ePhysLen - bin->parseLen, len);
334 bin->parseLen += copyLen;
338 bin->parseChkSum += *pbData;
339 *bin->parsePtr++ = *pbData++;
342 if (bin->parseLen == bin->ePhysLen) {
343 printf("Section [%02d]: address %p, size 0x%08X, checksum %s\n",
347 (bin->eChkSum == bin->parseChkSum) ? "ok" : "fail");
349 if (bin->eChkSum != bin->parseChkSum) {
350 printf("Error: Checksum error, corrupted .BIN file!\n");
351 printf("checksum calculated: 0x%08x from file: 0x%08x\n",
352 bin->parseChkSum, bin->eChkSum);
358 bin->parseState = CE_PS_E_ADDR;
360 bin->parsePtr = (unsigned char *)&bin->ePhysAddr;
373 if (!ce_lookup_ep_bin(bin)) {
374 printf("Error: entry point not found!\n");
379 printf("Entry point: %p, address range: %p-%p\n",
382 bin->rtiPhysAddr + bin->rtiPhysLen);
388 bin->binLen += bin->dataLen;
392 static int ce_bin_load(void *image, int imglen)
394 ce_init_bin(&g_bin, image);
395 g_bin.dataLen = imglen;
396 if (ce_parse_bin(&g_bin) == CE_PR_EOF) {
397 ce_prepare_run_bin(&g_bin);
404 static void ce_run_bin(void (*entry)(void))
406 printf("Launching Windows CE ...\n");
413 static int do_bootce(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
419 addr = (void *)simple_strtoul(argv[1], NULL, 16);
420 image_size = INT_MAX; /* actually we do not know the image size */
421 } else if (getenv("fileaddr") != NULL) {
422 addr = (void *)getenv_ulong("fileaddr", 16, 0);
423 image_size = getenv_ulong("filesize", 16, INT_MAX);
425 return CMD_RET_USAGE;
428 printf ("## Booting Windows CE Image from address %p ...\n", addr);
430 /* check if there is a valid windows CE image */
431 if (ce_is_bin_image(addr, image_size)) {
432 if (!ce_bin_load(addr, image_size)) {
433 /* Ops! Corrupted .BIN image! */
434 /* Handle error here ... */
435 printf("corrupted .BIN image !!!\n");
436 return CMD_RET_FAILURE;
438 if (getenv_yesno("autostart") != 1) {
440 * just use bootce to load the image to SDRAM;
441 * Do not start it automatically.
443 setenv_addr("fileaddr", g_bin.eEntryPoint);
444 return CMD_RET_SUCCESS;
446 ce_run_bin(g_bin.eEntryPoint); /* start the image */
448 printf("Image does not seem to be a valid Windows CE image!\n");
449 return CMD_RET_FAILURE;
451 return CMD_RET_FAILURE; /* never reached - just to keep compiler happy */
454 bootce, 2, 0, do_bootce,
455 "Boot a Windows CE image from RAM\n",
457 "\taddr\t\tboot image from address addr (default ${fileaddr})\n"
460 static int ce_nand_load(ce_bin *bin, loff_t *offset, void *buf, size_t max_len)
463 size_t len = max_len;
464 nand_info_t *nand = &nand_info[0];
466 while (nand_block_isbad(nand, *offset & ~(max_len - 1))) {
467 printf("Skipping bad block 0x%08llx\n",
468 *offset & ~(max_len - 1));
470 if (*offset + max_len > nand->size)
474 ret = nand_read(nand, *offset, &len, buf);
482 static int do_nbootce(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
485 struct mtd_device *dev;
486 struct part_info *part_info;
491 size_t bufsize = nand_info[0].erasesize, len;
493 if (argc < 2 || argc > 3)
494 return CMD_RET_USAGE;
496 ret = mtdparts_init();
498 return CMD_RET_FAILURE;
500 offset = simple_strtoul(argv[1], &end, 16);
502 ret = find_dev_and_part(argv[1], &dev, &part_num,
505 printf("Partition '%s' not found\n", argv[1]);
506 return CMD_RET_FAILURE;
508 offset = part_info->offset;
509 printf ("## Booting Windows CE Image from NAND partition %s at offset %08llx\n",
512 printf ("## Booting Windows CE Image from NAND offset %08llx\n",
516 buffer = malloc(bufsize);
517 if (buffer == NULL) {
518 printf("Failed to allocate %u byte buffer\n", bufsize);
519 return CMD_RET_FAILURE;
522 ce_init_bin(&g_bin, buffer);
524 ret = ce_nand_load(&g_bin, &offset, buffer, bufsize);
526 printf("Failed to read NAND: %d\n", ret);
530 /* check if there is a valid windows CE image header */
531 if (ce_is_bin_image(buffer, len)) {
533 ret = ce_parse_bin(&g_bin);
538 printf("NBOOTCE - canceled by user\n");
542 len = ce_nand_load(&g_bin, &offset, buffer,
545 printf("Nand read error: %d\n", len);
556 } while (ret == CE_PR_MORE);
557 if (ret != CE_PR_EOF)
558 return CMD_RET_FAILURE;
561 if (getenv_yesno("autostart") != 1) {
563 * just use bootce to load the image to SDRAM;
564 * Do not start it automatically.
566 setenv_addr("fileaddr", g_bin.eEntryPoint);
567 return CMD_RET_SUCCESS;
569 ce_run_bin(g_bin.eEntryPoint); /* start the image */
571 printf("Image does not seem to be a valid Windows CE image!\n");
575 return CMD_RET_FAILURE;
578 nbootce, 2, 0, do_nbootce,
579 "Boot a Windows CE image from NAND\n",
581 "\toff\t\t- flash offset (hex)\n"
582 "\tpartition\t- partition name\n"
585 static int ce_send_write_ack(ce_net *net)
588 unsigned short wdata[2];
591 wdata[0] = htons(EDBG_CMD_WRITE_ACK);
592 wdata[1] = htons(net->blockNum);
593 net->dataLen = sizeof(wdata);
594 memcpy(net->data, wdata, net->dataLen);
597 ret = bootme_send_frame(net->data, net->dataLen);
599 printf("Failed to send write ack %d; retries=%d\n",
602 } while (ret != 0 && retries-- > 0);
606 static enum bootme_state ce_process_download(ce_net *net, ce_bin *bin)
608 int ret = net->state;
610 if (net->dataLen >= 4) {
611 unsigned short command;
612 unsigned short blknum;
614 memcpy(&command, net->data, sizeof(command));
615 command = ntohs(command);
616 debug("command found: 0x%04X\n", command);
618 if (net->state == BOOTME_DOWNLOAD) {
619 unsigned short nxt = net->blockNum + 1;
621 memcpy(&blknum, &net->data[2], sizeof(blknum));
622 blknum = ntohs(blknum);
624 net->blockNum = blknum;
626 int rc = ce_send_write_ack(net);
628 printf("Dropping out of sequence packet with ID %d (expected %d)\n",
638 case EDBG_CMD_WRITE_REQ:
639 if (net->state == BOOTME_INIT) {
640 // Check file name for WRITE request
641 // CE EShell uses "boot.bin" file name
642 if (strncmp((char *)&net->data[2],
643 "boot.bin", 8) == 0) {
646 printf("Locked Down download link, IP: %pI4\n",
648 printf("Sending BOOTME request [%d] to %pI4\n",
649 net->seqNum, &NetServerIP);
652 // Lock down EShell download link
653 ret = BOOTME_DOWNLOAD;
656 printf("Unknown link\n");
659 if (ret == BOOTME_DOWNLOAD) {
660 int rc = ce_send_write_ack(net);
669 bin->data = &net->data[4];
670 bin->dataLen = net->dataLen - 4;
671 ret = ce_parse_bin(bin);
672 if (ret != CE_PR_ERROR) {
673 int rc = ce_send_write_ack(net);
676 if (ret == CE_PR_EOF)
683 case EDBG_CMD_READ_REQ:
684 printf("Ignoring EDBG_CMD_READ_REQ\n");
685 /* Read requests are not supported
691 printf("Error: unknown error on the host side\n");
698 printf("unknown command 0x%04X\n", command);
699 net->state = BOOTME_ERROR;
705 static enum bootme_state ce_process_edbg(ce_net *net, ce_bin *bin)
707 enum bootme_state ret = net->state;
710 if (net->dataLen < sizeof(header)) {
712 printf("Invalid packet size %u\n", net->dataLen);
716 memcpy(&header, net->data, sizeof(header));
717 if (header.id != EDBG_ID) {
719 printf("Bad EDBG ID %08x\n", header.id);
724 if (header.service != EDBG_SVC_ADMIN) {
725 /* Unknown service */
726 printf("Bad EDBG service %02x\n", header.service);
731 if (net->state == BOOTME_INIT) {
732 /* Some diag output */
734 printf("Locked Down EDBG service link, IP: %pI4\n",
738 /* Lock down EDBG link */
739 net->state = BOOTME_DEBUG;
742 debug("%s@%d\n", __func__, __LINE__);
743 switch (header.cmd) {
744 case EDBG_CMD_JUMPIMG:
745 debug("%s@%d\n", __func__, __LINE__);
746 net->gotJumpingRequest = 1;
749 printf("Received JUMPING command\n");
751 /* Just pass through and copy CONFIG structure */
752 case EDBG_CMD_OS_CONFIG:
753 debug("%s@%d\n", __func__, __LINE__);
754 /* Copy config structure */
755 memcpy(&bin->edbgConfig, header.data,
756 sizeof(edbg_os_config_data));
758 printf("Received CONFIG command\n");
759 if (bin->edbgConfig.flags & EDBG_FL_DBGMSG) {
760 printf("--> Enabling DBGMSG service, IP: %pI4, port: %d\n",
761 &bin->edbgConfig.dbgMsgIPAddr,
762 ntohs(bin->edbgConfig.dbgMsgPort));
765 if (bin->edbgConfig.flags & EDBG_FL_PPSH) {
766 printf("--> Enabling PPSH service, IP: %pI4, port: %d\n",
767 &bin->edbgConfig.ppshIPAddr,
768 ntohs(bin->edbgConfig.ppshPort));
771 if (bin->edbgConfig.flags & EDBG_FL_KDBG) {
772 printf("--> Enabling KDBG service, IP: %pI4, port: %d\n",
773 &bin->edbgConfig.kdbgIPAddr,
774 ntohs(bin->edbgConfig.kdbgPort));
777 if (bin->edbgConfig.flags & EDBG_FL_CLEANBOOT) {
778 printf("--> Force clean boot\n");
786 printf("Received unknown command: %08X\n", header.cmd);
791 /* Respond with ack */
792 header.flags = EDBG_FL_FROM_DEV | EDBG_FL_ACK;
793 net->dataLen = EDBG_DATA_OFFSET;
794 debug("%s@%d: sending packet %p len %u\n", __func__, __LINE__,
795 net->data, net->dataLen);
796 bootme_send_frame(net->data, net->dataLen);
800 static enum bootme_state ce_edbg_handler(const void *buf, size_t len)
805 g_net.data = (void *)buf;
808 return ce_process_edbg(&g_net, &g_bin);
811 static void ce_init_edbg_link(ce_net *net)
813 /* Initialize EDBG link for commands */
814 net->state = BOOTME_INIT;
817 static enum bootme_state ce_download_handler(const void *buf, size_t len)
819 g_net.data = (void *)buf;
822 g_net.state = ce_process_download(&g_net, &g_bin);
826 static int ce_send_bootme(ce_net *net)
829 edbg_bootme_data *data;
830 unsigned char txbuf[PKTSIZE_ALIGN];
835 /* Fill out BOOTME packet */
838 memset(net->data, 0, PKTSIZE);
839 header = (eth_dbg_hdr *)net->data;
840 data = (edbg_bootme_data *)header->data;
842 header->id = EDBG_ID;
843 header->service = EDBG_SVC_ADMIN;
844 header->flags = EDBG_FL_FROM_DEV;
845 header->seqNum = net->seqNum++;
846 header->cmd = EDBG_CMD_BOOTME;
848 data->versionMajor = 0;
849 data->versionMinor = 0;
850 data->cpuId = EDBG_CPU_TYPE_ARM;
851 data->bootmeVer = EDBG_CURRENT_BOOTME_VERSION;
853 data->downloadPort = 0;
856 /* MAC address from environment*/
857 if (!eth_getenv_enetaddr("ethaddr", data->macAddr)) {
858 printf("'ethaddr' is not set or invalid\n");
859 memset(data->macAddr, 0, sizeof(data->macAddr));
862 /* IP address from active config */
863 NetCopyIP(&data->ipAddr, &NetOurIP);
865 // Device name string (NULL terminated). Should include
866 // platform and number based on Ether address (e.g. Odo42, CEPCLS2346, etc)
868 // We will use lower MAC address segment to create device name
869 // eg. MAC '00-0C-C6-69-09-05', device name 'Triton05'
871 strncpy(data->platformId, "Triton", sizeof(data->platformId));
872 snprintf(data->deviceName, sizeof(data->deviceName), "%s%02X",
873 data->platformId, data->macAddr[5]);
876 printf("header->id: %08X\n", header->id);
877 printf("header->service: %08X\n", header->service);
878 printf("header->flags: %08X\n", header->flags);
879 printf("header->seqNum: %08X\n", header->seqNum);
880 printf("header->cmd: %08X\n\n", header->cmd);
882 printf("data->versionMajor: %08X\n", data->versionMajor);
883 printf("data->versionMinor: %08X\n", data->versionMinor);
884 printf("data->cpuId: %08X\n", data->cpuId);
885 printf("data->bootmeVer: %08X\n", data->bootmeVer);
886 printf("data->bootFlags: %08X\n", data->bootFlags);
887 printf("data->svcPort: %08X\n\n", ntohs(data->svcPort));
889 printf("data->macAddr: %pM\n", data->macAddr);
890 printf("data->ipAddr: %pI4\n", &data->ipAddr);
891 printf("data->platformId: %s\n", data->platformId);
892 printf("data->deviceName: %s\n", data->deviceName);
894 // Some diag output ...
896 printf("Sending BOOTME request [%d] to %pI4\n", net->seqNum,
900 net->dataLen = BOOTME_PKT_SIZE;
901 // net->status = CE_PR_MORE;
902 net->state = BOOTME_INIT;
904 debug("Start of buffer: %p\n", net->data);
905 debug("Start of ethernet buffer: %p\n", net->data);
906 debug("Start of CE header: %p\n", header);
907 debug("Start of CE data: %p\n", data);
910 debug("packet to send (ceconnect): \n");
911 for (i = 0; i < net->dataLen; i++) {
912 debug("0x%02X ", pkt[i]);
918 return BootMeRequest(server_ip, net->data, net->dataLen, 1);
921 static inline int ce_init_download_link(ce_net *net, ce_bin *bin, int verbose)
923 if (!eth_get_dev()) {
924 printf("No network interface available\n");
927 printf("Using device '%s'\n", eth_get_name());
929 /* Initialize EDBG link for download */
930 memset(net, 0, sizeof(*net));
932 net->verbose = verbose;
934 /* buffer will be dynamically assigned in ce_download_handler() */
935 ce_init_bin(bin, NULL);
939 #define UINT_MAX ~0UL
941 static inline int ce_download_file(ce_net *net, ulong timeout)
943 ulong start = get_timer_masked();
945 while (net->state == BOOTME_INIT) {
948 if (timeout && get_timer(start) > timeout) {
949 printf("CELOAD - Canceled, timeout\n");
954 printf("CELOAD - canceled by user\n");
958 if (ce_send_bootme(&g_net)) {
959 printf("CELOAD - error while sending BOOTME request\n");
964 printf("Waiting for connection, timeout %lu sec\n",
965 DIV_ROUND_UP(timeout - get_timer(start),
968 printf("Waiting for connection, enter ^C to abort\n");
972 ret = BootMeDownload(ce_download_handler);
973 if (ret == BOOTME_ERROR) {
974 printf("CELOAD - aborted\n");
981 static void ce_disconnect(void)
983 net_set_udp_handler(NULL);
987 static int do_ceconnect(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
996 for (i = 1; i < argc; i++){
999 if (argv[i][1] == 'v') {
1001 } else if (argv[i][1] == 't') {
1004 timeout = simple_strtoul(argv[i],
1006 if (timeout >= UINT_MAX / CONFIG_SYS_HZ) {
1007 printf("Timeout value %lu out of range (max.: %lu)\n",
1008 timeout, UINT_MAX / CONFIG_SYS_HZ - 1);
1009 return CMD_RET_USAGE;
1011 timeout *= CONFIG_SYS_HZ;
1013 printf("Option requires an argument - t\n");
1014 return CMD_RET_USAGE;
1016 } else if (argv[i][1] == 'h') {
1019 server_ip = string_to_ip(argv[i]);
1020 printf("Using server %pI4\n", &server_ip);
1022 printf("Option requires an argument - t\n");
1023 return CMD_RET_USAGE;
1028 if (ce_init_download_link(&g_net, &g_bin, verbose) != 0)
1031 if (ce_download_file(&g_net, timeout))
1035 // Try to receive edbg commands from host
1036 ce_init_edbg_link(&g_net);
1038 printf("Waiting for EDBG commands ...\n");
1040 ret = BootMeDebugStart(ce_edbg_handler);
1041 if (ret != BOOTME_DONE)
1044 // Prepare WinCE image for execution
1045 ce_prepare_run_bin(&g_bin);
1047 // Launch WinCE, if necessary
1048 if (g_net.gotJumpingRequest)
1049 ce_run_bin(g_bin.eEntryPoint);
1054 return ret == 0 ? CMD_RET_SUCCESS : CMD_RET_FAILURE;
1057 ceconnect, 6, 1, do_ceconnect,
1058 "Set up a connection to the CE host PC over TCP/IP and download the run-time image\n",
1059 "[-v] [-t <timeout>] [-h host]\n"
1060 " -v - verbose operation\n"
1061 " -t <timeout> - max wait time (#sec) for the connection\n"
1062 " -h <host> - send BOOTME requests to <host> (default: broadcast address 255.255.255.255)"