/* * pnpdump - PnP BIOS information dumper */ #include #include #include #include #include #include #include typedef struct _CM_PNP_BIOS_DEVICE_NODE { USHORT Size; UCHAR Node; ULONG ProductId; UCHAR DeviceType[3]; USHORT DeviceAttributes; } CM_PNP_BIOS_DEVICE_NODE,*PCM_PNP_BIOS_DEVICE_NODE; typedef struct _CM_PNP_BIOS_INSTALLATION_CHECK { UCHAR Signature[4]; // $PnP (ascii) UCHAR Revision; UCHAR Length; USHORT ControlField; UCHAR Checksum; ULONG EventFlagAddress; // Physical address USHORT RealModeEntryOffset; USHORT RealModeEntrySegment; USHORT ProtectedModeEntryOffset; ULONG ProtectedModeCodeBaseAddress; ULONG OemDeviceId; USHORT RealModeDataBaseAddress; ULONG ProtectedModeDataBaseAddress; } CM_PNP_BIOS_INSTALLATION_CHECK, *PCM_PNP_BIOS_INSTALLATION_CHECK; #include typedef struct _PNP_ID_NAME_ { char *PnpId; char *DeviceName; } PNP_ID_NAME, *PPNP_ID_NAME; static char Hex[] = "0123456789ABCDEF"; static PNP_ID_NAME PnpName[] = { /* Interrupt Controllers */ {"PNP0000", "AT Interrupt Controller"}, {"PNP0001", "EISA Interrupt Controller"}, {"PNP0002", "MCA Interrupt Controller"}, {"PNP0003", "APIC"}, {"PNP0004", "Cyrix SLiC MP Interrupt Controller"}, /* Timers */ {"PNP0100", "AT Timer"}, {"PNP0101", "EISA Timer"}, {"PNP0102", "MCA Timer"}, /* DMA Controllers */ {"PNP0200", "AT DMA Controller"}, {"PNP0201", "EISA DMA Controller"}, {"PNP0202", "MCA DMA Controller"}, /* Keyboards */ {"PNP0300", "IBM PC/XT Keyboard (83 keys)"}, {"PNP0301", "IBM PC/AT Keyboard (86 keys)"}, {"PNP0302", "IBM PC/XT Keyboard (84 keys)"}, {"PNP0303", "IBM Enhanced (101/102 keys)"}, {"PNP0304", "Olivetti Keyboard (83 keys)"}, {"PNP0305", "Olivetti Keyboard (102 keys)"}, {"PNP0306", "Olivetti Keyboard (86 keys)"}, {"PNP0307", "Microsoft Windows(R) Keyboard"}, {"PNP0308", "General Input Device Emulation Interface (GIDEI) legacy"}, {"PNP0309", "Olivetti Keyboard (A101/102 key)"}, {"PNP030A", "AT&T 302 keyboard"}, {"PNP030B", "Reserved by Microsoft"}, {"PNP0320", "Japanese 101-key keyboard"}, {"PNP0321", "Japanese AX keyboard"}, {"PNP0322", "Japanese 106-key keyboard A01"}, {"PNP0323", "Japanese 106-key keyboard 002/003"}, {"PNP0324", "Japanese 106-key keyboard 001"}, {"PNP0325", "Japanese Toshiba Desktop keyboard"}, {"PNP0326", "Japanese Toshiba Laptop keyboard"}, {"PNP0327", "Japanese Toshiba Notebook keyboard"}, {"PNP0340", "Korean 84-key keyboard"}, {"PNP0341", "Korean 86-key keyboard"}, {"PNP0342", "Korean Enhanced keyboard"}, {"PNP0343", "Korean Enhanced keyboard 101b"}, {"PNP0343", "Korean Enhanced keyboard 101c"}, {"PNP0344", "Korean Enhanced keyboard 103"}, /* Parallel Ports */ {"PNP0400", "Standard LPT printer port"}, {"PNP0401", "ECP printer port"}, /* Serial Ports */ {"PNP0500", "Standard PC COM port"}, {"PNP0501", "16550A-compatible COM port"}, {"PNP0510", "Generic IRDA-compatible port"}, /* Harddisk Controllers */ {"PNP0600", "Generic ESDI/ATA/IDE harddisk controller"}, {"PNP0601", "Plus Hardcard II"}, {"PNP0602", "Plus Hardcard IIXL/EZ"}, {"PNP0603", "Generic IDE supporting Microsoft Device Bay Specification"}, /* Floppy Controllers */ {"PNP0700", "PC standard floppy disk controller"}, {"PNP0701", "Standard floppy controller supporting MS Device Bay Specification"}, /* obsolete devices */ {"PNP0800", "Microsoft Sound System compatible device"}, /* Display Adapters */ {"PNP0900", "VGA Compatible"}, {"PNP0901", "Video Seven VRAM/VRAM II/1024i"}, {"PNP0902", "8514/A Compatible"}, {"PNP0903", "Trident VGA"}, {"PNP0904", "Cirrus Logic Laptop VGA"}, {"PNP0905", "Cirrus Logic VGA"}, {"PNP0906", "Tseng ET4000"}, {"PNP0907", "Western Digital VGA"}, {"PNP0908", "Western Digital Laptop VGA"}, {"PNP0909", "S3 Inc. 911/924"}, {"PNP090A", "ATI Ultra Pro/Plus (Mach 32)"}, {"PNP090B", "ATI Ultra (Mach 8)"}, {"PNP090C", "XGA Compatible"}, {"PNP090D", "ATI VGA Wonder"}, {"PNP090E", "Weitek P9000 Graphics Adapter"}, {"PNP090F", "Oak Technology VGA"}, {"PNP0910", "Compaq QVision"}, {"PNP0911", "XGA/2"}, {"PNP0912", "Tseng Labs W32/W32i/W32p"}, {"PNP0913", "S3 Inc. 801/928/964"}, {"PNP0914", "Cirrus Logic 5429/5434 (memory mapped)"}, {"PNP0915", "Compaq Advanced VGA (AVGA)"}, {"PNP0916", "ATI Ultra Pro Turbo (Mach64)"}, {"PNP0917", "Reserved by Microsoft"}, {"PNP0918", "Matrox MGA"}, {"PNP0919", "Compaq QVision 2000"}, {"PNP091A", "Tseng W128"}, {"PNP0930", "Chips & Technologies Super VGA"}, {"PNP0931", "Chips & Technologies Accelerator"}, {"PNP0940", "NCR 77c22e Super VGA"}, {"PNP0941", "NCR 77c32blt"}, {"PNP09FF", "Plug and Play Monitors (VESA DDC)"}, /* Peripheral Buses */ {"PNP0A00", "ISA Bus"}, {"PNP0A01", "EISA Bus"}, {"PNP0A02", "MCA Bus"}, {"PNP0A03", "PCI Bus"}, {"PNP0A04", "VESA/VL Bus"}, {"PNP0A05", "Generic ACPI Bus"}, {"PNP0A06", "Generic ACPI Extended-IO Bus (EIO bus)"}, /* System devices */ {"PNP0800", "AT-style speaker sound"}, {"PNP0B00", "AT Real-Time Clock"}, {"PNP0C00", "Plug and Play BIOS (only created by the root enumerator)"}, {"PNP0C01", "System Board"}, {"PNP0C02", "General Plug and Play motherboard registers."}, {"PNP0C03", "Plug and Play BIOS Event Notification Interrupt"}, {"PNP0C04", "Math Coprocessor"}, {"PNP0C05", "APM BIOS (Version independent)"}, {"PNP0C06", "Reserved for identification of early Plug and Play BIOS implementation"}, {"PNP0C07", "Reserved for identification of early Plug and Play BIOS implementation"}, {"PNP0C08", "ACPI system board hardware"}, {"PNP0C09", "ACPI Embedded Controller"}, {"PNP0C0A", "ACPI Control Method Battery"}, {"PNP0C0B", "ACPI Fan"}, {"PNP0C0C", "ACPI power button device"}, {"PNP0C0D", "ACPI lid device"}, {"PNP0C0E", "ACPI sleep button device"}, {"PNP0C0F", "PCI interrupt link device"}, {"PNP0C10", "ACPI system indicator device"}, {"PNP0C11", "ACPI thermal zone"}, {"PNP0C12", "Device Bay Controller"}, /* PCMCIA Controllers */ {"PNP0E00", "Intel 82365-Compatible PCMCIA Controller"}, {"PNP0E01", "Cirrus Logic CL-PD6720 PCMCIA Controller"}, {"PNP0E02", "VLSI VL82C146 PCMCIA Controller"}, {"PNP0E03", "Intel 82365-compatible CardBus controller"}, /* Mice */ {"PNP0F00", "Microsoft Bus Mouse"}, {"PNP0F01", "Microsoft Serial Mouse"}, {"PNP0F02", "Microsoft InPort Mouse"}, {"PNP0F03", "Microsoft PS/2-style Mouse"}, {"PNP0F04", "Mouse Systems Mouse"}, {"PNP0F05", "Mouse Systems 3-Button Mouse (COM2)"}, {"PNP0F06", "Genius Mouse (COM1)"}, {"PNP0F07", "Genius Mouse (COM2)"}, {"PNP0F08", "Logitech Serial Mouse"}, {"PNP0F09", "Microsoft BallPoint Serial Mouse"}, {"PNP0F0A", "Microsoft Plug and Play Mouse"}, {"PNP0F0B", "Microsoft Plug and Play BallPoint Mouse"}, {"PNP0F0C", "Microsoft-compatible Serial Mouse"}, {"PNP0F0D", "Microsoft-compatible InPort-compatible Mouse"}, {"PNP0F0E", "Microsoft-compatible PS/2-style Mouse"}, {"PNP0F0F", "Microsoft-compatible Serial BallPoint-compatible Mouse"}, {"PNP0F10", "Texas Instruments QuickPort Mouse"}, {"PNP0F11", "Microsoft-compatible Bus Mouse"}, {"PNP0F12", "Logitech PS/2-style Mouse"}, {"PNP0F13", "PS/2 Port for PS/2-style Mice"}, {"PNP0F14", "Microsoft Kids Mouse"}, {"PNP0F15", "Logitech bus mouse"}, {"PNP0F16", "Logitech SWIFT device"}, {"PNP0F17", "Logitech-compatible serial mouse"}, {"PNP0F18", "Logitech-compatible bus mouse"}, {"PNP0F19", "Logitech-compatible PS/2-style Mouse"}, {"PNP0F1A", "Logitech-compatible SWIFT Device"}, {"PNP0F1B", "HP Omnibook Mouse"}, {"PNP0F1C", "Compaq LTE Trackball PS/2-style Mouse"}, {"PNP0F1D", "Compaq LTE Trackball Serial Mouse"}, {"PNP0F1E", "Microsoft Kids Trackball Mouse"}, {"PNP0F1F", "Reserved by Microsoft Input Device Group"}, {"PNP0F20", "Reserved by Microsoft Input Device Group"}, {"PNP0F21", "Reserved by Microsoft Input Device Group"}, {"PNP0F22", "Reserved by Microsoft Input Device Group"}, {"PNP0F23", "Reserved by Microsoft Input Device Group"}, {"PNP0FFF", "Reserved by Microsoft Systems"}, /* List Terminator */ {NULL, NULL} }; /* FUNCTIONS ****************************************************************/ static char * GetDeviceName(char *PnpId) { PPNP_ID_NAME IdName; IdName = PnpName; while (IdName->PnpId != NULL) { if (!strcmp(IdName->PnpId, PnpId)) return IdName->DeviceName; IdName++; } return "Unknown Device"; } LONG GetPnpKey(PHKEY PnpKey) { LONG lError; char szBuffer[80]; HKEY hAdapterKey; HKEY hBusKey; DWORD dwBus; DWORD dwType; DWORD dwSize; *PnpKey = 0; lError = RegOpenKey(HKEY_LOCAL_MACHINE, "HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter", &hAdapterKey); if (lError != ERROR_SUCCESS) return 0; /* Enumerate buses */ for (dwBus = 0; ; dwBus++) { sprintf(szBuffer, "%lu", dwBus); lError = RegOpenKey(hAdapterKey, szBuffer, &hBusKey); if (lError != ERROR_SUCCESS) { RegCloseKey(hAdapterKey); return lError; } dwSize = 80; lError = RegQueryValueEx(hBusKey, "Identifier", NULL, &dwType, (LPBYTE)szBuffer, &dwSize); if (lError != ERROR_SUCCESS) { RegCloseKey(hBusKey); RegCloseKey(hAdapterKey); return lError; } if (dwType == REG_SZ && stricmp(szBuffer, "pnp bios") == 0) { *PnpKey = hBusKey; RegCloseKey(hAdapterKey); return ERROR_SUCCESS; } RegCloseKey(hBusKey); } return 1; } static VOID PnpDecodeIrq(unsigned char *Ptr) { USHORT IrqMask; int i; IrqMask = *Ptr; Ptr++; IrqMask |= (*Ptr << 8); printf(" IRQs:"); for (i = 0; i < 16; i++) { if (IrqMask & (1 << i)) { printf(" %u", i); } } printf("\n"); } static VOID PnpDecodeDma(unsigned char *Ptr) { unsigned char DmaChannel; unsigned char DmaStatus; int i; DmaChannel = *Ptr; Ptr++; DmaStatus = *Ptr; printf(" DMAs:"); for (i = 0; i < 8; i++) { if (DmaChannel & (1 << i)) { printf(" %u", i); } } printf("\n"); } static VOID PnpDecodeIoPort(unsigned char *Ptr) { USHORT MinBase; USHORT MaxBase; UCHAR Align; UCHAR Length; // Info = *Ptr; Ptr++; MinBase = *Ptr; Ptr++; MinBase += (*Ptr << 8); Ptr++; MaxBase = *Ptr; Ptr++; MaxBase += (*Ptr << 8); Ptr++; Align = *Ptr; Ptr++; Length = *Ptr; printf(" I/O Port descriptor\n"); printf(" MinBase 0x%x MaxBase 0x%x Align %u Length %u\n", MinBase, MaxBase, Align, Length); } static VOID PnpDecodeFixedIoPort(unsigned char *Ptr) { USHORT IoPort; UCHAR Length; IoPort = *Ptr; Ptr++; IoPort += (*Ptr << 8); Ptr++; Length = *Ptr; printf(" Fixed I/O Port descriptor\n"); printf(" PortBase 0x%hx Length 0x%x\n", IoPort, Length); #if 0 if (Length == 1) { printf(" Fixed location I/O Port descriptor: 0x%x\n", IoPort); } else { printf(" Fixed location I/O Port descriptor: 0x%x - 0x%x\n", IoPort, IoPort + Length - 1); } #endif } static VOID PnpDecodeMemory16(unsigned char *Ptr) { UCHAR Info; USHORT MinBase; USHORT MaxBase; USHORT Align; USHORT Length; Info = *Ptr; Ptr++; MinBase = *Ptr; Ptr++; MinBase += (*Ptr << 8); Ptr++; MaxBase = *Ptr; Ptr++; MaxBase += (*Ptr << 8); Ptr++; Align = *Ptr; Ptr++; Align += (*Ptr << 8); Ptr++; Length = *Ptr; Ptr++; Length += (*Ptr << 8); printf(" 16-Bit memory range descriptor\n"); printf(" MinBase 0x%hx MaxBase 0x%hx Align 0x%hx Length 0x%hx Flags 0x%02x\n", MinBase, MaxBase, Align,Length, Info); } static VOID PnpDecodeMemory32(unsigned char *Ptr) { UCHAR Info; ULONG MinBase; ULONG MaxBase; ULONG Align; ULONG Length; Info = *Ptr; Ptr++; MinBase = *Ptr; Ptr++; MinBase += (*Ptr << 8); Ptr++; MinBase += (*Ptr << 16); Ptr++; MinBase += (*Ptr << 24); Ptr++; MaxBase = *Ptr; Ptr++; MaxBase += (*Ptr << 8); Ptr++; MaxBase += (*Ptr << 16); Ptr++; MaxBase += (*Ptr << 24); Ptr++; Align = *Ptr; Ptr++; Align += (*Ptr << 8); Ptr++; Align += (*Ptr << 16); Ptr++; Align += (*Ptr << 24); Ptr++; Length = *Ptr; Ptr++; Length += (*Ptr << 8); Ptr++; Length += (*Ptr << 16); Ptr++; Length += (*Ptr << 24); printf(" 32-Bit memory range descriptor\n"); printf(" MinBase 0x%lx MaxBase 0x%lx Align 0x%lx Length 0x%lx Flags 0x%02x\n", MinBase, MaxBase, Align,Length, Info); } static VOID PnpDecodeFixedMemory(unsigned char *Ptr) { UCHAR Info; ULONG Base; ULONG Length; Info = *Ptr; Ptr++; Base = *Ptr; Ptr++; Base += (*Ptr << 8); Ptr++; Base += (*Ptr << 16); Ptr++; Base += (*Ptr << 24); Ptr++; Length = *Ptr; Ptr++; Length += (*Ptr << 8); Ptr++; Length += (*Ptr << 16); Ptr++; Length += (*Ptr << 24); printf(" 32-Bit fixed location memory range descriptor\n"); printf(" Base 0x%lx Length 0x%lx Flags 0x%02x\n", Base, Length, Info); } void PrintDeviceData (PCM_PNP_BIOS_DEVICE_NODE DeviceNode) { char PnpId[8]; unsigned char *Ptr; unsigned int TagSize; unsigned int TagType; unsigned char Id[4]; printf ("Node: %x Size %hu (0x%hx)\n", DeviceNode->Node, DeviceNode->Size, DeviceNode->Size); memcpy(Id, &DeviceNode->ProductId, 4); PnpId[0] = ((Id[0] >> 2) & 0x1F) + 0x40; PnpId[1] = ((Id[0] << 3) & 0x18) + ((Id[1] >> 5) & 0x07) + 0x40; PnpId[2] = (Id[1] & 0x1F) + 0x40; PnpId[3] = Hex[(Id[2] >> 4) & 0xF]; PnpId[4] = Hex[Id[2] & 0x0F]; PnpId[5] = Hex[(Id[3] >> 4) & 0x0F]; PnpId[6] = Hex[Id[3] & 0x0F]; PnpId[7] = 0; printf(" '%s' (%s)\n", PnpId, GetDeviceName(PnpId)); if (DeviceNode->Size > sizeof(CM_PNP_BIOS_DEVICE_NODE)) { Ptr = (unsigned char *)(DeviceNode + 1); while (TRUE) { if (*Ptr & 0x80) { TagType = *Ptr & 0x7F; Ptr++; TagSize = *Ptr; Ptr++; TagSize += (*Ptr << 16); Ptr++; switch (TagType) { case 1: PnpDecodeMemory16(Ptr); break; case 5: PnpDecodeMemory32(Ptr); break; case 6: PnpDecodeFixedMemory(Ptr); break; default: printf(" Large tag: type %u size %u\n", TagType, TagSize); break; } } else { TagType = (*Ptr >> 3) & 0x0F; TagSize = *Ptr & 0x07; Ptr++; switch (TagType) { case 2: printf(" Logical device ID\n"); break; case 3: printf(" Compatible device ID\n"); break; case 4: PnpDecodeIrq(Ptr); break; case 5: PnpDecodeDma(Ptr); break; case 8: PnpDecodeIoPort(Ptr); break; case 9: PnpDecodeFixedIoPort(Ptr); break; case 0x0F: /* end tag */ break; default: printf(" Small tag: type %u size %u\n", TagType, TagSize); break; } /* end tag */ if (TagType == 0x0F) break; } Ptr = Ptr + TagSize; } } } int main (int argc, char *argv[]) { LONG lError; HKEY hPnpKey; DWORD dwType; DWORD dwSize; BOOL Ask; PCM_FULL_RESOURCE_DESCRIPTOR lpBuffer; PCM_PNP_BIOS_INSTALLATION_CHECK lpPnpInst; PCM_PNP_BIOS_DEVICE_NODE lpDevNode; DWORD dwDataSize; DWORD dwResourceSize; hPnpKey = 0; Ask = TRUE; if (argc >1 && (!strcmp(argv[1],"/S") || !strcmp(argv[1],"/s"))) { Ask = FALSE; } if (argc >1 && !strcmp(argv[1],"/?")) { printf("This utility prints the PnP-nodes from the registry\n"); printf("\"/s\" prevents the \"Press any key\"\n\n"); return 0; } lError = GetPnpKey(&hPnpKey); if (lError != ERROR_SUCCESS) { printf("Failed to get PnP-BIOS key\n"); return 0; } if (hPnpKey != 0) { printf("Found PnP-BIOS key\n"); } /* Allocate buffer */ dwSize = 2048; lpBuffer = malloc(dwSize); if (lpBuffer == NULL) { printf("Error: malloc() failed\n"); RegCloseKey(hPnpKey); return 0; } do { lError = RegQueryValueEx(hPnpKey, "Configuration Data", NULL, &dwType, (LPBYTE)lpBuffer, &dwSize); if (lError == ERROR_MORE_DATA) { lpBuffer = realloc(lpBuffer, dwSize); if (lpBuffer == NULL) { printf("Error: realloc() of %u bytes failed\n", (unsigned) dwSize); RegCloseKey(hPnpKey); return 0; } } } while (lError == ERROR_MORE_DATA); if (lError != ERROR_SUCCESS) { printf("Failed to read 'Configuration Data' value\n"); free(lpBuffer); RegCloseKey(hPnpKey); return 0; } // printf ("Data size: %lu\n", dwSize); RegCloseKey(hPnpKey); // printf("Resource count %lu\n", lpBuffer->PartialResourceList.Count); if (lpBuffer->PartialResourceList.Count == 0) { printf("Invalid resource count!\n"); free(lpBuffer); return 0; } // printf("lpBuffer %p\n", lpBuffer); dwResourceSize = lpBuffer->PartialResourceList.PartialDescriptors[0].u.DeviceSpecificData.DataSize; // printf("ResourceSize: %lu\n", dwResourceSize); lpPnpInst = (PCM_PNP_BIOS_INSTALLATION_CHECK) ((ULONG_PTR)(&lpBuffer->PartialResourceList.PartialDescriptors[0]) + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR)); // printf("lpPnpInst %p\n", lpPnpInst); printf("Signature '%.4s'\n", lpPnpInst->Signature); if (strncmp((PCHAR)lpPnpInst->Signature, "$PnP", 4)) { printf("Error: Invalid PnP signature\n"); free(lpBuffer); return 0; } // printf("InstCheck length: %lu\n", lpPnpInst->Length); dwDataSize = sizeof(CM_PNP_BIOS_INSTALLATION_CHECK); lpDevNode = (PCM_PNP_BIOS_DEVICE_NODE)((DWORD)lpPnpInst + sizeof(CM_PNP_BIOS_INSTALLATION_CHECK)); if (lpDevNode->Size == 0) { printf("Error: Device node size is zero!\n"); return 0; } #if 0 printf("Node: %x Size %hu (0x%hx)\n", lpDevNode->Node, lpDevNode->Size, lpDevNode->Size); printf("Done.\n"); return 0; #endif while (dwDataSize < dwResourceSize) { if (lpDevNode->Size == 0) break; printf("Node: %x Size %hu (0x%hx)\n", lpDevNode->Node, lpDevNode->Size, lpDevNode->Size); dwDataSize += lpDevNode->Size; lpDevNode = (PCM_PNP_BIOS_DEVICE_NODE)((DWORD)lpDevNode + lpDevNode->Size); } if (Ask) { printf("\n Press any key...\n"); getch(); } else { printf("\n"); } dwDataSize = sizeof(CM_PNP_BIOS_INSTALLATION_CHECK); lpDevNode = (PCM_PNP_BIOS_DEVICE_NODE)((DWORD)lpPnpInst + sizeof(CM_PNP_BIOS_INSTALLATION_CHECK)); while (dwDataSize < dwResourceSize) { if (lpDevNode->Size == 0) break; PrintDeviceData(lpDevNode); if (Ask) { printf("\n Press any key...\n"); getch(); } else { printf("\n"); } dwDataSize += lpDevNode->Size; lpDevNode = (PCM_PNP_BIOS_DEVICE_NODE)((DWORD)lpDevNode + lpDevNode->Size); } free(lpBuffer); return 0; } /* EOF */