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.

672 lines
17 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. mps.c
  5. Abstract:
  6. WinDbg Extension Api
  7. Author:
  8. Peter Johnston (peterj) 30-September-1997
  9. Environment:
  10. User Mode.
  11. Revision History:
  12. --*/
  13. #include "precomp.h"
  14. #pragma hdrstop
  15. //
  16. // HACKHACK
  17. //
  18. // The debugger extensions are a little bit broken at the
  19. // moment (6/6/00) and I can't read a bitfield. So I'm
  20. // including the type here. And it doesn't matter
  21. // because this code only runs on 32-bit machines.
  22. //
  23. typedef struct _CPUIDENTIFIER {
  24. ULONG Stepping : 4;
  25. ULONG Model : 4;
  26. ULONG Family : 4;
  27. ULONG Reserved : 20;
  28. } CPUIDENTIFIER, *PCPUIDENTIFIER;
  29. //
  30. // xReadMemory is easier to use than ReadMemory and is
  31. // defined in ..\devnode.c
  32. //
  33. BOOLEAN
  34. xReadMemory(
  35. ULONG64 S,
  36. PVOID D,
  37. ULONG Len
  38. );
  39. PUCHAR
  40. mpsGetIntTypeDesc(
  41. UCHAR IntType
  42. )
  43. {
  44. switch (IntType) {
  45. case INT_TYPE_INTR:
  46. return "intr ";
  47. case INT_TYPE_NMI:
  48. return "nmi ";
  49. case INT_TYPE_SMI:
  50. return "smi ";
  51. case INT_TYPE_EXTINT:
  52. return "extint";
  53. default:
  54. return "unknwn";
  55. }
  56. }
  57. PUCHAR
  58. mpsExtAddrTypeToText(
  59. UCHAR AddressType
  60. )
  61. {
  62. switch (AddressType) {
  63. case MPS_ADDRESS_MAP_IO:
  64. return "io port ";
  65. case MPS_ADDRESS_MAP_MEMORY:
  66. return "memory ";
  67. case MPS_ADDRESS_MAP_PREFETCH_MEMORY:
  68. return "prefetch mem";
  69. case MPS_ADDRESS_MAP_UNDEFINED:
  70. return "mps undef ";
  71. default:
  72. return "unknown type";
  73. }
  74. }
  75. PUCHAR
  76. mpsExtCompatibleListToText(
  77. ULONG List
  78. )
  79. {
  80. switch (List) {
  81. case 0:
  82. return "ISA";
  83. case 1:
  84. return "VGA";
  85. default:
  86. return "unknown predefined range";
  87. }
  88. }
  89. BOOLEAN
  90. mpsBaseTable(
  91. ULONG64 BaseTableAddress,
  92. ULONG EntryCount
  93. )
  94. /*++
  95. Routine Description:
  96. Dumps entries from the MPS BASE table.
  97. Arguments:
  98. BaseTableAddress Address (in local memory) of the Base Entry Table
  99. EntryCount Number of entries in this table.
  100. Return Value:
  101. TRUE is all is well
  102. FALSE if execution cannot continue (ie we encountered an unknown
  103. entry type. Can't continue because we don't know how big
  104. it is.
  105. --*/
  106. {
  107. ULONG64 bp = BaseTableAddress;
  108. ULONG offset;
  109. ULONG featureFlags;
  110. ULONG64 cpuAddr;
  111. ULONG Family, Model, Stepping;
  112. CHAR busId[8] = {0};
  113. CPUIDENTIFIER cpuId;
  114. //dprintf("BaseTableAddress: %x%x\n", BaseTableAddress);
  115. while (EntryCount--) {
  116. ULONG64 CharAtAddress;
  117. GetFieldValue(bp, "UCHAR", NULL, CharAtAddress);
  118. //dprintf("CharAtAddress: %x%x %x\n", bp, CharAtAddress);
  119. dprintf(" ");
  120. switch ((UCHAR) CharAtAddress) {
  121. case ENTRY_PROCESSOR:
  122. {
  123. InitTypeRead(bp, hal!_PcMpProcessorEntry);
  124. dprintf(
  125. "processor. %s%sL.APIC ID %02x Vers %02x\n",
  126. (ULONG) ReadField(CpuFlags) & CPU_ENABLED ? "EN " : "",
  127. (ULONG) ReadField(CpuFlags) & BSP_CPU ? "BP " : "",
  128. (ULONG) ReadField(LocalApicId),
  129. (ULONG) ReadField(LocalApicVersion)
  130. );
  131. featureFlags = (ULONG)ReadField(FeatureFlags);
  132. GetFieldOffset("hal!_PcMpProcessorEntry", "CpuIdentification", &offset);
  133. cpuAddr = (bp + offset);
  134. xReadMemory(cpuAddr, &cpuId, 4);
  135. dprintf(
  136. " Family %x, Model %x, Stepping %x, CPUID Flags %04x\n",
  137. cpuId.Family,
  138. cpuId.Model,
  139. cpuId.Stepping,
  140. featureFlags
  141. );
  142. bp += GetTypeSize("hal!_PcMpProcessorEntry");
  143. }
  144. break;
  145. case ENTRY_BUS:
  146. {
  147. GetFieldOffset("hal!_PcMpBusEntry", "BusType", &offset);
  148. xReadMemory((bp + offset), busId, 6);
  149. InitTypeRead(bp, hal!_PcMpBusEntry);
  150. dprintf(
  151. "bus. id %02x, type %6.6s\n",
  152. (ULONG) ReadField(BusId),
  153. busId
  154. );
  155. bp += GetTypeSize("hal!_PcMpBusEntry");
  156. }
  157. break;
  158. case ENTRY_IOAPIC:
  159. {
  160. InitTypeRead(bp, hal!_PcMpIoApicEntry);
  161. bp += GetTypeSize("hal!_PcMpIoApicEntry");
  162. dprintf(
  163. "io apic. %s id %02x vers %02x @ %08x\n",
  164. (ULONG) ReadField(IoApicFlag) & IO_APIC_ENABLED ? "EN" : "DI",
  165. (ULONG) ReadField(IoApicId),
  166. (ULONG) ReadField(IoApicVersion),
  167. (ULONG) ReadField(IoApicAddress)
  168. );
  169. }
  170. break;
  171. case ENTRY_INTI:
  172. {
  173. InitTypeRead(bp, hal!_PcMpApicIntiEntry);
  174. bp += GetTypeSize("hal!_PcMpApicIntiEntry");
  175. dprintf(
  176. "io int. %s po=%x el=%x, srcbus %02x irq %02x dst apic %02x intin %02x\n",
  177. mpsGetIntTypeDesc((UCHAR) ReadField(IntType)),
  178. (ULONG) ReadField(Signal.Polarity),
  179. (ULONG) ReadField(Signal.Level),
  180. (ULONG) ReadField(SourceBusId),
  181. (ULONG) ReadField(SourceBusIrq),
  182. (ULONG) ReadField(IoApicId),
  183. (ULONG) ReadField(IoApicInti)
  184. );
  185. }
  186. break;
  187. case ENTRY_LINTI:
  188. {
  189. InitTypeRead(bp, hal!_PcMpLintiEntry);
  190. bp += GetTypeSize("hal!_PcMpLintiEntry");
  191. dprintf(
  192. "lcl int. %s po=%x el=%x, srcbus %02x irq %02x dst apic %02x intin %02x\n",
  193. mpsGetIntTypeDesc((UCHAR) ReadField(IntType)),
  194. (ULONG) ReadField(Signal.Polarity),
  195. (ULONG) ReadField(Signal.Level),
  196. (ULONG) ReadField(SourceBusId),
  197. (ULONG) ReadField(SourceBusIrq),
  198. (ULONG) ReadField(DestLocalApicId),
  199. (ULONG) ReadField(DestLocalApicInti)
  200. );
  201. }
  202. break;
  203. default:
  204. dprintf(
  205. "Unknown MPS base type 0x%02x, cannot continue.\n",
  206. CharAtAddress
  207. );
  208. return FALSE;
  209. }
  210. }
  211. return TRUE;
  212. }
  213. BOOLEAN
  214. mpsExtendedTable(
  215. ULONG64 ExtendedTableAddress,
  216. ULONG64 ExtendedTableAddressEnd
  217. )
  218. /*++
  219. Routine Description:
  220. Dumps entries from the MPS Extended table.
  221. Arguments:
  222. BaseTableAddress Address (in local memory) of the Base Entry Table
  223. EntryCount Number of entries in this table.
  224. Return Value:
  225. TRUE is all is well
  226. FALSE if execution cannot continue (ie we encountered an unknown
  227. entry type. Can't continue because we don't know how big
  228. it is.
  229. --*/
  230. {
  231. ULONG64 bp = ExtendedTableAddress;
  232. if (!bp) {
  233. return TRUE;
  234. }
  235. dprintf(" extended table entries\n");
  236. while (bp < ExtendedTableAddressEnd) {
  237. if (InitTypeRead(bp, hal!MPS_EXTENTRY)) {
  238. dprintf("Cannot get hal!MPS_EXTENTRY at %p\n", bp);
  239. return FALSE;
  240. }
  241. if (ReadField(Length) == 0) {
  242. dprintf("Malformed extended entry, length = 0, cannot continue.\n");
  243. return FALSE;
  244. }
  245. dprintf(" ");
  246. switch ((ULONG) ReadField(Type)) {
  247. case EXTTYPE_BUS_ADDRESS_MAP:
  248. dprintf(
  249. "address. bus %02x %s % 16I64x len %16I64x\n",
  250. (ULONG) ReadField(u.AddressMap.BusId),
  251. mpsExtAddrTypeToText((UCHAR) ReadField(u.AddressMap.Type)),
  252. ReadField(u.AddressMap.Base),
  253. ReadField(u.AddressMap.Length)
  254. );
  255. break;
  256. case EXTTYPE_BUS_HIERARCHY:
  257. dprintf(
  258. "child bus. bus %02x is child of bus %02x%s\n",
  259. (ULONG) ReadField(u.BusHierarchy.BusId),
  260. (ULONG) ReadField(u.BusHierarchy.ParentBusId),
  261. (ULONG) ReadField(u.BusHierarchy.SubtractiveDecode) ? " subtractive" : ""
  262. );
  263. break;
  264. case EXTTYPE_BUS_COMPATIBLE_MAP:
  265. dprintf(
  266. "bus comp. bus %02x %s %s ranges\n",
  267. (ULONG) ReadField(u.CompatibleMap.BusId),
  268. (ULONG) ReadField(u.CompatibleMap.Modifier) ? "exclude" : "include",
  269. mpsExtCompatibleListToText((ULONG) ReadField(u.CompatibleMap.List))
  270. );
  271. break;
  272. case EXTTYPE_PERSISTENT_STORE:
  273. dprintf(
  274. "persist. % 16I64x len %16I64x\n",
  275. ReadField(u.PersistentStore.Address),
  276. ReadField(u.PersistentStore.Length)
  277. );
  278. break;
  279. default:
  280. dprintf(
  281. "Unknown MPS extended type 0x%02x, cannot continue.\n",
  282. (ULONG) ReadField(Type)
  283. );
  284. return FALSE;
  285. }
  286. //
  287. // Advance to the next entry.
  288. //
  289. bp += (ULONG) ReadField(Length);
  290. }
  291. return TRUE;
  292. }
  293. DECLARE_API( mps )
  294. /*++
  295. Routine Description:
  296. Dumps the MPS (Multi Processor Specification) BIOS Tables.
  297. Arguments:
  298. None
  299. Return Value:
  300. None
  301. --*/
  302. {
  303. ULONG64 addr;
  304. UCHAR halName[32];
  305. UCHAR OemId[20]={0}, OemProductId[20]={0};
  306. ULONG64 PcMpTablePtr;
  307. ULONG entryCount;
  308. PUCHAR bp;
  309. UCHAR c;
  310. ULONG i, TableLength, ExtTableLength, Sz;
  311. UCHAR PcMpCfgTable[100];
  312. PUCHAR MpsBaseTable = NULL;
  313. PUCHAR MpsExtendedTable = NULL;
  314. PUCHAR MpsExtendedTableEnd;
  315. ULONG OemOffset, SigOffset, Sig = 0;
  316. ULONG BiosRev = 0;
  317. BOOLEAN halNameKnown = FALSE;
  318. if (TargetIsDump) {
  319. dprintf("!mps doesnt work on dump targets\n");
  320. return E_INVALIDARG;
  321. }
  322. //
  323. // Check to see if user entered the address of the MPS tables.
  324. // If not, try to obtain it using HAL symbols.
  325. //
  326. PcMpTablePtr = GetExpression(args);
  327. if (PcMpTablePtr == 0) {
  328. //
  329. // Get address of PC+MP structure from the HAL.
  330. // N.B. Should add code to allow hunting for the floating pointer.
  331. //
  332. addr = GetExpression("hal!HalName");
  333. if (addr == 0) {
  334. dprintf(
  335. "Unable to use HAL symbols (hal!HalName), please verify symbols.\n"
  336. );
  337. return E_INVALIDARG;
  338. }
  339. if (!xReadMemory(addr, halName, sizeof(halName))) {
  340. dprintf(
  341. "Failed to read HalName from host memory, quitting.\n"
  342. );
  343. return E_INVALIDARG;
  344. }
  345. halName[sizeof(halName)-1] = '\0';
  346. if (strstr(halName, "MPS ") == NULL) {
  347. dprintf("HAL = \"%s\".\n", halName);
  348. dprintf("HAL does not appear to be an MPS HAL, quitting.\n");
  349. return E_INVALIDARG;
  350. }
  351. halNameKnown = TRUE;
  352. addr = GetExpression("hal!PcMpTablePtr");
  353. if (addr == 0) {
  354. dprintf(
  355. "Unable to get address of hal!PcMpTablePtr, cannot continue.\n"
  356. );
  357. return E_INVALIDARG;
  358. }
  359. if (!ReadPointer(addr, &PcMpTablePtr)) {
  360. dprintf(
  361. "Failed to read PcMpTablePtr from host memory, cannot continue.\n"
  362. );
  363. return E_INVALIDARG;
  364. }
  365. }
  366. if (InitTypeRead(PcMpTablePtr, hal!PcMpTable)) {
  367. dprintf(
  368. "Failed to read MP Configuration Table Header @%08p\n"
  369. "Cannot continue.\n",
  370. PcMpTablePtr
  371. );
  372. return E_INVALIDARG;
  373. }
  374. GetFieldOffset("hal!PcMpTable", "Signature", &SigOffset);
  375. xReadMemory(PcMpTablePtr + SigOffset, &Sig, sizeof(Sig));
  376. if (Sig != PCMP_SIGNATURE) {
  377. dprintf(
  378. "MP Config Table Signature doesn't match. Cannot continue.\n"
  379. );
  380. return E_INVALIDARG;
  381. }
  382. dprintf(" BIOS Revision ");
  383. BiosRev = (ULONG) ReadField(Revision);
  384. switch (BiosRev) {
  385. case 1:
  386. dprintf(
  387. "MPS 1.1 (WARNING: This BIOS might not support NT 5 depending\n"
  388. " upon system configuration.)\n"
  389. );
  390. break;
  391. case 4:
  392. dprintf(
  393. "MPS 1.4 "
  394. );
  395. break;
  396. default:
  397. dprintf(
  398. "Unknown MPS revision byte 0x%2x, dumped values\n"
  399. " may be incorrect.\n",
  400. BiosRev);
  401. break;
  402. }
  403. if (halNameKnown) {
  404. dprintf(" HAL = %s", halName);
  405. }
  406. dprintf("\n");
  407. GetFieldOffset("hal!PcMpTable", "OemId", &OemOffset);
  408. xReadMemory(PcMpTablePtr + OemOffset, OemId, 8);
  409. dprintf(
  410. " OEM ID :%s\n",
  411. OemId
  412. );
  413. GetFieldOffset("hal!PcMpTable", "OemProductId", &OemOffset);
  414. xReadMemory(PcMpTablePtr + OemOffset, OemProductId, 12);
  415. dprintf(
  416. " OEM Product ID :%s\n",
  417. OemProductId
  418. );
  419. TableLength = (ULONG) ReadField(TableLength);
  420. Sz = GetTypeSize("hal!PcMpTable");
  421. if (TableLength <= Sz) {
  422. dprintf(
  423. "MPS Base Table length (%d) is too small to be reasonable,\n",
  424. TableLength
  425. );
  426. dprintf(
  427. "Must be >= sizeof(fixed table header) (%d bytes). "
  428. "Cannot continue.\n",
  429. Sz
  430. );
  431. return E_INVALIDARG;
  432. }
  433. //
  434. // Get memory for the base and extended tables and read them from
  435. // memory.
  436. //
  437. MpsBaseTable = malloc( TableLength - Sz);
  438. if (!MpsBaseTable) {
  439. dprintf(
  440. "Could not allocate %d bytes local memory, quitting.\n",
  441. TableLength - Sz
  442. );
  443. return E_INVALIDARG;
  444. }
  445. if (!xReadMemory(PcMpTablePtr + Sz,
  446. MpsBaseTable,
  447. TableLength - Sz)) {
  448. dprintf("Failed to read MPS Base Table from host memory. Quitting.\n");
  449. goto cleanup;
  450. }
  451. if (ExtTableLength = (ULONG) ReadField(ExtTableLength)) {
  452. MpsExtendedTable = malloc(ExtTableLength);
  453. if (!MpsExtendedTable) {
  454. dprintf(
  455. "Could not allocate %d bytes local memory for extended MPS Table, quitting.\n",
  456. ExtTableLength
  457. );
  458. goto cleanup;
  459. }
  460. if (!xReadMemory(PcMpTablePtr + TableLength,
  461. MpsExtendedTable,
  462. ExtTableLength)) {
  463. dprintf(
  464. "Could not read MPS Extended table from host memory.\n"
  465. "Will attempt to dump base structures.\n"
  466. );
  467. free(MpsExtendedTable);
  468. MpsExtendedTable = NULL;
  469. }
  470. MpsExtendedTableEnd = MpsExtendedTable + ExtTableLength;
  471. }
  472. //
  473. // Validate checksums.
  474. //
  475. // Base checksum is the sum of all bytes (inc checksum) in the
  476. // base table (including the fixed header).
  477. //
  478. c = 0;
  479. //
  480. // Sum fixed header.
  481. //
  482. if (Sz > sizeof(PcMpCfgTable)) {
  483. return E_INVALIDARG;
  484. }
  485. xReadMemory(PcMpTablePtr, PcMpCfgTable, Sz);
  486. bp = (PUCHAR)&PcMpCfgTable[0];
  487. for (i = 0; i < Sz; i++) {
  488. c += *bp++;
  489. }
  490. //
  491. // Add rest of base table.
  492. //
  493. bp = MpsBaseTable;
  494. for (i = 0; i < TableLength - Sz; i++) {
  495. c += *bp++;
  496. }
  497. //
  498. // The result should be zero.
  499. //
  500. if (c) {
  501. dprintf(
  502. "MPS Base Table checksum is in error.\n"
  503. "Found 0x%02x, Computed 0x%02x (Total 0x%02x).\n",
  504. (ULONG) ReadField(Checksum),
  505. (UCHAR)(c - (UCHAR) ReadField(Checksum)),
  506. c
  507. );
  508. }
  509. //
  510. // Now do the extended table checksum. This one doesn't include
  511. // itself so we should just match (rather than end up with zero).
  512. //
  513. if (MpsExtendedTable) {
  514. c = 0;
  515. bp = MpsExtendedTable;
  516. for (i = 0; i < ExtTableLength; i++) {
  517. c += *bp++;
  518. }
  519. //
  520. // To sum to zero it needs to end up being it's opposite.
  521. //
  522. c = -c;
  523. if (c != (UCHAR) ReadField(ExtTableChecksum)) {
  524. dprintf(
  525. "MPS Extended Table checksum is in error.\n"
  526. "Found 0x%02x, Computed 0x%02x.\n",
  527. (ULONG) ReadField(ExtTableChecksum),
  528. c
  529. );
  530. }
  531. }
  532. //
  533. // Dump the base table.
  534. //
  535. if (!mpsBaseTable(PcMpTablePtr + Sz, (ULONG) ReadField(NumOfEntries))) {
  536. goto cleanup;
  537. }
  538. //
  539. // Dump the extended table.
  540. //
  541. if (!mpsExtendedTable(PcMpTablePtr + TableLength, PcMpTablePtr + TableLength + ExtTableLength )) {
  542. goto cleanup;
  543. }
  544. cleanup:
  545. if (MpsBaseTable) {
  546. free(MpsBaseTable);
  547. }
  548. if (MpsExtendedTable) {
  549. free(MpsExtendedTable);
  550. }
  551. return S_OK;
  552. }