usblgoff: Add tool for disabling USB legacy emulation

This commit is contained in:
RichardG867
2022-01-06 19:59:18 -03:00
parent 82fe555a84
commit efa6536465
8 changed files with 231 additions and 1 deletions

View File

@@ -42,6 +42,10 @@ jobs:
wmake
make -f Makefile.uefi ARCH=x86_64
python3 pciids.py
- name: Build `usblgoff`
run: |
cd ${{ github.workspace }}/usblgoff
wmake
- uses: actions/upload-artifact@v2
with:
name: probing-tools-${{ github.sha }}
@@ -52,6 +56,7 @@ jobs:
ac97/*.md
acpi/*.md
pcireg/*.md
usblgoff/*.md
newbasic:
name: NewBasic

2
.gitignore vendored
View File

@@ -23,4 +23,4 @@ pci?????.bin
# Binaries
*.exe
*.com
*.efi
*.efi

View File

@@ -386,6 +386,34 @@ pci_get_io_bar(uint8_t bus, uint8_t dev, uint8_t func, uint8_t reg, uint16_t siz
}
#ifdef IS_32BIT
uint32_t
pci_get_mem_bar(uint8_t bus, uint8_t dev, uint8_t func, uint8_t reg, uint32_t size, const char *name)
{
uint32_t ret;
printf("%s memory BAR is ", name);
/* Read BAR register. */
ret = pci_readl(bus, dev, func, reg);
if ((ret & 0x00000001) || (ret == 0xffffffff)) {
printf("invalid! (%08X)", ret);
ret = 0;
} else {
/* Don't even try to find a valid memory range if the BAR is unassigned. */
ret &= ~(size - 1);
if (ret)
printf("assigned to %08X", ret);
else
printf("unassigned!");
}
printf("\n");
return ret;
}
#endif
int
pci_init()
{

View File

@@ -34,6 +34,9 @@
#ifndef __POSIX_UEFI__
# define FMT_FLOAT_SUPPORTED 1
#endif
#if !defined(__WATCOMC__) || defined(M_I386)
# define IS_32BIT 1
#endif
#pragma pack(push, 0)
@@ -124,6 +127,9 @@ extern uint16_t io_find_range(uint16_t size);
/* PCI functions. */
extern uint32_t pci_cf8(uint8_t bus, uint8_t dev, uint8_t func, uint8_t reg);
extern uint16_t pci_get_io_bar(uint8_t bus, uint8_t dev, uint8_t func, uint8_t reg, uint16_t size, const char *name);
#ifdef IS_32BIT
extern uint32_t pci_get_mem_bar(uint8_t bus, uint8_t dev, uint8_t func, uint8_t reg, uint32_t size, const char *name);
#endif
extern int pci_init();
extern uint8_t pci_readb(uint8_t bus, uint8_t dev, uint8_t func, uint8_t reg);
extern uint16_t pci_readw(uint8_t bus, uint8_t dev, uint8_t func, uint8_t reg);

View File

@@ -18,10 +18,12 @@
# Establish host-specific stuff.
!ifdef __UNIX__
DEL = rm -f
COPY = cp
CP437 = cp437
SLASH = /
!else
DEL = del
COPY = copy /y
CP437 = cp437.exe
SLASH = \
!if "$(SYSTEM)" == "HOST"
@@ -74,6 +76,9 @@ all: ..$(SLASH)cp437$(SLASH)$(CP437) $(DEST)
# Main target.
$(DEST): $(OBJS)
!if "$(SYSTEM)" == "PMODEW"
$(COPY) %WATCOM%$(SLASH)binw$(SLASH)pmodew.exe .$(SLASH)
!endif
%write $@.lnk NAME $@
!if "$(SYSTEM)" != "HOST"
%write $@.lnk SYSTEM $(SYSTEM)

22
usblgoff/Makefile Normal file
View File

@@ -0,0 +1,22 @@
#
# 86Box A hypervisor and IBM PC system emulator that specializes in
# running old operating systems and software designed for IBM
# PC systems and compatibles from 1981 through fairly recent
# system designs based on the PCI bus.
#
# This file is part of the 86Box Probing Tools distribution.
#
# Makefile for compiling C-based tools with Watcom.
#
#
#
# Authors: RichardG, <richardg867@gmail.com>
#
# Copyright 2021 RichardG.
#
SYSTEM = PMODEW
OBJS = usblgoff.obj clib.obj
DEST = USBLGOFF.EXE
!include ../clib/watcom.mk

12
usblgoff/README.md Normal file
View File

@@ -0,0 +1,12 @@
usblgoff
========
DOS tool for disabling USB legacy emulation to allow for running keyboard controller probing tools.
Usage
-----
Run `USBLGOFF.EXE` on a system with USB. The I/O traps set by onboard USB controllers and a handful of chipsets will be disabled, and the virtual keyboard controller created by the BIOS for USB input emulation should no longer interfere with KBC probing tools such as [amikey](../amikey) until the system is rebooted.
Building
--------
* **Windows:** Run `wmake` from an OpenWatcom "Build Environment" command prompt.
* **Linux:** Run `wmake` with OpenWatcom tools present in `$PATH`.

152
usblgoff/usblgoff.c Normal file
View File

@@ -0,0 +1,152 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box Probing Tools distribution.
*
* USB legacy emulation disable tool.
*
*
*
* Authors: RichardG, <richardg867@gmail.com>
*
* Copyright 2022 RichardG.
*
* ┌──────────────────────────────────────────────────────────────┐
* │ This file is UTF-8 encoded. If this text is surrounded by │
* │ garbage, please tell your editor to open this file as UTF-8. │
* └──────────────────────────────────────────────────────────────┘
*/
#include <inttypes.h>
#include <stdio.h>
#include <string.h>
#include "clib.h"
static void
pci_scan_callback(uint8_t bus, uint8_t dev, uint8_t func,
uint16_t ven_id, uint16_t dev_id)
{
uint8_t i;
uint16_t j, start, end;
#ifdef IS_32BIT
uint32_t mmio_base, *mmio;
#endif
#ifdef IS_32BIT
/* Disable southbridge I/O traps. */
if ((ven_id == 0x8086) && (((dev_id >= 0x2640) && (dev_id <= 0x2642)) /* ICH6 */ ||
((dev_id >= 0x27b0) && (dev_id <= 0x27bd)) /* ICH7 */ ||
((dev_id >= 0x2810) && (dev_id <= 0x2815)) /* ICH8 */ ||
((dev_id >= 0x2912) && (dev_id <= 0x2919)) /* ICH9 */ ||
((dev_id >= 0x3a14) && (dev_id <= 0x3a1a)) /* ICH10 */)) {
printf("Found ICH6-10 LPC bridge %04X at bus %02X device %02X function %d\n", dev_id, bus, dev, func);
/* Get RCBA. */
printf("> RCBA is ");
mmio_base = pci_readl(bus, dev, func, 0xf0) & ~0x00003fff;
if ((mmio_base & 0x00000001) && (mmio_base != 0xffffffff)) {
printf("assigned to %08X\n", mmio_base);
mmio = (uint32_t *) mmio_base;
/* Disable all relevant I/O traps. */
for (i = 0; i < 4; i++) {
/* Check if the trap is enabled. */
j = (0x1e80 | (i << 3)) >> 2;
if (mmio[j] & 0x00000001) {
start = mmio[j] & 0xfffc;
end = (mmio[j] >> 16) & 0xfc; /* temporarily just the mask */
printf("> Trap %d (%04X+%02X)", i, start, end);
end += start; /* now the actual end */
/* Check if the trap covers the KBC ports. */
if (((start <= 0x60) && (end >= 0x60)) ||
((start <= 0x64) && (end >= 0x64))) {
/* Clear TRSE bit. */
mmio[j] &= ~0x00000001;
/* Check if the bit was actually cleared. */
if (mmio[j] & 0x00000001)
printf("enable bit stuck! (%08X%08X)\n", mmio[j | 1], mmio[j]);
else
printf("disabled\n");
} else {
printf("not relevant\n");
}
}
}
} else {
printf("unassigned! (%08X)\n", mmio_base);
}
return;
}
#endif
/* Skip non-USB devices. */
if (pci_readw(bus, dev, func, 0x0a) != 0x0c03)
return;
/* Read progif code. */
i = pci_readb(bus, dev, func, 0x09);
/* Act according to the device class. */
if (i == 0x00) { /* UHCI */
printf("Found UHCI USB controller at bus %02X device %02X function %d\n", bus, dev, func);
/* Clear 60/64h trap/SMI R/W bits. */
j = pci_readw(bus, dev, func, 0xc0);
pci_writew(bus, dev, func, 0xc0, j & ~0x000f);
/* Check if the bits were actually cleared. */
j = pci_readw(bus, dev, func, 0xc0);
if (j & 0x000f)
printf("> I/O trap bits stuck! (%04X)\n", j);
else
printf("> I/O traps disabled\n");
} else if (i == 0x10) { /* OHCI */
printf("Found OHCI USB controller at bus %02X device %02X function %d\n", bus, dev, func);
#ifdef IS_32BIT
/* Get MMIO base address. */
mmio_base = pci_get_mem_bar(bus, dev, func, 0x10, 4096, "> MMIO");
if (mmio_base) {
mmio = (uint32_t *) mmio_base;
/* Clear EmulationEnable bit. */
mmio[0x100 >> 2] &= ~0x00000001;
/* Check if the bit was actually cleared. */
if (mmio[0x100 >> 2] & 0x00000001)
printf("> Emulation bit stuck! (%08X)\n", mmio[0x100 >> 2]);
else
printf("> Emulation disabled\n");
}
#else
printf("> OHCI not supported on 16-bit build!\n");
#endif
} else if ((i != 0x20) && (i != 0x30)) { /* not EHCI or XHCI */
printf("Found unknown USB controller type %02X at bus %02X device %02X function %d\n", i, bus, dev, func);
}
}
int
main(int argc, char **argv)
{
uint8_t dev, func;
/* Disable stdout buffering. */
term_unbuffer_stdout();
/* Initialize PCI, and exit in case of failure. */
if (!pci_init())
return 1;
/* Scan PCI bus 0. */
pci_scan_bus(0, pci_scan_callback);
return 0;
}