953 lines
21 KiB
C
953 lines
21 KiB
C
|
//smjfix - This code needs to be made MP safe if it isn't being called
|
|||
|
// by MP safe code.
|
|||
|
//jwlfix - It's currently being called by the kernel (ex, actually) in
|
|||
|
// an MP-safe fashion, and by config during phase 1 (?) of
|
|||
|
// bootstrapping the system.
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1991 Microsoft Corporation
|
|||
|
Copyright (c) 1992, 1993 Digital Equipment Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
environ.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
This module implements the ARC firmware Environment Variable functions as
|
|||
|
described in the Advanced Risc Computing Specification (Revision 1.00),
|
|||
|
section 3.3.3.11.
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
David M. Robinson (davidro) 13-June-1991
|
|||
|
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
James Livingston 94.05.17
|
|||
|
|
|||
|
Fix a coding error that caused NVRAM to get trashed in the attempt
|
|||
|
to update a nearly full environment variable space.
|
|||
|
|
|||
|
Steve Jenness 93.12.20
|
|||
|
|
|||
|
The firmware still requires the naked checksum set and check
|
|||
|
routines. Add them back in under the AXP_FIRMWARE conditional
|
|||
|
until the jxenvir.c in the firmware and the environ.c files
|
|||
|
are rationalized.
|
|||
|
|
|||
|
Steve Jenness. 93.12.17
|
|||
|
|
|||
|
Reduce the reads and writes to the NVRAM part. Some parts are
|
|||
|
slow to access (especially on writes). Do NVRAM access only when
|
|||
|
really necessary. Remove use of HalpCopyNVRamBuffer because it is
|
|||
|
too difficult to make generically fast (put more intelligence
|
|||
|
in higher code instead).
|
|||
|
|
|||
|
Steve Brooks. 6-Oct 1993 remove all platform and device specific references
|
|||
|
|
|||
|
These routines have been restructured to be platform and device
|
|||
|
independant. All calls access the NVRAM via the calls
|
|||
|
HalpReadNVRamBuffer, HalpWriteNVRamBuffer, and HalpCopyNVRamBuffer
|
|||
|
|
|||
|
Jeff McLeman (DEC) 31-Jul-1992 modify for Jensen
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#include "halp.h"
|
|||
|
#include "environ.h"
|
|||
|
|
|||
|
#include "arccodes.h"
|
|||
|
|
|||
|
//
|
|||
|
// Static data.
|
|||
|
//
|
|||
|
|
|||
|
UCHAR Environment[LENGTH_OF_ENVIRONMENT];
|
|||
|
ULONG EnvironmentChecksum;
|
|||
|
BOOLEAN EnvironmentValid = FALSE;
|
|||
|
|
|||
|
UCHAR OutputString[MAXIMUM_ENVIRONMENT_VALUE];
|
|||
|
PCONFIGURATION Configuration;
|
|||
|
|
|||
|
//
|
|||
|
// Routine prototypes.
|
|||
|
//
|
|||
|
|
|||
|
ARC_STATUS
|
|||
|
HalpReadAndChecksumEnvironment (
|
|||
|
);
|
|||
|
|
|||
|
ARC_STATUS
|
|||
|
HalpWriteAndChecksumEnvironment (
|
|||
|
);
|
|||
|
|
|||
|
ARC_STATUS
|
|||
|
HalGetEnvironmentVariable (
|
|||
|
IN PCHAR Variable,
|
|||
|
IN USHORT length,
|
|||
|
OUT PCHAR Buffer
|
|||
|
);
|
|||
|
|
|||
|
ARC_STATUS
|
|||
|
HalSetEnvironmentVariable (
|
|||
|
IN PCHAR Variable,
|
|||
|
IN PCHAR Value
|
|||
|
);
|
|||
|
|
|||
|
ARC_STATUS
|
|||
|
HalpFindEnvironmentVariable (
|
|||
|
IN PCHAR Variable,
|
|||
|
OUT PULONG VariableIndex,
|
|||
|
OUT PULONG ValueIndex
|
|||
|
);
|
|||
|
|
|||
|
#if defined(AXP_FIRMWARE)
|
|||
|
|
|||
|
ARC_STATUS
|
|||
|
HalpEnvironmentCheckChecksum (
|
|||
|
VOID
|
|||
|
);
|
|||
|
|
|||
|
ARC_STATUS
|
|||
|
HalpEnvironmentSetChecksum (
|
|||
|
VOID
|
|||
|
);
|
|||
|
|
|||
|
#endif //AXP_FIRMWARE
|
|||
|
|
|||
|
#ifdef AXP_FIRMWARE
|
|||
|
|
|||
|
#pragma alloc_text(DISTEXT, HalpReadAndChecksumEnvironment )
|
|||
|
#pragma alloc_text(DISTEXT, HalpWriteAndChecksumEnvironment )
|
|||
|
#pragma alloc_text(DISTEXT, HalGetEnvironmentVariable )
|
|||
|
#pragma alloc_text(DISTEXT, HalSetEnvironmentVariable )
|
|||
|
#pragma alloc_text(DISTEXT, HalpFindEnvironmentVariable )
|
|||
|
#pragma alloc_text(DISTEXT, HalpEnvironmentCheckChecksum )
|
|||
|
#pragma alloc_text(DISTEXT, HalpEnvironmentSetChecksum )
|
|||
|
|
|||
|
#endif // AXP_FIRMWARE
|
|||
|
|
|||
|
|
|||
|
ARC_STATUS
|
|||
|
HalpReadAndChecksumEnvironment(
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine reads the part of the NVRAM containing the environment
|
|||
|
variables into a memory buffer. It checksums the data as read.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
ESUCCESS - checksum is good.
|
|||
|
EIO - checksum is bad.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PUCHAR BufChar;
|
|||
|
ULONG Index;
|
|||
|
ULONG Checksum1, Checksum2;
|
|||
|
|
|||
|
#ifndef EISA_PLATFORM
|
|||
|
UCHAR Nvram[LENGTH_OF_ENVIRONMENT+16];
|
|||
|
#endif // EISA_PLATFORM
|
|||
|
|
|||
|
//
|
|||
|
// Read checksum of environment data from the NVRAM.
|
|||
|
// For non eisa machines we have only one checksum for the whole nvram.
|
|||
|
// And it is stored in Checksum
|
|||
|
//
|
|||
|
|
|||
|
HalpReadNVRamBuffer(
|
|||
|
(PUCHAR)&Checksum2,
|
|||
|
#ifdef EISA_PLATFORM
|
|||
|
&((PNV_CONFIGURATION)NVRAM_CONFIGURATION)->Checksum2[0],
|
|||
|
#else // EISA_PLATFORM
|
|||
|
&((PNV_CONFIGURATION)NVRAM_CONFIGURATION)->Checksum[0],
|
|||
|
#endif // EISA_PLATFORM
|
|||
|
4);
|
|||
|
|
|||
|
//
|
|||
|
// If the environment data stored in the buffer is already valid,
|
|||
|
// short-circuit the NVRAM read.
|
|||
|
//
|
|||
|
|
|||
|
if (EnvironmentValid == TRUE) {
|
|||
|
if (Checksum2 == EnvironmentChecksum) {
|
|||
|
return ESUCCESS;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
#ifdef EISA_PLATFORM
|
|||
|
//
|
|||
|
// Read the NVRAM environment data into the buffer.
|
|||
|
//
|
|||
|
|
|||
|
HalpReadNVRamBuffer(
|
|||
|
&Environment[0],
|
|||
|
&((PNV_CONFIGURATION)NVRAM_CONFIGURATION)->Environment[0],
|
|||
|
LENGTH_OF_ENVIRONMENT);
|
|||
|
|
|||
|
//
|
|||
|
// Form checksum of data read from NVRAM.
|
|||
|
//
|
|||
|
|
|||
|
BufChar = &Environment[0];
|
|||
|
Checksum1 = 0;
|
|||
|
for ( Index = 0 ; Index < LENGTH_OF_ENVIRONMENT; Index++ ) {
|
|||
|
Checksum1 += *BufChar++;
|
|||
|
}
|
|||
|
|
|||
|
if (Checksum1 != Checksum2) {
|
|||
|
return EIO;
|
|||
|
} else {
|
|||
|
EnvironmentValid = TRUE;
|
|||
|
EnvironmentChecksum = Checksum1;
|
|||
|
return ESUCCESS;
|
|||
|
}
|
|||
|
#else // EISA_PLATFORM
|
|||
|
|
|||
|
//
|
|||
|
// Read the NVRAM into Nvram.
|
|||
|
//
|
|||
|
|
|||
|
HalpReadNVRamBuffer( &Nvram[0],
|
|||
|
NVRAM_CONFIGURATION,
|
|||
|
LENGTH_OF_ENVIRONMENT + 16 );
|
|||
|
|
|||
|
//
|
|||
|
// Form checksum of data read from NVRAM.
|
|||
|
//
|
|||
|
|
|||
|
BufChar = &Nvram[0];
|
|||
|
Checksum1 = 0;
|
|||
|
for ( Index = 0 ; Index < LENGTH_OF_ENVIRONMENT+16; Index++ ) {
|
|||
|
Checksum1 += *BufChar++;
|
|||
|
}
|
|||
|
|
|||
|
if (Checksum1 != Checksum2) {
|
|||
|
return EIO;
|
|||
|
} else {
|
|||
|
EnvironmentValid = TRUE;
|
|||
|
EnvironmentChecksum = Checksum1;
|
|||
|
|
|||
|
//
|
|||
|
// Nvram checksum was ok. Save the read Environment part of NVRAM
|
|||
|
// in global Environment[].
|
|||
|
//
|
|||
|
BufChar = &Environment[0];
|
|||
|
for( Index = 16; Index < LENGTH_OF_ENVIRONMENT+16; Index++ ) {
|
|||
|
*BufChar++ = Nvram[Index];
|
|||
|
}
|
|||
|
|
|||
|
return ESUCCESS;
|
|||
|
}
|
|||
|
#endif // EISA_PLATFORM
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
ARC_STATUS
|
|||
|
HalpWriteAndChecksumEnvironment (
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine writes the environment data back to the NVRAM, calculates
|
|||
|
a new checksum, and stores the checksum.
|
|||
|
|
|||
|
N.B. - For this method of rewriting the environment variables to be
|
|||
|
effective (minimal NVRAM access and quick overall), the
|
|||
|
HalpWriteNVRamBuffer is assumed to do block access and to
|
|||
|
suppress writes it doesn't need to do.
|
|||
|
|
|||
|
N.B. - To allow the HalpWriteNVRamBuffer to suppress writes, the new data
|
|||
|
should have as many bytes in common with the current NVRAM
|
|||
|
contents as possible. For example, the environment variables
|
|||
|
should not be reordered unless needed.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
ESUCCESS - NVRAM write succeeded.
|
|||
|
EIO - NVRAM write failed.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
ULONG Index;
|
|||
|
ULONG Checksum;
|
|||
|
KIRQL OldIrql;
|
|||
|
PUCHAR BufChar;
|
|||
|
|
|||
|
KeRaiseIrql(DEVICE_LEVEL, &OldIrql);
|
|||
|
|
|||
|
//
|
|||
|
// Form checksum from new NVRAM data.
|
|||
|
//
|
|||
|
|
|||
|
Checksum = 0;
|
|||
|
|
|||
|
BufChar = &Environment[0];
|
|||
|
for ( Index = 0 ; Index < LENGTH_OF_ENVIRONMENT; Index++ ) {
|
|||
|
Checksum += *BufChar++;
|
|||
|
}
|
|||
|
|
|||
|
#ifndef EISA_PLATFORM
|
|||
|
{
|
|||
|
UCHAR TempBuffer[16];
|
|||
|
HalpReadNVRamBuffer( TempBuffer, (PUCHAR)NVRAM_CONFIGURATION, 16 );
|
|||
|
for ( Index = 0 ; Index < 16; Index++ ) {
|
|||
|
Checksum += TempBuffer[ Index ];
|
|||
|
}
|
|||
|
}
|
|||
|
#endif // !EISA_PLATFORM
|
|||
|
|
|||
|
//
|
|||
|
// Write environment variables to NVRAM.
|
|||
|
//
|
|||
|
|
|||
|
HalpWriteNVRamBuffer(
|
|||
|
&((PNV_CONFIGURATION)NVRAM_CONFIGURATION)->Environment[0],
|
|||
|
&Environment[0],
|
|||
|
LENGTH_OF_ENVIRONMENT);
|
|||
|
|
|||
|
//
|
|||
|
// Write environment checksum.
|
|||
|
//
|
|||
|
|
|||
|
HalpWriteNVRamBuffer(
|
|||
|
#ifdef EISA_PLATFORM
|
|||
|
&((PNV_CONFIGURATION)NVRAM_CONFIGURATION)->Checksum2[0],
|
|||
|
#else // EISA_PLATFORM
|
|||
|
&((PNV_CONFIGURATION)NVRAM_CONFIGURATION)->Checksum[0],
|
|||
|
#endif // EISA_PLATFORM
|
|||
|
(PUCHAR)&Checksum,
|
|||
|
4);
|
|||
|
|
|||
|
EnvironmentChecksum = Checksum;
|
|||
|
EnvironmentValid = TRUE;
|
|||
|
|
|||
|
KeLowerIrql(OldIrql);
|
|||
|
|
|||
|
return ESUCCESS;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
ARC_STATUS
|
|||
|
HalGetEnvironmentVariable (
|
|||
|
IN PCHAR Variable,
|
|||
|
IN USHORT length,
|
|||
|
OUT PCHAR Buffer
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine searches (not case sensitive) the non-volatile ram for
|
|||
|
Variable, and if found returns a pointer to a zero terminated string that
|
|||
|
contains the value, otherwise a NULL pointer is returned.
|
|||
|
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Variable - Supplies a zero terminated string containing an environment
|
|||
|
variable.
|
|||
|
Length - Supplies the length of the value buffer in bytes
|
|||
|
|
|||
|
Buffer - Supplies a pointer to a buffer that will recieve the
|
|||
|
environment variable.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
ESUCCESS - Buffer contains the zero terminated string value of Variable.
|
|||
|
ENOENT - The variable doesn't exist in the environment.
|
|||
|
ENOMEM - The variable exists, but the value is longer than Length.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PUCHAR NvChars;
|
|||
|
ULONG VariableIndex;
|
|||
|
ULONG ValueIndex;
|
|||
|
ULONG Index;
|
|||
|
ARC_STATUS Status;
|
|||
|
KIRQL OldIrql;
|
|||
|
|
|||
|
//
|
|||
|
// Raise IRQL to synchronize
|
|||
|
//
|
|||
|
|
|||
|
KeRaiseIrql(DEVICE_LEVEL, &OldIrql);
|
|||
|
|
|||
|
//
|
|||
|
// If checksum is wrong, or the variable can't be found, return NULL.
|
|||
|
//
|
|||
|
|
|||
|
if ((HalpReadAndChecksumEnvironment() != ESUCCESS) ||
|
|||
|
(HalpFindEnvironmentVariable(Variable,
|
|||
|
&VariableIndex,
|
|||
|
&ValueIndex) != ESUCCESS)) {
|
|||
|
Status = ENOENT;
|
|||
|
} else {
|
|||
|
|
|||
|
//
|
|||
|
// Copy value to an output string, break on zero terminator
|
|||
|
// or string max.
|
|||
|
//
|
|||
|
|
|||
|
NvChars = &Environment[ValueIndex];
|
|||
|
for ( Index = 0 ; Index < length ; Index += 1 ) {
|
|||
|
if ( (*Buffer++ = *NvChars++) == 0 ) {
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (Index == length) {
|
|||
|
Status = ENOMEM;
|
|||
|
} else {
|
|||
|
Status = ESUCCESS;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Lower IRQL back to where it was
|
|||
|
//
|
|||
|
|
|||
|
KeLowerIrql(OldIrql);
|
|||
|
|
|||
|
return Status;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
ARC_STATUS
|
|||
|
HalSetEnvironmentVariable (
|
|||
|
IN PCHAR Variable,
|
|||
|
IN PCHAR Value
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine sets Variable (not case sensitive) to Value.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Variable - Supplies a zero terminated string containing an environment
|
|||
|
variable.
|
|||
|
|
|||
|
Value - Supplies a zero terminated string containing an environment
|
|||
|
variable value.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
ESUCCESS - The set completed successfully
|
|||
|
ENOSPC - No space in NVRAM for set operation.
|
|||
|
EIO - Invalid Checksum.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
ULONG VariableIndex;
|
|||
|
ULONG ValueIndex;
|
|||
|
PUCHAR TopOfEnvironment;
|
|||
|
PCHAR String;
|
|||
|
PUCHAR NvChars;
|
|||
|
LONG Count;
|
|||
|
CHAR Char;
|
|||
|
KIRQL OldIrql;
|
|||
|
|
|||
|
//
|
|||
|
// Raise Irql to Synchronize
|
|||
|
//
|
|||
|
|
|||
|
KeRaiseIrql(DEVICE_LEVEL, &OldIrql);
|
|||
|
|
|||
|
//
|
|||
|
// If checksum is wrong, return EIO;
|
|||
|
//
|
|||
|
|
|||
|
if (HalpReadAndChecksumEnvironment() != ESUCCESS) {
|
|||
|
KeLowerIrql(OldIrql);
|
|||
|
return EIO;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
//smjfix - examine the boundary condition where the environment space
|
|||
|
// is exactly filled.
|
|||
|
|
|||
|
//
|
|||
|
// Determine the top of the environment space by looking for the first
|
|||
|
// non-null character from the top.
|
|||
|
//
|
|||
|
|
|||
|
TopOfEnvironment = &Environment[LENGTH_OF_ENVIRONMENT-1];
|
|||
|
|
|||
|
do {
|
|||
|
Char = *TopOfEnvironment;
|
|||
|
|
|||
|
} while ( Char == 0 && (--TopOfEnvironment > Environment) );
|
|||
|
|
|||
|
//
|
|||
|
// Adjust TopOfEnvironment to the first new character, unless environment
|
|||
|
// space is empty, or the environment is exactly full. In the latter
|
|||
|
// case, the new value MUST fit into the space taken by the old.
|
|||
|
//
|
|||
|
|
|||
|
if (TopOfEnvironment != Environment
|
|||
|
&& TopOfEnvironment < &Environment[LENGTH_OF_ENVIRONMENT-2]) {
|
|||
|
TopOfEnvironment += 2;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Handle the case where the content of the NVRAM has been corrupted
|
|||
|
// such that the last character in the environment is non-zero.
|
|||
|
//
|
|||
|
|
|||
|
Count = &Environment[LENGTH_OF_ENVIRONMENT-1] - TopOfEnvironment;
|
|||
|
if (Count < 0) {
|
|||
|
KeLowerIrql(OldIrql);
|
|||
|
return ENOSPC;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Check to see if the variable already has a value.
|
|||
|
//
|
|||
|
|
|||
|
if (HalpFindEnvironmentVariable(Variable, &VariableIndex, &ValueIndex)
|
|||
|
== ESUCCESS) {
|
|||
|
ULONG SizeOfValue = strlen(Value);
|
|||
|
|
|||
|
if (SizeOfValue == strlen(&Environment[ValueIndex])) {
|
|||
|
|
|||
|
//
|
|||
|
// Overwrite the current variable in place.
|
|||
|
//
|
|||
|
|
|||
|
RtlMoveMemory(&Environment[ValueIndex],
|
|||
|
Value,
|
|||
|
SizeOfValue);
|
|||
|
//
|
|||
|
// Suppress the append of the variable to the end of the
|
|||
|
// environment variable data.
|
|||
|
//
|
|||
|
|
|||
|
*Value = 0;
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
//
|
|||
|
// Count free space, starting with the free area at the top and
|
|||
|
// adding the old variable value.
|
|||
|
//
|
|||
|
|
|||
|
for ( NvChars = &Environment[ValueIndex];
|
|||
|
NvChars <= TopOfEnvironment;
|
|||
|
NvChars++ ) {
|
|||
|
|
|||
|
Char = *NvChars;
|
|||
|
if ( Char == 0 )
|
|||
|
break;
|
|||
|
Count++;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Determine if free area is large enough to handle new value, if
|
|||
|
// not return error.
|
|||
|
//
|
|||
|
|
|||
|
for ( String = Value ; *String != 0 ; String++ ) {
|
|||
|
if (Count-- == 0) {
|
|||
|
KeLowerIrql(OldIrql);
|
|||
|
return ENOSPC;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Move ValueIndex to the end of the value and compress strings.
|
|||
|
//
|
|||
|
|
|||
|
do {
|
|||
|
Char = Environment[ValueIndex++];
|
|||
|
} while( Char != 0 );
|
|||
|
|
|||
|
Count = TopOfEnvironment - &Environment[ValueIndex];
|
|||
|
RtlMoveMemory(&Environment[VariableIndex],
|
|||
|
&Environment[ValueIndex],
|
|||
|
Count);
|
|||
|
|
|||
|
//
|
|||
|
// Adjust new top of environment.
|
|||
|
//
|
|||
|
|
|||
|
TopOfEnvironment = &Environment[VariableIndex+Count];
|
|||
|
|
|||
|
//
|
|||
|
// Zero to the end.
|
|||
|
//
|
|||
|
|
|||
|
Count = &Environment[LENGTH_OF_ENVIRONMENT] - TopOfEnvironment;
|
|||
|
Char = 0;
|
|||
|
while ( Count -- ) {
|
|||
|
TopOfEnvironment[Count] = Char;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
//
|
|||
|
// Variable is new.
|
|||
|
//
|
|||
|
|
|||
|
//
|
|||
|
// Determine if free area is large enough to handle new value, if not
|
|||
|
// return error.
|
|||
|
//
|
|||
|
|
|||
|
//
|
|||
|
// From the length of free space subtract new variable's length,
|
|||
|
// Value's length and 2 chars, one for the '=' sign and one of the
|
|||
|
// null terminator.
|
|||
|
//
|
|||
|
|
|||
|
Count -= ( strlen(Variable) + strlen(Value) + 2 );
|
|||
|
|
|||
|
//
|
|||
|
// Check if there is space to fit the new variable.
|
|||
|
//
|
|||
|
|
|||
|
if (Count < 0) {
|
|||
|
KeLowerIrql(OldIrql);
|
|||
|
return ENOSPC;
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// If Value is not zero, append the new variable and value.
|
|||
|
//
|
|||
|
|
|||
|
if (*Value != 0) {
|
|||
|
|
|||
|
//
|
|||
|
// Write new variable, converting to upper case.
|
|||
|
//
|
|||
|
while ( *Variable != 0 ) {
|
|||
|
|
|||
|
Char = ((*Variable >= 'a') && (*Variable <= 'z') ?
|
|||
|
(*Variable - 'a' + 'A') : *Variable);
|
|||
|
|
|||
|
*TopOfEnvironment = Char;
|
|||
|
|
|||
|
Variable ++;
|
|||
|
TopOfEnvironment ++;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Write equal sign.
|
|||
|
//
|
|||
|
|
|||
|
Char = '=';
|
|||
|
*TopOfEnvironment++ = Char;
|
|||
|
|
|||
|
//
|
|||
|
// Write new value.
|
|||
|
//
|
|||
|
|
|||
|
for ( Count = 0; Value[Count] != 0; Count ++ )
|
|||
|
;
|
|||
|
|
|||
|
RtlMoveMemory(&TopOfEnvironment[0], Value, Count);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Write the environment variables out to NVRAM and checksum it.
|
|||
|
//
|
|||
|
|
|||
|
if (HalpWriteAndChecksumEnvironment() != ESUCCESS) {
|
|||
|
KeLowerIrql(OldIrql);
|
|||
|
return EIO;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Lower Irql back to where it was
|
|||
|
//
|
|||
|
|
|||
|
KeLowerIrql(OldIrql);
|
|||
|
|
|||
|
|
|||
|
return ESUCCESS;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
ARC_STATUS
|
|||
|
HalpFindEnvironmentVariable (
|
|||
|
IN PCHAR Variable,
|
|||
|
OUT PULONG VariableIndex,
|
|||
|
OUT PULONG ValueIndex
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine searches (not case sensitive) the supplied NVRAM image
|
|||
|
for the given Variable.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Variable - Supplies a zero terminated string containing an environment
|
|||
|
variable.
|
|||
|
VariableIndex - Returned byte offset into Environment of the
|
|||
|
Variable if found.
|
|||
|
ValueIndex - Returned byte offset into Environment of the
|
|||
|
value of the Variable if found.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
ESUCCESS - Variable found and indicies returned.
|
|||
|
ENOENT - Variable not found.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PUCHAR String;
|
|||
|
UCHAR Char;
|
|||
|
ULONG Index;
|
|||
|
|
|||
|
//
|
|||
|
// If Variable is null, return immediately.
|
|||
|
//
|
|||
|
|
|||
|
if (*Variable == 0) {
|
|||
|
return ENOENT;
|
|||
|
}
|
|||
|
|
|||
|
Index = 0;
|
|||
|
|
|||
|
while (TRUE) {
|
|||
|
|
|||
|
//
|
|||
|
// Set string to beginning of Variable.
|
|||
|
//
|
|||
|
|
|||
|
String = Variable;
|
|||
|
*VariableIndex = Index;
|
|||
|
|
|||
|
//
|
|||
|
// Search until the end of NVRAM.
|
|||
|
//
|
|||
|
|
|||
|
while ( Index < LENGTH_OF_ENVIRONMENT ) {
|
|||
|
|
|||
|
//
|
|||
|
// Convert to uppercase and break if mismatch.
|
|||
|
//
|
|||
|
|
|||
|
Char = Environment[Index];
|
|||
|
|
|||
|
if ( Char != ((*String >= 'a') && (*String <= 'z') ?
|
|||
|
(*String - 'a' + 'A') : *String) ) {
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
String++;
|
|||
|
Index++;
|
|||
|
}
|
|||
|
|
|||
|
if ( Index == LENGTH_OF_ENVIRONMENT )
|
|||
|
return ENOENT;
|
|||
|
|
|||
|
//
|
|||
|
// Check to see if we're at the end of the string and the variable,
|
|||
|
// which means a match.
|
|||
|
//
|
|||
|
|
|||
|
Char = Environment[Index];
|
|||
|
if ((*String == 0) && (Char == '=')) {
|
|||
|
*ValueIndex = ++Index;
|
|||
|
return ESUCCESS;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Move index to the start of the next variable.
|
|||
|
//
|
|||
|
|
|||
|
do {
|
|||
|
Char = Environment[Index++];
|
|||
|
|
|||
|
if (Index >= LENGTH_OF_ENVIRONMENT) {
|
|||
|
return ENOENT;
|
|||
|
}
|
|||
|
|
|||
|
} while (Char != 0);
|
|||
|
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
#if defined(AXP_FIRMWARE)
|
|||
|
|
|||
|
ARC_STATUS
|
|||
|
HalpEnvironmentCheckChecksum (
|
|||
|
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;
|
|||
|
UCHAR Char;
|
|||
|
PNV_CONFIGURATION NvConfiguration;
|
|||
|
ULONG Index;
|
|||
|
ULONG Checksum1, Checksum2;
|
|||
|
BOOLEAN AllZeroBytes;
|
|||
|
|
|||
|
NvConfiguration = (PNV_CONFIGURATION)NVRAM_CONFIGURATION;
|
|||
|
|
|||
|
//
|
|||
|
// Form checksum from NVRAM data.
|
|||
|
//
|
|||
|
|
|||
|
Checksum1 = 0;
|
|||
|
AllZeroBytes = TRUE;
|
|||
|
NvChars = (PUCHAR)&NvConfiguration->Environment[0];
|
|||
|
|
|||
|
for ( Index = 0 ; Index < LENGTH_OF_ENVIRONMENT; Index++ ) {
|
|||
|
|
|||
|
HalpReadNVRamBuffer(&Char,NvChars++,1);
|
|||
|
Checksum1 += Char;
|
|||
|
if (Char != 0) {
|
|||
|
AllZeroBytes = FALSE;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Reconstitute checksum and return error if no compare.
|
|||
|
//
|
|||
|
|
|||
|
#ifdef EISA_PLATFORM
|
|||
|
HalpReadNVRamBuffer((PCHAR)&Checksum2,&NvConfiguration->Checksum2[0],4);
|
|||
|
#else // EISA_PLATFORM
|
|||
|
HalpReadNVRamBuffer((PCHAR)&Checksum2,&NvConfiguration->Checksum[0],4);
|
|||
|
#endif // EISA_PLATFORM
|
|||
|
|
|||
|
//
|
|||
|
// We return an error condition if the Checksum does not match the sum
|
|||
|
// of all the protected bytes, *or* if all the protected bytes are zero.
|
|||
|
// The latter check covers the condition of a completely zeroed NVRAM;
|
|||
|
// such a condition would appear to have a valid checksum.
|
|||
|
//
|
|||
|
// We do not use a better checksum algorithm because the pain of
|
|||
|
// orchestrating a change in the existing SRM consoles (which read our
|
|||
|
// stored Nvram information for various purposes) has been deemed to be
|
|||
|
// too high.
|
|||
|
//
|
|||
|
|
|||
|
if ((Checksum1 != Checksum2) || (AllZeroBytes == TRUE)) {
|
|||
|
return EIO;
|
|||
|
} else {
|
|||
|
return ESUCCESS;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
ARC_STATUS
|
|||
|
HalpEnvironmentSetChecksum (
|
|||
|
VOID
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine sets the environment area checksum.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PUCHAR NvChars;
|
|||
|
UCHAR Char;
|
|||
|
PNV_CONFIGURATION NvConfiguration;
|
|||
|
ULONG Index;
|
|||
|
ULONG Checksum;
|
|||
|
KIRQL OldIrql;
|
|||
|
|
|||
|
NvConfiguration = (PNV_CONFIGURATION)NVRAM_CONFIGURATION;
|
|||
|
|
|||
|
//
|
|||
|
// Form checksum from NVRAM data.
|
|||
|
//
|
|||
|
|
|||
|
Checksum = 0;
|
|||
|
NvChars = (PUCHAR)&NvConfiguration->Environment[0];
|
|||
|
|
|||
|
KeRaiseIrql(DEVICE_LEVEL, &OldIrql);
|
|||
|
|
|||
|
for ( Index = 0 ; Index < LENGTH_OF_ENVIRONMENT; Index++ ) {
|
|||
|
HalpReadNVRamBuffer(&Char, NvChars ++, 1);
|
|||
|
Checksum += Char;
|
|||
|
}
|
|||
|
|
|||
|
KeLowerIrql(OldIrql);
|
|||
|
|
|||
|
//
|
|||
|
// Write environment checksum.
|
|||
|
//
|
|||
|
|
|||
|
if (
|
|||
|
#ifdef EISA_PLATFORM
|
|||
|
HalpWriteNVRamBuffer((PCHAR)NvConfiguration->Checksum2, (PCHAR)&Checksum, 4)
|
|||
|
#else // EISA_PLATFORM
|
|||
|
HalpWriteNVRamBuffer((PCHAR)NvConfiguration->Checksum, (PCHAR)&Checksum, 4)
|
|||
|
#endif // EISA_PLATFORM
|
|||
|
!= ESUCCESS ) {
|
|||
|
return EIO;
|
|||
|
} else {
|
|||
|
return ESUCCESS;
|
|||
|
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
#endif //AXP_FIRMWARE
|