Force redraw upon menu item selection
[qi-bootmenu.git] / qi-bootmenu.c
blob6bffc2a2c2e9b2fc46e3ea7270ef2f6601c611cc
1 /*
2 * qi-bootmenu - A kexec based bootloader with an elementary based GUI
4 * Copyright (c) 2009-2010 Marc Andre Tanner <mat@brain-dump.org>
6 * qi-bootmenu shares the basic idea with kexecboot which is written by:
8 * Copyright (c) 2008-2009 Yuri Bushmelev <jay4mail@gmail.com>
9 * Copyright (c) 2008 Thomas Kunze <thommycheck@gmx.de>
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2, or (at your option)
14 * any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
23 #include <stdbool.h>
24 #include <stdio.h>
25 #include <string.h>
26 #include <Eina.h>
27 #include <Evas.h>
28 #include <Ecore.h>
29 #include <Ecore_Evas.h>
31 #define countof(arr) (sizeof(arr) / sizeof((arr)[0]))
32 #define sstrlen(str) (sizeof(str) - 1)
34 static void eprint(const char *errstr, ...);
36 #ifdef NDEBUG
37 #define debug(format, args...)
38 #else
39 #define debug eprint
40 #endif
42 #define RGB(r, g, b) r,g,b
44 typedef struct {
45 const char *fs;
46 const char *dev;
47 const char *kernel;
48 const char *cmdline;
49 const char *logo;
50 } BootItem;
52 typedef struct {
53 const char *text;
54 const char *logo;
55 void(*callback)(void *data);
56 void *data;
57 } MenuItem;
59 /* menu actions */
60 static void boot_nand(void *data);
61 static void poweroff(void *data);
63 /* drawing related stuff */
64 static Ecore_Evas *ee;
65 static Evas *evas;
67 typedef struct {
68 char option;
69 void(*add)(MenuItem *item);
70 void(*select)(Evas_Object *item);
71 void(*deselect)(Evas_Object *item);
72 void(*error)(const char *errstr, va_list ap);
73 } Gui;
75 /* functions available to gui modules */
76 static void gui_item_clicked(void *data, Evas *evas, Evas_Object *item, void *event);
77 static void gui_show_error(const char *errstr, ...);
79 #include "config.h"
81 /* will be used to search the kernel as in {u,z}Image-$MACHINE.bin */
82 static const char *machine = DEFAULT_MACHINE;
84 /* if no option is passed in then use the first entry */
85 static Gui *gui = &guis[0];
87 #include "kexec.c"
88 #include "gui.c"
90 static void cleanup(int sig) {
91 umount_all();
92 ecore_main_loop_quit();
95 static void eprint(const char *errstr, ...) {
96 va_list ap;
97 va_start(ap, errstr);
98 vfprintf(stderr, errstr, ap);
99 va_end(ap);
102 static void usage() {
103 eprint("usage: qi-bootmenu [-d] [-m ...] [-i ...]\n");
104 exit(1);
107 int main(int argc, char **argv) {
109 BootItem *s;
110 Eina_List *l, *systems, *dev_ignore = NULL; /* partitions to ignore */
111 bool diag = false;
112 int arg;
113 unsigned int i;
115 if (!eina_init())
116 return 1;
118 for (arg = 1; arg < argc; arg++) {
119 if (argv[arg][0] != '-')
120 usage();
122 switch (argv[arg][1]) {
123 case 'h':
124 usage();
125 case 'd':
126 diag = true;
127 break;
128 case 'm':
129 if (arg + 1 >= argc)
130 usage();
131 machine = argv[++arg];
132 break;
133 case 'i':
134 if (arg + 1 >= argc)
135 usage();
136 dev_ignore = eina_list_append(dev_ignore, argv[++arg]);
137 break;
138 default:
139 for (i = 0; i < countof(guis); i++) {
140 if (argv[arg][1] == guis[i].option)
141 gui = &guis[i];
143 break;
147 if (diag) {
148 gui->error = NULL;
149 diagnostics(dev_ignore);
150 return 0;
153 if (!gui_init()) {
154 eprint("Couldn't init GUI\n");
155 return 1;
158 /* search for system images to boot and display them */
159 systems = scan_system(dev_ignore);
160 signal(SIGINT, cleanup);
161 signal(SIGTERM, cleanup);
163 EINA_LIST_FOREACH(systems, l, s) {
164 for (i = 0; i < countof(menu); i++) {
165 if (menu[i].data && !strcmp(menu[i].data, s->dev)) {
166 menu[i].text = NULL;
167 break;
170 MenuItem item = {
171 .text = s->dev,
172 .logo = s->logo,
173 .callback = gui_bootitem_clicked,
174 .data = s,
176 gui->add(&item);
179 /* add pre defined menu entries */
180 for (i = 0; i < countof(menu); i++) {
181 if (!menu[i].text)
182 continue;
183 gui->add(&menu[i]);
186 ecore_main_loop_begin();
188 return 0;