summaryrefslogtreecommitdiffstats
path: root/devices
diff options
context:
space:
mode:
authorDavid Woodhouse <dwmw2@infradead.org>2007-04-02 16:30:49 +1000
committerJeremy Kerr <jk@ozlabs.org>2007-04-03 14:15:24 +1000
commit747a0d462cf02ec2b6649f5a3d9b759424d793f8 (patch)
treefbca098101d79eee06495961cce84e5c3707457b /devices
parentf95c710a32afd514b7a1d5072bab0adf7323936b (diff)
downloadtalos-petitboot-747a0d462cf02ec2b6649f5a3d9b759424d793f8.tar.gz
talos-petitboot-747a0d462cf02ec2b6649f5a3d9b759424d793f8.zip
Add some basic yaboot.conf parsing support
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'devices')
-rw-r--r--devices/native-parser.c5
-rw-r--r--devices/udev-helper.c26
-rw-r--r--devices/udev-helper.h2
-rw-r--r--devices/yaboot-cfg.c492
-rw-r--r--devices/yaboot-cfg.h30
-rw-r--r--devices/yaboot-parser.c252
6 files changed, 798 insertions, 9 deletions
diff --git a/devices/native-parser.c b/devices/native-parser.c
index f47fdca..bb1ca51 100644
--- a/devices/native-parser.c
+++ b/devices/native-parser.c
@@ -102,6 +102,7 @@ static int parameter(char *param_name, char *param_value)
int parse(const char *devicepath, const char *_mountpoint)
{
char *filepath;
+ int rc;
mountpoint = _mountpoint;
@@ -112,7 +113,9 @@ int parse(const char *devicepath, const char *_mountpoint)
memset(dev, 0, sizeof(*dev));
dev->id = strdup(devicepath);
- pm_process(filepath, section, parameter);
+ rc = pm_process(filepath, section, parameter);
+ if (!rc)
+ return 0;
if (cur_opt) {
add_boot_option(cur_opt);
diff --git a/devices/udev-helper.c b/devices/udev-helper.c
index ade9787..a3f47a5 100644
--- a/devices/udev-helper.c
+++ b/devices/udev-helper.c
@@ -17,12 +17,14 @@
#include "petitboot-paths.h"
extern struct parser native_parser;
+extern struct parser yaboot_parser;
static FILE *logf;
static int sock;
/* array of parsers, ordered by priority */
static struct parser *parsers[] = {
&native_parser,
+ &yaboot_parser,
NULL
};
@@ -48,13 +50,14 @@ static void print_boot_option(const struct boot_option *opt)
log("\tname: %s\n", opt->name);
log("\tdescription: %s\n", opt->description);
log("\tboot_image: %s\n", opt->boot_image_file);
+ log("\tinitrd: %s\n", opt->initrd_file);
log("\tboot_args: %s\n", opt->boot_args);
}
static void print_device(const struct device *dev)
{
- log("\tid: %s\n", dev->name);
+ log("\tid: %s\n", dev->id);
log("\tname: %s\n", dev->name);
log("\tdescription: %s\n", dev->description);
log("\tboot_image: %s\n", dev->icon_file);
@@ -221,16 +224,21 @@ int connect_to_socket()
#endif
}
-#define template "mnt-XXXXXX"
-
-static int mount_device(const char *dev_path, char *mount_path)
+int mount_device(const char *dev_path, char *mount_path)
{
char *dir;
+ const char *basename;
int pid, status, rc = -1;
- /* create a unique mountpoint */
- dir = malloc(strlen(TMP_DIR) + 2 + strlen(template));
- sprintf(dir, "%s/%s", TMP_DIR, template);
+ basename = strrchr(dev_path, '/');
+ if (basename)
+ basename++;
+ else
+ basename = dev_path;
+
+ /* create a unique mountpoint */
+ dir = malloc(strlen(TMP_DIR) + 13 + strlen(basename));
+ sprintf(dir, "%s/mnt-%s-XXXXXX", TMP_DIR, basename);
if (!mkdtemp(dir)) {
log("failed to create temporary directory in %s: %s",
@@ -414,7 +422,9 @@ int main(int argc, char **argv)
remove_device(dev_path);
- unmount_device(dev_path);
+ /* Unmount it repeatedly, if needs be */
+ while (!unmount_device(dev_path))
+ ;
} else {
log("invalid action '%s'\n", action);
diff --git a/devices/udev-helper.h b/devices/udev-helper.h
index ea5400c..10e5d2b 100644
--- a/devices/udev-helper.h
+++ b/devices/udev-helper.h
@@ -6,6 +6,8 @@ int add_device(const struct device *dev);
int add_boot_option(const struct boot_option *opt);
void free_boot_option(struct boot_option *opt);
+int mount_device(const char *dev_path, char *mount_path);
+
struct parser {
char *name;
int priority;
diff --git a/devices/yaboot-cfg.c b/devices/yaboot-cfg.c
new file mode 100644
index 0000000..a252bdb
--- /dev/null
+++ b/devices/yaboot-cfg.c
@@ -0,0 +1,492 @@
+/*
+ * 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>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <libio.h>
+
+#define prom_printf printf
+#define prom_putchar putchar
+#define prom_vprintf vprintf
+
+/* Imported functions */
+extern int strcasecmp(const char *s1, const char *s2);
+
+typedef enum {
+ cft_strg, cft_flag, cft_end
+} CONFIG_TYPE;
+
+typedef struct {
+ CONFIG_TYPE type;
+ char *name;
+ void *data;
+} CONFIG;
+
+#define MAX_TOKEN 200
+#define MAX_VAR_NAME MAX_TOKEN
+char *cfg_get_default (void);
+
+CONFIG cf_options[] =
+{
+ {cft_strg, "device", NULL},
+ {cft_strg, "partition", NULL},
+ {cft_strg, "default", NULL},
+ {cft_strg, "timeout", NULL},
+ {cft_strg, "password", NULL},
+ {cft_flag, "restricted", NULL},
+ {cft_strg, "message", NULL},
+ {cft_strg, "root", NULL},
+ {cft_strg, "ramdisk", NULL},
+ {cft_flag, "read-only", NULL},
+ {cft_flag, "read-write", NULL},
+ {cft_strg, "append", NULL},
+ {cft_strg, "initrd", NULL},
+ {cft_flag, "initrd-prompt", NULL},
+ {cft_strg, "initrd-size", NULL},
+ {cft_flag, "pause-after", NULL},
+ {cft_strg, "pause-message", NULL},
+ {cft_strg, "init-code", NULL},
+ {cft_strg, "init-message", NULL},
+ {cft_strg, "fgcolor", NULL},
+ {cft_strg, "bgcolor", NULL},
+ {cft_strg, "ptypewarning", NULL},
+ {cft_end, NULL, NULL}};
+
+CONFIG cf_image[] =
+{
+ {cft_strg, "image", NULL},
+ {cft_strg, "label", NULL},
+ {cft_strg, "alias", NULL},
+ {cft_flag, "single-key", NULL},
+ {cft_flag, "restricted", NULL},
+ {cft_strg, "device", NULL},
+ {cft_strg, "partition", NULL},
+ {cft_strg, "root", NULL},
+ {cft_strg, "ramdisk", NULL},
+ {cft_flag, "read-only", NULL},
+ {cft_flag, "read-write", NULL},
+ {cft_strg, "append", NULL},
+ {cft_strg, "literal", NULL},
+ {cft_strg, "initrd", NULL},
+ {cft_flag, "initrd-prompt", NULL},
+ {cft_strg, "initrd-size", NULL},
+ {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 char *last_token = NULL, *last_item = NULL, *last_value = NULL;
+static int line_num;
+static int back = 0; /* can go back by one char */
+static char *currp = NULL;
+static char *endp = NULL;
+static char *file_name = NULL;
+static CONFIG *curr_table = cf_options;
+static jmp_buf env;
+
+static struct IMAGES {
+ CONFIG table[sizeof (cf_image) / sizeof (cf_image[0])];
+ struct IMAGES *next;
+} *images = NULL;
+
+void cfg_error (char *msg,...)
+{
+ va_list ap;
+
+ va_start (ap, msg);
+ prom_printf ("Config file error: ");
+ prom_vprintf (msg, ap);
+ va_end (ap);
+ prom_printf (" near line %d in file %s\n", line_num, file_name);
+ longjmp (env, 1);
+}
+
+void cfg_warn (char *msg,...)
+{
+ va_list ap;
+
+ va_start (ap, msg);
+ prom_printf ("Config file warning: ");
+ prom_vprintf (msg, ap);
+ va_end (ap);
+ prom_printf (" near line %d in file %s\n", line_num, file_name);
+}
+
+inline int cfg_getc ()
+{
+ if (currp == endp)
+ return EOF;
+ return *currp++;
+}
+
+#define next_raw next
+static int next (void)
+{
+ int ch;
+
+ if (!back)
+ return cfg_getc ();
+ ch = back;
+ back = 0;
+ return ch;
+}
+
+static void again (int ch)
+{
+ back = ch;
+}
+
+static char *cfg_get_token (void)
+{
+ char buf[MAX_TOKEN + 1];
+ char *here;
+ int ch, escaped;
+
+ if (last_token) {
+ here = last_token;
+ last_token = NULL;
+ return here;
+ }
+ while (1) {
+ while (ch = next (), ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r')
+ if (ch == '\n' || ch == '\r')
+ line_num++;
+ if (ch == EOF || ch == (int)NULL)
+ return NULL;
+ if (ch != '#')
+ break;
+ while (ch = next_raw (), (ch != '\n' && ch != '\r'))
+ if (ch == EOF)
+ return NULL;
+ line_num++;
+ }
+ if (ch == '=')
+ return strdup ("=");
+ if (ch == '"') {
+ here = buf;
+ while (here - buf < MAX_TOKEN) {
+ if ((ch = next ()) == EOF)
+ cfg_error ("EOF in quoted string");
+ if (ch == '"') {
+ *here = 0;
+ return strdup (buf);
+ }
+ if (ch == '\\') {
+ ch = next ();
+ switch (ch) {
+ case '"':
+ case '\\':
+ break;
+ case '\n':
+ case '\r':
+ while ((ch = next ()), ch == ' ' || ch == '\t');
+ if (!ch)
+ continue;
+ again (ch);
+ ch = ' ';
+ break;
+ case 'n':
+ ch = '\n';
+ break;
+ default:
+ cfg_error ("Bad use of \\ in quoted string");
+ }
+ } else if ((ch == '\n') || (ch == '\r'))
+ cfg_error ("newline is not allowed in quoted strings");
+ *here++ = ch;
+ }
+ cfg_error ("Quoted string is too long");
+ return 0; /* not reached */
+ }
+ here = buf;
+ escaped = 0;
+ while (here - buf < MAX_TOKEN) {
+ if (escaped) {
+ if (ch == EOF)
+ cfg_error ("\\ precedes EOF");
+ if (ch == '\n')
+ line_num++;
+ else
+ *here++ = ch == '\t' ? ' ' : ch;
+ escaped = 0;
+ } else {
+ if (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r' || ch == '#' ||
+ ch == '=' || ch == EOF) {
+ again (ch);
+ *here = 0;
+ return strdup (buf);
+ }
+ if (!(escaped = (ch == '\\')))
+ *here++ = ch;
+ }
+ ch = next ();
+ }
+ cfg_error ("Token is too long");
+ return 0; /* not reached */
+}
+
+static void cfg_return_token (char *token)
+{
+ last_token = token;
+}
+
+static int cfg_next (char **item, char **value)
+{
+ char *this;
+
+ if (last_item) {
+ *item = last_item;
+ *value = last_value;
+ last_item = NULL;
+ return 1;
+ }
+ *value = NULL;
+ if (!(*item = cfg_get_token ()))
+ return 0;
+ if (!strcmp (*item, "="))
+ cfg_error ("Syntax error");
+ if (!(this = cfg_get_token ()))
+ return 1;
+ if (strcmp (this, "=")) {
+ cfg_return_token (this);
+ return 1;
+ }
+ if (!(*value = cfg_get_token ()))
+ cfg_error ("Value expected at EOF");
+ if (!strcmp (*value, "="))
+ cfg_error ("Syntax error after %s", *item);
+ return 1;
+}
+
+#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.
+static void cfg_return (char *item, char *value)
+{
+ last_item = item;
+ last_value = value;
+}
+#endif
+
+static int cfg_set (char *item, char *value)
+{
+ CONFIG *walk;
+
+ if (!strcasecmp (item, "image")) {
+ struct IMAGES **p = &images;
+
+ while (*p)
+ p = &((*p)->next);
+ *p = (struct IMAGES *)malloc (sizeof (struct IMAGES));
+ if (*p == NULL) {
+ prom_printf("malloc error in cfg_set\n");
+ return -1;
+ }
+ (*p)->next = 0;
+ curr_table = ((*p)->table);
+ memcpy (curr_table, cf_image, sizeof (cf_image));
+ }
+ for (walk = curr_table; walk->type != cft_end; walk++) {
+ if (walk->name && !strcasecmp (walk->name, item)) {
+ if (value && walk->type != cft_strg)
+ cfg_warn ("'%s' doesn't have a value", walk->name);
+ else if (!value && walk->type == cft_strg)
+ cfg_warn ("Value expected for '%s'", walk->name);
+ else {
+ if (walk->data)
+ cfg_warn ("Duplicate entry '%s'", walk->name);
+ if (walk->type == cft_flag)
+ walk->data = &flag_set;
+ else if (walk->type == cft_strg)
+ walk->data = value;
+ }
+ break;
+ }
+ }
+ if (walk->type != cft_end)
+ return 1;
+// cfg_return (item, value);
+ return 0;
+}
+
+int cfg_parse (char *cfg_file, char *buff, int len)
+{
+ char *item, *value;
+
+ file_name = cfg_file;
+ currp = buff;
+ endp = currp + len;
+
+ if (setjmp (env))
+ return -1;
+ while (1) {
+ if (!cfg_next (&item, &value))
+ return 0;
+ if (!cfg_set (item, value)) {
+#if DEBUG
+ prom_printf("Can't set item %s to value %s\n", item, value);
+#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;
+ char *label, *alias;
+ char *ret;
+
+ if (!image)
+ return cfg_get_strg_i (cf_options, item);
+ for (p = images; p; p = p->next) {
+ label = cfg_get_strg_i (p->table, "label");
+ if (!label) {
+ label = cfg_get_strg_i (p->table, "image");
+ alias = strrchr (label, '/');
+ if (alias)
+ label = alias + 1;
+ }
+ alias = cfg_get_strg_i (p->table, "alias");
+ if (!strcmp (label, image) || (alias && !strcmp (alias, image))) {
+ ret = cfg_get_strg_i (p->table, item);
+ if (!ret)
+ ret = cfg_get_strg_i (cf_options, item);
+ return ret;
+ }
+ }
+ return 0;
+}
+
+int cfg_get_flag (char *image, char *item)
+{
+ return !!cfg_get_strg (image, item);
+}
+
+static int printl_count = 0;
+static void printlabel (char *label, int defflag)
+{
+ int len = strlen (label);
+
+ if (!printl_count)
+ prom_printf ("\n");
+ prom_printf ("%s %s",defflag?"*":" ", label);
+ while (len++ < 25)
+ prom_putchar (' ');
+ printl_count++;
+ if (printl_count == 3)
+ printl_count = 0;
+}
+
+void cfg_print_images (void)
+{
+ struct IMAGES *p;
+ char *label, *alias;
+
+ char *ret = cfg_get_default();//strg_i (cf_options, "default");
+ int defflag=0;
+
+ printl_count = 0;
+ for (p = images; p; p = p->next) {
+ label = cfg_get_strg_i (p->table, "label");
+ if (!label) {
+ label = cfg_get_strg_i (p->table, "image");
+ alias = strrchr (label, '/');
+ if (alias)
+ label = alias + 1;
+ }
+ if(!strcmp(ret,label))
+ defflag=1;
+ else
+ defflag=0;
+ alias = cfg_get_strg_i (p->table, "alias");
+ printlabel (label, defflag);
+ if (alias)
+ printlabel (alias, 0);
+ }
+ prom_printf("\n");
+}
+
+char *cfg_get_default (void)
+{
+ char *label;
+ 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");
+ if (!ret) {
+ ret = cfg_get_strg_i (images->table, "image");
+ label = strrchr (ret, '/');
+ if (label)
+ ret = label + 1;
+ }
+ return ret;
+}
+
+char *cfg_next_image(char *prev)
+{
+ struct IMAGES *p;
+ char *label, *alias;
+ int wantnext = 0;
+
+ if (!prev)
+ wantnext = 1;
+
+ for (p = images; p; p = p->next) {
+ label = cfg_get_strg_i (p->table, "label");
+ if (!label) {
+ label = cfg_get_strg_i (p->table, "image");
+ alias = strrchr (label, '/');
+ if (alias)
+ label = alias + 1;
+ }
+ if (wantnext)
+ return label;
+ if (!strcmp(prev, label))
+ wantnext = 1;
+ }
+ return NULL;
+}
+/*
+ * Local variables:
+ * c-file-style: "k&r"
+ * c-basic-offset: 5
+ * End:
+ */
diff --git a/devices/yaboot-cfg.h b/devices/yaboot-cfg.h
new file mode 100644
index 0000000..2ab4fec
--- /dev/null
+++ b/devices/yaboot-cfg.h
@@ -0,0 +1,30 @@
+/*
+ * cfg.h - config file parsing definitions
+ *
+ * Copyright (C) 1999 Benjamin Herrenschmidt
+ *
+ * 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.
+ */
+
+#ifndef CFG_H
+#define CFG_H
+
+extern int cfg_parse(char *cfg_file, char *buff, int len);
+extern char* cfg_get_strg(char *image, char *item);
+extern int cfg_get_flag(char *image, char *item);
+extern void cfg_print_images(void);
+extern char* cfg_get_default(void);
+extern char* cfg_next_image(char *);
+#endif
diff --git a/devices/yaboot-parser.c b/devices/yaboot-parser.c
new file mode 100644
index 0000000..ee1b992
--- /dev/null
+++ b/devices/yaboot-parser.c
@@ -0,0 +1,252 @@
+
+#include "udev-helper.h"
+#include "params.h"
+#include "yaboot-cfg.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <sys/param.h>
+
+static struct device *dev;
+static const char *mountpoint;
+static char partition_mntpoint[PATH_MAX];
+static char *defimage;
+
+char *
+make_params(char *label, char *params)
+{
+ char *p, *q;
+ static char buffer[2048];
+
+ q = buffer;
+ *q = 0;
+
+ p = cfg_get_strg(label, "literal");
+ if (p) {
+ strcpy(q, p);
+ q = strchr(q, 0);
+ if (params) {
+ if (*p)
+ *q++ = ' ';
+ strcpy(q, params);
+ }
+ return buffer;
+ }
+
+ p = cfg_get_strg(label, "root");
+ if (p) {
+ strcpy (q, "root=");
+ strcpy (q + 5, p);
+ q = strchr (q, 0);
+ *q++ = ' ';
+ }
+ if (cfg_get_flag(label, "read-only")) {
+ strcpy (q, "ro ");
+ q += 3;
+ }
+ if (cfg_get_flag(label, "read-write")) {
+ strcpy (q, "rw ");
+ q += 3;
+ }
+ p = cfg_get_strg(label, "ramdisk");
+ if (p) {
+ strcpy (q, "ramdisk=");
+ strcpy (q + 8, p);
+ q = strchr (q, 0);
+ *q++ = ' ';
+ }
+ p = cfg_get_strg(label, "initrd-size");
+ if (p) {
+ strcpy (q, "ramdisk_size=");
+ strcpy (q + 13, p);
+ q = strchr (q, 0);
+ *q++ = ' ';
+ }
+ if (cfg_get_flag(label, "novideo")) {
+ strcpy (q, "video=ofonly");
+ q = strchr (q, 0);
+ *q++ = ' ';
+ }
+ p = cfg_get_strg (label, "append");
+ if (p) {
+ strcpy (q, p);
+ q = strchr (q, 0);
+ *q++ = ' ';
+ }
+ *q = 0;
+ if (params)
+ strcpy(q, params);
+
+ return buffer;
+}
+
+static char *prepend_mountpoint(const char *path)
+{
+ char *full_path;
+
+ full_path = malloc(strlen(path) + strlen(mountpoint) + 2);
+
+ strcpy(full_path, mountpoint);
+ if (path[0] != '/')
+ strcat(full_path, "/");
+ strcat(full_path, path);
+
+ return full_path;
+}
+
+static int check_and_add_device(struct device *dev)
+{
+ if (!dev->icon_file)
+ dev->icon_file = strdup(generic_icon_file(guess_device_type()));
+
+ return !add_device(dev);
+}
+
+void process_image(char *label)
+{
+ struct boot_option opt;
+ char *cfgopt;
+
+ memset(&opt, 0, sizeof(opt));
+
+ opt.name = label;
+ cfgopt = cfg_get_strg(label, "image");
+ opt.boot_image_file = prepend_mountpoint(cfgopt);
+ if (cfgopt == defimage)
+ printf("This one is default. What do we do about it?\n");
+
+ cfgopt = cfg_get_strg(label, "initrd");
+ if (cfgopt)
+ opt.initrd_file = prepend_mountpoint(cfgopt);
+
+ opt.boot_args = make_params(label, NULL);
+
+ add_boot_option(&opt);
+
+ if (opt.initrd_file)
+ free(opt.initrd_file);
+}
+
+static int yaboot_parse(const char *devicepath, const char *_mountpoint)
+{
+ char *filepath;
+ char *conf_file;
+ char *tmpstr;
+ ssize_t conf_len;
+ int fd;
+ struct stat st;
+ char *label;
+
+ mountpoint = _mountpoint;
+
+ filepath = prepend_mountpoint("/etc/yaboot.conf");
+
+ fd = open(filepath, O_RDONLY);
+ if (fd < 0) {
+ free(filepath);
+ filepath = prepend_mountpoint("/yaboot.conf");
+ fd = open(filepath, O_RDONLY);
+
+ if (fd < 0)
+ return 0;
+ }
+
+ if (fstat(fd, &st)) {
+ close(fd);
+ return 0;
+ }
+
+ conf_file = malloc(st.st_size+1);
+ if (!conf_file) {
+ close(fd);
+ return 0;
+ }
+
+ conf_len = read(fd, conf_file, st.st_size);
+ if (conf_len < 0) {
+ close(fd);
+ return 0;
+ }
+ conf_file[conf_len] = 0;
+
+ close(fd);
+
+ if (cfg_parse(filepath, conf_file, conf_len)) {
+ printf("Error parsing yaboot.conf\n");
+ return 0;
+ }
+
+ free(filepath);
+
+ dev = malloc(sizeof(*dev));
+ memset(dev, 0, sizeof(*dev));
+ dev->id = strdup(devicepath);
+ if (cfg_get_strg(0, "init-message")) {
+ char *newline;
+ dev->description = strdup(cfg_get_strg(0, "init-message"));
+ newline = strchr(dev->description, '\n');
+ if (newline)
+ *newline = 0;
+ }
+ dev->icon_file = strdup(generic_icon_file(guess_device_type()));
+
+ /* Mount the 'partition' which is what all the image filenames
+ are relative to */
+ tmpstr = cfg_get_strg(0, "partition");
+ if (tmpstr) {
+ char *endp;
+ int partnr = strtol(tmpstr, &endp, 10);
+ if (endp != tmpstr && !*endp) {
+ char *new_dev = malloc(strlen(devicepath) + strlen(tmpstr) + 1);
+ if (!new_dev)
+ return 0;
+
+ strcpy(new_dev, devicepath);
+
+ /* Strip digits (partition number) from string */
+ endp = &new_dev[strlen(devicepath) - 1];
+ while (isdigit(*endp))
+ *(endp--) = 0;
+
+ /* and add our own... */
+ sprintf(endp+1, "%d", partnr);
+
+ /* FIXME: udev may not have created the device node
+ yet. And on removal, unmount_device() only unmounts
+ it once, while in fact it may be mounted twice. */
+ if (mount_device(new_dev, partition_mntpoint)) {
+ printf("Error mounting image partition\n");
+ return 0;
+ }
+ mountpoint = partition_mntpoint;
+ dev->id = new_dev;
+ }
+ }
+
+ defimage = cfg_get_default();
+ if (!defimage)
+ return 0;
+ defimage = cfg_get_strg(defimage, "image");
+
+ label = cfg_next_image(NULL);
+ if (!label || !check_and_add_device(dev))
+ return 0;
+
+ do {
+ process_image(label);
+ } while ((label = cfg_next_image(label)));
+
+ return 1;
+}
+
+struct parser yaboot_parser = {
+ .name = "yaboot.conf parser",
+ .priority = 99,
+ .parse = yaboot_parse
+};
OpenPOWER on IntegriCloud