OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [redboot/] [current/] [src/] [fconfig.c] - Blame information for rev 786

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 786 skrzyp
//==========================================================================
2
//
3
//      fconfig.c
4
//
5
//      RedBoot - persistent data storage support (FLASH or EEPROM)
6
//
7
//==========================================================================
8
// ####ECOSGPLCOPYRIGHTBEGIN####                                            
9
// -------------------------------------------                              
10
// This file is part of eCos, the Embedded Configurable Operating System.   
11
// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2008 Free Software Foundation, Inc.
12
//
13
// eCos is free software; you can redistribute it and/or modify it under    
14
// the terms of the GNU General Public License as published by the Free     
15
// Software Foundation; either version 2 or (at your option) any later      
16
// version.                                                                 
17
//
18
// eCos is distributed in the hope that it will be useful, but WITHOUT      
19
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or    
20
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License    
21
// for more details.                                                        
22
//
23
// You should have received a copy of the GNU General Public License        
24
// along with eCos; if not, write to the Free Software Foundation, Inc.,    
25
// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.            
26
//
27
// As a special exception, if other files instantiate templates or use      
28
// macros or inline functions from this file, or you compile this file      
29
// and link it with other works to produce a work based on this file,       
30
// this file does not by itself cause the resulting work to be covered by   
31
// the GNU General Public License. However the source code for this file    
32
// must still be made available in accordance with section (3) of the GNU   
33
// General Public License v2.                                               
34
//
35
// This exception does not invalidate any other reasons why a work based    
36
// on this file might be covered by the GNU General Public License.         
37
// -------------------------------------------                              
38
// ####ECOSGPLCOPYRIGHTEND####                                              
39
//==========================================================================
40
//#####DESCRIPTIONBEGIN####
41
//
42
// Author(s):    gthomas
43
// Contributors: gthomas, tkoeller
44
// Date:         2000-07-28
45
// Purpose:      
46
// Description:  
47
//              
48
// This code is part of RedBoot (tm).
49
//
50
//####DESCRIPTIONEND####
51
//
52
//==========================================================================
53
 
54
#include <redboot.h>
55
#include <cyg/io/flash.h>
56
#ifdef CYGOPT_REDBOOT_FIS
57
#include <fis.h>
58
#endif
59
 
60
#ifdef CYGSEM_REDBOOT_FLASH_COMBINED_FIS_AND_CONFIG
61
// Note horrid intertwining of functions, to save precious FLASH
62
externC void fis_read_directory(void);
63
externC void fis_update_directory(void);
64
#endif
65
 
66
#ifdef CYGHWR_REDBOOT_FLASH_CONFIG_MEDIA_EEPROM
67
externC void write_eeprom(void *buf, int len);
68
externC void read_eeprom(void *buf, int len);
69
#endif
70
 
71
#ifdef CYGSEM_REDBOOT_PLF_ESA_VALIDATE
72
externC bool cyg_plf_redboot_esa_validate(unsigned char *val);
73
#endif
74
 
75
#ifdef CYGHWR_REDBOOT_FLASH_CONFIG_MEDIA_FLASH
76
externC int do_flash_init(void);
77
#include <cyg/io/flash.h>
78
#endif
79
 
80
// Round a quantity up
81
#define _rup(n,s) ((((n)+(s-1))/s)*s)
82
 
83
#include <flash_config.h>
84
 
85
// Configuration data, saved in FLASH, used to set/update RedBoot
86
// normal "configuration" data items.
87
struct _config *config, *backup_config;
88
 
89
// Local data used by these routines
90
#ifdef CYGHWR_REDBOOT_FLASH_CONFIG_MEDIA_FLASH
91
extern cyg_flashaddr_t flash_start, flash_end;
92
extern size_t flash_block_size;
93
extern cyg_uint32 flash_num_blocks;
94
extern int __flash_init;
95
#ifdef CYGOPT_REDBOOT_FIS
96
extern void *fis_work_block;
97
extern cyg_flashaddr_t fis_addr;
98
extern int fisdir_size;  // Size of FIS directory.
99
#endif
100
#ifdef CYGSEM_REDBOOT_FLASH_CONFIG_READONLY_FALLBACK
101
static struct _config  *readonly_config;
102
#endif
103
cyg_flashaddr_t cfg_base;    // Location in Flash of config data
104
size_t  cfg_size;            // Length of config data - rounded to Flash block size
105
#endif // FLASH MEDIA
106
 
107
// Prototypes for local functions
108
static char *flash_lookup_config(char *key);
109
 
110
static bool config_ok;
111
 
112
#define CONFIG_KEY1    0x0BADFACE
113
#define CONFIG_KEY2    0xDEADDEAD
114
 
115
#define CONFIG_DONE    0
116
#define CONFIG_ABORT  -1
117
#define CONFIG_CHANGED 1
118
#define CONFIG_OK      2
119
#define CONFIG_BACK    3
120
#define CONFIG_BAD     4
121
 
122
// Note: the following options are related.  If 'boot_script' is false, then
123
// the other values are used in the configuration.  Because of the way
124
// that configuration tables are generated, they should have names which
125
// are related.  The configuration options will show up lexicographically
126
// ordered, thus the peculiar naming.
127
RedBoot_config_option("Run script at boot",
128
                      boot_script,
129
                      ALWAYS_ENABLED, true,
130
                      CONFIG_BOOL,
131
                      false
132
    );
133
RedBoot_config_option("Boot script",
134
                      boot_script_data,
135
                      "boot_script", true,
136
                      CONFIG_SCRIPT,
137
                      ""
138
    );
139
// Some preprocessor magic for building the [constant] prompt string
140
#define __cat(s1,c2,s3) s1 #c2 s3
141
#define _cat(s1,c2,s3) __cat(s1,c2,s3)
142
RedBoot_config_option(_cat("Boot script timeout (",
143
                           CYGNUM_REDBOOT_BOOT_SCRIPT_TIMEOUT_RESOLUTION,
144
                           "ms resolution)"),
145
                      boot_script_timeout,
146
                      "boot_script", true,
147
                      CONFIG_INT,
148
 
149
    );
150
#undef __cat
151
#undef _cat
152
 
153
#ifdef CYGSEM_REDBOOT_VARIABLE_BAUD_RATE
154
RedBoot_config_option("Console baud rate",
155
                      console_baud_rate,
156
                      ALWAYS_ENABLED, true,
157
                      CONFIG_INT,
158
                      CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD
159
    );
160
#endif
161
 
162
CYG_HAL_TABLE_BEGIN( __CONFIG_options_TAB__, RedBoot_config_options);
163
CYG_HAL_TABLE_END( __CONFIG_options_TAB_END__, RedBoot_config_options);
164
 
165
extern struct config_option __CONFIG_options_TAB__[], __CONFIG_options_TAB_END__[];
166
 
167
// 
168
// Layout of config data
169
// Each data item is variable length, with the name, type and dependencies
170
// encoded into the object.
171
//  offset   contents
172
//       0   data type
173
//       1   length of name (N)
174
//       2   enable sense
175
//       3   length of enable key (M)
176
//       4   key name
177
//     N+4   enable key
178
//   M+N+4   data value
179
//
180
 
181
#define CONFIG_OBJECT_TYPE(dp)          (dp)[0]
182
#define CONFIG_OBJECT_KEYLEN(dp)        (dp)[1]
183
#define CONFIG_OBJECT_ENABLE_SENSE(dp)  (dp)[2]
184
#define CONFIG_OBJECT_ENABLE_KEYLEN(dp) (dp)[3]
185
#define CONFIG_OBJECT_KEY(dp)           ((dp)+4)
186
#define CONFIG_OBJECT_ENABLE_KEY(dp)    ((dp)+4+CONFIG_OBJECT_KEYLEN(dp))
187
#define CONFIG_OBJECT_VALUE(dp)         ((dp)+4+CONFIG_OBJECT_KEYLEN(dp)+CONFIG_OBJECT_ENABLE_KEYLEN(dp))
188
 
189
#define LIST_OPT_LIST_ONLY (1)
190
#define LIST_OPT_NICKNAMES (2)
191
#define LIST_OPT_FULLNAMES (4)
192
#define LIST_OPT_DUMBTERM  (8)
193
 
194
static void config_init(void);
195
static int  config_length(int type);
196
 
197
// Change endianness of config data
198
void
199
conf_endian_fixup(void *ptr)
200
{
201
#ifdef REDBOOT_FLASH_REVERSE_BYTEORDER
202
    struct _config *p = (struct _config *)ptr;
203
    char *dp = p->config_data;
204
    void *val_ptr;
205
    int len;
206
    cyg_uint16 u16;
207
    cyg_uint32 u32;
208
 
209
    p->len = CYG_SWAP32(p->len);
210
    p->key1 = CYG_SWAP32(p->key1);
211
    p->key2 = CYG_SWAP32(p->key2);
212
    p->cksum = CYG_SWAP32(p->cksum);
213
 
214
    while (dp < &p->config_data[sizeof(config->config_data)]) {
215
        len = 4 + CONFIG_OBJECT_KEYLEN(dp) + CONFIG_OBJECT_ENABLE_KEYLEN(dp) +
216
            config_length(CONFIG_OBJECT_TYPE(dp));
217
        val_ptr = (void *)CONFIG_OBJECT_VALUE(dp);
218
 
219
        switch (CONFIG_OBJECT_TYPE(dp)) {
220
            // Note: the data may be unaligned in the configuration data
221
        case CONFIG_BOOL:
222
            if (sizeof(bool) == 2) {
223
                memcpy(&u16, val_ptr, 2);
224
                u16 = CYG_SWAP16(u16);
225
                memcpy(val_ptr, &u16, 2);
226
            } else if (sizeof(bool) == 4) {
227
                memcpy(&u32, val_ptr, 4);
228
                u32 = CYG_SWAP32(u32);
229
                memcpy(val_ptr, &u32, 4);
230
            }
231
            break;
232
        case CONFIG_INT:
233
            if (sizeof(unsigned long) == 2) {
234
                memcpy(&u16, val_ptr, 2);
235
                u16 = CYG_SWAP16(u16);
236
                memcpy(val_ptr, &u16, 2);
237
            } else if (sizeof(unsigned long) == 4) {
238
                memcpy(&u32, val_ptr, 4);
239
                u32 = CYG_SWAP32(u32);
240
                memcpy(val_ptr, &u32, 4);
241
            }
242
            break;
243
        }
244
 
245
        dp += len;
246
    }
247
#endif
248
}
249
 
250
static int
251
get_config(char *dp, char *title, int list_opt, char *newvalue )
252
{
253
    char line[256], hold_line[256], *sp, *lp;
254
    int ret;
255
    bool hold_bool_val, new_bool_val, enable;
256
    unsigned long hold_int_val, new_int_val;
257
#ifdef CYGPKG_REDBOOT_NETWORKING
258
    in_addr_t hold_ip_val, new_ip_val;
259
    enet_addr_t hold_esa_val;
260
    int esa_ptr;
261
    char *esp;
262
#endif
263
    void *val_ptr;
264
    int type, script_len;
265
 
266
    if (CONFIG_OBJECT_ENABLE_KEYLEN(dp)) {
267
        flash_get_config(CONFIG_OBJECT_ENABLE_KEY(dp), &enable, CONFIG_BOOL);
268
        if (((bool)CONFIG_OBJECT_ENABLE_SENSE(dp) && !enable) ||
269
            (!(bool)CONFIG_OBJECT_ENABLE_SENSE(dp) && enable)) {
270
            return CONFIG_OK;  // Disabled field
271
        }
272
    }
273
    lp = line;  *lp = '\0';
274
    val_ptr = (void *)CONFIG_OBJECT_VALUE(dp);
275
    if (LIST_OPT_NICKNAMES & list_opt)
276
        diag_printf("%s: ", CONFIG_OBJECT_KEY(dp));
277
    if (LIST_OPT_FULLNAMES & list_opt) {
278
        if (title != (char *)NULL) {
279
            diag_printf("%s: ", title);
280
        } else {
281
            diag_printf("%s: ", CONFIG_OBJECT_KEY(dp));
282
        }
283
    }
284
    switch (type = CONFIG_OBJECT_TYPE(dp)) {
285
    case CONFIG_BOOL:
286
        memcpy(&hold_bool_val, val_ptr, sizeof(bool));
287
        lp += diag_sprintf(lp, "%s", hold_bool_val ? "true" : "false");
288
        break;
289
    case CONFIG_INT:
290
        memcpy(&hold_int_val, val_ptr, sizeof(unsigned long));
291
        lp += diag_sprintf(lp, "%ld", hold_int_val);
292
        break;
293
#ifdef CYGPKG_REDBOOT_NETWORKING
294
    case CONFIG_IP:
295
        lp += diag_sprintf(lp, "%s", inet_ntoa((in_addr_t *)val_ptr));
296
        if (0 == strcmp("0.0.0.0", line) && !(LIST_OPT_LIST_ONLY & list_opt)) {
297
            // then we have a deeply unhelpful starting text - kill it off
298
            // (unless we are just listing all values)
299
            lp = line;  *lp = '\0';
300
        }
301
        break;
302
    case CONFIG_ESA:
303
        for (esa_ptr = 0;  esa_ptr < sizeof(enet_addr_t);  esa_ptr++) {
304
            lp += diag_sprintf(lp, "0x%02X", ((unsigned char *)val_ptr)[esa_ptr]);
305
            if (esa_ptr < (sizeof(enet_addr_t)-1)) lp += diag_sprintf(lp, ":");
306
        }
307
        break;
308
#if defined(CYGHWR_NET_DRIVERS) && (CYGHWR_NET_DRIVERS > 1)
309
    case CONFIG_NETPORT:
310
        lp += diag_sprintf(lp, "%s", (unsigned char *)val_ptr);
311
        break;
312
#endif
313
#endif
314
    case CONFIG_STRING:
315
        lp += diag_sprintf(lp, "%s", (unsigned char *)val_ptr);
316
        break;
317
    case CONFIG_SCRIPT:
318
        diag_printf("\n");
319
        sp = lp = (char *)val_ptr;
320
        while (*sp) {
321
            while (*lp != '\n') lp++;
322
            *lp = '\0';
323
            diag_printf(".. %s\n", sp);
324
            *lp++ = '\n';
325
            sp = lp;
326
        }
327
        break;
328
    }
329
    if (LIST_OPT_LIST_ONLY & list_opt) {
330
        diag_printf("%s\n", line);
331
        return CONFIG_OK;
332
    }
333
    if (type != CONFIG_SCRIPT) {
334
        if (NULL != newvalue) {
335
            ret = strlen(newvalue);
336
            if (ret > sizeof(line))
337
                return CONFIG_BAD;
338
            strcpy(hold_line, line); // Hold the old value for comparison
339
            strcpy(line, newvalue);
340
            diag_printf("Setting to %s\n", newvalue);
341
        } else {
342
            // read from terminal
343
            strcpy(hold_line, line);
344
            if (LIST_OPT_DUMBTERM & list_opt) {
345
                diag_printf( (CONFIG_STRING == type ?
346
                              "%s > " :
347
                              "%s ? " ), line);
348
                *line = '\0';
349
            }
350
            ret = _rb_gets_preloaded(line, sizeof(line), 0);
351
        }
352
        if (ret < 0) return CONFIG_ABORT;
353
        // empty input - leave value untouched (else DNS goes away for a
354
        // minute to try to look it up) but we must accept empty value for strings.
355
        if (0 == line[0] && CONFIG_STRING != type) return CONFIG_OK;
356
        if (strcmp(line, hold_line) == 0) return CONFIG_OK;  // Just a CR - leave value untouched
357
        lp = &line[strlen(line)-1];
358
        if (*lp == '.') return CONFIG_DONE;
359
        if (*lp == '^') return CONFIG_BACK;
360
    }
361
    switch (type) {
362
    case CONFIG_BOOL:
363
        memcpy(&hold_bool_val, val_ptr, sizeof(bool));
364
        if (!parse_bool(line, &new_bool_val)) {
365
            return CONFIG_BAD;
366
        }
367
        if (hold_bool_val != new_bool_val) {
368
            memcpy(val_ptr, &new_bool_val, sizeof(bool));
369
            return CONFIG_CHANGED;
370
        } else {
371
            return CONFIG_OK;
372
        }
373
        break;
374
    case CONFIG_INT:
375
        memcpy(&hold_int_val, val_ptr, sizeof(unsigned long));
376
        if (!parse_num(line, &new_int_val, 0, 0)) {
377
            return CONFIG_BAD;
378
        }
379
        if (hold_int_val != new_int_val) {
380
            memcpy(val_ptr, &new_int_val, sizeof(unsigned long));
381
            return CONFIG_CHANGED;
382
        } else {
383
            return CONFIG_OK;
384
        }
385
        break;
386
#ifdef CYGPKG_REDBOOT_NETWORKING
387
    case CONFIG_IP:
388
        memcpy(&hold_ip_val, val_ptr, sizeof(in_addr_t));
389
        if (!_gethostbyname(line, &new_ip_val)) {
390
            return CONFIG_BAD;
391
        }
392
        if (hold_ip_val.s_addr != new_ip_val.s_addr) {
393
            memcpy(val_ptr, &new_ip_val, sizeof(in_addr_t));
394
            return CONFIG_CHANGED;
395
        } else {
396
            return CONFIG_OK;
397
        }
398
        break;
399
    case CONFIG_ESA:
400
        memcpy(&hold_esa_val, val_ptr, sizeof(enet_addr_t));
401
        esp = line;
402
        for (esa_ptr = 0;  esa_ptr < sizeof(enet_addr_t);  esa_ptr++) {
403
            unsigned long esa_byte;
404
            if (!parse_num(esp, &esa_byte, &esp, ":")) {
405
                memcpy(val_ptr, &hold_esa_val, sizeof(enet_addr_t));
406
                return CONFIG_BAD;
407
            }
408
            ((unsigned char *)val_ptr)[esa_ptr] = esa_byte;
409
        }
410
#ifdef CYGSEM_REDBOOT_PLF_ESA_VALIDATE
411
        if (!cyg_plf_redboot_esa_validate(val_ptr)) {
412
            memcpy(val_ptr, &hold_esa_val, sizeof(enet_addr_t));
413
            return CONFIG_BAD;
414
        }
415
#endif
416
        return CONFIG_CHANGED;
417
        break;
418
#if defined(CYGHWR_NET_DRIVERS) && (CYGHWR_NET_DRIVERS > 1)
419
    case CONFIG_NETPORT:
420
        if (strlen(line) >= MAX_STRING_LENGTH || net_devindex(line) < 0) {
421
            int index;
422
            const char *name;
423
            diag_printf("Sorry, Port name must be one of:\n");
424
            for (index = 0; (name = net_devname(index)) != NULL; index++)
425
                diag_printf("    %s\n", name);
426
            return CONFIG_BAD;
427
        }
428
        strcpy((unsigned char *)val_ptr, line);
429
        break;
430
#endif
431
#endif
432
    case CONFIG_SCRIPT:
433
        // Assume it always changes
434
        sp = (char *)val_ptr;
435
        script_len = 0;
436
        diag_printf("Enter script, terminate with empty line\n");
437
        while (true) {
438
            *sp = '\0';
439
            diag_printf(">> ");
440
            ret = _rb_gets(line, sizeof(line), 0);
441
            if (ret < 0) return CONFIG_ABORT;
442
            if (strlen(line) == 0) break;
443
            script_len += strlen(line) + 1;
444
            if (script_len > config_length(CONFIG_SCRIPT)) {
445
                diag_printf("script longer than %d not allowed!\n",
446
                                config_length(CONFIG_SCRIPT));
447
                return CONFIG_ABORT;
448
            }
449
            lp = line;
450
            while (*lp) {
451
                *sp++ = *lp++;
452
            }
453
            *sp++ = '\n';
454
        }
455
        break;
456
    case CONFIG_STRING:
457
        if (strlen(line) >= MAX_STRING_LENGTH) {
458
            diag_printf("Sorry, value is too long\n");
459
            return CONFIG_BAD;
460
        }
461
        strcpy((char *)val_ptr, line);
462
        break;
463
    }
464
    return CONFIG_CHANGED;
465
}
466
 
467
//
468
// Manage configuration information with the FLASH
469
//
470
 
471
static int
472
config_length(int type)
473
{
474
    switch (type) {
475
    case CONFIG_BOOL:
476
        return sizeof(bool);
477
    case CONFIG_INT:
478
        return sizeof(unsigned long);
479
#ifdef CYGPKG_REDBOOT_NETWORKING
480
    case CONFIG_IP:
481
        return sizeof(in_addr_t);
482
    case CONFIG_ESA:
483
        // Would like this to be sizeof(enet_addr_t), but that causes much
484
        // pain since it fouls the alignment of data which follows.
485
        return 8;
486
#if defined(CYGHWR_NET_DRIVERS) && (CYGHWR_NET_DRIVERS > 1)
487
    case CONFIG_NETPORT:
488
        return MAX_STRING_LENGTH;
489
#endif
490
#endif
491
    case CONFIG_STRING:
492
        return MAX_STRING_LENGTH;
493
    case CONFIG_SCRIPT:
494
        return MAX_SCRIPT_LENGTH;
495
    default:
496
        return 0;
497
    }
498
}
499
 
500
static cmd_fun do_flash_config;
501
RedBoot_cmd("fconfig",
502
            "Manage configuration kept in FLASH memory",
503
            "[-i] [-l] [-n] [-f] [-d] | [-d] nickname [value]",
504
            do_flash_config
505
    );
506
 
507
static void
508
do_flash_config(int argc, char *argv[])
509
{
510
    bool need_update = false;
511
    struct config_option *optend = __CONFIG_options_TAB_END__;
512
    struct config_option *opt = __CONFIG_options_TAB__;
513
    struct option_info opts[5];
514
    bool list_only;
515
    bool nicknames;
516
    bool fullnames;
517
    bool dumbterminal;
518
    int list_opt = 0;
519
    char *dp;
520
    int len, ret;
521
    char *title;
522
    char *onlyone = NULL;
523
    char *onevalue = NULL;
524
    bool doneone = false;
525
    bool init = false;
526
 
527
#ifdef CYGHWR_REDBOOT_FLASH_CONFIG_MEDIA_FLASH
528
    if (!__flash_init) {
529
        diag_printf("Sorry, no FLASH memory is available\n");
530
        return;
531
    }
532
#endif
533
    memcpy(backup_config, config, sizeof(struct _config));
534
    script = NULL;
535
 
536
    init_opts(&opts[0], 'l', false, OPTION_ARG_TYPE_FLG,
537
              (void *)&list_only, (bool *)0, "list configuration only");
538
    init_opts(&opts[1], 'n', false, OPTION_ARG_TYPE_FLG,
539
              (void *)&nicknames, (bool *)0, "show nicknames");
540
    init_opts(&opts[2], 'f', false, OPTION_ARG_TYPE_FLG,
541
              (void *)&fullnames, (bool *)0, "show full names");
542
    init_opts(&opts[3], 'i', false, OPTION_ARG_TYPE_FLG,
543
              (void *)&init, (bool *)0, "initialize configuration database");
544
    init_opts(&opts[4], 'd', false, OPTION_ARG_TYPE_FLG,
545
              (void *)&dumbterminal, (bool *)0, "dumb terminal: no clever edits");
546
 
547
    // First look to see if we are setting or getting a single option
548
    // by just quoting its nickname
549
    if ( (2 == argc && '-' != argv[1][0]) ||
550
         (3 == argc && '-' != argv[1][0] && '-' != argv[2][0])) {
551
        // then the command was "fconfig foo [value]"
552
        onlyone = argv[1];
553
        onevalue = (3 == argc) ? argv[2] : NULL;
554
        list_opt = LIST_OPT_NICKNAMES;
555
    }
556
    // Next see if we are setting or getting a single option with a dumb
557
    // terminal invoked, ie. no line editing.
558
    else if (3 == argc &&
559
             '-' == argv[1][0] && 'd' == argv[1][1] && 0 == argv[1][2] &&
560
             '-' != argv[2][0]) {
561
        // then the command was "fconfig -d foo"
562
        onlyone = argv[2];
563
        onevalue = NULL;
564
        list_opt = LIST_OPT_NICKNAMES | LIST_OPT_DUMBTERM;
565
    }
566
    else {
567
        if (!scan_opts(argc, argv, 1, opts, 5, 0, 0, ""))
568
            return;
569
        list_opt |= list_only ? LIST_OPT_LIST_ONLY : 0;
570
        list_opt |= nicknames ? LIST_OPT_NICKNAMES : LIST_OPT_FULLNAMES;
571
        list_opt |= fullnames ? LIST_OPT_FULLNAMES : 0;
572
        list_opt |= dumbterminal ? LIST_OPT_DUMBTERM : 0;
573
    }
574
 
575
    if (init && verify_action("Initialize non-volatile configuration")) {
576
        config_init();
577
        need_update = true;
578
    }
579
 
580
    dp = &config->config_data[0];
581
    while (dp < &config->config_data[sizeof(config->config_data)]) {
582
        if (CONFIG_OBJECT_TYPE(dp) == CONFIG_EMPTY) {
583
            break;
584
        }
585
        len = 4 + CONFIG_OBJECT_KEYLEN(dp) + CONFIG_OBJECT_ENABLE_KEYLEN(dp) +
586
            config_length(CONFIG_OBJECT_TYPE(dp));
587
        // Provide a title for well known [i.e. builtin] objects
588
        title = (char *)NULL;
589
        opt = __CONFIG_options_TAB__;
590
        while (opt != optend) {
591
            if (strcmp(opt->key, CONFIG_OBJECT_KEY(dp)) == 0) {
592
                title = opt->title;
593
                break;
594
            }
595
            opt++;
596
        }
597
        if ( onlyone && 0 != strcmp(CONFIG_OBJECT_KEY(dp), onlyone) )
598
            ret = CONFIG_OK; // skip this entry
599
        else {
600
            doneone = true;
601
            ret = get_config(dp, title, list_opt, onevalue); // do this opt
602
        }
603
        switch (ret) {
604
        case CONFIG_DONE:
605
            goto done;
606
        case CONFIG_ABORT:
607
            memcpy(config, backup_config, sizeof(struct _config));
608
            return;
609
        case CONFIG_CHANGED:
610
            need_update = true;
611
        case CONFIG_OK:
612
            dp += len;
613
            break;
614
        case CONFIG_BACK:
615
            dp = &config->config_data[0];
616
            continue;
617
        case CONFIG_BAD:
618
            // Nothing - make him do it again
619
            diag_printf ("** invalid entry\n");
620
            onevalue = NULL; // request a good value be typed in - or abort/whatever
621
        }
622
    }
623
 
624
 done:
625
    if (NULL != onlyone && !doneone) {
626
#ifdef CYGSEM_REDBOOT_ALLOW_DYNAMIC_FLASH_CONFIG_DATA
627
        if (verify_action("** entry '%s' not found - add", onlyone)) {
628
            struct config_option opt;
629
            diag_printf("Trying to add value\n");
630
        }
631
#else
632
        diag_printf("** entry '%s' not found\n", onlyone);
633
#endif
634
    }
635
    if (!need_update)
636
        return;
637
    flash_write_config(true);
638
}
639
 
640
 
641
#ifdef CYGSEM_REDBOOT_FLASH_ALIASES
642
static cmd_fun do_alias;
643
RedBoot_cmd("alias",
644
            "Manage aliases kept in FLASH memory",
645
            "name [value]",
646
            do_alias
647
    );
648
 
649
static void
650
make_alias(char *alias, char *name)
651
{
652
    diag_sprintf(alias, "alias/%s", name);
653
}
654
 
655
static void
656
do_alias(int argc, char *argv[])
657
{
658
    char name[80];
659
    char *val;
660
    struct config_option opt;
661
 
662
    switch (argc) {
663
    case 2:
664
        make_alias(name, argv[1]);
665
        if (flash_get_config(name, &val, CONFIG_STRING)) {
666
            diag_printf("'%s' = '%s'\n", argv[1], val);
667
        } else {
668
            diag_printf("'%s' not found\n", argv[1]);
669
        }
670
        break;
671
    case 3:
672
        if (strlen(argv[2]) >= MAX_STRING_LENGTH) {
673
            diag_printf("Sorry, value is too long\n");
674
            break;
675
        }
676
        make_alias(name, argv[1]);
677
        opt.type = CONFIG_STRING;
678
        opt.enable = (char *)0;
679
        opt.enable_sense = 1;
680
        opt.key = name;
681
        opt.dflt = (CYG_ADDRESS)argv[2];
682
        flash_add_config(&opt, true);
683
        break;
684
    default:
685
        diag_printf("usage: alias name [value]\n");
686
    }
687
}
688
 
689
// Lookup an alias. First try plain string aliases. If that fails try
690
// other types so allowing access to all configured values. This allows
691
// for alias (macro) expansion of normal 'fconfig' data, such as the
692
// board IP address.
693
char *
694
flash_lookup_alias(char *alias, char *alias_buf)
695
{
696
    char name[80];
697
    char *val;
698
    char * dp;
699
    void *val_ptr;
700
    int type;
701
    bool hold_bool_val;
702
    long hold_long_val;
703
#ifdef CYGPKG_REDBOOT_NETWORKING
704
    int esa_ptr;
705
#endif
706
 
707
    make_alias(name, alias);
708
    if (flash_get_config(name, &val, CONFIG_STRING)) {
709
        return val;
710
    } else {
711
        dp = flash_lookup_config(alias);
712
        if (dp) {
713
            val_ptr = (void *)CONFIG_OBJECT_VALUE(dp);
714
            switch (type = CONFIG_OBJECT_TYPE(dp)) {
715
            case CONFIG_BOOL:
716
                memcpy(&hold_bool_val, val_ptr, sizeof(bool));
717
                diag_sprintf(alias_buf, "%s", hold_bool_val ? "true" : "false");
718
                break;
719
            case CONFIG_INT:
720
                memcpy(&hold_long_val, val_ptr, sizeof(unsigned long));
721
                diag_sprintf(alias_buf,"%ld", hold_long_val);
722
                break;
723
#ifdef CYGPKG_REDBOOT_NETWORKING
724
            case CONFIG_IP:
725
                diag_sprintf(alias_buf,"%s", inet_ntoa((in_addr_t *)val_ptr));
726
                break;
727
            case CONFIG_ESA:
728
                for (esa_ptr = 0;  esa_ptr < sizeof(enet_addr_t);  esa_ptr++) {
729
                    diag_sprintf(alias_buf+(3*esa_ptr), "0x%02X", ((unsigned char *)val_ptr)[esa_ptr]);
730
                    if (esa_ptr < (sizeof(enet_addr_t)-1)) diag_printf(":");
731
                }
732
                break;
733
#endif
734
            case CONFIG_SCRIPT:
735
                return (char *) val_ptr;
736
                break;
737
            default:
738
                return (char *)NULL;
739
            }
740
            return alias_buf;
741
        }
742
        return (char *)NULL;
743
    }
744
}
745
 
746
#endif //  CYGSEM_REDBOOT_FLASH_ALIASES
747
 
748
cyg_uint32
749
flash_crc(struct _config *conf)
750
{
751
    cyg_uint32 crc;
752
#ifdef REDBOOT_FLASH_REVERSE_BYTEORDER
753
    int        swabbed = 0;
754
 
755
    if (conf->key1 == CONFIG_KEY1 && conf->key2 == CONFIG_KEY2) {
756
        swabbed = 1;
757
        conf_endian_fixup(conf);
758
    }
759
#endif
760
 
761
    crc = cyg_crc32((unsigned char *)conf, sizeof(*conf)-sizeof(conf->cksum));
762
 
763
#ifdef REDBOOT_FLASH_REVERSE_BYTEORDER
764
    if (swabbed)
765
        conf_endian_fixup(conf);
766
#endif
767
    return crc;
768
}
769
 
770
//
771
// Write the in-memory copy of the configuration data to the flash device.
772
//
773
void
774
flash_write_config(bool prompt)
775
{
776
#if defined(CYGHWR_REDBOOT_FLASH_CONFIG_MEDIA_FLASH)
777
#if !defined(CYGSEM_REDBOOT_FLASH_COMBINED_FIS_AND_CONFIG)
778
    cyg_flashaddr_t err_addr;
779
    int stat;
780
#endif
781
#endif
782
 
783
    config->len = sizeof(struct _config);
784
    config->key1 = CONFIG_KEY1;
785
    config->key2 = CONFIG_KEY2;
786
    config->cksum = flash_crc(config);
787
    if (!prompt || verify_action("Update RedBoot non-volatile configuration")) {
788
#ifdef CYGHWR_REDBOOT_FLASH_CONFIG_MEDIA_FLASH
789
#ifdef CYGSEM_REDBOOT_FLASH_COMBINED_FIS_AND_CONFIG
790
        fis_read_directory();
791
        fis_update_directory();
792
#else 
793
#ifdef CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL
794
        // Insure [quietly] that the config page is unlocked before trying to update
795
        cyg_flash_unlock(cfg_base, cfg_size, &err_addr);
796
#endif
797
        if ((stat = cyg_flash_erase(cfg_base, cfg_size, &err_addr)) != 0) {
798
            diag_printf("   initialization failed at %p: %s\n", (void*)err_addr,
799
                        cyg_flash_errmsg(stat));
800
        } else {
801
            conf_endian_fixup(config);
802
            if ((stat = cyg_flash_program(cfg_base, (void *)config, sizeof(struct _config),
803
                                      &err_addr)) != 0) {
804
                diag_printf("Error writing config data at %p: %s\n",
805
                            (void*)err_addr, cyg_flash_errmsg(stat));
806
            }
807
            conf_endian_fixup(config);
808
        }
809
#ifdef CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL
810
        // Insure [quietly] that the config data is locked after the update
811
        cyg_flash_lock(cfg_base, cfg_size, &err_addr);
812
#endif
813
#endif // CYGSEM_REDBOOT_FLASH_COMBINED_FIS_AND_CONFIG
814
#else  // CYGHWR_REDBOOT_FLASH_CONFIG_MEDIA_FLASH
815
        write_eeprom(config, sizeof(struct _config));  // into 'config'
816
#endif
817
    }
818
}
819
 
820
//
821
// Find the configuration entry for a particular key
822
//
823
static char *
824
flash_lookup_config(char *key)
825
{
826
    char *dp;
827
    int len;
828
 
829
    if (!config_ok) return NULL;
830
 
831
    dp = &config->config_data[0];
832
    while (dp < &config->config_data[sizeof(config->config_data)]) {
833
        len = 4 + CONFIG_OBJECT_KEYLEN(dp) + CONFIG_OBJECT_ENABLE_KEYLEN(dp) +
834
            config_length(CONFIG_OBJECT_TYPE(dp));
835
        if (strcmp(key, CONFIG_OBJECT_KEY(dp)) == 0) {
836
            return dp;
837
        }
838
        // Sanity check to prevent RedBoot going into an infinite loop when
839
        // there is something dodgy in the fconfig area.
840
        if (len <= 0) {
841
            break;
842
        }
843
        dp += len;
844
    }
845
//    diag_printf("Can't find config data for '%s'\n", key);
846
    return NULL;
847
}
848
 
849
//
850
// Enumerate the keys from the configuration
851
//
852
bool
853
flash_next_key(char *key, int keylen, int *type, int *offset)
854
{
855
    char *dp;
856
    int len;
857
 
858
    if (!config_ok) return false;
859
    if ((*offset < 0) || (*offset >= MAX_CONFIG_DATA)) return false;
860
 
861
    dp = &config->config_data[*offset];
862
    if ((*type = CONFIG_OBJECT_TYPE(dp)) == CONFIG_EMPTY) return false;
863
    if ((len = CONFIG_OBJECT_KEYLEN(dp)) > keylen) return false;
864
    memcpy(key, CONFIG_OBJECT_KEY(dp), len);
865
    *offset += 4 + CONFIG_OBJECT_KEYLEN(dp) + CONFIG_OBJECT_ENABLE_KEYLEN(dp) +
866
        config_length(CONFIG_OBJECT_TYPE(dp));
867
    return true;
868
}
869
 
870
//
871
// Retrieve a data object from the data base (in memory copy)
872
//
873
bool
874
flash_get_config(char *key, void *val, int type)
875
{
876
    char *dp;
877
    void *val_ptr;
878
#ifdef CYGSEM_REDBOOT_FLASH_CONFIG_READONLY_FALLBACK
879
    struct _config *save_config = 0;
880
    bool res;
881
#endif
882
 
883
    if (!config_ok) return false;
884
 
885
    if ((dp = flash_lookup_config(key)) != NULL) {
886
        if (CONFIG_OBJECT_TYPE(dp) == type) {
887
            val_ptr = (void *)CONFIG_OBJECT_VALUE(dp);
888
            switch (type) {
889
                // Note: the data may be unaligned in the configuration data
890
            case CONFIG_BOOL:
891
                memcpy(val, val_ptr, sizeof(bool));
892
                break;
893
            case CONFIG_INT:
894
                memcpy(val, val_ptr, sizeof(unsigned long));
895
                break;
896
#ifdef CYGPKG_REDBOOT_NETWORKING
897
            case CONFIG_IP:
898
                memcpy(val, val_ptr, sizeof(in_addr_t));
899
                break;
900
            case CONFIG_ESA:
901
                memcpy(val, val_ptr, sizeof(enet_addr_t));
902
                break;
903
#endif
904
#if defined(CYGHWR_NET_DRIVERS) && (CYGHWR_NET_DRIVERS > 1)
905
            case CONFIG_NETPORT:
906
#endif
907
            case CONFIG_STRING:
908
            case CONFIG_SCRIPT:
909
                // Just return a pointer to the script/line
910
                *(unsigned char **)val = (unsigned char *)val_ptr;
911
                break;
912
            }
913
        } else {
914
            diag_printf("Request for config value '%s' - wrong type\n", key);
915
        }
916
        return true;
917
    }
918
#ifdef CYGSEM_REDBOOT_FLASH_CONFIG_READONLY_FALLBACK
919
    // Did not find key. Is configuration data valid?
920
    // Check to see if the config data is valid, if not, revert to 
921
    // readonly mode, by setting config to readonly_config.  We
922
    // will set it back before we leave this function.
923
    if ( (config != readonly_config) && ((flash_crc(config) != config->cksum) ||
924
        (config->key1 != CONFIG_KEY1)|| (config->key2 != CONFIG_KEY2))) {
925
        save_config = config;
926
        config = readonly_config;
927
        if ((flash_crc(config) != config->cksum) ||
928
            (config->key1 != CONFIG_KEY1)|| (config->key2 != CONFIG_KEY2)) {
929
            diag_printf("FLASH configuration checksum error or invalid key\n");
930
            config = save_config;
931
            return false;
932
        }
933
        else{
934
            diag_printf("Getting config information in READONLY mode\n");
935
            res = flash_get_config(key, val, type);
936
            config = save_config;
937
            return res;
938
        }
939
    }
940
#endif
941
    return false;
942
}
943
 
944
//
945
// Update a data object in the data base (in memory copy & backing store)
946
//
947
bool
948
flash_set_config(char *key, void *val, int type)
949
{
950
    char *dp;
951
    void *val_ptr;
952
 
953
    if (!config_ok) return false;
954
 
955
    if ((dp = flash_lookup_config(key)) != NULL) {
956
        if (CONFIG_OBJECT_TYPE(dp) == type) {
957
            val_ptr = (void *)CONFIG_OBJECT_VALUE(dp);
958
            switch (type) {
959
                // Note: the data may be unaligned in the configuration data
960
            case CONFIG_BOOL:
961
                memcpy(val_ptr, val, sizeof(bool));
962
                break;
963
            case CONFIG_INT:
964
                memcpy(val_ptr, val, sizeof(unsigned long));
965
                break;
966
#ifdef CYGPKG_REDBOOT_NETWORKING
967
            case CONFIG_IP:
968
                memcpy(val_ptr, val, sizeof(in_addr_t));
969
                break;
970
            case CONFIG_ESA:
971
                memcpy(val_ptr, val, sizeof(enet_addr_t));
972
                break;
973
#endif
974
#if defined(CYGHWR_NET_DRIVERS) && (CYGHWR_NET_DRIVERS > 1)
975
            case CONFIG_NETPORT:
976
#endif
977
            case CONFIG_STRING:
978
            case CONFIG_SCRIPT:
979
                memcpy(val_ptr, val, config_length(CONFIG_STRING));
980
                break;
981
            }
982
        } else {
983
            diag_printf("Can't set config value '%s' - wrong type\n", key);
984
            return false;
985
        }
986
        flash_write_config(false);
987
        return true;
988
    }
989
    return false;
990
}
991
 
992
//
993
// Copy data into the config area
994
//
995
static void
996
flash_config_insert_value(char *dp, struct config_option *opt)
997
{
998
    switch (opt->type) {
999
        // Note: the data may be unaligned in the configuration data
1000
    case CONFIG_BOOL:
1001
        memcpy(dp, (void *)&opt->dflt, sizeof(bool));
1002
        break;
1003
    case CONFIG_INT:
1004
        memcpy(dp, (void *)&opt->dflt, sizeof(unsigned long));
1005
        break;
1006
#ifdef CYGPKG_REDBOOT_NETWORKING
1007
    case CONFIG_IP:
1008
        memcpy(dp, (void *)&opt->dflt, sizeof(in_addr_t));
1009
        break;
1010
    case CONFIG_ESA:
1011
        memcpy(dp, (void *)opt->dflt, sizeof(enet_addr_t));
1012
        break;
1013
#if defined(CYGHWR_NET_DRIVERS) && (CYGHWR_NET_DRIVERS > 1)
1014
    case CONFIG_NETPORT:
1015
        // validate dflt and if not acceptable use first port
1016
        {
1017
            int index;
1018
            const char *name;
1019
            for (index = 0; (name = net_devname(index)) != NULL; index++)
1020
                if (!strcmp((char *)opt->dflt, name))
1021
                    break;
1022
            if (name == NULL)
1023
                name = net_devname(0);
1024
            memcpy(dp, name, strlen(name) + 1);
1025
        }
1026
        break;
1027
#endif
1028
#endif
1029
    case CONFIG_STRING:
1030
        memcpy(dp, (void *)opt->dflt, config_length(CONFIG_STRING));
1031
        break;
1032
    case CONFIG_SCRIPT:
1033
        break;
1034
    }
1035
}
1036
 
1037
//
1038
// Add a new option to the database
1039
//
1040
bool
1041
flash_add_config(struct config_option *opt, bool update)
1042
{
1043
    char *dp, *kp;
1044
    int len, elen, size;
1045
 
1046
    // If data item is already present, just update it
1047
    // Note: only the data value can be thusly changed
1048
    if ((dp = flash_lookup_config(opt->key)) != NULL) {
1049
        flash_config_insert_value(CONFIG_OBJECT_VALUE(dp), opt);
1050
        if (update) {
1051
            flash_write_config(true);
1052
        }
1053
        return true;
1054
    }
1055
    // Add the data item
1056
    dp = &config->config_data[0];
1057
    size = 0;
1058
    while (size < sizeof(config->config_data)) {
1059
        if (CONFIG_OBJECT_TYPE(dp) == CONFIG_EMPTY) {
1060
            kp = opt->key;
1061
            len = strlen(kp) + 1;
1062
            size += len + 2 + 2 + config_length(opt->type);
1063
            if (opt->enable) {
1064
                elen = strlen(opt->enable) + 1;
1065
                size += elen;
1066
            } else {
1067
                elen = 0;
1068
            }
1069
            if (size > sizeof(config->config_data)) {
1070
                break;
1071
            }
1072
            CONFIG_OBJECT_TYPE(dp) = opt->type;
1073
            CONFIG_OBJECT_KEYLEN(dp) = len;
1074
            CONFIG_OBJECT_ENABLE_SENSE(dp) = opt->enable_sense;
1075
            CONFIG_OBJECT_ENABLE_KEYLEN(dp) = elen;
1076
            dp = CONFIG_OBJECT_KEY(dp);
1077
            while (*kp) *dp++ += *kp++;
1078
            *dp++ = '\0';
1079
            if (elen) {
1080
                kp = opt->enable;
1081
                while (*kp) *dp++ += *kp++;
1082
                *dp++ = '\0';
1083
            }
1084
            flash_config_insert_value(dp, opt);
1085
            if (update) {
1086
                flash_write_config(true);
1087
            }
1088
            return true;
1089
        } else {
1090
            len = 4 + CONFIG_OBJECT_KEYLEN(dp) + CONFIG_OBJECT_ENABLE_KEYLEN(dp) +
1091
                config_length(CONFIG_OBJECT_TYPE(dp));
1092
            dp += len;
1093
            size += len;
1094
        }
1095
    }
1096
    diag_printf("No space to add '%s'\n", opt->key);
1097
    return false;
1098
}
1099
 
1100
//
1101
// Reset/initialize configuration data - used only when starting from scratch
1102
//
1103
static void
1104
config_init(void)
1105
{
1106
    // Well known option strings
1107
    struct config_option *optend = __CONFIG_options_TAB_END__;
1108
    struct config_option *opt = __CONFIG_options_TAB__;
1109
 
1110
    memset(config, 0, sizeof(struct _config));
1111
    while (opt != optend) {
1112
        if (!flash_add_config(opt, false)) {
1113
            return;
1114
        }
1115
        opt++;
1116
    }
1117
    config_ok = true;
1118
}
1119
 
1120
//
1121
// Attempt to get configuration information from the FLASH.
1122
// If available (i.e. good checksum, etc), initialize "known"
1123
// values for later use.
1124
//
1125
static void
1126
load_flash_config(void)
1127
{
1128
    bool use_boot_script;
1129
    unsigned char *cfg_temp = (unsigned char *)workspace_end;
1130
#ifdef CYGHWR_REDBOOT_FLASH_CONFIG_MEDIA_FLASH
1131
    cyg_flashaddr_t err_addr;
1132
#endif
1133
 
1134
    config_ok = false;
1135
    script = NULL;
1136
    cfg_temp -= sizeof(struct _config);  // Space for primary config data
1137
    config = (struct _config *)cfg_temp;
1138
    cfg_temp -= sizeof(struct _config);  // Space for backup config data
1139
    backup_config = (struct _config *)cfg_temp;
1140
#ifdef CYGSEM_REDBOOT_FLASH_CONFIG_READONLY_FALLBACK
1141
    cfg_temp -= sizeof(struct _config);  // Space for readonly copy of config data
1142
    readonly_config = (struct _config *)cfg_temp;
1143
#endif
1144
    workspace_end = cfg_temp;
1145
#ifdef CYGHWR_REDBOOT_FLASH_CONFIG_MEDIA_FLASH
1146
    if (do_flash_init()<0) return;
1147
#ifdef CYGSEM_REDBOOT_FLASH_COMBINED_FIS_AND_CONFIG
1148
    cfg_size = _rup(sizeof(struct _config), sizeof(struct fis_image_desc));
1149
    if ((fisdir_size-cfg_size) < (CYGNUM_REDBOOT_FIS_DIRECTORY_ENTRY_COUNT *
1150
                                  CYGNUM_REDBOOT_FIS_DIRECTORY_ENTRY_SIZE)) {
1151
        // Too bad this can't be checked at compile/build time
1152
        diag_printf("Sorry, FLASH config exceeds available space in FIS directory\n");
1153
        return;
1154
    }
1155
    cfg_base = (((CYG_ADDRESS)fis_addr + fisdir_size) - cfg_size);
1156
    fisdir_size -= cfg_size;
1157
#else
1158
    cfg_size = (flash_block_size > sizeof(struct _config)) ?
1159
        sizeof(struct _config) :
1160
        _rup(sizeof(struct _config), flash_block_size);
1161
    if (CYGNUM_REDBOOT_FLASH_CONFIG_BLOCK < 0) {
1162
        cfg_base = ((CYG_ADDRESS)flash_end + 1 -
1163
           _rup(_rup((-CYGNUM_REDBOOT_FLASH_CONFIG_BLOCK*flash_block_size), cfg_size), flash_block_size));
1164
    } else {
1165
        cfg_base = ((CYG_ADDRESS)flash_start +
1166
           _rup(_rup((CYGNUM_REDBOOT_FLASH_CONFIG_BLOCK*flash_block_size), cfg_size), flash_block_size));
1167
    }
1168
#endif
1169
    cyg_flash_read(cfg_base, (void *)config, sizeof(struct _config), &err_addr);
1170
    conf_endian_fixup(config);
1171
#else
1172
    read_eeprom(config, sizeof(struct _config));  // into 'config'
1173
#endif
1174
#ifdef CYGSEM_REDBOOT_FLASH_CONFIG_READONLY_FALLBACK
1175
    memcpy(readonly_config, config, sizeof(struct _config));
1176
#endif
1177
    if ((flash_crc(config) != config->cksum) ||
1178
        (config->key1 != CONFIG_KEY1)|| (config->key2 != CONFIG_KEY2)) {
1179
        diag_printf("**Warning** FLASH configuration checksum error or invalid key\n");
1180
        diag_printf("Use 'fconfig -i' to [re]initialize database\n");
1181
        config_init();
1182
        return;
1183
    }
1184
    config_ok = true;
1185
 
1186
    flash_get_config("boot_script", &use_boot_script, CONFIG_BOOL);
1187
    if (use_boot_script) {
1188
        flash_get_config("boot_script_data", &script, CONFIG_SCRIPT);
1189
        flash_get_config("boot_script_timeout", &script_timeout, CONFIG_INT);
1190
    }
1191
#ifdef CYGSEM_REDBOOT_VARIABLE_BAUD_RATE
1192
    if (flash_get_config("console_baud_rate", &console_baud_rate, CONFIG_INT)) {
1193
        extern int set_console_baud_rate(int);
1194
        set_console_baud_rate(console_baud_rate);
1195
    }
1196
#endif
1197
}
1198
 
1199
RedBoot_init(load_flash_config, RedBoot_INIT_SECOND);
1200
 
1201
// EOF fconfig.c

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.