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

Archive Download this file

Revision: 2057