503 lines
10 KiB
C
503 lines
10 KiB
C
|
#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
|
|||
|
|