Hookup kexec
authorDavid Woodhouse <dwmw2@infradead.org>
Mon, 2 Apr 2007 06:38:20 +0000 (16:38 +1000)
committerJeremy Kerr <jk@ozlabs.org>
Tue, 3 Apr 2007 04:16:31 +0000 (14:16 +1000)
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
devices.c
petitboot.c
petitboot.h

index 28cb3a38e3828f328a8ee7434eb073ffb970379a..0a0645096c0a30dcd4830ec210c0a82324215ef7 100644 (file)
--- a/devices.c
+++ b/devices.c
@@ -152,21 +152,22 @@ out:
 
 static int read_option(int fd, struct device_context *dev_ctx)
 {
-       struct boot_option opt;
+       struct boot_option *opt = malloc(sizeof(*opt));
        twin_pixmap_t *icon;
        int index = -1;
 
-       if (!read_strings(fd, opt))
+       if (!opt)
                return TWIN_FALSE;
 
-       LOG("got option: '%s'\n", opt.name);
-       icon = get_icon(opt.icon_file);
+       if (!read_strings(fd, (*opt)))
+               return TWIN_FALSE;
 
-       if (icon)
-               index = pboot_add_option(dev_ctx->device_idx, opt.name,
-                               opt.description, icon);
+       LOG("got option: '%s'\n", opt->name);
+       icon = get_icon(opt->icon_file);
 
-       free_strings(opt);
+       if (icon)
+               index = pboot_add_option(dev_ctx->device_idx, opt->name,
+                                        opt->description, icon, opt);
 
        return index != -1;
 }
@@ -270,3 +271,27 @@ int pboot_start_device_discovery(void)
        return TWIN_TRUE;
 }
 
+void pboot_exec_option(void *data)
+{
+       struct boot_option *opt = data;
+       char *kexec_opts[10];
+       int nr_opts = 2;
+
+       kexec_opts[0] = "/sbin/kexec";
+       kexec_opts[1] = "-f";
+       if (opt->initrd_file) {
+               kexec_opts[nr_opts] = malloc(10 + strlen(opt->initrd_file));
+               sprintf(kexec_opts[nr_opts], "--initrd=%s", opt->initrd_file);
+               nr_opts++;
+       }
+       if (opt->boot_args)  {
+               kexec_opts[nr_opts] = malloc(10 + strlen(opt->boot_args));
+               sprintf(kexec_opts[nr_opts], "--command-line=%s",
+                       opt->boot_args);
+               nr_opts++;
+       }
+
+       kexec_opts[nr_opts++] = opt->boot_image_file;
+       kexec_opts[nr_opts] = NULL;
+       execv(kexec_opts[0], kexec_opts);
+}
index 44e1cc87b394755b0cdc745725e07916a6f028be..e7eff4c91fee02730173febe09c0794e3486cf78 100644 (file)
@@ -76,6 +76,7 @@ struct _pboot_option
        twin_pixmap_t   *badge;
        twin_pixmap_t   *cache;
        twin_rect_t     box;
+       void            *data;
 };
 
 struct _pboot_device
@@ -400,6 +401,17 @@ static void pboot_rpane_mousetrack(twin_coord_t x, twin_coord_t y)
        pboot_rpane->mouse_target = candidate;
 }
 
+static void pboot_choose_option(void)
+{
+       pboot_device_t *dev = pboot_devices[pboot_dev_sel];
+       pboot_option_t *opt = &dev->options[pboot_rpane->focus_curindex];
+
+       LOG("Selected device %s\n", opt->title);
+
+       /* Give user feedback, make sure errors and panics will be seen */
+       pboot_exec_option(opt->data);
+}
+
 static twin_bool_t pboot_rpane_event (twin_window_t        *window,
                                      twin_event_t          *event)
 {
@@ -412,6 +424,9 @@ static twin_bool_t pboot_rpane_event (twin_window_t     *window,
                pboot_rpane_mousetrack(event->u.pointer.x, event->u.pointer.y);
                return TWIN_TRUE;
        case TwinEventButtonDown:
+               pboot_select_rpane();
+               pboot_rpane_mousetrack(event->u.pointer.x, event->u.pointer.y);
+               pboot_choose_option();
        case TwinEventButtonUp:
                return TWIN_TRUE;
        case TwinEventKeyDown:
@@ -425,6 +440,8 @@ static twin_bool_t pboot_rpane_event (twin_window_t     *window,
                case KEY_LEFT:
                        pboot_select_lpane();
                        return TWIN_TRUE;
+               case KEY_ENTER:
+                       pboot_choose_option();
                default:
                        break;
                }
@@ -437,7 +454,7 @@ static twin_bool_t pboot_rpane_event (twin_window_t     *window,
 
 
 int pboot_add_option(int devindex, const char *title,
-                           const char *subtitle, twin_pixmap_t *badge)
+                    const char *subtitle, twin_pixmap_t *badge, void *data)
 {
        pboot_device_t  *dev;
        pboot_option_t  *opt;
@@ -474,6 +491,7 @@ int pboot_add_option(int devindex, const char *title,
                index * PBOOT_RIGHT_OPTION_STRIDE;
        opt->box.bottom = opt->box.top + PBOOT_RIGHT_OPTION_HEIGHT;
 
+       opt->data = data;
        return index;
 }
 
index aeac73bd0a2efd5cda2f5ffe4036305cb26a53cc..147fe7f2d004bfa98a44c57bc35da4d48ecf2ea8 100644 (file)
@@ -9,7 +9,8 @@
 int pboot_add_device(const char *dev_id, const char *name,
                twin_pixmap_t *pixmap);
 int pboot_add_option(int devindex, const char *title,
-               const char *subtitle, twin_pixmap_t *badge);
+                    const char *subtitle, twin_pixmap_t *badge, void *data);
 int pboot_remove_device(const char *dev_id);
 
 int pboot_start_device_discovery(void);
+void pboot_exec_option(void *data);