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

Archive Download this file

Revision: 1913