diff options
author | Jeremy Kerr <jk@ozlabs.org> | 2008-12-15 15:22:34 +1100 |
---|---|---|
committer | Jeremy Kerr <jk@ozlabs.org> | 2008-12-15 15:22:34 +1100 |
commit | 32e6a41f33e5576716b351bd473a27939fe94fa1 (patch) | |
tree | 0d6b75ac0a02d2496416095405cb9498777c3beb /discover/yaboot-parser.c | |
parent | 000a92b4fa909c432732ac3ed8f28eeeaeac70ee (diff) | |
download | petitboot-32e6a41f33e5576716b351bd473a27939fe94fa1.zip petitboot-32e6a41f33e5576716b351bd473a27939fe94fa1.tar.gz |
Initial support for multiple UIs
Move the device discovery code from separate udev helpers to a single
process to listen on two sockets: one SOCK_DGRAM for incoming udev
events, and one SOCK_STREAM for UIs to connect.
Initial support for client/server infrastructure, still need to wire-up
the udev messages.
Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
Diffstat (limited to 'discover/yaboot-parser.c')
-rw-r--r-- | discover/yaboot-parser.c | 235 |
1 files changed, 235 insertions, 0 deletions
diff --git a/discover/yaboot-parser.c b/discover/yaboot-parser.c new file mode 100644 index 0000000..27b4b78 --- /dev/null +++ b/discover/yaboot-parser.c @@ -0,0 +1,235 @@ + +#include "parser.h" +#include "params.h" +#include "paths.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 char *devpath; +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 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 = resolve_path(cfgopt, devpath); + if (cfgopt == defimage) + pb_log("This one is default. What do we do about it?\n"); + + cfgopt = cfg_get_strg(label, "initrd"); + if (cfgopt) + opt.initrd_file = resolve_path(cfgopt, devpath); + + 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 *device) +{ + char *filepath; + char *conf_file; + char *tmpstr; + ssize_t conf_len; + int fd; + struct stat st; + char *label; + + devpath = strdup(device); + + filepath = resolve_path("/etc/yaboot.conf", devpath); + + fd = open(filepath, O_RDONLY); + if (fd < 0) { + free(filepath); + filepath = resolve_path("/yaboot.conf", devpath); + 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)) { + pb_log("Error parsing yaboot.conf\n"); + return 0; + } + + free(filepath); + + dev = malloc(sizeof(*dev)); + memset(dev, 0, sizeof(*dev)); + dev->id = strdup(devpath); + 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())); + + /* If we have a 'partiton=' directive, update the default devpath + * to use that instead of the current device */ + tmpstr = cfg_get_strg(0, "partition"); + if (tmpstr) { + char *endp; + int partnr = strtol(tmpstr, &endp, 10); + if (endp != tmpstr && !*endp) { + char *new_dev, *tmp; + + new_dev = malloc(strlen(devpath) + strlen(tmpstr) + 1); + if (!new_dev) + return 0; + + strcpy(new_dev, devpath); + + /* Strip digits (partition number) from string */ + endp = new_dev + strlen(devpath) - 1; + while (isdigit(*endp)) + *(endp--) = 0; + + /* and add our own... */ + sprintf(endp + 1, "%d", partnr); + + tmp = devpath; + devpath = parse_device_path(new_dev, devpath); + free(tmp); + free(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 +}; |