]>
Commit | Line | Data |
---|---|---|
27996c53 MT |
1 | diff -Nur grub-0.97-misc/docs/grub.texi grub-0.97-splash/docs/grub.texi |
2 | --- grub-0.97-misc/docs/grub.texi 2005-08-21 20:22:18.000000000 +0300 | |
3 | +++ grub-0.97-splash/docs/grub.texi 2005-08-21 20:29:22.000000000 +0300 | |
4 | @@ -2118,6 +2118,7 @@ | |
5 | * default:: Set the default entry | |
6 | * fallback:: Set the fallback entry | |
7 | * hiddenmenu:: Hide the menu interface | |
8 | +* gfxmenu:: Use graphical menu interface | |
9 | * timeout:: Set the timeout | |
10 | * title:: Start a menu entry | |
11 | @end menu | |
12 | @@ -2150,6 +2151,15 @@ | |
13 | @end deffn | |
14 | ||
15 | ||
16 | +@node gfxmenu | |
17 | +@subsection gfxmenu | |
18 | + | |
19 | +@deffn Command gfxmenu file | |
20 | +Use the graphical menu interface. The graphics data are taken from | |
21 | +@var{file} and must be created using 'mkbootmsg' from the gfxboot package. | |
22 | +@end deffn | |
23 | + | |
24 | + | |
25 | @node hiddenmenu | |
26 | @subsection hiddenmenu | |
27 | ||
28 | diff -Nur grub-0.97-misc/grub/asmstub.c grub-0.97-splash/grub/asmstub.c | |
29 | --- grub-0.97-misc/grub/asmstub.c 2005-08-21 20:22:18.000000000 +0300 | |
30 | +++ grub-0.97-splash/grub/asmstub.c 2005-08-21 20:29:22.000000000 +0300 | |
31 | @@ -480,6 +480,32 @@ | |
32 | return 0; | |
33 | } | |
34 | ||
35 | +/* graphical menu functions . */ | |
36 | +int | |
37 | +gfx_init (gfx_data_t *gfx_data) | |
38 | +{ | |
39 | + return 0; | |
40 | +} | |
41 | + | |
42 | +int | |
43 | +gfx_done (gfx_data_t *gfx_data) | |
44 | +{ | |
45 | + return 0; | |
46 | +} | |
47 | + | |
48 | +int | |
49 | +gfx_input (gfx_data_t *gfx_data, int *menu_entry) | |
50 | +{ | |
51 | + return 0; | |
52 | +} | |
53 | + | |
54 | +int | |
55 | +gfx_setup_menu (gfx_data_t *gfx_data) | |
56 | +{ | |
57 | + return 0; | |
58 | +} | |
59 | + | |
60 | + | |
61 | /* low-level timing info */ | |
62 | int | |
63 | getrtsecs (void) | |
64 | diff -Nur grub-0.97-misc/stage2/asm.S grub-0.97-splash/stage2/asm.S | |
65 | --- grub-0.97-misc/stage2/asm.S 2005-08-21 20:22:18.000000000 +0300 | |
66 | +++ grub-0.97-splash/stage2/asm.S 2005-08-21 20:29:22.000000000 +0300 | |
67 | @@ -1610,6 +1610,301 @@ | |
68 | popl %ebp | |
69 | ret | |
70 | ||
71 | + | |
72 | +/* | |
73 | + * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
74 | + * | |
75 | + * graphical menu functions | |
76 | + * | |
77 | + */ | |
78 | + | |
79 | +/* | |
80 | + * int gfx_init (gfx_data_t *gfx_data) | |
81 | + * | |
82 | + * init gfx things | |
83 | + * | |
84 | + * return vales: | |
85 | + * 0: ok | |
86 | + * 1: failed | |
87 | + * sets gfx_data->ok | |
88 | + */ | |
89 | + | |
90 | +ENTRY(gfx_init) | |
91 | + pushl %ebp | |
92 | + movl %esp, %ebp | |
93 | + | |
94 | + pushl %edi | |
95 | + pushl %esi | |
96 | + pushl %ebx | |
97 | + | |
98 | + movl 8(%ebp),%edx | |
99 | + movl %edx,%edi | |
100 | + andl $0xf,%edi | |
101 | + shrl $4,%edx | |
102 | + | |
103 | + pushl %ebp | |
104 | + | |
105 | + call EXT_C(prot_to_real) | |
106 | + .code16 | |
107 | + | |
108 | + pushw %ds | |
109 | + | |
110 | + movw %dx,%ds | |
111 | + leal gfx_ofs_sys_cfg(%di),%esi | |
112 | + movl gfx_ofs_mem_file(%di),%eax | |
113 | + movl gfx_ofs_mem_cur(%di),%ebx | |
114 | + movl gfx_ofs_mem_max(%di),%ecx | |
115 | + movw %ds,%dx | |
116 | + | |
117 | + /* basically just a lcall, but we need %edi */ | |
118 | + pushw %cs | |
119 | + pushw $gfx_init_50 | |
120 | + pushl gfx_ofs_jmp_table + 4 * 0 (%di) | |
121 | + | |
122 | + movl gfx_ofs_mem_align(%di),%edi | |
123 | + | |
124 | + lret | |
125 | + | |
126 | +gfx_init_50: | |
127 | + movl $0,%ebx | |
128 | + adcl $0,%ebx | |
129 | + | |
130 | + popw %ds | |
131 | + | |
132 | + DATA32 call EXT_C(real_to_prot) | |
133 | + .code32 | |
134 | + | |
135 | + popl %ebp | |
136 | + | |
137 | + movl %ebx,%eax | |
138 | + negl %ebx | |
139 | + incl %ebx | |
140 | + movl 8(%ebp),%edx | |
141 | + movl %ebx,gfx_ofs_ok(%edx) | |
142 | + | |
143 | + popl %ebx | |
144 | + popl %esi | |
145 | + popl %edi | |
146 | + | |
147 | + popl %ebp | |
148 | + ret | |
149 | + | |
150 | + | |
151 | +/* | |
152 | + * int gfx_done (gfx_data_t *gfx_data) | |
153 | + * | |
154 | + * shut down gfx things | |
155 | + * | |
156 | + * return vales: | |
157 | + * always 0 | |
158 | + * sets gfx_data->ok | |
159 | + */ | |
160 | + | |
161 | +ENTRY(gfx_done) | |
162 | + pushl %ebp | |
163 | + movl %esp, %ebp | |
164 | + | |
165 | + pushl %edi | |
166 | + pushl %esi | |
167 | + pushl %ebx | |
168 | + | |
169 | + movl 8(%ebp),%edx | |
170 | + movl %edx,%ebx | |
171 | + andl $0xf,%ebx | |
172 | + shrl $4,%edx | |
173 | + | |
174 | + pushl %ebp | |
175 | + | |
176 | + call EXT_C(prot_to_real) | |
177 | + .code16 | |
178 | + | |
179 | + pushw %ds | |
180 | + | |
181 | + movw %dx,%ds | |
182 | + | |
183 | + lcall *gfx_ofs_jmp_table + 4 * 1 (%bx) | |
184 | + | |
185 | + popw %ds | |
186 | + | |
187 | + DATA32 call EXT_C(real_to_prot) | |
188 | + .code32 | |
189 | + | |
190 | + popl %ebp | |
191 | + | |
192 | + xorl %eax,%eax | |
193 | + movl 8(%ebp),%edx | |
194 | + movl %eax,gfx_ofs_ok(%edx) | |
195 | + | |
196 | + popl %ebx | |
197 | + popl %esi | |
198 | + popl %edi | |
199 | + | |
200 | + popl %ebp | |
201 | + ret | |
202 | + | |
203 | + | |
204 | +/* | |
205 | + * int gfx_input (gfx_data_t *gfx_data, int *menu_entry) | |
206 | + * | |
207 | + * let user enter a command line | |
208 | + * | |
209 | + * uses gfx_data->cmdline as buffer | |
210 | + * | |
211 | + * return values: | |
212 | + * 1: abort | |
213 | + * 2: boot | |
214 | + * menu_entry: selected entry | |
215 | + */ | |
216 | + | |
217 | +ENTRY(gfx_input) | |
218 | + pushl %ebp | |
219 | + movl %esp, %ebp | |
220 | + | |
221 | + pushl %edi | |
222 | + pushl %esi | |
223 | + pushl %ebx | |
224 | + | |
225 | + movl 8(%ebp),%edx | |
226 | + movl %edx,%ebx | |
227 | + andl $0xf,%ebx | |
228 | + shrl $4,%edx | |
229 | + | |
230 | + pushl %ebp | |
231 | + | |
232 | + call EXT_C(prot_to_real) | |
233 | + .code16 | |
234 | + | |
235 | + pushw %ds | |
236 | + | |
237 | + movw %dx,%ds | |
238 | + shll $4,%edx | |
239 | + movl gfx_ofs_cmdline(%bx),%edi | |
240 | + subl %edx,%edi | |
241 | + movw gfx_ofs_cmdline_len(%bx),%cx | |
242 | + movw gfx_ofs_timeout(%bx),%ax | |
243 | + imulw $18,%ax | |
244 | + | |
245 | + pushl %ebp | |
246 | + lcall *gfx_ofs_jmp_table + 4 * 2 (%bx) | |
247 | + popl %ebp | |
248 | + movl %eax,%ecx | |
249 | + | |
250 | + popw %ds | |
251 | + | |
252 | + DATA32 call EXT_C(real_to_prot) | |
253 | + .code32 | |
254 | + | |
255 | + popl %ebp | |
256 | + | |
257 | + movl 12(%ebp),%edx | |
258 | + movl %ebx,(%edx) | |
259 | + | |
260 | + movl %ecx,%eax | |
261 | + | |
262 | + popl %ebx | |
263 | + popl %esi | |
264 | + popl %edi | |
265 | + | |
266 | + popl %ebp | |
267 | + ret | |
268 | + | |
269 | + | |
270 | +/* | |
271 | + * int gfx_setup_menu (gfx_data_t *gfx_data) | |
272 | + * | |
273 | + * draw boot menu | |
274 | + * | |
275 | + * return values: | |
276 | + * always 0 | |
277 | + */ | |
278 | + | |
279 | +/* menu entry descriptor */ | |
280 | +#define menu_entries 0 | |
281 | +#define menu_default 2 /* seg:ofs */ | |
282 | +#define menu_ent_list 6 /* seg:ofs */ | |
283 | +#define menu_ent_size 10 | |
284 | +#define menu_arg_list 12 /* seg:ofs */ | |
285 | +#define menu_arg_size 16 | |
286 | +#define sizeof_menu_desc 18 | |
287 | + | |
288 | +ENTRY(gfx_setup_menu) | |
289 | + pushl %ebp | |
290 | + movl %esp, %ebp | |
291 | + | |
292 | + pushl %edi | |
293 | + pushl %esi | |
294 | + pushl %ebx | |
295 | + | |
296 | + movl 8(%ebp),%edx | |
297 | + movl %edx,%ebx | |
298 | + andl $0xf,%ebx | |
299 | + shrl $4,%edx | |
300 | + | |
301 | + call EXT_C(prot_to_real) | |
302 | + .code16 | |
303 | + | |
304 | + pushw %ds | |
305 | + | |
306 | + movw %dx,%ds | |
307 | + shll $4,%edx | |
308 | + | |
309 | + subw $sizeof_menu_desc,%sp | |
310 | + movw %sp,%bp | |
311 | + | |
312 | + movl gfx_ofs_menu_entries(%bx),%eax | |
313 | + movw %ax,menu_entries(%bp) | |
314 | + | |
315 | + movl gfx_ofs_menu_default_entry(%bx),%eax | |
316 | + subl %edx,%eax | |
317 | + movw %ax,menu_default(%bp) | |
318 | + movw %ds,menu_default+2(%bp) | |
319 | + | |
320 | + movl gfx_ofs_menu_list(%bx),%eax | |
321 | + subl %edx,%eax | |
322 | + movw %ax,menu_ent_list(%bp) | |
323 | + movw %ds,menu_ent_list+2(%bp) | |
324 | + | |
325 | + movl gfx_ofs_menu_entry_len(%bx),%eax | |
326 | + movw %ax,menu_ent_size(%bp) | |
327 | + | |
328 | + movl gfx_ofs_args_list(%bx),%eax | |
329 | + subl %edx,%eax | |
330 | + movw %ax,menu_arg_list(%bp) | |
331 | + movw %ds,menu_arg_list+2(%bp) | |
332 | + | |
333 | + movl gfx_ofs_args_entry_len(%bx),%eax | |
334 | + movw %ax,menu_arg_size(%bp) | |
335 | + | |
336 | + movw %bp,%si | |
337 | + pushw %ss | |
338 | + popw %es | |
339 | + | |
340 | + lcall %ds: *gfx_ofs_jmp_table + 4 * 3 (%bx) | |
341 | + | |
342 | + addw $sizeof_menu_desc,%sp | |
343 | + | |
344 | + popw %ds | |
345 | + | |
346 | + DATA32 call EXT_C(real_to_prot) | |
347 | + .code32 | |
348 | + | |
349 | + xorl %eax,%eax | |
350 | + | |
351 | + popl %ebx | |
352 | + popl %esi | |
353 | + popl %edi | |
354 | + | |
355 | + popl %ebp | |
356 | + ret | |
357 | + | |
358 | + | |
359 | +/* | |
360 | + * | |
361 | + * end graphics stuff | |
362 | + * | |
363 | + * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
364 | + */ | |
365 | + | |
366 | ||
367 | /* | |
368 | * gateA20(int linear) | |
369 | diff -Nur grub-0.97-misc/stage2/builtins.c grub-0.97-splash/stage2/builtins.c | |
370 | --- grub-0.97-misc/stage2/builtins.c 2005-08-21 20:22:30.000000000 +0300 | |
371 | +++ grub-0.97-splash/stage2/builtins.c 2005-08-21 20:29:22.000000000 +0300 | |
372 | @@ -63,6 +63,8 @@ | |
373 | int fallback_entries[MAX_FALLBACK_ENTRIES]; | |
374 | /* The number of current entry. */ | |
375 | int current_entryno; | |
376 | +/* graphics file */ | |
377 | +char graphics_file[64]; | |
378 | /* The address for Multiboot command-line buffer. */ | |
379 | static char *mb_cmdline; | |
380 | /* The password. */ | |
381 | @@ -1331,6 +1333,26 @@ | |
382 | }; | |
383 | ||
384 | \f | |
385 | +/* graphics */ | |
386 | +static int | |
387 | +gfxmenu_func (char *arg, int flags) | |
388 | +{ | |
389 | + memmove(graphics_file, arg, sizeof graphics_file - 1); | |
390 | + graphics_file[sizeof graphics_file - 1] = 0; | |
391 | + | |
392 | + return 0; | |
393 | +} | |
394 | + | |
395 | +static struct builtin builtin_gfxmenu = | |
396 | +{ | |
397 | + "gfxmenu", | |
398 | + gfxmenu_func, | |
399 | + BUILTIN_MENU | BUILTIN_HELP_LIST, | |
400 | + "gfxmenu FILE", | |
401 | + "Use the graphical menu from FILE." | |
402 | +}; | |
403 | + | |
404 | +\f | |
405 | /* geometry */ | |
406 | static int | |
407 | geometry_func (char *arg, int flags) | |
408 | @@ -4837,6 +4859,7 @@ | |
409 | &builtin_find, | |
410 | &builtin_fstest, | |
411 | &builtin_geometry, | |
412 | + &builtin_gfxmenu, | |
413 | &builtin_halt, | |
414 | &builtin_help, | |
415 | &builtin_hiddenmenu, | |
416 | diff -Nur grub-0.97-misc/stage2/shared.h grub-0.97-splash/stage2/shared.h | |
417 | --- grub-0.97-misc/stage2/shared.h 2005-08-21 20:22:18.000000000 +0300 | |
418 | +++ grub-0.97-splash/stage2/shared.h 2005-08-21 20:29:22.000000000 +0300 | |
419 | @@ -374,6 +374,27 @@ | |
420 | #endif /* WITHOUT_LIBC_STUBS */ | |
421 | ||
422 | ||
423 | +/* see typedef gfx_data_t below */ | |
424 | +#define gfx_ofs_ok 0x00 | |
425 | +#define gfx_ofs_mem_start 0x04 | |
426 | +#define gfx_ofs_mem_cur 0x08 | |
427 | +#define gfx_ofs_mem_max 0x0c | |
428 | +#define gfx_ofs_code_seg 0x10 | |
429 | +#define gfx_ofs_jmp_table 0x14 | |
430 | +#define gfx_ofs_sys_cfg 0x44 | |
431 | +#define gfx_ofs_cmdline 0x64 | |
432 | +#define gfx_ofs_cmdline_len 0x68 | |
433 | +#define gfx_ofs_menu_list 0x6c | |
434 | +#define gfx_ofs_menu_default_entry 0x70 | |
435 | +#define gfx_ofs_menu_entries 0x74 | |
436 | +#define gfx_ofs_menu_entry_len 0x78 | |
437 | +#define gfx_ofs_args_list 0x7c | |
438 | +#define gfx_ofs_args_entry_len 0x80 | |
439 | +#define gfx_ofs_timeout 0x84 | |
440 | +#define gfx_ofs_mem_file 0x88 | |
441 | +#define gfx_ofs_mem_align 0x8c | |
442 | + | |
443 | + | |
444 | #ifndef ASM_FILE | |
445 | /* | |
446 | * Below this should be ONLY defines and other constructs for C code. | |
447 | @@ -595,6 +616,41 @@ | |
448 | extern int default_entry; | |
449 | extern int current_entryno; | |
450 | ||
451 | + | |
452 | +/* | |
453 | + * graphics menu stuff | |
454 | + * | |
455 | + * Note: gfx_data and all data referred to in it must lie within a 64k area. | |
456 | + */ | |
457 | +typedef struct { | |
458 | + unsigned ok; /* set while we're in graphics mode */ | |
459 | + unsigned mem_start, mem_cur, mem_max; | |
460 | + unsigned code_seg; /* code segment of binary graphics code */ | |
461 | + unsigned jmp_table[12]; /* link to graphics functions */ | |
462 | + unsigned char sys_cfg[32]; /* sys_cfg[0]: identifies boot loader (grub == 2) */ | |
463 | + char *cmdline; /* command line returned by gfx_input() */ | |
464 | + unsigned cmdline_len; /* length of the above */ | |
465 | + char *menu_list; /* list of menu entries, each of fixed length (menu_entry_len) */ | |
466 | + char *menu_default_entry; /* the default entry */ | |
467 | + unsigned menu_entries; /* number of entries in menu_list */ | |
468 | + unsigned menu_entry_len; /* one entry */ | |
469 | + char *args_list; /* same structure as menu_list, menu_entries entries */ | |
470 | + unsigned args_entry_len; /* one entry */ | |
471 | + unsigned timeout; /* in seconds (0: no timeout) */ | |
472 | + unsigned mem_file; /* aligned gfx file start */ | |
473 | + unsigned mem_align; /* aligned cpio file start */ | |
474 | +} __attribute__ ((packed)) gfx_data_t; | |
475 | + | |
476 | +extern gfx_data_t *graphics_data; | |
477 | + | |
478 | +/* pointer to graphics image data */ | |
479 | +extern char graphics_file[64]; | |
480 | + | |
481 | +int gfx_init(gfx_data_t *gfx_data); | |
482 | +int gfx_done(gfx_data_t *gfx_data); | |
483 | +int gfx_input(gfx_data_t *gfx_data, int *menu_entry); | |
484 | +int gfx_setup_menu(gfx_data_t *gfx_data); | |
485 | + | |
486 | /* The constants for password types. */ | |
487 | typedef enum | |
488 | { | |
489 | diff -Nur grub-0.97-misc/stage2/stage2.c grub-0.97-splash/stage2/stage2.c | |
490 | --- grub-0.97-misc/stage2/stage2.c 2005-08-21 20:22:18.000000000 +0300 | |
491 | +++ grub-0.97-splash/stage2/stage2.c 2005-08-21 20:29:22.000000000 +0300 | |
492 | @@ -22,6 +22,8 @@ | |
493 | ||
494 | grub_jmp_buf restart_env; | |
495 | ||
496 | +gfx_data_t *graphics_data; | |
497 | + | |
498 | #if defined(PRESET_MENU_STRING) || defined(SUPPORT_DISKLESS) | |
499 | ||
500 | # if defined(PRESET_MENU_STRING) | |
501 | @@ -310,6 +312,12 @@ | |
502 | ||
503 | if (! auth && password) | |
504 | { | |
505 | + if (*graphics_file) | |
506 | + { | |
507 | + printf ("\ | |
508 | + WARNING: graphical menu doesn\'t work\ | |
509 | + in conjunction with the password feature\n" ); | |
510 | + } | |
511 | printf ("\ | |
512 | Press enter to boot the selected OS or \'p\' to enter a\n\ | |
513 | password to unlock the next set of features."); | |
514 | @@ -753,6 +761,413 @@ | |
515 | } | |
516 | ||
517 | ||
518 | + | |
519 | +#if 0 | |
520 | +/* for debugging */ | |
521 | +static void hexdump(unsigned char *buf, unsigned len) | |
522 | +{ | |
523 | + int i, j = 0; | |
524 | + char s[17]; | |
525 | + unsigned addr = (unsigned) buf; | |
526 | + | |
527 | + s[16] = 0; | |
528 | + while(len--) { | |
529 | + i = buf[j]; | |
530 | + i = i & 0xff; | |
531 | + s[j & 15] = (i >= 0x20 && i <= 0x7e) ? i : '.'; | |
532 | + if(!(j & 15)) { | |
533 | + printf("%x ", j + addr); | |
534 | + } | |
535 | + if(!(j & 7) && (j & 15)) printf(" "); | |
536 | + /* stupid grub_printf */ | |
537 | + printf("%x", (i >> 4) & 0x0f); | |
538 | + printf("%x ", i & 0x0f); | |
539 | + if(!(++j & 15)) { | |
540 | + printf(" %s\n", s); | |
541 | + } | |
542 | + } | |
543 | + | |
544 | + if(j & 15) { | |
545 | + s[j & 15] = 0; | |
546 | + if(!(j & 8)) printf(" "); | |
547 | + i = 1 + 3 * (16 - (j & 15)); | |
548 | + while(i--) printf(" "); | |
549 | + printf("%s\n", s); | |
550 | + } | |
551 | +} | |
552 | +#endif | |
553 | + | |
554 | +/* | |
555 | + * Go through config entry and find kernel args, if any. | |
556 | + */ | |
557 | +static char *get_kernel_args(char *cfg) | |
558 | +{ | |
559 | + int j; | |
560 | + char *s, *t = ""; | |
561 | + | |
562 | + for(j = 0; ; j++) { | |
563 | + s = get_entry(cfg, j, 0); | |
564 | + if(!*s) break; | |
565 | + if(!memcmp(s, "kernel", 6) && (s[6] == ' ' || s[6] == '\t')) { | |
566 | + t = skip_to(0, s); | |
567 | + if(*t) t = skip_to(0, t); | |
568 | + break; | |
569 | + } | |
570 | + } | |
571 | + | |
572 | + return t; | |
573 | +} | |
574 | + | |
575 | + | |
576 | +/* | |
577 | + * Check header and return code start offset. | |
578 | + */ | |
579 | +static unsigned magic_ok(unsigned char *buf) | |
580 | +{ | |
581 | + if( | |
582 | + *(unsigned *) buf == 0x0b2d97f00 && /* magic id */ | |
583 | + (buf[4] == 5 || buf[4] == 6) /* version 5 or 6 */ | |
584 | + ) { | |
585 | + return *(unsigned *) (buf + 8); | |
586 | + } | |
587 | + | |
588 | + return 0; | |
589 | +} | |
590 | + | |
591 | + | |
592 | +/* | |
593 | + * Search cpio archive for gfx file. | |
594 | + */ | |
595 | +static unsigned find_file(unsigned char *buf, unsigned len, unsigned *gfx_file_start) | |
596 | +{ | |
597 | + unsigned i, fname_len, flen, code_start = 0; | |
598 | + | |
599 | + *gfx_file_start = 0; | |
600 | + | |
601 | + for(i = 0; i < len;) { | |
602 | + if((len - i) >= 0x1a && (buf[i] + (buf[i + 1] << 8)) == 0x71c7) { | |
603 | + fname_len = *(unsigned short *) (buf + i + 20); | |
604 | + flen = *(unsigned short *) (buf + i + 24) + (*(unsigned short *) (buf + i + 22) << 16); | |
605 | + i += 26 + fname_len; | |
606 | + i = ((i + 1) & ~1); | |
607 | + if((code_start = magic_ok(buf + i))) { | |
608 | + *gfx_file_start = i; | |
609 | + return code_start; | |
610 | + } | |
611 | + i += flen; | |
612 | + i = ((i + 1) & ~1); | |
613 | + } | |
614 | + else { | |
615 | + break; | |
616 | + } | |
617 | + } | |
618 | + | |
619 | + return code_start; | |
620 | +} | |
621 | + | |
622 | + | |
623 | +/* | |
624 | + * Leave that much space on the heap. Everything else goes to the graphics | |
625 | + * functions. | |
626 | + * | |
627 | + * 0x2000 is _not_ enough | |
628 | + */ | |
629 | +#define MIN_HEAP_SIZE 0x4000 | |
630 | + | |
631 | +/* gfx code needs at least this much free memory */ | |
632 | +#define MIN_GFX_FREE 0xc000 | |
633 | + | |
634 | +/* | |
635 | + * Does normally not return. | |
636 | + */ | |
637 | +static void | |
638 | +run_graphics_menu (char *menu_entries, char *config_entries, int num_entries, | |
639 | + char *heap, int entryno) | |
640 | +{ | |
641 | + unsigned char *buf; | |
642 | + unsigned u, buf_size, code_start, file_start; | |
643 | + char *s, *t, *cfg, *new_config; | |
644 | + char *saved_heap; | |
645 | + int i, j, max_len; | |
646 | + int selected_entry; | |
647 | + gfx_data_t *gfx_data; | |
648 | + | |
649 | + /* | |
650 | + * check gfx_data_t struct offsets for consistency; gcc will optimize away | |
651 | + * the whole block | |
652 | + */ | |
653 | + | |
654 | + /* dummy function to make ld fail */ | |
655 | + { | |
656 | + extern void wrong_struct_size(void); | |
657 | + #define gfx_ofs_check(a) if(gfx_ofs_##a != (char *) &gfx_data->a - (char *) gfx_data) wrong_struct_size(); | |
658 | + gfx_ofs_check(ok); | |
659 | + gfx_ofs_check(mem_start); | |
660 | + gfx_ofs_check(mem_cur); | |
661 | + gfx_ofs_check(mem_max); | |
662 | + gfx_ofs_check(code_seg); | |
663 | + gfx_ofs_check(jmp_table); | |
664 | + gfx_ofs_check(sys_cfg); | |
665 | + gfx_ofs_check(cmdline); | |
666 | + gfx_ofs_check(cmdline_len); | |
667 | + gfx_ofs_check(menu_list); | |
668 | + gfx_ofs_check(menu_default_entry); | |
669 | + gfx_ofs_check(menu_entries); | |
670 | + gfx_ofs_check(menu_entry_len); | |
671 | + gfx_ofs_check(args_list); | |
672 | + gfx_ofs_check(args_entry_len); | |
673 | + gfx_ofs_check(timeout); | |
674 | + gfx_ofs_check(mem_file); | |
675 | + gfx_ofs_check(mem_align); | |
676 | + #undef gfx_ofs_check | |
677 | + } | |
678 | + | |
679 | + if(!num_entries) return; | |
680 | + | |
681 | + graphics_data = gfx_data = (gfx_data_t *) heap; | |
682 | + heap += sizeof *gfx_data; | |
683 | + memset(gfx_data, 0, sizeof *gfx_data); | |
684 | + | |
685 | + gfx_data->sys_cfg[0] = 2; /* bootloader: grub */ | |
686 | + gfx_data->timeout = grub_timeout >= 0 ? grub_timeout : 0; | |
687 | + | |
688 | + | |
689 | + /* setup command line edit buffer */ | |
690 | + | |
691 | + gfx_data->cmdline_len = 256; | |
692 | + | |
693 | + gfx_data->cmdline = heap; | |
694 | + heap += gfx_data->cmdline_len; | |
695 | + memset(gfx_data->cmdline, 0, gfx_data->cmdline_len); | |
696 | + | |
697 | + | |
698 | + /* setup menu entries */ | |
699 | + | |
700 | + for(i = max_len = 0; i < num_entries; i++) { | |
701 | + j = strlen(get_entry(menu_entries, i, 0)); | |
702 | + if(j > max_len) max_len = j; | |
703 | + } | |
704 | + | |
705 | + if(!max_len) return; | |
706 | + | |
707 | + gfx_data->menu_entry_len = max_len + 1; | |
708 | + gfx_data->menu_entries = num_entries; | |
709 | + | |
710 | + gfx_data->menu_list = heap; | |
711 | + heap += gfx_data->menu_entry_len * gfx_data->menu_entries; | |
712 | + | |
713 | + memset(gfx_data->menu_list, 0, gfx_data->menu_entry_len * gfx_data->menu_entries); | |
714 | + | |
715 | + for(i = 0; i < (int) gfx_data->menu_entries; i++) { | |
716 | + strcpy(gfx_data->menu_list + i * gfx_data->menu_entry_len, get_entry(menu_entries, i, 0)); | |
717 | + } | |
718 | + | |
719 | + gfx_data->menu_default_entry = gfx_data->menu_list + entryno * gfx_data->menu_entry_len; | |
720 | + | |
721 | + | |
722 | + /* setup list of kernel args */ | |
723 | + | |
724 | + for(i = max_len = 0; i < num_entries; i++) { | |
725 | + s = get_kernel_args(get_entry(config_entries, i, 1)); | |
726 | + j = strlen(s); | |
727 | + if(j > max_len) max_len = j; | |
728 | + } | |
729 | + | |
730 | + gfx_data->args_entry_len = max_len + 1; | |
731 | + | |
732 | + gfx_data->args_list = heap; | |
733 | + heap += gfx_data->args_entry_len * gfx_data->menu_entries; | |
734 | + | |
735 | + memset(gfx_data->args_list, 0, gfx_data->args_entry_len * gfx_data->menu_entries); | |
736 | + | |
737 | + for(i = 0; i < (int) gfx_data->menu_entries; i++) { | |
738 | + strcpy(gfx_data->args_list + i* gfx_data->args_entry_len, get_kernel_args(get_entry(config_entries, i, 1))); | |
739 | + } | |
740 | + | |
741 | + | |
742 | + /* go back here when we no longer need the graphics data */ | |
743 | + saved_heap = heap; | |
744 | + | |
745 | + | |
746 | + /* get memory area to be used by graphics functions */ | |
747 | + | |
748 | + buf = (unsigned char *) (((unsigned) heap + 0xf) & ~0xf); | |
749 | + | |
750 | + buf_size = (unsigned char *) &buf - buf - MIN_HEAP_SIZE; | |
751 | + buf_size &= ~0xf; | |
752 | + | |
753 | + /* too small */ | |
754 | + if(buf_size < 0x10000) return; | |
755 | + | |
756 | + gfx_data->mem_start = (unsigned) buf; | |
757 | + gfx_data->mem_max = gfx_data->mem_start + buf_size; | |
758 | + | |
759 | +#if 0 | |
760 | + printf("graphics menu\n"); | |
761 | + printf( | |
762 | + "heap = 0x%x, buf = 0x%x (0x%x bytes), graphics_file = %s\n", | |
763 | + heap, gfx_data->mem_start, buf_size, graphics_file | |
764 | + ); | |
765 | + getkey(); | |
766 | +#endif | |
767 | + | |
768 | + heap += buf_size; | |
769 | + | |
770 | + | |
771 | + /* read the file */ | |
772 | + | |
773 | + if(!grub_open(graphics_file)) { | |
774 | + printf("graphics file \"%s\" missing, press a key to continue...\n", graphics_file); | |
775 | + getkey(); | |
776 | + return; | |
777 | + } | |
778 | + | |
779 | + i = grub_read(buf, buf_size); | |
780 | + | |
781 | + grub_close(); | |
782 | + | |
783 | + if(i <= 0) { | |
784 | + printf("error reading \"%s\", press a key to continue...\n", graphics_file); | |
785 | + getkey(); | |
786 | + return; | |
787 | + } | |
788 | + | |
789 | + /* besides the file, we need some working memory, too */ | |
790 | + if(i + MIN_GFX_FREE + 0x0f >= (int) buf_size) { | |
791 | + printf("file \"%s\" too large, press a key to continue...\n", graphics_file); | |
792 | + getkey(); | |
793 | + return; | |
794 | + } | |
795 | + | |
796 | + gfx_data->mem_cur = gfx_data->mem_start + ((i + 0x0f + 3) & ~3); /* align it */ | |
797 | + | |
798 | +#if 0 | |
799 | + printf("image: %d bytes (%d bytes left)\n", i, gfx_data->mem_max - gfx_data->mem_cur); | |
800 | + getkey(); | |
801 | +#endif | |
802 | + | |
803 | + | |
804 | + /* locate file inside cpio archive */ | |
805 | + if(!(code_start = find_file(buf, i, &file_start))) { | |
806 | + printf("\"%s\" has wrong format, press a key to continue...\n", graphics_file); | |
807 | + getkey(); | |
808 | + return; | |
809 | + } | |
810 | + | |
811 | + | |
812 | + /* align it */ | |
813 | + u = (-(code_start + gfx_data->mem_start + file_start)) & 0x0f; | |
814 | + gfx_data->mem_align = gfx_data->mem_start + u; | |
815 | + gfx_data->mem_file = gfx_data->mem_align + file_start; | |
816 | + if(u) { | |
817 | + memcpy((void *) gfx_data->mem_align, (void *) gfx_data->mem_start, i); | |
818 | + } | |
819 | + | |
820 | + /* init interface to graphics functions */ | |
821 | + | |
822 | + code_start += gfx_data->mem_file; | |
823 | + | |
824 | +#if 0 | |
825 | + printf("code_start: 0x%x, file_start: 0x%x, mem_align = 0x%x, mem_file = 0x%x\n", | |
826 | + code_start, file_start, gfx_data->mem_align, gfx_data->mem_file | |
827 | + ); | |
828 | + getkey(); | |
829 | +#endif | |
830 | + | |
831 | + gfx_data->code_seg = code_start >> 4; | |
832 | + | |
833 | +#if 0 | |
834 | + printf("code start = 0x%x, code_seg = 0x%x\n", code_start, gfx_data->code_seg); | |
835 | +#endif | |
836 | + | |
837 | + for(i = 0; (unsigned) i < sizeof gfx_data->jmp_table / sizeof *gfx_data->jmp_table; i++) { | |
838 | + gfx_data->jmp_table[i] = (gfx_data->code_seg << 16) + ((unsigned short *) code_start)[i]; | |
839 | + } | |
840 | + | |
841 | +#if 0 | |
842 | + for(i = 0; i < 12; i++) { | |
843 | + printf("%d: 0x%x\n", i, gfx_data->jmp_table[i]); | |
844 | + } | |
845 | + | |
846 | + for(i = 0; i < gfx_data->menu_entries; i++) { | |
847 | + printf(">%s< - >%s<\n", | |
848 | + gfx_data->menu_list + i * gfx_data->menu_entry_len, | |
849 | + gfx_data->args_list + i * gfx_data->args_entry_len | |
850 | + ); | |
851 | + } | |
852 | + | |
853 | + printf("def: >%s<\n", gfx_data->menu_default_entry); | |
854 | +#endif | |
855 | + | |
856 | + | |
857 | + /* switch to graphics mode */ | |
858 | + | |
859 | + if(gfx_init(gfx_data)) { | |
860 | +#if 0 | |
861 | + printf("gfx_init failed\n"); | |
862 | + getkey(); | |
863 | +#endif | |
864 | + return; | |
865 | + } | |
866 | + | |
867 | + gfx_setup_menu(gfx_data); | |
868 | + | |
869 | + i = gfx_input(gfx_data, &selected_entry); | |
870 | + | |
871 | + /* ESC -> show text menu */ | |
872 | + if(i == 1) { | |
873 | + gfx_done(gfx_data); | |
874 | + grub_timeout = -1; | |
875 | + | |
876 | + return; | |
877 | + } | |
878 | + | |
879 | + gfx_done(gfx_data); | |
880 | + | |
881 | + heap = saved_heap; /* free most of the graphics data */ | |
882 | + | |
883 | + // printf("cmdline: >%s<, entry = %d\n", gfx_data->cmdline, selected_entry); | |
884 | + | |
885 | + if(selected_entry < 0 || selected_entry > num_entries) return; | |
886 | + | |
887 | + | |
888 | + /* create new config with modified kernel option */ | |
889 | + | |
890 | + cfg = get_entry(config_entries, selected_entry, 1); | |
891 | + | |
892 | + new_config = heap; | |
893 | + | |
894 | + for(i = 0; ; i++) { | |
895 | + s = get_entry(cfg, i, 0); | |
896 | + if(!*s) { | |
897 | + if(!i) *heap++ = 0; | |
898 | + *heap++ = 0; | |
899 | + break; | |
900 | + } | |
901 | + if(!memcmp(s, "kernel", 6) && (s[6] == ' ' || s[6] == '\t')) { | |
902 | + t = skip_to(0, s); | |
903 | + if(*t) t = skip_to(0, t); | |
904 | + memmove(heap, s, t - s); | |
905 | + heap += t - s; | |
906 | + *heap++ = ' '; | |
907 | + strcpy(heap, gfx_data->cmdline); | |
908 | + heap += strlen(gfx_data->cmdline) + 1; | |
909 | + } | |
910 | + else { | |
911 | + strcpy(heap, s); | |
912 | + heap += strlen(s) + 1; | |
913 | + } | |
914 | + } | |
915 | + | |
916 | + *heap++ = 0; | |
917 | + | |
918 | + // hexdump(new_config, heap - new_config); | |
919 | + // getkey(); | |
920 | + | |
921 | + run_script(new_config, heap); | |
922 | +} | |
923 | + | |
924 | + | |
925 | static int | |
926 | get_line_from_config (char *cmdline, int maxlen, int read_from_file) | |
927 | { | |
928 | @@ -1059,9 +1474,12 @@ | |
929 | } | |
930 | else | |
931 | { | |
932 | - /* Run menu interface. */ | |
933 | - run_menu (menu_entries, config_entries, num_entries, | |
934 | - menu_entries + menu_len, default_entry); | |
935 | + if (*graphics_file && !password && show_menu && grub_timeout) | |
936 | + { | |
937 | + run_graphics_menu(menu_entries, config_entries, num_entries,menu_entries + menu_len, default_entry); | |
938 | + } | |
939 | + /* Run menu interface. */ | |
940 | + run_menu (menu_entries, config_entries, num_entries, menu_entries + menu_len, default_entry); | |
941 | } | |
942 | } | |
943 | } |