1 /* ----------------------------------------------------------------------- *
3 * Copyright 2004-2006 H. Peter Anvin - All Rights Reserved
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, Inc., 53 Temple Place Ste 330,
8 * Boston MA 02111-1307, USA; either version 2 of the License, or
9 * (at your option) any later version; incorporated herein by reference.
11 * ----------------------------------------------------------------------- */
13 #define _GNU_SOURCE /* Needed for asprintf() on Linux */
29 int allowedit
= 1; /* Allow edits of the command line */
31 int shiftkey
= 0; /* Only display menu if shift key pressed */
32 long long totaltimeout
= 0;
34 char *menu_title
= "";
35 char *ontimeout
= NULL
;
38 char *menu_master_passwd
= NULL
;
40 char *menu_background
= NULL
;
42 struct menu_entry menu_entries
[MAX_ENTRIES
];
43 struct menu_entry hide_entries
[MAX_ENTRIES
];
44 struct menu_entry
*menu_hotkeys
[256];
46 #define astrdup(x) ({ char *__x = (x); \
47 size_t __n = strlen(__x) + 1; \
48 char *__p = alloca(__n); \
49 if ( __p ) memcpy(__p, __x, __n); \
52 const char *ipappends
[32];
64 __intcall(0x22, &r
, &r
);
66 nipappends
= min(r
.ecx
.w
[0], 32);
67 ipp
= MK_PTR(r
.es
, r
.ebx
.w
[0]);
68 for ( i
= 0 ; i
< nipappends
; i
++ ) {
69 ipappends
[i
] = MK_PTR(r
.es
, *ipp
++);
72 ipappends
[0] = "ip=foo:bar:baz:quux";
73 ipappends
[1] = "BOOTIF=01-aa-bb-cc-dd-ee-ff";
84 __intcall(0x22, &r
, &r
);
86 return MK_PTR(r
.es
, r
.ebx
.w
[0]);
88 return "syslinux.cfg"; /* Dummy default name */
97 while (*p
&& my_isspace(*p
))
103 /* Check to see if we are at a certain keyword (case insensitive) */
104 /* Returns a pointer to the first character past the keyword */
106 looking_at(char *line
, const char *kwd
)
111 while ( *p
&& *q
&& ((*p
^*q
) & ~0x20) == 0 ) {
117 return NULL
; /* Didn't see the keyword */
119 return my_isspace(*p
) ? p
: NULL
; /* Must be EOL or whitespace */
128 unsigned int ipappend
;
129 unsigned int menuhide
;
130 unsigned int menudefault
;
134 record(struct labeldata
*ld
, char *append
)
136 char ipoptions
[256], *ipp
;
138 struct menu_entry
*me
= &menu_entries
[nentries
];
142 me
->displayname
= ld
->menulabel
? ld
->menulabel
: ld
->label
;
143 me
->label
= ld
->label
;
144 me
->passwd
= ld
->passwd
;
147 if ( ld
->menulabel
) {
148 unsigned char *p
= (unsigned char *)strchr(ld
->menulabel
, '^');
150 int hotkey
= p
[1] & ~0x20;
151 if ( !menu_hotkeys
[hotkey
] ) {
159 for ( i
= 0 ; i
< 32 ; i
++ ) {
160 if ( (ld
->ipappend
& (1U << i
)) && ipappends
[i
] )
161 ipp
+= sprintf(ipp
, " %s", ipappends
[i
]);
165 if ( !a
) a
= append
;
166 if ( !a
|| (a
[0] == '-' && !a
[1]) ) a
= "";
168 asprintf(&me
->cmdline
, "%s%s%s%s", ld
->kernel
, s
, a
, ipoptions
);
181 if ( !ld
->menuhide
) {
183 menu_hotkeys
[me
->hotkey
] = me
;
185 if ( ld
->menudefault
)
191 hide_entries
[nhidden
].displayname
= me
->displayname
;
192 hide_entries
[nhidden
].label
= me
->label
;
193 hide_entries
[nhidden
].cmdline
= me
->cmdline
;
194 hide_entries
[nhidden
].passwd
= me
->passwd
;
196 me
->displayname
= NULL
;
209 /* Convert a CLI-style command line to an executable command line */
212 struct menu_entry
*me
;
216 while ( *p
&& !my_isspace(*p
) )
219 /* p now points to the first byte beyond the kernel name */
222 for ( i
= 0 ; i
< nentries
; i
++ ) {
223 me
= &menu_entries
[i
];
225 if ( !strncmp(str
, me
->label
, pos
) && !me
->label
[pos
] ) {
226 /* Found matching label */
227 q
= malloc(strlen(me
->cmdline
) + strlen(p
) + 1);
228 strcpy(q
, me
->cmdline
);
237 for ( i
= 0 ; i
< nhidden
; i
++ ) {
238 me
= &hide_entries
[i
];
240 if ( !strncmp(str
, me
->label
, pos
) && !me
->label
[pos
] ) {
241 /* Found matching label */
242 q
= malloc(strlen(me
->cmdline
) + strlen(p
) + 1);
243 strcpy(q
, me
->cmdline
);
263 while (*ep
&& !my_isspace(*ep
))
276 static int my_isxdigit(char c
)
278 unsigned char uc
= c
| 0x20;
280 return (uc
-'0') < 10 || (uc
-'a') < 6;
283 static unsigned int hexval(char c
)
285 unsigned char uc
= c
| 0x20;
293 static unsigned int hexval2(char *p
)
295 return (hexval(p
[0]) << 4)+hexval(p
[1]);
298 static unsigned int parse_argb(char **p
)
310 while (my_isxdigit(*ep
))
320 (hexval(sp
[0])*0x11 << 16)|
321 (hexval(sp
[1])*0x11 << 8) |
322 (hexval(sp
[2])*0x11 << 0);
326 (hexval(sp
[0])*0x11 << 24)|
327 (hexval(sp
[1])*0x11 << 16)|
328 (hexval(sp
[2])*0x11 << 8) |
329 (hexval(sp
[3])*0x11 << 0);
331 case 6: /* #rrggbb */
332 case 9: /* #rrrgggbbb */
333 case 12: /* #rrrrggggbbbb */
337 (hexval2(sp
+0) << 16) |
338 (hexval2(sp
+dl
) << 8)|
339 (hexval2(sp
+dl
*2) << 0);
341 case 8: /* #aarrggbb */
342 /* 12 is indistinguishable from #rrrrggggbbbb,
343 assume that is a more common format */
344 case 16: /* #aaaarrrrggggbbbb */
347 (hexval2(sp
+0) << 24) |
348 (hexval2(sp
+dl
) << 16) |
349 (hexval2(sp
+dl
*2) << 8)|
350 (hexval2(sp
+dl
*3) << 0);
360 void parse_config(const char *filename
)
362 char line
[MAX_LINE
], *p
, *ep
;
365 unsigned int ipappend
= 0;
366 static struct labeldata ld
;
371 filename
= get_config();
373 f
= fopen(filename
, "r");
377 while ( fgets(line
, sizeof line
, f
) ) {
378 p
= strchr(line
, '\r');
381 p
= strchr(line
, '\n');
387 if ( looking_at(p
, "menu") ) {
390 if ( looking_at(p
, "title") ) {
391 menu_title
= strdup(skipspace(p
+5));
392 } else if ( looking_at(p
, "label") ) {
394 ld
.menulabel
= strdup(skipspace(p
+5));
395 } else if ( looking_at(p
, "default") ) {
397 } else if ( looking_at(p
, "hide") ) {
399 } else if ( looking_at(p
, "passwd") ) {
400 ld
.passwd
= strdup(skipspace(p
+6));
401 } else if ( looking_at(p
, "shiftkey") ) {
403 } else if ( looking_at(p
, "onerror") ) {
404 onerror
= strdup(skipspace(p
+7));
405 } else if ( looking_at(p
, "master") ) {
407 if ( looking_at(p
, "passwd") ) {
408 menu_master_passwd
= strdup(skipspace(p
+6));
410 } else if ( (ep
= looking_at(p
, "background")) ) {
412 menu_background
= dup_word(&p
);
413 } else if ((ep
= looking_at(p
, "color")) ||
414 (ep
= looking_at(p
, "colour"))) {
416 struct color_table
*cptr
;
418 cptr
= console_color_table
;
419 for ( i
= 0; i
< console_color_table_size
; i
++ ) {
420 if ( (ep
= looking_at(p
, cptr
->name
)) ) {
424 cptr
->ansi
= dup_word(&p
);
428 cptr
->argb_fg
= parse_argb(&p
);
431 cptr
->argb_bg
= parse_argb(&p
);
439 /* Unknown, check for layout parameters */
440 struct menu_parameter
*pp
;
441 for ( pp
= mparm
; pp
->name
; pp
++ ) {
442 if ( (ep
= looking_at(p
, pp
->name
)) ) {
443 pp
->value
= atoi(skipspace(ep
));
448 } else if ( looking_at(p
, "append") ) {
449 char *a
= strdup(skipspace(p
+6));
454 } else if ( looking_at(p
, "label") ) {
457 ld
.label
= strdup(p
);
458 ld
.kernel
= strdup(p
);
462 ld
.ipappend
= ipappend
;
463 ld
.menudefault
= ld
.menuhide
= 0;
464 } else if ( looking_at(p
, "kernel") ) {
467 ld
.kernel
= strdup(skipspace(p
+6));
469 } else if ( looking_at(p
, "timeout") ) {
470 timeout
= (atoi(skipspace(p
+7))*CLK_TCK
+9)/10;
471 } else if ( looking_at(p
, "totaltimeout") ) {
472 totaltimeout
= (atoll(skipspace(p
+13))*CLK_TCK
+9)/10;
473 } else if ( looking_at(p
, "ontimeout") ) {
474 ontimeout
= strdup(skipspace(p
+9));
475 } else if ( looking_at(p
, "allowoptions") ) {
476 allowedit
= atoi(skipspace(p
+12));
477 } else if ( looking_at(p
, "ipappend") ) {
479 ld
.ipappend
= atoi(skipspace(p
+8));
481 ipappend
= atoi(skipspace(p
+8));
482 } else if ( looking_at(p
, "localboot") ) {
483 ld
.kernel
= strdup(".localboot");
484 ld
.append
= strdup(skipspace(p
+9));
492 ontimeout
= unlabel(ontimeout
);
494 onerror
= unlabel(onerror
);