]> git.kernelconcepts.de Git - karo-tx-uboot.git/blobdiff - common/cmd_bootce.c
karo: bootce: suppress mtdparts related error message when CMD_MTDPARTS is not set
[karo-tx-uboot.git] / common / cmd_bootce.c
index 778bc2b21eabf60865fc93fdb6a14c2b848830d9..7103b7f898a238888810eb160991859db770a36b 100644 (file)
@@ -50,12 +50,9 @@ DECLARE_GLOBAL_DATA_PTR;
 #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 ce_bin __attribute__ ((aligned (32))) g_bin;
 static ce_net __attribute__ ((aligned (32))) g_net;
-static IPaddr_t server_ip;
+static struct in_addr server_ip;
 
 static void ce_init_bin(ce_bin *bin, unsigned char *dataBuffer)
 {
@@ -136,24 +133,38 @@ static void ce_setup_std_drv_globals(ce_std_driver_globals *std_drv_glb)
        snprintf(std_drv_glb->deviceId, sizeof(std_drv_glb->deviceId),
                "Triton%02X", eth_get_dev()->enetaddr[5]);
 
-       NetCopyIP(&std_drv_glb->kitl.ipAddress, &NetOurIP);
-       std_drv_glb->kitl.ipMask = getenv_IPaddr("netmask");
-       std_drv_glb->kitl.ipRoute = getenv_IPaddr("gatewayip");
+       net_copy_ip(&std_drv_glb->kitl.ipAddress, &net_ip);
+       std_drv_glb->kitl.ipMask = getenv_ip("netmask").s_addr;
+       std_drv_glb->kitl.ipRoute = getenv_ip("gatewayip").s_addr;
 
        if (mtdparts) {
                strncpy(std_drv_glb->mtdparts, mtdparts, max_len);
                std_drv_glb->mtdparts[max_len - 1] = '\0';
        } else {
-               printf("Failed to get mtdparts environment variable\n");
+               if (CONFIG_IS_ENABLED(CMD_MTDPARTS))
+                       printf("Failed to get mtdparts environment variable\n");
        }
 }
 
-static void ce_prepare_run_bin(ce_bin *bin)
+static void ce_init_drv_globals(void)
 {
-       ce_driver_globals *drv_glb;
        struct ce_magic *ce_magic = (void *)CONFIG_SYS_SDRAM_BASE + 0x160;
        ce_std_driver_globals *std_drv_glb = &ce_magic->drv_glb;
 
+       debug("Copying CE MAGIC from %p to %p..%p\n",
+               &ce_magic_template, ce_magic,
+               (void *)ce_magic + sizeof(*ce_magic) - 1);
+       memcpy(ce_magic, &ce_magic_template, sizeof(*ce_magic));
+
+       ce_setup_std_drv_globals(std_drv_glb);
+       ce_magic->size = sizeof(*std_drv_glb) +
+               strlen(std_drv_glb->mtdparts) + 1;
+       ce_dump_block(ce_magic, offsetof(struct ce_magic, drv_glb) +
+               ce_magic->size);
+}
+
+static void ce_prepare_run_bin(ce_bin *bin)
+{
        /* Clear os RAM area (if needed) */
        if (bin->edbgConfig.flags & EDBG_FL_CLEANBOOT) {
                debug("cleaning memory from %p to %p\n",
@@ -164,49 +175,7 @@ static void ce_prepare_run_bin(ce_bin *bin)
                printf("ok\n");
        }
 
-       /* Prepare driver globals (if needed) */
-       if (bin->eDrvGlb) {
-               debug("Copying CE MAGIC from %p to %p..%p\n",
-                       &ce_magic_template, ce_magic,
-                       (void *)ce_magic + sizeof(*ce_magic) - 1);
-               memcpy(ce_magic, &ce_magic_template, sizeof(*ce_magic));
-
-               ce_setup_std_drv_globals(std_drv_glb);
-               ce_magic->size = sizeof(*std_drv_glb) +
-                       strlen(std_drv_glb->mtdparts) + 1;
-               ce_dump_block(ce_magic, offsetof(struct ce_magic, drv_glb) +
-                       ce_magic->size);
-
-               drv_glb = bin->eDrvGlb;
-               memset(drv_glb, 0, sizeof(*drv_glb));
-
-               drv_glb->signature = DRV_GLB_SIGNATURE;
-
-               /* Local ethernet MAC address */
-               memcpy(drv_glb->macAddr, std_drv_glb->kitl.mac,
-                       sizeof(drv_glb->macAddr));
-               debug("got MAC address %02x:%02x:%02x:%02x:%02x:%02x from environment\n",
-                       drv_glb->macAddr[0], drv_glb->macAddr[1],
-                       drv_glb->macAddr[2], drv_glb->macAddr[3],
-                       drv_glb->macAddr[4], drv_glb->macAddr[5]);
-
-               /* Local IP address */
-               drv_glb->ipAddr = getenv_IPaddr("ipaddr");
-
-               /* Subnet mask */
-               drv_glb->ipMask = getenv_IPaddr("netmask");
-
-               /* Gateway config */
-               drv_glb->ipGate = getenv_IPaddr("gatewayip");
-#ifdef DEBUG
-               debug("got IP address %pI4 from environment\n", &drv_glb->ipAddr);
-               debug("got IP mask %pI4 from environment\n", &drv_glb->ipMask);
-               debug("got gateway address %pI4 from environment\n", &drv_glb->ipGate);
-#endif
-               /* EDBG services config */
-               memcpy(&drv_glb->edbgConfig, &bin->edbgConfig,
-                       sizeof(bin->edbgConfig));
-       }
+       ce_init_drv_globals();
 
        /*
         * Make sure, all the above makes it into SDRAM because
@@ -251,15 +220,6 @@ static int ce_lookup_ep_bin(ce_bin *bin)
                                e32->e32_entryrva;
                        bin->eRamStart = CE_FIX_ADDRESS(header->ramStart);
                        bin->eRamLen = header->ramEnd - header->ramStart;
-                       // Save driver_globals address
-                       // Must follow RAM section in CE config.bib file
-                       //
-                       // eg.
-                       //
-                       // RAM          80900000        03200000        RAM
-                       // DRV_GLB      83B00000        00001000        RESERVED
-                       //
-                       bin->eDrvGlb = CE_FIX_ADDRESS(header->ramEnd);
                        return 1;
                }
        }
@@ -418,6 +378,10 @@ static int do_bootce(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
        size_t image_size;
 
        if (argc > 1) {
+               if (strcmp(argv[1], "-i") == 0) {
+                       ce_init_drv_globals();
+                       return CMD_RET_SUCCESS;
+               }
                addr = (void *)simple_strtoul(argv[1], NULL, 16);
                image_size = INT_MAX;           /* actually we do not know the image size */
        } else if (getenv("fileaddr") != NULL) {
@@ -454,37 +418,46 @@ static int do_bootce(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
 }
 U_BOOT_CMD(
        bootce, 2, 0, do_bootce,
-       "bootce [addr]\t- Boot a Windows CE image from memory\n",
-       "[args..]\n"
-       "\taddr\t\t-boot image from address addr\n"
+       "Boot a Windows CE image from RAM",
+       "[addr]\n"
+       "\taddr\t\tboot image from address addr (default ${fileaddr})\n"
+       "or\n"
+       "\t-i\t\tinitialize the WinCE globals data structure (before loading a .nb0 image)"
 );
 
-static int ce_nand_load(ce_bin *bin, size_t offset, void *buf, size_t max_len)
+#ifdef CONFIG_CMD_NAND
+static int ce_nand_load(ce_bin *bin, loff_t *offset, void *buf, size_t max_len)
 {
        int ret;
        size_t len = max_len;
+       nand_info_t *nand = &nand_info[0];
+
+       while (nand_block_isbad(nand, *offset & ~(max_len - 1))) {
+               printf("Skipping bad block 0x%08llx\n",
+                       *offset & ~(max_len - 1));
+               *offset += max_len;
+               if (*offset + max_len > nand->size)
+                       return -EINVAL;
+       }
 
-       ret = nand_read_skip_bad(&nand_info[0], offset, &len, buf);
-       if (ret < 0) {
-               printf("NBOOTCE - aborted\n");
+       ret = nand_read(nand, *offset, &len, buf);
+       if (ret < 0)
                return ret;
-       }
+
        bin->dataLen = len;
        return len;
 }
 
-#define CE_NAND_BUF_SIZE       2048
-
 static int do_nbootce(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
 {
        int ret;
        struct mtd_device *dev;
        struct part_info *part_info;
        u8 part_num;
-       size_t offset;
+       loff_t offset;
        char *end;
        void *buffer;
-       size_t len = CE_NAND_BUF_SIZE;
+       size_t bufsize = nand_info[0].erasesize, len;
 
        if (argc < 2 || argc > 3)
                return CMD_RET_USAGE;
@@ -502,23 +475,22 @@ static int do_nbootce(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
                        return CMD_RET_FAILURE;
                }
                offset = part_info->offset;
-               printf ("## Booting Windows CE Image from NAND partition %s at offset %08x\n",
+               printf ("## Booting Windows CE Image from NAND partition %s at offset %08llx\n",
                        argv[1], offset);
        } else {
-               printf ("## Booting Windows CE Image from NAND offset %08x\n",
+               printf ("## Booting Windows CE Image from NAND offset %08llx\n",
                        offset);
        }
 
-       buffer = malloc(CE_NAND_BUF_SIZE);
+       buffer = malloc(bufsize);
        if (buffer == NULL) {
-               printf("Failed to allocate %u byte buffer\n", CE_NAND_BUF_SIZE);
+               printf("Failed to allocate %u byte buffer\n", bufsize);
                return CMD_RET_FAILURE;
        }
 
        ce_init_bin(&g_bin, buffer);
 
-       ret = ce_nand_load(&g_bin, offset, buffer,
-                       CE_NAND_BUF_SIZE);
+       ret = ce_nand_load(&g_bin, &offset, buffer, bufsize);
        if (ret < 0) {
                printf("Failed to read NAND: %d\n", ret);
                goto err;
@@ -526,19 +498,38 @@ static int do_nbootce(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
        len = ret;
        /* check if there is a valid windows CE image header */
        if (ce_is_bin_image(buffer, len)) {
-               while (ce_parse_bin(&g_bin) == CE_PR_MORE) {
-                       if (ctrlc()) {
-                               printf("NBOOTCE - canceled by user\n");
-                               goto err;
+               do {
+                       ret = ce_parse_bin(&g_bin);
+                       switch (ret) {
+                       case CE_PR_MORE:
+                       {
+                               if (ctrlc()) {
+                                       printf("NBOOTCE - canceled by user\n");
+                                       goto err;
+                               }
+                               offset += len;
+                               len = ce_nand_load(&g_bin, &offset, buffer,
+                                               bufsize);
+                               if (len < 0) {
+                                       printf("Nand read error: %d\n", len);
+                                       ret = len;
+                                       goto err;
+                               }
                        }
-                       offset += len;
-                       ret = ce_nand_load(&g_bin, offset, buffer,
-                                       CE_NAND_BUF_SIZE);
-                       if (ret < 0)
-                               goto err;
-                       len = ret;
-               }
+                       break;
+
+                       case CE_PR_EOF:
+                               ce_prepare_run_bin(&g_bin);
+                               break;
+
+                       case CE_PR_ERROR:
+                               break;
+                       }
+               } while (ret == CE_PR_MORE);
                free(buffer);
+               if (ret != CE_PR_EOF)
+                       return CMD_RET_FAILURE;
+
                if (getenv_yesno("autostart") != 1) {
                        /*
                         * just use bootce to load the image to SDRAM;
@@ -557,11 +548,12 @@ err:
 }
 U_BOOT_CMD(
        nbootce, 2, 0, do_nbootce,
-       "Boot a Windows CE image from NAND\n",
+       "Boot a Windows CE image from NAND",
        "off|partitition\n"
        "\toff\t\t- flash offset (hex)\n"
-       "\tpartition\t- partition name\n"
+       "\tpartition\t- partition name"
 );
+#endif
 
 static int ce_send_write_ack(ce_net *net)
 {
@@ -606,8 +598,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;
 
@@ -625,9 +618,9 @@ static enum bootme_state ce_process_download(ce_net *net, ce_bin *bin)
                                        // Some diag output
                                        if (net->verbose) {
                                                printf("Locked Down download link, IP: %pI4\n",
-                                                       &NetServerIP);
+                                                       &net_server_ip);
                                                printf("Sending BOOTME request [%d] to %pI4\n",
-                                                       net->seqNum, &NetServerIP);
+                                                       net->seqNum, &net_server_ip);
                                        }
 
                                        // Lock down EShell download link
@@ -713,54 +706,43 @@ static enum bootme_state ce_process_edbg(ce_net *net, ce_bin *bin)
                /* Some diag output */
                if (net->verbose) {
                        printf("Locked Down EDBG service link, IP: %pI4\n",
-                               &NetServerIP);
+                               &net_server_ip);
                }
 
                /* Lock down EDBG link */
                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");
                        if (bin->edbgConfig.flags & EDBG_FL_DBGMSG) {
-                               printf("--> Enabling DBGMSG service, IP: %d.%d.%d.%d, port: %d\n",
-                                       (bin->edbgConfig.dbgMsgIPAddr >> 0) & 0xFF,
-                                       (bin->edbgConfig.dbgMsgIPAddr >> 8) & 0xFF,
-                                       (bin->edbgConfig.dbgMsgIPAddr >> 16) & 0xFF,
-                                       (bin->edbgConfig.dbgMsgIPAddr >> 24) & 0xFF,
+                               printf("--> Enabling DBGMSG service, IP: %pI4, port: %d\n",
+                                       &bin->edbgConfig.dbgMsgIPAddr,
                                        ntohs(bin->edbgConfig.dbgMsgPort));
                        }
 
                        if (bin->edbgConfig.flags & EDBG_FL_PPSH) {
-                               printf("--> Enabling PPSH service, IP: %d.%d.%d.%d, port: %d\n",
-                                       (bin->edbgConfig.ppshIPAddr >> 0) & 0xFF,
-                                       (bin->edbgConfig.ppshIPAddr >> 8) & 0xFF,
-                                       (bin->edbgConfig.ppshIPAddr >> 16) & 0xFF,
-                                       (bin->edbgConfig.ppshIPAddr >> 24) & 0xFF,
+                               printf("--> Enabling PPSH service, IP: %pI4, port: %d\n",
+                                       &bin->edbgConfig.ppshIPAddr,
                                        ntohs(bin->edbgConfig.ppshPort));
                        }
 
                        if (bin->edbgConfig.flags & EDBG_FL_KDBG) {
-                               printf("--> Enabling KDBG service, IP: %d.%d.%d.%d, port: %d\n",
-                                       (bin->edbgConfig.kdbgIPAddr >> 0) & 0xFF,
-                                       (bin->edbgConfig.kdbgIPAddr >> 8) & 0xFF,
-                                       (bin->edbgConfig.kdbgIPAddr >> 16) & 0xFF,
-                                       (bin->edbgConfig.kdbgIPAddr >> 24) & 0xFF,
+                               printf("--> Enabling KDBG service, IP: %pI4, port: %d\n",
+                                       &bin->edbgConfig.kdbgIPAddr,
                                        ntohs(bin->edbgConfig.kdbgPort));
                        }
 
@@ -768,7 +750,6 @@ debug("%s@%d\n", __func__, __LINE__);
                                printf("--> Force clean boot\n");
                        }
                }
-               ret = BOOTME_DEBUG;
                break;
 
        default:
@@ -780,11 +761,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)
@@ -850,7 +838,7 @@ static int ce_send_bootme(ce_net *net)
        }
 
        /* IP address from active config */
-       NetCopyIP(&data->ipAddr, &NetOurIP);
+       net_copy_ip(&data->ipAddr, &net_ip);
 
        // Device name string (NULL terminated). Should include
        // platform and number based on Ether address (e.g. Odo42, CEPCLS2346, etc)
@@ -863,33 +851,23 @@ static int ce_send_bootme(ce_net *net)
                data->platformId, data->macAddr[5]);
 
 #ifdef DEBUG
-       printf("header->id: %08X\r\n", header->id);
-       printf("header->service: %08X\r\n", header->service);
-       printf("header->flags: %08X\r\n", header->flags);
-       printf("header->seqNum: %08X\r\n", header->seqNum);
-       printf("header->cmd: %08X\r\n\r\n", header->cmd);
-
-       printf("data->versionMajor: %08X\r\n", data->versionMajor);
-       printf("data->versionMinor: %08X\r\n", data->versionMinor);
-       printf("data->cpuId: %08X\r\n", data->cpuId);
-       printf("data->bootmeVer: %08X\r\n", data->bootmeVer);
-       printf("data->bootFlags: %08X\r\n", data->bootFlags);
-       printf("data->svcPort: %08X\r\n\r\n", ntohs(data->svcPort));
-
-       printf("data->macAddr: %02X-%02X-%02X-%02X-%02X-%02X\r\n",
-               data->macAddr[0], data->macAddr[1],
-               data->macAddr[2], data->macAddr[3],
-               data->macAddr[4], data->macAddr[5]);
-
-       printf("data->ipAddr: %d.%d.%d.%d\r\n",
-               (data->ipAddr >> 0) & 0xFF,
-               (data->ipAddr >> 8) & 0xFF,
-               (data->ipAddr >> 16) & 0xFF,
-               (data->ipAddr >> 24) & 0xFF);
-
-       printf("data->platformId: %s\r\n", data->platformId);
-
-       printf("data->deviceName: %s\r\n", data->deviceName);
+       printf("header->id: %08X\n", header->id);
+       printf("header->service: %08X\n", header->service);
+       printf("header->flags: %08X\n", header->flags);
+       printf("header->seqNum: %08X\n", header->seqNum);
+       printf("header->cmd: %08X\n\n", header->cmd);
+
+       printf("data->versionMajor: %08X\n", data->versionMajor);
+       printf("data->versionMinor: %08X\n", data->versionMinor);
+       printf("data->cpuId: %08X\n", data->cpuId);
+       printf("data->bootmeVer: %08X\n", data->bootmeVer);
+       printf("data->bootFlags: %08X\n", data->bootFlags);
+       printf("data->svcPort: %08X\n\n", ntohs(data->svcPort));
+
+       printf("data->macAddr: %pM\n", data->macAddr);
+       printf("data->ipAddr: %pI4\n", &data->ipAddr);
+       printf("data->platformId: %s\n", data->platformId);
+       printf("data->deviceName: %s\n", data->deviceName);
 #endif
        // Some diag output ...
        if (net->verbose) {
@@ -936,8 +914,6 @@ static inline int ce_init_download_link(ce_net *net, ce_bin *bin, int verbose)
        return 0;
 }
 
-#define UINT_MAX ~0UL
-
 static inline int ce_download_file(ce_net *net, ulong timeout)
 {
        ulong start = get_timer_masked();
@@ -991,7 +967,7 @@ static int do_ceconnect(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]
        int ret = 1;
        int i;
 
-       server_ip = 0;
+       server_ip.s_addr = 0;
 
        for (i = 1; i < argc; i++){
                if (*argv[i] != '-')
@@ -1002,9 +978,9 @@ 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",
+                                       printf("Timeout value %lu out of range (max.: %u)\n",
                                                timeout, UINT_MAX / CONFIG_SYS_HZ - 1);
                                        return CMD_RET_USAGE;
                                }
@@ -1019,7 +995,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;
                        }
                }
@@ -1055,7 +1031,7 @@ err:
 }
 U_BOOT_CMD(
        ceconnect, 6, 1, do_ceconnect,
-       "Set up a connection to the CE host PC over TCP/IP and download the run-time image\n",
+       "Set up a connection to the CE host PC over TCP/IP and download the run-time image",
        "[-v] [-t <timeout>] [-h host]\n"
        "  -v            - verbose operation\n"
        "  -t <timeout>  - max wait time (#sec) for the connection\n"