source: umon/main/common/spif.c @ 87db514

Last change on this file since 87db514 was 87db514, checked in by Amar Takhar <amar@…>, on 04/16/15 at 19:26:21

Initial commit of the umon repository.

Prior to this three changes were made:

  • Remove umon_ prefix from parent directories.
  • Collapse main/target/ into main/
  • Remove ports/template/flashtest.scr.ucon script.
  • Property mode set to 100644
File size: 12.1 KB
Line 
1/**************************************************************************
2 *
3 * Copyright (c) 2013 Alcatel-Lucent
4 *
5 * Alcatel Lucent licenses this file to You under the Apache License,
6 * Version 2.0 (the "License"); you may not use this file except in
7 * compliance with the License.  A copy of the License is contained the
8 * file LICENSE at the top level of this repository.
9 * You may also obtain a copy of the License at:
10 *
11 *      http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 **************************************************************************
20 *
21 * spif.c:
22 *
23 * This is the generic portion of the spi-flash interface command.
24 * It assumes there is an underlying SPI-flash device interface
25 * that provides the expected API (see spif.h).
26 *
27 * The "tfs-specific" portions of this code support the model of having
28 * non-volatile TFS storage in SPI-flash that is transferred to RAM for
29 * general use, but also provides the ability to do the following:
30
31 * tfsload:
32 *  Transfer a SPIF_TFS_SIZE area in SPI-flash from SPIF_TFS_BASE to
33 *      FLASHRAM_BASE in RAM.
34 * tfserase:
35 *  Erase the area in SPI-flash that is allocated to SPIF_TFS.
36 * tfsstore:
37 *  Transfer the RAM-based TFS space back to SPI-flash.
38 * tfsls:
39 *  List the files out of SPI_TFS directly.
40 * tfsrm:
41 *  Mark a file in SPI_TFS as deleted.
42 * tfsadd:
43 *  Append a file just after the last file currently stored in SPIF_TFS.
44 *
45 * NOTE: this does NOT support powersafe mode as of this writing.
46 *
47 * The spifmap.h file is port specific; hence would be part of the
48 * port directory.
49 *
50 * Original author:     Ed Sutter (ed.sutter@alcatel-lucent.com)
51 *
52 */
53#include "config.h"
54#include "genlib.h"
55#include "cli.h"
56#include "tfs.h"
57#include "tfsprivate.h"
58#include "spif.h"
59#include "spifmap.h"
60
61
62static unsigned long spif_tfs_size;
63static unsigned long spif_tfs_base;
64static unsigned long base_of_serialtfs;
65static unsigned long end_of_serialtfs;
66
67#ifndef SPIF_TFSRAM_BASE
68#define SPIF_TFSRAM_BASE FLASHRAM_BASE
69#endif
70
71char *SpifHelp[] = {
72        "Interface with SPI-Flash",
73        "-[v] {cmd} [arg1] [arg2] [...]",
74#if INCLUDE_VERBOSEHELP
75        "Options:",
76        " -v   incrementing verbosity level",
77        "",
78        "Cmds:",
79        " wen                       write enable",
80        " wfr                       wait-for-ready",
81        " stat                      show flash status register",
82        " gprot                     global protect",
83        " cerase                    chip erase",
84        " gunprot                   global unprotect",
85#if INCLUDE_TFS
86        " tfsls                     list files directly out of SPI flash",
87        " tfsload                   copy SPIF to TFSRAM",
88        " tfsstat                   show state of SPI flash",
89        " tfsstore                  copy TFSRAM to SPIF",
90        " tfserase                  erase SPIF space allocated to TFS",
91        " tfsrm {name}              remove file directly out of SPI flash",
92        " tfsadd {name} [src sz]    add file directly to SPI flash",
93#endif
94        " berase {addr bsize}       block erase (bsize=4K,32K,64K)",
95        " read {addr dest len}      read block",
96        " write {addr src len}      write block",
97#endif
98        0,
99};
100
101int
102SpifCmd(int argc,char *argv[])
103{
104        unsigned long addr;
105        char *cmd, *dest, *src;
106        int opt, verbose, len, bsize, rc;
107
108        spif_tfs_size = spifGetTFSSize();
109        spif_tfs_base = spifGetTFSBase();
110        base_of_serialtfs = spif_tfs_base;
111        end_of_serialtfs = spif_tfs_base + spif_tfs_size;
112
113        verbose = 0;
114        while((opt=getopt(argc,argv,"v")) != -1) {
115                switch(opt) {
116                case 'v':
117                        verbose++;
118                        break;
119                default:
120                        return(CMD_PARAM_ERROR);
121                }
122        }
123       
124        if (argc < optind+1)
125                return(CMD_PARAM_ERROR);
126
127        cmd = argv[optind];
128
129        if (verbose)
130                printf("CMD: %s\n",cmd);
131
132        // Establish the SPI configuration to match that of the SPI flash...
133        spifQinit();
134
135        if (strcmp(cmd,"stat") == 0) {
136                spifId(1);     
137                spifReadStatus(verbose+1);     
138        }
139        else if (strcmp(cmd,"gprot") == 0) {
140                spifGlobalProtect();   
141        }
142        else if (strcmp(cmd,"berase") == 0) {
143
144                if (argc != optind+3)
145                        return(CMD_PARAM_ERROR);
146
147                addr = strtoul(argv[optind+1],0,0);
148
149                if (strcmp(argv[optind+2],"4K") == 0)
150                        bsize = 0x1000;
151                else if (strcmp(argv[optind+2],"32K") == 0)
152                        bsize = 0x8000;
153                else if (strcmp(argv[optind+2],"64K") == 0)
154                        bsize = 0x10000;
155                else
156                        return(CMD_PARAM_ERROR);
157
158                spifBlockErase(bsize,addr);     
159        }
160        else if (strcmp(cmd,"cerase") == 0) {
161                spifChipErase();       
162        }
163        else if (strcmp(cmd,"wfr") == 0) {
164                spifWaitForReady();     
165        }
166        else if (strcmp(cmd,"gunprot") == 0) {
167                spifGlobalUnprotect(); 
168        }
169        else if (strcmp(cmd,"write") == 0) {
170                if (argc != optind+4)
171                        return(CMD_PARAM_ERROR);
172                addr = strtoul(argv[optind+1],0,0);
173                src = (char *)strtoul(argv[optind+2],0,0);
174                len = (int)strtol(argv[optind+3],0,0);
175                if ((rc = spifWriteBlock(addr,src,len)) < 0)
176                        printf("spifWriteBlock returned %d\n",rc);
177                       
178        }
179        else if (strcmp(cmd,"read") == 0) {
180                if (argc != optind+4)
181                        return(CMD_PARAM_ERROR);
182                addr = strtoul(argv[optind+1],0,0);
183                dest = (char *)strtoul(argv[optind+2],0,0);
184                len = (int)strtol(argv[optind+3],0,0);
185                if ((rc = spifReadBlock(addr,dest,len)) < 0)
186                        printf("spifReadBlock returned %d\n",rc);
187        }
188        else if (strcmp(cmd,"wen") == 0) {
189                spifWriteEnable();     
190        }
191#if INCLUDE_TFS
192        else if (strcmp(cmd,"tfsload") == 0) {
193                rc = spifReadBlock(spif_tfs_base,(char *)FLASHRAM_BASE,spifGetTFSSize());       
194                if (rc < 0)
195                        printf("spifReadBlock returned %d\n",rc);
196        }
197        else if (strcmp(cmd,"tfsstore") == 0) {
198                spifWriteEnable();     
199                spifGlobalUnprotect(); 
200                rc = spifWriteBlock(spif_tfs_base,(char *)FLASHRAM_BASE,spifGetTFSSize());     
201                if (rc < 0)
202                        printf("spifWriteBlock returned %d\n",rc);
203                spifGlobalProtect();   
204        }
205        else if (strcmp(cmd,"tfserase") == 0) {
206                spifWriteEnable();     
207                spifGlobalUnprotect(); 
208                addr = spif_tfs_base;
209                while (addr < (spif_tfs_base+spif_tfs_size)) {
210                        spifWriteEnable();     
211                        rc = spifBlockErase(0x10000,addr);     
212                        if (rc < 0) {
213                                printf("spifBlockErase(0x%lx) returned %d\n",addr,rc);
214                                break;
215                        }
216                        if (verbose)
217                                //ticktock();
218                                printf("%lx ",addr);
219                        addr += 0x10000;
220                }
221                spifGlobalProtect();   
222        }
223        else if (strcmp(cmd, "tfsls") == 0) {
224                int ftot;
225                unsigned long addr;
226                TFILE tfshdr, *fp;
227
228                ftot = 0;
229                fp = &tfshdr;
230                addr = base_of_serialtfs;
231                while(addr < end_of_serialtfs) {
232                        char fbuf[32], *flags;
233
234                        if ((rc = spifReadBlock(addr,(char *)fp,TFSHDRSIZ)) < 0) {
235                                printf("spifReadBlock failed %d\n",rc);
236                                break;
237                        }
238                        if (fp->hdrsize == 0xffff)
239                                break;
240                        if (TFS_FILEEXISTS(fp)) {
241                                if (ftot == 0)
242                                        printf(" Name                        Size    Offset    Flags  Info\n");
243                                ftot++;
244                                flags = tfsflagsbtoa(TFS_FLAGS(fp),fbuf);
245                                if ((!flags) || (!fbuf[0]))
246                                        flags = " ";
247                                printf(" %-23s  %7ld  0x%08lx  %-5s  %s\n",TFS_NAME(fp),
248                                        TFS_SIZE(fp),(unsigned long)(addr+TFSHDRSIZ),
249                                        flags,TFS_INFO(fp));
250                        }
251                        addr += TFS_SIZE(fp);
252                        addr += TFSHDRSIZ;
253                        while(addr & 0xf) addr++;
254                }
255        }
256        else if (strcmp(cmd, "tfsrm") == 0) {
257                unsigned long addr;
258                TFILE tfshdr, *fp;
259                char *arg2 = argv[optind+1];
260
261                fp = &tfshdr;
262                addr = base_of_serialtfs;
263                while(addr < end_of_serialtfs) {
264                        if ((rc = spifReadBlock(addr,(char *)fp,TFSHDRSIZ)) < 0) {
265                                printf("spifReadBlock failed %d\n",rc);
266                                break;
267                        }
268                        if (fp->hdrsize == 0xffff) {
269                                printf("%s not found\n",arg2);
270                                break;
271                        }
272                        if (strcmp(TFS_NAME(fp),arg2) == 0) {
273                                if (TFS_FILEEXISTS(fp)) {
274                                        fp->flags &= ~TFS_ACTIVE;
275                                        spifWriteEnable();     
276                                        spifGlobalUnprotect(); 
277                                        if ((rc = spifWriteBlock(addr,(char *)fp,TFSHDRSIZ)) < 0)
278                                                printf(" write_hdr failed %d\n",rc);
279                                        spifGlobalProtect();   
280                                        break;
281                                }
282                        }
283                        addr += TFS_SIZE(fp);
284                        addr += TFSHDRSIZ;
285                        while(addr & 0xf) addr++;
286                }
287        }
288        else if (strcmp(cmd, "tfsadd") == 0) {
289                int size;
290                long    bflags;
291                TFILE tfshdr, *fp;
292                unsigned long addr;
293                char *src, *name, *info;
294                char *arg2 = argv[optind+1];
295                char *arg3 = argv[optind+2];
296                char *arg4 = argv[optind+3];
297                char *icomma, *fcomma;
298
299                info = "";
300                bflags = 0;
301                name = arg2;
302                addr = base_of_serialtfs;
303
304                /* The incoming arguments can be either just the filename (in which
305                 * case we assume the source is the file in TFS with the same name),
306                 * or the filename, source address and size...
307                 */
308                if (argc == optind+2) {                 // Just filename?
309                        if ((fp = tfsstat(name)) == (TFILE *)0) {
310                                printf("File '%s' not in TFS\n",name);
311                                return(CMD_FAILURE);
312                        }
313                        name = fp->name;
314                        info = fp->info;
315                        bflags = fp->flags;
316                        size = fp->filsize;
317                        src = (char *)(fp + 1);
318                        fp = &tfshdr;
319                        memset((char *)fp,0,TFSHDRSIZ);
320                }
321                else if (argc == optind+4) {    // Filename with addr and len
322                        // Extract flags and info fields (if any) from the name...
323                        fcomma = strchr(name,',');
324                        if (fcomma) {
325                                icomma = strchr(fcomma+1,',');
326                                if (icomma) {
327                                        *icomma = 0;
328                                        info = icomma+1;
329                                }
330                                *fcomma = 0;
331                                bflags = tfsctrl(TFS_FATOB,(long)(fcomma+1),0);
332                        }
333       
334                        fp = &tfshdr;
335                        memset((char *)fp,0,TFSHDRSIZ);
336                        size = (int)strtol(arg4,0,0);
337                        src = (char *)strtoul(arg3,0,0);
338                }
339                else
340                        return(CMD_PARAM_ERROR);
341
342                while(addr < end_of_serialtfs) {
343                        if ((rc = spifReadBlock(addr,(char *)fp,TFSHDRSIZ)) < 0)
344                                break;
345                        if (fp->hdrsize == 0xffff) {
346                                unsigned long nextfileaddr;
347
348                                /* We're at the address in SPIF where we can add the new
349                                 * file, but first we need to make sure there's enough
350                                 * room...
351                                 */
352                                if ((TFSHDRSIZ + size + 16) >= (end_of_serialtfs - addr)) {
353                                        printf(" not enough space\n");
354                                        return(CMD_FAILURE);
355                                }
356
357                                /* Copy name and info data to header.
358                                 */
359                                strcpy(fp->name, name);
360                                strcpy(fp->info, info);
361                                fp->hdrsize = TFSHDRSIZ;
362                                fp->hdrvrsn = TFSHDRVERSION;
363                                fp->filsize = size;
364                                fp->flags = bflags;
365                                fp->flags |= (TFS_ACTIVE | TFS_NSTALE);
366                                fp->filcrc = crc32((unsigned char *)src,size);
367                                fp->modtime = tfsGetLtime();
368#if TFS_RESERVED
369                                {
370                                int     rsvd;
371                                for(rsvd=0;rsvd<TFS_RESERVED;rsvd++)
372                                        fp->rsvd[rsvd] = 0xffffffff;
373                                }
374#endif
375                                fp->next = 0;
376                                fp->hdrcrc = 0;
377                                fp->hdrcrc = crc32((unsigned char *)fp,TFSHDRSIZ);
378                                nextfileaddr = SPIF_TFSRAM_BASE - spif_tfs_base + addr + TFSHDRSIZ + size;
379                                if (nextfileaddr & 0xf)
380                                        nextfileaddr = (nextfileaddr | 0xf) + 1;
381                               
382                                fp->next = (TFILE *)nextfileaddr;
383
384                                printf(" writing %s...\n",arg2);
385                                spifWriteEnable();     
386                                spifGlobalUnprotect(); 
387                                spifWaitForReady();     
388
389                                spifWriteEnable();     
390                                if ((rc = spifWriteBlock(addr,(char *)fp,TFSHDRSIZ)) < 0)
391                                        printf(" write_hdr failed %d\n",rc);
392                                spifWaitForReady();     
393
394                                spifWriteEnable();     
395                                spifGlobalUnprotect(); 
396                                if ((rc = spifWriteBlock(addr+TFSHDRSIZ,src,size)) < 0)
397                                        printf(" write_file failed %d\n",rc);
398                                spifWaitForReady();     
399                                spifGlobalProtect();   
400                                break;
401                        }
402                        if (strcmp(TFS_NAME(fp),arg2) == 0) {
403                                if (TFS_FILEEXISTS(fp)) {
404                                        printf(" removing %s...\n",arg2);
405                                        fp->flags &= ~TFS_ACTIVE;
406                                        spifWriteEnable();     
407                                        spifGlobalUnprotect(); 
408                                        spifWaitForReady();     
409                                        spifWriteEnable();     
410                                        if ((rc = spifWriteBlock(addr,(char *)fp,TFSHDRSIZ)) < 0)
411                                                printf(" write_hdr failed %d\n",rc);
412                                        spifWaitForReady();     
413                                        spifGlobalProtect();   
414                                }
415                        }
416                        addr += TFS_SIZE(fp);
417                        addr += TFSHDRSIZ;
418                        while(addr & 0xf) addr++;
419                }
420        }
421        else if (strcmp(cmd, "tfsstat") == 0) {
422                unsigned long oaddr, addr, meminuse, memdead;
423                TFILE tfshdr, *fp;
424
425                fp = &tfshdr;
426                meminuse = memdead = 0;
427                addr = base_of_serialtfs;
428                while(addr < end_of_serialtfs) {
429                        if ((rc = spifReadBlock(addr,(char *)fp,TFSHDRSIZ)) < 0) {
430                                printf("spifReadBlock failed %d\n",rc);
431                                break;
432                        }
433                        if (fp->hdrsize == 0xffff)
434                                break;
435
436                        oaddr = addr;
437                        addr += TFS_SIZE(fp);
438                        addr += TFSHDRSIZ;
439                        while(addr & 0xf) addr++;
440
441                        if (TFS_FILEEXISTS(fp))
442                                meminuse += addr - oaddr;
443                        else
444                                memdead += addr - oaddr;
445                }
446                printf("Total: 0x%x, used: 0x%x, dead: 0x%x, avail: 0x%x\n",
447                        (end_of_serialtfs - base_of_serialtfs),
448                        meminuse, memdead,
449                        (end_of_serialtfs - base_of_serialtfs) - (meminuse + memdead));
450        }
451#endif
452        else
453                return(CMD_PARAM_ERROR);
454
455        return(CMD_SUCCESS);
456}
Note: See TracBrowser for help on using the repository browser.