mirror of https://github.com/lianthony/NT4.0
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.
862 lines
18 KiB
862 lines
18 KiB
/*++
|
|
|
|
Copyright (c) 1991 Microsoft Corporation
|
|
Copyright (c) 1993 Digital Equipment Corporation
|
|
|
|
Module Name:
|
|
|
|
jnsetcom.c
|
|
|
|
Abstract:
|
|
|
|
This program contains the common routines for the Jensen setup code,
|
|
the firmware update program (JNUPDATE.EXE), and the FailSafe Booter.
|
|
|
|
|
|
Author:
|
|
|
|
John DeRosa 31-July-1992.
|
|
|
|
This module, and the entire setup program, was based on the jzsetup
|
|
program written by David M. Robinson (davidro) of Microsoft, dated
|
|
9-Aug-1991.
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
|
|
#include "fwp.h"
|
|
#include "jnsnvdeo.h"
|
|
#include "machdef.h"
|
|
#include "string.h"
|
|
#include "iodevice.h"
|
|
#include "jnvendor.h"
|
|
#include "fwstring.h"
|
|
|
|
|
|
|
|
#ifdef ALPHA_FW_SERDEB
|
|
//
|
|
// Variable that enables printing on the COM1 line.
|
|
//
|
|
extern BOOLEAN SerSnapshot;
|
|
#endif
|
|
|
|
|
|
#ifndef FAILSAFE_BOOTER
|
|
|
|
ULONG
|
|
JzDisplayMenu (
|
|
IN PCHAR Choices[],
|
|
IN ULONG NumberOfChoices,
|
|
IN LONG DefaultChoice,
|
|
IN ULONG CurrentLine,
|
|
IN LONG AutobootValue,
|
|
IN BOOLEAN ShowTheTime
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Displays a menu and gets a selection.
|
|
|
|
This routine assumes that the entries in the Choices array
|
|
do not have two adjacent blank rows, and that the first and last
|
|
rows are not blank.
|
|
|
|
Arguments:
|
|
|
|
Choices[] The menu choices array
|
|
|
|
NumberOfChoices The 1-based number of entries in Choices[]
|
|
|
|
DefaultChoice The 0-based entry which should be highlighted
|
|
as the default choice.
|
|
|
|
CurrentLine The current line on the video.
|
|
|
|
AutobootValue If zero, do not do an autoboot countdown.
|
|
If nonzero, do an autoboot countdown with this value.
|
|
|
|
ShowTheTime If true, the time is displayed in the upper right
|
|
hand corner.
|
|
|
|
Return Value:
|
|
|
|
Returns -1 if the escape key is pressed, otherwise returns the menu item
|
|
selected, where 0 is the first item.
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG Index;
|
|
UCHAR Character;
|
|
ULONG Count;
|
|
ULONG PreviousTime;
|
|
ULONG RelativeTime;
|
|
BOOLEAN Timeout;
|
|
|
|
#ifndef JNUPDATE
|
|
|
|
//
|
|
// Setup for autoboot
|
|
//
|
|
|
|
if (AutobootValue == 0) {
|
|
Timeout = FALSE;
|
|
AutobootValue = 1;
|
|
} else {
|
|
Timeout = TRUE;
|
|
PreviousTime = FwGetRelativeTime();
|
|
}
|
|
|
|
#else
|
|
|
|
Timeout = FALSE;
|
|
AutobootValue = 1;
|
|
|
|
#endif
|
|
|
|
//
|
|
// Display the menu
|
|
//
|
|
|
|
for (Index = 0; Index < NumberOfChoices ; Index++ ) {
|
|
VenSetPosition( Index + CurrentLine, 5);
|
|
if (Index == DefaultChoice) {
|
|
VenSetScreenAttributes( TRUE, FALSE, TRUE);
|
|
VenPrint(Choices[Index]);
|
|
VenSetScreenAttributes( TRUE, FALSE, FALSE);
|
|
} else {
|
|
VenPrint(Choices[Index]);
|
|
}
|
|
}
|
|
|
|
Character = 0;
|
|
do {
|
|
#ifndef JNUPDATE
|
|
if (ShowTheTime) {
|
|
JzShowTime(FALSE);
|
|
}
|
|
#endif
|
|
if (ArcGetReadStatus(ARC_CONSOLE_INPUT) == ESUCCESS) {
|
|
ArcRead(ARC_CONSOLE_INPUT, &Character, 1, &Count);
|
|
switch (Character) {
|
|
|
|
case ASCII_ESC:
|
|
|
|
VenStallExecution(10000);
|
|
if (ArcGetReadStatus(ARC_CONSOLE_INPUT) == ESUCCESS) {
|
|
ArcRead(ARC_CONSOLE_INPUT, &Character, 1, &Count);
|
|
if (Character != '[') {
|
|
return(-1);
|
|
}
|
|
} else {
|
|
return(-1);
|
|
}
|
|
|
|
// We purposely fall through to ASCII_CSI.
|
|
|
|
case ASCII_CSI:
|
|
|
|
ArcRead(ARC_CONSOLE_INPUT, &Character, 1, &Count);
|
|
VenSetPosition( DefaultChoice + CurrentLine, 5);
|
|
VenPrint(Choices[DefaultChoice]);
|
|
|
|
switch (Character) {
|
|
|
|
case 'A':
|
|
case 'D':
|
|
DefaultChoice--;
|
|
if (DefaultChoice < 0) {
|
|
DefaultChoice = NumberOfChoices - 1;
|
|
}
|
|
if (*Choices[DefaultChoice] == 0) {
|
|
DefaultChoice--;
|
|
}
|
|
break;
|
|
|
|
case 'B':
|
|
case 'C':
|
|
DefaultChoice++;
|
|
if (DefaultChoice == NumberOfChoices) {
|
|
DefaultChoice = 0;
|
|
}
|
|
if (*Choices[DefaultChoice] == 0) {
|
|
DefaultChoice++;
|
|
}
|
|
break;
|
|
|
|
case 'H':
|
|
DefaultChoice = 0;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
VenSetPosition( DefaultChoice + CurrentLine, 5);
|
|
VenSetScreenAttributes( TRUE, FALSE, TRUE);
|
|
VenPrint(Choices[DefaultChoice]);
|
|
VenSetScreenAttributes( TRUE, FALSE, FALSE);
|
|
continue;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// If default choice is nonzero and a timeout is active, remove
|
|
// the timeout.
|
|
//
|
|
|
|
if ((DefaultChoice != 0) && Timeout) {
|
|
Timeout = FALSE;
|
|
VenSetPosition(NumberOfChoices + 9, 0);
|
|
VenPrint("\x9bK");
|
|
}
|
|
|
|
#ifndef JNUPDATE
|
|
|
|
//
|
|
// Update the timeout value if active.
|
|
//
|
|
|
|
if (Timeout) {
|
|
RelativeTime = FwGetRelativeTime();
|
|
if (RelativeTime != PreviousTime) {
|
|
PreviousTime = RelativeTime;
|
|
VenSetPosition(NumberOfChoices + 9, 62);
|
|
VenPrint("\x9bK");
|
|
VenPrint1("%d", AutobootValue--);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
} while ((Character != '\n') && (Character != ASCII_CR) && (AutobootValue >= 0));
|
|
|
|
return DefaultChoice;
|
|
}
|
|
#endif
|
|
|
|
#ifndef FAILSAFE_BOOTER
|
|
GETSTRING_ACTION
|
|
JzGetString(
|
|
OUT PCHAR String,
|
|
IN ULONG StringLength,
|
|
IN PCHAR InitialString OPTIONAL,
|
|
IN ULONG CurrentRow,
|
|
IN ULONG CurrentColumn,
|
|
IN BOOLEAN ShowTheTime
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine reads a string from standardin until a carriage return is
|
|
found, StringLength is reached, or ESC is pushed.
|
|
|
|
Semicolons are discarded. Reason: semicolons are key characters in
|
|
the parsing of multi-segment environment variables. They aren not
|
|
needed for any valid input to the firmware, so the easiest solution
|
|
is to filter them here.
|
|
|
|
Arguments:
|
|
|
|
String - Supplies a pointer to a location where the string is to be stored.
|
|
|
|
StringLength - Supplies the Max Length to read.
|
|
|
|
InitialString - Supplies an optional initial string.
|
|
|
|
CurrentRow - Supplies the current screen row.
|
|
|
|
CurrentColumn - Supplies the current screen column.
|
|
|
|
ShowTheTime If true, the time is displayed in the upper
|
|
right-hand corner of the screen.
|
|
|
|
Return Value:
|
|
|
|
If the string was successfully obtained GetStringSuccess is return,
|
|
otherwise one of the following codes is returned.
|
|
|
|
GetStringEscape - the escape key was pressed or StringLength was reached.
|
|
GetStringUpArrow - the up arrow key was pressed.
|
|
GetStringDownArrow - the down arrow key was pressed.
|
|
|
|
--*/
|
|
|
|
{
|
|
ARC_STATUS Status;
|
|
UCHAR c;
|
|
ULONG Count;
|
|
PCHAR Buffer;
|
|
PCHAR Cursor;
|
|
PCHAR CopyPointer;
|
|
GETSTRING_ACTION Action;
|
|
|
|
//
|
|
// If an initial string was supplied, update the output string.
|
|
//
|
|
|
|
if (ARGUMENT_PRESENT(InitialString)) {
|
|
strcpy(String, InitialString);
|
|
Buffer = strchr(String, 0);
|
|
} else {
|
|
*String = 0;
|
|
Buffer = String;
|
|
}
|
|
|
|
Cursor = Buffer;
|
|
|
|
while (TRUE) {
|
|
|
|
//
|
|
// Print the string.
|
|
//
|
|
|
|
VenSetPosition(CurrentRow, CurrentColumn);
|
|
VenPrint(String);
|
|
VenPrint("\x9bK");
|
|
|
|
//
|
|
// Print the cursor.
|
|
//
|
|
|
|
VenSetScreenAttributes(TRUE,FALSE,TRUE);
|
|
VenSetPosition(CurrentRow, (Cursor - String) + CurrentColumn);
|
|
|
|
if (Cursor >= Buffer) {
|
|
VenPrint(" ");
|
|
} else {
|
|
ArcWrite(ARC_CONSOLE_OUTPUT,Cursor,1,&Count);
|
|
}
|
|
VenSetScreenAttributes(TRUE,FALSE,FALSE);
|
|
|
|
#ifndef JNUPDATE
|
|
while (ShowTheTime &&
|
|
ArcGetReadStatus(ARC_CONSOLE_INPUT) != ESUCCESS) {
|
|
JzShowTime(FALSE);
|
|
}
|
|
#endif
|
|
Status = ArcRead(ARC_CONSOLE_INPUT,&c,1,&Count);
|
|
|
|
if (Status != ESUCCESS) {
|
|
Action = GetStringEscape;
|
|
goto EndGetString;
|
|
}
|
|
|
|
if (Buffer-String == StringLength) {
|
|
Action = GetStringEscape;
|
|
goto EndGetString;
|
|
}
|
|
|
|
switch (c) {
|
|
|
|
case ASCII_ESC:
|
|
|
|
//
|
|
// If there is another character available, look to see if
|
|
// this a control sequence, and fall through to ASCII_CSI.
|
|
// This is an attempt to make escape sequences from a terminal work.
|
|
//
|
|
|
|
VenStallExecution(10000);
|
|
|
|
if (ArcGetReadStatus(ARC_CONSOLE_INPUT) == ESUCCESS) {
|
|
ArcRead(ARC_CONSOLE_INPUT, &c, 1, &Count);
|
|
if (c != '[') {
|
|
Action = GetStringEscape;
|
|
goto EndGetString;
|
|
}
|
|
} else {
|
|
Action = GetStringEscape;
|
|
goto EndGetString;
|
|
}
|
|
|
|
case ASCII_CSI:
|
|
|
|
ArcRead(ARC_CONSOLE_INPUT, &c, 1, &Count);
|
|
switch (c) {
|
|
|
|
case 'A':
|
|
Action = GetStringUpArrow;
|
|
goto EndGetString;
|
|
|
|
case 'D':
|
|
if (Cursor != String) {
|
|
Cursor--;
|
|
}
|
|
continue;
|
|
|
|
case 'B':
|
|
Action = GetStringDownArrow;
|
|
goto EndGetString;
|
|
|
|
case 'C':
|
|
if (Cursor != Buffer) {
|
|
Cursor++;
|
|
}
|
|
continue;
|
|
|
|
case 'H':
|
|
Cursor = String;
|
|
continue;
|
|
|
|
case 'K':
|
|
Cursor = Buffer;
|
|
continue;
|
|
|
|
case 'P':
|
|
CopyPointer = Cursor;
|
|
while (*CopyPointer) {
|
|
*CopyPointer = *(CopyPointer + 1);
|
|
CopyPointer++;
|
|
}
|
|
if (Buffer != String) {
|
|
Buffer--;
|
|
}
|
|
continue;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case '\r':
|
|
case '\n':
|
|
|
|
Action = GetStringSuccess;
|
|
goto EndGetString;
|
|
|
|
//
|
|
// Do not bother handling the tab character properly.
|
|
//
|
|
|
|
case '\t' :
|
|
|
|
Action = GetStringEscape;
|
|
goto EndGetString;
|
|
|
|
case '\b':
|
|
|
|
if (Cursor != String) {
|
|
Cursor--;
|
|
}
|
|
CopyPointer = Cursor;
|
|
while (*CopyPointer) {
|
|
*CopyPointer = *(CopyPointer + 1);
|
|
CopyPointer++;
|
|
}
|
|
if (Buffer != String) {
|
|
Buffer--;
|
|
}
|
|
break;
|
|
|
|
//
|
|
// Discard any semicolons because they will corrupt multi-
|
|
// segment environment variables.
|
|
//
|
|
|
|
case ';':
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
//
|
|
// Store the character.
|
|
//
|
|
|
|
CopyPointer = ++Buffer;
|
|
if (CopyPointer > Cursor) {
|
|
while (CopyPointer != Cursor) {
|
|
*CopyPointer = *(CopyPointer - 1);
|
|
CopyPointer--;
|
|
}
|
|
}
|
|
*Cursor++ = c;
|
|
break;
|
|
}
|
|
}
|
|
|
|
Action = GetStringEscape;
|
|
|
|
EndGetString:
|
|
|
|
VenSetPosition(CurrentRow, (Cursor - String) + CurrentColumn);
|
|
|
|
if (Cursor >= Buffer) {
|
|
VenPrint(" ");
|
|
} else {
|
|
ArcWrite(ARC_CONSOLE_OUTPUT,Cursor,1,&Count);
|
|
}
|
|
|
|
//
|
|
// Make sure we return a null string if not successful.
|
|
//
|
|
|
|
if (Action != GetStringSuccess) {
|
|
*String = 0;
|
|
}
|
|
|
|
return(Action);
|
|
}
|
|
|
|
#endif
|
|
|
|
#if !defined(JNUPDATE) && !defined(FAILSAFE_BOOTER)
|
|
ARC_STATUS
|
|
JzEnvironmentCheckChecksum (
|
|
VOID
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine checks the environment area checksum.
|
|
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
If the checksum is good, ESUCCESS is returned, otherwise EIO is returned.
|
|
|
|
--*/
|
|
|
|
{
|
|
PUCHAR NvChars;
|
|
PNV_CONFIGURATION NvConfiguration;
|
|
ULONG Index;
|
|
ULONG Checksum1, Checksum2;
|
|
|
|
NvConfiguration = (PNV_CONFIGURATION)NVRAM_CONFIGURATION;
|
|
|
|
//
|
|
// Form checksum from NVRAM data.
|
|
//
|
|
|
|
Checksum1 = 0;
|
|
NvChars = (PUCHAR)&NvConfiguration->Environment[0];
|
|
|
|
for ( Index = 0 ;
|
|
Index < LENGTH_OF_ENVIRONMENT;
|
|
Index++ ) {
|
|
Checksum1 += HalpReadNVByte( NvChars++ );
|
|
}
|
|
|
|
//
|
|
// Reconstitute checksum and return error if no compare.
|
|
//
|
|
|
|
Checksum2 = (ULONG)HalpReadNVByte( &NvConfiguration->Checksum2[0] ) |
|
|
(ULONG)HalpReadNVByte( &NvConfiguration->Checksum2[1] ) << 8 |
|
|
(ULONG)HalpReadNVByte( &NvConfiguration->Checksum2[2] ) << 16 |
|
|
(ULONG)HalpReadNVByte( &NvConfiguration->Checksum2[3] ) << 24 ;
|
|
|
|
if (Checksum1 != Checksum2) {
|
|
return EIO;
|
|
} else {
|
|
return ESUCCESS;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#ifndef JNUPDATE
|
|
BOOLEAN
|
|
JzGetPathMnemonicKey(
|
|
IN PCHAR OpenPath,
|
|
IN PCHAR Mnemonic,
|
|
IN PULONG Key
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine looks for the given Mnemonic in OpenPath.
|
|
If Mnemonic is a component of the path, then it converts the key
|
|
value to an integer wich is returned in Key.
|
|
|
|
Arguments:
|
|
|
|
OpenPath - Pointer to a string that contains an ARC pathname.
|
|
|
|
Mnemonic - Pointer to a string that contains a ARC Mnemonic
|
|
|
|
Key - Pointer to a ULONG where the Key value is stored.
|
|
|
|
|
|
Return Value:
|
|
|
|
FALSE if mnemonic is found in path and a valid key is converted.
|
|
TRUE otherwise.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
PCHAR Tmp;
|
|
CHAR Digits[4];
|
|
ULONG i;
|
|
CHAR String[16];
|
|
|
|
//
|
|
// Construct a string of the form ")mnemonic("
|
|
//
|
|
String[0]=')';
|
|
for(i=1;*Mnemonic;i++) {
|
|
String[i] = * Mnemonic++;
|
|
}
|
|
String[i++]='(';
|
|
String[i]='\0';
|
|
|
|
if ((Tmp=strstr(OpenPath,&String[1])) == NULL) {
|
|
return TRUE;
|
|
}
|
|
|
|
if (Tmp != OpenPath) {
|
|
if ((Tmp=strstr(OpenPath,String)) == NULL) {
|
|
return TRUE;
|
|
}
|
|
} else {
|
|
i--;
|
|
}
|
|
//
|
|
// skip the mnemonic and convert the value in between parentesis to integer
|
|
//
|
|
Tmp+=i;
|
|
for (i=0;i<3;i++) {
|
|
if (*Tmp == ')') {
|
|
Digits[i] = '\0';
|
|
break;
|
|
}
|
|
Digits[i] = *Tmp++;
|
|
}
|
|
Digits[i]='\0';
|
|
*Key = atoi(Digits);
|
|
return FALSE;
|
|
}
|
|
|
|
#endif // ndef JNUPDATE
|
|
|
|
VOID
|
|
FwWaitForKeypress(
|
|
IN BOOLEAN ShowTheTime
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine waits for a keypress, then returns.
|
|
|
|
Arguments:
|
|
|
|
ShowTheTime TRUE = display the time.
|
|
FALSE = do not display the time.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
UCHAR Character;
|
|
ULONG Count;
|
|
|
|
VenPrint(SS_PRESS_KEY_MSG);
|
|
while (ArcGetReadStatus(ARC_CONSOLE_INPUT) != ESUCCESS) {
|
|
#if !defined(JNUPDATE) && !defined(FAILSAFE_BOOTER)
|
|
if (ShowTheTime) {
|
|
JzShowTime(FALSE);
|
|
}
|
|
#endif
|
|
}
|
|
ArcRead(ARC_CONSOLE_INPUT, &Character, 1, &Count);
|
|
VenPrint1("%c2J", ASCII_CSI);
|
|
}
|
|
|
|
#if !defined(JNUPDATE) && !defined(FAILSAFE_BOOTER)
|
|
|
|
BOOLEAN
|
|
FwGetVariableSegment (
|
|
IN ULONG SegmentNumber,
|
|
IN OUT PCHAR Segment
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine returns the specified segment of a volatile environment
|
|
variable. Segments are separated by semicolons.
|
|
|
|
Arguments:
|
|
|
|
SegmentNumber - Supplies the number of the segment to return.
|
|
|
|
Segment - Supplies a pointer to the name of the environment variable.
|
|
The variable may be followed by an equal sign.
|
|
An '=' and the segment value are appended to this name and
|
|
returned.
|
|
|
|
|
|
Return Value:
|
|
|
|
If one or more segments exist after the specified segment, TRUE is returned,
|
|
otherwise FALSE is returned.
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG Index;
|
|
ULONG Count;
|
|
PCHAR VariableValue;
|
|
PCHAR TempPointer;
|
|
|
|
//
|
|
// Remove an equal sign if present.
|
|
//
|
|
|
|
if ((TempPointer = strchr(Segment, '=')) != NULL) {
|
|
*TempPointer = 0;
|
|
}
|
|
|
|
//
|
|
// Get variable, add equal sign, and advance Segment to where the value
|
|
// is to be added.
|
|
//
|
|
|
|
VariableValue = FwGetVolatileEnvironmentVariable(Segment);
|
|
strcat(Segment, "=");
|
|
Segment = strchr(Segment, '=') + 1;
|
|
|
|
//
|
|
// If there was no variable, return.
|
|
//
|
|
|
|
if (VariableValue == NULL) {
|
|
return(FALSE);
|
|
}
|
|
|
|
Index = 0;
|
|
Count = 0;
|
|
|
|
//
|
|
// Search for the requested segment and copy it to the return value.
|
|
//
|
|
|
|
while ((TempPointer = strchr(VariableValue,';')) != NULL) {
|
|
Count = TempPointer - VariableValue;
|
|
|
|
if (Index == SegmentNumber) {
|
|
strncpy(Segment, VariableValue, Count);
|
|
Segment[Count] = 0;
|
|
return TRUE;
|
|
}
|
|
|
|
VariableValue += Count + 1;
|
|
Index++;
|
|
}
|
|
|
|
//
|
|
// If there is data left, copy it to the return value.
|
|
//
|
|
|
|
strcpy(Segment,VariableValue);
|
|
|
|
return(FALSE);
|
|
}
|
|
|
|
#endif
|
|
|
|
#if !defined(JNUPDATE) && !defined(FAILSAFE_BOOTER)
|
|
|
|
ARC_STATUS
|
|
FwSetVariableSegment (
|
|
IN ULONG SegmentNumber,
|
|
IN PCHAR VariableName,
|
|
IN PCHAR NewSegment
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine sets the specified segment of an environment variable
|
|
IN THE VOLATILE AREA ONLY. Segments are separated by semicolons.
|
|
|
|
Arguments:
|
|
|
|
SegmentNumber - Supplies the number of the segment to add.
|
|
|
|
VariableName - Supplies a pointer to the name of the environment variable.
|
|
The variable may be followed by an equal sign.
|
|
|
|
NewSegment - Supplies a pointer to the new segment.
|
|
|
|
Return Value:
|
|
|
|
Returns ESUCCESS if the segment is set, otherwise an error code is
|
|
returned.
|
|
|
|
--*/
|
|
|
|
{
|
|
ARC_STATUS Status;
|
|
PCHAR Variable;
|
|
PCHAR NextVariable;
|
|
PCHAR EndOfVariable;
|
|
CHAR VariableValue[256];
|
|
ULONG Index;
|
|
ULONG Count;
|
|
|
|
SetupROMPendingModified = TRUE;
|
|
|
|
Variable = FwGetVolatileEnvironmentVariable(VariableName);
|
|
VariableValue[0] = 0;
|
|
|
|
if (Variable != NULL) {
|
|
EndOfVariable = strchr(Variable, 0);
|
|
for (Index = 0; Index < SegmentNumber ; Index++ ) {
|
|
NextVariable = strchr(Variable, ';');
|
|
if (NextVariable != NULL) {
|
|
Count = NextVariable - Variable + 1;
|
|
strncat(VariableValue, Variable, Count);
|
|
Variable = NextVariable + 1;
|
|
} else {
|
|
strcat(VariableValue, Variable);
|
|
Variable = EndOfVariable;
|
|
strcat(VariableValue, ";");
|
|
}
|
|
}
|
|
} else {
|
|
for (Index = 0; Index < SegmentNumber ; Index++ ) {
|
|
strcat(VariableValue, ";");
|
|
}
|
|
}
|
|
|
|
strcat(VariableValue, NewSegment);
|
|
|
|
if ((Variable != NULL) && (Variable != EndOfVariable)) {
|
|
strcat(VariableValue, ";");
|
|
strcat(VariableValue, Variable);
|
|
}
|
|
|
|
Status = FwCoreSetEnvironmentVariable(VariableName, VariableValue, FALSE);
|
|
SetupROMPendingModified = TRUE;
|
|
return(Status);
|
|
}
|
|
|
|
#endif
|