diff options
Diffstat (limited to 'private/ntos/nthals/halfire/ppc/pxenviro.c')
-rw-r--r-- | private/ntos/nthals/halfire/ppc/pxenviro.c | 729 |
1 files changed, 729 insertions, 0 deletions
diff --git a/private/ntos/nthals/halfire/ppc/pxenviro.c b/private/ntos/nthals/halfire/ppc/pxenviro.c new file mode 100644 index 000000000..55c3677b3 --- /dev/null +++ b/private/ntos/nthals/halfire/ppc/pxenviro.c @@ -0,0 +1,729 @@ +/* + * Copyright (c) 1995 FirePower Systems, Inc. + * DO NOT DISTRIBUTE without permission + * + * $RCSfile: pxenviro.c $ + * $Revision: 1.12 $ + * $Date: 1996/05/18 00:28:50 $ + * $Locker: $ + */ + +/*********************************************************************** + + +Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file +contains copyrighted material. Use of this file is restricted +by the provisions of a Motorola Software License Agreement. + + File Name: + PXENVIRO.C + + Purpose: + Provides the interface to the PowerPC ARC firmware. + + Globals: + none + + Functions: + ULONG HalGetEnvironmentVariable(); + ULONG HalSetEnvironmentVariable(); + + History: + 27-Jul-1993 Steve Johns + Original version + 31-Jan-1994 Steve Johns + Added checksum logic + 08-Jul-1994 Steve Johns + Made Environment variable routines PReP compliant + 12-20-94 + Heavly re-written by Sol Kavy at FirePower to + clean-up the code and properly suppor the Prep spec. + + +NOTES: + + The fields in the NVRAM structure follow Big-Endian byte ordering. + + Each environment variable is stored as an zero-terminated ASCII string: + + <name>=<value>,0 + +***********************************************************************/ + + +#define USE_SPINLOCKS FALSE + +#include "halp.h" +//#include "fpdebug.h" +#include "arccodes.h" +#include "eisa.h" +#include "pxnvrsup.h" +#include "fpnvram.h" + +USHORT HalpComputeCrc(VOID); + +// +// Debug Define (first paramter is a place holder for future +// level handling: 1 = Calls, 2 = Routine Info). +// +#define NDBG(_lvl, _print) + +PKSPIN_LOCK NVRAM_Spinlock; + +#define NVSIZE 4096 + +// +// Location of the NVRAM registers +// +// #include "phsystem.h" +// extern PVOID HalpIoControlBase; +#define NVRAM ((PNVRAM_CONTROL) (HalpIoControlBase)) +// #define NVRAM ((PNVRAM_CONTROL) 0xb1000000) + +// +// Dummy pointer used to byte get offset information +// +PVOID NvramPtr=0; +#define NVMAP ((PHEADER) NvramPtr) + +extern BOOLEAN NvramFailure; + +// +// Use the routine from fpds1385.c to access the nvram chip. These +// routines protect their accesses with the appropriate spin locks +// to make sure the actions are atomic +// + +USHORT +HalpReadNvramUshort(USHORT Index) +{ + return (HalpDS1385ReadNVRAM(Index) << 8) + + HalpDS1385ReadNVRAM((USHORT)(Index+1)); +} + + +ULONG +HalpReadNvramUlong(USHORT Index) +{ + ULONG ReturnValue; + + // + // Read Big-Endian ULONG value & convert to Little-Endian + // + ReturnValue = ((ULONG) HalpReadNvramUshort(Index) << 16) + + (ULONG) HalpReadNvramUshort((USHORT)(Index+2)); + + return ReturnValue; +} + +VOID +HalpWriteNvramUshort(USHORT Index, + USHORT Value) +{ + // + // Write USHORT value in Big-Endian + // + HalpDS1385WriteNVRAM(Index, (UCHAR) (Value >> 8)); + HalpDS1385WriteNVRAM((USHORT)(Index+1),(UCHAR) Value); +} + + +VOID HalpWriteNvramUlong( + USHORT Index, + ULONG Value) +{ + // + // Write ULONG value in Big-Endian + // + HalpWriteNvramUshort(Index, (USHORT) (Value >> 16)); + HalpWriteNvramUshort((USHORT)(Index+2),(USHORT) Value); +} + +// +// DumpNVRAM +// +// Description: +// Used during bring-up to ensure that NVRAM is being handled +// correctly. Nothing more than a bunch of DbgPrint of NVRAM +// +VOID +DumpNVRAM() +{ + DbgPrint("HalpIoControlBase is at 0x%x\n", HalpIoControlBase); + DbgPrint("NVRAM is at 0x%x\n", NVRAM); + DbgPrint("NvramIndexLo is at 0x%x\n", &(NVRAM->NvramIndexLo)); + DbgPrint("NvramIndexHi is at 0x%x\n", &(NVRAM->NvramIndexHi)); + DbgPrint("NvramData is at 0x%x\n", &(NVRAM->NvramData)); + DbgPrint("NVRAM USHORT Size(%d): %d\n", + (USHORT)&NVMAP->Size, + HalpReadNvramUshort((USHORT)&NVMAP->Size)); + DbgPrint("NVRAM UCHAR Version(%d): %d\n", + (USHORT)&NVMAP->Version, + HalpDS1385ReadNVRAM((USHORT)&NVMAP->Version)); + DbgPrint("NVRAM UCHAR Revision(%d): %d\n", + (USHORT)&NVMAP->Revision, + HalpDS1385ReadNVRAM((USHORT)&NVMAP->Revision)); + DbgPrint("NVRAM USHORT Crc1(%d): 0x%x\n", + (USHORT)&NVMAP->Crc1, + HalpReadNvramUshort((USHORT)&NVMAP->Crc1)); + DbgPrint("NVRAM USHORT Crc2(%d): 0x%x\n", + (USHORT)&NVMAP->Crc2, + HalpReadNvramUshort((USHORT)&NVMAP->Crc2)); + DbgPrint("NVRAM UCHAR LastOS(%d): %d\n", + (USHORT)&NVMAP->LastOS, + HalpDS1385ReadNVRAM((USHORT)&NVMAP->LastOS)); + DbgPrint("NVRAM UCHAR Endian(%d): %d\n", + (USHORT)&NVMAP->Endian, + HalpDS1385ReadNVRAM((USHORT)&NVMAP->Endian)); + DbgPrint("NVRAM UCHAR OSAreaUsage(%d): %d\n", + (USHORT)&NVMAP->OSAreaUsage, + HalpDS1385ReadNVRAM((USHORT)&NVMAP->OSAreaUsage)); + DbgPrint("NVRAM UCHAR PMMode(%d): %d\n", + (USHORT)&NVMAP->PMMode, + HalpDS1385ReadNVRAM((USHORT)&NVMAP->PMMode)); + DbgPrint("NVRAM ULONG GEAddress(%d): %d\n", + (USHORT)&NVMAP->GEAddress, + HalpReadNvramUlong((USHORT)&NVMAP->GEAddress)); + DbgPrint("NVRAM ULONG GELength(%d): %d\n", + (USHORT)&NVMAP->GELength, + HalpReadNvramUlong((USHORT)&NVMAP->GELength)); + { + USHORT StartIndex, LastIndex, Index; + UCHAR NvramChar; + BOOLEAN LastNull = TRUE; // Assume it + + DbgPrint("NVRAM Global Environment Area:\n"); + + StartIndex = (USHORT) HalpReadNvramUlong((USHORT) (&NVMAP->GEAddress)); + LastIndex = (USHORT) HalpReadNvramUlong((USHORT) (&NVMAP->GELength)); + LastIndex += StartIndex - 1; + for (Index = StartIndex; Index <= LastIndex; Index++) { + NvramChar = HalpDS1385ReadNVRAM(Index); + if (NvramChar == '\0') { + LastNull = TRUE; + } else { + if (LastNull == TRUE) { + DbgPrint("\n[%d]: ", Index); + } + DbgPrint("%c", NvramChar); + LastNull = FALSE; + } + } + DbgPrint("\n"); + } + + DbgPrint("Checking Our version of CRC"); + DbgPrint("Compute CRC returns 0x%x\n", HalpComputeCrc()); +} + +UCHAR +HalpGetEnvironmentInfo( + OPTIONAL PUSHORT TotalSize, + OPTIONAL PUSHORT FreeSize, + OPTIONAL PULONG pCrc) +{ + USHORT Index; + USHORT InUse, TotalLength; + UCHAR DataByte1, DataByte2; + + NDBG(1, DbgPrint("HalpGetEnvironmentInfo: called\n");); + + TotalLength = (USHORT) HalpReadNvramUlong((USHORT) &NVMAP->GELength); + if (TotalSize != NULL) + *TotalSize = TotalLength; + + if (FreeSize != NULL) { + // + // Compute how much NVRAM is in use + // + InUse = 0; + Index = (USHORT)HalpReadNvramUlong ((USHORT) &NVMAP->GEAddress); + DataByte1 = HalpDS1385ReadNVRAM(Index++); + DataByte2 = DataByte1; + while (DataByte1 | DataByte2) { + DataByte1 = DataByte2; + DataByte2 = HalpDS1385ReadNVRAM(Index++); + InUse++; + } + *FreeSize = TotalLength - InUse; + } + + if (pCrc != NULL) { + *pCrc = HalpReadNvramUshort((USHORT) &NVMAP->Crc1); + } + return(HalpDS1385ReadNVRAM((USHORT) &NVMAP->Version)); +} + +// +// HalpAddByteCrc +// +// Description: +// Use the X^16 + X^12 + X^5 + 1, Polynomial for CRC +// +// Input: +// Stored in NVRAM +// +// Output: +// New Crc Value +// +USHORT +HalpAddByteCrc(USHORT CurrentCrc, USHORT Index) +{ + UCHAR Byte; + UCHAR CrcLo, CrcHi; + USHORT x,y,z; + + + Byte = HalpDS1385ReadNVRAM(Index); + CrcLo = CurrentCrc &0xff; + CrcHi = CurrentCrc >> 8; + x = (CrcLo << 8) | (CrcHi^Byte); + y = (CrcHi^Byte) << 8; + z = ((y >> 12) | (y << 4)) & 0xf00f; + x = x^z; + z = ((y << 13) | (y >> 3)) & 0x1fe0; + x = x^z; + z = y&0xf000; + x = x^z; + z = ((y<<9) | (y>>7)) & 0x1e0; + x = x^z; + return(x); +} + +// +// HalpComputeCrc +// +// Description: +// Find the parts that are part of the crc and compute the +// crc against them. +// +// Input: +// Stored in NVRAM +// +// Output: +// +USHORT +HalpComputeCrc(VOID) +{ + USHORT CurrentCrc = 0xffff; + USHORT Index, EndIndex; + + // + // Loop through different parts computing CRC + // This is from Size to Revision inclusive + // + for (Index = 0; Index <= 3; Index++) { + CurrentCrc = HalpAddByteCrc(CurrentCrc, Index); + } + + // + // Compute ending offset + // + EndIndex = (USHORT) HalpReadNvramUlong((USHORT) (&NVMAP->OSAreaAddress)); + + // + // Loop through second half + // This is from LastOS to OSArea (Note: 9 should be 8; however, + // IBM screwed up and we are all just going along with it). + // + for (Index = 9; Index < EndIndex; Index++) { + CurrentCrc = HalpAddByteCrc(CurrentCrc, Index); + } + return(CurrentCrc); +} + + +// +// HalpUpdateCrc +// +// Description: +// Compute the required Crc value and update the Header. This +// code only updates crc1. +// +VOID +HalpUpdateCrc() +{ + ULONG Crc; + + NDBG(1, DbgPrint("HalpUpdateCrc: called\n");); + Crc = HalpComputeCrc(); + HalpWriteNvramUshort((USHORT) &NVMAP->Crc1, (USHORT) Crc); +} + +// +// Returns the number of bytes removed +// +USHORT +HalpCompressEnvironmentSpace(IN USHORT StartIndex) +{ + USHORT Index, BytesRemoved; + UCHAR PreviousChar, NvramChar; + + Index = StartIndex+1; + while(HalpDS1385ReadNVRAM(Index++) != '=') { + /* Do Nothing */ + } + while(HalpDS1385ReadNVRAM(Index++) != 0) { + /* Do Nothing */ + } + BytesRemoved = Index - StartIndex; // Adjust amount of free space + + NvramChar = 0; + // + // Copy subsequent variables + // + do { + PreviousChar = NvramChar; + NvramChar = HalpDS1385ReadNVRAM(Index++); + HalpDS1385WriteNVRAM(StartIndex++, NvramChar); + } while (PreviousChar | NvramChar); + + // + // Make sure unused NVRAM area is zeroed + // + for (Index=0; Index <BytesRemoved; Index++) { + if (Index+StartIndex >= NVSIZE) { + break; + } + HalpDS1385WriteNVRAM((USHORT)(Index+StartIndex), 0); + } + return(BytesRemoved); +} + +// +//HalpFindEnviroVar +// Description: +// Searches the NVRAM for an environment variable. +// +// Parameters: +// Variable - ptr to the variable to search for. +// +// Return value: +// The NVRAM index where the environment variable's VALUE is stored. +// Returns 0 if the variable was not found. +// +// Assumes NVRAM_Spinlock has already been acquired by the caller. +// +USHORT +HalpFindEnviroVar(IN CHAR *Variable) +{ + USHORT Index, StartIndex, LastIndex; + CHAR *VariablePtr, UserChar, NvramChar; + + NDBG(1, DbgPrint("HalpFindEnviroVar: called for %s\n", Variable);); + + StartIndex = (USHORT) HalpReadNvramUlong((USHORT) (&NVMAP->GEAddress)); + LastIndex = (USHORT) HalpReadNvramUlong((USHORT) (&NVMAP->GELength)); + LastIndex += StartIndex - 1; + + + // + // Search the NVRAM for the variable. + // + VariablePtr = Variable; + for (Index = StartIndex ; Index <= LastIndex; ) { + // + // Get a character from the NVRAM + // + NvramChar = HalpDS1385ReadNVRAM(Index++); + if (NvramChar == 0) { + break; + } + + // + // Are we at the end of the variable name in both the + // input string and the NVRAM ? + // If so, then it is an exact match. Return the NVRAM index. + // + UserChar = *VariablePtr++; + if (UserChar == 0 && NvramChar == '=') { + NDBG(2, DbgPrint("HalpFindEnviroVar: found %s at %d\n", + Variable, Index);); + return(Index); + } + + // + // Convert variable to UPPER case + // + UserChar = (UserChar >= 'a' && UserChar <= 'z') ? + UserChar-0x20 : UserChar; + + // + // Is there a match on this character ? + // + + if (UserChar != NvramChar) { + // + // No, then skip over this variable in NVRAM and begin + // search again at start of variable NAME. + // + VariablePtr = Variable; + while (Index <= LastIndex) { + NvramChar = HalpDS1385ReadNVRAM(Index++); + if (NvramChar == '=') + break; + } + while (Index <= LastIndex) { + NvramChar = HalpDS1385ReadNVRAM(Index++); + if (NvramChar == 0) { + break; + } + } + } + } + + // + // The variable was not found + // + NDBG(2, DbgPrint("HalpFindEnviroVar: %s not found\n", Variable);); + return(0); +} + +// +// HalGetEnvironmentVariable +// +// Parameters: +// +// Variables: +// Supplies a pointer to the zero-terminated, case ASCII string that contains +// the name of the environment variable to be returned. +// Length - Supplies the length of the buffer in bytes. +// Buffer - Supplies a pointer to a buffer that receives the variable value. +// +// Return Value: +// If the variable, the function returns the value ESUCCESS and its +// value in Buffer. Otherwise, ENOENT is returned. +// +ULONG +HalGetEnvironmentVariable(IN CHAR *Variable, + IN USHORT Length, + OUT CHAR *Buffer) +{ + USHORT Index; + static DumpNVRAMOnce = FALSE; + ULONG retVal = ENOENT + + + NDBG(1, DbgPrint("HalpGetEnvironmentVariable: called\n");); + + // + // Check input parameters + // + if (!Variable) { + if (*Variable == 0 || Length < 1 || Buffer == NULL) { + NDBG(2, DbgPrint("HalpGetEnvironmentVariable: return ENOENT\n");); + return(retVal); + } + } + + if (!DumpNVRAMOnce) { + NDBG(2, DumpNVRAM();); + DumpNVRAMOnce = TRUE; + } + + // + // Grab control of NVRAM + // +#if USE_SPINLOCKS + KIRQL Irql; + KeAcquireSpinLock(NVRAM_Spinlock, &Irql); +#endif + NvramFailure = FALSE; + + // + // Get NVRAM index of environment variable + // + Index = HalpFindEnviroVar(Variable); + if (Index == 0) { + // + // Environment variable was not found + // +#if USE_SPINLOCKS + KeReleaseSpinLock(NVRAM_Spinlock, Irql); +#endif + return(retVal); + } + + // + // Copy the environment variable's value to Buffer + // + do { + *Buffer = HalpDS1385ReadNVRAM(Index++); + if (*Buffer++ == 0) { + if (NvramFailure == TRUE) { + retVal = ENOMEM; + } else { + retVal = ESUCCESS; + } +#if USE_SPINLOCKS + KeReleaseSpinLock(NVRAM_Spinlock, Irql); +#endif + return(retVal); + } + } while (--Length); + + // + // Truncate the returned string. The buffer was too short. + // + *--Buffer = 0; +#if USE_SPINLOCKS + KeReleaseSpinLock(NVRAM_Spinlock, Irql); +#endif + return(ENOMEM); +} + +// +// HalSetEnvironmentVariable +// +// Parameters: +// Variable +// Supplies a pointer to the zero-terminated ASCII string that contains +// the name of the environment variable to be returned. The string is +// converted to UPPER CASE. +// +// Value +// Supplies a pointer to the zero-terminated string that contains the new +// value of the environment variable. +// +// There are 4 cases: +// 1) The environment variable is deleted if Value is a null string. +// 2) The environment variable does not currently exist. It is appended +// if there is enough NVRAM available. +// 3) The environment variable already exists, and the new Value is +// shorter than the old value. +// 4) The environment variable already exists, and the new Value is longer than +// the old value. +// +// In all cases the environment space will be compressed after +// insertion/deletion. +// +ULONG +HalSetEnvironmentVariable( + IN CHAR *Variable, + IN CHAR *Value) +{ + USHORT TotalSize, FreeSize, Index; + USHORT OldLength, NewLength; + USHORT StartIndex; + USHORT i; + USHORT NameLength, ValueLength; + CHAR *VariablePtr, *ValuePtr, Char; + ARC_STATUS ReturnValue; + + + NDBG(1, DbgPrint("HalSetEnvironmentVariable: called set %s to %s\n", + Variable, Value);); + + if (Value == NULL) { + NDBG(2, DbgPrint("HalSetEnvironmentVariable: returning ENOENT\n");); + return(ENOENT); + } + + // + // Compute length of environment NAME + // + VariablePtr = Variable; + NameLength = 0; + while (*VariablePtr != 0) { + NameLength++; + VariablePtr++; + } + + // + // Compute length of environment VALUE + // + ValuePtr = Value; + ValueLength = 0; + while (*ValuePtr != 0) { + ValueLength++; + ValuePtr++; + } +#if USE_SPINLOCKS + KIRQL Irql; + KeAcquireSpinLock(NVRAM_Spinlock, &Irql); // Grab control of NVRAM +#endif + NvramFailure = FALSE; + + HalpGetEnvironmentInfo(&TotalSize, &FreeSize, NULL); + + + // Get index of environment variable + Index = HalpFindEnviroVar(Variable); + + ReturnValue = ESUCCESS; + // Index to start of NAME + StartIndex = Index-NameLength-1; + + // DELETE environment variable + if (ValueLength == 0) { + if (Index != 0) { + HalpCompressEnvironmentSpace(StartIndex); + } + } else { + // ADD or REPLACE environment variable + // Compute # bytes needed to store variable + NewLength = ValueLength + NameLength + 2; + + + // REPLACE environment variable. + // First we see if there is room. If so, delete the current + // variable & fall through to the code that ADDs a new variable. + if (Index != 0) { + // Compute current length of variable + OldLength = 0; + i = Index; + do { + OldLength++; + } while (HalpDS1385ReadNVRAM(i++) != 0); + + // Is there room for the new variable ? + if (FreeSize-NewLength+OldLength >= 0) + FreeSize += HalpCompressEnvironmentSpace(StartIndex); + } + // + // ADD environment variable + // + + if ((FreeSize-NewLength) >= 0) { // Room for new + + Index = (USHORT) HalpReadNvramUlong((USHORT) (&NVMAP->GEAddress)); + Index += (USHORT) HalpReadNvramUlong((USHORT) (&NVMAP->GELength)); + Index -= FreeSize; + + // + // Write Variable NVRAM. Convert to UPPER case first. + // + while (*Variable != 0) { + Char = *Variable++; + // + // Convert Variable to UPPER case + // + Char = (Char >= 'a' && Char <= 'z') ? Char-0x20 : Char; + HalpDS1385WriteNVRAM(Index++,Char); + } + + HalpDS1385WriteNVRAM(Index++,'='); // Write a "=" + + do { + // Write VALUE to NVRAM + HalpDS1385WriteNVRAM(Index++,*Value); + } while (*Value++ != 0); + + ReturnValue = ESUCCESS; + } + } + + // + // Update NVRAM checksum + // + HalpUpdateCrc(); + if (NvramFailure == TRUE) { + ReturnValue = ENOMEM; + } +#if USE_SPINLOCKS + KeReleaseSpinLock(NVRAM_Spinlock, Irql); +#endif + return(ReturnValue); +} + + |