2 * Petitboot twin bootloader
4 * Copyright Geoff Levand <geoff@infradead.org>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 #if defined(HAVE_CONFIG_H)
34 #include "talloc/talloc.h"
35 #include "waiter/waiter.h"
36 #include "ui/common/timer.h"
38 #include "pbt-client.h"
42 static struct pbt_client *client_from_item(struct pbt_item *item)
47 static int exit_to_shell_cb(struct pbt_item *item)
49 struct pbt_client *client = client_from_item(item);
51 client->signal_data.abort = 1;
55 static int edit_preferences_cb(struct pbt_item *item)
57 struct pbt_client *client = client_from_item(item);
61 pb_log("%s: TODO\n", __func__);
66 static struct pbt_item *setup_system_item(struct pbt_menu *menu,
67 struct pbt_client *client)
69 struct pbt_item *top_item;
70 struct pbt_item *sub_item;
73 top_item = pbt_item_create_reduced(menu, "system", 0,
74 PB_ARTWORK_PATH "/applications-system.png");
77 goto fail_top_item_create;
81 q.x = menu->window->pixmap->width;
83 q.width = menu->scr->tscreen->width - q.x;
84 q.height = menu->scr->tscreen->height;
86 top_item->sub_menu = pbt_menu_create(top_item, "system", menu->scr,
87 menu, &q, &menu->layout);
89 if (!top_item->sub_menu)
90 goto fail_sub_menu_create;
92 sub_item = pbt_item_create(top_item->sub_menu, "Preferences", 0,
93 PB_ARTWORK_PATH "/configure.png", "Preferences",
94 "Edit petitboot preferences");
99 sub_item->on_execute = edit_preferences_cb;
100 sub_item->data = client;
101 pbt_menu_set_selected(top_item->sub_menu, sub_item);
103 sub_item = pbt_item_create(top_item->sub_menu, "Exit to Shell", 1,
104 PB_ARTWORK_PATH "/utilities-terminal.png", "Exit to Shell",
105 "Exit to a system shell prompt");
108 goto fail_sub_item_1;
110 sub_item->on_execute = exit_to_shell_cb;
111 sub_item->data = client;
113 top_item->sub_menu->n_items = 2;
115 /* Set shell item as default */
117 pbt_menu_set_selected(top_item->sub_menu, sub_item);
123 fail_sub_menu_create:
125 fail_top_item_create:
126 // FIXME: need cleanup
131 static struct pbt_menu *menu_create(struct pbt_client *client)
133 static struct pbt_menu_layout layout = {
137 .title = {.font_size = 30, .color = 0xff000000,},
138 .text = {.font_size = 18, .color = 0xff800000,},
141 struct pbt_menu *device_menu;
142 struct pbt_item *system_item;
145 const struct pbt_border *border;
147 assert(client->frame.scr);
149 icon = pbt_icon_load(NULL);
154 assert((unsigned int)icon->height == layout.item_height);
156 /* Create main (device) menu */
158 border = &pbt_right_border;
162 q.width = icon->width + 2 * layout.item_space + border->left
164 q.height = client->frame.scr->tscreen->height;
166 device_menu = pbt_menu_create(client, "device", client->frame.scr, NULL,
172 //FIXME: move to accessors
173 device_menu->background_color = 0x80000000;
174 device_menu->border = *border;
176 /* Setup system item */
178 system_item = setup_system_item(device_menu, client);
181 goto fail_system_item;
183 device_menu->n_items++;
185 /* Set system item as default */
187 pbt_menu_set_selected(device_menu, system_item);
188 pbt_menu_set_focus(device_menu, 1);
189 pbt_menu_show(device_menu, 1);
191 pbt_menu_redraw(device_menu);
196 // FIXME: need cleanup
202 static int run(struct pbt_client *client)
205 int result = waiter_poll(client->waitset);
207 if (result < 0 && errno != EINTR) {
208 pb_log("%s: poll: %s\n", __func__, strerror(errno));
212 if (client->signal_data.abort)
215 ui_timer_process_sig(&client->signal_data.timer);
217 while (client->signal_data.resize) {
218 client->signal_data.resize = 0;
219 pbt_client_resize(client);
226 static struct pb_signal_data *_signal_data;
228 static void set_signal_data(struct pb_signal_data *sd)
233 static struct pb_signal_data *get_signal_data(void)
238 static void sig_handler(int signum)
240 DBGS("%d\n", signum);
242 struct pb_signal_data *sd = get_signal_data();
249 ui_timer_sigalrm(&sd->timer);
255 assert(0 && "unknown sig");
266 * main - twin bootloader main routine.
269 int main(int argc, char *argv[])
271 static struct sigaction sa;
272 static struct pbt_opts opts;
275 struct pbt_client *client;
277 result = pbt_opts_parse(&opts, argc, argv);
284 if (opts.show_help == pbt_opt_yes) {
289 if (opts.show_version == pbt_opt_yes) {
294 if (strcmp(opts.log_file, "-")) {
295 FILE *log = fopen(opts.log_file, "a");
298 pb_log_set_stream(log);
300 pb_log_set_stream(stderr);
303 pb_log_always_flush(1);
306 pb_log("--- petitboot-twin ---\n");
308 sa.sa_handler = sig_handler;
309 result = sigaction(SIGALRM, &sa, NULL);
310 result += sigaction(SIGHUP, &sa, NULL);
311 result += sigaction(SIGINT, &sa, NULL);
312 result += sigaction(SIGTERM, &sa, NULL);
313 result += sigaction(SIGWINCH, &sa, NULL);
316 pb_log("%s sigaction failed.\n", __func__);
320 client = pbt_client_init(opts.backend, 1024, 640, opts.start_daemon);
323 ui_result = EXIT_FAILURE;
327 set_signal_data(&client->signal_data);
329 client->frame.top_menu = menu_create(client);
331 if (!client->frame.top_menu) {
332 ui_result = EXIT_FAILURE;
336 twin_screen_update(client->frame.scr->tscreen);
337 ui_result = run(client);
342 pb_log("--- end ---\n");
344 return ui_result ? EXIT_FAILURE : EXIT_SUCCESS;