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

Archive Download this file

Revision: 1972