From: Lothar Waßmann Date: Fri, 11 Oct 2013 07:52:27 +0000 (+0200) Subject: Fix various bugs in WinCE boot protocol handler X-Git-Tag: KARO-TX-2013-10-25~10 X-Git-Url: https://git.kernelconcepts.de/?p=karo-tx-uboot.git;a=commitdiff_plain;h=06f0ba686bc3dcfecd0220fe508f4e38f8b4f919 Fix various bugs in WinCE boot protocol handler --- diff --git a/common/cmd_bootce.c b/common/cmd_bootce.c index 002acf905b..1796ddfcd2 100644 --- a/common/cmd_bootce.c +++ b/common/cmd_bootce.c @@ -554,10 +554,10 @@ static int do_nbootce(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) break; } } while (ret == CE_PR_MORE); + free(buffer); if (ret != CE_PR_EOF) return CMD_RET_FAILURE; - free(buffer); if (getenv_yesno("autostart") != 1) { /* * just use bootce to load the image to SDRAM; @@ -625,8 +625,9 @@ static enum bootme_state ce_process_download(ce_net *net, ce_bin *bin) } else { int rc = ce_send_write_ack(net); - printf("Dropping out of sequence packet with ID %d (expected %d)\n", - blknum, nxt); + if (net->verbose) + printf("Dropping out of sequence packet with ID %d (expected %d)\n", + blknum, nxt); if (rc != 0) return rc; @@ -739,20 +740,18 @@ static enum bootme_state ce_process_edbg(ce_net *net, ce_bin *bin) net->state = BOOTME_DEBUG; } -debug("%s@%d\n", __func__, __LINE__); switch (header.cmd) { case EDBG_CMD_JUMPIMG: -debug("%s@%d\n", __func__, __LINE__); net->gotJumpingRequest = 1; if (net->verbose) { printf("Received JUMPING command\n"); } /* Just pass through and copy CONFIG structure */ + ret = BOOTME_DONE; case EDBG_CMD_OS_CONFIG: -debug("%s@%d\n", __func__, __LINE__); /* Copy config structure */ - memcpy(&bin->edbgConfig, header.data, + memcpy(&bin->edbgConfig, &net->data[sizeof(header)], sizeof(edbg_os_config_data)); if (net->verbose) { printf("Received CONFIG command\n"); @@ -778,7 +777,6 @@ debug("%s@%d\n", __func__, __LINE__); printf("--> Force clean boot\n"); } } - ret = BOOTME_DEBUG; break; default: @@ -790,11 +788,18 @@ debug("%s@%d\n", __func__, __LINE__); /* Respond with ack */ header.flags = EDBG_FL_FROM_DEV | EDBG_FL_ACK; + memcpy(net->data, &header, sizeof(header)); net->dataLen = EDBG_DATA_OFFSET; -debug("%s@%d: sending packet %p len %u\n", __func__, __LINE__, - net->data, net->dataLen); - bootme_send_frame(net->data, net->dataLen); - return ret; + + int retries = 10; + int rc; + do { + rc = bootme_send_frame(net->data, net->dataLen); + if (rc != 0) { + printf("Failed to send ACK: %d\n", rc); + } + } while (rc && retries-- > 0); + return rc ?: ret; } static enum bootme_state ce_edbg_handler(const void *buf, size_t len) @@ -1002,7 +1007,7 @@ static int do_ceconnect(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[] i++; if (argc > i) { timeout = simple_strtoul(argv[i], - NULL, 10); + NULL, 0); if (timeout >= UINT_MAX / CONFIG_SYS_HZ) { printf("Timeout value %lu out of range (max.: %lu)\n", timeout, UINT_MAX / CONFIG_SYS_HZ - 1); @@ -1019,7 +1024,7 @@ static int do_ceconnect(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[] server_ip = string_to_ip(argv[i]); printf("Using server %pI4\n", &server_ip); } else { - printf("Option requires an argument - t\n"); + printf("Option requires an argument - h\n"); return CMD_RET_USAGE; } } diff --git a/include/wince.h b/include/wince.h index 1efd14f1a6..c853fc8d76 100644 --- a/include/wince.h +++ b/include/wince.h @@ -291,6 +291,7 @@ struct sockaddr_in { enum bootme_state { BOOTME_INIT, BOOTME_DOWNLOAD, + BOOTME_DEBUG_INIT, BOOTME_DEBUG, BOOTME_DONE, BOOTME_ERROR, diff --git a/net/bootme.c b/net/bootme.c index 56ae378347..af2ab9f57e 100644 --- a/net/bootme.c +++ b/net/bootme.c @@ -29,35 +29,12 @@ DECLARE_GLOBAL_DATA_PTR; -#define WINCE_VRAM_BASE 0x80000000 -#define CE_FIX_ADDRESS(a) ((void *)((a) - WINCE_VRAM_BASE + CONFIG_SYS_SDRAM_BASE)) - -#ifndef INT_MAX -#define INT_MAX ((int)(~0 >> 1)) -#endif - -/* Bin image parse states */ -#define CE_PS_RTI_ADDR 0 -#define CE_PS_RTI_LEN 1 -#define CE_PS_E_ADDR 2 -#define CE_PS_E_LEN 3 -#define CE_PS_E_CHKSUM 4 -#define CE_PS_E_DATA 5 - -#define CE_MIN(a, b) (((a) < (b)) ? (a) : (b)) -#define CE_MAX(a, b) (((a) > (b)) ? (a) : (b)) - -#define _STRMAC(s) #s -#define STRMAC(s) _STRMAC(s) - static enum bootme_state bootme_state; static int bootme_src_port = 0xdeadface; static int bootme_dst_port = 0xdeadbeef; static uchar bootme_ether[ETH_ALEN]; static IPaddr_t bootme_ip; static int bootme_timed_out; -//static size_t input_len, input_size; -//static void *input_packet; static const char *output_packet; /* used by first send udp */ static int output_packet_len; static unsigned long bootme_timeout; @@ -97,6 +74,7 @@ static inline void ce_dump_block(void *ptr, int length) static void bootme_timeout_handler(void) { + printf("%s\n", __func__); net_set_state(NETLOOP_SUCCESS); bootme_timed_out++; } @@ -196,12 +174,12 @@ static void bootme_handler(uchar *pkt, unsigned dest_port, IPaddr_t src_ip, uchar *eth_pkt = pkt; unsigned eth_len = len; static char cursor = '|'; - enum bootme_state last_state = BOOTME_INIT; -#if 1 + enum bootme_state last_state = bootme_state; + debug("received packet of len %d from %pI4:%d to port %d\n", len, &src_ip, src_port, dest_port); ce_dump_block(pkt, len); -#endif + if (!bootme_packet_handler) { printf("No packet handler set for BOOTME protocol; dropping packet\n"); return; @@ -212,27 +190,37 @@ static void bootme_handler(uchar *pkt, unsigned dest_port, IPaddr_t src_ip, printf("%c\x08", cursor); cursor = next_cursor(cursor); - if (is_broadcast(bootme_ip)) { - bootme_ip = src_ip; - } else if (src_ip != bootme_ip) { + if (!is_broadcast(bootme_ip) && src_ip != bootme_ip) { debug("src_ip %pI4 does not match destination IP %pI4\n", &src_ip, &bootme_ip); return; /* not from our server */ } - - last_state = bootme_state; - bootme_dst_port = src_port; - debug("bootme_dst_port set to %d\n", bootme_dst_port); + if (bootme_state == BOOTME_INIT || bootme_state == BOOTME_DEBUG_INIT) { + struct ethernet_hdr *eth = (struct ethernet_hdr *)(pkt - + NetEthHdrSize() - IP_UDP_HDR_SIZE); + memcpy(bootme_ether, eth->et_src, sizeof(bootme_ether)); + printf("Target MAC address set to %pM\n", bootme_ether); + + if (is_broadcast(bootme_ip)) { + NetCopyIP(&bootme_ip, &src_ip); + } + } if (bootme_state == BOOTME_INIT) { bootme_src_port = EDBG_SVC_PORT; debug("%s: bootme_src_port set to %d\n", __func__, bootme_src_port); } + + debug("bootme_dst_port %d -> %d\n", bootme_dst_port, src_port); + bootme_dst_port = src_port; + bootme_state = bootme_packet_handler(eth_pkt, eth_len); debug("bootme_packet_handler() returned %d\n", bootme_state); if (bootme_state != last_state) - debug("bootme_state: %d -> %d\n", last_state, bootme_state); + debug("%s@%d: bootme_state: %d -> %d\n", __func__, __LINE__, + last_state, bootme_state); switch (bootme_state) { case BOOTME_INIT: + case BOOTME_DEBUG_INIT: break; case BOOTME_DOWNLOAD: @@ -240,9 +228,9 @@ static void bootme_handler(uchar *pkt, unsigned dest_port, IPaddr_t src_ip, NetBootFileXferSize += len - 4; /* fallthru */ case BOOTME_DEBUG: - if (last_state == BOOTME_INIT) { + if (last_state == BOOTME_INIT || + last_state == BOOTME_DEBUG_INIT) bootme_timeout = 3 * 1000; - } NetSetTimeout(bootme_timeout, bootme_timeout_handler); break; @@ -276,8 +264,11 @@ void BootmeStart(void) assert(NetTxPacket != NULL); pkt = (uchar *)NetTxPacket + NetEthHdrSize() + IP_UDP_HDR_SIZE; memcpy(pkt, output_packet, output_packet_len); + debug("%s@%d: Sending ARP request:\n", __func__, __LINE__); + ce_dump_block(pkt, output_packet_len); NetSendUDPPacket(bootme_ether, bootme_ip, bootme_dst_port, bootme_src_port, output_packet_len); + output_packet_len = 0; } } @@ -285,23 +276,20 @@ int bootme_send_frame(const void *buf, size_t len) { int ret; struct eth_device *eth; - int inited = 0; uchar *pkt; eth = eth_get_dev(); if (eth == NULL) return -EINVAL; - if (bootme_state == BOOTME_INIT) + if (bootme_state == BOOTME_INIT || bootme_state == BOOTME_DEBUG_INIT) check_net_config(); debug("%s: buf: %p len: %u from %pI4:%d to %pI4:%d\n", - __func__, buf, len, &NetOurIP, bootme_src_port, &bootme_ip, bootme_dst_port); + __func__, buf, len, &NetOurIP, bootme_src_port, &bootme_ip, + bootme_dst_port); if (memcmp(bootme_ether, NetEtherNullAddr, ETH_ALEN) == 0) { - if (eth->state == ETH_STATE_ACTIVE) - return 0; /* inside net loop */ - output_packet = buf; output_packet_len = len; /* wait for arp reply and send packet */ @@ -316,36 +304,22 @@ int bootme_send_frame(const void *buf, size_t len) return 0; } - if (eth->state != ETH_STATE_ACTIVE) { - if (eth_is_on_demand_init()) { - ret = eth_init(gd->bd); - if (ret < 0) - return ret; - eth_set_last_protocol(BOOTME); - } else { - eth_init_state_only(gd->bd); - } - inited = 1; - } - assert(NetTxPacket != NULL); pkt = (uchar *)NetTxPacket + NetEthHdrSize() + IP_UDP_HDR_SIZE; memcpy(pkt, buf, len); ret = NetSendUDPPacket(bootme_ether, bootme_ip, bootme_dst_port, bootme_src_port, len); - if (inited) { - debug("Stopping network\n"); - if (eth_is_on_demand_init()) - eth_halt(); - else - eth_halt_state_only(); - } + if (ret) + printf("Failed to send packet: %d\n", ret); + return ret; } static void bootme_init(IPaddr_t server_ip) { + debug("%s@%d: bootme_state: %d -> %d\n", __func__, __LINE__, + bootme_state, BOOTME_INIT); bootme_state = BOOTME_INIT; bootme_ip = server_ip; /* force reconfiguration in check_net_config() */ @@ -374,7 +348,10 @@ int BootMeDebugStart(bootme_hand_f *handler) bootme_packet_handler = handler; bootme_init(bootme_ip); - bootme_state = BOOTME_DEBUG; + debug("%s@%d: bootme_state: %d -> %d\n", __func__, __LINE__, + bootme_state, BOOTME_DEBUG_INIT); + bootme_state = BOOTME_DEBUG_INIT; + bootme_timeout = 3 * 1000; NetSetTimeout(bootme_timeout, bootme_timeout_handler);