source: rtems/c/src/lib/libbsp/powerpc/shared/flash/flash.c @ 9b4422a2

4.115
Last change on this file since 9b4422a2 was 9b4422a2, checked in by Joel Sherrill <joel.sherrill@…>, on 05/03/12 at 15:09:24

Remove All CVS Id Strings Possible Using a Script

Script does what is expected and tries to do it as
smartly as possible.

+ remove occurrences of two blank comment lines

next to each other after Id string line removed.

+ remove entire comment blocks which only exited to

contain CVS Ids

+ If the processing left a blank line at the top of

a file, it was removed.

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