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.
29 static struct EntryObject
*EntryObject_new(char *name
, char *args
,
32 struct EntryObject
*self
;
34 self
= malloc(sizeof(struct EntryObject
));
35 self
->name
= strdup(name
);
38 self
->args
= strdup(args
);
39 self
->partition
= NULL
;
41 self
->partition
= strdup(partition
);
46 static menu_t
*entry_alloc(void)
49 entry
= malloc(sizeof(menu_t
));
55 entry
->modules_cnt
= 0;
57 entry
->device_type
= DEFAULT_TYPE
;
58 entry
->device_num
= 0;
65 static void entry_free(menu_t
* entry
)
67 if (entry
->title
!= NULL
)
69 if (entry
->kernel
!= NULL
)
71 if (entry
->other
!= NULL
)
73 if (entry
->append
!= NULL
)
75 if (entry
->initrd
!= NULL
)
77 /* FIXME: free modules and args */
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
)
88 if (*src_offset
>= src_len
)
91 nlptr
= strchr(src
+ *src_offset
, '\n');
93 len
= nlptr
- (src
+ *src_offset
) + 1;
95 len
= src_len
- *src_offset
;
97 line
= malloc(len
+ 1);
98 strncpy(line
, src
+ *src_offset
, len
);
105 char *eatcomments(char *line
)
109 cptr
= strchr(line
, '#');
112 line
[cptr
- line
] = 0;
117 char *getnextword(char *line
)
122 bptr
= strchr(line
, ' ');
125 bptr
= strchr(line
, '\t');
132 word
= malloc(len
+ 1);
133 strncpy(word
, line
, len
);
139 char *strtrim(char *s
)
145 for (; isspace(*ptr_s
); ptr_s
++) ;
147 for (n
= strlen(ptr_s
); n
> 0 && isspace(*(ptr_s
+ n
- 1)); n
--) ;
159 char *kick_eatcomments(char *line
)
163 cptr
= strchr(line
, ';');
166 line
[cptr
- line
] = 0;
171 static int kick_fsm(char *buffer
, int buffer_len
, menu_t
* menu
)
176 char *lineptr
= NULL
;
178 menu_t
/**menu,*/ * entry
= NULL
, *ptr
= NULL
;
180 menu = entry_alloc();
181 menu->default_os = 0;
188 int parse
= 1, kernel
= 0;
192 if ((line
= getline(buffer
, buffer_len
,
197 kick_eatcomments(line
);
199 if (strlen(line
) == 0) {
204 word
= getnextword(line
);
205 if (strcmp(word
, "LABEL") == 0) {
207 lineptr
= line
+ strlen(word
);
214 if (strlen(lineptr
) > 0) {
217 entry
= entry_alloc();
218 entry
->title
= strdup(lineptr
);
224 if ((line
= getline(buffer
, buffer_len
,
232 kick_eatcomments(line
);
234 if (strlen(line
) == 0) {
239 word
= getnextword(line
);
240 lineptr
= line
+ strlen(word
);
241 if (strcmp(word
, "EXEC") == 0) {
243 } else if (strcmp(word
, "MODULE") == 0) {
245 } else if (strcmp(word
, "LABEL") == 0) {
246 offset
-= strlen(line
) + 1;
261 word
= getnextword(lineptr
);
267 entry
->kernel
= strdup(word
);
268 lineptr
= lineptr
+ strlen(word
);
270 if (strlen(lineptr
) > 0) {
271 entry
->append
= strdup(lineptr
);
279 word
= getnextword(lineptr
);
284 entry
->modules
[entry
->modules_cnt
++] =
285 EntryObject_new(word
, NULL
, NULL
);
291 for (ptr
= menu
; ptr
->next
!= NULL
; ptr
= ptr
->next
) ;
301 for (ptr
= menu
; ptr
->next
!= NULL
; ptr
= ptr
->next
) ;
315 static int fsm(char *buffer
, int buffer_len
, menu_t
* menu
)
320 char *lineptr
= NULL
;
322 menu_t
/**menu,*/ * entry
= NULL
, *ptr
= NULL
;
325 menu = entry_alloc();
326 menu->default_os = 0;
333 int parse
= 1, kernel
= 0;
337 if ((line
= getline(buffer
, buffer_len
,
344 if (strlen(line
) == 0) {
349 word
= getnextword(line
);
350 if (strcmp(word
, "title") == 0) {
352 lineptr
= line
+ strlen(word
);
353 } else if (strcmp(word
, "default") == 0) {
355 lineptr
= line
+ strlen(word
);
356 } else if (strcmp(word
, "delay") == 0) {
358 lineptr
= line
+ strlen(word
);
365 if (strlen(lineptr
) == 0)
368 word
= getnextword(lineptr
);
369 if (strlen(word
) == 0)
371 menu
->default_os
= strtol(word
);
376 if (strlen(lineptr
) == 0)
379 word
= getnextword(lineptr
);
380 if (strlen(word
) == 0)
382 menu
->delay
= strtol(word
);
387 if (strlen(lineptr
) > 0) {
390 entry
= entry_alloc();
391 entry
->title
= strdup(lineptr
);
397 if ((line
= getline(buffer
, buffer_len
,
407 if (strlen(line
) == 0) {
412 word
= getnextword(line
);
413 lineptr
= line
+ strlen(word
);
414 if (strcmp(word
, "kernel") == 0) {
416 } else if (strcmp(word
, "other") == 0) {
418 } else if (strcmp(word
, "root") == 0) {
420 } else if (strcmp(word
, "initrd") == 0) {
422 } else if (strcmp(word
, "module") == 0) {
424 } else if (strcmp(word
, "title") == 0) {
425 offset
-= strlen(line
) + 1;
440 word
= getnextword(lineptr
);
446 entry
->kernel
= strdup(word
);
447 lineptr
= lineptr
+ strlen(word
);
449 if (strlen(lineptr
) > 0) {
450 entry
->append
= strdup(lineptr
);
458 word
= getnextword(lineptr
);
465 lineptr
= lineptr
+ strlen(word
);
467 if (strcmp(word
, "tftp") == 0) {
468 entry
->device_type
= TFTP_TYPE
;
472 } else if (strcmp(word
, "cdrom") == 0) {
473 entry
->device_type
= CD_TYPE
;
477 } else if (strcmp(word
, "ide") == 0) {
478 char *sep
= strchr(lineptr
, ':');
479 if (sep
== NULL
|| *++sep
== 0) {
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;
503 word
= getnextword(lineptr
);
510 lineptr
= lineptr
+ strlen(word
);
511 entry
->other
= strdup(word
);
517 word
= getnextword(lineptr
);
522 entry
->initrd
= strdup(word
);
529 word
= getnextword(lineptr
);
534 entry
->modules
[entry
->modules_cnt
++] =
535 EntryObject_new(word
, NULL
, NULL
);
541 for (ptr
= menu
; ptr
->next
!= NULL
; ptr
= ptr
->next
) ;
551 for (ptr
= menu
; ptr
->next
!= NULL
; ptr
= ptr
->next
) ;
565 typedef struct menu {
570 char *modules[MAX_MODULES];
572 char *argv[MAX_MODULES];
584 static int dev_load(menu_t
*self
, boot_dev_t
*dev
)
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",
596 n
+= kick_fsm(buffer
, buffer_length
, self
);
601 static int magic_load(menu_t
*self
)
606 struct RdbPartition
*partition
;
609 for(i
= 0; i
< RDB_LOCATION_LIMIT
; i
++) {
610 partition
= RdbPartitionTable_get(0, i
);
611 if(partition
== NULL
)
613 dev
= dos_create(partition
);
615 dev
= sfs_create(partition
);
617 dev
= ext2_create(partition
);
620 n
+= dev_load(self
, dev
);
621 for(ptr
= self
; ptr
!= NULL
; ptr
= ptr
->next
) {
622 if(ptr
->device_type
!= 0)
624 ptr
->device_type
= IDE_TYPE
;
633 menu_t
*menu_load(boot_dev_t
* boot
)
638 self
= entry_alloc();
639 self
->default_os
= 0;
645 n
= dev_load(self
, boot
);
647 n
= magic_load(self
);
657 menu_t
*display(menu_t
* self
, int selected
)
660 menu_t
*entry
, *sentry
= NULL
;
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
)
672 for (i
= 0; i
< first
; i
++)
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
,
680 if (i
+ first
== selected
)
684 last
= first
+ i
- 1;
689 menu_t
*menu_display(menu_t
* self
)
691 int key
, max
, selected
, delay
, old_delay
;
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;
700 entry
= display(self
, selected
);
703 if (old_delay
!= delay
/ 100) {
705 sprintf(tmp
, "(%d seconds left)", delay
/ 100);
706 video_draw_text(54, 6, 0, tmp
, 20);
707 old_delay
= delay
/ 100;
720 entry
= display(self
, selected
);
721 key
= video_get_key();
722 if (key
== 4 && selected
> 0)
724 if (key
== 3 && selected
< max
)
728 if (key
== 1 || key
== 6)
735 void menu_free(menu_t
* self
)
738 while (self
!= NULL
) {