#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