pcireg: Rewrite PCI ID system to compress database with LHA

Database building has been moved away from the build process at least for now, due to the fact lha isn't packaged anywhere.
This commit is contained in:
RichardG867
2024-10-23 19:08:35 -03:00
parent 2345666fc7
commit db68540a58
12 changed files with 794 additions and 260 deletions

View File

@@ -66,7 +66,6 @@ jobs:
make -f Makefile.gcc clean all CC=i686-w64-mingw32-gcc CFLAGS=-I/usr/local/include LDFLAGS=-static LDAPPEND=-lcfgmgr32 CP437_CONV=y DEST=pciregw
make -f Makefile.gcc clean all CC=x86_64-w64-mingw32-gcc CFLAGS=-I/usr/local/include LDFLAGS=-static LDAPPEND=-lcfgmgr32 CP437_CONV=y DEST=pciregw64
make -f Makefile.gcc clean all CC=i686-linux-gnu-gcc CFLAGS=-I/usr/local/include LDFLAGS=-static
python3 pciids.py
- name: Build `usblgoff`
run: |
cd ${{ github.workspace }}/usblgoff

2
.gitignore vendored
View File

@@ -27,4 +27,4 @@ pci?????.bin
*.efi
pcireg/pcireg
ac97/ac97
PCIIDS.BIN
PCIIDS_*.BIN

View File

@@ -16,7 +16,7 @@
#
SYSTEM = PMODEW
OBJS = pcireg.obj clib_pci.obj clib_std.obj clib_sys.obj clib_term.obj
OBJS = pcireg.obj lh5_extract.obj clib_pci.obj clib_std.obj clib_sys.obj clib_term.obj
DEST = PCIREG.EXE
!include ../clib/watcom.mk

View File

@@ -15,7 +15,7 @@
# Copyright 2023 RichardG.
#
export OBJS = pcireg.o clib_pci.o clib_std.o clib_sys.o clib_term.o
export OBJS = pcireg.o lh5_extract.o clib_pci.o clib_std.o clib_sys.o clib_term.o
export DEST = pcireg
override LDFLAGS += -lpci $(LDAPPEND)

View File

@@ -15,7 +15,7 @@
# Copyright 2021 RichardG.
#
export OBJS = pcireg.o clib_pci.o clib_std.o clib_sys.o clib_term.o
export OBJS = pcireg.o lh5_extract.o clib_pci.o clib_std.o clib_sys.o clib_term.o
export DEST = PCIREG.EFI
include ../clib/uefi.mk

BIN
pcireg/PCIIDS.LHA Normal file

Binary file not shown.

View File

@@ -71,5 +71,5 @@ Building
### PCI ID database
* Run `python3 pciids.py` to update the `PCIIDS.BIN` file.
* Run `python3 pciids.py` to update the PCI ID files, then `lha a1o5 PCIIDS.LHA PCIIDS_*.BIN` to compress them in the expected format.
* The latest version of `pci.ids` is automatically downloaded and used to update the database.

562
pcireg/lh5_extract.c Normal file
View File

@@ -0,0 +1,562 @@
/*
* This file is a severely cut down and cleaned up version of lha.
*
* All changes compared to lha-svn894 are:
*
* Copyright 2009 Luc Verhaegen <libv@skynet.be>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* LHA has a terrible history... It dates back to 1988, has had many different
* authors and has been mostly Public Domain Software.
*
* Since 1999, Koji Arai <arai@users.sourceforge.jp> has been doing most of
* the work at http://sourceforge.jp/projects/lha/.
*/
#define _GNU_SOURCE 1
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "lh5_extract.h"
#ifndef le16toh
# define le16toh(x) x
#endif
#ifndef le32toh
# define le32toh(x) x
#endif
/*
* LHA header parsing.
*/
static int calc_sum(unsigned char *p, int len)
{
int sum = 0;
while (len--)
sum += *p++;
return sum & 0xff;
}
/*
* level 1 header
*
*
* offset size field name
* -----------------------------------
* 0 1 header size [*1]
* 1 1 header sum
* -------------------------------------
* 2 5 method ID ^
* 7 4 skip size [*2] |
* 11 4 original size |
* 15 2 time |
* 17 2 date |
* 19 1 attribute (0x20 fixed) | [*1] header size (X+Y+25)
* 20 1 level (0x01 fixed) |
* 21 1 name length |
* 22 X filename |
* X+ 22 2 file crc (CRC-16) |
* X+ 24 1 OS ID |
* X +25 Y ??? |
* X+Y+25 2 next-header size v
* -------------------------------------------------
* X+Y+27 Z ext-header ^
* : |
* ----------------------------------- | [*2] skip size
* X+Y+Z+27 data |
* : v
* -------------------------------------------------
*
*/
unsigned int
LH5HeaderParse(unsigned char *Buffer, int BufferSize,
unsigned int *original_size, unsigned int *packed_size,
char **name, unsigned short *crc)
{
unsigned int offset;
unsigned char header_size, checksum, name_length;
if (BufferSize < 27) {
fprintf(stderr,
"Error: Packed Buffer is too small to contain an lha header.\n");
return 0;
}
/* check attribute */
if (Buffer[19] != 0x20) {
fprintf(stderr, "Error: Invalid lha header attribute byte.\n");
return 0;
}
/* check method */
if (memcmp(Buffer + 2, "-lh5-", 5) != 0) {
fprintf(stderr, "Error: Compression method is not LZHUFF5.\n");
return 0;
}
/* check header level */
if (Buffer[20] != 1) {
fprintf(stderr, "Error: Header level %d is not supported\n",
Buffer[20]);
return 0;
}
/* read in the full header */
header_size = Buffer[0];
if (BufferSize < (header_size + 2)) {
fprintf(stderr,
"Error: Packed Buffer is too small to contain the full header.\n");
return 0;
}
/* verify checksum */
checksum = Buffer[1];
if (calc_sum(Buffer + 2, header_size) != checksum)
fprintf(stderr, "Warning: Invalid lha header checksum.\n");
*packed_size = le32toh(*(unsigned int *)(Buffer + 7));
*original_size = le32toh(*(unsigned int *)(Buffer + 11));
name_length = Buffer[21];
*name = malloc(name_length + 1);
if (*name) {
memcpy(*name, (char *)Buffer + 22, name_length);
(*name)[name_length] = '\0';
}
*crc = le16toh(*(unsigned short *)(Buffer + 22 + name_length));
offset = header_size + 2;
/* Skip extended headers */
while (1) {
unsigned short extend_size =
le16toh(*(unsigned short *)(Buffer + offset - 2));
if (!extend_size)
break;
*packed_size -= extend_size;
offset += extend_size;
if (BufferSize < offset) {
fprintf(stderr,
"Warning: Buffer to small to contain extended header.\n");
offset = header_size + 2;
break;
}
}
return offset;
}
/*
* CRC Calculation.
*/
#define CRCPOLY 0xA001 /* CRC-16 (x^16+x^15+x^2+1) */
unsigned short CRC16Calculate(unsigned char *Buffer, int BufferSize)
{
unsigned short CRCTable[0x100];
unsigned short crc;
int i;
/* First, initialise our CRCTable */
for (i = 0; i < 0x100; i++) {
unsigned short r = i;
unsigned int j;
for (j = 0; j < 8; j++) {
if (r & 1)
r = (r >> 1) ^ CRCPOLY;
else
r >>= 1;
}
CRCTable[i] = r;
}
/* now go over the entire Buffer */
crc = 0;
for (i = 0; i < BufferSize; i++)
crc = CRCTable[(crc ^ Buffer[i]) & 0xFF] ^ (crc >> 8);
return crc;
}
/*
* Bit handling code.
*/
static unsigned char *CompressedBuffer;
static int CompressedSize;
static int CompressedOffset;
static unsigned short bitbuf;
static unsigned char subbitbuf, bitcount;
static void BitBufInit(unsigned char *Buffer, int BufferSize)
{
CompressedBuffer = Buffer;
CompressedOffset = 0;
CompressedSize = BufferSize;
bitbuf = 0;
subbitbuf = 0;
bitcount = 0;
}
static void fillbuf(unsigned char n)
{ /* Shift bitbuf n bits left, read n bits */
while (n > bitcount) {
n -= bitcount;
bitbuf = (bitbuf << bitcount) + (subbitbuf >> (8 - bitcount));
if (CompressedOffset < CompressedSize) {
subbitbuf = CompressedBuffer[CompressedOffset];
CompressedOffset++;
} else
subbitbuf = 0;
bitcount = 8;
}
bitcount -= n;
bitbuf = (bitbuf << n) + (subbitbuf >> (8 - n));
subbitbuf <<= n;
}
static unsigned short getbits(unsigned char n)
{
unsigned short x;
x = bitbuf >> (16 - n);
fillbuf(n);
return x;
}
static unsigned short peekbits(unsigned char n)
{
unsigned short x;
x = bitbuf >> (16 - n);
return x;
}
/*
*
* LHA extraction.
*
*/
#define MIN(a,b) ((a) <= (b) ? (a) : (b))
#define LZHUFF5_DICBIT 13 /* 2^13 = 8KB sliding dictionary */
#define MAXMATCH 256 /* formerly F (not more than 255 + 1) */
#define THRESHOLD 3 /* choose optimal value */
#define NP (LZHUFF5_DICBIT + 1)
#define NT (16 + 3) /* USHORT + THRESHOLD */
#define NC (255 + MAXMATCH + 2 - THRESHOLD)
#define PBIT 4 /* smallest integer such that (1 << PBIT) > * NP */
#define TBIT 5 /* smallest integer such that (1 << TBIT) > * NT */
#define CBIT 9 /* smallest integer such that (1 << CBIT) > * NC */
/* #if NT > NP #define NPT NT #else #define NPT NP #endif */
#define NPT 0x80
static unsigned short left[2 * NC - 1], right[2 * NC - 1];
static unsigned short c_table[4096]; /* decode */
static unsigned short pt_table[256]; /* decode */
static unsigned char c_len[NC];
static unsigned char pt_len[NPT];
static int
make_table(short nchar, unsigned char bitlen[], short tablebits,
unsigned short table[])
{
unsigned short count[17]; /* count of bitlen */
unsigned short weight[17]; /* 0x10000ul >> bitlen */
unsigned short start[17]; /* first code of bitlen */
unsigned short total;
unsigned int i, l;
int j, k, m, n, avail;
unsigned short *p;
avail = nchar;
/* initialize */
for (i = 1; i <= 16; i++) {
count[i] = 0;
weight[i] = 1 << (16 - i);
}
/* count */
for (i = 0; i < nchar; i++) {
if (bitlen[i] > 16) {
/* CVE-2006-4335 */
fprintf(stderr, "Error: Bad table (case a)\n");
return -1;
} else
count[bitlen[i]]++;
}
/* calculate first code */
total = 0;
for (i = 1; i <= 16; i++) {
start[i] = total;
total += weight[i] * count[i];
}
if (((total & 0xffff) != 0) || (tablebits > 16)) { /* 16 for weight below */
fprintf(stderr, "Error: make_table(): Bad table (case b)\n");
return -1;
}
/* shift data for make table. */
m = 16 - tablebits;
for (i = 1; i <= tablebits; i++) {
start[i] >>= m;
weight[i] >>= m;
}
/* initialize */
j = start[tablebits + 1] >> m;
k = MIN(1 << tablebits, 4096);
if (j != 0)
for (i = j; i < k; i++)
table[i] = 0;
/* create table and tree */
for (j = 0; j < nchar; j++) {
k = bitlen[j];
if (k == 0)
continue;
l = start[k] + weight[k];
if (k <= tablebits) {
/* code in table */
l = MIN(l, 4096);
for (i = start[k]; i < l; i++)
table[i] = j;
} else {
/* code not in table */
i = start[k];
if ((i >> m) > 4096) {
/* CVE-2006-4337 */
fprintf(stderr, "Error: Bad table (case c)");
exit(1);
}
p = &table[i >> m];
i <<= tablebits;
n = k - tablebits;
/* make tree (n length) */
while (--n >= 0) {
if (*p == 0) {
right[avail] = left[avail] = 0;
*p = avail++;
}
if (i & 0x8000)
p = &right[*p];
else
p = &left[*p];
i <<= 1;
}
*p = j;
}
start[k] = l;
}
return 0;
}
static int read_pt_len(short nn, short nbit, short i_special)
{
int i, c, n;
n = getbits(nbit);
if (n == 0) {
c = getbits(nbit);
for (i = 0; i < nn; i++)
pt_len[i] = 0;
for (i = 0; i < 256; i++)
pt_table[i] = c;
} else {
i = 0;
while (i < MIN(n, NPT)) {
c = peekbits(3);
if (c != 7)
fillbuf(3);
else {
unsigned short mask = 1 << (16 - 4);
while (mask & bitbuf) {
mask >>= 1;
c++;
}
fillbuf(c - 3);
}
pt_len[i++] = c;
if (i == i_special) {
c = getbits(2);
while (--c >= 0 && i < NPT)
pt_len[i++] = 0;
}
}
while (i < nn)
pt_len[i++] = 0;
if (make_table(nn, pt_len, 8, pt_table) == -1)
return -1;
}
return 0;
}
static int read_c_len(void)
{
short i, c, n;
n = getbits(CBIT);
if (n == 0) {
c = getbits(CBIT);
for (i = 0; i < NC; i++)
c_len[i] = 0;
for (i = 0; i < 4096; i++)
c_table[i] = c;
} else {
i = 0;
while (i < MIN(n, NC)) {
c = pt_table[peekbits(8)];
if (c >= NT) {
unsigned short mask = 1 << (16 - 9);
do {
if (bitbuf & mask)
c = right[c];
else
c = left[c];
mask >>= 1;
} while (c >= NT && (mask || c != left[c])); /* CVE-2006-4338 */
}
fillbuf(pt_len[c]);
if (c <= 2) {
if (c == 0)
c = 1;
else if (c == 1)
c = getbits(4) + 3;
else
c = getbits(CBIT) + 20;
while (--c >= 0)
c_len[i++] = 0;
} else
c_len[i++] = c - 2;
}
while (i < NC)
c_len[i++] = 0;
if (make_table(NC, c_len, 12, c_table) == -1)
return -1;
}
return 0;
}
static unsigned short decode_c_st1(void)
{
unsigned short j, mask;
j = c_table[peekbits(12)];
if (j < NC)
fillbuf(c_len[j]);
else {
fillbuf(12);
mask = 1 << (16 - 1);
do {
if (bitbuf & mask)
j = right[j];
else
j = left[j];
mask >>= 1;
} while (j >= NC && (mask || j != left[j])); /* CVE-2006-4338 */
fillbuf(c_len[j] - 12);
}
return j;
}
static unsigned short decode_p_st1(void)
{
unsigned short j, mask;
j = pt_table[peekbits(8)];
if (j < NP)
fillbuf(pt_len[j]);
else {
fillbuf(8);
mask = 1 << (16 - 1);
do {
if (bitbuf & mask)
j = right[j];
else
j = left[j];
mask >>= 1;
} while (j >= NP && (mask || j != left[j])); /* CVE-2006-4338 */
fillbuf(pt_len[j] - 8);
}
if (j != 0)
j = (1 << (j - 1)) + getbits(j - 1);
return j;
}
int
LH5Decode(unsigned char *PackedBuffer, int PackedBufferSize,
unsigned char *OutputBuffer, int OutputBufferSize)
{
unsigned short blocksize = 0;
unsigned int i, c;
int n = 0;
BitBufInit(PackedBuffer, PackedBufferSize);
fillbuf(2 * 8);
while (n < OutputBufferSize) {
if (blocksize == 0) {
blocksize = getbits(16);
if (read_pt_len(NT, TBIT, 3) == -1)
return -1;
if (read_c_len() == -1)
return -1;
if (read_pt_len(NP, PBIT, -1) == -1)
return -1;
}
blocksize--;
c = decode_c_st1();
if (c < 256)
OutputBuffer[n++] = c;
else {
int length = c - 256 + THRESHOLD;
int offset = 1 + decode_p_st1();
if (offset > n)
return -1;
for (i = 0; (i < length) && (n < OutputBufferSize); i++) {
OutputBuffer[n] = OutputBuffer[n - offset];
n++;
}
}
}
return CompressedOffset;
}

37
pcireg/lh5_extract.h Normal file
View File

@@ -0,0 +1,37 @@
/*
* Copyright 2009 Luc Verhaegen <libv@skynet.be>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef LH5_EXTRACT_H
#define LH5_EXTRACT_H
unsigned int LH5HeaderParse(unsigned char *Buffer, int BufferSize,
unsigned int *original_size,
unsigned int *packed_size,
char **name, unsigned short *crc);
unsigned short CRC16Calculate(unsigned char *Buffer, int BufferSize);
int LH5Decode(unsigned char *PackedBuffer, int PackedBufferSize,
unsigned char *OutputBuffer, int OutputBufferSize);
extern int lzari_in_bruteforce;
int unlzari(unsigned char *in, int insz, unsigned char *out, int outsz, char common);
int unlzh(unsigned char *in, int insz, unsigned char *out, int outsz);
#endif /* LH5_EXTRACT_H */

View File

@@ -13,7 +13,7 @@
#
# Authors: RichardG, <richardg867@gmail.com>
#
# Copyright 2021 RichardG.
# Copyright 2021-2024 RichardG.
#
import pciutil, struct, sys
@@ -26,8 +26,19 @@ def main():
vendor_db = device_db = subdevice_db = class_db = subclass_db = progif_db = string_db = b''
vendor_devices_offset = {}
string_db_lookup = {}
device_db_pos = subdevice_db_pos = 0
vendor_has_termination = device_has_termination = class_has_termination = subclass_has_termination = progif_has_termination = False
def string_db_add(s):
if not s:
return 0xffffffff
string_db_pos = string_db_lookup.get(s, None)
if string_db_pos == None:
nonlocal string_db
string_db_pos = string_db_lookup[s] = len(string_db)
string_db += s + b'\x00'
return string_db_pos
# Enumerate device IDs, while also going through subdevice IDs.
print('Enumerating devices and subdevices...')
current_vendor_id = None
@@ -37,15 +48,16 @@ def main():
# Add termination device entry if one isn't already present.
if current_vendor_id != None and not device_has_termination:
device_db += struct.pack('<HII', 0xffff, 0xffffffff, 0xffffffff)
device_db_pos += 1
# Mark this as the current vendor ID.
current_vendor_id = pci_id >> 16
# Store the device entries offset for this vendor.
vendor_devices_offset[current_vendor_id] = len(device_db)
vendor_devices_offset[current_vendor_id] = device_db_pos
# Enumerate this device's subdevices.
subdevice_db_pos = len(subdevice_db)
subdevice_db_pos_start = subdevice_db_pos
subdevice_has_termination = False
for pci_subid in sorted(pciutil._pci_subdevices.get(pci_id, {})):
# Store a null device entries offset for this vendor if one isn't already present.
@@ -57,42 +69,31 @@ def main():
subdevice = pciutil.clean_device(pciutil._pci_subdevices[pci_id][pci_subid]).encode('cp437', 'ignore')[:256]
# Add to string database if a valid result was found.
if subdevice:
string_db_pos = string_db_lookup.get(subdevice, None)
if string_db_pos == None:
string_db_pos = string_db_lookup[subdevice] = len(string_db)
string_db += struct.pack('<B', len(subdevice))
string_db += subdevice
else:
string_db_pos = 0xffffffff
string_db_pos = string_db_add(subdevice)
# Add to subdevice database.
subdevice_db += struct.pack('<HHI', subvendor_id, pci_subid & 0xffff, string_db_pos)
subdevice_db_pos += 1
subdevice_has_termination = (pci_subid & 0xffff) == 0xffff
# Mark subdevice entry if there is at least one subdevice entry.
if len(subdevice_db) != subdevice_db_pos:
if subdevice_db_pos != subdevice_db_pos_start:
# Add termination subdevice entry if one isn't already present.
if not subdevice_has_termination:
subdevice_db += struct.pack('<HHI', 0xffff, 0xffff, 0xffffffff)
subdevice_db_pos += 1
else:
subdevice_db_pos = 0xffffffff
subdevice_db_pos_start = 0xffffffff
# Look up device ID.
device = pciutil.clean_device(pciutil._pci_devices[pci_id]).encode('cp437', 'ignore')[:256]
# Add to string database if a valid result was found.
if device:
string_db_pos = string_db_lookup.get(device, None)
if string_db_pos == None:
string_db_pos = string_db_lookup[device] = len(string_db)
string_db += struct.pack('<B', len(device))
string_db += device
else:
string_db_pos = 0xffffffff
string_db_pos = string_db_add(device)
# Add to device database.
device_db += struct.pack('<HII', pci_id & 0xffff, subdevice_db_pos, string_db_pos)
device_db += struct.pack('<HII', pci_id & 0xffff, subdevice_db_pos_start, string_db_pos)
device_db_pos += 1
device_has_termination = (pci_id & 0xffff) == 0xffff
# Enumerate vendor IDs.
@@ -102,14 +103,7 @@ def main():
vendor = pciutil.clean_vendor(pciutil._pci_vendors.get(vendor_id, '')).encode('cp437', 'ignore')[:256]
# Add to string database if a valid result was found.
if vendor:
string_db_pos = string_db_lookup.get(vendor, None)
if string_db_pos == None:
string_db_pos = string_db_lookup[vendor] = len(string_db)
string_db += struct.pack('<B', len(vendor))
string_db += vendor
else:
string_db_pos = 0xffffffff
string_db_pos = string_db_add(vendor)
# Add to vendor database.
devices_offset = vendor_devices_offset.get(vendor_id, None)
@@ -126,14 +120,7 @@ def main():
class_name = pciutil._pci_classes[pci_class].encode('cp437', 'ignore')[:256]
# Add to string database if a valid result was found.
if class_name:
string_db_pos = string_db_lookup.get(class_name, None)
if string_db_pos == None:
string_db_pos = string_db_lookup[class_name] = len(string_db)
string_db += struct.pack('<B', len(class_name))
string_db += class_name
else:
string_db_pos = 0xffffffff
string_db_pos = string_db_add(class_name)
# Add to class database.
class_db += struct.pack('<BI', pci_class, string_db_pos)
@@ -146,14 +133,7 @@ def main():
subclass_name = pciutil._pci_subclasses[pci_subclass].encode('cp437', 'ignore')[:256]
# Add to string database if a valid result was found.
if subclass_name:
string_db_pos = string_db_lookup.get(subclass_name, None)
if string_db_pos == None:
string_db_pos = string_db_lookup[subclass_name] = len(string_db)
string_db += struct.pack('<B', len(subclass_name))
string_db += subclass_name
else:
string_db_pos = 0xffffffff
string_db_pos = string_db_add(subclass_name)
# Add to subclass database.
subclass_db += struct.pack('<BBI', (pci_subclass >> 8) & 0xff, pci_subclass & 0xff, string_db_pos)
@@ -166,50 +146,32 @@ def main():
progif_name = pciutil._pci_progifs[pci_progif].encode('cp437', 'ignore')[:256]
# Add to string database if a valid result was found.
if progif_name:
string_db_pos = string_db_lookup.get(progif_name, None)
if string_db_pos == None:
string_db_pos = string_db_lookup[progif_name] = len(string_db)
string_db += struct.pack('<B', len(progif_name))
string_db += progif_name
else:
string_db_pos = 0xffffffff
string_db_pos = string_db_add(progif_name)
# Add to progif database.
progif_db += struct.pack('<BBBI', (pci_progif >> 16) & 0xff, (pci_progif >> 8) & 0xff, pci_progif & 0xff, string_db_pos)
progif_has_termination = pci_progif == 0xffffff
# Create binary file.
print('Writing binary database...')
f = open('PCIIDS.BIN', 'wb')
# Create binary files.
print('Writing binary databases...')
# List all databases with their respective termination flags.
dbs = [
(vendor_db, 14, vendor_has_termination),
(device_db, 10, device_has_termination),
(subdevice_db, 8, True),
(class_db, 5, class_has_termination),
(subclass_db, 6, subclass_has_termination),
(progif_db, 7, progif_has_termination),
(string_db, None, True),
('V', vendor_db, 14, vendor_has_termination),
('D', device_db, 10, device_has_termination),
('S', subdevice_db, 8, True),
('C', class_db, 5, class_has_termination),
('U', subclass_db, 6, subclass_has_termination),
('P', progif_db, 7, progif_has_termination),
('T', string_db, None, True),
]
# Write header containing database offsets.
db_len = 4 * (len(dbs) - 1)
for db, entry_length, has_termination in dbs[:-1]:
db_len += len(db)
if not has_termination:
db_len += entry_length
f.write(struct.pack('<I', db_len))
# Write the databases themselves, adding termination if required.
for db, entry_length, has_termination in dbs:
f.write(db)
if not has_termination:
f.write(b'\xff' * entry_length)
# Finish file.
f.close()
for fn, db, entry_length, has_termination in dbs:
with open('PCIIDS_' + fn + '.BIN', 'wb') as f:
f.write(db)
if not has_termination:
f.write(b'\xff' * entry_length)
if __name__ == '__main__':
main()

View File

@@ -33,6 +33,7 @@
# include <i86.h>
# endif
#endif
#include "lh5_extract.h"
#include "clib_pci.h"
#include "clib_std.h"
#include "clib_sys.h"
@@ -100,7 +101,6 @@ static const char *bridge_flags[] = {
};
static int term_width;
static FILE *pciids_f = NULL;
#if defined(MSDOS)
static union REGS regs;
static struct SREGS seg_regs;
@@ -112,45 +112,40 @@ static struct PACKED {
# pragma pack(pop)
#endif
static int pciids_cur_vendor;
static int pciids_cur_device;
#pragma pack(push, 1)
static struct PACKED {
uint32_t device_db_offset,
subdevice_db_offset,
class_db_offset,
subclass_db_offset,
progif_db_offset,
string_db_offset;
} pciids_header;
static struct PACKED {
uint16_t vendor_id;
uint32_t devices_offset,
string_offset;
} pciids_vendor;
uint32_t devices_offset;
uint32_t string_offset;
} *pciids_vendor = NULL;
static struct PACKED {
uint16_t device_id;
uint32_t subdevices_offset,
string_offset;
} pciids_device;
static struct PACKED {
uint16_t subvendor_id,
subdevice_id;
uint32_t subdevices_offset;
uint32_t string_offset;
} pciids_subdevice;
} *pciids_device = NULL;
static struct PACKED {
uint16_t subvendor_id;
uint16_t subdevice_id;
uint32_t string_offset;
} *pciids_subdevice = NULL;
static struct PACKED {
uint8_t class_id;
uint32_t string_offset;
} pciids_class;
} *pciids_class = NULL;
static struct PACKED {
uint8_t class_id,
subclass_id;
uint8_t class_id;
uint8_t subclass_id;
uint32_t string_offset;
} pciids_subclass;
} *pciids_subclass = NULL;
static struct PACKED {
uint8_t class_id,
subclass_id,
progif_id;
uint8_t class_id;
uint8_t subclass_id;
uint8_t progif_id;
uint32_t string_offset;
} pciids_progif;
} *pciids_progif = NULL;
static char *pciids_string = NULL;
#if defined(MSDOS)
typedef struct {
@@ -174,84 +169,118 @@ typedef struct {
#pragma pack(pop)
static int
pciids_open_database()
pciids_open_database(void **ptr, char id)
{
/* No action is required if the file is already open. */
if (pciids_f)
FILE *f;
size_t pos;
unsigned int header_size;
unsigned int original_size;
unsigned int packed_size;
uint8_t header[128];
char *filename;
char target_filename[13];
unsigned short crc;
uint8_t *buf;
/* No action is required if the database is already loaded. */
if (*ptr)
return 0;
/* Open file, and stop if the open failed or the header couldn't be read. */
pciids_f = fopen("PCIIDS.BIN", "r" FOPEN_BINARY);
if (pciids_f && (fread(&pciids_header, sizeof(pciids_header), 1, pciids_f) < 1)) {
fclose(pciids_f);
pciids_f = NULL;
/* Open archive, and stop if the open failed. */
f = fopen("PCIIDS.LHA", "r" FOPEN_BINARY);
if (!f) {
f = NULL;
return 1;
}
/* Return 0 if the file was opened successfully, 1 otherwise. */
return !pciids_f;
/* Generate target filename. */
strcpy(target_filename, "PCIIDS_@.BIN");
target_filename[7] = id;
/* Go through archive. */
while (!feof(f)) {
/* Read LHA header. */
pos = ftell(f);
if (!fread(header, sizeof(header), 1, f))
break;
/* Parse LHA header. */
header_size = LH5HeaderParse(header, sizeof(header), &original_size, &packed_size, &filename, &crc);
if (!header_size)
break; /* invalid header */
/* Check filename. */
crc = !strcmp(filename, target_filename);
free(filename);
if (crc) {
/* Allocate buffer for reading the compressed data. */
buf = malloc(packed_size);
if (!buf)
goto fail;
/* Allocate buffer for the decompressed data. */
*ptr = malloc(original_size);
if (!*ptr)
goto fail;
/* Read and decompress data. */
fseek(f, pos + header_size, SEEK_SET);
if (!fread(buf, packed_size, 1, f))
goto fail;
if (LH5Decode(buf, packed_size, *ptr, original_size) == -1)
goto fail;
/* All done, close archive. */
fclose(f);
return 0;
}
/* Move on to the next header. */
fseek(f, pos + header_size + packed_size, SEEK_SET);
}
fail:
/* Entry not found or read/decompression failed. */
printf("PCI ID database %c decompression failed\n", id);
fclose(f);
return 1;
}
static char *
pciids_read_string(uint32_t offset)
{
uint8_t length, *buf;
uint32_t sum;
int i;
/* Return nothing if the string offset is invalid. */
if (offset == 0xffffffff)
return NULL;
/* Open database if required. */
if (pciids_open_database())
if (pciids_open_database((void **) &pciids_string, 'T'))
return NULL;
/* Seek to string offset. */
fseek(pciids_f, pciids_header.string_db_offset + offset, SEEK_SET);
/* Read string length, and return nothing if it's an empty string. */
fread(&length, sizeof(length), 1, pciids_f);
if (length == 0)
return NULL;
/* Read string into buffer. */
buf = malloc(length + 1);
if (fread(buf, length, 1, pciids_f) < 1) {
/* Clean up and return nothing if the read failed. */
free(buf);
return NULL;
}
buf[length] = '\0';
return buf;
return &pciids_string[offset];
}
static int
pciids_find_vendor(uint16_t vendor_id)
find_vendor(uint16_t vendor_id)
{
/* Open database if required. */
if (pciids_open_database())
if (pciids_open_database((void **) &pciids_vendor, 'V'))
return 0;
/* Seek to vendor database. */
fseek(pciids_f, sizeof(pciids_header), SEEK_SET);
/* Read vendor entries until the ID is matched or overtaken. */
do {
if (fread(&pciids_vendor, sizeof(pciids_vendor), 1, pciids_f) < 1)
break;
} while (pciids_vendor.vendor_id < vendor_id);
/* Go through vendor entries until the ID is matched or overtaken. */
for (pciids_cur_vendor = 0; pciids_vendor[pciids_cur_vendor].vendor_id < vendor_id; pciids_cur_vendor++)
;
/* Return 1 if the ID was matched, 0 otherwise. */
return pciids_vendor.vendor_id == vendor_id;
return pciids_vendor[pciids_cur_vendor].vendor_id == vendor_id;
}
static char *
pciids_get_vendor(uint16_t vendor_id)
{
/* Find vendor ID in the database, and return its name if found. */
if (pciids_find_vendor(vendor_id))
return pciids_read_string(pciids_vendor.string_offset);
if (find_vendor(vendor_id))
return pciids_read_string(pciids_vendor[pciids_cur_vendor].string_offset);
/* Return nothing if the vendor ID was not found. */
return NULL;
@@ -263,21 +292,16 @@ pciids_get_device(uint16_t device_id)
/* Must be preceded by a call to {find|get}_vendor to establish the vendor ID! */
/* Open database if required. */
if (pciids_open_database())
if (pciids_open_database((void **) &pciids_device, 'D'))
return NULL;
/* Seek to device database entries for the established vendor. */
fseek(pciids_f, pciids_header.device_db_offset + pciids_vendor.devices_offset, SEEK_SET);
/* Read device entries until the ID is matched or overtaken. */
do {
if (fread(&pciids_device, sizeof(pciids_device), 1, pciids_f) < 1)
break;
} while (pciids_device.device_id < device_id);
/* Go through device entries until the ID is matched or overtaken. */
for (pciids_cur_device = pciids_vendor[pciids_cur_vendor].devices_offset; pciids_device[pciids_cur_device].device_id < device_id; pciids_cur_device++)
;
/* Return the device name if found. */
if (pciids_device.device_id == device_id)
return pciids_read_string(pciids_device.string_offset);
if (pciids_device[pciids_cur_device].device_id == device_id)
return pciids_read_string(pciids_device[pciids_cur_device].string_offset);
/* Return nothing if the device ID was not found. */
return NULL;
@@ -287,23 +311,19 @@ static char *
pciids_get_subdevice(uint16_t subvendor_id, uint16_t subdevice_id)
{
/* Must be preceded by calls to {find|get}_vendor and get_device to establish the vendor/device ID! */
int i;
/* Open database if required. */
if (pciids_open_database())
if (pciids_open_database((void **) &pciids_subdevice, 'S'))
return NULL;
/* Seek to subdevice database entries for the established subvendor. */
fseek(pciids_f, pciids_header.subdevice_db_offset + pciids_device.subdevices_offset, SEEK_SET);
/* Read subdevice entries until the ID is matched or overtaken. */
do {
if (fread(&pciids_subdevice, sizeof(pciids_subdevice), 1, pciids_f) < 1)
break;
} while ((pciids_subdevice.subvendor_id < subvendor_id) || (pciids_subdevice.subdevice_id < subdevice_id));
/* Go through subdevice entries until the ID is matched or overtaken. */
for (i = pciids_device[pciids_cur_device].subdevices_offset; (pciids_subdevice[i].subvendor_id < subvendor_id) || (pciids_subdevice[i].subdevice_id < subdevice_id); i++)
;
/* Return the subdevice name if found. */
if ((pciids_subdevice.subvendor_id == subvendor_id) && (pciids_subdevice.subdevice_id == subdevice_id))
return pciids_read_string(pciids_subdevice.string_offset);
if ((pciids_subdevice[i].subvendor_id == subvendor_id) && (pciids_subdevice[i].subdevice_id == subdevice_id))
return pciids_read_string(pciids_subdevice[i].string_offset);
/* Return nothing if the subdevice ID was not found. */
return NULL;
@@ -312,22 +332,19 @@ pciids_get_subdevice(uint16_t subvendor_id, uint16_t subdevice_id)
static char *
pciids_get_class(uint8_t class_id)
{
int i;
/* Open database if required. */
if (pciids_open_database())
if (pciids_open_database((void **) &pciids_class, 'C'))
return NULL;
/* Seek to class database. */
fseek(pciids_f, pciids_header.class_db_offset, SEEK_SET);
/* Read class entries until the ID is matched or overtaken. */
do {
if (fread(&pciids_class, sizeof(pciids_class), 1, pciids_f) < 1)
break;
} while (pciids_class.class_id < class_id);
/* Go through class entries until the ID is matched or overtaken. */
for (i = 0; pciids_class[i].class_id < class_id; i++)
;
/* Return the class name if found. */
if (pciids_class.class_id == class_id)
return pciids_read_string(pciids_class.string_offset);
if (pciids_class[i].class_id == class_id)
return pciids_read_string(pciids_class[i].string_offset);
/* Return nothing if the class ID was not found. */
return NULL;
@@ -336,22 +353,19 @@ pciids_get_class(uint8_t class_id)
static char *
pciids_get_subclass(uint8_t class_id, uint8_t subclass_id)
{
int i;
/* Open database if required. */
if (pciids_open_database())
if (pciids_open_database((void **) &pciids_subclass, 'U'))
return NULL;
/* Seek to subclass database. */
fseek(pciids_f, pciids_header.subclass_db_offset, SEEK_SET);
/* Read subclass entries until the ID is matched or overtaken. */
do {
if (fread(&pciids_subclass, sizeof(pciids_subclass), 1, pciids_f) < 1)
break;
} while ((pciids_subclass.class_id < class_id) || (pciids_subclass.subclass_id < subclass_id));
/* Go through subclass entries until the ID is matched or overtaken. */
for (i = 0; (pciids_subclass[i].class_id < class_id) || (pciids_subclass[i].subclass_id < subclass_id); i++)
;
/* Return the subclass name if found. */
if ((pciids_subclass.class_id == class_id) && (pciids_subclass.subclass_id == subclass_id))
return pciids_read_string(pciids_subclass.string_offset);
if ((pciids_subclass[i].class_id == class_id) && (pciids_subclass[i].subclass_id == subclass_id))
return pciids_read_string(pciids_subclass[i].string_offset);
/* Return nothing if the subclass ID was not found. */
return NULL;
@@ -360,22 +374,19 @@ pciids_get_subclass(uint8_t class_id, uint8_t subclass_id)
static char *
pciids_get_progif(uint8_t class_id, uint8_t subclass_id, uint8_t progif_id)
{
int i;
/* Open database if required. */
if (pciids_open_database())
if (pciids_open_database((void **) &pciids_progif, 'P'))
return NULL;
/* Seek to programming interface database. */
fseek(pciids_f, pciids_header.progif_db_offset, SEEK_SET);
/* Read programming interface entries until the ID is matched or overtaken. */
do {
if (fread(&pciids_progif, sizeof(pciids_progif), 1, pciids_f) < 1)
break;
} while ((pciids_progif.class_id < class_id) || (pciids_progif.subclass_id < subclass_id) || (pciids_progif.progif_id < progif_id));
/* Go through programming interface entries until the ID is matched or overtaken. */
for (i = 0; (pciids_progif[i].class_id < class_id) || (pciids_progif[i].subclass_id < subclass_id) || (pciids_progif[i].progif_id < progif_id); i++)
;
/* Return the programming interface name if found. */
if ((pciids_progif.class_id == class_id) && (pciids_progif.subclass_id == subclass_id) && (pciids_progif.progif_id == progif_id))
return pciids_read_string(pciids_progif.string_offset);
if ((pciids_progif[i].class_id == class_id) && (pciids_progif[i].subclass_id == subclass_id) && (pciids_progif[i].progif_id == progif_id))
return pciids_read_string(pciids_progif[i].string_offset);
/* Return nothing if the programming interface ID was not found. */
return NULL;
@@ -612,14 +623,12 @@ scan_bus(uint8_t bus, int nesting, char dump, char *buf)
/* Add vendor name to buffer. */
strcat(buf, temp);
strcat(buf, " ");
free(temp);
/* Look up device name. */
temp = pciids_get_device(dev_id.u16[1]);
if (temp) {
/* Add device name to buffer. */
strcat(buf, temp);
free(temp);
} else {
/* Device name not found. */
goto unknown_device;
@@ -633,7 +642,6 @@ unknown_device: /* Look up class ID. */
if (temp) {
/* Add class name to buffer. */
sprintf(&buf[strlen(buf)], "[%s]", temp);
free(temp);
} else {
/* Class name not found. */
sprintf(&buf[strlen(buf)], "[Class %02X:%02X:%02X]", dev_rev_class.u8[3], dev_rev_class.u8[2], dev_rev_class.u8[1]);
@@ -807,24 +815,15 @@ dump_info(uint8_t bus, uint8_t dev, uint8_t func)
/* Print vendor name if found. */
temp = pciids_get_vendor(reg_val.u16[0]);
if (temp) {
printf("%s", temp);
free(temp);
} else {
printf("[Unknown]");
}
printf("%s", temp ? temp : "[Unknown]");
/* Print device ID. */
printf("\nDevice: [%04X] ", reg_val.u16[1]);
/* Print device name if found. */
temp = pciids_get_device(reg_val.u16[1]);
if (temp) {
printf("%s", temp);
free(temp);
} else {
printf("[Unknown]");
}
if (temp)
printf("%s", temp ? temp : "[Unknown]");
/* Read header type. We'll be using it a lot. */
header_type = pci_readb(bus, dev, func, 0x0e);
@@ -864,24 +863,14 @@ dump_info(uint8_t bus, uint8_t dev, uint8_t func)
/* Print subvendor name if found. */
temp = pciids_get_vendor(reg_val.u16[0]);
if (temp) {
printf("%s", temp);
free(temp);
} else {
printf("[Unknown]");
}
printf("%s", temp ? temp : "[Unknown]");
/* Print subdevice ID. */
printf("\nSubdevice: [%04X] ", reg_val.u16[1]);
/* Print subdevice ID if found. */
temp = pciids_get_subdevice(reg_val.u16[0], reg_val.u16[1]);
if (temp) {
printf("%s", temp);
free(temp);
} else {
printf("[Unknown]");
}
printf("%s", temp ? temp : "[Unknown]");
}
}
@@ -912,36 +901,21 @@ dump_info(uint8_t bus, uint8_t dev, uint8_t func)
/* Print class name if found. */
temp = pciids_get_class(reg_val.u8[3]);
if (temp) {
printf("%s", temp);
free(temp);
} else {
printf("[Unknown]");
}
printf("%s", temp ? temp : "[Unknown]");
/* Print subclass ID. */
printf("\n [%02X] ", reg_val.u8[2]);
/* Print subclass name if found. */
temp = pciids_get_subclass(reg_val.u8[3], reg_val.u8[2]);
if (temp) {
printf("%s", temp);
free(temp);
} else {
printf("[Unknown]");
}
printf("%s", temp ? temp : "[Unknown]");
/* Print programming interface ID. */
printf("\n [%02X] ", reg_val.u8[1]);
/* Print programming interface name if found. */
temp = pciids_get_progif(reg_val.u8[3], reg_val.u8[2], reg_val.u8[1]);
if (temp) {
printf("%s", temp);
free(temp);
} else {
printf("[Unknown]");
}
printf("%s", temp ? temp : "[Unknown]");
/* Read latency, grant and interrupt line. */
reg_val.u32 = pci_readl(bus, dev, func, 0x3c);

View File

@@ -43,7 +43,7 @@ clean_device_abbr = [
('High Definition Audio', 'HDA'),
('Host Adapter', 'HBA'),
('Host Bus Adapter', 'HBA'),
('Host Controller', 'HC'),
('Host[- ]Controller', 'HC'), # dash = 1106:3104
('Input/Output', 'I/O'),
('Integrated ([^\s]+) (?:Graphics|GPU)', '\\2 iGPU'), # VIA CLE266
('Integrated (?:Graphics|GPU)', 'iGPU'),
@@ -75,7 +75,7 @@ clean_device_abbr = [
clean_device_bit_pattern = re.compile('''( |^|\(|\[|\{|/)(?:([0-9]{1,4}) )?(?:(K)(?:ilo)?|(M)(?:ega)?|(G)(?:iga)?)bit( |$|\)|\]|\})''', re.I)
clean_device_suffix_pattern = re.compile(''' (?:Adapter|Card|Device|(?:Host )?Controller)( (?: [0-9#]+)?|$|\)|\]|\})''', re.I)
clean_vendor_abbr_pattern = re.compile(''' \[([^\]]+)\]''')
clean_vendor_suffix_pattern = re.compile('''[ ,.](?:Semiconductors?|(?:Micro)?electronics?|Interactive|Technolog(?:y|ies)|(?:Micro)?systems|Computer(?: works)?|Products|Group|and subsidiaries|of(?: America)?|Co(?:rp(?:oration)?|mpany)?|Inc|LLC|Ltd|GmbH(?: \& .+)?|AB|AG|SA|(?:\(|\[|\{).*)$''', re.I)
clean_vendor_suffix_pattern = re.compile('''[ ,.](?:Semiconductors?|(?:Micro)?electronics?|Interactive|Technolog(?:y|ies)|(?:Micro)?systems|Computer(?: works)?|Products|Group|and subsidiaries|of(?: America)?|Co(?:rp(?:oration)?|mpany)?|Inc|LLC|Ltd|GmbH(?: & .+)?|AB|AG|SA|(?:\(|\[|\{).*)$''', re.I)
clean_vendor_force = {
'National Semiconductor Corporation': 'NSC',
}