Leaked source code of windows server 2003
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.
 
 
 
 
 
 

1297 lines
35 KiB

/*++
Copyright (c) 1995 Intel Corporation
Module Name:
i64fw.c
Abstract:
This module implements the routines that transfer control
from the kernel to the PAL and SAL code.
Author:
Arad Rostampour ([email protected]) Mar-21-99
Environment:
Kernel mode
Revision History:
--*/
#include "halp.h"
#include "arc.h"
#include "arccodes.h"
#include "i64fw.h"
#include <efi.h>
extern KSPIN_LOCK HalpSalSpinLock;
extern KSPIN_LOCK HalpSalStateInfoSpinLock;
BOOLEAN
MmSetPageProtection(
IN PVOID VirtualAddress,
IN SIZE_T NumberOfBytes,
IN ULONG NewProtect
);
VOID
HalpReboot (
VOID
);
HALP_SAL_PAL_DATA HalpSalPalData;
ULONGLONG HalpSalProcPointer=0;
ULONGLONG HalpSalProcGlobalPointer=0;
ULONGLONG HalpPhysSalProcPointer=0;
ULONGLONG HalpPhysSalProcGlobalPointer=0;
ULONGLONG HalpPhysPalProcPointer=0;
ULONGLONG HalpVirtPalProcPointer=0;
// Testing #defines
//
//#define SAL_TEST
//#define PAL_TEST
#if DBG
ULONG HalpDebugTestSalPalCall=0;
#endif
LONGLONG
HalCallPal(
IN ULONGLONG FunctionIndex,
IN ULONGLONG Arguement1,
IN ULONGLONG Arguement2,
IN ULONGLONG Arguement3,
OUT PULONGLONG ReturnValue0,
OUT PULONGLONG ReturnValue1,
OUT PULONGLONG ReturnValue2,
OUT PULONGLONG ReturnValue3
)
/*++
--*/
{
//
// Will interface to PAL Calls.
//
LONGLONG Status;
SAL_PAL_RETURN_VALUES rv = {0};
PSAL_PAL_RETURN_VALUES p = &rv;
Status = (LONGLONG) HalpPalCall(FunctionIndex,Arguement1,Arguement2,Arguement3,p);
if (ReturnValue0 != 0) // Check the pointer is not NULL
*ReturnValue0 = (ULONGLONG)(p -> ReturnValues[0]);
if (ReturnValue1 != 0) // check the pointer is not NULL
*ReturnValue1 = (ULONGLONG)(p -> ReturnValues[1]);
if (ReturnValue2 != 0) // check the pointer is not NULL
*ReturnValue2 = (ULONGLONG)(p -> ReturnValues[2]);
if (ReturnValue3 != 0) // check the pointer is not NULL
*ReturnValue3 = (ULONGLONG)(p -> ReturnValues[3]);
return Status;
}
SAL_PAL_RETURN_VALUES
HalpSalProcPhysical(
IN LONGLONG FunctionId,
IN LONGLONG Arg1,
IN LONGLONG Arg2,
IN LONGLONG Arg3,
IN LONGLONG Arg4,
IN LONGLONG Arg5,
IN LONGLONG Arg6,
IN LONGLONG Arg7
)
/*++
Routine Description:
This function is a wrapper for making a physical mode SAL call. This
function's only job is to provide the stack and backing store pointers
needed by HalpSalProcPhysicalEx.
Arguments:
FunctionId - The SAL function ID.
Arg1 through Arg7 - The values to be passed to SAL_PROC.
Return Value:
A SAL_PAL_RETURN_VALUES structure filled in with the data returned by
HalpSalProcPhysicalEx.
--*/
{
ULONGLONG StackPointer;
ULONGLONG BackingStorePointer;
ULONGLONG StackBase;
//
// Load the addresses of the stack and backing store reserved for
// physical mode SAL calls on this processor.
//
StackBase = PCR->HalReserved[PROCESSOR_PHYSICAL_FW_STACK_INDEX];
StackPointer = GET_FW_STACK_POINTER(StackBase);
BackingStorePointer = GET_FW_BACKING_STORE_POINTER(StackBase);
//
// Branch to the assembly routine that makes the actual SAL call.
//
return HalpSalProcPhysicalEx(
FunctionId,
Arg1,
Arg2,
Arg3,
Arg4,
Arg5,
Arg6,
Arg7,
(LONGLONG) StackPointer,
(LONGLONG) BackingStorePointer
);
}
SAL_STATUS
HalpSalCall(
IN LONGLONG FunctionId,
IN LONGLONG Arg1,
IN LONGLONG Arg2,
IN LONGLONG Arg3,
IN LONGLONG Arg4,
IN LONGLONG Arg5,
IN LONGLONG Arg6,
IN LONGLONG Arg7,
OUT PSAL_PAL_RETURN_VALUES ReturnValues
)
/*++
Routine Description:
This function is a wrapper function for making a SAL call. Callers within the
HAL must use this function to call the SAL.
Arguments:
FunctionId - The SAL function ID
Arg1-Arg7 - SAL defined arguments for each call
ReturnValues - A pointer to an array of 4 64-bit return values
Return Value:
SAL's return status, return value 0, is returned in addition to the ReturnValues structure
being filled
--*/
{
KIRQL OldIrql;
KIRQL TempIrql;
BOOLEAN fixLogId;
HALP_SAL_PROC SalProc;
//
// Zero out the return buffer.
//
RtlZeroMemory(ReturnValues,sizeof(SAL_PAL_RETURN_VALUES));
//
// Choose a SAL call dispatcher depending upon whether a virtual mapping
// for the SAL exists. If a virtual mapping isn't in place we'll try
// to make the call in physical mode. Return SAL_STATUS_NOT_IMPLEMENTED
// if we aren't configured to make calls in either mode.
//
if (!NT_SUCCESS(HalpSalPalData.Status) || HalpSalProcPointer == 0) {
//
// We've already ruled out a virtual mode call. If possible
// we'll try to make an equivalent physical mode call in this
// case.
//
if (HalpPhysSalProcPointer != 0) {
SalProc = HalpSalProcPhysical;
} else {
return SAL_STATUS_NOT_IMPLEMENTED;
}
} else {
SalProc = HalpSalProc;
}
fixLogId = (HalpSalPalData.Flags & HALP_SALPAL_FIX_MCE_LOG_ID) != 0;
KeRaiseIrql(HIGH_LEVEL, &OldIrql);
switch (FunctionId) {
// These calls are neither re-entrant, nor MP-safe as defined by the SAL spec
case SAL_SET_VECTORS:
case SAL_MC_SET_PARAMS:
case SAL_FREQ_BASE:
KiAcquireSpinLock(&HalpSalSpinLock);
*ReturnValues = SalProc(FunctionId,Arg1,Arg2,Arg3,Arg4,Arg5,Arg6,Arg7);
KiReleaseSpinLock(&HalpSalSpinLock);
break;
case SAL_GET_STATE_INFO:
KiAcquireSpinLock(&HalpSalStateInfoSpinLock);
*ReturnValues = SalProc(FunctionId,Arg1,Arg2,Arg3,Arg4,Arg5,Arg6,Arg7);
if ( fixLogId && (ReturnValues->ReturnValues[0] >= (LONGLONG)0) ) {
// ERROR_RECORD_HEADER.Id++
*(PULONGLONG)((ULONGLONG)Arg3) = ++HalpSalPalData.Reserved[0];
}
KiReleaseSpinLock(&HalpSalStateInfoSpinLock);
break;
case SAL_GET_STATE_INFO_SIZE:
case SAL_CLEAR_STATE_INFO:
KiAcquireSpinLock(&HalpSalStateInfoSpinLock);
*ReturnValues = SalProc(FunctionId,Arg1,Arg2,Arg3,Arg4,Arg5,Arg6,Arg7);
KiReleaseSpinLock(&HalpSalStateInfoSpinLock);
break;
case SAL_PCI_CONFIG_READ:
case SAL_PCI_CONFIG_WRITE:
KiAcquireSpinLock(&HalpSalSpinLock);
*ReturnValues = SalProc(FunctionId,Arg1,Arg2,Arg3,Arg4,Arg5,Arg6,Arg7);
KiReleaseSpinLock(&HalpSalSpinLock);
break;
//
// Move these to MP safe after SAL is fixed
// Kernel ensures only one CACHE_FLUSH at a time
//
case SAL_CACHE_INIT:
case SAL_CACHE_FLUSH:
if ( HalpSalPalData.Flags & HALP_SALPAL_FIX_MP_SAFE ) {
KiAcquireSpinLock(&HalpSalSpinLock);
*ReturnValues = SalProc(FunctionId,Arg1,Arg2,Arg3,Arg4,Arg5,Arg6,Arg7);
KiReleaseSpinLock(&HalpSalSpinLock);
}
else
*ReturnValues = SalProc(FunctionId,Arg1,Arg2,Arg3,Arg4,Arg5,Arg6,Arg7);
break;
//
// These SAL calls are MP-safe, but not re-entrant
//
case SAL_MC_RENDEZ:
*ReturnValues = SalProc(FunctionId,Arg1,Arg2,Arg3,Arg4,Arg5,Arg6,Arg7);
break;
//
// These calls are not supported at this time
//
case SAL_UPDATE_PAL: // needs end of firmware space to be mapped, and possible authentication code to execute
default:
ReturnValues->ReturnValues[0] = SAL_STATUS_NOT_IMPLEMENTED;
}
KeLowerIrql(OldIrql);
#ifdef SAL_TEST
if (ReturnValues->ReturnValues[0] == SAL_STATUS_NOT_IMPLEMENTED) {
InternalTestSal(FunctionId,Arg1,Arg2,Arg3,Arg4,Arg5,Arg6,Arg7,ReturnValues);
}
#endif
#if 0
// To avoid Kd hangs while flushing and then MP synchronization issues..
HalDebugPrint(( HAL_INFO,
"HAL: Got out of SAL call #0x%I64x with status 0x%I64x and RetVals 0x%I64x, 0x%I64x, 0x%I64x\n",
FunctionId,
ReturnValues->ReturnValues[0],
ReturnValues->ReturnValues[1],
ReturnValues->ReturnValues[2],
ReturnValues->ReturnValues[3] ));
#endif
return (ReturnValues->ReturnValues[0]);
}
PAL_STATUS
HalpPalCall(
IN LONGLONG FunctionId,
IN LONGLONG Arg1,
IN LONGLONG Arg2,
IN LONGLONG Arg3,
OUT PSAL_PAL_RETURN_VALUES ReturnValues
)
/*++
Routine Description:
This function is a wrapper function for making a PAL call. Callers within the
HAL must use this function to call the PAL.
Arguments:
FunctionId - The PAL function ID
Arg1-Arg3 - PAL defined arguments for each call
ReturnValues - A pointer to an array of 4 64-bit return values
Return Value:
PAL's return status, return value 0, is returned in addition to the ReturnValues structure
being filled
Assumptions:
PAL is being called with psr.bn = 1 in all cases (not from an interrupted state)
--*/
{
// Zero out the return buffer
RtlZeroMemory(ReturnValues,sizeof(SAL_PAL_RETURN_VALUES));
// Only allow PAL calls that are supported
switch (FunctionId) {
// Virtual mode PAL calls
case PAL_CACHE_FLUSH:
case PAL_CACHE_INFO:
case PAL_CACHE_PROT_INFO:
case PAL_CACHE_SUMMARY:
case PAL_PTCE_INFO:
case PAL_VM_INFO:
case PAL_VM_PAGE_SIZE:
case PAL_VM_SUMMARY:
case PAL_PERF_MON_INFO:
case PAL_MC_CLEAR_LOG:
case PAL_MC_DRAIN:
case PAL_MC_ERROR_INFO:
case PAL_HALT_LIGHT:
case PAL_PREFETCH_VISIBILITY:
case PAL_SHUTDOWN:
case PAL_FREQ_RATIOS:
case PAL_VERSION:
case PAL_MEM_ATTRIB:
case PAL_DEBUG_INFO:
case PAL_FIXED_ADDR:
case PAL_FREQ_BASE:
case PAL_PLATFORM_ADDR:
case PAL_REGISTER_INFO:
case PAL_RSE_INFO:
// PAL is MP-safe, but not re-entrant, HalpPalProc/HalpPalProcPhysicalStatic disables interrupts.
//
// FIXFIX: Temporary solution to make sure we have a valid Pal TR per processor
// to make virtual PAL calls.
// PCR->HalReserved[ PROCESSOR_PHYSICAL_FW_STACK_INDEX] gets set for every processor
// by call to HalpAllocateProcessorPhysicalCallStacks during SalPal init
//
if (HalpVirtPalProcPointer && PCR->HalReserved[PROCESSOR_PHYSICAL_FW_STACK_INDEX]) {
*ReturnValues = HalpPalProc(FunctionId,Arg1,Arg2,Arg3);
} else if (HalpPhysPalProcPointer) {
// call in physical mode
*ReturnValues = HalpPalProcPhysicalStatic(FunctionId, Arg1, Arg2, Arg3);
} else {
// Hal PalProc pointers are not setup yet
ReturnValues->ReturnValues[0] = PAL_STATUS_NOT_IMPLEMENTED;
}
break;
// Physical mode, static PAL calls
case PAL_HALT:
case PAL_CACHE_INIT:
case PAL_BUS_GET_FEATURES:
case PAL_BUS_SET_FEATURES:
case PAL_PROC_GET_FEATURES:
case PAL_PROC_SET_FEATURES:
case PAL_MC_DYNAMIC_STATE:
case PAL_MC_EXPECTED:
case PAL_MC_REGISTER_MEM:
case PAL_MC_RESUME:
case PAL_CACHE_LINE_INIT:
case PAL_MEM_FOR_TEST:
case PAL_COPY_INFO:
case PAL_ENTER_IA_32_ENV:
case PAL_PMI_ENTRYPOINT:
//
// PAL is MP-safe, but not re-entrant, HalpPalProcPhysicalStatic
// disables interrupts.
//
if (HalpPhysPalProcPointer) {
*ReturnValues = HalpPalProcPhysicalStatic(FunctionId, Arg1, Arg2, Arg3);
} else {
// Hal PalProc pointers are not setup yet
ReturnValues->ReturnValues[0] = PAL_STATUS_NOT_IMPLEMENTED;
}
break;
// Physical mode, stacked PAL calls
case PAL_VM_TR_READ:
case PAL_CACHE_READ:
case PAL_CACHE_WRITE:
case PAL_TEST_PROC:
case PAL_COPY_PAL:
case PAL_HALT_INFO:
{
ULONGLONG StackBase;
ULONGLONG BackingStorePointer;
ULONGLONG StackPointer;
//
// Load the addresses of the stack and backing store reserved for
// physical mode PAL calls on this processor.
//
StackBase = PCR->HalReserved[PROCESSOR_PHYSICAL_FW_STACK_INDEX];
StackPointer = GET_FW_STACK_POINTER(StackBase);
BackingStorePointer = GET_FW_BACKING_STORE_POINTER(StackBase);
//
// PAL is MP-safe, but not re-entrant, HalpPalProcPhysicalStacked
// disables interrupts.
//
if (HalpPhysPalProcPointer) {
*ReturnValues = HalpPalProcPhysicalStacked(
FunctionId,
Arg1,
Arg2,
Arg3,
(LONGLONG) StackPointer,
(LONGLONG) BackingStorePointer
);
} else {
// Hal PalProc pointers are not setup yet
ReturnValues->ReturnValues[0] = PAL_STATUS_NOT_IMPLEMENTED;
}
}
break;
default:
HalDebugPrint(( HAL_ERROR, "HAL: Unknown PAL Call ProcId #0x%I64x\n", FunctionId ));
ReturnValues->ReturnValues[0] = PAL_STATUS_NOT_IMPLEMENTED;
}
#ifdef PAL_TEST
if (ReturnValues->ReturnValues[0] == PAL_STATUS_NOT_IMPLEMENTED) {
InternalTestPal(FunctionId,Arg1,Arg2,Arg3,ReturnValues);
}
#endif
#if 0
// To avoid Kd hangs while flushing...
HalDebugPrint(( HAL_INFO,
"HAL: Got out of PAL call #0x%I64x with status 0x%I64x and RetVals 0x%I64x, 0x%I64x, 0x%I64x\n",
FunctionId,
ReturnValues->ReturnValues[0],
ReturnValues->ReturnValues[1],
ReturnValues->ReturnValues[2],
ReturnValues->ReturnValues[3] ));
#endif
return (ReturnValues->ReturnValues[0]);
}
VOID
HalReturnToFirmware(
IN FIRMWARE_ENTRY Routine
)
/*++
Routine Description:
Returns control to the firmware routine specified. Since the simulation
does not provide PAL and SAL support, it just stops the system.
System reboot can be done here.
Arguments:
Routine - Supplies a value indicating which firmware routine to invoke.
Return Value:
Does not return.
--*/
{
switch (Routine) {
case HalHaltRoutine:
case HalPowerDownRoutine:
case HalRestartRoutine:
case HalRebootRoutine:
HalpReboot();
break;
default:
HalDebugPrint(( HAL_INFO, "HAL: HalReturnToFirmware called\n" ));
DbgBreakPoint();
break;
}
}
ARC_STATUS
HalGetEnvironmentVariable (
IN PCHAR Variable,
IN USHORT Length,
OUT PCHAR Buffer
)
/*++
Routine Description:
This function locates an environment variable and returns its value.
The following system environment variables are supported:
variable value
LastKnownGood FALSE
SYSTEMPARTITION multi(0)disk(0)rdisk(0)partition(1)
OSLOADER multi(0)disk(0)rdisk(0)partition(1)\osloader.exe
OSLOADPARTITION multi(0)disk(0)rdisk(0)partition(1)
OSLOADFILENAME \WINNT
LOADIDENTIFIER Windows NT
COUNTDOWN 10
AUTOLOAD YES
The only environment variable this implementation supports is
"LastKnownGood". The returned value is always "FALSE".
Arguments:
Variable - Supplies a pointer to a zero terminated environment variable
name.
Length - Supplies the length of the value buffer in bytes.
Buffer - Supplies a pointer to a buffer that receives the variable value.
Return Value:
ESUCCESS is returned if the enviroment variable is located. Otherwise,
ENOENT is returned.
--*/
{
return ENOENT;
}
ARC_STATUS
HalSetEnvironmentVariable (
IN PCHAR Variable,
IN PCHAR Value
)
/*++
Routine Description:
This function creates an environment variable with the specified value.
The environment variable this implementation supports is
LastKnownGood
SYSTEMPARTITION
OSLOADER
OSLOADPARTITION
OSLOADFILENAME
OSLOADOPTIONS
LOADIDENTIFIER
COUNTDOWN
AUTOLOAD
For all bug LastKnowGood we return ESUCCESS, but don't actually do
anything.
Arguments:
Variable - Supplies a pointer to an environment variable name.
Value - Supplies a pointer to the environment variable value.
Return Value:
ESUCCESS is returned if the environment variable is created. Otherwise,
ENOMEM is returned.
--*/
{
return ENOENT;
}
NTSTATUS
HalGetEnvironmentVariableEx (
IN PWSTR VariableName,
IN LPGUID VendorGuid,
OUT PVOID Value,
IN OUT PULONG ValueLength,
OUT PULONG Attributes OPTIONAL
)
/*++
Routine Description:
This function locates an environment variable and returns its value.
Arguments:
VariableName - The name of the variable to query. This is a null-terminated
Unicode string.
VendorGuid - The GUID for the vendor associated with the variable.
Value - The address of the buffer into which the variable value is to be copied.
ValueLength - On input, the length in bytes of the Value buffer. On output,
the length in bytes of the variable value. If the input buffer is large
enough, then ValueLength indicates the amount of data copied into Value.
If the input buffer is too small, then nothing is copied into the buffer,
and ValueLength indicates the required buffer length.
Attributes - Returns the attributes of the variable.
Return Value:
STATUS_SUCCESS The function succeeded.
STATUS_BUFFER_TOO_SMALL The input buffer was too small.
STATUS_VARIABLE_NOT_FOUND The requested variable does not exist.
STATUS_INVALID_PARAMETER One of the parameters is invalid.
STATUS_UNSUPPORTED The HAL does not support this function.
STATUS_UNSUCCESSFUL The firmware returned an unrecognized error.
--*/
{
NTSTATUS ntStatus;
EFI_STATUS efiStatus;
ULONGLONG wideValueLength = *ValueLength;
ULONGLONG wideAttributes;
efiStatus = HalpCallEfi (
EFI_GET_VARIABLE_INDEX,
(ULONGLONG)VariableName,
(ULONGLONG)VendorGuid,
(ULONGLONG)&wideAttributes,
(ULONGLONG)&wideValueLength,
(ULONGLONG)Value,
0,
0,
0
);
*ValueLength = (ULONG)wideValueLength;
if ( ARGUMENT_PRESENT(Attributes) ) {
*Attributes = (ULONG)wideAttributes;
}
switch (efiStatus) {
case EFI_SUCCESS:
ntStatus = STATUS_SUCCESS;
break;
case EFI_NOT_FOUND:
ntStatus = STATUS_VARIABLE_NOT_FOUND;
break;
case EFI_BUFFER_TOO_SMALL:
ntStatus = STATUS_BUFFER_TOO_SMALL;
break;
case EFI_INVALID_PARAMETER:
ntStatus = STATUS_INVALID_PARAMETER;
break;
default:
ntStatus = STATUS_UNSUCCESSFUL;
break;
}
return ntStatus;
}
NTSTATUS
HalSetEnvironmentVariableEx (
IN PWSTR VariableName,
IN LPGUID VendorGuid,
IN PVOID Value,
IN ULONG ValueLength,
IN ULONG Attributes
)
/*++
Routine Description:
This function creates an environment variable with the specified value.
Arguments:
VariableName - The name of the variable to set. This is a null-terminated
Unicode string.
VendorGuid - The GUID for the vendor associated with the variable.
Value - The address of the buffer containing the new variable value.
ValueLength - The length in bytes of the Value buffer.
Attributes - The attributes of the variable. The attribute bit
VARIABLE_ATTRIBUTE_NON_VOLATILE MUST be set.
Return Value:
STATUS_SUCCESS The function succeeded.
STATUS_INSUFFICIENT_RESOURCES Not enough storage is available.
STATUS_INVALID_PARAMETER One of the parameters is invalid.
STATUS_UNSUPPORTED The HAL does not support this function.
STATUS_UNSUCCESSFUL The firmware returned an unrecognized error.
--*/
{
NTSTATUS ntStatus;
EFI_STATUS efiStatus;
if ( (Attributes & VARIABLE_ATTRIBUTE_NON_VOLATILE) == 0 ) {
return STATUS_INVALID_PARAMETER;
}
//
// First, delete the old value, if it exists. This is necessary to ensure that
// the attributes specified to this routine are correctly applied.
//
efiStatus = HalpCallEfi (
EFI_SET_VARIABLE_INDEX,
(ULONGLONG)VariableName,
(ULONGLONG)VendorGuid,
(ULONGLONG)0, // Attributes
(ULONGLONG)0, // ValueLength
(ULONGLONG)NULL, // Value
0,
0,
0
);
//
// Now create the new variable, unless the ValueLength is zero. In that
// case, the caller actually wanted the variable deleted, which we just did.
//
if (ValueLength != 0) {
efiStatus = HalpCallEfi (
EFI_SET_VARIABLE_INDEX,
(ULONGLONG)VariableName,
(ULONGLONG)VendorGuid,
(ULONGLONG)EFI_VARIABLE_ATTRIBUTE,
(ULONGLONG)ValueLength,
(ULONGLONG)Value,
0,
0,
0
);
}
switch (efiStatus) {
case EFI_SUCCESS:
ntStatus = STATUS_SUCCESS;
break;
case EFI_NOT_FOUND:
ntStatus = STATUS_VARIABLE_NOT_FOUND;
break;
case EFI_OUT_OF_RESOURCES:
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
break;
case EFI_INVALID_PARAMETER:
ntStatus = STATUS_INVALID_PARAMETER;
break;
default:
ntStatus = STATUS_UNSUCCESSFUL;
break;
}
return ntStatus;
}
NTSTATUS
HalEnumerateEnvironmentVariablesEx (
IN ULONG InformationClass,
OUT PVOID Buffer,
IN OUT PULONG BufferLength
)
/*++
Routine Description:
This function returns information about system environment variables.
Arguments:
InformationClass - Specifies the type of information to return.
Buffer - The address of the buffer that is to receive the returned data.
The format of the returned data depends on InformationClass.
BufferLength - On input, the length in bytes of the buffer. On output,
the length in bytes of the returned data. If the input buffer is
large enough, then BufferLength indicates the amount of data copied
into Buffer. If the input buffer is too small, then BufferLength
indicates the required buffer length.
Return Value:
STATUS_SUCCESS The function succeeded.
STATUS_BUFFER_TOO_SMALL The input buffer was too small.
STATUS_INVALID_PARAMETER One of the parameters is invalid.
STATUS_UNSUPPORTED The HAL does not support this function.
STATUS_UNSUCCESSFUL The firmware returned an unrecognized error.
--*/
{
NTSTATUS ntStatus = STATUS_SUCCESS;
EFI_STATUS efiStatus;
PUCHAR currentPtr;
PVARIABLE_NAME name;
PVARIABLE_NAME_AND_VALUE nameAndValue;
PVARIABLE_NAME previousEntry;
PWCHAR previousName;
ULONG variableNameLength;
GUID guid;
ULONG baseLength;
ULONG remainingLength;
PUCHAR valuePtr;
ULONG valueLength;
PULONG attrPtr;
LOGICAL filling;
ULONG requiredLength;
#define MAX_VARIABLE_NAME 255
WCHAR variableName[MAX_VARIABLE_NAME + 1];
if ( (InformationClass != VARIABLE_INFORMATION_NAMES) &&
(InformationClass != VARIABLE_INFORMATION_VALUES) ) {
return STATUS_INVALID_PARAMETER;
}
if ( ALIGN_DOWN_POINTER(Buffer, ULONG) != Buffer ) {
return STATUS_INVALID_PARAMETER;
}
if ( InformationClass == VARIABLE_INFORMATION_NAMES ) {
baseLength = FIELD_OFFSET( VARIABLE_NAME, Name );
} else {
baseLength = FIELD_OFFSET( VARIABLE_NAME_AND_VALUE, Name );
}
currentPtr = Buffer;
remainingLength = *BufferLength;
filling = (LOGICAL)(remainingLength != 0);
if ( !filling ) {
ntStatus = STATUS_BUFFER_TOO_SMALL;
}
previousEntry = NULL;
variableName[0] = 0;
while ( TRUE ) {
variableNameLength = (MAX_VARIABLE_NAME + 1) * sizeof(WCHAR);
{
ULONGLONG wideLength = variableNameLength;
efiStatus = HalpCallEfi (
EFI_GET_NEXT_VARIABLE_NAME_INDEX,
(ULONGLONG)&wideLength,
(ULONGLONG)variableName,
(ULONGLONG)&guid,
0,
0,
0,
0,
0
);
variableNameLength = (ULONG)wideLength;
}
switch (efiStatus) {
case EFI_SUCCESS:
break;
case EFI_NOT_FOUND:
break;
default:
ntStatus = STATUS_UNSUCCESSFUL;
break;
}
if ( efiStatus != EFI_SUCCESS ) {
break;
}
if ( ALIGN_UP_POINTER(currentPtr, ULONG) != currentPtr ) {
PUCHAR alignedPtr = ALIGN_UP_POINTER( currentPtr, ULONG );
ULONG fill = (ULONG)(alignedPtr - currentPtr);
currentPtr = alignedPtr;
if ( remainingLength < fill ) {
filling = FALSE;
remainingLength = 0;
ntStatus = STATUS_BUFFER_TOO_SMALL;
} else {
remainingLength -= fill;
}
}
requiredLength = baseLength + variableNameLength;
if ( InformationClass != VARIABLE_INFORMATION_NAMES ) {
requiredLength = ALIGN_UP( requiredLength, ULONG );
}
if ( remainingLength < requiredLength ) {
remainingLength = 0;
filling = FALSE;
ntStatus = STATUS_BUFFER_TOO_SMALL;
} else {
remainingLength -= requiredLength;
}
name = (PVARIABLE_NAME)currentPtr;
nameAndValue = (PVARIABLE_NAME_AND_VALUE)currentPtr;
if ( InformationClass == VARIABLE_INFORMATION_NAMES ) {
if ( filling ) {
RtlCopyMemory( &name->VendorGuid, &guid, sizeof(GUID) );
wcscpy( name->Name, variableName );
if ( previousEntry != NULL ) {
previousEntry->NextEntryOffset = (ULONG)(currentPtr - (PUCHAR)previousEntry);
}
previousEntry = (PVARIABLE_NAME)currentPtr;
}
currentPtr += requiredLength;
} else {
ULONGLONG wideLength;
ULONGLONG wideAttr;
if ( filling ) {
RtlCopyMemory( &nameAndValue->VendorGuid, &guid, sizeof(GUID) );
wcscpy( nameAndValue->Name, variableName );
valuePtr = (PUCHAR)nameAndValue->Name + variableNameLength;
valuePtr = ALIGN_UP_POINTER( valuePtr, ULONG );
valueLength = remainingLength;
attrPtr = &nameAndValue->Attributes;
nameAndValue->ValueOffset = (ULONG)(valuePtr - (PUCHAR)nameAndValue);
} else {
valuePtr = NULL;
valueLength = 0;
attrPtr = NULL;
}
wideLength = valueLength;
efiStatus = HalpCallEfi (
EFI_GET_VARIABLE_INDEX,
(ULONGLONG)variableName,
(ULONGLONG)&guid,
(ULONGLONG)&wideAttr,
(ULONGLONG)&wideLength,
(ULONGLONG)valuePtr,
0,
0,
0
);
valueLength = (ULONG)wideLength;
if ( attrPtr != NULL ) {
*attrPtr = (ULONG)wideAttr;
}
switch (efiStatus) {
case EFI_SUCCESS:
if ( filling ) {
nameAndValue->ValueLength = valueLength;
remainingLength -= valueLength;
if ( previousEntry != NULL ) {
previousEntry->NextEntryOffset = (ULONG)(currentPtr - (PUCHAR)previousEntry);
}
previousEntry = (PVARIABLE_NAME)currentPtr;
}
break;
case EFI_BUFFER_TOO_SMALL:
efiStatus = EFI_SUCCESS;
remainingLength = 0;
filling = FALSE;
ntStatus = STATUS_BUFFER_TOO_SMALL;
break;
default:
ntStatus = STATUS_UNSUCCESSFUL;
break;
}
if ( efiStatus != EFI_SUCCESS ) {
break;
}
currentPtr += requiredLength + valueLength;
}
}
if ( previousEntry != NULL ) {
previousEntry->NextEntryOffset = 0;
}
*BufferLength = (ULONG)(currentPtr - (PUCHAR)Buffer);
return ntStatus;
}
NTSTATUS
HalpGetPlatformId(
OUT PHAL_PLATFORM_ID PlatformId
)
/*++
Routine Description:
This function fills in the ANSI_STRING structures for the Vendor and Device IDs out
of the SalSystemTable.
Arguments:
PlatformId - Pointer to a structure with two ANSI_STRING structures for Vendor/DeviceIds
Return Value:
STATUS_SUCCESS if SalSystemTable available, otherwise STATUS_UNSUCCESSFUL
Assumptions:
The two strings in PlatformId will not be freed or modified, and are therefore pointing
directly to the SalSystemTable.
--*/
{
UCHAR i;
// Initialize the VendorId ANSI_STRING structure to point to SalSystemTable entry
// Note, both strings are either NULL terminated OR exactly 32-bytes in length and
// not NULL terminated.
if (!NT_SUCCESS(HalpSalPalData.Status)) {
return STATUS_UNSUCCESSFUL;
}
i=0;;
while (HalpSalPalData.SalSystemTable->OemId[i] && i < OEM_ID_LENGTH) {
i++;
}
PlatformId->VendorId.Buffer = HalpSalPalData.SalSystemTable->OemId;
PlatformId->VendorId.Length = i;
PlatformId->VendorId.MaximumLength = i;
// Initialize the DeviceId ANSI_STRING structure to point to SalSystemTable entry
i=0;
while (HalpSalPalData.SalSystemTable->ProductId[i] && i < OEM_PRODUCT_ID_LENGTH) {
i++;
}
PlatformId->DeviceId.Buffer = HalpSalPalData.SalSystemTable->ProductId;
PlatformId->DeviceId.Length = i;
PlatformId->DeviceId.MaximumLength = i;
return STATUS_SUCCESS;
}
/*****************************************************************
TEST CODE FOR THE SAL AND PAL:
These routines provide an infrastructure for supporting SAL and
PAL calls not supported by firmware, overriding there meaning
if SAL or PAL returns STATUS_NOT_IMPLEMENTED. The #define for
SAL_TEST and/or PAL_TEST must be defined for this behavior.
*****************************************************************/
ULONG
NoSalPCIRead(
IN ULONG Tok,
IN ULONG Size
)
{
ULONG Data;
ULONG i = Tok % sizeof(ULONG);
WRITE_PORT_ULONG((PULONG)0xcf8, 0x80000000 | Tok);
switch (Size) {
case 1: Data = READ_PORT_UCHAR((PUCHAR)(ULongToPtr(0xcfc + i) )); break;
case 2: Data = READ_PORT_USHORT((PUSHORT)(ULongToPtr(0xcfc + i) )); break;
case 4: Data = READ_PORT_ULONG((PULONG)(0xcfc)); break;
}
return(Data);
}
VOID
NoSalPCIWrite(
IN ULONG Tok,
IN ULONG Size,
IN ULONG Data
)
{
ULONG i = Tok % sizeof(ULONG);
WRITE_PORT_ULONG((PULONG)0xcf8, 0x80000000 | Tok);
switch (Size) {
case 1: WRITE_PORT_UCHAR((PUCHAR)(ULongToPtr(0xcfc + i) ), (UCHAR)Data); break;
case 2: WRITE_PORT_USHORT((PUSHORT)(ULongToPtr(0xcfc + i) ), (USHORT)Data); break;
case 4: WRITE_PORT_ULONG((PULONG)(0xcfc), Data); break;
}
}
#define PCIBUS(Tok) (((ULONG)(Tok) >> 16) & 0xff)
#define PCIDEV(Tok) (((ULONG)(Tok) >> 11) & 0x1f)
#define PCIFUNC(Tok) (((ULONG)(Tok) >> 8) & 0x7)
#define PCIOFF(Tok) (((ULONG)(Tok) >> 2) & 0x3f)
VOID
InternalTestSal(
IN LONGLONG FunctionId,
IN LONGLONG Arg1,
IN LONGLONG Arg2,
IN LONGLONG Arg3,
IN LONGLONG Arg4,
IN LONGLONG Arg5,
IN LONGLONG Arg6,
IN LONGLONG Arg7,
OUT PSAL_PAL_RETURN_VALUES ReturnValues
)
{
switch (FunctionId) {
case SAL_PCI_CONFIG_READ: {
ULONG Data;
HalDebugPrint(( HAL_INFO, "HAL: << SAL_PCI_CONFIG_READ - Bus: %d Dev: %2d Func: %d Off: %2d Size = %d ",
PCIBUS(Arg1), PCIDEV(Arg1), PCIFUNC(Arg1), PCIOFF(Arg1), Arg2 ));
ReturnValues->ReturnValues[0] = SAL_STATUS_SUCCESS;
ReturnValues->ReturnValues[1] = Data = NoSalPCIRead((ULONG)Arg1, (ULONG)Arg2);
HalDebugPrint(( HAL_INFO, " Data = 0x%08x\n", Data ));
break;
}
case SAL_PCI_CONFIG_WRITE:
HalDebugPrint(( HAL_INFO, "HAL: >> SAL_PCI_CONFIG_WRITE: Bus: %d Dev: %2d Func: %d Off: %2d Size = %d Val = 0x%08x\n",
PCIBUS(Arg1), PCIDEV(Arg1), PCIFUNC(Arg1), PCIOFF(Arg1), Arg2, Arg3 ));
NoSalPCIWrite((ULONG)Arg1, (ULONG)Arg2, (ULONG)Arg3);
ReturnValues->ReturnValues[0] = SAL_STATUS_SUCCESS;
break;
default:
ReturnValues->ReturnValues[0] = SAL_STATUS_NOT_IMPLEMENTED;
}
}
VOID
InternalTestPal(
IN LONGLONG FunctionId,
IN LONGLONG Arg1,
IN LONGLONG Arg2,
IN LONGLONG Arg3,
OUT PSAL_PAL_RETURN_VALUES ReturnValues
)
{
switch (FunctionId) {
default:
ReturnValues->ReturnValues[0] = SAL_STATUS_NOT_IMPLEMENTED;
}
}