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

Archive Download this file

Revision: 2112