2 * pnpdump - PnP BIOS information dumper
11 #include <ddk/ntddk.h>
15 typedef struct _CM_PNP_BIOS_DEVICE_NODE
21 USHORT DeviceAttributes
;
22 } CM_PNP_BIOS_DEVICE_NODE
,*PCM_PNP_BIOS_DEVICE_NODE
;
24 typedef struct _CM_PNP_BIOS_INSTALLATION_CHECK
26 UCHAR Signature
[4]; // $PnP (ascii)
31 ULONG EventFlagAddress
; // Physical address
32 USHORT RealModeEntryOffset
;
33 USHORT RealModeEntrySegment
;
34 USHORT ProtectedModeEntryOffset
;
35 ULONG ProtectedModeCodeBaseAddress
;
37 USHORT RealModeDataBaseAddress
;
38 ULONG ProtectedModeDataBaseAddress
;
39 } CM_PNP_BIOS_INSTALLATION_CHECK
, *PCM_PNP_BIOS_INSTALLATION_CHECK
;
43 typedef struct _PNP_ID_NAME_
47 } PNP_ID_NAME
, *PPNP_ID_NAME
;
50 static char Hex
[] = "0123456789ABCDEF";
52 static PNP_ID_NAME PnpName
[] =
54 /* Interrupt Controllers */
55 {"PNP0000", "AT Interrupt Controller"},
56 {"PNP0001", "EISA Interrupt Controller"},
57 {"PNP0002", "MCA Interrupt Controller"},
59 {"PNP0004", "Cyrix SLiC MP Interrupt Controller"},
62 {"PNP0100", "AT Timer"},
63 {"PNP0101", "EISA Timer"},
64 {"PNP0102", "MCA Timer"},
67 {"PNP0200", "AT DMA Controller"},
68 {"PNP0201", "EISA DMA Controller"},
69 {"PNP0202", "MCA DMA Controller"},
72 {"PNP0300", "IBM PC/XT Keyboard (83 keys)"},
73 {"PNP0301", "IBM PC/AT Keyboard (86 keys)"},
74 {"PNP0302", "IBM PC/XT Keyboard (84 keys)"},
75 {"PNP0303", "IBM Enhanced (101/102 keys)"},
76 {"PNP0304", "Olivetti Keyboard (83 keys)"},
77 {"PNP0305", "Olivetti Keyboard (102 keys)"},
78 {"PNP0306", "Olivetti Keyboard (86 keys)"},
79 {"PNP0307", "Microsoft Windows(R) Keyboard"},
80 {"PNP0308", "General Input Device Emulation Interface (GIDEI) legacy"},
81 {"PNP0309", "Olivetti Keyboard (A101/102 key)"},
82 {"PNP030A", "AT&T 302 keyboard"},
83 {"PNP030B", "Reserved by Microsoft"},
84 {"PNP0320", "Japanese 101-key keyboard"},
85 {"PNP0321", "Japanese AX keyboard"},
86 {"PNP0322", "Japanese 106-key keyboard A01"},
87 {"PNP0323", "Japanese 106-key keyboard 002/003"},
88 {"PNP0324", "Japanese 106-key keyboard 001"},
89 {"PNP0325", "Japanese Toshiba Desktop keyboard"},
90 {"PNP0326", "Japanese Toshiba Laptop keyboard"},
91 {"PNP0327", "Japanese Toshiba Notebook keyboard"},
92 {"PNP0340", "Korean 84-key keyboard"},
93 {"PNP0341", "Korean 86-key keyboard"},
94 {"PNP0342", "Korean Enhanced keyboard"},
95 {"PNP0343", "Korean Enhanced keyboard 101b"},
96 {"PNP0343", "Korean Enhanced keyboard 101c"},
97 {"PNP0344", "Korean Enhanced keyboard 103"},
100 {"PNP0400", "Standard LPT printer port"},
101 {"PNP0401", "ECP printer port"},
104 {"PNP0500", "Standard PC COM port"},
105 {"PNP0501", "16550A-compatible COM port"},
106 {"PNP0510", "Generic IRDA-compatible port"},
108 /* Harddisk Controllers */
109 {"PNP0600", "Generic ESDI/ATA/IDE harddisk controller"},
110 {"PNP0601", "Plus Hardcard II"},
111 {"PNP0602", "Plus Hardcard IIXL/EZ"},
112 {"PNP0603", "Generic IDE supporting Microsoft Device Bay Specification"},
114 /* Floppy Controllers */
115 {"PNP0700", "PC standard floppy disk controller"},
116 {"PNP0701", "Standard floppy controller supporting MS Device Bay Specification"},
118 /* obsolete devices */
119 {"PNP0800", "Microsoft Sound System compatible device"},
121 /* Display Adapters */
122 {"PNP0900", "VGA Compatible"},
123 {"PNP0901", "Video Seven VRAM/VRAM II/1024i"},
124 {"PNP0902", "8514/A Compatible"},
125 {"PNP0903", "Trident VGA"},
126 {"PNP0904", "Cirrus Logic Laptop VGA"},
127 {"PNP0905", "Cirrus Logic VGA"},
128 {"PNP0906", "Tseng ET4000"},
129 {"PNP0907", "Western Digital VGA"},
130 {"PNP0908", "Western Digital Laptop VGA"},
131 {"PNP0909", "S3 Inc. 911/924"},
132 {"PNP090A", "ATI Ultra Pro/Plus (Mach 32)"},
133 {"PNP090B", "ATI Ultra (Mach 8)"},
134 {"PNP090C", "XGA Compatible"},
135 {"PNP090D", "ATI VGA Wonder"},
136 {"PNP090E", "Weitek P9000 Graphics Adapter"},
137 {"PNP090F", "Oak Technology VGA"},
138 {"PNP0910", "Compaq QVision"},
139 {"PNP0911", "XGA/2"},
140 {"PNP0912", "Tseng Labs W32/W32i/W32p"},
141 {"PNP0913", "S3 Inc. 801/928/964"},
142 {"PNP0914", "Cirrus Logic 5429/5434 (memory mapped)"},
143 {"PNP0915", "Compaq Advanced VGA (AVGA)"},
144 {"PNP0916", "ATI Ultra Pro Turbo (Mach64)"},
145 {"PNP0917", "Reserved by Microsoft"},
146 {"PNP0918", "Matrox MGA"},
147 {"PNP0919", "Compaq QVision 2000"},
148 {"PNP091A", "Tseng W128"},
149 {"PNP0930", "Chips & Technologies Super VGA"},
150 {"PNP0931", "Chips & Technologies Accelerator"},
151 {"PNP0940", "NCR 77c22e Super VGA"},
152 {"PNP0941", "NCR 77c32blt"},
153 {"PNP09FF", "Plug and Play Monitors (VESA DDC)"},
155 /* Peripheral Buses */
156 {"PNP0A00", "ISA Bus"},
157 {"PNP0A01", "EISA Bus"},
158 {"PNP0A02", "MCA Bus"},
159 {"PNP0A03", "PCI Bus"},
160 {"PNP0A04", "VESA/VL Bus"},
161 {"PNP0A05", "Generic ACPI Bus"},
162 {"PNP0A06", "Generic ACPI Extended-IO Bus (EIO bus)"},
165 {"PNP0800", "AT-style speaker sound"},
166 {"PNP0B00", "AT Real-Time Clock"},
167 {"PNP0C00", "Plug and Play BIOS (only created by the root enumerator)"},
168 {"PNP0C01", "System Board"},
169 {"PNP0C02", "General Plug and Play motherboard registers."},
170 {"PNP0C03", "Plug and Play BIOS Event Notification Interrupt"},
171 {"PNP0C04", "Math Coprocessor"},
172 {"PNP0C05", "APM BIOS (Version independent)"},
173 {"PNP0C06", "Reserved for identification of early Plug and Play BIOS implementation"},
174 {"PNP0C07", "Reserved for identification of early Plug and Play BIOS implementation"},
175 {"PNP0C08", "ACPI system board hardware"},
176 {"PNP0C09", "ACPI Embedded Controller"},
177 {"PNP0C0A", "ACPI Control Method Battery"},
178 {"PNP0C0B", "ACPI Fan"},
179 {"PNP0C0C", "ACPI power button device"},
180 {"PNP0C0D", "ACPI lid device"},
181 {"PNP0C0E", "ACPI sleep button device"},
182 {"PNP0C0F", "PCI interrupt link device"},
183 {"PNP0C10", "ACPI system indicator device"},
184 {"PNP0C11", "ACPI thermal zone"},
185 {"PNP0C12", "Device Bay Controller"},
187 /* PCMCIA Controllers */
188 {"PNP0E00", "Intel 82365-Compatible PCMCIA Controller"},
189 {"PNP0E01", "Cirrus Logic CL-PD6720 PCMCIA Controller"},
190 {"PNP0E02", "VLSI VL82C146 PCMCIA Controller"},
191 {"PNP0E03", "Intel 82365-compatible CardBus controller"},
194 {"PNP0F00", "Microsoft Bus Mouse"},
195 {"PNP0F01", "Microsoft Serial Mouse"},
196 {"PNP0F02", "Microsoft InPort Mouse"},
197 {"PNP0F03", "Microsoft PS/2-style Mouse"},
198 {"PNP0F04", "Mouse Systems Mouse"},
199 {"PNP0F05", "Mouse Systems 3-Button Mouse (COM2)"},
200 {"PNP0F06", "Genius Mouse (COM1)"},
201 {"PNP0F07", "Genius Mouse (COM2)"},
202 {"PNP0F08", "Logitech Serial Mouse"},
203 {"PNP0F09", "Microsoft BallPoint Serial Mouse"},
204 {"PNP0F0A", "Microsoft Plug and Play Mouse"},
205 {"PNP0F0B", "Microsoft Plug and Play BallPoint Mouse"},
206 {"PNP0F0C", "Microsoft-compatible Serial Mouse"},
207 {"PNP0F0D", "Microsoft-compatible InPort-compatible Mouse"},
208 {"PNP0F0E", "Microsoft-compatible PS/2-style Mouse"},
209 {"PNP0F0F", "Microsoft-compatible Serial BallPoint-compatible Mouse"},
210 {"PNP0F10", "Texas Instruments QuickPort Mouse"},
211 {"PNP0F11", "Microsoft-compatible Bus Mouse"},
212 {"PNP0F12", "Logitech PS/2-style Mouse"},
213 {"PNP0F13", "PS/2 Port for PS/2-style Mice"},
214 {"PNP0F14", "Microsoft Kids Mouse"},
215 {"PNP0F15", "Logitech bus mouse"},
216 {"PNP0F16", "Logitech SWIFT device"},
217 {"PNP0F17", "Logitech-compatible serial mouse"},
218 {"PNP0F18", "Logitech-compatible bus mouse"},
219 {"PNP0F19", "Logitech-compatible PS/2-style Mouse"},
220 {"PNP0F1A", "Logitech-compatible SWIFT Device"},
221 {"PNP0F1B", "HP Omnibook Mouse"},
222 {"PNP0F1C", "Compaq LTE Trackball PS/2-style Mouse"},
223 {"PNP0F1D", "Compaq LTE Trackball Serial Mouse"},
224 {"PNP0F1E", "Microsoft Kids Trackball Mouse"},
225 {"PNP0F1F", "Reserved by Microsoft Input Device Group"},
226 {"PNP0F20", "Reserved by Microsoft Input Device Group"},
227 {"PNP0F21", "Reserved by Microsoft Input Device Group"},
228 {"PNP0F22", "Reserved by Microsoft Input Device Group"},
229 {"PNP0F23", "Reserved by Microsoft Input Device Group"},
230 {"PNP0FFF", "Reserved by Microsoft Systems"},
232 /* List Terminator */
237 /* FUNCTIONS ****************************************************************/
240 GetDeviceName(char *PnpId
)
245 while (IdName
->PnpId
!= NULL
)
247 if (!strcmp(IdName
->PnpId
, PnpId
))
248 return IdName
->DeviceName
;
253 return "Unknown Device";
258 GetPnpKey(PHKEY PnpKey
)
270 lError
= RegOpenKey(HKEY_LOCAL_MACHINE
,
271 "HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter",
273 if (lError
!= ERROR_SUCCESS
)
276 /* Enumerate buses */
277 for (dwBus
= 0; ; dwBus
++)
279 sprintf(szBuffer
, "%lu", dwBus
);
281 lError
= RegOpenKey(hAdapterKey
,
284 if (lError
!= ERROR_SUCCESS
)
286 RegCloseKey(hAdapterKey
);
291 lError
= RegQueryValueEx(hBusKey
,
297 if (lError
!= ERROR_SUCCESS
)
299 RegCloseKey(hBusKey
);
300 RegCloseKey(hAdapterKey
);
304 if (dwType
== REG_SZ
&& stricmp(szBuffer
, "pnp bios") == 0)
307 RegCloseKey(hAdapterKey
);
308 return ERROR_SUCCESS
;
311 RegCloseKey(hBusKey
);
319 PnpDecodeIrq(unsigned char *Ptr
)
326 IrqMask
|= (*Ptr
<< 8);
330 for (i
= 0; i
< 16; i
++)
332 if (IrqMask
& (1 << i
))
343 PnpDecodeDma(unsigned char *Ptr
)
345 unsigned char DmaChannel
;
346 unsigned char DmaStatus
;
355 for (i
= 0; i
< 8; i
++)
357 if (DmaChannel
& (1 << i
))
368 PnpDecodeIoPort(unsigned char *Ptr
)
379 MinBase
+= (*Ptr
<< 8);
383 MaxBase
+= (*Ptr
<< 8);
389 printf(" I/O Port descriptor\n");
390 printf(" MinBase 0x%x MaxBase 0x%x Align %u Length %u\n",
391 MinBase
, MaxBase
, Align
, Length
);
396 PnpDecodeFixedIoPort(unsigned char *Ptr
)
403 IoPort
+= (*Ptr
<< 8);
407 printf(" Fixed I/O Port descriptor\n");
408 printf(" PortBase 0x%hx Length 0x%x\n",
414 printf(" Fixed location I/O Port descriptor: 0x%x\n",
419 printf(" Fixed location I/O Port descriptor: 0x%x - 0x%x\n",
421 IoPort
+ Length
- 1);
428 PnpDecodeMemory16(unsigned char *Ptr
)
441 MinBase
+= (*Ptr
<< 8);
446 MaxBase
+= (*Ptr
<< 8);
451 Align
+= (*Ptr
<< 8);
456 Length
+= (*Ptr
<< 8);
458 printf(" 16-Bit memory range descriptor\n");
459 printf(" MinBase 0x%hx MaxBase 0x%hx Align 0x%hx Length 0x%hx Flags 0x%02x\n",
460 MinBase
, MaxBase
, Align
,Length
, Info
);
465 PnpDecodeMemory32(unsigned char *Ptr
)
478 MinBase
+= (*Ptr
<< 8);
480 MinBase
+= (*Ptr
<< 16);
482 MinBase
+= (*Ptr
<< 24);
487 MaxBase
+= (*Ptr
<< 8);
489 MaxBase
+= (*Ptr
<< 16);
491 MaxBase
+= (*Ptr
<< 24);
496 Align
+= (*Ptr
<< 8);
498 Align
+= (*Ptr
<< 16);
500 Align
+= (*Ptr
<< 24);
505 Length
+= (*Ptr
<< 8);
507 Length
+= (*Ptr
<< 16);
509 Length
+= (*Ptr
<< 24);
511 printf(" 32-Bit memory range descriptor\n");
512 printf(" MinBase 0x%lx MaxBase 0x%lx Align 0x%lx Length 0x%lx Flags 0x%02x\n",
513 MinBase
, MaxBase
, Align
,Length
, Info
);
518 PnpDecodeFixedMemory(unsigned char *Ptr
)
531 Base
+= (*Ptr
<< 16);
533 Base
+= (*Ptr
<< 24);
538 Length
+= (*Ptr
<< 8);
540 Length
+= (*Ptr
<< 16);
542 Length
+= (*Ptr
<< 24);
544 printf(" 32-Bit fixed location memory range descriptor\n");
545 printf(" Base 0x%lx Length 0x%lx Flags 0x%02x\n",
550 void PrintDeviceData (PCM_PNP_BIOS_DEVICE_NODE DeviceNode
)
554 unsigned int TagSize
;
555 unsigned int TagType
;
559 printf ("Node: %x Size %hu (0x%hx)\n",
564 memcpy(Id
, &DeviceNode
->ProductId
, 4);
566 PnpId
[0] = ((Id
[0] >> 2) & 0x1F) + 0x40;
567 PnpId
[1] = ((Id
[0] << 3) & 0x18) +
568 ((Id
[1] >> 5) & 0x07) + 0x40;
569 PnpId
[2] = (Id
[1] & 0x1F) + 0x40;
571 PnpId
[3] = Hex
[(Id
[2] >> 4) & 0xF];
572 PnpId
[4] = Hex
[Id
[2] & 0x0F];
574 PnpId
[5] = Hex
[(Id
[3] >> 4) & 0x0F];
575 PnpId
[6] = Hex
[Id
[3] & 0x0F];
578 printf(" '%s' (%s)\n",
579 PnpId
, GetDeviceName(PnpId
));
581 if (DeviceNode
->Size
> sizeof(CM_PNP_BIOS_DEVICE_NODE
))
583 Ptr
= (unsigned char *)(DeviceNode
+ 1);
588 TagType
= *Ptr
& 0x7F;
592 TagSize
+= (*Ptr
<< 16);
599 PnpDecodeMemory16(Ptr
);
603 PnpDecodeMemory32(Ptr
);
607 PnpDecodeFixedMemory(Ptr
);
611 printf(" Large tag: type %u size %u\n",
619 TagType
= (*Ptr
>> 3) & 0x0F;
620 TagSize
= *Ptr
& 0x07;
626 printf(" Logical device ID\n");
630 printf(" Compatible device ID\n");
642 PnpDecodeIoPort(Ptr
);
646 PnpDecodeFixedIoPort(Ptr
);
649 case 0x0F: /* end tag */
653 printf(" Small tag: type %u size %u\n",
670 int main (int argc
, char *argv
[])
677 PCM_FULL_RESOURCE_DESCRIPTOR lpBuffer
;
678 PCM_PNP_BIOS_INSTALLATION_CHECK lpPnpInst
;
679 PCM_PNP_BIOS_DEVICE_NODE lpDevNode
;
681 DWORD dwResourceSize
;
686 if (argc
>1 && (!strcmp(argv
[1],"/S") || !strcmp(argv
[1],"/s")))
691 if (argc
>1 && !strcmp(argv
[1],"/?"))
693 printf("This utility prints the PnP-nodes from the registry\n");
694 printf("\"/s\" prevents the \"Press any key\"\n\n");
698 lError
= GetPnpKey(&hPnpKey
);
699 if (lError
!= ERROR_SUCCESS
)
701 printf("Failed to get PnP-BIOS key\n");
707 printf("Found PnP-BIOS key\n");
710 /* Allocate buffer */
712 lpBuffer
= malloc(dwSize
);
713 if (lpBuffer
== NULL
)
715 printf("Error: malloc() failed\n");
716 RegCloseKey(hPnpKey
);
722 lError
= RegQueryValueEx(hPnpKey
,
723 "Configuration Data",
728 if (lError
== ERROR_MORE_DATA
)
730 lpBuffer
= realloc(lpBuffer
, dwSize
);
731 if (lpBuffer
== NULL
)
733 printf("Error: realloc() of %u bytes failed\n", (unsigned) dwSize
);
734 RegCloseKey(hPnpKey
);
739 while (lError
== ERROR_MORE_DATA
);
740 if (lError
!= ERROR_SUCCESS
)
742 printf("Failed to read 'Configuration Data' value\n");
744 RegCloseKey(hPnpKey
);
748 // printf ("Data size: %lu\n", dwSize);
750 RegCloseKey(hPnpKey
);
752 // printf("Resource count %lu\n", lpBuffer->PartialResourceList.Count);
754 if (lpBuffer
->PartialResourceList
.Count
== 0)
756 printf("Invalid resource count!\n");
761 // printf("lpBuffer %p\n", lpBuffer);
763 dwResourceSize
= lpBuffer
->PartialResourceList
.PartialDescriptors
[0].u
.DeviceSpecificData
.DataSize
;
764 // printf("ResourceSize: %lu\n", dwResourceSize);
766 lpPnpInst
= (PCM_PNP_BIOS_INSTALLATION_CHECK
)
767 ((ULONG_PTR
)(&lpBuffer
->PartialResourceList
.PartialDescriptors
[0]) +
768 sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
));
770 // printf("lpPnpInst %p\n", lpPnpInst);
772 printf("Signature '%.4s'\n", lpPnpInst
->Signature
);
773 if (strncmp((PCHAR
)lpPnpInst
->Signature
, "$PnP", 4))
775 printf("Error: Invalid PnP signature\n");
780 // printf("InstCheck length: %lu\n", lpPnpInst->Length);
782 dwDataSize
= sizeof(CM_PNP_BIOS_INSTALLATION_CHECK
);
783 lpDevNode
= (PCM_PNP_BIOS_DEVICE_NODE
)((DWORD
)lpPnpInst
+ sizeof(CM_PNP_BIOS_INSTALLATION_CHECK
));
785 if (lpDevNode
->Size
== 0)
787 printf("Error: Device node size is zero!\n");
792 printf("Node: %x Size %hu (0x%hx)\n",
802 while (dwDataSize
< dwResourceSize
)
804 if (lpDevNode
->Size
== 0)
807 printf("Node: %x Size %hu (0x%hx)\n",
812 dwDataSize
+= lpDevNode
->Size
;
813 lpDevNode
= (PCM_PNP_BIOS_DEVICE_NODE
)((DWORD
)lpDevNode
+ lpDevNode
->Size
);
818 printf("\n Press any key...\n");
826 dwDataSize
= sizeof(CM_PNP_BIOS_INSTALLATION_CHECK
);
827 lpDevNode
= (PCM_PNP_BIOS_DEVICE_NODE
)((DWORD
)lpPnpInst
+ sizeof(CM_PNP_BIOS_INSTALLATION_CHECK
));
829 while (dwDataSize
< dwResourceSize
)
831 if (lpDevNode
->Size
== 0)
834 PrintDeviceData(lpDevNode
);
838 printf("\n Press any key...\n");
846 dwDataSize
+= lpDevNode
->Size
;
847 lpDevNode
= (PCM_PNP_BIOS_DEVICE_NODE
)((DWORD
)lpDevNode
+ lpDevNode
->Size
);