|
| 1 | +/* |
| 2 | + * 2008 (c) STMicroelectronics, Inc. |
| 3 | + * Author: Ryan Chen <Ryan.Chen at st.com> |
| 4 | + * |
| 5 | + * Redistribution and use in source and binary forms, with or without |
| 6 | + * modification, are permitted provided that the following conditions |
| 7 | + * are met: |
| 8 | + * 1. Redistributions of source code must retain the above copyright |
| 9 | + * notice, this list of conditions and the following disclaimer. |
| 10 | + * 2. Redistributions in binary form must reproduce the above copyright |
| 11 | + * notice, this list of conditions and the following disclaimer in the |
| 12 | + * documentation and/or other materials provided with the distribution. |
| 13 | + * 3. All advertising materials mentioning features or use of this software |
| 14 | + * must display the following acknowledgement: |
| 15 | + * This product includes software developed by Opsycon AB, Sweden. |
| 16 | + * 4. The name of the author may not be used to endorse or promote products |
| 17 | + * derived from this software without specific prior written permission. |
| 18 | + * |
| 19 | + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS |
| 20 | + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
| 21 | + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| 22 | + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY |
| 23 | + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| 24 | + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
| 25 | + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
| 26 | + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
| 27 | + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
| 28 | + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
| 29 | + * SUCH DAMAGE. |
| 30 | + */ |
| 31 | + |
| 32 | +/* |
| 33 | + * Windows CE Binary Image Data Format |
| 34 | + * The binary image (.bin) file format organizes data by sections. Each section contains |
| 35 | + * a section header that specifies the starting address, length, and checksum for that |
| 36 | + * section. |
| 37 | + * |
| 38 | + * Refer to <http://msdn.microsoft.com/en-us/library/ms924510.aspx> |
| 39 | + * |
| 40 | + * The following table shows the .bin file format. |
| 41 | + * Field Length (bytes) Description |
| 42 | + * Sync bytes (optional) 7 Byte 0 is B, indicating a .bin file format. |
| 43 | + * Bytes 1-6 are reserved and set to 0, 0, 0, F, F, \n. |
| 44 | + * Run-time image address 4 Physical starting address of the run-time image. |
| 45 | + * Run-time image length 4 Physical length, in bytes, of the run-time image. |
| 46 | + * Record Address 4 Physical starting address of data record. |
| 47 | + * If this value is zero, the Record Address is the end of |
| 48 | + * the file, and record length contains the starting address |
| 49 | + * of the run-time image. |
| 50 | + * Record length 4 Length of record data, in bytes. |
| 51 | + * Record checksum 4 Signed 32-bit sum of record data bytes. |
| 52 | + * Record data Record length Record data. |
| 53 | + */ |
| 54 | +#define WINCE_IMAGE_SYNC_SIZE 7 |
| 55 | +#define WINCE_IMAGE_SYNC "B000FF\n" |
| 56 | + |
| 57 | +typedef struct { |
| 58 | + unsigned char sync_bytes[WINCE_IMAGE_SYNC_SIZE]; |
| 59 | + unsigned int img_addr; |
| 60 | + unsigned int img_length; |
| 61 | +} type_wince_image_header; |
| 62 | + |
| 63 | +int check_sum(unsigned char * buf, int len, unsigned int checksum) |
| 64 | +{ |
| 65 | + unsigned int count,i; |
| 66 | + |
| 67 | + for (i = 0,count = 0 ; i < len ; i++) |
| 68 | + count += buf[i]; |
| 69 | + |
| 70 | + if (count == checksum) |
| 71 | + return 0; |
| 72 | + |
| 73 | + return 1; |
| 74 | +} |
| 75 | + |
| 76 | +/* ====================================================================== |
| 77 | + * Determine if a valid WinCE image exists at the given memory location. |
| 78 | + * First looks at the image header field, the makes sure that it is |
| 79 | + * WinCE image. |
| 80 | + * ====================================================================== */ |
| 81 | +int valid_wince_image (unsigned long addr) |
| 82 | +{ |
| 83 | + type_wince_image_header *p = (type_wince_image_header *)addr; |
| 84 | + |
| 85 | + if(strcmp((char *)p->sync_bytes, (char *)WINCE_IMAGE_SYNC) != 0) |
| 86 | + return 0; |
| 87 | + |
| 88 | + return 1; |
| 89 | +} |
| 90 | + |
| 91 | +/* ====================================================================== |
| 92 | + * A very simple WinCE image loader, assumes the image is valid, returns the |
| 93 | + * entry point address. |
| 94 | + * ====================================================================== */ |
| 95 | +unsigned long load_wince_image (unsigned long addr) |
| 96 | +{ |
| 97 | + unsigned char *p = (unsigned char *)addr; |
| 98 | + u32 start_addr, total_length; |
| 99 | + u32 record_addr, record_length, record_checksum; |
| 100 | + u32 i = 0; |
| 101 | + |
| 102 | + if(valid_wince_image(addr) == 0) |
| 103 | + return ~0; |
| 104 | + |
| 105 | + printf("WINCE image is found: "); |
| 106 | + p += WINCE_IMAGE_SYNC_SIZE; |
| 107 | + start_addr = (u32)(p[3]<<24) + (u32)(p[2]<<16) + (u32)(p[1]<<8) + (u32)p[0]; |
| 108 | + p += 4; |
| 109 | + total_length = (u32)(p[3]<<24) + (u32)(p[2]<<16) + (u32)(p[1]<<8) + (u32)p[0]; |
| 110 | + printf(" Start Address = 0x%x @ Total Length = 0x%x\n", start_addr, total_length); |
| 111 | + p += 4; |
| 112 | + |
| 113 | + /* read each records */ |
| 114 | + while(1) { |
| 115 | + record_length = (u32)(p[7]<<24) + (u32)(p[6]<<16) + (u32)(p[5]<<8) + (u32)p[4]; |
| 116 | + record_checksum = (u32)(p[11]<<24) + (u32)(p[10]<<16) + (u32)(p[9]<<8) + (u32)p[8]; |
| 117 | + record_addr = (u32)(p[3]<<24) + (u32)(p[2]<<16) + (u32)(p[1]<<8) + (u32)p[0]; |
| 118 | + if(record_addr == 0) |
| 119 | + break; |
| 120 | + |
| 121 | + if(check_sum((unsigned char *)&p[12], record_length, record_checksum) != 0) { |
| 122 | + printf("Checksum Error!\n"); |
| 123 | + return (unsigned long)~0; |
| 124 | + } |
| 125 | + memcpy ((void *)record_addr, (const void *)&p[12], (unsigned long)record_length); |
| 126 | + printf("Region %d: Loading from 0x%x to 0x%x @ Length 0x%x\n", i, (unsigned int)&p[12], \ |
| 127 | + (unsigned int)record_addr, record_length); |
| 128 | + p = p + 12 + record_length; |
| 129 | + i++; |
| 130 | + } |
| 131 | + |
| 132 | + /* the lastest checksun should be zero */ |
| 133 | + if(record_checksum != 0) { |
| 134 | + printf("Checksum Error!\n"); |
| 135 | + return (unsigned long)~0; |
| 136 | + } |
| 137 | + |
| 138 | + /* the lastest length is entry address */ |
| 139 | + return (unsigned long)record_length; |
| 140 | +} |
| 141 | + |
| 142 | +/* ====================================================================== |
| 143 | + * Interpreter command to boot WinCE from a memory image. The image can |
| 144 | + * be an WinCE image. WinCE image do not need the |
| 145 | + * bootline and other parameters. |
| 146 | + * ====================================================================== */ |
| 147 | +int do_bootwince (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) |
| 148 | +{ |
| 149 | + unsigned long addr; /* Address of image */ |
| 150 | + |
| 151 | + /* |
| 152 | + * Check the loadaddr variable. |
| 153 | + * If we don't know where the image is then we're done. |
| 154 | + */ |
| 155 | + if (argc < 2) |
| 156 | + addr = load_addr; |
| 157 | + else |
| 158 | + addr = simple_strtoul (argv[1], NULL, 16); |
| 159 | + |
| 160 | +#if defined(CONFIG_CMD_NET) |
| 161 | + /* Check to see if we need to tftp the image ourselves before starting */ |
| 162 | + if ((argc == 2) && (strcmp (argv[1], "tftp") == 0)) { |
| 163 | + if (NetLoop (TFTP) <= 0) |
| 164 | + return 1; |
| 165 | + printf ("Automatic boot of WinCE image at address 0x%08lx ... \n", addr); |
| 166 | + } |
| 167 | +#endif |
| 168 | + |
| 169 | + /* |
| 170 | + * If the data at the load address is an WinCE image, then |
| 171 | + * treat it like an WinCE image. Otherwise, return 1 |
| 172 | + */ |
| 173 | + if (valid_wince_image (addr)) { |
| 174 | + addr = load_wince_image (addr); |
| 175 | + } else { |
| 176 | + puts ("## Not an WinCE image, exit!\n"); |
| 177 | + return 1; |
| 178 | + /* leave addr as load_addr */ |
| 179 | + } |
| 180 | + |
| 181 | + printf ("## Starting Wince at 0x%08lx ...\n", addr); |
| 182 | + |
| 183 | + ((void (*)(void)) addr) (); |
| 184 | + |
| 185 | + puts ("## WinCE terminated\n"); |
| 186 | + return 1; |
| 187 | +} |
0 commit comments