source: rtems/c/src/lib/libbsp/powerpc/shared/flash/flash.c @ 183af89

4.115
Last change on this file since 183af89 was 90ea3de, checked in by Ralf Corsepius <ralf.corsepius@…>, on 04/14/10 at 08:53:48

2010-04-14 Ralf Corsépius <ralf.corsepius@…>

  • shared/flash/flash.c: Include <unistd.h>.
  • Property mode set to 100644
File size: 20.5 KB
Line 
1/* $Id$         */
2
3/* Trivial Flash Programmer                                  */
4
5/* Author: Till Straumann <strauman@slac.stanford.edu>, 2006 */
6
7/* To keep things simple, this driver makes a few assumptions about the
8 * hardware:
9 *
10 * - no CFI
11 * - devices operate with 16-bit data width
12 * - two devices are used in parallel (stride 4) to
13 *   provide 32-bit data. I.e., the devices are
14 *   organized like this:
15 *   unsigned short flash[FLASH_SIZE][2];
16 * - no endianness issues (i.e., flash endianness ==  CPU endianness)
17 * - fixed block size
18 * - fixed buffer size
19 * - all devices in a bank are identical
20 * - NOT THREAD SAFE; no locking scheme is implemented.
21 * - cannot copy within same flash bank.
22 * - timeout uses polling/busy-wait.
23 *
24 * NOTE: some attempts have been made to remove the restrictions
25 * on stride and 16-bit width with the goal to support widths 1/2 (bytes)
26 * and strides 1/2/4 and all (legal) combinations thereof.
27 * However, the intel chip driver only implements stride 4 / width 2
28 * and other combinations are untested.
29 */
30
31/*
32 * Authorship
33 * ----------
34 * This software was created by
35 *     Till Straumann <strauman@slac.stanford.edu>, 2005-2007,
36 *         Stanford Linear Accelerator Center, Stanford University.
37 *
38 * Acknowledgement of sponsorship
39 * ------------------------------
40 * The software was produced by
41 *     the Stanford Linear Accelerator Center, Stanford University,
42 *         under Contract DE-AC03-76SFO0515 with the Department of Energy.
43 *
44 * Government disclaimer of liability
45 * ----------------------------------
46 * Neither the United States nor the United States Department of Energy,
47 * nor any of their employees, makes any warranty, express or implied, or
48 * assumes any legal liability or responsibility for the accuracy,
49 * completeness, or usefulness of any data, apparatus, product, or process
50 * disclosed, or represents that its use would not infringe privately owned
51 * rights.
52 *
53 * Stanford disclaimer of liability
54 * --------------------------------
55 * Stanford University makes no representations or warranties, express or
56 * implied, nor assumes any liability for the use of this software.
57 *
58 * Stanford disclaimer of copyright
59 * --------------------------------
60 * Stanford University, owner of the copyright, hereby disclaims its
61 * copyright and all other rights in this software.  Hence, anyone may
62 * freely use it for any purpose without restriction.
63 *
64 * Maintenance of notices
65 * ----------------------
66 * In the interest of clarity regarding the origin and status of this
67 * SLAC software, this and all the preceding Stanford University notices
68 * are to remain affixed to any copy or derivative of this software made
69 * or distributed by the recipient and are to be affixed to any copy of
70 * software made or distributed by the recipient that contains a copy or
71 * derivative of this software.
72 *
73 * ------------------ SLAC Software Notices, Set 4 OTT.002a, 2004 FEB 03
74 */
75#ifndef TESTING
76#include <rtems.h>
77#include <bsp/flashPgm.h>
78#include <bsp/flashPgmPvt.h>
79#else
80#include "flashPgm.h"
81#include "flashPgmPvt.h"
82#endif
83
84#include <unistd.h>
85#include <stdio.h>
86#include <inttypes.h>
87#include <ctype.h>
88#include <fcntl.h>
89#include <stdlib.h>
90
91#define  DEBUG          0
92#undef   DEBUG
93
94#ifdef   DEBUG
95#define  STATIC
96#else
97#define  STATIC                         static
98#endif
99
100/* Forward decls. */
101
102STATIC uint32_t
103BSP_flashProbeSize(struct bankdesc *b);
104
105STATIC struct bankdesc *
106bankValidate(int bank, int quiet);
107
108static struct bankdesc *
109argcheck(int bank, uint32_t offset, char *src, uint32_t size);
110
111/* Type definitions */
112
113union bconv     {
114        uint32_t u;
115        uint16_t s[2];
116        char     c[4];
117};
118
119/* Little helpers... */
120
121/* Read parallel devices */
122static void
123rd_par(struct bankdesc *b, union bconv *pv, uint32_t a)
124{
125        if ( 4 == FLASH_STRIDE(b) ) {
126                pv->u    = *(_u32_a_t*)a;
127        } else if ( 2 == FLASH_STRIDE(b) ) {
128                pv->s[0] = *(_u16_a_t*)a;
129        } else {
130                pv->c[0] = *(_u8_a_t*)a;
131        }
132}
133
134/* 'flush' input buffer and get an upper-case char from stdin */
135STATIC int
136getUc(void)
137{
138        fseek(stdin, 0, SEEK_END);
139        return toupper(getchar());
140}
141
142/* Advance rotating progress indicator on stdout.
143 * The idea is that the caller updates a state variable
144 * using 'flip':
145 *
146 * unsigned f = 0;
147 *
148 *    // advance indicator
149 *    f = flip(f);
150 *
151 *    ...
152 *
153 *    // erase indicator
154 *    wipe(f);
155 */
156static unsigned flip(unsigned x)
157{
158static char bar[]= { '/', '-', '\\', '|' };
159        putchar('\b');
160        putchar(bar[ x & 3]);
161        fflush(stdout);
162        return x+1;
163}
164
165/* If f!=0 then erase one char on stdout.
166 * ( If 'flip' was never called then f should still
167 * be zero and no action is taken).
168 */
169static void wipe(unsigned f)
170{
171        if ( f ) {
172                putchar('\b');
173                putchar(' ');
174                putchar('\b');
175                fflush(stdout);
176        }
177}
178
179/* lookup vendor ID in table of known vendors using ops
180 * associated with the vendor.
181 */
182STATIC struct vendesc *
183knownVendor(struct bankdesc *b, uint32_t addr, uint32_t *pd, unsigned quiet)
184{
185uint32_t        v;
186struct vendesc *rval;
187
188        for ( rval=b->knownVendors; rval->name; rval++ ) {
189
190                if ( rval->ops->get_id(b, addr, &v, pd) ) {
191                        if ( quiet < 2 )
192                                fprintf(stderr,"Unable to read vendor/device info at 0x%08"PRIx32"\n", addr);
193                        return 0;
194                }
195
196                if ( rval->id == v ) {
197                        return rval;
198                }
199        }
200        if ( quiet < 2 )
201                fprintf(stderr,"Unknown vendor id (0x%04"PRIx32") at 0x%08"PRIx32"\n",v, addr);
202        return 0;
203}
204
205/* lookup device ID in table of known devices */
206STATIC struct devdesc *
207knownDevice(struct vendesc *v, uint32_t d)
208{
209struct devdesc *rval;
210        for ( rval=v->known_devs; rval->name; rval++ ) {
211                if ( rval->id == d ) {
212                        return rval;
213                }
214        }
215        return 0;
216}
217
218/* Write 'n_words' (32-bit) from 'src' to 'addr'ess on flash.
219 * (src is a char* to emphasize that no src-alignment is required)
220 *
221 * RETURNS: 0 on success, (destination) address of failure on error.
222 *
223 *   NOTES: - device switched back to array mode on exit.
224 *          - 'addr' must be 32-bit aligned.
225 */
226
227STATIC uint32_t
228BSP_flashWriteDataRaw(struct bankdesc *b, uint32_t addr, char *src, uint32_t n_words, int quiet)
229{
230uint32_t sta;
231uint32_t N;
232uint32_t nxt, a, i, bufsz;
233uint32_t then, now;
234unsigned f;
235char     *s;
236
237#ifdef DEBUG
238        printf("\nflashWriteDataRaw(0x%08"PRIx32", %p, 0x%"PRIx32")\n", addr, src, n_words);
239#endif
240
241        if ( 0 == n_words ) {
242                return 0;
243        }
244
245        if ( !b ) {
246                fprintf(stderr,"Missing bank descriptor argument\n");
247                return -1;
248        }
249        if ( !b->dd ) {
250                fprintf(stderr,"Bank descriptor not initialized\n");
251                return -1;
252        }
253
254        if ( addr & (FLASH_STRIDE(b)-1) ) {
255                fprintf(stderr,"Misaligned address (not on word boundary) 0x%08"PRIx32"\n", addr);
256                return -1;
257        }
258
259        if ( (sta = b->ops->check_ready(b, addr)) ) {
260                /* Error msgs have already been printed */
261                return addr;
262        }
263
264        bufsz = FLASH_NDEVS(b) * b->dd->bufsz;
265
266        then = BSP_flashBspOps.read_us_timer();
267
268        for ( f = 0, a = addr, s=src, i = n_words; i ; s+=N ) {
269                /* start of next buffer */
270                nxt = (a + bufsz) & ~(bufsz-1);
271
272                /* number of bytes */
273                N = (nxt - a);
274
275                if ( N > i * FLASH_STRIDE(b) )
276                        N = i * FLASH_STRIDE(b);
277
278                i -= N/FLASH_STRIDE(b);
279
280                if ( (sta = b->ops->write_line(b, a, s, N)) )
281                        goto bail;
282
283                if ( ! quiet && (now = BSP_flashBspOps.read_us_timer()) - then > 500000 ) {
284                        f = flip(f);
285                        then = now;
286                }
287
288                a = nxt;
289        }
290
291        sta = 0;
292
293        /* verify */
294        for ( i=0, a=addr; i < n_words * FLASH_STRIDE(b); i++, a++ ) {
295                if ( *(char*)a != src[i] ) {
296                        sta = -2;
297                        goto bail;
298                }
299        }
300
301bail:
302        if ( ! quiet ) {
303                wipe(f);
304        }
305        if ( sta ) {
306                switch ( sta ) {
307                        default:
308                                fprintf(stderr,"Error (flashWriteDataRaw): write error\n");
309                                b->ops->print_stat(b, sta,0);
310                        break;
311
312                        case -1:
313                                fprintf(stderr,"Error (flashWriteDataRaw): Timeout\n");
314                        break;
315
316                        case -2:
317                                fprintf(stderr,"Error (flashWriteDataRaw): write verification failed at 0x%08"PRIx32"\n", a);
318                        break;
319                }
320                b->ops->array_mode(b, a);
321        } else {
322                /* no errors */
323                a = 0;
324        }
325        return a;
326}
327
328
329/* Query device for basic information verifying that we talk
330 * to a 'known'/'supported' device.
331 *
332 * This is not really clean since (until we implement CFI)
333 * we already need to know what kind of device it is to
334 * be able to read its ID...
335 *
336 *   NOTES: - device switched back to array mode on exit.
337 *          - 'addr' must be 32-bit aligned.
338 */
339
340STATIC struct devdesc *
341BSP_flashCheckId(struct bankdesc *b, uint32_t addr, unsigned quiet)
342{
343uint8_t  x;
344uint32_t d;
345struct vendesc  *vd;
346struct devdesc  *dd;
347
348        /* check if it's flash at all: */
349        x = *(A8)addr;
350        *(A8)addr = ~x;
351        if ( x != *(A8)addr ) {
352                /* restore */
353                *(A8)addr = x;
354                if ( quiet < 3 )
355                        fprintf(stderr,"Addr 0x%08"PRIx32" seems to be RAM!\n", addr);
356                return 0;
357        }
358
359        if ( !(vd = knownVendor(b, addr, &d, quiet)) ) {
360                return 0;
361        }
362
363        /* Use the vendor ops for this bank */
364        b->ops    = vd->ops;
365
366        if ( !quiet )
367                printf("Flash device, vendor: %s", vd->name);
368
369        if ( !(dd = knownDevice(vd, d)) ) {
370                if ( !quiet )
371                        printf("\n");
372                if ( quiet < 2 )
373                        fprintf(stderr,"Unknown device id (0x%04"PRIx32") at 0x%08"PRIx32"\n",d, addr);
374                return 0;
375        }
376
377        /* logical sector size is device sector size
378         * multiplied by # of devices in parallel
379         */
380        b->fblksz = dd->fblksz * FLASH_NDEVS(b);
381
382        if ( !quiet )
383                printf(", device: %s -- size 0x%08"PRIx32" bytes\n", dd->name, dd->size);
384        return dd;
385}
386
387/* We don't have device info yet so just
388 * use 64k alignment
389 */
390#define SCAN_BACK_OFFSET        0x10000
391
392/* Scan address range for flash devices and compute total size
393 * of bank.
394 *
395 * RETURNS: size in bytes.
396 */
397STATIC uint32_t
398BSP_flashProbeSize(struct bankdesc *b)
399{
400int             max = b->max_size;
401uint32_t                rval;
402struct devdesc  *dd;
403unsigned                q;
404        if ( max > 0 ) {
405                for ( rval = 0, q=1; rval < max && (dd = BSP_flashCheckId(b, b->start + rval, q)); q=3 ) {
406                        rval += dd->size * FLASH_NDEVS(b);
407                }
408        } else {
409                /* bank is populated from the top; scan backwards */
410                max = -max;
411                for ( rval = 0, q=1; rval < max && (dd = BSP_flashCheckId(b, b->start + max - SCAN_BACK_OFFSET - rval, q)); q=3 ) {
412                        rval += dd->size * FLASH_NDEVS(b);
413                }
414                b->start += max - rval;
415        }
416        return rval;
417}
418
419uint32_t
420BSP_flashStart(int bank)
421{
422struct bankdesc *b;
423        if ( ! ( b = argcheck(bank, 0, 0, 0) ) )
424                return -1;
425        return b->start;
426}
427
428uint32_t
429BSP_flashSize(int bank)
430{
431struct bankdesc *b;
432        if ( ! ( b = argcheck(bank, 0, 0, 0) ) )
433                return -1;
434        return b->size;
435}
436
437uint32_t
438BSP_flashBlockSize(int bank)
439{
440struct bankdesc *b;
441        if ( ! ( b = argcheck(bank, 0, 0, 0) ) )
442                return -1;
443        return b->fblksz;
444}
445
446
447#ifndef TESTING
448
449/* Obtain bank description making sure it is initialized and not write protected */
450STATIC struct bankdesc *
451bankValidate(int bank, int quiet)
452{
453struct bankdesc *b = BSP_flashBspOps.bankcheck(bank, quiet);
454
455        /* If flash is write-protected then we can't even talk to it... */
456        if ( BSP_flashBspOps.flash_wp(bank, -1) ) {
457                fprintf(stderr,"Flash bank #%i is write-protected; use 'BSP_flashWriteEnable(int bank)' and/or jumper\n", bank);
458                return 0;
459        }
460
461        if ( !b->dd && !(b->dd = BSP_flashCheckId(b, b->start,1)) ) {
462                fprintf(stderr,"Error: unable to detect flash device in bank #%i\n", bank);
463                return 0;
464        }
465        return b;
466}
467
468/* Validate arguments and write-protection status of 'bank'.
469 *
470 *    'bank': 0..max bank supported by board.
471 *  'offset': 0..bank size - 1
472 *     'src': src .. src + size - 1 must not overlap bank; 'src' may be NULL
473 *            (check is skipped in this case)
474 *
475 *      RETURNS: pointer to bank description on success, NULL on error (invalid args;
476 *               error message is printed to stderr).
477 *
478 * SIDE EFFECTS: probes for bank size and stores result in bank description table.
479 */
480
481static struct bankdesc *
482argcheck(int bank, uint32_t offset, char *src, uint32_t size)
483{
484struct bankdesc *b;
485
486        if ( !(b=bankValidate(bank, 0)) ) {
487                return 0;
488        }
489
490        if ( !b->size && !(b->size = BSP_flashProbeSize(b)) ) {
491                fprintf(stderr,"Configuration Error - unable to determine flash size\n");
492                return 0;
493        }
494        if ( offset + size > b->size ) {
495                fprintf(stderr,"Error: requested size exceeds available flash (0x%08"PRIx32" bytes)\n", b->size);
496                return 0;
497        }
498
499        if ( src && ( src + size > (char*)b->start && src < (char*)(b->start + b->size) ) ) {
500                fprintf(stderr,"Error: cannot copy data within flash bank\n");
501                return 0;
502        }
503
504
505        return b;
506}
507
508/* Calculate region that needs to be erased from 'offset' and 'n_bytes'
509 * handling alignment and checking for blank areas that need not be
510 * erased.
511 * Ask for user confirmation and erase calculated region.
512 *
513 * RETURNS: 0 on success, -1 or destination address on error.
514 *
515 *   NOTES: - device switched back to array mode on exit.
516 *          - prints progress/messages.
517 */
518STATIC int
519regionCheckAndErase(int bank, uint32_t offset, char *src, uint32_t n_bytes, int quiet)
520{
521struct bankdesc *b;
522uint32_t         i;
523char            *p;
524uint32_t                a,e;
525
526        if ( ! (b = argcheck(bank, offset, src, n_bytes)) )
527                return -1;
528
529        a = offset & ~(b->fblksz - 1);
530        e = (offset + n_bytes +  b->fblksz - 1) & ~ (b->fblksz - 1);
531
532        /* If 'offset' is not block-aligned then rest of the block must
533         * be free.
534         */
535        if ( a != offset ) {
536                a += b->fblksz;
537                i  = ( a > offset + n_bytes ) ? offset + n_bytes : a;
538                for ( p = (char*)(b->start + offset); p < (char*)(b->start + i); p++ ) {
539                        if ( (char)0xff != *p ) {
540                                if ( ! quiet ) {
541                                        fprintf(stderr,"Starting offset not block-aligned and destination area not empty.\n");
542                                        fprintf(stderr,"I'll need to erase data below destination start\n");
543                                }
544                                a -= b->fblksz;
545                                break;
546                        }
547                }
548        }
549        if ( e != offset + n_bytes ) {
550                e -= b->fblksz;
551                i  = ( e < offset ) ? offset : e;
552                for ( p = (char*)(b->start + i); p < (char*)(b->start + offset + n_bytes); p++ ) {
553                        if ( (char)0xff != *p ) {
554                                if ( ! quiet ) {
555                                        fprintf(stderr,"Ending offset not block-aligned and destination area not empty.\n");
556                                        fprintf(stderr,"I'll need to erase data beyond destination end\n");
557                                }
558                                e += b->fblksz;
559                                break;
560                        }
561                }
562        }
563        if ( ! quiet ) {
564                if ( e > a )
565                        printf("ERASING 0x%08"PRIx32" .. 0x%08"PRIx32"\n", (b->start+a), (b->start + e - 1));
566                printf("WRITING 0x%08"PRIx32" .. 0x%08"PRIx32"\n", (b->start+offset), (b->start + offset + n_bytes - 1));
567                printf("OK to proceed y/[n]?"); fflush(stdout);
568                if ( 'Y' != getUc() ) {
569                        printf("ABORTED\n");
570                        return -1;
571                }
572        }
573        if ( e > a ) {
574                if ( quiet < 2 ) {
575                        printf("ERASING  "); fflush(stdout);
576                }
577
578                if ( (i = BSP_flashErase(bank, a, e-a, quiet ? quiet : 1)) )
579                        return i;
580
581                if ( quiet < 2 ) {
582                        printf("DONE\n");
583                }
584        }
585
586        return 0;
587}
588
589/* Write to a flash region ('offset'..'offset'+'n_bytes'-1 on 'bank').
590 *
591 * RETURNS: 0 on success, -1 or destination address on error.
592 *
593 *   NOTES: - device switched back to array mode on exit.
594 *          - no erase operation is performed.
595 *          - written data is verified against source.
596 */
597
598STATIC int
599BSP_flashWriteRegion(int bank, uint32_t offset, char *src, uint32_t n_bytes, int quiet)
600{
601struct bankdesc *b = BSP_flashBspOps.bankcheck(bank, 0);        /* caller did bankValidate() */
602uint32_t     ab = offset & ~(b->fblksz - 1);
603uint32_t     eb = (offset + n_bytes + b->fblksz - 1) & ~(b->fblksz - 1);
604uint32_t     o,i,a,e;
605int          err;
606char        *p;
607union bconv  buf;
608
609        /* unlock */
610        for ( i=ab; i<eb; i+=b->fblksz ) {
611                b->ops->unlock_block(b, b->start + i );
612        }
613
614        err = 0;
615        p = src;
616
617        /* handle misaligned offset merging old contents */
618        o = b->start + offset;
619        a = o & ~(FLASH_STRIDE(b)-1);
620        e = (o + n_bytes) & ~(FLASH_STRIDE(b)-1);
621
622        if ( o > a ) {
623                i = o - a;
624
625                rd_par(b, &buf, a);
626
627                while ( i < FLASH_STRIDE(b) && p < src + n_bytes ) {
628                        buf.c[i++] = *p++;
629                }
630                if ( (err = BSP_flashWriteDataRaw(b, a, buf.c, 1, quiet)) )
631                        goto bail;
632                a += FLASH_STRIDE(b);
633        }
634
635
636        /* caution if misaligned data covering only one or two words */
637
638        if ( e > a ) {
639                i = (e-a);
640                if ( (err = BSP_flashWriteDataRaw(b, a, p, i/FLASH_STRIDE(b), quiet)) )
641                        goto bail;
642                p += i;
643        }
644
645        /* handle misaligned end */
646        if ( o + n_bytes > e)  {
647                rd_par(b, &buf, e);
648                for ( i=0; p < src + n_bytes; ) {
649                        buf.c[i++] = *p++;
650                }
651                if ( (err = BSP_flashWriteDataRaw(b, e, buf.c, 1, quiet)) )
652                        goto bail;
653        }
654
655bail:
656        /* lock area */
657        for ( i=ab; i<eb; i+=b->fblksz ) {
658                b->ops->lock_block(b, b->start + i );
659        }
660
661        /* final verification */
662        if ( !err ) {
663                for ( i=0; i<n_bytes; i++ ) {
664                        if ( ((char*)(b->start + offset))[i] != src[i] ) {
665                                fprintf(stderr,"Final verification failed at offset 0x%08"PRIx32"\n", (offset + i));
666                                return b->start + offset + i;
667                        }
668                }
669        }
670
671        return err;
672}
673
674int
675BSP_flashErase(int bank, uint32_t offset, uint32_t size, int quiet)
676{
677struct bankdesc *b;
678uint32_t                 a,i;
679int              f;
680
681        if ( ! (b = argcheck(bank, offset, 0, size)) )
682                return -1;
683
684        if ( offset & (b->fblksz - 1) ) {
685                fprintf(stderr,"Offset misaligned (needs to be multiple of 0x%08"PRIx32")\n", b->fblksz);
686                return -1;
687        }
688        if ( size & (b->fblksz - 1) ) {
689                fprintf(stderr,"Size misaligned (needs to be multiple of 0x%08"PRIx32")\n", b->fblksz);
690                return -1;
691        }
692
693        a = b->start + offset;
694
695        if ( !quiet ) {
696                printf("ERASING Flash (Bank #%i)\n    from 0x%08"PRIx32" .. 0x%08"PRIx32"\nproceed y/[n]?",
697                        bank, a, (a+size-1));
698                fflush(stdout);
699                if ( 'Y' != getUc() ) {
700                        printf("ABORTED\n");
701                        return -1;
702                }
703        }
704        f = 0;
705        while ( size ) {
706                /* work to do ? */
707                for ( i = 0; i<b->fblksz; i++ ) {
708                        if ( (char)0xff != ((char*)a)[i] ) {
709                                b->ops->unlock_block(b, a);
710                                i = b->ops->erase_block(b, a);
711                                b->ops->lock_block(b, a);
712                                if (i) {
713                                        wipe(f);
714                                        return a;
715                                }
716                                break;
717                        }
718                }
719
720                if ( quiet < 2 ) {
721                        f = flip(f);
722                }
723
724                a    += b->fblksz;
725                size -= b->fblksz;
726        }
727        b->ops->array_mode(b, a);
728        if ( quiet < 2 ) {
729                wipe(f);
730        }
731        return 0;
732}
733
734int
735BSP_flashWrite(int bank, uint32_t offset, char *src, uint32_t n_bytes, int quiet)
736{
737int      rval;
738
739        if ( !src ) {
740                fprintf(stderr,"Error: Data source pointer is NULL\n");
741                return -1;
742        }
743
744        if ( (rval = regionCheckAndErase(bank, offset, src, n_bytes, quiet)) )
745                return rval;
746
747        if ( ! quiet ) {
748                printf("WRITING  "); fflush(stdout);
749        }
750
751        rval = BSP_flashWriteRegion(bank, offset, src, n_bytes, quiet);
752
753        if ( !quiet && !rval ) {
754                printf("DONE");
755        }
756        if ( !quiet )
757                printf("\n");
758        return rval;
759}
760
761static int
762bfill(int fd, char *buf, int size)
763{
764int got, avail;
765        for (avail = size; (got = read(fd, buf, avail)) > 0; avail-=got ) {
766                buf  += got;
767        }
768        return size - avail;
769}
770
771int
772BSP_flashWriteFile(int bank, uint32_t offset, char *fname, int quiet)
773{
774int             fd   = -1;
775struct stat     sb;
776uint32_t            sz;
777int                         rval = -1;
778char               *buf  = 0;
779uint32_t            got;
780struct bankdesc *b;
781unsigned        f    = 0;
782
783        if ( ! (b = bankValidate(bank, 0)) )
784                return -1;
785
786        for ( sz = 0; -1 == fd ;  ) {
787                if ( (fd = open(fname,O_RDONLY)) < 0 ) {
788                        perror("Opening file");
789                        return -1;
790                }
791
792                if ( sz )
793                        break;
794
795                if ( fstat(fd, &sb) ) {
796                        fprintf(stderr,"Warning: fstat doesn't work; need to slurp file to determine size; please be patient.\n");
797                        FILE *f;
798                        close(fd); fd = -1;
799                        f = fopen(fname,"r");
800                        if ( !f ) {
801                                perror("fdopen");
802                                return -1;
803                        }
804                        while ( EOF != fgetc(f) )
805                                sz++;
806                        fclose(f);
807                        /* reopen */
808                } else {
809                        sz = sb.st_size;
810                }
811                if ( 0 == sz ) {
812                        fprintf(stderr,"Error: zero file size (?)\n");
813                        goto bail;
814                }
815        }
816
817        if ( !(buf = malloc(b->fblksz)) ) {
818                perror("buffer allocation");
819                goto bail;
820        }
821
822        /* See if we can erase the entire region */
823        if ( (rval = regionCheckAndErase(bank, offset, buf, sz, quiet)) )
824                goto bail;
825
826        /* Proceed copying chunks */
827        if ( quiet < 2 ) {
828                printf("WRITING  "); fflush(stdout);
829        }
830
831        while ( (got = bfill(fd, buf, b->fblksz)) > 0 && sz ) {
832                if ( (rval = BSP_flashWriteRegion(bank, offset, buf, got, 1)) ) {
833                        wipe(f);
834                        goto bail;
835                }
836                offset += got;
837                sz     -= got;
838                if ( quiet < 2 ) {
839                        f = flip(f);
840                }
841        }
842        if ( got < 0 ) {
843                perror("reading file");
844                rval = offset;
845                goto bail;
846        }
847
848        if ( quiet < 2 ) {
849                wipe(f);
850                printf("DONE");
851        }
852bail:
853        if ( quiet < 2 ) {
854                printf("\n");
855        }
856        if ( fd > -1 )
857                close(fd);
858        free(buf);
859        return rval;
860}
861
862int
863BSP_flashWriteEnable(int bank)
864{
865        return BSP_flashBspOps.flash_wp(bank,0);
866}
867
868int
869BSP_flashWriteDisable(int bank)
870{
871        return BSP_flashBspOps.flash_wp(bank,1);
872}
873
874int
875BSP_flashDumpInfo(FILE *f)
876{
877struct bankdesc *b;
878int                     bank;
879
880        if ( !f )
881                f = stdout;
882
883        /* use 'bankValidate()' with 'quiet' flag to suppress error message when
884         * we reach the end of the table.
885         */
886        for ( bank = 0; BSP_flashBspOps.bankcheck(bank,1); bank++ ) {
887                if ( (b=argcheck(bank,0,0,0)) ) {
888                        fprintf(f,"Flash Bank #%i; 0x%08"PRIx32" .. 0x%08"PRIx32" (%"PRId32" bytes)\n",
889                                bank, b->start, (b->start + b->size - 1), b->size);
890                        fprintf(f,"%i * %i-bit devices in parallel; block size 0x%"PRIx32"\n", FLASH_NDEVS(b), FLASH_WIDTH(b)*8, b->fblksz);
891                        BSP_flashCheckId(b, b->start, 0);
892                }
893        }
894
895        return 0;
896}
897
898#else
899
900int
901main(int argc, char **argv)
902{
903uint32_t fla[1000];
904uint32_t qqq[1000];
905int i;
906        for ( i=0; i<sizeof(qqq)/sizeof(qqq[0]); i++ )
907                qqq[i] = 0xdada<<16 | i;
908        BSP_flashWriteDataRaw(0, (uint32_t)fla, (char*)qqq, 32, 0);
909}
910#endif
Note: See TracBrowser for help on using the repository browser.