merge with mainline

This commit is contained in:
BVK Chaitanya 2010-07-18 21:34:03 +05:30
commit 502cddef68
19 changed files with 1544 additions and 560 deletions

112
ChangeLog
View file

@ -1,3 +1,115 @@
2010-07-17 Aleš Nesrsta <starous@volny.cz>
Hotplugging and USB hub support.
* bus/usb/ohci.c (grub_ohci_td): Add convenience fields.
(grub_ohci): Likewise.
(GRUB_OHCI_REG_CONTROL_BULK_ENABLE): New definition.
(GRUB_OHCI_REG_CONTROL_CONTROL_ENABLE): Likewise.
(GRUB_OHCI_RESET_CONNECT_CHANGE): Likewise.
(GRUB_OHCI_CTRL_EDS): Likewise.
(GRUB_OHCI_BULK_EDS): Likewise.
(GRUB_OHCI_TDS): Likewise.
(GRUB_OHCI_ED_ADDR_MASK): Likewise.
(grub_ohci_ed_phys2virt): New function.
(grub_ohci_virt_to_phys): Likewise.
(grub_ohci_td_phys2virt): Likewise.
(grub_ohci_td_virt2phys): Likewise.
(grub_ohci_pci_iter): Allocate memory and don't wait for stable
attachment.
(grub_ohci_find_ed): New function.
(grub_ohci_alloc_td): Likewise.
(grub_ohci_free_td): Likewise.
(grub_ohci_free_tds): Likewise.
(grub_ohci_transfer): Use previously allocated memory.
(grub_ohci_portstatus): Reset status changed bit.
(grub_ohci_detect_dev): Supply status changed.
(grub_ohci_fini_hw): Free memory.
(grub_ohci_restore_hw): Reallocate memory.
* bus/usb/uhci.c (grub_uhci_portstatus): Don't reset on disable.
Reset status change.
(grub_uhci_detect_dev): Supply status_change.
* bus/usb/usb.c (attach_hooks): New var.
(grub_usb_device_attach): New function.
(grub_usb_register_attach_hook_class): Likewise.
(grub_usb_unregister_attach_hook_class): Likewise.
* bus/usb/usbhub.c (grub_usb_hub_add_dev): Handle errors correctly.
(grub_usb_add_hub): Reset connection changed bit.
(attach_root_port): New function.
(grub_usb_root_hub): Likewise.
(poll_nonroot_hub): Likewise.
(grub_usb_poll_devices): Likewise.
* commands/usbtest.c (grub_cmd_usbtest): Poll devices before listing.
* disk/usbms.c (grub_usbms_open): Use device hooks.
(grub_usbms_iterate) :Poll devices.
(grub_usbms_finddevs): Split into ...
(grub_usbms_attach): ... this ...
(grub_usbms_attach): ... and this.
* include/grub/usb.h (grub_usb_controller_dev): Supply status_changed
in detect_dev.
(grub_usb_interface): New fields attached and detach_hook.
(grub_usb_attach_hook_class): New type.
(grub_usb_attach_desc): New struct.
(grub_usb_register_attach_hook_class): New function.
(grub_usb_unregister_attach_hook_class): Likewise.
(grub_usb_poll_devices): Likewise.
(grub_usb_device_attach): Likewise.
* include/grub/usbtrans.h (GRUB_USB_HUB_FEATURE_C_CONNECTED): New const.
(GRUB_USB_HUB_STATUS_C_CONNECTED): Likewise.
2010-07-17 Vladimir Serbinenko <phcoder@gmail.com>
* include/grub/bsdlabel.h (GRUB_PC_PARTITION_BSD_LABEL_WHOLE_DISK_PARTITION): New definition.
* partmap/bsdlabel.c (bsdlabel_partition_map_iterate): Use FreeBSD
delta determination style. Works with most NetBSD partitions too.
2010-07-17 Vladimir Serbinenko <phcoder@gmail.com>
* kern/partition.c [GRUB_UTIL]: Add missing util/misc.h inclusion.
* partmap/bsdlabel.c [GRUB_UTIL]: Likewise.
2010-07-17 Vladimir Serbinenko <phcoder@gmail.com>
* disk/scsi.c (grub_scsi_open): Fix incorrect pointer dereference.
2010-07-14 Anton Blanchard <anton@samba.org>
* loader/powerpc/ieee1275/linux.c (grub_cmd_linux): Do not reject
ET_DYN files.
2010-07-14 Grégoire Sutre <gregoire.sutre@gmail.com>
* Makefile.in: Use the substituted @USE_NLS@ instead of ENABLE_NLS.
2010-07-14 Grégoire Sutre <gregoire.sutre@gmail.com>
* kern/partition.c (grub_partition_check_containment): New function to
check that a partition is physically contained in a parent. Since
offsets are relative (and non-negative), this reduces to checking that
the partition ends before its parent.
(grub_partition_map_probe): Discard out-of-range sub-partitions.
(grub_partition_iterate): Likewise.
* include/grub/partition.h (grub_partition_map): Slightly more detailed
comments.
* partmap/bsdlabel.c (bsdlabel_partition_map_iterate): Discard
partitions that start before their parent, and add debug printfs.
2010-07-13 Colin Watson <cjwatson@ubuntu.com>
* Makefile.in (.SUFFIX): Spell correctly, as ...
(.SUFFIXES): ... this. Fixes bug where `make foo' (where foo is a
bare module name without `.mod', e.g. `test') tried to invoke a
Modula-2 compiler.
2010-07-13 Colin Watson <cjwatson@ubuntu.com>
* README: Point to the Info manual.
2010-07-13 Jiro SEKIBA <jir@unicus.jp>
* fs/nilfs2.c: fix macro NILFS_2ND_SUPER_BLOCK to calculate
2nd superblock position from partition size.
2010-07-10 Colin Watson <cjwatson@ubuntu.com> 2010-07-10 Colin Watson <cjwatson@ubuntu.com>
* Makefile.in (MAINTAINER_CLEANFILES): Remove * Makefile.in (MAINTAINER_CLEANFILES): Remove

View file

@ -53,7 +53,7 @@ XGETTEXT = @XGETTEXT@
MSGMERGE = @MSGMERGE@ MSGMERGE = @MSGMERGE@
MSGFMT = @MSGFMT@ MSGFMT = @MSGFMT@
ifdef ENABLE_NLS ifeq (@USE_NLS@,yes)
LINGUAS = $(shell for i in $(srcdir)/po/*.po ; do \ LINGUAS = $(shell for i in $(srcdir)/po/*.po ; do \
if test -e $$i ; then echo $$i ; fi ; \ if test -e $$i ; then echo $$i ; fi ; \
done | sed -e "s,.*/po/\(.*\)\.po$$,\1,") done | sed -e "s,.*/po/\(.*\)\.po$$,\1,")
@ -524,8 +524,8 @@ check: all $(UNIT_TESTS) $(FUNCTIONAL_TESTS) $(SCRIPTED_TESTS)
$(builddir)/$$file; \ $(builddir)/$$file; \
done done
.SUFFIX: .SUFFIXES:
.SUFFIX: .c .o .S .d .SUFFIXES: .c .o .S .d
# Regenerate configure and Makefile automatically. # Regenerate configure and Makefile automatically.
$(srcdir)/aclocal.m4: configure.ac acinclude.m4 $(srcdir)/aclocal.m4: configure.ac acinclude.m4

12
README
View file

@ -10,5 +10,13 @@ GRUB 2 data and program files.
Please visit the official web page of GRUB 2, for more information. Please visit the official web page of GRUB 2, for more information.
The URL is <http://www.gnu.org/software/grub/grub.html>. The URL is <http://www.gnu.org/software/grub/grub.html>.
For now, there is not much documentation yet. Please look at the GRUB More extensive documentation is available in the Info manual,
Wiki <http://grub.enbug.org> for testing procedures. accessible using 'info grub' after building and installing GRUB 2.
Please look at the GRUB Wiki <http://grub.enbug.org> for testing
procedures.
There are a number of important user-visible differences from the
first version of GRUB, now known as GRUB Legacy. For a summary, please
see:
info grub Introduction 'Changes from GRUB Legacy'

File diff suppressed because it is too large Load diff

View file

@ -612,8 +612,23 @@ grub_uhci_portstatus (grub_usb_controller_t dev,
status = grub_uhci_readreg16 (u, reg); status = grub_uhci_readreg16 (u, reg);
grub_dprintf ("uhci", "detect=0x%02x\n", status); grub_dprintf ("uhci", "detect=0x%02x\n", status);
if (!enable) /* We don't need reset port */
{
/* Disable the port. */
grub_uhci_writereg16 (u, reg, 0 << 2);
grub_dprintf ("uhci", "waiting for the port to be disabled\n");
endtime = grub_get_time_ms () + 1000;
while ((grub_uhci_readreg16 (u, reg) & (1 << 2)))
if (grub_get_time_ms () > endtime)
return grub_error (GRUB_ERR_IO, "UHCI Timed out");
status = grub_uhci_readreg16 (u, reg);
grub_dprintf ("uhci", ">3detect=0x%02x\n", status);
return GRUB_ERR_NONE;
}
/* Reset the port. */ /* Reset the port. */
grub_uhci_writereg16 (u, reg, enable << 9); grub_uhci_writereg16 (u, reg, 1 << 9);
/* Wait for the reset to complete. XXX: How long exactly? */ /* Wait for the reset to complete. XXX: How long exactly? */
grub_millisleep (50); /* For root hub should be nominaly 50ms */ grub_millisleep (50); /* For root hub should be nominaly 50ms */
@ -623,16 +638,20 @@ grub_uhci_portstatus (grub_usb_controller_t dev,
grub_millisleep (10); grub_millisleep (10);
/* Enable the port. */ /* Enable the port. */
grub_uhci_writereg16 (u, reg, enable << 2); grub_uhci_writereg16 (u, reg, 1 << 2);
grub_millisleep (10); grub_millisleep (10);
grub_dprintf ("uhci", "waiting for the port to be enabled\n"); grub_dprintf ("uhci", "waiting for the port to be enabled\n");
endtime = grub_get_time_ms () + 1000; endtime = grub_get_time_ms () + 1000;
while (! (grub_uhci_readreg16 (u, reg) & (1 << 2))) while (! ((status = grub_uhci_readreg16 (u, reg)) & (1 << 2)))
if (grub_get_time_ms () > endtime) if (grub_get_time_ms () > endtime)
return grub_error (GRUB_ERR_IO, "UHCI Timed out"); return grub_error (GRUB_ERR_IO, "UHCI Timed out");
/* Reset bit Connect Status Change */
grub_uhci_writereg16 (u, reg, status | (1 << 1));
/* Read final port status */
status = grub_uhci_readreg16 (u, reg); status = grub_uhci_readreg16 (u, reg);
grub_dprintf ("uhci", ">3detect=0x%02x\n", status); grub_dprintf ("uhci", ">3detect=0x%02x\n", status);
@ -641,7 +660,7 @@ grub_uhci_portstatus (grub_usb_controller_t dev,
} }
static grub_usb_speed_t static grub_usb_speed_t
grub_uhci_detect_dev (grub_usb_controller_t dev, int port) grub_uhci_detect_dev (grub_usb_controller_t dev, int port, int *changed)
{ {
struct grub_uhci *u = (struct grub_uhci *) dev->data; struct grub_uhci *u = (struct grub_uhci *) dev->data;
int reg; int reg;
@ -661,6 +680,9 @@ grub_uhci_detect_dev (grub_usb_controller_t dev, int port)
grub_dprintf ("uhci", "detect=0x%02x port=%d\n", status, port); grub_dprintf ("uhci", "detect=0x%02x port=%d\n", status, port);
/* Connect Status Change bit - it detects change of connection */
*changed = ((status & (1 << 1)) != 0);
if (! (status & 1)) if (! (status & 1))
return GRUB_USB_SPEED_NONE; return GRUB_USB_SPEED_NONE;
else if (status & (1 << 8)) else if (status & (1 << 8))

View file

@ -21,8 +21,10 @@
#include <grub/mm.h> #include <grub/mm.h>
#include <grub/usb.h> #include <grub/usb.h>
#include <grub/misc.h> #include <grub/misc.h>
#include <grub/list.h>
static grub_usb_controller_dev_t grub_usb_list; static grub_usb_controller_dev_t grub_usb_list;
struct grub_usb_attach_desc *attach_hooks;
void void
grub_usb_controller_dev_register (grub_usb_controller_dev_t usb) grub_usb_controller_dev_register (grub_usb_controller_dev_t usb)
@ -232,3 +234,75 @@ grub_usb_device_initialize (grub_usb_device_t dev)
return err; return err;
} }
void grub_usb_device_attach (grub_usb_device_t dev)
{
int i;
/* XXX: Just check configuration 0 for now. */
for (i = 0; i < dev->config[0].descconf->numif; i++)
{
struct grub_usb_desc_if *interf;
struct grub_usb_attach_desc *desc;
interf = dev->config[0].interf[i].descif;
grub_dprintf ("usb", "iterate: interf=%d, class=%d, subclass=%d, protocol=%d\n",
i, interf->class, interf->subclass, interf->protocol);
if (dev->config[0].interf[i].attached)
continue;
for (desc = attach_hooks; desc; desc = desc->next)
if (interf->class == desc->class && desc->hook (dev, 0, i))
dev->config[0].interf[i].attached = 1;
}
}
void
grub_usb_register_attach_hook_class (struct grub_usb_attach_desc *desc)
{
auto int usb_iterate (grub_usb_device_t dev);
int usb_iterate (grub_usb_device_t usbdev)
{
struct grub_usb_desc_device *descdev = &usbdev->descdev;
int i;
if (descdev->class != 0 || descdev->subclass || descdev->protocol != 0
|| descdev->configcnt == 0)
return 0;
/* XXX: Just check configuration 0 for now. */
for (i = 0; i < usbdev->config[0].descconf->numif; i++)
{
struct grub_usb_desc_if *interf;
interf = usbdev->config[0].interf[i].descif;
grub_dprintf ("usb", "iterate: interf=%d, class=%d, subclass=%d, protocol=%d\n",
i, interf->class, interf->subclass, interf->protocol);
if (usbdev->config[0].interf[i].attached)
continue;
if (interf->class != desc->class)
continue;
if (desc->hook (usbdev, 0, i))
usbdev->config[0].interf[i].attached = 1;
}
return 0;
}
desc->next = attach_hooks;
attach_hooks = desc;
grub_usb_iterate (usb_iterate);
}
void
grub_usb_unregister_attach_hook_class (struct grub_usb_attach_desc *desc)
{
grub_list_remove (GRUB_AS_LIST_P (&attach_hooks), GRUB_AS_LIST (desc));
}

View file

@ -23,8 +23,21 @@
#include <grub/misc.h> #include <grub/misc.h>
#include <grub/time.h> #include <grub/time.h>
#define GRUB_USBHUB_MAX_DEVICES 128
/* USB Supports 127 devices, with device 0 as special case. */ /* USB Supports 127 devices, with device 0 as special case. */
static struct grub_usb_device *grub_usb_devs[128]; static struct grub_usb_device *grub_usb_devs[GRUB_USBHUB_MAX_DEVICES];
struct grub_usb_hub
{
struct grub_usb_hub *next;
grub_usb_controller_t controller;
int nports;
grub_usb_speed_t *speed;
grub_usb_device_t dev;
};
struct grub_usb_hub *hubs;
/* Add a device that currently has device number 0 and resides on /* Add a device that currently has device number 0 and resides on
CONTROLLER, the Hub reported that the device speed is SPEED. */ CONTROLLER, the Hub reported that the device speed is SPEED. */
@ -33,6 +46,7 @@ grub_usb_hub_add_dev (grub_usb_controller_t controller, grub_usb_speed_t speed)
{ {
grub_usb_device_t dev; grub_usb_device_t dev;
int i; int i;
grub_usb_err_t err;
dev = grub_zalloc (sizeof (struct grub_usb_device)); dev = grub_zalloc (sizeof (struct grub_usb_device));
if (! dev) if (! dev)
@ -41,31 +55,51 @@ grub_usb_hub_add_dev (grub_usb_controller_t controller, grub_usb_speed_t speed)
dev->controller = *controller; dev->controller = *controller;
dev->speed = speed; dev->speed = speed;
grub_usb_device_initialize (dev); err = grub_usb_device_initialize (dev);
if (err)
{
grub_free (dev);
return NULL;
}
/* Assign a new address to the device. */ /* Assign a new address to the device. */
for (i = 1; i < 128; i++) for (i = 1; i < GRUB_USBHUB_MAX_DEVICES; i++)
{ {
if (! grub_usb_devs[i]) if (! grub_usb_devs[i])
break; break;
} }
if (i == 128) if (i == GRUB_USBHUB_MAX_DEVICES)
{ {
grub_error (GRUB_ERR_IO, "can't assign address to USB device"); grub_error (GRUB_ERR_IO, "can't assign address to USB device");
for (i = 0; i < 8; i++)
grub_free (dev->config[i].descconf);
grub_free (dev);
return NULL; return NULL;
} }
grub_usb_control_msg (dev, err = grub_usb_control_msg (dev,
(GRUB_USB_REQTYPE_OUT (GRUB_USB_REQTYPE_OUT
| GRUB_USB_REQTYPE_STANDARD | GRUB_USB_REQTYPE_STANDARD
| GRUB_USB_REQTYPE_TARGET_DEV), | GRUB_USB_REQTYPE_TARGET_DEV),
GRUB_USB_REQ_SET_ADDRESS, GRUB_USB_REQ_SET_ADDRESS,
i, 0, 0, NULL); i, 0, 0, NULL);
if (err)
{
for (i = 0; i < 8; i++)
grub_free (dev->config[i].descconf);
grub_free (dev);
return NULL;
}
dev->addr = i; dev->addr = i;
dev->initialized = 1; dev->initialized = 1;
grub_usb_devs[i] = dev; grub_usb_devs[i] = dev;
/* Wait "recovery interval", spec. says 2ms */
grub_millisleep (2);
grub_usb_device_attach (dev);
return dev; return dev;
} }
@ -181,6 +215,21 @@ grub_usb_add_hub (grub_usb_device_t dev)
if (err || !(status & GRUB_USB_HUB_STATUS_C_PORT_RESET) ) if (err || !(status & GRUB_USB_HUB_STATUS_C_PORT_RESET) )
continue; continue;
/* Wait a recovery time after reset, spec. says 10ms */
grub_millisleep (10);
/* Do reset of connection change bit */
err = grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_OUT
| GRUB_USB_REQTYPE_CLASS
| GRUB_USB_REQTYPE_TARGET_OTHER),
GRUB_USB_REQ_CLEAR_FEATURE,
GRUB_USB_HUB_FEATURE_C_CONNECTED,
i, 0, 0);
/* Just ignore the device if the Hub reports some error */
if (err)
continue;
grub_dprintf ("usb", "Hub port - cleared connection change\n");
/* Add the device and assign a device address to it. */ /* Add the device and assign a device address to it. */
grub_dprintf ("usb", "Call hub_add_dev - port %d\n", i); grub_dprintf ("usb", "Call hub_add_dev - port %d\n", i);
next_dev = grub_usb_hub_add_dev (&dev->controller, speed); next_dev = grub_usb_hub_add_dev (&dev->controller, speed);
@ -196,49 +245,237 @@ grub_usb_add_hub (grub_usb_device_t dev)
return GRUB_ERR_NONE; return GRUB_ERR_NONE;
} }
grub_usb_err_t static void
grub_usb_root_hub (grub_usb_controller_t controller) attach_root_port (grub_usb_controller_t controller, int portno,
grub_usb_speed_t speed)
{ {
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; grub_usb_device_t dev;
grub_err_t err;
/* Disable the port. XXX: Why? */
err = controller->dev->portstatus (controller, portno, 0);
if (err)
return;
/* Enable the port. */ /* Enable the port. */
err = controller->dev->portstatus (controller, i, 1); err = controller->dev->portstatus (controller, portno, 1);
if (err) if (err)
continue; return;
/* Enable the port and create a device. */ /* Enable the port and create a device. */
dev = grub_usb_hub_add_dev (controller, speed); dev = grub_usb_hub_add_dev (controller, speed);
if (! dev) if (! dev)
continue; return;
/* If the device is a Hub, scan it for more devices. */ /* If the device is a Hub, scan it for more devices. */
if (dev->descdev.class == 0x09) if (dev->descdev.class == 0x09)
grub_usb_add_hub (dev); grub_usb_add_hub (dev);
}
grub_usb_err_t
grub_usb_root_hub (grub_usb_controller_t controller)
{
int i;
struct grub_usb_hub *hub;
int changed=0;
hub = grub_malloc (sizeof (*hub));
if (!hub)
return GRUB_USB_ERR_INTERNAL;
hub->next = hubs;
hubs = hub;
hub->controller = grub_malloc (sizeof (*controller));
if (!hub->controller)
{
grub_free (hub);
return GRUB_USB_ERR_INTERNAL;
} }
grub_memcpy (hub->controller, controller, sizeof (*controller));
hub->dev = 0;
/* Query the number of ports the root Hub has. */
hub->nports = controller->dev->hubports (controller);
hub->speed = grub_malloc (sizeof (hub->speed[0]) * hub->nports);
if (!hub->speed)
{
grub_free (hub->controller);
grub_free (hub);
return GRUB_USB_ERR_INTERNAL;
}
for (i = 0; i < hub->nports; i++)
{
hub->speed[i] = controller->dev->detect_dev (hub->controller, i,
&changed);
if (hub->speed[i] != GRUB_USB_SPEED_NONE)
attach_root_port (hub->controller, i, hub->speed[i]);
} }
return GRUB_USB_ERR_NONE; return GRUB_USB_ERR_NONE;
} }
static void
poll_nonroot_hub (grub_usb_device_t dev)
{
struct grub_usb_usb_hubdesc hubdesc;
grub_err_t err;
int i;
grub_uint64_t timeout;
grub_usb_device_t next_dev;
err = 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);
if (err)
return;
/* 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_GET_STATUS,
0, i, sizeof (status), (char *) &status);
/* Just ignore the device if the Hub does not report the
status. */
if (err)
continue;
/* Connected and status of connection changed ? */
if ((status & GRUB_USB_HUB_STATUS_CONNECTED)
&& (status & GRUB_USB_HUB_STATUS_C_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.
* Now do reset of port. */
err = grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_OUT
| GRUB_USB_REQTYPE_CLASS
| GRUB_USB_REQTYPE_TARGET_OTHER),
GRUB_USB_REQ_SET_FEATURE,
GRUB_USB_HUB_FEATURE_PORT_RESET,
i, 0, 0);
/* If the Hub does not cooperate for this port, just skip
the port. */
if (err)
continue;
/* Wait for reset procedure done */
timeout = grub_get_time_ms () + 1000;
do
{
/* 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_GET_STATUS,
0, i, sizeof (status), (char *) &status);
}
while (!err &&
!(status & GRUB_USB_HUB_STATUS_C_PORT_RESET) &&
(grub_get_time_ms() < timeout) );
if (err || !(status & GRUB_USB_HUB_STATUS_C_PORT_RESET) )
continue;
/* Wait a recovery time after reset, spec. says 10ms */
grub_millisleep (10);
/* Do reset of connection change bit */
err = grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_OUT
| GRUB_USB_REQTYPE_CLASS
| GRUB_USB_REQTYPE_TARGET_OTHER),
GRUB_USB_REQ_CLEAR_FEATURE,
GRUB_USB_HUB_FEATURE_C_CONNECTED,
i, 0, 0);
/* Just ignore the device if the Hub reports some error */
if (err)
continue;
/* Add the device and assign a device address to it. */
next_dev = grub_usb_hub_add_dev (&dev->controller, speed);
if (! next_dev)
continue;
/* If the device is a Hub, scan it for more devices. */
if (next_dev->descdev.class == 0x09)
grub_usb_add_hub (next_dev);
}
}
return;
}
void
grub_usb_poll_devices (void)
{
struct grub_usb_hub *hub;
int i;
for (hub = hubs; hub; hub = hub->next)
{
int changed=0;
/* Do we have to recheck number of ports? */
/* No, it should be never changed, it should be constant. */
for (i = 0; i < hub->nports; i++)
{
grub_usb_speed_t speed;
speed = hub->controller->dev->detect_dev (hub->controller, i,
&changed);
if (speed != GRUB_USB_SPEED_NONE)
{
if (changed)
attach_root_port (hub->controller, i, speed);
}
/* XXX: There should be also handling
* of disconnected devices. */
hub->speed[i] = speed;
}
}
/* We should check changes of non-root hubs too. */
for (i = 0; i < GRUB_USBHUB_MAX_DEVICES; i++)
{
grub_usb_device_t dev = grub_usb_devs[i];
if (dev && dev->descdev.class == 0x09)
{
poll_nonroot_hub (dev);
}
}
}
int int
grub_usb_iterate (int (*hook) (grub_usb_device_t dev)) grub_usb_iterate (int (*hook) (grub_usb_device_t dev))
{ {
int i; int i;
for (i = 0; i < 128; i++) for (i = 0; i < GRUB_USBHUB_MAX_DEVICES; i++)
{ {
if (grub_usb_devs[i]) if (grub_usb_devs[i])
{ {

View file

@ -81,7 +81,7 @@ grub_usb_control_msg (grub_usb_device_t dev,
else else
max = 64; max = 64;
grub_dprintf ("usb", "transfer = %p, dev = %p\n", transfer, dev); grub_dprintf ("usb", "control: transfer = %p, dev = %p\n", transfer, dev);
datablocks = (size + max - 1) / max; datablocks = (size + max - 1) / max;
@ -146,6 +146,7 @@ grub_usb_control_msg (grub_usb_device_t dev,
transfer->transactions[datablocks + 1].toggle = 1; transfer->transactions[datablocks + 1].toggle = 1;
err = dev->controller.dev->transfer (&dev->controller, transfer); err = dev->controller.dev->transfer (&dev->controller, transfer);
grub_dprintf ("usb", "control: err=%d\n", err);
grub_free (transfer->transactions); grub_free (transfer->transactions);
@ -174,6 +175,8 @@ grub_usb_bulk_readwrite (grub_usb_device_t dev,
struct grub_pci_dma_chunk *data_chunk; struct grub_pci_dma_chunk *data_chunk;
grub_size_t size = size0; grub_size_t size = size0;
grub_dprintf ("usb", "bulk: size=0x%02x type=%d\n", size, type);
/* FIXME: avoid allocation any kind of buffer in a first place. */ /* FIXME: avoid allocation any kind of buffer in a first place. */
data_chunk = grub_memalign_dma32 (128, size); data_chunk = grub_memalign_dma32 (128, size);
if (!data_chunk) if (!data_chunk)
@ -248,7 +251,7 @@ grub_usb_bulk_readwrite (grub_usb_device_t dev,
toggle = transfer->transactions[transfer->last_trans].toggle ? 0 : 1; toggle = transfer->transactions[transfer->last_trans].toggle ? 0 : 1;
else else
toggle = dev->toggle[endpoint]; /* Nothing done, take original */ toggle = dev->toggle[endpoint]; /* Nothing done, take original */
grub_dprintf ("usb", "toggle=%d\n", toggle); grub_dprintf ("usb", "bulk: err=%d, toggle=%d\n", err, toggle);
dev->toggle[endpoint] = toggle; dev->toggle[endpoint] = toggle;
grub_free (transfer->transactions); grub_free (transfer->transactions);

View file

@ -194,6 +194,8 @@ grub_cmd_usbtest (grub_command_t cmd __attribute__ ((unused)),
int argc __attribute__ ((unused)), int argc __attribute__ ((unused)),
char **args __attribute__ ((unused))) char **args __attribute__ ((unused)))
{ {
grub_usb_poll_devices ();
grub_printf ("USB devices:\n\n"); grub_printf ("USB devices:\n\n");
grub_usb_iterate (usb_iterate); grub_usb_iterate (usb_iterate);

View file

@ -402,7 +402,7 @@ grub_scsi_open (const char *name, grub_disk_t disk)
if (p->open (bus, scsi)) if (p->open (bus, scsi))
continue; continue;
disk->id = grub_make_scsi_id (scsi->dev->id, bus, lun); disk->id = grub_make_scsi_id (p->id, bus, lun);
disk->data = scsi; disk->data = scsi;
scsi->dev = p; scsi->dev = p;
scsi->lun = lun; scsi->lun = lun;

View file

@ -52,20 +52,19 @@ struct grub_usbms_dev
int luns; int luns;
int config;
int interface; int interface;
struct grub_usb_desc_endp *in; struct grub_usb_desc_endp *in;
struct grub_usb_desc_endp *out; struct grub_usb_desc_endp *out;
int in_maxsz; int in_maxsz;
int out_maxsz; int out_maxsz;
struct grub_usbms_dev *next;
}; };
typedef struct grub_usbms_dev *grub_usbms_dev_t; typedef struct grub_usbms_dev *grub_usbms_dev_t;
static grub_usbms_dev_t grub_usbms_dev_list; /* FIXME: remove limit. */
#define MAX_USBMS_DEVICES 128
static int devcnt; static grub_usbms_dev_t grub_usbms_devices[MAX_USBMS_DEVICES];
static grub_err_t static grub_err_t
grub_usbms_reset (grub_usb_device_t dev, int interface) grub_usbms_reset (grub_usb_device_t dev, int interface)
@ -74,58 +73,53 @@ grub_usbms_reset (grub_usb_device_t dev, int interface)
} }
static void static void
grub_usbms_finddevs (void) grub_usbms_detach (grub_usb_device_t usbdev, int config, int interface)
{ {
auto int usb_iterate (grub_usb_device_t dev); unsigned i;
for (i = 0; i < ARRAY_SIZE (grub_usbms_devices); i++)
int usb_iterate (grub_usb_device_t usbdev) if (grub_usbms_devices[i] && grub_usbms_devices[i]->dev == usbdev
&& grub_usbms_devices[i]->interface == interface
&& grub_usbms_devices[i]->config == config)
{ {
grub_usb_err_t err; grub_free (grub_usbms_devices[i]);
struct grub_usb_desc_device *descdev = &usbdev->descdev; grub_usbms_devices[i] = 0;
int i; }
}
if (descdev->class != 0 || descdev->subclass || descdev->protocol != 0 static int
|| descdev->configcnt == 0) grub_usbms_attach (grub_usb_device_t usbdev, int configno, int interfno)
return 0; {
struct grub_usb_desc_if *interf
/* XXX: Just check configuration 0 for now. */ = usbdev->config[configno].interf[interfno].descif;
for (i = 0; i < usbdev->config[0].descconf->numif; i++)
{
struct grub_usbms_dev *usbms;
struct grub_usb_desc_if *interf;
int j; int j;
grub_uint8_t luns = 0; grub_uint8_t luns = 0;
unsigned curnum;
grub_usb_err_t err;
grub_dprintf ("usbms", "alive\n"); for (curnum = 0; curnum < ARRAY_SIZE (grub_usbms_devices); curnum++)
if (!grub_usbms_devices[curnum])
break;
interf = usbdev->config[0].interf[i].descif; if (curnum == ARRAY_SIZE (grub_usbms_devices))
return 0;
/* If this is not a USB Mass Storage device with a supported interf = usbdev->config[configno].interf[interfno].descif;
protocol, just skip it. */
grub_dprintf ("usbms", "iterate: interf=%d, class=%d, subclass=%d, protocol=%d\n",
i, interf->class, interf->subclass, interf->protocol);
if (interf->class != GRUB_USB_CLASS_MASS_STORAGE if ((interf->subclass != GRUB_USBMS_SUBCLASS_BULK
|| ( interf->subclass != GRUB_USBMS_SUBCLASS_BULK &&
/* Experimental support of RBC, MMC-2, UFI, SFF-8070i devices */ /* Experimental support of RBC, MMC-2, UFI, SFF-8070i devices */
interf->subclass != GRUB_USBMS_SUBCLASS_RBC && && interf->subclass != GRUB_USBMS_SUBCLASS_RBC
interf->subclass != GRUB_USBMS_SUBCLASS_MMC2 && && interf->subclass != GRUB_USBMS_SUBCLASS_MMC2
interf->subclass != GRUB_USBMS_SUBCLASS_UFI && && interf->subclass != GRUB_USBMS_SUBCLASS_UFI
interf->subclass != GRUB_USBMS_SUBCLASS_SFF8070 ) && interf->subclass != GRUB_USBMS_SUBCLASS_SFF8070 )
|| interf->protocol != GRUB_USBMS_PROTOCOL_BULK) || interf->protocol != GRUB_USBMS_PROTOCOL_BULK)
{ return 0;
continue;
}
grub_dprintf ("usbms", "alive\n"); grub_usbms_devices[curnum] = grub_zalloc (sizeof (struct grub_usbms_dev));
if (! grub_usbms_devices[curnum])
return 0;
devcnt++; grub_usbms_devices[curnum]->dev = usbdev;
usbms = grub_zalloc (sizeof (struct grub_usbms_dev)); grub_usbms_devices[curnum]->interface = interfno;
if (! usbms)
return 1;
usbms->dev = usbdev;
usbms->interface = i;
grub_dprintf ("usbms", "alive\n"); grub_dprintf ("usbms", "alive\n");
@ -134,29 +128,30 @@ grub_usbms_finddevs (void)
for (j = 0; j < interf->endpointcnt; j++) for (j = 0; j < interf->endpointcnt; j++)
{ {
struct grub_usb_desc_endp *endp; struct grub_usb_desc_endp *endp;
endp = &usbdev->config[0].interf[i].descendp[j]; endp = &usbdev->config[0].interf[interfno].descendp[j];
if ((endp->endp_addr & 128) && (endp->attrib & 3) == 2) if ((endp->endp_addr & 128) && (endp->attrib & 3) == 2)
{ {
/* Bulk IN endpoint. */ /* Bulk IN endpoint. */
usbms->in = endp; grub_usbms_devices[curnum]->in = endp;
/* Clear Halt is not possible yet! */ /* Clear Halt is not possible yet! */
/* grub_usb_clear_halt (usbdev, endp->endp_addr); */ /* grub_usb_clear_halt (usbdev, endp->endp_addr); */
usbms->in_maxsz = endp->maxpacket; grub_usbms_devices[curnum]->in_maxsz = endp->maxpacket;
} }
else if (!(endp->endp_addr & 128) && (endp->attrib & 3) == 2) else if (!(endp->endp_addr & 128) && (endp->attrib & 3) == 2)
{ {
/* Bulk OUT endpoint. */ /* Bulk OUT endpoint. */
usbms->out = endp; grub_usbms_devices[curnum]->out = endp;
/* Clear Halt is not possible yet! */ /* Clear Halt is not possible yet! */
/* grub_usb_clear_halt (usbdev, endp->endp_addr); */ /* grub_usb_clear_halt (usbdev, endp->endp_addr); */
usbms->out_maxsz = endp->maxpacket; grub_usbms_devices[curnum]->out_maxsz = endp->maxpacket;
} }
} }
if (!usbms->in || !usbms->out) if (!grub_usbms_devices[curnum]->in || !grub_usbms_devices[curnum]->out)
{ {
grub_free (usbms); grub_free (grub_usbms_devices[curnum]);
grub_usbms_devices[curnum] = 0;
return 0; return 0;
} }
@ -166,32 +161,30 @@ grub_usbms_finddevs (void)
grub_usb_set_configuration (usbdev, 1); grub_usb_set_configuration (usbdev, 1);
/* Query the amount of LUNs. */ /* Query the amount of LUNs. */
err = grub_usb_control_msg (usbdev, 0xA1, 254, err = grub_usb_control_msg (usbdev, 0xA1, 254, 0, interfno, 1, (char *) &luns);
0, i, 1, (char *) &luns);
if (err) if (err)
{ {
/* In case of a stall, clear the stall. */ /* In case of a stall, clear the stall. */
if (err == GRUB_USB_ERR_STALL) if (err == GRUB_USB_ERR_STALL)
{ {
grub_usb_clear_halt (usbdev, usbms->in->endp_addr); grub_usb_clear_halt (usbdev, grub_usbms_devices[curnum]->in->endp_addr);
grub_usb_clear_halt (usbdev, usbms->out->endp_addr); grub_usb_clear_halt (usbdev, grub_usbms_devices[curnum]->out->endp_addr);
} }
/* Just set the amount of LUNs to one. */ /* Just set the amount of LUNs to one. */
grub_errno = GRUB_ERR_NONE; grub_errno = GRUB_ERR_NONE;
usbms->luns = 1; grub_usbms_devices[curnum]->luns = 1;
} }
else else
/* luns = 0 means one LUN with ID 0 present ! */ /* luns = 0 means one LUN with ID 0 present ! */
/* We get from device not number of LUNs but highest /* We get from device not number of LUNs but highest
* LUN number. LUNs are numbered from 0, * LUN number. LUNs are numbered from 0,
* i.e. number of LUNs is luns+1 ! */ * i.e. number of LUNs is luns+1 ! */
usbms->luns = luns + 1; grub_usbms_devices[curnum]->luns = luns + 1;
grub_dprintf ("usbms", "alive\n"); grub_dprintf ("usbms", "alive\n");
usbms->next = grub_usbms_dev_list; usbdev->config[configno].interf[interfno].detach_hook = grub_usbms_detach;
grub_usbms_dev_list = usbms;
#if 0 /* All this part should be probably deleted. #if 0 /* All this part should be probably deleted.
* This make trouble on some devices if they are not in * This make trouble on some devices if they are not in
@ -206,17 +199,7 @@ grub_usbms_finddevs (void)
grub_usb_clear_halt (usbdev, usbms->out->endp_addr); grub_usb_clear_halt (usbdev, usbms->out->endp_addr);
#endif #endif
return 0; return 1;
}
grub_dprintf ("usbms", "alive\n");
return 0;
}
grub_dprintf ("usbms", "alive\n");
grub_usb_iterate (usb_iterate);
grub_dprintf ("usbms", "alive\n");
} }
@ -224,14 +207,15 @@ grub_usbms_finddevs (void)
static int static int
grub_usbms_iterate (int (*hook) (int bus, int luns)) grub_usbms_iterate (int (*hook) (int bus, int luns))
{ {
grub_usbms_dev_t p; unsigned i;
int cnt = 0;
for (p = grub_usbms_dev_list; p; p = p->next) grub_usb_poll_devices ();
for (i = 0; i < ARRAY_SIZE (grub_usbms_devices); i++)
if (grub_usbms_devices[i])
{ {
if (hook (cnt, p->luns)) if (hook (i, grub_usbms_devices[i]->luns))
return 1; return 1;
cnt++;
} }
return 0; return 0;
@ -248,7 +232,6 @@ grub_usbms_transfer (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd,
grub_usb_err_t err = GRUB_USB_ERR_NONE; grub_usb_err_t err = GRUB_USB_ERR_NONE;
grub_usb_err_t errCSW = GRUB_USB_ERR_NONE; grub_usb_err_t errCSW = GRUB_USB_ERR_NONE;
int retrycnt = 3 + 1; int retrycnt = 3 + 1;
grub_size_t i;
retry: retry:
retrycnt--; retrycnt--;
@ -304,8 +287,11 @@ grub_usbms_transfer (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd,
/* Debug print of received data. */ /* Debug print of received data. */
grub_dprintf ("usb", "buf:\n"); grub_dprintf ("usb", "buf:\n");
if (size <= 64) if (size <= 64)
for (i=0; i<size; i++) {
grub_dprintf ("usb", "0x%02" PRIxGRUB_SIZE ": 0x%02x\n", i, buf[i]); unsigned i;
for (i = 0; i < size; i++)
grub_dprintf ("usb", "0x%02x: 0x%02x\n", i, buf[i]);
}
else else
grub_dprintf ("usb", "Too much data for debug print...\n"); grub_dprintf ("usb", "Too much data for debug print...\n");
} }
@ -313,7 +299,11 @@ grub_usbms_transfer (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd,
{ {
err = grub_usb_bulk_write (dev->dev, dev->out->endp_addr, size, buf); err = grub_usb_bulk_write (dev->dev, dev->out->endp_addr, size, buf);
grub_dprintf ("usb", "write: %d %d\n", err, GRUB_USB_ERR_STALL); grub_dprintf ("usb", "write: %d %d\n", err, GRUB_USB_ERR_STALL);
grub_dprintf ("usb", "buf:\n"); grub_dprintf ("usb", "First 16 bytes of sent data:\n %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
buf[ 0], buf[ 1], buf[ 2], buf[ 3],
buf[ 4], buf[ 5], buf[ 6], buf[ 7],
buf[ 8], buf[ 9], buf[10], buf[11],
buf[12], buf[13], buf[14], buf[15]);
if (err) if (err)
{ {
if (err == GRUB_USB_ERR_STALL) if (err == GRUB_USB_ERR_STALL)
@ -322,8 +312,11 @@ grub_usbms_transfer (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd,
} }
/* Debug print of sent data. */ /* Debug print of sent data. */
if (size <= 256) if (size <= 256)
{
unsigned i;
for (i=0; i<size; i++) for (i=0; i<size; i++)
grub_dprintf ("usb", "0x%02" PRIxGRUB_SIZE ": 0x%02x\n", i, buf[i]); grub_dprintf ("usb", "0x%02x: 0x%02x\n", i, buf[i]);
}
else else
grub_dprintf ("usb", "Too much data for debug print...\n"); grub_dprintf ("usb", "Too much data for debug print...\n");
} }
@ -393,24 +386,16 @@ grub_usbms_write (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd,
static grub_err_t static grub_err_t
grub_usbms_open (int devnum, struct grub_scsi *scsi) grub_usbms_open (int devnum, struct grub_scsi *scsi)
{ {
grub_usbms_dev_t p; grub_usb_poll_devices ();
int i = 0;
for (p = grub_usbms_dev_list; p; p = p->next)
{
/* Check if this is the devnumth device. */
if (devnum == i)
{
scsi->data = p;
scsi->luns = p->luns;
return GRUB_ERR_NONE;
}
i++;
}
if (!grub_usbms_devices[devnum])
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, return grub_error (GRUB_ERR_UNKNOWN_DEVICE,
"not a USB Mass Storage device"); "unknown USB Mass Storage device");
scsi->data = grub_usbms_devices[devnum];
scsi->luns = grub_usbms_devices[devnum]->luns;
return GRUB_ERR_NONE;
} }
static struct grub_scsi_dev grub_usbms_dev = static struct grub_scsi_dev grub_usbms_dev =
@ -423,13 +408,28 @@ static struct grub_scsi_dev grub_usbms_dev =
.write = grub_usbms_write .write = grub_usbms_write
}; };
struct grub_usb_attach_desc attach_hook =
{
.class = GRUB_USB_CLASS_MASS_STORAGE,
.hook = grub_usbms_attach
};
GRUB_MOD_INIT(usbms) GRUB_MOD_INIT(usbms)
{ {
grub_usbms_finddevs (); grub_usb_register_attach_hook_class (&attach_hook);
grub_scsi_dev_register (&grub_usbms_dev); grub_scsi_dev_register (&grub_usbms_dev);
} }
GRUB_MOD_FINI(usbms) GRUB_MOD_FINI(usbms)
{ {
unsigned i;
for (i = 0; i < ARRAY_SIZE (grub_usbms_devices); i++)
{
grub_usbms_devices[i]->dev->config[grub_usbms_devices[i]->config]
.interf[grub_usbms_devices[i]->interface].detach_hook = 0;
grub_usbms_devices[i]->dev->config[grub_usbms_devices[i]->config]
.interf[grub_usbms_devices[i]->interface].attached = 0;
}
grub_usb_unregister_attach_hook_class (&attach_hook);
grub_scsi_dev_unregister (&grub_usbms_dev); grub_scsi_dev_unregister (&grub_usbms_dev);
} }

View file

@ -52,9 +52,9 @@
/* nilfs 1st super block posission from beginning of the partition /* nilfs 1st super block posission from beginning of the partition
in 512 block size */ in 512 block size */
#define NILFS_1ST_SUPER_BLOCK 2 #define NILFS_1ST_SUPER_BLOCK 2
/* nilfs 2nd super block posission from end of the partition /* nilfs 2nd super block posission from beginning of the partition
in 512 block size */ in 512 block size */
#define NILFS_2ND_SUPER_BLOCK 8 #define NILFS_2ND_SUPER_BLOCK(devsize) (((devsize >> 3) - 1) << 3)
struct grub_nilfs2_inode struct grub_nilfs2_inode
{ {
@ -729,7 +729,7 @@ grub_nilfs2_load_sb (struct grub_nilfs2_data *data)
if (partition_size != GRUB_DISK_SIZE_UNKNOWN) if (partition_size != GRUB_DISK_SIZE_UNKNOWN)
{ {
/* Read second super block. */ /* Read second super block. */
grub_disk_read (disk, partition_size - NILFS_2ND_SUPER_BLOCK, 0, grub_disk_read (disk, NILFS_2ND_SUPER_BLOCK (partition_size), 0,
sizeof (struct grub_nilfs2_super_block), &sb2); sizeof (struct grub_nilfs2_super_block), &sb2);
/* Make sure if 2nd super block is valid. */ /* Make sure if 2nd super block is valid. */
valid[1] = grub_nilfs2_valid_sb (&sb2); valid[1] = grub_nilfs2_valid_sb (&sb2);

View file

@ -63,6 +63,8 @@
#define GRUB_PC_PARTITION_OPENBSD_TYPE_NTFS 18 #define GRUB_PC_PARTITION_OPENBSD_TYPE_NTFS 18
#define GRUB_PC_PARTITION_OPENBSD_TYPE_RAID 19 #define GRUB_PC_PARTITION_OPENBSD_TYPE_RAID 19
#define GRUB_PC_PARTITION_BSD_LABEL_WHOLE_DISK_PARTITION 2
/* The BSD partition entry. */ /* The BSD partition entry. */
struct grub_partition_bsd_entry struct grub_partition_bsd_entry
{ {

View file

@ -48,7 +48,7 @@ struct grub_partition
/* The partition number. */ /* The partition number. */
int number; int number;
/* The start sector. */ /* The start sector (relative to parent). */
grub_disk_addr_t start; grub_disk_addr_t start;
/* The length in sector units. */ /* The length in sector units. */
@ -60,7 +60,7 @@ struct grub_partition
/* The index of this partition in the partition table. */ /* The index of this partition in the partition table. */
int index; int index;
/* Parent partition map. */ /* Parent partition (physically contains this partition). */
struct grub_partition *parent; struct grub_partition *parent;
/* The type partition map. */ /* The type partition map. */

View file

@ -104,7 +104,7 @@ struct grub_usb_controller_dev
grub_err_t (*portstatus) (grub_usb_controller_t dev, unsigned int port, grub_err_t (*portstatus) (grub_usb_controller_t dev, unsigned int port,
unsigned int enable); unsigned int enable);
grub_usb_speed_t (*detect_dev) (grub_usb_controller_t dev, int port); grub_usb_speed_t (*detect_dev) (grub_usb_controller_t dev, int port, int *changed);
/* The next host controller. */ /* The next host controller. */
struct grub_usb_controller_dev *next; struct grub_usb_controller_dev *next;
@ -125,6 +125,13 @@ struct grub_usb_interface
struct grub_usb_desc_if *descif; struct grub_usb_desc_if *descif;
struct grub_usb_desc_endp *descendp; struct grub_usb_desc_endp *descendp;
/* A driver is handling this interface. Do we need to support multiple drivers
for single interface?
*/
int attached;
void (*detach_hook) (struct grub_usb_device *dev, int config, int interface);
}; };
struct grub_usb_configuration struct grub_usb_configuration
@ -207,4 +214,21 @@ grub_usb_get_config_interface (struct grub_usb_desc_config *config)
return interf; return interf;
} }
typedef int (*grub_usb_attach_hook_class) (grub_usb_device_t usbdev,
int configno, int interfno);
struct grub_usb_attach_desc
{
struct grub_usb_attach_desc *next;
int class;
grub_usb_attach_hook_class hook;
};
void grub_usb_register_attach_hook_class (struct grub_usb_attach_desc *desc);
void grub_usb_unregister_attach_hook_class (struct grub_usb_attach_desc *desc);
void grub_usb_poll_devices (void);
void grub_usb_device_attach (grub_usb_device_t dev);
#endif /* GRUB_USB_H */ #endif /* GRUB_USB_H */

View file

@ -93,10 +93,12 @@ typedef struct grub_usb_transfer *grub_usb_transfer_t;
#define GRUB_USB_HUB_FEATURE_PORT_RESET 0x04 #define GRUB_USB_HUB_FEATURE_PORT_RESET 0x04
#define GRUB_USB_HUB_FEATURE_PORT_POWER 0x08 #define GRUB_USB_HUB_FEATURE_PORT_POWER 0x08
#define GRUB_USB_HUB_FEATURE_C_CONNECTED 0x10
#define GRUB_USB_HUB_STATUS_CONNECTED (1 << 0) #define GRUB_USB_HUB_STATUS_CONNECTED (1 << 0)
#define GRUB_USB_HUB_STATUS_LOWSPEED (1 << 9) #define GRUB_USB_HUB_STATUS_LOWSPEED (1 << 9)
#define GRUB_USB_HUB_STATUS_HIGHSPEED (1 << 10) #define GRUB_USB_HUB_STATUS_HIGHSPEED (1 << 10)
#define GRUB_USB_HUB_STATUS_C_CONNECTED (1 << 16)
#define GRUB_USB_HUB_STATUS_C_PORT_RESET (1 << 20) #define GRUB_USB_HUB_STATUS_C_PORT_RESET (1 << 20)
struct grub_usb_packet_setup struct grub_usb_packet_setup

View file

@ -21,8 +21,43 @@
#include <grub/partition.h> #include <grub/partition.h>
#include <grub/disk.h> #include <grub/disk.h>
#ifdef GRUB_UTIL
#include <grub/util/misc.h>
#endif
grub_partition_map_t grub_partition_map_list; grub_partition_map_t grub_partition_map_list;
/*
* Checks that disk->partition contains part. This function assumes that the
* start of part is relative to the start of disk->partition. Returns 1 if
* disk->partition is null.
*/
static int
grub_partition_check_containment (const grub_disk_t disk,
const grub_partition_t part)
{
if (disk->partition == NULL)
return 1;
if (part->start + part->len > disk->partition->len)
{
char *partname;
partname = grub_partition_get_name (disk->partition);
grub_dprintf ("partition", "sub-partition %s%d of (%s,%s) ends after parent.\n",
part->partmap->name, part->number + 1, disk->name, partname);
#ifdef GRUB_UTIL
grub_util_warn ("Discarding improperly nested partition (%s,%s,%s%d)",
disk->name, partname, part->partmap->name, part->number + 1);
#endif
grub_free (partname);
return 0;
}
return 1;
}
static grub_partition_t static grub_partition_t
grub_partition_map_probe (const grub_partition_map_t partmap, grub_partition_map_probe (const grub_partition_map_t partmap,
grub_disk_t disk, int partnum) grub_disk_t disk, int partnum)
@ -31,11 +66,15 @@ grub_partition_map_probe (const grub_partition_map_t partmap,
auto int find_func (grub_disk_t d, const grub_partition_t partition); auto int find_func (grub_disk_t d, const grub_partition_t partition);
int find_func (grub_disk_t d __attribute__ ((unused)), int find_func (grub_disk_t dsk,
const grub_partition_t partition) const grub_partition_t partition)
{ {
if (partnum == partition->number) if (partnum != partition->number)
{ return 0;
if (!(grub_partition_check_containment (dsk, partition)))
return 0;
p = (grub_partition_t) grub_malloc (sizeof (*p)); p = (grub_partition_t) grub_malloc (sizeof (*p));
if (! p) if (! p)
return 1; return 1;
@ -44,9 +83,6 @@ grub_partition_map_probe (const grub_partition_map_t partmap,
return 1; return 1;
} }
return 0;
}
partmap->iterate (disk, find_func); partmap->iterate (disk, find_func);
if (grub_errno) if (grub_errno)
goto fail; goto fail;
@ -138,6 +174,10 @@ grub_partition_iterate (struct grub_disk *disk,
const grub_partition_t partition) const grub_partition_t partition)
{ {
struct grub_partition p = *partition; struct grub_partition p = *partition;
if (!(grub_partition_check_containment (dsk, partition)))
return 0;
p.parent = dsk->partition; p.parent = dsk->partition;
dsk->partition = 0; dsk->partition = 0;
if (hook (dsk, &p)) if (hook (dsk, &p))

View file

@ -220,7 +220,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
if (! elf) if (! elf)
goto out; goto out;
if (elf->ehdr.ehdr32.e_type != ET_EXEC) if (elf->ehdr.ehdr32.e_type != ET_EXEC && elf->ehdr.ehdr32.e_type != ET_DYN)
{ {
grub_error (GRUB_ERR_UNKNOWN_OS, grub_error (GRUB_ERR_UNKNOWN_OS,
"this ELF file is not of the right type"); "this ELF file is not of the right type");

View file

@ -24,6 +24,10 @@
#include <grub/misc.h> #include <grub/misc.h>
#include <grub/dl.h> #include <grub/dl.h>
#ifdef GRUB_UTIL
#include <grub/util/misc.h>
#endif
static struct grub_partition_map grub_bsdlabel_partition_map; static struct grub_partition_map grub_bsdlabel_partition_map;
@ -37,9 +41,6 @@ bsdlabel_partition_map_iterate (grub_disk_t disk,
grub_disk_addr_t delta = 0; grub_disk_addr_t delta = 0;
unsigned pos; unsigned pos;
/* BSDLabel offsets are absolute even when it's embed inside partition. */
delta = grub_partition_get_start (disk->partition);
/* Read the BSD label. */ /* Read the BSD label. */
if (grub_disk_read (disk, GRUB_PC_PARTITION_BSD_LABEL_SECTOR, if (grub_disk_read (disk, GRUB_PC_PARTITION_BSD_LABEL_SECTOR,
0, sizeof (label), &label)) 0, sizeof (label), &label))
@ -49,30 +50,79 @@ bsdlabel_partition_map_iterate (grub_disk_t disk,
if (label.magic != grub_cpu_to_le32 (GRUB_PC_PARTITION_BSD_LABEL_MAGIC)) if (label.magic != grub_cpu_to_le32 (GRUB_PC_PARTITION_BSD_LABEL_MAGIC))
return grub_error (GRUB_ERR_BAD_PART_TABLE, "no signature"); return grub_error (GRUB_ERR_BAD_PART_TABLE, "no signature");
/* A kludge to determine a base of be.offset. */
if (GRUB_PC_PARTITION_BSD_LABEL_WHOLE_DISK_PARTITION
< grub_cpu_to_le16 (label.num_partitions))
{
struct grub_partition_bsd_entry whole_disk_be;
pos = sizeof (label) + GRUB_PC_PARTITION_BSD_LABEL_SECTOR
* GRUB_DISK_SECTOR_SIZE + sizeof (struct grub_partition_bsd_entry)
* GRUB_PC_PARTITION_BSD_LABEL_WHOLE_DISK_PARTITION;
if (grub_disk_read (disk, pos / GRUB_DISK_SECTOR_SIZE,
pos % GRUB_DISK_SECTOR_SIZE, sizeof (whole_disk_be),
&whole_disk_be))
return grub_errno;
delta = grub_le_to_cpu32 (whole_disk_be.offset);
}
pos = sizeof (label) + GRUB_PC_PARTITION_BSD_LABEL_SECTOR pos = sizeof (label) + GRUB_PC_PARTITION_BSD_LABEL_SECTOR
* GRUB_DISK_SECTOR_SIZE; * GRUB_DISK_SECTOR_SIZE;
for (p.number = 0; for (p.number = 0;
p.number < grub_cpu_to_le16 (label.num_partitions); p.number < grub_cpu_to_le16 (label.num_partitions);
p.number++) p.number++, pos += sizeof (struct grub_partition_bsd_entry))
{ {
struct grub_partition_bsd_entry be; struct grub_partition_bsd_entry be;
if (p.number == GRUB_PC_PARTITION_BSD_LABEL_WHOLE_DISK_PARTITION)
continue;
p.offset = pos / GRUB_DISK_SECTOR_SIZE; p.offset = pos / GRUB_DISK_SECTOR_SIZE;
p.index = pos % GRUB_DISK_SECTOR_SIZE; p.index = pos % GRUB_DISK_SECTOR_SIZE;
if (grub_disk_read (disk, p.offset, p.index, sizeof (be), &be)) if (grub_disk_read (disk, p.offset, p.index, sizeof (be), &be))
return grub_errno; return grub_errno;
p.start = grub_le_to_cpu32 (be.offset) - delta; p.start = grub_le_to_cpu32 (be.offset);
p.len = grub_le_to_cpu32 (be.size); p.len = grub_le_to_cpu32 (be.size);
p.partmap = &grub_bsdlabel_partition_map; p.partmap = &grub_bsdlabel_partition_map;
if (be.fs_type != GRUB_PC_PARTITION_BSD_TYPE_UNUSED) grub_dprintf ("partition",
"partition %d: type 0x%x, start 0x%llx, len 0x%llx\n",
p.number, be.fs_type,
(unsigned long long) p.start,
(unsigned long long) p.len);
if (p.len == 0)
continue;
if (p.start < delta)
{
#ifdef GRUB_UTIL
char *partname;
#endif
grub_dprintf ("partition",
"partition %d: invalid start (found 0x%llx, wanted >= 0x%llx)\n",
p.number,
(unsigned long long) p.start,
(unsigned long long) delta);
#ifdef GRUB_UTIL
/* disk->partition != NULL as 0 < delta */
partname = grub_partition_get_name (disk->partition);
grub_util_warn ("Discarding improperly nested partition (%s,%s,%s%d)",
disk->name, partname, p.partmap->name, p.number + 1);
grub_free (partname);
#endif
continue;
}
p.start -= delta;
if (hook (disk, &p)) if (hook (disk, &p))
return grub_errno; return grub_errno;
pos += sizeof (struct grub_partition_bsd_entry);
} }
return GRUB_ERR_NONE; return GRUB_ERR_NONE;