pcireg: Port to Windows using libpci for dummy configuration space generation

This commit is contained in:
RichardG867
2024-10-23 15:09:38 -03:00
parent fbf70afa54
commit 2f6cad846c
7 changed files with 172 additions and 22 deletions

View File

@@ -15,7 +15,7 @@ jobs:
steps:
- name: Install build tools
run: sudo apt update && sudo apt install build-essential crossbuild-essential-i386 xz-utils
run: sudo apt update && sudo apt install build-essential crossbuild-essential-i386 gcc-mingw-w64-i686 binutils-mingw-w64-i686 mingw-w64-i686-dev gcc-mingw-w64-x86-64 binutils-mingw-w64-x86-64 mingw-w64-x86-64-dev xz-utils
- name: Download OpenWatcom
if: steps.cache.outputs.cache-hit != 'true'
run: |
@@ -31,6 +31,10 @@ jobs:
cd /opt/pciutils-*
make CC=i686-linux-gnu-gcc ZLIB=no DNS=no SHARED=no
sudo make install-lib
make clean all CROSS_COMPILE=i686-w64-mingw32- HOST=i586-windows ZLIB=no DNS=no SHARED=no IDSDIR=""
sudo make install-lib PREFIX=/usr/i686-w64-mingw32
make clean all CROSS_COMPILE=x86_64-w64-mingw32- HOST=x86_64-windows ZLIB=no DNS=no SHARED=no IDSDIR=""
sudo make install-lib PREFIX=/usr/x86_64-w64-mingw32
- uses: actions/checkout@v4
- name: Build `cp437`
run: |
@@ -57,7 +61,9 @@ jobs:
cd ${{ github.workspace }}/pcireg
wmake
make -f Makefile.uefi ARCH=x86_64
make -f Makefile.gcc clean default CC=i686-linux-gnu-gcc CFLAGS=-I/usr/local/include LDFLAGS=-static
make -f Makefile.gcc clean all CC=i686-w64-mingw32-gcc CFLAGS=-I/usr/local/include LDFLAGS=-static LDAPPEND=-lcfgmgr32 DEST=pciregw
make -f Makefile.gcc clean all CC=x86_64-w64-mingw32-gcc CFLAGS=-I/usr/local/include LDFLAGS=-static LDAPPEND=-lcfgmgr32 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: |

View File

@@ -20,6 +20,9 @@
#else
# include <stdio.h>
#endif
#ifdef PCI_LIB_VERSION
# include <stdarg.h>
#endif
#include "clib_pci.h"
#include "clib_sys.h"
@@ -27,6 +30,8 @@ uint8_t pci_mechanism = 0, pci_device_count = 0;
#ifdef PCI_LIB_VERSION
static struct pci_access *pacc;
static struct pci_dev *pdev;
static uint32_t last_addr = -1;
static const char win_notice[] = "NOTICE: These are dummy configuration registers generated by libpci, as it cannot access the real ones under Windows. It does not reflect the device's actual configuration.";
#endif
/* Configuration functions. */
@@ -116,8 +121,67 @@ pci_get_mem_bar(uint8_t bus, uint8_t dev, uint8_t func, uint8_t reg, uint32_t si
#ifdef PCI_LIB_VERSION
static void
dummy_print(char *msg, ...)
pci_printf(char *msg, ...)
{
va_list ap;
va_start(ap, msg);
vfprintf(stderr, msg, ap);
putc('\n', stderr);
va_end(ap);
}
static void
pci_init_dev(uint8_t bus, uint8_t dev, uint8_t func)
{
struct pci_dev *other;
uint32_t addr = (bus << 16) | (dev << 8) | func;
if (addr != last_addr) {
last_addr = addr;
if (!pacc->devices) {
libpci_scan_bus(pacc);
/* Generate additional configuration values not generated by
libpci's emulated configuration space code on Windows. */
if (pacc->method == PCI_ACCESS_WIN32_CFGMGR32) {
/* Create cache and read generated values for every device. */
for (pdev = pacc->devices; pdev; pdev = pdev->next) {
pdev->cache = malloc(0x40 + sizeof(win_notice));
pci_setup_cache(pdev, pdev->cache, 0x40 + sizeof(win_notice));
pci_read_block(pdev, 0, pdev->cache, 64);
if (pdev->cache[0x0e] & 0x7f)
pdev->cache[0x19] = -1;
strcpy(&pdev->cache[0x40], win_notice);
}
/* Perform scan to fill in some values. */
for (pdev = pacc->devices; pdev; pdev = pdev->next) {
/* Perform recursive scan to set multi-function bit if another function is present. */
for (other = pacc->devices; other; other = other->next) {
if (!pdev->func && (other->domain == pdev->domain) && (other->bus == pdev->bus) && (other->dev == pdev->dev) && other->func) {
pdev->cache[0x0e] |= 0x80;
break;
}
}
/* Set secondary bus value and cascade subordinate bus value to parents. */
other = pdev;
while (other->parent) {
other->parent->cache[0x19] = other->bus;
if (other->parent->cache[0x1a] < pdev->bus)
other->parent->cache[0x1a] = pdev->bus;
other = other->parent;
}
}
}
}
for (pdev = pacc->devices; pdev; pdev = pdev->next) {
if (!pdev->domain && (pdev->bus == bus) && (pdev->dev == dev) && (pdev->func == func))
break;
}
}
}
#endif
@@ -125,21 +189,23 @@ int
pci_init()
{
#ifdef PCI_LIB_VERSION
# ifndef _WIN32
if (iopl(3)) {
perror("iopl");
goto pci_init_fail;
}
# endif
pacc = pci_alloc();
if (!pacc) {
printf("Failed to allocate pci_access structure.\n");
pci_init_fail:
pci_mechanism = 0;
return pci_mechanism;
}
pacc = pci_alloc();
if (!pacc) {
printf("Failed to allocate pci_access structure.\n");
goto pci_init_fail;
}
pacc->error = pacc->warning = pacc->debug = pci_printf;
libpci_init(pacc);
pacc->error = pacc->warning = pacc->debug = dummy_print;
pci_mechanism = 1;
pci_device_count = 32;
@@ -174,7 +240,7 @@ uint8_t
pci_readb(uint8_t bus, uint8_t dev, uint8_t func, uint8_t reg)
{
#ifdef PCI_LIB_VERSION
pdev = pci_get_dev(pacc, 0, bus, dev, func);
pci_init_dev(bus, dev, func);
return pdev ? pci_read_byte(pdev, reg) : 0xff;
#else
uint8_t ret;
@@ -209,7 +275,7 @@ uint16_t
pci_readw(uint8_t bus, uint8_t dev, uint8_t func, uint8_t reg)
{
#ifdef PCI_LIB_VERSION
pdev = pci_get_dev(pacc, 0, bus, dev, func);
pci_init_dev(bus, dev, func);
return pdev ? pci_read_word(pdev, reg) : 0xffff;
#else
uint16_t ret, data_port;
@@ -243,7 +309,7 @@ uint32_t
pci_readl(uint8_t bus, uint8_t dev, uint8_t func, uint8_t reg)
{
#ifdef PCI_LIB_VERSION
pdev = pci_get_dev(pacc, 0, bus, dev, func);
pci_init_dev(bus, dev, func);
return pdev ? pci_read_long(pdev, reg) : 0xffffffff;
#else
uint16_t data_port;
@@ -281,7 +347,7 @@ void
pci_writeb(uint8_t bus, uint8_t dev, uint8_t func, uint8_t reg, uint8_t val)
{
#ifdef PCI_LIB_VERSION
pdev = pci_get_dev(pacc, 0, bus, dev, func);
pci_init_dev(bus, dev, func);
if (pdev)
pci_write_byte(pdev, reg, val);
#else
@@ -314,7 +380,7 @@ void
pci_writew(uint8_t bus, uint8_t dev, uint8_t func, uint8_t reg, uint16_t val)
{
#ifdef PCI_LIB_VERSION
pdev = pci_get_dev(pacc, 0, bus, dev, func);
pci_init_dev(bus, dev, func);
if (pdev)
pci_write_word(pdev, reg, val);
#else
@@ -347,7 +413,7 @@ void
pci_writel(uint8_t bus, uint8_t dev, uint8_t func, uint8_t reg, uint32_t val)
{
#ifdef PCI_LIB_VERSION
pdev = pci_get_dev(pacc, 0, bus, dev, func);
pci_init_dev(bus, dev, func);
if (pdev)
pci_write_long(pdev, reg, val);
#else
@@ -382,7 +448,8 @@ pci_scan_bus(uint8_t bus,
uint16_t ven_id, uint16_t dev_id))
{
#ifdef PCI_LIB_VERSION
libpci_scan_bus(pacc);
if (!pacc->devices)
libpci_scan_bus(pacc);
for (pdev = pacc->devices; pdev; pdev = pdev->next) {
if (pdev->domain || (pdev->bus != bus))
continue;

View File

@@ -64,7 +64,7 @@ void outl(uint16_t port, uint32_t data);
parm[dx][ax cx] modify[ax cx];
# endif
#else
# if defined(__GNUC__) && !defined(__POSIX_UEFI__)
# if defined(__GNUC__) && !defined(__POSIX_UEFI__) && !defined(_WIN32)
# define inb sys_inb
# define outb sys_outb
# define inw sys_inw

View File

@@ -17,6 +17,9 @@
*/
#ifdef __POSIX_UEFI__
# include <uefi.h>
#elif defined(_WIN32)
# include <stdio.h>
# include <windows.h>
#else
# include <stdio.h>
# ifdef __GNUC__
@@ -127,6 +130,54 @@ term_set_cursor_pos(uint8_t x, uint8_t y)
fflush(stdout);
return 1;
}
#elif defined(_WIN32)
static CONSOLE_SCREEN_BUFFER_INFO info_cache;
static CONSOLE_SCREEN_BUFFER_INFO *
term_get_info()
{
HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE);
if (h && GetConsoleScreenBufferInfo(h, &info_cache))
return &info_cache;
return NULL;
}
int
term_get_size_x()
{
CONSOLE_SCREEN_BUFFER_INFO *info = term_get_info();
return info ? (info->srWindow.Right - info->srWindow.Left + 1) : 80;
}
int
term_get_size_y()
{
CONSOLE_SCREEN_BUFFER_INFO *info = term_get_info();
return info ? (info->srWindow.Bottom - info->srWindow.Top + 1) : 25;
}
int
term_get_cursor_pos(uint8_t *x, uint8_t *y)
{
CONSOLE_SCREEN_BUFFER_INFO *info = term_get_info();
if (!info)
return 0;
*x = info->dwCursorPosition.X;
*y = info->dwCursorPosition.Y;
return 1;
}
int
term_set_cursor_pos(uint8_t x, uint8_t y)
{
COORD coords;
HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE);
if (!h)
return 0;
coords.X = x;
coords.Y = y;
return !!SetConsoleCursorPosition(h, coords);
}
#else
int
term_get_size_x()
@@ -170,6 +221,9 @@ term_final_linebreak()
void
term_unbuffer_stdout()
{
#ifdef _WIN32
SetConsoleOutputCP(65001);
#endif
}
void

View File

@@ -18,13 +18,13 @@
VPATH = . ../clib
CC ?= "gcc"
default: $(DEST)
all: $(DEST)
%.o: %.c $(HEADERS)
$(CC) -I../clib $(CFLAGS) -c $< -o $@
$(DEST): $(OBJS)
$(CC) $(OBJS) $(LDFLAGS) -o $@
$(CC) $(OBJS) $(LDFLAGS) $(LDAPPEND) -o $@
chmod +x $@ || true
clean:

View File

@@ -17,6 +17,6 @@
export OBJS = pcireg.o clib_pci.o clib_std.o clib_sys.o clib_term.o
export DEST = pcireg
override LDFLAGS += -lpci
override LDFLAGS += -lpci $(LDAPPEND)
include ../clib/gcc.mk

View File

@@ -1,6 +1,6 @@
pcireg
======
DOS, UEFI and Linux tool for reading, writing and dumping PCI configuration space registers; scanning the PCI bus; and more.
DOS, UEFI, Windows and Linux tool for reading, writing (where supported) and dumping PCI configuration space registers; scanning the PCI bus; and more.
Usage
-----
@@ -42,6 +42,29 @@ Building
* **Linux:** Run `make -f Makefile.uefi ARCH=x86_64` with a GCC toolchain installed.
* Note that 32-bit UEFI targets are not supported yet.
### Windows target
* **Windows:** Currently not supported due to issues building `pciutils` on MSYS2.
* **Linux:** Build `pciutils` then `pcireg` itself with a MinGW toolchain installed.
* 32-bit:
```
git clone https://github.com/pciutils/pciutils.git pciutils
cd pciutils
make CROSS_COMPILE=i686-w64-mingw32- HOST=i586-windows ZLIB=no DNS=no SHARED=no IDSDIR=""
sudo make install-lib PREFIX=/usr/i686-w64-mingw32
cd ..
make -f Makefile.gcc CC=i686-w64-mingw32-gcc CFLAGS=-I/usr/local/include LDFLAGS=-static LDAPPEND=-lcfgmgr32 DEST=pciregw
```
* 64-bit:
```
git clone https://github.com/pciutils/pciutils.git pciutils
cd pciutils
make CROSS_COMPILE=x86_64-w64-mingw32- HOST=x86_64-windows ZLIB=no DNS=no SHARED=no IDSDIR=""
sudo make install-lib PREFIX=/usr/x86_64-w64-mingw32
cd ..
make -f Makefile.gcc CC=x86_64-w64-mingw32-gcc CFLAGS=-I/usr/local/include LDFLAGS=-static LDAPPEND=-lcfgmgr32 DEST=pciregw64
```
### Linux target
* **Linux:** Run `make -f Makefile.gcc` with a GCC toolchain and development files for `libpci` installed.