summaryrefslogtreecommitdiff
path: root/apps
diff options
context:
space:
mode:
authorDaniel Stenberg <daniel@haxx.se>2003-07-21 10:56:23 +0000
committerDaniel Stenberg <daniel@haxx.se>2003-07-21 10:56:23 +0000
commit754426e11f82eca75bbca302674d4cc92cdf53be (patch)
tree9a1e374332b68348e9d29842448ba6c2c2067592 /apps
parentbf6481e79d2eef90183cdd07ada7633fdc5fcf55 (diff)
downloadrockbox-754426e11f82eca75bbca302674d4cc92cdf53be.tar.gz
rockbox-754426e11f82eca75bbca302674d4cc92cdf53be.zip
Massive code-policing. Use proper indent. Use proper comments. Use proper
source code width. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@3857 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps')
-rw-r--r--apps/plugins/rockbox_flash.c1052
1 files changed, 537 insertions, 515 deletions
diff --git a/apps/plugins/rockbox_flash.c b/apps/plugins/rockbox_flash.c
index 9a8306e5df..1fb8ce5bcc 100644
--- a/apps/plugins/rockbox_flash.c
+++ b/apps/plugins/rockbox_flash.c
@@ -35,398 +35,415 @@
35#define UINT32 unsigned long 35#define UINT32 unsigned long
36#endif 36#endif
37 37
38// hard-coded values 38/* hard-coded values */
39static volatile UINT8* FB = (UINT8*)0x02000000; // Flash base address 39static volatile UINT8* FB = (UINT8*)0x02000000; /* Flash base address */
40#define SECTORSIZE 4096 // size of one flash sector 40#define SECTORSIZE 4096 /* size of one flash sector */
41 41
42#define ROCKBOX_DEST 0x09000000 42#define ROCKBOX_DEST 0x09000000
43#define ROCKBOX_EXEC 0x09000200 43#define ROCKBOX_EXEC 0x09000200
44#define FILENAME "/rockbox.ucl" 44#define FILENAME "/rockbox.ucl"
45#define VERS_ADR 0xFE // position of firmware version value in Flash 45#define VERS_ADR 0xFE /* position of firmware version value in Flash */
46#define UCL_HEADER 26 // size of the header generated by uclpack 46#define UCL_HEADER 26 /* size of the header generated by uclpack */
47 47
48typedef struct 48typedef struct
49{ 49{
50 UINT32 destination; // address to copy it to 50 UINT32 destination; /* address to copy it to */
51 UINT32 size; // how many bytes of payload (to the next header) 51 UINT32 size; /* how many bytes of payload (to the next header) */
52 UINT32 execute; // entry point 52 UINT32 execute; /* entry point */
53 UINT32 flags; // uncompressed or compressed 53 UINT32 flags; /* uncompressed or compressed */
54 // end of header, now comes the payload 54 /* end of header, now comes the payload */
55} tImageHeader; 55} tImageHeader;
56 56
57 57/* result of the CheckFirmwareFile() function */
58// result of the CheckFirmwareFile() function
59typedef enum 58typedef enum
60{ 59{
61 eOK = 0, 60 eOK = 0,
62 eFileNotFound, // errors from here on 61 eFileNotFound, /* errors from here on */
63 eTooBig, 62 eTooBig,
64 eTooSmall, 63 eTooSmall,
65 eReadErr, 64 eReadErr,
66 eNotUCL, 65 eNotUCL,
67 eWrongAlgorithm, 66 eWrongAlgorithm,
68 eMultiBlocks, 67 eMultiBlocks,
69} tCheckResult; 68} tCheckResult;
70 69
71typedef struct 70typedef struct
72{ 71{
73 UINT8 manufacturer; 72 UINT8 manufacturer;
74 UINT8 id; 73 UINT8 id;
75 int size; 74 int size;
76 char name[32]; 75 char name[32];
77} tFlashInfo; 76} tFlashInfo;
78 77
79static struct plugin_api* rb; // here is a global api struct pointer 78static struct plugin_api* rb; /* here is a global api struct pointer */
80
81#define SEC_SIZE 4096 // size of one flash sector
82static UINT8 sector[SEC_SIZE]; // better not place this on the stack...
83 79
80#define SEC_SIZE 4096 /* size of one flash sector */
81static UINT8 sector[SEC_SIZE]; /* better not place this on the stack... */
84 82
85/***************** Flash Functions *****************/ 83/***************** Flash Functions *****************/
86 84
87 85
88// read the manufacturer and device ID 86/* read the manufacturer and device ID */
89bool ReadID(volatile UINT8* pBase, UINT8* pManufacturerID, UINT8* pDeviceID) 87bool ReadID(volatile UINT8* pBase, UINT8* pManufacturerID, UINT8* pDeviceID)
90{ 88{
91 UINT8 not_manu, not_id; // read values before switching to ID mode 89 UINT8 not_manu, not_id; /* read values before switching to ID mode */
92 UINT8 manu, id; // read values when in ID mode 90 UINT8 manu, id; /* read values when in ID mode */
93 91
94 pBase = (UINT8*)((UINT32)pBase & 0xFFF80000); // round down to 512k align, to make shure 92 pBase = (UINT8*)((UINT32)pBase & 0xFFF80000); /* round down to 512k align,
95 93 to make sure */
96 not_manu = pBase[0]; // read the normal content 94
97 not_id = pBase[1]; // should be 'A' (0x41) and 'R' (0x52) from the "ARCH" marker 95 not_manu = pBase[0]; /* read the normal content */
98 96 not_id = pBase[1]; /* should be 'A' (0x41) and 'R' (0x52) from the
99 pBase[0x5555] = 0xAA; // enter command mode 97 "ARCH" marker */
100 pBase[0x2AAA] = 0x55; 98
101 pBase[0x5555] = 0x90; // ID command 99 pBase[0x5555] = 0xAA; /* enter command mode */
102 rb->sleep(HZ/50); // Atmel wants 20ms pause here 100 pBase[0x2AAA] = 0x55;
103 101 pBase[0x5555] = 0x90; /* ID command */
104 manu = pBase[0]; 102 rb->sleep(HZ/50); /* Atmel wants 20ms pause here */
105 id = pBase[1]; 103
106 104 manu = pBase[0];
107 pBase[0] = 0xF0; // reset flash (back to normal read mode) 105 id = pBase[1];
108 rb->sleep(HZ/50); // Atmel wants 20ms pause here 106
109 107 pBase[0] = 0xF0; /* reset flash (back to normal read mode) */
110 /* I assume success if the obtained values are different from 108 rb->sleep(HZ/50); /* Atmel wants 20ms pause here */
111 the normal flash content. This is not perfectly bulletproof, they 109
112 could theoretically be the same by chance, causing us to fail. */ 110 /* I assume success if the obtained values are different from
113 if (not_manu != manu || not_id != id) // a value has changed 111 the normal flash content. This is not perfectly bulletproof, they
114 { 112 could theoretically be the same by chance, causing us to fail. */
115 *pManufacturerID = manu; // return the results 113 if (not_manu != manu || not_id != id) /* a value has changed */
116 *pDeviceID = id; 114 {
117 return true; // success 115 *pManufacturerID = manu; /* return the results */
118 } 116 *pDeviceID = id;
119 return false; // fail 117 return true; /* success */
118 }
119 return false; /* fail */
120} 120}
121 121
122 122/* eraze the sector which contains the given address */
123// eraze the sector which contains the given address
124bool ErazeSector(volatile UINT8* pAddr) 123bool ErazeSector(volatile UINT8* pAddr)
125{ 124{
126 volatile UINT8* pBase = (UINT8*)((UINT32)pAddr & 0xFFF80000); // round down to 512k align 125 volatile UINT8* pBase =
127 unsigned timeout = 43000; // the timeout loop should be no less than 25ms 126 (UINT8*)((UINT32)pAddr & 0xFFF80000); /* round down to 512k align */
128 127 unsigned timeout = 43000; /* the timeout loop should be no less than
129 pBase[0x5555] = 0xAA; // enter command mode 128 25ms */
130 pBase[0x2AAA] = 0x55; 129
131 pBase[0x5555] = 0x80; // eraze command 130 pBase[0x5555] = 0xAA; /* enter command mode */
132 pBase[0x5555] = 0xAA; // enter command mode 131 pBase[0x2AAA] = 0x55;
133 pBase[0x2AAA] = 0x55; 132 pBase[0x5555] = 0x80; /* eraze command */
134 *pAddr = 0x30; // eraze the sector 133 pBase[0x5555] = 0xAA; /* enter command mode */
135 134 pBase[0x2AAA] = 0x55;
136 // I counted 7 instructions for this loop -> min. 0.58 us per round 135 *pAddr = 0x30; /* eraze the sector */
137 // Plus memory waitstates it will be much more, gives margin 136
138 while (*pAddr != 0xFF && --timeout); // poll for erazed 137 /* I counted 7 instructions for this loop -> min. 0.58 us per round
139 138 Plus memory waitstates it will be much more, gives margin */
140 return (timeout != 0); 139 while (*pAddr != 0xFF && --timeout); /* poll for erazed */
140
141 return (timeout != 0);
141} 142}
142 143
143// address must be in an erazed location 144/* address must be in an erazed location */
144inline bool ProgramByte(volatile UINT8* pAddr, UINT8 data) 145inline bool ProgramByte(volatile UINT8* pAddr, UINT8 data)
145{ 146{
146 unsigned timeout = 35; // the timeout loop should be no less than 20us 147 unsigned timeout = 35; /* the timeout loop should be no less than 20us */
147 148
148 if (~*pAddr & data) // just a safety feature, not really necessary 149 if (~*pAddr & data) /* just a safety feature, not really necessary */
149 return false; // can't set any bit from 0 to 1 150 return false; /* can't set any bit from 0 to 1 */
150 151
151 FB[0x5555] = 0xAA; // enter command mode 152 FB[0x5555] = 0xAA; /* enter command mode */
152 FB[0x2AAA] = 0x55; 153 FB[0x2AAA] = 0x55;
153 FB[0x5555] = 0xA0; // byte program command 154 FB[0x5555] = 0xA0; /* byte program command */
154 155
155 *pAddr = data; 156 *pAddr = data;
156 157
157 // I counted 7 instructions for this loop -> min. 0.58 us per round 158 /* I counted 7 instructions for this loop -> min. 0.58 us per round
158 // Plus memory waitstates it will be much more, gives margin 159 Plus memory waitstates it will be much more, gives margin */
159 while (*pAddr != data && --timeout); // poll for programmed 160 while (*pAddr != data && --timeout); /* poll for programmed */
160 161
161 return (timeout != 0); 162 return (timeout != 0);
162} 163}
163 164
164// this returns true if supported and fills the info struct 165/* this returns true if supported and fills the info struct */
165bool GetFlashInfo(tFlashInfo* pInfo) 166bool GetFlashInfo(tFlashInfo* pInfo)
166{ 167{
167 rb->memset(pInfo, 0, sizeof(tFlashInfo)); 168 rb->memset(pInfo, 0, sizeof(tFlashInfo));
168 169
169 if (!ReadID(FB, &pInfo->manufacturer, &pInfo->id)) 170 if (!ReadID(FB, &pInfo->manufacturer, &pInfo->id))
170 return false; 171 return false;
171 172
172 if (pInfo->manufacturer == 0xBF) // SST 173 if (pInfo->manufacturer == 0xBF) /* SST */
173 { 174 {
174 if (pInfo->id == 0xD6) 175 if (pInfo->id == 0xD6)
175 { 176 {
176 pInfo->size = 256* 1024; // 256k 177 pInfo->size = 256* 1024; /* 256k */
177 rb->strcpy(pInfo->name, "SST39VF020"); 178 rb->strcpy(pInfo->name, "SST39VF020");
178 return true; 179 return true;
179 } 180 }
180 else if (pInfo->id == 0xD7) 181 else if (pInfo->id == 0xD7)
181 { 182 {
182 pInfo->size = 512* 1024; // 512k 183 pInfo->size = 512* 1024; /* 512k */
183 rb->strcpy(pInfo->name, "SST39VF040"); 184 rb->strcpy(pInfo->name, "SST39VF040");
184 return true; 185 return true;
185 } 186 }
186 else 187 else
187 return false; 188 return false;
188 } 189 }
189 return false; 190 return false;
190} 191}
191 192
192 193
193/*********** Tool Functions ************/ 194/*********** Tool Functions ************/
194 195
195// place a 32 bit value into memory, big endian 196/* place a 32 bit value into memory, big endian */
196void Write32(UINT8* pByte, UINT32 value) 197void Write32(UINT8* pByte, UINT32 value)
197{ 198{
198 pByte[0] = (UINT8)(value >> 24); 199 pByte[0] = (UINT8)(value >> 24);
199 pByte[1] = (UINT8)(value >> 16); 200 pByte[1] = (UINT8)(value >> 16);
200 pByte[2] = (UINT8)(value >> 8); 201 pByte[2] = (UINT8)(value >> 8);
201 pByte[3] = (UINT8)(value); 202 pByte[3] = (UINT8)(value);
202} 203}
203 204
204// read a 32 bit value from memory, big endian 205/* read a 32 bit value from memory, big endian */
205UINT32 Read32(UINT8* pByte) 206UINT32 Read32(UINT8* pByte)
206{ 207{
207 UINT32 value = 0; 208 UINT32 value;
208 209
209 value |= (UINT32)pByte[0] << 24; 210 value = (UINT32)pByte[0] << 24;
210 value |= (UINT32)pByte[1] << 16; 211 value |= (UINT32)pByte[1] << 16;
211 value |= (UINT32)pByte[2] << 8; 212 value |= (UINT32)pByte[2] << 8;
212 value |= (UINT32)pByte[3]; 213 value |= (UINT32)pByte[3];
213 214
214 return value; 215 return value;
215} 216}
216 217
217 218/* get the start address of the second image */
218// get the start address of the second image
219tImageHeader* GetSecondImage(void) 219tImageHeader* GetSecondImage(void)
220{ 220{
221 tImageHeader* pImage1; 221 tImageHeader* pImage1;
222 UINT32 pos = 0; // dafault: not found 222 UINT32 pos = 0; /* default: not found */
223 UINT32* pFlash = (UINT32*)FB; 223 UINT32* pFlash = (UINT32*)FB;
224 224
225 UINT16 version = *(UINT16*)(FB + VERS_ADR); 225 UINT16 version = *(UINT16*)(FB + VERS_ADR);
226 if (version < 200) // at least 2.00 226 if (version < 200) /* at least 2.00 */
227 { 227 {
228 return 0; // not our flash layout 228 return 0; /* not our flash layout */
229 } 229 }
230 230
231 // determine the first image position 231 /* determine the first image position */
232 pos = pFlash[2] + pFlash[3]; // position + size of the bootloader = after it 232 pos = pFlash[2] + pFlash[3]; /* position + size of the bootloader = after
233 pos = (pos + 3) & ~3; // be shure it's 32 bit aligned 233 it */
234 pImage1 = (tImageHeader*)pos; 234 pos = (pos + 3) & ~3; /* be sure it's 32 bit aligned */
235 235 pImage1 = (tImageHeader*)pos;
236 if (pImage1->destination != ROCKBOX_DEST || pImage1->execute != ROCKBOX_EXEC) 236
237 return 0; // seems to be no Rockbox stuff in here 237 if (pImage1->destination != ROCKBOX_DEST ||
238 238 pImage1->execute != ROCKBOX_EXEC)
239 if (pImage1->size != 0) 239 return 0; /* seems to be no Rockbox stuff in here */
240 { // success, we have a second image 240
241 pos = (UINT32)pImage1 + sizeof(tImageHeader) + pImage1->size; 241 if (pImage1->size != 0)
242 if (((pos + SECTORSIZE-1) & ~(SECTORSIZE-1)) != pos) 242 {
243 { // not sector-aligned 243 /* success, we have a second image */
244 pos = 0; // sanity check failed 244 pos = (UINT32)pImage1 + sizeof(tImageHeader) + pImage1->size;
245 } 245 if (((pos + SECTORSIZE-1) & ~(SECTORSIZE-1)) != pos)
246 } 246 { /* not sector-aligned */
247 247 pos = 0; // sanity check failed
248 return (tImageHeader*)pos; 248 }
249 }
250
251 return (tImageHeader*)pos;
249} 252}
250 253
251 254
252/*********** Image File Functions ************/ 255/*********** Image File Functions ************/
253 256
254// so far, only compressed images in UCL NRV algorithm 2e supported 257/* so far, only compressed images in UCL NRV algorithm 2e supported */
255tCheckResult CheckImageFile(char* filename, int space, tImageHeader* pHeader) 258tCheckResult CheckImageFile(char* filename, int space, tImageHeader* pHeader)
256{ 259{
257 int i; 260 int i;
258 int fd; 261 int fd;
259 int filesize; // size info 262 int filesize; /* size info */
260 263
261 int fileread = 0; // total size as read from the file 264 int fileread = 0; /* total size as read from the file */
262 int read; // how many for this sector 265 int read; /* how many for this sector */
263 266
264 // magic file header for compressed files 267 /* magic file header for compressed files */
265 static const UINT8 magic[8] = { 0x00,0xe9,0x55,0x43,0x4c,0xff,0x01,0x1a }; 268 static const UINT8 magic[8] = { 0x00,0xe9,0x55,0x43,0x4c,0xff,0x01,0x1a };
266 UINT8 ucl_header[UCL_HEADER]; 269 UINT8 ucl_header[UCL_HEADER];
267 270
268 fd = rb->open(filename, O_RDONLY); 271 fd = rb->open(filename, O_RDONLY);
269 if (fd < 0) 272 if (fd < 0)
270 return eFileNotFound; 273 return eFileNotFound;
271 274
272 filesize = rb->filesize(fd); 275 filesize = rb->filesize(fd);
273 if (filesize - (int)sizeof(ucl_header) - 8 > space) 276 if (filesize - (int)sizeof(ucl_header) - 8 > space)
274 { 277 {
275 rb->close(fd); 278 rb->close(fd);
276 return eTooBig; 279 return eTooBig;
277 } 280 }
278 else if (filesize < 50000) // give it some reasonable lower limit 281 else if (filesize < 50000) /* give it some reasonable lower limit */
279 { 282 {
280 rb->close(fd); 283 rb->close(fd);
281 return eTooSmall; 284 return eTooSmall;
282 } 285 }
283 286
284 // do some sanity checks 287 /* do some sanity checks */
285 288
286 read = rb->read(fd, ucl_header, sizeof(ucl_header)); 289 read = rb->read(fd, ucl_header, sizeof(ucl_header));
287 fileread += read; 290 fileread += read;
288 if (read != sizeof(ucl_header)) 291 if (read != sizeof(ucl_header))
289 { 292 {
290 rb->close(fd); 293 rb->close(fd);
291 return eReadErr; 294 return eReadErr;
292 } 295 }
293 296
294 // compare the magic header 297 /* compare the magic header */
295 for (i=0; i<8; i++) 298 for (i=0; i<8; i++)
296 { 299 {
297 if (ucl_header[i] != magic[i]) 300 if (ucl_header[i] != magic[i])
298 { 301 {
299 rb->close(fd); 302 rb->close(fd);
300 return eNotUCL; 303 return eNotUCL;
301 } 304 }
302 } 305 }
303 306
304 // check for supported algorithm 307 /* check for supported algorithm */
305 if (ucl_header[12] != 0x2E) 308 if (ucl_header[12] != 0x2E)
306 { 309 {
307 rb->close(fd); 310 rb->close(fd);
308 return eWrongAlgorithm; 311 return eWrongAlgorithm;
309 } 312 }
310 313
311 pHeader->size = Read32(ucl_header + 22); // compressed size 314 pHeader->size = Read32(ucl_header + 22); /* compressed size */
312 if (pHeader->size != filesize - sizeof(ucl_header) - 8) 315 if (pHeader->size != filesize - sizeof(ucl_header) - 8)
313 { 316 {
314 rb->close(fd); 317 rb->close(fd);
315 return eMultiBlocks; 318 return eMultiBlocks;
316 } 319 }
317 320
318 if (Read32(ucl_header + 18) > pHeader->size) // compare with uncompressed size 321 if (Read32(ucl_header + 18) > pHeader->size) /* compare with uncompressed
319 { // normal case 322 size */
320 pHeader->flags = 0x00000001; // flags for UCL compressed 323 { /* normal case */
321 } 324 pHeader->flags = 0x00000001; /* flags for UCL compressed */
322 else 325 }
323 { 326 else
324 pHeader->flags = 0x00000000; // very unlikely, content was not compressible 327 {
325 } 328 pHeader->flags = 0x00000000; /* very unlikely, content was not
326 329 compressible */
327 // check if we can read the whole file 330 }
328 do 331
329 { 332 /* check if we can read the whole file */
330 read = rb->read(fd, sector, SEC_SIZE); 333 do
331 fileread += read; 334 {
332 } while (read == SEC_SIZE); 335 read = rb->read(fd, sector, SEC_SIZE);
333 336 fileread += read;
334 rb->close(fd); 337 } while (read == SEC_SIZE);
335 338
336 if (fileread != filesize) 339 rb->close(fd);
337 return eReadErr; 340
338 341 if (fileread != filesize)
339 // fill in the hardcoded rest of the header 342 return eReadErr;
340 pHeader->destination = ROCKBOX_DEST; 343
341 pHeader->execute = ROCKBOX_EXEC; 344 /* fill in the hardcoded rest of the header */
342 345 pHeader->destination = ROCKBOX_DEST;
343 return eOK; 346 pHeader->execute = ROCKBOX_EXEC;
347
348 return eOK;
344} 349}
345 350
346 351
347// returns the # of failures, 0 on success 352/* returns the # of failures, 0 on success */
348unsigned ProgramImageFile(char* filename, UINT8* pos, tImageHeader* pImageHeader, int start, int size) 353unsigned ProgramImageFile(char* filename, UINT8* pos,
354 tImageHeader* pImageHeader, int start, int size)
349{ 355{
350 int i; 356 int i;
351 int fd; 357 int fd;
352 int read; // how many for this sector 358 int read; /* how many for this sector */
353 unsigned failures = 0; 359 unsigned failures = 0;
354 360
355 fd = rb->open(filename, O_RDONLY); 361 fd = rb->open(filename, O_RDONLY);
356 if (fd < 0) 362 if (fd < 0)
357 return false; 363 return false;
358 364
359 // no error checking necessary here, we checked for minimum size already 365 /* no error checking necessary here, we checked for minimum size
360 rb->lseek(fd, start, SEEK_SET); // go to start position 366 already */
361 367 rb->lseek(fd, start, SEEK_SET); /* go to start position */
362 *(tImageHeader*)sector = *pImageHeader; // copy header into sector buffer 368
363 read = rb->read(fd, sector + sizeof(tImageHeader), SEC_SIZE - sizeof(tImageHeader)); // payload behind 369 *(tImageHeader*)sector = *pImageHeader; /* copy header into sector
364 size -= read; 370 buffer */
365 read += sizeof(tImageHeader); // to be programmed, but not part of the file 371 read = rb->read(fd, sector + sizeof(tImageHeader),
366 372 SEC_SIZE - sizeof(tImageHeader)); /* payload behind */
367 do 373 size -= read;
368 { 374 read += sizeof(tImageHeader); /* to be programmed, but not part of the
369 if (!ErazeSector(pos)) 375 file */
370 { 376
371 // nothing we can do, let the programming count the errors 377 do {
372 } 378 if (!ErazeSector(pos))
373 379 {
374 for (i=0; i<read; i++) 380 /* nothing we can do, let the programming count the errors */
375 { 381 }
376 if (!ProgramByte(pos + i, sector[i])) 382
377 { 383 for (i=0; i<read; i++)
378 failures++; 384 {
379 } 385 if (!ProgramByte(pos + i, sector[i]))
380 } 386 {
381 387 failures++;
382 pos += SEC_SIZE; 388 }
383 read = rb->read(fd, sector, (size > SEC_SIZE) ? SEC_SIZE : size); // payload for next sector 389 }
384 size -= read; 390
385 } while (read > 0); 391 pos += SEC_SIZE;
386 392 read = rb->read(fd, sector, (size > SEC_SIZE) ? SEC_SIZE : size);
387 rb->close(fd); 393 /* payload for next sector */
388 394 size -= read;
389 return failures; 395 } while (read > 0);
396
397 rb->close(fd);
398
399 return failures;
390} 400}
391 401
392// returns the # of failures, 0 on success 402/* returns the # of failures, 0 on success */
393unsigned VerifyImageFile(char* filename, UINT8* pos, tImageHeader* pImageHeader, int start, int size) 403unsigned VerifyImageFile(char* filename, UINT8* pos,
404 tImageHeader* pImageHeader, int start, int size)
394{ 405{
395 int i; 406 int i;
396 int fd; 407 int fd;
397 int read; // how many for this sector 408 int read; /* how many for this sector */
398 unsigned failures = 0; 409 unsigned failures = 0;
399 410
400 fd = rb->open(filename, O_RDONLY); 411 fd = rb->open(filename, O_RDONLY);
401 if (fd < 0) 412 if (fd < 0)
402 return false; 413 return false;
403 414
404 // no error checking necessary here, we checked for minimum size already 415 /* no error checking necessary here, we checked for minimum size
405 rb->lseek(fd, start, SEEK_SET); // go to start position 416 already */
406 417 rb->lseek(fd, start, SEEK_SET); /* go to start position */
407 *(tImageHeader*)sector = *pImageHeader; // copy header into sector buffer 418
408 read = rb->read(fd, sector + sizeof(tImageHeader), SEC_SIZE - sizeof(tImageHeader)); // payload behind 419 *(tImageHeader*)sector = *pImageHeader; /* copy header into sector
409 size -= read; 420 buffer */
410 read += sizeof(tImageHeader); // to be programmed, but not part of the file 421 read = rb->read(fd, sector + sizeof(tImageHeader),
411 422 SEC_SIZE - sizeof(tImageHeader)); /* payload behind */
412 do 423
413 { 424 size -= read;
414 for (i=0; i<read; i++) 425 read += sizeof(tImageHeader); /* to be programmed, but not part of the
415 { 426 file */
416 if (pos[i] != sector[i]) 427
417 { 428 do
418 failures++; 429 {
419 } 430 for (i=0; i<read; i++)
420 } 431 {
421 432 if (pos[i] != sector[i])
422 pos += SEC_SIZE; 433 {
423 read = rb->read(fd, sector, (size > SEC_SIZE) ? SEC_SIZE : size); // payload for next sector 434 failures++;
424 size -= read; 435 }
425 } while (read); 436 }
426 437
427 rb->close(fd); 438 pos += SEC_SIZE;
428 439 read = rb->read(fd, sector, (size > SEC_SIZE) ? SEC_SIZE : size);
429 return failures; 440 /* payload for next sector */
441 size -= read;
442 } while (read);
443
444 rb->close(fd);
445
446 return failures;
430} 447}
431 448
432 449
@@ -435,235 +452,240 @@ unsigned VerifyImageFile(char* filename, UINT8* pos, tImageHeader* pImageHeader,
435 452
436#ifdef HAVE_LCD_BITMAP 453#ifdef HAVE_LCD_BITMAP
437 454
438// helper for DoUserDialog() 455/* helper for DoUserDialog() */
439void ShowFlashInfo(tFlashInfo* pInfo, tImageHeader* pImageHeader) 456void ShowFlashInfo(tFlashInfo* pInfo, tImageHeader* pImageHeader)
440{ 457{
441 char buf[32]; 458 char buf[32];
442 459
443 if (!pInfo->manufacturer) 460 if (!pInfo->manufacturer)
444 { 461 {
445 rb->lcd_puts(0, 0, "Flash: M=?? D=??"); 462 rb->lcd_puts(0, 0, "Flash: M=?? D=??");
446 } 463 }
464 else
465 {
466 if (pInfo->size)
467 {
468 rb->snprintf(buf, sizeof(buf), "Flash size: %d KB",
469 pInfo->size / 1024);
470 rb->lcd_puts(0, 0, buf);
471 }
472 else
473 {
474 rb->lcd_puts(0, 0, "Unsupported chip");
475 }
476
477 }
478
479 if (pImageHeader)
480 {
481 rb->snprintf(buf, sizeof(buf), "Image at %d KB",
482 ((UINT8*)pImageHeader - FB) / 1024);
483 rb->lcd_puts(0, 1, buf);
484 }
447 else 485 else
448 { 486 {
449 if (pInfo->size) 487 rb->lcd_puts(0, 1, "No image found!");
450 {
451 rb->snprintf(buf, sizeof(buf), "Flash size: %d KB", pInfo->size / 1024);
452 rb->lcd_puts(0, 0, buf);
453 }
454 else
455 {
456 rb->lcd_puts(0, 0, "Unsupported chip");
457 }
458
459 }
460
461 if (pImageHeader)
462 {
463 rb->snprintf(buf, sizeof(buf), "Image at %d KB", ((UINT8*)pImageHeader - FB) / 1024);
464 rb->lcd_puts(0, 1, buf);
465 } 488 }
466 else 489
467 { 490 rb->lcd_update();
468 rb->lcd_puts(0, 1, "No image found!");
469 }
470
471 rb->lcd_update();
472} 491}
473 492
474 493
475// Kind of our main function, defines the application flow. 494/* Kind of our main function, defines the application flow. */
476void DoUserDialog(void) 495void DoUserDialog(void)
477{ 496{
478 tImageHeader ImageHeader; 497 tImageHeader ImageHeader;
479 tFlashInfo FlashInfo; 498 tFlashInfo FlashInfo;
480 char buf[32]; 499 char buf[32];
481 int button; 500 int button;
482 int rc; // generic return code 501 int rc; /* generic return code */
483 UINT32 space, aligned_size, true_size; 502 UINT32 space, aligned_size, true_size;
484 UINT8* pos; 503 UINT8* pos;
485 504
486 rb->lcd_setfont(FONT_SYSFIXED); 505 rb->lcd_setfont(FONT_SYSFIXED);
487 506
488 pos = (void*)GetSecondImage(); 507 pos = (void*)GetSecondImage();
489 rc = GetFlashInfo(&FlashInfo); 508 rc = GetFlashInfo(&FlashInfo);
490 509
491 ShowFlashInfo(&FlashInfo, (void*)pos); 510 ShowFlashInfo(&FlashInfo, (void*)pos);
492 if (FlashInfo.size == 0) // no valid chip 511 if (FlashInfo.size == 0) /* no valid chip */
493 { 512 {
494 rb->splash(HZ*3, 0, true, "Not flashable"); 513 rb->splash(HZ*3, 0, true, "Not flashable");
495 return; // exit 514 return; /* exit */
496 } 515 }
497 else if (pos == 0) 516 else if (pos == 0)
498 { 517 {
499 rb->splash(HZ*3, 0, true, "No Image"); 518 rb->splash(HZ*3, 0, true, "No Image");
500 return; // exit 519 return; /* exit */
501 } 520 }
502 521
503 rb->lcd_puts(0, 3, "using file:"); 522 rb->lcd_puts(0, 3, "using file:");
504 rb->lcd_puts(0, 4, FILENAME); 523 rb->lcd_puts(0, 4, FILENAME);
505 rb->lcd_puts(0, 6, "[F1] to check file"); 524 rb->lcd_puts(0, 6, "[F1] to check file");
506 rb->lcd_puts(0, 7, "other key to exit"); 525 rb->lcd_puts(0, 7, "other key to exit");
507 rb->lcd_update(); 526 rb->lcd_update();
508 527
509 button = rb->button_get(true); 528 button = rb->button_get(true);
510 button = rb->button_get(true); 529 button = rb->button_get(true);
511 530
512 if (button != BUTTON_F1) 531 if (button != BUTTON_F1)
513 { 532 {
514 return; 533 return;
515 } 534 }
516 535
517 rb->lcd_clear_display(); 536 rb->lcd_clear_display();
518 rb->lcd_puts(0, 0, "checking..."); 537 rb->lcd_puts(0, 0, "checking...");
519 rb->lcd_update(); 538 rb->lcd_update();
520 539
521 space = FlashInfo.size - (pos-FB + sizeof(ImageHeader)); // size minus start 540 space = FlashInfo.size - (pos-FB + sizeof(ImageHeader));
522 rc = CheckImageFile(FILENAME, space, &ImageHeader); 541 /* size minus start */
523 rb->lcd_puts(0, 0, "checked:"); 542
524 switch (rc) 543 rc = CheckImageFile(FILENAME, space, &ImageHeader);
525 { 544 rb->lcd_puts(0, 0, "checked:");
526 case eOK: 545 switch (rc) {
527 rb->lcd_puts(0, 1, "File OK."); 546 case eOK:
528 break; 547 rb->lcd_puts(0, 1, "File OK.");
548 break;
529 case eNotUCL: 549 case eNotUCL:
530 rb->lcd_puts(0, 1, "File not UCL "); 550 rb->lcd_puts(0, 1, "File not UCL ");
531 rb->lcd_puts(0, 2, "compressed."); 551 rb->lcd_puts(0, 2, "compressed.");
532 rb->lcd_puts(0, 3, "Use uclpack --2e"); 552 rb->lcd_puts(0, 3, "Use uclpack --2e");
533 rb->lcd_puts(0, 4, " --10 rockbox.bin"); 553 rb->lcd_puts(0, 4, " --10 rockbox.bin");
534 break; 554 break;
535 case eWrongAlgorithm: 555 case eWrongAlgorithm:
536 rb->lcd_puts(0, 1, "Wrong algorithm"); 556 rb->lcd_puts(0, 1, "Wrong algorithm");
537 rb->lcd_puts(0, 2, "for compression."); 557 rb->lcd_puts(0, 2, "for compression.");
538 rb->lcd_puts(0, 3, "Use uclpack --2e"); 558 rb->lcd_puts(0, 3, "Use uclpack --2e");
539 rb->lcd_puts(0, 4, " --10 rockbox.bin"); 559 rb->lcd_puts(0, 4, " --10 rockbox.bin");
540 break; 560 break;
541 case eFileNotFound: 561 case eFileNotFound:
542 rb->lcd_puts(0, 1, "File not found."); 562 rb->lcd_puts(0, 1, "File not found.");
543 rb->lcd_puts(0, 2, "Put this in root:"); 563 rb->lcd_puts(0, 2, "Put this in root:");
544 rb->lcd_puts(0, 4, FILENAME); 564 rb->lcd_puts(0, 4, FILENAME);
545 break; 565 break;
546 case eTooBig: 566 case eTooBig:
547 rb->lcd_puts(0, 1, "File too big,"); 567 rb->lcd_puts(0, 1, "File too big,");
548 rb->lcd_puts(0, 2, "won't fit in chip."); 568 rb->lcd_puts(0, 2, "won't fit in chip.");
549 break; 569 break;
550 case eTooSmall: 570 case eTooSmall:
551 rb->lcd_puts(0, 1, "File too small."); 571 rb->lcd_puts(0, 1, "File too small.");
552 rb->lcd_puts(0, 2, "Incomplete?"); 572 rb->lcd_puts(0, 2, "Incomplete?");
553 break; 573 break;
554 case eReadErr: 574 case eReadErr:
555 rb->lcd_puts(0, 1, "File read error."); 575 rb->lcd_puts(0, 1, "File read error.");
556 break; 576 break;
557 case eMultiBlocks: 577 case eMultiBlocks:
558 rb->lcd_puts(0, 1, "File invalid."); 578 rb->lcd_puts(0, 1, "File invalid.");
559 rb->lcd_puts(0, 2, "Blocksize"); 579 rb->lcd_puts(0, 2, "Blocksize");
560 rb->lcd_puts(0, 3, " too small?"); 580 rb->lcd_puts(0, 3, " too small?");
561 break; 581 break;
562 default: 582 default:
563 rb->lcd_puts(0, 1, "Check failed."); 583 rb->lcd_puts(0, 1, "Check failed.");
564 break; 584 break;
565 } 585 }
566 586
567 if (rc == eOK) 587 if (rc == eOK)
568 { // was OK 588 { /* was OK */
569 rb->lcd_puts(0, 6, "[F2] to program"); 589 rb->lcd_puts(0, 6, "[F2] to program");
570 rb->lcd_puts(0, 7, "other key to exit"); 590 rb->lcd_puts(0, 7, "other key to exit");
571 } 591 }
572 else 592 else
573 { // error occured 593 { /* error occured */
574 rb->lcd_puts(0, 6, "Any key to exit"); 594 rb->lcd_puts(0, 6, "Any key to exit");
575 } 595 }
576 596
577 rb->lcd_update(); 597 rb->lcd_update();
578 598
579 button = rb->button_get(true); 599 button = rb->button_get(true);
580 button = rb->button_get(true); 600 button = rb->button_get(true);
581 601
582 if (rc != eOK || button != BUTTON_F2) 602 if (rc != eOK || button != BUTTON_F2)
583 { 603 {
584 return; 604 return;
585 } 605 }
586 606
587 true_size = ImageHeader.size; 607 true_size = ImageHeader.size;
588 aligned_size = ((sizeof(tImageHeader) + true_size + SECTORSIZE-1) & ~(SECTORSIZE-1)) - sizeof(tImageHeader); // round up to next flash sector 608 aligned_size = ((sizeof(tImageHeader) + true_size + SECTORSIZE-1) &
589 ImageHeader.size = aligned_size; // increase image size such that we reach the next sector 609 ~(SECTORSIZE-1)) - sizeof(tImageHeader); /* round up to
590 610 next flash
591 rb->lcd_clear_display(); 611 sector */
592 rb->lcd_puts(0, 0, "Programming..."); 612 ImageHeader.size = aligned_size; /* increase image size such that we reach
593 rb->lcd_update(); 613 the next sector */
594 614
595 rc = ProgramImageFile(FILENAME, pos, &ImageHeader, UCL_HEADER, true_size); 615 rb->lcd_clear_display();
596 if (rc) 616 rb->lcd_puts(0, 0, "Programming...");
597 { // errors 617 rb->lcd_update();
598 rb->lcd_clear_display(); 618
599 rb->lcd_puts(0, 0, "Error:"); 619 rc = ProgramImageFile(FILENAME, pos, &ImageHeader, UCL_HEADER, true_size);
600 rb->lcd_puts(0, 1, "Programming fail!"); 620 if (rc)
601 rb->snprintf(buf, sizeof(buf), "%d errors", rc); 621 { /* errors */
602 rb->lcd_puts(0, 2, buf); 622 rb->lcd_clear_display();
603 rb->lcd_update(); 623 rb->lcd_puts(0, 0, "Error:");
604 button = rb->button_get(true); 624 rb->lcd_puts(0, 1, "Programming fail!");
605 button = rb->button_get(true); 625 rb->snprintf(buf, sizeof(buf), "%d errors", rc);
606 } 626 rb->lcd_puts(0, 2, buf);
607 627 rb->lcd_update();
608 rb->lcd_clear_display(); 628 button = rb->button_get(true);
609 rb->lcd_puts(0, 0, "Verifying..."); 629 button = rb->button_get(true);
610 rb->lcd_update(); 630 }
611 631
612 rc = VerifyImageFile(FILENAME, pos, &ImageHeader, UCL_HEADER, true_size); 632 rb->lcd_clear_display();
613 633 rb->lcd_puts(0, 0, "Verifying...");
614 rb->lcd_clear_display(); 634 rb->lcd_update();
615 if (rc == 0) 635
616 { 636 rc = VerifyImageFile(FILENAME, pos, &ImageHeader, UCL_HEADER, true_size);
617 rb->lcd_puts(0, 0, "Verify OK."); 637
618 } 638 rb->lcd_clear_display();
619 else 639 if (rc == 0)
620 { 640 {
621 rb->lcd_puts(0, 0, "Error:"); 641 rb->lcd_puts(0, 0, "Verify OK.");
622 rb->lcd_puts(0, 1, "Verify fail!"); 642 }
623 rb->snprintf(buf, sizeof(buf), "%d errors", rc); 643 else
624 rb->lcd_puts(0, 2, buf); 644 {
625 rb->lcd_puts(0, 3, "Use safe image"); 645 rb->lcd_puts(0, 0, "Error:");
626 rb->lcd_puts(0, 4, "if booting hangs:"); 646 rb->lcd_puts(0, 1, "Verify fail!");
627 rb->lcd_puts(0, 5, "F1 during power-on"); 647 rb->snprintf(buf, sizeof(buf), "%d errors", rc);
628 } 648 rb->lcd_puts(0, 2, buf);
629 rb->lcd_puts(0, 7, "Any key to exit"); 649 rb->lcd_puts(0, 3, "Use safe image");
630 rb->lcd_update(); 650 rb->lcd_puts(0, 4, "if booting hangs:");
631 651 rb->lcd_puts(0, 5, "F1 during power-on");
632 button = rb->button_get(true); 652 }
633 button = rb->button_get(true); 653 rb->lcd_puts(0, 7, "Any key to exit");
654 rb->lcd_update();
655
656 button = rb->button_get(true);
657 button = rb->button_get(true);
634} 658}
635 659
636#else // HAVE_LCD_BITMAP 660#else /* HAVE_LCD_BITMAP */
637 661
638// Player implementation has to go here 662/* Player implementation has to go here */
639void DoUserDialog(void) 663void DoUserDialog(void)
640{ 664{
641} 665}
642 666
643#endif // HAVE_LCD_BITMAP 667#endif /* HAVE_LCD_BITMAP */
644 668
645 669
646/***************** Plugin Entry Point *****************/ 670/***************** Plugin Entry Point *****************/
647 671
648enum plugin_status plugin_start(struct plugin_api* api, void* parameter) 672enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
649{ 673{
674 /* this macro should be called as the first thing you do in the plugin.
675 it test that the api version and model the plugin was compiled for
676 matches the machine it is running on */
677 TEST_PLUGIN_API(api);
650 678
679 /* if you don't use the parameter, you can do like
680 this to avoid the compiler warning about it */
681 (void)parameter;
682
683 rb = api; /* copy to global api pointer */
651 684
652 /* this macro should be called as the first thing you do in the plugin. 685 /* now go ahead and have fun! */
653 it test that the api version and model the plugin was compiled for 686 DoUserDialog();
654 matches the machine it is running on */
655 TEST_PLUGIN_API(api);
656
657 /* if you don't use the parameter, you can do like
658 this to avoid the compiler warning about it */
659 (void)parameter;
660
661 rb = api; /* copy to global api pointer */
662
663 /* now go ahead and have fun! */
664 DoUserDialog();
665 687
666 return PLUGIN_OK; 688 return PLUGIN_OK;
667} 689}
668 690
669#endif 691#endif