Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1201 lines
24 KiB

/*++
Copyright (c) 1991 Microsoft Corporation
Module Name:
jzboot.c
Abstract:
This module contains the code to manage the boot selections.
Author:
David M. Robinson (davidro) 25-Oct-1991
Revision History:
--*/
#include "jzsetup.h"
//
// Routine prototypes.
//
ARC_STATUS
JzPickSystemPartition (
OUT PCHAR SystemPartition,
IN OUT PULONG CurrentLine
);
ARC_STATUS
JzPickOsPartition (
OUT PCHAR OsPartition,
IN OUT PULONG CurrentLine
);
ULONG
JzGetYesNo (
IN PULONG CurrentLine,
IN PCHAR PromptString,
IN BOOLEAN YesIsDefault
)
/*++
Routine Description:
Arguments:
None.
Return Value:
None.
--*/
{
ULONG Line;
ULONG ReturnValue;
Line = *CurrentLine;
*CurrentLine += NUMBER_OF_YES_NO + 2;
JzSetPosition( Line, 0);
JzPrint(PromptString);
ReturnValue = JxDisplayMenu( YesNoChoices,
NUMBER_OF_YES_NO,
YesIsDefault ? 0 : 1,
Line + 1);
JzSetPosition( *CurrentLine, 0);
return ReturnValue;
}
ULONG
JzGetCountdownValue (
IN PULONG CurrentLine
)
/*++
Routine Description:
Arguments:
None.
Return Value:
None.
--*/
{
ULONG Line;
ULONG ReturnValue;
CHAR TempString[5];
GETSTRING_ACTION Action;
Line = *CurrentLine;
*CurrentLine += 1;
JzSetPosition( Line, 0);
JzPrint(JZ_COUNTDOWN_MSG);
JzPrint("\x9bK");
do {
Action = FwGetString( TempString,
sizeof(TempString),
"5",
Line,
strlen(JZ_COUNTDOWN_MSG));
if (Action == GetStringEscape) {
return(-1);
}
} while ( Action != GetStringSuccess );
ReturnValue = atoi(TempString);
JzSetPosition( *CurrentLine, 0);
return ReturnValue;
}
VOID
JzDeleteVariableSegment (
PCHAR VariableName,
ULONG Selection
)
/*++
Routine Description:
Arguments:
None.
Return Value:
None.
--*/
{
PCHAR Variable;
CHAR VariableValue[MAXIMUM_ENVIRONMENT_VALUE];
ULONG Index;
ULONG Count;
BOOLEAN FirstSegment;
if ((Variable = ArcGetEnvironmentVariable(VariableName)) == NULL) {
return;
}
FirstSegment = TRUE;
Index = 0;
*VariableValue = 0;
while (strchr(Variable,';') != NULL) {
Count = strchr(Variable,';') - Variable;
if (Index != Selection) {
if (!FirstSegment) {
strcat(VariableValue,";");
}
strncat(VariableValue, Variable, Count);
FirstSegment = FALSE;
}
Variable += Count + 1;
Index++;
}
if (Index != Selection) {
if (!FirstSegment) {
strcat(VariableValue,";");
}
strcat(VariableValue,Variable);
}
ArcSetEnvironmentVariable(VariableName, VariableValue);
return;
}
VOID
JzAddBootSelection (
VOID
)
/*++
Routine Description:
Arguments:
None.
Return Value:
None.
--*/
{
ARC_STATUS Status;
CHAR SystemPartition[128];
CHAR OsloaderFilename[80];
CHAR OsPartition[128];
CHAR OsFilename[80];
CHAR LoadIdentifier[80];
PCHAR Variable;
PCHAR TempPointer;
CHAR VariableValue[256];
ULONG Index;
UCHAR Character;
ULONG Count;
ULONG CurrentLine;
LONG YesNo;
BOOLEAN DebugOn;
GETSTRING_ACTION Action;
BOOLEAN SecondaryBoot;
JzClearScreen();
JzShowTime(TRUE);
CurrentLine = 2;
JzSetPosition( CurrentLine, 0);
//
// Count the boot selections
//
strcpy(OsPartition, BootString[OsLoadPartitionVariable]);
strcpy(OsFilename, BootString[OsLoadFilenameVariable]);
for ( Index = 0 ; Index < 4 ; Index++ ) {
SecondaryBoot = FwGetVariableSegment(Index, OsPartition);
SecondaryBoot = FwGetVariableSegment(Index, OsFilename) ||
SecondaryBoot;
if (!SecondaryBoot) {
break;
}
}
//
// Increment to new boot selection. Print warning and return if too many.
//
Index++;
// if (Index == 5) {
// JzPrint(" Too many boot selections, delete some before adding another,\r\n");
// Index = 0;
// goto MakeError;
// }
//
// Pick a system partition.
//
if (JzPickSystemPartition(SystemPartition, &CurrentLine) != ESUCCESS) {
return;
}
JzPrint(JZ_OSLOADER_MSG);
do {
Action = FwGetString( OsloaderFilename,
sizeof(OsloaderFilename),
"\\os\\nt\\osloader.exe",
CurrentLine,
strlen(JZ_OSLOADER_MSG));
if (Action == GetStringEscape) {
return;
}
} while ( Action != GetStringSuccess );
CurrentLine += 1;
JzSetPosition( CurrentLine, 0);
YesNo = JzGetYesNo(&CurrentLine, JZ_OS_MSG, TRUE);
if (YesNo == -1) {
return;
}
if (YesNo == 0) {
strcpy(OsPartition, SystemPartition);
} else {
//
// Determine os partition.
//
if (JzPickOsPartition(OsPartition, &CurrentLine) != ESUCCESS) {
return;
}
}
JzPrint(JZ_OS_ROOT_MSG);
do {
Action = FwGetString( OsFilename,
sizeof(OsFilename),
"\\winnt",
CurrentLine,
strlen(JZ_OS_ROOT_MSG));
if (Action == GetStringEscape) {
return;
}
} while ( Action != GetStringSuccess );
CurrentLine += 1;
JzSetPosition( CurrentLine, 0);
JzPrint(JZ_BOOT_NAME_MSG);
do {
Action = FwGetString( LoadIdentifier,
sizeof(LoadIdentifier),
"Windows NT ",
CurrentLine,
strlen(JZ_BOOT_NAME_MSG));
if (Action == GetStringEscape) {
return;
}
} while ( Action != GetStringSuccess );
CurrentLine += 1;
JzSetPosition( CurrentLine, 0);
YesNo = JzGetYesNo(&CurrentLine,JZ_INIT_DEBUG_MSG , FALSE);
if (YesNo == -1) {
return;
}
if (YesNo == 0) {
DebugOn = TRUE;
} else {
DebugOn = FALSE;
}
Index = 0;
Status = FwSetVariableSegment(0, BootString[LoadIdentifierVariable], LoadIdentifier);
if (Status != ESUCCESS) {
goto MakeError;
}
Index = 1;
//
// If the SystemPartition variable is set but the Osloader variable is null,
// clear the SystemPartition variable before adding it back.
//
if ((ArcGetEnvironmentVariable(BootString[SystemPartitionVariable]) != NULL) &&
(ArcGetEnvironmentVariable(BootString[OsLoaderVariable]) == NULL)) {
ArcSetEnvironmentVariable(BootString[SystemPartitionVariable],"");
}
Status = FwSetVariableSegment(0, BootString[SystemPartitionVariable], SystemPartition);
if (Status != ESUCCESS) {
goto MakeError;
}
//
// Add a new selection to the OSLOADER environment variable.
//
Index = 2;
strcpy(VariableValue, SystemPartition);
strcat(VariableValue, OsloaderFilename);
Status = FwSetVariableSegment(0, BootString[OsLoaderVariable], VariableValue);
if (Status != ESUCCESS) {
goto MakeError;
}
//
// Add a new selection to the OSLOADPARTITION environment variable.
//
Index = 3;
Status = FwSetVariableSegment(0, BootString[OsLoadPartitionVariable], OsPartition);
if (Status != ESUCCESS) {
goto MakeError;
}
//
// Add a new selection to the OSLOADFILENAME environment variable.
//
Index = 4;
Status = FwSetVariableSegment(0, BootString[OsLoadFilenameVariable], OsFilename);
if (Status != ESUCCESS) {
goto MakeError;
}
//
// Add a new selection to the OSLOADOPTIONS environment variable.
//
if (DebugOn) {
strcpy(VariableValue, "debug");
} else {
strcpy(VariableValue, "nodebug");
}
Index = 5;
Status = FwSetVariableSegment(0, BootString[OsLoadOptionsVariable], VariableValue);
if (Status != ESUCCESS) {
goto MakeError;
}
return;
MakeError:
JzPrint(JZ_CANT_SET_VARIABLE_MSG);
//
// Delete any segments that were added.
//
for ( Count = 0 ; Count < Index ; Count++ ) {
JzDeleteVariableSegment(BootString[Count], 0);
}
FwWaitForKeypress();
}
LONG
JzPickBootSelection (
IN OUT PULONG CurrentLine,
IN PCHAR PromptString
)
/*++
Routine Description:
This routine allows the user to indicate a boot selection choice.
Arguments:
CurrentLine - Supplies a pointer to the current display line value.
PromptString - Supplies a pointer to a string which indicates the reason
the boot selection choice is needed.
Return Value:
Returns the boot selection number, -1 if none.
--*/
{
PCHAR Variable;
CHAR VariableValue[MAXIMUM_ENVIRONMENT_VALUE];
CHAR BootChoices[5][128];
PCHAR BootMenu[5];
CHAR OsloadPartition[128];
CHAR OsloadFilename[128];
CHAR LoadIdentifier[80];
BOOLEAN SecondaryBoot;
ULONG Index;
ULONG Selection;
//
// Get each boot selection
//
strcpy(OsloadPartition, BootString[OsLoadPartitionVariable]);
strcpy(OsloadFilename, BootString[OsLoadFilenameVariable]);
strcpy(LoadIdentifier, BootString[LoadIdentifierVariable]);
for ( Index = 0 ; ; Index++ ) {
SecondaryBoot = FwGetVariableSegment(Index, OsloadPartition);
SecondaryBoot = FwGetVariableSegment(Index, OsloadFilename) ||
SecondaryBoot;
SecondaryBoot = FwGetVariableSegment(Index, LoadIdentifier) ||
SecondaryBoot;
if (LoadIdentifier[sizeof("LOADIDENTIFIER=") - 1] != 0) {
strcpy(BootChoices[Index],
&LoadIdentifier[sizeof("LOADIDENTIFIER=") - 1]);
} else {
strcpy(BootChoices[Index],
&OsloadPartition[sizeof("OsloadPartition=") - 1]);
strcat(BootChoices[Index],
&OsloadFilename[sizeof("OsloadFilename=") - 1]);
}
BootMenu[Index] = BootChoices[Index];
if (!SecondaryBoot || (Index == 4)) {
break;
}
}
JzPrint(PromptString);
*CurrentLine += 1;
Selection = JxDisplayMenu( BootMenu,
Index + 1,
0,
*CurrentLine);
JzSetPosition(*CurrentLine, 0);
return(Selection);
}
VOID
JzDeleteBootSelection (
VOID
)
/*++
Routine Description:
This routine deletes a boot selection from the boot environment variables.
Arguments:
None.
Return Value:
None.
--*/
{
ARC_STATUS Status;
ULONG CurrentLine;
LONG Selection;
ULONG Index;
JzClearScreen();
JzShowTime(TRUE);
CurrentLine = 2;
JzSetPosition( CurrentLine, 0);
if (ArcGetEnvironmentVariable(BootString[OsLoadPartitionVariable]) == NULL) {
JzPrint(JZ_NO_SELECTIONS_TO_DELETE_MSG);
CurrentLine += 1;
FwWaitForKeypress();
return;
}
Selection = JzPickBootSelection( &CurrentLine, JZ_SELECTION_TO_DELETE_MSG);
if (Selection == -1) {
return;
}
for ( Index = 0 ; Index < MaximumBootVariable ; Index++ ) {
JzDeleteVariableSegment(BootString[Index],Selection);
}
JzPrint(JZ_CRLF_MSG);
return;
}
VOID
JzEditSelection (
LONG Selection
)
/*++
Routine Description:
This routine allows the environment variables for a specified boot
selection to be edited.
Arguments:
Selection - Specifies the boot selection to edit.
Return Value:
None.
--*/
{
ARC_STATUS Status;
CHAR SystemPartition[128];
CHAR Osloader[128];
CHAR OsloadPartition[128];
CHAR OsloadFilename[128];
CHAR OsloadOptions[128];
CHAR LoadIdentifier[128];
do {
JzClearScreen();
JzShowTime(TRUE);
JzSetPosition( 7, 0);
//
// Display the current boot selection environment variables.
//
strcpy(SystemPartition, BootString[SystemPartitionVariable]);
strcpy(Osloader, BootString[OsLoaderVariable]);
strcpy(OsloadPartition, BootString[OsLoadPartitionVariable]);
strcpy(OsloadFilename, BootString[OsLoadFilenameVariable]);
strcpy(OsloadOptions, BootString[OsLoadOptionsVariable]);
strcpy(LoadIdentifier, BootString[LoadIdentifierVariable]);
FwGetVariableSegment(Selection, SystemPartition);
FwGetVariableSegment(Selection, Osloader);
FwGetVariableSegment(Selection, OsloadPartition);
FwGetVariableSegment(Selection, OsloadFilename);
FwGetVariableSegment(Selection, OsloadOptions);
FwGetVariableSegment(Selection, LoadIdentifier);
JzPrint( JZ_ENVIR_FOR_BOOT_MSG,
Selection + 1);
JzPrint(JZ_FORMAT1_MSG, LoadIdentifier);
JzPrint(JZ_FORMAT1_MSG, SystemPartition);
JzPrint(JZ_FORMAT1_MSG, Osloader);
JzPrint(JZ_FORMAT1_MSG, OsloadPartition);
JzPrint(JZ_FORMAT1_MSG, OsloadFilename);
JzPrint(JZ_FORMAT1_MSG, OsloadOptions);
JzSetPosition( 2, 0);
JzPrint(JZ_USE_ARROWS_MSG);
} while ( JzSetBootEnvironmentVariable(Selection) );
return;
}
VOID
JzEditBootSelection (
VOID
)
/*++
Routine Description:
This routine allows the environment variables for a boot selection to
be edited.
Arguments:
None.
Return Value:
None.
--*/
{
ARC_STATUS Status;
ULONG CurrentLine;
LONG Selection;
JzClearScreen();
JzShowTime(TRUE);
CurrentLine = 2;
JzSetPosition( CurrentLine, 0);
if (ArcGetEnvironmentVariable(BootString[OsLoadPartitionVariable]) == NULL) {
JzPrint(JZ_NO_SELECTIONS_TO_EDIT_MSG);
CurrentLine += 1;
FwWaitForKeypress();
return;
}
Selection = JzPickBootSelection( &CurrentLine, JZ_SELECTION_TO_EDIT_MSG);
if (Selection == -1) {
return;
}
JzEditSelection(Selection);
return;
}
VOID
JzRearrangeBootSelections (
VOID
)
/*++
Routine Description:
This routine allows the environment variables for a boot selection to
be rearranged.
Arguments:
None.
Return Value:
None.
--*/
{
ARC_STATUS Status;
ULONG CurrentLine;
LONG Selection;
ULONG Index;
CHAR Segment[128];
JzClearScreen();
JzShowTime(TRUE);
CurrentLine = 2;
JzSetPosition( CurrentLine, 0);
if (ArcGetEnvironmentVariable(BootString[OsLoadPartitionVariable]) == NULL) {
JzPrint(JZ_NO_SELECTIONS_TO_REARRANGE_MSG);
CurrentLine += 1;
FwWaitForKeypress();
return;
}
do {
JzClearScreen();
JzShowTime(TRUE);
CurrentLine = 2;
JzSetPosition( CurrentLine, 0);
Selection = JzPickBootSelection( &CurrentLine, JZ_PICK_SELECTION_MSG);
if (Selection == -1) {
continue;
}
for ( Index = 0 ; Index < MaximumBootVariable ; Index++ ) {
strcpy( Segment, BootString[Index]);
FwGetVariableSegment( Selection, Segment );
JzDeleteVariableSegment( BootString[Index], Selection );
FwSetVariableSegment( 0, BootString[Index], strchr(Segment, '=') + 1);
}
} while ( Selection != -1 );
return;
}
VOID
JzSetupAutoboot (
VOID
)
/*++
Routine Description:
This routine allows the environment variables controlling autoboot
to be set.
Arguments:
None.
Return Value:
None.
--*/
{
ARC_STATUS Status;
ULONG Autoboot;
ULONG Countdown;
CHAR CountdownString[5];
ULONG CurrentLine;
JzClearScreen();
JzShowTime(TRUE);
CurrentLine = 2;
Autoboot = JzGetYesNo(&CurrentLine, JZ_SHOULD_AUTOBOOT_MSG, FALSE);
if (Autoboot == -1) {
return;
}
switch (Autoboot) {
case 0:
Status = ArcSetEnvironmentVariable("AUTOLOAD",
"YES");
break;
default:
Status = ArcSetEnvironmentVariable("AUTOLOAD",
"NO");
break;
}
if (Status != ESUCCESS) {
JzPrint(JZ_CANT_SET_VARIABLE_MSG);
return;
}
if (Autoboot != 0) {
return;
}
Countdown = JzGetCountdownValue(&CurrentLine);
if (Countdown == -1) {
return;
}
if (Countdown != 5) {
sprintf( CountdownString,
"%d",
Countdown);
Status = ArcSetEnvironmentVariable("COUNTDOWN",
CountdownString);
if (Status != ESUCCESS) {
JzPrint(JZ_CANT_SET_VARIABLE_MSG);
return;
}
} else {
ArcSetEnvironmentVariable("COUNTDOWN",
"");
}
return;
}
VOID
JzEditVariable (
VOID
)
/*++
Routine Description:
This routine allows environment variables to be edited.
Arguments:
None.
Return Value:
None.
--*/
{
ARC_STATUS Status;
ULONG CurrentLine;
PCHAR Variable;
ULONG Index, Count;
do {
JzClearScreen();
JzShowTime(TRUE);
JzSetPosition( 7, 0);
//
// Get the entire environment.
//
Variable = FwEnvironmentLoad();
JzPrint(JZ_ENVIRONMENT_VARS_MSG);
if (Variable != NULL) {
//
// Print all of the other environment variables.
//
while (*Variable) {
if ((strstr(Variable, "SYSTEMPARTITION=") == NULL) &&
(strstr(Variable, "OSLOADER=") == NULL) &&
(strstr(Variable, "OSLOADPARTITION=") == NULL) &&
(strstr(Variable, "OSLOADFILENAME=") == NULL) &&
(strstr(Variable, "OSLOADOPTIONS=") == NULL) &&
(strstr(Variable, "LOADIDENTIFIER=") == NULL)) {
JzPrint(" ");
while (strchr(Variable,';') != NULL) {
Index = strchr(Variable,';') - Variable + 1;
ArcWrite(ARC_CONSOLE_OUTPUT, Variable, Index, &Count);
JzPrint("\r\n ");
Variable += Index;
}
JzPrint(Variable);
JzPrint(JZ_CRLF_MSG);
}
Variable = strchr(Variable,'\0') + 1;
}
}
JzSetPosition( 2, 0);
JzPrint(JZ_USE_ARROWS_MSG);
} while ( JzSetEnvironmentVariable() );
return;
}
BOOLEAN
JzCheckBootSelection (
IN LONG Selection
)
/*++
Routine Description:
This routine checks the integrity of a boot selection.
Arguments:
Selection - The number of the selection to check.
Return Value:
Returns TRUE if there are more selections after the current one, otherwise
returns FALSE.
--*/
{
ARC_STATUS Status;
ULONG CurrentLine;
ULONG Fid;
ULONG MenuSelection;
ULONG Index;
CHAR Segment[128];
CHAR Value[128];
BOOLEAN MoreSelections;
BOOLEAN Problem;
JzClearScreen();
JzSetPosition( 2, 0);
JzPrint(JZ_CHECKING_BOOT_SEL_MSG, Selection);
CurrentLine = 5 + NUMBER_OF_PROBLEMS;
JzSetPosition( CurrentLine, 0);
MoreSelections = FALSE;
Problem = FALSE;
JzSetScreenColor( ArcColorYellow, ArcColorBlue);
for ( Index = 0 ; Index < MaximumBootVariable ; Index++ ) {
strcpy(Segment, BootString[Index]);
MoreSelections = FwGetVariableSegment(Selection, Segment) || MoreSelections;
strcpy(Value, strchr(Segment, '=') + 1);
//
// Check to make sure the value is not NULL, except for OsloadOptions
// which can legally have a NULL value.
//
if (Index != OsLoadOptionsVariable) {
if (Value[0] == 0) {
Problem = TRUE;
JzPrint(JZ_VARIABLE_NULL_MSG, BootString[Index]);
continue;
}
}
//
// If this is the SystemPartition, Osloader, or OsloadPartition variable,
// check to make sure it can be opened.
//
if ((Index == SystemPartitionVariable) ||
(Index == OsLoaderVariable) ||
(Index == OsLoadPartitionVariable) ) {
if (ArcOpen(Value, ArcOpenReadOnly, &Fid) != ESUCCESS) {
Problem = TRUE;
JzPrint( JZ_CANT_BE_FOUND_MSG,
BootString[Index]);
JzPrint( JZ_FORMAT1_MSG,
Value);
} else {
ArcClose(Fid);
}
}
}
JzSetScreenColor( ArcColorWhite, ArcColorBlue);
if (Problem) {
JzShowTime(TRUE);
CurrentLine = 2;
JzSetPosition( CurrentLine, 0);
JzPrint( JZ_PROBLEMS_FOUND_MSG, Selection);
MenuSelection = JxDisplayMenu( ProblemChoices,
NUMBER_OF_PROBLEMS,
0,
CurrentLine + 2);
//
// Switch based on the action.
//
switch (MenuSelection) {
//
// Ignore
//
case 0:
break;
//
// Delete this boot selection
//
case 1:
for ( Index = 0 ; Index < MaximumBootVariable ; Index++ ) {
JzDeleteVariableSegment(BootString[Index],Selection);
}
break;
//
// Edit this boot selection
//
case 2:
JzEditSelection(Selection);
break;
default:
break;
}
}
return(MoreSelections);
}
VOID
JzCheckBootSelections (
VOID
)
/*++
Routine Description:
This routine cycles through all of the boot selections and checks them.
Arguments:
None.
Return Value:
None.
--*/
{
ULONG Index;
//
// Look to see if any boot selections exist. Skip the SystemPartition
// variable because that can be set without any selections.
//
for ( Index = 0 ; Index < MaximumBootVariable ; Index++ ) {
if ( (Index != SystemPartitionVariable) &&
(ArcGetEnvironmentVariable(BootString[Index]) != NULL)) {
break;
}
}
//
// If there are boot selections, check them.
//
if (Index != MaximumBootVariable) {
Index = 0;
while (JzCheckBootSelection(Index)) {
Index++;
}
}
return;
}
VOID
JzBootMenu(
VOID
)
/*++
Routine Description:
This routine displays the boot menu.
Arguments:
None.
Return Value:
None.
--*/
{
LONG DefaultChoice = 0;
//
// Loop on choices until exit is selected.
//
while (TRUE) {
DefaultChoice = JzGetSelection(JzBootChoices,
NUMBER_OF_JZ_BOOT_CHOICES,
DefaultChoice);
//
// If the escape key was pressed, return.
//
if (DefaultChoice == -1) {
DefaultChoice = 0x7fffffff;
}
//
// Switch based on the action.
//
switch (DefaultChoice) {
//
// Add boot selection
//
case 0:
JzAddBootSelection();
break;
//
// Delete a boot selection
//
case 1:
JzDeleteBootSelection();
break;
//
// Edit a boot selection
//
case 2:
JzEditBootSelection();
break;
//
// Rearrange boot selections
//
case 3:
JzRearrangeBootSelections();
break;
//
// Check boot selections
//
case 4:
JzCheckBootSelections();
break;
//
// Setup autoboot parameters
//
case 5:
JzSetupAutoboot();
break;
//
// Exit.
//
default:
return;
}
}
}