merge mainline into net
This commit is contained in:
commit
8f72becdef
45 changed files with 2702 additions and 1144 deletions
317
ChangeLog
317
ChangeLog
|
@ -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>
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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:
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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, ®exop);
|
||||
if (noregexop >= regexop) /* no more wildcards */
|
||||
break;
|
||||
|
||||
if (make_regex (noregexop, regexop, ®exp))
|
||||
goto fail;
|
||||
|
|
733
grub-core/disk/ahci.c
Normal file
733
grub-core/disk/ahci.c
Normal 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
|
@ -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;
|
||||
}
|
|
@ -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");
|
||||
|
|
|
@ -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
531
grub-core/disk/pata.c
Normal 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);
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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, §or_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)
|
||||
{
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -24,6 +24,8 @@
|
|||
#include <grub/fs.h>
|
||||
#include <grub/fshelp.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
struct grub_romfs_superblock
|
||||
{
|
||||
char magic[8];
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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, §or, &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, §or, &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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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, §or_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)
|
||||
|
|
|
@ -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: */
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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"; \
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
||||
|
|
|
@ -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++)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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}"
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -80,6 +80,8 @@ grub_util_raid_getmembers (const char *name)
|
|||
|
||||
devicelist[j] = NULL;
|
||||
|
||||
close (fd);
|
||||
|
||||
return devicelist;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue