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.
 
 
 
 
 
 

502 lines
10 KiB

#if defined(JAZZ)
/*++
Copyright (c) 1991 Microsoft Corporation
Module Name:
jxenvir.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, for a MIPS R3000 or R4000 Jazz system.
Author:
David M. Robinson (davidro) 13-June-1991
Revision History:
--*/
#include "fwp.h"
//
// Static data.
//
UCHAR OutputString[MAXIMUM_ENVIRONMENT_VALUE];
PCHAR VolatileEnvironment;
//
// Routine prototypes.
//
VOID
FwEnvironmentSetChecksum (
VOID
);
ARC_STATUS
FwFindEnvironmentVariable (
IN PCHAR Variable,
OUT PULONG VariableIndex,
OUT PULONG ValueIndex
);
VOID
FwEnvironmentInitialize (
VOID
)
/*++
Routine Description:
This routine initializes the environment routine addresses.
Arguments:
None.
Return Value:
None.
--*/
{
//
// Allocate enough memory to load the environment for loaded programs.
//
VolatileEnvironment = FwAllocatePool(LENGTH_OF_ENVIRONMENT);
//
// Initialize the environment routine addresses in the system
// parameter block.
//
(PARC_GET_ENVIRONMENT_ROUTINE)SYSTEM_BLOCK->FirmwareVector[GetEnvironmentRoutine] =
FwGetEnvironmentVariable;
(PARC_SET_ENVIRONMENT_ROUTINE)SYSTEM_BLOCK->FirmwareVector[SetEnvironmentRoutine] =
FwSetEnvironmentVariable;
return;
}
VOID
FwEnvironmentSetChecksum (
VOID
)
/*++
Routine Description:
This routine sets the environment area checksum.
Arguments:
None.
Return Value:
None.
--*/
{
PUCHAR NvChars;
PNV_CONFIGURATION NvConfiguration;
ULONG Index;
ULONG Checksum;
NvConfiguration = (PNV_CONFIGURATION)NVRAM_CONFIGURATION;
//
// Form checksum from NVRAM data.
//
Checksum = 0;
NvChars = (PUCHAR)&NvConfiguration->Environment[0];
for ( Index = 0 ;
Index < LENGTH_OF_ENVIRONMENT;
Index++ ) {
Checksum += READ_REGISTER_UCHAR( NvChars++ );
}
//
// Write environment checksum.
//
WRITE_REGISTER_UCHAR( &NvConfiguration->Checksum2[0],
(UCHAR)(Checksum & 0xFF));
WRITE_REGISTER_UCHAR( &NvConfiguration->Checksum2[1],
(UCHAR)((Checksum >> 8) & 0xFF));
WRITE_REGISTER_UCHAR( &NvConfiguration->Checksum2[2],
(UCHAR)((Checksum >> 16) & 0xFF));
WRITE_REGISTER_UCHAR( &NvConfiguration->Checksum2[3],
(UCHAR)(Checksum >> 24));
}
PCHAR
FwGetEnvironmentVariable (
IN PCHAR Variable
)
/*++
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.
Return Value:
If successful, returns a zero terminated string that is the value of
Variable, otherwise NULL is returned.
--*/
{
PNV_CONFIGURATION NvConfiguration;
ULONG VariableIndex;
ULONG ValueIndex;
ULONG Outdex;
NvConfiguration = (PNV_CONFIGURATION)NVRAM_CONFIGURATION;
//
// If checksum is wrong, or the variable can't be found, return NULL.
//
if ((FwEnvironmentCheckChecksum() != ESUCCESS) ||
(FwFindEnvironmentVariable(Variable, &VariableIndex, &ValueIndex) != ESUCCESS)) {
return NULL;
}
//
// Copy value to an output string, break on zero terminator or string max.
//
for ( Outdex = 0 ; Outdex < (MAXIMUM_ENVIRONMENT_VALUE - 1) ; Outdex++ ) {
if (NvConfiguration->Environment[ValueIndex] == 0) {
break;
}
OutputString[Outdex] =
READ_REGISTER_UCHAR( &NvConfiguration->Environment[ValueIndex++] );
}
//
// Zero terminate string, and return.
//
OutputString[Outdex] = 0;
return OutputString;
}
ARC_STATUS
FwSetEnvironmentVariable (
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:
Returns ESUCCESS if the set completed successfully, otherwise one of
the following error codes is returned.
ENOSPC No space in NVRAM for set operation.
EIO Invalid Checksum.
--*/
{
PNV_CONFIGURATION NvConfiguration;
ULONG VariableIndex;
ULONG ValueIndex;
ULONG TopOfEnvironment;
PCHAR String;
ULONG Count;
CHAR Char;
NvConfiguration = (PNV_CONFIGURATION)NVRAM_CONFIGURATION;
//
// If checksum is wrong, return EIO;
//
if (FwEnvironmentCheckChecksum() != ESUCCESS) {
return EIO;
}
//
// Determine the top of the environment space by looking for the first
// non-null character from the top.
//
TopOfEnvironment = LENGTH_OF_ENVIRONMENT - 1;
while (READ_REGISTER_UCHAR( &NvConfiguration->Environment[--TopOfEnvironment]) == 0) {
if (TopOfEnvironment == 0) {
break;
}
}
//
// Adjust TopOfEnvironment to the first new character, unless environment
// space is empty.
//
if (TopOfEnvironment != 0) {
TopOfEnvironment += 2;
}
//
// Check to see if the variable already has a value.
//
Count = LENGTH_OF_ENVIRONMENT - TopOfEnvironment;
if (FwFindEnvironmentVariable(Variable, &VariableIndex, &ValueIndex) == ESUCCESS) {
//
// Count free space, starting with the free area at the top and adding
// the old variable value.
//
for ( String = &NvConfiguration->Environment[ValueIndex] ;
READ_REGISTER_UCHAR( String ) != 0 ;
String++ ) {
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) {
return ENOSPC;
}
}
//
// Move ValueIndex to the end of the value and compress strings.
//
while(READ_REGISTER_UCHAR( &NvConfiguration->Environment[ValueIndex++]) != 0) {
}
while (ValueIndex < TopOfEnvironment ) {
Char = READ_REGISTER_UCHAR( &NvConfiguration->Environment[ValueIndex++] );
WRITE_REGISTER_UCHAR( &NvConfiguration->Environment[VariableIndex++], Char);
}
//
// Adjust new top of environment.
//
TopOfEnvironment = VariableIndex;
//
// Zero to the end.
//
while (VariableIndex < LENGTH_OF_ENVIRONMENT) {
WRITE_REGISTER_UCHAR( &NvConfiguration->Environment[VariableIndex++],
0);
}
//
// Variable is new.
//
} else {
//
// Determine if free area is large enough to handle new value, if not
// return error.
//
for ( String = Value ; *String != 0 ; String++ ) {
if (Count-- == 0) {
return ENOSPC;
}
}
}
//
// If Value is not zero, write new variable and value.
//
if (*Value != 0) {
//
// Write new variable, converting to upper case.
//
while (*Variable != 0) {
WRITE_REGISTER_UCHAR( &NvConfiguration->Environment[TopOfEnvironment++],
((*Variable >= 'a') &&
(*Variable <= 'z') ?
(*Variable - 'a' + 'A') : *Variable));
Variable++;
}
//
// Write equal sign.
//
WRITE_REGISTER_UCHAR( &NvConfiguration->Environment[TopOfEnvironment++], '=');
//
// Write new value.
//
while (*Value != 0) {
WRITE_REGISTER_UCHAR( &NvConfiguration->Environment[TopOfEnvironment++],
*Value++);
}
}
//
// Set checksum.
//
FwEnvironmentSetChecksum();
return ESUCCESS;
}
ARC_STATUS
FwFindEnvironmentVariable (
IN PCHAR Variable,
OUT PULONG VariableIndex,
OUT PULONG ValueIndex
)
/*++
Routine Description:
This routine searches (not case sensitive) the non-volatile ram for
Variable.
Arguments:
Variable - Supplies a zero terminated string containing an environment
variable.
Return Value:
If successful, returns ESUCCESS, otherwise returns ENOENT.
--*/
{
PNV_CONFIGURATION NvConfiguration;
PUCHAR String;
PUCHAR Environment;
ULONG Index;
NvConfiguration = (PNV_CONFIGURATION)NVRAM_CONFIGURATION;
//
// If Variable is null, return immediately.
//
if (*Variable == 0) {
return ENOENT;
}
Environment = NvConfiguration->Environment;
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.
//
if ( READ_REGISTER_UCHAR( &Environment[Index] ) !=
((*String >= 'a') &&
(*String <= 'z') ?
(*String - 'a' + 'A') : *String) ) {
break;
}
String++;
Index++;
}
//
// Check to see if we're at the end of the string and the variable,
// which means a match.
//
if ((*String == 0) && (READ_REGISTER_UCHAR( &Environment[Index] ) == '=')) {
*ValueIndex = ++Index;
return ESUCCESS;
}
//
// Move index to the start of the next variable.
//
while (READ_REGISTER_UCHAR( &Environment[Index++] ) != 0) {
if (Index >= LENGTH_OF_ENVIRONMENT) {
return ENOENT;
}
}
}
}
#endif