source: umon/main/common/nand.c

Last change on this file was a7b6f00, checked in by Ed Sutter <edsutterjr@…>, on 08/04/15 at 01:35:50

tree cleanup using 'astyle --unpad-paren --align-pointer=name --lineend=linux --add-brackets --convert-tabs --style=knf -A4 FILENAME'

  • Property mode set to 100644
File size: 11.4 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 * nand.c
22 *
23 * Original author:     Ed Sutter (ed.sutter@alcatel-lucent.com)
24 *
25 */
26#include "config.h"
27#if INCLUDE_NANDCMD
28#include "cpuio.h"
29#include "genlib.h"
30#include "stddefs.h"
31#include "tfs.h"
32#include "tfsprivate.h"
33#include "cli.h"
34#include "nand.h"
35
36int nandVerbose;
37
38#define END_OF_NAND (BASE_OF_NAND+SIZE_OF_NAND-1)
39
40#ifdef FLASHRAM_BASE
41#ifndef NAND_TFSRAM_BASE
42#define NAND_TFSRAM_BASE FLASHRAM_BASE
43#endif
44#endif
45
46char *nandHelp[] = {
47    "Interface with Nand-Flash",
48    "-[v] {cmd} [cmd-specific args]",
49#if INCLUDE_VERBOSEHELP
50    "Options:",
51    " -v   incrementing verbosity level",
52    "",
53    "Cmds:",
54    " init                      initialize interface",
55    " info                      show device info",
56#ifdef FLASHRAM_BASE
57    " tfsls                     list files directly out of SPI flash",
58    " tfsload                   copy NAND to TFSRAM",
59    " tfsstat                   show state of SPI flash",
60    " tfsstore                  copy TFSRAM to NAND",
61    " tfserase                  erase NAND space allocated to TFS",
62    " tfsrm {name}              remove file directly out of NAND flash",
63    " tfsadd {name} [src sz]    add file directly to NAND flash",
64#endif
65    " erase {addr len}          erase block",
66    " read {addr dest len}      read block",
67    " write {addr src len}      write block",
68#endif
69    0,
70};
71
72int
73nandCmd(int argc,char *argv[])
74{
75    unsigned long addr;
76    char *cmd, *dest, *src;
77    int opt, len, rc;
78
79    rc = 0;
80    nandVerbose = 0;
81    while((opt=getopt(argc,argv,"v")) != -1) {
82        switch(opt) {
83        case 'v':
84            nandVerbose++;
85            break;
86        default:
87            return(CMD_PARAM_ERROR);
88        }
89    }
90
91    if(argc < optind+1) {
92        return(CMD_PARAM_ERROR);
93    }
94
95    cmd = argv[optind];
96
97    if(nandVerbose) {
98        printf("CMD: %s\n",cmd);
99    }
100
101    if(strcmp(cmd,"init") == 0) {
102        nandInit();
103    } else if(strcmp(cmd,"info") == 0) {
104        nandInfo();
105    } else if(strcmp(cmd,"erase") == 0) {
106        if(argc != optind+3) {
107            return(CMD_PARAM_ERROR);
108        }
109        addr = strtoul(argv[optind+1],0,0);
110        len = (int)strtol(argv[optind+2],0,0);
111        nandEraseChunk((char *)addr,len);
112    } else if(strcmp(cmd,"write") == 0) {
113        if(argc != optind+4) {
114            return(CMD_PARAM_ERROR);
115        }
116        addr = strtoul(argv[optind+1],0,0);
117        src = (char *)strtoul(argv[optind+2],0,0);
118        len = (int)strtol(argv[optind+3],0,0);
119        nandWriteChunk((char *)addr,src,len);
120    } else if(strcmp(cmd,"read") == 0) {
121        if(argc != optind+4) {
122            return(CMD_PARAM_ERROR);
123        }
124        addr = strtoul(argv[optind+1],0,0);
125        dest = (char *)strtoul(argv[optind+2],0,0);
126        len = (int)strtol(argv[optind+3],0,0);
127        nandReadChunk((char *)addr,dest,len);
128    }
129#ifdef FLASHRAM_BASE
130    else if(strcmp(cmd,"tfsload") == 0) {
131    } else if(strcmp(cmd,"tfsstore") == 0) {
132    } else if(strcmp(cmd,"tfserase") == 0) {
133    } else if(strcmp(cmd, "tfsls") == 0) {
134        int ftot;
135        char *addr;
136        TFILE tfshdr, *fp;
137
138        ftot = 0;
139        fp = &tfshdr;
140        addr = (char *)BASE_OF_NAND;
141        while(addr < (char *)END_OF_NAND) {
142            char fbuf[32], *flags;
143
144            if((rc = nandReadChunk(addr,(char *)fp,TFSHDRSIZ)) < 0) {
145                printf("nandReadChunk failed %d\n",rc);
146                break;
147            }
148            if(fp->hdrsize == 0xffff) {
149                break;
150            }
151            if(TFS_FILEEXISTS(fp)) {
152                if(ftot == 0) {
153                    printf(" Name                        Size    Offset    Flags  Info\n");
154                }
155                ftot++;
156                flags = tfsflagsbtoa(TFS_FLAGS(fp),fbuf);
157                if((!flags) || (!fbuf[0])) {
158                    flags = " ";
159                }
160                printf(" %-23s  %7ld  0x%08lx  %-5s  %s\n",TFS_NAME(fp),
161                       TFS_SIZE(fp),(unsigned long)(addr+TFSHDRSIZ),
162                       flags,TFS_INFO(fp));
163            }
164            addr += TFS_SIZE(fp);
165            addr += TFSHDRSIZ;
166            while((long)addr & 0xf) {
167                addr++;
168            }
169        }
170    } else if(strcmp(cmd, "tfsrm") == 0) {
171        char *addr;
172        TFILE tfshdr, *fp;
173        char *arg2 = argv[optind+1];
174
175        fp = &tfshdr;
176        addr = (char *)BASE_OF_NAND;
177        while(addr < (char *)END_OF_NAND) {
178            if((rc = nandReadChunk(addr,(char *)fp,TFSHDRSIZ)) < 0) {
179                printf("nandReadChunk failed %d\n",rc);
180                break;
181            }
182            if(fp->hdrsize == 0xffff) {
183                printf("%s not found\n",arg2);
184                break;
185            }
186            if(strcmp(TFS_NAME(fp),arg2) == 0) {
187                if(TFS_FILEEXISTS(fp)) {
188                    fp->flags &= ~TFS_ACTIVE;
189                    if((rc = nandWriteChunk(addr,(char *)fp,TFSHDRSIZ)) < 0) {
190                        printf(" write_hdr failed %d\n",rc);
191                    }
192                    break;
193                }
194            }
195            addr += TFS_SIZE(fp);
196            addr += TFSHDRSIZ;
197            while((long)addr & 0xf) {
198                addr++;
199            }
200        }
201    } else if(strcmp(cmd, "tfsadd") == 0) {
202        int size;
203        long    bflags;
204        TFILE tfshdr, *fp;
205        char *addr;
206        char *src, *name, *info;
207        char *arg2 = argv[optind+1];
208        char *arg3 = argv[optind+2];
209        char *arg4 = argv[optind+3];
210        char *icomma, *fcomma;
211
212        info = "";
213        bflags = 0;
214        name = arg2;
215        addr = (char *)BASE_OF_NAND;
216
217        /* The incoming arguments can be either just the filename (in which
218         * case we assume the source is the file in TFS with the same name),
219         * or the filename, source address and size...
220         */
221        if(argc == optind+2) {          // Just filename?
222            if((fp = tfsstat(name)) == (TFILE *)0) {
223                printf("File '%s' not in TFS\n",name);
224                return(CMD_FAILURE);
225            }
226            name = fp->name;
227            info = fp->info;
228            bflags = fp->flags;
229            size = fp->filsize;
230            src = (char *)(fp + 1);
231            fp = &tfshdr;
232            memset((char *)fp,0,TFSHDRSIZ);
233        } else if(argc == optind+4) {   // Filename with addr and len
234            // Extract flags and info fields (if any) from the name...
235            fcomma = strchr(name,',');
236            if(fcomma) {
237                icomma = strchr(fcomma+1,',');
238                if(icomma) {
239                    *icomma = 0;
240                    info = icomma+1;
241                }
242                *fcomma = 0;
243                bflags = tfsctrl(TFS_FATOB,(long)(fcomma+1),0);
244            }
245
246            fp = &tfshdr;
247            memset((char *)fp,0,TFSHDRSIZ);
248            size = (int)strtol(arg4,0,0);
249            src = (char *)strtoul(arg3,0,0);
250        } else {
251            return(CMD_PARAM_ERROR);
252        }
253
254        while(addr < (char *)END_OF_NAND) {
255            if((rc = nandReadChunk(addr,(char *)fp,TFSHDRSIZ)) < 0) {
256                break;
257            }
258            if(fp->hdrsize == 0xffff) {
259                unsigned long nextfileaddr;
260
261                /* We're at the address in NAND where we can add the new
262                 * file, but first we need to make sure there's enough
263                 * room...
264                 */
265                if((TFSHDRSIZ + size + 16) >= ((char *)END_OF_NAND - addr)) {
266                    printf(" not enough space\n");
267                    return(CMD_FAILURE);
268                }
269
270                /* Copy name and info data to header.
271                 */
272                strcpy(fp->name, name);
273                strcpy(fp->info, info);
274                fp->hdrsize = TFSHDRSIZ;
275                fp->hdrvrsn = TFSHDRVERSION;
276                fp->filsize = size;
277                fp->flags = bflags;
278                fp->flags |= (TFS_ACTIVE | TFS_NSTALE);
279                fp->filcrc = crc32((unsigned char *)src,size);
280                fp->modtime = tfsGetLtime();
281#if TFS_RESERVED
282                {
283                    int rsvd;
284                    for(rsvd=0; rsvd<TFS_RESERVED; rsvd++) {
285                        fp->rsvd[rsvd] = 0xffffffff;
286                    }
287                }
288#endif
289                fp->next = 0;
290                fp->hdrcrc = 0;
291                fp->hdrcrc = crc32((unsigned char *)fp,TFSHDRSIZ);
292                nextfileaddr = NAND_TFSRAM_BASE - NAND_TFS_BASE + (long)addr + TFSHDRSIZ + size;
293                if(nextfileaddr & 0xf) {
294                    nextfileaddr = (nextfileaddr | 0xf) + 1;
295                }
296
297                fp->next = (TFILE *)nextfileaddr;
298
299                printf(" writing %s...\n",arg2);
300                if((rc = nandWriteChunk(addr,(char *)fp,TFSHDRSIZ)) < 0) {
301                    printf(" write_hdr failed %d\n",rc);
302                }
303
304                if((rc = nandWriteChunk(addr+TFSHDRSIZ,src,size)) < 0) {
305                    printf(" write_file failed %d\n",rc);
306                }
307                break;
308            }
309            if(strcmp(TFS_NAME(fp),arg2) == 0) {
310                if(TFS_FILEEXISTS(fp)) {
311                    printf(" removing %s...\n",arg2);
312                    fp->flags &= ~TFS_ACTIVE;
313                    if((rc = nandWriteChunk(addr,(char *)fp,TFSHDRSIZ)) < 0) {
314                        printf(" write_hdr failed %d\n",rc);
315                    }
316                }
317            }
318            addr += TFS_SIZE(fp);
319            addr += TFSHDRSIZ;
320            while((long)addr & 0xf) {
321                addr++;
322            }
323        }
324    } else if(strcmp(cmd, "tfsstat") == 0) {
325        char *addr, *oaddr;
326        TFILE tfshdr, *fp;
327        unsigned long meminuse, memdead;
328
329        fp = &tfshdr;
330        meminuse = memdead = 0;
331        addr = (char *)BASE_OF_NAND;
332        while(addr < (char *)END_OF_NAND) {
333            if((rc = nandReadChunk(addr,(char *)fp,TFSHDRSIZ)) < 0) {
334                printf("nandReadChunk failed %d\n",rc);
335                break;
336            }
337            if(fp->hdrsize == 0xffff) {
338                break;
339            }
340
341            oaddr = addr;
342            addr += TFS_SIZE(fp);
343            addr += TFSHDRSIZ;
344            while((long)addr & 0xf) {
345                addr++;
346            }
347
348            if(TFS_FILEEXISTS(fp)) {
349                meminuse += addr - oaddr;
350            } else {
351                memdead += addr - oaddr;
352            }
353        }
354        printf("Total: 0x%x, used: 0x%x, dead: 0x%x, avail: 0x%x\n",
355               SIZE_OF_NAND, meminuse, memdead,
356               SIZE_OF_NAND - (meminuse + memdead));
357    }
358#endif
359    else {
360        return(CMD_PARAM_ERROR);
361    }
362
363    return(CMD_SUCCESS);
364}
365#endif
Note: See TracBrowser for help on using the repository browser.