Chameleon

Chameleon Svn Source Tree

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

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

Archive Download this file

Revision: 1899