| 1 | /* |
|---|
| 2 | * kexecboot - A kexec based bootloader |
|---|
| 3 | * |
|---|
| 4 | * Copyright (c) 2008-2009 Yuri Bushmelev <jay4mail@gmail.com> |
|---|
| 5 | * Copyright (c) 2008 Thomas Kunze <thommycheck@gmx.de> |
|---|
| 6 | * |
|---|
| 7 | * small parts: |
|---|
| 8 | * Copyright (c) 2006 Matthew Allum <mallum@o-hand.com> |
|---|
| 9 | * |
|---|
| 10 | * This program is free software; you can redistribute it and/or modify |
|---|
| 11 | * it under the terms of the GNU General Public License as published by |
|---|
| 12 | * the Free Software Foundation; either version 2, or (at your option) |
|---|
| 13 | * any later version. |
|---|
| 14 | * |
|---|
| 15 | * This program is distributed in the hope that it will be useful, |
|---|
| 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 18 | * GNU General Public License for more details. |
|---|
| 19 | * |
|---|
| 20 | */ |
|---|
| 21 | |
|---|
| 22 | #include "kexecboot.h" |
|---|
| 23 | |
|---|
| 24 | /* Draw background with logo and text */ |
|---|
| 25 | void draw_background(FB *fb, const char *text) { |
|---|
| 26 | int margin = fb->width/64; |
|---|
| 27 | |
|---|
| 28 | /* Clear the background with #ecece1 */ |
|---|
| 29 | fb_draw_rect(fb, 0, 0, fb->width, fb->height,0xec, 0xec, 0xe1); |
|---|
| 30 | |
|---|
| 31 | /* logo */ |
|---|
| 32 | fb_draw_image(fb, |
|---|
| 33 | 0, |
|---|
| 34 | 0, |
|---|
| 35 | LOGO_IMG_WIDTH, |
|---|
| 36 | LOGO_IMG_HEIGHT, |
|---|
| 37 | LOGO_IMG_BYTES_PER_PIXEL, LOGO_IMG_RLE_PIXEL_DATA); |
|---|
| 38 | |
|---|
| 39 | fb_draw_text (fb, LOGO_IMG_WIDTH + margin, margin, 0, 0, 0, |
|---|
| 40 | &radeon_font, text); |
|---|
| 41 | } |
|---|
| 42 | |
|---|
| 43 | /* Draw one slot in menu */ |
|---|
| 44 | void draw_slot(FB *fb, struct boot * boot,int slot, int height, int iscurrent) |
|---|
| 45 | { |
|---|
| 46 | int margin = (height - CF_IMG_HEIGHT)/2; |
|---|
| 47 | char text[100]; |
|---|
| 48 | if(!iscurrent) |
|---|
| 49 | fb_draw_rect(fb, 0, slot*height, fb->width, height, |
|---|
| 50 | 0xec, 0xec, 0xe1); |
|---|
| 51 | else { //draw red border |
|---|
| 52 | fb_draw_rect(fb, 0, slot*height, fb->width, height, |
|---|
| 53 | 0xff, 0x00, 0x00); |
|---|
| 54 | fb_draw_rect(fb, margin, slot*height+margin, fb->width-2*margin |
|---|
| 55 | , height-2*margin, 0xec, 0xec, 0xe1); |
|---|
| 56 | } |
|---|
| 57 | if(!strncmp(boot->device,"/dev/hd",strlen("/dev/hd"))) |
|---|
| 58 | fb_draw_image(fb, margin, slot*height+margin, CF_IMG_WIDTH, |
|---|
| 59 | CF_IMG_HEIGHT, CF_IMG_BYTES_PER_PIXEL, CF_IMG_RLE_PIXEL_DATA); |
|---|
| 60 | else if(!strncmp(boot->device,"/dev/mmcblk",strlen("/dev/mmcblk"))) |
|---|
| 61 | fb_draw_image(fb, margin, slot*height + margin, MMC_IMG_WIDTH, |
|---|
| 62 | MMC_IMG_HEIGHT, MMC_IMG_BYTES_PER_PIXEL, MMC_IMG_RLE_PIXEL_DATA); |
|---|
| 63 | else if(!strncmp(boot->device,"/dev/mtdblock",strlen("/dev/mtdblock"))) |
|---|
| 64 | fb_draw_image(fb, margin, slot*height + margin, MEMORY_IMG_WIDTH, |
|---|
| 65 | MEMORY_IMG_HEIGHT, MEMORY_IMG_BYTES_PER_PIXEL, MEMORY_IMG_RLE_PIXEL_DATA); |
|---|
| 66 | sprintf(text,"%s (%s)",boot->device, boot->fstype); |
|---|
| 67 | fb_draw_text (fb, CF_IMG_WIDTH+margin, slot*height+margin, 0, 0, 0, |
|---|
| 68 | &radeon_font, text); |
|---|
| 69 | |
|---|
| 70 | } |
|---|
| 71 | |
|---|
| 72 | /* Display bootlist menu with selection */ |
|---|
| 73 | void display_menu(FB *fb, struct bootlist *bl, int current) |
|---|
| 74 | { |
|---|
| 75 | int i,j; |
|---|
| 76 | int slotheight = LOGO_IMG_HEIGHT; |
|---|
| 77 | int slots = fb->height/slotheight -1; |
|---|
| 78 | // struct boot that is in fist slot |
|---|
| 79 | static int firstslot=0; |
|---|
| 80 | |
|---|
| 81 | if (0 == bl->size) { |
|---|
| 82 | draw_background(fb, "No bootable devices found.\nInsert bootable device!\nR: Reboot S: Rescan devices"); |
|---|
| 83 | } else { |
|---|
| 84 | draw_background(fb, "Make your choice by selecting\nan item with the cursor keys.\nOK/Enter: Boot selected device\nR: Reboot S: Rescan devices"); |
|---|
| 85 | } |
|---|
| 86 | |
|---|
| 87 | if(current < firstslot) |
|---|
| 88 | firstslot=current; |
|---|
| 89 | if(current > firstslot + slots -1) |
|---|
| 90 | firstslot = current - (slots -1); |
|---|
| 91 | for(i=1, j=firstslot; i <= slots && j< bl->size; i++, j++){ |
|---|
| 92 | draw_slot(fb, bl->list[j], i, slotheight, j == current); |
|---|
| 93 | } |
|---|
| 94 | fb_render(fb); |
|---|
| 95 | } |
|---|
| 96 | |
|---|
| 97 | /* Display custom text near logo */ |
|---|
| 98 | void display_text(FB *fb, const char *text) { |
|---|
| 99 | draw_background(fb, text); |
|---|
| 100 | fb_render(fb); |
|---|
| 101 | } |
|---|
| 102 | |
|---|
| 103 | /* |
|---|
| 104 | * Function: get_extra_cmdline() |
|---|
| 105 | * It gets wanted tags from original cmdline. |
|---|
| 106 | * Takes 2 args: |
|---|
| 107 | * - extra_cmdline - buffer to store cmdline parameters; |
|---|
| 108 | * - extra_cmdline_size - size of buffer |
|---|
| 109 | * (inc. terminating '\0'). |
|---|
| 110 | * Return values: |
|---|
| 111 | * - length of extra_cmdline on success (w/o term. zero); |
|---|
| 112 | * - -1 on error; |
|---|
| 113 | * - (- length of extra_cmdline - 1) on insufficient buffer space. |
|---|
| 114 | * REFACTOR: do something with wanted_tags and this function (may be move to util) |
|---|
| 115 | */ |
|---|
| 116 | |
|---|
| 117 | int get_extra_cmdline(char *const extra_cmdline, const size_t extra_cmdline_size) |
|---|
| 118 | { |
|---|
| 119 | char *p, *t, *tag = NULL; |
|---|
| 120 | char line[COMMAND_LINE_SIZE]; |
|---|
| 121 | int i, len, sp_size; |
|---|
| 122 | int sum_len = 0; |
|---|
| 123 | int wanted_tag_found = 0; |
|---|
| 124 | int overflow = 0; |
|---|
| 125 | |
|---|
| 126 | const char proc_cmdline_path[] = "/proc/cmdline"; |
|---|
| 127 | |
|---|
| 128 | /* Open /proc/cmdline and read cmdline */ |
|---|
| 129 | FILE *f = fopen(proc_cmdline_path, "r"); |
|---|
| 130 | if (NULL == f) { |
|---|
| 131 | perror("Can't open /proc/cmdline"); |
|---|
| 132 | return -1; |
|---|
| 133 | } |
|---|
| 134 | |
|---|
| 135 | if ( NULL == fgets(line, sizeof(line), f) ) { |
|---|
| 136 | perror("Can't read /proc/cmdline"); |
|---|
| 137 | fclose(f); |
|---|
| 138 | return -1; |
|---|
| 139 | } |
|---|
| 140 | |
|---|
| 141 | fclose(f); |
|---|
| 142 | |
|---|
| 143 | /* clean up buffer before parsing */ |
|---|
| 144 | t = extra_cmdline; |
|---|
| 145 | *t = '\0'; |
|---|
| 146 | |
|---|
| 147 | p = line-1; /* because of ++p below */ |
|---|
| 148 | |
|---|
| 149 | sp_size = 0; /* size of (first) space */ |
|---|
| 150 | |
|---|
| 151 | do { |
|---|
| 152 | ++p; |
|---|
| 153 | |
|---|
| 154 | if ( (NULL == tag) && (isalnum(*p)) ) { |
|---|
| 155 | /* new tag found */ |
|---|
| 156 | tag = p; |
|---|
| 157 | } else if (tag) { |
|---|
| 158 | /* we are working on some tag */ |
|---|
| 159 | |
|---|
| 160 | if (isspace(*p) || ('\0' == *p) || ('=' == *p) ) { |
|---|
| 161 | /* end of tag or '=' found */ |
|---|
| 162 | |
|---|
| 163 | if (!wanted_tag_found) { |
|---|
| 164 | /* search in wanted_tags */ |
|---|
| 165 | for (i = 0; wanted_tags[i] != NULL; i++) { |
|---|
| 166 | if ( 0 == strncmp(wanted_tags[i], tag, p-tag) ) { |
|---|
| 167 | /* match found */ |
|---|
| 168 | wanted_tag_found = 1; |
|---|
| 169 | break; |
|---|
| 170 | } |
|---|
| 171 | } |
|---|
| 172 | } |
|---|
| 173 | |
|---|
| 174 | if ( ('=' != *p) && wanted_tag_found ) { |
|---|
| 175 | /* end of wanted tag found -> copy */ |
|---|
| 176 | |
|---|
| 177 | len = p - tag; |
|---|
| 178 | if ( (sum_len + len + sp_size) < extra_cmdline_size ) { |
|---|
| 179 | if (sp_size) { |
|---|
| 180 | /* prepend space when have tags already */ |
|---|
| 181 | *t = ' '; |
|---|
| 182 | ++t; |
|---|
| 183 | *t = '\0'; |
|---|
| 184 | ++sum_len; |
|---|
| 185 | } else { |
|---|
| 186 | sp_size = sizeof(char); |
|---|
| 187 | } |
|---|
| 188 | |
|---|
| 189 | /* NOTE: tag is not null-terminated so copy only |
|---|
| 190 | * len chars and terminate it directly |
|---|
| 191 | */ |
|---|
| 192 | strncpy(t, tag, len); |
|---|
| 193 | /* move pointer to position after copied tag */ |
|---|
| 194 | t += len ; |
|---|
| 195 | /* null-terminate */ |
|---|
| 196 | *t = '\0'; |
|---|
| 197 | /* update summary length */ |
|---|
| 198 | sum_len += len; |
|---|
| 199 | } else { |
|---|
| 200 | /* we have no space - skip this tag */ |
|---|
| 201 | overflow = 1; |
|---|
| 202 | } |
|---|
| 203 | |
|---|
| 204 | /* reset wanted_tag_found */ |
|---|
| 205 | wanted_tag_found = 0; |
|---|
| 206 | } |
|---|
| 207 | |
|---|
| 208 | /* reset tag */ |
|---|
| 209 | if (!wanted_tag_found) tag = NULL; |
|---|
| 210 | |
|---|
| 211 | } |
|---|
| 212 | } |
|---|
| 213 | |
|---|
| 214 | } while ('\0' != *p); |
|---|
| 215 | |
|---|
| 216 | if (overflow) return -sum_len-1; |
|---|
| 217 | return sum_len; |
|---|
| 218 | } |
|---|
| 219 | |
|---|
| 220 | void start_kernel(struct boot *boot) |
|---|
| 221 | { |
|---|
| 222 | /* we use var[] instead of *var because sizeof(var) using */ |
|---|
| 223 | const char mount_point[] = "/mnt"; |
|---|
| 224 | const char kexec_path[] = "/usr/sbin/kexec"; |
|---|
| 225 | |
|---|
| 226 | const char str_cmdline_start[] = "--command-line="; |
|---|
| 227 | const char str_root[] = " root="; |
|---|
| 228 | const char str_rootfstype[] = " rootfstype="; |
|---|
| 229 | const char str_rootwait[] = " rootwait"; |
|---|
| 230 | |
|---|
| 231 | /* empty environment */ |
|---|
| 232 | char *const envp[] = { NULL }; |
|---|
| 233 | |
|---|
| 234 | const char *kexec_load_argv[] = { NULL, "-l", NULL, NULL, NULL }; |
|---|
| 235 | const char *kexec_exec_argv[] = { NULL, "-e", NULL, NULL}; |
|---|
| 236 | |
|---|
| 237 | char extra_cmdline_buffer[COMMAND_LINE_SIZE]; |
|---|
| 238 | char *extra_cmdline, *cmdline_arg = NULL; |
|---|
| 239 | int n, idx; |
|---|
| 240 | struct stat *sinfo = malloc(sizeof(struct stat)); |
|---|
| 241 | |
|---|
| 242 | kexec_exec_argv[0] = kexec_path; |
|---|
| 243 | |
|---|
| 244 | /* Check /proc/sys/net presence */ |
|---|
| 245 | if ( -1 == stat("/proc/sys/net", sinfo) ) { |
|---|
| 246 | if (ENOENT == errno) { |
|---|
| 247 | /* We have no network, don't issue ifdown() while kexec'ing */ |
|---|
| 248 | kexec_exec_argv[2] = "-x"; |
|---|
| 249 | DPRINTF("No network is detected, disabling ifdown()\n"); |
|---|
| 250 | } else { |
|---|
| 251 | perror("Can't stat /proc/sys/net"); |
|---|
| 252 | } |
|---|
| 253 | } |
|---|
| 254 | free(sinfo); |
|---|
| 255 | |
|---|
| 256 | kexec_load_argv[0] = kexec_path; |
|---|
| 257 | |
|---|
| 258 | /* --command-line arg generation */ |
|---|
| 259 | idx = 2; /* kexec_load_argv current option index */ |
|---|
| 260 | |
|---|
| 261 | /* get some parts of cmdline from boot loader (e.g. mtdparts) */ |
|---|
| 262 | n = get_extra_cmdline( extra_cmdline_buffer, |
|---|
| 263 | sizeof(extra_cmdline_buffer) ); |
|---|
| 264 | if ( -1 == n ) { |
|---|
| 265 | /* clean up extra_cmdline on error */ |
|---|
| 266 | extra_cmdline = NULL; |
|---|
| 267 | /* } else if ( n < -1 ) { */ |
|---|
| 268 | /* Do something when we have no space to get all wanted tags */ |
|---|
| 269 | /* Now do nothing ;) */ |
|---|
| 270 | } else { |
|---|
| 271 | extra_cmdline = extra_cmdline_buffer; |
|---|
| 272 | } |
|---|
| 273 | |
|---|
| 274 | /* fill '--command-line' option */ |
|---|
| 275 | if (boot->cmdline || extra_cmdline || boot->device) { |
|---|
| 276 | /* allocate space */ |
|---|
| 277 | n = strlenn(str_cmdline_start) + strlenn(boot->cmdline) + |
|---|
| 278 | sizeof(char) + strlenn(extra_cmdline) + |
|---|
| 279 | strlenn(str_root) + strlenn(boot->device) + |
|---|
| 280 | strlenn(str_rootfstype) + strlenn(boot->fstype) + |
|---|
| 281 | strlenn(str_rootwait) + sizeof(char); |
|---|
| 282 | |
|---|
| 283 | cmdline_arg = (char *)malloc(n); |
|---|
| 284 | if (NULL == cmdline_arg) { |
|---|
| 285 | perror("Can't allocate memory for cmdline_arg"); |
|---|
| 286 | /* Should we exit? |
|---|
| 287 | exit(-1); |
|---|
| 288 | */ |
|---|
| 289 | } else { |
|---|
| 290 | strcpy(cmdline_arg, str_cmdline_start); |
|---|
| 291 | if (extra_cmdline) |
|---|
| 292 | strcat(cmdline_arg, extra_cmdline); |
|---|
| 293 | if (boot->cmdline && extra_cmdline) |
|---|
| 294 | strcat(cmdline_arg, " "); |
|---|
| 295 | if (boot->cmdline) |
|---|
| 296 | strcat(cmdline_arg, boot->cmdline); |
|---|
| 297 | if (boot->device) { |
|---|
| 298 | strcat(cmdline_arg, str_root); |
|---|
| 299 | strcat(cmdline_arg, boot->device); |
|---|
| 300 | if (boot->fstype) { |
|---|
| 301 | strcat(cmdline_arg, str_rootfstype); |
|---|
| 302 | strcat(cmdline_arg, boot->fstype); |
|---|
| 303 | } |
|---|
| 304 | } |
|---|
| 305 | strcat(cmdline_arg, str_rootwait); |
|---|
| 306 | |
|---|
| 307 | kexec_load_argv[idx] = cmdline_arg; |
|---|
| 308 | ++idx; |
|---|
| 309 | } |
|---|
| 310 | } |
|---|
| 311 | |
|---|
| 312 | /* Append kernelpath as last arg of kexec */ |
|---|
| 313 | kexec_load_argv[idx] = boot->kernelpath; |
|---|
| 314 | |
|---|
| 315 | DPRINTF("kexec_load_argv: %s, %s, %s, %s\n", kexec_load_argv[0], |
|---|
| 316 | kexec_load_argv[1], kexec_load_argv[2], |
|---|
| 317 | kexec_load_argv[3]); |
|---|
| 318 | |
|---|
| 319 | DPRINTF("kexec_exec_argv: %s, %s, %s\n", kexec_exec_argv[0], |
|---|
| 320 | kexec_exec_argv[1], kexec_exec_argv[2]); |
|---|
| 321 | |
|---|
| 322 | /* Mount boot device */ |
|---|
| 323 | if ( -1 == mount(boot->device, mount_point, boot->fstype, |
|---|
| 324 | MS_RDONLY, NULL) ) { |
|---|
| 325 | perror("Can't mount boot device"); |
|---|
| 326 | exit(-1); |
|---|
| 327 | } |
|---|
| 328 | |
|---|
| 329 | /* Load kernel */ |
|---|
| 330 | n = fexecw(kexec_path, (char *const *)kexec_load_argv, envp); |
|---|
| 331 | if (-1 == n) { |
|---|
| 332 | perror("Kexec can't load kernel"); |
|---|
| 333 | exit(-1); |
|---|
| 334 | } |
|---|
| 335 | |
|---|
| 336 | if (cmdline_arg) |
|---|
| 337 | free(cmdline_arg); |
|---|
| 338 | |
|---|
| 339 | umount(mount_point); |
|---|
| 340 | |
|---|
| 341 | /* Boot new kernel */ |
|---|
| 342 | execve(kexec_path, (char *const *)kexec_exec_argv, envp); |
|---|
| 343 | } |
|---|
| 344 | |
|---|
| 345 | int main(int argc, char **argv) |
|---|
| 346 | { |
|---|
| 347 | int choice = 0; |
|---|
| 348 | int initmode = 0; |
|---|
| 349 | FB *fb; |
|---|
| 350 | FILE *f; |
|---|
| 351 | int angle = KXB_FBANGLE; |
|---|
| 352 | struct bootlist * bl; |
|---|
| 353 | struct input_event evt; |
|---|
| 354 | struct termios old, new; |
|---|
| 355 | struct hw_model_info *model; |
|---|
| 356 | int ev0; |
|---|
| 357 | int ev1; |
|---|
| 358 | fd_set fds; |
|---|
| 359 | /* hardcoded for openmoko gta02 with 2.6.24 kernel */ |
|---|
| 360 | char *eventif = "/dev/event0"; |
|---|
| 361 | char *eventif1 = "/dev/event1"; |
|---|
| 362 | |
|---|
| 363 | struct input_event evt1; |
|---|
| 364 | int maxfd; |
|---|
| 365 | int nready; |
|---|
| 366 | int nread; |
|---|
| 367 | struct timeval tv; |
|---|
| 368 | /* When our pid is 1 we are init-process */ |
|---|
| 369 | if ( 1 == getpid() ) { |
|---|
| 370 | initmode = 1; |
|---|
| 371 | |
|---|
| 372 | DPRINTF("I'm the init-process!\n"); |
|---|
| 373 | |
|---|
| 374 | /* extra delay for initializing slow SD/CF */ |
|---|
| 375 | sleep(1); |
|---|
| 376 | |
|---|
| 377 | /* Mount procfs */ |
|---|
| 378 | if ( -1 == mount("proc", "/proc", "proc", |
|---|
| 379 | 0, NULL) ) { |
|---|
| 380 | perror("Can't mount procfs"); |
|---|
| 381 | exit(-1); |
|---|
| 382 | } |
|---|
| 383 | |
|---|
| 384 | DPRINTF("Procfs mounted\n"); |
|---|
| 385 | |
|---|
| 386 | /* Set up console loglevel */ |
|---|
| 387 | f = fopen("/proc/sys/kernel/printk", "w"); |
|---|
| 388 | if (NULL == f) { |
|---|
| 389 | perror("/proc/sys/kernel/printk"); |
|---|
| 390 | exit(-1); |
|---|
| 391 | } |
|---|
| 392 | fputs("0 4 1 7\n", f); |
|---|
| 393 | fclose(f); |
|---|
| 394 | |
|---|
| 395 | DPRINTF("Console loglevel is set\n"); |
|---|
| 396 | |
|---|
| 397 | } |
|---|
| 398 | |
|---|
| 399 | /* Get hardware model parameters (now FB angle only) */ |
|---|
| 400 | model = detect_hw_model(model_info); |
|---|
| 401 | if (model->hw_model_id != HW_MODEL_UNKNOWN) { |
|---|
| 402 | angle = model->angle; |
|---|
| 403 | DPRINTF("Model is %s, fbangle is %d\n", model->name, model->angle); |
|---|
| 404 | } |
|---|
| 405 | |
|---|
| 406 | /* Check command-line args when not an init-process */ |
|---|
| 407 | if (!initmode) { |
|---|
| 408 | int i = 0; |
|---|
| 409 | while (++i < argc) { |
|---|
| 410 | if (!strcmp(argv[i], "-a") || !strcmp(argv[i], "--angle")) { |
|---|
| 411 | if (++i > argc) |
|---|
| 412 | goto fail; |
|---|
| 413 | angle = atoi(argv[i]); |
|---|
| 414 | continue; |
|---|
| 415 | } |
|---|
| 416 | |
|---|
| 417 | if (!strcmp(argv[i], "-i") || !strcmp(argv[i], "--input")) { |
|---|
| 418 | if (++i > argc) |
|---|
| 419 | goto fail; |
|---|
| 420 | eventif = argv[i]; |
|---|
| 421 | continue; |
|---|
| 422 | } |
|---|
| 423 | if (!strcmp(argv[i], "-e") || !strcmp(argv[i], "--event")) { |
|---|
| 424 | if (++i > argc) |
|---|
| 425 | goto fail; |
|---|
| 426 | eventif1 = argv[i]; |
|---|
| 427 | continue; |
|---|
| 428 | } |
|---|
| 429 | |
|---|
| 430 | fail: |
|---|
| 431 | fprintf(stderr, "Usage: %s [-a|--angle <0|90|180|270>] \ |
|---|
| 432 | [-i|--input </dev/input/eventX> [-e|--eventt </dev/input/eventX2>\n", |
|---|
| 433 | /* kxecboot -i /dev/input4 -e /dev/input0 for GTA02*/ |
|---|
| 434 | /* aux tscreen on GTA running shr-unstable */ |
|---|
| 435 | argv[0]); |
|---|
| 436 | exit(-1); |
|---|
| 437 | } |
|---|
| 438 | } |
|---|
| 439 | |
|---|
| 440 | DPRINTF("FB angle is %d, input device is %s\n", angle, eventif); |
|---|
| 441 | DPRINTF("Going to fb mode\n"); |
|---|
| 442 | |
|---|
| 443 | if ((fb = fb_new(angle)) == NULL) |
|---|
| 444 | exit(-1); |
|---|
| 445 | |
|---|
| 446 | ev0 = open(eventif,O_RDONLY); |
|---|
| 447 | ev1 = open(eventif1,O_RDONLY); |
|---|
| 448 | if(!ev0 && !ev1 ){ |
|---|
| 449 | perror(eventif); /* maybe more sane output for for eventif1 */ |
|---|
| 450 | exit(3); |
|---|
| 451 | } |
|---|
| 452 | |
|---|
| 453 | /* Switch cursor off. NOTE: works only when master-console is tty */ |
|---|
| 454 | printf("\033[?25l\n"); |
|---|
| 455 | |
|---|
| 456 | // deactivate terminal input |
|---|
| 457 | tcgetattr(fileno(stdin), &old); |
|---|
| 458 | new = old; |
|---|
| 459 | new.c_lflag &= ~ECHO; |
|---|
| 460 | // new.c_cflag &=~CREAD; |
|---|
| 461 | tcsetattr(fileno(stdin), TCSANOW, &new); |
|---|
| 462 | |
|---|
| 463 | bl = scan_devices(model); |
|---|
| 464 | |
|---|
| 465 | do { |
|---|
| 466 | display_menu(fb, bl, choice); |
|---|
| 467 | do{ |
|---|
| 468 | /* Wait for some input. */ |
|---|
| 469 | tv.tv_sec =1; |
|---|
| 470 | tv.tv_usec = 0; |
|---|
| 471 | FD_ZERO(&fds); |
|---|
| 472 | FD_SET( ev0,&fds); |
|---|
| 473 | FD_SET(ev1,&fds); |
|---|
| 474 | maxfd = 8; |
|---|
| 475 | nready = select(maxfd, &fds, NULL,NULL,&tv); |
|---|
| 476 | /* now GTA02 specific */ |
|---|
| 477 | if( FD_ISSET(ev0, &fds)) |
|---|
| 478 | { |
|---|
| 479 | read(ev0,&evt, sizeof(struct input_event)); |
|---|
| 480 | DPRINTF("event: %i %i %i,\n",evt.type, evt.code,evt.value); |
|---|
| 481 | } |
|---|
| 482 | if( FD_ISSET(ev1, &fds)) |
|---|
| 483 | { |
|---|
| 484 | read(ev1,&evt1 ,sizeof(struct input_event) ); |
|---|
| 485 | DPRINTF("event1: %i %i %i,\n",evt1.type, evt1.code,evt1.value); |
|---|
| 486 | if ((evt1.code == 330) && (evt1.value == 1)) |
|---|
| 487 | { |
|---|
| 488 | if ( choice < (bl->size - 1) ) |
|---|
| 489 | { |
|---|
| 490 | choice++; |
|---|
| 491 | DPRINTF("Choice %i\n", choice); |
|---|
| 492 | } |
|---|
| 493 | else |
|---|
| 494 | { |
|---|
| 495 | choice=0; |
|---|
| 496 | } |
|---|
| 497 | DPRINTF("Selected: %i ,\n",choice ); |
|---|
| 498 | break; |
|---|
| 499 | } |
|---|
| 500 | } |
|---|
| 501 | } while( ( evt.type != EV_KEY || evt.value != 0) || ( evt.type != EV_KEY || evt1.value != 0) ); |
|---|
| 502 | // dev/event0 power 116 |
|---|
| 503 | }while( ( evt.code != 169 ) || (bl->size == 0) ); |
|---|
| 504 | draw_background(fb, "DEBUG by EW: .\n Boot selected "); |
|---|
| 505 | fb_render(fb); |
|---|
| 506 | |
|---|
| 507 | fclose(f); |
|---|
| 508 | // reset terminal |
|---|
| 509 | tcsetattr(fileno(stdin), TCSANOW, &old); |
|---|
| 510 | fb_destroy(fb); |
|---|
| 511 | start_kernel(bl->list[choice]); |
|---|
| 512 | /* When we reach this point then some error has occured */ |
|---|
| 513 | DPRINTF("We should not reach this point!"); |
|---|
| 514 | return -1; |
|---|
| 515 | } |
|---|