alsa.audio: build the bridge link lib only for linux architecture
[AROS.git] / arch / ppc-sam440 / boot / parthenope / src / menu.c
blob433f23565f99070e0d6b58374bbcc6ff0732e3e9
1 /* menu.c */
3 /* <project_name> -- <project_description>
5 * Copyright (C) 2006 - 2007
6 * Giuseppe Coviello <cjg@cruxppc.org>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 #include "menu.h"
24 #include "ext2.h"
25 #include "sfs.h"
26 #include "dos.h"
27 #include "rdb.h"
29 static struct EntryObject *EntryObject_new(char *name, char *args,
30 char *partition)
32 struct EntryObject *self;
34 self = malloc(sizeof(struct EntryObject));
35 self->name = strdup(name);
36 self->args = NULL;
37 if(args != NULL)
38 self->args = strdup(args);
39 self->partition = NULL;
40 if(partition != NULL)
41 self->partition = strdup(partition);
43 return self;
46 static menu_t *entry_alloc(void)
48 menu_t *entry;
49 entry = malloc(sizeof(menu_t));
50 entry->title = NULL;
51 entry->kernel = NULL;
52 entry->other = NULL;
53 entry->append = NULL;
54 entry->initrd = NULL;
55 entry->modules_cnt = 0;
56 entry->argc = 0;
57 entry->device_type = DEFAULT_TYPE;
58 entry->device_num = 0;
59 entry->partition = 0;
60 entry->server_ip = 0;
61 entry->next = NULL;
62 return entry;
65 static void entry_free(menu_t * entry)
67 if (entry->title != NULL)
68 free(entry->title);
69 if (entry->kernel != NULL)
70 free(entry->kernel);
71 if (entry->other != NULL)
72 free(entry->other);
73 if (entry->append != NULL)
74 free(entry->append);
75 if (entry->initrd != NULL)
76 free(entry->initrd);
77 /* FIXME: free modules and args */
78 free(entry);
81 enum states { S, DEF, DLY, TIT, IN, RT, K, O, RD, M, A, R, AQ, RQ };
83 char *getline(char *src, int src_len, int *src_offset)
85 char *nlptr, *line;
86 int len;
88 if (*src_offset >= src_len)
89 return NULL;
91 nlptr = strchr(src + *src_offset, '\n');
92 if (nlptr != NULL)
93 len = nlptr - (src + *src_offset) + 1;
94 else
95 len = src_len - *src_offset;
97 line = malloc(len + 1);
98 strncpy(line, src + *src_offset, len);
99 *src_offset += len;
100 line[len] = 0;
102 return line;
105 char *eatcomments(char *line)
107 char *cptr;
109 cptr = strchr(line, '#');
111 if (cptr != NULL)
112 line[cptr - line] = 0;
114 return line;
117 char *getnextword(char *line)
119 char *bptr, *word;
120 int len;
122 bptr = strchr(line, ' ');
124 if (bptr == NULL)
125 bptr = strchr(line, '\t');
127 if (bptr != NULL)
128 len = bptr - line;
129 else
130 len = strlen(line);
132 word = malloc(len + 1);
133 strncpy(word, line, len);
134 word[len] = 0;
136 return word;
139 char *strtrim(char *s)
141 char *ptr_s, *tmp;
142 int n;
144 ptr_s = s;
145 for (; isspace(*ptr_s); ptr_s++) ;
147 for (n = strlen(ptr_s); n > 0 && isspace(*(ptr_s + n - 1)); n--) ;
148 if (n < 0)
149 n = 0;
151 tmp = strdup(ptr_s);
152 strcpy(s, tmp);
153 *(s + n) = 0;
154 free(tmp);
156 return s;
159 char *kick_eatcomments(char *line)
161 char *cptr;
163 cptr = strchr(line, ';');
165 if (cptr != NULL)
166 line[cptr - line] = 0;
168 return line;
171 static int kick_fsm(char *buffer, int buffer_len, menu_t * menu)
173 int offset;
174 char *line;
175 char *word;
176 char *lineptr = NULL;
177 int status, n;
178 menu_t /**menu,*/ * entry = NULL, *ptr = NULL;
180 menu = entry_alloc();
181 menu->default_os = 0;
182 menu->delay = 5;
184 line = NULL;
185 offset = 0;
186 status = S;
187 n = 0;
188 int parse = 1, kernel = 0;
189 while (parse) {
190 switch (status) {
191 case S:
192 if ((line = getline(buffer, buffer_len,
193 &offset)) == NULL) {
194 parse = 0;
195 break;
197 kick_eatcomments(line);
198 strtrim(line);
199 if (strlen(line) == 0) {
200 free(line);
201 status = S;
202 break;
204 word = getnextword(line);
205 if (strcmp(word, "LABEL") == 0) {
206 status = TIT;
207 lineptr = line + strlen(word);
208 } else
209 status = S;
210 free(word);
211 break;
212 case TIT:
213 strtrim(lineptr);
214 if (strlen(lineptr) > 0) {
215 status = IN;
216 kernel = 0;
217 entry = entry_alloc();
218 entry->title = strdup(lineptr);
219 } else
220 status = S;
221 free(line);
222 break;
223 case IN:
224 if ((line = getline(buffer, buffer_len,
225 &offset)) == NULL) {
226 if (kernel)
227 status = AQ;
228 else
229 status = RQ;
230 break;
232 kick_eatcomments(line);
233 strtrim(line);
234 if (strlen(line) == 0) {
235 free(line);
236 status = IN;
237 break;
239 word = getnextword(line);
240 lineptr = line + strlen(word);
241 if (strcmp(word, "EXEC") == 0) {
242 status = K;
243 } else if (strcmp(word, "MODULE") == 0) {
244 status = M;
245 } else if (strcmp(word, "LABEL") == 0) {
246 offset -= strlen(line) + 1;
247 free(line);
248 if (kernel) {
249 status = A;
250 } else {
251 status = R;
253 } else {
254 free(line);
255 status = R;
257 free(word);
258 break;
259 case K:
260 strtrim(lineptr);
261 word = getnextword(lineptr);
262 if (!strlen(word))
263 status = R;
264 else {
265 status = IN;
266 kernel = 1;
267 entry->kernel = strdup(word);
268 lineptr = lineptr + strlen(word);
269 strtrim(lineptr);
270 if (strlen(lineptr) > 0) {
271 entry->append = strdup(lineptr);
274 free(line);
275 free(word);
276 break;
277 case M:
278 strtrim(lineptr);
279 word = getnextword(lineptr);
280 if (!strlen(word))
281 status = R;
282 else {
283 status = IN;
284 entry->modules[entry->modules_cnt++] =
285 EntryObject_new(word, NULL, NULL);
287 free(line);
288 free(word);
289 break;
290 case A:
291 for (ptr = menu; ptr->next != NULL; ptr = ptr->next) ;
292 ptr->next = entry;
293 n++;
294 status = S;
295 break;
296 case R:
297 entry_free(entry);
298 status = S;
299 break;
300 case AQ:
301 for (ptr = menu; ptr->next != NULL; ptr = ptr->next) ;
302 ptr->next = entry;
303 return 1;
304 break;
305 case RQ:
306 default:
307 entry_free(entry);
308 return 0;
309 break;
312 return n;
315 static int fsm(char *buffer, int buffer_len, menu_t * menu)
317 int offset;
318 char *line;
319 char *word;
320 char *lineptr = NULL;
321 int status, n;
322 menu_t /**menu,*/ * entry = NULL, *ptr = NULL;
325 menu = entry_alloc();
326 menu->default_os = 0;
327 menu->delay = 5;
329 line = NULL;
330 offset = 0;
331 status = S;
332 n = 0;
333 int parse = 1, kernel = 0;
334 while (parse) {
335 switch (status) {
336 case S:
337 if ((line = getline(buffer, buffer_len,
338 &offset)) == NULL) {
339 parse = 0;
340 break;
342 eatcomments(line);
343 strtrim(line);
344 if (strlen(line) == 0) {
345 free(line);
346 status = S;
347 break;
349 word = getnextword(line);
350 if (strcmp(word, "title") == 0) {
351 status = TIT;
352 lineptr = line + strlen(word);
353 } else if (strcmp(word, "default") == 0) {
354 status = DEF;
355 lineptr = line + strlen(word);
356 } else if (strcmp(word, "delay") == 0) {
357 status = DLY;
358 lineptr = line + strlen(word);
359 } else
360 status = S;
361 free(word);
362 break;
363 case DEF:
364 status = S;
365 if (strlen(lineptr) == 0)
366 break;
367 strtrim(lineptr);
368 word = getnextword(lineptr);
369 if (strlen(word) == 0)
370 break;
371 menu->default_os = strtol(word);
372 free(word);
373 break;
374 case DLY:
375 status = S;
376 if (strlen(lineptr) == 0)
377 break;
378 strtrim(lineptr);
379 word = getnextword(lineptr);
380 if (strlen(word) == 0)
381 break;
382 menu->delay = strtol(word);
383 free(word);
384 break;
385 case TIT:
386 strtrim(lineptr);
387 if (strlen(lineptr) > 0) {
388 status = IN;
389 kernel = 0;
390 entry = entry_alloc();
391 entry->title = strdup(lineptr);
392 } else
393 status = S;
394 free(line);
395 break;
396 case IN:
397 if ((line = getline(buffer, buffer_len,
398 &offset)) == NULL) {
399 if (kernel)
400 status = AQ;
401 else
402 status = RQ;
403 break;
405 eatcomments(line);
406 strtrim(line);
407 if (strlen(line) == 0) {
408 free(line);
409 status = IN;
410 break;
412 word = getnextword(line);
413 lineptr = line + strlen(word);
414 if (strcmp(word, "kernel") == 0) {
415 status = K;
416 } else if (strcmp(word, "other") == 0) {
417 status = O;
418 } else if (strcmp(word, "root") == 0) {
419 status = RT;
420 } else if (strcmp(word, "initrd") == 0) {
421 status = RD;
422 } else if (strcmp(word, "module") == 0) {
423 status = M;
424 } else if (strcmp(word, "title") == 0) {
425 offset -= strlen(line) + 1;
426 free(line);
427 if (kernel) {
428 status = A;
429 } else {
430 status = R;
432 } else {
433 free(line);
434 status = R;
436 free(word);
437 break;
438 case K:
439 strtrim(lineptr);
440 word = getnextword(lineptr);
441 if (!strlen(word))
442 status = R;
443 else {
444 status = IN;
445 kernel = 1;
446 entry->kernel = strdup(word);
447 lineptr = lineptr + strlen(word);
448 strtrim(lineptr);
449 if (strlen(lineptr) > 0) {
450 entry->append = strdup(lineptr);
453 free(line);
454 free(word);
455 break;
456 case RT:
457 strtrim(lineptr);
458 word = getnextword(lineptr);
459 if (!strlen(word)) {
460 status = R;
461 free(word);
462 free(line);
463 break;
465 lineptr = lineptr + strlen(word);
466 strtrim(lineptr);
467 if (strcmp(word, "tftp") == 0) {
468 entry->device_type = TFTP_TYPE;
469 free(word);
470 free(line);
471 status = IN;
472 } else if (strcmp(word, "cdrom") == 0) {
473 entry->device_type = CD_TYPE;
474 free(word);
475 free(line);
476 status = IN;
477 } else if (strcmp(word, "ide") == 0) {
478 char *sep = strchr(lineptr, ':');
479 if (sep == NULL || *++sep == 0) {
480 status = R;
481 free(line);
482 free(word);
483 break;
485 char *dev = malloc(sep - lineptr);
486 strncpy(dev, lineptr, sep - lineptr - 1);
487 dev[sep - lineptr - 1] = 0;
488 entry->device_type = IDE_TYPE;
489 entry->device_num = strtol(dev);
490 entry->partition = strtol(sep) - 1;
491 free(word);
492 free(line);
493 free(dev);
494 status = IN;
495 } else {
496 status = R;
497 free(word);
498 free(line);
500 break;
501 case O:
502 strtrim(lineptr);
503 word = getnextword(lineptr);
504 if (!strlen(word)) {
505 status = R;
506 free(word);
507 free(line);
508 break;
510 lineptr = lineptr + strlen(word);
511 entry->other = strdup(word);
512 kernel = 1;
513 status = IN;
514 break;
515 case RD:
516 strtrim(lineptr);
517 word = getnextword(lineptr);
518 if (!strlen(word))
519 status = R;
520 else {
521 status = IN;
522 entry->initrd = strdup(word);
524 free(line);
525 free(word);
526 break;
527 case M:
528 strtrim(lineptr);
529 word = getnextword(lineptr);
530 if (!strlen(word))
531 status = R;
532 else {
533 status = IN;
534 entry->modules[entry->modules_cnt++] =
535 EntryObject_new(word, NULL, NULL);
537 free(line);
538 free(word);
539 break;
540 case A:
541 for (ptr = menu; ptr->next != NULL; ptr = ptr->next) ;
542 ptr->next = entry;
543 n++;
544 status = S;
545 break;
546 case R:
547 entry_free(entry);
548 status = S;
549 break;
550 case AQ:
551 for (ptr = menu; ptr->next != NULL; ptr = ptr->next) ;
552 ptr->next = entry;
553 return 1;
554 break;
555 case RQ:
556 default:
557 entry_free(entry);
558 return 0;
559 break;
562 return 1;
565 typedef struct menu {
566 char *title;
567 char *kernel;
568 char *append;
569 char *initrd;
570 char *modules[MAX_MODULES];
571 int modules_cnt;
572 char *argv[MAX_MODULES];
573 int argc;
574 int device_type;
575 int device_num;
576 int partition;
577 int default_os;
578 int delay;
579 char *server_ip;
580 struct menu *next;
581 } menu_t;
584 static int dev_load(menu_t *self, boot_dev_t *dev)
586 int n = 0;
587 char *buffer;
588 int buffer_length;
589 buffer = malloc(16 * 0x1000);
590 if ((buffer_length = dev->load_file(dev, "menu.lst", buffer)) > 0)
591 n += fsm(buffer, buffer_length, self);
592 else if ((buffer_length = dev->load_file(dev, "boot/menu.lst", buffer)) > 0)
593 n += fsm(buffer, buffer_length, self);
594 else if ((buffer_length = dev->load_file(dev, "Kickstart/Kicklayout",
595 buffer)) > 0)
596 n += kick_fsm(buffer, buffer_length, self);
597 free(buffer);
598 return n;
601 static int magic_load(menu_t *self)
603 int i, n;
604 boot_dev_t *dev;
605 menu_t *ptr;
606 struct RdbPartition *partition;
608 n = 0;
609 for(i = 0; i < RDB_LOCATION_LIMIT; i++) {
610 partition = RdbPartitionTable_get(0, i);
611 if(partition == NULL)
612 break;
613 dev = dos_create(partition);
614 if (dev == NULL)
615 dev = sfs_create(partition);
616 if (dev == NULL)
617 dev = ext2_create(partition);
618 if(dev == NULL)
619 continue;
620 n += dev_load(self, dev);
621 for(ptr = self; ptr != NULL; ptr = ptr->next) {
622 if(ptr->device_type != 0)
623 continue;
624 ptr->device_type = IDE_TYPE;
625 ptr->device_num = 0;
626 ptr->partition = i;
628 dev->destroy(dev);
630 return n;
633 menu_t *menu_load(boot_dev_t * boot)
635 menu_t *self;
636 int n;
638 self = entry_alloc();
639 self->default_os = 0;
640 self->delay = 5;
642 n = 0;
644 if(boot != NULL)
645 n = dev_load(self, boot);
646 else
647 n = magic_load(self);
649 if (n == 0) {
650 return NULL;
651 free(self);
654 return self;
657 menu_t *display(menu_t * self, int selected)
659 int i;
660 menu_t *entry, *sentry = NULL;
661 char buff[100];
662 static int first = 0, last = 10;
664 video_draw_box(1, 0, "Select boot option.", 1, 5, 5, 70, 15);
666 if (selected < first)
667 first--;
669 if (selected > last)
670 first++;
672 for (i = 0; i < first; i++)
673 self = self->next;
675 for (i = 0, entry = self->next; entry != NULL && i < 11;
676 entry = entry->next, i++) {
677 sprintf(buff, " %s", entry->title);
678 video_draw_text(6, 8 + i, (i + first == selected ? 2 : 0), buff,
679 68);
680 if (i + first == selected)
681 sentry = entry;
684 last = first + i - 1;
686 return sentry;
689 menu_t *menu_display(menu_t * self)
691 int key, max, selected, delay, old_delay;
692 menu_t *entry;
693 for (max = -2, entry = self; entry != NULL;
694 entry = entry->next, max++) ;
696 selected = self->default_os <= max ? self->default_os : max;
697 delay = self->delay * 100;
698 if (delay <= 0)
699 goto skip_delay;
700 entry = display(self, selected);
701 old_delay = 0;
702 while (delay) {
703 if (old_delay != delay / 100) {
704 char tmp[30];
705 sprintf(tmp, "(%d seconds left)", delay / 100);
706 video_draw_text(54, 6, 0, tmp, 20);
707 old_delay = delay / 100;
709 if (tstc())
710 break;
711 udelay(10000);
712 delay--;
715 if (delay == 0)
716 return entry;
718 skip_delay:
719 while (1) {
720 entry = display(self, selected);
721 key = video_get_key();
722 if (key == 4 && selected > 0)
723 selected--;
724 if (key == 3 && selected < max)
725 selected++;
726 if (key == 117)
727 break;
728 if (key == 1 || key == 6)
729 return entry;
732 return NULL;
735 void menu_free(menu_t * self)
737 menu_t *entry;
738 while (self != NULL) {
739 entry = self;
740 self = self->next;
741 entry_free(entry);