Chameleon

Chameleon Svn Source Tree

Root/branches/azimutz/Chazileon/i386/boot2/options.c

1/*
2 * Copyright (c) 1999-2004 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Portions Copyright (c) 1999-2004 Apple Computer, Inc. All Rights
7 * Reserved. This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 2.0 (the "License"). You may not use this file
10 * except in compliance with the License. Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
12 * this file.
13 *
14 * The Original Code and all software distributed under the License are
15 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
20 * under the License.
21 *
22 * @APPLE_LICENSE_HEADER_END@
23 */
24
25//Azi:include
26//#include "boot.h" - included on graphics.h, which is included on gui.h
27//#include "bootstruct.h" - same as above
28#include "embedded.h"
29#include "fdisk.h"
30#include "gui.h"
31#include "pci.h"
32#include "ramdisk.h"
33#include "sl.h" //Azi:sysversion
34
35#include "autoresolution.h" //Azi:autoresolution - "was" included on boot.h, which is everywere!! -> gui.h -> graphics.h
36
37static bool shouldboot = false;
38
39char gMacOSVersion[8]; //Azi:sysversion
40
41extern int multiboot_timeout;
42extern int multiboot_timeout_set;
43
44extern BVRef bvChain;
45//extern intmenucount;
46
47extern intgDeviceCount;
48
49intselectIndex = 0;
50MenuItem * menuItems = NULL;
51
52enum {
53 kMenuTopRow = 5,
54 kMenuMaxItems = 10,
55 kScreenLastRow = 24
56};
57
58//==========================================================================
59
60typedef struct {
61 int x;
62 int y;
63 int type;
64} CursorState;
65
66static void changeCursor( int col, int row, int type, CursorState * cs )
67{
68 if (cs) getCursorPositionAndType( &cs->x, &cs->y, &cs->type );
69 setCursorType( type );
70 setCursorPosition( col, row, 0 );
71}
72
73static void moveCursor( int col, int row )
74{
75 setCursorPosition( col, row, 0 );
76}
77
78static void restoreCursor( const CursorState * cs )
79{
80 setCursorPosition( cs->x, cs->y, 0 );
81 setCursorType( cs->type );
82}
83
84//==========================================================================
85
86/* Flush keyboard buffer; returns TRUE if any of the flushed
87 * characters was F8.
88 */
89
90static bool flushKeyboardBuffer(void)
91{
92 bool status = false;
93
94 while ( readKeyboardStatus() ) {
95 if (bgetc() == 0x4200) status = true;
96 }
97 return status;
98}
99
100//==========================================================================
101
102static int countdown( const char * msg, int row, int timeout )
103{
104 unsigned long time;
105 int ch = 0;
106 int col = strlen(msg) + 1;
107
108 flushKeyboardBuffer();
109
110if( bootArgs->Video.v_display == VGA_TEXT_MODE )
111{
112moveCursor( 0, row );
113printf(msg);
114
115} else {
116
117position_t p = pos( gui.screen.width / 2 + 1 , ( gui.devicelist.pos.y + 3 ) +
118( ( gui.devicelist.height - gui.devicelist.iconspacing ) / 2 ) );
119
120char dummy[80];
121getBootVolumeDescription( gBootVolume, dummy, 80, true );
122drawDeviceIcon( gBootVolume, gui.screen.pixmap, p, false );
123drawStrCenteredAt( (char *) msg, &font_small, gui.screen.pixmap, gui.countdown.pos );
124
125// make this screen the new background
126memcpy( gui.backbuffer->pixels, gui.screen.pixmap->pixels, gui.backbuffer->width * gui.backbuffer->height * 4 );
127
128}
129
130int multi_buff = 18 * (timeout);
131 int multi = ++multi_buff;
132
133 int lasttime=0;
134
135 for ( time = time18(), timeout++; timeout > 0; )
136 {
137if( time18() > lasttime)
138{
139multi--;
140lasttime=time18();
141}
142
143 if (ch = readKeyboardStatus())
144 break;
145
146 // Count can be interrupted by holding down shift,
147 // control or alt key
148 if ( ( readKeyboardShiftFlags() & 0x0F ) != 0 )
149{
150 ch = 1;
151 break;
152 }
153
154 if ( time18() >= time )
155 {
156 time += 18;
157 timeout--;
158
159if( bootArgs->Video.v_display == VGA_TEXT_MODE )
160{
161moveCursor( col, row );
162printf("(%d) ", timeout);
163}
164 }
165
166if( bootArgs->Video.v_display == GRAPHICS_MODE )
167{
168drawProgressBar( gui.screen.pixmap, 100, gui.progressbar.pos , ( multi * 100 / multi_buff ) );
169gui.redraw = true;
170updateVRAM();
171}
172
173 }
174
175 flushKeyboardBuffer();
176
177 return ch;
178}
179
180//==========================================================================
181
182static char gBootArgs[BOOT_STRING_LEN];
183static char * gBootArgsPtr = gBootArgs;
184static char * gBootArgsEnd = gBootArgs + BOOT_STRING_LEN - 1;
185static char booterCommand[BOOT_STRING_LEN];
186static char booterParam[BOOT_STRING_LEN];
187
188static void clearBootArgs(void)
189{
190gBootArgsPtr = gBootArgs;
191memset(gBootArgs, '\0', BOOT_STRING_LEN);
192
193if (bootArgs->Video.v_display == GRAPHICS_MODE) {
194clearGraphicBootPrompt();
195}
196}
197
198//==========================================================================
199
200static void showBootPrompt(int row, bool visible)
201{
202extern char bootPrompt[];
203extern char bootRescanPrompt[];
204
205if( bootArgs->Video.v_display == VGA_TEXT_MODE ) {
206changeCursor( 0, row, kCursorTypeUnderline, 0 );
207clearScreenRows( row, kScreenLastRow );
208}
209
210clearBootArgs();
211
212if (visible) {
213if (bootArgs->Video.v_display == VGA_TEXT_MODE) {
214if (gEnableCDROMRescan) {
215printf( bootRescanPrompt );
216} else {
217printf( bootPrompt );
218}
219}
220} else {
221if (bootArgs->Video.v_display == GRAPHICS_MODE) {
222clearGraphicBootPrompt();
223} else {
224printf("Press Enter to start up the foreign OS. ");
225}
226}
227}
228
229//==========================================================================
230
231static void updateBootArgs( int key )
232{
233 key &= kASCIIKeyMask;
234
235 switch ( key )
236 {
237 case kBackspaceKey:
238 if ( gBootArgsPtr > gBootArgs )
239 {
240 int x, y, t;
241 getCursorPositionAndType( &x, &y, &t );
242 if ( x == 0 && y )
243 {
244 x = 80; y--;
245 }
246 if (x)
247x--;
248if( bootArgs->Video.v_display == VGA_TEXT_MODE )
249{
250setCursorPosition( x, y, 0 );
251putca(' ', 0x07, 1);
252} else
253updateGraphicBootPrompt(kBackspaceKey);
254
255*gBootArgsPtr-- = '\0';
256}
257
258break;
259
260 default:
261 if ( key >= ' ' && gBootArgsPtr < gBootArgsEnd)
262 {
263if( bootArgs->Video.v_display == VGA_TEXT_MODE )
264putchar(key); // echo to screen
265else
266updateGraphicBootPrompt(key);
267*gBootArgsPtr++ = key;
268}
269
270break;
271 }
272}
273
274//==========================================================================
275
276static const MenuItem * gMenuItems = NULL;
277
278static int gMenuItemCount;
279static int gMenuRow;
280static int gMenuHeight;
281static int gMenuTop;
282static int gMenuBottom;
283static int gMenuSelection;
284
285static int gMenuStart;
286static int gMenuEnd;
287
288static void printMenuItem( const MenuItem * item, int highlight )
289{
290 printf(" ");
291
292 if ( highlight )
293 putca(' ', 0x70, strlen(item->name) + 4);
294 else
295 putca(' ', 0x07, 40);
296
297 printf(" %40s\n", item->name);
298}
299
300//==========================================================================
301
302static void showMenu( const MenuItem * items, int count,
303 int selection, int row, int height )
304{
305 int i;
306 CursorState cursorState;
307
308 if ( items == NULL || count == 0 )
309return;
310
311 // head and tail points to the start and the end of the list.
312 // top and bottom points to the first and last visible items
313 // in the menu window.
314
315 gMenuItems= items;
316 gMenuRow= row;
317 gMenuHeight= height;
318 gMenuItemCount= count;
319 gMenuTop= 0;
320 gMenuBottom= min( count, height ) - 1;
321 gMenuSelection= selection;
322
323 gMenuStart= 0;
324 gMenuEnd = min( count, gui.maxdevices ) - 1;
325
326// If the selected item is not visible, shift the list down.
327
328 if ( gMenuSelection > gMenuBottom )
329 {
330 gMenuTop += ( gMenuSelection - gMenuBottom );
331 gMenuBottom = gMenuSelection;
332 }
333
334if ( gMenuSelection > gMenuEnd )
335 {
336gMenuStart += ( gMenuSelection - gMenuEnd );
337 gMenuEnd = gMenuSelection;
338 }
339
340// Draw the visible items.
341
342if( bootArgs->Video.v_display == GRAPHICS_MODE )
343
344drawDeviceList(gMenuStart, gMenuEnd, gMenuSelection);
345
346else {
347
348changeCursor( 0, row, kCursorTypeHidden, &cursorState );
349
350for ( i = gMenuTop; i <= gMenuBottom; i++ )
351{
352printMenuItem( &items[i], (i == gMenuSelection) );
353}
354
355restoreCursor( &cursorState );
356 }
357}
358
359//==========================================================================
360
361static int updateMenu( int key, void ** paramPtr )
362{
363 int moved = 0;
364
365 union {
366 struct {
367 unsigned int
368 selectionUp : 1,
369 selectionDown : 1,
370 scrollUp : 1,
371 scrollDown : 1;
372 } f;
373 unsigned int w;
374 } draw = {{0}};
375
376 if ( gMenuItems == NULL )
377return 0;
378
379if( bootArgs->Video.v_display == GRAPHICS_MODE )
380{
381int res;
382
383// set navigation keys for horizontal layout as defaults
384int previous= 0x4B00;// left arrow
385int subsequent= 0x4D00;// right arrow
386int menu= 0x5000;// down arrow
387
388if ( gui.layout == VerticalLayout )
389{
390// set navigation keys for vertical layout
391previous= 0x4800;// up arrow
392subsequent= 0x5000;// down arrow
393menu= 0x4B00;// right arrow
394}
395
396if ( key == previous )
397{
398if ( gMenuSelection > gMenuTop )
399draw.f.selectionUp = 1;
400else if ( gMenuTop > 0 )
401draw.f.scrollDown = 1;
402
403}
404
405else if ( key == subsequent )
406{
407if ( gMenuSelection != gMenuBottom)
408draw.f.selectionDown = 1;
409else if ( gMenuBottom < ( gMenuItemCount - 1 ) )
410draw.f.scrollUp = 1;
411}
412
413else if ( key == menu )
414{
415if ( gui.menu.draw )
416updateInfoMenu(key);
417else
418drawInfoMenu();
419}
420
421else if ( gui.menu.draw )
422{
423res = updateInfoMenu(key);
424
425if ( res == CLOSE_INFO_MENU )
426gui.menu.draw = false;
427else
428{
429shouldboot = ( res != DO_NOT_BOOT );
430
431if ( shouldboot )
432gui.menu.draw = false;
433
434switch (res)
435{
436case BOOT_NORMAL:
437gVerboseMode = false;
438gBootMode = kBootModeNormal;
439break;
440
441case BOOT_VERBOSE:
442gVerboseMode = true;
443gBootMode = kBootModeNormal;
444*gBootArgsPtr++ = '-';
445*gBootArgsPtr++ = 'v';
446break;
447
448case BOOT_IGNORECACHE:
449gVerboseMode = false;
450gBootMode = kBootModeNormal;
451*gBootArgsPtr++ = '-';
452*gBootArgsPtr++ = 'f';
453break;
454
455case BOOT_SINGLEUSER:
456gVerboseMode = true;
457gBootMode = kBootModeNormal;
458*gBootArgsPtr++ = '-';
459*gBootArgsPtr++ = 's';
460break;
461}
462
463}
464
465}
466
467} else {
468switch ( key )
469{
470 case 0x4800: // Up Arrow
471if ( gMenuSelection != gMenuTop )
472draw.f.selectionUp = 1;
473else if ( gMenuTop > 0 )
474draw.f.scrollDown = 1;
475break;
476
477case 0x5000: // Down Arrow
478if ( gMenuSelection != gMenuBottom )
479draw.f.selectionDown = 1;
480else if ( gMenuBottom < (gMenuItemCount - 1) )
481draw.f.scrollUp = 1;
482break;
483}
484}
485
486 if ( draw.w )
487 {
488 if ( draw.f.scrollUp )
489 {
490 scollPage(0, gMenuRow, 40, gMenuRow + gMenuHeight - 1, 0x07, 1, 1);
491 gMenuTop++; gMenuBottom++;
492gMenuStart++; gMenuEnd++;
493 draw.f.selectionDown = 1;
494 }
495
496 if ( draw.f.scrollDown )
497 {
498 scollPage(0, gMenuRow, 40, gMenuRow + gMenuHeight - 1, 0x07, 1, -1);
499 gMenuTop--; gMenuBottom--;
500 gMenuStart--; gMenuEnd--;
501 draw.f.selectionUp = 1;
502 }
503
504 if ( draw.f.selectionUp || draw.f.selectionDown )
505 {
506
507CursorState cursorState;
508
509// Set cursor at current position, and clear inverse video.
510
511if( bootArgs->Video.v_display == VGA_TEXT_MODE )
512{
513changeCursor( 0, gMenuRow + gMenuSelection - gMenuTop, kCursorTypeHidden, &cursorState );
514printMenuItem( &gMenuItems[gMenuSelection], 0 );
515}
516
517if ( draw.f.selectionUp )
518{
519gMenuSelection--;
520if(( gMenuSelection - gMenuStart) == -1 )
521{
522gMenuStart--;
523gMenuEnd--;
524}
525
526} else {
527gMenuSelection++;
528if(( gMenuSelection - ( gui.maxdevices - 1) - gMenuStart) > 0 )
529{
530gMenuStart++;
531gMenuEnd++;
532}
533 }
534
535if( bootArgs->Video.v_display == VGA_TEXT_MODE )
536 {
537moveCursor( 0, gMenuRow + gMenuSelection - gMenuTop );
538printMenuItem( &gMenuItems[gMenuSelection], 1 );
539restoreCursor( &cursorState );
540
541 } else
542
543drawDeviceList (gMenuStart, gMenuEnd, gMenuSelection);
544
545}
546
547 *paramPtr = gMenuItems[gMenuSelection].param;
548 moved = 1;
549 }
550
551return moved;
552}
553
554//==========================================================================
555
556static void skipblanks( const char ** cpp )
557{
558 while ( **(cpp) == ' ' || **(cpp) == '\t' ) ++(*cpp);
559}
560
561//==========================================================================
562
563static const char * extractKernelName( char ** cpp )
564{
565 char * kn = *cpp;
566 char * cp = *cpp;
567 char c;
568
569 // Convert char to lower case.
570
571 c = *cp | 0x20;
572
573 // Must start with a letter or a '/'.
574
575 if ( (c < 'a' || c > 'z') && ( c != '/' ) )
576 return 0;
577
578 // Keep consuming characters until we hit a separator.
579
580 while ( *cp && (*cp != '=') && (*cp != ' ') && (*cp != '\t') )
581 cp++;
582
583 // Only SPACE or TAB separator is accepted.
584 // Reject everything else.
585
586 if (*cp == '=')
587 return 0;
588
589 // Overwrite the separator, and move the pointer past
590 // the kernel name.
591
592 if (*cp != '\0') *cp++ = '\0';
593 *cpp = cp;
594
595 return kn;
596}
597
598//==========================================================================
599
600static void
601printMemoryInfo(void)
602{
603 int line;
604 int i;
605 MemoryRange *mp = bootInfo->memoryMap;
606
607 // Activate and clear page 1
608 setActiveDisplayPage(1);
609 clearScreenRows(0, 24);
610 setCursorPosition( 0, 0, 1 );
611
612 printf("BIOS reported memory ranges:\n");
613 line = 1;
614 for (i=0; i<bootInfo->memoryMapCount; i++) {
615 printf("Base 0x%08x%08x, ",
616 (unsigned long)(mp->base >> 32),
617 (unsigned long)(mp->base));
618 printf("length 0x%08x%08x, type %d\n",
619 (unsigned long)(mp->length >> 32),
620 (unsigned long)(mp->length),
621 mp->type);
622 if (line++ > 20) {
623 pause();
624 line = 0;
625 }
626 mp++;
627 }
628 if (line > 0) {
629 pause();
630 }
631
632 setActiveDisplayPage(0);
633}
634
635char *getMemoryInfoString()
636{
637 int i;
638 MemoryRange *mp = bootInfo->memoryMap;
639char *buff = malloc(sizeof(char)*1024);
640if(!buff) return 0;
641
642char info[] = "BIOS reported memory ranges:\n";
643sprintf(buff, "%s", info);
644 for (i=0; i<bootInfo->memoryMapCount; i++) {
645 sprintf( buff+strlen(buff), "Base 0x%08x%08x, ",
646 (unsigned long)(mp->base >> 32),
647 (unsigned long)(mp->base));
648 sprintf( buff+strlen(buff), "length 0x%08x%08x, type %d\n",
649 (unsigned long)(mp->length >> 32),
650 (unsigned long)(mp->length),
651 mp->type);
652 mp++;
653 }
654return buff;
655}
656
657//==========================================================================
658
659void lspci(void)
660{
661if (bootArgs->Video.v_display == VGA_TEXT_MODE) {
662setActiveDisplayPage(1);
663clearScreenRows(0, 24);
664setCursorPosition(0, 0, 1);
665}
666
667dump_pci_dt(root_pci_dev->children);
668
669pause();
670
671if (bootArgs->Video.v_display == VGA_TEXT_MODE) {
672setActiveDisplayPage(0);
673}
674}
675
676//==========================================================================
677
678int getBootOptions(bool firstRun)
679{
680int i;
681int key;
682int nextRow;
683int timeout;
684int bvCount;
685BVRef bvr;
686BVRef menuBVR;
687bool showPrompt, newShowPrompt, isCDROM;
688
689// Initialize default menu selection entry.
690gBootVolume = menuBVR = selectBootVolume(bvChain);
691
692if (biosDevIsCDROM(gBIOSDev)) {
693isCDROM = true;
694} else {
695isCDROM = false;
696}
697
698// ensure we're in graphics mode if gui is setup
699if (gui.initialised) {
700if (bootArgs->Video.v_display == VGA_TEXT_MODE) {
701setVideoMode(GRAPHICS_MODE, 0);
702}
703}
704
705// Allow user to override default timeout.
706if (multiboot_timeout_set) {
707timeout = multiboot_timeout;
708} else if (!getIntForKey(kTimeoutKey, &timeout, &bootInfo->bootConfig)) {
709/* If there is no timeout key in the file use the default timeout
710 which is different for CDs vs. hard disks. However, if not booting
711 a CD and no config file could be loaded set the timeout
712 to zero which causes the menu to display immediately.
713 This way, if no partitions can be found, that is the disk is unpartitioned
714 or simply cannot be read) then an empty menu is displayed.
715 If some partitions are found, for example a Windows partition, then
716 these will be displayed in the menu as foreign partitions.
717 */
718if (isCDROM) {
719timeout = kCDBootTimeout;
720} else {
721timeout = sysConfigValid ? kBootTimeout : 0;
722}
723}
724
725if (timeout < 0) {
726gBootMode |= kBootModeQuiet;
727}
728
729// If the user is holding down a modifier key, enter safe mode.
730if ((readKeyboardShiftFlags() & 0x0F) != 0) {
731gBootMode |= kBootModeSafe; //Azi: Mek has this commented out.
732}
733
734// If user typed F8, abort quiet mode, and display the menu.
735{
736bool f8press = false, spress = false, vpress = false;
737int key;
738while (readKeyboardStatus()) {
739key = bgetc ();
740if (key == 0x4200) f8press = true;
741if ((key & 0xff) == 's' || (key & 0xff) == 'S') spress = true;
742if ((key & 0xff) == 'v' || (key & 0xff) == 'V') vpress = true;
743}
744if (f8press) {
745gBootMode &= ~kBootModeQuiet;
746timeout = 0;
747}
748if ((gBootMode & kBootModeQuiet) && firstRun && vpress && (gBootArgsPtr + 3 < gBootArgsEnd)) {
749*(gBootArgsPtr++) = ' ';
750*(gBootArgsPtr++) = '-';
751*(gBootArgsPtr++) = 'v';
752}
753if ((gBootMode & kBootModeQuiet) && firstRun && spress && (gBootArgsPtr + 3 < gBootArgsEnd)) {
754*(gBootArgsPtr++) = ' ';
755*(gBootArgsPtr++) = '-';
756*(gBootArgsPtr++) = 's';
757}
758}
759clearBootArgs();
760
761if (bootArgs->Video.v_display == VGA_TEXT_MODE) {
762setCursorPosition(0, 0, 0);
763clearScreenRows(0, kScreenLastRow);
764if (!(gBootMode & kBootModeQuiet)) {
765// Display banner and show hardware info.
766printf(bootBanner, (bootInfo->convmem + bootInfo->extmem) / 1024);
767printf(getVBEInfoString());
768}
769changeCursor(0, kMenuTopRow, kCursorTypeUnderline, 0);
770verbose("Scanning device %x...", gBIOSDev);
771}
772
773// When booting from CD, default to hard drive boot when possible.
774if (isCDROM && firstRun) {
775const char *val;
776char *prompt;
777char *name;
778int cnt;
779int optionKey;
780
781if (getValueForKey(kCDROMPromptKey, &val, &cnt, &bootInfo->bootConfig)) {
782cnt += 1;
783prompt = malloc(cnt);
784strlcpy(prompt, val, cnt);
785} else {
786name = malloc(80);
787getBootVolumeDescription(gBootVolume, name, 80, false);
788prompt = malloc(256);
789sprintf(prompt, "Press any key to start up from %s, or press F8 to enter startup options.", name);
790free(name);
791cnt = 0;
792}
793
794if (getIntForKey( kCDROMOptionKey, &optionKey, &bootInfo->bootConfig )) {
795// The key specified is a special key.
796} else if (getValueForKey( kCDROMOptionKey, &val, &cnt, &bootInfo->bootConfig ) && cnt >= 1) {
797optionKey = val[0];
798} else {
799// Default to F8.
800optionKey = 0x4200;
801}
802
803// If the timeout is zero then it must have been set above due to the
804// early catch of F8 which means the user wants to set boot options
805// which we ought to interpret as meaning he wants to boot the CD.
806if (timeout != 0) {
807key = countdown(prompt, kMenuTopRow, timeout);
808} else {
809key = optionKey;
810}
811
812if (cnt) {
813free(prompt);
814}
815
816clearScreenRows( kMenuTopRow, kMenuTopRow + 2 );
817
818// Hit the option key ?
819if (key == optionKey) {
820gBootMode &= ~kBootModeQuiet;
821timeout = 0;
822} else {
823key = key & 0xFF;
824
825// Try booting hard disk if user pressed 'h'
826if (biosDevIsCDROM(gBIOSDev) && key == 'h') {
827BVRef bvr;
828
829// Look at partitions hosting OS X other than the CD-ROM
830for (bvr = bvChain; bvr; bvr=bvr->next) {
831if ((bvr->flags & kBVFlagSystemVolume) && bvr->biosdev != gBIOSDev) {
832gBootVolume = bvr;
833}
834}
835}
836goto done;
837}
838}
839
840if (gBootMode & kBootModeQuiet) {
841// No input allowed from user.
842goto done;
843}
844
845if (firstRun && timeout > 0 && countdown("Press any key to enter startup options.", kMenuTopRow, timeout) == 0) {
846// If the user is holding down a modifier key,
847// enter safe mode.
848if ((readKeyboardShiftFlags() & 0x0F) != 0) {
849gBootMode |= kBootModeSafe;
850}
851goto done;
852}
853
854if (gDeviceCount) {
855// Allocate memory for an array of menu items.
856menuItems = malloc(sizeof(MenuItem) * gDeviceCount);
857if (menuItems == NULL) {
858goto done;
859}
860
861// Associate a menu item for each BVRef.
862for (bvr=bvChain, i=gDeviceCount-1, selectIndex=0; bvr; bvr=bvr->next) {
863if (bvr->visible) {
864getBootVolumeDescription(bvr, menuItems[i].name, 80, true);
865menuItems[i].param = (void *) bvr;
866if (bvr == menuBVR) {
867selectIndex = i;
868}
869i--;
870}
871}
872}
873
874if (bootArgs->Video.v_display == GRAPHICS_MODE) {
875// redraw the background buffer
876drawBackground();
877gui.devicelist.draw = true;
878gui.redraw = true;
879if (!(gBootMode & kBootModeQuiet)) {
880bool showBootBanner = true;
881
882// Check if "Boot Banner"=N switch is present in config file.
883getBoolForKey(kBootBannerKey, &showBootBanner, &bootInfo->bootConfig);
884if (showBootBanner) {
885// Display banner and show hardware info.
886gprintf(&gui.screen, bootBanner + 1, (bootInfo->convmem + bootInfo->extmem) / 1024);
887}
888
889// redraw background
890memcpy(gui.backbuffer->pixels, gui.screen.pixmap->pixels, gui.backbuffer->width * gui.backbuffer->height * 4);
891}
892} else {
893// Clear screen and hide the blinking cursor.
894clearScreenRows(kMenuTopRow, kMenuTopRow + 2);
895changeCursor(0, kMenuTopRow, kCursorTypeHidden, 0);
896}
897
898nextRow = kMenuTopRow;
899showPrompt = true;
900
901if (gDeviceCount) {
902if( bootArgs->Video.v_display == VGA_TEXT_MODE ) {
903printf("Use \30\31 keys to select the startup volume.");
904}
905showMenu( menuItems, gDeviceCount, selectIndex, kMenuTopRow + 2, kMenuMaxItems );
906nextRow += min( gDeviceCount, kMenuMaxItems ) + 3;
907}
908
909// Show the boot prompt.
910showPrompt = (gDeviceCount == 0) || (menuBVR->flags & kBVFlagNativeBoot);
911showBootPrompt( nextRow, showPrompt );
912
913do //Azi:style
914{
915if (bootArgs->Video.v_display == GRAPHICS_MODE) {
916// redraw background
917memcpy( gui.backbuffer->pixels, gui.screen.pixmap->pixels, gui.backbuffer->width * gui.backbuffer->height * 4 );
918// reset cursor co-ords
919gui.debug.cursor = pos( gui.screen.width - 160 , 10 );
920}
921key = getc();
922updateMenu( key, (void **) &menuBVR );
923newShowPrompt = (gDeviceCount == 0) || (menuBVR->flags & kBVFlagNativeBoot);
924
925if (newShowPrompt != showPrompt) {
926showPrompt = newShowPrompt;
927showBootPrompt( nextRow, showPrompt );
928}
929
930if (showPrompt) {
931updateBootArgs(key);
932}
933
934switch (key)
935{
936case kReturnKey:
937if (gui.menu.draw)
938{
939key=0;
940break;
941}
942if (*gBootArgs == '?')
943{
944char * argPtr = gBootArgs;
945
946// Skip the leading "?" character.
947argPtr++;
948getNextArg(&argPtr, booterCommand);
949getNextArg(&argPtr, booterParam);
950
951/*
952* TODO: this needs to be refactored.
953*/
954if (strcmp( booterCommand, "video" ) == 0)
955{
956if (bootArgs->Video.v_display == GRAPHICS_MODE)
957{
958showInfoBox(getVBEInfoString(), getVBEModeInfoString());
959}
960else
961{
962printVBEModeInfo();
963}
964}
965else if ( strcmp( booterCommand, "memory" ) == 0)
966{
967if (bootArgs->Video.v_display == GRAPHICS_MODE )
968{
969showInfoBox("Memory Map", getMemoryInfoString());
970}
971else
972{
973printMemoryInfo();
974}
975}
976else if (strcmp(booterCommand, "lspci") == 0)
977{
978lspci();
979} //Azi: ?more ??
980else if (strcmp(booterCommand, "more") == 0)
981{
982showTextFile(booterParam);
983}
984else if (strcmp(booterCommand, "rd") == 0)
985{
986processRAMDiskCommand(&argPtr, booterParam);
987}
988else if (strcmp(booterCommand, "norescan") == 0)
989{
990if (gEnableCDROMRescan)
991{
992gEnableCDROMRescan = false;
993break;
994}
995}
996else
997{
998showHelp();
999}
1000key = 0;
1001showBootPrompt(nextRow, showPrompt);
1002break;
1003}
1004gBootVolume = menuBVR;
1005setRootVolume(menuBVR);
1006gBIOSDev = menuBVR->biosdev;
1007break;
1008
1009case kEscapeKey:
1010clearBootArgs();
1011break;
1012
1013case kF2Key:
1014
1015/*
1016 * AutoResolution - Reapply the patch if Graphics Mode was incorrect
1017 * or EDID Info was insane
1018 */
1019
1020//get the new Graphics Mode key
1021processBootOptions();
1022if ((gAutoResolution == TRUE) && map)
1023{
1024UInt32 params[4];
1025params[3] = 0;
1026//Has the target Resolution Changed ?
1027int count = getNumberArrayFromProperty(kGraphicsModeKey, params, 4);
1028if ( count < 3 )
1029getResolution(params);
1030
1031if ((params[0] != 0) && (params[1] != 0)
1032&&(params[0] != map->currentX) && (params[1] != map->currentY))
1033{
1034
1035//Go back to TEXT mode while we change the mode
1036if (bootArgs->Video.v_display == GRAPHICS_MODE)
1037{
1038CursorState cursorState;
1039
1040setVideoMode(VGA_TEXT_MODE, 0);
1041
1042setCursorPosition(0, 0, 0);
1043clearScreenRows(0, kScreenLastRow);
1044changeCursor( 0, 0, kCursorTypeHidden, &cursorState );
1045
1046//Reapply patch in case resolution have changed
1047
1048patchVbios(map, params[0], params[1], params[2], 0, 0);
1049
1050if (useGUI && (gui.initialised == true))
1051initGUI();
1052// Make sure all values are set
1053if (bootArgs->Video.v_display != GRAPHICS_MODE)
1054bootArgs->Video.v_display = GRAPHICS_MODE;
1055
1056if (!useGUI)
1057useGUI = true;
1058
1059// redraw the background buffer
1060drawBackground();
1061gui.devicelist.draw = true;
1062gui.redraw = true;
1063if (!(gBootMode & kBootModeQuiet))
1064{
1065bool showBootBanner = true;
1066
1067// Check if "Boot Banner"=N switch is present in config file.
1068getBoolForKey(kBootBannerKey, &showBootBanner, &bootInfo->bootConfig);
1069if (showBootBanner)
1070// Display banner and show hardware info.
1071gprintf(&gui.screen, bootBanner + 1, (bootInfo->convmem + bootInfo->extmem) / 1024);
1072
1073// redraw background
1074memcpy(gui.backbuffer->pixels, gui.screen.pixmap->pixels, gui.backbuffer->width * gui.backbuffer->height * 4);
1075}
1076
1077nextRow = kMenuTopRow;
1078showPrompt = true;
1079
1080if (gDeviceCount)
1081{
1082showMenu( menuItems, gDeviceCount, selectIndex, kMenuTopRow + 2, kMenuMaxItems );
1083nextRow += min( gDeviceCount, kMenuMaxItems ) + 3;
1084}
1085
1086// Show the boot prompt.
1087showPrompt = (gDeviceCount == 0) || (menuBVR->flags & kBVFlagNativeBoot);
1088showBootPrompt( nextRow, showPrompt );
1089
1090//this is used to avoid resetting the incorrect mode while quiting the boot menu
1091map->hasSwitched = true;
1092}
1093}
1094clearBootArgs();
1095key = 0;
1096}
1097break;
1098
1099case kF5Key:
1100// New behavior:
1101// Clear gBootVolume to restart the loop
1102// if the user enabled rescanning the optical drive.
1103// Otherwise boot the default boot volume.
1104if (gEnableCDROMRescan)
1105{
1106gBootVolume = NULL;
1107clearBootArgs();
1108}
1109break;
1110
1111case kF10Key:
1112gScanSingleDrive = false;
1113scanDisks(gBIOSDev, &bvCount);
1114gBootVolume = NULL;
1115clearBootArgs();
1116break;
1117
1118case kTabKey:
1119// New behavior:
1120// Switch between text & graphic interfaces
1121// Only Permitted if started in graphics interface
1122if (useGUI)
1123{
1124setVideoMode(VGA_TEXT_MODE, 0);
1125
1126setCursorPosition(0, 0, 0);
1127clearScreenRows(0, kScreenLastRow);
1128
1129// Display banner and show hardware info.
1130printf(bootBanner, (bootInfo->convmem + bootInfo->extmem) / 1024);
1131printf(getVBEInfoString());
1132
1133clearScreenRows(kMenuTopRow, kMenuTopRow + 2);
1134changeCursor(0, kMenuTopRow, kCursorTypeHidden, 0);
1135
1136nextRow = kMenuTopRow;
1137showPrompt = true;
1138
1139if (gDeviceCount)
1140{
1141printf("Use \30\31 keys to select the startup volume.");
1142showMenu(menuItems, gDeviceCount, selectIndex, kMenuTopRow + 2, kMenuMaxItems);
1143nextRow += min(gDeviceCount, kMenuMaxItems) + 3;
1144}
1145
1146showPrompt = (gDeviceCount == 0) || (menuBVR->flags & kBVFlagNativeBoot);
1147showBootPrompt(nextRow, showPrompt);
1148//changeCursor( 0, kMenuTopRow, kCursorTypeUnderline, 0 );
1149
1150/*
1151 * AutoResolution - make sure all values are set
1152 */
1153
1154bootArgs->Video.v_display = VGA_TEXT_MODE;
1155useGUI = false;
1156}
1157else
1158{
1159gui.redraw = true;
1160setVideoMode(GRAPHICS_MODE, 0);
1161
1162/*
1163 * AutoResolution - make sure all values are set
1164 */
1165bootArgs->Video.v_display = GRAPHICS_MODE;
1166useGUI = true;
1167
1168updateVRAM();
1169}
1170key = 0;
1171break;
1172
1173default:
1174key = 0;
1175break;
1176}
1177} while (0 == key);
1178
1179done:
1180if (bootArgs->Video.v_display == VGA_TEXT_MODE) {
1181clearScreenRows(kMenuTopRow, kScreenLastRow);
1182changeCursor(0, kMenuTopRow, kCursorTypeUnderline, 0);
1183}
1184shouldboot = false;
1185gui.menu.draw = false;
1186if (menuItems) {
1187free(menuItems);
1188menuItems = NULL;
1189}
1190return 0;
1191}
1192
1193//==========================================================================
1194
1195extern unsigned char chainbootdev;
1196extern unsigned char chainbootflag;
1197
1198bool copyArgument(const char *argName, const char *val, int cnt, char **argP, int *cntRemainingP)
1199{
1200 int argLen = argName ? strlen(argName) : 0;
1201 int len = argLen + cnt + 1; // +1 to account for space
1202
1203 if (len > *cntRemainingP) {
1204 error("Warning: boot arguments too long, truncating\n");
1205 return false;
1206 }
1207
1208 if (argName) {
1209 strncpy( *argP, argName, argLen );
1210 *argP += argLen;
1211 *argP[0] = '=';
1212 (*argP)++;
1213 len++; // +1 to account for '='
1214 }
1215 strncpy( *argP, val, cnt );
1216 *argP += cnt;
1217 *argP[0] = ' ';
1218 (*argP)++;
1219
1220 *cntRemainingP -= len;
1221 return true;
1222}
1223
1224//
1225// Returns TRUE if an argument was copied, FALSE otherwise
1226bool
1227processBootArgument(
1228 const char *argName, // The argument to search for
1229 const char *userString, // Typed-in boot arguments
1230 const char *kernelFlags, // Kernel flags from config table
1231 const char *configTable,
1232 char **argP, // Output value
1233 int *cntRemainingP, // Output count
1234 char *foundVal // found value
1235 )
1236{
1237 const char *val;
1238 int cnt;
1239 bool found = false;
1240
1241 if (getValueForBootKey(userString, argName, &val, &cnt)) {
1242 // Don't copy; these values will be copied at the end of argument processing.
1243 found = true;
1244 } else if (getValueForBootKey(kernelFlags, argName, &val, &cnt)) {
1245 // Don't copy; these values will be copied at the end of argument processing.
1246 found = true;
1247 } else if (getValueForKey(argName, &val, &cnt, &bootInfo->bootConfig)) {
1248 copyArgument(argName, val, cnt, argP, cntRemainingP);
1249 found = true;
1250 }
1251 if (found && foundVal) {
1252 strlcpy(foundVal, val, cnt+1);
1253 }
1254 return found;
1255}
1256
1257// Maximum config table value size
1258#define VALUE_SIZE 2048
1259
1260int
1261processBootOptions()
1262{
1263 const char * cp = gBootArgs;
1264 const char * val = 0;
1265 const char * kernel;
1266const char*value; //Azi:sysversion
1267int len; //Azi:sysversion
1268 int cnt;
1269int userCnt;
1270 int cntRemaining;
1271 char * argP;
1272 char uuidStr[64];
1273 bool uuidSet = false;
1274 char * configKernelFlags;
1275 char * valueBuffer;
1276config_file_t systemVersion;//Azi:sysversion - system.plist of booting partition
1277
1278 valueBuffer = malloc(VALUE_SIZE);
1279
1280 skipblanks( &cp );
1281
1282 // Update the unit and partition number.
1283
1284 if ( gBootVolume )
1285 {
1286 if (!( gBootVolume->flags & kBVFlagNativeBoot ))
1287 {
1288 readBootSector( gBootVolume->biosdev, gBootVolume->part_boff,
1289 (void *) 0x7c00 );
1290
1291 //
1292 // Setup edx, and signal intention to chain load the
1293 // foreign booter.
1294 //
1295
1296 chainbootdev = gBootVolume->biosdev;
1297 chainbootflag = 1;
1298
1299 return 1;
1300 }
1301 setRootVolume( gBootVolume );
1302 }
1303 // If no boot volume fail immediately because we're just going to fail
1304 // trying to load the config file anyway.
1305 else
1306 return -1;
1307
1308// Find out which version mac os we're booting. Azi:sysversion - Ok, if i move this here,
1309// which seems ideal to me, it gets hidden from verbose and this info been pretty helpful to me;
1310// plus, for some reason gMacOSVersion doesn't get initialized on boot.c?! i have to call this anyway
1311// with another variable name so, back to were i was. Need advice! Check below on loadOverrideConfig.
1312if (!loadConfigFile("/System/Library/CoreServices/SystemVersion.plist", &systemVersion))
1313{ //Azi: shouldn't this path start with / ?
1314if (getValueForKey(kProductVersion, &value, &len, &systemVersion))
1315{
1316// getValueForKey uses const char for val
1317// so copy it and trim
1318strncpy(gMacOSVersion, value, MIN(len, 4));
1319gMacOSVersion[MIN(len, 4)] = '\0';
1320}
1321} // doesn't print to screen here!
1322
1323//Azi: check loadOverrideConfig().
1324// Load config table specified by the user, or use the default.
1325/* if (!getValueForBootKey(cp, "config", &val, &cnt)) {
1326val = 0;
1327cnt = 0;
1328 }*/
1329
1330 // Load com.apple.Boot.plist from the selected volume
1331 // and use its contents to override default bootConfig.
1332 // This is not a mandatory operation anymore. Azi: meaning, it desn't return -1 anymore.
1333
1334// About overriding from OS specific folders: gMacOSVersion is not stored at this point;
1335// placed a "call 2" under common_boot, right after getting system version.
1336loadOverrideConfig(&bootInfo->overrideConfig); // call 1 - first to print to screen
1337
1338 // Use the kernel name specified by the user, or fetch the name
1339 // in the config table, or use the default if not specified.
1340 // Specifying a kernel name on the command line, or specifying
1341 // a non-default kernel name in the config file counts as
1342 // overriding the kernel, which causes the kernelcache not
1343 // to be used.
1344
1345 gOverrideKernel = false;
1346 if (( kernel = extractKernelName((char **)&cp) )) {
1347 strcpy( bootInfo->bootFile, kernel );
1348 gOverrideKernel = true;
1349 } else {
1350 if ( getValueForKey( kKernelNameKey, &val, &cnt, &bootInfo->bootConfig ) ) {
1351 strlcpy( bootInfo->bootFile, val, cnt+1 );
1352 if (strcmp( bootInfo->bootFile, kDefaultKernelName ) != 0) {
1353 gOverrideKernel = true;
1354 }
1355 } else {
1356 strcpy( bootInfo->bootFile, kDefaultKernelName );
1357 }
1358 }
1359
1360 cntRemaining = BOOT_STRING_LEN - 2; // save 1 for NULL, 1 for space
1361 argP = bootArgs->CommandLine;
1362
1363 // Get config table kernel flags, if not ignored.
1364 if (getValueForBootKey(cp, kIgnoreBootFileFlag, &val, &cnt) ||
1365!getValueForKey( kKernelFlagsKey, &val, &cnt, &bootInfo->bootConfig )) {
1366 val = "";
1367 cnt = 0;
1368 }
1369 configKernelFlags = malloc(cnt + 1);
1370 strlcpy(configKernelFlags, val, cnt + 1);
1371
1372 if (processBootArgument(kBootUUIDKey, cp, configKernelFlags, bootInfo->config, &argP, &cntRemaining, 0)) {
1373 // boot-uuid was set either on the command-line or in the config file.
1374 uuidSet = true;
1375 } else {
1376 // Try an alternate method for getting the root UUID on boot helper partitions.
1377 if (gBootVolume->flags & kBVFlagBooter)
1378 {
1379 if ((loadHelperConfig(&bootInfo->helperConfig) == 0)
1380 && getValueForKey(kHelperRootUUIDKey, &val, &cnt, &bootInfo->helperConfig) )
1381 {
1382 getValueForKey(kHelperRootUUIDKey, &val, &cnt, &bootInfo->helperConfig);
1383 copyArgument(kBootUUIDKey, val, cnt, &argP, &cntRemaining);
1384 uuidSet = true;
1385 }
1386 }
1387
1388 if (!uuidSet && gBootVolume->fs_getuuid && gBootVolume->fs_getuuid (gBootVolume, uuidStr) == 0) {
1389 verbose("Setting boot-uuid to: %s\n", uuidStr);
1390 copyArgument(kBootUUIDKey, uuidStr, strlen(uuidStr), &argP, &cntRemaining);
1391 uuidSet = true;
1392 }
1393 }
1394
1395 if (!processBootArgument(kRootDeviceKey, cp, configKernelFlags, bootInfo->config, &argP, &cntRemaining, gRootDevice)) {
1396 cnt = 0;
1397 if ( getValueForKey( kBootDeviceKey, &val, &cnt, &bootInfo->bootConfig)) {
1398 valueBuffer[0] = '*';
1399 cnt++;
1400 strlcpy(valueBuffer + 1, val, cnt);
1401 val = valueBuffer;
1402 } else {
1403 if (uuidSet) {
1404 val = "*uuid";
1405 cnt = 5;
1406 } else {
1407 // Don't set "rd=.." if there is no boot device key
1408 // and no UUID.
1409 val = "";
1410 cnt = 0;
1411 }
1412 }
1413 if (cnt > 0) {
1414 copyArgument( kRootDeviceKey, val, cnt, &argP, &cntRemaining);
1415 }
1416 strlcpy( gRootDevice, val, (cnt + 1));
1417 }
1418
1419 /*
1420 * Removed. We don't need this anymore.
1421 *
1422 if (!processBootArgument(kPlatformKey, cp, configKernelFlags, bootInfo->config, &argP, &cntRemaining, gPlatformName)) {
1423 getPlatformName(gPlatformName);
1424 copyArgument(kPlatformKey, gPlatformName, strlen(gPlatformName), &argP, &cntRemaining);
1425 }
1426 */
1427
1428 if (!getValueForBootKey(cp, kSafeModeFlag, &val, &cnt) &&
1429 !getValueForBootKey(configKernelFlags, kSafeModeFlag, &val, &cnt)) {
1430 if (gBootMode & kBootModeSafe) {
1431 copyArgument(0, kSafeModeFlag, strlen(kSafeModeFlag), &argP, &cntRemaining);
1432 }
1433 }
1434
1435 // Store the merged kernel flags and boot args.
1436
1437 cnt = strlen(configKernelFlags);
1438 if (cnt) {
1439 if (cnt > cntRemaining) {
1440 error("Warning: boot arguments too long, truncating\n");
1441 cnt = cntRemaining;
1442 }
1443 strncpy(argP, configKernelFlags, cnt);
1444 argP[cnt++] = ' ';
1445 cntRemaining -= cnt;
1446 }
1447 userCnt = strlen(cp);
1448 if (userCnt > cntRemaining) {
1449 error("Warning: boot arguments too long, truncating\n");
1450 userCnt = cntRemaining;
1451 }
1452 strncpy(&argP[cnt], cp, userCnt);
1453 argP[cnt+userCnt] = '\0';
1454
1455 if(!shouldboot)
1456 {
1457 gVerboseMode = getValueForKey( kVerboseModeFlag, &val, &cnt, &bootInfo->bootConfig ) ||
1458 getValueForKey( kSingleUserModeFlag, &val, &cnt, &bootInfo->bootConfig );
1459
1460 gBootMode = ( getValueForKey( kSafeModeFlag, &val, &cnt, &bootInfo->bootConfig ) ) ?
1461 kBootModeSafe : kBootModeNormal;
1462
1463 if ( getValueForKey( kOldSafeModeFlag, &val, &cnt, &bootInfo->bootConfig ) ) {
1464 gBootMode = kBootModeSafe;
1465 }
1466
1467 if ( getValueForKey( kMKextCacheKey, &val, &cnt, &bootInfo->bootConfig ) ) {
1468 strlcpy(gMKextName, val, cnt + 1);
1469 }
1470
1471 }
1472
1473 free(configKernelFlags);
1474 free(valueBuffer);
1475
1476 return 0;
1477}
1478
1479
1480//==========================================================================
1481// Load the help file and display the file contents on the screen.
1482
1483static void showTextBuffer(char *buf, int size)
1484{
1485char*bp;
1486intline;
1487intline_offset;
1488intc;
1489
1490if (bootArgs->Video.v_display == GRAPHICS_MODE) {
1491showInfoBox( "Press q to quit\n",buf );
1492return;
1493}
1494
1495 bp = buf;
1496 while (size-- > 0) {
1497if (*bp == '\n') {
1498*bp = '\0';
1499}
1500bp++;
1501 }
1502 *bp = '\1';
1503 line_offset = 0;
1504
1505 setActiveDisplayPage(1);
1506
1507 while (1) {
1508clearScreenRows(0, 24);
1509setCursorPosition(0, 0, 1);
1510bp = buf;
1511for (line = 0; *bp != '\1' && line < line_offset; line++) {
1512while (*bp != '\0') {
1513bp++;
1514}
1515bp++;
1516}
1517for (line = 0; *bp != '\1' && line < 23; line++) {
1518setCursorPosition(0, line, 1);
1519printf("%s\n", bp);
1520while (*bp != '\0') {
1521bp++;
1522}
1523bp++;
1524}
1525
1526setCursorPosition(0, 23, 1);
1527if (*bp == '\1') {
1528printf("[Type %sq or space to quit viewer]", (line_offset > 0) ? "p for previous page, " : "");
1529} else {
1530printf("[Type %s%sq to quit viewer]", (line_offset > 0) ? "p for previous page, " : "", (*bp != '\1') ? "space for next page, " : "");
1531}
1532
1533c = getc();
1534if (c == 'q' || c == 'Q') {
1535break;
1536}
1537if ((c == 'p' || c == 'P') && line_offset > 0) {
1538line_offset -= 23;
1539}
1540if (c == ' ') {
1541if (*bp == '\1') {
1542break;
1543} else {
1544line_offset += 23;
1545}
1546}
1547 }
1548 setActiveDisplayPage(0);
1549}
1550
1551void showHelp(void)
1552{
1553if (bootArgs->Video.v_display == GRAPHICS_MODE) {
1554showInfoBox("Help. Press q to quit.\n", (char *)BootHelp_txt);
1555} else {
1556showTextBuffer((char *)BootHelp_txt, BootHelp_txt_len);
1557}
1558}
1559
1560void showTextFile(const char * filename) //Azi: ?more - check this...
1561{
1562#define MAX_TEXT_FILE_SIZE 65536
1563char*buf;
1564intfd;
1565intsize;
1566
1567if ((fd = open_bvdev("bt(0,0)", filename, 0)) < 0) {
1568printf("\nFile not found: %s\n", filename);
1569sleep(2);
1570return;
1571}
1572
1573 size = file_size(fd);
1574 if (size > MAX_TEXT_FILE_SIZE) {
1575size = MAX_TEXT_FILE_SIZE;
1576}
1577 buf = malloc(size);
1578 read(fd, buf, size);
1579 close(fd);
1580showTextBuffer(buf, size);
1581free(buf);
1582}
1583
1584// This is a very simplistic prompting scheme that just grabs two hex characters
1585// Eventually we need to do something more user-friendly like display a menu
1586// based off of the Multiboot device list
1587
1588int selectAlternateBootDevice(int bootdevice)
1589{
1590int key;
1591int newbootdevice;
1592int digitsI = 0;
1593char *end;
1594char digits[3] = {0,0,0};
1595
1596// We've already printed the current boot device so user knows what it is
1597printf("Typical boot devices are 80 (First HD), 81 (Second HD)\n");
1598printf("Enter two-digit hexadecimal boot device [%02x]: ", bootdevice);
1599do {
1600key = getc();
1601switch (key & kASCIIKeyMask) {
1602case kBackspaceKey:
1603if (digitsI > 0) {
1604int x, y, t;
1605getCursorPositionAndType(&x, &y, &t);
1606// Assume x is not 0;
1607x--;
1608setCursorPosition(x,y,0); // back up one char
1609// Overwrite with space without moving cursor position
1610putca(' ', 0x07, 1);
1611digitsI--;
1612} else {
1613// TODO: Beep or something
1614}
1615break;
1616
1617case kReturnKey:
1618digits[digitsI] = '\0';
1619newbootdevice = strtol(digits, &end, 16);
1620if (end == digits && *end == '\0') {
1621// User entered empty string
1622printf("\nUsing default boot device %x\n", bootdevice);
1623key = 0;
1624} else if(end != digits && *end == '\0') {
1625bootdevice = newbootdevice;
1626printf("\n");
1627key = 0; // We gots da boot device
1628} else {
1629printf("\nCouldn't parse. try again: ");
1630digitsI = 0;
1631}
1632break;
1633
1634default:
1635if (isxdigit(key & kASCIIKeyMask) && digitsI < 2) {
1636putc(key & kASCIIKeyMask);
1637digits[digitsI++] = key & kASCIIKeyMask;
1638} else {
1639// TODO: Beep or something
1640}
1641break;
1642};
1643} while (key != 0);
1644
1645return bootdevice;
1646}
1647
1648bool promptForRescanOption(void)
1649{
1650printf("\nWould you like to enable media rescan option?\nPress ENTER to enable or any key to skip.\n");
1651if (getc() == kReturnKey) {
1652return true;
1653} else {
1654return false;
1655}
1656}
1657

Archive Download this file

Revision: 296