2009-02-08 Marco Gerards <marco@gnu.org>
* Makefile.in (enable_grub_emu_usb): New variable. * conf/i386-pc.rmk (grub_emu_SOURCES): Add `disk/scsi.c'. (grub_emu_SOURCES) [grub_emu_SOURCES]: Add `disk/usbms.c', `util/usb.c', `bus/usb/usb.c' and `commands/usbtest.c'. (grub_emu_LDFLAGS): Add `$(LIBUSB)'. (pkglib_MODULES): Add `usb.mod', `uhci.mod', `ohci.mod', `usbtest.mod' and `usbms.mod'. (usb_mod_SOURCES, usb_mod_CFLAGS, usb_mod_LDFLAGS) (usbtest_mod_SOURCES, usbtest_mod_CFLAGS, usbtest_mod_LDFLAGS) (uhci_mod_SOURCES, uhci_mod_CFLAGS, uhci_mod_LDFLAGS, (ohci_mod_SOURCES, ohci_mod_CFLAGS, ohci_mod_LDFLAGS) (usbms_mod_SOURCES, usbms_mod_CFLAGS, usbms_mod_LDFLAGS): New variables. * disk/usbms.c: New file. * include/grub/usb.h: Likewise. * include/grub/usbtrans.h: Likewise. * include/grub/usbdesc.h: Likewise. * bus/usb/usbtrans.c: Likewise. * bus/usb/ohci.c: Likewise. * bus/usb/uhci.c: Likewise. * bus/usb/usbhub.c: Likewise. * bus/usb/usb.c: Likewise. * commands/usbtest.c: Likewise. * util/usb.c: Likewise. * include/grub/err.h (grub_err_t): Add `GRUB_ERR_IO'. * configure.ac: Test for libusb presence. * util/grub-emu.c (main) [HAVE_LIBUSB_H]: Call `grub_libusb_init'.
This commit is contained in:
parent
2b40d6bb9f
commit
d64399b562
21 changed files with 3846 additions and 16 deletions
44
ChangeLog
44
ChangeLog
|
@ -1,3 +1,47 @@
|
||||||
|
2009-02-08 Marco Gerards <marco@gnu.org>
|
||||||
|
|
||||||
|
* Makefile.in (enable_grub_emu_usb): New variable.
|
||||||
|
* conf/i386-pc.rmk (grub_emu_SOURCES): Add `disk/scsi.c'.
|
||||||
|
(grub_emu_SOURCES) [grub_emu_SOURCES]: Add `disk/usbms.c',
|
||||||
|
`util/usb.c', `bus/usb/usb.c' and `commands/usbtest.c'.
|
||||||
|
(grub_emu_LDFLAGS): Add `$(LIBUSB)'.
|
||||||
|
(pkglib_MODULES): Add `usb.mod', `uhci.mod', `ohci.mod',
|
||||||
|
`usbtest.mod' and `usbms.mod'.
|
||||||
|
(usb_mod_SOURCES, usb_mod_CFLAGS, usb_mod_LDFLAGS)
|
||||||
|
(usbtest_mod_SOURCES, usbtest_mod_CFLAGS, usbtest_mod_LDFLAGS)
|
||||||
|
(uhci_mod_SOURCES, uhci_mod_CFLAGS, uhci_mod_LDFLAGS,
|
||||||
|
(ohci_mod_SOURCES, ohci_mod_CFLAGS, ohci_mod_LDFLAGS)
|
||||||
|
(usbms_mod_SOURCES, usbms_mod_CFLAGS, usbms_mod_LDFLAGS): New
|
||||||
|
variables.
|
||||||
|
|
||||||
|
* disk/usbms.c: New file.
|
||||||
|
|
||||||
|
* include/grub/usb.h: Likewise.
|
||||||
|
|
||||||
|
* include/grub/usbtrans.h: Likewise.
|
||||||
|
|
||||||
|
* include/grub/usbdesc.h: Likewise.
|
||||||
|
|
||||||
|
* bus/usb/usbtrans.c: Likewise.
|
||||||
|
|
||||||
|
* bus/usb/ohci.c: Likewise.
|
||||||
|
|
||||||
|
* bus/usb/uhci.c: Likewise.
|
||||||
|
|
||||||
|
* bus/usb/usbhub.c: Likewise.
|
||||||
|
|
||||||
|
* bus/usb/usb.c: Likewise.
|
||||||
|
|
||||||
|
* commands/usbtest.c: Likewise.
|
||||||
|
|
||||||
|
* util/usb.c: Likewise.
|
||||||
|
|
||||||
|
* include/grub/err.h (grub_err_t): Add `GRUB_ERR_IO'.
|
||||||
|
|
||||||
|
* configure.ac: Test for libusb presence.
|
||||||
|
|
||||||
|
* util/grub-emu.c (main) [HAVE_LIBUSB_H]: Call `grub_libusb_init'.
|
||||||
|
|
||||||
2009-02-08 Vesa Jääskeläinen <chaac@nic.fi>
|
2009-02-08 Vesa Jääskeläinen <chaac@nic.fi>
|
||||||
|
|
||||||
* kern/mm.c: Add more comments.
|
* kern/mm.c: Add more comments.
|
||||||
|
|
11
DISTLIST
11
DISTLIST
|
@ -35,6 +35,11 @@ boot/i386/pc/diskboot.S
|
||||||
boot/i386/pc/lnxboot.S
|
boot/i386/pc/lnxboot.S
|
||||||
boot/i386/pc/pxeboot.S
|
boot/i386/pc/pxeboot.S
|
||||||
bus/pci.c
|
bus/pci.c
|
||||||
|
bus/usb/ohci.c
|
||||||
|
bus/usb/uhci.c
|
||||||
|
bus/usb/usb.c
|
||||||
|
bus/usb/usbhub.c
|
||||||
|
bus/usb/usbtrans.c
|
||||||
commands/blocklist.c
|
commands/blocklist.c
|
||||||
commands/boot.c
|
commands/boot.c
|
||||||
commands/cat.c
|
commands/cat.c
|
||||||
|
@ -56,6 +61,7 @@ commands/search.c
|
||||||
commands/sleep.c
|
commands/sleep.c
|
||||||
commands/terminal.c
|
commands/terminal.c
|
||||||
commands/test.c
|
commands/test.c
|
||||||
|
commands/usbtest.c
|
||||||
commands/videotest.c
|
commands/videotest.c
|
||||||
commands/i386/cpuid.c
|
commands/i386/cpuid.c
|
||||||
commands/i386/pc/halt.c
|
commands/i386/pc/halt.c
|
||||||
|
@ -95,6 +101,7 @@ disk/raid.c
|
||||||
disk/raid5_recover.c
|
disk/raid5_recover.c
|
||||||
disk/raid6_recover.c
|
disk/raid6_recover.c
|
||||||
disk/scsi.c
|
disk/scsi.c
|
||||||
|
disk/usbms.c
|
||||||
disk/efi/efidisk.c
|
disk/efi/efidisk.c
|
||||||
disk/i386/pc/biosdisk.c
|
disk/i386/pc/biosdisk.c
|
||||||
disk/ieee1275/nand.c
|
disk/ieee1275/nand.c
|
||||||
|
@ -179,6 +186,9 @@ include/grub/terminfo.h
|
||||||
include/grub/time.h
|
include/grub/time.h
|
||||||
include/grub/tparm.h
|
include/grub/tparm.h
|
||||||
include/grub/types.h
|
include/grub/types.h
|
||||||
|
include/grub/usb.h
|
||||||
|
include/grub/usbdesc.h
|
||||||
|
include/grub/usbtrans.h
|
||||||
include/grub/video.h
|
include/grub/video.h
|
||||||
include/grub/efi/api.h
|
include/grub/efi/api.h
|
||||||
include/grub/efi/chainloader.h
|
include/grub/efi/chainloader.h
|
||||||
|
@ -438,6 +448,7 @@ util/misc.c
|
||||||
util/raid.c
|
util/raid.c
|
||||||
util/resolve.c
|
util/resolve.c
|
||||||
util/update-grub_lib.in
|
util/update-grub_lib.in
|
||||||
|
util/usb.c
|
||||||
util/elf/grub-mkimage.c
|
util/elf/grub-mkimage.c
|
||||||
util/grub.d/00_header.in
|
util/grub.d/00_header.in
|
||||||
util/grub.d/10_freebsd.in
|
util/grub.d/10_freebsd.in
|
||||||
|
|
|
@ -92,6 +92,7 @@ UNIFONT_BDF = @UNIFONT_BDF@
|
||||||
|
|
||||||
# Options.
|
# Options.
|
||||||
enable_grub_emu = @enable_grub_emu@
|
enable_grub_emu = @enable_grub_emu@
|
||||||
|
enable_grub_emu_usb = @enable_grub_emu_usb@
|
||||||
enable_grub_fstest = @enable_grub_fstest@
|
enable_grub_fstest = @enable_grub_fstest@
|
||||||
enable_grub_pe2elf = @enable_grub_pe2elf@
|
enable_grub_pe2elf = @enable_grub_pe2elf@
|
||||||
enable_lzo = @enable_lzo@
|
enable_lzo = @enable_lzo@
|
||||||
|
|
608
bus/usb/ohci.c
Normal file
608
bus/usb/ohci.c
Normal file
|
@ -0,0 +1,608 @@
|
||||||
|
/* ohci.c - OHCI Support. */
|
||||||
|
/*
|
||||||
|
* GRUB -- GRand Unified Bootloader
|
||||||
|
* Copyright (C) 2008 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* GRUB 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 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* GRUB 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 GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <grub/dl.h>
|
||||||
|
#include <grub/mm.h>
|
||||||
|
#include <grub/usb.h>
|
||||||
|
#include <grub/usbtrans.h>
|
||||||
|
#include <grub/misc.h>
|
||||||
|
#include <grub/pci.h>
|
||||||
|
#include <grub/cpu/pci.h>
|
||||||
|
#include <grub/i386/io.h>
|
||||||
|
#include <grub/time.h>
|
||||||
|
|
||||||
|
struct grub_ohci_hcca
|
||||||
|
{
|
||||||
|
/* Pointers to Interrupt Endpoint Descriptors. Not used by
|
||||||
|
GRUB. */
|
||||||
|
grub_uint32_t inttable[32];
|
||||||
|
|
||||||
|
/* Current frame number. */
|
||||||
|
grub_uint16_t framenumber;
|
||||||
|
|
||||||
|
grub_uint16_t pad;
|
||||||
|
|
||||||
|
/* List of completed TDs. */
|
||||||
|
grub_uint32_t donehead;
|
||||||
|
|
||||||
|
grub_uint8_t reserved[116];
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
/* OHCI Endpoint Descriptor. */
|
||||||
|
struct grub_ohci_ed
|
||||||
|
{
|
||||||
|
grub_uint32_t target;
|
||||||
|
grub_uint32_t td_tail;
|
||||||
|
grub_uint32_t td_head;
|
||||||
|
grub_uint32_t next_ed;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
struct grub_ohci_td
|
||||||
|
{
|
||||||
|
/* Information used to construct the TOKEN packet. */
|
||||||
|
grub_uint32_t token;
|
||||||
|
|
||||||
|
grub_uint32_t buffer;
|
||||||
|
grub_uint32_t next_td;
|
||||||
|
grub_uint32_t buffer_end;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
typedef struct grub_ohci_td *grub_ohci_td_t;
|
||||||
|
typedef struct grub_ohci_ed *grub_ohci_ed_t;
|
||||||
|
|
||||||
|
struct grub_ohci
|
||||||
|
{
|
||||||
|
volatile grub_uint32_t *iobase;
|
||||||
|
volatile struct grub_ohci_hcca *hcca;
|
||||||
|
struct grub_ohci *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct grub_ohci *ohci;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
GRUB_OHCI_REG_REVISION = 0x00,
|
||||||
|
GRUB_OHCI_REG_CONTROL,
|
||||||
|
GRUB_OHCI_REG_CMDSTATUS,
|
||||||
|
GRUB_OHCI_REG_INTSTATUS,
|
||||||
|
GRUB_OHCI_REG_INTENA,
|
||||||
|
GRUB_OHCI_REG_INTDIS,
|
||||||
|
GRUB_OHCI_REG_HCCA,
|
||||||
|
GRUB_OHCI_REG_PERIODIC,
|
||||||
|
GRUB_OHCI_REG_CONTROLHEAD,
|
||||||
|
GRUB_OHCI_REG_CONTROLCURR,
|
||||||
|
GRUB_OHCI_REG_BULKHEAD,
|
||||||
|
GRUB_OHCI_REG_BULKCURR,
|
||||||
|
GRUB_OHCI_REG_DONEHEAD,
|
||||||
|
GRUB_OHCI_REG_FRAME_INTERVAL,
|
||||||
|
GRUB_OHCI_REG_RHUBA = 18,
|
||||||
|
GRUB_OHCI_REG_RHUBPORT = 21
|
||||||
|
} grub_ohci_reg_t;
|
||||||
|
|
||||||
|
static grub_uint32_t
|
||||||
|
grub_ohci_readreg32 (struct grub_ohci *o, grub_ohci_reg_t reg)
|
||||||
|
{
|
||||||
|
return grub_le_to_cpu32 (*(o->iobase + reg));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
grub_ohci_writereg32 (struct grub_ohci *o,
|
||||||
|
grub_ohci_reg_t reg, grub_uint32_t val)
|
||||||
|
{
|
||||||
|
*(o->iobase + reg) = grub_cpu_to_le32 (val);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Iterate over all PCI devices. Determine if a device is an OHCI
|
||||||
|
controller. If this is the case, initialize it. */
|
||||||
|
static int grub_ohci_pci_iter (int bus, int device, int func,
|
||||||
|
grub_pci_id_t pciid __attribute__((unused)))
|
||||||
|
{
|
||||||
|
grub_uint32_t class;
|
||||||
|
grub_uint32_t subclass;
|
||||||
|
int interf;
|
||||||
|
grub_uint32_t base;
|
||||||
|
grub_pci_address_t addr;
|
||||||
|
struct grub_ohci *o;
|
||||||
|
grub_uint32_t revision;
|
||||||
|
grub_uint32_t frame_interval;
|
||||||
|
|
||||||
|
addr = grub_pci_make_address (bus, device, func, 2);
|
||||||
|
class = grub_pci_read (addr);
|
||||||
|
addr = grub_pci_make_address (bus, device, func, 2);
|
||||||
|
class = grub_pci_read (addr);
|
||||||
|
|
||||||
|
interf = class & 0xFF;
|
||||||
|
subclass = (class >> 16) & 0xFF;
|
||||||
|
class >>= 24;
|
||||||
|
|
||||||
|
/* If this is not an OHCI controller, just return. */
|
||||||
|
if (class != 0x0c || subclass != 0x03)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Determine IO base address. */
|
||||||
|
addr = grub_pci_make_address (bus, device, func, 4);
|
||||||
|
base = grub_pci_read (addr);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/* Stop if there is no IO space base address defined. */
|
||||||
|
if (! (base & 1))
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Allocate memory for the controller and register it. */
|
||||||
|
o = grub_malloc (sizeof (*o));
|
||||||
|
if (! o)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
/* Link in the OHCI. */
|
||||||
|
o->next = ohci;
|
||||||
|
ohci = o;
|
||||||
|
o->iobase = (grub_uint32_t *) base;
|
||||||
|
|
||||||
|
/* Reserve memory for the HCCA. */
|
||||||
|
o->hcca = (struct grub_ohci_hcca *) grub_memalign (256, 256);
|
||||||
|
|
||||||
|
/* Check if the OHCI revision is actually 1.0 as supported. */
|
||||||
|
revision = grub_ohci_readreg32 (o, GRUB_OHCI_REG_REVISION);
|
||||||
|
grub_dprintf ("ohci", "OHCI revision=0x%02x\n", revision & 0xFF);
|
||||||
|
if ((revision & 0xFF) != 0x10)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
/* Backup the frame interval register. */
|
||||||
|
frame_interval = grub_ohci_readreg32 (o, GRUB_OHCI_REG_FRAME_INTERVAL);
|
||||||
|
|
||||||
|
/* Suspend the OHCI by issuing a reset. */
|
||||||
|
grub_ohci_writereg32 (o, GRUB_OHCI_REG_CMDSTATUS, 1); /* XXX: Magic.
|
||||||
|
*/
|
||||||
|
grub_millisleep (1);
|
||||||
|
grub_dprintf ("ohci", "OHCI reset\n");
|
||||||
|
|
||||||
|
/* Restore the frame interval register. */
|
||||||
|
grub_ohci_writereg32 (o, GRUB_OHCI_REG_FRAME_INTERVAL, frame_interval);
|
||||||
|
|
||||||
|
/* Setup the HCCA. */
|
||||||
|
grub_ohci_writereg32 (o, GRUB_OHCI_REG_HCCA, (grub_uint32_t) o->hcca);
|
||||||
|
grub_dprintf ("ohci", "OHCI HCCA\n");
|
||||||
|
|
||||||
|
/* Enable the OHCI. */
|
||||||
|
grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROL,
|
||||||
|
(2 << 6));
|
||||||
|
grub_dprintf ("ohci", "OHCI enable: 0x%02x\n",
|
||||||
|
(grub_ohci_readreg32 (o, GRUB_OHCI_REG_CONTROL) >> 6) & 3);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
if (o)
|
||||||
|
grub_free ((void *) o->hcca);
|
||||||
|
grub_free (o);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
grub_ohci_inithw (void)
|
||||||
|
{
|
||||||
|
grub_pci_iterate (grub_ohci_pci_iter);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
grub_ohci_iterate (int (*hook) (grub_usb_controller_t dev))
|
||||||
|
{
|
||||||
|
struct grub_ohci *o;
|
||||||
|
struct grub_usb_controller dev;
|
||||||
|
|
||||||
|
for (o = ohci; o; o = o->next)
|
||||||
|
{
|
||||||
|
dev.data = o;
|
||||||
|
if (hook (&dev))
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
grub_ohci_transaction (grub_ohci_td_t td,
|
||||||
|
grub_transfer_type_t type, unsigned int toggle,
|
||||||
|
grub_size_t size, char *data)
|
||||||
|
{
|
||||||
|
grub_uint32_t token;
|
||||||
|
grub_uint32_t buffer;
|
||||||
|
grub_uint32_t buffer_end;
|
||||||
|
|
||||||
|
grub_dprintf ("ohci", "OHCI transaction td=0x%02x type=%d, toggle=%d, size=%d\n",
|
||||||
|
td, type, toggle, size);
|
||||||
|
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case GRUB_USB_TRANSFER_TYPE_SETUP:
|
||||||
|
token = 0 << 19;
|
||||||
|
break;
|
||||||
|
case GRUB_USB_TRANSFER_TYPE_IN:
|
||||||
|
token = 2 << 19;
|
||||||
|
break;
|
||||||
|
case GRUB_USB_TRANSFER_TYPE_OUT:
|
||||||
|
token = 1 << 19;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
token = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Generate no interrupts. */
|
||||||
|
token |= 7 << 21;
|
||||||
|
|
||||||
|
/* Set the token. */
|
||||||
|
token |= toggle << 24;
|
||||||
|
token |= 1 << 25;
|
||||||
|
|
||||||
|
buffer = (grub_uint32_t) data;
|
||||||
|
buffer_end = buffer + size - 1;
|
||||||
|
|
||||||
|
td->token = grub_cpu_to_le32 (token);
|
||||||
|
td->buffer = grub_cpu_to_le32 (buffer);
|
||||||
|
td->next_td = 0;
|
||||||
|
td->buffer_end = grub_cpu_to_le32 (buffer_end);
|
||||||
|
}
|
||||||
|
|
||||||
|
static grub_usb_err_t
|
||||||
|
grub_ohci_transfer (grub_usb_controller_t dev,
|
||||||
|
grub_usb_transfer_t transfer)
|
||||||
|
{
|
||||||
|
struct grub_ohci *o = (struct grub_ohci *) dev->data;
|
||||||
|
grub_ohci_ed_t ed;
|
||||||
|
grub_ohci_td_t td_list;
|
||||||
|
grub_uint32_t target;
|
||||||
|
grub_uint32_t td_tail;
|
||||||
|
grub_uint32_t td_head;
|
||||||
|
grub_uint32_t status;
|
||||||
|
grub_uint32_t control;
|
||||||
|
grub_usb_err_t err;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* Allocate an Endpoint Descriptor. */
|
||||||
|
ed = grub_memalign (16, sizeof (*ed));
|
||||||
|
if (! ed)
|
||||||
|
return GRUB_USB_ERR_INTERNAL;
|
||||||
|
|
||||||
|
td_list = grub_memalign (16, sizeof (*td_list) * (transfer->transcnt + 1));
|
||||||
|
if (! td_list)
|
||||||
|
{
|
||||||
|
grub_free ((void *) ed);
|
||||||
|
return GRUB_USB_ERR_INTERNAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
grub_dprintf ("ohci", "alloc=0x%08x\n", td_list);
|
||||||
|
|
||||||
|
/* Setup all Transfer Descriptors. */
|
||||||
|
for (i = 0; i < transfer->transcnt; i++)
|
||||||
|
{
|
||||||
|
grub_usb_transaction_t tr = &transfer->transactions[i];
|
||||||
|
|
||||||
|
grub_ohci_transaction (&td_list[i], tr->pid, tr->toggle,
|
||||||
|
tr->size, tr->data);
|
||||||
|
|
||||||
|
td_list[i].next_td = grub_cpu_to_le32 (&td_list[i + 1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Setup the Endpoint Descriptor. */
|
||||||
|
|
||||||
|
/* Set the device address. */
|
||||||
|
target = transfer->devaddr;
|
||||||
|
|
||||||
|
/* Set the endpoint. */
|
||||||
|
target |= transfer->endpoint << 7;
|
||||||
|
|
||||||
|
/* Set the device speed. */
|
||||||
|
target |= (transfer->dev->speed == GRUB_USB_SPEED_LOW) << 13;
|
||||||
|
|
||||||
|
/* Set the maximum packet size. */
|
||||||
|
target |= transfer->max << 16;
|
||||||
|
|
||||||
|
td_head = (grub_uint32_t) td_list;
|
||||||
|
|
||||||
|
td_tail = (grub_uint32_t) &td_list[transfer->transcnt];
|
||||||
|
|
||||||
|
ed->target = grub_cpu_to_le32 (target);
|
||||||
|
ed->td_head = grub_cpu_to_le32 (td_head);
|
||||||
|
ed->td_tail = grub_cpu_to_le32 (td_tail);
|
||||||
|
ed->next_ed = grub_cpu_to_le32 (0);
|
||||||
|
|
||||||
|
grub_dprintf ("ohci", "program OHCI\n");
|
||||||
|
|
||||||
|
/* Program the OHCI to actually transfer. */
|
||||||
|
switch (transfer->type)
|
||||||
|
{
|
||||||
|
case GRUB_USB_TRANSACTION_TYPE_BULK:
|
||||||
|
{
|
||||||
|
grub_dprintf ("ohci", "add to bulk list\n");
|
||||||
|
|
||||||
|
status = grub_ohci_readreg32 (o, GRUB_OHCI_REG_CMDSTATUS);
|
||||||
|
control = grub_ohci_readreg32 (o, GRUB_OHCI_REG_CONTROL);
|
||||||
|
|
||||||
|
/* Disable the Control and Bulk lists. */
|
||||||
|
control &= ~(3 << 4);
|
||||||
|
grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROL, control);
|
||||||
|
|
||||||
|
/* Clear BulkListFilled. */
|
||||||
|
status &= ~(1 << 2);
|
||||||
|
grub_ohci_writereg32 (o, GRUB_OHCI_REG_CMDSTATUS, status);
|
||||||
|
|
||||||
|
grub_ohci_writereg32 (o, GRUB_OHCI_REG_BULKHEAD, (grub_uint32_t) ed);
|
||||||
|
|
||||||
|
/* Enable the Bulk list. */
|
||||||
|
control |= 1 << 5;
|
||||||
|
grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROL, control);
|
||||||
|
|
||||||
|
/* Set BulkListFilled. */
|
||||||
|
status |= 1 << 2;
|
||||||
|
grub_ohci_writereg32 (o, GRUB_OHCI_REG_CMDSTATUS, status);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case GRUB_USB_TRANSACTION_TYPE_CONTROL:
|
||||||
|
{
|
||||||
|
grub_dprintf ("ohci", "add to control list\n");
|
||||||
|
status = grub_ohci_readreg32 (o, GRUB_OHCI_REG_CMDSTATUS);
|
||||||
|
control = grub_ohci_readreg32 (o, GRUB_OHCI_REG_CONTROL);
|
||||||
|
|
||||||
|
/* Disable the Control and Bulk lists. */
|
||||||
|
control &= ~(3 << 4);
|
||||||
|
grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROL, control);
|
||||||
|
|
||||||
|
/* Clear ControlListFilled. */
|
||||||
|
status &= ~(1 << 1);
|
||||||
|
grub_ohci_writereg32 (o, GRUB_OHCI_REG_CMDSTATUS, status);
|
||||||
|
|
||||||
|
grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROLHEAD,
|
||||||
|
(grub_uint32_t) ed);
|
||||||
|
grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROLHEAD+1,
|
||||||
|
(grub_uint32_t) ed);
|
||||||
|
|
||||||
|
/* Enable the Control list. */
|
||||||
|
control |= 1 << 4;
|
||||||
|
grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROL, control);
|
||||||
|
|
||||||
|
/* Set ControlListFilled. */
|
||||||
|
status |= 1 << 1;
|
||||||
|
grub_ohci_writereg32 (o, GRUB_OHCI_REG_CMDSTATUS, status);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
grub_dprintf ("ohci", "wait for completion\n");
|
||||||
|
grub_dprintf ("ohci", "control=0x%02x status=0x%02x\n",
|
||||||
|
grub_ohci_readreg32 (o, GRUB_OHCI_REG_CONTROL),
|
||||||
|
grub_ohci_readreg32 (o, GRUB_OHCI_REG_CMDSTATUS));
|
||||||
|
|
||||||
|
/* Wait until the transfer is completed or STALLs. */
|
||||||
|
while ((ed->td_head & ~0xf) != (ed->td_tail & ~0xf))
|
||||||
|
{
|
||||||
|
grub_cpu_idle ();
|
||||||
|
|
||||||
|
grub_dprintf ("ohci", "head=0x%02x tail=0x%02x\n", ed->td_head, ed->td_tail);
|
||||||
|
|
||||||
|
/* Detected a STALL. */
|
||||||
|
if (ed->td_head & 1)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
grub_dprintf ("ohci", "complete\n");
|
||||||
|
|
||||||
|
/* if (ed->td_head & 1) */
|
||||||
|
/* err = GRUB_USB_ERR_STALL; */
|
||||||
|
/* else if (ed->td */
|
||||||
|
|
||||||
|
|
||||||
|
if (ed->td_head & 1)
|
||||||
|
{
|
||||||
|
grub_uint8_t errcode;
|
||||||
|
grub_ohci_td_t tderr;
|
||||||
|
|
||||||
|
tderr = (grub_ohci_td_t) grub_ohci_readreg32 (o,
|
||||||
|
GRUB_OHCI_REG_DONEHEAD);
|
||||||
|
errcode = tderr->token >> 28;
|
||||||
|
|
||||||
|
switch (errcode)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
/* XXX: Should not happen! */
|
||||||
|
grub_error (GRUB_ERR_IO, "OHCI without reporting the reason");
|
||||||
|
err = GRUB_USB_ERR_INTERNAL;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
/* XXX: CRC error. */
|
||||||
|
err = GRUB_USB_ERR_TIMEOUT;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
err = GRUB_USB_ERR_BITSTUFF;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
/* XXX: Data Toggle error. */
|
||||||
|
err = GRUB_USB_ERR_DATA;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 4:
|
||||||
|
err = GRUB_USB_ERR_STALL;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 5:
|
||||||
|
/* XXX: Not responding. */
|
||||||
|
err = GRUB_USB_ERR_TIMEOUT;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 6:
|
||||||
|
/* XXX: PID Check bits failed. */
|
||||||
|
err = GRUB_USB_ERR_BABBLE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 7:
|
||||||
|
/* XXX: PID unexpected failed. */
|
||||||
|
err = GRUB_USB_ERR_BABBLE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 8:
|
||||||
|
/* XXX: Data overrun error. */
|
||||||
|
err = GRUB_USB_ERR_DATA;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 9:
|
||||||
|
/* XXX: Data underrun error. */
|
||||||
|
err = GRUB_USB_ERR_DATA;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 10:
|
||||||
|
/* XXX: Reserved. */
|
||||||
|
err = GRUB_USB_ERR_NAK;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 11:
|
||||||
|
/* XXX: Reserved. */
|
||||||
|
err = GRUB_USB_ERR_NAK;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 12:
|
||||||
|
/* XXX: Buffer overrun. */
|
||||||
|
err = GRUB_USB_ERR_DATA;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 13:
|
||||||
|
/* XXX: Buffer underrun. */
|
||||||
|
err = GRUB_USB_ERR_DATA;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
err = GRUB_USB_ERR_NAK;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
err = GRUB_USB_ERR_NONE;
|
||||||
|
|
||||||
|
/* Disable the Control and Bulk lists. */
|
||||||
|
control = grub_ohci_readreg32 (o, GRUB_OHCI_REG_CONTROL);
|
||||||
|
control &= ~(3 << 4);
|
||||||
|
grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROL, control);
|
||||||
|
|
||||||
|
/* Clear BulkListFilled and ControlListFilled. */
|
||||||
|
status = grub_ohci_readreg32 (o, GRUB_OHCI_REG_CMDSTATUS);
|
||||||
|
status &= ~((1 << 2) | (1 << 3));
|
||||||
|
grub_ohci_writereg32 (o, GRUB_OHCI_REG_CMDSTATUS, status);
|
||||||
|
|
||||||
|
/* XXX */
|
||||||
|
grub_free (td_list);
|
||||||
|
grub_free (ed);
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static grub_err_t
|
||||||
|
grub_ohci_portstatus (grub_usb_controller_t dev,
|
||||||
|
unsigned int port, unsigned int enable)
|
||||||
|
{
|
||||||
|
struct grub_ohci *o = (struct grub_ohci *) dev->data;
|
||||||
|
grub_uint32_t status;
|
||||||
|
|
||||||
|
/* Reset the port. */
|
||||||
|
status = grub_ohci_readreg32 (o, GRUB_OHCI_REG_RHUBPORT + port);
|
||||||
|
status |= (1 << 4); /* XXX: Magic. */
|
||||||
|
grub_ohci_writereg32 (o, GRUB_OHCI_REG_RHUBPORT + port, status);
|
||||||
|
grub_millisleep (100);
|
||||||
|
|
||||||
|
/* End the reset signaling. */
|
||||||
|
status = grub_ohci_readreg32 (o, GRUB_OHCI_REG_RHUBPORT + port);
|
||||||
|
status |= (1 << 20); /* XXX: Magic. */
|
||||||
|
grub_ohci_writereg32 (o, GRUB_OHCI_REG_RHUBPORT + port, status);
|
||||||
|
grub_millisleep (10);
|
||||||
|
|
||||||
|
/* Enable the port. */
|
||||||
|
status = grub_ohci_readreg32 (o, GRUB_OHCI_REG_RHUBPORT + port);
|
||||||
|
status |= (enable << 1); /* XXX: Magic. */
|
||||||
|
grub_ohci_writereg32 (o, GRUB_OHCI_REG_RHUBPORT + port, status);
|
||||||
|
|
||||||
|
status = grub_ohci_readreg32 (o, GRUB_OHCI_REG_RHUBPORT + port);
|
||||||
|
grub_dprintf ("ohci", "portstatus=0x%02x\n", status);
|
||||||
|
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static grub_usb_speed_t
|
||||||
|
grub_ohci_detect_dev (grub_usb_controller_t dev, int port)
|
||||||
|
{
|
||||||
|
struct grub_ohci *o = (struct grub_ohci *) dev->data;
|
||||||
|
grub_uint32_t status;
|
||||||
|
|
||||||
|
status = grub_ohci_readreg32 (o, GRUB_OHCI_REG_RHUBPORT + port);
|
||||||
|
|
||||||
|
grub_dprintf ("ohci", "detect_dev status=0x%02x\n", status);
|
||||||
|
|
||||||
|
if (! (status & 1))
|
||||||
|
return GRUB_USB_SPEED_NONE;
|
||||||
|
else if (status & (1 << 9))
|
||||||
|
return GRUB_USB_SPEED_LOW;
|
||||||
|
else
|
||||||
|
return GRUB_USB_SPEED_FULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
grub_ohci_hubports (grub_usb_controller_t dev)
|
||||||
|
{
|
||||||
|
struct grub_ohci *o = (struct grub_ohci *) dev->data;
|
||||||
|
grub_uint32_t portinfo;
|
||||||
|
|
||||||
|
portinfo = grub_ohci_readreg32 (o, GRUB_OHCI_REG_RHUBA);
|
||||||
|
|
||||||
|
grub_dprintf ("ohci", "root hub ports=%d\n", portinfo & 0xFF);
|
||||||
|
|
||||||
|
/* The root hub has exactly two ports. */
|
||||||
|
return portinfo & 0xFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static struct grub_usb_controller_dev usb_controller =
|
||||||
|
{
|
||||||
|
.name = "ohci",
|
||||||
|
.iterate = grub_ohci_iterate,
|
||||||
|
.transfer = grub_ohci_transfer,
|
||||||
|
.hubports = grub_ohci_hubports,
|
||||||
|
.portstatus = grub_ohci_portstatus,
|
||||||
|
.detect_dev = grub_ohci_detect_dev
|
||||||
|
};
|
||||||
|
|
||||||
|
GRUB_MOD_INIT(ohci)
|
||||||
|
{
|
||||||
|
grub_ohci_inithw ();
|
||||||
|
grub_usb_controller_dev_register (&usb_controller);
|
||||||
|
}
|
||||||
|
|
||||||
|
GRUB_MOD_FINI(ohci)
|
||||||
|
{
|
||||||
|
grub_usb_controller_dev_unregister (&usb_controller);
|
||||||
|
}
|
675
bus/usb/uhci.c
Normal file
675
bus/usb/uhci.c
Normal file
|
@ -0,0 +1,675 @@
|
||||||
|
/* uhci.c - UHCI Support. */
|
||||||
|
/*
|
||||||
|
* GRUB -- GRand Unified Bootloader
|
||||||
|
* Copyright (C) 2008 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* GRUB 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 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* GRUB 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 GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <grub/dl.h>
|
||||||
|
#include <grub/mm.h>
|
||||||
|
#include <grub/misc.h>
|
||||||
|
#include <grub/usb.h>
|
||||||
|
#include <grub/usbtrans.h>
|
||||||
|
#include <grub/pci.h>
|
||||||
|
#include <grub/cpu/pci.h>
|
||||||
|
#include <grub/i386/io.h>
|
||||||
|
#include <grub/time.h>
|
||||||
|
|
||||||
|
#define GRUB_UHCI_IOMASK (0x7FF << 5)
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
GRUB_UHCI_REG_USBCMD = 0x00,
|
||||||
|
GRUB_UHCI_REG_FLBASEADD = 0x08,
|
||||||
|
GRUB_UHCI_REG_PORTSC1 = 0x10,
|
||||||
|
GRUB_UHCI_REG_PORTSC2 = 0x12
|
||||||
|
} grub_uhci_reg_t;
|
||||||
|
|
||||||
|
#define GRUB_UHCI_LINK_TERMINATE 1
|
||||||
|
#define GRUB_UHCI_LINK_QUEUE_HEAD 2
|
||||||
|
|
||||||
|
|
||||||
|
/* UHCI Queue Head. */
|
||||||
|
struct grub_uhci_qh
|
||||||
|
{
|
||||||
|
/* Queue head link pointer which points to the next queue head. */
|
||||||
|
grub_uint32_t linkptr;
|
||||||
|
|
||||||
|
/* Queue element link pointer which points to the first data object
|
||||||
|
within the queue. */
|
||||||
|
grub_uint32_t elinkptr;
|
||||||
|
|
||||||
|
/* Queue heads are aligned on 16 bytes, pad so a queue head is 16
|
||||||
|
bytes so we can store many in a 4K page. */
|
||||||
|
grub_uint8_t pad[8];
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
/* UHCI Tranfer Descriptor. */
|
||||||
|
struct grub_uhci_td
|
||||||
|
{
|
||||||
|
/* Pointer to the next TD in the list. */
|
||||||
|
grub_uint32_t linkptr;
|
||||||
|
|
||||||
|
/* Control and status bits. */
|
||||||
|
grub_uint32_t ctrl_status;
|
||||||
|
|
||||||
|
/* All information required to transfer the Token packet. */
|
||||||
|
grub_uint32_t token;
|
||||||
|
|
||||||
|
/* A pointer to the data buffer, UHCI requires this pointer to be 32
|
||||||
|
bits. */
|
||||||
|
grub_uint32_t buffer;
|
||||||
|
|
||||||
|
/* Another linkptr that is not overwritten by the Host Controller.
|
||||||
|
This is GRUB specific. */
|
||||||
|
grub_uint32_t linkptr2;
|
||||||
|
|
||||||
|
/* 3 additional 32 bits words reserved for the Host Controller Driver. */
|
||||||
|
grub_uint32_t data[3];
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
typedef volatile struct grub_uhci_td *grub_uhci_td_t;
|
||||||
|
typedef volatile struct grub_uhci_qh *grub_uhci_qh_t;
|
||||||
|
|
||||||
|
struct grub_uhci
|
||||||
|
{
|
||||||
|
int iobase;
|
||||||
|
grub_uint32_t *framelist;
|
||||||
|
|
||||||
|
/* 256 Queue Heads. */
|
||||||
|
grub_uhci_qh_t qh;
|
||||||
|
|
||||||
|
/* 256 Transfer Descriptors. */
|
||||||
|
grub_uhci_td_t td;
|
||||||
|
|
||||||
|
/* Free Transfer Descriptors. */
|
||||||
|
grub_uhci_td_t tdfree;
|
||||||
|
|
||||||
|
struct grub_uhci *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct grub_uhci *uhci;
|
||||||
|
|
||||||
|
static grub_uint16_t
|
||||||
|
grub_uhci_readreg16 (struct grub_uhci *u, grub_uhci_reg_t reg)
|
||||||
|
{
|
||||||
|
return grub_inw (u->iobase + reg);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
static grub_uint32_t
|
||||||
|
grub_uhci_readreg32 (struct grub_uhci *u, grub_uhci_reg_t reg)
|
||||||
|
{
|
||||||
|
return grub_inl (u->iobase + reg);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void
|
||||||
|
grub_uhci_writereg16 (struct grub_uhci *u,
|
||||||
|
grub_uhci_reg_t reg, grub_uint16_t val)
|
||||||
|
{
|
||||||
|
grub_outw (val, u->iobase + reg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
grub_uhci_writereg32 (struct grub_uhci *u,
|
||||||
|
grub_uhci_reg_t reg, grub_uint32_t val)
|
||||||
|
{
|
||||||
|
grub_outl (val, u->iobase + reg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static grub_err_t
|
||||||
|
grub_uhci_portstatus (grub_usb_controller_t dev,
|
||||||
|
unsigned int port, unsigned int enable);
|
||||||
|
|
||||||
|
|
||||||
|
/* Iterate over all PCI devices. Determine if a device is an UHCI
|
||||||
|
controller. If this is the case, initialize it. */
|
||||||
|
static int grub_uhci_pci_iter (int bus, int device, int func,
|
||||||
|
grub_pci_id_t pciid __attribute__((unused)))
|
||||||
|
{
|
||||||
|
grub_uint32_t class;
|
||||||
|
grub_uint32_t subclass;
|
||||||
|
grub_uint32_t base;
|
||||||
|
grub_uint32_t fp;
|
||||||
|
grub_pci_address_t addr;
|
||||||
|
struct grub_uhci *u;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
addr = grub_pci_make_address (bus, device, func, 2);
|
||||||
|
class = grub_pci_read (addr);
|
||||||
|
addr = grub_pci_make_address (bus, device, func, 2);
|
||||||
|
class = grub_pci_read (addr);
|
||||||
|
|
||||||
|
subclass = (class >> 16) & 0xFF;
|
||||||
|
class >>= 24;
|
||||||
|
|
||||||
|
/* If this is not an UHCI controller, just return. */
|
||||||
|
if (class != 0x0c || subclass != 0x03)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Determine IO base address. */
|
||||||
|
addr = grub_pci_make_address (bus, device, func, 8);
|
||||||
|
base = grub_pci_read (addr);
|
||||||
|
/* Stop if there is no IO space base address defined. */
|
||||||
|
if (! (base & 1))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Allocate memory for the controller and register it. */
|
||||||
|
u = grub_malloc (sizeof (*u));
|
||||||
|
if (! u)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
u->next = uhci;
|
||||||
|
uhci = u;
|
||||||
|
u->iobase = base & GRUB_UHCI_IOMASK;
|
||||||
|
u->framelist = 0;
|
||||||
|
u->qh = 0;
|
||||||
|
u->td = 0;
|
||||||
|
grub_dprintf ("uhci", "class=0x%02x 0x%02x base=0x%x\n",
|
||||||
|
class, subclass, u->iobase);
|
||||||
|
|
||||||
|
/* Reserve a page for the frame list. */
|
||||||
|
u->framelist = grub_memalign (4096, 4096);
|
||||||
|
if (! u->framelist)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
/* The framelist pointer of UHCI is only 32 bits, make sure this
|
||||||
|
code works on on 64 bits architectures. */
|
||||||
|
#if GRUB_CPU_SIZEOF_VOID_P == 8
|
||||||
|
if ((grub_uint64_t) u->framelist >> 32)
|
||||||
|
{
|
||||||
|
grub_error (GRUB_ERR_OUT_OF_MEMORY,
|
||||||
|
"allocated frame list memory not <4GB");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* The QH pointer of UHCI is only 32 bits, make sure this
|
||||||
|
code works on on 64 bits architectures. */
|
||||||
|
u->qh = (grub_uhci_qh_t) grub_memalign (4096, 4096);
|
||||||
|
if (! u->qh)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
#if GRUB_CPU_SIZEOF_VOID_P == 8
|
||||||
|
if ((grub_uint64_t) u->qh >> 32)
|
||||||
|
{
|
||||||
|
grub_error (GRUB_ERR_OUT_OF_MEMORY, "allocated QH memory not <4GB");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* The TD pointer of UHCI is only 32 bits, make sure this
|
||||||
|
code works on on 64 bits architectures. */
|
||||||
|
u->td = (grub_uhci_td_t) grub_memalign (4096, 4096*2);
|
||||||
|
if (! u->td)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
#if GRUB_CPU_SIZEOF_VOID_P == 8
|
||||||
|
if ((grub_uint64_t) u->td >> 32)
|
||||||
|
{
|
||||||
|
grub_error (GRUB_ERR_OUT_OF_MEMORY, "allocated TD memory not <4GB");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Link all Transfer Descriptors in a list of available Transfer
|
||||||
|
Descriptors. */
|
||||||
|
for (i = 0; i < 256; i++)
|
||||||
|
u->td[i].linkptr = (grub_uint32_t) &u->td[i + 1];
|
||||||
|
u->td[255 - 1].linkptr = 0;
|
||||||
|
u->tdfree = u->td;
|
||||||
|
|
||||||
|
/* Make sure UHCI is disabled! */
|
||||||
|
grub_uhci_writereg16 (u, GRUB_UHCI_REG_USBCMD, 0);
|
||||||
|
|
||||||
|
/* Setup the frame list pointers. Since no isochronous transfers
|
||||||
|
are and will be supported, they all point to the (same!) queue
|
||||||
|
head. */
|
||||||
|
fp = (grub_uint32_t) u->qh & (~15);
|
||||||
|
/* Mark this as a queue head. */
|
||||||
|
fp |= 2;
|
||||||
|
for (i = 0; i < 1024; i++)
|
||||||
|
u->framelist[i] = fp;
|
||||||
|
/* Program the framelist address into the UHCI controller. */
|
||||||
|
grub_uhci_writereg32 (u, GRUB_UHCI_REG_FLBASEADD,
|
||||||
|
(grub_uint32_t) u->framelist);
|
||||||
|
|
||||||
|
/* Make the Queue Heads point to eachother. */
|
||||||
|
for (i = 0; i < 256; i++)
|
||||||
|
{
|
||||||
|
/* Point to the next QH. */
|
||||||
|
u->qh[i].linkptr = (grub_uint32_t) (&u->qh[i + 1]) & (~15);
|
||||||
|
|
||||||
|
/* This is a QH. */
|
||||||
|
u->qh[i].linkptr |= GRUB_UHCI_LINK_QUEUE_HEAD;
|
||||||
|
|
||||||
|
/* For the moment, do not point to a Transfer Descriptor. These
|
||||||
|
are set at transfer time, so just terminate it. */
|
||||||
|
u->qh[i].elinkptr = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The last Queue Head should terminate. 256 are too many QHs so
|
||||||
|
just use 50. */
|
||||||
|
u->qh[50 - 1].linkptr = 1;
|
||||||
|
|
||||||
|
/* Enable UHCI again. */
|
||||||
|
grub_uhci_writereg16 (u, GRUB_UHCI_REG_USBCMD, 1 | (1 << 7));
|
||||||
|
|
||||||
|
/* UHCI is initialized and ready for transfers. */
|
||||||
|
grub_dprintf ("uhci", "UHCI initialized\n");
|
||||||
|
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < 10; i++)
|
||||||
|
{
|
||||||
|
grub_uint16_t frnum;
|
||||||
|
|
||||||
|
frnum = grub_uhci_readreg16 (u, 6);
|
||||||
|
grub_dprintf ("uhci", "Framenum=%d\n", frnum);
|
||||||
|
grub_millisleep (100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
if (u)
|
||||||
|
{
|
||||||
|
grub_free ((void *) u->qh);
|
||||||
|
grub_free (u->framelist);
|
||||||
|
}
|
||||||
|
grub_free (u);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
grub_uhci_inithw (void)
|
||||||
|
{
|
||||||
|
grub_pci_iterate (grub_uhci_pci_iter);
|
||||||
|
}
|
||||||
|
|
||||||
|
static grub_uhci_td_t
|
||||||
|
grub_alloc_td (struct grub_uhci *u)
|
||||||
|
{
|
||||||
|
grub_uhci_td_t ret;
|
||||||
|
|
||||||
|
/* Check if there is a Transfer Descriptor available. */
|
||||||
|
if (! u->tdfree)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
ret = u->tdfree;
|
||||||
|
u->tdfree = (grub_uhci_td_t) u->tdfree->linkptr;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
grub_free_td (struct grub_uhci *u, grub_uhci_td_t td)
|
||||||
|
{
|
||||||
|
td->linkptr = (grub_uint32_t) u->tdfree;
|
||||||
|
u->tdfree = td;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
grub_free_queue (struct grub_uhci *u, grub_uhci_td_t td)
|
||||||
|
{
|
||||||
|
/* Free the TDs in this queue. */
|
||||||
|
while (td)
|
||||||
|
{
|
||||||
|
grub_uhci_td_t tdprev;
|
||||||
|
|
||||||
|
/* Unlink the queue. */
|
||||||
|
tdprev = td;
|
||||||
|
td = (grub_uhci_td_t) td->linkptr2;
|
||||||
|
|
||||||
|
/* Free the TD. */
|
||||||
|
grub_free_td (u, tdprev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static grub_uhci_qh_t
|
||||||
|
grub_alloc_qh (struct grub_uhci *u,
|
||||||
|
grub_transaction_type_t tr __attribute__((unused)))
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
grub_uhci_qh_t qh;
|
||||||
|
|
||||||
|
/* Look for a Queue Head for this transfer. Skip the first QH if
|
||||||
|
this is a Interrupt Transfer. */
|
||||||
|
#if 0
|
||||||
|
if (tr == GRUB_USB_TRANSACTION_TYPE_INTERRUPT)
|
||||||
|
i = 0;
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
i = 1;
|
||||||
|
|
||||||
|
for (; i < 255; i++)
|
||||||
|
{
|
||||||
|
if (u->qh[i].elinkptr & 1)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
qh = &u->qh[i];
|
||||||
|
if (! (qh->elinkptr & 1))
|
||||||
|
{
|
||||||
|
grub_error (GRUB_ERR_OUT_OF_MEMORY,
|
||||||
|
"no free queue heads available");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return qh;
|
||||||
|
}
|
||||||
|
|
||||||
|
static grub_uhci_td_t
|
||||||
|
grub_uhci_transaction (struct grub_uhci *u, unsigned int endp,
|
||||||
|
grub_transfer_type_t type, unsigned int addr,
|
||||||
|
unsigned int toggle, grub_size_t size,
|
||||||
|
char *data)
|
||||||
|
{
|
||||||
|
grub_uhci_td_t td;
|
||||||
|
static const unsigned int tf[] = { 0x69, 0xE1, 0x2D };
|
||||||
|
|
||||||
|
/* XXX: Check if data is <4GB. If it isn't, just copy stuff around.
|
||||||
|
This is only relevant for 64 bits architectures. */
|
||||||
|
|
||||||
|
/* Grab a free Transfer Descriptor and initialize it. */
|
||||||
|
td = grub_alloc_td (u);
|
||||||
|
if (! td)
|
||||||
|
{
|
||||||
|
grub_error (GRUB_ERR_OUT_OF_MEMORY,
|
||||||
|
"no transfer descriptors available for UHCI transfer");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
grub_dprintf ("uhci",
|
||||||
|
"transaction: endp=%d, type=%d, addr=%d, toggle=%d, size=%d data=%p td=%p\n",
|
||||||
|
endp, type, addr, toggle, size, data, td);
|
||||||
|
|
||||||
|
/* Don't point to any TD, just terminate. */
|
||||||
|
td->linkptr = 1;
|
||||||
|
|
||||||
|
/* Active! Only retry a transfer 3 times. */
|
||||||
|
td->ctrl_status = (1 << 23) | (3 << 27);
|
||||||
|
|
||||||
|
/* If zero bytes are transmitted, size is 0x7FF. Otherwise size is
|
||||||
|
size-1. */
|
||||||
|
if (size == 0)
|
||||||
|
size = 0x7FF;
|
||||||
|
else
|
||||||
|
size = size - 1;
|
||||||
|
|
||||||
|
/* Setup whatever is required for the token packet. */
|
||||||
|
td->token = ((size << 21) | (toggle << 19) | (endp << 15)
|
||||||
|
| (addr << 8) | tf[type]);
|
||||||
|
|
||||||
|
td->buffer = (grub_uint32_t) data;
|
||||||
|
|
||||||
|
return td;
|
||||||
|
}
|
||||||
|
|
||||||
|
static grub_usb_err_t
|
||||||
|
grub_uhci_transfer (grub_usb_controller_t dev,
|
||||||
|
grub_usb_transfer_t transfer)
|
||||||
|
{
|
||||||
|
struct grub_uhci *u = (struct grub_uhci *) dev->data;
|
||||||
|
grub_uhci_qh_t qh;
|
||||||
|
grub_uhci_td_t td;
|
||||||
|
grub_uhci_td_t td_first = NULL;
|
||||||
|
grub_uhci_td_t td_prev = NULL;
|
||||||
|
grub_usb_err_t err = GRUB_USB_ERR_NONE;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* Allocate a queue head for the transfer queue. */
|
||||||
|
qh = grub_alloc_qh (u, GRUB_USB_TRANSACTION_TYPE_CONTROL);
|
||||||
|
if (! qh)
|
||||||
|
return grub_errno;
|
||||||
|
|
||||||
|
for (i = 0; i < transfer->transcnt; i++)
|
||||||
|
{
|
||||||
|
grub_usb_transaction_t tr = &transfer->transactions[i];
|
||||||
|
|
||||||
|
td = grub_uhci_transaction (u, transfer->endpoint, tr->pid,
|
||||||
|
transfer->devaddr, tr->toggle,
|
||||||
|
tr->size, tr->data);
|
||||||
|
if (! td)
|
||||||
|
{
|
||||||
|
/* Terminate and free. */
|
||||||
|
td_prev->linkptr2 = 0;
|
||||||
|
td_prev->linkptr = 1;
|
||||||
|
|
||||||
|
if (td_first)
|
||||||
|
grub_free_queue (u, td_first);
|
||||||
|
|
||||||
|
return GRUB_USB_ERR_INTERNAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! td_first)
|
||||||
|
td_first = td;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
td_prev->linkptr2 = (grub_uint32_t) td;
|
||||||
|
td_prev->linkptr = (grub_uint32_t) td;
|
||||||
|
td_prev->linkptr |= 4;
|
||||||
|
}
|
||||||
|
td_prev = td;
|
||||||
|
}
|
||||||
|
td_prev->linkptr2 = 0;
|
||||||
|
td_prev->linkptr = 1;
|
||||||
|
|
||||||
|
grub_dprintf ("uhci", "setup transaction %d\n", transfer->type);
|
||||||
|
|
||||||
|
/* Link it into the queue and terminate. Now the transaction can
|
||||||
|
take place. */
|
||||||
|
qh->elinkptr = (grub_uint32_t) td_first;
|
||||||
|
|
||||||
|
grub_dprintf ("uhci", "initiate transaction\n");
|
||||||
|
|
||||||
|
/* Wait until either the transaction completed or an error
|
||||||
|
occured. */
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
grub_uhci_td_t errtd;
|
||||||
|
|
||||||
|
errtd = (grub_uhci_td_t) (qh->elinkptr & ~0x0f);
|
||||||
|
|
||||||
|
grub_dprintf ("uhci", ">t status=0x%02x data=0x%02x td=%p\n",
|
||||||
|
errtd->ctrl_status, errtd->buffer & (~15), errtd);
|
||||||
|
|
||||||
|
/* Check if the transaction completed. */
|
||||||
|
if (qh->elinkptr & 1)
|
||||||
|
break;
|
||||||
|
|
||||||
|
grub_dprintf ("uhci", "t status=0x%02x\n", errtd->ctrl_status);
|
||||||
|
|
||||||
|
/* Check if the TD is not longer active. */
|
||||||
|
if (! (errtd->ctrl_status & (1 << 23)))
|
||||||
|
{
|
||||||
|
grub_dprintf ("uhci", ">>t status=0x%02x\n", errtd->ctrl_status);
|
||||||
|
|
||||||
|
/* Check if the endpoint is stalled. */
|
||||||
|
if (errtd->ctrl_status & (1 << 22))
|
||||||
|
err = GRUB_USB_ERR_STALL;
|
||||||
|
|
||||||
|
/* Check if an error related to the data buffer occured. */
|
||||||
|
if (errtd->ctrl_status & (1 << 21))
|
||||||
|
err = GRUB_USB_ERR_DATA;
|
||||||
|
|
||||||
|
/* Check if a babble error occured. */
|
||||||
|
if (errtd->ctrl_status & (1 << 20))
|
||||||
|
err = GRUB_USB_ERR_BABBLE;
|
||||||
|
|
||||||
|
/* Check if a NAK occured. */
|
||||||
|
if (errtd->ctrl_status & (1 << 19))
|
||||||
|
err = GRUB_USB_ERR_NAK;
|
||||||
|
|
||||||
|
/* Check if a timeout occured. */
|
||||||
|
if (errtd->ctrl_status & (1 << 18))
|
||||||
|
err = GRUB_USB_ERR_TIMEOUT;
|
||||||
|
|
||||||
|
/* Check if a bitstuff error occured. */
|
||||||
|
if (errtd->ctrl_status & (1 << 17))
|
||||||
|
err = GRUB_USB_ERR_BITSTUFF;
|
||||||
|
|
||||||
|
if (err)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
/* Fall through, no errors occured, so the QH might be
|
||||||
|
updated. */
|
||||||
|
grub_dprintf ("uhci", "transaction fallthrough\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
grub_dprintf ("uhci", "transaction complete\n");
|
||||||
|
|
||||||
|
fail:
|
||||||
|
|
||||||
|
grub_dprintf ("uhci", "transaction failed\n");
|
||||||
|
|
||||||
|
/* Place the QH back in the free list and deallocate the associated
|
||||||
|
TDs. */
|
||||||
|
qh->elinkptr = 1;
|
||||||
|
grub_free_queue (u, td_first);
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
grub_uhci_iterate (int (*hook) (grub_usb_controller_t dev))
|
||||||
|
{
|
||||||
|
struct grub_uhci *u;
|
||||||
|
struct grub_usb_controller dev;
|
||||||
|
|
||||||
|
for (u = uhci; u; u = u->next)
|
||||||
|
{
|
||||||
|
dev.data = u;
|
||||||
|
if (hook (&dev))
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static grub_err_t
|
||||||
|
grub_uhci_portstatus (grub_usb_controller_t dev,
|
||||||
|
unsigned int port, unsigned int enable)
|
||||||
|
{
|
||||||
|
struct grub_uhci *u = (struct grub_uhci *) dev->data;
|
||||||
|
int reg;
|
||||||
|
unsigned int status;
|
||||||
|
|
||||||
|
grub_dprintf ("uhci", "enable=%d port=%d\n", enable, port);
|
||||||
|
|
||||||
|
if (port == 0)
|
||||||
|
reg = GRUB_UHCI_REG_PORTSC1;
|
||||||
|
else if (port == 1)
|
||||||
|
reg = GRUB_UHCI_REG_PORTSC2;
|
||||||
|
else
|
||||||
|
return grub_error (GRUB_ERR_OUT_OF_RANGE,
|
||||||
|
"UHCI Root Hub port does not exist");
|
||||||
|
|
||||||
|
status = grub_uhci_readreg16 (u, reg);
|
||||||
|
grub_dprintf ("uhci", "detect=0x%02x\n", status);
|
||||||
|
|
||||||
|
/* Reset the port. */
|
||||||
|
grub_uhci_writereg16 (u, reg, enable << 9);
|
||||||
|
|
||||||
|
/* Wait for the reset to complete. XXX: How long exactly? */
|
||||||
|
grub_millisleep (10);
|
||||||
|
status = grub_uhci_readreg16 (u, reg);
|
||||||
|
grub_uhci_writereg16 (u, reg, status & ~(1 << 9));
|
||||||
|
grub_dprintf ("uhci", "reset completed\n");
|
||||||
|
|
||||||
|
/* Enable the port. */
|
||||||
|
grub_uhci_writereg16 (u, reg, enable << 2);
|
||||||
|
grub_millisleep (10);
|
||||||
|
|
||||||
|
grub_dprintf ("uhci", "waiting for the port to be enabled\n");
|
||||||
|
|
||||||
|
while (! (grub_uhci_readreg16 (u, reg) & (1 << 2)));
|
||||||
|
|
||||||
|
status = grub_uhci_readreg16 (u, reg);
|
||||||
|
grub_dprintf ("uhci", ">3detect=0x%02x\n", status);
|
||||||
|
|
||||||
|
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static grub_usb_speed_t
|
||||||
|
grub_uhci_detect_dev (grub_usb_controller_t dev, int port)
|
||||||
|
{
|
||||||
|
struct grub_uhci *u = (struct grub_uhci *) dev->data;
|
||||||
|
int reg;
|
||||||
|
unsigned int status;
|
||||||
|
|
||||||
|
if (port == 0)
|
||||||
|
reg = GRUB_UHCI_REG_PORTSC1;
|
||||||
|
else if (port == 1)
|
||||||
|
reg = GRUB_UHCI_REG_PORTSC2;
|
||||||
|
else
|
||||||
|
return grub_error (GRUB_ERR_OUT_OF_RANGE,
|
||||||
|
"UHCI Root Hub port does not exist");
|
||||||
|
|
||||||
|
status = grub_uhci_readreg16 (u, reg);
|
||||||
|
|
||||||
|
grub_dprintf ("uhci", "detect=0x%02x port=%d\n", status, port);
|
||||||
|
|
||||||
|
if (! (status & 1))
|
||||||
|
return GRUB_USB_SPEED_NONE;
|
||||||
|
else if (status & (1 << 8))
|
||||||
|
return GRUB_USB_SPEED_LOW;
|
||||||
|
else
|
||||||
|
return GRUB_USB_SPEED_FULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
grub_uhci_hubports (grub_usb_controller_t dev __attribute__((unused)))
|
||||||
|
{
|
||||||
|
/* The root hub has exactly two ports. */
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static struct grub_usb_controller_dev usb_controller =
|
||||||
|
{
|
||||||
|
.name = "uhci",
|
||||||
|
.iterate = grub_uhci_iterate,
|
||||||
|
.transfer = grub_uhci_transfer,
|
||||||
|
.hubports = grub_uhci_hubports,
|
||||||
|
.portstatus = grub_uhci_portstatus,
|
||||||
|
.detect_dev = grub_uhci_detect_dev
|
||||||
|
};
|
||||||
|
|
||||||
|
GRUB_MOD_INIT(uhci)
|
||||||
|
{
|
||||||
|
grub_uhci_inithw ();
|
||||||
|
grub_usb_controller_dev_register (&usb_controller);
|
||||||
|
grub_dprintf ("uhci", "registed\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
GRUB_MOD_FINI(uhci)
|
||||||
|
{
|
||||||
|
struct grub_uhci *u;
|
||||||
|
|
||||||
|
/* Disable all UHCI controllers. */
|
||||||
|
for (u = uhci; u; u = u->next)
|
||||||
|
grub_uhci_writereg16 (u, GRUB_UHCI_REG_USBCMD, 0);
|
||||||
|
|
||||||
|
/* Unregister the controller. */
|
||||||
|
grub_usb_controller_dev_unregister (&usb_controller);
|
||||||
|
}
|
263
bus/usb/usb.c
Normal file
263
bus/usb/usb.c
Normal file
|
@ -0,0 +1,263 @@
|
||||||
|
/* usb.c - Generic USB interfaces. */
|
||||||
|
/*
|
||||||
|
* GRUB -- GRand Unified Bootloader
|
||||||
|
* Copyright (C) 2008 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* GRUB 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 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* GRUB 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 GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <grub/dl.h>
|
||||||
|
#include <grub/mm.h>
|
||||||
|
#include <grub/usb.h>
|
||||||
|
#include <grub/misc.h>
|
||||||
|
|
||||||
|
static grub_usb_controller_dev_t grub_usb_list;
|
||||||
|
|
||||||
|
void
|
||||||
|
grub_usb_controller_dev_register (grub_usb_controller_dev_t usb)
|
||||||
|
{
|
||||||
|
auto int iterate_hook (grub_usb_controller_t dev);
|
||||||
|
|
||||||
|
/* Iterate over all controllers found by the driver. */
|
||||||
|
int iterate_hook (grub_usb_controller_t dev)
|
||||||
|
{
|
||||||
|
dev->dev = usb;
|
||||||
|
|
||||||
|
/* Enable the ports of the USB Root Hub. */
|
||||||
|
grub_usb_root_hub (dev);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
usb->next = grub_usb_list;
|
||||||
|
grub_usb_list = usb;
|
||||||
|
|
||||||
|
if (usb->iterate)
|
||||||
|
usb->iterate (iterate_hook);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
grub_usb_controller_dev_unregister (grub_usb_controller_dev_t usb)
|
||||||
|
{
|
||||||
|
grub_usb_controller_dev_t *p, q;
|
||||||
|
|
||||||
|
for (p = &grub_usb_list, q = *p; q; p = &(q->next), q = q->next)
|
||||||
|
if (q == usb)
|
||||||
|
{
|
||||||
|
*p = q->next;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
int
|
||||||
|
grub_usb_controller_iterate (int (*hook) (grub_usb_controller_t dev))
|
||||||
|
{
|
||||||
|
grub_usb_controller_dev_t p;
|
||||||
|
|
||||||
|
auto int iterate_hook (grub_usb_controller_t dev);
|
||||||
|
|
||||||
|
int iterate_hook (grub_usb_controller_t dev)
|
||||||
|
{
|
||||||
|
dev->dev = p;
|
||||||
|
if (hook (dev))
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Iterate over all controller drivers. */
|
||||||
|
for (p = grub_usb_list; p; p = p->next)
|
||||||
|
{
|
||||||
|
/* Iterate over the busses of the controllers. XXX: Actually, a
|
||||||
|
hub driver should do this. */
|
||||||
|
if (p->iterate (iterate_hook))
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
grub_usb_err_t
|
||||||
|
grub_usb_clear_halt (grub_usb_device_t dev, int endpoint)
|
||||||
|
{
|
||||||
|
dev->toggle[endpoint] = 0;
|
||||||
|
return grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_OUT
|
||||||
|
| GRUB_USB_REQTYPE_STANDARD
|
||||||
|
| GRUB_USB_REQTYPE_TARGET_ENDP),
|
||||||
|
GRUB_USB_REQ_CLEAR_FEATURE,
|
||||||
|
GRUB_USB_FEATURE_ENDP_HALT,
|
||||||
|
endpoint, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
grub_usb_err_t
|
||||||
|
grub_usb_set_configuration (grub_usb_device_t dev, int configuration)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < 16; i++)
|
||||||
|
dev->toggle[i] = 0;
|
||||||
|
|
||||||
|
return grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_OUT
|
||||||
|
| GRUB_USB_REQTYPE_STANDARD
|
||||||
|
| GRUB_USB_REQTYPE_TARGET_DEV),
|
||||||
|
GRUB_USB_REQ_SET_CONFIGURATION, configuration,
|
||||||
|
0, 0, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
grub_usb_err_t
|
||||||
|
grub_usb_get_descriptor (grub_usb_device_t dev,
|
||||||
|
grub_uint8_t type, grub_uint8_t index,
|
||||||
|
grub_size_t size, char *data)
|
||||||
|
{
|
||||||
|
return grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_IN
|
||||||
|
| GRUB_USB_REQTYPE_STANDARD
|
||||||
|
| GRUB_USB_REQTYPE_TARGET_DEV),
|
||||||
|
GRUB_USB_REQ_GET_DESCRIPTOR,
|
||||||
|
(type << 8) | index,
|
||||||
|
0, size, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct grub_usb_desc_endp *
|
||||||
|
grub_usb_get_endpdescriptor (grub_usb_device_t usbdev, int addr)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < usbdev->config[0].descconf->numif; i++)
|
||||||
|
{
|
||||||
|
struct grub_usb_desc_if *interf;
|
||||||
|
int j;
|
||||||
|
|
||||||
|
interf = usbdev->config[0].interf[i].descif;
|
||||||
|
|
||||||
|
for (j = 0; j < interf->endpointcnt; j++)
|
||||||
|
{
|
||||||
|
struct grub_usb_desc_endp *endp;
|
||||||
|
endp = &usbdev->config[0].interf[i].descendp[j];
|
||||||
|
|
||||||
|
if (endp->endp_addr == addr)
|
||||||
|
return endp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
grub_usb_err_t
|
||||||
|
grub_usb_get_string (grub_usb_device_t dev, grub_uint8_t index, int langid,
|
||||||
|
char **string)
|
||||||
|
{
|
||||||
|
struct grub_usb_desc_str descstr;
|
||||||
|
struct grub_usb_desc_str *descstrp;
|
||||||
|
grub_usb_err_t err;
|
||||||
|
|
||||||
|
/* Only get the length. */
|
||||||
|
err = grub_usb_control_msg (dev, 1 << 7,
|
||||||
|
0x06, (3 << 8) | index,
|
||||||
|
langid, 1, (char *) &descstr);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
descstrp = grub_malloc (descstr.length);
|
||||||
|
if (! descstrp)
|
||||||
|
return GRUB_USB_ERR_INTERNAL;
|
||||||
|
err = grub_usb_control_msg (dev, 1 << 7,
|
||||||
|
0x06, (3 << 8) | index,
|
||||||
|
langid, descstr.length, (char *) descstrp);
|
||||||
|
|
||||||
|
*string = grub_malloc (descstr.length / 2);
|
||||||
|
if (! *string)
|
||||||
|
{
|
||||||
|
grub_free (descstrp);
|
||||||
|
return GRUB_USB_ERR_INTERNAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
grub_utf16_to_utf8 ((grub_uint8_t *) *string, descstrp->str, descstrp->length / 2 - 1);
|
||||||
|
(*string)[descstr.length / 2 - 1] = '\0';
|
||||||
|
grub_free (descstrp);
|
||||||
|
|
||||||
|
return GRUB_USB_ERR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
grub_usb_err_t
|
||||||
|
grub_usb_device_initialize (grub_usb_device_t dev)
|
||||||
|
{
|
||||||
|
struct grub_usb_desc_device *descdev;
|
||||||
|
struct grub_usb_desc_config config;
|
||||||
|
grub_usb_err_t err;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
err = grub_usb_get_descriptor (dev, GRUB_USB_DESCRIPTOR_DEVICE,
|
||||||
|
0, sizeof (struct grub_usb_desc_device),
|
||||||
|
(char *) &dev->descdev);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
descdev = &dev->descdev;
|
||||||
|
|
||||||
|
for (i = 0; i < 8; i++)
|
||||||
|
dev->config[i].descconf = NULL;
|
||||||
|
|
||||||
|
for (i = 0; i < descdev->configcnt; i++)
|
||||||
|
{
|
||||||
|
int pos;
|
||||||
|
int currif;
|
||||||
|
char *data;
|
||||||
|
|
||||||
|
/* First just read the first 4 bytes of the configuration
|
||||||
|
descriptor, after that it is known how many bytes really have
|
||||||
|
to be read. */
|
||||||
|
err = grub_usb_get_descriptor (dev, GRUB_USB_DESCRIPTOR_CONFIG, i, 4,
|
||||||
|
(char *) &config);
|
||||||
|
|
||||||
|
data = grub_malloc (config.totallen);
|
||||||
|
if (! data)
|
||||||
|
{
|
||||||
|
err = GRUB_USB_ERR_INTERNAL;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
dev->config[i].descconf = (struct grub_usb_desc_config *) data;
|
||||||
|
err = grub_usb_get_descriptor (dev, GRUB_USB_DESCRIPTOR_CONFIG, i,
|
||||||
|
config.totallen, data);
|
||||||
|
if (err)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
/* Skip the configuration descriptor. */
|
||||||
|
pos = sizeof (struct grub_usb_desc_config);
|
||||||
|
|
||||||
|
/* Read all interfaces. */
|
||||||
|
for (currif = 0; currif < dev->config[i].descconf->numif; currif++)
|
||||||
|
{
|
||||||
|
dev->config[i].interf[currif].descif
|
||||||
|
= (struct grub_usb_desc_if *) &data[pos];
|
||||||
|
pos += sizeof (struct grub_usb_desc_if);
|
||||||
|
|
||||||
|
/* Point to the first endpoint. */
|
||||||
|
dev->config[i].interf[currif].descendp
|
||||||
|
= (struct grub_usb_desc_endp *) &data[pos];
|
||||||
|
pos += (sizeof (struct grub_usb_desc_endp)
|
||||||
|
* dev->config[i].interf[currif].descif->endpointcnt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return GRUB_USB_ERR_NONE;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
|
||||||
|
for (i = 0; i < 8; i++)
|
||||||
|
grub_free (dev->config[i].descconf);
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
193
bus/usb/usbhub.c
Normal file
193
bus/usb/usbhub.c
Normal file
|
@ -0,0 +1,193 @@
|
||||||
|
/* usb.c - USB Hub Support. */
|
||||||
|
/*
|
||||||
|
* GRUB -- GRand Unified Bootloader
|
||||||
|
* Copyright (C) 2008 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* GRUB 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 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* GRUB 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 GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <grub/dl.h>
|
||||||
|
#include <grub/mm.h>
|
||||||
|
#include <grub/usb.h>
|
||||||
|
#include <grub/misc.h>
|
||||||
|
|
||||||
|
/* USB Supports 127 devices, with device 0 as special case. */
|
||||||
|
static struct grub_usb_device *grub_usb_devs[128];
|
||||||
|
|
||||||
|
/* Add a device that currently has device number 0 and resides on
|
||||||
|
CONTROLLER, the Hub reported that the device speed is SPEED. */
|
||||||
|
static grub_usb_device_t
|
||||||
|
grub_usb_hub_add_dev (grub_usb_controller_t controller, grub_usb_speed_t speed)
|
||||||
|
{
|
||||||
|
grub_usb_device_t dev;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
dev = grub_malloc (sizeof (struct grub_usb_device));
|
||||||
|
if (! dev)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
dev->controller = *controller;
|
||||||
|
dev->addr = 0;
|
||||||
|
dev->initialized = 0;
|
||||||
|
dev->speed = speed;
|
||||||
|
|
||||||
|
grub_usb_device_initialize (dev);
|
||||||
|
|
||||||
|
/* Assign a new address to the device. */
|
||||||
|
for (i = 1; i < 128; i++)
|
||||||
|
{
|
||||||
|
if (! grub_usb_devs[i])
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (grub_usb_devs[i])
|
||||||
|
{
|
||||||
|
grub_error (GRUB_ERR_IO, "Can't assign address to USB device");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
grub_usb_control_msg (dev,
|
||||||
|
(GRUB_USB_REQTYPE_OUT
|
||||||
|
| GRUB_USB_REQTYPE_STANDARD
|
||||||
|
| GRUB_USB_REQTYPE_TARGET_DEV),
|
||||||
|
GRUB_USB_REQ_SET_ADDRESS,
|
||||||
|
i, 0, 0, NULL);
|
||||||
|
dev->addr = i;
|
||||||
|
dev->initialized = 1;
|
||||||
|
grub_usb_devs[i] = dev;
|
||||||
|
|
||||||
|
return dev;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static grub_err_t
|
||||||
|
grub_usb_add_hub (grub_usb_device_t dev)
|
||||||
|
{
|
||||||
|
struct grub_usb_usb_hubdesc hubdesc;
|
||||||
|
grub_err_t err;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_IN
|
||||||
|
| GRUB_USB_REQTYPE_CLASS
|
||||||
|
| GRUB_USB_REQTYPE_TARGET_DEV),
|
||||||
|
GRUB_USB_REQ_GET_DESCRIPTOR,
|
||||||
|
(GRUB_USB_DESCRIPTOR_HUB << 8) | 0,
|
||||||
|
0, sizeof (hubdesc), (char *) &hubdesc);
|
||||||
|
|
||||||
|
/* Iterate over the Hub ports. */
|
||||||
|
for (i = 1; i <= hubdesc.portcnt; i++)
|
||||||
|
{
|
||||||
|
grub_uint32_t status;
|
||||||
|
|
||||||
|
/* Get the port status. */
|
||||||
|
err = grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_IN
|
||||||
|
| GRUB_USB_REQTYPE_CLASS
|
||||||
|
| GRUB_USB_REQTYPE_TARGET_OTHER),
|
||||||
|
GRUB_USB_REQ_HUB_GET_PORT_STATUS,
|
||||||
|
0, i, sizeof (status), (char *) &status);
|
||||||
|
|
||||||
|
/* Just ignore the device if the Hub does not report the
|
||||||
|
status. */
|
||||||
|
if (err)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* If connected, reset and enable the port. */
|
||||||
|
if (status & GRUB_USB_HUB_STATUS_CONNECTED)
|
||||||
|
{
|
||||||
|
grub_usb_speed_t speed;
|
||||||
|
|
||||||
|
/* Determine the device speed. */
|
||||||
|
if (status & GRUB_USB_HUB_STATUS_LOWSPEED)
|
||||||
|
speed = GRUB_USB_SPEED_LOW;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (status & GRUB_USB_HUB_STATUS_HIGHSPEED)
|
||||||
|
speed = GRUB_USB_SPEED_HIGH;
|
||||||
|
else
|
||||||
|
speed = GRUB_USB_SPEED_FULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* A device is actually connected to this port, not enable
|
||||||
|
the port. XXX: Why 0x03? According to some docs it
|
||||||
|
should be 0x0. Check the specification! */
|
||||||
|
err = grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_OUT
|
||||||
|
| GRUB_USB_REQTYPE_CLASS
|
||||||
|
| GRUB_USB_REQTYPE_TARGET_OTHER),
|
||||||
|
0x3, 0x4, i, 0, 0);
|
||||||
|
|
||||||
|
/* If the Hub does not cooperate for this port, just skip
|
||||||
|
the port. */
|
||||||
|
if (err)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Add the device and assign a device address to it. */
|
||||||
|
grub_usb_hub_add_dev (&dev->controller, speed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
grub_usb_err_t
|
||||||
|
grub_usb_root_hub (grub_usb_controller_t controller)
|
||||||
|
{
|
||||||
|
grub_err_t err;
|
||||||
|
int ports;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* Query the number of ports the root Hub has. */
|
||||||
|
ports = controller->dev->hubports (controller);
|
||||||
|
|
||||||
|
for (i = 0; i < ports; i++)
|
||||||
|
{
|
||||||
|
grub_usb_speed_t speed = controller->dev->detect_dev (controller, i);
|
||||||
|
|
||||||
|
if (speed != GRUB_USB_SPEED_NONE)
|
||||||
|
{
|
||||||
|
grub_usb_device_t dev;
|
||||||
|
|
||||||
|
/* Enable the port. */
|
||||||
|
err = controller->dev->portstatus (controller, i, 1);
|
||||||
|
if (err)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Enable the port and create a device. */
|
||||||
|
dev = grub_usb_hub_add_dev (controller, speed);
|
||||||
|
if (! dev)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* If the device is a Hub, scan it for more devices. */
|
||||||
|
if (dev->descdev.class == 0x09)
|
||||||
|
grub_usb_add_hub (dev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return GRUB_USB_ERR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
grub_usb_iterate (int (*hook) (grub_usb_device_t dev))
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < 128; i++)
|
||||||
|
{
|
||||||
|
if (grub_usb_devs[i])
|
||||||
|
{
|
||||||
|
if (hook (grub_usb_devs[i]))
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
212
bus/usb/usbtrans.c
Normal file
212
bus/usb/usbtrans.c
Normal file
|
@ -0,0 +1,212 @@
|
||||||
|
/* usbtrans.c - USB Transfers and Transactions. */
|
||||||
|
/*
|
||||||
|
* GRUB -- GRand Unified Bootloader
|
||||||
|
* Copyright (C) 2008 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* GRUB 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 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* GRUB 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 GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <grub/dl.h>
|
||||||
|
#include <grub/mm.h>
|
||||||
|
#include <grub/misc.h>
|
||||||
|
#include <grub/usb.h>
|
||||||
|
#include <grub/usbtrans.h>
|
||||||
|
|
||||||
|
grub_usb_err_t
|
||||||
|
grub_usb_control_msg (grub_usb_device_t dev,
|
||||||
|
grub_uint8_t reqtype,
|
||||||
|
grub_uint8_t request,
|
||||||
|
grub_uint16_t value,
|
||||||
|
grub_uint16_t index,
|
||||||
|
grub_size_t size, char *data)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
grub_usb_transfer_t transfer;
|
||||||
|
int datablocks;
|
||||||
|
struct grub_usb_packet_setup setupdata;
|
||||||
|
grub_usb_err_t err;
|
||||||
|
int max;
|
||||||
|
|
||||||
|
grub_dprintf ("usb",
|
||||||
|
"control: reqtype=0x%02x req=0x%02x val=0x%02x idx=0x%02x size=%d\n",
|
||||||
|
reqtype, request, value, index, size);
|
||||||
|
|
||||||
|
/* Create a transfer. */
|
||||||
|
transfer = grub_malloc (sizeof (struct grub_usb_transfer));
|
||||||
|
if (! transfer)
|
||||||
|
return grub_errno;
|
||||||
|
|
||||||
|
/* Determine the maximum packet size. */
|
||||||
|
if (dev->initialized)
|
||||||
|
max = dev->descdev.maxsize0;
|
||||||
|
else
|
||||||
|
max = 64;
|
||||||
|
|
||||||
|
datablocks = (size + max - 1) / max;
|
||||||
|
|
||||||
|
/* XXX: Discriminate between different types of control
|
||||||
|
messages. */
|
||||||
|
transfer->transcnt = datablocks + 2;
|
||||||
|
transfer->size = size; /* XXX ? */
|
||||||
|
transfer->endpoint = 0;
|
||||||
|
transfer->devaddr = dev->addr;
|
||||||
|
transfer->type = GRUB_USB_TRANSACTION_TYPE_CONTROL;
|
||||||
|
transfer->max = max;
|
||||||
|
transfer->dev = dev;
|
||||||
|
|
||||||
|
/* Allocate an array of transfer data structures. */
|
||||||
|
transfer->transactions = grub_malloc (transfer->transcnt
|
||||||
|
* sizeof (struct grub_usb_transfer));
|
||||||
|
if (! transfer->transactions)
|
||||||
|
{
|
||||||
|
grub_free (transfer);
|
||||||
|
return grub_errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Build a Setup packet. XXX: Endianess. */
|
||||||
|
setupdata.reqtype = reqtype;
|
||||||
|
setupdata.request = request;
|
||||||
|
setupdata.value = value;
|
||||||
|
setupdata.index = index;
|
||||||
|
setupdata.length = size;
|
||||||
|
transfer->transactions[0].size = sizeof (setupdata);
|
||||||
|
transfer->transactions[0].pid = GRUB_USB_TRANSFER_TYPE_SETUP;
|
||||||
|
transfer->transactions[0].data = (char *) &setupdata;
|
||||||
|
transfer->transactions[0].toggle = 0;
|
||||||
|
|
||||||
|
/* Now the data... XXX: Is this the right way to transfer control
|
||||||
|
transfers? */
|
||||||
|
for (i = 0; i < datablocks; i++)
|
||||||
|
{
|
||||||
|
grub_usb_transaction_t tr = &transfer->transactions[i + 1];
|
||||||
|
|
||||||
|
tr->size = (size > max) ? max : size;
|
||||||
|
/* Use the right most bit as the data toggle. Simple and
|
||||||
|
effective. */
|
||||||
|
tr->toggle = !(i & 1);
|
||||||
|
if (reqtype & 128)
|
||||||
|
tr->pid = GRUB_USB_TRANSFER_TYPE_IN;
|
||||||
|
else
|
||||||
|
tr->pid = GRUB_USB_TRANSFER_TYPE_OUT;
|
||||||
|
tr->data = &data[i * max];
|
||||||
|
size -= max;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* End with an empty OUT transaction. */
|
||||||
|
transfer->transactions[datablocks + 1].size = 0;
|
||||||
|
transfer->transactions[datablocks + 1].data = NULL;
|
||||||
|
if (reqtype & 128)
|
||||||
|
transfer->transactions[datablocks + 1].pid = GRUB_USB_TRANSFER_TYPE_OUT;
|
||||||
|
else
|
||||||
|
transfer->transactions[datablocks + 1].pid = GRUB_USB_TRANSFER_TYPE_IN;
|
||||||
|
|
||||||
|
transfer->transactions[datablocks + 1].toggle = 1;
|
||||||
|
|
||||||
|
err = dev->controller.dev->transfer (&dev->controller, transfer);
|
||||||
|
|
||||||
|
grub_free (transfer->transactions);
|
||||||
|
grub_free (transfer);
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static grub_usb_err_t
|
||||||
|
grub_usb_bulk_readwrite (grub_usb_device_t dev,
|
||||||
|
int endpoint, grub_size_t size, char *data,
|
||||||
|
grub_transfer_type_t type)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
grub_usb_transfer_t transfer;
|
||||||
|
int datablocks;
|
||||||
|
unsigned int max;
|
||||||
|
grub_usb_err_t err;
|
||||||
|
int toggle = dev->toggle[endpoint];
|
||||||
|
|
||||||
|
/* Use the maximum packet size given in the endpoint descriptor. */
|
||||||
|
if (dev->initialized)
|
||||||
|
{
|
||||||
|
struct grub_usb_desc_endp *endpdesc;
|
||||||
|
endpdesc = grub_usb_get_endpdescriptor (dev, 0);
|
||||||
|
|
||||||
|
if (endpdesc)
|
||||||
|
max = endpdesc->maxpacket;
|
||||||
|
else
|
||||||
|
max = 64;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
max = 64;
|
||||||
|
|
||||||
|
/* Create a transfer. */
|
||||||
|
transfer = grub_malloc (sizeof (struct grub_usb_transfer));
|
||||||
|
if (! transfer)
|
||||||
|
return grub_errno;
|
||||||
|
|
||||||
|
datablocks = ((size + max - 1) / max);
|
||||||
|
transfer->transcnt = datablocks;
|
||||||
|
transfer->size = size - 1;
|
||||||
|
transfer->endpoint = endpoint;
|
||||||
|
transfer->devaddr = dev->addr;
|
||||||
|
transfer->type = GRUB_USB_TRANSACTION_TYPE_BULK;
|
||||||
|
transfer->max = max;
|
||||||
|
transfer->dev = dev;
|
||||||
|
|
||||||
|
/* Allocate an array of transfer data structures. */
|
||||||
|
transfer->transactions = grub_malloc (transfer->transcnt
|
||||||
|
* sizeof (struct grub_usb_transfer));
|
||||||
|
if (! transfer->transactions)
|
||||||
|
{
|
||||||
|
grub_free (transfer);
|
||||||
|
return grub_errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set up all transfers. */
|
||||||
|
for (i = 0; i < datablocks; i++)
|
||||||
|
{
|
||||||
|
grub_usb_transaction_t tr = &transfer->transactions[i];
|
||||||
|
|
||||||
|
tr->size = (size > max) ? max : size;
|
||||||
|
/* XXX: Use the right most bit as the data toggle. Simple and
|
||||||
|
effective. */
|
||||||
|
tr->toggle = toggle;
|
||||||
|
toggle = toggle ? 0 : 1;
|
||||||
|
tr->pid = type;
|
||||||
|
tr->data = &data[i * max];
|
||||||
|
size -= tr->size;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = dev->controller.dev->transfer (&dev->controller, transfer);
|
||||||
|
grub_dprintf ("usb", "toggle=%d\n", toggle);
|
||||||
|
dev->toggle[endpoint] = toggle;
|
||||||
|
|
||||||
|
grub_free (transfer->transactions);
|
||||||
|
grub_free (transfer);
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
grub_usb_err_t
|
||||||
|
grub_usb_bulk_write (grub_usb_device_t dev,
|
||||||
|
int endpoint, grub_size_t size, char *data)
|
||||||
|
{
|
||||||
|
return grub_usb_bulk_readwrite (dev, endpoint, size, data,
|
||||||
|
GRUB_USB_TRANSFER_TYPE_OUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
grub_usb_err_t
|
||||||
|
grub_usb_bulk_read (grub_usb_device_t dev,
|
||||||
|
int endpoint, grub_size_t size, char *data)
|
||||||
|
{
|
||||||
|
return grub_usb_bulk_readwrite (dev, endpoint, size, data,
|
||||||
|
GRUB_USB_TRANSFER_TYPE_IN);
|
||||||
|
}
|
160
commands/usbtest.c
Normal file
160
commands/usbtest.c
Normal file
|
@ -0,0 +1,160 @@
|
||||||
|
/* usbtest.c - test module for USB */
|
||||||
|
/*
|
||||||
|
* GRUB -- GRand Unified Bootloader
|
||||||
|
* Copyright (C) 2008 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* GRUB 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 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* GRUB 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 GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <grub/types.h>
|
||||||
|
#include <grub/misc.h>
|
||||||
|
#include <grub/mm.h>
|
||||||
|
#include <grub/err.h>
|
||||||
|
#include <grub/dl.h>
|
||||||
|
#include <grub/normal.h>
|
||||||
|
#include <grub/usb.h>
|
||||||
|
|
||||||
|
static const char *usb_classes[] =
|
||||||
|
{
|
||||||
|
"",
|
||||||
|
"Audio",
|
||||||
|
"Communication Interface",
|
||||||
|
"HID",
|
||||||
|
"",
|
||||||
|
"Physical",
|
||||||
|
"Image",
|
||||||
|
"Printer",
|
||||||
|
"Mass Storage",
|
||||||
|
"Hub",
|
||||||
|
"Data Interface",
|
||||||
|
"Smart Card",
|
||||||
|
"Content Security",
|
||||||
|
"Video"
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char *usb_endp_type[] =
|
||||||
|
{
|
||||||
|
"Control",
|
||||||
|
"Isochronous",
|
||||||
|
"Bulk",
|
||||||
|
"Interrupt"
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char *usb_devspeed[] =
|
||||||
|
{
|
||||||
|
"",
|
||||||
|
"Low",
|
||||||
|
"Full",
|
||||||
|
"High"
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
usb_print_str (const char *description, grub_usb_device_t dev, int idx)
|
||||||
|
{
|
||||||
|
char *name;
|
||||||
|
/* XXX: LANGID */
|
||||||
|
|
||||||
|
if (! idx)
|
||||||
|
return;
|
||||||
|
|
||||||
|
grub_usb_get_string (dev, idx, 0x0409, &name);
|
||||||
|
grub_printf ("%s: `%s'\n", description, name);
|
||||||
|
grub_free (name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
usb_iterate (grub_usb_device_t dev)
|
||||||
|
{
|
||||||
|
struct grub_usb_desc_device *descdev;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
descdev = &dev->descdev;
|
||||||
|
|
||||||
|
usb_print_str ("Product", dev, descdev->strprod);
|
||||||
|
usb_print_str ("Vendor", dev, descdev->strvendor);
|
||||||
|
usb_print_str ("Serial", dev, descdev->strserial);
|
||||||
|
|
||||||
|
if (descdev->class > 0 && descdev->class <= 0x0E)
|
||||||
|
grub_printf ("Class: (0x%02x) %s, Subclass: 0x%02x, Protocol: 0x%02x\n",
|
||||||
|
descdev->class, usb_classes[descdev->class],
|
||||||
|
descdev->subclass, descdev->protocol);
|
||||||
|
grub_printf ("USB version %d.%d, VendorID: 0x%02x, ProductID: 0x%02x, #conf: %d\n",
|
||||||
|
descdev->usbrel >> 8, (descdev->usbrel >> 4) & 0x0F,
|
||||||
|
descdev->vendorid, descdev->prodid, descdev->configcnt);
|
||||||
|
|
||||||
|
grub_printf ("%s speed device\n", usb_devspeed[dev->speed]);
|
||||||
|
|
||||||
|
for (i = 0; i < descdev->configcnt; i++)
|
||||||
|
{
|
||||||
|
struct grub_usb_desc_config *config;
|
||||||
|
|
||||||
|
config = dev->config[i].descconf;
|
||||||
|
usb_print_str ("Configuration:", dev, config->strconfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < dev->config[0].descconf->numif; i++)
|
||||||
|
{
|
||||||
|
int j;
|
||||||
|
struct grub_usb_desc_if *interf;
|
||||||
|
interf = dev->config[0].interf[i].descif;
|
||||||
|
|
||||||
|
grub_printf ("Interface #%d: #Endpoints: %d ",
|
||||||
|
i, interf->endpointcnt);
|
||||||
|
if (interf->class > 0 && interf->class <= 0x0E)
|
||||||
|
grub_printf ("Class: (0x%02x) %s, Subclass: 0x%02x, Protocol: 0x%02x\n",
|
||||||
|
interf->class, usb_classes[interf->class],
|
||||||
|
interf->subclass, interf->protocol);
|
||||||
|
|
||||||
|
usb_print_str ("Interface", dev, interf->strif);
|
||||||
|
|
||||||
|
for (j = 0; j < interf->endpointcnt; j++)
|
||||||
|
{
|
||||||
|
struct grub_usb_desc_endp *endp;
|
||||||
|
endp = &dev->config[0].interf[i].descendp[j];
|
||||||
|
|
||||||
|
grub_printf ("Endpoint #%d: %s, max packed size: %d, transfer type: %s, latency: %d\n",
|
||||||
|
endp->endp_addr & 15,
|
||||||
|
(endp->endp_addr & 128) ? "IN" : "OUT",
|
||||||
|
endp->maxpacket, usb_endp_type[endp->attrib & 3],
|
||||||
|
endp->interval);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
grub_printf("\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static grub_err_t
|
||||||
|
grub_cmd_usbtest (struct grub_arg_list *state __attribute__ ((unused)),
|
||||||
|
int argc __attribute__ ((unused)),
|
||||||
|
char **args __attribute__ ((unused)))
|
||||||
|
{
|
||||||
|
grub_printf ("USB devices:\n\n");
|
||||||
|
grub_usb_iterate (usb_iterate);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
GRUB_MOD_INIT(usbtest)
|
||||||
|
{
|
||||||
|
(void)mod; /* To stop warning. */
|
||||||
|
grub_register_command ("usb", grub_cmd_usbtest, GRUB_COMMAND_FLAG_BOTH,
|
||||||
|
"usb", "Test USB support", 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
GRUB_MOD_FINI(usbtest)
|
||||||
|
{
|
||||||
|
grub_unregister_command ("usb");
|
||||||
|
}
|
368
conf/i386-pc.mk
368
conf/i386-pc.mk
|
@ -525,7 +525,7 @@ grub_emu_SOURCES = commands/boot.c commands/cat.c commands/cmp.c \
|
||||||
commands/search.c commands/blocklist.c commands/hexdump.c \
|
commands/search.c commands/blocklist.c commands/hexdump.c \
|
||||||
lib/hexdump.c commands/i386/pc/halt.c commands/reboot.c \
|
lib/hexdump.c commands/i386/pc/halt.c commands/reboot.c \
|
||||||
commands/i386/cpuid.c \
|
commands/i386/cpuid.c \
|
||||||
disk/host.c disk/loopback.c \
|
disk/host.c disk/loopback.c disk/scsi.c \
|
||||||
fs/fshelp.c \
|
fs/fshelp.c \
|
||||||
\
|
\
|
||||||
io/gzio.c \
|
io/gzio.c \
|
||||||
|
@ -553,11 +553,11 @@ grub_emu_SOURCES = commands/boot.c commands/cat.c commands/cmp.c \
|
||||||
disk/raid.c disk/raid5_recover.c disk/raid6_recover.c \
|
disk/raid.c disk/raid5_recover.c disk/raid6_recover.c \
|
||||||
disk/mdraid_linux.c disk/dmraid_nvidia.c disk/lvm.c \
|
disk/mdraid_linux.c disk/dmraid_nvidia.c disk/lvm.c \
|
||||||
grub_emu_init.c
|
grub_emu_init.c
|
||||||
CLEANFILES += grub-emu$(EXEEXT) grub_emu-commands_boot.o grub_emu-commands_cat.o grub_emu-commands_cmp.o grub_emu-commands_configfile.o grub_emu-commands_echo.o grub_emu-commands_help.o grub_emu-commands_terminal.o grub_emu-commands_ls.o grub_emu-commands_test.o grub_emu-commands_search.o grub_emu-commands_blocklist.o grub_emu-commands_hexdump.o grub_emu-lib_hexdump.o grub_emu-commands_i386_pc_halt.o grub_emu-commands_reboot.o grub_emu-commands_i386_cpuid.o grub_emu-disk_host.o grub_emu-disk_loopback.o grub_emu-fs_fshelp.o grub_emu-io_gzio.o grub_emu-kern_device.o grub_emu-kern_disk.o grub_emu-kern_dl.o grub_emu-kern_elf.o grub_emu-kern_env.o grub_emu-kern_err.o grub_emu-normal_execute.o grub_emu-kern_file.o grub_emu-kern_fs.o grub_emu-normal_lexer.o grub_emu-kern_loader.o grub_emu-kern_main.o grub_emu-kern_misc.o grub_emu-kern_parser.o grub_emu-grub_script_tab.o grub_emu-kern_partition.o grub_emu-kern_rescue.o grub_emu-kern_term.o grub_emu-normal_arg.o grub_emu-normal_cmdline.o grub_emu-normal_command.o grub_emu-normal_function.o grub_emu-normal_completion.o grub_emu-normal_main.o grub_emu-normal_color.o grub_emu-normal_menu.o grub_emu-normal_menu_entry.o grub_emu-normal_menu_viewer.o grub_emu-normal_misc.o grub_emu-normal_script.o grub_emu-partmap_amiga.o grub_emu-partmap_apple.o grub_emu-partmap_pc.o grub_emu-partmap_sun.o grub_emu-partmap_acorn.o grub_emu-partmap_gpt.o grub_emu-fs_affs.o grub_emu-fs_cpio.o grub_emu-fs_ext2.o grub_emu-fs_fat.o grub_emu-fs_hfs.o grub_emu-fs_hfsplus.o grub_emu-fs_iso9660.o grub_emu-fs_udf.o grub_emu-fs_jfs.o grub_emu-fs_minix.o grub_emu-fs_ntfs.o grub_emu-fs_ntfscomp.o grub_emu-fs_reiserfs.o grub_emu-fs_sfs.o grub_emu-fs_ufs.o grub_emu-fs_xfs.o grub_emu-fs_afs.o grub_emu-fs_tar.o grub_emu-util_console.o grub_emu-util_hostfs.o grub_emu-util_grub_emu.o grub_emu-util_misc.o grub_emu-util_hostdisk.o grub_emu-util_getroot.o grub_emu-util_i386_pc_misc.o grub_emu-disk_raid.o grub_emu-disk_raid5_recover.o grub_emu-disk_raid6_recover.o grub_emu-disk_mdraid_linux.o grub_emu-disk_dmraid_nvidia.o grub_emu-disk_lvm.o grub_emu-grub_emu_init.o
|
CLEANFILES += grub-emu$(EXEEXT) grub_emu-commands_boot.o grub_emu-commands_cat.o grub_emu-commands_cmp.o grub_emu-commands_configfile.o grub_emu-commands_echo.o grub_emu-commands_help.o grub_emu-commands_terminal.o grub_emu-commands_ls.o grub_emu-commands_test.o grub_emu-commands_search.o grub_emu-commands_blocklist.o grub_emu-commands_hexdump.o grub_emu-lib_hexdump.o grub_emu-commands_i386_pc_halt.o grub_emu-commands_reboot.o grub_emu-commands_i386_cpuid.o grub_emu-disk_host.o grub_emu-disk_loopback.o grub_emu-disk_scsi.o grub_emu-fs_fshelp.o grub_emu-io_gzio.o grub_emu-kern_device.o grub_emu-kern_disk.o grub_emu-kern_dl.o grub_emu-kern_elf.o grub_emu-kern_env.o grub_emu-kern_err.o grub_emu-normal_execute.o grub_emu-kern_file.o grub_emu-kern_fs.o grub_emu-normal_lexer.o grub_emu-kern_loader.o grub_emu-kern_main.o grub_emu-kern_misc.o grub_emu-kern_parser.o grub_emu-grub_script_tab.o grub_emu-kern_partition.o grub_emu-kern_rescue.o grub_emu-kern_term.o grub_emu-normal_arg.o grub_emu-normal_cmdline.o grub_emu-normal_command.o grub_emu-normal_function.o grub_emu-normal_completion.o grub_emu-normal_main.o grub_emu-normal_color.o grub_emu-normal_menu.o grub_emu-normal_menu_entry.o grub_emu-normal_menu_viewer.o grub_emu-normal_misc.o grub_emu-normal_script.o grub_emu-partmap_amiga.o grub_emu-partmap_apple.o grub_emu-partmap_pc.o grub_emu-partmap_sun.o grub_emu-partmap_acorn.o grub_emu-partmap_gpt.o grub_emu-fs_affs.o grub_emu-fs_cpio.o grub_emu-fs_ext2.o grub_emu-fs_fat.o grub_emu-fs_hfs.o grub_emu-fs_hfsplus.o grub_emu-fs_iso9660.o grub_emu-fs_udf.o grub_emu-fs_jfs.o grub_emu-fs_minix.o grub_emu-fs_ntfs.o grub_emu-fs_ntfscomp.o grub_emu-fs_reiserfs.o grub_emu-fs_sfs.o grub_emu-fs_ufs.o grub_emu-fs_xfs.o grub_emu-fs_afs.o grub_emu-fs_tar.o grub_emu-util_console.o grub_emu-util_hostfs.o grub_emu-util_grub_emu.o grub_emu-util_misc.o grub_emu-util_hostdisk.o grub_emu-util_getroot.o grub_emu-util_i386_pc_misc.o grub_emu-disk_raid.o grub_emu-disk_raid5_recover.o grub_emu-disk_raid6_recover.o grub_emu-disk_mdraid_linux.o grub_emu-disk_dmraid_nvidia.o grub_emu-disk_lvm.o grub_emu-grub_emu_init.o
|
||||||
MOSTLYCLEANFILES += grub_emu-commands_boot.d grub_emu-commands_cat.d grub_emu-commands_cmp.d grub_emu-commands_configfile.d grub_emu-commands_echo.d grub_emu-commands_help.d grub_emu-commands_terminal.d grub_emu-commands_ls.d grub_emu-commands_test.d grub_emu-commands_search.d grub_emu-commands_blocklist.d grub_emu-commands_hexdump.d grub_emu-lib_hexdump.d grub_emu-commands_i386_pc_halt.d grub_emu-commands_reboot.d grub_emu-commands_i386_cpuid.d grub_emu-disk_host.d grub_emu-disk_loopback.d grub_emu-fs_fshelp.d grub_emu-io_gzio.d grub_emu-kern_device.d grub_emu-kern_disk.d grub_emu-kern_dl.d grub_emu-kern_elf.d grub_emu-kern_env.d grub_emu-kern_err.d grub_emu-normal_execute.d grub_emu-kern_file.d grub_emu-kern_fs.d grub_emu-normal_lexer.d grub_emu-kern_loader.d grub_emu-kern_main.d grub_emu-kern_misc.d grub_emu-kern_parser.d grub_emu-grub_script_tab.d grub_emu-kern_partition.d grub_emu-kern_rescue.d grub_emu-kern_term.d grub_emu-normal_arg.d grub_emu-normal_cmdline.d grub_emu-normal_command.d grub_emu-normal_function.d grub_emu-normal_completion.d grub_emu-normal_main.d grub_emu-normal_color.d grub_emu-normal_menu.d grub_emu-normal_menu_entry.d grub_emu-normal_menu_viewer.d grub_emu-normal_misc.d grub_emu-normal_script.d grub_emu-partmap_amiga.d grub_emu-partmap_apple.d grub_emu-partmap_pc.d grub_emu-partmap_sun.d grub_emu-partmap_acorn.d grub_emu-partmap_gpt.d grub_emu-fs_affs.d grub_emu-fs_cpio.d grub_emu-fs_ext2.d grub_emu-fs_fat.d grub_emu-fs_hfs.d grub_emu-fs_hfsplus.d grub_emu-fs_iso9660.d grub_emu-fs_udf.d grub_emu-fs_jfs.d grub_emu-fs_minix.d grub_emu-fs_ntfs.d grub_emu-fs_ntfscomp.d grub_emu-fs_reiserfs.d grub_emu-fs_sfs.d grub_emu-fs_ufs.d grub_emu-fs_xfs.d grub_emu-fs_afs.d grub_emu-fs_tar.d grub_emu-util_console.d grub_emu-util_hostfs.d grub_emu-util_grub_emu.d grub_emu-util_misc.d grub_emu-util_hostdisk.d grub_emu-util_getroot.d grub_emu-util_i386_pc_misc.d grub_emu-disk_raid.d grub_emu-disk_raid5_recover.d grub_emu-disk_raid6_recover.d grub_emu-disk_mdraid_linux.d grub_emu-disk_dmraid_nvidia.d grub_emu-disk_lvm.d grub_emu-grub_emu_init.d
|
MOSTLYCLEANFILES += grub_emu-commands_boot.d grub_emu-commands_cat.d grub_emu-commands_cmp.d grub_emu-commands_configfile.d grub_emu-commands_echo.d grub_emu-commands_help.d grub_emu-commands_terminal.d grub_emu-commands_ls.d grub_emu-commands_test.d grub_emu-commands_search.d grub_emu-commands_blocklist.d grub_emu-commands_hexdump.d grub_emu-lib_hexdump.d grub_emu-commands_i386_pc_halt.d grub_emu-commands_reboot.d grub_emu-commands_i386_cpuid.d grub_emu-disk_host.d grub_emu-disk_loopback.d grub_emu-disk_scsi.d grub_emu-fs_fshelp.d grub_emu-io_gzio.d grub_emu-kern_device.d grub_emu-kern_disk.d grub_emu-kern_dl.d grub_emu-kern_elf.d grub_emu-kern_env.d grub_emu-kern_err.d grub_emu-normal_execute.d grub_emu-kern_file.d grub_emu-kern_fs.d grub_emu-normal_lexer.d grub_emu-kern_loader.d grub_emu-kern_main.d grub_emu-kern_misc.d grub_emu-kern_parser.d grub_emu-grub_script_tab.d grub_emu-kern_partition.d grub_emu-kern_rescue.d grub_emu-kern_term.d grub_emu-normal_arg.d grub_emu-normal_cmdline.d grub_emu-normal_command.d grub_emu-normal_function.d grub_emu-normal_completion.d grub_emu-normal_main.d grub_emu-normal_color.d grub_emu-normal_menu.d grub_emu-normal_menu_entry.d grub_emu-normal_menu_viewer.d grub_emu-normal_misc.d grub_emu-normal_script.d grub_emu-partmap_amiga.d grub_emu-partmap_apple.d grub_emu-partmap_pc.d grub_emu-partmap_sun.d grub_emu-partmap_acorn.d grub_emu-partmap_gpt.d grub_emu-fs_affs.d grub_emu-fs_cpio.d grub_emu-fs_ext2.d grub_emu-fs_fat.d grub_emu-fs_hfs.d grub_emu-fs_hfsplus.d grub_emu-fs_iso9660.d grub_emu-fs_udf.d grub_emu-fs_jfs.d grub_emu-fs_minix.d grub_emu-fs_ntfs.d grub_emu-fs_ntfscomp.d grub_emu-fs_reiserfs.d grub_emu-fs_sfs.d grub_emu-fs_ufs.d grub_emu-fs_xfs.d grub_emu-fs_afs.d grub_emu-fs_tar.d grub_emu-util_console.d grub_emu-util_hostfs.d grub_emu-util_grub_emu.d grub_emu-util_misc.d grub_emu-util_hostdisk.d grub_emu-util_getroot.d grub_emu-util_i386_pc_misc.d grub_emu-disk_raid.d grub_emu-disk_raid5_recover.d grub_emu-disk_raid6_recover.d grub_emu-disk_mdraid_linux.d grub_emu-disk_dmraid_nvidia.d grub_emu-disk_lvm.d grub_emu-grub_emu_init.d
|
||||||
|
|
||||||
grub-emu: $(grub_emu_DEPENDENCIES) grub_emu-commands_boot.o grub_emu-commands_cat.o grub_emu-commands_cmp.o grub_emu-commands_configfile.o grub_emu-commands_echo.o grub_emu-commands_help.o grub_emu-commands_terminal.o grub_emu-commands_ls.o grub_emu-commands_test.o grub_emu-commands_search.o grub_emu-commands_blocklist.o grub_emu-commands_hexdump.o grub_emu-lib_hexdump.o grub_emu-commands_i386_pc_halt.o grub_emu-commands_reboot.o grub_emu-commands_i386_cpuid.o grub_emu-disk_host.o grub_emu-disk_loopback.o grub_emu-fs_fshelp.o grub_emu-io_gzio.o grub_emu-kern_device.o grub_emu-kern_disk.o grub_emu-kern_dl.o grub_emu-kern_elf.o grub_emu-kern_env.o grub_emu-kern_err.o grub_emu-normal_execute.o grub_emu-kern_file.o grub_emu-kern_fs.o grub_emu-normal_lexer.o grub_emu-kern_loader.o grub_emu-kern_main.o grub_emu-kern_misc.o grub_emu-kern_parser.o grub_emu-grub_script_tab.o grub_emu-kern_partition.o grub_emu-kern_rescue.o grub_emu-kern_term.o grub_emu-normal_arg.o grub_emu-normal_cmdline.o grub_emu-normal_command.o grub_emu-normal_function.o grub_emu-normal_completion.o grub_emu-normal_main.o grub_emu-normal_color.o grub_emu-normal_menu.o grub_emu-normal_menu_entry.o grub_emu-normal_menu_viewer.o grub_emu-normal_misc.o grub_emu-normal_script.o grub_emu-partmap_amiga.o grub_emu-partmap_apple.o grub_emu-partmap_pc.o grub_emu-partmap_sun.o grub_emu-partmap_acorn.o grub_emu-partmap_gpt.o grub_emu-fs_affs.o grub_emu-fs_cpio.o grub_emu-fs_ext2.o grub_emu-fs_fat.o grub_emu-fs_hfs.o grub_emu-fs_hfsplus.o grub_emu-fs_iso9660.o grub_emu-fs_udf.o grub_emu-fs_jfs.o grub_emu-fs_minix.o grub_emu-fs_ntfs.o grub_emu-fs_ntfscomp.o grub_emu-fs_reiserfs.o grub_emu-fs_sfs.o grub_emu-fs_ufs.o grub_emu-fs_xfs.o grub_emu-fs_afs.o grub_emu-fs_tar.o grub_emu-util_console.o grub_emu-util_hostfs.o grub_emu-util_grub_emu.o grub_emu-util_misc.o grub_emu-util_hostdisk.o grub_emu-util_getroot.o grub_emu-util_i386_pc_misc.o grub_emu-disk_raid.o grub_emu-disk_raid5_recover.o grub_emu-disk_raid6_recover.o grub_emu-disk_mdraid_linux.o grub_emu-disk_dmraid_nvidia.o grub_emu-disk_lvm.o grub_emu-grub_emu_init.o
|
grub-emu: $(grub_emu_DEPENDENCIES) grub_emu-commands_boot.o grub_emu-commands_cat.o grub_emu-commands_cmp.o grub_emu-commands_configfile.o grub_emu-commands_echo.o grub_emu-commands_help.o grub_emu-commands_terminal.o grub_emu-commands_ls.o grub_emu-commands_test.o grub_emu-commands_search.o grub_emu-commands_blocklist.o grub_emu-commands_hexdump.o grub_emu-lib_hexdump.o grub_emu-commands_i386_pc_halt.o grub_emu-commands_reboot.o grub_emu-commands_i386_cpuid.o grub_emu-disk_host.o grub_emu-disk_loopback.o grub_emu-disk_scsi.o grub_emu-fs_fshelp.o grub_emu-io_gzio.o grub_emu-kern_device.o grub_emu-kern_disk.o grub_emu-kern_dl.o grub_emu-kern_elf.o grub_emu-kern_env.o grub_emu-kern_err.o grub_emu-normal_execute.o grub_emu-kern_file.o grub_emu-kern_fs.o grub_emu-normal_lexer.o grub_emu-kern_loader.o grub_emu-kern_main.o grub_emu-kern_misc.o grub_emu-kern_parser.o grub_emu-grub_script_tab.o grub_emu-kern_partition.o grub_emu-kern_rescue.o grub_emu-kern_term.o grub_emu-normal_arg.o grub_emu-normal_cmdline.o grub_emu-normal_command.o grub_emu-normal_function.o grub_emu-normal_completion.o grub_emu-normal_main.o grub_emu-normal_color.o grub_emu-normal_menu.o grub_emu-normal_menu_entry.o grub_emu-normal_menu_viewer.o grub_emu-normal_misc.o grub_emu-normal_script.o grub_emu-partmap_amiga.o grub_emu-partmap_apple.o grub_emu-partmap_pc.o grub_emu-partmap_sun.o grub_emu-partmap_acorn.o grub_emu-partmap_gpt.o grub_emu-fs_affs.o grub_emu-fs_cpio.o grub_emu-fs_ext2.o grub_emu-fs_fat.o grub_emu-fs_hfs.o grub_emu-fs_hfsplus.o grub_emu-fs_iso9660.o grub_emu-fs_udf.o grub_emu-fs_jfs.o grub_emu-fs_minix.o grub_emu-fs_ntfs.o grub_emu-fs_ntfscomp.o grub_emu-fs_reiserfs.o grub_emu-fs_sfs.o grub_emu-fs_ufs.o grub_emu-fs_xfs.o grub_emu-fs_afs.o grub_emu-fs_tar.o grub_emu-util_console.o grub_emu-util_hostfs.o grub_emu-util_grub_emu.o grub_emu-util_misc.o grub_emu-util_hostdisk.o grub_emu-util_getroot.o grub_emu-util_i386_pc_misc.o grub_emu-disk_raid.o grub_emu-disk_raid5_recover.o grub_emu-disk_raid6_recover.o grub_emu-disk_mdraid_linux.o grub_emu-disk_dmraid_nvidia.o grub_emu-disk_lvm.o grub_emu-grub_emu_init.o
|
||||||
$(CC) -o $@ grub_emu-commands_boot.o grub_emu-commands_cat.o grub_emu-commands_cmp.o grub_emu-commands_configfile.o grub_emu-commands_echo.o grub_emu-commands_help.o grub_emu-commands_terminal.o grub_emu-commands_ls.o grub_emu-commands_test.o grub_emu-commands_search.o grub_emu-commands_blocklist.o grub_emu-commands_hexdump.o grub_emu-lib_hexdump.o grub_emu-commands_i386_pc_halt.o grub_emu-commands_reboot.o grub_emu-commands_i386_cpuid.o grub_emu-disk_host.o grub_emu-disk_loopback.o grub_emu-fs_fshelp.o grub_emu-io_gzio.o grub_emu-kern_device.o grub_emu-kern_disk.o grub_emu-kern_dl.o grub_emu-kern_elf.o grub_emu-kern_env.o grub_emu-kern_err.o grub_emu-normal_execute.o grub_emu-kern_file.o grub_emu-kern_fs.o grub_emu-normal_lexer.o grub_emu-kern_loader.o grub_emu-kern_main.o grub_emu-kern_misc.o grub_emu-kern_parser.o grub_emu-grub_script_tab.o grub_emu-kern_partition.o grub_emu-kern_rescue.o grub_emu-kern_term.o grub_emu-normal_arg.o grub_emu-normal_cmdline.o grub_emu-normal_command.o grub_emu-normal_function.o grub_emu-normal_completion.o grub_emu-normal_main.o grub_emu-normal_color.o grub_emu-normal_menu.o grub_emu-normal_menu_entry.o grub_emu-normal_menu_viewer.o grub_emu-normal_misc.o grub_emu-normal_script.o grub_emu-partmap_amiga.o grub_emu-partmap_apple.o grub_emu-partmap_pc.o grub_emu-partmap_sun.o grub_emu-partmap_acorn.o grub_emu-partmap_gpt.o grub_emu-fs_affs.o grub_emu-fs_cpio.o grub_emu-fs_ext2.o grub_emu-fs_fat.o grub_emu-fs_hfs.o grub_emu-fs_hfsplus.o grub_emu-fs_iso9660.o grub_emu-fs_udf.o grub_emu-fs_jfs.o grub_emu-fs_minix.o grub_emu-fs_ntfs.o grub_emu-fs_ntfscomp.o grub_emu-fs_reiserfs.o grub_emu-fs_sfs.o grub_emu-fs_ufs.o grub_emu-fs_xfs.o grub_emu-fs_afs.o grub_emu-fs_tar.o grub_emu-util_console.o grub_emu-util_hostfs.o grub_emu-util_grub_emu.o grub_emu-util_misc.o grub_emu-util_hostdisk.o grub_emu-util_getroot.o grub_emu-util_i386_pc_misc.o grub_emu-disk_raid.o grub_emu-disk_raid5_recover.o grub_emu-disk_raid6_recover.o grub_emu-disk_mdraid_linux.o grub_emu-disk_dmraid_nvidia.o grub_emu-disk_lvm.o grub_emu-grub_emu_init.o $(LDFLAGS) $(grub_emu_LDFLAGS)
|
$(CC) -o $@ grub_emu-commands_boot.o grub_emu-commands_cat.o grub_emu-commands_cmp.o grub_emu-commands_configfile.o grub_emu-commands_echo.o grub_emu-commands_help.o grub_emu-commands_terminal.o grub_emu-commands_ls.o grub_emu-commands_test.o grub_emu-commands_search.o grub_emu-commands_blocklist.o grub_emu-commands_hexdump.o grub_emu-lib_hexdump.o grub_emu-commands_i386_pc_halt.o grub_emu-commands_reboot.o grub_emu-commands_i386_cpuid.o grub_emu-disk_host.o grub_emu-disk_loopback.o grub_emu-disk_scsi.o grub_emu-fs_fshelp.o grub_emu-io_gzio.o grub_emu-kern_device.o grub_emu-kern_disk.o grub_emu-kern_dl.o grub_emu-kern_elf.o grub_emu-kern_env.o grub_emu-kern_err.o grub_emu-normal_execute.o grub_emu-kern_file.o grub_emu-kern_fs.o grub_emu-normal_lexer.o grub_emu-kern_loader.o grub_emu-kern_main.o grub_emu-kern_misc.o grub_emu-kern_parser.o grub_emu-grub_script_tab.o grub_emu-kern_partition.o grub_emu-kern_rescue.o grub_emu-kern_term.o grub_emu-normal_arg.o grub_emu-normal_cmdline.o grub_emu-normal_command.o grub_emu-normal_function.o grub_emu-normal_completion.o grub_emu-normal_main.o grub_emu-normal_color.o grub_emu-normal_menu.o grub_emu-normal_menu_entry.o grub_emu-normal_menu_viewer.o grub_emu-normal_misc.o grub_emu-normal_script.o grub_emu-partmap_amiga.o grub_emu-partmap_apple.o grub_emu-partmap_pc.o grub_emu-partmap_sun.o grub_emu-partmap_acorn.o grub_emu-partmap_gpt.o grub_emu-fs_affs.o grub_emu-fs_cpio.o grub_emu-fs_ext2.o grub_emu-fs_fat.o grub_emu-fs_hfs.o grub_emu-fs_hfsplus.o grub_emu-fs_iso9660.o grub_emu-fs_udf.o grub_emu-fs_jfs.o grub_emu-fs_minix.o grub_emu-fs_ntfs.o grub_emu-fs_ntfscomp.o grub_emu-fs_reiserfs.o grub_emu-fs_sfs.o grub_emu-fs_ufs.o grub_emu-fs_xfs.o grub_emu-fs_afs.o grub_emu-fs_tar.o grub_emu-util_console.o grub_emu-util_hostfs.o grub_emu-util_grub_emu.o grub_emu-util_misc.o grub_emu-util_hostdisk.o grub_emu-util_getroot.o grub_emu-util_i386_pc_misc.o grub_emu-disk_raid.o grub_emu-disk_raid5_recover.o grub_emu-disk_raid6_recover.o grub_emu-disk_mdraid_linux.o grub_emu-disk_dmraid_nvidia.o grub_emu-disk_lvm.o grub_emu-grub_emu_init.o $(LDFLAGS) $(grub_emu_LDFLAGS)
|
||||||
|
|
||||||
grub_emu-commands_boot.o: commands/boot.c $(commands/boot.c_DEPENDENCIES)
|
grub_emu-commands_boot.o: commands/boot.c $(commands/boot.c_DEPENDENCIES)
|
||||||
$(CC) -Icommands -I$(srcdir)/commands $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
|
$(CC) -Icommands -I$(srcdir)/commands $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
|
||||||
|
@ -631,6 +631,10 @@ grub_emu-disk_loopback.o: disk/loopback.c $(disk/loopback.c_DEPENDENCIES)
|
||||||
$(CC) -Idisk -I$(srcdir)/disk $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
|
$(CC) -Idisk -I$(srcdir)/disk $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
|
||||||
-include grub_emu-disk_loopback.d
|
-include grub_emu-disk_loopback.d
|
||||||
|
|
||||||
|
grub_emu-disk_scsi.o: disk/scsi.c $(disk/scsi.c_DEPENDENCIES)
|
||||||
|
$(CC) -Idisk -I$(srcdir)/disk $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
|
||||||
|
-include grub_emu-disk_scsi.d
|
||||||
|
|
||||||
grub_emu-fs_fshelp.o: fs/fshelp.c $(fs/fshelp.c_DEPENDENCIES)
|
grub_emu-fs_fshelp.o: fs/fshelp.c $(fs/fshelp.c_DEPENDENCIES)
|
||||||
$(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
|
$(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
|
||||||
-include grub_emu-fs_fshelp.d
|
-include grub_emu-fs_fshelp.d
|
||||||
|
@ -914,6 +918,34 @@ grub_emu-grub_emu_init.o: grub_emu_init.c $(grub_emu_init.c_DEPENDENCIES)
|
||||||
|
|
||||||
grub_emu_LDFLAGS = $(LIBCURSES)
|
grub_emu_LDFLAGS = $(LIBCURSES)
|
||||||
|
|
||||||
|
ifeq ($(enable_grub_emu_usb), yes)
|
||||||
|
grub_emu_SOURCES += disk/usbms.c util/usb.c bus/usb/usb.c \
|
||||||
|
commands/usbtest.c
|
||||||
|
CLEANFILES += grub-emu$(EXEEXT) grub_emu-disk_usbms.o grub_emu-util_usb.o grub_emu-bus_usb_usb.o grub_emu-commands_usbtest.o
|
||||||
|
MOSTLYCLEANFILES += grub_emu-disk_usbms.d grub_emu-util_usb.d grub_emu-bus_usb_usb.d grub_emu-commands_usbtest.d
|
||||||
|
|
||||||
|
grub-emu: $(grub_emu_DEPENDENCIES) grub_emu-disk_usbms.o grub_emu-util_usb.o grub_emu-bus_usb_usb.o grub_emu-commands_usbtest.o
|
||||||
|
$(CC) -o $@ grub_emu-disk_usbms.o grub_emu-util_usb.o grub_emu-bus_usb_usb.o grub_emu-commands_usbtest.o $(LDFLAGS) $(grub_emu_LDFLAGS)
|
||||||
|
|
||||||
|
grub_emu-disk_usbms.o: disk/usbms.c $(disk/usbms.c_DEPENDENCIES)
|
||||||
|
$(CC) -Idisk -I$(srcdir)/disk $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
|
||||||
|
-include grub_emu-disk_usbms.d
|
||||||
|
|
||||||
|
grub_emu-util_usb.o: util/usb.c $(util/usb.c_DEPENDENCIES)
|
||||||
|
$(CC) -Iutil -I$(srcdir)/util $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
|
||||||
|
-include grub_emu-util_usb.d
|
||||||
|
|
||||||
|
grub_emu-bus_usb_usb.o: bus/usb/usb.c $(bus/usb/usb.c_DEPENDENCIES)
|
||||||
|
$(CC) -Ibus/usb -I$(srcdir)/bus/usb $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
|
||||||
|
-include grub_emu-bus_usb_usb.d
|
||||||
|
|
||||||
|
grub_emu-commands_usbtest.o: commands/usbtest.c $(commands/usbtest.c_DEPENDENCIES)
|
||||||
|
$(CC) -Icommands -I$(srcdir)/commands $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
|
||||||
|
-include grub_emu-commands_usbtest.d
|
||||||
|
|
||||||
|
grub_emu_LDFLAGS += $(LIBCURSES) $(LIBUSB)
|
||||||
|
endif
|
||||||
|
|
||||||
# Scripts.
|
# Scripts.
|
||||||
sbin_SCRIPTS = grub-install
|
sbin_SCRIPTS = grub-install
|
||||||
bin_SCRIPTS = grub-mkrescue
|
bin_SCRIPTS = grub-mkrescue
|
||||||
|
@ -942,7 +974,8 @@ pkglib_MODULES = biosdisk.mod _chain.mod _linux.mod linux.mod normal.mod \
|
||||||
vbe.mod vbetest.mod vbeinfo.mod play.mod serial.mod \
|
vbe.mod vbetest.mod vbeinfo.mod play.mod serial.mod \
|
||||||
ata.mod vga.mod memdisk.mod pci.mod lspci.mod \
|
ata.mod vga.mod memdisk.mod pci.mod lspci.mod \
|
||||||
aout.mod _bsd.mod bsd.mod pxe.mod pxecmd.mod datetime.mod date.mod \
|
aout.mod _bsd.mod bsd.mod pxe.mod pxecmd.mod datetime.mod date.mod \
|
||||||
datehook.mod lsmmap.mod
|
datehook.mod lsmmap.mod \
|
||||||
|
usb.mod uhci.mod ohci.mod usbtest.mod usbms.mod
|
||||||
|
|
||||||
# For biosdisk.mod.
|
# For biosdisk.mod.
|
||||||
biosdisk_mod_SOURCES = disk/i386/pc/biosdisk.c
|
biosdisk_mod_SOURCES = disk/i386/pc/biosdisk.c
|
||||||
|
@ -2673,6 +2706,329 @@ partmap-bsd_mod-loader_i386_bsd_normal.lst: loader/i386/bsd_normal.c $(loader/i3
|
||||||
bsd_mod_CFLAGS = $(COMMON_CFLAGS)
|
bsd_mod_CFLAGS = $(COMMON_CFLAGS)
|
||||||
bsd_mod_LDFLAGS = $(COMMON_LDFLAGS)
|
bsd_mod_LDFLAGS = $(COMMON_LDFLAGS)
|
||||||
|
|
||||||
|
# For usb.mod
|
||||||
|
usb_mod_SOURCES = bus/usb/usb.c bus/usb/usbtrans.c bus/usb/usbhub.c
|
||||||
|
CLEANFILES += usb.mod mod-usb.o mod-usb.c pre-usb.o usb_mod-bus_usb_usb.o usb_mod-bus_usb_usbtrans.o usb_mod-bus_usb_usbhub.o und-usb.lst
|
||||||
|
ifneq ($(usb_mod_EXPORTS),no)
|
||||||
|
CLEANFILES += def-usb.lst
|
||||||
|
DEFSYMFILES += def-usb.lst
|
||||||
|
endif
|
||||||
|
MOSTLYCLEANFILES += usb_mod-bus_usb_usb.d usb_mod-bus_usb_usbtrans.d usb_mod-bus_usb_usbhub.d
|
||||||
|
UNDSYMFILES += und-usb.lst
|
||||||
|
|
||||||
|
usb.mod: pre-usb.o mod-usb.o $(TARGET_OBJ2ELF)
|
||||||
|
-rm -f $@
|
||||||
|
$(TARGET_CC) $(usb_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-usb.o mod-usb.o
|
||||||
|
if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
|
||||||
|
$(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
|
||||||
|
|
||||||
|
pre-usb.o: $(usb_mod_DEPENDENCIES) usb_mod-bus_usb_usb.o usb_mod-bus_usb_usbtrans.o usb_mod-bus_usb_usbhub.o
|
||||||
|
-rm -f $@
|
||||||
|
$(TARGET_CC) $(usb_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ usb_mod-bus_usb_usb.o usb_mod-bus_usb_usbtrans.o usb_mod-bus_usb_usbhub.o
|
||||||
|
|
||||||
|
mod-usb.o: mod-usb.c
|
||||||
|
$(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(usb_mod_CFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
|
mod-usb.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
|
||||||
|
sh $(srcdir)/genmodsrc.sh 'usb' $< > $@ || (rm -f $@; exit 1)
|
||||||
|
|
||||||
|
ifneq ($(usb_mod_EXPORTS),no)
|
||||||
|
def-usb.lst: pre-usb.o
|
||||||
|
$(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 usb/' > $@
|
||||||
|
endif
|
||||||
|
|
||||||
|
und-usb.lst: pre-usb.o
|
||||||
|
echo 'usb' > $@
|
||||||
|
$(NM) -u -P -p $< | cut -f1 -d' ' >> $@
|
||||||
|
|
||||||
|
usb_mod-bus_usb_usb.o: bus/usb/usb.c $(bus/usb/usb.c_DEPENDENCIES)
|
||||||
|
$(TARGET_CC) -Ibus/usb -I$(srcdir)/bus/usb $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(usb_mod_CFLAGS) -MD -c -o $@ $<
|
||||||
|
-include usb_mod-bus_usb_usb.d
|
||||||
|
|
||||||
|
CLEANFILES += cmd-usb_mod-bus_usb_usb.lst fs-usb_mod-bus_usb_usb.lst partmap-usb_mod-bus_usb_usb.lst
|
||||||
|
COMMANDFILES += cmd-usb_mod-bus_usb_usb.lst
|
||||||
|
FSFILES += fs-usb_mod-bus_usb_usb.lst
|
||||||
|
PARTMAPFILES += partmap-usb_mod-bus_usb_usb.lst
|
||||||
|
|
||||||
|
cmd-usb_mod-bus_usb_usb.lst: bus/usb/usb.c $(bus/usb/usb.c_DEPENDENCIES) gencmdlist.sh
|
||||||
|
set -e; $(TARGET_CC) -Ibus/usb -I$(srcdir)/bus/usb $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(usb_mod_CFLAGS) -E $< | sh $(srcdir)/gencmdlist.sh usb > $@ || (rm -f $@; exit 1)
|
||||||
|
|
||||||
|
fs-usb_mod-bus_usb_usb.lst: bus/usb/usb.c $(bus/usb/usb.c_DEPENDENCIES) genfslist.sh
|
||||||
|
set -e; $(TARGET_CC) -Ibus/usb -I$(srcdir)/bus/usb $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(usb_mod_CFLAGS) -E $< | sh $(srcdir)/genfslist.sh usb > $@ || (rm -f $@; exit 1)
|
||||||
|
|
||||||
|
partmap-usb_mod-bus_usb_usb.lst: bus/usb/usb.c $(bus/usb/usb.c_DEPENDENCIES) genpartmaplist.sh
|
||||||
|
set -e; $(TARGET_CC) -Ibus/usb -I$(srcdir)/bus/usb $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(usb_mod_CFLAGS) -E $< | sh $(srcdir)/genpartmaplist.sh usb > $@ || (rm -f $@; exit 1)
|
||||||
|
|
||||||
|
|
||||||
|
usb_mod-bus_usb_usbtrans.o: bus/usb/usbtrans.c $(bus/usb/usbtrans.c_DEPENDENCIES)
|
||||||
|
$(TARGET_CC) -Ibus/usb -I$(srcdir)/bus/usb $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(usb_mod_CFLAGS) -MD -c -o $@ $<
|
||||||
|
-include usb_mod-bus_usb_usbtrans.d
|
||||||
|
|
||||||
|
CLEANFILES += cmd-usb_mod-bus_usb_usbtrans.lst fs-usb_mod-bus_usb_usbtrans.lst partmap-usb_mod-bus_usb_usbtrans.lst
|
||||||
|
COMMANDFILES += cmd-usb_mod-bus_usb_usbtrans.lst
|
||||||
|
FSFILES += fs-usb_mod-bus_usb_usbtrans.lst
|
||||||
|
PARTMAPFILES += partmap-usb_mod-bus_usb_usbtrans.lst
|
||||||
|
|
||||||
|
cmd-usb_mod-bus_usb_usbtrans.lst: bus/usb/usbtrans.c $(bus/usb/usbtrans.c_DEPENDENCIES) gencmdlist.sh
|
||||||
|
set -e; $(TARGET_CC) -Ibus/usb -I$(srcdir)/bus/usb $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(usb_mod_CFLAGS) -E $< | sh $(srcdir)/gencmdlist.sh usb > $@ || (rm -f $@; exit 1)
|
||||||
|
|
||||||
|
fs-usb_mod-bus_usb_usbtrans.lst: bus/usb/usbtrans.c $(bus/usb/usbtrans.c_DEPENDENCIES) genfslist.sh
|
||||||
|
set -e; $(TARGET_CC) -Ibus/usb -I$(srcdir)/bus/usb $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(usb_mod_CFLAGS) -E $< | sh $(srcdir)/genfslist.sh usb > $@ || (rm -f $@; exit 1)
|
||||||
|
|
||||||
|
partmap-usb_mod-bus_usb_usbtrans.lst: bus/usb/usbtrans.c $(bus/usb/usbtrans.c_DEPENDENCIES) genpartmaplist.sh
|
||||||
|
set -e; $(TARGET_CC) -Ibus/usb -I$(srcdir)/bus/usb $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(usb_mod_CFLAGS) -E $< | sh $(srcdir)/genpartmaplist.sh usb > $@ || (rm -f $@; exit 1)
|
||||||
|
|
||||||
|
|
||||||
|
usb_mod-bus_usb_usbhub.o: bus/usb/usbhub.c $(bus/usb/usbhub.c_DEPENDENCIES)
|
||||||
|
$(TARGET_CC) -Ibus/usb -I$(srcdir)/bus/usb $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(usb_mod_CFLAGS) -MD -c -o $@ $<
|
||||||
|
-include usb_mod-bus_usb_usbhub.d
|
||||||
|
|
||||||
|
CLEANFILES += cmd-usb_mod-bus_usb_usbhub.lst fs-usb_mod-bus_usb_usbhub.lst partmap-usb_mod-bus_usb_usbhub.lst
|
||||||
|
COMMANDFILES += cmd-usb_mod-bus_usb_usbhub.lst
|
||||||
|
FSFILES += fs-usb_mod-bus_usb_usbhub.lst
|
||||||
|
PARTMAPFILES += partmap-usb_mod-bus_usb_usbhub.lst
|
||||||
|
|
||||||
|
cmd-usb_mod-bus_usb_usbhub.lst: bus/usb/usbhub.c $(bus/usb/usbhub.c_DEPENDENCIES) gencmdlist.sh
|
||||||
|
set -e; $(TARGET_CC) -Ibus/usb -I$(srcdir)/bus/usb $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(usb_mod_CFLAGS) -E $< | sh $(srcdir)/gencmdlist.sh usb > $@ || (rm -f $@; exit 1)
|
||||||
|
|
||||||
|
fs-usb_mod-bus_usb_usbhub.lst: bus/usb/usbhub.c $(bus/usb/usbhub.c_DEPENDENCIES) genfslist.sh
|
||||||
|
set -e; $(TARGET_CC) -Ibus/usb -I$(srcdir)/bus/usb $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(usb_mod_CFLAGS) -E $< | sh $(srcdir)/genfslist.sh usb > $@ || (rm -f $@; exit 1)
|
||||||
|
|
||||||
|
partmap-usb_mod-bus_usb_usbhub.lst: bus/usb/usbhub.c $(bus/usb/usbhub.c_DEPENDENCIES) genpartmaplist.sh
|
||||||
|
set -e; $(TARGET_CC) -Ibus/usb -I$(srcdir)/bus/usb $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(usb_mod_CFLAGS) -E $< | sh $(srcdir)/genpartmaplist.sh usb > $@ || (rm -f $@; exit 1)
|
||||||
|
|
||||||
|
|
||||||
|
usb_mod_CFLAGS = $(COMMON_CFLAGS)
|
||||||
|
usb_mod_LDFLAGS = $(COMMON_LDFLAGS)
|
||||||
|
|
||||||
|
# For usbtest.mod
|
||||||
|
usbtest_mod_SOURCES = commands/usbtest.c
|
||||||
|
CLEANFILES += usbtest.mod mod-usbtest.o mod-usbtest.c pre-usbtest.o usbtest_mod-commands_usbtest.o und-usbtest.lst
|
||||||
|
ifneq ($(usbtest_mod_EXPORTS),no)
|
||||||
|
CLEANFILES += def-usbtest.lst
|
||||||
|
DEFSYMFILES += def-usbtest.lst
|
||||||
|
endif
|
||||||
|
MOSTLYCLEANFILES += usbtest_mod-commands_usbtest.d
|
||||||
|
UNDSYMFILES += und-usbtest.lst
|
||||||
|
|
||||||
|
usbtest.mod: pre-usbtest.o mod-usbtest.o $(TARGET_OBJ2ELF)
|
||||||
|
-rm -f $@
|
||||||
|
$(TARGET_CC) $(usbtest_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-usbtest.o mod-usbtest.o
|
||||||
|
if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
|
||||||
|
$(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
|
||||||
|
|
||||||
|
pre-usbtest.o: $(usbtest_mod_DEPENDENCIES) usbtest_mod-commands_usbtest.o
|
||||||
|
-rm -f $@
|
||||||
|
$(TARGET_CC) $(usbtest_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ usbtest_mod-commands_usbtest.o
|
||||||
|
|
||||||
|
mod-usbtest.o: mod-usbtest.c
|
||||||
|
$(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(usbtest_mod_CFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
|
mod-usbtest.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
|
||||||
|
sh $(srcdir)/genmodsrc.sh 'usbtest' $< > $@ || (rm -f $@; exit 1)
|
||||||
|
|
||||||
|
ifneq ($(usbtest_mod_EXPORTS),no)
|
||||||
|
def-usbtest.lst: pre-usbtest.o
|
||||||
|
$(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 usbtest/' > $@
|
||||||
|
endif
|
||||||
|
|
||||||
|
und-usbtest.lst: pre-usbtest.o
|
||||||
|
echo 'usbtest' > $@
|
||||||
|
$(NM) -u -P -p $< | cut -f1 -d' ' >> $@
|
||||||
|
|
||||||
|
usbtest_mod-commands_usbtest.o: commands/usbtest.c $(commands/usbtest.c_DEPENDENCIES)
|
||||||
|
$(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(usbtest_mod_CFLAGS) -MD -c -o $@ $<
|
||||||
|
-include usbtest_mod-commands_usbtest.d
|
||||||
|
|
||||||
|
CLEANFILES += cmd-usbtest_mod-commands_usbtest.lst fs-usbtest_mod-commands_usbtest.lst partmap-usbtest_mod-commands_usbtest.lst
|
||||||
|
COMMANDFILES += cmd-usbtest_mod-commands_usbtest.lst
|
||||||
|
FSFILES += fs-usbtest_mod-commands_usbtest.lst
|
||||||
|
PARTMAPFILES += partmap-usbtest_mod-commands_usbtest.lst
|
||||||
|
|
||||||
|
cmd-usbtest_mod-commands_usbtest.lst: commands/usbtest.c $(commands/usbtest.c_DEPENDENCIES) gencmdlist.sh
|
||||||
|
set -e; $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(usbtest_mod_CFLAGS) -E $< | sh $(srcdir)/gencmdlist.sh usbtest > $@ || (rm -f $@; exit 1)
|
||||||
|
|
||||||
|
fs-usbtest_mod-commands_usbtest.lst: commands/usbtest.c $(commands/usbtest.c_DEPENDENCIES) genfslist.sh
|
||||||
|
set -e; $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(usbtest_mod_CFLAGS) -E $< | sh $(srcdir)/genfslist.sh usbtest > $@ || (rm -f $@; exit 1)
|
||||||
|
|
||||||
|
partmap-usbtest_mod-commands_usbtest.lst: commands/usbtest.c $(commands/usbtest.c_DEPENDENCIES) genpartmaplist.sh
|
||||||
|
set -e; $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(usbtest_mod_CFLAGS) -E $< | sh $(srcdir)/genpartmaplist.sh usbtest > $@ || (rm -f $@; exit 1)
|
||||||
|
|
||||||
|
|
||||||
|
usbtest_mod_CFLAGS = $(COMMON_CFLAGS)
|
||||||
|
usbtest_mod_LDFLAGS = $(COMMON_LDFLAGS)
|
||||||
|
|
||||||
|
# For uhci.mod
|
||||||
|
uhci_mod_SOURCES = bus/usb/uhci.c
|
||||||
|
CLEANFILES += uhci.mod mod-uhci.o mod-uhci.c pre-uhci.o uhci_mod-bus_usb_uhci.o und-uhci.lst
|
||||||
|
ifneq ($(uhci_mod_EXPORTS),no)
|
||||||
|
CLEANFILES += def-uhci.lst
|
||||||
|
DEFSYMFILES += def-uhci.lst
|
||||||
|
endif
|
||||||
|
MOSTLYCLEANFILES += uhci_mod-bus_usb_uhci.d
|
||||||
|
UNDSYMFILES += und-uhci.lst
|
||||||
|
|
||||||
|
uhci.mod: pre-uhci.o mod-uhci.o $(TARGET_OBJ2ELF)
|
||||||
|
-rm -f $@
|
||||||
|
$(TARGET_CC) $(uhci_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-uhci.o mod-uhci.o
|
||||||
|
if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
|
||||||
|
$(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
|
||||||
|
|
||||||
|
pre-uhci.o: $(uhci_mod_DEPENDENCIES) uhci_mod-bus_usb_uhci.o
|
||||||
|
-rm -f $@
|
||||||
|
$(TARGET_CC) $(uhci_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ uhci_mod-bus_usb_uhci.o
|
||||||
|
|
||||||
|
mod-uhci.o: mod-uhci.c
|
||||||
|
$(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(uhci_mod_CFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
|
mod-uhci.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
|
||||||
|
sh $(srcdir)/genmodsrc.sh 'uhci' $< > $@ || (rm -f $@; exit 1)
|
||||||
|
|
||||||
|
ifneq ($(uhci_mod_EXPORTS),no)
|
||||||
|
def-uhci.lst: pre-uhci.o
|
||||||
|
$(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 uhci/' > $@
|
||||||
|
endif
|
||||||
|
|
||||||
|
und-uhci.lst: pre-uhci.o
|
||||||
|
echo 'uhci' > $@
|
||||||
|
$(NM) -u -P -p $< | cut -f1 -d' ' >> $@
|
||||||
|
|
||||||
|
uhci_mod-bus_usb_uhci.o: bus/usb/uhci.c $(bus/usb/uhci.c_DEPENDENCIES)
|
||||||
|
$(TARGET_CC) -Ibus/usb -I$(srcdir)/bus/usb $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(uhci_mod_CFLAGS) -MD -c -o $@ $<
|
||||||
|
-include uhci_mod-bus_usb_uhci.d
|
||||||
|
|
||||||
|
CLEANFILES += cmd-uhci_mod-bus_usb_uhci.lst fs-uhci_mod-bus_usb_uhci.lst partmap-uhci_mod-bus_usb_uhci.lst
|
||||||
|
COMMANDFILES += cmd-uhci_mod-bus_usb_uhci.lst
|
||||||
|
FSFILES += fs-uhci_mod-bus_usb_uhci.lst
|
||||||
|
PARTMAPFILES += partmap-uhci_mod-bus_usb_uhci.lst
|
||||||
|
|
||||||
|
cmd-uhci_mod-bus_usb_uhci.lst: bus/usb/uhci.c $(bus/usb/uhci.c_DEPENDENCIES) gencmdlist.sh
|
||||||
|
set -e; $(TARGET_CC) -Ibus/usb -I$(srcdir)/bus/usb $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(uhci_mod_CFLAGS) -E $< | sh $(srcdir)/gencmdlist.sh uhci > $@ || (rm -f $@; exit 1)
|
||||||
|
|
||||||
|
fs-uhci_mod-bus_usb_uhci.lst: bus/usb/uhci.c $(bus/usb/uhci.c_DEPENDENCIES) genfslist.sh
|
||||||
|
set -e; $(TARGET_CC) -Ibus/usb -I$(srcdir)/bus/usb $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(uhci_mod_CFLAGS) -E $< | sh $(srcdir)/genfslist.sh uhci > $@ || (rm -f $@; exit 1)
|
||||||
|
|
||||||
|
partmap-uhci_mod-bus_usb_uhci.lst: bus/usb/uhci.c $(bus/usb/uhci.c_DEPENDENCIES) genpartmaplist.sh
|
||||||
|
set -e; $(TARGET_CC) -Ibus/usb -I$(srcdir)/bus/usb $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(uhci_mod_CFLAGS) -E $< | sh $(srcdir)/genpartmaplist.sh uhci > $@ || (rm -f $@; exit 1)
|
||||||
|
|
||||||
|
|
||||||
|
uhci_mod_CFLAGS = $(COMMON_CFLAGS)
|
||||||
|
uhci_mod_LDFLAGS = $(COMMON_LDFLAGS)
|
||||||
|
|
||||||
|
# For ohci.mod
|
||||||
|
ohci_mod_SOURCES = bus/usb/ohci.c
|
||||||
|
CLEANFILES += ohci.mod mod-ohci.o mod-ohci.c pre-ohci.o ohci_mod-bus_usb_ohci.o und-ohci.lst
|
||||||
|
ifneq ($(ohci_mod_EXPORTS),no)
|
||||||
|
CLEANFILES += def-ohci.lst
|
||||||
|
DEFSYMFILES += def-ohci.lst
|
||||||
|
endif
|
||||||
|
MOSTLYCLEANFILES += ohci_mod-bus_usb_ohci.d
|
||||||
|
UNDSYMFILES += und-ohci.lst
|
||||||
|
|
||||||
|
ohci.mod: pre-ohci.o mod-ohci.o $(TARGET_OBJ2ELF)
|
||||||
|
-rm -f $@
|
||||||
|
$(TARGET_CC) $(ohci_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-ohci.o mod-ohci.o
|
||||||
|
if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
|
||||||
|
$(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
|
||||||
|
|
||||||
|
pre-ohci.o: $(ohci_mod_DEPENDENCIES) ohci_mod-bus_usb_ohci.o
|
||||||
|
-rm -f $@
|
||||||
|
$(TARGET_CC) $(ohci_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ ohci_mod-bus_usb_ohci.o
|
||||||
|
|
||||||
|
mod-ohci.o: mod-ohci.c
|
||||||
|
$(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(ohci_mod_CFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
|
mod-ohci.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
|
||||||
|
sh $(srcdir)/genmodsrc.sh 'ohci' $< > $@ || (rm -f $@; exit 1)
|
||||||
|
|
||||||
|
ifneq ($(ohci_mod_EXPORTS),no)
|
||||||
|
def-ohci.lst: pre-ohci.o
|
||||||
|
$(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 ohci/' > $@
|
||||||
|
endif
|
||||||
|
|
||||||
|
und-ohci.lst: pre-ohci.o
|
||||||
|
echo 'ohci' > $@
|
||||||
|
$(NM) -u -P -p $< | cut -f1 -d' ' >> $@
|
||||||
|
|
||||||
|
ohci_mod-bus_usb_ohci.o: bus/usb/ohci.c $(bus/usb/ohci.c_DEPENDENCIES)
|
||||||
|
$(TARGET_CC) -Ibus/usb -I$(srcdir)/bus/usb $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(ohci_mod_CFLAGS) -MD -c -o $@ $<
|
||||||
|
-include ohci_mod-bus_usb_ohci.d
|
||||||
|
|
||||||
|
CLEANFILES += cmd-ohci_mod-bus_usb_ohci.lst fs-ohci_mod-bus_usb_ohci.lst partmap-ohci_mod-bus_usb_ohci.lst
|
||||||
|
COMMANDFILES += cmd-ohci_mod-bus_usb_ohci.lst
|
||||||
|
FSFILES += fs-ohci_mod-bus_usb_ohci.lst
|
||||||
|
PARTMAPFILES += partmap-ohci_mod-bus_usb_ohci.lst
|
||||||
|
|
||||||
|
cmd-ohci_mod-bus_usb_ohci.lst: bus/usb/ohci.c $(bus/usb/ohci.c_DEPENDENCIES) gencmdlist.sh
|
||||||
|
set -e; $(TARGET_CC) -Ibus/usb -I$(srcdir)/bus/usb $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(ohci_mod_CFLAGS) -E $< | sh $(srcdir)/gencmdlist.sh ohci > $@ || (rm -f $@; exit 1)
|
||||||
|
|
||||||
|
fs-ohci_mod-bus_usb_ohci.lst: bus/usb/ohci.c $(bus/usb/ohci.c_DEPENDENCIES) genfslist.sh
|
||||||
|
set -e; $(TARGET_CC) -Ibus/usb -I$(srcdir)/bus/usb $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(ohci_mod_CFLAGS) -E $< | sh $(srcdir)/genfslist.sh ohci > $@ || (rm -f $@; exit 1)
|
||||||
|
|
||||||
|
partmap-ohci_mod-bus_usb_ohci.lst: bus/usb/ohci.c $(bus/usb/ohci.c_DEPENDENCIES) genpartmaplist.sh
|
||||||
|
set -e; $(TARGET_CC) -Ibus/usb -I$(srcdir)/bus/usb $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(ohci_mod_CFLAGS) -E $< | sh $(srcdir)/genpartmaplist.sh ohci > $@ || (rm -f $@; exit 1)
|
||||||
|
|
||||||
|
|
||||||
|
ohci_mod_CFLAGS = $(COMMON_CFLAGS)
|
||||||
|
ohci_mod_LDFLAGS = $(COMMON_LDFLAGS)
|
||||||
|
|
||||||
|
# For usbms.mod
|
||||||
|
usbms_mod_SOURCES = disk/usbms.c
|
||||||
|
CLEANFILES += usbms.mod mod-usbms.o mod-usbms.c pre-usbms.o usbms_mod-disk_usbms.o und-usbms.lst
|
||||||
|
ifneq ($(usbms_mod_EXPORTS),no)
|
||||||
|
CLEANFILES += def-usbms.lst
|
||||||
|
DEFSYMFILES += def-usbms.lst
|
||||||
|
endif
|
||||||
|
MOSTLYCLEANFILES += usbms_mod-disk_usbms.d
|
||||||
|
UNDSYMFILES += und-usbms.lst
|
||||||
|
|
||||||
|
usbms.mod: pre-usbms.o mod-usbms.o $(TARGET_OBJ2ELF)
|
||||||
|
-rm -f $@
|
||||||
|
$(TARGET_CC) $(usbms_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-usbms.o mod-usbms.o
|
||||||
|
if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
|
||||||
|
$(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
|
||||||
|
|
||||||
|
pre-usbms.o: $(usbms_mod_DEPENDENCIES) usbms_mod-disk_usbms.o
|
||||||
|
-rm -f $@
|
||||||
|
$(TARGET_CC) $(usbms_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ usbms_mod-disk_usbms.o
|
||||||
|
|
||||||
|
mod-usbms.o: mod-usbms.c
|
||||||
|
$(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(usbms_mod_CFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
|
mod-usbms.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
|
||||||
|
sh $(srcdir)/genmodsrc.sh 'usbms' $< > $@ || (rm -f $@; exit 1)
|
||||||
|
|
||||||
|
ifneq ($(usbms_mod_EXPORTS),no)
|
||||||
|
def-usbms.lst: pre-usbms.o
|
||||||
|
$(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 usbms/' > $@
|
||||||
|
endif
|
||||||
|
|
||||||
|
und-usbms.lst: pre-usbms.o
|
||||||
|
echo 'usbms' > $@
|
||||||
|
$(NM) -u -P -p $< | cut -f1 -d' ' >> $@
|
||||||
|
|
||||||
|
usbms_mod-disk_usbms.o: disk/usbms.c $(disk/usbms.c_DEPENDENCIES)
|
||||||
|
$(TARGET_CC) -Idisk -I$(srcdir)/disk $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(usbms_mod_CFLAGS) -MD -c -o $@ $<
|
||||||
|
-include usbms_mod-disk_usbms.d
|
||||||
|
|
||||||
|
CLEANFILES += cmd-usbms_mod-disk_usbms.lst fs-usbms_mod-disk_usbms.lst partmap-usbms_mod-disk_usbms.lst
|
||||||
|
COMMANDFILES += cmd-usbms_mod-disk_usbms.lst
|
||||||
|
FSFILES += fs-usbms_mod-disk_usbms.lst
|
||||||
|
PARTMAPFILES += partmap-usbms_mod-disk_usbms.lst
|
||||||
|
|
||||||
|
cmd-usbms_mod-disk_usbms.lst: disk/usbms.c $(disk/usbms.c_DEPENDENCIES) gencmdlist.sh
|
||||||
|
set -e; $(TARGET_CC) -Idisk -I$(srcdir)/disk $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(usbms_mod_CFLAGS) -E $< | sh $(srcdir)/gencmdlist.sh usbms > $@ || (rm -f $@; exit 1)
|
||||||
|
|
||||||
|
fs-usbms_mod-disk_usbms.lst: disk/usbms.c $(disk/usbms.c_DEPENDENCIES) genfslist.sh
|
||||||
|
set -e; $(TARGET_CC) -Idisk -I$(srcdir)/disk $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(usbms_mod_CFLAGS) -E $< | sh $(srcdir)/genfslist.sh usbms > $@ || (rm -f $@; exit 1)
|
||||||
|
|
||||||
|
partmap-usbms_mod-disk_usbms.lst: disk/usbms.c $(disk/usbms.c_DEPENDENCIES) genpartmaplist.sh
|
||||||
|
set -e; $(TARGET_CC) -Idisk -I$(srcdir)/disk $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(usbms_mod_CFLAGS) -E $< | sh $(srcdir)/genpartmaplist.sh usbms > $@ || (rm -f $@; exit 1)
|
||||||
|
|
||||||
|
|
||||||
|
usbms_mod_CFLAGS = $(COMMON_CFLAGS)
|
||||||
|
usbms_mod_LDFLAGS = $(COMMON_LDFLAGS)
|
||||||
|
|
||||||
# For pxe.mod
|
# For pxe.mod
|
||||||
pxe_mod_SOURCES = fs/i386/pc/pxe.c
|
pxe_mod_SOURCES = fs/i386/pc/pxe.c
|
||||||
CLEANFILES += pxe.mod mod-pxe.o mod-pxe.c pre-pxe.o pxe_mod-fs_i386_pc_pxe.o und-pxe.lst
|
CLEANFILES += pxe.mod mod-pxe.o mod-pxe.c pre-pxe.o pxe_mod-fs_i386_pc_pxe.o und-pxe.lst
|
||||||
|
|
|
@ -118,7 +118,7 @@ grub_emu_SOURCES = commands/boot.c commands/cat.c commands/cmp.c \
|
||||||
commands/search.c commands/blocklist.c commands/hexdump.c \
|
commands/search.c commands/blocklist.c commands/hexdump.c \
|
||||||
lib/hexdump.c commands/i386/pc/halt.c commands/reboot.c \
|
lib/hexdump.c commands/i386/pc/halt.c commands/reboot.c \
|
||||||
commands/i386/cpuid.c \
|
commands/i386/cpuid.c \
|
||||||
disk/host.c disk/loopback.c \
|
disk/host.c disk/loopback.c disk/scsi.c \
|
||||||
fs/fshelp.c \
|
fs/fshelp.c \
|
||||||
\
|
\
|
||||||
io/gzio.c \
|
io/gzio.c \
|
||||||
|
@ -149,6 +149,12 @@ grub_emu_SOURCES = commands/boot.c commands/cat.c commands/cmp.c \
|
||||||
|
|
||||||
grub_emu_LDFLAGS = $(LIBCURSES)
|
grub_emu_LDFLAGS = $(LIBCURSES)
|
||||||
|
|
||||||
|
ifeq ($(enable_grub_emu_usb), yes)
|
||||||
|
grub_emu_SOURCES += disk/usbms.c util/usb.c bus/usb/usb.c \
|
||||||
|
commands/usbtest.c
|
||||||
|
grub_emu_LDFLAGS += $(LIBCURSES) $(LIBUSB)
|
||||||
|
endif
|
||||||
|
|
||||||
# Scripts.
|
# Scripts.
|
||||||
sbin_SCRIPTS = grub-install
|
sbin_SCRIPTS = grub-install
|
||||||
bin_SCRIPTS = grub-mkrescue
|
bin_SCRIPTS = grub-mkrescue
|
||||||
|
@ -165,7 +171,8 @@ pkglib_MODULES = biosdisk.mod _chain.mod _linux.mod linux.mod normal.mod \
|
||||||
vbe.mod vbetest.mod vbeinfo.mod play.mod serial.mod \
|
vbe.mod vbetest.mod vbeinfo.mod play.mod serial.mod \
|
||||||
ata.mod vga.mod memdisk.mod pci.mod lspci.mod \
|
ata.mod vga.mod memdisk.mod pci.mod lspci.mod \
|
||||||
aout.mod _bsd.mod bsd.mod pxe.mod pxecmd.mod datetime.mod date.mod \
|
aout.mod _bsd.mod bsd.mod pxe.mod pxecmd.mod datetime.mod date.mod \
|
||||||
datehook.mod lsmmap.mod
|
datehook.mod lsmmap.mod \
|
||||||
|
usb.mod uhci.mod ohci.mod usbtest.mod usbms.mod
|
||||||
|
|
||||||
# For biosdisk.mod.
|
# For biosdisk.mod.
|
||||||
biosdisk_mod_SOURCES = disk/i386/pc/biosdisk.c
|
biosdisk_mod_SOURCES = disk/i386/pc/biosdisk.c
|
||||||
|
@ -301,6 +308,31 @@ bsd_mod_SOURCES = loader/i386/bsd_normal.c
|
||||||
bsd_mod_CFLAGS = $(COMMON_CFLAGS)
|
bsd_mod_CFLAGS = $(COMMON_CFLAGS)
|
||||||
bsd_mod_LDFLAGS = $(COMMON_LDFLAGS)
|
bsd_mod_LDFLAGS = $(COMMON_LDFLAGS)
|
||||||
|
|
||||||
|
# For usb.mod
|
||||||
|
usb_mod_SOURCES = bus/usb/usb.c bus/usb/usbtrans.c bus/usb/usbhub.c
|
||||||
|
usb_mod_CFLAGS = $(COMMON_CFLAGS)
|
||||||
|
usb_mod_LDFLAGS = $(COMMON_LDFLAGS)
|
||||||
|
|
||||||
|
# For usbtest.mod
|
||||||
|
usbtest_mod_SOURCES = commands/usbtest.c
|
||||||
|
usbtest_mod_CFLAGS = $(COMMON_CFLAGS)
|
||||||
|
usbtest_mod_LDFLAGS = $(COMMON_LDFLAGS)
|
||||||
|
|
||||||
|
# For uhci.mod
|
||||||
|
uhci_mod_SOURCES = bus/usb/uhci.c
|
||||||
|
uhci_mod_CFLAGS = $(COMMON_CFLAGS)
|
||||||
|
uhci_mod_LDFLAGS = $(COMMON_LDFLAGS)
|
||||||
|
|
||||||
|
# For ohci.mod
|
||||||
|
ohci_mod_SOURCES = bus/usb/ohci.c
|
||||||
|
ohci_mod_CFLAGS = $(COMMON_CFLAGS)
|
||||||
|
ohci_mod_LDFLAGS = $(COMMON_LDFLAGS)
|
||||||
|
|
||||||
|
# For usbms.mod
|
||||||
|
usbms_mod_SOURCES = disk/usbms.c
|
||||||
|
usbms_mod_CFLAGS = $(COMMON_CFLAGS)
|
||||||
|
usbms_mod_LDFLAGS = $(COMMON_LDFLAGS)
|
||||||
|
|
||||||
# For pxe.mod
|
# For pxe.mod
|
||||||
pxe_mod_SOURCES = fs/i386/pc/pxe.c
|
pxe_mod_SOURCES = fs/i386/pc/pxe.c
|
||||||
pxe_mod_CFLAGS = $(COMMON_CFLAGS)
|
pxe_mod_CFLAGS = $(COMMON_CFLAGS)
|
||||||
|
|
|
@ -76,6 +76,9 @@
|
||||||
/* Define to 1 if you have the <unistd.h> header file. */
|
/* Define to 1 if you have the <unistd.h> header file. */
|
||||||
#undef HAVE_UNISTD_H
|
#undef HAVE_UNISTD_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <usb.h> header file. */
|
||||||
|
#undef HAVE_USB_H
|
||||||
|
|
||||||
/* Define to 1 if you enable memory manager debugging. */
|
/* Define to 1 if you enable memory manager debugging. */
|
||||||
#undef MM_DEBUG
|
#undef MM_DEBUG
|
||||||
|
|
||||||
|
|
245
configure
vendored
245
configure
vendored
|
@ -700,7 +700,9 @@ TARGET_CPPFLAGS
|
||||||
TARGET_LDFLAGS
|
TARGET_LDFLAGS
|
||||||
MODULE_LDFLAGS
|
MODULE_LDFLAGS
|
||||||
LIBCURSES
|
LIBCURSES
|
||||||
|
LIBUSB
|
||||||
enable_grub_emu
|
enable_grub_emu
|
||||||
|
enable_grub_emu_usb
|
||||||
enable_grub_fstest
|
enable_grub_fstest
|
||||||
enable_grub_pe2elf
|
enable_grub_pe2elf
|
||||||
FREETYPE
|
FREETYPE
|
||||||
|
@ -1303,6 +1305,8 @@ Optional Features:
|
||||||
--enable-lzo use lzo to compress kernel (default is lzma)
|
--enable-lzo use lzo to compress kernel (default is lzma)
|
||||||
--enable-mm-debug include memory manager debugging
|
--enable-mm-debug include memory manager debugging
|
||||||
--enable-grub-emu build and install the `grub-emu' debugging utility
|
--enable-grub-emu build and install the `grub-emu' debugging utility
|
||||||
|
--enable-grub-emu-usb build and install the `grub-emu' debugging utility
|
||||||
|
with USB support
|
||||||
--enable-grub-fstest build and install the `grub-fstest' debugging
|
--enable-grub-fstest build and install the `grub-fstest' debugging
|
||||||
utility
|
utility
|
||||||
--enable-grub-pe2elf build and install the `grub-pe2elf' conversion
|
--enable-grub-pe2elf build and install the `grub-pe2elf' conversion
|
||||||
|
@ -7832,6 +7836,11 @@ if test "${enable_grub_emu+set}" = set; then
|
||||||
enableval=$enable_grub_emu;
|
enableval=$enable_grub_emu;
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Check whether --enable-grub-emu-usb was given.
|
||||||
|
if test "${enable_grub_emu_usb+set}" = set; then
|
||||||
|
enableval=$enable_grub_emu_usb;
|
||||||
|
fi
|
||||||
|
|
||||||
if [ x"$enable_grub_emu" = xyes ]; then
|
if [ x"$enable_grub_emu" = xyes ]; then
|
||||||
# Check for curses libraries.
|
# Check for curses libraries.
|
||||||
{ echo "$as_me:$LINENO: checking for wgetch in -lncurses" >&5
|
{ echo "$as_me:$LINENO: checking for wgetch in -lncurses" >&5
|
||||||
|
@ -8413,8 +8422,234 @@ fi
|
||||||
|
|
||||||
done
|
done
|
||||||
|
|
||||||
|
|
||||||
|
if [ x"$enable_grub_emu_usb" = xyes ]; then
|
||||||
|
# Check for libusb libraries.
|
||||||
|
{ echo "$as_me:$LINENO: checking for usb_claim_interface in -lusb" >&5
|
||||||
|
echo $ECHO_N "checking for usb_claim_interface in -lusb... $ECHO_C" >&6; }
|
||||||
|
if test "${ac_cv_lib_usb_usb_claim_interface+set}" = set; then
|
||||||
|
echo $ECHO_N "(cached) $ECHO_C" >&6
|
||||||
|
else
|
||||||
|
ac_check_lib_save_LIBS=$LIBS
|
||||||
|
LIBS="-lusb $LIBS"
|
||||||
|
cat >conftest.$ac_ext <<_ACEOF
|
||||||
|
/* confdefs.h. */
|
||||||
|
_ACEOF
|
||||||
|
cat confdefs.h >>conftest.$ac_ext
|
||||||
|
cat >>conftest.$ac_ext <<_ACEOF
|
||||||
|
/* end confdefs.h. */
|
||||||
|
|
||||||
|
/* Override any GCC internal prototype to avoid an error.
|
||||||
|
Use char because int might match the return type of a GCC
|
||||||
|
builtin and then its argument prototype would still apply. */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
#endif
|
||||||
|
char usb_claim_interface ();
|
||||||
|
int
|
||||||
|
main ()
|
||||||
|
{
|
||||||
|
return usb_claim_interface ();
|
||||||
|
;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
_ACEOF
|
||||||
|
rm -f conftest.$ac_objext conftest$ac_exeext
|
||||||
|
if { (ac_try="$ac_link"
|
||||||
|
case "(($ac_try" in
|
||||||
|
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
|
||||||
|
*) ac_try_echo=$ac_try;;
|
||||||
|
esac
|
||||||
|
eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
|
||||||
|
(eval "$ac_link") 2>conftest.er1
|
||||||
|
ac_status=$?
|
||||||
|
grep -v '^ *+' conftest.er1 >conftest.err
|
||||||
|
rm -f conftest.er1
|
||||||
|
cat conftest.err >&5
|
||||||
|
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||||
|
(exit $ac_status); } && {
|
||||||
|
test -z "$ac_c_werror_flag" ||
|
||||||
|
test ! -s conftest.err
|
||||||
|
} && test -s conftest$ac_exeext &&
|
||||||
|
$as_test_x conftest$ac_exeext; then
|
||||||
|
ac_cv_lib_usb_usb_claim_interface=yes
|
||||||
|
else
|
||||||
|
echo "$as_me: failed program was:" >&5
|
||||||
|
sed 's/^/| /' conftest.$ac_ext >&5
|
||||||
|
|
||||||
|
ac_cv_lib_usb_usb_claim_interface=no
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
|
||||||
|
conftest$ac_exeext conftest.$ac_ext
|
||||||
|
LIBS=$ac_check_lib_save_LIBS
|
||||||
|
fi
|
||||||
|
{ echo "$as_me:$LINENO: result: $ac_cv_lib_usb_usb_claim_interface" >&5
|
||||||
|
echo "${ECHO_T}$ac_cv_lib_usb_usb_claim_interface" >&6; }
|
||||||
|
if test $ac_cv_lib_usb_usb_claim_interface = yes; then
|
||||||
|
LIBUSB="-lusb"
|
||||||
|
else
|
||||||
|
{ { echo "$as_me:$LINENO: error: libusb libraries are required to build \`grub-emu' with USB support" >&5
|
||||||
|
echo "$as_me: error: libusb libraries are required to build \`grub-emu' with USB support" >&2;}
|
||||||
|
{ (exit 1); exit 1; }; }
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Check for headers.
|
||||||
|
|
||||||
|
for ac_header in usb.h
|
||||||
|
do
|
||||||
|
as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
|
||||||
|
if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
|
||||||
|
{ echo "$as_me:$LINENO: checking for $ac_header" >&5
|
||||||
|
echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
|
||||||
|
if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
|
||||||
|
echo $ECHO_N "(cached) $ECHO_C" >&6
|
||||||
|
fi
|
||||||
|
ac_res=`eval echo '${'$as_ac_Header'}'`
|
||||||
|
{ echo "$as_me:$LINENO: result: $ac_res" >&5
|
||||||
|
echo "${ECHO_T}$ac_res" >&6; }
|
||||||
|
else
|
||||||
|
# Is the header compilable?
|
||||||
|
{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
|
||||||
|
echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
|
||||||
|
cat >conftest.$ac_ext <<_ACEOF
|
||||||
|
/* confdefs.h. */
|
||||||
|
_ACEOF
|
||||||
|
cat confdefs.h >>conftest.$ac_ext
|
||||||
|
cat >>conftest.$ac_ext <<_ACEOF
|
||||||
|
/* end confdefs.h. */
|
||||||
|
$ac_includes_default
|
||||||
|
#include <$ac_header>
|
||||||
|
_ACEOF
|
||||||
|
rm -f conftest.$ac_objext
|
||||||
|
if { (ac_try="$ac_compile"
|
||||||
|
case "(($ac_try" in
|
||||||
|
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
|
||||||
|
*) ac_try_echo=$ac_try;;
|
||||||
|
esac
|
||||||
|
eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
|
||||||
|
(eval "$ac_compile") 2>conftest.er1
|
||||||
|
ac_status=$?
|
||||||
|
grep -v '^ *+' conftest.er1 >conftest.err
|
||||||
|
rm -f conftest.er1
|
||||||
|
cat conftest.err >&5
|
||||||
|
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||||
|
(exit $ac_status); } && {
|
||||||
|
test -z "$ac_c_werror_flag" ||
|
||||||
|
test ! -s conftest.err
|
||||||
|
} && test -s conftest.$ac_objext; then
|
||||||
|
ac_header_compiler=yes
|
||||||
|
else
|
||||||
|
echo "$as_me: failed program was:" >&5
|
||||||
|
sed 's/^/| /' conftest.$ac_ext >&5
|
||||||
|
|
||||||
|
ac_header_compiler=no
|
||||||
|
fi
|
||||||
|
|
||||||
|
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||||
|
{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
|
||||||
|
echo "${ECHO_T}$ac_header_compiler" >&6; }
|
||||||
|
|
||||||
|
# Is the header present?
|
||||||
|
{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
|
||||||
|
echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
|
||||||
|
cat >conftest.$ac_ext <<_ACEOF
|
||||||
|
/* confdefs.h. */
|
||||||
|
_ACEOF
|
||||||
|
cat confdefs.h >>conftest.$ac_ext
|
||||||
|
cat >>conftest.$ac_ext <<_ACEOF
|
||||||
|
/* end confdefs.h. */
|
||||||
|
#include <$ac_header>
|
||||||
|
_ACEOF
|
||||||
|
if { (ac_try="$ac_cpp conftest.$ac_ext"
|
||||||
|
case "(($ac_try" in
|
||||||
|
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
|
||||||
|
*) ac_try_echo=$ac_try;;
|
||||||
|
esac
|
||||||
|
eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
|
||||||
|
(eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
|
||||||
|
ac_status=$?
|
||||||
|
grep -v '^ *+' conftest.er1 >conftest.err
|
||||||
|
rm -f conftest.er1
|
||||||
|
cat conftest.err >&5
|
||||||
|
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||||
|
(exit $ac_status); } >/dev/null && {
|
||||||
|
test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
|
||||||
|
test ! -s conftest.err
|
||||||
|
}; then
|
||||||
|
ac_header_preproc=yes
|
||||||
|
else
|
||||||
|
echo "$as_me: failed program was:" >&5
|
||||||
|
sed 's/^/| /' conftest.$ac_ext >&5
|
||||||
|
|
||||||
|
ac_header_preproc=no
|
||||||
|
fi
|
||||||
|
|
||||||
|
rm -f conftest.err conftest.$ac_ext
|
||||||
|
{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
|
||||||
|
echo "${ECHO_T}$ac_header_preproc" >&6; }
|
||||||
|
|
||||||
|
# So? What about this header?
|
||||||
|
case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
|
||||||
|
yes:no: )
|
||||||
|
{ echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
|
||||||
|
echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
|
||||||
|
{ echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
|
||||||
|
echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
|
||||||
|
ac_header_preproc=yes
|
||||||
|
;;
|
||||||
|
no:yes:* )
|
||||||
|
{ echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
|
||||||
|
echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
|
||||||
|
{ echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
|
||||||
|
echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
|
||||||
|
{ echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
|
||||||
|
echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
|
||||||
|
{ echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
|
||||||
|
echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
|
||||||
|
{ echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
|
||||||
|
echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
|
||||||
|
{ echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
|
||||||
|
echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
|
||||||
|
( cat <<\_ASBOX
|
||||||
|
## ------------------------------- ##
|
||||||
|
## Report this to bug-grub@gnu.org ##
|
||||||
|
## ------------------------------- ##
|
||||||
|
_ASBOX
|
||||||
|
) | sed "s/^/$as_me: WARNING: /" >&2
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
{ echo "$as_me:$LINENO: checking for $ac_header" >&5
|
||||||
|
echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
|
||||||
|
if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
|
||||||
|
echo $ECHO_N "(cached) $ECHO_C" >&6
|
||||||
|
else
|
||||||
|
eval "$as_ac_Header=\$ac_header_preproc"
|
||||||
|
fi
|
||||||
|
ac_res=`eval echo '${'$as_ac_Header'}'`
|
||||||
|
{ echo "$as_me:$LINENO: result: $ac_res" >&5
|
||||||
|
echo "${ECHO_T}$ac_res" >&6; }
|
||||||
|
|
||||||
|
fi
|
||||||
|
if test `eval echo '${'$as_ac_Header'}'` = yes; then
|
||||||
|
cat >>confdefs.h <<_ACEOF
|
||||||
|
#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
|
||||||
|
_ACEOF
|
||||||
|
|
||||||
|
else
|
||||||
|
{ { echo "$as_me:$LINENO: error: libusb header file is required to build \`grub-emu' with USB support" >&5
|
||||||
|
echo "$as_me: error: libusb header file is required to build \`grub-emu' with USB support" >&2;}
|
||||||
|
{ (exit 1); exit 1; }; }
|
||||||
|
fi
|
||||||
|
|
||||||
|
done
|
||||||
|
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Check whether --enable-grub-fstest was given.
|
# Check whether --enable-grub-fstest was given.
|
||||||
if test "${enable_grub_fstest+set}" = set; then
|
if test "${enable_grub_fstest+set}" = set; then
|
||||||
|
@ -9209,7 +9444,9 @@ TARGET_CPPFLAGS!$TARGET_CPPFLAGS$ac_delim
|
||||||
TARGET_LDFLAGS!$TARGET_LDFLAGS$ac_delim
|
TARGET_LDFLAGS!$TARGET_LDFLAGS$ac_delim
|
||||||
MODULE_LDFLAGS!$MODULE_LDFLAGS$ac_delim
|
MODULE_LDFLAGS!$MODULE_LDFLAGS$ac_delim
|
||||||
LIBCURSES!$LIBCURSES$ac_delim
|
LIBCURSES!$LIBCURSES$ac_delim
|
||||||
|
LIBUSB!$LIBUSB$ac_delim
|
||||||
enable_grub_emu!$enable_grub_emu$ac_delim
|
enable_grub_emu!$enable_grub_emu$ac_delim
|
||||||
|
enable_grub_emu_usb!$enable_grub_emu_usb$ac_delim
|
||||||
enable_grub_fstest!$enable_grub_fstest$ac_delim
|
enable_grub_fstest!$enable_grub_fstest$ac_delim
|
||||||
enable_grub_pe2elf!$enable_grub_pe2elf$ac_delim
|
enable_grub_pe2elf!$enable_grub_pe2elf$ac_delim
|
||||||
FREETYPE!$FREETYPE$ac_delim
|
FREETYPE!$FREETYPE$ac_delim
|
||||||
|
@ -9220,7 +9457,7 @@ LIBOBJS!$LIBOBJS$ac_delim
|
||||||
LTLIBOBJS!$LTLIBOBJS$ac_delim
|
LTLIBOBJS!$LTLIBOBJS$ac_delim
|
||||||
_ACEOF
|
_ACEOF
|
||||||
|
|
||||||
if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 94; then
|
if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 96; then
|
||||||
break
|
break
|
||||||
elif $ac_last_try; then
|
elif $ac_last_try; then
|
||||||
{ { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
|
{ { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
|
||||||
|
@ -9239,7 +9476,7 @@ fi
|
||||||
|
|
||||||
cat >>$CONFIG_STATUS <<_ACEOF
|
cat >>$CONFIG_STATUS <<_ACEOF
|
||||||
cat >"\$tmp/subs-1.sed" <<\CEOF$ac_eof
|
cat >"\$tmp/subs-1.sed" <<\CEOF$ac_eof
|
||||||
/@[a-zA-Z_][a-zA-Z_0-9]*@/!b end
|
/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
|
||||||
_ACEOF
|
_ACEOF
|
||||||
sed '
|
sed '
|
||||||
s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g
|
s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g
|
||||||
|
@ -9252,8 +9489,6 @@ N; s/^.*\n//; s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g; b n
|
||||||
' >>$CONFIG_STATUS <conf$$subs.sed
|
' >>$CONFIG_STATUS <conf$$subs.sed
|
||||||
rm -f conf$$subs.sed
|
rm -f conf$$subs.sed
|
||||||
cat >>$CONFIG_STATUS <<_ACEOF
|
cat >>$CONFIG_STATUS <<_ACEOF
|
||||||
:end
|
|
||||||
s/|#_!!_#|//g
|
|
||||||
CEOF$ac_eof
|
CEOF$ac_eof
|
||||||
_ACEOF
|
_ACEOF
|
||||||
|
|
||||||
|
@ -9501,7 +9736,7 @@ s&@abs_builddir@&$ac_abs_builddir&;t t
|
||||||
s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
|
s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
|
||||||
s&@INSTALL@&$ac_INSTALL&;t t
|
s&@INSTALL@&$ac_INSTALL&;t t
|
||||||
$ac_datarootdir_hack
|
$ac_datarootdir_hack
|
||||||
" $ac_file_inputs | sed -f "$tmp/subs-1.sed" >$tmp/out
|
" $ac_file_inputs | sed -f "$tmp/subs-1.sed" | sed 's/|#_!!_#|//g' >$tmp/out
|
||||||
|
|
||||||
test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
|
test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
|
||||||
{ ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } &&
|
{ ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } &&
|
||||||
|
|
15
configure.ac
15
configure.ac
|
@ -382,6 +382,9 @@ AC_ARG_ENABLE([mm-debug],
|
||||||
AC_ARG_ENABLE([grub-emu],
|
AC_ARG_ENABLE([grub-emu],
|
||||||
[AS_HELP_STRING([--enable-grub-emu],
|
[AS_HELP_STRING([--enable-grub-emu],
|
||||||
[build and install the `grub-emu' debugging utility])])
|
[build and install the `grub-emu' debugging utility])])
|
||||||
|
AC_ARG_ENABLE([grub-emu-usb],
|
||||||
|
[AS_HELP_STRING([--enable-grub-emu-usb],
|
||||||
|
[build and install the `grub-emu' debugging utility with USB support])])
|
||||||
[if [ x"$enable_grub_emu" = xyes ]; then
|
[if [ x"$enable_grub_emu" = xyes ]; then
|
||||||
# Check for curses libraries.]
|
# Check for curses libraries.]
|
||||||
AC_CHECK_LIB([ncurses], [wgetch], [LIBCURSES="-lncurses"],
|
AC_CHECK_LIB([ncurses], [wgetch], [LIBCURSES="-lncurses"],
|
||||||
|
@ -394,8 +397,20 @@ AC_ARG_ENABLE([grub-emu],
|
||||||
[AC_CHECK_HEADERS([ncurses.h], [],
|
[AC_CHECK_HEADERS([ncurses.h], [],
|
||||||
[AC_CHECK_HEADERS([curses.h], [],
|
[AC_CHECK_HEADERS([curses.h], [],
|
||||||
[AC_MSG_ERROR([(n)curses header files are required to build `grub-emu'])])])])
|
[AC_MSG_ERROR([(n)curses header files are required to build `grub-emu'])])])])
|
||||||
|
|
||||||
|
[if [ x"$enable_grub_emu_usb" = xyes ]; then
|
||||||
|
# Check for libusb libraries.]
|
||||||
|
AC_CHECK_LIB([usb], [usb_claim_interface], [LIBUSB="-lusb"],
|
||||||
|
[AC_MSG_ERROR([libusb libraries are required to build `grub-emu' with USB support])])
|
||||||
|
AC_SUBST([LIBUSB])
|
||||||
|
|
||||||
|
[# Check for headers.]
|
||||||
|
AC_CHECK_HEADERS([usb.h], [],
|
||||||
|
[AC_MSG_ERROR([libusb header file is required to build `grub-emu' with USB support])])
|
||||||
|
[fi]
|
||||||
[fi]
|
[fi]
|
||||||
AC_SUBST([enable_grub_emu])
|
AC_SUBST([enable_grub_emu])
|
||||||
|
AC_SUBST([enable_grub_emu_usb])
|
||||||
|
|
||||||
AC_ARG_ENABLE([grub-fstest],
|
AC_ARG_ENABLE([grub-fstest],
|
||||||
[AS_HELP_STRING([--enable-grub-fstest],
|
[AS_HELP_STRING([--enable-grub-fstest],
|
||||||
|
|
393
disk/usbms.c
Normal file
393
disk/usbms.c
Normal file
|
@ -0,0 +1,393 @@
|
||||||
|
/* usbms.c - USB Mass Storage Support. */
|
||||||
|
/*
|
||||||
|
* GRUB -- GRand Unified Bootloader
|
||||||
|
* Copyright (C) 2008 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* GRUB 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 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* GRUB 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 GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <grub/dl.h>
|
||||||
|
#include <grub/mm.h>
|
||||||
|
#include <grub/usb.h>
|
||||||
|
#include <grub/scsi.h>
|
||||||
|
#include <grub/scsicmd.h>
|
||||||
|
#include <grub/misc.h>
|
||||||
|
|
||||||
|
#define GRUB_USBMS_DIRECTION_BIT 7
|
||||||
|
|
||||||
|
/* The USB Mass Storage Command Block Wrapper. */
|
||||||
|
struct grub_usbms_cbw
|
||||||
|
{
|
||||||
|
grub_uint32_t signature;
|
||||||
|
grub_uint32_t tag;
|
||||||
|
grub_uint32_t transfer_length;
|
||||||
|
grub_uint8_t flags;
|
||||||
|
grub_uint8_t lun;
|
||||||
|
grub_uint8_t length;
|
||||||
|
grub_uint8_t cbwcb[16];
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
struct grub_usbms_csw
|
||||||
|
{
|
||||||
|
grub_uint32_t signature;
|
||||||
|
grub_uint32_t tag;
|
||||||
|
grub_uint32_t residue;
|
||||||
|
grub_uint8_t status;
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
struct grub_usbms_dev
|
||||||
|
{
|
||||||
|
struct grub_usb_device *dev;
|
||||||
|
|
||||||
|
int luns;
|
||||||
|
|
||||||
|
int interface;
|
||||||
|
struct grub_usb_desc_endp *in;
|
||||||
|
struct grub_usb_desc_endp *out;
|
||||||
|
|
||||||
|
int in_maxsz;
|
||||||
|
int out_maxsz;
|
||||||
|
|
||||||
|
struct grub_usbms_dev *next;
|
||||||
|
};
|
||||||
|
typedef struct grub_usbms_dev *grub_usbms_dev_t;
|
||||||
|
|
||||||
|
static grub_usbms_dev_t grub_usbms_dev_list;
|
||||||
|
|
||||||
|
static int devcnt;
|
||||||
|
|
||||||
|
static grub_err_t
|
||||||
|
grub_usbms_reset (grub_usb_device_t dev, int interface)
|
||||||
|
{
|
||||||
|
return grub_usb_control_msg (dev, 0x21, 255, 0, interface, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
grub_usbms_finddevs (void)
|
||||||
|
{
|
||||||
|
auto int usb_iterate (grub_usb_device_t dev);
|
||||||
|
|
||||||
|
int usb_iterate (grub_usb_device_t usbdev)
|
||||||
|
{
|
||||||
|
grub_usb_err_t err;
|
||||||
|
struct grub_usb_desc_device *descdev = &usbdev->descdev;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (descdev->class != 0 || descdev->subclass || descdev->protocol != 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* XXX: Just check configuration 0 for now. */
|
||||||
|
for (i = 0; i < usbdev->config[0].descconf->numif; i++)
|
||||||
|
{
|
||||||
|
struct grub_usbms_dev *usbms;
|
||||||
|
struct grub_usb_desc_if *interf;
|
||||||
|
int j;
|
||||||
|
grub_uint8_t luns;
|
||||||
|
|
||||||
|
interf = usbdev->config[0].interf[i].descif;
|
||||||
|
|
||||||
|
/* If this is not a USB Mass Storage device with a supported
|
||||||
|
protocol, just skip it. */
|
||||||
|
if (interf->class != GRUB_USB_CLASS_MASS_STORAGE
|
||||||
|
|| interf->subclass != GRUB_USBMS_SUBCLASS_BULK
|
||||||
|
|| interf->protocol != GRUB_USBMS_PROTOCOL_BULK)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
devcnt++;
|
||||||
|
usbms = grub_malloc (sizeof (struct grub_usbms_dev));
|
||||||
|
if (! usbms)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
usbms->dev = usbdev;
|
||||||
|
usbms->interface = i;
|
||||||
|
usbms->in = NULL;
|
||||||
|
usbms->out = NULL;
|
||||||
|
|
||||||
|
/* Iterate over all endpoints of this interface, at least a
|
||||||
|
IN and OUT bulk endpoint are required. */
|
||||||
|
for (j = 0; j < interf->endpointcnt; j++)
|
||||||
|
{
|
||||||
|
struct grub_usb_desc_endp *endp;
|
||||||
|
endp = &usbdev->config[0].interf[i].descendp[j];
|
||||||
|
|
||||||
|
if ((endp->endp_addr & 128) && (endp->attrib & 3) == 2)
|
||||||
|
{
|
||||||
|
/* Bulk IN endpoint. */
|
||||||
|
usbms->in = endp;
|
||||||
|
grub_usb_clear_halt (usbdev, endp->endp_addr & 128);
|
||||||
|
usbms->in_maxsz = endp->maxpacket;
|
||||||
|
}
|
||||||
|
else if (!(endp->endp_addr & 128) && (endp->attrib & 3) == 2)
|
||||||
|
{
|
||||||
|
/* Bulk OUT endpoint. */
|
||||||
|
usbms->out = endp;
|
||||||
|
grub_usb_clear_halt (usbdev, endp->endp_addr & 128);
|
||||||
|
usbms->out_maxsz = endp->maxpacket;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!usbms->in || !usbms->out)
|
||||||
|
{
|
||||||
|
grub_free (usbms);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Query the amount of LUNs. */
|
||||||
|
err = grub_usb_control_msg (usbdev, 0xA1, 254,
|
||||||
|
0, i, 1, (char *) &luns);
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
/* In case of a stall, clear the stall. */
|
||||||
|
if (err == GRUB_USB_ERR_STALL)
|
||||||
|
{
|
||||||
|
grub_usb_clear_halt (usbdev, usbms->in->endp_addr & 3);
|
||||||
|
grub_usb_clear_halt (usbdev, usbms->out->endp_addr & 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Just set the amount of LUNs to one. */
|
||||||
|
grub_errno = GRUB_ERR_NONE;
|
||||||
|
usbms->luns = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
usbms->luns = luns;
|
||||||
|
|
||||||
|
/* XXX: Check the magic values, does this really make
|
||||||
|
sense? */
|
||||||
|
grub_usb_control_msg (usbdev, (1 << 6) | 1, 255,
|
||||||
|
0, i, 0, 0);
|
||||||
|
|
||||||
|
/* XXX: To make Qemu work? */
|
||||||
|
if (usbms->luns == 0)
|
||||||
|
usbms->luns = 1;
|
||||||
|
|
||||||
|
usbms->next = grub_usbms_dev_list;
|
||||||
|
grub_usbms_dev_list = usbms;
|
||||||
|
|
||||||
|
/* XXX: Activate the first configuration. */
|
||||||
|
grub_usb_set_configuration (usbdev, 1);
|
||||||
|
|
||||||
|
/* Bolk-Only Mass Storage Reset, after the reset commands
|
||||||
|
will be accepted. */
|
||||||
|
grub_usbms_reset (usbdev, i);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
grub_usb_iterate (usb_iterate);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
grub_usbms_iterate (int (*hook) (const char *name, int luns))
|
||||||
|
{
|
||||||
|
grub_usbms_dev_t p;
|
||||||
|
int cnt = 0;
|
||||||
|
|
||||||
|
for (p = grub_usbms_dev_list; p; p = p->next)
|
||||||
|
{
|
||||||
|
char devname[20];
|
||||||
|
grub_sprintf (devname, "usb%d", cnt);
|
||||||
|
|
||||||
|
if (hook (devname, p->luns))
|
||||||
|
return 1;
|
||||||
|
cnt++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static grub_err_t
|
||||||
|
grub_usbms_tranfer (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd,
|
||||||
|
grub_size_t size, char *buf, int read_write)
|
||||||
|
{
|
||||||
|
struct grub_usbms_cbw cbw;
|
||||||
|
grub_usbms_dev_t dev = (grub_usbms_dev_t) scsi->data;
|
||||||
|
struct grub_usbms_csw status;
|
||||||
|
static grub_uint32_t tag = 0;
|
||||||
|
grub_usb_err_t err;
|
||||||
|
int retrycnt = 3;
|
||||||
|
|
||||||
|
retry:
|
||||||
|
if (retrycnt == 0)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
/* Setup the request. */
|
||||||
|
grub_memset (&cbw, 0, sizeof (cbw));
|
||||||
|
cbw.signature = grub_cpu_to_le32 (0x43425355);
|
||||||
|
cbw.tag = tag++;
|
||||||
|
cbw.transfer_length = grub_cpu_to_le32 (size);
|
||||||
|
cbw.flags = (!read_write) << GRUB_USBMS_DIRECTION_BIT;
|
||||||
|
cbw.lun = scsi->lun << GRUB_SCSI_LUN_SHIFT;
|
||||||
|
cbw.length = cmdsize;
|
||||||
|
grub_memcpy (cbw.cbwcb, cmd, cmdsize);
|
||||||
|
|
||||||
|
/* Write the request. */
|
||||||
|
err = grub_usb_bulk_write (dev->dev, dev->out->endp_addr & 15,
|
||||||
|
sizeof (cbw), (char *) &cbw);
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
if (err == GRUB_USB_ERR_STALL)
|
||||||
|
{
|
||||||
|
grub_usb_clear_halt (dev->dev, dev->out->endp_addr);
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
|
return grub_error (GRUB_ERR_IO, "USB Mass Storage request failed");;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read/write the data. */
|
||||||
|
if (read_write == 0)
|
||||||
|
{
|
||||||
|
err = grub_usb_bulk_read (dev->dev, dev->in->endp_addr & 15, size, buf);
|
||||||
|
grub_dprintf ("usb", "read: %d %d\n", err, GRUB_USB_ERR_STALL);
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
if (err == GRUB_USB_ERR_STALL)
|
||||||
|
{
|
||||||
|
grub_usb_clear_halt (dev->dev, dev->in->endp_addr);
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
|
return grub_error (GRUB_ERR_READ_ERROR,
|
||||||
|
"can't read from USB Mass Storage device");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
err = grub_usb_bulk_write (dev->dev, dev->in->endp_addr & 15, size, buf);
|
||||||
|
grub_dprintf ("usb", "write: %d %d\n", err, GRUB_USB_ERR_STALL);
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
if (err == GRUB_USB_ERR_STALL)
|
||||||
|
{
|
||||||
|
grub_usb_clear_halt (dev->dev, dev->out->endp_addr);
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
|
return grub_error (GRUB_ERR_WRITE_ERROR,
|
||||||
|
"can't write to USB Mass Storage device");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read the status. */
|
||||||
|
err = grub_usb_bulk_read (dev->dev, dev->in->endp_addr & 15,
|
||||||
|
sizeof (status), (char *) &status);
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
if (err == GRUB_USB_ERR_STALL)
|
||||||
|
{
|
||||||
|
grub_usb_clear_halt (dev->dev, dev->in->endp_addr);
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
|
return grub_error (GRUB_ERR_READ_ERROR,
|
||||||
|
"can't read status from USB Mass Storage device");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* XXX: Magic and check this code. */
|
||||||
|
if (status.status == 2)
|
||||||
|
{
|
||||||
|
/* XXX: Phase error, reset device. */
|
||||||
|
grub_usbms_reset (dev->dev, dev->interface);
|
||||||
|
grub_usb_clear_halt (dev->dev, dev->in->endp_addr);
|
||||||
|
grub_usb_clear_halt (dev->dev, dev->out->endp_addr);
|
||||||
|
|
||||||
|
retrycnt--;
|
||||||
|
if (retrycnt)
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status.status)
|
||||||
|
return grub_error (GRUB_ERR_READ_ERROR,
|
||||||
|
"error communication with USB Mass Storage device");
|
||||||
|
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static grub_err_t
|
||||||
|
grub_usbms_read (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd,
|
||||||
|
grub_size_t size, char *buf)
|
||||||
|
{
|
||||||
|
return grub_usbms_tranfer (scsi, cmdsize, cmd, size, buf, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static grub_err_t
|
||||||
|
grub_usbms_write (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd,
|
||||||
|
grub_size_t size, char *buf)
|
||||||
|
{
|
||||||
|
return grub_usbms_tranfer (scsi, cmdsize, cmd, size, buf, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static grub_err_t
|
||||||
|
grub_usbms_open (const char *name, struct grub_scsi *scsi)
|
||||||
|
{
|
||||||
|
grub_usbms_dev_t p;
|
||||||
|
int devnum;
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
if (grub_strncmp (name, "usb", 3))
|
||||||
|
return grub_error (GRUB_ERR_UNKNOWN_DEVICE,
|
||||||
|
"not a USB Mass Storage device");
|
||||||
|
|
||||||
|
devnum = grub_strtoul (name + 3, NULL, 10);
|
||||||
|
for (p = grub_usbms_dev_list; p; p = p->next)
|
||||||
|
{
|
||||||
|
/* Check if this is the devnumth device. */
|
||||||
|
if (devnum == i)
|
||||||
|
{
|
||||||
|
scsi->data = p;
|
||||||
|
scsi->name = grub_strdup (name);
|
||||||
|
scsi->luns = p->luns;
|
||||||
|
if (! scsi->name)
|
||||||
|
return grub_errno;
|
||||||
|
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return grub_error (GRUB_ERR_UNKNOWN_DEVICE,
|
||||||
|
"not a USB Mass Storage device");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
grub_usbms_close (struct grub_scsi *scsi)
|
||||||
|
{
|
||||||
|
grub_free (scsi->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct grub_scsi_dev grub_usbms_dev =
|
||||||
|
{
|
||||||
|
.name = "usb",
|
||||||
|
.iterate = grub_usbms_iterate,
|
||||||
|
.open = grub_usbms_open,
|
||||||
|
.close = grub_usbms_close,
|
||||||
|
.read = grub_usbms_read,
|
||||||
|
.write = grub_usbms_write
|
||||||
|
};
|
||||||
|
|
||||||
|
GRUB_MOD_INIT(usbms)
|
||||||
|
{
|
||||||
|
grub_usbms_finddevs ();
|
||||||
|
grub_scsi_dev_register (&grub_usbms_dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
GRUB_MOD_FINI(usbms)
|
||||||
|
{
|
||||||
|
grub_scsi_dev_unregister (&grub_usbms_dev);
|
||||||
|
}
|
|
@ -52,7 +52,8 @@ typedef enum
|
||||||
GRUB_ERR_SYMLINK_LOOP,
|
GRUB_ERR_SYMLINK_LOOP,
|
||||||
GRUB_ERR_BAD_GZIP_DATA,
|
GRUB_ERR_BAD_GZIP_DATA,
|
||||||
GRUB_ERR_MENU,
|
GRUB_ERR_MENU,
|
||||||
GRUB_ERR_TIMEOUT
|
GRUB_ERR_TIMEOUT,
|
||||||
|
GRUB_ERR_IO
|
||||||
}
|
}
|
||||||
grub_err_t;
|
grub_err_t;
|
||||||
|
|
||||||
|
|
207
include/grub/usb.h
Normal file
207
include/grub/usb.h
Normal file
|
@ -0,0 +1,207 @@
|
||||||
|
/*
|
||||||
|
* GRUB -- GRand Unified Bootloader
|
||||||
|
* Copyright (C) 2008 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* GRUB 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 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* GRUB 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 GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef GRUB_USB_H
|
||||||
|
#define GRUB_USB_H 1
|
||||||
|
|
||||||
|
#include <grub/usbdesc.h>
|
||||||
|
#include <grub/usbtrans.h>
|
||||||
|
|
||||||
|
typedef struct grub_usb_device *grub_usb_device_t;
|
||||||
|
typedef struct grub_usb_controller *grub_usb_controller_t;
|
||||||
|
typedef struct grub_usb_controller_dev *grub_usb_controller_dev_t;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
GRUB_USB_ERR_NONE,
|
||||||
|
GRUB_USB_ERR_INTERNAL,
|
||||||
|
GRUB_USB_ERR_STALL,
|
||||||
|
GRUB_USB_ERR_DATA,
|
||||||
|
GRUB_USB_ERR_NAK,
|
||||||
|
GRUB_USB_ERR_BABBLE,
|
||||||
|
GRUB_USB_ERR_TIMEOUT,
|
||||||
|
GRUB_USB_ERR_BITSTUFF
|
||||||
|
} grub_usb_err_t;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
GRUB_USB_SPEED_NONE,
|
||||||
|
GRUB_USB_SPEED_LOW,
|
||||||
|
GRUB_USB_SPEED_FULL,
|
||||||
|
GRUB_USB_SPEED_HIGH
|
||||||
|
} grub_usb_speed_t;
|
||||||
|
|
||||||
|
/* Call HOOK with each device, until HOOK returns non-zero. */
|
||||||
|
int grub_usb_iterate (int (*hook) (grub_usb_device_t dev));
|
||||||
|
|
||||||
|
grub_usb_err_t grub_usb_device_initialize (grub_usb_device_t dev);
|
||||||
|
|
||||||
|
grub_usb_err_t grub_usb_get_descriptor (grub_usb_device_t dev,
|
||||||
|
grub_uint8_t type, grub_uint8_t index,
|
||||||
|
grub_size_t size, char *data);
|
||||||
|
|
||||||
|
struct grub_usb_desc_endp *
|
||||||
|
grub_usb_get_endpdescriptor (grub_usb_device_t usbdev, int addr);
|
||||||
|
|
||||||
|
grub_usb_err_t grub_usb_clear_halt (grub_usb_device_t dev, int endpoint);
|
||||||
|
|
||||||
|
|
||||||
|
grub_usb_err_t grub_usb_set_configuration (grub_usb_device_t dev,
|
||||||
|
int configuration);
|
||||||
|
|
||||||
|
grub_usb_err_t grub_usb_get_string (grub_usb_device_t dev, grub_uint8_t index,
|
||||||
|
int langid, char **string);
|
||||||
|
|
||||||
|
void grub_usb_controller_dev_register (grub_usb_controller_dev_t usb);
|
||||||
|
|
||||||
|
void grub_usb_controller_dev_unregister (grub_usb_controller_dev_t usb);
|
||||||
|
|
||||||
|
int grub_usb_controller_iterate (int (*hook) (grub_usb_controller_t dev));
|
||||||
|
|
||||||
|
|
||||||
|
grub_usb_err_t grub_usb_control_msg (grub_usb_device_t dev, grub_uint8_t reqtype,
|
||||||
|
grub_uint8_t request, grub_uint16_t value,
|
||||||
|
grub_uint16_t index, grub_size_t size,
|
||||||
|
char *data);
|
||||||
|
|
||||||
|
grub_usb_err_t
|
||||||
|
grub_usb_bulk_read (grub_usb_device_t dev,
|
||||||
|
int endpoint, grub_size_t size, char *data);
|
||||||
|
grub_usb_err_t
|
||||||
|
grub_usb_bulk_write (grub_usb_device_t dev,
|
||||||
|
int endpoint, grub_size_t size, char *data);
|
||||||
|
|
||||||
|
grub_usb_err_t
|
||||||
|
grub_usb_root_hub (grub_usb_controller_t controller);
|
||||||
|
|
||||||
|
|
||||||
|
/* XXX: All handled by libusb for now. */
|
||||||
|
struct grub_usb_controller_dev
|
||||||
|
{
|
||||||
|
/* The device name. */
|
||||||
|
const char *name;
|
||||||
|
|
||||||
|
int (*iterate) (int (*hook) (grub_usb_controller_t dev));
|
||||||
|
|
||||||
|
grub_usb_err_t (*transfer) (grub_usb_controller_t dev,
|
||||||
|
grub_usb_transfer_t transfer);
|
||||||
|
|
||||||
|
int (*hubports) (grub_usb_controller_t dev);
|
||||||
|
|
||||||
|
grub_err_t (*portstatus) (grub_usb_controller_t dev, unsigned int port,
|
||||||
|
unsigned int enable);
|
||||||
|
|
||||||
|
grub_usb_speed_t (*detect_dev) (grub_usb_controller_t dev, int port);
|
||||||
|
|
||||||
|
/* The next host controller. */
|
||||||
|
struct grub_usb_controller_dev *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct grub_usb_controller
|
||||||
|
{
|
||||||
|
/* The underlying USB Host Controller device. */
|
||||||
|
grub_usb_controller_dev_t dev;
|
||||||
|
|
||||||
|
/* Data used by the USB Host Controller Driver. */
|
||||||
|
void *data;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct grub_usb_interface
|
||||||
|
{
|
||||||
|
struct grub_usb_desc_if *descif;
|
||||||
|
|
||||||
|
struct grub_usb_desc_endp *descendp;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct grub_usb_configuration
|
||||||
|
{
|
||||||
|
/* Configuration descriptors . */
|
||||||
|
struct grub_usb_desc_config *descconf;
|
||||||
|
|
||||||
|
/* Interfaces associated to this configuration. */
|
||||||
|
struct grub_usb_interface interf[32];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct grub_usb_device
|
||||||
|
{
|
||||||
|
/* The device descriptor of this device. */
|
||||||
|
struct grub_usb_desc_device descdev;
|
||||||
|
|
||||||
|
/* The controller the device is connected to. */
|
||||||
|
struct grub_usb_controller controller;
|
||||||
|
|
||||||
|
/* Device configurations (after opening the device). */
|
||||||
|
struct grub_usb_configuration config[8];
|
||||||
|
|
||||||
|
/* Device address. */
|
||||||
|
int addr;
|
||||||
|
|
||||||
|
/* Device speed. */
|
||||||
|
grub_usb_speed_t speed;
|
||||||
|
|
||||||
|
/* All desciptors are read if this is set to 1. */
|
||||||
|
int initialized;
|
||||||
|
|
||||||
|
/* Data toggle values (used for bulk transfers only). */
|
||||||
|
int toggle[16];
|
||||||
|
|
||||||
|
/* Device-specific data. */
|
||||||
|
void *data;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
GRUB_USB_CLASS_NOTHERE,
|
||||||
|
GRUB_USB_CLASS_AUDIO,
|
||||||
|
GRUB_USB_CLASS_COMMUNICATION,
|
||||||
|
GRUB_USB_CLASS_HID,
|
||||||
|
GRUB_USB_CLASS_XXX,
|
||||||
|
GRUB_USB_CLASS_PHYSICAL,
|
||||||
|
GRUB_USB_CLASS_IMAGE,
|
||||||
|
GRUB_USB_CLASS_PRINTER,
|
||||||
|
GRUB_USB_CLASS_MASS_STORAGE,
|
||||||
|
GRUB_USB_CLASS_HUB,
|
||||||
|
GRUB_USB_CLASS_DATA_INTERFACE,
|
||||||
|
GRUB_USB_CLASS_SMART_CARD,
|
||||||
|
GRUB_USB_CLASS_CONTENT_SECURITY,
|
||||||
|
GRUB_USB_CLASS_VIDEO
|
||||||
|
} grub_usb_classes_t;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
GRUB_USBMS_SUBCLASS_BULK = 0x06
|
||||||
|
} grub_usbms_subclass_t;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
GRUB_USBMS_PROTOCOL_BULK = 0x50
|
||||||
|
} grub_usbms_protocol_t;
|
||||||
|
|
||||||
|
static inline struct grub_usb_desc_if *
|
||||||
|
grub_usb_get_config_interface (struct grub_usb_desc_config *config)
|
||||||
|
{
|
||||||
|
struct grub_usb_desc_if *interf;
|
||||||
|
|
||||||
|
interf = (struct grub_usb_desc_if *) (sizeof (*config) + (char *) config);
|
||||||
|
return interf;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* GRUB_USB_H */
|
119
include/grub/usbdesc.h
Normal file
119
include/grub/usbdesc.h
Normal file
|
@ -0,0 +1,119 @@
|
||||||
|
/*
|
||||||
|
* GRUB -- GRand Unified Bootloader
|
||||||
|
* Copyright (C) 2008 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* GRUB 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 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* GRUB 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 GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef GRUB_USBDESC_H
|
||||||
|
#define GRUB_USBDESC_H 1
|
||||||
|
|
||||||
|
#include <grub/types.h>
|
||||||
|
#include <grub/symbol.h>
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
GRUB_USB_DESCRIPTOR_DEVICE = 1,
|
||||||
|
GRUB_USB_DESCRIPTOR_CONFIG,
|
||||||
|
GRUB_USB_DESCRIPTOR_STRING,
|
||||||
|
GRUB_USB_DESCRIPTOR_INTERFACE,
|
||||||
|
GRUB_USB_DESCRIPTOR_ENDPOINT,
|
||||||
|
GRUB_USB_DESCRIPTOR_HUB = 0x29
|
||||||
|
} grub_usb_descriptor_t;
|
||||||
|
|
||||||
|
struct grub_usb_desc_device
|
||||||
|
{
|
||||||
|
grub_uint8_t length;
|
||||||
|
grub_uint8_t type;
|
||||||
|
grub_uint16_t usbrel;
|
||||||
|
grub_uint8_t class;
|
||||||
|
grub_uint8_t subclass;
|
||||||
|
grub_uint8_t protocol;
|
||||||
|
grub_uint8_t maxsize0;
|
||||||
|
grub_uint16_t vendorid;
|
||||||
|
grub_uint16_t prodid;
|
||||||
|
grub_uint16_t devrel;
|
||||||
|
grub_uint8_t strvendor;
|
||||||
|
grub_uint8_t strprod;
|
||||||
|
grub_uint8_t strserial;
|
||||||
|
grub_uint8_t configcnt;
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
struct grub_usb_desc_config
|
||||||
|
{
|
||||||
|
grub_uint8_t length;
|
||||||
|
grub_uint8_t type;
|
||||||
|
grub_uint16_t totallen;
|
||||||
|
grub_uint8_t numif;
|
||||||
|
grub_uint8_t config;
|
||||||
|
grub_uint8_t strconfig;
|
||||||
|
grub_uint8_t attrib;
|
||||||
|
grub_uint8_t maxpower;
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
struct grub_usb_desc_ifassosiation
|
||||||
|
{
|
||||||
|
grub_uint8_t length;
|
||||||
|
grub_uint8_t type;
|
||||||
|
grub_uint8_t firstif;
|
||||||
|
grub_uint8_t ifcnt;
|
||||||
|
grub_uint8_t class;
|
||||||
|
grub_uint8_t subclass;
|
||||||
|
grub_uint8_t protocol;
|
||||||
|
grub_uint8_t function;
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct grub_usb_desc_if
|
||||||
|
{
|
||||||
|
grub_uint8_t length;
|
||||||
|
grub_uint8_t type;
|
||||||
|
grub_uint8_t ifnum;
|
||||||
|
grub_uint8_t altsetting;
|
||||||
|
grub_uint8_t endpointcnt;
|
||||||
|
grub_uint8_t class;
|
||||||
|
grub_uint8_t subclass;
|
||||||
|
grub_uint8_t protocol;
|
||||||
|
grub_uint8_t strif;
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
struct grub_usb_desc_endp
|
||||||
|
{
|
||||||
|
grub_uint8_t length;
|
||||||
|
grub_uint8_t type;
|
||||||
|
grub_uint8_t endp_addr;
|
||||||
|
grub_uint8_t attrib;
|
||||||
|
grub_uint16_t maxpacket;
|
||||||
|
grub_uint8_t interval;
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
struct grub_usb_desc_str
|
||||||
|
{
|
||||||
|
grub_uint8_t length;
|
||||||
|
grub_uint8_t type;
|
||||||
|
grub_uint16_t str[0];
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
struct grub_usb_usb_hubdesc
|
||||||
|
{
|
||||||
|
grub_uint8_t length;
|
||||||
|
grub_uint8_t type;
|
||||||
|
grub_uint8_t portcnt;
|
||||||
|
grub_uint16_t characteristics;
|
||||||
|
grub_uint8_t pwdgood;
|
||||||
|
grub_uint8_t current;
|
||||||
|
/* Removable and power control bits follow. */
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
#endif /* GRUB_USBDESC_H */
|
107
include/grub/usbtrans.h
Normal file
107
include/grub/usbtrans.h
Normal file
|
@ -0,0 +1,107 @@
|
||||||
|
/*
|
||||||
|
* GRUB -- GRand Unified Bootloader
|
||||||
|
* Copyright (C) 2008 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* GRUB 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 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* GRUB 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 GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef GRUB_USBTRANS_H
|
||||||
|
#define GRUB_USBTRANS_H 1
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
GRUB_USB_TRANSFER_TYPE_IN,
|
||||||
|
GRUB_USB_TRANSFER_TYPE_OUT,
|
||||||
|
GRUB_USB_TRANSFER_TYPE_SETUP
|
||||||
|
} grub_transfer_type_t;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
GRUB_USB_TRANSACTION_TYPE_CONTROL,
|
||||||
|
GRUB_USB_TRANSACTION_TYPE_BULK
|
||||||
|
} grub_transaction_type_t;
|
||||||
|
|
||||||
|
struct grub_usb_transaction
|
||||||
|
{
|
||||||
|
int size;
|
||||||
|
int toggle;
|
||||||
|
grub_transfer_type_t pid;
|
||||||
|
char *data;
|
||||||
|
};
|
||||||
|
typedef struct grub_usb_transaction *grub_usb_transaction_t;
|
||||||
|
|
||||||
|
struct grub_usb_transfer
|
||||||
|
{
|
||||||
|
int devaddr;
|
||||||
|
|
||||||
|
int endpoint;
|
||||||
|
|
||||||
|
int size;
|
||||||
|
|
||||||
|
int transcnt;
|
||||||
|
|
||||||
|
int max;
|
||||||
|
|
||||||
|
grub_transaction_type_t type;
|
||||||
|
|
||||||
|
struct grub_usb_device *dev;
|
||||||
|
|
||||||
|
struct grub_usb_transaction *transactions;
|
||||||
|
};
|
||||||
|
typedef struct grub_usb_transfer *grub_usb_transfer_t;
|
||||||
|
|
||||||
|
|
||||||
|
#define GRUB_USB_REQTYPE_IN (1 << 7)
|
||||||
|
#define GRUB_USB_REQTYPE_OUT (0 << 7)
|
||||||
|
#define GRUB_USB_REQTYPE_STANDARD (0 << 5)
|
||||||
|
#define GRUB_USB_REQTYPE_CLASS (1 << 5)
|
||||||
|
#define GRUB_USB_REQTYPE_VENDOR (2 << 5)
|
||||||
|
#define GRUB_USB_REQTYPE_TARGET_DEV (0 << 0)
|
||||||
|
#define GRUB_USB_REQTYPE_TARGET_INTERF (1 << 0)
|
||||||
|
#define GRUB_USB_REQTYPE_TARGET_ENDP (2 << 0)
|
||||||
|
#define GRUB_USB_REQTYPE_TARGET_OTHER (3 << 0)
|
||||||
|
|
||||||
|
#define GRUB_USB_REQ_GET_STATUS 0x00
|
||||||
|
#define GRUB_USB_REQ_CLEAR_FEATURE 0x01
|
||||||
|
#define GRUB_USB_REQ_SET_FEATURE 0x03
|
||||||
|
#define GRUB_USB_REQ_SET_ADDRESS 0x05
|
||||||
|
#define GRUB_USB_REQ_GET_DESCRIPTOR 0x06
|
||||||
|
#define GRUB_USB_REQ_SET_DESCRIPTOR 0x07
|
||||||
|
#define GRUB_USB_REQ_GET_CONFIGURATION 0x08
|
||||||
|
#define GRUB_USB_REQ_SET_CONFIGURATION 0x09
|
||||||
|
#define GRUB_USB_REQ_GET_INTERFACE 0x0A
|
||||||
|
#define GRUB_USB_REQ_SET_INTERFACE 0x0B
|
||||||
|
#define GRUB_USB_REQ_SYNC_FRAME 0x0C
|
||||||
|
|
||||||
|
#define GRUB_USB_REQ_HUB_GET_PORT_STATUS 0x00
|
||||||
|
|
||||||
|
#define GRUB_USB_FEATURE_ENDP_HALT 0x01
|
||||||
|
#define GRUB_USB_FEATURE_DEV_REMOTE_WU 0x02
|
||||||
|
#define GRUB_USB_FEATURE_TEST_MODE 0x04
|
||||||
|
|
||||||
|
#define GRUB_USB_HUB_STATUS_CONNECTED (1 << 0)
|
||||||
|
#define GRUB_USB_HUB_STATUS_LOWSPEED (1 << 9)
|
||||||
|
#define GRUB_USB_HUB_STATUS_HIGHSPEED (1 << 10)
|
||||||
|
|
||||||
|
struct grub_usb_packet_setup
|
||||||
|
{
|
||||||
|
grub_uint8_t reqtype;
|
||||||
|
grub_uint8_t request;
|
||||||
|
grub_uint16_t value;
|
||||||
|
grub_uint16_t index;
|
||||||
|
grub_uint16_t length;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* GRUB_USBTRANS_H */
|
|
@ -187,6 +187,10 @@ main (int argc, char *argv[])
|
||||||
/* XXX: This is a bit unportable. */
|
/* XXX: This is a bit unportable. */
|
||||||
grub_util_biosdisk_init (dev_map);
|
grub_util_biosdisk_init (dev_map);
|
||||||
|
|
||||||
|
#if HAVE_USB_H
|
||||||
|
grub_libusb_init ();
|
||||||
|
#endif
|
||||||
|
|
||||||
grub_init_all ();
|
grub_init_all ();
|
||||||
|
|
||||||
/* Make sure that there is a root device. */
|
/* Make sure that there is a root device. */
|
||||||
|
|
191
util/usb.c
Normal file
191
util/usb.c
Normal file
|
@ -0,0 +1,191 @@
|
||||||
|
/* usb.c -- libusb USB support for GRUB. */
|
||||||
|
/*
|
||||||
|
* GRUB -- GRand Unified Bootloader
|
||||||
|
* Copyright (C) 2008 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* GRUB 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 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* GRUB 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 GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
#include <grub/misc.h>
|
||||||
|
#include <grub/mm.h>
|
||||||
|
#include <usb.h>
|
||||||
|
#include <grub/usb.h>
|
||||||
|
#include <grub/dl.h>
|
||||||
|
|
||||||
|
|
||||||
|
static struct grub_usb_controller_dev usb_controller =
|
||||||
|
{
|
||||||
|
.name = "libusb"
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct grub_usb_device *grub_usb_devs[128];
|
||||||
|
|
||||||
|
struct usb_bus *busses;
|
||||||
|
|
||||||
|
static grub_err_t
|
||||||
|
grub_libusb_devices (void)
|
||||||
|
|
||||||
|
{
|
||||||
|
struct usb_bus *bus;
|
||||||
|
int last = 0;
|
||||||
|
|
||||||
|
busses = usb_get_busses();
|
||||||
|
|
||||||
|
for (bus = busses; bus; bus = bus->next)
|
||||||
|
{
|
||||||
|
struct usb_device *usbdev;
|
||||||
|
struct grub_usb_device *dev;
|
||||||
|
|
||||||
|
for (usbdev = bus->devices; usbdev; usbdev = usbdev->next)
|
||||||
|
{
|
||||||
|
struct usb_device_descriptor *desc = &usbdev->descriptor;
|
||||||
|
|
||||||
|
if (! desc->bcdUSB)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
dev = grub_malloc (sizeof (*dev));
|
||||||
|
if (! dev)
|
||||||
|
return grub_errno;
|
||||||
|
|
||||||
|
dev->data = usbdev;
|
||||||
|
|
||||||
|
/* Fill in all descriptors. */
|
||||||
|
grub_usb_device_initialize (dev);
|
||||||
|
|
||||||
|
/* Register the device. */
|
||||||
|
grub_usb_devs[last++] = dev;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return GRUB_USB_ERR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
grub_err_t
|
||||||
|
grub_libusb_init (void)
|
||||||
|
{
|
||||||
|
usb_init();
|
||||||
|
usb_find_busses();
|
||||||
|
usb_find_devices();
|
||||||
|
|
||||||
|
if (grub_libusb_devices ())
|
||||||
|
return grub_errno;
|
||||||
|
|
||||||
|
grub_usb_controller_dev_register (&usb_controller);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
grub_err_t
|
||||||
|
grub_libusb_fini (void)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
grub_usb_iterate (int (*hook) (grub_usb_device_t dev))
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < 128; i++)
|
||||||
|
{
|
||||||
|
if (grub_usb_devs[i])
|
||||||
|
{
|
||||||
|
if (hook (grub_usb_devs[i]))
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
grub_usb_err_t
|
||||||
|
grub_usb_root_hub (grub_usb_controller_t controller __attribute__((unused)))
|
||||||
|
{
|
||||||
|
return GRUB_USB_ERR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
grub_usb_err_t
|
||||||
|
grub_usb_control_msg (grub_usb_device_t dev, grub_uint8_t reqtype,
|
||||||
|
grub_uint8_t request, grub_uint16_t value,
|
||||||
|
grub_uint16_t index, grub_size_t size, char *data)
|
||||||
|
{
|
||||||
|
usb_dev_handle *devh;
|
||||||
|
struct usb_device *d = dev->data;
|
||||||
|
|
||||||
|
devh = usb_open (d);
|
||||||
|
if (usb_control_msg (devh, reqtype, request,
|
||||||
|
value, index, data, size, 20) < 0)
|
||||||
|
{
|
||||||
|
usb_close (devh);
|
||||||
|
return GRUB_USB_ERR_STALL;
|
||||||
|
}
|
||||||
|
|
||||||
|
usb_close (devh);
|
||||||
|
|
||||||
|
return GRUB_USB_ERR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
grub_usb_err_t
|
||||||
|
grub_usb_bulk_read (grub_usb_device_t dev,
|
||||||
|
int endpoint, grub_size_t size, char *data)
|
||||||
|
{
|
||||||
|
usb_dev_handle *devh;
|
||||||
|
struct usb_device *d = dev->data;
|
||||||
|
|
||||||
|
devh = usb_open (d);
|
||||||
|
if (usb_claim_interface (devh, 0) < 1)
|
||||||
|
{
|
||||||
|
usb_close (devh);
|
||||||
|
return GRUB_USB_ERR_STALL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (usb_bulk_read (devh, endpoint, data, size, 20) < 1)
|
||||||
|
{
|
||||||
|
usb_close (devh);
|
||||||
|
return GRUB_USB_ERR_STALL;
|
||||||
|
}
|
||||||
|
|
||||||
|
usb_release_interface (devh, 0);
|
||||||
|
usb_close (devh);
|
||||||
|
|
||||||
|
return GRUB_USB_ERR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
grub_usb_err_t
|
||||||
|
grub_usb_bulk_write (grub_usb_device_t dev,
|
||||||
|
int endpoint, grub_size_t size, char *data)
|
||||||
|
{
|
||||||
|
usb_dev_handle *devh;
|
||||||
|
struct usb_device *d = dev->data;
|
||||||
|
|
||||||
|
devh = usb_open (d);
|
||||||
|
if (usb_claim_interface (devh, 0) < 0)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
if (usb_bulk_write (devh, endpoint, data, size, 20) < 0)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
if (usb_release_interface (devh, 0) < 0)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
usb_close (devh);
|
||||||
|
|
||||||
|
return GRUB_USB_ERR_NONE;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
usb_close (devh);
|
||||||
|
return GRUB_USB_ERR_STALL;
|
||||||
|
}
|
Loading…
Reference in a new issue