source: umon/main/common/nand.c @ 24d5973

Last change on this file since 24d5973 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 100755
File size: 8.9 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        cmd = argv[optind];
95
96        if (nandVerbose)
97                printf("CMD: %s\n",cmd);
98
99        if (strcmp(cmd,"init") == 0) {
100                nandInit();
101        }
102        else if (strcmp(cmd,"info") == 0) {
103                nandInfo();
104        }
105        else if (strcmp(cmd,"erase") == 0) {
106                if (argc != optind+3)
107                        return(CMD_PARAM_ERROR);
108                addr = strtoul(argv[optind+1],0,0);
109                len = (int)strtol(argv[optind+2],0,0);
110                nandEraseChunk((char *)addr,len);
111        }
112        else if (strcmp(cmd,"write") == 0) {
113                if (argc != optind+4)
114                        return(CMD_PARAM_ERROR);
115                addr = strtoul(argv[optind+1],0,0);
116                src = (char *)strtoul(argv[optind+2],0,0);
117                len = (int)strtol(argv[optind+3],0,0);
118                nandWriteChunk((char *)addr,src,len);
119        }
120        else if (strcmp(cmd,"read") == 0) {
121                if (argc != optind+4)
122                        return(CMD_PARAM_ERROR);
123                addr = strtoul(argv[optind+1],0,0);
124                dest = (char *)strtoul(argv[optind+2],0,0);
125                len = (int)strtol(argv[optind+3],0,0);
126                nandReadChunk((char *)addr,dest,len);
127        }
128#ifdef FLASHRAM_BASE
129        else if (strcmp(cmd,"tfsload") == 0) {
130        }
131        else if (strcmp(cmd,"tfsstore") == 0) {
132        }
133        else if (strcmp(cmd,"tfserase") == 0) {
134        }
135        else if (strcmp(cmd, "tfsls") == 0) {
136                int ftot;
137                char *addr;
138                TFILE tfshdr, *fp;
139
140                ftot = 0;
141                fp = &tfshdr;
142                addr = (char *)BASE_OF_NAND;
143                while(addr < (char *)END_OF_NAND) {
144                        char fbuf[32], *flags;
145
146                        if ((rc = nandReadChunk(addr,(char *)fp,TFSHDRSIZ)) < 0) {
147                                printf("nandReadChunk failed %d\n",rc);
148                                break;
149                        }
150                        if (fp->hdrsize == 0xffff)
151                                break;
152                        if (TFS_FILEEXISTS(fp)) {
153                                if (ftot == 0)
154                                        printf(" Name                        Size    Offset    Flags  Info\n");
155                                ftot++;
156                                flags = tfsflagsbtoa(TFS_FLAGS(fp),fbuf);
157                                if ((!flags) || (!fbuf[0]))
158                                        flags = " ";
159                                printf(" %-23s  %7ld  0x%08lx  %-5s  %s\n",TFS_NAME(fp),
160                                        TFS_SIZE(fp),(unsigned long)(addr+TFSHDRSIZ),
161                                        flags,TFS_INFO(fp));
162                        }
163                        addr += TFS_SIZE(fp);
164                        addr += TFSHDRSIZ;
165                        while((long)addr & 0xf) addr++;
166                }
167        }
168        else if (strcmp(cmd, "tfsrm") == 0) {
169                char *addr;
170                TFILE tfshdr, *fp;
171                char *arg2 = argv[optind+1];
172
173                fp = &tfshdr;
174                addr = (char *)BASE_OF_NAND;
175                while(addr < (char *)END_OF_NAND) {
176                        if ((rc = nandReadChunk(addr,(char *)fp,TFSHDRSIZ)) < 0) {
177                                printf("nandReadChunk failed %d\n",rc);
178                                break;
179                        }
180                        if (fp->hdrsize == 0xffff) {
181                                printf("%s not found\n",arg2);
182                                break;
183                        }
184                        if (strcmp(TFS_NAME(fp),arg2) == 0) {
185                                if (TFS_FILEEXISTS(fp)) {
186                                        fp->flags &= ~TFS_ACTIVE;
187                                        if ((rc = nandWriteChunk(addr,(char *)fp,TFSHDRSIZ)) < 0)
188                                                printf(" write_hdr failed %d\n",rc);
189                                        break;
190                                }
191                        }
192                        addr += TFS_SIZE(fp);
193                        addr += TFSHDRSIZ;
194                        while((long)addr & 0xf) addr++;
195                }
196        }
197        else if (strcmp(cmd, "tfsadd") == 0) {
198                int size;
199                long    bflags;
200                TFILE tfshdr, *fp;
201                char *addr;
202                char *src, *name, *info;
203                char *arg2 = argv[optind+1];
204                char *arg3 = argv[optind+2];
205                char *arg4 = argv[optind+3];
206                char *icomma, *fcomma;
207
208                info = "";
209                bflags = 0;
210                name = arg2;
211                addr = (char *)BASE_OF_NAND;
212
213                /* The incoming arguments can be either just the filename (in which
214                 * case we assume the source is the file in TFS with the same name),
215                 * or the filename, source address and size...
216                 */
217                if (argc == optind+2) {                 // Just filename?
218                        if ((fp = tfsstat(name)) == (TFILE *)0) {
219                                printf("File '%s' not in TFS\n",name);
220                                return(CMD_FAILURE);
221                        }
222                        name = fp->name;
223                        info = fp->info;
224                        bflags = fp->flags;
225                        size = fp->filsize;
226                        src = (char *)(fp + 1);
227                        fp = &tfshdr;
228                        memset((char *)fp,0,TFSHDRSIZ);
229                }
230                else if (argc == optind+4) {    // Filename with addr and len
231                        // Extract flags and info fields (if any) from the name...
232                        fcomma = strchr(name,',');
233                        if (fcomma) {
234                                icomma = strchr(fcomma+1,',');
235                                if (icomma) {
236                                        *icomma = 0;
237                                        info = icomma+1;
238                                }
239                                *fcomma = 0;
240                                bflags = tfsctrl(TFS_FATOB,(long)(fcomma+1),0);
241                        }
242       
243                        fp = &tfshdr;
244                        memset((char *)fp,0,TFSHDRSIZ);
245                        size = (int)strtol(arg4,0,0);
246                        src = (char *)strtoul(arg3,0,0);
247                }
248                else
249                        return(CMD_PARAM_ERROR);
250
251                while(addr < (char *)END_OF_NAND) {
252                        if ((rc = nandReadChunk(addr,(char *)fp,TFSHDRSIZ)) < 0)
253                                break;
254                        if (fp->hdrsize == 0xffff) {
255                                unsigned long nextfileaddr;
256
257                                /* We're at the address in NAND where we can add the new
258                                 * file, but first we need to make sure there's enough
259                                 * room...
260                                 */
261                                if ((TFSHDRSIZ + size + 16) >= ((char *)END_OF_NAND - addr)) {
262                                        printf(" not enough space\n");
263                                        return(CMD_FAILURE);
264                                }
265
266                                /* Copy name and info data to header.
267                                 */
268                                strcpy(fp->name, name);
269                                strcpy(fp->info, info);
270                                fp->hdrsize = TFSHDRSIZ;
271                                fp->hdrvrsn = TFSHDRVERSION;
272                                fp->filsize = size;
273                                fp->flags = bflags;
274                                fp->flags |= (TFS_ACTIVE | TFS_NSTALE);
275                                fp->filcrc = crc32((unsigned char *)src,size);
276                                fp->modtime = tfsGetLtime();
277#if TFS_RESERVED
278                                {
279                                int     rsvd;
280                                for(rsvd=0;rsvd<TFS_RESERVED;rsvd++)
281                                        fp->rsvd[rsvd] = 0xffffffff;
282                                }
283#endif
284                                fp->next = 0;
285                                fp->hdrcrc = 0;
286                                fp->hdrcrc = crc32((unsigned char *)fp,TFSHDRSIZ);
287                                nextfileaddr = NAND_TFSRAM_BASE - NAND_TFS_BASE + (long)addr + TFSHDRSIZ + size;
288                                if (nextfileaddr & 0xf)
289                                        nextfileaddr = (nextfileaddr | 0xf) + 1;
290                               
291                                fp->next = (TFILE *)nextfileaddr;
292
293                                printf(" writing %s...\n",arg2);
294                                if ((rc = nandWriteChunk(addr,(char *)fp,TFSHDRSIZ)) < 0)
295                                        printf(" write_hdr failed %d\n",rc);
296
297                                if ((rc = nandWriteChunk(addr+TFSHDRSIZ,src,size)) < 0)
298                                        printf(" write_file failed %d\n",rc);
299                                break;
300                        }
301                        if (strcmp(TFS_NAME(fp),arg2) == 0) {
302                                if (TFS_FILEEXISTS(fp)) {
303                                        printf(" removing %s...\n",arg2);
304                                        fp->flags &= ~TFS_ACTIVE;
305                                        if ((rc = nandWriteChunk(addr,(char *)fp,TFSHDRSIZ)) < 0)
306                                                printf(" write_hdr failed %d\n",rc);
307                                }
308                        }
309                        addr += TFS_SIZE(fp);
310                        addr += TFSHDRSIZ;
311                        while((long)addr & 0xf) addr++;
312                }
313        }
314        else if (strcmp(cmd, "tfsstat") == 0) {
315                char *addr, *oaddr;
316                TFILE tfshdr, *fp;
317                unsigned long meminuse, memdead;
318
319                fp = &tfshdr;
320                meminuse = memdead = 0;
321                addr = (char *)BASE_OF_NAND;
322                while(addr < (char *)END_OF_NAND) {
323                        if ((rc = nandReadChunk(addr,(char *)fp,TFSHDRSIZ)) < 0) {
324                                printf("nandReadChunk failed %d\n",rc);
325                                break;
326                        }
327                        if (fp->hdrsize == 0xffff)
328                                break;
329
330                        oaddr = addr;
331                        addr += TFS_SIZE(fp);
332                        addr += TFSHDRSIZ;
333                        while((long)addr & 0xf) addr++;
334
335                        if (TFS_FILEEXISTS(fp))
336                                meminuse += addr - oaddr;
337                        else
338                                memdead += addr - oaddr;
339                }
340                printf("Total: 0x%x, used: 0x%x, dead: 0x%x, avail: 0x%x\n",
341                        SIZE_OF_NAND, meminuse, memdead,
342                        SIZE_OF_NAND - (meminuse + memdead));
343        }
344#endif
345        else
346                return(CMD_PARAM_ERROR);
347
348        return(CMD_SUCCESS);
349}
350#endif
Note: See TracBrowser for help on using the repository browser.