]> git.kernelconcepts.de Git - karo-tx-redboot.git/blobdiff - packages/redboot/v2_0/src/wince.c
unified MX27, MX25, MX37 trees
[karo-tx-redboot.git] / packages / redboot / v2_0 / src / wince.c
index 1afa5558b1588abe7509ca26b15ee06270eb4a75..23cda480f96b085161542f090025f230a67462e6 100755 (executable)
@@ -1,4 +1,5 @@
 #include <redboot.h>
+#include <cyg/io/flash.h>
 #include <net/net.h>
 #include CYGHWR_MEMORY_LAYOUT_H
 #include <wince.h>
@@ -16,6 +17,22 @@ cmd_fun do_go;
 #define CE_WINCE_VRAM_BASE             0x80000000
 #define CE_FIX_ADDRESS(a)              (((a) - CE_WINCE_VRAM_BASE) + CE_RAM_BASE)
 
+#ifdef CYGHWR_REDBOOT_FLASH_CONFIG_MEDIA_FLASH
+extern void *flash_start, *flash_end;
+
+static inline int is_rom_addr(void *addr)
+{
+       return addr >= flash_start && addr <= flash_end;
+}
+#else
+#define is_rom_addr(p)         0
+#endif
+
+static inline int is_ram_addr(unsigned long addr)
+{
+       return addr >= CE_RAM_BASE && addr < CE_RAM_END;
+}
+
 // Bin image parse states
 #define CE_PS_RTI_ADDR                 0
 #define CE_PS_RTI_LEN                  1
@@ -35,22 +52,22 @@ cmd_fun do_go;
 ///////////////////////////////////////////////////////////////////////////////////////////////
 // Local types
 typedef struct {
-       unsigned int rtiPhysAddr;
-       unsigned int rtiPhysLen;
-       unsigned int ePhysAddr;
-       unsigned int ePhysLen;
-       unsigned int eChkSum;
+       unsigned long rtiPhysAddr;
+       unsigned long rtiPhysLen;
+       unsigned long ePhysAddr;
+       unsigned long ePhysLen;
+       unsigned long eChkSum;
 
-       unsigned int eEntryPoint;
-       unsigned int eRamStart;
-       unsigned int eRamLen;
-       unsigned int eDrvGlb;
+       unsigned long eEntryPoint;
+       unsigned long eRamStart;
+       unsigned long eRamLen;
+       unsigned long eDrvGlb;
 
        unsigned char parseState;
-       unsigned int parseChkSum;
+       unsigned long parseChkSum;
        int parseLen;
        unsigned char *parsePtr;
-       int secion;
+       int section;
 
        int dataLen;
        unsigned char *data;
@@ -95,7 +112,6 @@ int ce_parse_bin(ce_bin *bin);
 bool ce_lookup_ep_bin(ce_bin *bin);
 void ce_prepare_run_bin(ce_bin *bin);
 void ce_run_bin(ce_bin *bin);
-void ce_redboot_version(unsigned int *vhigh, unsigned int *vlow);
 
 #ifdef CYGPKG_REDBOOT_NETWORKING
 // Redboot network based routines
@@ -144,17 +160,27 @@ bool ce_bin_load(void *image, int imglen)
 bool ce_is_bin_image(void *image, int imglen)
 {
        if (imglen < CE_BIN_SIGN_LEN) {
+               diag_printf("Not a valid CE image: image size %u shorter than minimum %u\n",
+                           imglen, CE_BIN_SIGN_LEN);
                return 0;
        }
+       if (is_rom_addr(image)) {
+               unsigned char sign_buf[CE_BIN_SIGN_LEN];
+               void *err_addr;
 
-       return (memcmp(image, CE_BIN_SIGN, CE_BIN_SIGN_LEN) == 0);
+               if (flash_read(image, sign_buf,
+                              CE_BIN_SIGN_LEN, &err_addr) != FLASH_ERR_OK) {
+                       return 0;
+               }
+               return memcmp(sign_buf, CE_BIN_SIGN, CE_BIN_SIGN_LEN) == 0;
+       }
+       return memcmp(image, CE_BIN_SIGN, CE_BIN_SIGN_LEN) == 0;
 }
 
 void ce_bin_init_parser()
 {
        // No buffer address by now, will be specified
-       // latter by the ce_bin_parse_next routine
-
+       // later by the ce_bin_parse_next routine
        ce_init_bin(&g_bin, NULL);
 }
 
@@ -191,9 +217,8 @@ int ce_parse_bin(ce_bin *bin)
        if (pbLen) {
                if (bin->binLen == 0) {
                        // Check for the .BIN signature first
-
                        if (!ce_is_bin_image(pbData, pbLen)) {
-                               diag_printf("Error: Invalid or corrupted .BIN image!\n");
+                               diag_printf("** Error: Invalid or corrupted .BIN image!\n");
 
                                return CE_PR_ERROR;
                        }
@@ -201,7 +226,6 @@ int ce_parse_bin(ce_bin *bin)
                        diag_printf("Loading Windows CE .BIN image ...\n");
 
                        // Skip signature
-
                        pbLen -= CE_BIN_SIGN_LEN;
                        pbData += CE_BIN_SIGN_LEN;
                }
@@ -216,8 +240,16 @@ int ce_parse_bin(ce_bin *bin)
 
                                copyLen = CE_MIN(sizeof(unsigned int) - bin->parseLen, pbLen);
 
-                               memcpy(&bin->parsePtr[ bin->parseLen ], pbData, copyLen);
+                               if (is_rom_addr(pbData)) {
+                                       void *err_addr;
 
+                                       if (flash_read(pbData, &bin->parsePtr[bin->parseLen],
+                                                      copyLen, &err_addr) != FLASH_ERR_OK) {
+                                               return CE_PR_ERROR;
+                                       }
+                               } else {
+                                       memcpy(&bin->parsePtr[bin->parseLen], pbData, copyLen);
+                               }
                                bin->parseLen += copyLen;
                                pbLen -= copyLen;
                                pbData += copyLen;
@@ -225,23 +257,31 @@ int ce_parse_bin(ce_bin *bin)
                                if (bin->parseLen == sizeof(unsigned int)) {
                                        if (bin->parseState == CE_PS_RTI_ADDR) {
                                                bin->rtiPhysAddr = CE_FIX_ADDRESS(bin->rtiPhysAddr);
+                                               if (!is_ram_addr(bin->rtiPhysAddr)) {
+                                                       diag_printf("Invalid address %08lx in CE_PS_RTI_ADDR section\n",
+                                                                   bin->rtiPhysAddr);
+                                                       return CE_PR_ERROR;
+                                               }
                                        } else if (bin->parseState == CE_PS_E_ADDR) {
                                                if (bin->ePhysAddr) {
                                                        bin->ePhysAddr = CE_FIX_ADDRESS(bin->ePhysAddr);
+                                                       if (!is_ram_addr(bin->ePhysAddr)) {
+                                                               diag_printf("Invalid address %08lx in CE_PS_E_ADDR section\n",
+                                                                           bin->ePhysAddr);
+                                                               return CE_PR_ERROR;
+                                                       }
                                                }
                                        }
 
                                        bin->parseState ++;
                                        bin->parseLen = 0;
                                        bin->parsePtr += sizeof(unsigned int);
-
                                        if (bin->parseState == CE_PS_E_DATA) {
                                                if (bin->ePhysAddr) {
                                                        bin->parsePtr = (unsigned char*)(bin->ePhysAddr);
                                                        bin->parseChkSum = 0;
                                                } else {
                                                        // EOF
-
                                                        pbLen = 0;
                                                        bin->endOfBin = 1;
                                                }
@@ -251,20 +291,30 @@ int ce_parse_bin(ce_bin *bin)
                                break;
 
                        case CE_PS_E_DATA:
-
                                if (bin->ePhysAddr) {
                                        copyLen = CE_MIN(bin->ePhysLen - bin->parseLen, pbLen);
                                        bin->parseLen += copyLen;
                                        pbLen -= copyLen;
+                                       if (is_rom_addr(pbData)) {
+                                               void *err_addr;
 
-                                       while (copyLen --) {
-                                               bin->parseChkSum += *pbData;
-                                               *bin->parsePtr ++ = *pbData ++;
+                                               if (flash_read(pbData, bin->parsePtr,
+                                                              copyLen, &err_addr) != FLASH_ERR_OK) {
+                                                       return CE_PR_ERROR;
+                                               }
+                                               pbData += copyLen;
+                                               while (copyLen--) {
+                                                       bin->parseChkSum += *bin->parsePtr++;
+                                               }
+                                       } else {
+                                               while (copyLen--) {
+                                                       bin->parseChkSum += *pbData;
+                                                       *bin->parsePtr ++ = *pbData ++;
+                                               }
                                        }
-
                                        if (bin->parseLen == bin->ePhysLen) {
-                                               diag_printf("Section [%02d]: address 0x%08X, size 0x%08X, checksum %s\n",
-                                                       bin->secion,
+                                               diag_printf("Section [%02d]: address 0x%08lX, size 0x%08lX, checksum %s\n",
+                                                       bin->section,
                                                        bin->ePhysAddr,
                                                        bin->ePhysLen,
                                                        (bin->eChkSum == bin->parseChkSum) ? "ok" : "fail");
@@ -279,7 +329,7 @@ int ce_parse_bin(ce_bin *bin)
                                                        return CE_PR_ERROR;
                                                }
 
-                                               bin->secion ++;
+                                               bin->section ++;
                                                bin->parseState = CE_PS_E_ADDR;
                                                bin->parseLen = 0;
                                                bin->parsePtr = (unsigned char*)(&bin->ePhysAddr);
@@ -299,14 +349,14 @@ int ce_parse_bin(ce_bin *bin)
                // Find entry point
 
                if (!ce_lookup_ep_bin(bin)) {
-                       diag_printf("Error: entry point not found!\n");
+                       diag_printf("** Error: entry point not found!\n");
 
                        bin->binLen = 0;
 
                        return CE_PR_ERROR;
                }
 
-               diag_printf("Entry point: 0x%08X, address range: 0x%08X-0x%08X\n",
+               diag_printf("Entry point: 0x%08lX, address range: 0x%08lX-0x%08lX\n",
                        bin->eEntryPoint,
                        bin->rtiPhysAddr,
                        bin->rtiPhysAddr + bin->rtiPhysLen);
@@ -329,7 +379,6 @@ bool ce_lookup_ep_bin(ce_bin *bin)
        unsigned int i;
 
        // Check image Table Of Contents (TOC) signature
-
        if (*(unsigned int*)(bin->rtiPhysAddr + ROM_SIGNATURE_OFFSET) != ROM_SIGNATURE) {
                // Error: Did not find image TOC signature!
 
@@ -338,7 +387,6 @@ bool ce_lookup_ep_bin(ce_bin *bin)
 
 
        // Lookup entry point
-
        header = (ce_rom_hdr*)CE_FIX_ADDRESS(*(unsigned int*)(bin->rtiPhysAddr +
                                                              ROM_SIGNATURE_OFFSET +
                                                              sizeof(unsigned int)));
@@ -346,13 +394,13 @@ bool ce_lookup_ep_bin(ce_bin *bin)
 
        for (i = 0; i < header->nummods; i ++) {
                // Look for 'nk.exe' module
-
                if (strcmp((char*)CE_FIX_ADDRESS(tentry[ i ].fileName), "nk.exe") == 0) {
                        // Save entry point and RAM addresses
 
                        e32 = (e32_rom*)CE_FIX_ADDRESS(tentry[ i ].e32Offset);
 
-                       bin->eEntryPoint = CE_FIX_ADDRESS(tentry[ i ].loadOffset) + e32->e32_entryrva;
+                       bin->eEntryPoint = CE_FIX_ADDRESS(tentry[ i ].loadOffset) +
+                               e32->e32_entryrva;
                        bin->eRamStart = CE_FIX_ADDRESS(header->ramStart);
                        bin->eRamLen = header->ramEnd - header->ramStart;
 
@@ -365,8 +413,8 @@ bool ce_lookup_ep_bin(ce_bin *bin)
                        // DRV_GLB      83B00000        00001000        RESERVED
                        //
 
-                       bin->eDrvGlb = CE_FIX_ADDRESS(header->ramEnd);
-
+                       bin->eDrvGlb = CE_FIX_ADDRESS(header->ramEnd) -
+                               sizeof(ce_driver_globals);
                        return 1;
                }
        }
@@ -376,74 +424,102 @@ bool ce_lookup_ep_bin(ce_bin *bin)
        return 0;
 }
 
-void ce_prepare_run_bin(ce_bin *bin)
+void setup_drv_globals(ce_driver_globals *drv_glb)
 {
-       ce_driver_globals *drv_glb;
+       diag_printf("%s %p\n", __FUNCTION__, drv_glb);
 
-       // Clear os RAM area (if needed)
+       // Fill out driver globals
+       memset(drv_glb, 0, sizeof(ce_driver_globals));
 
-       if (1 || bin->edbgConfig.flags & EDBG_FL_CLEANBOOT) {
-               diag_printf("Preparing clean boot ... ");
-               memset((void*)bin->eRamStart, 0, bin->eRamLen);
-               diag_printf("ok\n");
-       }
+       // Signature
+       drv_glb->signature = DRV_GLB_SIGNATURE;
 
-       // Prepare driver globals (if needed)
+       // No flags by now
+       drv_glb->flags = 0;
 
-       if (bin->eDrvGlb) {
-               drv_glb = (ce_driver_globals*)bin->eDrvGlb;
+#ifdef CYGPKG_REDBOOT_NETWORKING
+       // Local ethernet MAC address
+       memcpy(drv_glb->macAddr, __local_enet_addr, sizeof(__local_enet_addr));
+
+       // Local IP address
+       memcpy(&drv_glb->ipAddr, __local_ip_addr, sizeof(__local_ip_addr));
+
+       // Subnet mask
+       memcpy(&drv_glb->ipMask, __local_ip_mask, sizeof(__local_ip_mask));
+
+       // Gateway config
+#ifdef CYGSEM_REDBOOT_NETWORKING_USE_GATEWAY
+       // Getway IP address
+       memcpy(&drv_glb->ipGate, __local_ip_gate, sizeof(__local_ip_gate));
+#endif
+#endif
+}
 
-               // Fill out driver globals
-               memset(drv_glb, 0, sizeof(ce_driver_globals));
+#if WINCE_ALTERNATE_ARG_BASE
+void setup_alt_drv_globals(ce_alt_driver_globals *alt_drv_glb)
+{
+       diag_printf("%s %p\n", __FUNCTION__, alt_drv_glb);
+       // Fill out driver globals
+       memset(alt_drv_glb, 0, sizeof(ce_alt_driver_globals));
 
-               // Signature
-               drv_glb->signature = DRV_GLB_SIGNATURE;
+       alt_drv_glb->header.signature = ALT_DRV_GLB_SIGNATURE;
+       alt_drv_glb->header.oalVersion = 1;
+       alt_drv_glb->header.bspVersion = 1;
 
-               // No flags by now
-               drv_glb->flags = 0;
+       alt_drv_glb->kitl.flags = 0;
+       diag_sprintf(alt_drv_glb->deviceId, "Triton");          
 
 #ifdef CYGPKG_REDBOOT_NETWORKING
-               // Local ethernet MAC address
-               memcpy(drv_glb->macAddr, __local_enet_addr, sizeof(__local_enet_addr));
+       memcpy(&alt_drv_glb->kitl.mac[0], __local_enet_addr, sizeof(__local_enet_addr));
+       diag_sprintf(alt_drv_glb->deviceId, "Triton%02X", __local_enet_addr[5]);
 
-               // Local IP address
-               memcpy(&drv_glb->ipAddr, __local_ip_addr, sizeof(__local_ip_addr));
+       // Local IP address
+       memcpy(&alt_drv_glb->kitl.ipAddress, __local_ip_addr, sizeof(__local_ip_addr));
 
-               // Subnet mask
-               memcpy(&drv_glb->ipMask, __local_ip_mask, sizeof(__local_ip_mask));
+       // Subnet mask
+       memcpy(&alt_drv_glb->kitl.ipMask, __local_ip_mask, sizeof(__local_ip_mask));
 
-               // Gateway config
+       // Gateway config
 #ifdef CYGSEM_REDBOOT_NETWORKING_USE_GATEWAY
-               // Getway IP address
-               memcpy(&drv_glb->ipGate, __local_ip_gate, sizeof(__local_ip_gate));
+       // Getway IP address
+       memcpy(&alt_drv_glb->kitl.ipRoute, __local_ip_gate, sizeof(__local_ip_gate));
 #endif
+#endif
+}
 #else
-               // Local ethernet MAC address
-               memset(drv_glb->macAddr, 0, sizeof(drv_glb->macAddr));
+#define setup_alt_drv_globals(x)       CYG_EMPTY_STATEMENT
+#endif
 
-               // Local IP address
-               memset(&drv_glb->ipAddr, 0, sizeof(drv_glb->ipAddr));
+void ce_prepare_run_bin(ce_bin *bin)
+{
+       ce_driver_globals *drv_glb;
 
-               // Subnet mask
-               memset(&drv_glb->ipMask, 0, sizeof(drv_glb->ipMask));
+       diag_printf("%s\n", __FUNCTION__);
 
-               // Getway IP address
-               memset(&drv_glb->ipGate, 0, sizeof(drv_glb->ipGate));
-#endif // CYGPKG_REDBOOT_NETWORKING
-               // EDBG services config
-               memcpy(&drv_glb->edbgConfig, &bin->edbgConfig, sizeof(bin->edbgConfig));
+#if WINCE_ALTERNATE_ARG_BASE
+       ce_alt_driver_globals *alt_drv_glb = &_KARO_CECFG_START;
+       char *karo_magic = &_KARO_MAGIC[0];
+       unsigned long *karo_structure_size = &_KARO_STRUCT_SIZE;
 
-               // Equotip specific
-#ifdef CYGPKG_HAL_ARM_XSCALE_TRITON270_EQT32
-               // Copy configuration
+       memcpy(karo_magic, "KARO_CE6", sizeof(_KARO_MAGIC));
+       *karo_structure_size = sizeof(ce_alt_driver_globals);
+#endif
+       // Clear os RAM area (if needed)
+       if (bin->edbgConfig.flags & EDBG_FL_CLEANBOOT) {
+               diag_printf("Preparing clean boot ... ");
+               memset((void *)bin->eRamStart, 0, bin->eRamLen);
+               diag_printf("ok\n");
+       }
 
-               drv_glb->contrastDefault = eedat.lcd_contrast;
-               drv_glb->contrastBand = eedat.lcd_contrast_band;
-               drv_glb->backlight = eedat.lcd_backlight;
-               drv_glb->backlightOffset = eedat.lcd_backlight_offset;
+       // Prepare driver globals (if needed)
+       if (bin->eDrvGlb) {
+               drv_glb = (ce_driver_globals *)bin->eDrvGlb;
 
-               memcpy(drv_glb->macAddr, eedat.mac_address, sizeof(drv_glb->macAddr));
-#endif
+               setup_drv_globals(drv_glb);
+               setup_alt_drv_globals(alt_drv_glb);
+
+               // EDBG services config
+               memcpy(&drv_glb->edbgConfig, &bin->edbgConfig, sizeof(bin->edbgConfig));
        }
 
        // Update global RedBoot entry point address
@@ -477,7 +553,7 @@ void ce_redboot_version(unsigned int *vhigh, unsigned int *vlow)
        pow = 1;
        p = pver + strlen(pver) - 1;
 
-       while (len --) {
+       while (len--) {
                if (*p >= '0' && *p <= '9') {
                        *ver += ((*p - '0') * pow);
                        pow *= 10;
@@ -490,7 +566,7 @@ void ce_redboot_version(unsigned int *vhigh, unsigned int *vlow)
                                break;
                        }
                }
-               p --;
+               p--;
        }
 }
 
@@ -592,7 +668,6 @@ void ce_load(int argc, char *argv[])
 
        if (g_bin.binLen) {
                // Try to receive edbg commands from host
-
                ce_init_edbg_link(&g_net);
 
                if (verbose) {
@@ -604,11 +679,9 @@ void ce_load(int argc, char *argv[])
                }
 
                // Prepare WinCE image for execution
-
                ce_prepare_run_bin(&g_bin);
 
                // Launch WinCE, if necessary
-
                if (g_net.gotJumpingRequest) {
                        ce_run_bin(&g_bin);
                }
@@ -697,7 +770,7 @@ int ce_send_bootme(ce_net *net)
 {
        eth_dbg_hdr *header;
        edbg_bootme_data *data;
-       int verHigh, verLow;
+       unsigned int verHigh, verLow;
 
        // Fill out BOOTME packet
        memset(net->data, 0, BOOTME_PKT_SIZE);
@@ -767,8 +840,8 @@ int ce_send_bootme(ce_net *net)
        // Some diag output ...
        if (net->verbose) {
                diag_printf("Sending BOOTME request [%d] to %s\n",
-                       (int)net->secNum,
-                       inet_ntoa((in_addr_t *)&net->srvAddrSend));
+                           net->secNum,
+                           inet_ntoa((in_addr_t *)&net->srvAddrSend));
        }
 
        // Send packet