Chameleon

Chameleon Svn Source Tree

Root/branches/cparm/i386/modules/GUI/GUI_module.c

1/*
2 * Copyright (c) 2009 Evan Lojewski. All rights reserved.
3 *
4 */
5
6/*
7 * cparm : cleaned
8 */
9
10
11#include "libsaio.h"
12#include "platform.h"
13#include "graphic_utils.h"
14#include "embedded.h"
15
16#include "picopng.h"
17#include "gui.h"
18
19#include "modules.h"
20
21enum {
22 kMenuTopRow = 5,
23 kMenuMaxItems = 10,
24 kScreenLastRow = 24
25};
26
27enum {
28kBackspaceKey= 0x08,
29kTabKey= 0x09,
30kReturnKey= 0x0d,
31kEscapeKey= 0x1b,
32kUpArrowkey= 0x4800,
33kDownArrowkey= 0x5000,
34kASCIIKeyMask= 0x7f,
35kF5Key= 0x3f00,
36kF10Key= 0x4400
37};
38/*
39 * Flags to the booter or kernel
40 */
41#define kVerboseModeFlag"-v"
42#define kSafeModeFlag"-x"
43#define kIgnoreCachesFlag"-f"
44#define kSingleUserModeFlag"-s"
45#define kIgnorePrelinkKern "-F"
46#define kIgnoreBootFileFlag"-B"
47
48/*
49 * Booter behavior control
50 */
51#define kBootTimeout -1
52#define kCDBootTimeout 8
53
54/*
55 * A global set by boot() to record the device that the booter
56 * was loaded from.
57 */
58#define Cache_len_name 512
59
60/*
61 * Boot Modes
62 */
63enum {
64 kBootModeNormal = 0,
65 kBootModeSafe = 1,
66 kBootModeSecure = 2,
67 kBootModeQuiet = 4
68};
69typedef struct {
70 int x;
71 int y;
72 int type;
73} CursorState;
74
75/* Kabyl: BooterLog */
76#define BOOTER_LOG_SIZE (128 * 1024)
77#define SAFE_LOG_SIZE 134
78
79static bool useGUI = true;
80static intselectIndex = 0;
81
82void GUI_Kernel_Start_hook(void* kernelEntry, void* arg2, void* arg3, void* arg4, void* arg5, void* arg6);
83void GUI_PreBoot_hook(void* arg1, void* arg2, void* arg3, void* arg4, void* arg5, void* arg6);
84
85int GUI_getBootOptions(bool firstRun);
86
87static void GUI_updateBootArgs( int key );
88void GUI_clearBootArgs(void);
89void GUI_addBootArg(const char * argStr);
90
91static void GUI_showBootPrompt(int row, bool visible);
92static void GUI_showMenu( const MenuItem * items, int count, int selection, int row, int height );
93static int GUI_updateMenu( int key, void ** paramPtr );
94static void GUI_showHelp(void);
95static void GUI_showMessage(char *message);
96
97int GUI_printf(const char * fmt, ...);
98int GUI_verbose(const char * fmt, ...);
99int GUI_error(const char * fmt, ...);
100void GUI_stop(const char * fmt, ...);
101
102
103/* console.c */
104struct putc_info {
105 char * str;
106 char * last_str;
107};
108void sputc(int c, struct putc_info * pi);
109extern char *msgbuf;
110extern char *cursor;
111
112static void (*showTextBuffer)(char *, int ) = NULL;
113static char *(*getMemoryInfoString)(void) = NULL;
114static BVRef (*getBvChain)(void) = NULL;
115static void (*lspci)(void) = NULL;
116static void (*printMemoryInfo)(void) = NULL;
117static void (*showHelp)(void) = NULL;
118static void (*showTextFile)(const char * ) = NULL;
119static void (*showMessage)(char * ) = NULL;
120
121static const MenuItem * gMenuItems = NULL;
122static MenuItem * menuItems = NULL;
123
124static char gBootArgs[BOOT_STRING_LEN];
125static char * gBootArgsPtr = gBootArgs;
126static char * gBootArgsEnd = gBootArgs + BOOT_STRING_LEN - 1;
127static char booterCommand[BOOT_STRING_LEN];
128static char booterParam[BOOT_STRING_LEN];
129
130static void printMenuItem( const MenuItem * item, int highlight )
131{
132 printf(" ");
133
134 if ( highlight )
135 putca(' ', 0x70, strlen(item->name) + 4);
136 else
137 putca(' ', 0x07, 40);
138
139 printf(" %40s\n", item->name);
140}
141//==========================================================================
142
143static void changeCursor( int col, int row, int type, CursorState * cs )
144{
145 if (cs) getCursorPositionAndType( &cs->x, &cs->y, &cs->type );
146 setCursorType( type );
147 setCursorPosition( col, row, 0 );
148}
149
150static void moveCursor( int col, int row )
151{
152 setCursorPosition( col, row, 0 );
153}
154
155static void restoreCursor( const CursorState * cs )
156{
157 setCursorPosition( cs->x, cs->y, 0 );
158 setCursorType( cs->type );
159}
160
161char GUI_bootRescanPrompt[] =
162"Press Enter to start up Darwin/x86 with no options, or you can:\n"
163" Press F5 after you swapped the media. The drive will be rescanned.\n"
164" Type -v and press Enter to start up with diagnostic messages\n"
165" Type ? and press Enter to learn about advanced startup options\n\n"
166"boot: ";
167
168
169static bool KernelStart = false;
170/**
171 ** The kernel is about to start, draw the boot graphics if we are not in
172 ** verbose mode.
173 **/
174void GUI_ExecKernel_hook(void* arg1, void* arg2, void* arg3, void* arg4, void* arg5, void* arg6)
175{
176if(!gVerboseMode)
177{
178// Note: shouldn't be needed, but just in case
179drawBootGraphics();
180}
181else
182{
183#if UNUSED
184setVideoMode(GRAPHICS_MODE, 0);
185#else
186setVideoMode(GRAPHICS_MODE);
187#endif
188
189}
190KernelStart = true;
191}
192
193/**
194 ** A boot option has been selected, disable the graphical elements on screen.
195 **/
196void GUI_PreBoot_hook(void* arg1, void* arg2, void* arg3, void* arg4, void* arg5, void* arg6)
197{
198// Turn off any GUI elements
199if( bootArgs->Video.v_display == GRAPHICS_MODE )
200{
201gui.devicelist.draw = false;
202gui.bootprompt.draw = false;
203gui.menu.draw = false;
204gui.infobox.draw = false;
205gui.logo.draw = false;
206drawBackground();
207updateVRAM();
208
209if(!gVerboseMode)
210{
211// Disable outputs, they will still show in the boot log.
212replace_system_function("_printf", &GUI_verbose);
213//drawBootGraphics();
214}
215
216}
217
218}
219
220void GUI_diplay_hook(void* arg1, void* arg2, void* arg3, void* arg4, void* arg5, void* arg6)
221{
222// Start and display the gui
223msglog("* Attempting to Display GUI\n");
224
225if (initGUI())
226{
227
228useGUI = false; // initGUI() returned with an error, disabling GUI.
229msglog("* GUI failed to Display, or disabled by user (a.k.a you)\n");
230
231
232}
233else
234{
235//replace_system_function("_initGraphicsMode", &GUI_initGraphicsMode);
236replace_system_function("_getBootOptions", &GUI_getBootOptions);
237replace_system_function("_clearBootArgs", &GUI_clearBootArgs);
238 replace_system_function("_addBootArg", &GUI_addBootArg);
239
240 replace_system_function("_showHelp", &GUI_showHelp);
241
242replace_system_function("_printf", &GUI_printf);
243replace_system_function("_verbose", &GUI_verbose);
244replace_system_function("_error", &GUI_error);
245replace_system_function("_stop", &GUI_stop);
246replace_system_function("_showMessage", &GUI_showMessage);
247
248
249// Hook for the boot screen
250register_hook_callback("GUI_ExecKernel", &GUI_ExecKernel_hook);
251register_hook_callback("GUI_PreBoot", &GUI_PreBoot_hook);
252
253
254 getBvChain = (void*)lookup_all_symbols(SYMBOLS_MODULE,"_getBvChain");
255 getMemoryInfoString = (void*)lookup_all_symbols(SYMBOLS_MODULE,"_getMemoryInfoString");
256
257 printMemoryInfo = (void*)lookup_all_symbols(SYMBOLS_MODULE,"_printMemoryInfo");
258 lspci = (void*)lookup_all_symbols(SYMBOLS_MODULE,"_lspci");
259 showHelp = (void*)lookup_all_symbols(SYMBOLS_MODULE,"_showHelp");
260 showTextFile = (void*)lookup_all_symbols(SYMBOLS_MODULE,"_showTextFile");
261 showMessage = (void*)lookup_all_symbols(SYMBOLS_MODULE,"_showMessage");
262 showTextBuffer = (void*)lookup_all_symbols(SYMBOLS_MODULE,"_showTextBuffer");
263safe_set_env(envgBootArgs,(uint32_t)gBootArgs);
264
265msglog("* GUI successfully Displayed\n");
266
267}
268}
269
270/**
271 ** Module startup code. Replace console only print functions as well as
272 ** replace various menu functions. Finaly, initialize the gui and hook
273 ** into important events.
274 **/
275void GUI_start(moduleList_t* module)
276{
277register_hook_callback("GUI_Display", &GUI_diplay_hook);
278
279}
280
281/**
282 ** Overriden chameleon function. Draws the updated menu.
283 **/
284static int GUI_updateMenu( int key, void ** paramPtr )
285{
286 int moved = 0;
287
288 int MenuTop = (int)get_env(envgMenuTop);
289 int MenuSelection = (int)get_env(envgMenuSelection);
290 int MenuRow = (int)get_env(envgMenuRow);
291 int MenuHeight = (int)get_env(envgMenuHeight);
292 int MenuBottom = (int)get_env(envgMenuBottom);
293 int MenuStart = (int)get_env(envgMenuStart);
294 int MenuEnd = (int)get_env(envgMenuEnd);
295
296 union {
297 struct {
298 unsigned int
299selectionUp : 1,
300selectionDown : 1,
301scrollUp : 1,
302scrollDown : 1;
303 } f;
304 unsigned int w;
305 } draw = {{0}};
306
307 if ( gMenuItems == NULL )
308return 0;
309
310if( bootArgs->Video.v_display == GRAPHICS_MODE )
311{
312int res;
313
314// set navigation keys for horizontal layout as defaults
315int previous= 0x4B00;// left arrow
316int subsequent= 0x4D00;// right arrow
317int menu= 0x5000;// down arrow
318
319if ( gui.layout == VerticalLayout )
320{
321// set navigation keys for vertical layout
322previous= 0x4800;// up arrow
323subsequent= 0x5000;// down arrow
324menu= 0x4B00;// right arrow
325}
326
327if ( key == previous )
328{
329if ( MenuSelection > MenuTop )
330draw.f.selectionUp = 1;
331else if ( MenuTop > 0 )
332draw.f.scrollDown = 1;
333
334}
335
336else if ( key == subsequent )
337{
338if ( MenuSelection != MenuBottom)
339draw.f.selectionDown = 1;
340else if ( MenuBottom < ( get_env(envgMenuItemCount) - 1 ) )
341draw.f.scrollUp = 1;
342}
343
344else if ( key == menu )
345{
346if ( gui.menu.draw )
347updateInfoMenu(key);
348else
349drawInfoMenu();
350}
351
352else if ( gui.menu.draw )
353{
354res = updateInfoMenu(key);
355
356if ( res == CLOSE_INFO_MENU )
357gui.menu.draw = false;
358else
359{
360bool shouldboot = ( res != DO_NOT_BOOT );
361 safe_set_env(envShouldboot, shouldboot);
362
363if ( shouldboot )
364gui.menu.draw = false;
365
366switch (res)
367{
368case BOOT_NORMAL:
369gVerboseMode = false;
370 safe_set_env(envgBootMode, kBootModeNormal);
371
372break;
373
374case BOOT_VERBOSE:
375gVerboseMode = true;
376 safe_set_env(envgBootMode, kBootModeNormal);
377GUI_addBootArg(kVerboseModeFlag);
378break;
379
380case BOOT_IGNORECACHE:
381gVerboseMode = false;
382 safe_set_env(envgBootMode, kBootModeNormal);
383GUI_addBootArg(kIgnoreCachesFlag);
384break;
385
386case BOOT_SINGLEUSER:
387gVerboseMode = true;
388 safe_set_env(envgBootMode, kBootModeNormal);
389GUI_addBootArg(kSingleUserModeFlag);
390break;
391default:
392break;
393}
394
395}
396
397}
398
399} else {
400switch ( key )
401{
402 case 0x4800: // Up Arrow
403if ( MenuSelection != MenuTop )
404{
405draw.f.selectionUp = 1;
406}
407else if ( MenuTop > 0 )
408{
409draw.f.scrollDown = 1;
410}
411break;
412
413case 0x5000: // Down Arrow
414if ( MenuSelection != MenuBottom )
415{
416draw.f.selectionDown = 1;
417}
418else if ( MenuBottom < (get_env(envgMenuItemCount) - 1) )
419{
420draw.f.scrollUp = 1;
421}
422break;
423default:
424break;
425}
426}
427
428 if ( draw.w )
429 {
430 if ( draw.f.scrollUp )
431 {
432 scollPage(0, MenuRow, 40, MenuRow + MenuHeight - 1, 0x07, 1, 1);
433 MenuTop++; MenuBottom++;
434MenuStart++; MenuEnd++;
435 draw.f.selectionDown = 1;
436 }
437
438 if ( draw.f.scrollDown )
439 {
440 scollPage(0, MenuRow, 40, MenuRow + MenuHeight - 1, 0x07, 1, -1);
441 MenuTop--; MenuBottom--;
442 MenuStart--; MenuEnd--;
443 draw.f.selectionUp = 1;
444 }
445
446 if ( draw.f.selectionUp || draw.f.selectionDown )
447 {
448
449CursorState cursorState;
450
451// Set cursor at current position, and clear inverse video.
452
453if( bootArgs->Video.v_display == VGA_TEXT_MODE )
454{
455changeCursor( 0, (MenuRow + MenuSelection - MenuTop), kCursorTypeHidden, &cursorState );
456printMenuItem( &gMenuItems[MenuSelection], 0 );
457}
458
459if ( draw.f.selectionUp )
460{
461MenuSelection--;
462if(( MenuSelection - MenuStart) == -1 )
463{
464MenuStart--;
465MenuEnd--;
466}
467
468} else {
469MenuSelection++;
470if(( MenuSelection - ( gui.maxdevices - 1) - MenuStart) > 0 )
471{
472MenuStart++;
473MenuEnd++;
474}
475}
476
477if( bootArgs->Video.v_display == VGA_TEXT_MODE )
478{
479moveCursor( 0, MenuRow + MenuSelection - MenuTop );
480printMenuItem( &gMenuItems[MenuSelection], 1 );
481restoreCursor( &cursorState );
482
483}
484else
485{
486drawDeviceList (MenuStart, MenuEnd, MenuSelection, menuItems);
487}
488
489}
490
491 *paramPtr = gMenuItems[MenuSelection].param;
492 moved = 1;
493 }
494
495safe_set_env(envgMenuSelection,MenuSelection);
496 safe_set_env(envgMenuTop,MenuTop );
497 safe_set_env(envgMenuRow,MenuRow);
498 safe_set_env(envgMenuHeight,MenuHeight);
499 safe_set_env(envgMenuBottom,MenuBottom);
500 safe_set_env(envgMenuStart,MenuStart);
501 safe_set_env(envgMenuEnd,MenuEnd);
502
503return moved;
504}
505
506
507static void GUI_showMenu( const MenuItem * items, int count,
508 int selection, int row, int height )
509{
510 int i;
511 CursorState cursorState;
512
513 if ( items == NULL || count == 0 )
514return;
515
516 // head and tail points to the start and the end of the list.
517 // top and bottom points to the first and last visible items
518 // in the menu window.
519
520 gMenuItems= items;
521 int MenuTop= 0;
522 int MenuBottom= min( count, height ) - 1;
523 int MenuSelection= selection;
524 int MenuStart= 0;
525 int MenuEnd = count; //min( count, gui.maxdevices ) - 1;
526
527// If the selected item is not visible, shift the list down.
528
529 if ( MenuSelection > MenuBottom )
530 {
531 MenuTop += ( MenuSelection - MenuBottom );
532 MenuBottom = MenuSelection;
533 }
534
535if ( MenuSelection > MenuEnd )
536 {
537MenuStart += ( MenuSelection - MenuEnd );
538 MenuEnd = MenuSelection;
539 }
540
541// Draw the visible items.
542
543if( bootArgs->Video.v_display == GRAPHICS_MODE )
544{
545drawDeviceList(MenuStart, MenuEnd, MenuSelection, menuItems);
546}
547else
548{
549
550changeCursor( 0, row, kCursorTypeHidden, &cursorState );
551
552for ( i = MenuTop; i <= MenuBottom; i++ )
553{
554printMenuItem( &items[i], (i == MenuSelection) );
555}
556
557restoreCursor( &cursorState );
558 }
559
560 safe_set_env(envgMenuRow,row);
561 safe_set_env(envgMenuHeight,height);
562 safe_set_env(envgMenuItemCount,count);
563 safe_set_env(envgMenuTop,MenuTop);
564 safe_set_env(envgMenuBottom,MenuBottom);
565 safe_set_env(envgMenuSelection,MenuSelection);
566 safe_set_env(envgMenuStart,MenuStart);
567 safe_set_env(envgMenuEnd,MenuEnd);
568}
569
570
571static void GUI_updateBootArgs( int key )
572{
573 key &= kASCIIKeyMask;
574
575 switch ( key )
576 {
577 case kBackspaceKey:
578 if ( gBootArgsPtr > gBootArgs )
579 {
580 int x, y, t;
581 getCursorPositionAndType( &x, &y, &t );
582 if ( x == 0 && y )
583 {
584 x = 80; y--;
585 }
586 if (x)
587x--;
588if( bootArgs->Video.v_display == VGA_TEXT_MODE )
589{
590setCursorPosition( x, y, 0 );
591putca(' ', 0x07, 1);
592} else
593{
594updateGraphicBootPrompt(kBackspaceKey);
595}
596
597*gBootArgsPtr-- = '\0';
598}
599
600break;
601
602 default:
603 if ( key >= ' ' && gBootArgsPtr < gBootArgsEnd)
604 {
605if( bootArgs->Video.v_display == VGA_TEXT_MODE )
606{
607putchar(key); // echo to screen
608}
609else
610{
611updateGraphicBootPrompt(key);
612}
613*gBootArgsPtr++ = key;
614}
615
616break;
617 }
618}
619
620
621static void GUI_showBootPrompt(int row, bool visible)
622{
623char * bootPrompt = (char*)(uint32_t)get_env(envBootPrompt);
624
625if( bootArgs->Video.v_display == VGA_TEXT_MODE )
626{
627changeCursor( 0, row, kCursorTypeUnderline, 0 );
628clearScreenRows( row, kScreenLastRow );
629}
630
631GUI_clearBootArgs();
632
633if (visible)
634{
635if (bootArgs->Video.v_display == VGA_TEXT_MODE)
636{
637if (get_env(envgEnableCDROMRescan))
638{
639printf( GUI_bootRescanPrompt );
640}
641else
642{
643printf( bootPrompt );
644}
645}
646}
647else
648{
649if (bootArgs->Video.v_display == GRAPHICS_MODE)
650{
651clearGraphicBootPrompt();
652}
653else
654{
655printf("Press Enter to start up the foreign OS. ");
656}
657}
658}
659
660void GUI_clearBootArgs(void)
661{
662gBootArgsPtr = gBootArgs;
663memset(gBootArgs, '\0', BOOT_STRING_LEN);
664
665if (bootArgs->Video.v_display == GRAPHICS_MODE)
666{
667clearGraphicBootPrompt();
668}
669}
670
671void GUI_addBootArg(const char * argStr)
672{
673if ( (gBootArgsPtr + strlen(argStr) + 1) < gBootArgsEnd)
674{
675*gBootArgsPtr++ = ' ';
676strcat(gBootArgs, argStr);
677gBootArgsPtr += strlen(argStr);
678}
679}
680
681int GUI_getBootOptions(bool firstRun)
682{
683int i;
684int key;
685int nextRow;
686int timeout;
687#if UNUSED
688int bvCount;
689#endif
690BVRef bvr;
691BVRef menuBVR;
692bool showPrompt, newShowPrompt, isCDROM;
693 int optionKey;
694 int devcnt = (int)get_env(envgDeviceCount);
695
696// Initialize default menu selection entry.
697gBootVolume = menuBVR = selectBootVolume(getBvChain());
698
699if (biosDevIsCDROM((int)get_env(envgBIOSDev)))
700{
701isCDROM = true;
702}
703else
704{
705isCDROM = false;
706}
707
708// ensure we're in graphics mode if gui is setup
709if (gui.initialised && bootArgs->Video.v_display == VGA_TEXT_MODE)
710{
711#if UNUSED
712setVideoMode(GRAPHICS_MODE, 0);
713#else
714setVideoMode(GRAPHICS_MODE);
715#endif
716}
717
718// Clear command line boot arguments
719GUI_clearBootArgs();
720
721// Allow user to override default timeout.
722if (!getIntForKey(kTimeoutKey, &timeout, DEFAULT_BOOT_CONFIG))
723{
724/* If there is no timeout key in the file use the default timeout
725 which is different for CDs vs. hard disks. However, if not booting
726 a CD and no config file could be loaded set the timeout
727 to zero which causes the menu to display immediately.
728 This way, if no partitions can be found, that is the disk is unpartitioned
729 or simply cannot be read) then an empty menu is displayed.
730 If some partitions are found, for example a Windows partition, then
731 these will be displayed in the menu as foreign partitions.
732 */
733if (isCDROM)
734{
735timeout = kCDBootTimeout;
736}
737else
738{
739timeout = get_env(envSysConfigValid) ? kBootTimeout : 0;
740}
741}
742
743long gBootMode = get_env(envgBootMode);
744
745if (timeout < 0)
746{
747gBootMode |= kBootModeQuiet;
748 safe_set_env(envgBootMode,gBootMode);
749
750}
751
752// If the user is holding down a modifier key, enter safe mode.
753if ((readKeyboardShiftFlags() & 0x0F) != 0)
754{
755
756gBootMode |= kBootModeSafe;
757 safe_set_env(envgBootMode,gBootMode);
758
759}
760
761// Checking user pressed keys
762bool f8press = false, spress = false, vpress = false;
763while (readKeyboardStatus())
764{
765key = bgetc ();
766if (key == 0x4200) f8press = true;
767if ((key & 0xff) == 's' || (key & 0xff) == 'S') spress = true;
768if ((key & 0xff) == 'v' || (key & 0xff) == 'V') vpress = true;
769}
770// If user typed F8, abort quiet mode, and display the menu.
771if (f8press)
772{
773gBootMode &= ~kBootModeQuiet;
774 safe_set_env(envgBootMode,gBootMode);
775
776timeout = 0;
777}
778// If user typed 'v' or 'V', boot in verbose mode.
779if ((gBootMode & kBootModeQuiet) && firstRun && vpress)
780{
781GUI_addBootArg(kVerboseModeFlag);
782}
783// If user typed 's' or 'S', boot in single user mode.
784if ((gBootMode & kBootModeQuiet) && firstRun && spress)
785{
786GUI_addBootArg(kSingleUserModeFlag);
787}
788
789if (bootArgs->Video.v_display == VGA_TEXT_MODE)
790{
791setCursorPosition(0, 0, 0);
792clearScreenRows(0, kScreenLastRow);
793if (!(gBootMode & kBootModeQuiet))
794{
795 char * bootBanner = (char*)(uint32_t)get_env(envBootBanner);
796// Display banner and show hardware info.
797printf(bootBanner, (bootInfo->convmem + bootInfo->extmem) / 1024);
798printf(getVBEInfoString());
799}
800changeCursor(0, kMenuTopRow, kCursorTypeUnderline, 0);
801msglog("Scanning device %x...", (uint32_t)get_env(envgBIOSDev));
802}
803
804// When booting from CD, default to hard drive boot when possible.
805if (isCDROM && firstRun)
806{
807const char *val;
808char *prompt = NULL;
809char *name = NULL;
810int cnt;
811
812if (getValueForKey(kCDROMPromptKey, &val, &cnt, DEFAULT_BOOT_CONFIG))
813{
814prompt = malloc(cnt + 1);
815strncat(prompt, val, cnt);
816}
817else
818{
819name = malloc(80);
820getBootVolumeDescription(gBootVolume, name, 79, false);
821prompt = malloc(256);
822sprintf(prompt, "Press ENTER to start up from %s, or press any key to enter startup options.", name);
823free(name);
824}
825
826if (getIntForKey( kCDROMOptionKey, &optionKey, DEFAULT_BOOT_CONFIG ))
827{
828// The key specified is a special key.
829}
830else
831{
832// Default to F8.
833optionKey = 0x4200;
834}
835
836// If the timeout is zero then it must have been set above due to the
837// early catch of F8 which means the user wants to set boot options
838// which we ought to interpret as meaning he wants to boot the CD.
839if (timeout != 0) {
840key = GUI_countdown(prompt, kMenuTopRow, timeout, &optionKey);
841}
842else
843{
844key = optionKey;
845}
846
847if (prompt != NULL)
848{
849free(prompt);
850}
851
852clearScreenRows( kMenuTopRow, kMenuTopRow + 2 );
853
854do {
855 // Hit the option key ?
856 if (key == optionKey) {
857
858 if (key != 0x1C0D) {
859 gBootMode &= ~kBootModeQuiet;
860 safe_set_env(envgBootMode,gBootMode);
861 timeout = 0;
862 break;
863 }
864
865 }
866
867 key = key & 0xFF;
868
869 // Try booting hard disk if user pressed 'h'
870 if (biosDevIsCDROM((int)get_env(envgBIOSDev)) && key == 'h') {
871 BVRef bvr;
872
873 // Look at partitions hosting OS X other than the CD-ROM
874 for (bvr = getBvChain(); bvr; bvr=bvr->next) {
875 if ((bvr->flags & kBVFlagSystemVolume) && bvr->biosdev != (int)get_env(envgBIOSDev)) {
876 gBootVolume = bvr;
877 }
878 }
879 }
880 goto done;
881
882 } while (0);
883}
884
885if (gBootMode & kBootModeQuiet)
886{
887// No input allowed from user.
888goto done;
889}
890
891if (firstRun && timeout > 0 ) {
892
893 key = GUI_countdown("Press ENTER to start up, or press any key to enter startup options.", kMenuTopRow, timeout, &optionKey);
894
895 if (key == 0x1C0D) {
896 goto done;
897
898 }
899 else if (key == 0)
900 {
901 // If the user is holding down a modifier key,
902 // enter safe mode.
903
904 if ((readKeyboardShiftFlags() & 0x0F) != 0) {
905 gBootMode |= kBootModeSafe;
906 safe_set_env(envgBootMode,gBootMode);
907 }
908 goto done;
909 }
910}
911
912if (devcnt)
913{
914// Allocate memory for an array of menu items.
915menuItems = malloc(sizeof(MenuItem) * devcnt);
916if (menuItems == NULL)
917{
918goto done;
919}
920
921// Associate a menu item for each BVRef.
922for (bvr=getBvChain(), i=devcnt-1, selectIndex=0; bvr; bvr=bvr->next)
923{
924if (bvr->visible)
925{
926getBootVolumeDescription(bvr, menuItems[i].name, sizeof(menuItems[i].name) - 1, true);
927menuItems[i].param = (void *) bvr;
928if (bvr == menuBVR)
929{
930selectIndex = i;
931 safe_set_env(envSelectIndex, selectIndex);
932}
933i--;
934}
935}
936}
937
938if (bootArgs->Video.v_display == GRAPHICS_MODE)
939{
940// redraw the background buffer
941gui.logo.draw = true;
942drawBackground();
943gui.devicelist.draw = true;
944gui.redraw = true;
945if (!(gBootMode & kBootModeQuiet))
946{
947bool showBootBanner = true;
948
949// Check if "Boot Banner"=N switch is present in config file.
950getBoolForKey(kBootBannerKey, &showBootBanner, DEFAULT_BOOT_CONFIG);
951if (showBootBanner)
952{
953 char * bootBanner = (char*)(uint32_t)get_env(envBootBanner);
954
955// Display banner and show hardware info.
956gprintf(&gui.screen, bootBanner + 1, (bootInfo->convmem + bootInfo->extmem) / 1024);
957}
958
959// redraw background
960memcpy(gui.backbuffer->pixels, gui.screen.pixmap->pixels, gui.backbuffer->width * gui.backbuffer->height * 4);
961}
962}
963else
964{
965// Clear screen and hide the blinking cursor.
966clearScreenRows(kMenuTopRow, kMenuTopRow + 2);
967changeCursor(0, kMenuTopRow, kCursorTypeHidden, 0);
968}
969
970nextRow = kMenuTopRow;
971showPrompt = true;
972
973if (devcnt)
974{
975if( bootArgs->Video.v_display == VGA_TEXT_MODE )
976{
977printf("Use \30\31 keys to select the startup volume.");
978}
979GUI_showMenu( menuItems, devcnt, selectIndex, kMenuTopRow + 2, kMenuMaxItems );
980nextRow += min( devcnt, kMenuMaxItems ) + 3;
981}
982
983// Show the boot prompt.
984showPrompt = (devcnt == 0) || (menuBVR->flags & kBVFlagNativeBoot);
985GUI_showBootPrompt( nextRow, showPrompt );
986
987do {
988if (bootArgs->Video.v_display == GRAPHICS_MODE)
989{
990// redraw background
991memcpy( gui.backbuffer->pixels, gui.screen.pixmap->pixels, gui.backbuffer->width * gui.backbuffer->height * 4 );
992// reset cursor co-ords
993gui.debug.cursor = pos( gui.screen.width - 160 , 10 );
994}
995key = getc();
996GUI_updateMenu( key, (void **) &menuBVR );
997newShowPrompt = (devcnt == 0) || (menuBVR->flags & kBVFlagNativeBoot);
998
999if (newShowPrompt != showPrompt)
1000{
1001showPrompt = newShowPrompt;
1002GUI_showBootPrompt( nextRow, showPrompt );
1003}
1004
1005if (showPrompt)
1006{
1007GUI_updateBootArgs(key);
1008}
1009
1010switch (key)
1011{
1012case kReturnKey:
1013if (gui.menu.draw)
1014{
1015key=0;
1016break;
1017}
1018if (*gBootArgs == '?')
1019{
1020char * argPtr = gBootArgs;
1021
1022// Skip the leading "?" character.
1023argPtr++;
1024getNextArg(&argPtr, booterCommand);
1025getNextArg(&argPtr, booterParam);
1026
1027/*
1028 * TODO: this needs to be refactored.
1029 */
1030if (strcmp( booterCommand, "video" ) == 0)
1031{
1032if (bootArgs->Video.v_display == GRAPHICS_MODE)
1033{
1034showInfoBox(getVBEInfoString(), getVBEModeInfoString());
1035}
1036else
1037{
1038printVBEModeInfo();
1039}
1040}
1041else if ( strcmp( booterCommand, "memory" ) == 0)
1042{
1043if (bootArgs->Video.v_display == GRAPHICS_MODE )
1044{
1045showInfoBox("Memory Map", getMemoryInfoString());
1046}
1047else
1048{
1049printMemoryInfo();
1050}
1051}
1052else if (strcmp(booterCommand, "lspci") == 0)
1053{
1054lspci();
1055}
1056else if (strcmp(booterCommand, "more") == 0)
1057{
1058showTextFile(booterParam);
1059}
1060else if (strcmp(booterCommand, "rd") == 0)
1061{
1062if (execute_hook("processRAMDiskCommand", (void*)argPtr, &booterParam, NULL, NULL, NULL, NULL) != EFI_SUCCESS)
1063showMessage("ramdisk module not found, please install RamdiskLoader.dylib in /Extra/modules/");
1064}
1065else if (strcmp(booterCommand, "norescan") == 0)
1066{
1067if (get_env(envgEnableCDROMRescan))
1068 {
1069 safe_set_env(envgEnableCDROMRescan,false);
1070 break;
1071 }
1072}
1073else
1074{
1075showHelp();
1076}
1077key = 0;
1078GUI_showBootPrompt(nextRow, showPrompt);
1079break;
1080}
1081gBootVolume = menuBVR;
1082setRootVolume(menuBVR);
1083 safe_set_env(envgBIOSDev,menuBVR->biosdev);
1084break;
1085
1086case kEscapeKey:
1087GUI_clearBootArgs();
1088break;
1089
1090case kF5Key:
1091// New behavior:
1092// Clear gBootVolume to restart the loop
1093// if the user enabled rescanning the optical drive.
1094// Otherwise boot the default boot volume.
1095if (get_env(envgEnableCDROMRescan)) {
1096gBootVolume = NULL;
1097GUI_clearBootArgs();
1098}
1099break;
1100
1101case kF10Key:
1102 safe_set_env(envgScanSingleDrive, false);
1103#if UNUSED
1104 scanDisks((int)get_env(envgBIOSDev), &bvCount);
1105#else
1106 scanDisks();
1107#endif
1108gBootVolume = NULL;
1109GUI_clearBootArgs();
1110break;
1111
1112case kTabKey:
1113// New behavior:
1114// Switch between text & graphic interfaces
1115// Only Permitted if started in graphics interface
1116if (useGUI)
1117{
1118if (bootArgs->Video.v_display == GRAPHICS_MODE)
1119{
1120#if UNUSED
1121setVideoMode(VGA_TEXT_MODE, 0);
1122#else
1123setVideoMode(VGA_TEXT_MODE);
1124#endif
1125setCursorPosition(0, 0, 0);
1126clearScreenRows(0, kScreenLastRow);
1127
1128char * bootBanner = (char*)(uint32_t)get_env(envBootBanner);
1129
1130// Display banner and show hardware info.
1131printf(bootBanner, (bootInfo->convmem + bootInfo->extmem) / 1024);
1132printf(getVBEInfoString());
1133
1134clearScreenRows(kMenuTopRow, kMenuTopRow + 2);
1135changeCursor(0, kMenuTopRow, kCursorTypeHidden, 0);
1136
1137nextRow = kMenuTopRow;
1138showPrompt = true;
1139
1140if (devcnt)
1141{
1142printf("Use \30\31 keys to select the startup volume.");
1143GUI_showMenu(menuItems, devcnt, selectIndex, kMenuTopRow + 2, kMenuMaxItems);
1144nextRow += min(devcnt, kMenuMaxItems) + 3;
1145}
1146
1147showPrompt = (devcnt == 0) || (menuBVR->flags & kBVFlagNativeBoot);
1148GUI_showBootPrompt(nextRow, showPrompt);
1149//changeCursor( 0, kMenuTopRow, kCursorTypeUnderline, 0 );
1150}
1151else
1152{
1153gui.redraw = true;
1154#if UNUSED
1155setVideoMode(GRAPHICS_MODE, 0);
1156#else
1157setVideoMode(GRAPHICS_MODE);
1158#endif
1159updateVRAM();
1160}
1161}
1162key = 0;
1163break;
1164
1165default:
1166key = 0;
1167break;
1168}
1169} while (0 == key);
1170
1171done:
1172if (bootArgs->Video.v_display == VGA_TEXT_MODE)
1173{
1174clearScreenRows(kMenuTopRow, kScreenLastRow);
1175changeCursor(0, kMenuTopRow, kCursorTypeUnderline, 0);
1176}
1177 safe_set_env(envShouldboot, false);
1178gui.menu.draw = false;
1179if (menuItems)
1180{
1181free(menuItems);
1182menuItems = NULL;
1183}
1184return 0;
1185}
1186
1187
1188
1189int GUI_error(const char * fmt, ...)
1190{
1191 va_list ap;
1192 gErrors = true;
1193 va_start(ap, fmt);
1194
1195if (bootArgs->Video.v_display == VGA_TEXT_MODE)
1196{
1197prf(fmt, ap, putchar, 0);
1198 }
1199else
1200{
1201vprf(fmt, ap);
1202}
1203
1204va_end(ap);
1205 return(0);
1206}
1207
1208int GUI_verbose(const char * fmt, ...)
1209{
1210 va_list ap;
1211
1212va_start(ap, fmt);
1213
1214 if (gVerboseMode && (KernelStart == false))
1215 {
1216if (bootArgs->Video.v_display == VGA_TEXT_MODE)
1217{
1218prf(fmt, ap, putchar, 0);
1219}
1220else
1221{
1222vprf(fmt, ap);
1223}
1224 }
1225
1226/* Kabyl: BooterLog */
1227struct putc_info pi;
1228
1229if (!msgbuf)
1230return 0;
1231
1232if (((cursor - msgbuf) > (BOOTER_LOG_SIZE - SAFE_LOG_SIZE)))
1233return 0;
1234pi.str = cursor;
1235pi.last_str = 0;
1236prf(fmt, ap, sputc, &pi);
1237cursor += strlen((char *)cursor);
1238
1239
1240 va_end(ap);
1241 return(0);
1242}
1243
1244int GUI_printf(const char * fmt, ...)
1245{
1246 va_list ap;
1247va_start(ap, fmt);
1248
1249if (KernelStart == false) {
1250
1251if (bootArgs->Video.v_display == VGA_TEXT_MODE)
1252{
1253prf(fmt, ap, putchar, 0);
1254}
1255else
1256{
1257vprf(fmt, ap);
1258}
1259}
1260/* Kabyl: BooterLog */
1261struct putc_info pi;
1262
1263if (!msgbuf)
1264return 0;
1265
1266if (((cursor - msgbuf) > (BOOTER_LOG_SIZE - SAFE_LOG_SIZE)))
1267return 0;
1268pi.str = cursor;
1269pi.last_str = 0;
1270prf(fmt, ap, sputc, &pi);
1271cursor += strlen((char *)cursor);
1272
1273va_end(ap);
1274 return 0;
1275}
1276
1277void GUI_stop(const char * fmt, ...)
1278{
1279va_list ap;
1280
1281printf("\n");
1282va_start(ap, fmt);
1283
1284if (bootArgs->Video.v_display == VGA_TEXT_MODE)
1285{
1286prf(fmt, ap, putchar, 0);
1287}
1288else
1289{
1290vprf(fmt, ap);
1291}
1292va_end(ap);
1293
1294printf("\nThis is a non recoverable error! System HALTED!!!");
1295halt();
1296while (1);
1297}
1298
1299void GUI_showHelp(void)
1300{
1301if (bootArgs->Video.v_display == GRAPHICS_MODE) {
1302showInfoBox("Help. Press q to quit.\n", (char *)BootHelp_txt);
1303} else {
1304showTextBuffer((char *)BootHelp_txt, BootHelp_txt_len);
1305}
1306}
1307
1308void GUI_showMessage(char *message)
1309{
1310if (bootArgs->Video.v_display == GRAPHICS_MODE) {
1311showInfoBox("Help. Press q to quit.\n", message);
1312} else {
1313showTextBuffer(message, strlen(message));
1314}
1315}

Archive Download this file

Revision: 1840