Nico Huber (nico.h@gmx.de) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/4695
-gerrit
commit d8ba4b63ff4c59f54300ccce2976225c69b93a7e Author: Nico Huber nico.h@gmx.de Date: Wed Jan 1 20:47:55 2014 +0100
uio_usbdebug: User-space-i/o framework for usbdebug
uio_usbdebug enables you to debug coreboot's usbdebug driver inside a running operating system (only Linux at this time). This comes very handy if you're hacking the usbdebug driver and don't have any other debug output from coreboot itself.
Currently, only Intel chipsets are supported.
Change-Id: Iaf0bcd4b4c01ae0b099d1206d553344054a62f31 Signed-off-by: Nico Huber nico.h@gmx.de --- util/uio_usbdebug/Makefile | 44 ++++++++++++++ util/uio_usbdebug/README | 77 ++++++++++++++++++++++++ util/uio_usbdebug/console/printk.c | 34 +++++++++++ util/uio_usbdebug/device/device_util.c | 42 +++++++++++++ util/uio_usbdebug/device/pci_device.c | 30 ++++++++++ util/uio_usbdebug/device/pci_ops.c | 25 ++++++++ util/uio_usbdebug/lib/cbmem.c | 8 +++ util/uio_usbdebug/linux/Makefile | 13 ++++ util/uio_usbdebug/linux/uio_ehci_pci.c | 106 +++++++++++++++++++++++++++++++++ util/uio_usbdebug/uio_usbdebug.c | 60 +++++++++++++++++++ util/uio_usbdebug/uio_usbdebug_intel.c | 41 +++++++++++++ 11 files changed, 480 insertions(+)
diff --git a/util/uio_usbdebug/Makefile b/util/uio_usbdebug/Makefile new file mode 100644 index 0000000..0ec9a8e --- /dev/null +++ b/util/uio_usbdebug/Makefile @@ -0,0 +1,44 @@ +include ../../.config + +ARCHDIR-$(CONFIG_ARCH_ARMV7) := armv7 +ARCHDIR-$(CONFIG_ARCH_X86) := x86 + +# Only Intel chipsets supported, currently. +OBJ-$(CONFIG_SOUTHBRIDGE_INTEL_COMMON) += uio_usbdebug_intel.o + +PROGRAM := uio_usbdebug + +CB_SRC := $(shell realpath ../../src) +CB_SOURCES := drivers/usb/pci_ehci.c drivers/usb/ehci_debug.c +CB_INCLUDES := drivers/usb/ehci.h drivers/usb/ehci_debug.h \ + drivers/usb/usb_ch9.h +OBJECTS := uio_usbdebug.o \ + console/printk.o \ + device/device_util.o device/pci_device.o device/pci_ops.o \ + lib/cbmem.o \ + $(OBJ-y) \ + $(patsubst %.c,%.o,$(CB_SOURCES)) + +CONFIG_H := ../../build/config.h + +CFLAGS += -m32 -g \ + -Wall -Wextra -Werror \ + -Wno-unused-parameter -Wno-error=sign-compare +CPPFLAGS += -I../../src/include/ -I../../src/arch/$(ARCHDIR-y)/include/ \ + -include$(CONFIG_H) + +all: $(PROGRAM) + +$(PROGRAM): $(OBJECTS) $(OBJ-y) + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJECTS) + +$(CB_SOURCES) $(CB_INCLUDES): + @mkdir -p $(dir $@) + @ln -sf $(CB_SRC)/$@ $@ + +$(OBJECTS): $(CONFIG_H) $(CB_INCLUDES) + +clean: + -@rm -rf $(CB_SOURCES) $(CB_INCLUDES) $(OBJECTS) $(PROGRAM) + +.PHONY: all clean diff --git a/util/uio_usbdebug/README b/util/uio_usbdebug/README new file mode 100644 index 0000000..2d52338 --- /dev/null +++ b/util/uio_usbdebug/README @@ -0,0 +1,77 @@ + +uio_usbdebug - Run coreboot's usbdebug driver in userspace +========================================================== + + +## Purpose + +uio_usbdebug enables you to debug coreboot's usbdebug driver inside a +running operating system (only Linux at this time). This comes very +handy if you're hacking the usbdebug driver and don't have any other +debug output from coreboot itself. + + +## State + +Currently only Intel chipsets are supported. Support for other chipsets +should be straightforward (normally just some port-enable code has to +be implemented). + +The Linux kernel driver (see linux/uio_ehci_pci.c) has only one PCI ID +hardcoded (for ICH7). The whole setup has been developed and tested on +a ThinkPad T60. + +### Files + +uio_usbdebug.c - The userspace part of the uio interface. + +uio_usbdebug_intel.c - Port enable code for Intel chipsets. + +linux/uio_ehci_pci.c - Kernel part of the uio interface. + +console/printk.c - A do_printk() implementation so you can see debug + output with CONFIG_DEBUG_USBDEBUG enabled. + +device/*.c lib/*.c - Some stubs for (hopefully) unneeded functions for + proper linking. + + +## Usage + +### Preparations + +The MMIO space has to be a whole 4K page in size and alignment to be +mapped into userspace. This is very uncommon, so you'll most probably +have to remap the MMIO space. The Linux kernel does that for you with +the `pci=resource_alignment=<pci address>` kernel parameter (e.g. +`pci=resource_alignment=0:1d.7` for ICH7). + +If your PCI device isn't listed in the kernel driver yet, you might want +to add it to the `ehci_pci_ids` table in `linux/uio_ehci_pci.c` (or do +some module alias magic if you know how to). + +### Build / Install + +Somehow like this: + +$ # Configure coreboot for your board and enable CONFIG_USBDEBUG +$ make menuconfig +$ cd util/uio_usbdebug/ +$ make -Clinux/ +$ sudo make -Clinux/ install +$ make + +### Run + +$ # Unload Linux' EHCI driver (high-speed devices will stop working) +$ sudo modprobe -r ehci-pci +$ # Load the uio driver +$ sudo modprobe uio-ehci-pci +$ # Find your uio device +$ ls /sys/module/uio_ehci_pci/drivers/*/*/uio/ +uio0 +$ # Run uio_usbdebug on this device +$ sudo ./uio_usbdebug /dev/uio0 + +Sadly, uio_usbdebug has to be run with root privileges since there are +port-80 writes in the usbdebug driver. diff --git a/util/uio_usbdebug/console/printk.c b/util/uio_usbdebug/console/printk.c new file mode 100644 index 0000000..a73407c --- /dev/null +++ b/util/uio_usbdebug/console/printk.c @@ -0,0 +1,34 @@ +/* + * This file is part of uio_usbdebug + * + * Copyright (C) 2013 Nico Huber nico.h@gmx.de + * + * 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; version 2 of the License. + * + * 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; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <stdio.h> +#include <stdarg.h> +#include <console/console.h> + +int do_printk(int msg_level, const char *const fmt, ...) +{ + va_list args; + int i; + + va_start(args, fmt); + i = vfprintf(stderr, fmt, args); + va_end(args); + + return i; +} diff --git a/util/uio_usbdebug/device/device_util.c b/util/uio_usbdebug/device/device_util.c new file mode 100644 index 0000000..213780e --- /dev/null +++ b/util/uio_usbdebug/device/device_util.c @@ -0,0 +1,42 @@ +/* + * This file is part of uio_usbdebug + * + * Copyright (C) 2013 Nico Huber nico.h@gmx.de + * + * 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; version 2 of the License. + * + * 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; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <device/device.h> + +static char g_path[] = { '\0' }; + +const char *dev_path(device_t dev) +{ + return g_path; +} + +struct resource *find_resource(device_t dev, unsigned index) +{ + return NULL; +} + +void report_resource_stored(device_t dev, struct resource *resource, + const char *comment) +{ +} + +struct device *dev_find_slot(unsigned int bus, unsigned int devfn) +{ + return NULL; +} diff --git a/util/uio_usbdebug/device/pci_device.c b/util/uio_usbdebug/device/pci_device.c new file mode 100644 index 0000000..980117f --- /dev/null +++ b/util/uio_usbdebug/device/pci_device.c @@ -0,0 +1,30 @@ +/* + * This file is part of uio_usbdebug + * + * Copyright (C) 2013 Nico Huber nico.h@gmx.de + * + * 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; version 2 of the License. + * + * 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; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <device/pci.h> +#include <device/device.h> + +unsigned int pci_match_simple_dev(device_t dev, pci_devfn_t sdev) +{ + return 0; +} + +void pci_dev_read_resources(struct device *dev) +{ +} diff --git a/util/uio_usbdebug/device/pci_ops.c b/util/uio_usbdebug/device/pci_ops.c new file mode 100644 index 0000000..2bcfec0 --- /dev/null +++ b/util/uio_usbdebug/device/pci_ops.c @@ -0,0 +1,25 @@ +/* + * This file is part of uio_usbdebug + * + * Copyright (C) 2013 Nico Huber nico.h@gmx.de + * + * 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; version 2 of the License. + * + * 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; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <device/device.h> + +u32 pci_read_config32(device_t dev, unsigned int where) +{ + return 0; +} diff --git a/util/uio_usbdebug/lib/cbmem.c b/util/uio_usbdebug/lib/cbmem.c new file mode 100644 index 0000000..6d87880 --- /dev/null +++ b/util/uio_usbdebug/lib/cbmem.c @@ -0,0 +1,8 @@ + +#include <stdint.h> +#include <stddef.h> + +void *cbmem_find(u32 id) +{ + return NULL; +} diff --git a/util/uio_usbdebug/linux/Makefile b/util/uio_usbdebug/linux/Makefile new file mode 100644 index 0000000..fd60b4f --- /dev/null +++ b/util/uio_usbdebug/linux/Makefile @@ -0,0 +1,13 @@ + +obj-m := uio_ehci_pci.o + +all: uio_ehci_pci.c + @$(MAKE) -C/lib/modules/`uname -r`/build M=$(CURDIR) modules + +install: + @$(MAKE) -C/lib/modules/`uname -r`/build M=$(CURDIR) modules_install + +clean: + -@$(MAKE) -C/lib/modules/`uname -r`/build M=$(CURDIR) clean + +.PHONY: all install clean diff --git a/util/uio_usbdebug/linux/uio_ehci_pci.c b/util/uio_usbdebug/linux/uio_ehci_pci.c new file mode 100644 index 0000000..d5c33e3 --- /dev/null +++ b/util/uio_usbdebug/linux/uio_ehci_pci.c @@ -0,0 +1,106 @@ +/* + * uio_ehci_pci - UIO driver for PCI EHCI devices + * + * Copyright (C) 2013 Nico Huber nico.h@gmx.de + * + * This only implements MMIO access (no interrupts). + * + * 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; version 2 of the License. + * + * 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; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA + */ + +#include <linux/device.h> +#include <linux/module.h> +#include <linux/pci.h> +#include <linux/uio_driver.h> + +#define DRIVER_VERSION "0.0.1" +#define DRIVER_AUTHOR "Nico Huber nico.h@gmx.de" +#define DRIVER_DESC "UIO driver for PCI EHCI devices" +#define DRIVER_TAG "uio_ehci_pci" + +static int probe(struct pci_dev *const pci_dev, + const struct pci_device_id *const did) +{ + struct uio_info *info; + int ret; + + ret = pci_enable_device(pci_dev); + if (ret) + goto return_; + + ret = pci_request_regions(pci_dev, DRIVER_TAG); + if (ret) + goto return_disable; + + info = kzalloc(sizeof(struct uio_info), GFP_KERNEL); + if (!info) { + ret = -ENOMEM; + goto return_release; + } + + info->name = DRIVER_TAG; + info->version = DRIVER_VERSION; + + info->mem[0].name = "EHCI MMIO area"; + info->mem[0].addr = pci_resource_start(pci_dev, 0); + if (!info->mem[0].addr) { + ret = -ENODEV; + goto return_free; + } + info->mem[0].size = pci_resource_len(pci_dev, 0); + info->mem[0].memtype = UIO_MEM_PHYS; + + ret = uio_register_device(&pci_dev->dev, info); + if (ret) + goto return_free; + pci_set_drvdata(pci_dev, info); + + return 0; +return_free: + kfree(info); +return_release: + pci_release_regions(pci_dev); +return_disable: + pci_disable_device(pci_dev); +return_: + return ret; +} + +static void remove(struct pci_dev *const pci_dev) +{ + struct uio_info *const info = pci_get_drvdata(pci_dev); + + uio_unregister_device(info); + kfree(info); + pci_release_regions(pci_dev); + pci_disable_device(pci_dev); +} + +static DEFINE_PCI_DEVICE_TABLE(ehci_pci_ids) = { + { PCI_DEVICE(0x8086, 0x27cc) }, + { 0, } +}; + +static struct pci_driver uio_ehci_pci_driver = { + .name = DRIVER_TAG, + .id_table = ehci_pci_ids, + .probe = probe, + .remove = remove, +}; + +module_pci_driver(uio_ehci_pci_driver); +MODULE_VERSION(DRIVER_VERSION); +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); diff --git a/util/uio_usbdebug/uio_usbdebug.c b/util/uio_usbdebug/uio_usbdebug.c new file mode 100644 index 0000000..e4024bf --- /dev/null +++ b/util/uio_usbdebug/uio_usbdebug.c @@ -0,0 +1,60 @@ +/* + * uio_usbdebug - Run coreboot's usbdebug driver in userspace + * + * Copyright (C) 2013 Nico Huber nico.h@gmx.de + * + * 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; version 2 of the License. + * + * 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; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <stdio.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#include <sys/mman.h> + +/* coreboot's arch/io.h conflicts with libc's sys/io.h, so declare this here: */ +int ioperm(unsigned long from, unsigned long num, int turn_on); + +#include <arch/io.h> +#include <console/usb.h> + +void *ehci_bar; + +int main(int argc, char *argv[]) +{ + if (argc != 2) { + fprintf(stderr, "Usage: %s <uio-dev>\n", argv[0]); + return 1; + } + const int fd = open(argv[1], O_RDWR); + if (fd < 0) { + perror("Failed to open uio device"); + return 2; + } + ehci_bar = + mmap(NULL, 1 << 8, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (MAP_FAILED == ehci_bar) { + perror("Failed to map ehci bar"); + close(fd); + return 3; + } + + ioperm(0x80, 1, 1); + + usbdebug_simple_init_at((unsigned)ehci_bar); + + munmap(ehci_bar, 1 << 8); + close(fd); + return 0; +} diff --git a/util/uio_usbdebug/uio_usbdebug_intel.c b/util/uio_usbdebug/uio_usbdebug_intel.c new file mode 100644 index 0000000..95aec01 --- /dev/null +++ b/util/uio_usbdebug/uio_usbdebug_intel.c @@ -0,0 +1,41 @@ +/* + * This file is part of uio_usbdebug + * + * Copyright (C) 2013 Nico Huber nico.h@gmx.de + * + * 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; version 2 of the License. + * + * 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; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <arch/io.h> +#include <device/device.h> +#include <console/usb.h> + +extern void *ehci_bar; + +pci_devfn_t pci_ehci_dbg_dev(unsigned hcd_idx) +{ + return 0; +} + +void pci_ehci_dbg_set_port(pci_devfn_t dev, unsigned int port) +{ + /* claim usb debug port */ + const unsigned long dbgctl_addr = + ((unsigned long)ehci_bar) + CONFIG_EHCI_DEBUG_OFFSET; + write32(dbgctl_addr, read32(dbgctl_addr) | (1 << 30)); +} + +void pci_ehci_dbg_enable(pci_devfn_t dev, unsigned long base) +{ +}