diff options
author | Jeremy Kerr <jk@ozlabs.org> | 2009-01-02 16:34:18 +0900 |
---|---|---|
committer | Jeremy Kerr <jk@ozlabs.org> | 2009-01-02 16:34:18 +0900 |
commit | ce5eab024583af5a4725503bad6ed2aee452b1aa (patch) | |
tree | 534753bfa7fd65f6c173f62e75995adc6376ff9f | |
parent | b118597194815910897ccf86d77b8b5a066adf5a (diff) | |
download | talos-petitboot-ce5eab024583af5a4725503bad6ed2aee452b1aa.tar.gz talos-petitboot-ce5eab024583af5a4725503bad6ed2aee452b1aa.zip |
Hook up parsers to device discovery
Iterate the parsers from the device handler on an add event.
Initial change to just the kboot parser.
Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
-rw-r--r-- | discover/device-handler.c | 28 | ||||
-rw-r--r-- | discover/device-handler.h | 14 | ||||
-rw-r--r-- | discover/discover-server.c | 20 | ||||
-rw-r--r-- | discover/discover-server.h | 5 | ||||
-rw-r--r-- | discover/kboot-parser.c | 155 | ||||
-rw-r--r-- | discover/parser-utils.c | 53 | ||||
-rw-r--r-- | discover/parser-utils.h | 17 | ||||
-rw-r--r-- | discover/parser.c | 69 | ||||
-rw-r--r-- | discover/parser.h | 33 | ||||
-rw-r--r-- | rules.mk | 7 |
10 files changed, 224 insertions, 177 deletions
diff --git a/discover/device-handler.c b/discover/device-handler.c index 1f8938f..593b8e0 100644 --- a/discover/device-handler.c +++ b/discover/device-handler.c @@ -11,6 +11,8 @@ #include <pb-protocol/pb-protocol.h> #include "device-handler.h" +#include "discover-server.h" +#include "parser.h" #include "udev.h" #include "log.h" #include "paths.h" @@ -28,18 +30,6 @@ struct device_handler { struct list contexts; }; -struct discover_context { - char *id; - char *device_path; - char *mount_path; - struct udev_event *event; - struct device *device; - char **links; - int n_links; - - struct list_item list; -}; - struct mount_map { char *device_path; char *mount_point; @@ -335,9 +325,18 @@ static int handle_add_event(struct device_handler *handler, } list_add(&handler->contexts, &ctx->list); - talloc_set_destructor(ctx, destroy_context); + /* set up the top-level device */ + ctx->device = talloc_zero(ctx, struct device); + ctx->device->id = talloc_strdup(ctx->device, ctx->id); + list_init(&ctx->device->boot_options); + + /* run the parsers */ + iterate_parsers(ctx); + + discover_server_notify_add(handler->server, ctx->device); + return 0; } @@ -350,6 +349,8 @@ static int handle_remove_event(struct device_handler *handler, if (!ctx) return 0; + discover_server_notify_remove(handler->server, ctx->device); + talloc_free(ctx); return 0; @@ -381,6 +382,7 @@ struct device_handler *device_handler_init(struct discover_server *server) handler = talloc(NULL, struct device_handler); handler->devices = NULL; handler->n_devices = 0; + handler->server = server; list_init(&handler->contexts); diff --git a/discover/device-handler.h b/discover/device-handler.h index ddcb201..cd28420 100644 --- a/discover/device-handler.h +++ b/discover/device-handler.h @@ -1,11 +1,25 @@ #ifndef _DEVICE_HANDLER_H #define _DEVICE_HANDLER_H +#include <list/list.h> + struct device_handler; struct discover_server; struct udev_event; struct device; +struct discover_context { + char *id; + char *device_path; + char *mount_path; + struct udev_event *event; + struct device *device; + char **links; + int n_links; + + struct list_item list; +}; + struct device_handler *device_handler_init(struct discover_server *server); void device_handler_destroy(struct device_handler *devices); diff --git a/discover/discover-server.c b/discover/discover-server.c index 225f58c..8ec1949 100644 --- a/discover/discover-server.c +++ b/discover/discover-server.c @@ -154,6 +154,26 @@ static int discover_server_process(void *arg) return 0; } +void discover_server_notify_add(struct discover_server *server, + struct device *device) +{ + struct client *client; + + list_for_each_entry(&server->clients, client, list) + write_add_message(server, client, device); + +} + +void discover_server_notify_remove(struct discover_server *server, + struct device *device) +{ + struct client *client; + + list_for_each_entry(&server->clients, client, list) + write_remove_message(server, client, device->id); + +} + void discover_server_set_device_source(struct discover_server *server, struct device_handler *handler) { diff --git a/discover/discover-server.h b/discover/discover-server.h index e5d7881..7c89938 100644 --- a/discover/discover-server.h +++ b/discover/discover-server.h @@ -3,6 +3,7 @@ struct discover_server; struct device_handler; +struct device; struct discover_server *discover_server_init(void); @@ -11,4 +12,8 @@ void discover_server_destroy(struct discover_server *server); void discover_server_set_device_source(struct discover_server *server, struct device_handler *handler); +void discover_server_notify_add(struct discover_server *server, + struct device *device); +void discover_server_notify_remove(struct discover_server *server, + struct device *device); #endif /* _DISCOVER_SERVER_H */ diff --git a/discover/kboot-parser.c b/discover/kboot-parser.c index df2e762..f227ee3 100644 --- a/discover/kboot-parser.c +++ b/discover/kboot-parser.c @@ -10,12 +10,28 @@ #include <sys/types.h> #include <sys/stat.h> -#include "parser.h" +#include <talloc/talloc.h> + +#include "log.h" +#include "pb-protocol/pb-protocol.h" +#include "paths.h" #include "params.h" +#include "parser-utils.h" +#include "device-handler.h" #define buf_size 1024 -static const char *devpath; +struct kboot_context { + struct discover_context *discover; + + char *buf; + + struct global_option { + char *name; + char *value; + } *global_options; + int n_global_options; +}; static int param_is_ignored(const char *param) { @@ -76,12 +92,6 @@ static char *get_param_pair(char *str, char **name_out, char **value_out, return tmp ? tmp + 1 : NULL; } -struct global_option { - char *name; - char *value; -}; - - static struct global_option global_options[] = { { .name = "root" }, { .name = "initrd" }, @@ -93,20 +103,21 @@ static struct global_option global_options[] = { * Check if an option (name=value) is a global option. If so, store it in * the global options table, and return 1. Otherwise, return 0. */ -static int check_for_global_option(const char *name, const char *value) +static int check_for_global_option(struct kboot_context *ctx, + const char *name, const char *value) { int i; - for (i = 0; global_options[i].name ;i++) { - if (!strcmp(name, global_options[i].name)) { + for (i = 0; i < ctx->n_global_options; i++) { + if (!strcmp(name, ctx->global_options[i].name)) { global_options[i].value = strdup(value); - return 1; + break; } } return 0; } -static char *get_global_option(const char *name) +static char *get_global_option(struct kboot_context *ctx, const char *name) { int i; @@ -117,9 +128,11 @@ static char *get_global_option(const char *name) return NULL; } -static int parse_option(struct boot_option *opt, char *config) +static int parse_option(struct kboot_context *kboot_ctx, char *opt_name, + char *config) { char *pos, *name, *value, *root, *initrd, *cmdline, *tmp; + struct boot_option *opt; root = initrd = cmdline = NULL; @@ -136,17 +149,24 @@ static int parse_option(struct boot_option *opt, char *config) pos = strchr(config, ' '); + opt = talloc_zero(kboot_ctx, struct boot_option); + opt->id = talloc_asprintf(opt, "%s#%s", + kboot_ctx->discover->device->id, opt_name); + opt->name = talloc_strdup(opt, opt_name); + /* if there's no space, it's only a kernel image with no params */ if (!pos) { - opt->boot_image_file = resolve_path(config, devpath); - opt->description = strdup(config); - return 1; + opt->boot_image_file = resolve_path(opt, config, + kboot_ctx->discover->device_path); + opt->description = talloc_strdup(opt, config); + goto out_add; } *pos = 0; - opt->boot_image_file = resolve_path(config, devpath); + opt->boot_image_file = resolve_path(opt, config, + kboot_ctx->discover->device_path); - cmdline = malloc(buf_size); + cmdline = talloc_array(opt, char, buf_size); *cmdline = 0; for (pos++; pos;) { @@ -170,119 +190,108 @@ static int parse_option(struct boot_option *opt, char *config) } if (!root) - root = get_global_option("root"); + root = get_global_option(kboot_ctx, "root"); if (!initrd) - initrd = get_global_option("initrd"); + initrd = get_global_option(kboot_ctx, "initrd"); if (initrd) { - asprintf(&tmp, "initrd=%s %s", initrd, cmdline); - free(cmdline); + tmp = talloc_asprintf(opt, "initrd=%s %s", initrd, cmdline); + talloc_free(cmdline); cmdline = tmp; - opt->initrd_file = resolve_path(initrd, devpath); + opt->initrd_file = resolve_path(opt, initrd, + kboot_ctx->discover->device_path); } if (root) { - asprintf(&tmp, "root=%s %s", root, cmdline); - free(cmdline); + tmp = talloc_asprintf(opt, "root=%s %s", root, cmdline); + talloc_free(cmdline); cmdline = tmp; } else if (initrd) { /* if there's an initrd but no root, fake up /dev/ram0 */ - asprintf(&tmp, "root=/dev/ram0 %s", cmdline); - free(cmdline); + tmp = talloc_asprintf(opt, "root=/dev/ram0 %s", cmdline); + talloc_free(cmdline); cmdline = tmp; } - pb_log("kboot cmdline: %s\n", cmdline); opt->boot_args = cmdline; - asprintf(&opt->description, "%s %s", + opt->description = talloc_asprintf(opt, "%s %s", config, opt->boot_args); +out_add: + device_add_boot_option(kboot_ctx->discover->device, opt); return 1; } -static void parse_buf(struct device *dev, char *buf) +static void parse_buf(struct kboot_context *kboot_ctx) { char *pos, *name, *value; - int sent_device = 0; - - for (pos = buf; pos;) { - struct boot_option opt; + for (pos = kboot_ctx->buf; pos;) { pos = get_param_pair(pos, &name, &value, '\n'); - pb_log("kboot param: '%s' = '%s'\n", name, value); - if (name == NULL || param_is_ignored(name)) continue; if (*name == '#') continue; - if (check_for_global_option(name, value)) + if (check_for_global_option(kboot_ctx, name, value)) continue; - memset(&opt, 0, sizeof(opt)); - opt.name = strdup(name); - - if (parse_option(&opt, value)) - if (!sent_device++) - add_device(dev); - add_boot_option(&opt); - - free(opt.name); + parse_option(kboot_ctx, name, value); } } -static int parse(const char *device) + +static int parse(struct discover_context *ctx) { - char *filepath, *buf; - int fd, len, rc = 0; + struct kboot_context *kboot_ctx; + char *filepath; + int fd, len, rc; struct stat stat; - struct device *dev; - devpath = device; + rc = 0; + fd = -1; + + kboot_ctx = talloc_zero(ctx, struct kboot_context); + kboot_ctx->discover = ctx; - filepath = resolve_path("/etc/kboot.conf", devpath); + filepath = resolve_path(kboot_ctx, "/etc/kboot.conf", ctx->device_path); fd = open(filepath, O_RDONLY); if (fd < 0) - goto out_free_path; + goto out; if (fstat(fd, &stat)) - goto out_close; + goto out; - buf = malloc(stat.st_size + 1); - if (!buf) - goto out_close;; + kboot_ctx->buf = talloc_array(kboot_ctx, char, stat.st_size + 1); - len = read(fd, buf, stat.st_size); + len = read(fd, kboot_ctx->buf, stat.st_size); if (len < 0) - goto out_free_buf; - buf[len] = 0; + goto out; + kboot_ctx->buf[len] = 0; - dev = malloc(sizeof(*dev)); - memset(dev, 0, sizeof(*dev)); - dev->id = strdup(device); - dev->icon_file = strdup(generic_icon_file(guess_device_type())); + if (!ctx->device->icon_file) + ctx->device->icon_file = talloc_strdup(ctx, + generic_icon_file(guess_device_type(ctx))); - parse_buf(dev, buf); + parse_buf(kboot_ctx); rc = 1; -out_free_buf: - free(buf); -out_close: - close(fd); -out_free_path: - free(filepath); +out: + if (fd >= 0) + close(fd); + talloc_free(kboot_ctx); return rc; } struct parser kboot_parser = { - .name = "kboot.conf parser", + .name = "kboot.conf parser", .priority = 98, .parse = parse }; diff --git a/discover/parser-utils.c b/discover/parser-utils.c new file mode 100644 index 0000000..4982112 --- /dev/null +++ b/discover/parser-utils.c @@ -0,0 +1,53 @@ + +#include <string.h> + +#include <talloc/talloc.h> + +#include "pb-protocol/pb-protocol.h" +#include "udev.h" +#include "device-handler.h" +#include "parser-utils.h" + +void device_add_boot_option(struct device *device, + struct boot_option *boot_option) +{ + list_add(&device->boot_options, &boot_option->list); + talloc_steal(device, boot_option); +} + +const char *generic_icon_file(enum generic_icon_type type) +{ + switch (type) { + case ICON_TYPE_DISK: + return artwork_pathname("hdd.png"); + case ICON_TYPE_USB: + return artwork_pathname("usbpen.png"); + case ICON_TYPE_OPTICAL: + return artwork_pathname("cdrom.png"); + case ICON_TYPE_NETWORK: + case ICON_TYPE_UNKNOWN: + break; + } + return artwork_pathname("hdd.png"); +} + +enum generic_icon_type guess_device_type(struct discover_context *ctx) +{ + struct udev_event *event; + const char *type, *bus; + + event = ctx->event; + + type = udev_event_param(event, "ID_TYPE"); + bus = udev_event_param(event, "ID_BUS"); + + if (type && streq(type, "cd")) + return ICON_TYPE_OPTICAL; + if (!bus) + return ICON_TYPE_UNKNOWN; + if (streq(bus, "usb")) + return ICON_TYPE_USB; + if (streq(bus, "ata") || streq(bus, "scsi")) + return ICON_TYPE_DISK; + return ICON_TYPE_UNKNOWN; +} diff --git a/discover/parser-utils.h b/discover/parser-utils.h new file mode 100644 index 0000000..e82e3f9 --- /dev/null +++ b/discover/parser-utils.h @@ -0,0 +1,17 @@ +#ifndef PARSER_UTILS_H +#define PARSER_UTILS_H + +#include "parser.h" + +#define streq(a,b) (!strcasecmp((a),(b))) + +#define artwork_pathname(file) (PKG_SHARE_DIR "/artwork/" file) + +void device_add_boot_option(struct device *device, + struct boot_option *boot_option); + +const char *generic_icon_file(enum generic_icon_type type); + +enum generic_icon_type guess_device_type(struct discover_context *ctx); + +#endif /* PARSER_UTILS_H */ diff --git a/discover/parser.c b/discover/parser.c index 5e50dcb..5b1a7ab 100644 --- a/discover/parser.c +++ b/discover/parser.c @@ -1,85 +1,30 @@ -#include <petitboot-paths.h> #include <stdlib.h> -#include <string.h> -#include "parser.h" +#include "pb-protocol/pb-protocol.h" -extern struct parser native_parser; -extern struct parser yaboot_parser; +#include "device-handler.h" +#include "log.h" +#include "parser.h" extern struct parser kboot_parser; /* array of parsers, ordered by priority */ static struct parser *parsers[] = { - &native_parser, - &yaboot_parser, &kboot_parser, NULL }; -void iterate_parsers(const char *devpath, const char *mountpoint) +void iterate_parsers(struct discover_context *ctx) { int i; - pb_log("trying parsers for %s\n", devpath); + pb_log("trying parsers for %s\n", ctx->device_path); for (i = 0; parsers[i]; i++) { pb_log("\ttrying parser '%s'\n", parsers[i]->name); /* just use a dummy device path for now */ - if (parsers[i]->parse(devpath)) + if (parsers[i]->parse(ctx)) return; } pb_log("\tno boot_options found\n"); } - -/* convenience functions for parsers */ -void free_device(struct device *dev) -{ - if (!dev) - return; - if (dev->id) - free(dev->id); - if (dev->name) - free(dev->name); - if (dev->description) - free(dev->description); - if (dev->icon_file) - free(dev->icon_file); - free(dev); -} - -void free_boot_option(struct boot_option *opt) -{ - if (!opt) - return; - if (opt->name) - free(opt->name); - if (opt->description) - free(opt->description); - if (opt->icon_file) - free(opt->icon_file); - if (opt->boot_image_file) - free(opt->boot_image_file); - if (opt->initrd_file) - free(opt->initrd_file); - if (opt->boot_args) - free(opt->boot_args); - free(opt); -} - -const char *generic_icon_file(enum generic_icon_type type) -{ - switch (type) { - case ICON_TYPE_DISK: - return artwork_pathname("hdd.png"); - case ICON_TYPE_USB: - return artwork_pathname("usbpen.png"); - case ICON_TYPE_OPTICAL: - return artwork_pathname("cdrom.png"); - case ICON_TYPE_NETWORK: - case ICON_TYPE_UNKNOWN: - break; - } - return artwork_pathname("hdd.png"); -} - diff --git a/discover/parser.h b/discover/parser.h index 9c6fb35..bf9a4d0 100644 --- a/discover/parser.h +++ b/discover/parser.h @@ -1,14 +1,12 @@ +#ifndef _PARSER_H +#define _PARSER_H -#ifndef _PARSERS_H -#define _PARSERS_H - -#include <stdarg.h> -#include "message.h" +struct discover_context; struct parser { char *name; int priority; - int (*parse)(const char *device); + int (*parse)(struct discover_context *ctx); struct parser *next; }; @@ -22,25 +20,6 @@ enum generic_icon_type { #define streq(a,b) (!strcasecmp((a),(b))) -/* general functions provided by parsers.c */ -void iterate_parsers(const char *devpath, const char *mountpoint); - -void free_device(struct device *dev); -void free_boot_option(struct boot_option *opt); - -const char *generic_icon_file(enum generic_icon_type type); - -/* functions provided by udev-helper or the test wrapper */ -void pb_log(const char *fmt, ...); - -int mount_device(const char *dev_path); - -char *resolve_path(const char *path, const char *current_dev); -const char *mountpoint_for_device(const char *dev_path); - -enum generic_icon_type guess_device_type(void); - -int add_device(const struct device *dev); -int add_boot_option(const struct boot_option *opt); +void iterate_parsers(struct discover_context *ctx); -#endif /* _PARSERS_H */ +#endif /* _PARSER_H */ @@ -9,13 +9,16 @@ DEFS += '-DPREFIX="$(prefix)"' '-DPKG_SHARE_DIR="$(pkgdatadir)"' \ #uis = ui/twin/pb-twin uis = ui/test/pb-test -parsers = native yaboot kboot +#parsers = native yaboot kboot +parsers = kboot artwork = background.jpg cdrom.png hdd.png usbpen.png tux.png cursor.gz talloc_objs = lib/talloc/talloc.o list_objs = lib/list/list.o server_objs = lib/pb-protocol/pb-protocol.o +parser_objs = discover/parser.o discover/parser-utils.o \ + $(foreach p, $(parsers), discover/$(p)-parser.o) parser_test_objs = parser-test.o $(parser_objs) @@ -45,7 +48,7 @@ ui/test/pb-test: $(pb_test_objs) pb_discover_objs = discover/pb-discover.o discover/udev.o discover/log.o \ discover/waiter.o discover/discover-server.o \ discover/device-handler.o discover/paths.o \ - $(talloc_objs) $(server_objs) $(list_objs) + $(talloc_objs) $(server_objs) $(parser_objs) $(list_objs) discover/pb-discover: $(pb_discover_objs) $(LINK.o) -o $@ $^ |