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.

478 lines
14 KiB

  1. /*++
  2. Module Name:
  3. MCALOG.C
  4. Abstract:
  5. Sample Application for logging errors for Machine Check Architecture
  6. Author:
  7. Anil Aggarwal (10/12/98)
  8. Intel Corporation
  9. Revision History:
  10. --*/
  11. #include <windows.h>
  12. #include <winioctl.h>
  13. #include <stdio.h>
  14. #include <stdlib.h>
  15. #include <winbase.h>
  16. #include <mce.h>
  17. #include "imca.h"
  18. //
  19. // Variables for parsing command line arguments
  20. //
  21. extern int opterr;
  22. extern int optind;
  23. extern char *optarg;
  24. //
  25. // Print the usage information for MCA logging application
  26. //
  27. VOID
  28. McaUsage(
  29. PCHAR Name
  30. )
  31. {
  32. fprintf(stderr,"Usage\n\t%s: [-s] [-a]\n",Name);
  33. fprintf(stderr,"\n\t-s: Read Machine Check registers now\n");
  34. fprintf(stderr,"\n\t-a: Post asynchronous request for errors\n");
  35. ExitProcess(1);
  36. }
  37. //
  38. // This routine prints the Machine Check registers
  39. //
  40. #if defined(_AMD64_)
  41. VOID
  42. McaPrintLog(
  43. PMCA_EXCEPTION McaException
  44. )
  45. {
  46. if (McaException->ExceptionType != HAL_MCA_RECORD) {
  47. fprintf(stderr, "Bad exception record type\n");
  48. //ExitProcess(1);
  49. }
  50. printf("Processor Number = %d\n", McaException->ProcessorNumber);
  51. printf("Bank Number = %d\n", McaException->u.Mca.BankNumber);
  52. printf("Mci_Status %I64X\n", McaException->u.Mca.Status.QuadPart);
  53. printf("Mci_Address %I64X\n", McaException->u.Mca.Address.QuadPart);
  54. printf("Mci_Misc %I64X\n", McaException->u.Mca.Misc);
  55. } // McaPrintLog()
  56. #endif // _AMD64_
  57. #if defined(_X86_)
  58. VOID
  59. PrintX86McaLog(
  60. PMCA_EXCEPTION McaException
  61. )
  62. {
  63. if (McaException->ExceptionType != HAL_MCA_RECORD) {
  64. fprintf(stderr, "Bad exception record type\n");
  65. //ExitProcess(1);
  66. }
  67. printf("Processor Number = %d\n", McaException->ProcessorNumber);
  68. printf("Bank Number = %d\n", (__int64)McaException->u.Mca.BankNumber);
  69. printf("Mci_Status %I64X\n", (__int64)McaException->u.Mca.Status.QuadPart);
  70. printf("Mci_Address %I64X\n", (__int64)McaException->u.Mca.Address.QuadPart);
  71. printf("Mci_Misc %I64X\n", (__int64)McaException->u.Mca.Misc);
  72. } // PrintX86McaLog()
  73. #define McaPrintLog PrintX86McaLog
  74. #endif // _X86_
  75. #if defined(_IA64_)
  76. #define ERROR_RECORD_HEADER_FORMAT \
  77. "MCA Error Record Header\n" \
  78. "\tId : 0x%I64x\n" \
  79. "\tRevision : 0x%x\n" \
  80. "\t\tMajor : %x\n" \
  81. "\t\tMinor : %x\n" \
  82. "\tSeverity : 0x%x\n" \
  83. "\tValid : 0x%x\n" \
  84. "\t\tPlatformId: %x\n" \
  85. "\tLength : 0x%x\n" \
  86. "\tTimeStamp : 0x%I64x\n" \
  87. "\t\tSeconds: %x\n" \
  88. "\t\tMinutes: %x\n" \
  89. "\t\tHours : %x\n" \
  90. "\t\tDay : %x\n" \
  91. "\t\tMonth : %x\n" \
  92. "\t\tYear : %x\n" \
  93. "\t\tCentury: %x\n" \
  94. "\tPlatformId: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n"
  95. VOID
  96. PrintIa64ErrorRecordHeader(
  97. PERROR_RECORD_HEADER Header
  98. )
  99. {
  100. printf( ERROR_RECORD_HEADER_FORMAT,
  101. (ULONGLONG) Header->Id,
  102. (ULONG) Header->Revision.Revision,
  103. (ULONG) Header->Revision.Major, (ULONG) Header->Revision.Minor,
  104. (ULONG) Header->ErrorSeverity,
  105. (ULONG) Header->Valid.Valid,
  106. (ULONG) Header->Valid.OemPlatformID,
  107. (ULONG) Header->Length,
  108. (ULONGLONG) Header->TimeStamp.TimeStamp,
  109. (ULONG) Header->TimeStamp.Seconds,
  110. (ULONG) Header->TimeStamp.Minutes,
  111. (ULONG) Header->TimeStamp.Hours,
  112. (ULONG) Header->TimeStamp.Day,
  113. (ULONG) Header->TimeStamp.Month,
  114. (ULONG) Header->TimeStamp.Year,
  115. (ULONG) Header->TimeStamp.Century,
  116. (ULONG) Header->OemPlatformId[0],
  117. (ULONG) Header->OemPlatformId[1],
  118. (ULONG) Header->OemPlatformId[2],
  119. (ULONG) Header->OemPlatformId[3],
  120. (ULONG) Header->OemPlatformId[4],
  121. (ULONG) Header->OemPlatformId[5],
  122. (ULONG) Header->OemPlatformId[6],
  123. (ULONG) Header->OemPlatformId[7],
  124. (ULONG) Header->OemPlatformId[8],
  125. (ULONG) Header->OemPlatformId[9],
  126. (ULONG) Header->OemPlatformId[10],
  127. (ULONG) Header->OemPlatformId[11],
  128. (ULONG) Header->OemPlatformId[12],
  129. (ULONG) Header->OemPlatformId[13],
  130. (ULONG) Header->OemPlatformId[14],
  131. (ULONG) Header->OemPlatformId[15]
  132. );
  133. return;
  134. } // PrintIa64ErrorRecordHeader()
  135. VOID
  136. PrintIa64McaLog(
  137. PMCA_EXCEPTION McaException
  138. )
  139. {
  140. //
  141. // Start by printing the record header.
  142. //
  143. PrintIa64ErrorRecordHeader( McaException );
  144. //
  145. // Then print and/or process error device specific information here.
  146. //
  147. return;
  148. } // PrintIa64McaLog()
  149. #define McaPrintLog PrintIa64McaLog
  150. #endif // _IA64_
  151. //
  152. // This routine prints a user friendly error message based on GetLastError()
  153. //
  154. VOID
  155. McaPrintError(
  156. VOID
  157. )
  158. {
  159. LPVOID lpMsgBuf;
  160. DWORD Err = GetLastError();
  161. if (FormatMessage(
  162. FORMAT_MESSAGE_ALLOCATE_BUFFER |
  163. FORMAT_MESSAGE_FROM_SYSTEM |
  164. FORMAT_MESSAGE_IGNORE_INSERTS,
  165. NULL,
  166. Err,
  167. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
  168. (LPTSTR) &lpMsgBuf,
  169. 0,
  170. NULL
  171. )) {
  172. fprintf(stderr, "%s\n", lpMsgBuf);
  173. LocalFree( lpMsgBuf );
  174. } else {
  175. fprintf(stderr, "%d\n", Err);
  176. }
  177. }
  178. //
  179. // Main entry point
  180. //
  181. int
  182. __cdecl
  183. main(
  184. int argc,
  185. char *argv[]
  186. )
  187. {
  188. CHAR Option;
  189. BOOLEAN ReadBanks = FALSE;
  190. BOOLEAN PostAsyncRequest = FALSE;
  191. HANDLE McaDeviceHandle;
  192. HANDLE LogEvent;
  193. OVERLAPPED Overlap;
  194. BOOL ReturnStatus;
  195. DWORD ActualCount;
  196. DWORD WaitStatus;
  197. DWORD NumberOfBytes;
  198. MCA_EXCEPTION McaException;
  199. LONG i;
  200. //
  201. // Process the command line arguments
  202. //
  203. for (i=1; i < argc; i++) {
  204. if (!((argv[i][0] == '-') || (argv[i][2] != 0)) ) {
  205. McaUsage(argv[0]);
  206. }
  207. Option = argv[i][1];
  208. switch (Option) {
  209. case 's':
  210. ReadBanks = TRUE;
  211. break;
  212. case 'a':
  213. PostAsyncRequest = TRUE;
  214. break;
  215. default:
  216. McaUsage(argv[0]);
  217. }
  218. }
  219. if ((ReadBanks != TRUE) && (PostAsyncRequest != TRUE)) {
  220. fprintf(stderr, "One of -s and -a options must be specified\n");
  221. ExitProcess(1);
  222. }
  223. if ((ReadBanks == TRUE) && (PostAsyncRequest == TRUE)) {
  224. fprintf(stderr, "Only one of -s and -a options can be specified\n");
  225. ExitProcess(1);
  226. }
  227. //
  228. // Open MCA device with overlap flag set
  229. //
  230. McaDeviceHandle = CreateFile(
  231. MCA_DEVICE_NAME_WIN32,
  232. GENERIC_READ|GENERIC_WRITE,
  233. 0,
  234. (LPSECURITY_ATTRIBUTES)NULL,
  235. OPEN_EXISTING,
  236. FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED,
  237. (HANDLE)NULL
  238. );
  239. if (McaDeviceHandle == INVALID_HANDLE_VALUE) {
  240. fprintf(stderr, "%s: Error 0x%lx opening MCA device\n",
  241. argv[0], GetLastError());
  242. ExitProcess(1);
  243. }
  244. if (ReadBanks == TRUE) {
  245. //
  246. // Read the error logs on all banks on all procs.
  247. // IOCTL_READ_BANKS will read only one error at a time. So
  248. // we need to keep issuing this ioctl till all the errors are read
  249. //
  250. do {
  251. ReturnStatus = DeviceIoControl(
  252. McaDeviceHandle,
  253. (ULONG)IOCTL_READ_BANKS,
  254. NULL,
  255. 0,
  256. &McaException,
  257. sizeof(MCA_EXCEPTION),
  258. &ActualCount,
  259. NULL
  260. );
  261. if (ReturnStatus == 0) {
  262. //
  263. // Some error has occurred. Either there are no more machine
  264. // check errors present or the processor does not have
  265. // support for Intel Machine Check Architecture
  266. //
  267. if (GetLastError() == ERROR_NOT_FOUND) {
  268. fprintf(stderr, "No Machine Check errors present\n");
  269. } else if (GetLastError() == ERROR_FILE_NOT_FOUND) {
  270. fprintf(stderr, "Intel Machine Check support not available\n");
  271. ExitProcess(1);
  272. } else {
  273. fprintf(stderr, "%s: Error 0x%lx in DeviceIoControl\n",
  274. argv[0], GetLastError());
  275. ExitProcess(1);
  276. }
  277. } else {
  278. //
  279. // Successfully read the error. Print it.
  280. //
  281. McaPrintLog(&McaException);
  282. }
  283. } while (ReturnStatus != 0);
  284. //
  285. // We are done
  286. //
  287. return 1;
  288. }
  289. //
  290. // If we are here, we are supposed to post asynchronous calls to MCA driver
  291. //
  292. //
  293. // Set up structures for asynchronous call for reading the log
  294. // Create the event object
  295. //
  296. LogEvent = CreateEvent(
  297. NULL, // No Security Attributes
  298. FALSE, // Auto Reset Event
  299. FALSE, // Initial State = non-signaled
  300. NULL // Unnamed object
  301. );
  302. if (LogEvent == NULL) {
  303. fprintf(stderr, "%s: Error 0x%lx creating event\n",
  304. argv[0], GetLastError());
  305. ExitProcess(1);
  306. }
  307. //
  308. // Initialize the overlap structure
  309. //
  310. Overlap.hEvent = LogEvent; // Specify event for overlapped object
  311. Overlap.Offset = 0; // Offset is zero for devices
  312. Overlap.OffsetHigh = 0; // OffsetHigh is zero for devices
  313. ReturnStatus = DeviceIoControl(
  314. McaDeviceHandle,
  315. (ULONG)IOCTL_READ_BANKS_ASYNC,
  316. NULL,
  317. 0,
  318. &McaException,
  319. sizeof(MCA_EXCEPTION),
  320. &ActualCount,
  321. &Overlap
  322. );
  323. if ((ReturnStatus == 0) && (GetLastError() != ERROR_IO_PENDING)) {
  324. fprintf(stderr, "%s: Error 0x%lx in IOCTL_READ_BANKS_ASYNC\n",
  325. argv[0], GetLastError());
  326. ExitProcess(1);
  327. }
  328. //
  329. // Either Ioctl was successful or IO is currently pending
  330. // If successful then display the log else wait for specified interval
  331. //
  332. if (ReturnStatus == TRUE) {
  333. //
  334. // Read log async returned succesfully. Display it
  335. //
  336. McaPrintLog(&McaException);
  337. }
  338. //
  339. // Wait forever to get an error
  340. //
  341. WaitStatus = WaitForSingleObject(
  342. LogEvent,
  343. INFINITE
  344. );
  345. if (WaitStatus == WAIT_OBJECT_0) {
  346. //
  347. // The state of the event object is signalled
  348. // check if the I/O operation was successful
  349. //
  350. ReturnStatus = GetOverlappedResult(
  351. McaDeviceHandle,
  352. &Overlap,
  353. &NumberOfBytes,
  354. FALSE // Return immediately
  355. );
  356. if (ReturnStatus == 0) {
  357. fprintf(stderr, "%s: Error 0x%lx in GetOverlappedResult\n",
  358. argv[0], GetLastError());
  359. ExitProcess(1);
  360. }
  361. if (NumberOfBytes) {
  362. //
  363. // Print the results
  364. //
  365. McaPrintLog(&McaException);
  366. } else {
  367. //
  368. // Error as the I/O operation was signalled complete before
  369. // timeout but no data transferred
  370. //
  371. fprintf(stderr, "%s: No data from GetOverlappedResult\n",
  372. argv[0]);
  373. ExitProcess(1);
  374. }
  375. } else {
  376. //
  377. // We should not get any other return value
  378. //
  379. fprintf(stderr, "%s: Unexpected return value from WaitForSingleObject()\n", argv[0]);
  380. ExitProcess(1);
  381. }
  382. CloseHandle(McaDeviceHandle);
  383. return 1;
  384. }