Source code of Windows XP (NT5)
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.

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