source: umon/main/common/memcmds.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: 26.0 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 * memcmds.c:
22 *
23 * This code allows the monitor to display, modify, search, copy, fill
24 * and test memory in a variety of different ways.
25 *
26 * Original author:     Ed Sutter (ed.sutter@alcatel-lucent.com)
27 *
28 */
29#include "config.h"
30#include "genlib.h"
31#include "stddefs.h"
32#include <ctype.h>
33#include "cli.h"
34
35/* With INCLUDE_MEMCMDS defined in config.h, all uMon commands in this
36 * file are automatically pulled into the build.  If there is a need to
37 * be more selective, then set INCLUDE_MEMCMDS to zero in config.h and
38 * define only the INCLUDE_XX macros needed (shown below) to one in
39 * config.h.
40 */
41#if INCLUDE_MEMCMDS
42#define INCLUDE_PM 1
43#define INCLUDE_DM 1
44#define INCLUDE_FM 1
45#define INCLUDE_CM 1
46#define INCLUDE_SM 1
47#define INCLUDE_MT 1
48#endif
49
50#if INCLUDE_PM
51
52/* Pm():
53 *      Put to memory.
54 *
55 *      Arguments...
56 *      arg1:           address.
57 *      arg2-argN:      data to put beginning at specified address (max of 8).
58 *
59 *      Options...
60 *      -2      access as a short.
61 *      -4      access as a long.
62 *      -f      fifo access (address does not increment).
63 *      -s      data is ascii string.
64 *      -S      data is ascii string and should be concatenated with the
65 *              string that starts at the specified address.
66 */
67
68char *PmHelp[] = {
69        "Put to Memory",
70        "-[24aefosSx] {addr} {val|string} [val] ...",
71#if INCLUDE_VERBOSEHELP
72        "Options:",
73        " -2   short access",
74        " -4   long access",
75        " -a   AND operation",
76        " -e   endian swap",
77        " -f   fifo mode",
78        " -o   OR operation",
79        " -s   strcpy",
80        " -S   strcat",
81        " -x   XOR operation",
82#endif
83        0,
84};
85
86#define PM_EQ_OPERATION         1
87#define PM_AND_OPERATION        2
88#define PM_OR_OPERATION         3
89#define PM_XOR_OPERATION        4
90
91int
92Pm(int argc,char *argv[])
93{
94        ulong   val4, add, base;
95        ushort  val2;
96        uchar   val1, c;
97        int     opt, width, ascii, fifo, i, j, concatenate, endian_swap, pmop;
98
99        pmop = PM_EQ_OPERATION;
100        width = 1;
101        ascii = fifo = 0;
102        concatenate = 0;
103        endian_swap = 0;
104        while((opt=getopt(argc,argv,"24aefosSx")) != -1) {
105                switch(opt) {
106                case '2':
107                        width = 2;
108                        break;
109                case '4':
110                        width = 4;
111                        break;
112                case 'a':
113                        pmop = PM_AND_OPERATION;
114                        break;
115                case 'e':
116                        endian_swap = 1;
117                        break;
118                case 'f':
119                        fifo = 1;
120                        break;
121                case 'o':
122                        pmop = PM_OR_OPERATION;
123                        break;
124                case 's':
125                        ascii = 1;
126                        break;
127                case 'S':
128                        ascii = 1;
129                        concatenate = 1;
130                        break;
131                case 'x':
132                        pmop = PM_XOR_OPERATION;
133                        concatenate = 1;
134                        break;
135                default:
136                        return(CMD_PARAM_ERROR);
137                }
138        }
139
140        if (argc < (optind+2))
141                return(CMD_PARAM_ERROR);
142
143        add = strtoul(argv[optind],(char **)0,0);
144
145        if (ascii) {
146                base = add;
147                if (concatenate) {                      /* If concatenate, skip to */
148                        while(*(uchar *)add)    /* end of string, then start. */
149                                add++;
150                }
151                for(i=optind+1;i<argc;i++) {
152                        j = 0;
153                        while(argv[i][j]) {
154                                c = argv[i][j++];
155                                if (c == '\\') {
156                                        c = argv[i][j++];
157                                        if (c == 'n')
158                                                *(char *)add = '\n';
159                                        else if (c == 'r')
160                                                *(char *)add = '\r';
161                                        else if (c == 't')
162                                                *(char *)add = '\t';
163                                        else {
164                                                *(char *)add = '\\';
165                                                if (!fifo)
166                                                        add++;
167                                                *(char *)add = c;
168                                        }
169                                }
170                                else {
171                                        *(char *)add = c;
172                                }
173                                if (!fifo)
174                                        add++;
175                        }
176                }
177                *(uchar *)add = 0;
178                shell_sprintf("STRLEN","%d",add-base);
179                return(CMD_SUCCESS);
180        }
181        for(i=optind+1;i<argc;i++) {
182                switch(width) {
183                case 1:
184                        val1 = (uchar)strtoul(argv[i],(char **)0,0);
185                        switch (pmop) {
186                                case PM_EQ_OPERATION:
187                        *(uchar *)add = val1;
188                                        break;
189                                case PM_AND_OPERATION:
190                                        *(uchar *)add &= val1;
191                                        break;
192                                case PM_OR_OPERATION:
193                                        *(uchar *)add |= val1;
194                                        break;
195                                case PM_XOR_OPERATION:
196                                        *(uchar *)add ^= val1;
197                                        break;
198                        }
199                        if (!fifo) add++;
200                        break;
201                case 2:
202                        val2 = (ushort)strtoul(argv[i],(char **)0,0);
203                        switch (pmop) {
204                                case PM_EQ_OPERATION:
205                        *(ushort *)add = endian_swap ? swap2(val2) : val2;
206                                        break;
207                                case PM_AND_OPERATION:
208                                        *(ushort *)add &= endian_swap ? swap2(val2) : val2;
209                                        break;
210                                case PM_OR_OPERATION:
211                                        *(ushort *)add |= endian_swap ? swap2(val2) : val2;
212                                        break;
213                                case PM_XOR_OPERATION:
214                                        *(ushort *)add ^= endian_swap ? swap2(val2) : val2;
215                                        break;
216                        }
217                        if (!fifo) add += 2;
218                        break;
219                case 4:
220                        val4 = (ulong)strtoul(argv[i],(char **)0,0);
221                        switch (pmop) {
222                                case PM_EQ_OPERATION:
223                        *(ulong *)add = endian_swap ? swap4(val4) : val4;
224                                        break;
225                                case PM_AND_OPERATION:
226                                        *(ulong *)add &= endian_swap ? swap4(val4) : val4;
227                                        break;
228                                case PM_OR_OPERATION:
229                                        *(ulong *)add |= endian_swap ? swap4(val4) : val4;
230                                        break;
231                                case PM_XOR_OPERATION:
232                                        *(ulong *)add ^= endian_swap ? swap4(val4) : val4;
233                                        break;
234                        }
235                        if (!fifo) add += 4;
236                        break;
237                }
238        }
239        return(CMD_SUCCESS);
240}
241#endif
242
243#if INCLUDE_DM
244/* Dm():
245 *      Display memory. 
246 *
247 *      Arguments...
248 *      arg1: address to start display
249 *      arg2: if present, specifies the number of units to be displayed.
250 *
251 *      Options...
252 *      -2      a unit is a short.
253 *      -4      a unit is a long.
254 *      -b      print chars out as is (binary).
255 *      -d      display in decimal.
256 *      -e      endian-swap for short/long display.
257 *      -f      fifo-type access (address does not increment).
258 *      -l#     size of line to be printed.
259 *      -m      prompt user for more.
260 *      -s      print chars out as is (binary) and terminates at a null.
261 *      -v {varname} assign last value displayed to shell var varname. 
262 *     
263 *      Defaults...
264 *      Display in hex, and unit type is byte. 
265 */
266
267char *DmHelp[] = {
268        "Display Memory",
269        "-[24bdefl:msv:] {addr} [byte-cnt]",
270#if INCLUDE_VERBOSEHELP
271        "Options:",
272        " -2   short access",
273        " -4   long access",
274        " -b   binary",
275        " -d   decimal",
276        " -e   endian swap",
277        " -f   fifo mode",
278        " -l#  size of line (in bytes)",
279        " -m   use 'more'",
280        " -s   string",
281        " -v {var} load 'var' with element",
282#endif
283        0,
284};
285
286#define BD_NULL                 0
287#define BD_RAWBINARY    1
288#define BD_ASCIISTRING  2
289
290int
291Dm(int argc,char *argv[])
292{
293        ushort  *sp;
294        uchar   *cp, cbuf[128];
295        ulong   *lp, add, count_rqst;
296        char    *varname, *prfmt, *vprfmt;
297        int             i, count, width, opt, more, size, fifo;
298        int             hex_display, bin_display, endian_swap, linesize, sol;
299
300        linesize = 0;
301        width = 1;
302        more = fifo = 0;
303        bin_display = BD_NULL;
304        hex_display = 1;
305        endian_swap = 0;
306        varname = (char *)0;
307        while((opt=getopt(argc,argv,"24bdefl:msv:")) != -1) {
308                switch(opt) {
309                case '2':
310                        width = 2;
311                        break;
312                case '4':
313                        width = 4;
314                        break;
315                case 'b':
316                        bin_display = BD_RAWBINARY;
317                        break;
318                case 'd':
319                        hex_display = 0;
320                        break;
321                case 'e':
322                        endian_swap = 1;
323                        break;
324                case 'f':
325                        fifo = 1;
326                        break;
327                case 'l':
328                        linesize = atoi(optarg);
329                        break;
330                case 'm':
331                        more = 1;
332                        break;
333                case 'v':
334                        varname = optarg;
335                        break;
336                case 's':
337                        bin_display = BD_ASCIISTRING;
338                        break;
339                default:
340                        return(CMD_PARAM_ERROR);
341                }
342        }
343
344        if (argc < (optind+1))
345                return(CMD_PARAM_ERROR);
346
347        add = strtoul(argv[optind],(char **)0,0);
348        if (hex_display)
349                vprfmt = "0x%x";
350        else
351                vprfmt = "%d";
352
353        if (argc-(optind-1) == 3) {
354                count_rqst = strtoul(argv[optind+1],(char **)0,0);
355                count_rqst *= width;
356        }
357        else
358                count_rqst = 128;
359
360
361        if (bin_display != BD_NULL) {
362                cp = (uchar *)add;
363                if (bin_display == BD_ASCIISTRING) {
364                        putstr((char *)cp);
365                        if (varname) {
366                                shell_sprintf(varname,vprfmt,cp+strlen((char *)cp)+1);
367                        }
368                }
369                else {
370                        for(i=0;i<count_rqst;i++)
371                                putchar(*cp++);
372                }
373                putchar('\n');
374                return(CMD_SUCCESS);
375        }
376
377        sol = linesize == 0 ? 16 : linesize;
378        do {
379                count = count_rqst;
380
381                if (width == 1) {
382                        cp = (uchar *)add;
383                        if (hex_display)
384                                prfmt = "%02X ";
385                        else
386                                prfmt = "%3d ";
387       
388                        if (varname) {
389                                shell_sprintf(varname,vprfmt,*cp);
390                        }
391                        else {
392                                while(count > 0) {
393                                        printf("%08lx: ",(ulong)cp);
394                                        if (count > sol)
395                                                size = sol;
396                                        else   
397                                                size = count;
398       
399                                        for(i=0;i<sol;i++) {
400                                                if (i >= size)
401                                                        putstr("   ");
402                                                else  {
403                                                        cbuf[i] = *cp;
404                                                        printf(prfmt,cbuf[i]);
405                                                }
406                                                if ((linesize == 0) && (i == 7))
407                                                        putstr("  ");
408                                                if (!fifo)
409                                                        cp++;
410                                        }
411                                        if ((hex_display) && (!fifo)) {
412                                                putstr("  ");
413                                                prascii(cbuf,size);
414                                        }
415                                        putchar('\n');
416                                        count -= size;
417                                        if (!fifo) {
418                                                add += size;
419                                                cp = (uchar *)add;
420                                        }
421                                }
422                        }
423                }
424                else if (width == 2) {
425                        sp = (ushort *)add;
426                        if (hex_display)
427                                prfmt = "%04X ";
428                        else
429                                prfmt = "%5d ";
430       
431                        if (varname) {
432                                shell_sprintf(varname,vprfmt,endian_swap ? swap2(*sp) : *sp);
433                        }
434                        else {
435                                while(count>0) {
436                                        printf("%08lx: ",(ulong)sp);
437                                        if (count > sol)
438                                                size = sol;
439                                        else   
440                                                size = count;
441               
442                                        for(i=0;i<size;i+=2) {
443                                                printf(prfmt,endian_swap ? swap2(*sp) : *sp);
444                                                if (!fifo)
445                                                        sp++;
446                                        }
447                                        putchar('\n');
448                                        count -= size;
449                                        if (!fifo) {
450                                                add += size;
451                                                sp = (ushort *)add;
452                                        }
453                                }
454                        }
455                }
456                else if (width == 4) {
457                        lp = (ulong *)add;
458                        if (hex_display)
459                                prfmt = "%08X  ";
460                        else
461                                prfmt = "%12d  ";
462                       
463                        if (varname) {
464                                shell_sprintf(varname,vprfmt,endian_swap ? swap4(*lp) : *lp);
465                        }
466                        else {
467                                while(count>0) {
468                                        printf("%08lx: ",(ulong)lp);
469                                        if (count > sol)
470                                                size = sol;
471                                        else   
472                                                size = count;
473                                        for(i=0;i<size;i+=4) {
474                                                printf(prfmt,endian_swap ? swap4(*lp) : *lp);
475                                                if (!fifo)
476                                                        lp++;
477                                        }
478                                        putchar('\n');
479                                        count -= size;
480                                        if (!fifo) {
481                                                add += size;
482                                                lp = (ulong *)add;
483                                        }
484                                }
485                        }
486                }
487        } while (more && More());
488        return(CMD_SUCCESS);
489}
490#endif
491
492
493#if INCLUDE_FM
494/* Fm():
495 *      Fill memory with user-specified data.
496 *      Syntax:
497 *              fm [options] {start} {count | finish} {value}
498 */
499
500char *FmHelp[] = {
501        "Fill Memory",
502        "-[24cinp] {start} {finish|byte-cnt} {value|pattern}",
503#if INCLUDE_VERBOSEHELP
504        "Options:",
505        " -2   short access",
506        " -4   long access",
507        " -c   arg2 is count (in bytes)",
508        " -i   increment {value|pattern}",
509        " -n   no verification",
510        " -p   arg3 is a pattern",
511#endif
512        0,
513};
514
515int
516Fm(int argc,char *argv[])
517{
518        char    *pp, *pattern;
519        ulong   start, finish;
520        uchar   *cptr, cdata;
521        ushort  *wptr, wdata;
522        ulong   *lptr, ldata, error_at;
523        int     width, opt, arg2iscount, arg3ispattern, err, verify, increment;
524
525        width = 1;
526        verify = 1;
527        increment = 0;
528        error_at = 0;
529        arg2iscount = 0;
530        arg3ispattern = 0;
531        pattern = pp = (char *)0;
532        while((opt=getopt(argc,argv,"24cinp")) != -1) {
533                switch(opt) {
534                case '2':
535                        width = 2;
536                        break;
537                case '4':
538                        width = 4;
539                        break;
540                case 'c':
541                        arg2iscount = 1;
542                        break;
543                case 'i':
544                        increment = 1;
545                        break;
546                case 'n':
547                        verify = 0;
548                        break;
549                case 'p':
550                        arg3ispattern = 1;
551                        break;
552                default:
553                        return(CMD_PARAM_ERROR);
554                }
555        }
556
557        /* Three args required...
558         * If -p is specfied, then width can only be 1...
559         */
560        if (argc != optind+3)
561                return(CMD_PARAM_ERROR);
562
563        if ((arg3ispattern) && (width != 1)) {
564                printf("Note: -p uses byte-wide access (-%d ignored)\n",width);
565                width = 1;
566        }
567
568        start = strtoul(argv[optind],(char **)0,0);
569        finish = strtoul(argv[optind+1],(char **)0,0);
570        if (arg3ispattern) {
571                pattern = pp = argv[optind+2];
572                ldata = 0;
573        }
574        else
575                ldata = strtoul(argv[optind+2],0,0);
576
577        if (arg2iscount)
578                finish = start + finish;
579        else if (start >= finish) {
580                printf("start > finish\n");
581                return(CMD_PARAM_ERROR);
582        }
583
584        err = 0;
585        switch (width) {
586        case 1:
587                cdata = (uchar) ldata;
588                for(cptr=(uchar *)start;cptr<(uchar *)finish;cptr++) {
589                        if (arg3ispattern) {
590                                if (*pp == 0)
591                                        pp = pattern;
592                                cdata = (uchar)*pp++;
593                        }
594                        *cptr = cdata;
595                        if (verify) {
596                                if (*cptr != cdata) {
597                                        err = 1;
598                                        error_at = (ulong)cptr;
599                                        break;
600                                }
601                        }
602                        cdata += increment;
603                }
604                break;
605        case 2:
606                wdata = (ushort) ldata;
607                for(wptr=(ushort *)start;wptr<(ushort *)finish;wptr++) {
608                        *wptr = wdata;
609                        if (verify) {
610                                if (*wptr != wdata) {
611                                        err = 1;
612                                        error_at = (ulong)wptr;
613                                        break;
614                                }
615                        }
616                        wdata += increment;
617                }
618                break;
619        case 4:
620                for(lptr=(ulong *)start;lptr<(ulong *)finish;lptr++) {
621                        *lptr = ldata;
622                        if (verify) {
623                                if (*lptr != ldata) {
624                                        err = 1;
625                                        error_at = (ulong)lptr;
626                                        break;
627                                }
628                        }
629                        ldata += increment;
630                }
631                break;
632        }
633        if (err) {
634                printf("Error at 0x%lx\n",error_at);
635                return(CMD_FAILURE);
636        }
637        return(CMD_SUCCESS);
638}
639#endif
640
641#if INCLUDE_SM
642
643/* Sm():
644 *      Search memory.
645 */
646
647char *SmHelp[] = {
648        "Search Memory",
649        "-[24cnqsx] {start} {finish|byte-cnt} {srchfor}",
650#if INCLUDE_VERBOSEHELP
651        "Options:",
652        " -2   short access",
653        " -4   long access",
654        " -c   arg2 is count (in bytes)",
655        " -n   srchfor_not (NA for -s or -x)",
656        " -q   quit after first search hit",
657        " -s   string srch",
658        " -x   hexblock srch",
659#endif
660                0,
661};
662
663#define SM_NORMAL               1               /* Search for 1 value */
664#define SM_STRING               2               /* Search for ascii string */
665#define SM_HEXBLOCK             3               /* Search for block of hex data */
666
667int
668Sm(int argc,char *argv[])
669{
670        ulong   start, finish;
671        int             width, opt, i, j, mode, arg2iscount, not, quit;
672        char    *srchfor, tmp;
673        uchar   *cptr, cdata, data[32];
674        ushort  *wptr, wdata;
675        ulong   *lptr, ldata;
676
677        not = 0;
678        quit = 0;
679        width = 1;
680        arg2iscount = 0;
681        mode = SM_NORMAL;
682        while((opt=getopt(argc,argv,"24cnqsx")) != -1) {
683                switch(opt) {
684                case '2':
685                        width = 2;
686                        break;
687                case '4':
688                        width = 4;
689                        break;
690                case 'c':
691                        arg2iscount = 1;
692                        break;
693                case 'n':
694                        not = 1;                                /* opposite logic SM_NORMAL only. */
695                        break;
696                case 'q':
697                        quit = 1;                               /* quit after first [no]match */
698                        break;
699                case 's':
700                        mode = SM_STRING;               /* ascii string */
701                        break;
702                case 'x':
703                        mode = SM_HEXBLOCK;             /* hex data */
704                        break;
705                default:
706                        return(CMD_PARAM_ERROR);
707                }
708        }
709
710        if (argc != optind+3)
711                return(CMD_PARAM_ERROR);
712
713        start = strtoul(argv[optind],(char **)0,0);
714        finish = strtoul(argv[optind+1],(char **)0,0);
715        if (arg2iscount)
716                finish = start + finish;
717        srchfor = argv[optind+2];
718
719        if (mode == SM_HEXBLOCK) {
720                char    *ex;
721
722                if (not)
723                        return(CMD_PARAM_ERROR);
724                ex = strpbrk(srchfor,"xX");
725                if (ex)
726                        srchfor=ex+1;
727                if (strlen(srchfor) % 2)
728                        return(CMD_PARAM_ERROR);
729                for(i=0,j=0;i<(sizeof data);i++,j+=2) {
730                        if (srchfor[j] == 0)
731                                break;
732                        tmp = srchfor[j+2];
733                        srchfor[j+2] = 0;
734                        data[i] = (uchar)strtoul(&srchfor[j],0,16);
735                        srchfor[j+2] = tmp;
736                }
737                for(cptr=(uchar *)start;cptr<(uchar *)finish;cptr++) {
738                        if (memcmp((char *)cptr,(char *)data,i) == 0) {
739                                printf("Match @ 0x%lx\n",(ulong)cptr);
740                                if (quit || gotachar())
741                                        break;
742                        }
743                }
744                return(CMD_SUCCESS);
745        }
746        else if (mode == SM_STRING) {
747                int     len;
748
749                if (not)
750                        return(CMD_PARAM_ERROR);
751                len = strlen(srchfor);
752                for(cptr=(uchar *)start;cptr<(uchar *)finish;cptr++) {
753                        if (strncmp((char *)cptr,srchfor,len) == 0) {
754                                printf("Match @ 0x%lx\n",(ulong)cptr);
755                                if (quit || gotachar())
756                                        break;
757                        }
758                }
759        }
760        else if (width == 1) {
761                cdata = (uchar)strtoul(srchfor,(char **)0,0);
762                for(cptr=(uchar *)start;cptr<(uchar *)finish;cptr++) {
763                        if (not) {
764                                if (*cptr != cdata) {
765                                        printf("Nomatch @ 0x%lx (0x%x)\n",(ulong)cptr,*cptr);
766                                        if (quit || gotachar())
767                                                break;
768                                }
769                        }
770                        else if (*cptr == cdata) {
771                                printf("Match @ 0x%lx\n",(ulong)cptr);
772                                if (quit || gotachar())
773                                        break;
774                        }
775                }
776        }
777        else if (width == 2) {
778                wdata = (ushort)strtoul(srchfor,(char **)0,0);
779                for(wptr=(ushort *)start;wptr<(ushort *)finish;wptr++) {
780                        if (not) {
781                                if (*wptr != wdata) {
782                                        printf("Nomatch @ 0x%lx (0x%x)\n",(ulong)wptr,*wptr);
783                                        if (quit || gotachar())
784                                                break;
785                                }
786                        }
787                        else if (*wptr == wdata) {
788                                printf("Match @ 0x%lx\n",(ulong)wptr);
789                                if (quit || gotachar())
790                                        break;
791                        }
792                }
793        }
794        else {
795                ldata = (ulong)strtoul(srchfor,(char **)0,0);
796                for(lptr=(ulong *)start;lptr<(ulong *)finish;lptr++) {
797                        if (not) {
798                                if (*lptr != ldata) {
799                                        printf("Nomatch @ 0x%lx (0x%lx)\n",(ulong)lptr,*lptr);
800                                        if (quit || gotachar())
801                                                break;
802                                }
803                        }
804                        else if (*lptr == ldata) {
805                                printf("Match @ 0x%lx\n",(ulong)lptr);
806                                if (quit || gotachar())
807                                        break;
808                        }
809                }
810        }
811        return(CMD_SUCCESS);
812}
813#endif
814
815#if INCLUDE_CM
816
817/* Cm():
818 *      Copy memory.
819 *
820 *      Arguments...
821 *      arg1:           source address
822 *      arg2:           destination address
823 *      arg3:           byte count
824 *
825 *      Options...
826 *      -2      access as a short.
827 *      -4      access as a long.
828 *      -f      fifo access (address does not increment).
829 *      -v      verify (only) that the range specified, is copied.
830 */
831
832char *CmHelp[] = {
833        "Copy Memory",
834        "-[24fv] {src} {dst} {byte-cnt}",
835#if INCLUDE_VERBOSEHELP
836        "Options:",
837        " -2   short access",
838        " -4   long access",
839        " -f   fifo mode",
840        " -v   verify only",
841#endif
842        0,
843};
844
845int
846Cm(int argc,char *argv[])
847{
848        ulong   src, dest, end, bytecount;
849        int     opt, width, fifo, verify, verify_failed;
850
851        width = 1;
852        fifo = verify = 0;
853        verify_failed = 0;
854        while((opt=getopt(argc,argv,"24fv")) != -1) {
855                switch(opt) {
856                case '2':
857                        width = 2;
858                        break;
859                case '4':
860                        width = 4;
861                        break;
862                case 'f':
863                        fifo = 1;
864                        break;
865                case 'v':
866                        verify = 1;
867                        break;
868                default:
869                        return(CMD_PARAM_ERROR);
870                }
871        }
872
873        if (argc != optind+3) {
874                return(CMD_PARAM_ERROR);
875        }
876        if ((verify) && (fifo)) {
877                printf("Can't verify in fifo mode\n");
878                return(CMD_FAILURE);
879        }
880
881        src = strtoul(argv[optind],(char **)0,0);
882        dest = strtoul(argv[optind+1],(char **)0,0);
883        bytecount = strtoul(argv[optind+2],(char **)0,0);
884
885        if (bytecount <= 0) {
886                printf("Invalid byte count\n");
887                return(CMD_FAILURE);
888        }
889
890        end = src+bytecount-1;
891        if (src > end) {
892                printf("Invalid range (possibly overlapping address 0?)\n");
893                return(CMD_FAILURE);
894        }
895
896        if (width == 1) {
897                while(src <= end) {
898                        if (verify) {
899                                if (*(uchar *)dest != *(uchar *)src) {
900                                        verify_failed = 1;
901                                        break;
902                                }
903                        }
904                        else
905                                *(uchar *)dest = *(uchar *)src;
906                        if (!fifo)
907                                dest++;
908                        src++;
909                }
910        }
911        else if (width == 2) {
912                while(src <= end) {
913                        if (verify) {
914                                if (*(ushort *)dest != *(ushort *)src) {
915                                        verify_failed = 1;
916                                        break;
917                                }
918                        }
919                        else
920                                *(ushort *)dest = *(ushort *)src;
921                        if (!fifo)
922                                dest += 2;
923                        src += 2;
924                }
925        }
926        else {  /* width == 4 */
927                while(src <= end) {
928                        if (verify) {
929                                if (*(ulong *)dest != *(ulong *)src) {
930                                        verify_failed = 1;
931                                        break;
932                                }
933                        }
934                        else
935                                *(ulong *)dest = *(ulong *)src;
936                        if (!fifo)
937                                dest += 4;
938                        src += 4;
939                }
940        }
941        if ((verify) && (verify_failed)) {
942                printf("Verify failed: *0x%lx != *0x%lx\n",src,dest);
943                return(CMD_FAILURE);
944        }
945        return(CMD_SUCCESS);
946}
947
948#endif
949
950#if INCLUDE_MT
951
952/* Mt():
953 *      Memory test
954 *      Walking ones and address-in-address tests for data and address bus
955 *      testing respectively.  This test, within the context of a monitor
956 *      command, has limited value.  It must assume that the memory space
957 *      from which this code is executing is sane (obviously, or the code
958 *      would not be executing) and the ram used for stack and bss must
959 *      already be somewhat useable.
960 */
961char *MtHelp[] = {
962        "Memory test",
963        "-[CcqSs:t:v] {addr} {len}",
964#if INCLUDE_VERBOSEHELP
965        "Options:",
966        " -c    continuous",
967        " -C    crc32 calculation",
968        " -q    quit on error",
969        " -S    determine size of on-board memory (see note below)",
970        " -s##  sleep ## seconds between adr-in-addr write and readback",
971        " -t##  toggle data on '##'-bit boundary (##: 32 or 64)",
972        " -v    cumulative verbosity...",
973        "       -v=<ticker>, -vv=<ticker + msg-per-error>",
974        "",
975        "Memory test is walking ones followed by address-in-address",
976        "",
977        "Note1: For normal memory test, hit any key to abort test with errors",
978        "Note2: With -S option, {addr} is the base of physical memory and",
979        "       {len} is the maximum expected size of that memory.  The",
980        "       shell variable MEMSIZE is loaded with the result.",
981#endif
982        0,
983};
984
985int
986Mt(int argc,char *argv[])
987{
988        int             errcnt, len, testaborted, opt, runcrc;
989        int             quitonerr, verbose, continuous, testtot, sizemem;
990        ulong   arg1, arg2, *start, rwsleep, togglemask;
991        ulong   *end, walker, readback, shouldbe;
992        volatile ulong *addr;
993
994        runcrc = 0;
995        sizemem = 0;
996        continuous = 0;
997        quitonerr = 0;
998        verbose = 0;
999        rwsleep = 0;
1000        togglemask = 0;
1001        while((opt=getopt(argc,argv,"cCqSs:t:v")) != -1) {
1002                switch(opt) {
1003                case 'c':
1004                        continuous = 1;
1005                        break;
1006                case 'C':
1007                        runcrc = 1;
1008                        break;
1009                case 'q':
1010                        quitonerr = 1;
1011                        break;
1012                case 'S':
1013                        sizemem = 1;
1014                        break;
1015                case 's':
1016                        rwsleep = strtoul(optarg,0,0);
1017                        break;
1018                case 't':
1019                        switch(atoi(optarg)) {
1020                                case 32:
1021                                        togglemask = 0x00000004;
1022                                        break;
1023                                case 64:
1024                                        togglemask = 0x00000008;
1025                                        break;
1026                                default:
1027                                        return(CMD_PARAM_ERROR);
1028                        }
1029                        break;
1030                case 'v':
1031                        verbose++;              /* Cumulative verbosity */
1032                        break;
1033                default:
1034                        return(CMD_PARAM_ERROR);
1035                }
1036        }
1037
1038        if (argc != optind+2)
1039                return(CMD_PARAM_ERROR);
1040
1041        arg1 = strtoul(argv[optind],(char **)0,0);
1042        arg2 = strtoul(argv[optind+1],(char **)0,0);
1043
1044        /* If -S option, then run a memory size test.
1045         * For this case, arg1 is the base and arg2 is the maximum expected
1046         * size of the on-board memory...
1047         */
1048        if (sizemem) {
1049                vulong tmp1, base, test;
1050
1051                base = arg1;
1052                test = arg2;
1053
1054                tmp1 = *(vulong *)base;
1055                *(vulong *)base = 0xDEADBEEF;
1056
1057                /* Got this algorithm from Bill Gatliff...
1058                 * Assume that memory always starts at address 0, for
1059                 * simplicity in the explanation.  What you do is write 256
1060                 * at 256MB, 128 at 128MB, 64@64MB, and so on.  When you get
1061                 * down to zero (or the smallest available memory address, if
1062                 * you want to stop sooner), you read the value stored at 0.
1063                 * That value is the size of available memory.
1064                 */
1065                while(test >= 0x100000) {
1066                        *(vulong *)(base + test) = test/0x100000;
1067                        if (verbose)
1068                                printf("*0x%lx = 0x%lx (0x%lx)\n",(base+test),test/0x100000,
1069                                        *(vulong *)(base + test));
1070                        test >>= 1;
1071                }
1072
1073                /* If the base location was not changed by the above algorithm
1074                 * then the address bus doesn't alias, so try something else...
1075                 * This time, walk up the address space starting at 0x100000
1076                 * and doubling each time until the write to the address (minus 4)
1077                 * fails.  The last successful write indicates the top of memory.
1078                 */
1079                if (*(vulong *)base == 0xDEADBEEF) {
1080                        test = 0x100000;
1081                        while(test <= arg2) {
1082                                vulong *lp = (vulong *)(base+test-sizeof(long));
1083
1084                                if (verbose)
1085                                        printf("write to 0x%lx, ",(long)lp);
1086                                *lp = 0xdeadbeef;
1087                                monDelay(100);
1088                                if (*lp != 0xdeadbeef) {
1089                                        if (verbose)
1090                                                printf("failed\n");
1091                                        break;
1092                                }
1093                                if (verbose)
1094                                        printf("passed\n");
1095                                test <<= 1;
1096                        }
1097                        test >>= 1;
1098                        printf("Size: %ld MB\n",test/0x100000);
1099                        shell_sprintf("MEMSIZE","0x%lx",test);
1100                }
1101                else {
1102                        printf("Size: %ld MB\n",*(vulong *)base);
1103                        shell_sprintf("MEMSIZE","0x%lx",*(vulong *)base * 0x100000);
1104                }
1105       
1106                *(vulong *)base = tmp1;
1107                return(CMD_SUCCESS);
1108        }
1109
1110        /* If -C option, then run a CRC32 on a specified block of memory...
1111         */
1112        if (runcrc) {
1113                ulong mtcrc;
1114
1115                mtcrc = crc32((uchar *)arg1,arg2);
1116                printf("CRC32 @ 0x%lx (0x%lx bytes) = 0x%lx\n",arg1,arg2,mtcrc);
1117                shell_sprintf("MTCRC","0x%lx",mtcrc);
1118                return(CMD_SUCCESS);
1119        }
1120
1121        arg1 &= ~0x3;   /* Word align */
1122        arg2 &= ~0x3;
1123
1124        testtot = 0;
1125        printf("Testing 0x%lx .. 0x%lx\n",arg1,arg1+arg2);
1126
1127        start = (ulong *)arg1;
1128        len = (int)arg2;
1129        testaborted = errcnt = 0;
1130
1131        while(1) {
1132                /* Walking Ones test:
1133                 * This test is done to verify that no data bits are shorted.
1134                 * Write 32 locations, each with a different bit set, then
1135                 * read back those 32 locations and make sure that bit (and only
1136                 * that bit) is set.
1137                 */
1138                walker = 1;
1139                end = start + 32;
1140                for (addr=start;addr<end;addr++) {
1141                        *addr = walker;
1142                        walker <<= 1;
1143                }
1144
1145                walker = 1;
1146                for (addr=start;addr<end;addr++) {
1147                        readback = *addr;
1148                        if (readback != walker) {
1149                                errcnt++;
1150                                if (verbose > 1)
1151                                        printf("WalkingOneErr @ x%lx: read x%lx expected x%lx\n",
1152                                                (ulong)addr,readback,walker);
1153                                if (quitonerr)
1154                                        break;
1155                        }
1156                        walker <<= 1;
1157                }
1158
1159                /* Address-in-address test:
1160                 * This test serves three purposes...
1161                 * 1. the "address-in-address" tests for stuck address bits.
1162                 * 2. the "not-address-in-address" (-t option) exercises the
1163                 *        data bus.
1164                 * 3. the sleep between read and write tests for valid memory
1165                 *    refresh in SDRAM based systems.
1166                 *
1167                 * The togglemask is used to determine at what rate the data
1168                 * should be flipped... every 32 bits or every 64 bits.
1169                 */
1170                if ((!testaborted) && ((!errcnt) || (errcnt && !quitonerr))) {
1171
1172                        /* In each 32-bit address, store either the address or the
1173                         * complimented address...
1174                         */
1175                        end = (ulong *)((int)start + len);
1176                        for (addr=start;addr<end;addr++) {
1177                                if (((ulong)addr & 0x3ffff) == 0) {
1178                                        if (gotachar()) {
1179                                                testaborted = 1;
1180                                                break;
1181                                        }
1182                                        if (verbose)
1183                                                ticktock();
1184                                }
1185       
1186                                if ((ulong)addr & togglemask)
1187                                        *addr = ~(ulong)addr;
1188                                else
1189                                        *addr = (ulong)addr;
1190                        }
1191
1192                        /* If -s is specified, then delay for the specified number
1193                         * of seconds.  This option just allows the ram to "sit"
1194                         * for a a while; hence, verifying automatic refresh in
1195                         * the case of SDRAM.
1196                         */
1197                        if (rwsleep && !testaborted) {
1198                                int i;
1199                                for(i=0;i<rwsleep;i++) {
1200                                        monDelay(1000);
1201                                        if (gotachar()) {
1202                                                testaborted = 1;
1203                                                break;
1204                                        }
1205                                        if (verbose)
1206                                                ticktock();
1207                                }
1208                        }
1209
1210                        if (testaborted)
1211                                break;
1212       
1213                        /* For each 32-bit address, verify either the address or the
1214                         * complimented address...
1215                         */
1216                        for (addr=start;addr<end;addr++) {
1217                                if (((ulong)addr & 0x3ffff) == 0) {
1218                                        if (gotachar()) {
1219                                                testaborted = 1;
1220                                                break;
1221                                        }
1222                                        if (verbose)
1223                                                ticktock();
1224                                }
1225
1226                                readback = *addr;
1227                                if ((ulong)addr & togglemask)
1228                                        shouldbe = ~(ulong)addr;
1229                                else
1230                                        shouldbe = (ulong)addr;
1231                                if (readback != shouldbe) {
1232                                        errcnt++;
1233                                        if (verbose > 1)
1234                                                printf("AdrInAdrErr @ x%lx: read x%lx expected x%lx\n",
1235                                                        (ulong)addr,readback,shouldbe);
1236                                        if (quitonerr) {
1237                                                testaborted = 1;
1238                                                break;
1239                                        }
1240                                }
1241                        }
1242                }
1243                testtot++;
1244                if (!continuous || testaborted || (errcnt && quitonerr))
1245                        break;
1246        }
1247
1248
1249        printf("Found %d errors", errcnt);
1250        if (continuous && testaborted)
1251                printf(" after %d test loops",testtot);
1252        printf(".\n");
1253
1254        if (errcnt)
1255                return(CMD_FAILURE);
1256        else
1257                return(CMD_SUCCESS);
1258}
1259#endif
Note: See TracBrowser for help on using the repository browser.