merge mainline into net

This commit is contained in:
Vladimir 'phcoder' Serbinenko 2011-06-24 22:20:50 +02:00
commit 8f72becdef
45 changed files with 2702 additions and 1144 deletions

317
ChangeLog
View file

@ -1,28 +1,307 @@
2011-06-07 Vladimir Serbinenko <phcoder@gmail.com>
2011-06-07 Manoel Rebelo Abranches <mrabran@gmail.com>
2011-06-24 Vladimir Serbinenko <phcoder@gmail.com>
2011-06-24 Manoel Rebelo Abranches <mrabran@gmail.com>
Network infrastructure.
The ARP protocol was made by Paulo Pinatti <ppinatti@br.ibm.com>
* include/grub/net/arp.h: New file.
* include/grub/net/ethernet.h: New file.
* include/grub/net/ip.h: New file.
* include/grub/net/netbuff.h: New file.
* include/grub/net/tftp.h: New file.
* include/grub/net/udp.h: New file.
* include/grub/net.h: New file.
* grub-core/net/arp.c: New file.
* grub-core/net/ethernet.c: New file.
* grub-core/net/ip.c: New file.
* grub-core/net/netbuff.c: New file.
* grub-core/net/net.c: New file.
* grub-core/net/drivers/emu/emunet.c: New file.
* grub-core/net/drivers/ieee1275/ofnet.c: New file.
* grub-core/kern/device.c (grub_net_open) : New function.
(grub_device_open) : Handle Network device.
* grub-core/kern/file.c (grub_file_net_seek) : New function.
(grub_file_net_seek): Seek in network device.
* include/grub/net/device.h: Likewise.
* include/grub/net/ethernet.h: Likewise.
* include/grub/net/ip.h: Likewise.
* include/grub/net/netbuff.h: Likewise.
* include/grub/net/tftp.h: Likewise.
* include/grub/net/udp.h: Likewise.
* include/grub/ieee1275/ofnet.h: Likewise.
* include/grub/emu/export.h: Likewise.
* include/grub/net.h: Likewise.
* grub-core/net/arp.c: Likewise.
* grub-core/net/ethernet.c: Likewise.
* grub-core/net/ip.c: Likewise.
* grub-core/net/udp.c: Likewise.
* grub-core/net/tftp.c: Likewise.
* grub-core/net/netbuff.c: Likewise.
* grub-core/net/net.c: Likewise.
* grub-core/net/drivers/emu/emunet.c: Likewise.
* grub-core/net/drivers/ieee1275/ofnet.c: Likewise.
* grub-core/Makefile.am (KERNEL_HEADER_FILES): Add net.h, ofnet.h and
export.h.
* grub-core/Makefile.core.def (net): New module.
(tftp): Likewise.
(ofnet): Likewise.
(emunet): Likewise.
* grub-core/commands/ls.c (grub_ls_list_devices) [!GRUB_UTIL]: List
network protocols.
* grub-core/kern/device.c (grub_net_open) : New variable.
(grub_device_open): Handle network device.
(grub_device_close): Likewise.
* grub-core/kern/file.c (grub_file_net_seek) : New variable.
(grub_grubnet_fini): Likewise.
(grub_file_seek): Seek in network device.
* grub-core/kern/fs.c (grub_fs_probe): Handle network devices.
* grub-core/kern/ieee1275/init.c (grub_machine_set_prefix): Handle
network root.
(grub_machine_fini): Call grub_grubnet_fini.
* grub-core/kern/ieee1275/openfw.c (grub_ieee1275_parse_args): Handle
network.
(grub_ieee1275_get_aliasdevname): New function.
* grub-core/loader/i386/multiboot_mbi.c (grub_multiboot_get_mbi_size):
Add unofficial Solaris network info.
(grub_multiboot_make_mbi): Likewise.
* grub-core/fs/i386/pc/pxe.c: Moved from here ...
* grub-core/net/i386/pc/pxe.c: ...here. Adapted for new design.
* include/grub/device.h (grub_fs): Removed.
* include/grub/err.h (grub_err_t): Add network-related values.
* include/grub/i386/pc/pxe.h: Removed bootp parts.
* include/grub/ieee1275/ieee1275.h (grub_ofnetcard_data): New struct.
(grub_ieee1275_get_aliasdevname): New proto.
* include/grub/net.h: Rewritten.
2011-06-24 Vladimir Serbinenko <phcoder@gmail.com>
* grub-core/disk/raid.c (insert_array): Ensure uniqueness of readable
names.
2011-06-24 Vladimir Serbinenko <phcoder@gmail.com>
* grub-core/commands/wildcard.c (match_files): Add a useful dprintf.
(wildcard_expand): Don't stop on nonregexp parts after regexp ones since
it truncates the output.
Reported by: Ximin Luo.
2011-06-24 Vladimir Serbinenko <phcoder@gmail.com>
* grub-core/fs/iso9660.c (grub_iso9660_iterate_dir): Skip . and ..
2011-06-24 Vladimir Serbinenko <phcoder@gmail.com>
* util/grub-mkconfig_lib.in (prepare_grub_to_access_device): Load
partmap before abstraction.
2011-06-24 Alexander Kurtz <kurtz.alex@googlemail.com>
* util/grub-mkconfig_lib.in: Add missing quotes.
2011-06-24 Vladimir Serbinenko <phcoder@gmail.com>
* grub-core/kern/emu/getroot.c (grub_guess_root_device): Revert to
old method if mountinfo would return /dev/root and /dev/root doesn't
exist.
2011-06-24 Vladimir Serbinenko <phcoder@gmail.com>
ZFS zlib support
* grub-core/fs/zfs/zfs.c (zlib_decompress): New function.
(decomp_table): Add zlib entries.
(zio_read): USe 8 bits for compression function rather than 3.
* include/grub/zfs/zio.h (zio_compress): Add zlib values.
2011-06-24 Vladimir Serbinenko <phcoder@gmail.com>
* grub-core/disk/ahci.c: Add missing license statements.
* grub-core/fs/romfs.c: Likewise.
* grub-core/lib/ia64/setjmp.S: Likewise.
* grub-core/loader/i386/pc/freedos.c: Likewise.
* grub-core/loader/ia64/efi/linux.c: Likewise.
* grub-core/video/colors.c: Likewise.
* include/grub/dl.h (GRUB_MOD_DEP): New macro.
2011-06-23 Vladimir Serbinenko <phcoder@gmail.com>
AHCI support.
* grub-core/Makefile.core.def (ata_pthru): Removed.
(ahci): New module.
(pata): Likewise.
* grub-core/bus/usb/ohci.c (GRUB_MOD_FINI): Unregister preboot hook
on unload.
* grub-core/commands/hdparm.c (grub_hdparm_do_ata_cmd): Use ATA
readwrite.
(grub_hdparm_do_check_powermode_cmd): Likewise.
(grub_hdparm_do_smart_cmd): Likewise.
(grub_hdparm_set_val_cmd): Likewise.
(grub_cmd_hdparm): Likewise. Check thta we have an ATA device.
* grub-core/disk/ahci.c: New file.
* grub-core/disk/ata.c: Factor out the low-level part into ...
* grub-core/disk/pata.c: ... here.
* grub-core/disk/ata_pthru.c: Contents moved to ...
* grub-core/disk/pata.c: ... here.
* grub-core/disk/scsi.c (grub_scsi_names): New array.
(grub_scsi_iterate): Use grub_scsi_names.
(grub_scsi_open): Likewise.
* grub-core/kern/disk.c (grub_disk_ata_pass_through): Removed.
* include/grub/ata.h (grub_ata_commands): Add DMA commands.
(grub_ata_regs_t): New struct.
(grub_disk_ata_pass_through_parms): Likewise.
(grub_ata_device): Renamed to ...
(grub_ata): ... this.
(grub_ata_dev): New struct.
Removed all low-level inline functions.
* include/grub/scsi.h: Add PATA and AHCI subsystems.
(grub_scsi_dev): Removed 'name' and 'id'. Added 'id' parameter to
iterate hooks and open. All users updated.
* util/grub-install.in: Handle AHCI disk module.
2011-06-23 Szymon Janc <szymon@janc.net.pl>
Add support for DRI and RSTn markers in JPEG files.
* grub-core/video/readers/jpeg.c (JPEG_MARKER_DRI): New define.
(JPEG_MARKER_RST0): Likewise.
(JPEG_MARKER_RST1): Likewise.
(JPEG_MARKER_RST2): Likewise.
(JPEG_MARKER_RST3): Likewise.
(JPEG_MARKER_RST4): Likewise.
(JPEG_MARKER_RST5): Likewise.
(JPEG_MARKER_RST6): Likewise.
(JPEG_MARKER_RST7): Likewise.
(grub_jpeg_data): New fields dri, r1, bitmap_ptr.
(grub_jpeg_decode_dri): New function.
(grub_jpeg_decode_sos): Move image data related part into
grub_jpeg_decode_data function.
(grub_jpeg_decode_data): New function.
(grub_jpeg_reset): New function.
(grub_jpeg_decode_jpeg): Handle new markers.
2011-06-23 Vladimir Serbinenko <phcoder@gmail.com>
* util/ieee1275/ofpath.c (check_sas): Close fd.
(main): Free of_path.
Reported by: David Volgyes <dvolgyes>.
2011-06-23 Vladimir Serbinenko <phcoder@gmail.com>
* util/grub-mkpasswd-pbkdf2.c (main): Don't double-close.
Reported by: David Volgyes <dvolgyes>.
2011-06-23 Vladimir Serbinenko <phcoder@gmail.com>
* grub-core/kern/emu/hostdisk.c (grub_util_biosdisk_is_floppy): Close
file after stat.
Reported by: David Volgyes <dvolgyes>.
2011-06-23 Vladimir Serbinenko <phcoder@gmail.com>
* util/raid.c (grub_util_raid_getmembers): Close fd before returning.
Reported by: David Volgyes <dvolgyes>.
2011-06-23 Vladimir Serbinenko <phcoder@gmail.com>
* grub-core/lib/reed_solomon.c (rs_recover) [STANDALONE]:
Prevent memory leak.
2011-06-23 Vladimir Serbinenko <phcoder@gmail.com>
* grub-core/lib/reed_solomon.c (rs_recover): Prevent memory leak.
(main): Close file.
Reported by: David Volgyes <dvolgyes>.
2011-06-23 Vladimir Serbinenko <phcoder@gmail.com>
* grub-core/loader/i386/xnu.c (grub_cpu_xnu_fill_devprop): Don't attempt
to continue if allocation is failed.
Reported by: David Volgyes <dvolgyes>.
2011-06-23 David Volgyes <dvolgyes>
* grub-core/bus/usb/ohci.c (grub_ohci_pci_iter): Avoid NULL-pointer
dereference.
2011-06-23 Vladimir Serbinenko <phcoder@gmail.com>
Fix spurious warning.
* grub-core/partmap/acorn.c (grub_acorn_boot_block): Make a union.
(acorn_partition_map_find): Use .bin member.
2011-06-23 Vladimir Serbinenko <phcoder@gmail.com>
* grub-core/kern/emu/getroot.c (grub_guess_root_device): Don't accept
/dev/root as a valid device.
2011-06-23 Jim Meyering <meyering@redhat.com>
Avoid NULL deref in grub_device_open.
* grub-core/kern/device.c (grub_device_open): Don't dereference
a NULL pointer upon failed grub_env_get.
2011-06-23 Vladimir Serbinenko <phcoder@gmail.com>
Support non-512B sectors and agglomerate reads.
* Makefile.util.def (libgrubmods.a): Add grub-core/commands/testload.c.
* grub-core/disk/efi/efidisk.c (grub_efidisk_data): Remove disk_io.
(disk_io_guid): Removed.
(make_devices): Locate solely by BlockIO.
(grub_efidisk_open): Fill log_sector_size and total_sectors.
(grub_efidisk_read): Use read_blocks.
(grub_efidisk_write): Use write_blocks.
* grub-core/disk/i386/pc/biosdisk.c (grub_biosdisk_open): Fill
log_sector_size.
(get_safe_sectors): Handle non-512B sectors.
(grub_biosdisk_read): Remove special CDROM handling. Handle non-512B
sectors.
(grub_biosdisk_write): Handle non-512B sectors.
* grub-core/disk/scsi.c (grub_scsi_open): Fill log_sector_size.
(grub_scsi_read): Remove special non-512B block handling (now handled
one level up).
* grub-core/kern/disk.c (grub_disk_open): Fill default log_sector_size
and do sanity checks.
(grub_disk_adjust_range): Handle non-512B sectors.
(transform_sector): New function.
(grub_disk_read_small): Likewise.
(grub_disk_read): Rewritten.
(grub_disk_write): Handle non-512B sectors.
* grub-core/kern/emu/hostdisk.c (grub_util_biosdisk_open): Fill
log_sector_size.
(open_device): Use log_sector_size.
(grub_util_biosdisk_read): Likewise.
(grub_util_biosdisk_write): Likewise.
* grub-core/partmap/msdos.c (grub_partition_msdos_iterate): Handle
non-512B sectors.
(pc_partition_map_embed): Likewise.
* include/grub/disk.h (grub_disk): New field log_sector_size.
(GRUB_DISK_CACHE_SIZE): Redefined from GRUB_DISK_CACHE_BITS.
(GRUB_DISK_CACHE_BITS): Increased to 6.
* util/grub-fstest.c (fstest): New command testload.
(argp_parser): Likewise.
2011-06-16 Robert Millan <rmh@gnu.org>
Detect `ataraid' devices on GNU/kFreeBSD. Fix for ATA devices using
`ata' driver on kernel of FreeBSD 9.
* util/deviceiter.c [__FreeBSD_kernel__] (get_ada_disk_name)
(get_ataraid_disk_name): New functions.
[__FreeBSD_kernel__] (grub_util_iterate_devices): Scan for ataraid
(/dev/ar[0-9]+) and ada (/dev/ada[0-9]+) devices using
get_ataraid_disk_name() and get_ada_disk_name().
2011-06-13 Colin Watson <cjwatson@ubuntu.com>
* docs/man/grub-mklayout.h2m (DESCRIPTION): Add a reference to the
input format.
2011-05-29 Colin Watson <cjwatson@ubuntu.com>
* docs/grub.texi (Obtaining and Building GRUB): Substitute
`ftp.gnu.org' for `alpha.gnu.org'.
2011-05-27 Colin Watson <cjwatson@ubuntu.com>
* grub-core/kern/emu/hostdisk.c (linux_find_partition): Handle
partitions under /dev/disk/by-id/.
2011-05-27 Colin Watson <cjwatson@ubuntu.com>
* grub-core/kern/emu/hostdisk.c (linux_find_partition): Give up
after ten consecutive open failures. Scanning all the way up to
10000 is excessive and can cause serious performance problems in
some configurations.
Fixes Ubuntu bug #787461.
2011-05-21 Vladimir Serbinenko <phcoder@gmail.com>

View file

@ -34,6 +34,7 @@ library = {
common_nodist = grub_script.tab.h;
common = grub-core/commands/blocklist.c;
common = grub-core/commands/testload.c;
common = grub-core/commands/extcmd.c;
common = grub-core/commands/ls.c;
common = grub-core/disk/dmraid_nvidia.c;

View file

@ -4330,11 +4330,11 @@ how to get the latest version.
@end quotation
GRUB is available from the GNU alpha archive site
@uref{ftp://alpha.gnu.org/gnu/grub} or any of its mirrors. The file
@uref{ftp://ftp.gnu.org/gnu/grub} or any of its mirrors. The file
will be named grub-version.tar.gz. The current version is
@value{VERSION}, so the file you should grab is:
@uref{ftp://alpha.gnu.org/gnu/grub/grub-@value{VERSION}.tar.gz}
@uref{ftp://ftp.gnu.org/gnu/grub/grub-@value{VERSION}.tar.gz}
To unbundle GRUB use the instruction:

View file

@ -1,4 +1,10 @@
[NAME]
grub-mklayout \- generate a GRUB keyboard layout file
[DESCRIPTION]
grub-mklayout processes a keyboard layout description in
.BR keymaps (5)
format into a format that can be used by GRUB's
.B keymap
command.
[SEE ALSO]
.BR grub-mkconfig (8)

View file

@ -868,8 +868,14 @@ module = {
};
module = {
name = ata_pthru;
common = disk/ata_pthru.c;
name = ahci;
common = disk/ahci.c;
enable = pci;
};
module = {
name = pata;
common = disk/pata.c;
enable = pci;
enable = mips_qemu_mips;
};

View file

@ -454,10 +454,12 @@ grub_ohci_pci_iter (grub_pci_device_t dev,
fail:
if (o)
grub_dma_free (o->td_chunk);
grub_dma_free (o->ed_bulk_chunk);
grub_dma_free (o->ed_ctrl_chunk);
grub_dma_free (o->hcca_chunk);
{
grub_dma_free (o->td_chunk);
grub_dma_free (o->ed_bulk_chunk);
grub_dma_free (o->ed_ctrl_chunk);
grub_dma_free (o->hcca_chunk);
}
grub_free (o);
return 0;
@ -1424,18 +1426,22 @@ static struct grub_usb_controller_dev usb_controller =
.detect_dev = grub_ohci_detect_dev
};
static void *fini_hnd;
GRUB_MOD_INIT(ohci)
{
COMPILE_TIME_ASSERT (sizeof (struct grub_ohci_td) == 32);
COMPILE_TIME_ASSERT (sizeof (struct grub_ohci_ed) == 16);
grub_ohci_inithw ();
grub_usb_controller_dev_register (&usb_controller);
grub_loader_register_preboot_hook (grub_ohci_fini_hw, grub_ohci_restore_hw,
GRUB_LOADER_PREBOOT_HOOK_PRIO_DISK);
fini_hnd = grub_loader_register_preboot_hook (grub_ohci_fini_hw,
grub_ohci_restore_hw,
GRUB_LOADER_PREBOOT_HOOK_PRIO_DISK);
}
GRUB_MOD_FINI(ohci)
{
grub_ohci_fini_hw (0);
grub_loader_unregister_preboot_hook (fini_hnd);
grub_usb_controller_dev_unregister (&usb_controller);
}

View file

@ -18,6 +18,7 @@
*/
#include <grub/ata.h>
#include <grub/scsi.h>
#include <grub/disk.h>
#include <grub/dl.h>
#include <grub/misc.h>
@ -63,60 +64,64 @@ enum grub_ata_smart_commands
static int quiet = 0;
static grub_err_t
grub_hdparm_do_ata_cmd (grub_disk_t disk, grub_uint8_t cmd,
grub_hdparm_do_ata_cmd (grub_ata_t ata, grub_uint8_t cmd,
grub_uint8_t features, grub_uint8_t sectors,
void * buffer, int size)
{
struct grub_disk_ata_pass_through_parms apt;
grub_memset (&apt, 0, sizeof (apt));
apt.taskfile[GRUB_ATA_REG_CMD] = cmd;
apt.taskfile[GRUB_ATA_REG_FEATURES] = features;
apt.taskfile[GRUB_ATA_REG_SECTORS] = sectors;
apt.taskfile.cmd = cmd;
apt.taskfile.features = features;
apt.taskfile.sectors = sectors;
apt.taskfile.disk = 0xE0;
apt.buffer = buffer;
apt.size = size;
if (grub_disk_ata_pass_through (disk, &apt))
if (ata->dev->readwrite (ata, &apt, 0))
return grub_errno;
return GRUB_ERR_NONE;
}
static int
grub_hdparm_do_check_powermode_cmd (grub_disk_t disk)
grub_hdparm_do_check_powermode_cmd (grub_ata_t ata)
{
struct grub_disk_ata_pass_through_parms apt;
grub_memset (&apt, 0, sizeof (apt));
apt.taskfile[GRUB_ATA_REG_CMD] = GRUB_ATA_CMD_CHECK_POWER_MODE;
apt.taskfile.cmd = GRUB_ATA_CMD_CHECK_POWER_MODE;
apt.taskfile.disk = 0xE0;
if (grub_disk_ata_pass_through (disk, &apt))
if (ata->dev->readwrite (ata, &apt, 0))
return -1;
return apt.taskfile[GRUB_ATA_REG_SECTORS];
return apt.taskfile.sectors;
}
static int
grub_hdparm_do_smart_cmd (grub_disk_t disk, grub_uint8_t features)
grub_hdparm_do_smart_cmd (grub_ata_t ata, grub_uint8_t features)
{
struct grub_disk_ata_pass_through_parms apt;
grub_memset (&apt, 0, sizeof (apt));
apt.taskfile[GRUB_ATA_REG_CMD] = GRUB_ATA_CMD_SMART;
apt.taskfile[GRUB_ATA_REG_FEATURES] = features;
apt.taskfile[GRUB_ATA_REG_LBAMID] = 0x4f;
apt.taskfile[GRUB_ATA_REG_LBAHIGH] = 0xc2;
apt.taskfile.cmd = GRUB_ATA_CMD_SMART;
apt.taskfile.features = features;
apt.taskfile.lba_mid = 0x4f;
apt.taskfile.lba_high = 0xc2;
apt.taskfile.disk = 0xE0;
if (grub_disk_ata_pass_through (disk, &apt))
if (ata->dev->readwrite (ata, &apt, 0))
return -1;
if (features == GRUB_ATA_FEAT_SMART_STATUS)
{
if ( apt.taskfile[GRUB_ATA_REG_LBAMID] == 0x4f
&& apt.taskfile[GRUB_ATA_REG_LBAHIGH] == 0xc2)
if ( apt.taskfile.lba_mid == 0x4f
&& apt.taskfile.lba_high == 0xc2)
return 0; /* Good SMART status. */
else if ( apt.taskfile[GRUB_ATA_REG_LBAMID] == 0xf4
&& apt.taskfile[GRUB_ATA_REG_LBAHIGH] == 0x2c)
else if ( apt.taskfile.lba_mid == 0xf4
&& apt.taskfile.lba_high == 0x2c)
return 1; /* Bad SMART status. */
else
return -1;
@ -126,12 +131,12 @@ grub_hdparm_do_smart_cmd (grub_disk_t disk, grub_uint8_t features)
static grub_err_t
grub_hdparm_simple_cmd (const char * msg,
grub_disk_t disk, grub_uint8_t cmd)
grub_ata_t ata, grub_uint8_t cmd)
{
if (! quiet && msg)
grub_printf ("%s", msg);
grub_err_t err = grub_hdparm_do_ata_cmd (disk, cmd, 0, 0, NULL, 0);
grub_err_t err = grub_hdparm_do_ata_cmd (ata, cmd, 0, 0, NULL, 0);
if (! quiet && msg)
grub_printf ("%s\n", ! err ? "" : ": not supported");
@ -140,7 +145,7 @@ grub_hdparm_simple_cmd (const char * msg,
static grub_err_t
grub_hdparm_set_val_cmd (const char * msg, int val,
grub_disk_t disk, grub_uint8_t cmd,
grub_ata_t ata, grub_uint8_t cmd,
grub_uint8_t features, grub_uint8_t sectors)
{
if (! quiet && msg && *msg)
@ -151,7 +156,7 @@ grub_hdparm_set_val_cmd (const char * msg, int val,
grub_printf ("Disable %s", msg);
}
grub_err_t err = grub_hdparm_do_ata_cmd (disk, cmd, features, sectors,
grub_err_t err = grub_hdparm_do_ata_cmd (ata, cmd, features, sectors,
NULL, 0);
if (! quiet && msg)
@ -275,6 +280,7 @@ static grub_err_t
grub_cmd_hdparm (grub_extcmd_context_t ctxt, int argc, char **args) // state????
{
struct grub_arg_list *state = ctxt->state;
struct grub_ata *ata;
/* Check command line. */
if (argc != 1)
@ -285,9 +291,6 @@ grub_cmd_hdparm (grub_extcmd_context_t ctxt, int argc, char **args) // state????
return grub_error (GRUB_ERR_BAD_ARGUMENT, "argument is not a device name");
args[0][len - 1] = 0;
if (! grub_disk_ata_pass_through)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "ATA pass through not available");
int i = 0;
int apm = get_int_arg (&state[i++]);
int power = state[i++].set;
@ -313,15 +316,37 @@ grub_cmd_hdparm (grub_extcmd_context_t ctxt, int argc, char **args) // state????
return grub_error (GRUB_ERR_BAD_ARGUMENT, "partition not allowed");
}
switch (disk->dev->id)
{
case GRUB_DISK_DEVICE_ATA_ID:
ata = disk->data;
break;
case GRUB_DISK_DEVICE_SCSI_ID:
if (((disk->id >> GRUB_SCSI_ID_SUBSYSTEM_SHIFT) & 0xFF)
== GRUB_SCSI_SUBSYSTEM_PATA
|| (((disk->id >> GRUB_SCSI_ID_SUBSYSTEM_SHIFT) & 0xFF)
== GRUB_SCSI_SUBSYSTEM_AHCI))
{
ata = ((struct grub_scsi *) disk->data)->data;
break;
}
default:
return grub_error (GRUB_ERR_IO, "not an ATA device");
}
/* Change settings. */
if (aam >= 0)
grub_hdparm_set_val_cmd ("Automatic Acoustic Management", (aam ? aam : -1),
disk, GRUB_ATA_CMD_SET_FEATURES, (aam ? 0x42 : 0xc2), aam);
ata, GRUB_ATA_CMD_SET_FEATURES,
(aam ? 0x42 : 0xc2), aam);
if (apm >= 0)
grub_hdparm_set_val_cmd ("Advanced Power Management",
(apm != 255 ? apm : -1), disk, GRUB_ATA_CMD_SET_FEATURES,
(apm != 255 ? 0x05 : 0x85), (apm != 255 ? apm : 0));
(apm != 255 ? apm : -1), ata,
GRUB_ATA_CMD_SET_FEATURES,
(apm != 255 ? 0x05 : 0x85),
(apm != 255 ? apm : 0));
if (standby_tout >= 0)
{
@ -332,28 +357,28 @@ grub_cmd_hdparm (grub_extcmd_context_t ctxt, int argc, char **args) // state????
grub_printf (")");
}
/* The IDLE cmd sets disk to idle mode and configures standby timer. */
grub_hdparm_set_val_cmd ("", -1, disk, GRUB_ATA_CMD_IDLE, 0, standby_tout);
grub_hdparm_set_val_cmd ("", -1, ata, GRUB_ATA_CMD_IDLE, 0, standby_tout);
}
if (enable_smart >= 0)
{
if (! quiet)
grub_printf ("%sable SMART operations", (enable_smart ? "En" : "Dis"));
int err = grub_hdparm_do_smart_cmd (disk, (enable_smart ?
int err = grub_hdparm_do_smart_cmd (ata, (enable_smart ?
GRUB_ATA_FEAT_SMART_ENABLE : GRUB_ATA_FEAT_SMART_DISABLE));
if (! quiet)
grub_printf ("%s\n", err ? ": not supported" : "");
}
if (sec_freeze)
grub_hdparm_simple_cmd ("Freeze security settings", disk,
grub_hdparm_simple_cmd ("Freeze security settings", ata,
GRUB_ATA_CMD_SECURITY_FREEZE_LOCK);
/* Print/dump IDENTIFY. */
if (ident || dumpid)
{
char buf[GRUB_DISK_SECTOR_SIZE];
if (grub_hdparm_do_ata_cmd (disk, GRUB_ATA_CMD_IDENTIFY_DEVICE,
if (grub_hdparm_do_ata_cmd (ata, GRUB_ATA_CMD_IDENTIFY_DEVICE,
0, 0, buf, sizeof (buf)))
grub_printf ("Cannot read ATA IDENTIFY data\n");
else
@ -369,7 +394,7 @@ grub_cmd_hdparm (grub_extcmd_context_t ctxt, int argc, char **args) // state????
if (power)
{
grub_printf ("Disk power mode is: ");
int mode = grub_hdparm_do_check_powermode_cmd (disk);
int mode = grub_hdparm_do_check_powermode_cmd (ata);
if (mode < 0)
grub_printf ("unknown\n");
else
@ -385,7 +410,7 @@ grub_cmd_hdparm (grub_extcmd_context_t ctxt, int argc, char **args) // state????
{
if (! quiet)
grub_printf ("SMART status is: ");
int err = grub_hdparm_do_smart_cmd (disk, GRUB_ATA_FEAT_SMART_STATUS);
int err = grub_hdparm_do_smart_cmd (ata, GRUB_ATA_FEAT_SMART_STATUS);
if (! quiet)
grub_printf ("%s\n", (err < 0 ? "unknown" :
err == 0 ? "OK" : "*BAD*"));
@ -394,11 +419,11 @@ grub_cmd_hdparm (grub_extcmd_context_t ctxt, int argc, char **args) // state????
/* Change power mode. */
if (standby_now)
grub_hdparm_simple_cmd ("Set disk to standby mode", disk,
grub_hdparm_simple_cmd ("Set disk to standby mode", ata,
GRUB_ATA_CMD_STANDBY_IMMEDIATE);
if (sleep_now)
grub_hdparm_simple_cmd ("Set disk to sleep mode", disk,
grub_hdparm_simple_cmd ("Set disk to sleep mode", ata,
GRUB_ATA_CMD_SLEEP);
grub_disk_close (disk);

View file

@ -288,6 +288,8 @@ match_files (const char *prefix, const char *suffix, const char *end,
if (regexec (regexp, name, 0, 0, 0))
return 0;
grub_dprintf ("expand", "matched\n");
buffer = grub_xasprintf ("%s%s", dir, name);
if (! buffer)
return 1;
@ -423,8 +425,6 @@ wildcard_expand (const char *s, char ***strs)
while (*start)
{
split_path (start, &noregexop, &regexop);
if (noregexop >= regexop) /* no more wildcards */
break;
if (make_regex (noregexop, regexop, &regexp))
goto fail;

733
grub-core/disk/ahci.c Normal file
View file

@ -0,0 +1,733 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <grub/dl.h>
#include <grub/disk.h>
#include <grub/mm.h>
#include <grub/time.h>
#include <grub/pci.h>
#include <grub/ata.h>
#include <grub/scsi.h>
#include <grub/misc.h>
#include <grub/list.h>
#include <grub/loader.h>
GRUB_MOD_LICENSE ("GPLv3+");
struct grub_ahci_cmd_head
{
grub_uint32_t config;
grub_uint32_t transfered;
grub_uint64_t command_table_base;
grub_uint32_t unused[4];
};
struct grub_ahci_prdt_entry
{
grub_uint64_t data_base;
grub_uint32_t unused;
grub_uint32_t size;
};
struct grub_ahci_cmd_table
{
grub_uint8_t cfis[0x40];
grub_uint8_t command[0x10];
grub_uint8_t reserved[0x30];
struct grub_ahci_prdt_entry prdt[1];
};
struct grub_ahci_hba_port
{
grub_uint64_t command_list_base;
grub_uint64_t fis_base;
grub_uint32_t intstatus;
grub_uint32_t inten;
grub_uint32_t command;
grub_uint32_t unused1;
grub_uint32_t task_file_data;
grub_uint32_t sig;
grub_uint32_t status;
grub_uint32_t unused2;
grub_uint32_t sata_error;
grub_uint32_t sata_active;
grub_uint32_t command_issue;
grub_uint32_t unused3;
grub_uint32_t fbs;
grub_uint32_t unused4[15];
};
enum grub_ahci_hba_port_command
{
GRUB_AHCI_HBA_PORT_CMD_ST = 0x01,
GRUB_AHCI_HBA_PORT_CMD_FRE = 0x10,
GRUB_AHCI_HBA_PORT_CMD_CR = 0x8000,
GRUB_AHCI_HBA_PORT_CMD_FR = 0x4000,
};
struct grub_ahci_hba
{
grub_uint32_t cap;
grub_uint32_t global_control;
grub_uint32_t intr_status;
grub_uint32_t ports_implemented;
grub_uint32_t unused1[6];
grub_uint32_t bios_handoff;
grub_uint32_t unused2[53];
struct grub_ahci_hba_port ports[32];
};
struct grub_ahci_received_fis
{
char raw[4096];
};
enum
{
GRUB_AHCI_HBA_CAP_NPORTS_MASK = 0x1f
};
enum
{
GRUB_AHCI_HBA_GLOBAL_CONTROL_RESET = 0x00000001,
GRUB_AHCI_HBA_GLOBAL_CONTROL_INTR_EN = 0x00000002,
GRUB_AHCI_HBA_GLOBAL_CONTROL_AHCI_EN = 0x80000000,
};
enum
{
GRUB_AHCI_BIOS_HANDOFF_BIOS_OWNED = 1,
GRUB_AHCI_BIOS_HANDOFF_OS_OWNED = 2,
GRUB_AHCI_BIOS_HANDOFF_OS_OWNERSHIP_CHANGED = 8,
GRUB_AHCI_BIOS_HANDOFF_RWC = 8
};
struct grub_ahci_device
{
struct grub_ahci_device *next;
volatile struct grub_ahci_hba *hba;
int port;
int num;
struct grub_pci_dma_chunk *command_list_chunk;
volatile struct grub_ahci_cmd_head *command_list;
struct grub_pci_dma_chunk *command_table_chunk;
volatile struct grub_ahci_cmd_table *command_table;
struct grub_pci_dma_chunk *rfis;
int present;
};
static grub_err_t
grub_ahci_readwrite_real (struct grub_ahci_device *dev,
struct grub_disk_ata_pass_through_parms *parms,
int spinup);
enum
{
GRUB_AHCI_CONFIG_READ = 0,
GRUB_AHCI_CONFIG_CFIS_LENGTH_MASK = 0x1f,
GRUB_AHCI_CONFIG_ATAPI = 0x20,
GRUB_AHCI_CONFIG_WRITE = 0x40,
GRUB_AHCI_CONFIG_PREFETCH = 0x80,
GRUB_AHCI_CONFIG_RESET = 0x100,
GRUB_AHCI_CONFIG_BIST = 0x200,
GRUB_AHCI_CONFIG_CLEAR_R_OK = 0x400,
GRUB_AHCI_CONFIG_PMP_MASK = 0xf000,
GRUB_AHCI_CONFIG_PRDT_LENGTH_MASK = 0xffff0000,
};
#define GRUB_AHCI_CONFIG_CFIS_LENGTH_SHIFT 0
#define GRUB_AHCI_CONFIG_PMP_SHIFT 12
#define GRUB_AHCI_CONFIG_PRDT_LENGTH_SHIFT 16
#define GRUB_AHCI_INTERRUPT_ON_COMPLETE 0x80000000
#define GRUB_AHCI_PRDT_MAX_CHUNK_LENGTH 0x200000
static struct grub_ahci_device *grub_ahci_devices;
static int numdevs;
static int
init_port (struct grub_ahci_device *dev)
{
struct grub_pci_dma_chunk *command_list;
struct grub_pci_dma_chunk *command_table;
grub_uint64_t endtime;
command_list = grub_memalign_dma32 (1024, sizeof (struct grub_ahci_cmd_head));
if (!command_list)
return 1;
command_table = grub_memalign_dma32 (1024,
sizeof (struct grub_ahci_cmd_table));
if (!command_table)
{
grub_dma_free (command_list);
return 1;
}
grub_dprintf ("ahci", "found device ahci%d (port %d)\n", dev->num, dev->port);
dev->hba->ports[dev->port].command &= ~GRUB_AHCI_HBA_PORT_CMD_FRE;
endtime = grub_get_time_ms () + 1000;
while ((dev->hba->ports[dev->port].command & GRUB_AHCI_HBA_PORT_CMD_FR))
if (grub_get_time_ms () > endtime)
{
grub_dprintf ("ahci", "couldn't stop FR\n");
goto out;
}
dev->hba->ports[dev->port].command &= ~GRUB_AHCI_HBA_PORT_CMD_ST;
endtime = grub_get_time_ms () + 1000;
while ((dev->hba->ports[dev->port].command & GRUB_AHCI_HBA_PORT_CMD_CR))
if (grub_get_time_ms () > endtime)
{
grub_dprintf ("ahci", "couldn't stop CR\n");
goto out;
}
dev->hba->ports[dev->port].fbs = 2;
dev->rfis = grub_memalign_dma32 (4096,
sizeof (struct grub_ahci_received_fis));
grub_memset ((char *) grub_dma_get_virt (dev->rfis), 0,
sizeof (struct grub_ahci_received_fis));
dev->hba->ports[dev->port].fis_base = grub_dma_get_phys (dev->rfis);
dev->hba->ports[dev->port].command_list_base
= grub_dma_get_phys (command_list);
dev->hba->ports[dev->port].command |= GRUB_AHCI_HBA_PORT_CMD_FRE;
while (!(dev->hba->ports[dev->port].command & GRUB_AHCI_HBA_PORT_CMD_FR))
if (grub_get_time_ms () > endtime)
{
grub_dprintf ("ahci", "couldn't start FR\n");
dev->hba->ports[dev->port].command &= ~GRUB_AHCI_HBA_PORT_CMD_FRE;
goto out;
}
dev->hba->ports[dev->port].command |= GRUB_AHCI_HBA_PORT_CMD_ST;
while (!(dev->hba->ports[dev->port].command & GRUB_AHCI_HBA_PORT_CMD_CR))
if (grub_get_time_ms () > endtime)
{
grub_dprintf ("ahci", "couldn't start CR\n");
dev->hba->ports[dev->port].command &= ~GRUB_AHCI_HBA_PORT_CMD_CR;
goto out_stop_fr;
}
dev->hba->ports[dev->port].command
= (dev->hba->ports[dev->port].command & 0x0fffffff) | (1 << 28) | 2 | 4;
dev->command_list_chunk = command_list;
dev->command_list = grub_dma_get_virt (command_list);
dev->command_table_chunk = command_table;
dev->command_table = grub_dma_get_virt (command_table);
dev->command_list->command_table_base
= grub_dma_get_phys (command_table);
return 0;
out_stop_fr:
dev->hba->ports[dev->port].command &= ~GRUB_AHCI_HBA_PORT_CMD_FRE;
endtime = grub_get_time_ms () + 1000;
while ((dev->hba->ports[dev->port].command & GRUB_AHCI_HBA_PORT_CMD_FR))
if (grub_get_time_ms () > endtime)
{
grub_dprintf ("ahci", "couldn't stop FR\n");
break;
}
out:
grub_dma_free (command_list);
grub_dma_free (command_table);
grub_dma_free (dev->rfis);
return 1;
}
static int NESTED_FUNC_ATTR
grub_ahci_pciinit (grub_pci_device_t dev,
grub_pci_id_t pciid __attribute__ ((unused)))
{
grub_pci_address_t addr;
grub_uint32_t class;
grub_uint32_t bar;
unsigned i, nports;
volatile struct grub_ahci_hba *hba;
/* Read class. */
addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS);
class = grub_pci_read (addr);
/* Check if this class ID matches that of a PCI IDE Controller. */
if (class >> 8 != 0x010601)
return 0;
addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG5);
bar = grub_pci_read (addr);
if ((bar & (GRUB_PCI_ADDR_SPACE_MASK | GRUB_PCI_ADDR_MEM_TYPE_MASK
| GRUB_PCI_ADDR_MEM_PREFETCH))
!= (GRUB_PCI_ADDR_SPACE_MEMORY | GRUB_PCI_ADDR_MEM_TYPE_32))
return 0;
hba = grub_pci_device_map_range (dev, bar & GRUB_PCI_ADDR_MEM_MASK,
sizeof (hba));
if (! (hba->bios_handoff & GRUB_AHCI_BIOS_HANDOFF_OS_OWNED))
{
grub_uint64_t endtime;
grub_dprintf ("ahci", "Requesting AHCI ownership\n");
hba->bios_handoff = (hba->bios_handoff & ~GRUB_AHCI_BIOS_HANDOFF_RWC)
| GRUB_AHCI_BIOS_HANDOFF_OS_OWNED;
grub_dprintf ("ahci", "Waiting for BIOS to give up ownership\n");
endtime = grub_get_time_ms () + 1000;
while ((hba->bios_handoff & GRUB_AHCI_BIOS_HANDOFF_BIOS_OWNED)
&& grub_get_time_ms () < endtime);
if (hba->bios_handoff & GRUB_AHCI_BIOS_HANDOFF_BIOS_OWNED)
{
grub_dprintf ("ahci", "Forcibly taking ownership\n");
hba->bios_handoff = GRUB_AHCI_BIOS_HANDOFF_OS_OWNED;
hba->bios_handoff |= GRUB_AHCI_BIOS_HANDOFF_OS_OWNERSHIP_CHANGED;
}
else
grub_dprintf ("ahci", "AHCI ownership obtained\n");
}
else
grub_dprintf ("ahci", "AHCI is already in OS mode\n");
if (~(hba->global_control & GRUB_AHCI_HBA_GLOBAL_CONTROL_AHCI_EN))
grub_dprintf ("ahci", "AHCI is in compat mode. Switching\n");
else
grub_dprintf ("ahci", "AHCI is in AHCI mode.\n");
for (i = 0; i < 5; i++)
{
hba->global_control |= GRUB_AHCI_HBA_GLOBAL_CONTROL_AHCI_EN;
grub_millisleep (1);
if (hba->global_control & GRUB_AHCI_HBA_GLOBAL_CONTROL_AHCI_EN)
break;
}
if (i == 5)
{
grub_dprintf ("ahci", "Couldn't put AHCI in AHCI mode\n");
return 0;
}
/*
{
grub_uint64_t endtime;
hba->global_control |= 1;
endtime = grub_get_time_ms () + 1000;
while (hba->global_control & 1)
if (grub_get_time_ms () > endtime)
{
grub_dprintf ("ahci", "couldn't reset AHCI\n");
return 0;
}
}
for (i = 0; i < 5; i++)
{
hba->global_control |= GRUB_AHCI_HBA_GLOBAL_CONTROL_AHCI_EN;
grub_millisleep (1);
if (hba->global_control & GRUB_AHCI_HBA_GLOBAL_CONTROL_AHCI_EN)
break;
}
if (i == 5)
{
grub_dprintf ("ahci", "Couldn't put AHCI in AHCI mode\n");
return 0;
}
*/
nports = (hba->cap & GRUB_AHCI_HBA_CAP_NPORTS_MASK) + 1;
grub_dprintf ("ahci", "%d AHCI ports\n", nports);
for (i = 0; i < nports; i++)
{
struct grub_ahci_device *adev;
grub_uint32_t st;
if (!(hba->ports_implemented & (1 << i)))
continue;
grub_dprintf ("ahci", "status %d:%x\n", i, hba->ports[i].status);
/* FIXME: support hotplugging. */
st = hba->ports[i].status;
if ((st & 0xf) != 0x3 && (st & 0xf) != 0x1)
continue;
adev = grub_malloc (sizeof (*adev));
if (!adev)
return 1;
adev->hba = hba;
adev->port = i;
adev->present = 1;
adev->num = numdevs++;
if (init_port (adev))
{
grub_free (adev);
return 1;
}
grub_list_push (GRUB_AS_LIST_P (&grub_ahci_devices),
GRUB_AS_LIST (adev));
}
return 0;
}
static grub_err_t
grub_ahci_initialize (void)
{
grub_pci_iterate (grub_ahci_pciinit);
return grub_errno;
}
static grub_err_t
grub_ahci_fini_hw (int noreturn __attribute__ ((unused)))
{
struct grub_ahci_device *dev;
for (dev = grub_ahci_devices; dev; dev = dev->next)
{
grub_uint64_t endtime;
dev->hba->ports[dev->port].command &= ~GRUB_AHCI_HBA_PORT_CMD_FRE;
endtime = grub_get_time_ms () + 1000;
while ((dev->hba->ports[dev->port].command & GRUB_AHCI_HBA_PORT_CMD_FR))
if (grub_get_time_ms () > endtime)
{
grub_dprintf ("ahci", "couldn't stop FR\n");
break;
}
dev->hba->ports[dev->port].command &= ~GRUB_AHCI_HBA_PORT_CMD_ST;
endtime = grub_get_time_ms () + 1000;
while ((dev->hba->ports[dev->port].command & GRUB_AHCI_HBA_PORT_CMD_CR))
if (grub_get_time_ms () > endtime)
{
grub_dprintf ("ahci", "couldn't stop CR\n");
break;
}
grub_dma_free (dev->command_list_chunk);
grub_dma_free (dev->command_table_chunk);
grub_dma_free (dev->rfis);
dev->command_list_chunk = NULL;
dev->command_table_chunk = NULL;
dev->rfis = NULL;
}
return GRUB_ERR_NONE;
}
static grub_err_t
grub_ahci_restore_hw (void)
{
struct grub_ahci_device **pdev;
for (pdev = &grub_ahci_devices; *pdev; pdev = &((*pdev)->next))
if (init_port (*pdev))
{
struct grub_ahci_device *odev;
odev = *pdev;
*pdev = (*pdev)->next;
grub_free (odev);
}
return GRUB_ERR_NONE;
}
static int
grub_ahci_iterate (int (*hook) (int id, int bus))
{
struct grub_ahci_device *dev;
FOR_LIST_ELEMENTS(dev, grub_ahci_devices)
if (hook (GRUB_SCSI_SUBSYSTEM_AHCI, dev->num))
return 1;
return 0;
}
#if 0
static int
find_free_cmd_slot (struct grub_ahci_device *dev)
{
int i;
for (i = 0; i < 32; i++)
{
if (dev->hda->ports[dev->port].command_issue & (1 << i))
continue;
if (dev->hda->ports[dev->port].sata_active & (1 << i))
continue;
return i;
}
return -1;
}
#endif
enum
{
GRUB_AHCI_FIS_REG_H2D = 0x27
};
static const int register_map[11] = { 3 /* Features */,
12 /* Sectors */,
4 /* LBA low */,
5 /* LBA mid */,
6 /* LBA high */,
7 /* Device */,
2 /* CMD register */,
13 /* Sectors 48 */,
8 /* LBA48 low */,
9 /* LBA48 mid */,
10 /* LBA48 high */ };
static grub_err_t
grub_ahci_readwrite_real (struct grub_ahci_device *dev,
struct grub_disk_ata_pass_through_parms *parms,
int spinup)
{
struct grub_pci_dma_chunk *bufc;
grub_uint64_t endtime;
unsigned i;
grub_err_t err = GRUB_ERR_NONE;
grub_dprintf ("ahci", "AHCI tfd = %x\n",
dev->hba->ports[dev->port].task_file_data);
if ((dev->hba->ports[dev->port].task_file_data & 0x80))
{
dev->hba->ports[dev->port].command &= ~GRUB_AHCI_HBA_PORT_CMD_ST;
endtime = grub_get_time_ms () + 1000;
while ((dev->hba->ports[dev->port].command & GRUB_AHCI_HBA_PORT_CMD_CR))
if (grub_get_time_ms () > endtime)
{
grub_dprintf ("ahci", "couldn't stop CR\n");
break;
}
dev->hba->ports[dev->port].command |= GRUB_AHCI_HBA_PORT_CMD_ST;
endtime = grub_get_time_ms () + (spinup ? 10000 : 1000);
while (!(dev->hba->ports[dev->port].command & GRUB_AHCI_HBA_PORT_CMD_CR))
if (grub_get_time_ms () > endtime)
{
grub_dprintf ("ahci", "couldn't start CR\n");
break;
}
}
dev->hba->ports[dev->port].sata_error = dev->hba->ports[dev->port].sata_error;
grub_dprintf("ahci", "grub_ahci_read (size=%llu, cmdsize = %llu)\n",
(unsigned long long) parms->size,
(unsigned long long) parms->cmdsize);
if (parms->cmdsize != 0 && parms->cmdsize != 12 && parms->cmdsize != 16)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "incorrect ATAPI command size");
if (parms->size > GRUB_AHCI_PRDT_MAX_CHUNK_LENGTH)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "too big data buffer");
bufc = grub_memalign_dma32 (1024, parms->size + (parms->size & 1));
dev->hba->ports[dev->port].command |= 8;
grub_dprintf ("ahci", "AHCI tfd = %x\n",
dev->hba->ports[dev->port].task_file_data);
/* FIXME: support port multipliers. */
dev->command_list[0].config
= (5 << GRUB_AHCI_CONFIG_CFIS_LENGTH_SHIFT)
// | GRUB_AHCI_CONFIG_CLEAR_R_OK
| (0 << GRUB_AHCI_CONFIG_PMP_SHIFT)
| (1 << GRUB_AHCI_CONFIG_PRDT_LENGTH_SHIFT)
| (parms->cmdsize ? GRUB_AHCI_CONFIG_ATAPI : 0)
| (parms->write ? GRUB_AHCI_CONFIG_WRITE : GRUB_AHCI_CONFIG_READ)
| (parms->taskfile.cmd == 8 ? (1 << 8) : 0);
dev->command_list[0].transfered = 0;
dev->command_list[0].command_table_base
= grub_dma_get_phys (dev->command_table_chunk);
grub_memset ((char *) dev->command_list[0].unused, 0,
sizeof (dev->command_list[0].unused));
grub_memset ((char *) &dev->command_table[0], 0,
sizeof (dev->command_table[0]));
if (parms->cmdsize)
grub_memcpy ((char *) dev->command_table[0].command, parms->cmd,
parms->cmdsize);
dev->command_table[0].cfis[0] = GRUB_AHCI_FIS_REG_H2D;
dev->command_table[0].cfis[1] = 0x80;
for (i = 0; i < sizeof (parms->taskfile.raw); i++)
dev->command_table[0].cfis[register_map[i]] = parms->taskfile.raw[i];
grub_dprintf ("ahci", "cfis: %02x %02x %02x %02x %02x %02x %02x %02x\n",
dev->command_table[0].cfis[0], dev->command_table[0].cfis[1],
dev->command_table[0].cfis[2], dev->command_table[0].cfis[3],
dev->command_table[0].cfis[4], dev->command_table[0].cfis[5],
dev->command_table[0].cfis[6], dev->command_table[0].cfis[7]);
grub_dprintf ("ahci", "cfis: %02x %02x %02x %02x %02x %02x %02x %02x\n",
dev->command_table[0].cfis[8], dev->command_table[0].cfis[9],
dev->command_table[0].cfis[10], dev->command_table[0].cfis[11],
dev->command_table[0].cfis[12], dev->command_table[0].cfis[13],
dev->command_table[0].cfis[14], dev->command_table[0].cfis[15]);
dev->command_table[0].prdt[0].data_base = grub_dma_get_phys (bufc);
dev->command_table[0].prdt[0].unused = 0;
dev->command_table[0].prdt[0].size = (parms->size + (parms->size & 1) - 1)
| GRUB_AHCI_INTERRUPT_ON_COMPLETE;
grub_dprintf ("ahci", "PRDT = %" PRIxGRUB_UINT64_T ", %x, %x (%x)\n",
dev->command_table[0].prdt[0].data_base,
dev->command_table[0].prdt[0].unused,
dev->command_table[0].prdt[0].size,
(char *) &dev->command_table[0].prdt[0]
- (char *) &dev->command_table[0]);
if (parms->write)
grub_memcpy ((char *) grub_dma_get_virt (bufc), parms->buffer, parms->size);
grub_dprintf ("ahci", "AHCI command schedulded\n");
grub_dprintf ("ahci", "AHCI tfd = %x\n",
dev->hba->ports[dev->port].task_file_data);
dev->hba->ports[dev->port].inten = 0xffffffff;//(1 << 2) | (1 << 5);
dev->hba->ports[dev->port].intstatus = 0xffffffff;//(1 << 2) | (1 << 5);
grub_dprintf ("ahci", "AHCI tfd = %x\n",
dev->hba->ports[dev->port].task_file_data);
dev->hba->ports[dev->port].command_issue |= 1;
grub_dprintf ("ahci", "AHCI sig = %x\n", dev->hba->ports[dev->port].sig);
grub_dprintf ("ahci", "AHCI tfd = %x\n",
dev->hba->ports[dev->port].task_file_data);
endtime = grub_get_time_ms () + (spinup ? 10000 : 1000);
while ((dev->hba->ports[dev->port].command_issue & 1))
if (grub_get_time_ms () > endtime)
{
grub_dprintf ("ahci", "AHCI status <%x %x %x>\n",
dev->hba->ports[dev->port].command_issue,
dev->hba->ports[dev->port].intstatus,
dev->hba->ports[dev->port].task_file_data);
err = grub_error (GRUB_ERR_IO, "AHCI transfer timeouted");
break;
}
grub_dprintf ("ahci", "AHCI command completed <%x %x %x %x %x, %x %x>\n",
dev->hba->ports[dev->port].command_issue,
dev->hba->ports[dev->port].intstatus,
dev->hba->ports[dev->port].task_file_data,
dev->command_list[0].transfered,
dev->hba->ports[dev->port].sata_error,
((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x00],
((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x18]);
grub_dprintf ("ahci",
"last PIO FIS %08x %08x %08x %08x %08x %08x %08x %08x\n",
((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x08],
((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x09],
((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x0a],
((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x0b],
((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x0c],
((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x0d],
((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x0e],
((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x0f]);
grub_dprintf ("ahci",
"last REG FIS %08x %08x %08x %08x %08x %08x %08x %08x\n",
((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x10],
((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x11],
((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x12],
((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x13],
((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x14],
((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x15],
((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x16],
((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x17]);
if (!parms->write)
grub_memcpy (parms->buffer, (char *) grub_dma_get_virt (bufc), parms->size);
grub_dma_free (bufc);
return err;
}
static grub_err_t
grub_ahci_readwrite (grub_ata_t disk,
struct grub_disk_ata_pass_through_parms *parms,
int spinup)
{
return grub_ahci_readwrite_real (disk->data, parms, spinup);
}
static grub_err_t
grub_ahci_open (int id, int devnum, struct grub_ata *ata)
{
struct grub_ahci_device *dev;
if (id != GRUB_SCSI_SUBSYSTEM_AHCI)
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not an AHCI device");
FOR_LIST_ELEMENTS(dev, grub_ahci_devices)
if (dev->num == devnum)
break;
if (! dev)
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no such AHCI device");
grub_dprintf ("ahci", "opening AHCI dev `ahci%d'\n", dev->num);
ata->data = dev;
ata->dma = 1;
ata->present = &dev->present;
return GRUB_ERR_NONE;
}
static struct grub_ata_dev grub_ahci_dev =
{
.iterate = grub_ahci_iterate,
.open = grub_ahci_open,
.readwrite = grub_ahci_readwrite,
};
static void *fini_hnd;
GRUB_MOD_INIT(ahci)
{
/* To prevent two drivers operating on the same disks. */
grub_disk_firmware_is_tainted = 1;
if (grub_disk_firmware_fini)
{
grub_disk_firmware_fini ();
grub_disk_firmware_fini = NULL;
}
/* AHCI initialization. */
grub_ahci_initialize ();
/* AHCI devices are handled by scsi.mod. */
grub_ata_dev_register (&grub_ahci_dev);
fini_hnd = grub_loader_register_preboot_hook (grub_ahci_fini_hw,
grub_ahci_restore_hw,
GRUB_LOADER_PREBOOT_HOOK_PRIO_DISK);
}
GRUB_MOD_FINI(ahci)
{
grub_ahci_fini_hw (0);
grub_loader_unregister_preboot_hook (fini_hnd);
grub_ata_dev_unregister (&grub_ahci_dev);
}

File diff suppressed because it is too large Load diff

View file

@ -1,108 +0,0 @@
/* ata_pthru.c - ATA pass through for ata.mod. */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2009 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <grub/ata.h>
#include <grub/disk.h>
#include <grub/dl.h>
#include <grub/mm.h>
GRUB_MOD_LICENSE ("GPLv3+");
/* ATA pass through support, used by hdparm.mod. */
static grub_err_t
grub_ata_pass_through (grub_disk_t disk,
struct grub_disk_ata_pass_through_parms *parms)
{
if (disk->dev->id != GRUB_DISK_DEVICE_ATA_ID)
return grub_error (GRUB_ERR_BAD_DEVICE,
"device not accessed via ata.mod");
struct grub_ata_device *dev = (struct grub_ata_device *) disk->data;
if (! (parms->size == 0 || parms->size == GRUB_DISK_SECTOR_SIZE))
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
"ATA multi-sector read and DATA OUT not implemented");
grub_dprintf ("ata", "ata_pass_through: cmd=0x%x, features=0x%x, sectors=0x%x\n",
parms->taskfile[GRUB_ATA_REG_CMD],
parms->taskfile[GRUB_ATA_REG_FEATURES],
parms->taskfile[GRUB_ATA_REG_SECTORS]);
grub_dprintf ("ata", "lba_high=0x%x, lba_mid=0x%x, lba_low=0x%x, size=%d\n",
parms->taskfile[GRUB_ATA_REG_LBAHIGH],
parms->taskfile[GRUB_ATA_REG_LBAMID],
parms->taskfile[GRUB_ATA_REG_LBALOW], parms->size);
/* Set registers. */
grub_ata_regset (dev, GRUB_ATA_REG_DISK, 0xE0 | dev->device << 4
| (parms->taskfile[GRUB_ATA_REG_DISK] & 0xf));
if (grub_ata_check_ready (dev))
return grub_errno;
int i;
for (i = GRUB_ATA_REG_FEATURES; i <= GRUB_ATA_REG_LBAHIGH; i++)
grub_ata_regset (dev, i, parms->taskfile[i]);
/* Start command. */
grub_ata_regset (dev, GRUB_ATA_REG_CMD, parms->taskfile[GRUB_ATA_REG_CMD]);
/* Wait for !BSY. */
if (grub_ata_wait_not_busy (dev, GRUB_ATA_TOUT_DATA))
return grub_errno;
/* Check status. */
grub_int8_t sts = grub_ata_regget (dev, GRUB_ATA_REG_STATUS);
grub_dprintf ("ata", "status=0x%x\n", sts);
/* Transfer data. */
if ((sts & (GRUB_ATA_STATUS_DRQ | GRUB_ATA_STATUS_ERR)) == GRUB_ATA_STATUS_DRQ)
{
if (parms->size != GRUB_DISK_SECTOR_SIZE)
return grub_error (GRUB_ERR_READ_ERROR, "DRQ unexpected");
grub_ata_pio_read (dev, parms->buffer, GRUB_DISK_SECTOR_SIZE);
}
/* Return registers. */
for (i = GRUB_ATA_REG_ERROR; i <= GRUB_ATA_REG_STATUS; i++)
parms->taskfile[i] = grub_ata_regget (dev, i);
grub_dprintf ("ata", "status=0x%x, error=0x%x, sectors=0x%x\n",
parms->taskfile[GRUB_ATA_REG_STATUS],
parms->taskfile[GRUB_ATA_REG_ERROR],
parms->taskfile[GRUB_ATA_REG_SECTORS]);
if (parms->taskfile[GRUB_ATA_REG_STATUS]
& (GRUB_ATA_STATUS_DRQ | GRUB_ATA_STATUS_ERR))
return grub_error (GRUB_ERR_READ_ERROR, "ATA passthrough failed");
return GRUB_ERR_NONE;
}
GRUB_MOD_INIT(ata_pthru)
{
/* Register ATA pass through function. */
grub_disk_ata_pass_through = grub_ata_pass_through;
}
GRUB_MOD_FINI(ata_pthru)
{
if (grub_disk_ata_pass_through == grub_ata_pass_through)
grub_disk_ata_pass_through = NULL;
}

View file

@ -33,12 +33,10 @@ struct grub_efidisk_data
grub_efi_device_path_t *device_path;
grub_efi_device_path_t *last_device_path;
grub_efi_block_io_t *block_io;
grub_efi_disk_io_t *disk_io;
struct grub_efidisk_data *next;
};
/* GUIDs. */
static grub_efi_guid_t disk_io_guid = GRUB_EFI_DISK_IO_GUID;
/* GUID. */
static grub_efi_guid_t block_io_guid = GRUB_EFI_BLOCK_IO_GUID;
static struct grub_efidisk_data *fd_devices;
@ -143,7 +141,7 @@ make_devices (void)
struct grub_efidisk_data *devices = 0;
/* Find handles which support the disk io interface. */
handles = grub_efi_locate_handle (GRUB_EFI_BY_PROTOCOL, &disk_io_guid,
handles = grub_efi_locate_handle (GRUB_EFI_BY_PROTOCOL, &block_io_guid,
0, &num_handles);
if (! handles)
return 0;
@ -155,7 +153,6 @@ make_devices (void)
grub_efi_device_path_t *ldp;
struct grub_efidisk_data *d;
grub_efi_block_io_t *bio;
grub_efi_disk_io_t *dio;
dp = grub_efi_get_device_path (*handle);
if (! dp)
@ -168,9 +165,7 @@ make_devices (void)
bio = grub_efi_open_protocol (*handle, &block_io_guid,
GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
dio = grub_efi_open_protocol (*handle, &disk_io_guid,
GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
if (! bio || ! dio)
if (! bio)
/* This should not happen... Why? */
continue;
@ -186,7 +181,6 @@ make_devices (void)
d->device_path = dp;
d->last_device_path = ldp;
d->block_io = bio;
d->disk_io = dio;
d->next = devices;
devices = d;
}
@ -536,8 +530,13 @@ grub_efidisk_open (const char *name, struct grub_disk *disk)
and total sectors should be replaced with total blocks. */
grub_dprintf ("efidisk", "m = %p, last block = %llx, block size = %x\n",
m, (unsigned long long) m->last_block, m->block_size);
disk->total_sectors = (m->last_block
* (m->block_size >> GRUB_DISK_SECTOR_BITS));
disk->total_sectors = m->last_block;
if (m->block_size & (m->block_size - 1) || !m->block_size)
return grub_error (GRUB_ERR_IO, "invalid sector size %d",
m->block_size);
for (disk->log_sector_size = 0;
(1U << disk->log_sector_size) < m->block_size;
disk->log_sector_size++);
disk->data = d;
grub_dprintf ("efidisk", "opening %s succeeded\n", name);
@ -558,22 +557,20 @@ grub_efidisk_read (struct grub_disk *disk, grub_disk_addr_t sector,
{
/* For now, use the disk io interface rather than the block io's. */
struct grub_efidisk_data *d;
grub_efi_disk_io_t *dio;
grub_efi_block_io_t *bio;
grub_efi_status_t status;
d = disk->data;
dio = d->disk_io;
bio = d->block_io;
grub_dprintf ("efidisk",
"reading 0x%lx sectors at the sector 0x%llx from %s\n",
(unsigned long) size, (unsigned long long) sector, disk->name);
status = efi_call_5 (dio->read, dio, bio->media->media_id,
(grub_efi_uint64_t) sector << GRUB_DISK_SECTOR_BITS,
(grub_efi_uintn_t) size << GRUB_DISK_SECTOR_BITS,
buf);
status = efi_call_5 (bio->read_blocks, bio, bio->media->media_id,
(grub_efi_uint64_t) sector,
(grub_efi_uintn_t) size << disk->log_sector_size,
buf);
if (status != GRUB_EFI_SUCCESS)
return grub_error (GRUB_ERR_READ_ERROR, "efidisk read error");
@ -586,21 +583,19 @@ grub_efidisk_write (struct grub_disk *disk, grub_disk_addr_t sector,
{
/* For now, use the disk io interface rather than the block io's. */
struct grub_efidisk_data *d;
grub_efi_disk_io_t *dio;
grub_efi_block_io_t *bio;
grub_efi_status_t status;
d = disk->data;
dio = d->disk_io;
bio = d->block_io;
grub_dprintf ("efidisk",
"writing 0x%lx sectors at the sector 0x%llx to %s\n",
(unsigned long) size, (unsigned long long) sector, disk->name);
status = efi_call_5 (dio->write, dio, bio->media->media_id,
(grub_efi_uint64_t) sector << GRUB_DISK_SECTOR_BITS,
(grub_efi_uintn_t) size << GRUB_DISK_SECTOR_BITS,
status = efi_call_5 (bio->write_blocks, bio, bio->media->media_id,
(grub_efi_uint64_t) sector,
(grub_efi_uintn_t) size << disk->log_sector_size,
(void *) buf);
if (status != GRUB_EFI_SUCCESS)
return grub_error (GRUB_ERR_WRITE_ERROR, "efidisk write error");

View file

@ -340,7 +340,8 @@ grub_biosdisk_open (const char *name, grub_disk_t disk)
if ((cd_drive) && (drive == cd_drive))
{
data->flags = GRUB_BIOSDISK_FLAG_LBA | GRUB_BIOSDISK_FLAG_CDROM;
data->sectors = 32;
data->sectors = 8;
disk->log_sector_size = 11;
/* TODO: get the correct size. */
total_sectors = GRUB_DISK_SIZE_UNKNOWN;
}
@ -349,6 +350,8 @@ grub_biosdisk_open (const char *name, grub_disk_t disk)
/* HDD */
int version;
disk->log_sector_size = 9;
version = grub_biosdisk_check_int13_extensions (drive);
if (version)
{
@ -369,6 +372,15 @@ grub_biosdisk_open (const char *name, grub_disk_t disk)
correctly but returns zero. So if it is zero, compute
it by C/H/S returned by the LBA BIOS call. */
total_sectors = drp->cylinders * drp->heads * drp->sectors;
if (drp->bytes_per_sector
&& !(drp->bytes_per_sector & (drp->bytes_per_sector - 1))
&& drp->bytes_per_sector >= 512
&& drp->bytes_per_sector <= 16384)
{
for (disk->log_sector_size = 0;
(1 << disk->log_sector_size) < drp->bytes_per_sector;
disk->log_sector_size++);
}
}
}
}
@ -431,7 +443,7 @@ grub_biosdisk_rw (int cmd, grub_disk_t disk,
dap = (struct grub_biosdisk_dap *) (GRUB_MEMORY_MACHINE_SCRATCH_ADDR
+ (data->sectors
<< GRUB_DISK_SECTOR_BITS));
<< disk->log_sector_size));
dap->length = sizeof (*dap);
dap->reserved = 0;
dap->blocks = size;
@ -445,9 +457,6 @@ grub_biosdisk_rw (int cmd, grub_disk_t disk,
if (cmd)
return grub_error (GRUB_ERR_WRITE_ERROR, "can\'t write to cdrom");
dap->blocks = ALIGN_UP (dap->blocks, 4) >> 2;
dap->block >>= 2;
for (i = 0; i < GRUB_BIOSDISK_CDROM_RETRY_COUNT; i++)
if (! grub_biosdisk_rw_int13_extensions (0x42, data->drive, dap))
break;
@ -503,10 +512,12 @@ grub_biosdisk_rw (int cmd, grub_disk_t disk,
/* Return the number of sectors which can be read safely at a time. */
static grub_size_t
get_safe_sectors (grub_disk_addr_t sector, grub_uint32_t sectors)
get_safe_sectors (grub_disk_t disk, grub_disk_addr_t sector)
{
grub_size_t size;
grub_uint64_t offset;
struct grub_biosdisk_data *data = disk->data;
grub_uint32_t sectors = data->sectors;
/* OFFSET = SECTOR % SECTORS */
grub_divmod64 (sector, sectors, &offset);
@ -514,8 +525,8 @@ get_safe_sectors (grub_disk_addr_t sector, grub_uint32_t sectors)
size = sectors - offset;
/* Limit the max to 0x7f because of Phoenix EDD. */
if (size > 0x7f)
size = 0x7f;
if (size > ((0x7fU << GRUB_DISK_SECTOR_BITS) >> disk->log_sector_size))
size = ((0x7fU << GRUB_DISK_SECTOR_BITS) >> disk->log_sector_size);
return size;
}
@ -524,21 +535,11 @@ static grub_err_t
grub_biosdisk_read (grub_disk_t disk, grub_disk_addr_t sector,
grub_size_t size, char *buf)
{
struct grub_biosdisk_data *data = disk->data;
while (size)
{
grub_size_t len;
grub_size_t cdoff = 0;
len = get_safe_sectors (sector, data->sectors);
if (data->flags & GRUB_BIOSDISK_FLAG_CDROM)
{
cdoff = (sector & 3) << GRUB_DISK_SECTOR_BITS;
len = ALIGN_UP (sector + len, 4) - (sector & ~3);
sector &= ~3;
}
len = get_safe_sectors (disk, sector);
if (len > size)
len = size;
@ -547,9 +548,10 @@ grub_biosdisk_read (grub_disk_t disk, grub_disk_addr_t sector,
GRUB_MEMORY_MACHINE_SCRATCH_SEG))
return grub_errno;
grub_memcpy (buf, (void *) (GRUB_MEMORY_MACHINE_SCRATCH_ADDR + cdoff),
len << GRUB_DISK_SECTOR_BITS);
buf += len << GRUB_DISK_SECTOR_BITS;
grub_memcpy (buf, (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR,
len << disk->log_sector_size);
buf += len << disk->log_sector_size;
sector += len;
size -= len;
}
@ -570,18 +572,18 @@ grub_biosdisk_write (grub_disk_t disk, grub_disk_addr_t sector,
{
grub_size_t len;
len = get_safe_sectors (sector, data->sectors);
len = get_safe_sectors (disk, sector);
if (len > size)
len = size;
grub_memcpy ((void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR, buf,
len << GRUB_DISK_SECTOR_BITS);
len << disk->log_sector_size);
if (grub_biosdisk_rw (GRUB_BIOSDISK_WRITE, disk, sector, len,
GRUB_MEMORY_MACHINE_SCRATCH_SEG))
return grub_errno;
buf += len << GRUB_DISK_SECTOR_BITS;
buf += len << disk->log_sector_size;
sector += len;
size -= len;
}

531
grub-core/disk/pata.c Normal file
View file

@ -0,0 +1,531 @@
/* ata_pthru.c - ATA pass through for ata.mod. */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2009 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <grub/ata.h>
#include <grub/scsi.h>
#include <grub/disk.h>
#include <grub/dl.h>
#include <grub/mm.h>
#ifndef GRUB_MACHINE_MIPS_QEMU_MIPS
#include <grub/pci.h>
#include <grub/cs5536.h>
#else
#define GRUB_MACHINE_PCI_IO_BASE 0xb4000000
#endif
#include <grub/time.h>
GRUB_MOD_LICENSE ("GPLv3+");
/* At the moment, only two IDE ports are supported. */
static const grub_port_t grub_pata_ioaddress[] = { GRUB_ATA_CH0_PORT1,
GRUB_ATA_CH1_PORT1 };
struct grub_pata_device
{
/* IDE port to use. */
int port;
/* IO addresses on which the registers for this device can be
found. */
grub_port_t ioaddress;
/* Two devices can be connected to a single cable. Use this field
to select device 0 (commonly known as "master") or device 1
(commonly known as "slave"). */
int device;
int present;
struct grub_pata_device *next;
};
static struct grub_pata_device *grub_pata_devices;
static inline void
grub_pata_regset (struct grub_pata_device *dev, int reg, int val)
{
grub_outb (val, dev->ioaddress + reg);
}
static inline grub_uint8_t
grub_pata_regget (struct grub_pata_device *dev, int reg)
{
return grub_inb (dev->ioaddress + reg);
}
/* Wait for !BSY. */
static grub_err_t
grub_pata_wait_not_busy (struct grub_pata_device *dev, int milliseconds)
{
/* ATA requires 400ns (after a write to CMD register) or
1 PIO cycle (after a DRQ block transfer) before
first check of BSY. */
grub_millisleep (1);
int i = 1;
grub_uint8_t sts;
while ((sts = grub_pata_regget (dev, GRUB_ATA_REG_STATUS))
& GRUB_ATA_STATUS_BUSY)
{
if (i >= milliseconds)
{
grub_dprintf ("pata", "timeout: %dms, status=0x%x\n",
milliseconds, sts);
return grub_error (GRUB_ERR_TIMEOUT, "PATA timeout");
}
grub_millisleep (1);
i++;
}
return GRUB_ERR_NONE;
}
static inline grub_err_t
grub_pata_check_ready (struct grub_pata_device *dev, int spinup)
{
if (grub_pata_regget (dev, GRUB_ATA_REG_STATUS) & GRUB_ATA_STATUS_BUSY)
return grub_pata_wait_not_busy (dev, spinup ? GRUB_ATA_TOUT_SPINUP
: GRUB_ATA_TOUT_STD);
return GRUB_ERR_NONE;
}
static inline void
grub_pata_wait (void)
{
grub_millisleep (50);
}
static void
grub_pata_pio_read (struct grub_pata_device *dev, char *buf, grub_size_t size)
{
grub_uint16_t *buf16 = (grub_uint16_t *) buf;
unsigned int i;
/* Read in the data, word by word. */
for (i = 0; i < size / 2; i++)
buf16[i] = grub_le_to_cpu16 (grub_inw(dev->ioaddress + GRUB_ATA_REG_DATA));
if (size & 1)
buf[size - 1] = (char) grub_le_to_cpu16 (grub_inw (dev->ioaddress
+ GRUB_ATA_REG_DATA));
}
static void
grub_pata_pio_write (struct grub_pata_device *dev, char *buf, grub_size_t size)
{
grub_uint16_t *buf16 = (grub_uint16_t *) buf;
unsigned int i;
/* Write the data, word by word. */
for (i = 0; i < size / 2; i++)
grub_outw(grub_cpu_to_le16 (buf16[i]), dev->ioaddress + GRUB_ATA_REG_DATA);
}
/* ATA pass through support, used by hdparm.mod. */
static grub_err_t
grub_pata_readwrite (struct grub_ata *disk,
struct grub_disk_ata_pass_through_parms *parms,
int spinup)
{
struct grub_pata_device *dev = (struct grub_pata_device *) disk->data;
grub_size_t nread = 0;
int i;
if (! (parms->cmdsize == 0 || parms->cmdsize == 12))
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
"ATAPI non-12 byte commands not supported");
grub_dprintf ("pata", "pata_pass_through: cmd=0x%x, features=0x%x, sectors=0x%x\n",
parms->taskfile.cmd,
parms->taskfile.features,
parms->taskfile.sectors);
grub_dprintf ("pata", "lba_high=0x%x, lba_mid=0x%x, lba_low=0x%x, size=%d\n",
parms->taskfile.lba_high,
parms->taskfile.lba_mid,
parms->taskfile.lba_low, parms->size);
/* Set registers. */
grub_pata_regset (dev, GRUB_ATA_REG_DISK, (dev->device << 4)
| (parms->taskfile.disk & 0xef));
if (grub_pata_check_ready (dev, spinup))
return grub_errno;
for (i = GRUB_ATA_REG_SECTORS; i <= GRUB_ATA_REG_LBAHIGH; i++)
grub_pata_regset (dev, i,
parms->taskfile.raw[7 + (i - GRUB_ATA_REG_SECTORS)]);
for (i = GRUB_ATA_REG_FEATURES; i <= GRUB_ATA_REG_LBAHIGH; i++)
grub_pata_regset (dev, i, parms->taskfile.raw[i - GRUB_ATA_REG_FEATURES]);
/* Start command. */
grub_pata_regset (dev, GRUB_ATA_REG_CMD, parms->taskfile.cmd);
/* Check status. */
grub_int8_t sts = grub_pata_regget (dev, GRUB_ATA_REG_STATUS);
grub_dprintf ("pata", "status=0x%x\n", sts);
if (parms->cmdsize)
{
grub_uint8_t irs;
/* Wait for !BSY. */
if (grub_pata_wait_not_busy (dev, GRUB_ATA_TOUT_DATA))
return grub_errno;
irs = grub_pata_regget (dev, GRUB_ATAPI_REG_IREASON);
/* OK if DRQ is asserted and interrupt reason is as expected. */
if (!((sts & GRUB_ATA_STATUS_DRQ)
&& (irs & GRUB_ATAPI_IREASON_MASK) == GRUB_ATAPI_IREASON_CMD_OUT))
return grub_error (GRUB_ERR_READ_ERROR, "ATAPI protocol error");
/* Write the packet. */
grub_pata_pio_write (dev, parms->cmd, parms->cmdsize);
}
/* Transfer data. */
while (nread < parms->size
&& ((sts & (GRUB_ATA_STATUS_DRQ | GRUB_ATA_STATUS_ERR))
== GRUB_ATA_STATUS_DRQ)
&& (!parms->cmdsize
|| ((grub_pata_regget (dev, GRUB_ATAPI_REG_IREASON)
& GRUB_ATAPI_IREASON_MASK) == GRUB_ATAPI_IREASON_DATA_IN)))
{
unsigned cnt;
/* Wait for !BSY. */
if (grub_pata_wait_not_busy (dev, GRUB_ATA_TOUT_DATA))
return grub_errno;
if (parms->cmdsize)
{
cnt = grub_pata_regget (dev, GRUB_ATAPI_REG_CNTHIGH) << 8
| grub_pata_regget (dev, GRUB_ATAPI_REG_CNTLOW);
grub_dprintf("pata", "DRQ count=%u\n", cnt);
/* Count of last transfer may be uneven. */
if (! (0 < cnt && cnt <= parms->size - nread
&& (! (cnt & 1) || cnt == parms->size - nread)))
return grub_error (GRUB_ERR_READ_ERROR,
"invalid ATAPI transfer count");
}
else
cnt = GRUB_DISK_SECTOR_SIZE;
if (cnt > parms->size - nread)
cnt = parms->size - nread;
if (parms->write)
grub_pata_pio_write (dev, (char *) parms->buffer + nread, cnt);
else
grub_pata_pio_read (dev, (char *) parms->buffer + nread, cnt);
nread += cnt;
}
if (parms->write)
{
/* Check for write error. */
if (grub_pata_wait_not_busy (dev, GRUB_ATA_TOUT_DATA))
return grub_errno;
if (grub_pata_regget (dev, GRUB_ATA_REG_STATUS)
& (GRUB_ATA_STATUS_DRQ | GRUB_ATA_STATUS_ERR))
return grub_error (GRUB_ERR_WRITE_ERROR, "ATA write error");
}
parms->size = nread;
/* Wait for !BSY. */
if (grub_pata_wait_not_busy (dev, GRUB_ATA_TOUT_DATA))
return grub_errno;
/* Return registers. */
for (i = GRUB_ATA_REG_ERROR; i <= GRUB_ATA_REG_STATUS; i++)
parms->taskfile.raw[i - GRUB_ATA_REG_FEATURES] = grub_pata_regget (dev, i);
grub_dprintf ("pata", "status=0x%x, error=0x%x, sectors=0x%x\n",
parms->taskfile.status,
parms->taskfile.error,
parms->taskfile.sectors);
if (parms->taskfile.status
& (GRUB_ATA_STATUS_DRQ | GRUB_ATA_STATUS_ERR))
return grub_error (GRUB_ERR_READ_ERROR, "PATA passthrough failed");
return GRUB_ERR_NONE;
}
static grub_err_t
check_device (struct grub_pata_device *dev)
{
grub_pata_regset (dev, GRUB_ATA_REG_DISK, dev->device << 4);
grub_pata_wait ();
/* Try to detect if the port is in use by writing to it,
waiting for a while and reading it again. If the value
was preserved, there is a device connected. */
grub_pata_regset (dev, GRUB_ATA_REG_SECTORS, 0x5A);
grub_pata_wait ();
grub_uint8_t sec = grub_pata_regget (dev, GRUB_ATA_REG_SECTORS);
grub_dprintf ("ata", "sectors=0x%x\n", sec);
if (sec != 0x5A)
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no device connected");
/* The above test may detect a second (slave) device
connected to a SATA controller which supports only one
(master) device. It is not safe to use the status register
READY bit to check for controller channel existence. Some
ATAPI commands (RESET, DIAGNOSTIC) may clear this bit. */
return GRUB_ERR_NONE;
}
static grub_err_t
grub_pata_device_initialize (int port, int device, int addr)
{
struct grub_pata_device *dev;
struct grub_pata_device **devp;
grub_err_t err;
grub_dprintf ("pata", "detecting device %d,%d (0x%x)\n",
port, device, addr);
dev = grub_malloc (sizeof(*dev));
if (! dev)
return grub_errno;
/* Setup the device information. */
dev->port = port;
dev->device = device;
dev->ioaddress = addr + GRUB_MACHINE_PCI_IO_BASE;
dev->present = 1;
dev->next = NULL;
/* Register the device. */
for (devp = &grub_pata_devices; *devp; devp = &(*devp)->next);
*devp = dev;
err = check_device (dev);
if (err)
grub_print_error ();
return 0;
}
#ifndef GRUB_MACHINE_MIPS_QEMU_MIPS
static int NESTED_FUNC_ATTR
grub_pata_pciinit (grub_pci_device_t dev,
grub_pci_id_t pciid)
{
static int compat_use[2] = { 0 };
grub_pci_address_t addr;
grub_uint32_t class;
grub_uint32_t bar1;
grub_uint32_t bar2;
int rega;
int i;
static int controller = 0;
int cs5536 = 0;
int nports = 2;
/* Read class. */
addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS);
class = grub_pci_read (addr);
/* AMD CS5536 Southbridge. */
if (pciid == GRUB_CS5536_PCIID)
{
cs5536 = 1;
nports = 1;
}
/* Check if this class ID matches that of a PCI IDE Controller. */
if (!cs5536 && (class >> 16 != 0x0101))
return 0;
for (i = 0; i < nports; i++)
{
/* Set to 0 when the channel operated in compatibility mode. */
int compat;
/* We don't support non-compatibility mode for CS5536. */
if (cs5536)
compat = 0;
else
compat = (class >> (8 + 2 * i)) & 1;
rega = 0;
/* If the channel is in compatibility mode, just assign the
default registers. */
if (compat == 0 && !compat_use[i])
{
rega = grub_pata_ioaddress[i];
compat_use[i] = 1;
}
else if (compat)
{
/* Read the BARs, which either contain a mmapped IO address
or the IO port address. */
addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESSES
+ sizeof (grub_uint64_t) * i);
bar1 = grub_pci_read (addr);
addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESSES
+ sizeof (grub_uint64_t) * i
+ sizeof (grub_uint32_t));
bar2 = grub_pci_read (addr);
/* Check if the BARs describe an IO region. */
if ((bar1 & 1) && (bar2 & 1))
{
rega = bar1 & ~3;
}
}
grub_dprintf ("pata",
"PCI dev (%d,%d,%d) compat=%d rega=0x%x\n",
grub_pci_get_bus (dev), grub_pci_get_device (dev),
grub_pci_get_function (dev), compat, rega);
if (rega)
{
grub_errno = GRUB_ERR_NONE;
grub_pata_device_initialize (controller * 2 + i, 0, rega);
/* Most errors raised by grub_ata_device_initialize() are harmless.
They just indicate this particular drive is not responding, most
likely because it doesn't exist. We might want to ignore specific
error types here, instead of printing them. */
if (grub_errno)
{
grub_print_error ();
grub_errno = GRUB_ERR_NONE;
}
grub_pata_device_initialize (controller * 2 + i, 1, rega);
/* Likewise. */
if (grub_errno)
{
grub_print_error ();
grub_errno = GRUB_ERR_NONE;
}
}
}
controller++;
return 0;
}
static grub_err_t
grub_pata_initialize (void)
{
grub_pci_iterate (grub_pata_pciinit);
return 0;
}
#else
static grub_err_t
grub_ata_initialize (void)
{
int i;
for (i = 0; i < 2; i++)
{
grub_ata_device_initialize (i, 0, grub_ata_ioaddress[i],
grub_ata_ioaddress2[i]);
grub_ata_device_initialize (i, 1, grub_ata_ioaddress[i],
grub_ata_ioaddress2[i]);
}
return 0;
}
#endif
static grub_err_t
grub_pata_open (int id, int devnum, struct grub_ata *ata)
{
struct grub_pata_device *dev;
struct grub_pata_device *devfnd = 0;
grub_err_t err;
if (id != GRUB_SCSI_SUBSYSTEM_PATA)
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a PATA device");
for (dev = grub_pata_devices; dev; dev = dev->next)
{
if (dev->port * 2 + dev->device == devnum)
{
devfnd = dev;
break;
}
}
grub_dprintf ("pata", "opening PATA dev `ata%d'\n", devnum);
if (! devfnd)
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no such PATA device");
err = check_device (devfnd);
if (err)
return err;
ata->data = devfnd;
ata->dma = 0;
ata->present = &devfnd->present;
return GRUB_ERR_NONE;
}
static int
grub_pata_iterate (int (*hook) (int id, int bus))
{
struct grub_pata_device *dev;
for (dev = grub_pata_devices; dev; dev = dev->next)
if (hook (GRUB_SCSI_SUBSYSTEM_PATA, dev->port * 2 + dev->device))
return 1;
return 0;
}
static struct grub_ata_dev grub_pata_dev =
{
.iterate = grub_pata_iterate,
.open = grub_pata_open,
.readwrite = grub_pata_readwrite,
};
GRUB_MOD_INIT(ata_pthru)
{
/* To prevent two drivers operating on the same disks. */
grub_disk_firmware_is_tainted = 1;
if (grub_disk_firmware_fini)
{
grub_disk_firmware_fini ();
grub_disk_firmware_fini = NULL;
}
/* ATA initialization. */
grub_pata_initialize ();
grub_ata_dev_register (&grub_pata_dev);
}
GRUB_MOD_FINI(ata_pthru)
{
grub_ata_dev_unregister (&grub_pata_dev);
}

View file

@ -679,6 +679,49 @@ insert_array (grub_disk_t disk, struct grub_raid_array *new_array,
scanner_name);
#endif
{
int max_used_number = 0, len, need_new_name = 0;
int add_us = 0;
len = grub_strlen (array->name);
if (len && grub_isdigit (array->name[len-1]))
add_us = 1;
for (p = array_list; p != NULL; p = p->next)
{
int cur_num;
char *num, *end;
if (grub_strncmp (p->name, array->name, len) != 0)
continue;
if (p->name[len] == 0)
{
need_new_name = 1;
continue;
}
if (add_us && p->name[len] != '_')
continue;
if (add_us)
num = p->name + len + 1;
else
num = p->name + len;
if (!grub_isdigit (num[0]))
continue;
cur_num = grub_strtoull (num, &end, 10);
if (end[0])
continue;
if (cur_num > max_used_number)
max_used_number = cur_num;
}
if (need_new_name)
{
char *tmp;
tmp = grub_xasprintf ("%s%s%d", array->name, add_us ? "_" : "",
max_used_number + 1);
if (!tmp)
return grub_errno;
grub_free (array->name);
array->name = tmp;
}
}
/* Add our new array to the list. */
array->next = array_list;
array_list = array;

View file

@ -32,6 +32,12 @@ GRUB_MOD_LICENSE ("GPLv3+");
static grub_scsi_dev_t grub_scsi_dev_list;
const char grub_scsi_names[GRUB_SCSI_NUM_SUBSYSTEMS][5] = {
[GRUB_SCSI_SUBSYSTEM_USBMS] = "usb",
[GRUB_SCSI_SUBSYSTEM_PATA] = "ata",
[GRUB_SCSI_SUBSYSTEM_AHCI] = "ahci"
};
void
grub_scsi_dev_register (grub_scsi_dev_t dev)
{
@ -320,9 +326,9 @@ grub_scsi_iterate (int (*hook) (const char *name))
{
grub_scsi_dev_t p;
auto int scsi_iterate (int bus, int luns);
auto int NESTED_FUNC_ATTR scsi_iterate (int id, int bus, int luns);
int scsi_iterate (int bus, int luns)
int NESTED_FUNC_ATTR scsi_iterate (int id, int bus, int luns)
{
int i;
@ -331,7 +337,7 @@ grub_scsi_iterate (int (*hook) (const char *name))
{
char *sname;
int ret;
sname = grub_xasprintf ("%s%d", p->name, bus);
sname = grub_xasprintf ("%s%d", grub_scsi_names[id], bus);
if (!sname)
return 1;
ret = hook (sname);
@ -345,7 +351,7 @@ grub_scsi_iterate (int (*hook) (const char *name))
{
char *sname;
int ret;
sname = grub_xasprintf ("%s%d%c", p->name, bus, 'a' + i);
sname = grub_xasprintf ("%s%d%c", grub_scsi_names[id], bus, 'a' + i);
if (!sname)
return 1;
ret = hook (sname);
@ -372,6 +378,7 @@ grub_scsi_open (const char *name, grub_disk_t disk)
int lun, bus;
grub_uint64_t maxtime;
const char *nameend;
unsigned id;
nameend = name + grub_strlen (name) - 1;
/* Try to detect a LUN ('a'-'z'), otherwise just use the first
@ -396,15 +403,25 @@ grub_scsi_open (const char *name, grub_disk_t disk)
if (! scsi)
return grub_errno;
for (id = 0; id < ARRAY_SIZE (grub_scsi_names); id++)
if (grub_strncmp (grub_scsi_names[id], name, nameend - name) == 0)
break;
if (id == ARRAY_SIZE (grub_scsi_names))
{
grub_free (scsi);
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a SCSI disk");
}
for (p = grub_scsi_dev_list; p; p = p->next)
{
if (grub_strncmp (p->name, name, nameend - name) != 0)
continue;
if (p->open (id, bus, scsi))
{
grub_errno = GRUB_ERR_NONE;
continue;
}
if (p->open (bus, scsi))
continue;
disk->id = grub_make_scsi_id (p->id, bus, lun);
disk->id = grub_make_scsi_id (id, bus, lun);
disk->data = scsi;
scsi->dev = p;
scsi->lun = lun;
@ -465,22 +482,26 @@ grub_scsi_open (const char *name, grub_disk_t disk)
return err;
}
/* SCSI blocks can be something else than 512, although GRUB
wants 512 byte blocks. */
disk->total_sectors = ((grub_uint64_t)scsi->size
* (grub_uint64_t)scsi->blocksize)
>> GRUB_DISK_SECTOR_BITS;
disk->total_sectors = scsi->size;
if (scsi->blocksize & (scsi->blocksize - 1) || !scsi->blocksize)
{
grub_free (scsi);
return grub_error (GRUB_ERR_IO, "invalid sector size %d",
scsi->blocksize);
}
for (disk->log_sector_size = 0;
(1 << disk->log_sector_size) < scsi->blocksize;
disk->log_sector_size++);
grub_dprintf ("scsi", "blocks=%u, blocksize=%u\n",
scsi->size, scsi->blocksize);
grub_dprintf ("scsi", "Disk total 512 sectors = %llu\n",
grub_dprintf ("scsi", "Disk total sectors = %llu\n",
(unsigned long long) disk->total_sectors);
return GRUB_ERR_NONE;
}
grub_free (scsi);
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a SCSI disk");
}
@ -503,25 +524,6 @@ grub_scsi_read (grub_disk_t disk, grub_disk_addr_t sector,
scsi = disk->data;
/* SCSI sectors are variable in size. GRUB uses 512 byte
sectors. */
if (scsi->blocksize != GRUB_DISK_SECTOR_SIZE)
{
unsigned spb = scsi->blocksize >> GRUB_DISK_SECTOR_BITS;
if (spb == 0 || (scsi->blocksize & (GRUB_DISK_SECTOR_SIZE - 1)) != 0)
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
"unsupported SCSI block size");
grub_uint64_t sector_mod = 0;
sector = grub_divmod64 (sector, spb, &sector_mod);
if (! (sector_mod == 0 && size % spb == 0))
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
"unaligned SCSI read not supported");
size /= spb;
}
/* Depending on the type, select a read function. */
switch (scsi->devtype)
{

View file

@ -211,7 +211,7 @@ grub_usbms_attach (grub_usb_device_t usbdev, int configno, int interfno)
static int
grub_usbms_iterate (int (*hook) (int bus, int luns))
grub_usbms_iterate (int NESTED_FUNC_ATTR (*hook) (int id, int bus, int luns))
{
unsigned i;
@ -220,7 +220,7 @@ grub_usbms_iterate (int (*hook) (int bus, int luns))
for (i = 0; i < ARRAY_SIZE (grub_usbms_devices); i++)
if (grub_usbms_devices[i])
{
if (hook (i, grub_usbms_devices[i]->luns))
if (hook (GRUB_SCSI_SUBSYSTEM_USBMS, i, grub_usbms_devices[i]->luns))
return 1;
}
@ -390,8 +390,12 @@ grub_usbms_write (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd,
}
static grub_err_t
grub_usbms_open (int devnum, struct grub_scsi *scsi)
grub_usbms_open (int id, int devnum, struct grub_scsi *scsi)
{
if (id != GRUB_SCSI_SUBSYSTEM_USBMS)
return grub_error (GRUB_ERR_UNKNOWN_DEVICE,
"not USB Mass Storage device");
grub_usb_poll_devices ();
if (!grub_usbms_devices[devnum])
@ -406,8 +410,6 @@ grub_usbms_open (int devnum, struct grub_scsi *scsi)
static struct grub_scsi_dev grub_usbms_dev =
{
.name = "usb",
.id = GRUB_SCSI_SUBSYSTEM_USBMS,
.iterate = grub_usbms_iterate,
.open = grub_usbms_open,
.read = grub_usbms_read,

View file

@ -598,7 +598,7 @@ grub_iso9660_iterate_dir (grub_fshelp_node_t dir,
return 0;
}
while (offset < dir->size)
for (; offset < dir->size; offset += dirent.len)
{
if (grub_disk_read (dir->data->disk,
(dir->blk << GRUB_ISO9660_LOG2_BLKSZ)
@ -676,10 +676,9 @@ grub_iso9660_iterate_dir (grub_fshelp_node_t dir,
if (filename)
*filename = '\0';
if (dirent.namelen == 1 && name[0] == 0)
filename = ".";
else if (dirent.namelen == 1 && name[0] == 1)
filename = "..";
/* . and .. */
if (dirent.namelen == 1 && (name[0] == 0 || name[0] == 1))
continue;
else
filename = name;
}
@ -712,8 +711,6 @@ grub_iso9660_iterate_dir (grub_fshelp_node_t dir,
if (filename_alloc)
grub_free (filename);
}
offset += dirent.len;
}
return 0;

View file

@ -24,6 +24,8 @@
#include <grub/fs.h>
#include <grub/fshelp.h>
GRUB_MOD_LICENSE ("GPLv3+");
struct grub_romfs_superblock
{
char magic[8];

View file

@ -51,6 +51,7 @@
#include <grub/zfs/sa_impl.h>
#include <grub/zfs/dsl_dir.h>
#include <grub/zfs/dsl_dataset.h>
#include <grub/deflate.h>
GRUB_MOD_LICENSE ("GPLv3+");
@ -163,13 +164,30 @@ struct grub_zfs_data
grub_disk_addr_t vdev_phys_sector;
};
static grub_err_t
zlib_decompress (void *s, void *d,
grub_size_t slen, grub_size_t dlen)
{
if (grub_zlib_decompress (s, slen, 0, d, dlen) < 0)
return grub_errno;
return GRUB_ERR_NONE;
}
static decomp_entry_t decomp_table[ZIO_COMPRESS_FUNCTIONS] = {
{"inherit", NULL}, /* ZIO_COMPRESS_INHERIT */
{"on", lzjb_decompress}, /* ZIO_COMPRESS_ON */
{"off", NULL}, /* ZIO_COMPRESS_OFF */
{"lzjb", lzjb_decompress}, /* ZIO_COMPRESS_LZJB */
{"empty", NULL}, /* ZIO_COMPRESS_EMPTY */
{"gzip", NULL}, /* ZIO_COMPRESS_GZIP */
{"gzip-1", zlib_decompress}, /* ZIO_COMPRESS_GZIP1 */
{"gzip-2", zlib_decompress}, /* ZIO_COMPRESS_GZIP2 */
{"gzip-3", zlib_decompress}, /* ZIO_COMPRESS_GZIP3 */
{"gzip-4", zlib_decompress}, /* ZIO_COMPRESS_GZIP4 */
{"gzip-5", zlib_decompress}, /* ZIO_COMPRESS_GZIP5 */
{"gzip-6", zlib_decompress}, /* ZIO_COMPRESS_GZIP6 */
{"gzip-7", zlib_decompress}, /* ZIO_COMPRESS_GZIP7 */
{"gzip-8", zlib_decompress}, /* ZIO_COMPRESS_GZIP8 */
{"gzip-9", zlib_decompress}, /* ZIO_COMPRESS_GZIP9 */
};
static grub_err_t zio_read_data (blkptr_t * bp, grub_zfs_endian_t endian,
@ -527,7 +545,7 @@ zio_read (blkptr_t * bp, grub_zfs_endian_t endian, void **buf,
*buf = NULL;
checksum = (grub_zfs_to_cpu64((bp)->blk_prop, endian) >> 40) & 0xff;
comp = (grub_zfs_to_cpu64((bp)->blk_prop, endian)>>32) & 0x7;
comp = (grub_zfs_to_cpu64((bp)->blk_prop, endian)>>32) & 0xff;
lsize = (BP_IS_HOLE(bp) ? 0 :
(((grub_zfs_to_cpu64 ((bp)->blk_prop, endian) & 0xffff) + 1)
<< SPA_MINBLOCKSHIFT));

View file

@ -37,7 +37,7 @@ grub_device_open (const char *name)
if (! name)
{
name = grub_env_get ("root");
if (*name == '\0')
if (name == NULL || *name == '\0')
{
grub_error (GRUB_ERR_BAD_DEVICE, "no device is set");
goto fail;

View file

@ -46,10 +46,6 @@ static struct grub_disk_cache grub_disk_cache_table[GRUB_DISK_CACHE_NUM];
void (*grub_disk_firmware_fini) (void);
int grub_disk_firmware_is_tainted;
grub_err_t (* grub_disk_ata_pass_through) (grub_disk_t,
struct grub_disk_ata_pass_through_parms *);
#if 0
static unsigned long grub_disk_cache_hits;
static unsigned long grub_disk_cache_misses;
@ -247,6 +243,7 @@ grub_disk_open (const char *name)
disk = (grub_disk_t) grub_zalloc (sizeof (*disk));
if (! disk)
return 0;
disk->log_sector_size = GRUB_DISK_SECTOR_BITS;
p = find_part_sep (name);
if (p)
@ -266,7 +263,6 @@ grub_disk_open (const char *name)
if (! disk->name)
goto fail;
for (dev = grub_disk_dev_list; dev; dev = dev->next)
{
if ((dev->open) (raw, disk) == GRUB_ERR_NONE)
@ -282,6 +278,14 @@ grub_disk_open (const char *name)
grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no such disk");
goto fail;
}
if (disk->log_sector_size > GRUB_DISK_CACHE_BITS + GRUB_DISK_SECTOR_BITS
|| disk->log_sector_size < GRUB_DISK_SECTOR_BITS)
{
grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
"sector sizes of %d bytes aren't supported yet",
(1 << disk->log_sector_size));
goto fail;
}
disk->dev = dev;
@ -373,21 +377,110 @@ grub_disk_adjust_range (grub_disk_t disk, grub_disk_addr_t *sector,
*sector += start;
}
if (disk->total_sectors <= *sector
|| ((*offset + size + GRUB_DISK_SECTOR_SIZE - 1)
>> GRUB_DISK_SECTOR_BITS) > disk->total_sectors - *sector)
if (disk->total_sectors != GRUB_DISK_SIZE_UNKNOWN
&& ((disk->total_sectors << (disk->log_sector_size - GRUB_DISK_SECTOR_BITS)) <= *sector
|| ((*offset + size + GRUB_DISK_SECTOR_SIZE - 1)
>> GRUB_DISK_SECTOR_BITS) > (disk->total_sectors
<< (disk->log_sector_size
- GRUB_DISK_SECTOR_BITS)) - *sector))
return grub_error (GRUB_ERR_OUT_OF_RANGE, "out of disk");
return GRUB_ERR_NONE;
}
static inline grub_disk_addr_t
transform_sector (grub_disk_t disk, grub_disk_addr_t sector)
{
return sector >> (disk->log_sector_size - GRUB_DISK_SECTOR_BITS);
}
/* Small read (less than cache size and not pass across cache unit boundaries).
sector is already adjusted and is divisible by cache unit size.
*/
static grub_err_t
grub_disk_read_small (grub_disk_t disk, grub_disk_addr_t sector,
grub_off_t offset, grub_size_t size, void *buf)
{
char *data;
char *tmp_buf;
/* Fetch the cache. */
data = grub_disk_cache_fetch (disk->dev->id, disk->id, sector);
if (data)
{
/* Just copy it! */
grub_memcpy (buf, data + offset, size);
grub_disk_cache_unlock (disk->dev->id, disk->id, sector);
return GRUB_ERR_NONE;
}
/* Allocate a temporary buffer. */
tmp_buf = grub_malloc (GRUB_DISK_SECTOR_SIZE << GRUB_DISK_CACHE_BITS);
if (! tmp_buf)
return grub_errno;
/* Otherwise read data from the disk actually. */
if (disk->total_sectors == GRUB_DISK_SIZE_UNKNOWN
|| sector + GRUB_DISK_CACHE_SIZE
< (disk->total_sectors << (disk->log_sector_size - GRUB_DISK_SECTOR_BITS)))
{
grub_err_t err;
err = (disk->dev->read) (disk, transform_sector (disk, sector),
1 << (GRUB_DISK_CACHE_BITS
+ GRUB_DISK_SECTOR_BITS
- disk->log_sector_size), tmp_buf);
if (!err)
{
/* Copy it and store it in the disk cache. */
grub_memcpy (buf, tmp_buf + offset, size);
grub_disk_cache_store (disk->dev->id, disk->id,
sector, tmp_buf);
grub_free (tmp_buf);
return GRUB_ERR_NONE;
}
}
grub_errno = GRUB_ERR_NONE;
{
/* Uggh... Failed. Instead, just read necessary data. */
unsigned num;
grub_disk_addr_t aligned_sector;
sector += (offset >> GRUB_DISK_SECTOR_BITS);
offset &= ((1 << GRUB_DISK_SECTOR_BITS) - 1);
aligned_sector = (sector & ~((1 << (disk->log_sector_size
- GRUB_DISK_SECTOR_BITS))
- 1));
offset += ((sector - aligned_sector) << GRUB_DISK_SECTOR_BITS);
num = ((size + offset + (1 << (disk->log_sector_size))
- 1) >> (disk->log_sector_size));
tmp_buf = grub_malloc (num << disk->log_sector_size);
if (!tmp_buf)
return grub_errno;
if ((disk->dev->read) (disk, transform_sector (disk, aligned_sector),
num, tmp_buf))
{
grub_error_push ();
grub_dprintf ("disk", "%s read failed\n", disk->name);
grub_error_pop ();
return grub_errno;
}
grub_memcpy (buf, tmp_buf + offset, size);
return GRUB_ERR_NONE;
}
}
/* Read data from the disk. */
grub_err_t
grub_disk_read (grub_disk_t disk, grub_disk_addr_t sector,
grub_off_t offset, grub_size_t size, void *buf)
{
char *tmp_buf;
unsigned real_offset;
grub_off_t real_offset;
grub_disk_addr_t real_sector;
grub_size_t real_size;
/* First of all, check if the region is within the disk. */
if (grub_disk_adjust_range (disk, &sector, &offset, size) != GRUB_ERR_NONE)
@ -399,126 +492,125 @@ grub_disk_read (grub_disk_t disk, grub_disk_addr_t sector,
return grub_errno;
}
real_sector = sector;
real_offset = offset;
real_size = size;
/* Allocate a temporary buffer. */
tmp_buf = grub_malloc (GRUB_DISK_SECTOR_SIZE << GRUB_DISK_CACHE_BITS);
if (! tmp_buf)
return grub_errno;
/* Until SIZE is zero... */
while (size)
/* First read until first cache boundary. */
if (offset || (sector & (GRUB_DISK_CACHE_SIZE - 1)))
{
char *data;
grub_disk_addr_t start_sector;
grub_size_t len;
grub_size_t pos;
grub_err_t err;
grub_size_t len;
/* For reading bulk data. */
start_sector = sector & ~(GRUB_DISK_CACHE_SIZE - 1);
pos = (sector - start_sector) << GRUB_DISK_SECTOR_BITS;
len = ((GRUB_DISK_SECTOR_SIZE << GRUB_DISK_CACHE_BITS)
- pos - real_offset);
- pos - offset);
if (len > size)
len = size;
/* Fetch the cache. */
data = grub_disk_cache_fetch (disk->dev->id, disk->id, start_sector);
if (data)
{
/* Just copy it! */
grub_memcpy (buf, data + pos + real_offset, len);
grub_disk_cache_unlock (disk->dev->id, disk->id, start_sector);
}
else
{
/* Otherwise read data from the disk actually. */
if (start_sector + GRUB_DISK_CACHE_SIZE > disk->total_sectors
|| (disk->dev->read) (disk, start_sector,
GRUB_DISK_CACHE_SIZE, tmp_buf)
!= GRUB_ERR_NONE)
{
/* Uggh... Failed. Instead, just read necessary data. */
unsigned num;
char *p;
grub_errno = GRUB_ERR_NONE;
num = ((size + real_offset + GRUB_DISK_SECTOR_SIZE - 1)
>> GRUB_DISK_SECTOR_BITS);
p = grub_realloc (tmp_buf, num << GRUB_DISK_SECTOR_BITS);
if (!p)
goto finish;
tmp_buf = p;
if ((disk->dev->read) (disk, sector, num, tmp_buf))
{
grub_error_push ();
grub_dprintf ("disk", "%s read failed\n", disk->name);
grub_error_pop ();
goto finish;
}
grub_memcpy (buf, tmp_buf + real_offset, size);
/* Call the read hook, if any. */
if (disk->read_hook)
while (size)
{
grub_size_t to_read = (size > GRUB_DISK_SECTOR_SIZE) ? GRUB_DISK_SECTOR_SIZE : size;
(disk->read_hook) (sector, real_offset,
to_read);
if (grub_errno != GRUB_ERR_NONE)
goto finish;
sector++;
size -= to_read - real_offset;
real_offset = 0;
}
/* This must be the end. */
goto finish;
}
/* Copy it and store it in the disk cache. */
grub_memcpy (buf, tmp_buf + pos + real_offset, len);
grub_disk_cache_store (disk->dev->id, disk->id,
start_sector, tmp_buf);
}
/* Call the read hook, if any. */
if (disk->read_hook)
{
grub_disk_addr_t s = sector;
grub_size_t l = len;
while (l)
{
(disk->read_hook) (s, real_offset,
((l > GRUB_DISK_SECTOR_SIZE)
? GRUB_DISK_SECTOR_SIZE
: l));
if (l < GRUB_DISK_SECTOR_SIZE - real_offset)
break;
s++;
l -= GRUB_DISK_SECTOR_SIZE - real_offset;
real_offset = 0;
}
}
sector = start_sector + GRUB_DISK_CACHE_SIZE;
err = grub_disk_read_small (disk, start_sector,
offset + pos, len, buf);
if (err)
return err;
buf = (char *) buf + len;
size -= len;
real_offset = 0;
offset += len;
sector += (offset >> GRUB_DISK_SECTOR_BITS);
offset &= ((1 << GRUB_DISK_SECTOR_BITS) - 1);
}
finish:
/* Until SIZE is zero... */
while (size >= (GRUB_DISK_CACHE_SIZE << GRUB_DISK_SECTOR_BITS))
{
char *data = NULL;
grub_disk_addr_t agglomerate;
grub_err_t err;
grub_free (tmp_buf);
/* agglomerate read until we find a first cached entry. */
for (agglomerate = 0; agglomerate
< (size >> (GRUB_DISK_SECTOR_BITS + GRUB_DISK_CACHE_BITS));
agglomerate++)
{
data = grub_disk_cache_fetch (disk->dev->id, disk->id,
sector + (agglomerate
<< GRUB_DISK_CACHE_BITS));
if (data)
break;
}
if (data)
{
grub_memcpy ((char *) buf
+ (agglomerate << (GRUB_DISK_CACHE_BITS
+ GRUB_DISK_SECTOR_BITS)),
data, GRUB_DISK_CACHE_SIZE << GRUB_DISK_SECTOR_BITS);
grub_disk_cache_unlock (disk->dev->id, disk->id,
sector + (agglomerate
<< GRUB_DISK_CACHE_BITS));
}
if (agglomerate)
{
grub_disk_addr_t i;
err = (disk->dev->read) (disk, transform_sector (disk, sector),
agglomerate << (GRUB_DISK_CACHE_BITS
+ GRUB_DISK_SECTOR_BITS
- disk->log_sector_size),
buf);
if (err)
return err;
for (i = 0; i < agglomerate; i ++)
grub_disk_cache_store (disk->dev->id, disk->id,
sector + (i << GRUB_DISK_CACHE_BITS),
(char *) buf
+ (i << (GRUB_DISK_CACHE_BITS
+ GRUB_DISK_SECTOR_BITS)));
sector += agglomerate << GRUB_DISK_CACHE_BITS;
size -= agglomerate << (GRUB_DISK_CACHE_BITS + GRUB_DISK_SECTOR_BITS);
buf = (char *) buf
+ (agglomerate << (GRUB_DISK_CACHE_BITS + GRUB_DISK_SECTOR_BITS));
}
if (data)
{
sector += GRUB_DISK_CACHE_SIZE;
buf = (char *) buf + (GRUB_DISK_CACHE_SIZE << GRUB_DISK_SECTOR_BITS);
size -= (GRUB_DISK_CACHE_SIZE << GRUB_DISK_SECTOR_BITS);
}
}
/* And now read the last part. */
if (size)
{
grub_err_t err;
err = grub_disk_read_small (disk, sector, 0, size, buf);
if (err)
return err;
}
/* Call the read hook, if any. */
if (disk->read_hook)
{
grub_disk_addr_t s = real_sector;
grub_size_t l = real_size;
grub_off_t o = real_offset;
while (l)
{
(disk->read_hook) (s, o,
((l > GRUB_DISK_SECTOR_SIZE)
? GRUB_DISK_SECTOR_SIZE
: l));
s++;
l -= GRUB_DISK_SECTOR_SIZE - o;
o = 0;
}
}
return grub_errno;
}
@ -528,25 +620,31 @@ grub_disk_write (grub_disk_t disk, grub_disk_addr_t sector,
grub_off_t offset, grub_size_t size, const void *buf)
{
unsigned real_offset;
grub_disk_addr_t aligned_sector;
grub_dprintf ("disk", "Writing `%s'...\n", disk->name);
if (grub_disk_adjust_range (disk, &sector, &offset, size) != GRUB_ERR_NONE)
return -1;
real_offset = offset;
aligned_sector = (sector & ~((1 << (disk->log_sector_size
- GRUB_DISK_SECTOR_BITS)) - 1));
real_offset = offset + ((sector - aligned_sector) << GRUB_DISK_SECTOR_BITS);
sector = aligned_sector;
while (size)
{
if (real_offset != 0 || (size < GRUB_DISK_SECTOR_SIZE && size != 0))
if (real_offset != 0 || (size < (1U << disk->log_sector_size)
&& size != 0))
{
char tmp_buf[GRUB_DISK_SECTOR_SIZE];
char tmp_buf[1 << disk->log_sector_size];
grub_size_t len;
grub_partition_t part;
part = disk->partition;
disk->partition = 0;
if (grub_disk_read (disk, sector, 0, GRUB_DISK_SECTOR_SIZE, tmp_buf)
if (grub_disk_read (disk, sector,
0, (1 << disk->log_sector_size), tmp_buf)
!= GRUB_ERR_NONE)
{
disk->partition = part;
@ -554,7 +652,7 @@ grub_disk_write (grub_disk_t disk, grub_disk_addr_t sector,
}
disk->partition = part;
len = GRUB_DISK_SECTOR_SIZE - real_offset;
len = (1 << disk->log_sector_size) - real_offset;
if (len > size)
len = size;
@ -565,7 +663,7 @@ grub_disk_write (grub_disk_t disk, grub_disk_addr_t sector,
if ((disk->dev->write) (disk, sector, 1, tmp_buf) != GRUB_ERR_NONE)
goto finish;
sector++;
sector += (1 << (disk->log_sector_size - GRUB_DISK_SECTOR_BITS));
buf = (char *) buf + len;
size -= len;
real_offset = 0;
@ -575,8 +673,8 @@ grub_disk_write (grub_disk_t disk, grub_disk_addr_t sector,
grub_size_t len;
grub_size_t n;
len = size & ~(GRUB_DISK_SECTOR_SIZE - 1);
n = size >> GRUB_DISK_SECTOR_BITS;
len = size & ~((1 << disk->log_sector_size) - 1);
n = size >> disk->log_sector_size;
if ((disk->dev->write) (disk, sector, n, buf) != GRUB_ERR_NONE)
goto finish;
@ -599,6 +697,8 @@ grub_disk_get_size (grub_disk_t disk)
{
if (disk->partition)
return grub_partition_get_len (disk->partition);
else if (disk->total_sectors != GRUB_DISK_SIZE_UNKNOWN)
return disk->total_sectors << (disk->log_sector_size - GRUB_DISK_SECTOR_BITS);
else
return disk->total_sectors;
return GRUB_DISK_SIZE_UNKNOWN;
}

View file

@ -616,13 +616,17 @@ grub_guess_root_device (const char *dir)
if (os_dev)
{
if (strncmp (os_dev, "/dev/dm-", sizeof ("/dev/dm-") - 1) != 0)
int dm = (strncmp (os_dev, "/dev/dm-", sizeof ("/dev/dm-") - 1) == 0);
int root = (strcmp (os_dev, "/dev/root") == 0);
if (!dm && !root)
return os_dev;
if (stat (os_dev, &st) < 0)
grub_util_error ("cannot stat `%s'", os_dev);
if (stat (os_dev, &st) >= 0)
{
free (os_dev);
dev = st.st_rdev;
return grub_find_device (dm ? "/dev/mapper" : "/dev", dev);
}
free (os_dev);
dev = st.st_rdev;
return grub_find_device ("/dev/mapper", dev);
}
if (stat (dir, &st) < 0)

View file

@ -43,6 +43,7 @@
#ifdef __linux__
# include <sys/ioctl.h> /* ioctl */
# include <sys/mount.h>
# if !defined(__GLIBC__) || \
((__GLIBC__ < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ < 1)))
/* Maybe libc doesn't have large file support. */
@ -267,6 +268,7 @@ grub_util_biosdisk_open (const char *name, grub_disk_t disk)
# else
unsigned long long nr;
# endif
int sector_size;
int fd;
fd = open (map[drive].device, O_RDONLY);
@ -299,16 +301,28 @@ grub_util_biosdisk_open (const char *name, grub_disk_t disk)
goto fail;
}
if (ioctl (fd, BLKSSZGET, &sector_size))
{
close (fd);
goto fail;
}
close (fd);
if (sector_size & (sector_size - 1) || !sector_size)
goto fail;
for (disk->log_sector_size = 0;
(1 << disk->log_sector_size) < sector_size;
disk->log_sector_size++);
# if defined (__APPLE__)
disk->total_sectors = nr;
# elif defined(__NetBSD__)
disk->total_sectors = label.d_secperunit;
# else
disk->total_sectors = nr / 512;
disk->total_sectors = nr >> disk->log_sector_size;
if (nr % 512)
if (nr & ((1 << disk->log_sector_size) - 1))
grub_util_error ("unaligned device size");
# endif
@ -325,7 +339,7 @@ grub_util_biosdisk_open (const char *name, grub_disk_t disk)
if (stat (map[drive].device, &st) < 0)
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "cannot stat `%s'", map[drive].device);
disk->total_sectors = st.st_size >> GRUB_DISK_SECTOR_BITS;
disk->total_sectors = st.st_size >> disk->log_sector_size;
grub_util_info ("the size of %s is %lu", name, disk->total_sectors);
@ -564,6 +578,7 @@ linux_find_partition (char *dev, grub_disk_addr_t sector)
int i;
char real_dev[PATH_MAX];
struct linux_partition_cache *cache;
int missing = 0;
strcpy(real_dev, dev);
@ -572,6 +587,12 @@ linux_find_partition (char *dev, grub_disk_addr_t sector)
p = real_dev + len - 4;
format = "part%d";
}
else if (strncmp (real_dev, "/dev/disk/by-id/",
sizeof ("/dev/disk/by-id/") - 1) == 0)
{
p = real_dev + len;
format = "-part%d";
}
else if (real_dev[len - 1] >= '0' && real_dev[len - 1] <= '9')
{
p = real_dev + len;
@ -602,7 +623,13 @@ linux_find_partition (char *dev, grub_disk_addr_t sector)
fd = open (real_dev, O_RDONLY);
if (fd == -1)
continue;
{
if (missing++ < 10)
continue;
else
return 0;
}
missing = 0;
close (fd);
start = find_partition_start (real_dev);
@ -791,7 +818,7 @@ open_device (const grub_disk_t disk, grub_disk_addr_t sector, int flags)
_syscall5 (int, _llseek, uint, filedes, ulong, hi, ulong, lo,
loff_t *, res, uint, wh);
offset = (loff_t) sector << GRUB_DISK_SECTOR_BITS;
offset = (loff_t) sector << disk->log_sector_size;
if (_llseek (fd, offset >> 32, offset & 0xffffffff, &result, SEEK_SET))
{
grub_error (GRUB_ERR_BAD_DEVICE, "cannot seek `%s'", map[disk->id].device);
@ -801,7 +828,7 @@ open_device (const grub_disk_t disk, grub_disk_addr_t sector, int flags)
}
#else
{
off_t offset = (off_t) sector << GRUB_DISK_SECTOR_BITS;
off_t offset = (off_t) sector << disk->log_sector_size;
if (lseek (fd, offset, SEEK_SET) != offset)
{
@ -901,19 +928,20 @@ grub_util_biosdisk_read (grub_disk_t disk, grub_disk_addr_t sector,
sectors that are read together with the MBR in one read. It
should only remap the MBR, so we split the read in two
parts. -jochen */
if (nread (fd, buf, GRUB_DISK_SECTOR_SIZE) != GRUB_DISK_SECTOR_SIZE)
if (nread (fd, buf, (1 << disk->log_sector_size))
!= (1 << disk->log_sector_size))
{
grub_error (GRUB_ERR_READ_ERROR, "cannot read `%s'", map[disk->id].device);
return grub_errno;
}
buf += GRUB_DISK_SECTOR_SIZE;
buf += (1 << disk->log_sector_size);
size--;
}
#endif /* __linux__ */
if (nread (fd, buf, size << GRUB_DISK_SECTOR_BITS)
!= (ssize_t) (size << GRUB_DISK_SECTOR_BITS))
if (nread (fd, buf, size << disk->log_sector_size)
!= (ssize_t) (size << disk->log_sector_size))
grub_error (GRUB_ERR_READ_ERROR, "cannot read from `%s'", map[disk->id].device);
return grub_errno;
@ -946,8 +974,8 @@ grub_util_biosdisk_write (grub_disk_t disk, grub_disk_addr_t sector,
if (fd < 0)
return grub_errno;
if (nwrite (fd, buf, size << GRUB_DISK_SECTOR_BITS)
!= (ssize_t) (size << GRUB_DISK_SECTOR_BITS))
if (nwrite (fd, buf, size << disk->log_sector_size)
!= (ssize_t) (size << disk->log_sector_size))
grub_error (GRUB_ERR_WRITE_ERROR, "cannot write to `%s'", map[disk->id].device);
return grub_errno;
@ -1838,7 +1866,12 @@ grub_util_biosdisk_is_floppy (grub_disk_t disk)
/* Shouldn't happen either. */
if (fstat (fd, &st) < 0)
return 0;
{
close (fd);
return 0;
}
close (fd);
#if defined(__NetBSD__)
if (major(st.st_rdev) == RAW_FLOPPY_MAJOR)

View file

@ -64,6 +64,12 @@
0x1b0 f30
0x1c0 f31 */
#include <grub/symbol.h>
#include <grub/dl.h>
.file "setjmp.S"
GRUB_MOD_LICENSE ("GPLv2+")
/* The following two entry points are the traditional entry points: */

View file

@ -265,6 +265,27 @@ rs_recover (gf_single_t *m, grub_size_t s, grub_size_t rs)
syndroms (m, s, rs, sy);
for (i = 0; i < (int) rs; i++)
if (sy[i] != 0)
break;
/* No error detected. */
if (i == (int) rs)
{
#ifndef STANDALONE
free (sigma);
free (errpot);
free (errpos);
free (sy);
#else
scratch -= rs2 * sizeof (gf_single_t);
scratch -= rs2 * sizeof (gf_single_t);
scratch -= rs2 * sizeof (int);
scratch -= rs * sizeof (gf_single_t);
#endif
return;
}
{
gf_single_t *eq;
@ -275,14 +296,6 @@ rs_recover (gf_single_t *m, grub_size_t s, grub_size_t rs)
scratch += rs2 * (rs2 + 1) * sizeof (gf_single_t);
#endif
for (i = 0; i < (int) rs; i++)
if (sy[i] != 0)
break;
/* No error detected. */
if (i == (int) rs)
return;
for (i = 0; i < (int) rs2; i++)
for (j = 0; j < (int) rs2 + 1; j++)
eq[i * (rs2 + 1) + j] = sy[i+j];
@ -504,6 +517,7 @@ main (int argc, char **argv)
rs = s / 3;
buf = xmalloc (s + rs + SECTOR_SIZE);
fread (buf, 1, s, in);
fclose (in);
grub_reed_solomon_add_redundancy (buf, s, rs);

View file

@ -33,6 +33,8 @@
#include <grub/mm.h>
#include <grub/cpu/relocator.h>
GRUB_MOD_LICENSE ("GPLv3+");
static grub_dl_t my_mod;
static struct grub_relocator *rel;
static grub_uint32_t ebx = 0xffffffff;

View file

@ -452,11 +452,11 @@ grub_cpu_xnu_fill_devprop (void)
}
devprop = grub_xnu_create_value (&(efikey->first_child), "device-properties");
if (devprop)
{
devprop->data = grub_malloc (total_length);
devprop->datasize = total_length;
}
if (!devprop)
return grub_errno;
devprop->data = grub_malloc (total_length);
devprop->datasize = total_length;
ptr = devprop->data;
head = ptr;

View file

@ -31,6 +31,8 @@
#include <grub/efi/efi.h>
#include <grub/elf.h>
GRUB_MOD_LICENSE ("GPLv3+");
#define ALIGN_MIN (256*1024*1024)
#define GRUB_ELF_SEARCH 1024

View file

@ -34,11 +34,18 @@ GRUB_MOD_LICENSE ("GPLv3+");
struct grub_acorn_boot_block
{
grub_uint8_t misc[0x1C0];
struct grub_filecore_disc_record disc_record;
grub_uint8_t flags;
grub_uint16_t start_cylinder;
grub_uint8_t checksum;
union
{
struct
{
grub_uint8_t misc[0x1C0];
struct grub_filecore_disc_record disc_record;
grub_uint8_t flags;
grub_uint16_t start_cylinder;
grub_uint8_t checksum;
} __attribute__ ((packed, aligned));
grub_uint8_t bin[0x200];
};
} __attribute__ ((packed, aligned));
struct linux_part
@ -71,7 +78,7 @@ acorn_partition_map_find (grub_disk_t disk, struct linux_part *m,
goto fail;
for (i = 0; i != 0x1ff; ++i)
checksum = (checksum & 0xff) + (checksum >> 8) + boot.misc[i];
checksum = ((checksum & 0xff) + (checksum >> 8) + boot.bin[i]);
if ((grub_uint8_t) checksum != boot.checksum)
goto fail;

View file

@ -92,8 +92,11 @@ grub_partition_msdos_iterate (grub_disk_t disk,
{
e = mbr.entries + p.index;
p.start = p.offset + grub_le_to_cpu32 (e->start) - delta;
p.len = grub_le_to_cpu32 (e->length);
p.start = p.offset
+ (grub_le_to_cpu32 (e->start)
<< (disk->log_sector_size - GRUB_DISK_SECTOR_BITS)) - delta;
p.len = grub_le_to_cpu32 (e->length)
<< (disk->log_sector_size - GRUB_DISK_SECTOR_BITS);
p.msdostype = e->type;
grub_dprintf ("partition",
@ -128,7 +131,9 @@ grub_partition_msdos_iterate (grub_disk_t disk,
if (grub_msdos_partition_is_extended (e->type))
{
p.offset = ext_offset + grub_le_to_cpu32 (e->start);
p.offset = ext_offset
+ (grub_le_to_cpu32 (e->start)
<< (disk->log_sector_size - GRUB_DISK_SECTOR_BITS));
if (! ext_offset)
ext_offset = p.offset;
@ -206,8 +211,11 @@ pc_partition_map_embed (struct grub_disk *disk, unsigned int *nsectors,
e = mbr.entries + i;
if (!grub_msdos_partition_is_empty (e->type)
&& end > offset + grub_le_to_cpu32 (e->start))
end = offset + grub_le_to_cpu32 (e->start);
&& end > offset
+ (grub_le_to_cpu32 (e->start)
<< (disk->log_sector_size - GRUB_DISK_SECTOR_BITS)))
end = offset + (grub_le_to_cpu32 (e->start)
<< (disk->log_sector_size - GRUB_DISK_SECTOR_BITS));
/* If this is a GPT partition, this MBR is just a dummy. */
if (e->type == GRUB_PC_PARTITION_TYPE_GPT_DISK && i == 0)
@ -221,7 +229,9 @@ pc_partition_map_embed (struct grub_disk *disk, unsigned int *nsectors,
if (grub_msdos_partition_is_extended (e->type))
{
offset = ext_offset + grub_le_to_cpu32 (e->start);
offset = ext_offset
+ (grub_le_to_cpu32 (e->start)
<< (disk->log_sector_size - GRUB_DISK_SECTOR_BITS));
if (! ext_offset)
ext_offset = offset;

View file

@ -21,6 +21,9 @@
#include <grub/gui.h>
#include <grub/gui_string_util.h>
#include <grub/misc.h>
#include <grub/dl.h>
GRUB_MOD_LICENSE ("GPLv3+");
struct named_color
{

View file

@ -39,6 +39,15 @@ GRUB_MOD_LICENSE ("GPLv3+");
#define JPEG_MARKER_DQT 0xdb
#define JPEG_MARKER_SOF0 0xc0
#define JPEG_MARKER_SOS 0xda
#define JPEG_MARKER_DRI 0xdd
#define JPEG_MARKER_RST0 0xd0
#define JPEG_MARKER_RST1 0xd1
#define JPEG_MARKER_RST2 0xd2
#define JPEG_MARKER_RST3 0xd3
#define JPEG_MARKER_RST4 0xd4
#define JPEG_MARKER_RST5 0xd5
#define JPEG_MARKER_RST6 0xd6
#define JPEG_MARKER_RST7 0xd7
#define SHIFT_BITS 8
#define CONST(x) ((int) ((x) * (1L << SHIFT_BITS) + 0.5))
@ -66,6 +75,7 @@ struct grub_jpeg_data
{
grub_file_t file;
struct grub_video_bitmap **bitmap;
grub_uint8_t *bitmap_ptr;
int image_width;
int image_height;
@ -82,6 +92,8 @@ struct grub_jpeg_data
jpeg_data_unit_t cbdu;
int vs, hs;
int dri;
int r1;
int dc_value[3];
@ -315,6 +327,18 @@ grub_jpeg_decode_sof (struct grub_jpeg_data *data)
return grub_errno;
}
static grub_err_t
grub_jpeg_decode_dri (struct grub_jpeg_data *data)
{
if (grub_jpeg_get_word (data) != 4)
return grub_error (GRUB_ERR_BAD_FILE_TYPE,
"jpeg: DRI marker length must be 4");
data->dri = grub_jpeg_get_word (data);
return grub_errno;
}
static void
grub_jpeg_idct_transform (jpeg_data_unit_t du)
{
@ -526,8 +550,7 @@ grub_jpeg_ycrcb_to_rgb (int yy, int cr, int cb, grub_uint8_t * rgb)
static grub_err_t
grub_jpeg_decode_sos (struct grub_jpeg_data *data)
{
int i, cc, r1, c1, nr1, nc1, vb, hb;
grub_uint8_t *ptr1;
int i, cc;
grub_uint32_t data_offset;
data_offset = data->file->offset;
@ -563,17 +586,25 @@ grub_jpeg_decode_sos (struct grub_jpeg_data *data)
GRUB_VIDEO_BLIT_FORMAT_RGB_888))
return grub_errno;
data->bit_mask = 0x0;
data->bitmap_ptr = (*data->bitmap)->data;
return GRUB_ERR_NONE;
}
static grub_err_t
grub_jpeg_decode_data (struct grub_jpeg_data *data)
{
int c1, vb, hb, nr1, nc1;
int rst = data->dri;
vb = data->vs * 8;
hb = data->hs * 8;
nr1 = (data->image_height + vb - 1) / vb;
nc1 = (data->image_width + hb - 1) / hb;
ptr1 = (*data->bitmap)->data;
for (r1 = 0; r1 < nr1;
r1++, ptr1 += (vb * data->image_width - hb * nc1) * 3)
for (c1 = 0; c1 < nc1; c1++, ptr1 += hb * 3)
for (; data->r1 < nr1 && (!data->dri || rst);
data->r1++, data->bitmap_ptr += (vb * data->image_width - hb * nc1) * 3)
for (c1 = 0; c1 < nc1 && (!data->dri || rst);
c1++, rst--, data->bitmap_ptr += hb * 3)
{
int r2, c2, nr2, nc2;
grub_uint8_t *ptr2;
@ -588,10 +619,10 @@ grub_jpeg_decode_sos (struct grub_jpeg_data *data)
if (grub_errno)
return grub_errno;
nr2 = (r1 == nr1 - 1) ? (data->image_height - r1 * vb) : vb;
nr2 = (data->r1 == nr1 - 1) ? (data->image_height - data->r1 * vb) : vb;
nc2 = (c1 == nc1 - 1) ? (data->image_width - c1 * hb) : hb;
ptr2 = ptr1;
ptr2 = data->bitmap_ptr;
for (r2 = 0; r2 < nr2; r2++, ptr2 += (data->image_width - nc2) * 3)
for (c2 = 0; c2 < nc2; c2++, ptr2 += 3)
{
@ -600,8 +631,7 @@ grub_jpeg_decode_sos (struct grub_jpeg_data *data)
i0 = (r2 / data->vs) * 8 + (c2 / data->hs);
cr = data->crdu[i0];
cb = data->cbdu[i0];
yy =
data->ydu[(r2 / 8) * 2 + (c2 / 8)][(r2 % 8) * 8 + (c2 % 8)];
yy = data->ydu[(r2 / 8) * 2 + (c2 / 8)][(r2 % 8) * 8 + (c2 % 8)];
grub_jpeg_ycrcb_to_rgb (yy, cr, cb, ptr2);
}
@ -610,6 +640,16 @@ grub_jpeg_decode_sos (struct grub_jpeg_data *data)
return grub_errno;
}
static void
grub_jpeg_reset (struct grub_jpeg_data *data)
{
data->bit_mask = 0x0;
data->dc_value[0] = 0;
data->dc_value[1] = 0;
data->dc_value[2] = 0;
}
static grub_uint8_t
grub_jpeg_get_marker (struct grub_jpeg_data *data)
{
@ -655,8 +695,22 @@ grub_jpeg_decode_jpeg (struct grub_jpeg_data *data)
case JPEG_MARKER_SOF0: /* Start Of Frame 0. */
grub_jpeg_decode_sof (data);
break;
case JPEG_MARKER_DRI: /* Define Restart Interval. */
grub_jpeg_decode_dri (data);
break;
case JPEG_MARKER_SOS: /* Start Of Scan. */
grub_jpeg_decode_sos (data);
if (grub_jpeg_decode_sos (data))
break;
case JPEG_MARKER_RST0: /* Restart. */
case JPEG_MARKER_RST1:
case JPEG_MARKER_RST2:
case JPEG_MARKER_RST3:
case JPEG_MARKER_RST4:
case JPEG_MARKER_RST5:
case JPEG_MARKER_RST6:
case JPEG_MARKER_RST7:
grub_jpeg_decode_data (data);
grub_jpeg_reset (data);
break;
case JPEG_MARKER_EOI: /* End Of Image. */
return grub_errno;

View file

@ -82,6 +82,9 @@ enum grub_ata_commands
GRUB_ATA_CMD_PACKET = 0xa0,
GRUB_ATA_CMD_READ_SECTORS = 0x20,
GRUB_ATA_CMD_READ_SECTORS_EXT = 0x24,
GRUB_ATA_CMD_READ_SECTORS_DMA = 0xc8,
GRUB_ATA_CMD_READ_SECTORS_DMA_EXT = 0x25,
GRUB_ATA_CMD_SECURITY_FREEZE_LOCK = 0xf5,
GRUB_ATA_CMD_SET_FEATURES = 0xef,
GRUB_ATA_CMD_SLEEP = 0xe6,
@ -89,30 +92,76 @@ enum grub_ata_commands
GRUB_ATA_CMD_STANDBY_IMMEDIATE = 0xe0,
GRUB_ATA_CMD_WRITE_SECTORS = 0x30,
GRUB_ATA_CMD_WRITE_SECTORS_EXT = 0x34,
GRUB_ATA_CMD_WRITE_SECTORS_DMA_EXT = 0x35,
GRUB_ATA_CMD_WRITE_SECTORS_DMA = 0xca,
};
enum grub_ata_timeout_milliseconds
{
GRUB_ATA_TOUT_STD = 1000, /* 1s standard timeout. */
GRUB_ATA_TOUT_DATA = 10000, /* 10s DATA I/O timeout. */
GRUB_ATA_TOUT_DEV_INIT = 10000, /* Give the device 10s on first try to spinon. */
GRUB_ATA_TOUT_SPINUP = 10000, /* Give the device 10s on first try to spinon. */
};
struct grub_ata_device
typedef union
{
/* IDE port to use. */
int port;
grub_uint8_t raw[11];
struct
{
union
{
grub_uint8_t features;
grub_uint8_t error;
};
union
{
grub_uint8_t sectors;
grub_uint8_t atapi_ireason;
};
union
{
grub_uint8_t lba_low;
grub_uint8_t sectnum;
};
union
{
grub_uint8_t lba_mid;
grub_uint8_t cyllsb;
grub_uint8_t atapi_cntlow;
};
union
{
grub_uint8_t lba_high;
grub_uint8_t cylmsb;
grub_uint8_t atapi_cnthigh;
};
grub_uint8_t disk;
union
{
grub_uint8_t cmd;
grub_uint8_t status;
};
grub_uint8_t sectors48;
grub_uint8_t lba48_low;
grub_uint8_t lba48_mid;
grub_uint8_t lba48_high;
};
} grub_ata_regs_t;
/* IO addresses on which the registers for this device can be
found. */
grub_port_t ioaddress;
grub_port_t ioaddress2;
/* Two devices can be connected to a single cable. Use this field
to select device 0 (commonly known as "master") or device 1
(commonly known as "slave"). */
int device;
/* ATA pass through parameters and function. */
struct grub_disk_ata_pass_through_parms
{
grub_ata_regs_t taskfile;
void * buffer;
grub_size_t size;
int write;
void *cmd;
int cmdsize;
int dma;
};
struct grub_ata
{
/* Addressing methods available for accessing this device. If CHS
is only available, use that. Otherwise use LBA, except for the
high sectors. In that case use LBA48. */
@ -129,49 +178,41 @@ struct grub_ata_device
/* Set to 0 for ATA, set to 1 for ATAPI. */
int atapi;
int present;
int dma;
struct grub_ata_device *next;
int *present;
void *data;
struct grub_ata_dev *dev;
};
grub_err_t EXPORT_FUNC(grub_ata_wait_not_busy) (struct grub_ata_device *dev,
int milliseconds);
grub_err_t EXPORT_FUNC(grub_ata_wait_drq) (struct grub_ata_device *dev,
int rw, int milliseconds);
void EXPORT_FUNC(grub_ata_pio_read) (struct grub_ata_device *dev,
char *buf, grub_size_t size);
typedef struct grub_ata *grub_ata_t;
static inline void
grub_ata_regset (struct grub_ata_device *dev, int reg, int val)
struct grub_ata_dev
{
grub_outb (val, dev->ioaddress + reg);
}
/* Call HOOK with each device name, until HOOK returns non-zero. */
int (*iterate) (int (*hook) (int id, int bus));
static inline grub_uint8_t
grub_ata_regget (struct grub_ata_device *dev, int reg)
{
return grub_inb (dev->ioaddress + reg);
}
/* Open the device named NAME, and set up SCSI. */
grub_err_t (*open) (int id, int bus, struct grub_ata *scsi);
static inline void
grub_ata_regset2 (struct grub_ata_device *dev, int reg, int val)
{
grub_outb (val, dev->ioaddress2 + reg);
}
/* Close the scsi device SCSI. */
void (*close) (struct grub_ata *ata);
static inline grub_uint8_t
grub_ata_regget2 (struct grub_ata_device *dev, int reg)
{
return grub_inb (dev->ioaddress2 + reg);
}
/* Read SIZE bytes from the device SCSI into BUF after sending the
command CMD of size CMDSIZE. */
grub_err_t (*readwrite) (struct grub_ata *ata,
struct grub_disk_ata_pass_through_parms *parms,
int spinup);
static inline grub_err_t
grub_ata_check_ready (struct grub_ata_device *dev)
{
if (grub_ata_regget (dev, GRUB_ATA_REG_STATUS) & GRUB_ATA_STATUS_BUSY)
return grub_ata_wait_not_busy (dev, GRUB_ATA_TOUT_STD);
/* The next scsi device. */
struct grub_ata_dev *next;
};
return GRUB_ERR_NONE;
}
typedef struct grub_ata_dev *grub_ata_dev_t;
void grub_ata_dev_register (grub_ata_dev_t dev);
void grub_ata_dev_unregister (grub_ata_dev_t dev);
#endif /* ! GRUB_ATA_HEADER */

View file

@ -101,6 +101,9 @@ struct grub_disk
/* The total number of sectors. */
grub_uint64_t total_sectors;
/* Logarithm of sector size. */
unsigned int log_sector_size;
/* The id used by the disk cache manager. */
unsigned long id;
@ -133,9 +136,10 @@ typedef struct grub_disk_memberlist *grub_disk_memberlist_t;
/* The maximum number of disk caches. */
#define GRUB_DISK_CACHE_NUM 1021
/* The size of a disk cache in sector units. */
#define GRUB_DISK_CACHE_SIZE 8
#define GRUB_DISK_CACHE_BITS 3
/* The size of a disk cache in 512B units. Must be at least as big as the
largest supported sector size, currently 16K. */
#define GRUB_DISK_CACHE_BITS 6
#define GRUB_DISK_CACHE_SIZE (1 << GRUB_DISK_CACHE_BITS)
/* Return value of grub_disk_get_size() in case disk size is unknown. */
#define GRUB_DISK_SIZE_UNKNOWN 0xffffffffffffffffULL
@ -165,17 +169,6 @@ grub_uint64_t EXPORT_FUNC(grub_disk_get_size) (grub_disk_t disk);
extern void (* EXPORT_VAR(grub_disk_firmware_fini)) (void);
extern int EXPORT_VAR(grub_disk_firmware_is_tainted);
/* ATA pass through parameters and function. */
struct grub_disk_ata_pass_through_parms
{
grub_uint8_t taskfile[8];
void * buffer;
int size;
};
extern grub_err_t (* EXPORT_VAR(grub_disk_ata_pass_through)) (grub_disk_t,
struct grub_disk_ata_pass_through_parms *);
#if defined (GRUB_UTIL) || defined (GRUB_MACHINE_EMU)
void grub_lvm_init (void);
void grub_mdraid09_init (void);

View file

@ -90,6 +90,9 @@ static const char grub_module_name_##name[] \
#ifndef ASM_FILE
#define GRUB_MOD_LICENSE(license) \
static char grub_module_license[] __attribute__ ((section (GRUB_MOD_SECTION (module_license)), used)) = "LICENSE=" license;
#define GRUB_MOD_DEP(name) \
static const char grub_module_depend_##name[] \
__attribute__((section(GRUB_MOD_SECTION(moddeps)), __used__)) = #name
#else
#define GRUB_MOD_LICENSE(license) \
.section GRUB_MOD_SECTION(module_license), "a"; \

View file

@ -29,9 +29,13 @@ struct grub_scsi;
enum
{
GRUB_SCSI_SUBSYSTEM_USBMS,
GRUB_SCSI_SUBSYSTEM_ATAPI
GRUB_SCSI_SUBSYSTEM_PATA,
GRUB_SCSI_SUBSYSTEM_AHCI,
GRUB_SCSI_NUM_SUBSYSTEMS
};
extern const char grub_scsi_names[GRUB_SCSI_NUM_SUBSYSTEMS][5];
#define GRUB_SCSI_ID_SUBSYSTEM_SHIFT 24
#define GRUB_SCSI_ID_BUS_SHIFT 8
#define GRUB_SCSI_ID_LUN_SHIFT 0
@ -45,16 +49,11 @@ grub_make_scsi_id (int subsystem, int bus, int lun)
struct grub_scsi_dev
{
/* The device name. */
const char *name;
grub_uint8_t id;
/* Call HOOK with each device name, until HOOK returns non-zero. */
int (*iterate) (int (*hook) (int bus, int luns));
int (*iterate) (int NESTED_FUNC_ATTR (*hook) (int id, int bus, int luns));
/* Open the device named NAME, and set up SCSI. */
grub_err_t (*open) (int bus, struct grub_scsi *scsi);
grub_err_t (*open) (int id, int bus, struct grub_scsi *scsi);
/* Close the scsi device SCSI. */
void (*close) (struct grub_scsi *scsi);

View file

@ -77,7 +77,15 @@ enum zio_compress {
ZIO_COMPRESS_OFF,
ZIO_COMPRESS_LZJB,
ZIO_COMPRESS_EMPTY,
ZIO_COMPRESS_GZIP,
ZIO_COMPRESS_GZIP1,
ZIO_COMPRESS_GZIP2,
ZIO_COMPRESS_GZIP3,
ZIO_COMPRESS_GZIP4,
ZIO_COMPRESS_GZIP5,
ZIO_COMPRESS_GZIP6,
ZIO_COMPRESS_GZIP7,
ZIO_COMPRESS_GZIP8,
ZIO_COMPRESS_GZIP9,
ZIO_COMPRESS_FUNCTIONS
};

View file

@ -1,7 +1,7 @@
/* deviceiter.c - iterate over system devices */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2007,2008 Free Software Foundation, Inc.
* Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2007,2008,2011 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -286,6 +286,20 @@ get_scsi_disk_name (char *name, int unit)
#endif
}
#ifdef __FreeBSD_kernel__
static void
get_ada_disk_name (char *name, int unit)
{
sprintf (name, "/dev/ada%d", unit);
}
static void
get_ataraid_disk_name (char *name, int unit)
{
sprintf (name, "/dev/ar%d", unit);
}
#endif
#ifdef __linux__
static void
get_virtio_disk_name (char *name, int unit)
@ -620,6 +634,35 @@ grub_util_iterate_devices (int NESTED_FUNC_ATTR (*hook) (const char *, int),
}
}
#ifdef __FreeBSD_kernel__
/* IDE disks using ATA Direct Access driver. */
if (get_kfreebsd_version () >= 800000)
for (i = 0; i < 96; i++)
{
char name[16];
get_ada_disk_name (name, i);
if (check_device_readable_unique (name))
{
if (hook (name, 0))
goto out;
}
}
/* ATARAID disks. */
for (i = 0; i < 8; i++)
{
char name[20];
get_ataraid_disk_name (name, i);
if (check_device_readable_unique (name))
{
if (hook (name, 0))
goto out;
}
}
#endif
#ifdef __linux__
/* Virtio disks. */
for (i = 0; i < 26; i++)

View file

@ -61,7 +61,8 @@ enum {
CMD_CMP,
CMD_HEX,
CMD_CRC,
CMD_BLOCKLIST
CMD_BLOCKLIST,
CMD_TESTLOAD
};
#define BUF_SIZE 32256
@ -359,6 +360,9 @@ fstest (int n, char **args)
case CMD_BLOCKLIST:
execute_command ("blocklist", n, args);
grub_printf ("\n");
case CMD_TESTLOAD:
execute_command ("testload", n, args);
grub_printf ("\n");
}
for (i = 0; i < num_disks; i++)
@ -520,6 +524,11 @@ argp_parser (int key, char *arg, struct argp_state *state)
cmd = CMD_BLOCKLIST;
nparm = 1;
}
else if (!grub_strcmp (arg, "testload"))
{
cmd = CMD_TESTLOAD;
nparm = 1;
}
else
{
fprintf (stderr, _("Invalid command %s.\n"), arg);

View file

@ -74,7 +74,7 @@ if [ "${target_cpu}-${platform}" = "i386-pc" ] ; then
elif [ "${platform}" = "ieee1275" ] || [ "${platform}" = "efi" ] ; then
disk_module=
else
disk_module=ata
disk_module=native
fi
# Usage: usage
@ -111,7 +111,7 @@ Install GRUB on your drive.
EOF
if [ "${target_cpu}-${platform}" = "i386-pc" ] ; then
cat <<EOF
--disk-module=MODULE disk module to use
--disk-module=MODULE disk module to use (biosdisk or native)
EOF
fi
if [ "${target_cpu}-${platform}" = "i386-ieee1275" ] || [ "${target_cpu}-${platform}" = "powerpc-ieee1275" ] ; then
@ -489,6 +489,14 @@ done
# Device abstraction module, if any (lvm, raid).
devabstraction_module="`"$grub_probe" --device-map="${device_map}" --target=abstraction --device "${grub_device}"`"
if [ "x$disk_module" = xata ]; then
disk_module=pata
fi
if [ "x$disk_module" = xnative ]; then
disk_module="pata ahci ohci uhci usbms"
fi
# The order in this list is critical. Be careful when modifying it.
modules="$modules $disk_module"
modules="$modules $fs_module $partmap_module $devabstraction_module"
@ -522,7 +530,7 @@ if [ "x${devabstraction_module}" = "x" ] ; then
# Strip partition number
grub_partition="`echo "${grub_drive}" | sed -e 's/^[^,]*[,)]//; s/)$//'`"
grub_drive="`echo "${grub_drive}" | sed -e s/,[a-z0-9,]*//g`"
if [ "$disk_module" = ata ] || [ "x${grub_drive}" != "x${install_drive}" ] || ([ "x$platform" != xefi ] && [ "x$platform" != xpc ] && [ x"${target_cpu}-${platform}" != x"sparc64-ieee1275" ]) ; then
if ([ "x$disk_module" != x ] && [ "x$disk_module" != xbiosdisk ]) || [ "x${grub_drive}" != "x${install_drive}" ] || ([ "x$platform" != xefi ] && [ "x$platform" != xpc ] && [ x"${target_cpu}-${platform}" != x"sparc64-ieee1275" ]); then
# generic method (used on coreboot and ata mod)
uuid="`"$grub_probe" --device-map="${device_map}" --target=fs_uuid --device "${grub_device}"`"
if [ "x${uuid}" = "x" ] ; then

View file

@ -63,7 +63,7 @@ is_path_readable_by_grub ()
# ... or if we can't figure out the abstraction module, for example if
# memberlist fails on an LVM volume group.
if ${grub_probe} -t abstraction $path > /dev/null 2>&1 ; then : ; else
if "${grub_probe}" -t abstraction "$path" > /dev/null 2>&1 ; then : ; else
return 1
fi
@ -105,12 +105,6 @@ prepare_grub_to_access_device ()
{
device="$1"
# Abstraction modules aren't auto-loaded.
abstraction="`"${grub_probe}" --device "${device}" --target=abstraction`"
for module in ${abstraction} ; do
echo "insmod ${module}"
done
partmap="`"${grub_probe}" --device "${device}" --target=partmap`"
for module in ${partmap} ; do
case "${module}" in
@ -121,6 +115,12 @@ prepare_grub_to_access_device ()
esac
done
# Abstraction modules aren't auto-loaded.
abstraction="`"${grub_probe}" --device "${device}" --target=abstraction`"
for module in ${abstraction} ; do
echo "insmod ${module}"
done
fs="`"${grub_probe}" --device "${device}" --target=fs`"
for module in ${fs} ; do
echo "insmod ${module}"

View file

@ -270,7 +270,6 @@ main (int argc, char *argv[])
free (bufhex);
free (salthex);
free (salt);
fclose (f);
grub_util_error ("couldn't retrieve random data for salt");
}
fclose (f);

View file

@ -297,6 +297,7 @@ check_sas (char *sysfs_path, int *tgt)
free (path);
free (p);
close (fd);
}
static void
@ -419,6 +420,7 @@ int main(int argc, char **argv)
of_path = grub_util_devname_to_ofpath (argv[1]);
printf("%s\n", of_path);
free (of_path);
return 0;
}

View file

@ -80,6 +80,8 @@ grub_util_raid_getmembers (const char *name)
devicelist[j] = NULL;
close (fd);
return devicelist;
}