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;
}
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);
+}
twin_pixmap_t *badge;
twin_pixmap_t *cache;
twin_rect_t box;
+ void *data;
};
struct _pboot_device
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)
{
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:
case KEY_LEFT:
pboot_select_lpane();
return TWIN_TRUE;
+ case KEY_ENTER:
+ pboot_choose_option();
default:
break;
}
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;
index * PBOOT_RIGHT_OPTION_STRIDE;
opt->box.bottom = opt->box.top + PBOOT_RIGHT_OPTION_HEIGHT;
+ opt->data = data;
return index;
}
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);