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

Archive Download this file

Revision: 1929