]>
git.saurik.com Git - apple/boot.git/blob - i386/boot2/options.c
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Portions Copyright (c) 1999 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 1.1 (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
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
22 * @APPLE_LICENSE_HEADER_END@
41 static BVRef gBootVolume
= 0;
43 static void showHelp();
45 //==========================================================================
48 kCursorTypeHidden
= 0x0100,
49 kCursorTypeUnderline
= 0x0607
58 static void changeCursor( int col
, int row
, int type
, CursorState
* cs
)
60 if (cs
) getCursorPositionAndType( &cs
->x
, &cs
->y
, &cs
->type
);
61 setCursorType( type
);
62 setCursorPosition( col
, row
, 0 );
65 static void moveCursor( int col
, int row
)
67 setCursorPosition( col
, row
, 0 );
70 static void restoreCursor( const CursorState
* cs
)
72 setCursorPosition( cs
->x
, cs
->y
, 0 );
73 setCursorType( cs
->type
);
76 //==========================================================================
78 static void flushKeyboardBuffer()
80 while ( readKeyboardStatus() ) getc();
83 //==========================================================================
85 static int countdown( const char * msg
, int row
, int timeout
)
89 int col
= strlen(msg
) + 1;
91 flushKeyboardBuffer();
96 for ( time
= time18(), timeout
++; timeout
; )
98 if (ch
= readKeyboardStatus())
101 if ( time18() >= time
)
105 moveCursor( col
, row
);
106 printf("(%d) ", timeout
);
110 flushKeyboardBuffer();
115 //==========================================================================
117 static char gBootArgs
[BOOT_STRING_LEN
];
118 static char * gBootArgsPtr
= gBootArgs
;
119 static char * gBootArgsEnd
= gBootArgs
+ BOOT_STRING_LEN
- 1;
121 static void clearBootArgs()
123 gBootArgsPtr
= gBootArgs
;
124 memset( gBootArgs
, '\0', BOOT_STRING_LEN
);
127 //==========================================================================
129 static void showBootPrompt( int row
, BOOL visible
)
131 extern char bootPrompt
[];
133 changeCursor( 0, row
, kCursorTypeUnderline
, 0 );
134 clearScreenRows( row
, kScreenLastRow
);
139 printf( bootPrompt
);
143 printf("Press Return to start up the foreign OS. ");
147 //==========================================================================
149 static void updateBootArgs( int key
)
151 key
&= kASCIIKeyMask
;
156 if ( gBootArgsPtr
> gBootArgs
)
159 getCursorPositionAndType( &x
, &y
, &t
);
165 setCursorPosition( x
, y
, 0 );
167 *gBootArgsPtr
-- = '\0';
172 if ( key
>= ' ' && gBootArgsPtr
< gBootArgsEnd
)
174 putchar(key
); // echo to screen
175 *gBootArgsPtr
++ = key
;
181 //==========================================================================
188 static const MenuItem
* gMenuItems
= NULL
;
189 static int gMenuItemCount
;
191 static int gMenuHeight
;
193 static int gMenuBottom
;
194 static int gMenuSelection
;
196 static void printMenuItem( const MenuItem
* item
, int highlight
)
201 putca(' ', 0x70, strlen(item
->name
) + 4);
203 putca(' ', 0x07, 40);
205 printf(" %40s\n", item
->name
);
208 //==========================================================================
210 static void showMenu( const MenuItem
* items
, int count
,
211 int selection
, int row
, int height
)
214 CursorState cursorState
;
216 if ( items
== NULL
|| count
== 0 ) return;
218 // head and tail points to the start and the end of the list.
219 // top and bottom points to the first and last visible items
220 // in the menu window.
224 gMenuHeight
= height
;
225 gMenuItemCount
= count
;
227 gMenuBottom
= min( count
, height
) - 1;
228 gMenuSelection
= selection
;
230 // If the selected item is not visible, shift the list down.
232 if ( gMenuSelection
> gMenuBottom
)
234 gMenuTop
+= ( gMenuSelection
- gMenuBottom
);
235 gMenuBottom
= gMenuSelection
;
238 // Draw the visible items.
240 changeCursor( 0, row
, kCursorTypeHidden
, &cursorState
);
242 for ( i
= gMenuTop
; i
<= gMenuBottom
; i
++ )
244 printMenuItem( &items
[i
], (i
== gMenuSelection
) );
247 restoreCursor( &cursorState
);
250 //==========================================================================
252 static int updateMenu( int key
, void ** paramPtr
)
267 if ( NULL
== gMenuItems
) return 0;
269 // Look at the scan code.
273 case 0x4800: // Up Arrow
274 if ( gMenuSelection
!= gMenuTop
)
275 draw
.f
.selectionUp
= 1;
276 else if ( gMenuTop
> 0 )
277 draw
.f
.scrollDown
= 1;
280 case 0x5000: // Down Arrow
281 if ( gMenuSelection
!= gMenuBottom
)
282 draw
.f
.selectionDown
= 1;
283 else if ( gMenuBottom
< (gMenuItemCount
- 1) )
290 if ( draw
.f
.scrollUp
)
292 scollPage(0, gMenuRow
, 40, gMenuRow
+ gMenuHeight
- 1, 0x07, 1, 1);
293 gMenuTop
++; gMenuBottom
++;
294 draw
.f
.selectionDown
= 1;
297 if ( draw
.f
.scrollDown
)
299 scollPage(0, gMenuRow
, 40, gMenuRow
+ gMenuHeight
- 1, 0x07, 1, -1);
300 gMenuTop
--; gMenuBottom
--;
301 draw
.f
.selectionUp
= 1;
304 if ( draw
.f
.selectionUp
|| draw
.f
.selectionDown
)
306 CursorState cursorState
;
308 // Set cursor at current position, and clear inverse video.
310 changeCursor( 0, gMenuRow
+ gMenuSelection
- gMenuTop
,
311 kCursorTypeHidden
, &cursorState
);
313 printMenuItem( &gMenuItems
[gMenuSelection
], 0 );
315 if ( draw
.f
.selectionUp
) gMenuSelection
--;
316 else gMenuSelection
++;
318 moveCursor( 0, gMenuRow
+ gMenuSelection
- gMenuTop
);
320 printMenuItem( &gMenuItems
[gMenuSelection
], 1 );
322 restoreCursor( &cursorState
);
325 *paramPtr
= gMenuItems
[gMenuSelection
].param
;
332 //==========================================================================
334 static void skipblanks( const char ** cpp
)
336 while ( **(cpp
) == ' ' || **(cpp
) == '\t' ) ++(*cpp
);
339 //==========================================================================
341 static const char * extractKernelName( char ** cpp
)
347 // Convert char to lower case.
351 // Must start with a letter or a '/'.
353 if ( (c
< 'a' || c
> 'z') && ( c
!= '/' ) )
356 // Keep consuming characters until we hit a separator.
358 while ( *cp
&& (*cp
!= '=') && (*cp
!= ' ') && (*cp
!= '\t') )
361 // Only SPACE or TAB separator is accepted.
362 // Reject everything else.
367 // Overwrite the separator, and move the pointer past
370 if (*cp
!= '\0') *cp
++ = '\0';
376 //==========================================================================
378 void getBootOptions()
388 BOOL showPrompt
, newShowPrompt
;
389 MenuItem
* menuItems
= NULL
;
390 static BOOL firstRun
= YES
;
393 clearScreenRows( kMenuTopRow
, kScreenLastRow
);
394 changeCursor( 0, kMenuTopRow
, kCursorTypeUnderline
, 0 );
395 printf("Scanning device %x...", gBIOSDev
);
397 // Get a list of bootable volumes on the device.
399 bvChain
= scanBootVolumes( gBIOSDev
, &bvCount
);
400 gBootVolume
= menuBVR
= selectBootVolume( bvChain
);
403 // When booting from CD (via HD emulation), default to hard
404 // drive boot when possible.
406 if ( gBootVolume
->part_type
== FDISK_BOOTER
&&
407 gBootVolume
->biosdev
== 0x80 )
409 // Scan the original device 0x80 that has been displaced
412 BVRef hd_bvr
= selectBootVolume(scanBootVolumes(0x81, 0));
413 if ( hd_bvr
->flags
& kBVFlagNativeBoot
)
415 int key
= countdown("Press C to start up from CD-ROM.",
418 if ( (key
& 0x5f) != 'c' )
420 gBootVolume
= hd_bvr
;
421 gBIOSDev
= hd_bvr
->biosdev
;
422 initKernBootStruct( gBIOSDev
);
429 // Allow user to override default setting.
432 countdown("Press any key to enter startup options.",
433 kMenuTopRow
, 3) == 0 )
440 // Allocate memory for an array of menu items.
442 menuItems
= (MenuItem
*) malloc( sizeof(MenuItem
) * bvCount
);
443 if ( menuItems
== NULL
) goto done
;
445 // Associate a menu item for each BVRef.
447 for ( bvr
= bvChain
, i
= bvCount
- 1, selectIndex
= 0;
448 bvr
; bvr
= bvr
->next
, i
-- )
450 getBootVolumeDescription( bvr
, menuItems
[i
].name
, 80 );
451 menuItems
[i
].param
= (void *) bvr
;
452 if ( bvr
== menuBVR
) selectIndex
= i
;
456 // Clear screen and hide the blinking cursor.
458 clearScreenRows( kMenuTopRow
, kMenuTopRow
+ 2 );
459 changeCursor( 0, kMenuTopRow
, kCursorTypeHidden
, 0 );
460 nextRow
= kMenuTopRow
;
467 printf("Use \30\31 keys to select the startup volume.");
468 showMenu( menuItems
, bvCount
, selectIndex
, kMenuTopRow
+ 2, kMenuMaxItems
);
469 nextRow
+= min( bvCount
, kMenuMaxItems
) + 3;
472 // Show the boot prompt.
474 showPrompt
= (bvCount
== 0) || (menuBVR
->flags
& kBVFlagNativeBoot
);
475 showBootPrompt( nextRow
, showPrompt
);
480 updateMenu( key
, (void **) &menuBVR
);
482 newShowPrompt
= (bvCount
== 0) ||
483 (menuBVR
->flags
& kBVFlagNativeBoot
);
485 if ( newShowPrompt
!= showPrompt
)
487 showPrompt
= newShowPrompt
;
488 showBootPrompt( nextRow
, showPrompt
);
490 if ( showPrompt
) updateBootArgs( key
);
492 switch ( key
& kASCIIKeyMask
)
495 if ( *gBootArgs
== '?' )
498 showBootPrompt( nextRow
, showPrompt
);
501 gBootVolume
= menuBVR
;
517 clearScreenRows( kMenuTopRow
, kScreenLastRow
);
518 changeCursor( 0, kMenuTopRow
, kCursorTypeUnderline
, 0 );
520 if ( menuItems
) free(menuItems
);
523 //==========================================================================
525 extern unsigned char chainbootdev
;
526 extern unsigned char chainbootflag
;
528 int processBootOptions()
530 KERNBOOTSTRUCT
* kbp
= kernBootStruct
;
531 const char * cp
= gBootArgs
;
532 const char * val
= 0;
538 // Update the unit and partition number.
542 if ( gBootVolume
->flags
& kBVFlagForeignBoot
)
544 readBootSector( gBootVolume
->biosdev
, gBootVolume
->part_boff
,
548 // Setup edx, and signal intention to chain load the
552 chainbootdev
= gBootVolume
->biosdev
;
558 kbp
->kernDev
&= ~((B_UNITMASK
<< B_UNITSHIFT
) |
559 (B_PARTITIONMASK
<< B_PARTITIONSHIFT
));
561 kbp
->kernDev
|= MAKEKERNDEV( 0,
562 /* unit */ BIOS_DEV_UNIT(gBootVolume
->biosdev
),
563 /* partition */ gBootVolume
->part_no
);
566 // Load config table specified by the user, or use the default.
568 getValueForBootKey( cp
, "config", &val
, &cnt
);
569 loadSystemConfig(val
, cnt
);
570 if ( !sysConfigValid
) return -1;
572 // Use the kernel name specified by the user, or fetch the name
573 // in the config table.
575 if (( kernel
= extractKernelName((char **)&cp
) ))
577 strcpy( kbp
->bootFile
, kernel
);
581 if ( getValueForKey( kKernelNameKey
, &val
, &cnt
) )
582 strncpy( kbp
->bootFile
, val
, cnt
);
585 // Store the merged kernel flags and boot args.
587 getValueForKey( kKernelFlagsKey
, &val
, &cnt
);
588 if ( (strlen(cp
) + 1 + cnt
) < BOOT_STRING_LEN
)
590 if (cnt
) strncpy(kbp
->bootString
, val
, cnt
);
591 sprintf(&kbp
->bootString
[cnt
], "%s%s", cnt
? " " : "", cp
);
594 gVerboseMode
= getValueForKey( "-v", &val
, &cnt
) ||
595 getValueForKey( "-s", &val
, &cnt
);
597 gBootGraphics
= getBoolForKey( kBootGraphicsKey
);
599 gBootMode
= ( getValueForKey( "-f", &val
, &cnt
) ) ?
600 kBootModeSafe
: kBootModeNormal
;
605 //==========================================================================
606 // Load the help file and display the file contents on the screen.
608 static void showHelp()
610 #define BOOT_HELP_PATH "/usr/standalone/i386/BootHelp.txt"
614 if ( (fd
= open(BOOT_HELP_PATH
, 0)) >= 0 )
618 // Activate and clear page 1
619 // Perhaps this should be loaded only once?
621 setActiveDisplayPage(1);
622 clearScreenRows(0, 24);
623 setCursorPosition( 0, 0, 1 );
625 buffer
= malloc( file_size(fd
) );
626 read(fd
, buffer
, file_size(fd
) - 1);
628 printf("%s", buffer
);
631 // Wait for a keystroke and return to page 0.
634 setActiveDisplayPage(0);