windows-nt/Source/XPSP1/NT/base/hals/mcasample/imca/exe/mcalog.c

452 lines
12 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
Module Name:
MCALOG.C
Abstract:
Sample Application for logging errors for Machine Check Architecture
Author:
Anil Aggarwal (10/12/98)
Intel Corporation
Revision History:
--*/
#include <windows.h>
#include <winioctl.h>
#include <stdio.h>
#include <stdlib.h>
#include <winbase.h>
#include <mce.h>
#include "imca.h"
//
// Variables for parsing command line arguments
//
extern int opterr;
extern int optind;
extern char *optarg;
//
// Print the usage information for MCA logging application
//
VOID
McaUsage(
PCHAR Name
)
{
fprintf(stderr,"Usage\n\t%s: [-s] [-a]\n",Name);
fprintf(stderr,"\n\t-s: Read Machine Check registers now\n");
fprintf(stderr,"\n\t-a: Post asynchronous request for errors\n");
ExitProcess(1);
}
//
// This routine prints the Machine Check registers
//
#if defined(_X86_)
VOID
PrintX86McaLog(
PMCA_EXCEPTION McaException
)
{
if (McaException->ExceptionType != HAL_MCA_RECORD) {
fprintf(stderr, "Bad exception record type\n");
//ExitProcess(1);
}
printf("Processor Number = %d\n", McaException->ProcessorNumber);
printf("Bank Number = %d\n", (__int64)McaException->u.Mca.BankNumber);
printf("Mci_Status %I64X\n", (__int64)McaException->u.Mca.Status.QuadPart);
printf("Mci_Address %I64X\n", (__int64)McaException->u.Mca.Address.QuadPart);
printf("Mci_Misc %I64X\n", (__int64)McaException->u.Mca.Misc);
} // PrintX86McaLog()
#define McaPrintLog PrintX86McaLog
#endif // _X86_
#if defined(_IA64_)
#define ERROR_RECORD_HEADER_FORMAT \
"MCA Error Record Header\n" \
"\tId : 0x%I64x\n" \
"\tRevision : 0x%x\n" \
"\t\tMajor : %x\n" \
"\t\tMinor : %x\n" \
"\tSeverity : 0x%x\n" \
"\tValid : 0x%x\n" \
"\t\tPlatformId: %x\n" \
"\tLength : 0x%x\n" \
"\tTimeStamp : 0x%I64x\n" \
"\t\tSeconds: %x\n" \
"\t\tMinutes: %x\n" \
"\t\tHours : %x\n" \
"\t\tDay : %x\n" \
"\t\tMonth : %x\n" \
"\t\tYear : %x\n" \
"\t\tCentury: %x\n" \
"\tPlatformId: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n"
VOID
PrintIa64ErrorRecordHeader(
PERROR_RECORD_HEADER Header
)
{
printf( ERROR_RECORD_HEADER_FORMAT,
(ULONGLONG) Header->Id,
(ULONG) Header->Revision.Revision,
(ULONG) Header->Revision.Major, (ULONG) Header->Revision.Minor,
(ULONG) Header->ErrorSeverity,
(ULONG) Header->Valid.Valid,
(ULONG) Header->Valid.OemPlatformID,
(ULONG) Header->Length,
(ULONGLONG) Header->TimeStamp.TimeStamp,
(ULONG) Header->TimeStamp.Seconds,
(ULONG) Header->TimeStamp.Minutes,
(ULONG) Header->TimeStamp.Hours,
(ULONG) Header->TimeStamp.Day,
(ULONG) Header->TimeStamp.Month,
(ULONG) Header->TimeStamp.Year,
(ULONG) Header->TimeStamp.Century,
(ULONG) Header->OemPlatformId[0],
(ULONG) Header->OemPlatformId[1],
(ULONG) Header->OemPlatformId[2],
(ULONG) Header->OemPlatformId[3],
(ULONG) Header->OemPlatformId[4],
(ULONG) Header->OemPlatformId[5],
(ULONG) Header->OemPlatformId[6],
(ULONG) Header->OemPlatformId[7],
(ULONG) Header->OemPlatformId[8],
(ULONG) Header->OemPlatformId[9],
(ULONG) Header->OemPlatformId[10],
(ULONG) Header->OemPlatformId[11],
(ULONG) Header->OemPlatformId[12],
(ULONG) Header->OemPlatformId[13],
(ULONG) Header->OemPlatformId[14],
(ULONG) Header->OemPlatformId[15]
);
return;
} // PrintIa64ErrorRecordHeader()
VOID
PrintIa64McaLog(
PMCA_EXCEPTION McaException
)
{
//
// Start by printing the record header.
//
PrintIa64ErrorRecordHeader( McaException );
//
// Then print and/or process error device specific information here.
//
return;
} // PrintIa64McaLog()
#define McaPrintLog PrintIa64McaLog
#endif // _IA64_
//
// This routine prints a user friendly error message based on GetLastError()
//
VOID
McaPrintError(
VOID
)
{
LPVOID lpMsgBuf;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR) &lpMsgBuf,
0,
NULL
);
fprintf(stderr, "%s\n", lpMsgBuf);
LocalFree( lpMsgBuf );
}
//
// Main entry point
//
int
__cdecl
main(
int argc,
char *argv[]
)
{
CHAR Option;
BOOLEAN ReadBanks = FALSE;
BOOLEAN PostAsyncRequest = FALSE;
HANDLE McaDeviceHandle;
HANDLE LogEvent;
OVERLAPPED Overlap;
BOOL ReturnStatus;
DWORD ActualCount;
DWORD WaitStatus;
DWORD NumberOfBytes;
MCA_EXCEPTION McaException;
LONG i;
//
// Process the command line arguments
//
for (i=1; i < argc; i++) {
if (!((argv[i][0] == '-') || (argv[i][2] != 0)) ) {
McaUsage(argv[0]);
}
Option = argv[i][1];
switch (Option) {
case 's':
ReadBanks = TRUE;
break;
case 'a':
PostAsyncRequest = TRUE;
break;
default:
McaUsage(argv[0]);
}
}
if ((ReadBanks != TRUE) && (PostAsyncRequest != TRUE)) {
fprintf(stderr, "One of -s and -a options must be specified\n");
ExitProcess(1);
}
if ((ReadBanks == TRUE) && (PostAsyncRequest == TRUE)) {
fprintf(stderr, "Only one of -s and -a options can be specified\n");
ExitProcess(1);
}
//
// Open MCA device with overlap flag set
//
McaDeviceHandle = CreateFile(
MCA_DEVICE_NAME_WIN32,
GENERIC_READ|GENERIC_WRITE,
0,
(LPSECURITY_ATTRIBUTES)NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED,
(HANDLE)NULL
);
if (McaDeviceHandle == INVALID_HANDLE_VALUE) {
fprintf(stderr, "%s: Error 0x%lx opening MCA device\n",
argv[0], GetLastError());
ExitProcess(1);
}
if (ReadBanks == TRUE) {
//
// Read the error logs on all banks on all procs.
// IOCTL_READ_BANKS will read only one error at a time. So
// we need to keep issuing this ioctl till all the errors are read
//
do {
ReturnStatus = DeviceIoControl(
McaDeviceHandle,
(ULONG)IOCTL_READ_BANKS,
NULL,
0,
&McaException,
sizeof(MCA_EXCEPTION),
&ActualCount,
NULL
);
if (ReturnStatus == 0) {
//
// Some error has occurred. Either there are no more machine
// check errors present or the processor does not have
// support for Intel Machine Check Architecture
//
if (GetLastError() == ERROR_NOT_FOUND) {
fprintf(stderr, "No Machine Check errors present\n");
} else if (GetLastError() == ERROR_FILE_NOT_FOUND) {
fprintf(stderr, "Intel Machine Check support not available\n");
ExitProcess(1);
} else {
fprintf(stderr, "%s: Error 0x%lx in DeviceIoControl\n",
argv[0], GetLastError());
ExitProcess(1);
}
} else {
//
// Successfully read the error. Print it.
//
McaPrintLog(&McaException);
}
} while (ReturnStatus != 0);
//
// We are done
//
return 1;
}
//
// If we are here, we are supposed to post asynchronous calls to MCA driver
//
//
// Set up structures for asynchronous call for reading the log
// Create the event object
//
LogEvent = CreateEvent(
NULL, // No Security Attributes
FALSE, // Auto Reset Event
FALSE, // Initial State = non-signaled
NULL // Unnamed object
);
if (LogEvent == NULL) {
fprintf(stderr, "%s: Error 0x%lx creating event\n",
argv[0], GetLastError());
ExitProcess(1);
}
//
// Initialize the overlap structure
//
Overlap.hEvent = LogEvent; // Specify event for overlapped object
Overlap.Offset = 0; // Offset is zero for devices
Overlap.OffsetHigh = 0; // OffsetHigh is zero for devices
ReturnStatus = DeviceIoControl(
McaDeviceHandle,
(ULONG)IOCTL_READ_BANKS_ASYNC,
NULL,
0,
&McaException,
sizeof(MCA_EXCEPTION),
&ActualCount,
&Overlap
);
if ((ReturnStatus == 0) && (GetLastError() != ERROR_IO_PENDING)) {
fprintf(stderr, "%s: Error 0x%lx in IOCTL_READ_BANKS_ASYNC\n",
argv[0], GetLastError());
ExitProcess(1);
}
//
// Either Ioctl was successful or IO is currently pending
// If successful then display the log else wait for specified interval
//
if (ReturnStatus == TRUE) {
//
// Read log async returned succesfully. Display it
//
McaPrintLog(&McaException);
}
//
// Wait forever to get an error
//
WaitStatus = WaitForSingleObject(
LogEvent,
INFINITE
);
if (WaitStatus == WAIT_OBJECT_0) {
//
// The state of the event object is signalled
// check if the I/O operation was successful
//
ReturnStatus = GetOverlappedResult(
McaDeviceHandle,
&Overlap,
&NumberOfBytes,
FALSE // Return immediately
);
if (ReturnStatus == 0) {
fprintf(stderr, "%s: Error 0x%lx in GetOverlappedResult\n",
argv[0], GetLastError());
ExitProcess(1);
}
if (NumberOfBytes) {
//
// Print the results
//
McaPrintLog(&McaException);
} else {
//
// Error as the I/O operation was signalled complete before
// timeout but no data transferred
//
fprintf(stderr, "%s: No data from GetOverlappedResult\n",
argv[0]);
ExitProcess(1);
}
} else {
//
// We should not get any other return value
//
fprintf(stderr, "%s: Unexpected return value from WaitForSingleObject()\n", argv[0]);
ExitProcess(1);
}
CloseHandle(McaDeviceHandle);
return 1;
}