openbcm

Git mirror of https://github.com/Broadcom-Network-Switching-Software/OpenBCM
git clone git://git.finwo.net/mirror/broadcom/openbcm
Log | Files | Refs | README

config.c (34339B)


      1 /*
      2  * 
      3  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      4  * 
      5  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      6  *
      7  * SAL Configuration Variable Support
      8  *
      9  * The SAL layer maintains a set of configuration variables for use
     10  * by any upper layers (such as SOC or BCM).  It is maintained in the
     11  * SAL layer without using anything other than the standard lib calls
     12  * to avoid requiring anything other than just itself.
     13  *
     14  * These config variables can either be compiled into the image or read
     15  * from a file during initialization.
     16  *
     17  * Precompiled values are defined in the function sal_config_init_defaults()
     18  * which is automatically built from the uncommented values
     19  * in $SDK/rc/config.bcm using the bcm2c.pl script.  This generates a source
     20  * file called platform_defines.c
     21  *
     22  * Runtime values are loaded by reading the file config.bcm, typically
     23  * stored in the switch's flash file system.  The variables are stored one
     24  * per line in the file, in the form VARIABLE=VALUE.  Comment lines beginning
     25  * with a # character and empty lines consisting of only white space are
     26  * ignored.  The file $SDK/rc/config.bcm is an example that can be used
     27  * as a guide.
     28  *
     29  * If the image is compile with NO_FILEIO or SAL_CONFIG_FILE_DISABLE
     30  * defined, then the runtime values are not loaded from an external file.
     31  */
     32 
     33 #ifdef __KERNEL__
     34 #include <linux/string.h>
     35 #include <linux/ctype.h>
     36 #else
     37 #include <string.h>
     38 #include <ctype.h>
     39 #include <stdlib.h>
     40 #include <stdio.h>
     41 #endif
     42 #include <assert.h>
     43 
     44 #include <sal/core/libc.h>
     45 #include <sal/core/alloc.h>
     46 #include <sal/core/spl.h>
     47 #include <sal/types.h>
     48 #include <sal/appl/config.h>
     49 #include <sal/appl/io.h>
     50 #include <sal/appl/sal.h>
     51 #include <shared/util.h>
     52 
     53 #ifdef  NO_FILEIO
     54 #undef  SAL_CONFIG_FILE_DISABLE
     55 #define SAL_CONFIG_FILE_DISABLE
     56 #endif  /* NO_FILEIO */
     57 
     58 typedef uint16  sc_hash_t;
     59 
     60 /*
     61  * Speed up searches by first checking if a hash matches.
     62  * It encodes the first and last character, as well as string length.
     63  */
     64 
     65 #define MAX_CONFIG_HASH_COUNT 1024
     66 #define SC_HASH(_n, _h) do { \
     67     uint32 _hash = 5381; \
     68     uint32 _i = 0; \
     69     while (_n[_i] != 0) { \
     70         _hash = ((_hash << 5) + _hash) + _n[_i]; \
     71         _i++; \
     72     } \
     73     _hash = ((_hash << 5) + _hash) + _i; \
     74     _h = (sc_hash_t)(_hash % MAX_CONFIG_HASH_COUNT); \
     75     } while (0)
     76   
     77 typedef struct sc_s {
     78     struct sc_s *sc_next;
     79     char    *sc_name;
     80     char    *sc_value;
     81     uint16  sc_flag;  /* Used for duplicate checking, flushing, and hits */
     82     uint16  sc_line;
     83     sc_hash_t   sc_hash;    
     84 } sc_t;
     85 
     86 /* Defines for sc_t->sc_flag */
     87 #define SC_COMPILE_VALUE 0x0001
     88 #define SC_FLUSHED       0x0002
     89 #define SC_HIT           0x0004
     90 
     91 static char *sal_config_file_name = NULL;
     92 static char *sal_config_temp_name = NULL;
     93 
     94 static sc_t *sal_config_list[MAX_CONFIG_HASH_COUNT];
     95 
     96 /*
     97  *  sal_config_compiled_values is the count of compiled values
     98  *  sal_config_imported_values is the count of imported values
     99  *  from sal_config_file_name (ex. config.bcm)
    100  */
    101 
    102 static uint32 sal_config_compiled_values = 0;
    103 static uint32 sal_config_imported_values = 0;
    104 
    105 #define FREE_SC(_s) if (_s) {                   \
    106                 if ((_s)->sc_name) sal_free((_s)->sc_name); \
    107                 if ((_s)->sc_value) sal_free((_s)->sc_value);\
    108                 sal_free(_s);               \
    109             }
    110 
    111 #ifndef SAL_CONFIG_FILE_DISABLE
    112 #include <soc/property.h>
    113 static char *sal_config_prop_names[] = BCM_SOC_PROP_NAMES_INITIALIZER;          
    114 #endif
    115 
    116 /*
    117  * Function: 
    118  *  wildcard_search
    119  * Purpose: 
    120  *  search for "*" in name and save prefix as wildcard 
    121  *  
    122  * Returns: 
    123  *  wildcard returns prefix of name
    124  *  length returns length of wildcard
    125  */
    126 char*
    127 wildcard_search(const char *name, char *wildcard, int *length)
    128 {
    129     int len, index = 0;
    130     const char *m = name;
    131 
    132     len = strlen(name);
    133     wildcard = sal_alloc(len + 1, "wildcard");
    134 
    135     while (index < len) {
    136         if (*m == '*') {
    137             *(wildcard+index) = 0;
    138             *length = index;
    139             return wildcard;
    140         }
    141         else {
    142             *(wildcard+index) = *m;
    143             m++;
    144             index++;
    145         }
    146     }
    147 
    148     /* no '*' found */
    149     sal_free(wildcard);
    150     return NULL;
    151 }
    152 
    153 
    154 /*
    155  * Function:
    156  *  sal_config_file_set
    157  * Purpose:
    158  *  Set the name of the active configuration file.
    159  * Parameters:
    160  *  fname - name of config file (if NULL, use default; if empty
    161  *      string, there is no config file)
    162  *  tname - name of temporary file that gets renamed to config file
    163  *      (must be given if fname is non-NULL and non-empty)
    164  * Returns:
    165  *  -1  Illegal parameter
    166  *  0   Success
    167  * Notes:
    168  *  Makes a copy of the input string.
    169  */
    170 
    171 int
    172 sal_config_file_set(const char *fname, const char *tname)
    173 {
    174     if (sal_config_file_name != NULL) {
    175     sal_free(sal_config_file_name);
    176     sal_config_file_name = NULL;
    177     }
    178 
    179     if (sal_config_temp_name != NULL) {
    180     sal_free(sal_config_temp_name);
    181     sal_config_temp_name = NULL;
    182     }
    183 
    184     if (fname != NULL) {
    185     sal_config_file_name = sal_strdup(fname);
    186 
    187     if (fname[0] != 0) {
    188         if (tname == NULL || tname[0] == 0) {
    189         return -1;
    190         }
    191 
    192         sal_config_temp_name = sal_strdup(tname);
    193     }
    194     }
    195 
    196     return 0;
    197 }
    198 
    199 /*
    200  * Function:
    201  *  sal_config_file_get
    202  * Purpose:
    203  *  Return the config file names
    204  * Parameters:
    205  *  fname - (OUT) Name of config file, NULL if none
    206  *  tname - (OUT) Name of temporary file, NULL if none
    207  * Returns:
    208  *  0   Success
    209  */
    210 
    211 int
    212 sal_config_file_get(const char **fname, const char **tname)
    213 {
    214     *fname = (sal_config_file_name != NULL ?
    215           sal_config_file_name : SAL_CONFIG_FILE);
    216     *tname = (sal_config_temp_name != NULL ?
    217           sal_config_temp_name : SAL_CONFIG_TEMP);
    218 
    219     return 0;
    220 }
    221 
    222 /*
    223  * Function:
    224  *  sal_config_find
    225  * Purpose:
    226  *  Find a config entry for the specified name.
    227  * Parameters:
    228  *  name - name of variable to recover
    229  * Returns:
    230  *  NULL - not found
    231  *  !NULL - pointer to value
    232  */
    233 
    234 static sc_t *
    235 sal_config_find(const char *name)
    236 {
    237     sc_t  *sc;
    238     sc_hash_t hash;
    239     SC_HASH(name, hash);
    240     SAL_GLOBAL_LOCK;
    241     sc = sal_config_list[hash];
    242     while (sc != NULL) {
    243         if ((sc->sc_name != NULL) && (sc->sc_value != NULL) && (sal_strcmp(sc->sc_name, name) == 0)) {
    244             break;
    245         }
    246         sc = sc->sc_next;
    247     }
    248 
    249     SAL_GLOBAL_UNLOCK;
    250     return sc;
    251 }
    252 
    253 #ifndef SAL_CONFIG_FILE_DISABLE /* Only used by fileio functions */
    254 static int
    255 sal_config_get_lvalue(char *str, sc_t *sc)
    256 {
    257     char *equals_loc;
    258 
    259     if ((equals_loc = strchr(str, '=')) == NULL) {
    260         if (sc != NULL) {
    261             FREE_SC(sc);
    262         }
    263         return FALSE;
    264     }
    265 
    266     while (isspace((unsigned)*str)) {
    267         str++;              /* skip leading whitespace */
    268     }
    269 
    270     if (str == equals_loc) {
    271         if (sc != NULL) {
    272             FREE_SC(sc);
    273         }
    274         return FALSE;           /* lvalue is empty or only whitespace */
    275     }
    276 
    277     while (isspace((unsigned)*(equals_loc - 1)) && equals_loc > str) {
    278         equals_loc--;       /* trim trailing whitespace */
    279     }
    280 
    281     sc->sc_name = sal_alloc(equals_loc - str + 1, "config name");
    282     sal_strncpy(sc->sc_name, str, equals_loc - str);
    283 
    284     sc->sc_name[equals_loc - str] = '\0';
    285 
    286     SC_HASH(sc->sc_name, sc->sc_hash);
    287     return TRUE;
    288 }
    289 
    290 static int
    291 sal_config_get_rvalue(char *str, sc_t *sc)
    292 {
    293     char *begin;
    294     char *end;
    295 
    296     if ((begin = strchr(str, '=')) == NULL) {
    297         if (sc != NULL) {
    298             FREE_SC(sc);
    299         }
    300         return FALSE;
    301     }
    302 
    303     begin++;             /* Move past '=' */
    304     while (isspace((unsigned)*begin)) {
    305         begin++;         /* Trim leading whitespace */
    306     }
    307 
    308     for (end = begin + strlen(begin) - 1; isspace((unsigned)*end); end--)
    309         *end = '\0';     /* Trim trailing whitespace */
    310 
    311     sc->sc_value = sal_alloc(end - begin + 2, "config value");
    312     if (sc->sc_value == NULL) {
    313         sal_printf("sal_config_parse: Memory allocation failed\n");
    314         FREE_SC(sc);
    315         return FALSE;
    316     }
    317 
    318     sal_strncpy(sc->sc_value, begin, end - begin + 1);
    319     sc->sc_value[end - begin + 1] = '\0';
    320 
    321     return TRUE;
    322 }
    323 
    324 /*
    325  * Function:
    326  *  sal_config_parse
    327  * Purpose:
    328  *  Parse a single input line.
    329  * Parameters:
    330  *  str - pointer to null terminated input line.
    331  * Returns:
    332  *  NULL - failed to parse
    333  *  !NULL - pointer to sc entry.
    334  * Notes:
    335  *  Does not modify input line.
    336  */
    337 static  sc_t    *
    338 sal_config_parse(char *str)
    339 {
    340     sc_t    *sc;
    341 
    342     sc = (sc_t *)sal_alloc(sizeof(sc_t), "config parse");
    343     if (sc != NULL) {
    344         sal_memset(sc, 0, sizeof(sc_t));
    345     }
    346     
    347     if (!sc || !sal_config_get_lvalue(str, sc) || 
    348         !sal_config_get_rvalue(str, sc)) {
    349         return NULL;
    350     }
    351 
    352     sc->sc_next = NULL;
    353     return sc;
    354 }
    355 #endif  /* SAL_CONFIG_FILE_DISABLE */
    356 
    357 /*
    358  * Function:
    359  *  sal_config_init
    360  * Purpose:
    361  *  If not already initialized, call refresh.
    362  * Parameters:
    363  *  None
    364  * Returns:
    365  *  0 - success
    366  *  -1 - failed.
    367  */
    368 
    369 int
    370 sal_config_init(void)
    371 {
    372     static int initdone = FALSE;
    373 
    374     if (!initdone) {
    375         sal_memset(sal_config_list, 0, sizeof(sal_config_list));
    376         initdone = TRUE;
    377         return sal_config_refresh();
    378     }
    379 
    380     return 0;
    381 }
    382 
    383 #ifndef SAL_CONFIG_FILE_DISABLE
    384 int
    385 sal_config_search_valid_prop(char *name)
    386 {
    387     int i;
    388 
    389     for (i = 0; sal_config_prop_names[i][0] != '\0'; i++) {
    390         if (sal_strcasecmp(sal_config_prop_names[i], name) == 0) {
    391             return TRUE;
    392         }
    393     }
    394 
    395     return FALSE;
    396 }
    397 
    398 /*
    399  * Function:
    400  *   sal_config_prop_is_known
    401  * Purpose:
    402  *   Determine if a given property is valid or not
    403  * Returns:
    404  *   TRUE if property exists in property.h, FALSE if it does not
    405  */
    406 int
    407 sal_config_prop_is_known(sc_t *sc)
    408 {
    409     static char name[256];
    410     char *loc;
    411 
    412     sal_strncpy(name, sc->sc_name, sizeof(name) - 1);
    413     name[sizeof(name) - 1] = '\0';
    414     if (sal_config_search_valid_prop(name)) {
    415         return TRUE;
    416     }
    417 
    418     /* try removing the . if there is one, for "prop.0" style */
    419     loc = sal_strrchr(name, '.');
    420     if (loc != NULL) {
    421         *loc = '\0';
    422         if (sal_config_search_valid_prop(name)) {
    423             return TRUE;
    424         }
    425     }
    426 
    427     /* try removing the . again if there is another one, 
    428        for "prop.port.0" style */
    429     loc = sal_strrchr(name, '.');
    430     if (loc != NULL) {
    431         *loc = '\0';
    432         if (sal_config_search_valid_prop(name)) {
    433             return TRUE;
    434         }
    435     }
    436 
    437     /* try removing the . again if there is another one, 
    438        for "prop.prop1.port.0" style */
    439     loc = sal_strrchr(name, '.');
    440     if (loc != NULL) {
    441         *loc = '\0';
    442         if (sal_config_search_valid_prop(name)) {
    443             return TRUE;
    444         }
    445     }
    446 
    447     /* try removing the . again if there is another one, 
    448        for "prop.prop1.prop2.port.0" style */
    449     loc = sal_strrchr(name, '.');
    450     if (loc != NULL) {
    451         *loc = '\0';
    452         if (sal_config_search_valid_prop(name)) {
    453             return TRUE;
    454         }
    455     }
    456 
    457     /* try removing the . again if there is another one, 
    458        for "prop.prop1.prop2.prop3.port.0" style */
    459     loc = sal_strrchr(name, '.');
    460     if (loc != NULL) {
    461         *loc = '\0';
    462         if (sal_config_search_valid_prop(name)) {
    463             return TRUE;
    464         }
    465     }
    466   
    467     /* try removing the last brace if it exists, for "prop{0}" style */
    468     loc = sal_strrchr(name, '{');
    469     if (loc != NULL) {
    470         *loc = '\0';
    471         if (sal_config_search_valid_prop(name)) {
    472             return TRUE;
    473         }
    474     }
    475 
    476     /* try removing the last underscore if it exists, for "prop_xe.0" style */
    477     loc = sal_strrchr(name, '_');
    478     if (loc != NULL) {
    479         *loc = '\0';
    480         if (sal_config_search_valid_prop(name)) {
    481             return TRUE;
    482         }
    483     }
    484 
    485     /* 
    486      * try removing one more underscore if it exists, for "prop_in_203.bcm88650" 
    487      * style 
    488      */
    489     loc = sal_strrchr(name, '_');
    490     if (loc != NULL) {
    491         *loc = '\0';
    492         if (sal_config_search_valid_prop(name)) {
    493             return TRUE;
    494         }
    495     }
    496 
    497     /* 
    498      * try removing one more underscore if it exists, for "prop_dram0_byte0_bit0.BCM88675"
    499      * style 
    500      */
    501 
    502     loc = sal_strrchr(name, '_');
    503     if (loc != NULL) {
    504         *loc = '\0';
    505         if (sal_config_search_valid_prop(name)) {
    506             return TRUE;
    507         }
    508     }
    509 
    510     /*
    511      * try removing 2 more underscore if exists, for "serdes_lane_config_cl72_auto_polarity_en_<port>.BCM8879X"
    512      * and "serdes_lane_config_cl72_restart_timeout_en_<port>.BCM8879X"
    513      */
    514 
    515     loc = sal_strrchr(name, '_');
    516     if (loc != NULL) {
    517         *loc = '\0';
    518         if (sal_config_search_valid_prop(name)) {
    519             return TRUE;
    520         }
    521     }
    522 
    523     loc = sal_strrchr(name, '_');
    524     if (loc != NULL) {
    525         *loc = '\0';
    526         if (sal_config_search_valid_prop(name)) {
    527             return TRUE;
    528         }
    529     }
    530 
    531     return FALSE;
    532 }
    533 #endif
    534 
    535 #ifndef SAL_CONFIG_FILE_DISABLE
    536 #define SAL_CONFIG_MAX_IMPORTED_CONFIG_FILES  1024
    537 
    538 /**
    539  * 
    540  * 
    541  * 
    542  * @param import_fname 
    543  * @param nof_imported_config_files 
    544  * @param already_imported_tables 
    545  * check if file already 
    546  * imported 
    547  * 
    548  * @return int 
    549  */
    550 static int
    551  sal_config_already_imported(char *import_fname,int *nof_imported_config_files, char *already_imported_tables[])
    552 {
    553     int i;
    554 
    555     /*
    556      *  the function save the file names to keep we are not enter
    557      *  into infinite loop of imports
    558      *  the saved name is
    559      *  1.basename(config.bcm) - first time
    560      *  2. the argument to import command
    561  */
    562     if (SAL_CONFIG_MAX_IMPORTED_CONFIG_FILES<=*nof_imported_config_files) {
    563         sal_printf("nof imported files exceeded its limit: %d:\n ",SAL_CONFIG_MAX_IMPORTED_CONFIG_FILES);
    564         return 1;
    565     }
    566     for (i=0;i<*nof_imported_config_files;i++) {
    567         if (!sal_strcmp(import_fname, already_imported_tables[i])) {
    568 #if defined(BROADCOM_DEBUG)
    569             sal_printf("sal_config_already_imported: file: %s, "
    570                    "is already imported\n",
    571                    import_fname);
    572 #endif /* BROADCOM_DEBUG */
    573             return 1;
    574         }
    575     }
    576     already_imported_tables[i] = sal_alloc(sal_strlen(import_fname)+1," alloc bcm file name");
    577     sal_strcpy(already_imported_tables[i],import_fname);
    578     (*nof_imported_config_files)++;
    579     return 0;
    580 }
    581 
    582 /**
    583  * import config file 
    584  * to one config file 
    585  */
    586 
    587 static int 
    588 sal_config_line_import(char *str,char *import_fname) {
    589     char  line[SAL_CONFIG_STR_MAX];
    590     char *sep=" \t\n\r";
    591     char *token;
    592     /*
    593      * we check the case if the 
    594      * line of the form 
    595      * import <filename> 
    596     */
    597 
    598 
    599     if ((sal_strlen(str)) < SAL_CONFIG_STR_MAX) {
    600         sal_strcpy(line,str);
    601     } else {
    602         return 0;
    603     }
    604     /*
    605      * split the line into 2 tokens
    606      */
    607     token=sal_strtok(line,sep);
    608     if (token==NULL) {
    609         return 0;
    610     }
    611 
    612     /*
    613      * if the first token is import 
    614      * then we look for the second token to be the file name 
    615      */
    616 
    617     if (sal_strcmp(token,"import")) {
    618         return 0;
    619     }
    620     token = sal_strtok(NULL, sep);
    621     if (token==NULL) {
    622         return 0;
    623     }
    624 
    625     /*
    626      * we build the import file name as 
    627      * dirname/filename contained at the second token 
    628  */
    629     sal_strcpy(import_fname, token); 
    630 
    631     return 1;
    632 }
    633 
    634 /**
    635  * Function:
    636  *  sal_config_file_process
    637  * Purpose:
    638  *      parse single config-bcm file .
    639  *      if find import statement in the parsed file
    640  *      call recursively itself with the import file name
    641  * @param fname 
    642  * @param nof_imported_config_files 
    643  * @param already_imported_tables 
    644  * @param dir_name - the location of the file.
    645  * @param override_duplicates - set to 1 to override existing soc properties
    646  * @return int 
    647  */
    648 int
    649 sal_config_file_process(char *fname,int *nof_imported_config_files, char *already_imported_tables[], char *dirname, int override_duplicates)
    650 {
    651     FILE  *fp;
    652     sc_t  *found_sc;
    653     char  str[SAL_CONFIG_STR_MAX], *c;
    654     int   line = 0;
    655     int   suppress_unknown_warnings = 0;
    656     char import_fname[SAL_NAME_MAX];
    657     char fname_full_path[SAL_NAME_MAX];
    658     sc_t  *sc;
    659 
    660 
    661     if (dirname!=NULL && sal_strcasecmp(dirname,".")) {
    662         sal_sprintf(fname_full_path, "%s/%s", dirname, fname); 
    663     } else {
    664         sal_strncpy(fname_full_path, fname,sizeof(fname_full_path)-1); 
    665     }
    666     if ((fp = sal_fopen(fname_full_path, "r")) == NULL) {
    667         sal_printf("sal_config_refresh: cannot read file: %s, "
    668                "variables not loaded\n",
    669                fname_full_path);
    670         return -1;
    671     }
    672 
    673     /* Read the entire file  - parsing as we go */
    674 
    675     while (sal_fgets(str, sizeof(str), fp)) {
    676 
    677         line++;
    678 
    679         /* Skip comment lines */
    680 
    681         if (str[0] == '#') {
    682             continue;
    683         }
    684         if (sal_config_line_import(str,import_fname)) {
    685             if (already_imported_tables == NULL)
    686             {
    687                 sal_printf("import is not allowed \n");
    688                 continue;
    689             }
    690             else
    691             {
    692                 if (sal_config_already_imported(import_fname, nof_imported_config_files,already_imported_tables)) {
    693                     sal_printf("%s already imported\n",import_fname);
    694                     continue;
    695                 }
    696                 if (sal_config_file_process(import_fname,  nof_imported_config_files,already_imported_tables,dirname, override_duplicates) == -1) {
    697                     continue; 
    698                 }
    699                 continue;
    700             }
    701         }
    702 
    703         /* Strip trailing newline/blanks */
    704 
    705         c = str + strlen(str);
    706         while (c > str && isspace((unsigned) c[-1])) {
    707             c--;
    708         }
    709 
    710         *c = '\0';
    711 
    712         /* Skip blank lines */
    713 
    714         if (str[0] == 0) {
    715             continue;
    716         }
    717 
    718         if ((sc = sal_config_parse(str)) == NULL) {
    719             sal_printf("sal_config_refresh: format error "
    720                  "in %s on line %d (ignored)\n",
    721                  fname, line);
    722             continue;
    723         }
    724 
    725         /* 
    726          * Scan for "suppress_unknown_prop_warnings" directly as we go
    727          * instead of sal_config_find() because it's much faster
    728          */
    729         if (sal_strcasecmp("suppress_unknown_prop_warnings", 
    730                            sc->sc_name) == 0) {
    731             suppress_unknown_warnings = _shr_ctoi(sc->sc_value);
    732             continue;
    733         }
    734 
    735         /* Check for pre-existing default or duplicates in the file */        
    736         found_sc = sal_config_list[sc->sc_hash];
    737         while (found_sc != NULL) {
    738             if (sal_strcmp(found_sc->sc_name, sc->sc_name) == 0) {
    739                 break;
    740             }
    741             found_sc = found_sc->sc_next;
    742         }
    743 
    744         if (found_sc != NULL) {
    745             if (!(found_sc->sc_flag & SC_COMPILE_VALUE) && !override_duplicates) {
    746                 sal_printf("sal_config_refresh: ignoring duplicate entry "
    747                "\"%s\"\n"
    748                "                    %s line %d "
    749                "(first defined on line %d)\n",
    750                sc->sc_name, fname,
    751                line, found_sc->sc_line);
    752             }
    753             else {
    754                 /* Clobber the compiled-in default value */
    755                 char *temp = sc->sc_value;         /* New value */
    756                 sc->sc_value = found_sc->sc_value; /* Old, to be freed */
    757                 found_sc->sc_value = temp;
    758                 found_sc->sc_line = line; /* Line # of 1st definition */
    759             }
    760             FREE_SC(sc);
    761             continue;
    762         }
    763 
    764         if (!suppress_unknown_warnings) {
    765             if (sal_config_prop_is_known(sc) == FALSE) {
    766                 sal_printf("sal_config_refresh: unknown entry \"%s\""
    767                            " on %s line %d\n", sc->sc_name, fname, line);
    768             }
    769         }
    770 
    771         sc->sc_line = line; /* Line # of 1st definition */
    772         sc->sc_next = sal_config_list[sc->sc_hash];
    773         sal_config_list[sc->sc_hash] = sc;  
    774         sal_config_imported_values++;
    775     } /* parse config file */
    776     sal_fclose(fp);
    777     return 0;
    778 }
    779 #endif
    780 /*
    781  * Function:
    782  *  sal_config_refresh
    783  * Purpose:
    784  *      Refresh default (compiled-in) configuration.
    785  *  Refresh the memory image from the configuration file,
    786  *      clobbering default values (if the config file exists).
    787  * Parameters:
    788  *  None
    789  * Returns:
    790  *  0 - success
    791  *  -1 - failed.
    792  */
    793 int
    794 sal_config_refresh(void)
    795 {
    796     sc_t  *sc, *sc_tmp;
    797     int i;
    798 
    799 #ifndef SAL_CONFIG_FILE_DISABLE
    800     char *fname;
    801     int  nof_imported_config_files=1;
    802     char  *already_imported_tables[SAL_CONFIG_MAX_IMPORTED_CONFIG_FILES]={NULL};
    803     int rv;
    804     char dirname[SAL_NAME_MAX];
    805     int flen;
    806 
    807 
    808     fname = (sal_config_file_name != NULL ?
    809     sal_config_file_name : SAL_CONFIG_FILE);
    810 
    811     if (fname[0] == 0) {
    812         return 0;   /* No config file */
    813     }
    814 
    815     /* Try to load config file ... */
    816 #endif
    817 
    818     /* Clear all previous state */
    819     for (i = 0; i < MAX_CONFIG_HASH_COUNT; i++) {
    820         sc = sal_config_list[i];
    821         sal_config_list[i] = NULL;
    822         while (sc != NULL) {
    823             sc_tmp = sc->sc_next;
    824             FREE_SC(sc);
    825             sc = sc_tmp;
    826         }
    827     }
    828     /* load precompiled values from platform_defines.c */
    829     sal_config_init_defaults();
    830 
    831 #ifndef SAL_CONFIG_FILE_DISABLE
    832     /*
    833      * Add new file-based variables, superseding any matching compiled
    834      * variables.  Find end-of-list, and initialize the default-or-file
    835      * flag.
    836      */
    837     sal_config_compiled_values = 0;
    838     sal_config_imported_values = 0;
    839 
    840     for (i = 0; i < MAX_CONFIG_HASH_COUNT; i++) {
    841         for (sc = sal_config_list[i]; sc != NULL; sc = sc->sc_next) {
    842             sc->sc_flag |= SC_COMPILE_VALUE;
    843             sal_config_compiled_values++;
    844         }
    845     }
    846     flen = sal_strnlen(fname, SAL_NAME_MAX);
    847     if (flen == SAL_NAME_MAX)
    848     {
    849         sal_printf("sal_config_refresh: config file path length is not supported (max length supported %d) \n", SAL_NAME_MAX);
    850         return -1; /*throw a failure*/
    851     }
    852     sal_dirname(fname,dirname);
    853     already_imported_tables[0] = sal_alloc(sal_strlen(fname)+1 ," alloc bcm file name");
    854     sal_basename(fname, already_imported_tables[0]);
    855     rv =  sal_config_file_process(already_imported_tables[0],&nof_imported_config_files,already_imported_tables, dirname, 0);
    856 
    857     for (i=0;i<nof_imported_config_files;i++) {
    858         sal_free(already_imported_tables[i]);
    859     }
    860 
    861     return rv;
    862 
    863 #endif /* SAL_CONFIG_FILE_DISABLE */
    864 
    865     return 0;
    866 }
    867 
    868 /*
    869  * Function:
    870  *  sal_config_flush
    871  * Purpose:
    872  *  Flush the memory image to the configuration file.
    873  * Parameters:
    874  *  None
    875  * Returns:
    876  *  0 - success
    877  *  -1 - failed.
    878  */
    879 
    880 int
    881 sal_config_flush(void)
    882 {
    883     int   rv = 0;
    884 #ifndef SAL_CONFIG_FILE_DISABLE
    885     FILE  *old_fp, *new_fp;
    886     sc_t  *sc, *new_sc;
    887     char  str[SAL_CONFIG_STR_MAX], *c;
    888     int   line = 0;
    889     char  *fname, *tname;
    890     int i;
    891 
    892     fname = (sal_config_file_name != NULL ?
    893        sal_config_file_name : SAL_CONFIG_FILE);
    894 
    895     if (fname[0] == 0) {
    896         return 0; /* No config file */
    897     }
    898 
    899     tname = (sal_config_temp_name != NULL ?
    900        sal_config_temp_name : SAL_CONFIG_TEMP);
    901 
    902     assert(tname != NULL && tname[0] != 0);
    903 
    904     /* Attempt to create temp file */
    905 
    906     if ((new_fp = sal_fopen(tname, "w")) == NULL) {
    907         rv = -1;
    908         goto done;
    909     }
    910 
    911     /* old_fp can be NULL if creating config file for first time */
    912 
    913     old_fp = sal_fopen(fname, "r");
    914 
    915     /* Initialize the "flushed" flag */
    916     for (i = 0; i < MAX_CONFIG_HASH_COUNT; i++) {
    917         for (sc = sal_config_list[i]; sc != NULL; sc = sc->sc_next) {
    918             sc->sc_flag &= ~SC_FLUSHED;
    919         }
    920     }
    921 
    922     /* Read the entire file  - parsing as we go */
    923 
    924     while (old_fp != NULL && sal_fgets(str, sizeof(str), old_fp)) {
    925         char *s;
    926       
    927         line++;
    928       
    929         /* Strip trailing newline/blanks */
    930       
    931         c = str + strlen(str);
    932         while (c > str && isspace((unsigned) c[-1])) {
    933             c--;
    934         }
    935       
    936         *c = '\0';
    937       
    938         /*
    939          * Transfer blank lines and comment lines, but NOT commented-out
    940          * variable settings (yet)
    941          */
    942       
    943         if (str[0] == 0 || (str[0] == '#' && strchr(str, '=') == NULL)) {
    944             sal_fprintf(new_fp, "%s\n", str);
    945             continue;
    946         }
    947       
    948         s = str;
    949         if (*s == '#') {
    950             s++;
    951         }
    952       
    953         if ((sc = sal_config_parse(s)) == NULL) {
    954             sal_printf("sal_config_flush: format error "
    955                  "in %s on line %d (removed)\n",
    956                  fname, line);
    957             continue;
    958         }
    959       
    960         /* Write new value (or comment) for this entry */
    961       
    962         if ((new_sc = sal_config_find(sc->sc_name)) == NULL ||
    963             (new_sc->sc_flag & SC_FLUSHED)) {
    964             /* Not found or a dup, write out commented assignment */
    965             sal_fprintf(new_fp, "#%s=%s\n", sc->sc_name, sc->sc_value);
    966         } else {
    967             sal_fprintf(new_fp, "%s=%s\n", new_sc->sc_name, new_sc->sc_value);
    968             new_sc->sc_flag |= SC_FLUSHED;
    969         }
    970       
    971         FREE_SC(sc);
    972     }
    973 
    974     /* Write out the current values that were not in the old_fp file */
    975     for (i = 0; i < MAX_CONFIG_HASH_COUNT; i++) {
    976         for (sc = sal_config_list[i]; sc != NULL; sc = sc->sc_next) {
    977             if (!(sc->sc_flag & SC_FLUSHED)) {
    978                 sal_fprintf(new_fp, "%s=%s\n", sc->sc_name, sc->sc_value);
    979             }
    980         }
    981     }
    982 
    983     sal_fclose(new_fp);
    984 
    985     if (old_fp != NULL) {
    986         sal_fclose(old_fp);
    987     }
    988 
    989     if (rv == 0) {      /* No error, rename file */
    990         rv = sal_rename(tname, fname);
    991     }
    992 
    993     if (rv != 0) {      /* Error, remove temp file */
    994         (void)sal_remove(tname);
    995     }
    996 
    997  done:
    998     if (rv < 0) {
    999         sal_printf("sal_config_flush: variables not saved\n");
   1000     }
   1001 #endif /* SAL_CONFIG_FILE_DISABLE */
   1002 
   1003     return rv;
   1004 }
   1005 
   1006 /*
   1007  * Function:
   1008  *  sal_config_save
   1009  * Purpose:
   1010  *  Flush the config to the a given file.
   1011  * Parameters:
   1012  *  None
   1013  * Returns:
   1014  *  0 - success
   1015  *  -1 - failed.
   1016  */
   1017 
   1018 int
   1019 sal_config_save(char *fname, char *pat, int append)
   1020 {
   1021     int   rv = 0;
   1022 #ifndef SAL_CONFIG_FILE_DISABLE
   1023     FILE  *new_fp;
   1024     sc_t  *sc;
   1025     int   pat_len = 0;
   1026     int   i;
   1027 
   1028     if (fname == NULL) {
   1029         return 0; /* No config file */
   1030     }
   1031 
   1032     if(append) {
   1033         new_fp = sal_fopen(fname, "a");
   1034     } else {
   1035         new_fp = sal_fopen(fname, "w");
   1036     }
   1037     
   1038     if (new_fp == NULL) {
   1039         rv = -1;
   1040         goto done;
   1041     }
   1042 
   1043     if (pat) {
   1044         pat_len = strlen(pat);
   1045     }
   1046     /* Write out the current values */
   1047     for (i = 0; i < MAX_CONFIG_HASH_COUNT; i++) {
   1048         for (sc = sal_config_list[i]; sc != NULL; sc = sc->sc_next) {
   1049             if ((pat == NULL) || (sal_strncasecmp(sc->sc_name, pat, pat_len) == 0)) {
   1050                 sal_fprintf(new_fp, "%s=%s\n", sc->sc_name, sc->sc_value);
   1051             }
   1052         }
   1053     }
   1054 
   1055     sal_fclose(new_fp);
   1056 
   1057  done:
   1058     if (rv < 0) {
   1059         sal_printf("sal_config_flush: variables not saved\n");
   1060     }
   1061 #endif /* SAL_CONFIG_FILE_DISABLE */
   1062 
   1063     return rv;
   1064 }
   1065 
   1066 /*
   1067  * Function:
   1068  *  sal_config_get
   1069  * Purpose:
   1070  *  Recover a sal configuration variable
   1071  * Parameters:
   1072  *  name - name of variable to recover
   1073  * Returns:
   1074  *  NULL - not found
   1075  *  !NULL - pointer to value
   1076  */
   1077 
   1078 char *
   1079 sal_config_get(const char *name)
   1080 {
   1081     sc_t  *sc;
   1082 
   1083     sc = sal_config_find(name);
   1084     if (sc != NULL) {
   1085         sc->sc_flag |= SC_HIT;
   1086         return sc->sc_value;
   1087     } else {
   1088         return NULL;
   1089     }
   1090 }
   1091 
   1092 /*
   1093  * Function:
   1094  *  sal_config_get_next
   1095  * Purpose:
   1096  *  Recover a sal configuration variables in order.
   1097  * Parameters:
   1098  *  name - (IN/OUT) name of last variable recovered.
   1099  *  value- (OUT) value of variable recovered.
   1100  * Returns:
   1101  *  0 - variable recovered.
   1102  *  -1 - All complete, not more variables.
   1103  */
   1104 
   1105 int
   1106 sal_config_get_next(char **name, char **value)
   1107 {
   1108     sc_t  *sc;
   1109     sc_hash_t hash;
   1110     char * nm = *name;
   1111 
   1112     SAL_GLOBAL_LOCK;
   1113     if (nm) {
   1114         SC_HASH(nm, hash);
   1115         sc = sal_config_list[hash];
   1116         while (sc != NULL) {
   1117             if (sal_strcmp(sc->sc_name, nm) == 0) {
   1118                 break;
   1119             }
   1120             sc = sc->sc_next;
   1121         } 
   1122         if (sc != NULL) {
   1123             sc = sc->sc_next;
   1124             if (sc == NULL) {
   1125                 hash++;
   1126                 for (;hash < MAX_CONFIG_HASH_COUNT; hash++) {
   1127                     sc = sal_config_list[hash];
   1128                     if (sc != NULL) {
   1129                         break;
   1130                     }
   1131                 }
   1132             }
   1133         }
   1134         
   1135     } else {
   1136         for (hash = 0; hash < MAX_CONFIG_HASH_COUNT; hash++) {
   1137             sc = sal_config_list[hash];
   1138             if (sc != NULL) {
   1139                 break;  
   1140             }
   1141         }
   1142     }
   1143     SAL_GLOBAL_UNLOCK;
   1144     
   1145     if (sc) {     
   1146         *name = sc->sc_name;
   1147         *value = sc->sc_value;
   1148         return 0;
   1149     } else {
   1150         return -1;
   1151     }
   1152 }
   1153 
   1154 /*
   1155  * Function:
   1156  *  sal_config_set
   1157  * Purpose:
   1158  *  Set a sal configuration variable
   1159  * Parameters:
   1160  *  name - name of variable to set
   1161  *  value - name of value; can be NULL to delete a variable
   1162  * Returns:
   1163  *  0 - found and changed
   1164  *  -1 - not found or out of memory
   1165  */
   1166 
   1167 int
   1168 sal_config_set(char *name, char *value)
   1169 {
   1170     sc_t  *sc, *psc;
   1171     char  *newval;
   1172     char    *wildcard = NULL;
   1173     char    *sc_wildcard;
   1174     int     length;
   1175     sc_hash_t hash;
   1176 
   1177     if (name == NULL || *name == '\0') {
   1178         return -1;
   1179     }
   1180 
   1181     SAL_GLOBAL_LOCK;
   1182 
   1183     SC_HASH(name, hash);
   1184     sc = sal_config_list[hash];
   1185     psc = NULL;
   1186     while (sc != NULL) {
   1187         if (sal_strcmp(sc->sc_name, name) == 0) {
   1188             break;
   1189         }
   1190         psc = sc;
   1191         sc = sc->sc_next;
   1192     }
   1193     
   1194     if (sc != NULL) {   /* found */
   1195         if (value == NULL) {  /* delete */
   1196             if (sal_config_list[hash] == sc)  {
   1197                 sal_config_list[hash] = sc->sc_next;
   1198             } else {
   1199                 if (psc !=NULL) {
   1200                     psc->sc_next = sc->sc_next;
   1201                 } 
   1202             }
   1203             FREE_SC(sc);
   1204             SAL_GLOBAL_UNLOCK;
   1205             return 0;
   1206         } else {    /* replace */
   1207             newval = sal_alloc(strlen(value) + 1, "config value");
   1208             if (newval == NULL) {
   1209                 SAL_GLOBAL_UNLOCK;
   1210                 return -1;
   1211             }
   1212             sc->sc_flag = 0;
   1213             sal_strncpy(newval, value, strlen(value));
   1214             newval[strlen(value)] = '\0';
   1215             sal_free(sc->sc_value);
   1216             sc->sc_value = newval;
   1217             SAL_GLOBAL_UNLOCK;
   1218             return 0;
   1219         }
   1220     }
   1221 
   1222     /* not found, delete */
   1223     if (value == NULL) {
   1224         int i;
   1225         wildcard = wildcard_search(name, wildcard, &length);
   1226         if (wildcard != NULL) {
   1227             sc_wildcard = sal_alloc((length + 1), "sc_wildcard");
   1228             *(sc_wildcard+length) = 0;
   1229             for (i = 0; i < MAX_CONFIG_HASH_COUNT; i++) {
   1230                 sc = sal_config_list[i];
   1231                 psc = NULL;
   1232                 while (sc != NULL){
   1233                     sc_wildcard = sal_strncpy(sc_wildcard, sc->sc_name, length);
   1234                     sc_wildcard[length] = '\0';
   1235                     if (sal_strcmp(sc_wildcard, wildcard) == 0) {
   1236                         if (sal_config_list[i] == sc) {
   1237                             sal_config_list[i] = sc->sc_next;
   1238                             FREE_SC(sc);
   1239                             sc = sal_config_list[i]; 
   1240                             psc = NULL;  
   1241                         } else {
   1242                             if (psc !=NULL) {
   1243                                 psc->sc_next = sc->sc_next;
   1244                             } 
   1245                             FREE_SC(sc);
   1246                             if (psc !=NULL) {
   1247                                 sc = psc->sc_next;
   1248                             }
   1249                         }
   1250                     } else {
   1251                         psc = sc;
   1252                         sc = sc->sc_next;
   1253                     }
   1254                 }
   1255             }
   1256             sal_free(wildcard);
   1257             sal_free(sc_wildcard);
   1258             SAL_GLOBAL_UNLOCK;
   1259             return 0;
   1260         } else {
   1261             SAL_GLOBAL_UNLOCK;
   1262             return -1;
   1263         }
   1264     }
   1265 
   1266     
   1267 
   1268     /* not found, add */
   1269     if ((sc = sal_alloc(sizeof(sc_t), "config set")) == NULL) {
   1270         SAL_GLOBAL_UNLOCK;
   1271         return -1;
   1272     }
   1273     sc->sc_flag = 0;
   1274     sc->sc_line = 0;
   1275 
   1276     sc->sc_name = sal_alloc(strlen(name) + 1, "config name");
   1277     sc->sc_value = sal_alloc(strlen(value) + 1, "config value");
   1278 
   1279     if (sc->sc_name == NULL || sc->sc_value == NULL) {
   1280         FREE_SC(sc);
   1281         SAL_GLOBAL_UNLOCK;
   1282         return -1;
   1283     }
   1284 
   1285     sal_strncpy(sc->sc_name, name, strlen(name));
   1286     sc->sc_name[strlen(name)] = '\0';
   1287     sal_strncpy(sc->sc_value, value, strlen(value));
   1288     sc->sc_value[strlen(value)] = '\0';
   1289     sc->sc_hash = hash;
   1290 
   1291     sc->sc_next = sal_config_list[hash];
   1292     sal_config_list[hash] = sc;
   1293 
   1294     SAL_GLOBAL_UNLOCK;
   1295     return 0;
   1296 }
   1297 
   1298 /*
   1299  * Function:
   1300  *  sal_config_show
   1301  * Purpose:
   1302  *  Display current configuration variables.
   1303  * Parameters:
   1304  *  none
   1305  * Returns:
   1306  *  Nothing
   1307  */
   1308 
   1309 void
   1310 sal_config_show(void)
   1311 {
   1312     sc_t  *sc;
   1313     int i;
   1314 
   1315     SAL_GLOBAL_LOCK;
   1316     for (i = 0; i < MAX_CONFIG_HASH_COUNT; i++) {
   1317         for (sc = sal_config_list[i]; sc != NULL; sc = sc->sc_next) {
   1318             sal_printf("\t%s=%s\n", sc->sc_name, sc->sc_value);
   1319         }
   1320     }
   1321     SAL_GLOBAL_UNLOCK;
   1322 }
   1323 
   1324 void
   1325 sal_config_dump(void)
   1326 {
   1327     sc_t  *sc;
   1328     int i;
   1329     const char *fname, *tname;
   1330 
   1331 
   1332     SAL_GLOBAL_LOCK;
   1333     for (i = 0; i < MAX_CONFIG_HASH_COUNT; i++) {
   1334         for (sc = sal_config_list[i]; sc != NULL; sc = sc->sc_next) {
   1335             sal_printf("hash:%4d, line:%4d, flag: 0x%04x, %s=%s\n",
   1336                        i,
   1337                        sc->sc_line,
   1338                        sc->sc_flag,
   1339                        sc->sc_name,
   1340                        sc->sc_value);
   1341         }
   1342     }
   1343     SAL_GLOBAL_UNLOCK;
   1344 
   1345     sal_config_file_get(&fname, &tname);
   1346     sal_printf("\nconfig file:\n\t%s\n", fname);
   1347 
   1348     sal_printf("\nNumber of compiled values:\n\t%4d\n",
   1349                 sal_config_compiled_values);
   1350 
   1351     sal_printf("\nNumber of imported values from %s:\n\t%4d\n",
   1352                 fname,
   1353                 sal_config_imported_values);
   1354 
   1355     sal_printf("\nflags:\n");
   1356     sal_printf("\t#define SC_COMPILE_VALUE 0x%04x\n",SC_COMPILE_VALUE);
   1357     sal_printf("\t#define SC_FLUSHED       0x%04x\n",SC_FLUSHED);
   1358     sal_printf("\t#define SC_HIT           0x%04x\n",SC_HIT);
   1359 
   1360 
   1361 }