-/* Handling and parsing of silo.conf
-
- Copyright (C) 1995 Werner Almesberger
- 1996 Jakub Jelinek
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+/*
+ * cfg.c - Handling and parsing of yaboot.conf
+ *
+ * Copyright (C) 1995 Werner Almesberger
+ * 1996 Jakub Jelinek
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
#include "setjmp.h"
#include "stdarg.h"
/* Imported functions */
extern int strcasecmp(const char *s1, const char *s2);
+extern int strncasecmp(const char *cs, const char *ct, size_t n);
+extern char bootoncelabel[1024];
typedef enum {
cft_strg, cft_flag, cft_end
void *data;
} CONFIG;
-#define MAX_TOKEN 200
-#define MAX_VAR_NAME MAX_TOKEN
+#define MAX_TOKEN 511
#define EOF -1
CONFIG cf_options[] =
{cft_flag, "pause-after", NULL},
{cft_strg, "pause-message", NULL},
{cft_flag, "novideo", NULL},
- {cft_strg, "sysmap", NULL},
{cft_end, NULL, NULL}};
static char flag_set;
static struct IMAGES {
CONFIG table[sizeof (cf_image) / sizeof (cf_image[0])];
+ int obsolete;
struct IMAGES *next;
} *images = NULL;
return 1;
}
+static char *cfg_get_strg_i (CONFIG * table, char *item)
+{
+ CONFIG *walk;
+
+ for (walk = table; walk->type != cft_end; walk++)
+ if (walk->name && !strcasecmp (walk->name, item))
+ return walk->data;
+ return 0;
+}
+
#if 0
// The one and only call to this procedure is commented out
// below, so we don't need this unless we decide to use it again.
}
#endif
+static int match_arch(const char *name)
+{
+ static prom_handle root;
+ static char model[256], *p;
+
+ if (!root) {
+ if (!(root = prom_finddevice("/")))
+ return 0;
+ }
+
+ if (!model[0]) {
+ if (!prom_getprop(root, "compatible", model, sizeof(model)))
+ return 0;
+ }
+
+ for (p = model; *p; p += strlen(p) + 1) {
+ if (!strcasecmp(p, name))
+ return 1;
+ }
+
+ return 0;
+}
+
+static void check_for_obsolete(const char *label)
+{
+ struct IMAGES *p;
+ char *cur_label;
+
+ /* Make sure our current entry isn't obsolete (ignored) */
+ for (p = images; p; p = p->next) {
+ if (curr_table == p->table && p->obsolete)
+ return;
+ }
+
+ for (p = images; p; p = p->next) {
+ if (curr_table == p->table)
+ continue;
+
+ cur_label = cfg_get_strg_i (p->table, "label");
+ if (!cur_label)
+ cur_label = cfg_get_strg_i (p->table, "image");
+
+ if (!cur_label)
+ continue;
+
+ if (!strcasecmp(cur_label, label))
+ p->obsolete = 1;
+ }
+}
+
static int cfg_set (char *item, char *value)
{
CONFIG *walk;
- if (!strcasecmp (item, "image")) {
+ if (!strncasecmp (item, "image", 5)) {
struct IMAGES **p = &images;
+ int ignore = 0;
+
+ if (item[5] == '[' && item[strlen(item) - 1] == ']') {
+ char *s, *q = item;
+ /* Get rid of braces */
+ item[strlen(item) - 1] = 0;
+ item[5] = 0;
+
+ for (s = item + 6; q; s = q) {
+ q = strchr(s, '|');
+ if (q)
+ *q++ = 0;
+
+ if (match_arch(s))
+ goto cfg_set_cont;
+ }
+ /* This just creates an unused table. It will get ignored */
+ ignore = 1;
+ } else if (item[5])
+ goto cfg_set_redo;
+
+cfg_set_cont:
while (*p)
p = &((*p)->next);
*p = (struct IMAGES *)malloc (sizeof (struct IMAGES));
return -1;
}
(*p)->next = 0;
+ (*p)->obsolete = ignore;
curr_table = ((*p)->table);
memcpy (curr_table, cf_image, sizeof (cf_image));
}
+
+cfg_set_redo:
for (walk = curr_table; walk->type != cft_end; walk++) {
if (walk->name && !strcasecmp (walk->name, item)) {
if (value && walk->type != cft_strg)
else if (!value && walk->type == cft_strg)
cfg_warn ("Value expected for '%s'", walk->name);
else {
+ if (!strcasecmp (item, "label"))
+ check_for_obsolete(value);
if (walk->data)
cfg_warn ("Duplicate entry '%s'", walk->name);
if (walk->type == cft_flag)
break;
}
}
+
if (walk->type != cft_end)
return 1;
-// cfg_return (item, value);
+
+ //cfg_return (item, value);
+
return 0;
}
+static int cfg_reset ()
+{
+ CONFIG *walk;
+#if DEBUG
+ prom_printf("Resetting image table\n");
+#endif
+ line_num = 0;
+ images = NULL;
+ curr_table = NULL;
+ curr_table = cf_options;
+ for (walk = curr_table; walk->type != cft_end; walk++) {
+#if DEBUG
+ prom_printf("ItemA %s = %s\n", walk->name, walk->data);
+#endif
+ if (walk->data != NULL)
+ walk->data = NULL;
+#if DEBUG
+ prom_printf("ItemB %s = %s\n\n", walk->name, walk->data);
+#endif
+ }
+
+ return 0;
+}
+
int cfg_parse (char *cfg_file, char *buff, int len)
{
char *item, *value;
currp = buff;
endp = currp + len;
+ cfg_reset();
+
if (setjmp (env))
return -1;
while (1) {
if (!cfg_set (item, value)) {
#if DEBUG
prom_printf("Can't set item %s to value %s\n", item, value);
-#endif
+#endif
}
free (item);
}
}
-static char *cfg_get_strg_i (CONFIG * table, char *item)
-{
- CONFIG *walk;
-
- for (walk = table; walk->type != cft_end; walk++)
- if (walk->name && !strcasecmp (walk->name, item))
- return walk->data;
- return 0;
-}
-
char *cfg_get_strg (char *image, char *item)
{
struct IMAGES *p;
if (!image)
return cfg_get_strg_i (cf_options, item);
for (p = images; p; p = p->next) {
+ if (p->obsolete)
+ continue;
+
label = cfg_get_strg_i (p->table, "label");
if (!label) {
label = cfg_get_strg_i (p->table, "image");
static void printlabel (char *label, int defflag)
{
int len = strlen (label);
+ char a = ' ';
if (!printl_count)
prom_printf ("\n");
- prom_printf ("%s %s",defflag?"*":" ", label);
+ switch (defflag) {
+ case 1: a='*'; break;
+ case 2: a='&'; break;
+ default: a=' '; break;
+ }
+ prom_printf ("%c %s", a, label);
while (len++ < 25)
prom_putchar (' ');
printl_count++;
printl_count = 0;
for (p = images; p; p = p->next) {
+ if (p->obsolete)
+ continue;
+
label = cfg_get_strg_i (p->table, "label");
if (!label) {
label = cfg_get_strg_i (p->table, "image");
if (alias)
label = alias + 1;
}
- if(!strcmp(ret,label))
+ if(!strcmp(bootoncelabel,label))
+ defflag=2;
+ else if(!strcmp(ret,label))
defflag=1;
else
defflag=0;
char *cfg_get_default (void)
{
char *label;
+ struct IMAGES *p;
char *ret = cfg_get_strg_i (cf_options, "default");
if (ret)
return ret;
if (!images)
return 0;
- ret = cfg_get_strg_i (images->table, "label");
+
+ for (p = images; p && p->obsolete; p = p->next);
+ if (!p)
+ return 0;
+
+ ret = cfg_get_strg_i (p->table, "label");
if (!ret) {
- ret = cfg_get_strg_i (images->table, "image");
+ ret = cfg_get_strg_i (p->table, "image");
label = strrchr (ret, '/');
if (label)
ret = label + 1;
return ret;
}
-/*
+/*
+ * cfg_set_default_by_mac ()
+ * return 1 if the default cf_option was changed to label with the MAC addr
+ * return 0 if not changed
+ */
+int cfg_set_default_by_mac (char *mac_addr)
+{
+ CONFIG *walk;
+ struct IMAGES *tmp;
+ char * label = NULL;
+ int haslabel = 0;
+
+ /* check if there is an image label equal to mac_addr */
+ for (tmp = images; tmp; tmp = tmp->next) {
+ label = cfg_get_strg_i (tmp->table, "label");
+ if (!strcmp(label,mac_addr)){
+ haslabel = 1;
+ }
+ }
+
+ if (!haslabel)
+ return 0;
+ else {
+ /*
+ * if there is an image label equal to mac_addr, change the default
+ * cf_options to this image label
+ */
+ for (walk = cf_options; walk->type != cft_end; walk++) {
+ if (!strcasecmp(walk->name,"default")) {
+ walk->data = mac_addr;
+ return 1;
+ }
+ }
+ return 0;
+ }
+}
+
+/*
* Local variables:
- * c-file-style: "K&R"
+ * c-file-style: "k&r"
* c-basic-offset: 5
* End:
*/