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

Archive Download this file

Revision: 1977