2 * pnpdump - PnP BIOS information dumper
10 typedef struct _CM_PNP_BIOS_DEVICE_NODE
16 USHORT DeviceAttributes;
17 } PACKED CM_PNP_BIOS_DEVICE_NODE,*PCM_PNP_BIOS_DEVICE_NODE;
19 typedef struct _CM_PNP_BIOS_INSTALLATION_CHECK
21 UCHAR Signature[4]; // $PnP (ascii)
26 ULONG EventFlagAddress; // Physical address
27 USHORT RealModeEntryOffset;
28 USHORT RealModeEntrySegment;
29 USHORT ProtectedModeEntryOffset;
30 ULONG ProtectedModeCodeBaseAddress;
32 USHORT RealModeDataBaseAddress;
33 ULONG ProtectedModeDataBaseAddress;
34 } PACKED CM_PNP_BIOS_INSTALLATION_CHECK, *PCM_PNP_BIOS_INSTALLATION_CHECK;
36 typedef struct _PNP_ID_NAME_
40 } PNP_ID_NAME, *PPNP_ID_NAME;
43 static char Hex[] = "0123456789ABCDEF";
45 static PNP_ID_NAME PnpName[] =
47 /* Interrupt Controllers */
48 {"PNP0000", "AT Interrupt Controller"},
49 {"PNP0001", "EISA Interrupt Controller"},
50 {"PNP0002", "MCA Interrupt Controller"},
52 {"PNP0004", "Cyrix SLiC MP Interrupt Controller"},
55 {"PNP0100", "AT Timer"},
56 {"PNP0101", "EISA Timer"},
57 {"PNP0102", "MCA Timer"},
60 {"PNP0200", "AT DMA Controller"},
61 {"PNP0201", "EISA DMA Controller"},
62 {"PNP0202", "MCA DMA Controller"},
65 {"PNP0300", "IBM PC/XT Keyboard (83 keys)"},
66 {"PNP0301", "IBM PC/AT Keyboard (86 keys)"},
67 {"PNP0302", "IBM PC/XT Keyboard (84 keys)"},
68 {"PNP0303", "IBM Enhanced (101/102 keys)"},
69 {"PNP0304", "Olivetti Keyboard (83 keys)"},
70 {"PNP0305", "Olivetti Keyboard (102 keys)"},
71 {"PNP0306", "Olivetti Keyboard (86 keys)"},
72 {"PNP0307", "Microsoft Windows(R) Keyboard"},
73 {"PNP0308", "General Input Device Emulation Interface (GIDEI) legacy"},
74 {"PNP0309", "Olivetti Keyboard (A101/102 key)"},
75 {"PNP030A", "AT&T 302 keyboard"},
76 {"PNP030B", "Reserved by Microsoft"},
77 {"PNP0320", "Japanese 101-key keyboard"},
78 {"PNP0321", "Japanese AX keyboard"},
79 {"PNP0322", "Japanese 106-key keyboard A01"},
80 {"PNP0323", "Japanese 106-key keyboard 002/003"},
81 {"PNP0324", "Japanese 106-key keyboard 001"},
82 {"PNP0325", "Japanese Toshiba Desktop keyboard"},
83 {"PNP0326", "Japanese Toshiba Laptop keyboard"},
84 {"PNP0327", "Japanese Toshiba Notebook keyboard"},
85 {"PNP0340", "Korean 84-key keyboard"},
86 {"PNP0341", "Korean 86-key keyboard"},
87 {"PNP0342", "Korean Enhanced keyboard"},
88 {"PNP0343", "Korean Enhanced keyboard 101b"},
89 {"PNP0343", "Korean Enhanced keyboard 101c"},
90 {"PNP0344", "Korean Enhanced keyboard 103"},
93 {"PNP0400", "Standard LPT printer port"},
94 {"PNP0401", "ECP printer port"},
97 {"PNP0500", "Standard PC COM port"},
98 {"PNP0501", "16550A-compatible COM port"},
99 {"PNP0510", "Generic IRDA-compatible port"},
101 /* Harddisk Controllers */
102 {"PNP0600", "Generic ESDI/ATA/IDE harddisk controller"},
103 {"PNP0601", "Plus Hardcard II"},
104 {"PNP0602", "Plus Hardcard IIXL/EZ"},
105 {"PNP0603", "Generic IDE supporting Microsoft Device Bay Specification"},
107 /* Floppy Controllers */
108 {"PNP0700", "PC standard floppy disk controller"},
109 {"PNP0701", "Standard floppy controller supporting MS Device Bay Specification"},
111 /* obsolete devices */
112 {"PNP0800", "Microsoft Sound System compatible device"},
114 /* Display Adapters */
115 {"PNP0900", "VGA Compatible"},
116 {"PNP0901", "Video Seven VRAM/VRAM II/1024i"},
117 {"PNP0902", "8514/A Compatible"},
118 {"PNP0903", "Trident VGA"},
119 {"PNP0904", "Cirrus Logic Laptop VGA"},
120 {"PNP0905", "Cirrus Logic VGA"},
121 {"PNP0906", "Tseng ET4000"},
122 {"PNP0907", "Western Digital VGA"},
123 {"PNP0908", "Western Digital Laptop VGA"},
124 {"PNP0909", "S3 Inc. 911/924"},
125 {"PNP090A", "ATI Ultra Pro/Plus (Mach 32)"},
126 {"PNP090B", "ATI Ultra (Mach 8)"},
127 {"PNP090C", "XGA Compatible"},
128 {"PNP090D", "ATI VGA Wonder"},
129 {"PNP090E", "Weitek P9000 Graphics Adapter"},
130 {"PNP090F", "Oak Technology VGA"},
131 {"PNP0910", "Compaq QVision"},
132 {"PNP0911", "XGA/2"},
133 {"PNP0912", "Tseng Labs W32/W32i/W32p"},
134 {"PNP0913", "S3 Inc. 801/928/964"},
135 {"PNP0914", "Cirrus Logic 5429/5434 (memory mapped)"},
136 {"PNP0915", "Compaq Advanced VGA (AVGA)"},
137 {"PNP0916", "ATI Ultra Pro Turbo (Mach64)"},
138 {"PNP0917", "Reserved by Microsoft"},
139 {"PNP0918", "Matrox MGA"},
140 {"PNP0919", "Compaq QVision 2000"},
141 {"PNP091A", "Tseng W128"},
142 {"PNP0930", "Chips & Technologies Super VGA"},
143 {"PNP0931", "Chips & Technologies Accelerator"},
144 {"PNP0940", "NCR 77c22e Super VGA"},
145 {"PNP0941", "NCR 77c32blt"},
146 {"PNP09FF", "Plug and Play Monitors (VESA DDC)"},
148 /* Peripheral Buses */
149 {"PNP0A00", "ISA Bus"},
150 {"PNP0A01", "EISA Bus"},
151 {"PNP0A02", "MCA Bus"},
152 {"PNP0A03", "PCI Bus"},
153 {"PNP0A04", "VESA/VL Bus"},
154 {"PNP0A05", "Generic ACPI Bus"},
155 {"PNP0A06", "Generic ACPI Extended-IO Bus (EIO bus)"},
158 {"PNP0800", "AT-style speaker sound"},
159 {"PNP0B00", "AT Real-Time Clock"},
160 {"PNP0C00", "Plug and Play BIOS (only created by the root enumerator)"},
161 {"PNP0C01", "System Board"},
162 {"PNP0C02", "General Plug and Play motherboard registers."},
163 {"PNP0C03", "Plug and Play BIOS Event Notification Interrupt"},
164 {"PNP0C04", "Math Coprocessor"},
165 {"PNP0C05", "APM BIOS (Version independent)"},
166 {"PNP0C06", "Reserved for identification of early Plug and Play BIOS implementation"},
167 {"PNP0C07", "Reserved for identification of early Plug and Play BIOS implementation"},
168 {"PNP0C08", "ACPI system board hardware"},
169 {"PNP0C09", "ACPI Embedded Controller"},
170 {"PNP0C0A", "ACPI Control Method Battery"},
171 {"PNP0C0B", "ACPI Fan"},
172 {"PNP0C0C", "ACPI power button device"},
173 {"PNP0C0D", "ACPI lid device"},
174 {"PNP0C0E", "ACPI sleep button device"},
175 {"PNP0C0F", "PCI interrupt link device"},
176 {"PNP0C10", "ACPI system indicator device"},
177 {"PNP0C11", "ACPI thermal zone"},
178 {"PNP0C12", "Device Bay Controller"},
180 /* PCMCIA Controllers */
181 {"PNP0E00", "Intel 82365-Compatible PCMCIA Controller"},
182 {"PNP0E01", "Cirrus Logic CL-PD6720 PCMCIA Controller"},
183 {"PNP0E02", "VLSI VL82C146 PCMCIA Controller"},
184 {"PNP0E03", "Intel 82365-compatible CardBus controller"},
187 {"PNP0F00", "Microsoft Bus Mouse"},
188 {"PNP0F01", "Microsoft Serial Mouse"},
189 {"PNP0F02", "Microsoft InPort Mouse"},
190 {"PNP0F03", "Microsoft PS/2-style Mouse"},
191 {"PNP0F04", "Mouse Systems Mouse"},
192 {"PNP0F05", "Mouse Systems 3-Button Mouse (COM2)"},
193 {"PNP0F06", "Genius Mouse (COM1)"},
194 {"PNP0F07", "Genius Mouse (COM2)"},
195 {"PNP0F08", "Logitech Serial Mouse"},
196 {"PNP0F09", "Microsoft BallPoint Serial Mouse"},
197 {"PNP0F0A", "Microsoft Plug and Play Mouse"},
198 {"PNP0F0B", "Microsoft Plug and Play BallPoint Mouse"},
199 {"PNP0F0C", "Microsoft-compatible Serial Mouse"},
200 {"PNP0F0D", "Microsoft-compatible InPort-compatible Mouse"},
201 {"PNP0F0E", "Microsoft-compatible PS/2-style Mouse"},
202 {"PNP0F0F", "Microsoft-compatible Serial BallPoint-compatible Mouse"},
203 {"PNP0F10", "Texas Instruments QuickPort Mouse"},
204 {"PNP0F11", "Microsoft-compatible Bus Mouse"},
205 {"PNP0F12", "Logitech PS/2-style Mouse"},
206 {"PNP0F13", "PS/2 Port for PS/2-style Mice"},
207 {"PNP0F14", "Microsoft Kids Mouse"},
208 {"PNP0F15", "Logitech bus mouse"},
209 {"PNP0F16", "Logitech SWIFT device"},
210 {"PNP0F17", "Logitech-compatible serial mouse"},
211 {"PNP0F18", "Logitech-compatible bus mouse"},
212 {"PNP0F19", "Logitech-compatible PS/2-style Mouse"},
213 {"PNP0F1A", "Logitech-compatible SWIFT Device"},
214 {"PNP0F1B", "HP Omnibook Mouse"},
215 {"PNP0F1C", "Compaq LTE Trackball PS/2-style Mouse"},
216 {"PNP0F1D", "Compaq LTE Trackball Serial Mouse"},
217 {"PNP0F1E", "Microsoft Kids Trackball Mouse"},
218 {"PNP0F1F", "Reserved by Microsoft Input Device Group"},
219 {"PNP0F20", "Reserved by Microsoft Input Device Group"},
220 {"PNP0F21", "Reserved by Microsoft Input Device Group"},
221 {"PNP0F22", "Reserved by Microsoft Input Device Group"},
222 {"PNP0F23", "Reserved by Microsoft Input Device Group"},
223 {"PNP0FFF", "Reserved by Microsoft Systems"},
225 /* List Terminator */
230 /* FUNCTIONS ****************************************************************/
233 GetDeviceName(char *PnpId)
238 while (IdName->PnpId != NULL)
240 if (!strcmp(IdName->PnpId, PnpId))
241 return IdName->DeviceName;
246 return "Unknown Device";
251 GetPnpKey(PHKEY PnpKey)
263 lError = RegOpenKey(HKEY_LOCAL_MACHINE,
264 "HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter",
266 if (lError != ERROR_SUCCESS)
269 /* Enumerate buses */
270 for (dwBus = 0; ; dwBus++)
272 sprintf(szBuffer, "%lu", dwBus);
274 lError = RegOpenKey(hAdapterKey,
277 if (lError != ERROR_SUCCESS)
279 RegCloseKey(hAdapterKey);
284 lError = RegQueryValueEx(hBusKey,
290 if (lError != ERROR_SUCCESS)
292 RegCloseKey(hBusKey);
293 RegCloseKey(hAdapterKey);
297 if (dwType == REG_SZ && stricmp(szBuffer, "pnp bios") == 0)
300 RegCloseKey(hAdapterKey);
301 return ERROR_SUCCESS;
304 RegCloseKey(hBusKey);
312 PnpDecodeIrq(unsigned char *Ptr)
319 IrqMask |= (*Ptr << 8);
323 for (i = 0; i < 16; i++)
325 if (IrqMask & (1 << i))
336 PnpDecodeDma(unsigned char *Ptr)
338 unsigned char DmaChannel;
339 unsigned char DmaStatus;
348 for (i = 0; i < 8; i++)
350 if (DmaChannel & (1 << i))
361 PnpDecodeIoPort(unsigned char *Ptr)
372 MinBase += (*Ptr << 8);
376 MaxBase += (*Ptr << 8);
382 printf(" I/O Port descriptor\n");
383 printf(" MinBase 0x%x MaxBase 0x%x Align %u Length %u\n",
384 MinBase, MaxBase, Align, Length);
389 PnpDecodeFixedIoPort(unsigned char *Ptr)
396 IoPort += (*Ptr << 8);
400 printf(" Fixed I/O Port descriptor\n");
401 printf(" PortBase 0x%hx Length 0x%x\n",
407 printf(" Fixed location I/O Port descriptor: 0x%x\n",
412 printf(" Fixed location I/O Port descriptor: 0x%x - 0x%x\n",
414 IoPort + Length - 1);
421 PnpDecodeMemory16(unsigned char *Ptr)
435 MinBase += (*Ptr << 8);
440 MaxBase += (*Ptr << 8);
445 Align += (*Ptr << 8);
450 Length += (*Ptr << 8);
452 printf(" 16-Bit memory range descriptor\n");
453 printf(" MinBase 0x%hx MaxBase 0x%hx Align 0x%hx Length 0x%hx Flags 0x%02x\n",
454 MinBase, MaxBase, Align,Length, Info);
459 PnpDecodeMemory32(unsigned char *Ptr)
473 MinBase += (*Ptr << 8);
475 MinBase += (*Ptr << 16);
477 MinBase += (*Ptr << 24);
482 MaxBase += (*Ptr << 8);
484 MaxBase += (*Ptr << 16);
486 MaxBase += (*Ptr << 24);
491 Align += (*Ptr << 8);
493 Align += (*Ptr << 16);
495 Align += (*Ptr << 24);
500 Length += (*Ptr << 8);
502 Length += (*Ptr << 16);
504 Length += (*Ptr << 24);
506 printf(" 32-Bit memory range descriptor\n");
507 printf(" MinBase 0x%lx MaxBase 0x%lx Align 0x%lx Length 0x%lx Flags 0x%02x\n",
508 MinBase, MaxBase, Align,Length, Info);
513 PnpDecodeFixedMemory(unsigned char *Ptr)
527 Base += (*Ptr << 16);
529 Base += (*Ptr << 24);
534 Length += (*Ptr << 8);
536 Length += (*Ptr << 16);
538 Length += (*Ptr << 24);
540 printf(" 32-Bit fixed location memory range descriptor\n");
541 printf(" Base 0x%lx Length 0x%lx Flags 0x%02x\n",
546 void PrintDeviceData (PCM_PNP_BIOS_DEVICE_NODE DeviceNode)
548 unsigned char PnpId[8];
550 unsigned int TagSize;
551 unsigned int TagType;
555 printf ("Node: %x Size %hu (0x%hx)\n",
560 memcpy(Id, &DeviceNode->ProductId, 4);
562 PnpId[0] = ((Id[0] >> 2) & 0x1F) + 0x40;
563 PnpId[1] = ((Id[0] << 3) & 0x18) +
564 ((Id[1] >> 5) & 0x07) + 0x40;
565 PnpId[2] = (Id[1] & 0x1F) + 0x40;
567 PnpId[3] = Hex[(Id[2] >> 4) & 0xF];
568 PnpId[4] = Hex[Id[2] & 0x0F];
570 PnpId[5] = Hex[(Id[3] >> 4) & 0x0F];
571 PnpId[6] = Hex[Id[3] & 0x0F];
574 printf(" '%s' (%s)\n",
575 PnpId, GetDeviceName(PnpId));
577 if (DeviceNode->Size > sizeof(CM_PNP_BIOS_DEVICE_NODE))
579 Ptr = (unsigned char *)(DeviceNode + 1);
584 TagType = *Ptr & 0x7F;
588 TagSize += (*Ptr << 16);
595 PnpDecodeMemory16(Ptr);
599 PnpDecodeMemory32(Ptr);
603 PnpDecodeFixedMemory(Ptr);
607 printf(" Large tag: type %u size %u\n",
615 TagType = (*Ptr >> 3) & 0x0F;
616 TagSize = *Ptr & 0x07;
622 printf(" Logical device ID\n");
626 printf(" Compatible device ID\n");
638 PnpDecodeIoPort(Ptr);
642 PnpDecodeFixedIoPort(Ptr);
645 case 0x0F: /* end tag */
649 printf(" Small tag: type %u size %u\n",
666 int main (int argc, char *argv[])
673 PCM_FULL_RESOURCE_DESCRIPTOR lpBuffer;
674 PCM_PNP_BIOS_INSTALLATION_CHECK lpPnpInst;
675 PCM_PNP_BIOS_DEVICE_NODE lpDevNode;
677 DWORD dwDataSize, dwResourceSize;
681 lError = GetPnpKey(&hPnpKey);
682 if (lError != ERROR_SUCCESS)
684 printf("Failed to get PnP-BIOS key\n");
690 printf("Found PnP-BIOS key\n");
693 /* Allocate buffer */
695 lpBuffer = malloc(dwSize);
697 lError = RegQueryValueEx(hPnpKey,
698 "Configuration Data",
703 if (lError != ERROR_SUCCESS)
705 if (lError == ERROR_MORE_DATA)
707 printf("Need to resize buffer to %lu\n", dwSize);
711 printf("Failed to read 'Configuration Data' value\n");
713 RegCloseKey(hPnpKey);
717 // printf ("Data size: %lu\n", dwSize);
719 RegCloseKey(hPnpKey);
721 // printf("Resource count %lu\n", lpBuffer->PartialResourceList.Count);
723 if (lpBuffer->PartialResourceList.Count == 0)
725 printf("Invalid resource count!\n");
730 // printf("lpBuffer %p\n", lpBuffer);
732 dwResourceSize = lpBuffer->PartialResourceList.PartialDescriptors[0].u.DeviceSpecificData.DataSize;
733 // printf("ResourceSize: %lu\n", dwResourceSize);
735 lpPnpInst = (PCM_PNP_BIOS_INSTALLATION_CHECK)
736 ((DWORD)(&lpBuffer->PartialResourceList.PartialDescriptors[0]) +
737 sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
739 // printf("lpPnpInst %p\n", lpPnpInst);
741 printf("Signature '%.4s'\n", lpPnpInst->Signature);
742 if (strncmp(lpPnpInst->Signature, "$PnP", 4))
744 printf("Error: Invalid PnP signature\n");
749 // printf("InstCheck length: %lu\n", lpPnpInst->Length);
751 dwDataSize = sizeof(CM_PNP_BIOS_INSTALLATION_CHECK);
752 lpDevNode = (PCM_PNP_BIOS_DEVICE_NODE)((DWORD)lpPnpInst + sizeof(CM_PNP_BIOS_INSTALLATION_CHECK));
754 if (lpDevNode->Size == 0)
756 printf("Error: Device node size is zero!\n");
761 printf ("Node: %x Size %hu (0x%hx)\n",
771 while (dwDataSize < dwResourceSize)
773 if (lpDevNode->Size == 0)
776 printf ("Node: %x Size %hu (0x%hx)\n",
781 dwDataSize += lpDevNode->Size;
782 lpDevNode = (PCM_PNP_BIOS_DEVICE_NODE)((DWORD)lpDevNode + lpDevNode->Size);
785 printf ("\n Press any key...\n");
788 dwDataSize = sizeof(CM_PNP_BIOS_INSTALLATION_CHECK);
789 lpDevNode = (PCM_PNP_BIOS_DEVICE_NODE)((DWORD)lpPnpInst + sizeof(CM_PNP_BIOS_INSTALLATION_CHECK));
791 while (dwDataSize < dwResourceSize)
793 PrintDeviceData (lpDevNode);
795 printf ("\n Press any key...\n");
798 dwDataSize += lpDevNode->Size;
799 lpDevNode = (PCM_PNP_BIOS_DEVICE_NODE)((DWORD)lpDevNode + lpDevNode->Size);