merge with mainline

This commit is contained in:
BVK Chaitanya 2010-07-22 22:39:20 +05:30
commit 82e323a3d7
36 changed files with 2198 additions and 723 deletions

View file

@ -1,5 +1,6 @@
00_header 00_header
10_* 10_*
20_linux_xen
30_os-prober 30_os-prober
40_custom 40_custom
41_custom 41_custom

242
ChangeLog
View file

@ -1,3 +1,245 @@
2010-07-20 Colin Watson <cjwatson@ubuntu.com>
* bus/usb/emu/usb.c (grub_usb_poll_devices): Add a dummy
implementation of this so that grub-emu links again, with a note
that this should support hotplugging in the future.
2010-07-20 Colin Watson <cjwatson@ubuntu.com>
* kern/emu/getroot.c (grub_util_get_grub_dev): Use xasprintf.
2010-07-20 Colin Watson <cjwatson@ubuntu.com>
* disk/loopback.c (grub_cmd_loopback): Don't leak a grub_file_t
handle on failure.
(grub_loopback_close): Remove empty function.
(grub_loopback_dev): Remove close method.
2010-07-20 Colin Watson <cjwatson@ubuntu.com>
Disable EFI cursor when the EFI console becomes inactive.
* term/efi/console.c (grub_efi_console_init): New function.
(grub_efi_console_fini): New function.
(grub_console_term_output): Register init and fini methods.
2010-07-20 Vladimir Serbinenko <phcoder@gmail.com>
* tests/util/grub-shell-tester.in: Remove bashism and declare as
sh script.
2010-07-20 Vladimir Serbinenko <phcoder@gmail.com>
* disk/loopback.c (grub_loopback): Replace filename with file.
(delete_loopback): Handle new semantics.
(grub_cmd_loopback): Likewise.
(grub_loopback_iterate): Likewise.
(grub_loopback_close): Likewise.
2010-07-20 Vladimir Serbinenko <phcoder@gmail.com>
* util/i386/efi/grub-install.in: Revert to platform-specific behaviour
with -p "".
Reported by: Tito Keitel.
2010-07-20 Vladimir Serbinenko <phcoder@gmail.com>
* docs/grub.texi (Naming convention): Document new naming convention.
2010-07-20 Vadim Solomin <vadic052@gmail.com>
2010-07-20 Colin Watson <cjwatson@ubuntu.com>
Generate device.map in something closer to the old ordering.
* util/deviceiter.c (struct device): New declaration.
(compare_file_names): Rename to ...
(compare_devices): ... this. Sort by kernel name in preference to
the stable by-id name, but keep the latter as a fallback comparison.
Update header comment.
(grub_util_iterate_devices) [__linux__]: Construct and sort an array
of `struct device' rather than of plain file names.
2010-07-20 Thomas Frauendorfer <Thomas.Frauendorfer@googlemail.com>
* lib/i386/relocator_asm.S [! __x86_64__]: Don't try to disable amd64
on i386.
2010-07-20 Vladimir Serbinenko <phcoder@gmail.com>
* commands/acpi.c (setup_common_tables): Use sizeof instead of
hardcoding size.
(setv1table): Likewise.
2010-07-20 Colin Watson <cjwatson@ubuntu.com>
* disk/raid.c (insert_array): Use md/%s to name mdadm 1.x devices,
removing the homehost if present.
* kern/emu/getroot.c (get_mdadm_name) [__linux__]: New function.
(grub_util_get_grub_dev): Use md/%s to name mdadm 1.x devices,
removing the homehost if present.
(grub_util_get_grub_dev) [__linux__]: Get the array name from mdadm
if possible.
* util/i386/pc/grub-setup.c (main): Handle md/* devices.
* disk/dmraid_nvidia.c (grub_dmraid_nv_detect): Add start_sector
parameter. Set its pointer target to 0.
* disk/mdraid_linux.c (grub_mdraid_detect): Add start_sector
parameter. Set its pointer target to 0 for 0.9 metadata, or to the
`data_offset' value from the superblock for 1.x metadata.
* disk/raid.c (grub_raid_read): Offset reads by the start sector of
data on the device.
(insert_array): Record the start sector of data on the device.
(grub_raid_register): Pass start_sector parameters to
grub_raid_list->detect and insert_array.
* include/grub/raid.h (struct grub_raid_array): Add start_sector
member.
(struct grub_raid): Add start_sector parameter to `detect'.
* disk/mdraid_linux.c (struct grub_raid_super_1x): Remove
__attribute__ ((packed)), leaving a comment.
(grub_mdraid_detect): Split out 0.9 and 1.x detection to ...
(grub_mdraid_detect_09): ... here and ...
(grub_mdraid_detect_1x): ... here.
2010-07-20 Peter Henn <peter.henn@web.de>
* disk/mdraid_linux.c (grub_mdraid_detect): Fix calculation of 1.x
chunk size and disk size, which are already given as sector counts
as distinct from the 0.90 units. Fetch the correct device number
from the role table instead of using the table index.
2010-07-20 Felix Zielcke <fzielcke@z-51.de>
* disk/dmraid_nvidia.c (grub_dmraid_nv_detect): Set array->name to NULL.
* disk/mdraid_linux.c (grub_raid_super_1x): New structure.
(WriteMostly1): New macro.
Set array->name to NULL for metadata format 0.90. Add support for
metadata 1.x. Fix some comments.
* disk/raid.c (): Add support for name based RAID arrays. Fix a
few comments.
* util/getroot.c (grub_util_get_grub_dev): Add support for
/dev/md/name style devices.
2010-07-20 Colin Watson <cjwatson@ubuntu.com>
* .bzrignore: Ignore 20_linux_xen.
2010-07-17 Colin Watson <cjwatson@ubuntu.com>
* util/import_unicode.py: Remove unnecessary imports.
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'

View file

@ -78,6 +78,12 @@ grub_libusb_devices (void)
return GRUB_USB_ERR_NONE; return GRUB_USB_ERR_NONE;
} }
void
grub_usb_poll_devices (void)
{
/* TODO: recheck grub_usb_devs */
}
int int
grub_usb_iterate (int (*hook) (grub_usb_device_t dev)) grub_usb_iterate (int (*hook) (grub_usb_device_t dev))

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

@ -325,7 +325,8 @@ setup_common_tables (void)
/* If it's FADT correct DSDT and FACS addresses. */ /* If it's FADT correct DSDT and FACS addresses. */
fadt = (struct grub_acpi_fadt *) cur->addr; fadt = (struct grub_acpi_fadt *) cur->addr;
if (grub_memcmp (fadt->hdr.signature, "FACP", 4) == 0) if (grub_memcmp (fadt->hdr.signature, "FACP",
sizeof (fadt->hdr.signature)) == 0)
{ {
fadt->dsdt_addr = PTR_TO_UINT32 (table_dsdt); fadt->dsdt_addr = PTR_TO_UINT32 (table_dsdt);
fadt->facs_addr = facs_addr; fadt->facs_addr = facs_addr;
@ -351,16 +352,16 @@ setup_common_tables (void)
rsdt_addr = rsdt = (struct grub_acpi_table_header *) playground_ptr; rsdt_addr = rsdt = (struct grub_acpi_table_header *) playground_ptr;
playground_ptr += sizeof (struct grub_acpi_table_header) + 4 * numoftables; playground_ptr += sizeof (struct grub_acpi_table_header) + 4 * numoftables;
rsdt_entry = (grub_uint32_t *)(rsdt + 1); rsdt_entry = (grub_uint32_t *) (rsdt + 1);
/* Fill RSDT header. */ /* Fill RSDT header. */
grub_memcpy (&(rsdt->signature), "RSDT", 4); grub_memcpy (&(rsdt->signature), "RSDT", 4);
rsdt->length = sizeof (struct grub_acpi_table_header) + 4 * numoftables; rsdt->length = sizeof (struct grub_acpi_table_header) + 4 * numoftables;
rsdt->revision = 1; rsdt->revision = 1;
grub_memcpy (&(rsdt->oemid), root_oemid, 6); grub_memcpy (&(rsdt->oemid), root_oemid, sizeof (rsdt->oemid));
grub_memcpy (&(rsdt->oemtable), root_oemtable, 4); grub_memcpy (&(rsdt->oemtable), root_oemtable, sizeof (rsdt->oemtable));
rsdt->oemrev = root_oemrev; rsdt->oemrev = root_oemrev;
grub_memcpy (&(rsdt->creator_id), root_creator_id, 6); grub_memcpy (&(rsdt->creator_id), root_creator_id, sizeof (rsdt->creator_id));
rsdt->creator_rev = root_creator_rev; rsdt->creator_rev = root_creator_rev;
for (cur = acpi_tables; cur; cur = cur->next) for (cur = acpi_tables; cur; cur = cur->next)
@ -378,7 +379,8 @@ setv1table (void)
/* Create RSDP. */ /* Create RSDP. */
rsdpv1_new = (struct grub_acpi_rsdp_v10 *) playground_ptr; rsdpv1_new = (struct grub_acpi_rsdp_v10 *) playground_ptr;
playground_ptr += sizeof (struct grub_acpi_rsdp_v10); playground_ptr += sizeof (struct grub_acpi_rsdp_v10);
grub_memcpy (&(rsdpv1_new->signature), "RSD PTR ", 8); grub_memcpy (&(rsdpv1_new->signature), "RSD PTR ",
sizeof (rsdpv1_new->signature));
grub_memcpy (&(rsdpv1_new->oemid), root_oemid, sizeof (rsdpv1_new->oemid)); grub_memcpy (&(rsdpv1_new->oemid), root_oemid, sizeof (rsdpv1_new->oemid));
rsdpv1_new->revision = 0; rsdpv1_new->revision = 0;
rsdpv1_new->rsdt_addr = PTR_TO_UINT32 (rsdt_addr); rsdpv1_new->rsdt_addr = PTR_TO_UINT32 (rsdt_addr);

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

@ -89,7 +89,8 @@ struct grub_nv_super
} __attribute__ ((packed)); } __attribute__ ((packed));
static grub_err_t static grub_err_t
grub_dmraid_nv_detect (grub_disk_t disk, struct grub_raid_array *array) grub_dmraid_nv_detect (grub_disk_t disk, struct grub_raid_array *array,
grub_disk_addr_t *start_sector)
{ {
grub_disk_addr_t sector; grub_disk_addr_t sector;
struct grub_nv_super sb; struct grub_nv_super sb;
@ -132,6 +133,7 @@ grub_dmraid_nv_detect (grub_disk_t disk, struct grub_raid_array *array)
"unsupported RAID level: %d", sb.array.raid_level); "unsupported RAID level: %d", sb.array.raid_level);
} }
array->name = NULL;
array->number = 0; array->number = 0;
array->total_devs = sb.array.total_volumes; array->total_devs = sb.array.total_volumes;
array->chunk_size = sb.array.stripe_block_size; array->chunk_size = sb.array.stripe_block_size;
@ -144,6 +146,8 @@ grub_dmraid_nv_detect (grub_disk_t disk, struct grub_raid_array *array)
grub_memcpy (array->uuid, (char *) &sb.array.signature, grub_memcpy (array->uuid, (char *) &sb.array.signature,
sizeof (sb.array.signature)); sizeof (sb.array.signature));
*start_sector = 0;
return 0; return 0;
} }

View file

@ -28,7 +28,7 @@
struct grub_loopback struct grub_loopback
{ {
char *devname; char *devname;
char *filename; grub_file_t file;
int has_partitions; int has_partitions;
struct grub_loopback *next; struct grub_loopback *next;
}; };
@ -63,7 +63,7 @@ delete_loopback (const char *name)
*prev = dev->next; *prev = dev->next;
grub_free (dev->devname); grub_free (dev->devname);
grub_free (dev->filename); grub_file_close (dev->file);
grub_free (dev); grub_free (dev);
return 0; return 0;
@ -76,6 +76,7 @@ grub_cmd_loopback (grub_extcmd_t cmd, int argc, char **args)
struct grub_arg_list *state = state = cmd->state; struct grub_arg_list *state = state = cmd->state;
grub_file_t file; grub_file_t file;
struct grub_loopback *newdev; struct grub_loopback *newdev;
grub_err_t ret;
if (argc < 1) if (argc < 1)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "device name required"); return grub_error (GRUB_ERR_BAD_ARGUMENT, "device name required");
@ -91,9 +92,6 @@ grub_cmd_loopback (grub_extcmd_t cmd, int argc, char **args)
if (! file) if (! file)
return grub_errno; return grub_errno;
/* Close the file, the only reason for opening it is validation. */
grub_file_close (file);
/* First try to replace the old device. */ /* First try to replace the old device. */
for (newdev = loopback_list; newdev; newdev = newdev->next) for (newdev = loopback_list; newdev; newdev = newdev->next)
if (grub_strcmp (newdev->devname, args[0]) == 0) if (grub_strcmp (newdev->devname, args[0]) == 0)
@ -103,10 +101,10 @@ grub_cmd_loopback (grub_extcmd_t cmd, int argc, char **args)
{ {
char *newname = grub_strdup (args[1]); char *newname = grub_strdup (args[1]);
if (! newname) if (! newname)
return grub_errno; goto fail;
grub_free (newdev->filename); grub_file_close (newdev->file);
newdev->filename = newname; newdev->file = file;
/* Set has_partitions when `--partitions' was used. */ /* Set has_partitions when `--partitions' was used. */
newdev->has_partitions = state[1].set; newdev->has_partitions = state[1].set;
@ -117,22 +115,16 @@ grub_cmd_loopback (grub_extcmd_t cmd, int argc, char **args)
/* Unable to replace it, make a new entry. */ /* Unable to replace it, make a new entry. */
newdev = grub_malloc (sizeof (struct grub_loopback)); newdev = grub_malloc (sizeof (struct grub_loopback));
if (! newdev) if (! newdev)
return grub_errno; goto fail;
newdev->devname = grub_strdup (args[0]); newdev->devname = grub_strdup (args[0]);
if (! newdev->devname) if (! newdev->devname)
{ {
grub_free (newdev); grub_free (newdev);
return grub_errno; goto fail;
} }
newdev->filename = grub_strdup (args[1]); newdev->file = file;
if (! newdev->filename)
{
grub_free (newdev->devname);
grub_free (newdev);
return grub_errno;
}
/* Set has_partitions when `--partitions' was used. */ /* Set has_partitions when `--partitions' was used. */
newdev->has_partitions = state[1].set; newdev->has_partitions = state[1].set;
@ -142,6 +134,11 @@ grub_cmd_loopback (grub_extcmd_t cmd, int argc, char **args)
loopback_list = newdev; loopback_list = newdev;
return 0; return 0;
fail:
ret = grub_errno;
grub_file_close (file);
return ret;
} }
@ -160,7 +157,6 @@ grub_loopback_iterate (int (*hook) (const char *name))
static grub_err_t static grub_err_t
grub_loopback_open (const char *name, grub_disk_t disk) grub_loopback_open (const char *name, grub_disk_t disk)
{ {
grub_file_t file;
struct grub_loopback *dev; struct grub_loopback *dev;
for (dev = loopback_list; dev; dev = dev->next) for (dev = loopback_list; dev; dev = dev->next)
@ -170,29 +166,17 @@ grub_loopback_open (const char *name, grub_disk_t disk)
if (! dev) if (! dev)
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't open device"); return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't open device");
file = grub_file_open (dev->filename);
if (! file)
return grub_errno;
/* Use the filesize for the disk size, round up to a complete sector. */ /* Use the filesize for the disk size, round up to a complete sector. */
disk->total_sectors = ((file->size + GRUB_DISK_SECTOR_SIZE - 1) disk->total_sectors = ((dev->file->size + GRUB_DISK_SECTOR_SIZE - 1)
/ GRUB_DISK_SECTOR_SIZE); / GRUB_DISK_SECTOR_SIZE);
disk->id = (unsigned long) dev; disk->id = (unsigned long) dev;
disk->has_partitions = dev->has_partitions; disk->has_partitions = dev->has_partitions;
disk->data = file; disk->data = dev->file;
return 0; return 0;
} }
static void
grub_loopback_close (grub_disk_t disk)
{
grub_file_t file = (grub_file_t) disk->data;
grub_file_close (file);
}
static grub_err_t static grub_err_t
grub_loopback_read (grub_disk_t disk, grub_disk_addr_t sector, grub_loopback_read (grub_disk_t disk, grub_disk_addr_t sector,
grub_size_t size, char *buf) grub_size_t size, char *buf)
@ -234,7 +218,6 @@ static struct grub_disk_dev grub_loopback_dev =
.id = GRUB_DISK_DEVICE_LOOPBACK_ID, .id = GRUB_DISK_DEVICE_LOOPBACK_ID,
.iterate = grub_loopback_iterate, .iterate = grub_loopback_iterate,
.open = grub_loopback_open, .open = grub_loopback_open,
.close = grub_loopback_close,
.read = grub_loopback_read, .read = grub_loopback_read,
.write = grub_loopback_write, .write = grub_loopback_write,
.next = 0 .next = 0

View file

@ -1,7 +1,7 @@
/* mdraid_linux.c - module to handle linux softraid. */ /* mdraid_linux.c - module to handle Linux Software RAID. */
/* /*
* GRUB -- GRand Unified Bootloader * GRUB -- GRand Unified Bootloader
* Copyright (C) 2008 Free Software Foundation, Inc. * Copyright (C) 2008,2009,2010 Free Software Foundation, Inc.
* *
* GRUB is free software: you can redistribute it and/or modify * GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -159,63 +159,254 @@ struct grub_raid_super_09
struct grub_raid_disk_09 this_disk; struct grub_raid_disk_09 this_disk;
} __attribute__ ((packed)); } __attribute__ ((packed));
static grub_err_t /*
grub_mdraid_detect (grub_disk_t disk, struct grub_raid_array *array) * The version-1 superblock :
* All numeric fields are little-endian.
*
* Total size: 256 bytes plus 2 per device.
* 1K allows 384 devices.
*/
struct grub_raid_super_1x
{
/* Constant array information - 128 bytes. */
grub_uint32_t magic; /* MD_SB_MAGIC: 0xa92b4efc - little endian. */
grub_uint32_t major_version; /* 1. */
grub_uint32_t feature_map; /* Bit 0 set if 'bitmap_offset' is meaningful. */
grub_uint32_t pad0; /* Always set to 0 when writing. */
grub_uint8_t set_uuid[16]; /* User-space generated. */
char set_name[32]; /* Set and interpreted by user-space. */
grub_uint64_t ctime; /* Lo 40 bits are seconds, top 24 are microseconds or 0. */
grub_uint32_t level; /* -4 (multipath), -1 (linear), 0,1,4,5. */
grub_uint32_t layout; /* only for raid5 and raid10 currently. */
grub_uint64_t size; /* Used size of component devices, in 512byte sectors. */
grub_uint32_t chunksize; /* In 512byte sectors. */
grub_uint32_t raid_disks;
grub_uint32_t bitmap_offset; /* Sectors after start of superblock that bitmap starts
* NOTE: signed, so bitmap can be before superblock
* only meaningful of feature_map[0] is set.
*/
/* These are only valid with feature bit '4'. */
grub_uint32_t new_level; /* New level we are reshaping to. */
grub_uint64_t reshape_position; /* Next address in array-space for reshape. */
grub_uint32_t delta_disks; /* Change in number of raid_disks. */
grub_uint32_t new_layout; /* New layout. */
grub_uint32_t new_chunk; /* New chunk size (512byte sectors). */
grub_uint8_t pad1[128 - 124]; /* Set to 0 when written. */
/* Constant this-device information - 64 bytes. */
grub_uint64_t data_offset; /* Sector start of data, often 0. */
grub_uint64_t data_size; /* Sectors in this device that can be used for data. */
grub_uint64_t super_offset; /* Sector start of this superblock. */
grub_uint64_t recovery_offset; /* Sectors before this offset (from data_offset) have been recovered. */
grub_uint32_t dev_number; /* Permanent identifier of this device - not role in raid. */
grub_uint32_t cnt_corrected_read; /* Number of read errors that were corrected by re-writing. */
grub_uint8_t device_uuid[16]; /* User-space setable, ignored by kernel. */
grub_uint8_t devflags; /* Per-device flags. Only one defined... */
grub_uint8_t pad2[64 - 57]; /* Set to 0 when writing. */
/* Array state information - 64 bytes. */
grub_uint64_t utime; /* 40 bits second, 24 btes microseconds. */
grub_uint64_t events; /* Incremented when superblock updated. */
grub_uint64_t resync_offset; /* Data before this offset (from data_offset) known to be in sync. */
grub_uint32_t sb_csum; /* Checksum upto devs[max_dev]. */
grub_uint32_t max_dev; /* Size of devs[] array to consider. */
grub_uint8_t pad3[64 - 32]; /* Set to 0 when writing. */
/* Device state information. Indexed by dev_number.
* 2 bytes per device.
* Note there are no per-device state flags. State information is rolled
* into the 'roles' value. If a device is spare or faulty, then it doesn't
* have a meaningful role.
*/
grub_uint16_t dev_roles[0]; /* Role in array, or 0xffff for a spare, or 0xfffe for faulty. */
};
/* Could be __attribute__ ((packed)), but since all members in this struct
are already appropriately aligned, we can omit this and avoid suboptimal
assembly in some cases. */
#define WriteMostly1 1 /* Mask for writemostly flag in above devflags. */
static grub_err_t
grub_mdraid_detect_09 (grub_disk_addr_t sector,
struct grub_raid_super_09 *sb,
struct grub_raid_array *array,
grub_disk_addr_t *start_sector)
{ {
grub_disk_addr_t sector;
grub_uint64_t size;
struct grub_raid_super_09 sb;
grub_uint32_t *uuid; grub_uint32_t *uuid;
/* The sector where the RAID superblock is stored, if available. */ if (sb->major_version != 0 || sb->minor_version != 90)
size = grub_disk_get_size (disk);
sector = NEW_SIZE_SECTORS (size);
if (grub_disk_read (disk, sector, 0, SB_BYTES, &sb))
return grub_errno;
/* Look whether there is a RAID superblock. */
if (sb.md_magic != SB_MAGIC)
return grub_error (GRUB_ERR_OUT_OF_RANGE, "not raid");
/* FIXME: Also support version 1.0. */
if (sb.major_version != 0 || sb.minor_version != 90)
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
"unsupported RAID version: %d.%d", "unsupported RAID version: %d.%d",
sb.major_version, sb.minor_version); sb->major_version, sb->minor_version);
/* FIXME: Check the checksum. */ /* FIXME: Check the checksum. */
/* Multipath. */ /* Multipath. */
if ((int) sb.level == -4) if ((int) sb->level == -4)
sb.level = 1; sb->level = 1;
if (sb.level != 0 && sb.level != 1 && sb.level != 4 && if (sb->level != 0 && sb->level != 1 && sb->level != 4 &&
sb.level != 5 && sb.level != 6 && sb.level != 10) sb->level != 5 && sb->level != 6 && sb->level != 10)
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
"unsupported RAID level: %d", sb.level); "unsupported RAID level: %d", sb->level);
array->number = sb.md_minor; array->name = NULL;
array->level = sb.level; array->number = sb->md_minor;
array->layout = sb.layout; array->level = sb->level;
array->total_devs = sb.raid_disks; array->layout = sb->layout;
array->disk_size = (sb.size) ? sb.size * 2 : sector; array->total_devs = sb->raid_disks;
array->chunk_size = sb.chunk_size >> 9; array->disk_size = (sb->size) ? sb->size * 2 : sector;
array->index = sb.this_disk.number; array->chunk_size = sb->chunk_size >> 9;
array->index = sb->this_disk.number;
array->uuid_len = 16; array->uuid_len = 16;
array->uuid = grub_malloc (16); array->uuid = grub_malloc (16);
if (!array->uuid) if (!array->uuid)
return grub_errno; return grub_errno;
uuid = (grub_uint32_t *) array->uuid; uuid = (grub_uint32_t *) array->uuid;
uuid[0] = sb.set_uuid0; uuid[0] = sb->set_uuid0;
uuid[1] = sb.set_uuid1; uuid[1] = sb->set_uuid1;
uuid[2] = sb.set_uuid2; uuid[2] = sb->set_uuid2;
uuid[3] = sb.set_uuid3; uuid[3] = sb->set_uuid3;
*start_sector = 0;
return 0; return 0;
} }
static grub_err_t
grub_mdraid_detect_1x (grub_disk_t disk, grub_disk_addr_t sector,
struct grub_raid_super_1x *sb,
struct grub_raid_array *array,
grub_disk_addr_t *start_sector)
{
grub_uint64_t sb_size;
struct grub_raid_super_1x *real_sb;
if (sb->major_version != 1)
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
"Unsupported RAID version: %d",
sb->major_version);
/* Multipath. */
if ((int) sb->level == -4)
sb->level = 1;
if (sb->level != 0 && sb->level != 1 && sb->level != 4 &&
sb->level != 5 && sb->level != 6 && sb->level != 10)
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
"Unsupported RAID level: %d", sb->level);
/* 1.x superblocks don't have a fixed size on disk. So we have to
read it again now that we now the max device count. */
sb_size = sizeof (struct grub_raid_super_1x) + 2 * grub_le_to_cpu32 (sb->max_dev);
real_sb = grub_malloc (sb_size);
if (! real_sb)
return grub_errno;
if (grub_disk_read (disk, sector, 0, sb_size, real_sb))
{
grub_free (real_sb);
return grub_errno;
}
array->name = grub_strdup (real_sb->set_name);
if (! array->name)
{
grub_free (real_sb);
return grub_errno;
}
array->number = 0;
array->level = grub_le_to_cpu32 (real_sb->level);
array->layout = grub_le_to_cpu32 (real_sb->layout);
array->total_devs = grub_le_to_cpu32 (real_sb->raid_disks);
array->disk_size = grub_le_to_cpu64 (real_sb->size);
array->chunk_size = grub_le_to_cpu32 (real_sb->chunksize);
if (grub_le_to_cpu32 (real_sb->dev_number) <
grub_le_to_cpu32 (real_sb->max_dev))
array->index = grub_le_to_cpu16
(real_sb->dev_roles[grub_le_to_cpu32 (real_sb->dev_number)]);
else
array->index = 0xffff; /* disk will be later not used! */
array->uuid_len = 16;
array->uuid = grub_malloc (16);
if (!array->uuid)
{
grub_free (real_sb);
return grub_errno;
}
grub_memcpy (array->uuid, real_sb->set_uuid, 16);
*start_sector = real_sb->data_offset;
grub_free (real_sb);
return 0;
}
static grub_err_t
grub_mdraid_detect (grub_disk_t disk, struct grub_raid_array *array,
grub_disk_addr_t *start_sector)
{
grub_disk_addr_t sector;
grub_uint64_t size;
struct grub_raid_super_09 sb_09;
struct grub_raid_super_1x sb_1x;
grub_uint8_t minor_version;
/* The sector where the mdraid 0.90 superblock is stored, if available. */
size = grub_disk_get_size (disk);
sector = NEW_SIZE_SECTORS (size);
if (grub_disk_read (disk, sector, 0, SB_BYTES, &sb_09))
return grub_errno;
/* Look whether there is a mdraid 0.90 superblock. */
if (sb_09.md_magic == SB_MAGIC)
return grub_mdraid_detect_09 (sector, &sb_09, array, start_sector);
/* Check for an 1.x superblock.
* It's always aligned to a 4K boundary
* and depending on the minor version it can be:
* 0: At least 8K, but less than 12K, from end of device
* 1: At start of device
* 2: 4K from start of device.
*/
for (minor_version = 0; minor_version < 3; ++minor_version)
{
switch (minor_version)
{
case 0:
sector = (size - 8 * 2) & ~(4 * 2 - 1);
break;
case 1:
sector = 0;
break;
case 2:
sector = 4 * 2;
break;
}
if (grub_disk_read (disk, sector, 0, sizeof (struct grub_raid_super_1x),
&sb_1x))
return grub_errno;
if (sb_1x.magic == SB_MAGIC)
return grub_mdraid_detect_1x (disk, sector, &sb_1x, array,
start_sector);
}
/* Neither 0.90 nor 1.x. */
return grub_error (GRUB_ERR_OUT_OF_RANGE, "not raid");
}
static struct grub_raid grub_mdraid_dev = { static struct grub_raid grub_mdraid_dev = {
.name = "mdraid", .name = "mdraid",
.detect = grub_mdraid_detect, .detect = grub_mdraid_detect,

View file

@ -1,7 +1,7 @@
/* raid.c - module to read RAID arrays. */ /* raid.c - module to read RAID arrays. */
/* /*
* GRUB -- GRand Unified Bootloader * GRUB -- GRand Unified Bootloader
* Copyright (C) 2006,2007,2008,2009 Free Software Foundation, Inc. * Copyright (C) 2006,2007,2008,2009,2010 Free Software Foundation, Inc.
* *
* GRUB is free software: you can redistribute it and/or modify * GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -254,6 +254,7 @@ grub_raid_read (grub_disk_t disk, grub_disk_addr_t sector,
grub_errno = GRUB_ERR_NONE; grub_errno = GRUB_ERR_NONE;
err = grub_disk_read (array->device[k], err = grub_disk_read (array->device[k],
array->start_sector[k] +
read_sector + j * far_ofs + b, read_sector + j * far_ofs + b,
0, 0,
read_size << GRUB_DISK_SECTOR_BITS, read_size << GRUB_DISK_SECTOR_BITS,
@ -366,6 +367,7 @@ grub_raid_read (grub_disk_t disk, grub_disk_addr_t sector,
grub_errno = GRUB_ERR_NONE; grub_errno = GRUB_ERR_NONE;
err = grub_disk_read (array->device[disknr], err = grub_disk_read (array->device[disknr],
array->start_sector[disknr] +
read_sector + b, 0, read_sector + b, 0,
read_size << GRUB_DISK_SECTOR_BITS, read_size << GRUB_DISK_SECTOR_BITS,
buf); buf);
@ -475,7 +477,7 @@ grub_raid_write (grub_disk_t disk __attribute ((unused)),
static grub_err_t static grub_err_t
insert_array (grub_disk_t disk, struct grub_raid_array *new_array, insert_array (grub_disk_t disk, struct grub_raid_array *new_array,
const char *scanner_name) grub_disk_addr_t start_sector, const char *scanner_name)
{ {
struct grub_raid_array *array = 0, *p; struct grub_raid_array *array = 0, *p;
@ -502,7 +504,7 @@ insert_array (grub_disk_t disk, struct grub_raid_array *new_array,
if (array->device[new_array->index] != NULL) if (array->device[new_array->index] != NULL)
/* We found multiple devices with the same number. Again, /* We found multiple devices with the same number. Again,
this shouldn't happen.*/ this shouldn't happen. */
grub_dprintf ("raid", "Found two disks with the number %d?!?", grub_dprintf ("raid", "Found two disks with the number %d?!?",
new_array->number); new_array->number);
@ -524,7 +526,10 @@ insert_array (grub_disk_t disk, struct grub_raid_array *new_array,
*array = *new_array; *array = *new_array;
array->nr_devs = 0; array->nr_devs = 0;
grub_memset (&array->device, 0, sizeof (array->device)); grub_memset (&array->device, 0, sizeof (array->device));
grub_memset (&array->start_sector, 0, sizeof (array->start_sector));
if (array->name)
goto skip_duplicate_check;
/* Check whether we don't have multiple arrays with the same number. */ /* Check whether we don't have multiple arrays with the same number. */
for (p = array_list; p != NULL; p = p->next) for (p = array_list; p != NULL; p = p->next)
{ {
@ -534,7 +539,7 @@ insert_array (grub_disk_t disk, struct grub_raid_array *new_array,
if (p) if (p)
{ {
/* The number is already in use, so we need to find an new number. */ /* The number is already in use, so we need to find a new one. */
int i = 0; int i = 0;
while (1) while (1)
@ -545,7 +550,7 @@ insert_array (grub_disk_t disk, struct grub_raid_array *new_array,
break; break;
} }
if (!p) if (! p)
{ {
/* We found an unused number. */ /* We found an unused number. */
array->number = i; array->number = i;
@ -555,7 +560,11 @@ insert_array (grub_disk_t disk, struct grub_raid_array *new_array,
i++; i++;
} }
} }
skip_duplicate_check:
/* mdraid 1.x superblocks have only a name stored not a number.
Use it directly as GRUB device. */
if (! array->name)
{
array->name = grub_xasprintf ("md%d", array->number); array->name = grub_xasprintf ("md%d", array->number);
if (! array->name) if (! array->name)
{ {
@ -564,6 +573,25 @@ insert_array (grub_disk_t disk, struct grub_raid_array *new_array,
return grub_errno; return grub_errno;
} }
}
else
{
/* Strip off the homehost if present. */
char *colon = grub_strchr (array->name, ':');
char *new_name = grub_xasprintf ("md/%s",
colon ? colon + 1 : array->name);
if (! new_name)
{
grub_free (array->uuid);
grub_free (array);
return grub_errno;
}
grub_free (array->name);
array->name = new_name;
}
grub_dprintf ("raid", "Found array %s (%s)\n", array->name, grub_dprintf ("raid", "Found array %s (%s)\n", array->name,
scanner_name); scanner_name);
@ -580,6 +608,7 @@ insert_array (grub_disk_t disk, struct grub_raid_array *new_array,
/* Add the device to the array. */ /* Add the device to the array. */
array->device[new_array->index] = disk; array->device[new_array->index] = disk;
array->start_sector[new_array->index] = start_sector;
array->nr_devs++; array->nr_devs++;
return 0; return 0;
@ -621,6 +650,7 @@ grub_raid_register (grub_raid_t raid)
{ {
grub_disk_t disk; grub_disk_t disk;
struct grub_raid_array array; struct grub_raid_array array;
grub_disk_addr_t start_sector;
grub_dprintf ("raid", "Scanning for RAID devices on disk %s\n", name); grub_dprintf ("raid", "Scanning for RAID devices on disk %s\n", name);
@ -629,8 +659,8 @@ grub_raid_register (grub_raid_t raid)
return 0; return 0;
if ((disk->total_sectors != GRUB_ULONG_MAX) && if ((disk->total_sectors != GRUB_ULONG_MAX) &&
(! grub_raid_list->detect (disk, &array)) && (! grub_raid_list->detect (disk, &array, &start_sector)) &&
(! insert_array (disk, &array, grub_raid_list->name))) (! insert_array (disk, &array, start_sector, grub_raid_list->name)))
return 0; return 0;
/* This error usually means it's not raid, no need to display /* This error usually means it's not raid, no need to display

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

@ -444,12 +444,13 @@ disk. The number @samp{0} is the drive number, which is counted from
disk. disk.
@example @example
(hd0,2) (hd0,msdos2)
@end example @end example
Here, @samp{hd} means it is a hard disk drive. The first integer Here, @samp{hd} means it is a hard disk drive. The first integer
@samp{0} indicates the drive number, that is, the first hard disk, while @samp{0} indicates the drive number, that is, the first hard disk,
the second integer, @samp{1}, indicates the partition number (or the the string @samp{msdos} indicates the partition scheme, while
the second integer, @samp{2}, indicates the partition number (or the
@sc{pc} slice number in the BSD terminology). The partition numbers are @sc{pc} slice number in the BSD terminology). The partition numbers are
counted from @emph{one}, not from zero (as was the case in previous counted from @emph{one}, not from zero (as was the case in previous
versions of GRUB). This expression means the second partition of the versions of GRUB). This expression means the second partition of the
@ -457,7 +458,7 @@ first hard disk drive. In this case, GRUB uses one partition of the
disk, instead of the whole disk. disk, instead of the whole disk.
@example @example
(hd0,5) (hd0,msdos5)
@end example @end example
This specifies the first @dfn{extended partition} of the first hard disk This specifies the first @dfn{extended partition} of the first hard disk
@ -466,18 +467,15 @@ counted from @samp{5}, regardless of the actual number of primary
partitions on your hard disk. partitions on your hard disk.
@example @example
(hd1,a) (hd1,msdos1,bsd1)
@end example @end example
This means the BSD @samp{a} partition of the second hard disk. If you This means the BSD @samp{a} partition on first @sc{pc} slice number
need to specify which @sc{pc} slice number should be used, use something of the second hard disk.
like this: @samp{(hd1,1,a)}. If the @sc{pc} slice number is omitted,
GRUB searches for the first @sc{pc} slice which has a BSD @samp{a}
partition.
Of course, to actually access the disks or partitions with GRUB, you Of course, to actually access the disks or partitions with GRUB, you
need to use the device specification in a command, like @samp{set need to use the device specification in a command, like @samp{set
root=(fd0)} or @samp{parttool (hd0,3) hidden-}. To help you find out root=(fd0)} or @samp{parttool (hd0,msdos3) hidden-}. To help you find out
which number specifies a partition you want, the GRUB command-line which number specifies a partition you want, the GRUB command-line
(@pxref{Command-line interface}) options have argument (@pxref{Command-line interface}) options have argument
completion. This means that, for example, you only need to type completion. This means that, for example, you only need to type
@ -501,7 +499,7 @@ Now the question is, how to specify a file? Again, consider an
example: example:
@example @example
(hd0,1)/vmlinuz (hd0,msdos1)/vmlinuz
@end example @end example
This specifies the file named @samp{vmlinuz}, found on the first This specifies the file named @samp{vmlinuz}, found on the first

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

@ -1,7 +1,7 @@
/* raid.h - On disk structures for RAID. */ /* raid.h - On disk structures for RAID. */
/* /*
* GRUB -- GRand Unified Bootloader * GRUB -- GRand Unified Bootloader
* Copyright (C) 2006,2007,2008 Free Software Foundation, Inc. * Copyright (C) 2006,2007,2008,2010 Free Software Foundation, Inc.
* *
* GRUB is free software: you can redistribute it and/or modify * GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -51,6 +51,8 @@ struct grub_raid_array
char *name; /* That will be "md<number>". */ char *name; /* That will be "md<number>". */
unsigned int nr_devs; /* The number of devices we've found so far. */ unsigned int nr_devs; /* The number of devices we've found so far. */
grub_disk_t device[GRUB_RAID_MAX_DEVICES]; /* Array of total_devs devices. */ grub_disk_t device[GRUB_RAID_MAX_DEVICES]; /* Array of total_devs devices. */
grub_disk_addr_t start_sector[GRUB_RAID_MAX_DEVICES];
/* Start of each device, in 512 byte sectors. */
struct grub_raid_array *next; struct grub_raid_array *next;
}; };
@ -58,7 +60,8 @@ struct grub_raid
{ {
const char *name; const char *name;
grub_err_t (*detect) (grub_disk_t disk, struct grub_raid_array *array); grub_err_t (*detect) (grub_disk_t disk, struct grub_raid_array *array,
grub_disk_addr_t *start_sector);
struct grub_raid *next; struct grub_raid *next;
}; };

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

@ -1,7 +1,7 @@
/* getroot.c - Get root device */ /* getroot.c - Get root device */
/* /*
* GRUB -- GRand Unified Bootloader * GRUB -- GRand Unified Bootloader
* Copyright (C) 1999,2000,2001,2002,2003,2006,2007,2008,2009 Free Software Foundation, Inc. * Copyright (C) 1999,2000,2001,2002,2003,2006,2007,2008,2009,2010 Free Software Foundation, Inc.
* *
* GRUB is free software: you can redistribute it and/or modify * GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -36,6 +36,11 @@
#include <sys/mman.h> #include <sys/mman.h>
#endif #endif
#ifdef __linux__
# include <sys/types.h>
# include <sys/wait.h>
#endif
#include <grub/mm.h> #include <grub/mm.h>
#include <grub/misc.h> #include <grub/misc.h>
#include <grub/emu/misc.h> #include <grub/emu/misc.h>
@ -516,10 +521,89 @@ grub_util_get_dev_abstraction (const char *os_dev __attribute__((unused)))
return GRUB_DEV_ABSTRACTION_NONE; return GRUB_DEV_ABSTRACTION_NONE;
} }
#ifdef __linux__
static char *
get_mdadm_name (const char *os_dev)
{
int mdadm_pipe[2];
pid_t mdadm_pid;
char *name = NULL;
if (pipe (mdadm_pipe) < 0)
{
grub_util_warn ("Unable to create pipe for mdadm: %s", strerror (errno));
return NULL;
}
mdadm_pid = fork ();
if (mdadm_pid < 0)
grub_util_warn ("Unable to fork mdadm: %s", strerror (errno));
else if (mdadm_pid == 0)
{
/* Child. */
char *argv[5];
close (mdadm_pipe[0]);
dup2 (mdadm_pipe[1], STDOUT_FILENO);
close (mdadm_pipe[1]);
/* execvp has inconvenient types, hence the casts. None of these
strings will actually be modified. */
argv[0] = (char *) "mdadm";
argv[1] = (char *) "--detail";
argv[2] = (char *) "--export";
argv[3] = (char *) os_dev;
argv[4] = NULL;
execvp ("mdadm", argv);
exit (127);
}
else
{
/* Parent. Read mdadm's output. */
FILE *mdadm;
char *buf = NULL;
size_t len = 0;
close (mdadm_pipe[1]);
mdadm = fdopen (mdadm_pipe[0], "r");
if (! mdadm)
{
grub_util_warn ("Unable to open stream from mdadm: %s",
strerror (errno));
goto out;
}
while (getline (&buf, &len, mdadm) > 0)
{
if (strncmp (buf, "MD_NAME=", sizeof ("MD_NAME=") - 1) == 0)
{
char *name_start, *colon;
size_t name_len;
free (name);
name_start = buf + sizeof ("MD_NAME=") - 1;
/* Strip off the homehost if present. */
colon = strchr (name_start, ':');
name = strdup (colon ? colon + 1 : name_start);
name_len = strlen (name);
if (name[name_len - 1] == '\n')
name[name_len - 1] = '\0';
}
}
out:
close (mdadm_pipe[0]);
waitpid (mdadm_pid, NULL, 0);
}
return name;
}
#endif /* __linux__ */
char * char *
grub_util_get_grub_dev (const char *os_dev) grub_util_get_grub_dev (const char *os_dev)
{ {
char *grub_dev; char *grub_dev = NULL;
switch (grub_util_get_dev_abstraction (os_dev)) switch (grub_util_get_dev_abstraction (os_dev))
{ {
@ -600,9 +684,36 @@ grub_util_get_grub_dev (const char *os_dev)
grub_dev = xasprintf ("md%s", p); grub_dev = xasprintf ("md%s", p);
free (p); free (p);
} }
else if (os_dev[7] == '/')
{
/* mdraid 1.x with a free name. */
char *p , *q;
p = strdup (os_dev + sizeof ("/dev/md/") - 1);
q = strchr (p, 'p');
if (q)
*q = ',';
grub_dev = xasprintf ("md/%s", p);
free (p);
}
else else
grub_util_error ("unknown kind of RAID device `%s'", os_dev); grub_util_error ("unknown kind of RAID device `%s'", os_dev);
#ifdef __linux__
{
char *mdadm_name = get_mdadm_name (os_dev);
if (mdadm_name)
{
free (grub_dev);
grub_dev = xasprintf ("md/%s", mdadm_name);
free (mdadm_name);
}
}
#endif /* __linux__ */
break; break;
default: /* GRUB_DEV_ABSTRACTION_NONE */ default: /* GRUB_DEV_ABSTRACTION_NONE */

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

@ -157,11 +157,13 @@ LOCAL(cont1):
andl $(~GRUB_MEMORY_CPU_CR0_PAGING_ON), %eax andl $(~GRUB_MEMORY_CPU_CR0_PAGING_ON), %eax
movl %eax, %cr0 movl %eax, %cr0
#ifdef __x86_64__
/* Disable amd64. */ /* Disable amd64. */
movl $GRUB_MEMORY_CPU_AMD64_MSR, %ecx movl $GRUB_MEMORY_CPU_AMD64_MSR, %ecx
rdmsr rdmsr
andl $(~GRUB_MEMORY_CPU_AMD64_MSR_ON), %eax andl $(~GRUB_MEMORY_CPU_AMD64_MSR_ON), %eax
wrmsr wrmsr
#endif
/* Turn off PAE. */ /* Turn off PAE. */
movl %cr4, %eax movl %cr4, %eax

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;

View file

@ -311,6 +311,20 @@ grub_console_setcursor (struct grub_term_output *term __attribute__ ((unused)),
efi_call_2 (o->enable_cursor, o, on); efi_call_2 (o->enable_cursor, o, on);
} }
static grub_err_t
grub_efi_console_init (struct grub_term_output *term)
{
grub_console_setcursor (term, 1);
return 0;
}
static grub_err_t
grub_efi_console_fini (struct grub_term_output *term)
{
grub_console_setcursor (term, 0);
return 0;
}
static struct grub_term_input grub_console_term_input = static struct grub_term_input grub_console_term_input =
{ {
.name = "console", .name = "console",
@ -321,6 +335,8 @@ static struct grub_term_input grub_console_term_input =
static struct grub_term_output grub_console_term_output = static struct grub_term_output grub_console_term_output =
{ {
.name = "console", .name = "console",
.init = grub_efi_console_init,
.fini = grub_efi_console_fini,
.putchar = grub_console_putchar, .putchar = grub_console_putchar,
.getwh = grub_console_getwh, .getwh = grub_console_getwh,
.getxy = grub_console_getxy, .getxy = grub_console_getxy,

View file

@ -1,4 +1,4 @@
#! /bin/bash -e #! /bin/sh -e
# Compares GRUB script output with BASH output. # Compares GRUB script output with BASH output.
# Copyright (C) 2009,2010 Free Software Foundation, Inc. # Copyright (C) 2009,2010 Free Software Foundation, Inc.
@ -84,7 +84,7 @@ done
if [ "x${source}" = x ] ; then if [ "x${source}" = x ] ; then
tmpfile=`mktemp` tmpfile=`mktemp`
while read; do while read REPLY; do
echo $REPLY >> ${tmpfile} echo $REPLY >> ${tmpfile}
done done
source=${tmpfile} source=${tmpfile}

View file

@ -467,13 +467,30 @@ clear_seen_devices (void)
} }
#ifdef __linux__ #ifdef __linux__
/* Like strcmp, but doesn't require a cast for use as a qsort comparator. */ struct device
static int
compare_file_names (const void *a, const void *b)
{ {
const char *left = *(const char **) a; char *stable;
const char *right = *(const char **) b; char *kernel;
return strcmp (left, right); };
/* Sort by the kernel name for preference since that most closely matches
older device.map files, but sort by stable by-id names as a fallback.
This is because /dev/disk/by-id/ usually has a few alternative
identifications of devices (e.g. ATA vs. SATA).
check_device_readable_unique will ensure that we only get one for any
given disk, but sort the list so that the choice of which one we get is
stable. */
static int
compare_devices (const void *a, const void *b)
{
const struct device *left = (const struct device *) a;
const struct device *right = (const struct device *) b;
int ret;
ret = strcmp (left->kernel, right->kernel);
if (ret)
return ret;
else
return strcmp (left->stable, right->stable);
} }
#endif /* __linux__ */ #endif /* __linux__ */
@ -507,10 +524,10 @@ grub_util_iterate_devices (int NESTED_FUNC_ATTR (*hook) (const char *, int),
if (dir) if (dir)
{ {
struct dirent *entry; struct dirent *entry;
char **names; struct device *devs;
size_t names_len = 0, names_max = 1024, i; size_t devs_len = 0, devs_max = 1024, i;
names = xmalloc (names_max * sizeof (*names)); devs = xmalloc (devs_max * sizeof (*devs));
/* Dump all the directory entries into names, resizing if /* Dump all the directory entries into names, resizing if
necessary. */ necessary. */
@ -526,35 +543,34 @@ grub_util_iterate_devices (int NESTED_FUNC_ATTR (*hook) (const char *, int),
/* Skip RAID entries; they are handled by upper layers. */ /* Skip RAID entries; they are handled by upper layers. */
if (strncmp (entry->d_name, "md-", sizeof ("md-") - 1) == 0) if (strncmp (entry->d_name, "md-", sizeof ("md-") - 1) == 0)
continue; continue;
if (names_len >= names_max) if (devs_len >= devs_max)
{ {
names_max *= 2; devs_max *= 2;
names = xrealloc (names, names_max * sizeof (*names)); devs = xrealloc (devs, devs_max * sizeof (*devs));
} }
names[names_len++] = xasprintf (entry->d_name); devs[devs_len].stable =
xasprintf ("/dev/disk/by-id/%s", entry->d_name);
devs[devs_len].kernel =
canonicalize_file_name (devs[devs_len].stable);
devs_len++;
} }
/* /dev/disk/by-id/ usually has a few alternative identifications of qsort (devs, devs_len, sizeof (*devs), &compare_devices);
devices (e.g. ATA vs. SATA). check_device_readable_unique will
ensure that we only get one for any given disk, but sort the list
so that the choice of which one we get is stable. */
qsort (names, names_len, sizeof (*names), &compare_file_names);
closedir (dir); closedir (dir);
/* Now add all the devices in sorted order. */ /* Now add all the devices in sorted order. */
for (i = 0; i < names_len; ++i) for (i = 0; i < devs_len; ++i)
{ {
char *path = xasprintf ("/dev/disk/by-id/%s", names[i]); if (check_device_readable_unique (devs[i].stable))
if (check_device_readable_unique (path))
{ {
if (hook (path, 0)) if (hook (devs[i].stable, 0))
goto out; goto out;
} }
free (path); free (devs[i].stable);
free (names[i]); free (devs[i].kernel);
} }
free (names); free (devs);
} }
} }

View file

@ -246,7 +246,7 @@ devabstraction_module=`$grub_probe --target=abstraction --device-map=${device_ma
# The order in this list is critical. Be careful when modifying it. # The order in this list is critical. Be careful when modifying it.
modules="$modules $fs_module $partmap_module $devabstraction_module" modules="$modules $fs_module $partmap_module $devabstraction_module"
$grub_mkimage -O ${target_cpu}-efi --output=${grubdir}/grub.efi $modules || exit 1 $grub_mkimage -p "" -O ${target_cpu}-efi --output=${grubdir}/grub.efi $modules || exit 1
# Prompt the user to check if the device map is correct. # Prompt the user to check if the device map is correct.
echo "Installation finished. No error reported." echo "Installation finished. No error reported."

View file

@ -812,14 +812,14 @@ main (int argc, char *argv[])
must_embed = 1; must_embed = 1;
if (root_dev[0] == 'm' && root_dev[1] == 'd' if (root_dev[0] == 'm' && root_dev[1] == 'd'
&& root_dev[2] >= '0' && root_dev[2] <= '9') && ((root_dev[2] >= '0' && root_dev[2] <= '9') || root_dev[2] == '/'))
{ {
/* FIXME: we can avoid this on RAID1. */ /* FIXME: we can avoid this on RAID1. */
must_embed = 1; must_embed = 1;
} }
if (dest_dev[0] == 'm' && dest_dev[1] == 'd' if (dest_dev[0] == 'm' && dest_dev[1] == 'd'
&& dest_dev[2] >= '0' && dest_dev[2] <= '9') && ((dest_dev[2] >= '0' && dest_dev[2] <= '9') || dest_dev[2] == '/'))
{ {
char **devicelist; char **devicelist;
int i; int i;

View file

@ -18,8 +18,6 @@
import re import re
import sys import sys
import os
import datetime
if len (sys.argv) < 3: if len (sys.argv) < 3:
print ("Usage: %s SOURCE DESTINATION" % sys.argv[0]) print ("Usage: %s SOURCE DESTINATION" % sys.argv[0])