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)) {
819prompt = malloc(cnt + 1);
820 if (!prompt) {
821 stop("Couldn't allocate memory for the prompt\n"); //TODO: Find a better stategie
822 return -1;
823 }
824strncat(prompt, val, cnt);
825} else {
826name = malloc(80);
827 if (!name) {
828 stop("Couldn't allocate memory for the device name\n"); //TODO: Find a better stategie
829 return -1;
830 }
831getBootVolumeDescription(gBootVolume, name, 79, false);
832prompt = malloc(256);
833 if (!prompt) {
834 free(name);
835 stop("Couldn't allocate memory for the prompt\n"); //TODO: Find a better stategie
836 return -1;
837 }
838sprintf(prompt, "Press ENTER to start up from %s, or press any key to enter startup options.", name);
839free(name);
840}
841
842if (getIntForKey( kCDROMOptionKey, &optionKey, DEFAULT_BOOT_CONFIG ))
843{
844// The key specified is a special key.
845}
846else
847{
848// Default to F8.
849optionKey = 0x4200;
850}
851
852// If the timeout is zero then it must have been set above due to the
853// early catch of F8 which means the user wants to set boot options
854// which we ought to interpret as meaning he wants to boot the CD.
855if (timeout != 0) {
856key = GUI_countdown(prompt, kMenuTopRow, timeout, &optionKey);
857}
858else
859{
860key = optionKey;
861}
862
863if (prompt != NULL)
864{
865free(prompt);
866}
867
868clearScreenRows( kMenuTopRow, kMenuTopRow + 2 );
869
870do {
871 // Hit the option key ?
872 if (key == optionKey) {
873
874 if (key != 0x1C0D) {
875 gBootMode &= ~kBootModeQuiet;
876 safe_set_env(envgBootMode,gBootMode);
877 timeout = 0;
878 break;
879 }
880
881 }
882
883 key = key & 0xFF;
884
885 // Try booting hard disk if user pressed 'h'
886 if (biosDevIsCDROM((int)get_env(envgBIOSDev)) && key == 'h') {
887 BVRef bvr;
888
889 // Look at partitions hosting OS X other than the CD-ROM
890 for (bvr = getBvChain(); bvr; bvr=bvr->next) {
891 if ((bvr->flags & kBVFlagSystemVolume) && bvr->biosdev != (int)get_env(envgBIOSDev)) {
892 gBootVolume = bvr;
893 }
894 }
895 }
896 goto done;
897
898 } while (0);
899}
900
901if (gBootMode & kBootModeQuiet)
902{
903// No input allowed from user.
904goto done;
905}
906
907if (firstRun && timeout > 0 ) {
908
909 key = GUI_countdown("Press ENTER to start up, or press any key to enter startup options.", kMenuTopRow, timeout, &optionKey);
910
911 if (key == 0x1C0D) {
912 goto done;
913
914 }
915 else if (key == 0)
916 {
917 // If the user is holding down a modifier key,
918 // enter safe mode.
919
920 if ((readKeyboardShiftFlags() & 0x0F) != 0) {
921 gBootMode |= kBootModeSafe;
922 safe_set_env(envgBootMode,gBootMode);
923 }
924 goto done;
925 }
926}
927
928if (devcnt)
929{
930// Allocate memory for an array of menu items.
931menuItems = malloc(sizeof(MenuItem) * devcnt);
932if (menuItems == NULL)
933{
934goto done;
935}
936
937// Associate a menu item for each BVRef.
938for (bvr=getBvChain(), i=devcnt-1, selectIndex=0; bvr; bvr=bvr->next)
939{
940if (bvr->visible)
941{
942getBootVolumeDescription(bvr, menuItems[i].name, sizeof(menuItems[i].name) - 1, true);
943menuItems[i].param = (void *) bvr;
944if (bvr == menuBVR)
945{
946selectIndex = i;
947 safe_set_env(envSelectIndex, selectIndex);
948}
949i--;
950}
951}
952}
953
954if (getVideoMode() == GRAPHICS_MODE)
955{
956// redraw the background buffer
957gui.logo.draw = true;
958drawBackground();
959gui.devicelist.draw = true;
960gui.redraw = true;
961if (!(gBootMode & kBootModeQuiet))
962{
963bool showBootBanner = true;
964
965// Check if "Boot Banner"=N switch is present in config file.
966getBoolForKey(kBootBannerKey, &showBootBanner, DEFAULT_BOOT_CONFIG);
967if (showBootBanner)
968{
969 char * bootBanner = (char*)(uint32_t)get_env(envBootBanner);
970
971// Display banner and show hardware info.
972gprintf(&gui.screen, bootBanner + 1, (int)(get_env(envConvMem) + get_env(envExtMem)) / 1024);
973
974}
975
976// redraw background
977memcpy(gui.backbuffer->pixels, gui.screen.pixmap->pixels, gui.backbuffer->width * gui.backbuffer->height * 4);
978}
979}
980else
981{
982// Clear screen and hide the blinking cursor.
983clearScreenRows(kMenuTopRow, kMenuTopRow + 2);
984changeCursor(0, kMenuTopRow, kCursorTypeHidden, 0);
985}
986
987nextRow = kMenuTopRow;
988
989if (devcnt)
990{
991if( getVideoMode() == VGA_TEXT_MODE )
992{
993printf("Use \30\31 keys to select the startup volume.");
994}
995GUI_showMenu( menuItems, devcnt, selectIndex, kMenuTopRow + 2, kMenuMaxItems );
996nextRow += min( devcnt, kMenuMaxItems ) + 3;
997}
998
999// Show the boot prompt.
1000showPrompt = (devcnt == 0) || (menuBVR->flags & kBVFlagNativeBoot);
1001GUI_showBootPrompt( nextRow, showPrompt );
1002
1003do {
1004if (getVideoMode() == GRAPHICS_MODE)
1005{
1006// redraw background
1007memcpy( gui.backbuffer->pixels, gui.screen.pixmap->pixels, gui.backbuffer->width * gui.backbuffer->height * 4 );
1008// reset cursor co-ords
1009gui.debug.cursor = pos( gui.screen.width - 160 , 10 );
1010}
1011key = getc();
1012GUI_updateMenu( key, (void **) &menuBVR );
1013newShowPrompt = (devcnt == 0) || (menuBVR->flags & kBVFlagNativeBoot);
1014
1015if (newShowPrompt != showPrompt)
1016{
1017showPrompt = newShowPrompt;
1018GUI_showBootPrompt( nextRow, showPrompt );
1019}
1020
1021if (showPrompt)
1022{
1023GUI_updateBootArgs(key);
1024}
1025
1026switch (key)
1027{
1028case kReturnKey:
1029if (gui.menu.draw)
1030{
1031key=0;
1032break;
1033}
1034if (*gBootArgs == '?')
1035{
1036char * argPtr = gBootArgs;
1037
1038// Skip the leading "?" character.
1039argPtr++;
1040getNextArg(&argPtr, booterCommand);
1041getNextArg(&argPtr, booterParam);
1042
1043/*
1044 * TODO: this needs to be refactored.
1045 */
1046if (strcmp( booterCommand, "video" ) == 0)
1047{
1048if (getVideoMode() == GRAPHICS_MODE)
1049{
1050showInfoBox(getVBEInfoString(), getVBEModeInfoString());
1051}
1052else
1053{
1054printVBEModeInfo();
1055}
1056}
1057else if ( strcmp( booterCommand, "memory" ) == 0)
1058{
1059if (getVideoMode() == GRAPHICS_MODE )
1060{
1061showInfoBox("Memory Map", getMemoryInfoString());
1062}
1063else
1064{
1065printMemoryInfo();
1066}
1067}
1068else if (strcmp(booterCommand, "lspci") == 0)
1069{
1070lspci();
1071}
1072else if (strcmp(booterCommand, "more") == 0)
1073{
1074showTextFile(booterParam);
1075}
1076else if (strcmp(booterCommand, "rd") == 0)
1077{
1078if (execute_hook("processRAMDiskCommand", (void*)argPtr, &booterParam, NULL, NULL, NULL, NULL) != EFI_SUCCESS)
1079showMessage("ramdisk module not found, please install RamdiskLoader.dylib in /Extra/modules/");
1080}
1081else if (strcmp(booterCommand, "norescan") == 0)
1082{
1083if (get_env(envgEnableCDROMRescan))
1084 {
1085 safe_set_env(envgEnableCDROMRescan,false);
1086 break;
1087 }
1088}
1089else
1090{
1091showHelp();
1092}
1093key = 0;
1094GUI_showBootPrompt(nextRow, showPrompt);
1095break;
1096}
1097gBootVolume = menuBVR;
1098setRootVolume(menuBVR);
1099 safe_set_env(envgBIOSDev,menuBVR->biosdev);
1100break;
1101
1102case kEscapeKey:
1103GUI_clearBootArgs();
1104break;
1105
1106case kF5Key:
1107// New behavior:
1108// Clear gBootVolume to restart the loop
1109// if the user enabled rescanning the optical drive.
1110// Otherwise boot the default boot volume.
1111if (get_env(envgEnableCDROMRescan)) {
1112gBootVolume = NULL;
1113GUI_clearBootArgs();
1114}
1115break;
1116
1117case kF10Key:
1118 safe_set_env(envgScanSingleDrive, false);
1119#if UNUSED
1120 scanDisks((int)get_env(envgBIOSDev), &bvCount);
1121#else
1122 scanDisks();
1123#endif
1124gBootVolume = NULL;
1125GUI_clearBootArgs();
1126break;
1127
1128case kTabKey:
1129// New behavior:
1130// Switch between text & graphic interfaces
1131// Only Permitted if started in graphics interface
1132if (useGUI)
1133{
1134if (getVideoMode() == GRAPHICS_MODE)
1135{
1136#if UNUSED
1137setVideoMode(VGA_TEXT_MODE, 0);
1138#else
1139setVideoMode(VGA_TEXT_MODE);
1140#endif
1141setCursorPosition(0, 0, 0);
1142clearScreenRows(0, kScreenLastRow);
1143
1144char * bootBanner = (char*)(uint32_t)get_env(envBootBanner);
1145
1146// Display banner and show hardware info.
1147printf(bootBanner, (int)(get_env(envConvMem) + get_env(envExtMem)) / 1024);
1148printf(getVBEInfoString());
1149
1150clearScreenRows(kMenuTopRow, kMenuTopRow + 2);
1151changeCursor(0, kMenuTopRow, kCursorTypeHidden, 0);
1152
1153nextRow = kMenuTopRow;
1154
1155if (devcnt)
1156{
1157printf("Use \30\31 keys to select the startup volume.");
1158GUI_showMenu(menuItems, devcnt, selectIndex, kMenuTopRow + 2, kMenuMaxItems);
1159nextRow += min(devcnt, kMenuMaxItems) + 3;
1160}
1161
1162showPrompt = (devcnt == 0) || (menuBVR->flags & kBVFlagNativeBoot);
1163GUI_showBootPrompt(nextRow, showPrompt);
1164//changeCursor( 0, kMenuTopRow, kCursorTypeUnderline, 0 );
1165}
1166else
1167{
1168gui.redraw = true;
1169#if UNUSED
1170setVideoMode(GRAPHICS_MODE, 0);
1171#else
1172setVideoMode(GRAPHICS_MODE);
1173#endif
1174updateVRAM();
1175}
1176}
1177key = 0;
1178break;
1179
1180default:
1181key = 0;
1182break;
1183}
1184} while (0 == key);
1185
1186done:
1187if (getVideoMode() == VGA_TEXT_MODE)
1188{
1189clearScreenRows(kMenuTopRow, kScreenLastRow);
1190changeCursor(0, kMenuTopRow, kCursorTypeUnderline, 0);
1191}
1192 safe_set_env(envShouldboot, false);
1193gui.menu.draw = false;
1194if (menuItems)
1195{
1196free(menuItems);
1197menuItems = NULL;
1198}
1199return 0;
1200}
1201
1202
1203
1204int GUI_error(const char * fmt, ...)
1205{
1206 va_list ap;
1207 gErrors = true;
1208 va_start(ap, fmt);
1209
1210if (getVideoMode() == VGA_TEXT_MODE)
1211{
1212prf(fmt, ap, putchar, 0);
1213 }
1214else
1215{
1216vprf(fmt, ap);
1217}
1218
1219va_end(ap);
1220 return(0);
1221}
1222
1223int GUI_verbose(const char * fmt, ...)
1224{
1225 va_list ap;
1226
1227va_start(ap, fmt);
1228
1229 if (gVerboseMode && (KernelStart == false))
1230 {
1231if (getVideoMode() == VGA_TEXT_MODE)
1232{
1233prf(fmt, ap, putchar, 0);
1234}
1235else
1236{
1237vprf(fmt, ap);
1238}
1239 }
1240
1241/* Kabyl: BooterLog */
1242struct putc_info pi;
1243
1244if (!msgbuf)
1245return 0;
1246
1247if (((cursor - msgbuf) > (BOOTER_LOG_SIZE - SAFE_LOG_SIZE)))
1248return 0;
1249pi.str = cursor;
1250pi.last_str = 0;
1251prf(fmt, ap, sputc, &pi);
1252cursor += strlen((char *)cursor);
1253
1254
1255 va_end(ap);
1256 return(0);
1257}
1258
1259int GUI_printf(const char * fmt, ...)
1260{
1261 va_list ap;
1262va_start(ap, fmt);
1263
1264if (KernelStart == false) {
1265
1266if (getVideoMode() == VGA_TEXT_MODE)
1267{
1268prf(fmt, ap, putchar, 0);
1269}
1270else
1271{
1272vprf(fmt, ap);
1273}
1274}
1275/* Kabyl: BooterLog */
1276struct putc_info pi;
1277
1278if (!msgbuf)
1279return 0;
1280
1281if (((cursor - msgbuf) > (BOOTER_LOG_SIZE - SAFE_LOG_SIZE)))
1282return 0;
1283pi.str = cursor;
1284pi.last_str = 0;
1285prf(fmt, ap, sputc, &pi);
1286cursor += strlen((char *)cursor);
1287
1288va_end(ap);
1289 return 0;
1290}
1291
1292void GUI_stop(const char * fmt, ...)
1293{
1294va_list ap;
1295
1296printf("\n");
1297va_start(ap, fmt);
1298
1299if (getVideoMode() == VGA_TEXT_MODE)
1300{
1301prf(fmt, ap, putchar, 0);
1302}
1303else
1304{
1305vprf(fmt, ap);
1306}
1307va_end(ap);
1308
1309printf("\nThis is a non recoverable error! System HALTED!!!");
1310halt();
1311while (1);
1312}
1313
1314void GUI_showHelp(void)
1315{
1316if (getVideoMode() == GRAPHICS_MODE) {
1317showInfoBox("Help. Press q to quit.\n", (char *)BootHelp_txt);
1318} else {
1319showTextBuffer((char *)BootHelp_txt, BootHelp_txt_len);
1320}
1321}
1322
1323void GUI_showMessage(char *message)
1324{
1325if (getVideoMode() == GRAPHICS_MODE) {
1326showInfoBox("Help. Press q to quit.\n", message);
1327} else {
1328showTextBuffer(message, strlen(message));
1329}
1330}

Archive Download this file

Revision: 1919