merge with mainline
This commit is contained in:
commit
baea17662b
31 changed files with 2794 additions and 319 deletions
246
ChangeLog
246
ChangeLog
|
@ -1,3 +1,249 @@
|
||||||
|
2010-06-07 Colin Watson <cjwatson@ubuntu.com>
|
||||||
|
|
||||||
|
* docs/grub.texi (Filesystem): Refer to `search' instead of `find'.
|
||||||
|
(password): New section.
|
||||||
|
(password_pbkdf2): New section.
|
||||||
|
(search): New section.
|
||||||
|
(Security): New section.
|
||||||
|
(Troubleshooting): New section, currently very incomplete.
|
||||||
|
(Invoking grub-mkpasswd-pbkdf2): New section.
|
||||||
|
(Internals): New section, currently very incomplete.
|
||||||
|
|
||||||
|
2010-06-07 Colin Watson <cjwatson@ubuntu.com>
|
||||||
|
|
||||||
|
* util/grub.d/00_header.in: Add some more quoting (of
|
||||||
|
"${prev_saved_entry}" and "${boot_once}") needed to make savedefault
|
||||||
|
work again.
|
||||||
|
Reported by: Mario 'BitKoenig' Holbe (Debian bug #584812).
|
||||||
|
|
||||||
|
2010-06-07 Colin Watson <cjwatson@ubuntu.com>
|
||||||
|
|
||||||
|
* util/grub-mkpasswd-pbkdf2.c (main): Rename top-level `c' variable
|
||||||
|
to `count', fixing variable shadowing that broke the -c option.
|
||||||
|
|
||||||
|
2010-06-05 Colin Watson <cjwatson@ubuntu.com>
|
||||||
|
|
||||||
|
* util/grub.d/00_header.in: Quote values assigned to `saved_entry',
|
||||||
|
in case they contain spaces.
|
||||||
|
|
||||||
|
2010-06-04 Colin Watson <cjwatson@ubuntu.com>
|
||||||
|
|
||||||
|
* util/grub-mkconfig_lib.in (prepare_grub_to_access_device): Prepend
|
||||||
|
"part_" to partmap module names, in line with grub-install.
|
||||||
|
Reported by: Jindřich Makovička (Debian bug #584426).
|
||||||
|
|
||||||
|
2010-06-04 Colin Watson <cjwatson@ubuntu.com>
|
||||||
|
|
||||||
|
* util/grub-mkimage.c: Make target-related error messages slightly
|
||||||
|
more helpful; -O talks about "format". Explicitly point to the use
|
||||||
|
of -O if no target is specified.
|
||||||
|
Reported by: Didier Raboud (Debian bug #584415).
|
||||||
|
|
||||||
|
2010-06-03 Colin Watson <cjwatson@ubuntu.com>
|
||||||
|
|
||||||
|
* INSTALL: Document several build requirements for optional features
|
||||||
|
(libdevmapper, ncurses, libusb, SDL, FreeType, GNU Unifont).
|
||||||
|
|
||||||
|
2010-06-02 Grégoire Sutre <gregoire.sutre@gmail.com>
|
||||||
|
|
||||||
|
* kern/emu/hostdisk.c (convert_system_partition_to_system_disk)
|
||||||
|
[__NetBSD__]: Handle all device names matching /dev/r[a-z]+[0-9][a-z].
|
||||||
|
(find_partition_start) [__NetBSD__]: Correct error messages for NetBSD.
|
||||||
|
|
||||||
|
2010-06-02 Colin Watson <cjwatson@ubuntu.com>
|
||||||
|
|
||||||
|
* docs/grub.texi (Simple configuration): Fix copy-and-paste typo.
|
||||||
|
Thanks to Jordan Uggla for spotting this.
|
||||||
|
|
||||||
|
2010-06-02 Aleš Nesrsta <starous@volny.cz>
|
||||||
|
|
||||||
|
Finally make USB usable.
|
||||||
|
|
||||||
|
* bus/usb/ohci.c (grub_ohci_reg_t): Add missing values.
|
||||||
|
(GRUB_OHCI_RHUB_PORT_POWER_MASK): New macro.
|
||||||
|
(GRUB_OHCI_RHUB_PORT_ALL_POWERED): Likewise.
|
||||||
|
(GRUB_OHCI_REG_FRAME_INTERVAL_FSMPS_MASK): Likewise.
|
||||||
|
(GRUB_OHCI_REG_FRAME_INTERVAL_FSMPS_SHIFT): Likewise.
|
||||||
|
(GRUB_OHCI_REG_FRAME_INTERVAL_FI_SHIFT): Likewise.
|
||||||
|
(GRUB_OHCI_FSMPS): Likewise.
|
||||||
|
(GRUB_OHCI_PERIODIC_START): Likewise.
|
||||||
|
(GRUB_OHCI_FRAME_INTERVAL): Likewise.
|
||||||
|
(GRUB_OHCI_SET_PORT_ENABLE): Likewise.
|
||||||
|
(GRUB_OHCI_CLEAR_PORT_ENABLE): Likewise.
|
||||||
|
(GRUB_OHCI_SET_PORT_RESET): Likewise.
|
||||||
|
(GRUB_OHCI_SET_PORT_RESET_STATUS_CHANGE): Likewise.
|
||||||
|
* bus/usb/ohci.c (grub_ohci_pci_iter): Various important fixups.
|
||||||
|
(grub_ohci_transaction): Likewise.
|
||||||
|
(grub_ohci_transfer): Improve condition detection algorithms.
|
||||||
|
Handle toggle property. Program the transactions correctly.
|
||||||
|
Improve error handling. Various important fixups.
|
||||||
|
(grub_ohci_portstatus): Put register writes in right order.
|
||||||
|
* bus/usb/uhci.c (grub_free_queue): Compute last_trans.
|
||||||
|
(grub_uhci_transfer): Don't show "failed" message on success.
|
||||||
|
* bus/usb/usb.c (grub_usb_set_configuration): Zero-fill whole "toggle"
|
||||||
|
array.
|
||||||
|
(grub_usb_device_initialize): Read first 8 bytes of descriptor to
|
||||||
|
determine its size.
|
||||||
|
* bus/usb/usbtrans.c (grub_usb_control_msg): Use descdev.maxsize0 even
|
||||||
|
before initialization is completed. Use IN direction for empty
|
||||||
|
transfers. Use last_trans and compute toggle.
|
||||||
|
* include/grub/usbtrans.h (grub_usb_transfer): New field last_trans.
|
||||||
|
(GRUB_USB_FEATURE_ENDP_HALT): Correct the value.
|
||||||
|
(GRUB_USB_FEATURE_DEV_REMOTE_WU): Likewise.
|
||||||
|
(GRUB_USB_FEATURE_TEST_MODE): Likewise.
|
||||||
|
* include/grub/usb.h (grub_usb_err_t): New value GRUB_USB_ERR_UNRECOVERABLE.
|
||||||
|
(grub_usb_device): Increase toggle to 256.
|
||||||
|
(grub_usbms_subclass_t): New values GRUB_USBMS_SUBCLASS_RBC,
|
||||||
|
GRUB_USBMS_SUBCLASS_MMC2, GRUB_USBMS_SUBCLASS_UFI and
|
||||||
|
GRUB_USBMS_SUBCLASS_SFF8070.
|
||||||
|
* include/grub/scsicmd.h (grub_scsi_test_unit_ready): New structure.
|
||||||
|
(grub_scsi_inquiry): New member page and alloc_length.
|
||||||
|
(grub_scsi_request_sense): New structure.
|
||||||
|
(grub_scsi_request_sense_data): Likewise.
|
||||||
|
(grub_scsi_read_capacity): New fields logical_block_addr, PMI and
|
||||||
|
control.
|
||||||
|
* disk/scsi.c (grub_scsi_request_sense): New function.
|
||||||
|
(grub_scsi_test_unit_ready): Likewise.
|
||||||
|
(grub_scsi_inquiry): Fill new fields.
|
||||||
|
(grub_scsi_read_capacity): Likewise.
|
||||||
|
(grub_scsi_read10): Add request sense at the end.
|
||||||
|
(grub_scsi_read12): Likewise.
|
||||||
|
(grub_scsi_write10): Likewise.
|
||||||
|
(grub_scsi_write12): Likewise.
|
||||||
|
(grub_scsi_open): Add Test Unit Ready.
|
||||||
|
* disk/usbms.c (grub_usbms_finddevs): Check configcnt.
|
||||||
|
Support additional subclasses. Con't clear halt yet. Activate the
|
||||||
|
proper config. Calculate LUNs correctly.
|
||||||
|
(grub_usbms_transfer): Various important fixups.
|
||||||
|
|
||||||
|
2010-06-02 Vladimir Serbinenko <phcoder@gmail.com>
|
||||||
|
|
||||||
|
* bus/pci.c (grub_pci_iterate) [GRUB_MACHINE_MIPS_YEELOONG]: Skip ghosts.
|
||||||
|
* bus/usb/ohci.c (grub_ohci_portstatus): Handle R/WC correctly.
|
||||||
|
(grub_ohci_fini_hw): New function.
|
||||||
|
(grub_ohci_restore_hw): Likewise.
|
||||||
|
(GRUB_MOD_INIT(ohci)): Register preboot hook.
|
||||||
|
(GRUB_MOD_FINI(ohci)): Shutdown OHCI.
|
||||||
|
* term/usb_keyboard.c: Remove include of grub/machine/console.h.
|
||||||
|
|
||||||
|
2010-06-02 Vladimir Serbinenko <phcoder@gmail.com>
|
||||||
|
|
||||||
|
Dedicated DMA allocations.
|
||||||
|
|
||||||
|
* bus/pci.c (grub_memalign_dma32): New function
|
||||||
|
(grub_dma_free): Likewise.
|
||||||
|
(grub_dma_get_virt): Likewise.
|
||||||
|
(grub_dma_get_phys): Likewise.
|
||||||
|
* bus/usb/ohci.c (grub_ohci): New members hcca_addr and hcca_chunk.
|
||||||
|
(grub_ohci_pci_iter): Use dma32_alloc.
|
||||||
|
(grub_ohci_transfer): Likewise.
|
||||||
|
* bus/usb/usbtrans.c (grub_usb_control_msg): Likewise.
|
||||||
|
(grub_usb_bulk_readwrite): Likewise.
|
||||||
|
* include/grub/pci.h: Add declarations.
|
||||||
|
|
||||||
|
2010-06-02 Vladimir Serbinenko <phcoder@gmail.com>
|
||||||
|
|
||||||
|
CS5536 support.
|
||||||
|
|
||||||
|
* bus/cs5536.c: New file.
|
||||||
|
* bus/usb/ohci.c (grub_ohci_pci_iter): Check for CS5536.
|
||||||
|
* conf/i386.rmk (pkglib_MODULES): Add cs5536.mod.
|
||||||
|
(cs5536_mod_SOURCES): New variable.
|
||||||
|
(cs5536_mod_CFLAGS): Likewise.
|
||||||
|
(cs5536_mod_LDFLAGS): Likewise.
|
||||||
|
* conf/mips-yeeloong.rmk (kernel_img_HEADERS): Add cs5536.h and
|
||||||
|
machine/pci.h.
|
||||||
|
(kernel_img_SOURCES): Add bus/cs5536.c.
|
||||||
|
(pkglib_MODULES): Add usb.mod, usbtest.mod, ohci.mod, usbms.mod and
|
||||||
|
usb_keyboard.mod.
|
||||||
|
(usb_mod_SOURCES): New variable.
|
||||||
|
(usb_mod_CFLAGS): New variable.
|
||||||
|
(usb_mod_LDFLAGS): New variable.
|
||||||
|
(usbtest_mod_SOURCES): New variable.
|
||||||
|
(usbtest_mod_CFLAGS): New variable.
|
||||||
|
(usbtest_mod_LDFLAGS): New variable.
|
||||||
|
(ohci_mod_SOURCES): New variable.
|
||||||
|
(ohci_mod_CFLAGS): New variable.
|
||||||
|
(ohci_mod_LDFLAGS): New variable.
|
||||||
|
(usbms_mod_SOURCES): New variable.
|
||||||
|
(usbms_mod_CFLAGS): New variable.
|
||||||
|
(usbms_mod_LDFLAGS): New variable.
|
||||||
|
(usb_keyboard_mod_SOURCES): New variable.
|
||||||
|
(usb_keyboard_mod_CFLAGS): New variable.
|
||||||
|
(usb_keyboard_mod_LDFLAGS): New variable.
|
||||||
|
* include/grub/smbus.h: New file.
|
||||||
|
* include/grub/cs5536.h: New file.
|
||||||
|
|
||||||
|
2010-06-02 Colin Watson <cjwatson@ubuntu.com>
|
||||||
|
|
||||||
|
* util/grub.d/00_header.in: Add safety check to make sure that
|
||||||
|
${locale_dir} exists before trying to probe it.
|
||||||
|
|
||||||
|
2010-06-02 Colin Watson <cjwatson@ubuntu.com>
|
||||||
|
|
||||||
|
* docs/grub.texi (SCO UnixWare): Remove, at Vladimir's request and
|
||||||
|
per the GNU Coding Standards; this is now too obscure to be worth
|
||||||
|
documenting.
|
||||||
|
(QNX): Likewise.
|
||||||
|
(chainloader): Remove cross-reference to `SCO UnixWare'.
|
||||||
|
|
||||||
|
2010-06-02 Colin Watson <cjwatson@ubuntu.com>
|
||||||
|
|
||||||
|
* docs/grub.texi (Chain-loading): New section.
|
||||||
|
(DOS/Windows): New section, borrowed from GRUB Legacy with details
|
||||||
|
adjusted for GRUB 2.
|
||||||
|
(SCO UnixWare): Likewise.
|
||||||
|
(QNX): Likewise.
|
||||||
|
(chainloader): Add reference to `Block list syntax'.
|
||||||
|
(drivemap): New section.
|
||||||
|
(parttool): New section.
|
||||||
|
|
||||||
|
2010-06-02 Colin Watson <cjwatson@ubuntu.com>
|
||||||
|
|
||||||
|
* docs/grub.texi (GNU GRUB manual): Remove reference to `Invoking
|
||||||
|
the grub shell'.
|
||||||
|
(Installation): Add reference to `Making a GRUB bootable CD-ROM'.
|
||||||
|
(Installing GRUB using grub-install): Remove reference to the grub
|
||||||
|
shell; mention `grub-mkimage' and `grub-setup' instead.
|
||||||
|
(Invoking grub-install): Likewise.
|
||||||
|
(Interface): Add reference to `Menu entry editor'.
|
||||||
|
(serial): Remove `--device' option.
|
||||||
|
|
||||||
|
2010-06-02 Colin Watson <cjwatson@ubuntu.com>
|
||||||
|
|
||||||
|
* docs/grub.texi (Configuration): New section, documenting
|
||||||
|
configuration file generation using grub-mkconfig. I've left a slot
|
||||||
|
for documenting the full shell scripting format but have not yet
|
||||||
|
started on writing that up.
|
||||||
|
(Invoking grub-mkconfig): New section.
|
||||||
|
|
||||||
|
2010-06-02 Colin Watson <cjwatson@ubuntu.com>
|
||||||
|
|
||||||
|
* docs/grub.texi (direntry): Remove grub-terminfo reference.
|
||||||
|
(GNU GRUB manual): Likewise.
|
||||||
|
(General commands): Update description of `terminfo' for GRUB 2.
|
||||||
|
|
||||||
|
2010-06-02 Colin Watson <cjwatson@ubuntu.com>
|
||||||
|
|
||||||
|
* commands/gptsync.c (grub_cmd_gptsync): Fix typos.
|
||||||
|
(GRUB_MOD_INIT): Fix capitalisation.
|
||||||
|
* docs/grub.texi (Command-line and menu entry commands): Document
|
||||||
|
gettext and gptsync commands.
|
||||||
|
|
||||||
|
2010-06-02 Colin Watson <cjwatson@ubuntu.com>
|
||||||
|
|
||||||
|
* conf/any-emu.rmk (kernel_img_SOURCES) [!x86]: Include
|
||||||
|
kern/$(target_cpu)/cache.S even if TARGET_NO_MODULES = yes.
|
||||||
|
|
||||||
|
2010-06-01 Colin Watson <cjwatson@ubuntu.com>
|
||||||
|
|
||||||
|
Add btrfs probing support, currently only in the single-device case.
|
||||||
|
|
||||||
|
* kern/emu/getroot.c (find_root_device_from_mountinfo): New
|
||||||
|
function.
|
||||||
|
(grub_guess_root_device): Call find_root_device_from_mountinfo
|
||||||
|
before looking in /dev.
|
||||||
|
|
||||||
2010-05-31 Vladimir Serbinenko <phcoder@gmail.com>
|
2010-05-31 Vladimir Serbinenko <phcoder@gmail.com>
|
||||||
|
|
||||||
* disk/i386/pc/biosdisk.c (grub_biosdisk_open): Use
|
* disk/i386/pc/biosdisk.c (grub_biosdisk_open): Use
|
||||||
|
|
15
INSTALL
15
INSTALL
|
@ -19,6 +19,21 @@ configuring the GRUB.
|
||||||
* Flex 2.5.35 or later
|
* Flex 2.5.35 or later
|
||||||
* Other standard GNU/Unix tools
|
* Other standard GNU/Unix tools
|
||||||
|
|
||||||
|
On GNU/Linux, you also need:
|
||||||
|
|
||||||
|
* libdevmapper (recommended)
|
||||||
|
|
||||||
|
To build grub-emu, you need:
|
||||||
|
|
||||||
|
* ncurses
|
||||||
|
* libusb (recommended)
|
||||||
|
* SDL (recommended)
|
||||||
|
|
||||||
|
To build GRUB's graphical terminal (gfxterm), you need:
|
||||||
|
|
||||||
|
* FreeType 2 or later
|
||||||
|
* GNU Unifont
|
||||||
|
|
||||||
If you use a development snapshot or want to hack on GRUB you may
|
If you use a development snapshot or want to hack on GRUB you may
|
||||||
need the following.
|
need the following.
|
||||||
|
|
||||||
|
|
771
docs/grub.texi
771
docs/grub.texi
|
@ -20,7 +20,7 @@
|
||||||
This manual is for GNU GRUB (version @value{VERSION},
|
This manual is for GNU GRUB (version @value{VERSION},
|
||||||
@value{UPDATED}).
|
@value{UPDATED}).
|
||||||
|
|
||||||
Copyright @copyright{} 1999,2000,2001,2002,2004,2006,2008,2009 Free Software Foundation, Inc.
|
Copyright @copyright{} 1999,2000,2001,2002,2004,2006,2008,2009,2010 Free Software Foundation, Inc.
|
||||||
|
|
||||||
@quotation
|
@quotation
|
||||||
Permission is granted to copy, distribute and/or modify this document
|
Permission is granted to copy, distribute and/or modify this document
|
||||||
|
@ -34,9 +34,8 @@ Invariant Sections.
|
||||||
@direntry
|
@direntry
|
||||||
* GRUB: (grub). The GRand Unified Bootloader
|
* GRUB: (grub). The GRand Unified Bootloader
|
||||||
* grub-install: (grub)Invoking grub-install. Install GRUB on your drive
|
* grub-install: (grub)Invoking grub-install. Install GRUB on your drive
|
||||||
* grub-terminfo: (grub)Invoking grub-terminfo. Generate a terminfo
|
* grub-mkconfig: (grub)Invoking grub-mkconfig. Generate GRUB configuration
|
||||||
command from a
|
* grub-mkpasswd-pbkdf2: (grub)Invoking grub-mkpasswd-pbkdf2.
|
||||||
terminfo name
|
|
||||||
@end direntry
|
@end direntry
|
||||||
|
|
||||||
@setchapternewpage odd
|
@setchapternewpage odd
|
||||||
|
@ -86,10 +85,12 @@ This edition documents version @value{VERSION}.
|
||||||
* Filesystem:: Filesystem syntax and semantics
|
* Filesystem:: Filesystem syntax and semantics
|
||||||
* Interface:: The menu and the command-line
|
* Interface:: The menu and the command-line
|
||||||
* Commands:: The list of available builtin commands
|
* Commands:: The list of available builtin commands
|
||||||
|
* Security:: Authentication and authorisation
|
||||||
* Troubleshooting:: Error messages produced by GRUB
|
* Troubleshooting:: Error messages produced by GRUB
|
||||||
* Invoking the grub shell:: How to use the grub shell
|
|
||||||
* Invoking grub-install:: How to use the GRUB installer
|
* Invoking grub-install:: How to use the GRUB installer
|
||||||
* Invoking grub-terminfo:: How to generate a terminfo command
|
* Invoking grub-mkconfig:: Generate a GRUB configuration file
|
||||||
|
* Invoking grub-mkpasswd-pbkdf2::
|
||||||
|
Generate GRUB password hashes
|
||||||
* Obtaining and Building GRUB:: How to obtain and build GRUB
|
* Obtaining and Building GRUB:: How to obtain and build GRUB
|
||||||
* Reporting bugs:: Where you should send a bug report
|
* Reporting bugs:: Where you should send a bug report
|
||||||
* Future:: Some future plans on GRUB
|
* Future:: Some future plans on GRUB
|
||||||
|
@ -453,6 +454,7 @@ the @dfn{boot directory}.
|
||||||
|
|
||||||
@menu
|
@menu
|
||||||
* Installing GRUB using grub-install::
|
* Installing GRUB using grub-install::
|
||||||
|
* Making a GRUB bootable CD-ROM::
|
||||||
@end menu
|
@end menu
|
||||||
|
|
||||||
|
|
||||||
|
@ -532,11 +534,11 @@ quite careful. If the output is wrong, it is unlikely that your
|
||||||
computer will be able to boot with no problem.
|
computer will be able to boot with no problem.
|
||||||
|
|
||||||
Note that @command{grub-install} is actually just a shell script and the
|
Note that @command{grub-install} is actually just a shell script and the
|
||||||
real task is done by the grub shell @command{grub} (@pxref{Invoking the
|
real task is done by @command{grub-mkimage} and @command{grub-setup}.
|
||||||
grub shell}). Therefore, you may run @command{grub} directly to install
|
Therefore, you may run those commands directly to install GRUB, without
|
||||||
GRUB, without using @command{grub-install}. Don't do that, however,
|
using @command{grub-install}. Don't do that, however, unless you are very
|
||||||
unless you are very familiar with the internals of GRUB. Installing a
|
familiar with the internals of GRUB. Installing a boot loader on a running
|
||||||
boot loader on a running OS may be extremely dangerous.
|
OS may be extremely dangerous.
|
||||||
|
|
||||||
|
|
||||||
@node Making a GRUB bootable CD-ROM
|
@node Making a GRUB bootable CD-ROM
|
||||||
|
@ -649,6 +651,35 @@ use more complicated instructions. @xref{DOS/Windows}, for more
|
||||||
information.
|
information.
|
||||||
|
|
||||||
|
|
||||||
|
@node Chain-loading
|
||||||
|
@subsection Chain-loading an OS
|
||||||
|
|
||||||
|
Operating systems that do not support Multiboot and do not have specific
|
||||||
|
support in GRUB (specific support is available for Linux, FreeBSD, NetBSD
|
||||||
|
and OpenBSD) must be chain-loaded, which involves loading another boot
|
||||||
|
loader and jumping to it in real mode.
|
||||||
|
|
||||||
|
The @command{chainloader} command (@pxref{chainloader}) is used to set this
|
||||||
|
up. It is normally also necessary to load some GRUB modules and set the
|
||||||
|
appropriate root device. Putting this together, we get something like this,
|
||||||
|
for a Windows system on the first partition of the first hard disk:
|
||||||
|
|
||||||
|
@verbatim
|
||||||
|
menuentry "Windows" {
|
||||||
|
insmod chain
|
||||||
|
insmod ntfs
|
||||||
|
set root=(hd0,1)
|
||||||
|
chainloader +1
|
||||||
|
}
|
||||||
|
@end verbatim
|
||||||
|
@c FIXME: document UUIDs.
|
||||||
|
|
||||||
|
On systems with multiple hard disks, an additional workaround may be
|
||||||
|
required. @xref{DOS/Windows}.
|
||||||
|
|
||||||
|
Chain-loading is only supported on PC BIOS and EFI platforms.
|
||||||
|
|
||||||
|
|
||||||
@node OS-specific notes
|
@node OS-specific notes
|
||||||
@section Some caveats on OS-specific issues
|
@section Some caveats on OS-specific issues
|
||||||
|
|
||||||
|
@ -657,6 +688,7 @@ Here, we describe some caveats on several operating systems.
|
||||||
@menu
|
@menu
|
||||||
* GNU/Hurd::
|
* GNU/Hurd::
|
||||||
* GNU/Linux::
|
* GNU/Linux::
|
||||||
|
* DOS/Windows::
|
||||||
@end menu
|
@end menu
|
||||||
|
|
||||||
|
|
||||||
|
@ -698,6 +730,246 @@ the size, run the command @command{uppermem} @emph{before} loading the
|
||||||
kernel. @xref{uppermem}, for more information.
|
kernel. @xref{uppermem}, for more information.
|
||||||
|
|
||||||
|
|
||||||
|
@node DOS/Windows
|
||||||
|
@subsection DOS/Windows
|
||||||
|
|
||||||
|
GRUB cannot boot DOS or Windows directly, so you must chain-load them
|
||||||
|
(@pxref{Chain-loading}). However, their boot loaders have some critical
|
||||||
|
deficiencies, so it may not work to just chain-load them. To overcome
|
||||||
|
the problems, GRUB provides you with two helper functions.
|
||||||
|
|
||||||
|
If you have installed DOS (or Windows) on a non-first hard disk, you
|
||||||
|
have to use the disk swapping technique, because that OS cannot boot
|
||||||
|
from any disks but the first one. The workaround used in GRUB is the
|
||||||
|
command @command{drivemap} (@pxref{drivemap}), like this:
|
||||||
|
|
||||||
|
@example
|
||||||
|
drivemap -s (hd0) (hd1)
|
||||||
|
@end example
|
||||||
|
|
||||||
|
This performs a @dfn{virtual} swap between your first and second hard
|
||||||
|
drive.
|
||||||
|
|
||||||
|
@strong{Caution:} This is effective only if DOS (or Windows) uses BIOS
|
||||||
|
to access the swapped disks. If that OS uses a special driver for the
|
||||||
|
disks, this probably won't work.
|
||||||
|
|
||||||
|
Another problem arises if you installed more than one set of DOS/Windows
|
||||||
|
onto one disk, because they could be confused if there are more than one
|
||||||
|
primary partitions for DOS/Windows. Certainly you should avoid doing
|
||||||
|
this, but there is a solution if you do want to do so. Use the partition
|
||||||
|
hiding/unhiding technique.
|
||||||
|
|
||||||
|
If GRUB @dfn{hides} a DOS (or Windows) partition (@pxref{parttool}), DOS (or
|
||||||
|
Windows) will ignore the partition. If GRUB @dfn{unhides} a DOS (or Windows)
|
||||||
|
partition, DOS (or Windows) will detect the partition. Thus, if you have
|
||||||
|
installed DOS (or Windows) on the first and the second partition of the
|
||||||
|
first hard disk, and you want to boot the copy on the first partition, do
|
||||||
|
the following:
|
||||||
|
|
||||||
|
@example
|
||||||
|
@group
|
||||||
|
parttool (hd0,1) hidden-
|
||||||
|
parttool (hd0,2) hidden+
|
||||||
|
set root=(hd0,1)
|
||||||
|
chainloader +1
|
||||||
|
parttool @verb{'${root}'} boot+
|
||||||
|
boot
|
||||||
|
@end group
|
||||||
|
@end example
|
||||||
|
|
||||||
|
|
||||||
|
@node Configuration
|
||||||
|
@chapter Writing your own configuration file
|
||||||
|
|
||||||
|
GRUB is configured using @file{grub.cfg}, usually located under
|
||||||
|
@file{/boot/grub}. This file is quite flexible, but most users will not
|
||||||
|
need to write the whole thing by hand.
|
||||||
|
|
||||||
|
@menu
|
||||||
|
* Simple configuration:: Recommended for most users
|
||||||
|
* Shell-like scripting:: For power users and developers
|
||||||
|
@end menu
|
||||||
|
|
||||||
|
|
||||||
|
@node Simple configuration
|
||||||
|
@section Simple configuration handling
|
||||||
|
|
||||||
|
The program @command{grub-mkconfig} (@pxref{Invoking grub-mkconfig})
|
||||||
|
generates @file{grub.cfg} files suitable for most cases. It is suitable for
|
||||||
|
use when upgrading a distribution, and will discover available kernels and
|
||||||
|
attempt to generate menu entries for them.
|
||||||
|
|
||||||
|
The file @file{/etc/default/grub} controls the operation of
|
||||||
|
@command{grub-mkconfig}. It is sourced by a shell script, and so must be
|
||||||
|
valid POSIX shell input; normally, it will just be a sequence of
|
||||||
|
@samp{KEY=value} lines, but if the value contains spaces or other special
|
||||||
|
characters then it must be quoted. For example:
|
||||||
|
|
||||||
|
@example
|
||||||
|
GRUB_TERMINAL_INPUT="console serial"
|
||||||
|
@end example
|
||||||
|
|
||||||
|
Valid keys in @file{/etc/default/grub} are as follows:
|
||||||
|
|
||||||
|
@table @samp
|
||||||
|
@item GRUB_DEFAULT
|
||||||
|
The default menu entry. This may be a number, in which case it identifies
|
||||||
|
the Nth entry in the generated menu counted from zero, or the full name of a
|
||||||
|
menu entry, or the special string @samp{saved}. Using the full name may be
|
||||||
|
useful if you want to set a menu entry as the default even though there may
|
||||||
|
be a variable number of entries before it.
|
||||||
|
|
||||||
|
If you set this to @samp{saved}, then the default menu entry will be that
|
||||||
|
saved by @samp{GRUB_SAVEDEFAULT}, @command{grub-set-default}, or
|
||||||
|
@command{grub-reboot}.
|
||||||
|
|
||||||
|
The default is @samp{0}.
|
||||||
|
|
||||||
|
@item GRUB_SAVEDEFAULT
|
||||||
|
If this option is set to @samp{true}, then, when an entry is selected, save
|
||||||
|
it as a new default entry for use by future runs of GRUB. This is only
|
||||||
|
useful if @samp{GRUB_DEFAULT=saved}; it is a separate option because
|
||||||
|
@samp{GRUB_DEFAULT=saved} is useful without this option, in conjunction with
|
||||||
|
@command{grub-set-default} or @command{grub-reboot}. Unset by default.
|
||||||
|
|
||||||
|
@item GRUB_TIMEOUT
|
||||||
|
Boot the default entry this many seconds after the menu is displayed, unless
|
||||||
|
a key is pressed. The default is @samp{5}. Set to @samp{0} to boot
|
||||||
|
immediately without displaying the menu, or to @samp{-1} to wait
|
||||||
|
indefinitely.
|
||||||
|
|
||||||
|
@item GRUB_HIDDEN_TIMEOUT
|
||||||
|
Wait this many seconds for a key to be pressed before displaying the menu.
|
||||||
|
If no key is pressed during that time, boot immediately. Unset by default.
|
||||||
|
|
||||||
|
@item GRUB_HIDDEN_TIMEOUT_QUIET
|
||||||
|
In conjunction with @samp{GRUB_HIDDEN_TIMEOUT}, set this to @samp{true} to
|
||||||
|
suppress the verbose countdown while waiting for a key to be pressed before
|
||||||
|
displaying the menu. Unset by default.
|
||||||
|
|
||||||
|
@item GRUB_DEFAULT_BUTTON
|
||||||
|
@itemx GRUB_TIMEOUT_BUTTON
|
||||||
|
@itemx GRUB_HIDDEN_TIMEOUT_BUTTON
|
||||||
|
@itemx GRUB_BUTTON_CMOS_ADDRESS
|
||||||
|
Variants of the corresponding variables without the @samp{_BUTTON} suffix,
|
||||||
|
used to support vendor-specific power buttons. @xref{Vendor power-on keys}.
|
||||||
|
|
||||||
|
@item GRUB_DISTRIBUTOR
|
||||||
|
Set by distributors of GRUB to their identifying name. This is used to
|
||||||
|
generate more informative menu entry titles.
|
||||||
|
|
||||||
|
@item GRUB_TERMINAL_INPUT
|
||||||
|
Select the terminal input device. You may select multiple devices here,
|
||||||
|
separated by spaces.
|
||||||
|
|
||||||
|
Valid terminal input names depend on the platform, but may include
|
||||||
|
@samp{console} (PC BIOS and EFI consoles), @samp{serial} (serial terminal),
|
||||||
|
@samp{ofconsole} (Open Firmware console), @samp{at_keyboard} (PC AT
|
||||||
|
keyboard, mainly useful with Coreboot), or @samp{usb_keyboard} (USB keyboard
|
||||||
|
using the HID Boot Protocol, for cases where the firmware does not handle
|
||||||
|
this).
|
||||||
|
|
||||||
|
The default is to use the platform's native terminal input.
|
||||||
|
|
||||||
|
@item GRUB_TERMINAL_OUTPUT
|
||||||
|
Select the terminal output device. You may select multiple devices here,
|
||||||
|
separated by spaces.
|
||||||
|
|
||||||
|
Valid terminal output names depend on the platform, but may include
|
||||||
|
@samp{console} (PC BIOS and EFI consoles), @samp{serial} (serial terminal),
|
||||||
|
@samp{gfxterm} (graphics-mode output), @samp{ofconsole} (Open Firmware
|
||||||
|
console), or @samp{vga_text} (VGA text output, mainly useful with Coreboot).
|
||||||
|
|
||||||
|
The default is to use the platform's native terminal output.
|
||||||
|
|
||||||
|
@item GRUB_TERMINAL
|
||||||
|
If this option is set, it overrides both @samp{GRUB_TERMINAL_INPUT} and
|
||||||
|
@samp{GRUB_TERMINAL_OUTPUT} to the same value.
|
||||||
|
|
||||||
|
@item GRUB_SERIAL_COMMAND
|
||||||
|
A command to configure the serial port when using the serial console.
|
||||||
|
@xref{serial}. Defaults to @samp{serial}.
|
||||||
|
|
||||||
|
@item GRUB_CMDLINE_LINUX
|
||||||
|
Command-line arguments to add to menu entries for the Linux kernel.
|
||||||
|
|
||||||
|
@item GRUB_CMDLINE_LINUX_DEFAULT
|
||||||
|
Unless @samp{GRUB_DISABLE_LINUX_RECOVERY} is set, two menu entries will be
|
||||||
|
generated for each Linux kernel: one default entry and one entry for
|
||||||
|
recovery mode. This option lists command-line arguments to add only to the
|
||||||
|
default menu entry, after those listed in @samp{GRUB_CMDLINE_LINUX}.
|
||||||
|
|
||||||
|
@item GRUB_CMDLINE_NETBSD
|
||||||
|
@itemx GRUB_CMDLINE_NETBSD_DEFAULT
|
||||||
|
As @samp{GRUB_CMDLINE_LINUX} and @samp{GRUB_CMDLINE_LINUX_DEFAULT}, but for
|
||||||
|
NetBSD.
|
||||||
|
|
||||||
|
@item GRUB_DISABLE_LINUX_UUID
|
||||||
|
Normally, @command{grub-mkconfig} will generate menu entries that use
|
||||||
|
universally-unique identifiers (UUIDs) to identify the root filesystem to
|
||||||
|
the Linux kernel, using a @samp{root=UUID=...} kernel parameter. This is
|
||||||
|
usually more reliable, but in some cases it may not be appropriate. To
|
||||||
|
disable the use of UUIDs, set this option to @samp{true}.
|
||||||
|
|
||||||
|
@item GRUB_DISABLE_LINUX_RECOVERY
|
||||||
|
Disable the generation of recovery mode menu entries for Linux.
|
||||||
|
|
||||||
|
@item GRUB_DISABLE_NETBSD_RECOVERY
|
||||||
|
Disable the generation of recovery mode menu entries for NetBSD.
|
||||||
|
|
||||||
|
@item GRUB_GFXMODE
|
||||||
|
Set the resolution used on the @samp{gfxterm} graphical terminal. Note that
|
||||||
|
you can only use modes which your graphics card supports via VESA BIOS
|
||||||
|
Extensions (VBE), so for example native LCD panel resolutions may not be
|
||||||
|
available. The default is @samp{640x480}.
|
||||||
|
|
||||||
|
@item GRUB_BACKGROUND
|
||||||
|
Set a background image for use with the @samp{gfxterm} graphical terminal.
|
||||||
|
The value of this option must be a file readable by GRUB at boot time, and
|
||||||
|
it must end with @file{.png}, @file{.tga}, @file{.jpg}, or @file{.jpeg}.
|
||||||
|
The image will be scaled if necessary to fit the screen.
|
||||||
|
|
||||||
|
@item GRUB_THEME
|
||||||
|
Set a theme for use with the @samp{gfxterm} graphical terminal.
|
||||||
|
@xref{Themes}.
|
||||||
|
|
||||||
|
@item GRUB_GFXPAYLOAD_LINUX
|
||||||
|
Set to @samp{text} to force the Linux kernel to boot in normal text mode,
|
||||||
|
@samp{keep} to preserve the graphics mode set using @samp{GRUB_GFXMODE},
|
||||||
|
@samp{@var{width}x@var{height}}[@samp{x@var{depth}}] to set a particular
|
||||||
|
graphics mode, or a sequence of these separated by commas or semicolons to
|
||||||
|
try several modes in sequence.
|
||||||
|
|
||||||
|
Depending on your kernel, your distribution, your graphics card, and the
|
||||||
|
phase of the moon, note that using this option may cause GNU/Linux to suffer
|
||||||
|
from various display problems, particularly during the early part of the
|
||||||
|
boot sequence. If you have problems, simply unset this option and GRUB will
|
||||||
|
tell Linux to boot in normal text mode.
|
||||||
|
|
||||||
|
@item GRUB_DISABLE_OS_PROBER
|
||||||
|
Normally, @command{grub-mkconfig} will try to use the external
|
||||||
|
@command{os-prober} program, if installed, to discover other operating
|
||||||
|
systems installed on the same system and generate appropriate menu entries
|
||||||
|
for them. Set this option to @samp{true} to disable this.
|
||||||
|
|
||||||
|
@item GRUB_INIT_TUNE
|
||||||
|
Play a tune on the speaker when GRUB starts. This is particularly useful
|
||||||
|
for users unable to see the screen. The value of this option is passed
|
||||||
|
directly to @ref{play}.
|
||||||
|
@end table
|
||||||
|
|
||||||
|
For more detailed customisation of @command{grub-mkconfig}'s output, you may
|
||||||
|
edit the scripts in @file{/etc/grub.d} directly.
|
||||||
|
@file{/etc/grub.d/40_custom} is particularly useful for adding entire custom
|
||||||
|
menu entries; simply type the menu entries you want to add at the end of
|
||||||
|
that file, making sure to leave at least the first two lines intact.
|
||||||
|
|
||||||
|
|
||||||
|
@node Shell-like scripting
|
||||||
|
@section Writing full configuration files directly
|
||||||
|
|
||||||
|
|
||||||
@node Serial terminal
|
@node Serial terminal
|
||||||
@chapter Using GRUB via a serial line
|
@chapter Using GRUB via a serial line
|
||||||
|
|
||||||
|
@ -773,8 +1045,8 @@ GRUB uses a special syntax for specifying disk drives which can be
|
||||||
accessed by BIOS. Because of BIOS limitations, GRUB cannot distinguish
|
accessed by BIOS. Because of BIOS limitations, GRUB cannot distinguish
|
||||||
between IDE, ESDI, SCSI, or others. You must know yourself which BIOS
|
between IDE, ESDI, SCSI, or others. You must know yourself which BIOS
|
||||||
device is equivalent to which OS device. Normally, that will be clear if
|
device is equivalent to which OS device. Normally, that will be clear if
|
||||||
you see the files in a device or use the command @command{find}
|
you see the files in a device or use the command @command{search}
|
||||||
(@pxref{find}).
|
(@pxref{search}).
|
||||||
|
|
||||||
@menu
|
@menu
|
||||||
* Device syntax:: How to specify devices
|
* Device syntax:: How to specify devices
|
||||||
|
@ -884,6 +1156,7 @@ the command-line interface.
|
||||||
@menu
|
@menu
|
||||||
* Command-line interface:: The flexible command-line interface
|
* Command-line interface:: The flexible command-line interface
|
||||||
* Menu interface:: The simple menu interface
|
* Menu interface:: The simple menu interface
|
||||||
|
* Menu entry editor:: Editing a menu entry
|
||||||
@end menu
|
@end menu
|
||||||
|
|
||||||
|
|
||||||
|
@ -1076,14 +1349,14 @@ Commands usable anywhere in the menu and in the command-line.
|
||||||
|
|
||||||
@menu
|
@menu
|
||||||
* serial:: Set up a serial device
|
* serial:: Set up a serial device
|
||||||
* terminfo:: Define escape sequences for a terminal
|
* terminfo:: Define terminal type
|
||||||
@end menu
|
@end menu
|
||||||
|
|
||||||
|
|
||||||
@node serial
|
@node serial
|
||||||
@subsection serial
|
@subsection serial
|
||||||
|
|
||||||
@deffn Command serial [@option{--unit=unit}] [@option{--port=port}] [@option{--speed=speed}] [@option{--word=word}] [@option{--parity=parity}] [@option{--stop=stop}] [@option{--device=dev}]
|
@deffn Command serial [@option{--unit=unit}] [@option{--port=port}] [@option{--speed=speed}] [@option{--word=word}] [@option{--parity=parity}] [@option{--stop=stop}]
|
||||||
Initialize a serial device. @var{unit} is a number in the range 0-3
|
Initialize a serial device. @var{unit} is a number in the range 0-3
|
||||||
specifying which serial port to use; default is 0, which corresponds to
|
specifying which serial port to use; default is 0, which corresponds to
|
||||||
the port often called COM1. @var{port} is the I/O port where the UART
|
the port often called COM1. @var{port} is the I/O port where the UART
|
||||||
|
@ -1092,10 +1365,7 @@ is to be found; if specified it takes precedence over @var{unit}.
|
||||||
@var{stop} are the number of data bits and stop bits. Data bits must
|
@var{stop} are the number of data bits and stop bits. Data bits must
|
||||||
be in the range 5-8 and stop bits must be 1 or 2. Default is 8 data
|
be in the range 5-8 and stop bits must be 1 or 2. Default is 8 data
|
||||||
bits and one stop bit. @var{parity} is one of @samp{no}, @samp{odd},
|
bits and one stop bit. @var{parity} is one of @samp{no}, @samp{odd},
|
||||||
@samp{even} and defaults to @samp{no}. The option @option{--device}
|
@samp{even} and defaults to @samp{no}.
|
||||||
can only be used in the grub shell and is used to specify the
|
|
||||||
tty device to be used in the host operating system (@pxref{Invoking the
|
|
||||||
grub shell}).
|
|
||||||
|
|
||||||
The serial port is not used as a communication channel unless the
|
The serial port is not used as a communication channel unless the
|
||||||
@command{terminal} command is used (@pxref{terminal}).
|
@command{terminal} command is used (@pxref{terminal}).
|
||||||
|
@ -1108,15 +1378,16 @@ support. See also @ref{Serial terminal}.
|
||||||
@node terminfo
|
@node terminfo
|
||||||
@subsection terminfo
|
@subsection terminfo
|
||||||
|
|
||||||
@deffn Command terminfo @option{--name=name} @option{--cursor-address=seq} [@option{--clear-screen=seq}] [@option{--enter-standout-mode=seq}] [@option{--exit-standout-mode=seq}]
|
@deffn Command terminfo [term]
|
||||||
Define the capabilities of your terminal. Use this command to define
|
Define the capabilities of your terminal by giving the name of an entry in
|
||||||
escape sequences, if it is not vt100-compatible. You may use @samp{\e}
|
the terminfo database, which should correspond roughly to a @samp{TERM}
|
||||||
for @key{ESC} and @samp{^X} for a control character.
|
environment variable in Unix.
|
||||||
|
|
||||||
You can use the utility @command{grub-terminfo} to generate
|
At the moment, only @samp{vt100} is supported in GRUB 2. If you need other
|
||||||
appropriate arguments to this command. @xref{Invoking grub-terminfo}.
|
terminal types, please contact us to discuss the best way to include support
|
||||||
|
for these in GRUB.
|
||||||
|
|
||||||
If no option is specified, the current settings are printed.
|
If no option is specified, the current terminal type is printed.
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
|
|
||||||
|
@ -1137,15 +1408,22 @@ you forget a command, you can run the command @command{help}
|
||||||
* configfile:: Load a configuration file
|
* configfile:: Load a configuration file
|
||||||
* crc:: Calculate CRC32 checksums
|
* crc:: Calculate CRC32 checksums
|
||||||
* date:: Display or set current date and time
|
* date:: Display or set current date and time
|
||||||
|
* drivemap:: Map a drive to another
|
||||||
* echo:: Display a line of text
|
* echo:: Display a line of text
|
||||||
* export:: Export an environment variable
|
* export:: Export an environment variable
|
||||||
|
* gettext:: Translate a string
|
||||||
|
* gptsync:: Fill an MBR based on GPT entries
|
||||||
* halt:: Shut down your computer
|
* halt:: Shut down your computer
|
||||||
* help:: Show help messages
|
* help:: Show help messages
|
||||||
* insmod:: Insert a module
|
* insmod:: Insert a module
|
||||||
* keystatus:: Check key modifier status
|
* keystatus:: Check key modifier status
|
||||||
* ls:: List devices or files
|
* ls:: List devices or files
|
||||||
|
* parttool:: Modify partition table entries
|
||||||
|
* password:: Set a clear-text password
|
||||||
|
* password_pbkdf2:: Set a hashed password
|
||||||
* play:: Play a tune
|
* play:: Play a tune
|
||||||
* reboot:: Reboot your computer
|
* reboot:: Reboot your computer
|
||||||
|
* search:: Search devices by file, label, or UUID
|
||||||
* set:: Set an environment variable
|
* set:: Set an environment variable
|
||||||
* unset:: Unset an environment variable
|
* unset:: Unset an environment variable
|
||||||
@end menu
|
@end menu
|
||||||
|
@ -1209,11 +1487,11 @@ grub> @kbd{cat /etc/fstab}
|
||||||
|
|
||||||
@deffn Command chainloader [@option{--force}] file
|
@deffn Command chainloader [@option{--force}] file
|
||||||
Load @var{file} as a chain-loader. Like any other file loaded by the
|
Load @var{file} as a chain-loader. Like any other file loaded by the
|
||||||
filesystem code, it can use the blocklist notation to grab the first
|
filesystem code, it can use the blocklist notation (@pxref{Block list
|
||||||
sector of the current partition with @samp{+1}. If you specify the
|
syntax}) to grab the first sector of the current partition with @samp{+1}.
|
||||||
option @option{--force}, then load @var{file} forcibly, whether it has a
|
If you specify the option @option{--force}, then load @var{file} forcibly,
|
||||||
correct signature or not. This is required when you want to load a
|
whether it has a correct signature or not. This is required when you want to
|
||||||
defective boot loader, such as SCO UnixWare 7.1 (@pxref{SCO UnixWare}).
|
load a defective boot loader, such as SCO UnixWare 7.1.
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
|
|
||||||
|
@ -1268,6 +1546,32 @@ hour, minute, and second unchanged.
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
|
|
||||||
|
@node drivemap
|
||||||
|
@subsection drivemap
|
||||||
|
|
||||||
|
@deffn Command drivemap @option{-l}|@option{-r}|[@option{-s}] @
|
||||||
|
from_drive to_drive
|
||||||
|
Without options, map the drive @var{from_drive} to the drive @var{to_drive}.
|
||||||
|
This is necessary when you chain-load some operating systems, such as DOS,
|
||||||
|
if such an OS resides at a non-first drive. For convenience, any partition
|
||||||
|
suffix on the drive is ignored, so you can safely use @verb{'${root}'} as a
|
||||||
|
drive specification.
|
||||||
|
|
||||||
|
With the @option{-s} option, perform the reverse mapping as well, swapping
|
||||||
|
the two drives.
|
||||||
|
|
||||||
|
With the @option{-l} option, list the current mappings.
|
||||||
|
|
||||||
|
With the @option{-r} option, reset all mappings to the default values.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
@example
|
||||||
|
drivemap -s (hd0) (hd1)
|
||||||
|
@end example
|
||||||
|
@end deffn
|
||||||
|
|
||||||
|
|
||||||
@node echo
|
@node echo
|
||||||
@subsection echo
|
@subsection echo
|
||||||
|
|
||||||
|
@ -1320,6 +1624,38 @@ to subsidiary configuration files loaded using @command{configfile}.
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
|
|
||||||
|
@node gettext
|
||||||
|
@subsection gettext
|
||||||
|
|
||||||
|
@deffn Command gettext string
|
||||||
|
Translate @var{string} into the current language.
|
||||||
|
|
||||||
|
The current language code is stored in the @samp{lang} variable in GRUB's
|
||||||
|
environment. Translation files in MO format are read from
|
||||||
|
@samp{locale_dir}, usually @file{/boot/grub/locale}.
|
||||||
|
@end deffn
|
||||||
|
|
||||||
|
|
||||||
|
@node gptsync
|
||||||
|
@subsection gptsync
|
||||||
|
|
||||||
|
@deffn Command gptsync device [partition[+/-[type]]] @dots{}
|
||||||
|
Disks using the GUID Partition Table (GPT) also have a legacy Master Boot
|
||||||
|
Record (MBR) partition table for compatibility with the BIOS and with older
|
||||||
|
operating systems. The legacy MBR can only represent a limited subset of
|
||||||
|
GPT partition entries.
|
||||||
|
|
||||||
|
This command populates the legacy MBR with the specified @var{partition}
|
||||||
|
entries on @var{device}. Up to three partitions may be used.
|
||||||
|
|
||||||
|
@var{type} is an MBR partition type code; prefix with @samp{0x} if you want
|
||||||
|
to enter this in hexadecimal. The separator between @var{partition} and
|
||||||
|
@var{type} may be @samp{+} to make the partition active, or @samp{-} to make
|
||||||
|
it inactive; only one partition may be active. If both the separator and
|
||||||
|
type are omitted, then the partition will be inactive.
|
||||||
|
@end deffn
|
||||||
|
|
||||||
|
|
||||||
@node halt
|
@node halt
|
||||||
@subsection halt
|
@subsection halt
|
||||||
|
|
||||||
|
@ -1383,6 +1719,60 @@ name syntax}), then list the contents of that directory.
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
|
|
||||||
|
@node parttool
|
||||||
|
@subsection parttool
|
||||||
|
|
||||||
|
@deffn Command parttool partition commands
|
||||||
|
Make various modifications to partition table entries.
|
||||||
|
|
||||||
|
Each @var{command} is either a boolean option, in which case it must be
|
||||||
|
followed with @samp{+} or @samp{-} (with no intervening space) to enable or
|
||||||
|
disable that option, or else it takes a value in the form
|
||||||
|
@samp{@var{command}=@var{value}}.
|
||||||
|
|
||||||
|
Currently, @command{parttool} is only useful on DOS partition tables (also
|
||||||
|
known as Master Boot Record, or MBR). On these partition tables, the
|
||||||
|
following commands are available:
|
||||||
|
|
||||||
|
@table @asis
|
||||||
|
@item @samp{boot} (boolean)
|
||||||
|
When enabled, this makes the selected partition be the active (bootable)
|
||||||
|
partition on its disk, clearing the active flag on all other partitions.
|
||||||
|
This command is limited to @emph{primary} partitions.
|
||||||
|
|
||||||
|
@item @samp{type} (value)
|
||||||
|
Change the type of an existing partition. The value must be a number in the
|
||||||
|
range 0-0xFF (prefix with @samp{0x} to enter it in hexadecimal).
|
||||||
|
|
||||||
|
@item @samp{hidden} (boolean)
|
||||||
|
When enabled, this hides the selected partition by setting the @dfn{hidden}
|
||||||
|
bit in its partition type code; when disabled, unhides the selected
|
||||||
|
partition by clearing this bit. This is useful only when booting DOS or
|
||||||
|
Wwindows and multiple primary FAT partitions exist in one disk. See also
|
||||||
|
@ref{DOS/Windows}.
|
||||||
|
@end table
|
||||||
|
@end deffn
|
||||||
|
|
||||||
|
|
||||||
|
@node password
|
||||||
|
@subsection password
|
||||||
|
|
||||||
|
@deffn Command password user clear-password
|
||||||
|
Define a user named @var{user} with password @var{clear-password}.
|
||||||
|
@xref{Security}.
|
||||||
|
@end deffn
|
||||||
|
|
||||||
|
|
||||||
|
@node password_pbkdf2
|
||||||
|
@subsection password_pbkdf2
|
||||||
|
|
||||||
|
@deffn Command password_pbkdf2 user hashed-password
|
||||||
|
Define a user named @var{user} with password hash @var{hashed-password}.
|
||||||
|
Use @command{grub-mkpasswd-pbkdf2} (@pxref{Invoking grub-mkpasswd-pbkdf2})
|
||||||
|
to generate password hashes. @xref{Security}.
|
||||||
|
@end deffn
|
||||||
|
|
||||||
|
|
||||||
@node play
|
@node play
|
||||||
@subsection play
|
@subsection play
|
||||||
|
|
||||||
|
@ -1410,6 +1800,29 @@ Reboot the computer.
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
|
|
||||||
|
@node search
|
||||||
|
@subsection search
|
||||||
|
|
||||||
|
@deffn Command search @
|
||||||
|
[@option{--file}|@option{--label}|@option{--fs-uuid}] @
|
||||||
|
[@option{--set} var] [@option{--no-floppy}] name
|
||||||
|
Search devices by file (@option{-f}, @option{--file}), filesystem label
|
||||||
|
(@option{-l}, @option{--label}), or filesystem UUID (@option{-u},
|
||||||
|
@option{--fs-uuid}).
|
||||||
|
|
||||||
|
If the @option{--set} option is used, the first device found is set as the
|
||||||
|
value of environment variable @var{var}. The default variable is
|
||||||
|
@samp{root}.
|
||||||
|
|
||||||
|
The @option{--no-floppy} option prevents searching floppy devices, which can
|
||||||
|
be slow.
|
||||||
|
|
||||||
|
The @samp{search.file}, @samp{search.fs_label}, and @samp{search.fs_uuid}
|
||||||
|
commands are aliases for @samp{search --file}, @samp{search --label}, and
|
||||||
|
@samp{search --fs-uuid} respectively.
|
||||||
|
@end deffn
|
||||||
|
|
||||||
|
|
||||||
@node set
|
@node set
|
||||||
@subsection set
|
@subsection set
|
||||||
|
|
||||||
|
@ -1427,12 +1840,141 @@ Unset the environment variable @var{envvar}.
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
|
|
||||||
|
@node Security
|
||||||
|
@chapter Authentication and authorisation
|
||||||
|
|
||||||
|
By default, the boot loader interface is accessible to anyone with physical
|
||||||
|
access to the console: anyone can select and edit any menu entry, and anyone
|
||||||
|
can get direct access to a GRUB shell prompt. For most systems, this is
|
||||||
|
reasonable since anyone with direct physical access has a variety of other
|
||||||
|
ways to gain full access, and requiring authentication at the boot loader
|
||||||
|
level would only serve to make it difficult to recover broken systems.
|
||||||
|
|
||||||
|
However, in some environments, such as kiosks, it may be appropriate to lock
|
||||||
|
down the boot loader to require authentication before performing certain
|
||||||
|
operations.
|
||||||
|
|
||||||
|
The @samp{password} (@pxref{password}) and @samp{password_pbkdf2}
|
||||||
|
(@pxref{password_pbkdf2}) commands can be used to define users, each of
|
||||||
|
which has an associated password. @samp{password} sets the password in
|
||||||
|
plain text, requiring @file{grub.cfg} to be secure; @samp{password_pbkdf2}
|
||||||
|
sets the password hashed using the Password-Based Key Derivation Function
|
||||||
|
(RFC 2898), requiring the use of @command{grub-mkpasswd-pbkdf2}
|
||||||
|
(@pxref{Invoking grub-mkpasswd-pbkdf2}) to generate password hashes.
|
||||||
|
|
||||||
|
In order to enable authentication support, the @samp{superusers} environment
|
||||||
|
variable must be set to a list of usernames, separated by any of spaces,
|
||||||
|
commas, semicolons, pipes, or ampersands. Superusers are permitted to use
|
||||||
|
the GRUB command line, edit menu entries, and execute any menu entry.
|
||||||
|
|
||||||
|
Other users may be given access to specific menu entries by giving a list of
|
||||||
|
usernames (as above) using the @kbd{--users} option to the @samp{menuentry}
|
||||||
|
command (@pxref{menuentry}).
|
||||||
|
|
||||||
|
Putting this together, a typical @file{grub.cfg} fragment might look like
|
||||||
|
this:
|
||||||
|
|
||||||
|
@example
|
||||||
|
@group
|
||||||
|
set superusers="root"
|
||||||
|
password_pbkdf2 root grub.pbkdf2.sha512.10000.biglongstring
|
||||||
|
password user1 insecure
|
||||||
|
|
||||||
|
menuentry "Superusers only" @{
|
||||||
|
set root=(hd0,1)
|
||||||
|
linux /vmlinuz
|
||||||
|
@}
|
||||||
|
|
||||||
|
menuentry "May be run by user1" --users user1 @{
|
||||||
|
set root=(hd0,2)
|
||||||
|
chainloader +1
|
||||||
|
@}
|
||||||
|
@end group
|
||||||
|
@end example
|
||||||
|
|
||||||
|
The @command{grub-mkconfig} program does not yet have built-in support for
|
||||||
|
generating configuration files with authentication. You can use
|
||||||
|
@file{/etc/grub.d/40_custom} to add simple superuser authentication, by
|
||||||
|
adding @kbd{set superusers=} and @kbd{password} or @kbd{password_pbkdf2}
|
||||||
|
commands.
|
||||||
|
|
||||||
|
|
||||||
|
@node Troubleshooting
|
||||||
|
@chapter Error messages produced by GRUB
|
||||||
|
|
||||||
|
@menu
|
||||||
|
* GRUB only offers a rescue shell::
|
||||||
|
@end menu
|
||||||
|
|
||||||
|
|
||||||
|
@node GRUB only offers a rescue shell
|
||||||
|
@section GRUB only offers a rescue shell
|
||||||
|
|
||||||
|
GRUB's normal start-up procedure involves setting the @samp{prefix}
|
||||||
|
environment variable to a value set in the core image by
|
||||||
|
@command{grub-install}, setting the @samp{root} variable to match, loading
|
||||||
|
the @samp{normal} module from the prefix, and running the @samp{normal}
|
||||||
|
command. This command is responsible for reading
|
||||||
|
@file{/boot/grub/grub.cfg}, running the menu, and doing all the useful
|
||||||
|
things GRUB is supposed to do.
|
||||||
|
|
||||||
|
If, instead, you only get a rescue shell, this usually means that GRUB
|
||||||
|
failed to load the @samp{normal} module for some reason. It may be possible
|
||||||
|
to work around this temporarily: for instance, if the reason for the failure
|
||||||
|
is that @samp{prefix} is wrong (perhaps it refers to the wrong device, or
|
||||||
|
perhaps the path to @file{/boot/grub} was not correctly made relative to the
|
||||||
|
device), then you can correct this and enter normal mode manually:
|
||||||
|
|
||||||
|
@example
|
||||||
|
@group
|
||||||
|
# Inspect the current prefix:
|
||||||
|
echo @verb{'${prefix}'}
|
||||||
|
# Set to the correct value, which might be something like this:
|
||||||
|
set prefix=(hd0,1)/grub
|
||||||
|
set root=(hd0,1)
|
||||||
|
insmod normal
|
||||||
|
normal
|
||||||
|
@end group
|
||||||
|
@end example
|
||||||
|
|
||||||
|
However, any problem that leaves you in the rescue shell probably means that
|
||||||
|
GRUB was not correctly installed. It may be more useful to try to reinstall
|
||||||
|
it properly using @kbd{grub-install @var{device}} (@pxref{Invoking
|
||||||
|
grub-install}). When doing this, there are a few things to remember:
|
||||||
|
|
||||||
|
@itemize @bullet{}
|
||||||
|
@item
|
||||||
|
Drive ordering in your operating system may not be the same as the boot
|
||||||
|
drive ordering used by your firmware. Do not assume that your first hard
|
||||||
|
drive (e.g. @samp{/dev/sda}) is the one that your firmware will boot from.
|
||||||
|
|
||||||
|
@item
|
||||||
|
At least on BIOS systems, if you tell @command{grub-install} to install GRUB
|
||||||
|
to a partition but GRUB has already been installed in the master boot
|
||||||
|
record, then the GRUB installation in the partition will be ignored.
|
||||||
|
|
||||||
|
@item
|
||||||
|
If possible, it is generally best to avoid installing GRUB to a partition
|
||||||
|
(unless it is a special partition for the use of GRUB alone, such as the
|
||||||
|
BIOS Boot Partition used on GPT). Doing this means that GRUB may stop being
|
||||||
|
able to read its core image due to a file system moving blocks around, such
|
||||||
|
as while defragmenting, running checks, or even during normal operation.
|
||||||
|
Installing to the whole disk device is normally more robust.
|
||||||
|
|
||||||
|
@item
|
||||||
|
Check that GRUB actually knows how to read from the device and file system
|
||||||
|
containing @file{/boot/grub}. It will not be able to read from encrypted
|
||||||
|
devices, nor from file systems for which support has not yet been added to
|
||||||
|
GRUB.
|
||||||
|
@end itemize
|
||||||
|
|
||||||
|
|
||||||
@node Invoking grub-install
|
@node Invoking grub-install
|
||||||
@chapter Invoking grub-install
|
@chapter Invoking grub-install
|
||||||
|
|
||||||
The program @command{grub-install} installs GRUB on your drive using the
|
The program @command{grub-install} installs GRUB on your drive using
|
||||||
grub shell (@pxref{Invoking the grub shell}). You must specify the
|
@command{grub-mkimage} and (on some platforms) @command{grub-setup}. You
|
||||||
device name on which you want to install GRUB, like this:
|
must specify the device name on which you want to install GRUB, like this:
|
||||||
|
|
||||||
@example
|
@example
|
||||||
grub-install @var{install_device}
|
grub-install @var{install_device}
|
||||||
|
@ -1468,6 +2010,60 @@ into/from your computer.
|
||||||
@end table
|
@end table
|
||||||
|
|
||||||
|
|
||||||
|
@node Invoking grub-mkconfig
|
||||||
|
@chapter Invoking grub-mkconfig
|
||||||
|
|
||||||
|
The program @command{grub-mkconfig} generates a configuration file for GRUB
|
||||||
|
(@pxref{Simple configuration}).
|
||||||
|
|
||||||
|
@example
|
||||||
|
grub-mkconfig -o /boot/grub/grub.cfg
|
||||||
|
@end example
|
||||||
|
|
||||||
|
@command{grub-mkconfig} accepts the following options:
|
||||||
|
|
||||||
|
@table @option
|
||||||
|
@item --help
|
||||||
|
Print a summary of the command-line options and exit.
|
||||||
|
|
||||||
|
@item --version
|
||||||
|
Print the version number of GRUB and exit.
|
||||||
|
|
||||||
|
@item -o @var{file}
|
||||||
|
@itemx --output=@var{file}
|
||||||
|
Send the generated configuration file to @var{file}. The default is to send
|
||||||
|
it to standard output.
|
||||||
|
@end table
|
||||||
|
|
||||||
|
|
||||||
|
@node Invoking grub-mkpasswd-pbkdf2
|
||||||
|
@chapter Invoking grub-mkpasswd-pbkdf2
|
||||||
|
|
||||||
|
The program @command{grub-mkpasswd-pbkdf2} generates password hashes for
|
||||||
|
GRUB (@pxref{Security}).
|
||||||
|
|
||||||
|
@example
|
||||||
|
grub-mkpasswd-pbkdf2
|
||||||
|
@end example
|
||||||
|
|
||||||
|
@command{grub-mkpasswd-pbkdf2} accepts the following options:
|
||||||
|
|
||||||
|
@table @option
|
||||||
|
@item -c @var{number}
|
||||||
|
@itemx --iteration-count=@var{number}
|
||||||
|
Number of iterations of the underlying pseudo-random function. Defaults to
|
||||||
|
10000.
|
||||||
|
|
||||||
|
@item -l @var{number}
|
||||||
|
@itemx --buflen=@var{number}
|
||||||
|
Length of the generated hash. Defaults to 64.
|
||||||
|
|
||||||
|
@item -s @var{number}
|
||||||
|
@itemx --salt=@var{number}
|
||||||
|
Length of the salt. Defaults to 64.
|
||||||
|
@end table
|
||||||
|
|
||||||
|
|
||||||
@node Obtaining and Building GRUB
|
@node Obtaining and Building GRUB
|
||||||
@appendix How to obtain and build GRUB
|
@appendix How to obtain and build GRUB
|
||||||
|
|
||||||
|
@ -1586,6 +2182,113 @@ a look at @uref{http://www.gnu.org/software/grub/grub.html, the
|
||||||
homepage}.
|
homepage}.
|
||||||
|
|
||||||
|
|
||||||
|
@node Internals
|
||||||
|
@appendix Hacking GRUB
|
||||||
|
|
||||||
|
@menu
|
||||||
|
* Getting the source code::
|
||||||
|
* Finding your way around::
|
||||||
|
@end menu
|
||||||
|
|
||||||
|
|
||||||
|
@node Getting the source code
|
||||||
|
@section Getting the source code
|
||||||
|
|
||||||
|
GRUB is maintained using the @uref{http://bazaar-vcs.org/, Bazaar revision
|
||||||
|
control system}. To fetch the primary development branch:
|
||||||
|
|
||||||
|
@example
|
||||||
|
bzr get http://bzr.savannah.gnu.org/r/grub/trunk/grub
|
||||||
|
@end example
|
||||||
|
|
||||||
|
The GRUB developers maintain several other branches with work in progress.
|
||||||
|
Of these, the most interesting is the experimental branch, which is a
|
||||||
|
staging area for new code which we expect to eventually merge into trunk but
|
||||||
|
which is not yet ready:
|
||||||
|
|
||||||
|
@example
|
||||||
|
bzr get http://bzr.savannah.gnu.org/r/grub/branches/experimental
|
||||||
|
@end example
|
||||||
|
|
||||||
|
Once you have used @kbd{bzr get} to fetch an initial copy of a branch, you
|
||||||
|
can use @kbd{bzr pull} to keep it up to date. If you have modified your
|
||||||
|
local version, you may need to resolve conflicts when pulling.
|
||||||
|
|
||||||
|
|
||||||
|
@node Finding your way around
|
||||||
|
@section Finding your way around
|
||||||
|
|
||||||
|
Here is a brief map of the GRUB code base.
|
||||||
|
|
||||||
|
GRUB uses Autoconf, but not (yet) Automake. The top-level build rules are
|
||||||
|
in @file{configure.ac}, @file{Makefile.in}, and @file{conf/*.rmk}. Each
|
||||||
|
@file{conf/*.rmk} file represents a particular target configuration, and is
|
||||||
|
processed into GNU Make rules by @file{genmk.rb} (which you only need to
|
||||||
|
look at if you are extending the build system). If you are adding a new
|
||||||
|
module which follows an existing pattern, such as a new command or a new
|
||||||
|
filesystem implementation, it is usually easiest to grep @file{conf/*.rmk}
|
||||||
|
for an existing example of that pattern to find out where it should be
|
||||||
|
added.
|
||||||
|
|
||||||
|
Low-level boot code, such as the MBR implementation on PC BIOS systems, is
|
||||||
|
in the @file{boot/} directory.
|
||||||
|
|
||||||
|
The GRUB kernel is in @file{kern/}. This contains core facilities such as
|
||||||
|
the device, disk, and file frameworks, environment variable handling, list
|
||||||
|
processing, and so on. The kernel should contain enough to get up to a
|
||||||
|
rescue prompt. Header files for kernel facilities, among others, are in
|
||||||
|
@file{include/}.
|
||||||
|
|
||||||
|
Terminal implementations are in @file{term/}.
|
||||||
|
|
||||||
|
Disk access code is spread across @file{disk/} (for accessing the disk
|
||||||
|
devices themselves), @file{partmap/} (for interpreting partition table
|
||||||
|
data), and @file{fs/} (for accessing filesystems). Note that, with the odd
|
||||||
|
specialised exception, GRUB only contains code to @emph{read} from
|
||||||
|
filesystems and tries to avoid containing any code to @emph{write} to
|
||||||
|
filesystems; this lets us confidently assure users that GRUB cannot be
|
||||||
|
responsible for filesystem corruption.
|
||||||
|
|
||||||
|
PCI and USB bus handling is in @file{bus/}.
|
||||||
|
|
||||||
|
Video handling code is in @file{video/}. The graphical menu system uses
|
||||||
|
this heavily, but is in a separate directory, @file{gfxmenu/}.
|
||||||
|
|
||||||
|
Most commands are implemented by files in @file{commands/}, with the
|
||||||
|
following exceptions:
|
||||||
|
|
||||||
|
@itemize
|
||||||
|
@item
|
||||||
|
A few core commands live in @file{kern/corecmd.c}.
|
||||||
|
|
||||||
|
@item
|
||||||
|
Commands related to normal mode live under @file{normal/}.
|
||||||
|
|
||||||
|
@item
|
||||||
|
Commands that load and boot kernels live under @file{loader/}.
|
||||||
|
|
||||||
|
@item
|
||||||
|
The @samp{loopback} command is really a disk device, and so lives in
|
||||||
|
@file{disk/loopback.c}.
|
||||||
|
|
||||||
|
@item
|
||||||
|
The @samp{gettext} command lives under @file{gettext/}.
|
||||||
|
|
||||||
|
@item
|
||||||
|
The @samp{loadfont} and @samp{lsfonts} commands live under @file{font/}.
|
||||||
|
|
||||||
|
@item
|
||||||
|
The @samp{serial}, @samp{terminfo}, and @samp{background_image} commands
|
||||||
|
live under @file{term/}.
|
||||||
|
|
||||||
|
@item
|
||||||
|
The @samp{efiemu_*} commands live under @file{efiemu/}.
|
||||||
|
@end itemize
|
||||||
|
|
||||||
|
There are a few other special-purpose exceptions; grep for them if they
|
||||||
|
matter to you.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@node Copying This Manual
|
@node Copying This Manual
|
||||||
@appendix Copying This Manual
|
@appendix Copying This Manual
|
||||||
|
|
|
@ -121,6 +121,8 @@ KERNEL_HEADER_FILES += include/grub/bitmap_scale.h
|
||||||
KERNEL_HEADER_FILES += include/grub/bufio.h
|
KERNEL_HEADER_FILES += include/grub/bufio.h
|
||||||
KERNEL_HEADER_FILES += include/grub/pci.h
|
KERNEL_HEADER_FILES += include/grub/pci.h
|
||||||
KERNEL_HEADER_FILES += include/grub/libgcc.h
|
KERNEL_HEADER_FILES += include/grub/libgcc.h
|
||||||
|
KERNEL_HEADER_FILES += include/grub/cs5536.h
|
||||||
|
KERNEL_HEADER_FILES += include/grub/machine/pci.h
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if COND_powerpc_ieee1275
|
if COND_powerpc_ieee1275
|
||||||
|
|
215
grub-core/bus/cs5536.c
Normal file
215
grub-core/bus/cs5536.c
Normal file
|
@ -0,0 +1,215 @@
|
||||||
|
/*
|
||||||
|
* GRUB -- GRand Unified Bootloader
|
||||||
|
* Copyright (C) 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/types.h>
|
||||||
|
#include <grub/cs5536.h>
|
||||||
|
#include <grub/pci.h>
|
||||||
|
#include <grub/time.h>
|
||||||
|
#include <grub/ata.h>
|
||||||
|
|
||||||
|
int
|
||||||
|
grub_cs5536_find (grub_pci_device_t *devp)
|
||||||
|
{
|
||||||
|
int found = 0;
|
||||||
|
auto int NESTED_FUNC_ATTR hook (grub_pci_device_t dev,
|
||||||
|
grub_pci_id_t pciid);
|
||||||
|
|
||||||
|
int NESTED_FUNC_ATTR hook (grub_pci_device_t dev,
|
||||||
|
grub_pci_id_t pciid)
|
||||||
|
{
|
||||||
|
if (pciid == GRUB_CS5536_PCIID)
|
||||||
|
{
|
||||||
|
*devp = dev;
|
||||||
|
found = 1;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
grub_pci_iterate (hook);
|
||||||
|
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
|
grub_uint64_t
|
||||||
|
grub_cs5536_read_msr (grub_pci_device_t dev, grub_uint32_t addr)
|
||||||
|
{
|
||||||
|
grub_uint64_t ret = 0;
|
||||||
|
grub_pci_write (grub_pci_make_address (dev, GRUB_CS5536_MSR_MAILBOX_ADDR),
|
||||||
|
addr);
|
||||||
|
ret = (grub_uint64_t)
|
||||||
|
grub_pci_read (grub_pci_make_address (dev, GRUB_CS5536_MSR_MAILBOX_DATA0));
|
||||||
|
ret |= (((grub_uint64_t)
|
||||||
|
grub_pci_read (grub_pci_make_address (dev,
|
||||||
|
GRUB_CS5536_MSR_MAILBOX_DATA1)))
|
||||||
|
<< 32);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
grub_cs5536_write_msr (grub_pci_device_t dev, grub_uint32_t addr,
|
||||||
|
grub_uint64_t val)
|
||||||
|
{
|
||||||
|
grub_pci_write (grub_pci_make_address (dev, GRUB_CS5536_MSR_MAILBOX_ADDR),
|
||||||
|
addr);
|
||||||
|
grub_pci_write (grub_pci_make_address (dev, GRUB_CS5536_MSR_MAILBOX_DATA0),
|
||||||
|
val & 0xffffffff);
|
||||||
|
grub_pci_write (grub_pci_make_address (dev, GRUB_CS5536_MSR_MAILBOX_DATA1),
|
||||||
|
val >> 32);
|
||||||
|
}
|
||||||
|
|
||||||
|
grub_err_t
|
||||||
|
grub_cs5536_smbus_wait (grub_port_t smbbase)
|
||||||
|
{
|
||||||
|
grub_uint64_t start = grub_get_time_ms ();
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
grub_uint8_t status;
|
||||||
|
status = grub_inb (smbbase + GRUB_CS5536_SMB_REG_STATUS);
|
||||||
|
if (status & GRUB_CS5536_SMB_REG_STATUS_SDAST)
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
if (status & GRUB_CS5536_SMB_REG_STATUS_BER)
|
||||||
|
return grub_error (GRUB_ERR_IO, "SM bus error");
|
||||||
|
if (status & GRUB_CS5536_SMB_REG_STATUS_NACK)
|
||||||
|
return grub_error (GRUB_ERR_IO, "NACK received");
|
||||||
|
if (grub_get_time_ms () > start + 40)
|
||||||
|
return grub_error (GRUB_ERR_IO, "SM stalled");
|
||||||
|
}
|
||||||
|
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
grub_err_t
|
||||||
|
grub_cs5536_read_spd_byte (grub_port_t smbbase, grub_uint8_t dev,
|
||||||
|
grub_uint8_t addr, grub_uint8_t *res)
|
||||||
|
{
|
||||||
|
grub_err_t err;
|
||||||
|
|
||||||
|
/* Send START. */
|
||||||
|
grub_outb (grub_inb (smbbase + GRUB_CS5536_SMB_REG_CTRL1)
|
||||||
|
| GRUB_CS5536_SMB_REG_CTRL1_START,
|
||||||
|
smbbase + GRUB_CS5536_SMB_REG_CTRL1);
|
||||||
|
|
||||||
|
/* Send device address. */
|
||||||
|
err = grub_cs5536_smbus_wait (smbbase);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
grub_outb (dev << 1, smbbase + GRUB_CS5536_SMB_REG_DATA);
|
||||||
|
|
||||||
|
/* Send ACK. */
|
||||||
|
err = grub_cs5536_smbus_wait (smbbase);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
grub_outb (grub_inb (smbbase + GRUB_CS5536_SMB_REG_CTRL1)
|
||||||
|
| GRUB_CS5536_SMB_REG_CTRL1_ACK,
|
||||||
|
smbbase + GRUB_CS5536_SMB_REG_CTRL1);
|
||||||
|
|
||||||
|
/* Send byte address. */
|
||||||
|
grub_outb (addr, smbbase + GRUB_CS5536_SMB_REG_DATA);
|
||||||
|
|
||||||
|
/* Send START. */
|
||||||
|
err = grub_cs5536_smbus_wait (smbbase);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
grub_outb (grub_inb (smbbase + GRUB_CS5536_SMB_REG_CTRL1)
|
||||||
|
| GRUB_CS5536_SMB_REG_CTRL1_START,
|
||||||
|
smbbase + GRUB_CS5536_SMB_REG_CTRL1);
|
||||||
|
|
||||||
|
/* Send device address. */
|
||||||
|
err = grub_cs5536_smbus_wait (smbbase);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
grub_outb ((dev << 1) | 1, smbbase + GRUB_CS5536_SMB_REG_DATA);
|
||||||
|
|
||||||
|
/* Send STOP. */
|
||||||
|
err = grub_cs5536_smbus_wait (smbbase);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
grub_outb (grub_inb (smbbase + GRUB_CS5536_SMB_REG_CTRL1)
|
||||||
|
| GRUB_CS5536_SMB_REG_CTRL1_STOP,
|
||||||
|
smbbase + GRUB_CS5536_SMB_REG_CTRL1);
|
||||||
|
|
||||||
|
err = grub_cs5536_smbus_wait (smbbase);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
*res = grub_inb (smbbase + GRUB_CS5536_SMB_REG_DATA);
|
||||||
|
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
grub_err_t
|
||||||
|
grub_cs5536_init_smbus (grub_pci_device_t dev, grub_uint16_t divisor,
|
||||||
|
grub_port_t *smbbase)
|
||||||
|
{
|
||||||
|
grub_uint64_t smbbar;
|
||||||
|
|
||||||
|
smbbar = grub_cs5536_read_msr (dev, GRUB_CS5536_MSR_SMB_BAR);
|
||||||
|
|
||||||
|
/* FIXME */
|
||||||
|
if (!(smbbar & GRUB_CS5536_LBAR_ENABLE))
|
||||||
|
return grub_error(GRUB_ERR_IO, "SMB controller not enabled\n");
|
||||||
|
*smbbase = (smbbar & GRUB_CS5536_LBAR_ADDR_MASK) + GRUB_MACHINE_PCI_IO_BASE;
|
||||||
|
|
||||||
|
if (divisor < 8)
|
||||||
|
return grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid divisor");
|
||||||
|
|
||||||
|
/* Disable SMB. */
|
||||||
|
grub_outb (0, *smbbase + GRUB_CS5536_SMB_REG_CTRL2);
|
||||||
|
|
||||||
|
/* Disable interrupts. */
|
||||||
|
grub_outb (0, *smbbase + GRUB_CS5536_SMB_REG_CTRL1);
|
||||||
|
|
||||||
|
/* Set as master. */
|
||||||
|
grub_outb (GRUB_CS5536_SMB_REG_ADDR_MASTER,
|
||||||
|
*smbbase + GRUB_CS5536_SMB_REG_ADDR);
|
||||||
|
|
||||||
|
/* Launch. */
|
||||||
|
grub_outb (((divisor >> 7) & 0xff), *smbbase + GRUB_CS5536_SMB_REG_CTRL3);
|
||||||
|
grub_outb (((divisor << 1) & 0xfe) | GRUB_CS5536_SMB_REG_CTRL2_ENABLE,
|
||||||
|
*smbbase + GRUB_CS5536_SMB_REG_CTRL2);
|
||||||
|
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
grub_err_t
|
||||||
|
grub_cs5536_read_spd (grub_port_t smbbase, grub_uint8_t dev,
|
||||||
|
struct grub_smbus_spd *res)
|
||||||
|
{
|
||||||
|
grub_err_t err;
|
||||||
|
grub_size_t size;
|
||||||
|
grub_uint8_t b;
|
||||||
|
grub_size_t ptr;
|
||||||
|
|
||||||
|
err = grub_cs5536_read_spd_byte (smbbase, dev, 0, &b);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
if (b == 0)
|
||||||
|
return grub_error (GRUB_ERR_IO, "no SPD found");
|
||||||
|
size = b;
|
||||||
|
|
||||||
|
((grub_uint8_t *) res)[0] = b;
|
||||||
|
for (ptr = 1; ptr < size; ptr++)
|
||||||
|
{
|
||||||
|
err = grub_cs5536_read_spd_byte (smbbase, dev, ptr,
|
||||||
|
&((grub_uint8_t *) res)[ptr]);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
|
|
@ -19,6 +19,50 @@
|
||||||
|
|
||||||
#include <grub/dl.h>
|
#include <grub/dl.h>
|
||||||
#include <grub/pci.h>
|
#include <grub/pci.h>
|
||||||
|
#include <grub/mm.h>
|
||||||
|
|
||||||
|
/* FIXME: correctly support 64-bit architectures. */
|
||||||
|
/* #if GRUB_TARGET_SIZEOF_VOID_P == 4 */
|
||||||
|
struct grub_pci_dma_chunk *
|
||||||
|
grub_memalign_dma32 (grub_size_t align, grub_size_t size)
|
||||||
|
{
|
||||||
|
return grub_memalign (align, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
grub_dma_free (struct grub_pci_dma_chunk *ch)
|
||||||
|
{
|
||||||
|
grub_free (ch);
|
||||||
|
}
|
||||||
|
/* #endif */
|
||||||
|
|
||||||
|
#ifdef GRUB_MACHINE_MIPS_YEELOONG
|
||||||
|
volatile void *
|
||||||
|
grub_dma_get_virt (struct grub_pci_dma_chunk *ch)
|
||||||
|
{
|
||||||
|
return (void *) ((((grub_uint32_t) ch) & 0x1fffffff) | 0xa0000000);
|
||||||
|
}
|
||||||
|
|
||||||
|
grub_uint32_t
|
||||||
|
grub_dma_get_phys (struct grub_pci_dma_chunk *ch)
|
||||||
|
{
|
||||||
|
return (((grub_uint32_t) ch) & 0x1fffffff) | 0x80000000;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
|
||||||
|
volatile void *
|
||||||
|
grub_dma_get_virt (struct grub_pci_dma_chunk *ch)
|
||||||
|
{
|
||||||
|
return (void *) ch;
|
||||||
|
}
|
||||||
|
|
||||||
|
grub_uint32_t
|
||||||
|
grub_dma_get_phys (struct grub_pci_dma_chunk *ch)
|
||||||
|
{
|
||||||
|
return (grub_uint32_t) (grub_addr_t) ch;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
grub_pci_address_t
|
grub_pci_address_t
|
||||||
grub_pci_make_address (grub_pci_device_t dev, int reg)
|
grub_pci_make_address (grub_pci_device_t dev, int reg)
|
||||||
|
@ -48,6 +92,16 @@ grub_pci_iterate (grub_pci_iteratefunc_t hook)
|
||||||
if (id >> 16 == 0xFFFF)
|
if (id >> 16 == 0xFFFF)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
#ifdef GRUB_MACHINE_MIPS_YEELOONG
|
||||||
|
/* Skip ghosts. */
|
||||||
|
if (id == GRUB_YEELOONG_OHCI_PCIID
|
||||||
|
&& dev.function == GRUB_YEELOONG_OHCI_GHOST_FUNCTION)
|
||||||
|
continue;
|
||||||
|
if (id == GRUB_YEELOONG_EHCI_PCIID
|
||||||
|
&& dev.function == GRUB_YEELOONG_EHCI_GHOST_FUNCTION)
|
||||||
|
continue;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (hook (dev, id))
|
if (hook (dev, id))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
|
@ -24,8 +24,10 @@
|
||||||
#include <grub/misc.h>
|
#include <grub/misc.h>
|
||||||
#include <grub/pci.h>
|
#include <grub/pci.h>
|
||||||
#include <grub/cpu/pci.h>
|
#include <grub/cpu/pci.h>
|
||||||
#include <grub/i386/io.h>
|
#include <grub/cpu/io.h>
|
||||||
#include <grub/time.h>
|
#include <grub/time.h>
|
||||||
|
#include <grub/cs5536.h>
|
||||||
|
#include <grub/loader.h>
|
||||||
|
|
||||||
struct grub_ohci_hcca
|
struct grub_ohci_hcca
|
||||||
{
|
{
|
||||||
|
@ -63,13 +65,15 @@ struct grub_ohci_td
|
||||||
grub_uint32_t buffer_end;
|
grub_uint32_t buffer_end;
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
typedef struct grub_ohci_td *grub_ohci_td_t;
|
typedef volatile struct grub_ohci_td *grub_ohci_td_t;
|
||||||
typedef struct grub_ohci_ed *grub_ohci_ed_t;
|
typedef volatile struct grub_ohci_ed *grub_ohci_ed_t;
|
||||||
|
|
||||||
struct grub_ohci
|
struct grub_ohci
|
||||||
{
|
{
|
||||||
volatile grub_uint32_t *iobase;
|
volatile grub_uint32_t *iobase;
|
||||||
volatile struct grub_ohci_hcca *hcca;
|
volatile struct grub_ohci_hcca *hcca;
|
||||||
|
grub_uint32_t hcca_addr;
|
||||||
|
struct grub_pci_dma_chunk *hcca_chunk;
|
||||||
struct grub_ohci *next;
|
struct grub_ohci *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -91,10 +95,32 @@ typedef enum
|
||||||
GRUB_OHCI_REG_BULKCURR,
|
GRUB_OHCI_REG_BULKCURR,
|
||||||
GRUB_OHCI_REG_DONEHEAD,
|
GRUB_OHCI_REG_DONEHEAD,
|
||||||
GRUB_OHCI_REG_FRAME_INTERVAL,
|
GRUB_OHCI_REG_FRAME_INTERVAL,
|
||||||
|
GRUB_OHCI_REG_PERIODIC_START = 16,
|
||||||
GRUB_OHCI_REG_RHUBA = 18,
|
GRUB_OHCI_REG_RHUBA = 18,
|
||||||
GRUB_OHCI_REG_RHUBPORT = 21
|
GRUB_OHCI_REG_RHUBPORT = 21,
|
||||||
|
GRUB_OHCI_REG_LEGACY_CONTROL = 0x100,
|
||||||
|
GRUB_OHCI_REG_LEGACY_INPUT = 0x104,
|
||||||
|
GRUB_OHCI_REG_LEGACY_OUTPUT = 0x108,
|
||||||
|
GRUB_OHCI_REG_LEGACY_STATUS = 0x10c
|
||||||
} grub_ohci_reg_t;
|
} grub_ohci_reg_t;
|
||||||
|
|
||||||
|
#define GRUB_OHCI_RHUB_PORT_POWER_MASK 0x300
|
||||||
|
#define GRUB_OHCI_RHUB_PORT_ALL_POWERED 0x200
|
||||||
|
|
||||||
|
#define GRUB_OHCI_REG_FRAME_INTERVAL_FSMPS_MASK 0x8fff0000
|
||||||
|
#define GRUB_OHCI_REG_FRAME_INTERVAL_FSMPS_SHIFT 16
|
||||||
|
#define GRUB_OHCI_REG_FRAME_INTERVAL_FI_SHIFT 0
|
||||||
|
|
||||||
|
/* XXX: Is this choice of timings sane? */
|
||||||
|
#define GRUB_OHCI_FSMPS 0x2778
|
||||||
|
#define GRUB_OHCI_PERIODIC_START 0x257f
|
||||||
|
#define GRUB_OHCI_FRAME_INTERVAL 0x2edf
|
||||||
|
|
||||||
|
#define GRUB_OHCI_SET_PORT_ENABLE (1 << 1)
|
||||||
|
#define GRUB_OHCI_CLEAR_PORT_ENABLE (1 << 0)
|
||||||
|
#define GRUB_OHCI_SET_PORT_RESET (1 << 4)
|
||||||
|
#define GRUB_OHCI_SET_PORT_RESET_STATUS_CHANGE (1 << 20)
|
||||||
|
|
||||||
static grub_uint32_t
|
static grub_uint32_t
|
||||||
grub_ohci_readreg32 (struct grub_ohci *o, grub_ohci_reg_t reg)
|
grub_ohci_readreg32 (struct grub_ohci *o, grub_ohci_reg_t reg)
|
||||||
{
|
{
|
||||||
|
@ -114,17 +140,41 @@ grub_ohci_writereg32 (struct grub_ohci *o,
|
||||||
controller. If this is the case, initialize it. */
|
controller. If this is the case, initialize it. */
|
||||||
static int NESTED_FUNC_ATTR
|
static int NESTED_FUNC_ATTR
|
||||||
grub_ohci_pci_iter (grub_pci_device_t dev,
|
grub_ohci_pci_iter (grub_pci_device_t dev,
|
||||||
grub_pci_id_t pciid __attribute__((unused)))
|
grub_pci_id_t pciid)
|
||||||
{
|
{
|
||||||
grub_uint32_t class_code;
|
|
||||||
grub_uint32_t class;
|
|
||||||
grub_uint32_t subclass;
|
|
||||||
grub_uint32_t interf;
|
grub_uint32_t interf;
|
||||||
grub_uint32_t base;
|
grub_uint32_t base;
|
||||||
grub_pci_address_t addr;
|
grub_pci_address_t addr;
|
||||||
struct grub_ohci *o;
|
struct grub_ohci *o;
|
||||||
grub_uint32_t revision;
|
grub_uint32_t revision;
|
||||||
grub_uint32_t frame_interval;
|
int cs5536;
|
||||||
|
|
||||||
|
/* Determine IO base address. */
|
||||||
|
grub_dprintf ("ohci", "pciid = %x\n", pciid);
|
||||||
|
|
||||||
|
if (pciid == GRUB_CS5536_PCIID)
|
||||||
|
{
|
||||||
|
grub_uint64_t basereg;
|
||||||
|
|
||||||
|
cs5536 = 1;
|
||||||
|
basereg = grub_cs5536_read_msr (dev, GRUB_CS5536_MSR_USB_OHCI_BASE);
|
||||||
|
if (!(basereg & GRUB_CS5536_MSR_USB_BASE_MEMORY_ENABLE))
|
||||||
|
{
|
||||||
|
/* Shouldn't happen. */
|
||||||
|
grub_dprintf ("ohci", "No OHCI address is assigned\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
base = (basereg & GRUB_CS5536_MSR_USB_BASE_ADDR_MASK);
|
||||||
|
basereg |= GRUB_CS5536_MSR_USB_BASE_BUS_MASTER;
|
||||||
|
basereg &= ~GRUB_CS5536_MSR_USB_BASE_PME_ENABLED;
|
||||||
|
basereg &= ~GRUB_CS5536_MSR_USB_BASE_PME_STATUS;
|
||||||
|
grub_cs5536_write_msr (dev, GRUB_CS5536_MSR_USB_OHCI_BASE, basereg);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
grub_uint32_t class_code;
|
||||||
|
grub_uint32_t class;
|
||||||
|
grub_uint32_t subclass;
|
||||||
|
|
||||||
addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS);
|
addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS);
|
||||||
class_code = grub_pci_read (addr) >> 8;
|
class_code = grub_pci_read (addr) >> 8;
|
||||||
|
@ -137,7 +187,6 @@ grub_ohci_pci_iter (grub_pci_device_t dev,
|
||||||
if (class != 0x0c || subclass != 0x03 || interf != 0x10)
|
if (class != 0x0c || subclass != 0x03 || interf != 0x10)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Determine IO base address. */
|
|
||||||
addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0);
|
addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0);
|
||||||
base = grub_pci_read (addr);
|
base = grub_pci_read (addr);
|
||||||
|
|
||||||
|
@ -147,18 +196,25 @@ grub_ohci_pci_iter (grub_pci_device_t dev,
|
||||||
return 0;
|
return 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
grub_dprintf ("ohci", "class=0x%02x 0x%02x interface 0x%02x\n",
|
||||||
|
class, subclass, interf);
|
||||||
|
}
|
||||||
|
|
||||||
/* Allocate memory for the controller and register it. */
|
/* Allocate memory for the controller and register it. */
|
||||||
o = grub_malloc (sizeof (*o));
|
o = grub_malloc (sizeof (*o));
|
||||||
if (! o)
|
if (! o)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
o->iobase = (grub_uint32_t *) base;
|
o->iobase = grub_pci_device_map_range (dev, base, 0x800);
|
||||||
|
|
||||||
|
grub_dprintf ("ohci", "base=%p\n", o->iobase);
|
||||||
|
|
||||||
/* Reserve memory for the HCCA. */
|
/* Reserve memory for the HCCA. */
|
||||||
o->hcca = (struct grub_ohci_hcca *) grub_memalign (256, 256);
|
o->hcca_chunk = grub_memalign_dma32 (256, 256);
|
||||||
|
if (! o->hcca_chunk)
|
||||||
grub_dprintf ("ohci", "class=0x%02x 0x%02x interface 0x%02x base=%p\n",
|
return 1;
|
||||||
class, subclass, interf, o->iobase);
|
o->hcca = grub_dma_get_virt (o->hcca_chunk);
|
||||||
|
o->hcca_addr = grub_dma_get_phys (o->hcca_chunk);
|
||||||
|
|
||||||
/* Check if the OHCI revision is actually 1.0 as supported. */
|
/* Check if the OHCI revision is actually 1.0 as supported. */
|
||||||
revision = grub_ohci_readreg32 (o, GRUB_OHCI_REG_REVISION);
|
revision = grub_ohci_readreg32 (o, GRUB_OHCI_REG_REVISION);
|
||||||
|
@ -166,27 +222,116 @@ grub_ohci_pci_iter (grub_pci_device_t dev,
|
||||||
if ((revision & 0xFF) != 0x10)
|
if ((revision & 0xFF) != 0x10)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
/* Backup the frame interval register. */
|
|
||||||
frame_interval = grub_ohci_readreg32 (o, GRUB_OHCI_REG_FRAME_INTERVAL);
|
{
|
||||||
|
grub_uint32_t control;
|
||||||
|
/* Check SMM/BIOS ownership of OHCI (SMM = USB Legacy Support driver for BIOS) */
|
||||||
|
control = grub_ohci_readreg32 (o, GRUB_OHCI_REG_CONTROL);
|
||||||
|
if ((control & 0x100) != 0)
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
grub_dprintf("ohci", "OHCI is owned by SMM\n");
|
||||||
|
/* Do change of ownership */
|
||||||
|
/* Ownership change request */
|
||||||
|
grub_ohci_writereg32 (o, GRUB_OHCI_REG_CMDSTATUS, (1<<3)); /* XXX: Magic. */
|
||||||
|
/* Waiting for SMM deactivation */
|
||||||
|
for (i=0; i < 10; i++)
|
||||||
|
{
|
||||||
|
if ((grub_ohci_readreg32 (o, GRUB_OHCI_REG_CONTROL) & 0x100) == 0)
|
||||||
|
{
|
||||||
|
grub_dprintf("ohci", "Ownership changed normally.\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
grub_millisleep (100);
|
||||||
|
}
|
||||||
|
if (i >= 10)
|
||||||
|
{
|
||||||
|
grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROL,
|
||||||
|
grub_ohci_readreg32 (o, GRUB_OHCI_REG_CONTROL) & ~0x100);
|
||||||
|
grub_dprintf("ohci", "Ownership changing timeout, change forced !\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (((control & 0x100) == 0) &&
|
||||||
|
((control & 0xc0) != 0)) /* Not owned by SMM nor reset */
|
||||||
|
{
|
||||||
|
grub_dprintf("ohci", "OHCI is owned by BIOS\n");
|
||||||
|
/* Do change of ownership - not implemented yet... */
|
||||||
|
/* In fact we probably need to do nothing ...? */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
grub_dprintf("ohci", "OHCI is not owned by SMM nor BIOS\n");
|
||||||
|
/* We can setup OHCI. */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Suspend the OHCI by issuing a reset. */
|
/* Suspend the OHCI by issuing a reset. */
|
||||||
grub_ohci_writereg32 (o, GRUB_OHCI_REG_CMDSTATUS, 1); /* XXX: Magic. */
|
grub_ohci_writereg32 (o, GRUB_OHCI_REG_CMDSTATUS, 1); /* XXX: Magic. */
|
||||||
grub_millisleep (1);
|
grub_millisleep (1);
|
||||||
grub_dprintf ("ohci", "OHCI reset\n");
|
grub_dprintf ("ohci", "OHCI reset\n");
|
||||||
|
|
||||||
/* Restore the frame interval register. */
|
grub_ohci_writereg32 (o, GRUB_OHCI_REG_FRAME_INTERVAL,
|
||||||
grub_ohci_writereg32 (o, GRUB_OHCI_REG_FRAME_INTERVAL, frame_interval);
|
(GRUB_OHCI_FSMPS
|
||||||
|
<< GRUB_OHCI_REG_FRAME_INTERVAL_FSMPS_SHIFT)
|
||||||
|
| (GRUB_OHCI_FRAME_INTERVAL
|
||||||
|
<< GRUB_OHCI_REG_FRAME_INTERVAL_FI_SHIFT));
|
||||||
|
|
||||||
|
grub_ohci_writereg32 (o, GRUB_OHCI_REG_PERIODIC_START,
|
||||||
|
GRUB_OHCI_PERIODIC_START);
|
||||||
|
|
||||||
/* Setup the HCCA. */
|
/* Setup the HCCA. */
|
||||||
grub_ohci_writereg32 (o, GRUB_OHCI_REG_HCCA, (grub_uint32_t) o->hcca);
|
o->hcca->donehead = 0;
|
||||||
|
grub_ohci_writereg32 (o, GRUB_OHCI_REG_HCCA, o->hcca_addr);
|
||||||
grub_dprintf ("ohci", "OHCI HCCA\n");
|
grub_dprintf ("ohci", "OHCI HCCA\n");
|
||||||
|
|
||||||
|
/* Misc. pre-sets. */
|
||||||
|
o->hcca->donehead = 0;
|
||||||
|
grub_ohci_writereg32 (o, GRUB_OHCI_REG_INTSTATUS, 0x7f); /* Clears everything */
|
||||||
|
grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROLHEAD, 0);
|
||||||
|
grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROLCURR, 0);
|
||||||
|
grub_ohci_writereg32 (o, GRUB_OHCI_REG_BULKHEAD, 0);
|
||||||
|
grub_ohci_writereg32 (o, GRUB_OHCI_REG_BULKCURR, 0);
|
||||||
|
|
||||||
|
/* Check OHCI Legacy Support */
|
||||||
|
if ((revision & 0x100) != 0)
|
||||||
|
{
|
||||||
|
grub_dprintf ("ohci", "Legacy Support registers detected\n");
|
||||||
|
grub_dprintf ("ohci", "Current state of legacy control reg.: 0x%04x\n",
|
||||||
|
grub_ohci_readreg32 (o, GRUB_OHCI_REG_LEGACY_CONTROL));
|
||||||
|
grub_ohci_writereg32 (o, GRUB_OHCI_REG_LEGACY_CONTROL,
|
||||||
|
(grub_ohci_readreg32 (o, GRUB_OHCI_REG_LEGACY_CONTROL)) & ~1);
|
||||||
|
grub_dprintf ("ohci", "OHCI Legacy Support disabled.\n");
|
||||||
|
}
|
||||||
|
|
||||||
/* Enable the OHCI. */
|
/* Enable the OHCI. */
|
||||||
grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROL,
|
grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROL,
|
||||||
(2 << 6));
|
(2 << 6));
|
||||||
grub_dprintf ("ohci", "OHCI enable: 0x%02x\n",
|
grub_dprintf ("ohci", "OHCI enable: 0x%02x\n",
|
||||||
(grub_ohci_readreg32 (o, GRUB_OHCI_REG_CONTROL) >> 6) & 3);
|
(grub_ohci_readreg32 (o, GRUB_OHCI_REG_CONTROL) >> 6) & 3);
|
||||||
|
|
||||||
|
/* Power on all ports */
|
||||||
|
grub_ohci_writereg32 (o, GRUB_OHCI_REG_RHUBA,
|
||||||
|
(grub_ohci_readreg32 (o, GRUB_OHCI_REG_RHUBA)
|
||||||
|
& ~GRUB_OHCI_RHUB_PORT_POWER_MASK)
|
||||||
|
| GRUB_OHCI_RHUB_PORT_ALL_POWERED);
|
||||||
|
/* Wait for stable power (100ms) and stable attachment (100ms) */
|
||||||
|
/* I.e. minimum wait time should be probably 200ms. */
|
||||||
|
/* We assume that device is attached when ohci is loaded. */
|
||||||
|
/* Some devices take long time to power-on or indicate attach. */
|
||||||
|
/* Here is some experimental value which should probably mostly work. */
|
||||||
|
/* Cameras with manual USB mode selection and maybe some other similar
|
||||||
|
* devices will not work in some cases - they are repowered during
|
||||||
|
* ownership change and then they are starting slowly and mostly they
|
||||||
|
* are wanting select proper mode again...
|
||||||
|
* The same situation can be on computers where BIOS not set-up OHCI
|
||||||
|
* to be at least powered USB bus (maybe it is Yeelong case...?)
|
||||||
|
* Possible workaround could be for example some prompt
|
||||||
|
* for user with confirmation of proper USB device connection.
|
||||||
|
* Another workaround - "rmmod usbms", "rmmod ohci", proper start
|
||||||
|
* and configuration of USB device and then "insmod ohci"
|
||||||
|
* and "insmod usbms". */
|
||||||
|
grub_millisleep (500);
|
||||||
|
|
||||||
/* Link to ohci now that initialisation is successful. */
|
/* Link to ohci now that initialisation is successful. */
|
||||||
o->next = ohci;
|
o->next = ohci;
|
||||||
ohci = o;
|
ohci = o;
|
||||||
|
@ -195,10 +340,10 @@ grub_ohci_pci_iter (grub_pci_device_t dev,
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
if (o)
|
if (o)
|
||||||
grub_free ((void *) o->hcca);
|
grub_dma_free (o->hcca_chunk);
|
||||||
grub_free (o);
|
grub_free (o);
|
||||||
|
|
||||||
return 1;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -229,7 +374,7 @@ grub_ohci_iterate (int (*hook) (grub_usb_controller_t dev))
|
||||||
static void
|
static void
|
||||||
grub_ohci_transaction (grub_ohci_td_t td,
|
grub_ohci_transaction (grub_ohci_td_t td,
|
||||||
grub_transfer_type_t type, unsigned int toggle,
|
grub_transfer_type_t type, unsigned int toggle,
|
||||||
grub_size_t size, char *data)
|
grub_size_t size, grub_uint32_t data)
|
||||||
{
|
{
|
||||||
grub_uint32_t token;
|
grub_uint32_t token;
|
||||||
grub_uint32_t buffer;
|
grub_uint32_t buffer;
|
||||||
|
@ -254,21 +399,39 @@ grub_ohci_transaction (grub_ohci_td_t td,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0 /* Always generate interrupt */
|
||||||
/* Generate no interrupts. */
|
/* Generate no interrupts. */
|
||||||
token |= 7 << 21;
|
token |= 7 << 21;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Set the token. */
|
/* Set the token. */
|
||||||
token |= toggle << 24;
|
token |= toggle << 24;
|
||||||
token |= 1 << 25;
|
token |= 1 << 25;
|
||||||
|
|
||||||
buffer = (grub_uint32_t) data;
|
/* Set "Not accessed" error code */
|
||||||
|
token |= 15 << 28;
|
||||||
|
|
||||||
|
buffer = data;
|
||||||
buffer_end = buffer + size - 1;
|
buffer_end = buffer + size - 1;
|
||||||
|
|
||||||
td->token = grub_cpu_to_le32 (token);
|
/* Set correct buffer values in TD if zero transfer occurs */
|
||||||
|
if (size)
|
||||||
|
{
|
||||||
|
buffer = (grub_uint32_t) data;
|
||||||
|
buffer_end = buffer + size - 1;
|
||||||
td->buffer = grub_cpu_to_le32 (buffer);
|
td->buffer = grub_cpu_to_le32 (buffer);
|
||||||
td->next_td = 0;
|
|
||||||
td->buffer_end = grub_cpu_to_le32 (buffer_end);
|
td->buffer_end = grub_cpu_to_le32 (buffer_end);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
td->buffer = 0;
|
||||||
|
td->buffer_end = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set the rest of TD */
|
||||||
|
td->token = grub_cpu_to_le32 (token);
|
||||||
|
td->next_td = 0;
|
||||||
|
}
|
||||||
|
|
||||||
static grub_usb_err_t
|
static grub_usb_err_t
|
||||||
grub_ohci_transfer (grub_usb_controller_t dev,
|
grub_ohci_transfer (grub_usb_controller_t dev,
|
||||||
|
@ -276,7 +439,10 @@ grub_ohci_transfer (grub_usb_controller_t dev,
|
||||||
{
|
{
|
||||||
struct grub_ohci *o = (struct grub_ohci *) dev->data;
|
struct grub_ohci *o = (struct grub_ohci *) dev->data;
|
||||||
grub_ohci_ed_t ed;
|
grub_ohci_ed_t ed;
|
||||||
|
grub_uint32_t ed_addr;
|
||||||
|
struct grub_pci_dma_chunk *ed_chunk, *td_list_chunk;
|
||||||
grub_ohci_td_t td_list;
|
grub_ohci_td_t td_list;
|
||||||
|
grub_uint32_t td_list_addr;
|
||||||
grub_uint32_t target;
|
grub_uint32_t target;
|
||||||
grub_uint32_t td_tail;
|
grub_uint32_t td_tail;
|
||||||
grub_uint32_t td_head;
|
grub_uint32_t td_head;
|
||||||
|
@ -284,20 +450,30 @@ grub_ohci_transfer (grub_usb_controller_t dev,
|
||||||
grub_uint32_t control;
|
grub_uint32_t control;
|
||||||
grub_usb_err_t err;
|
grub_usb_err_t err;
|
||||||
int i;
|
int i;
|
||||||
|
grub_uint64_t maxtime;
|
||||||
|
int err_timeout = 0;
|
||||||
|
int err_unrec = 0;
|
||||||
|
grub_uint32_t intstatus;
|
||||||
|
grub_uint32_t tderr_addr = 0;
|
||||||
|
|
||||||
/* Allocate an Endpoint Descriptor. */
|
/* Allocate an Endpoint Descriptor. */
|
||||||
ed = grub_memalign (16, sizeof (*ed));
|
ed_chunk = grub_memalign_dma32 (256, sizeof (*ed));
|
||||||
if (! ed)
|
if (! ed_chunk)
|
||||||
return GRUB_USB_ERR_INTERNAL;
|
return GRUB_USB_ERR_INTERNAL;
|
||||||
|
ed = grub_dma_get_virt (ed_chunk);
|
||||||
|
ed_addr = grub_dma_get_phys (ed_chunk);
|
||||||
|
|
||||||
td_list = grub_memalign (16, sizeof (*td_list) * (transfer->transcnt + 1));
|
td_list_chunk = grub_memalign_dma32 (256, sizeof (*td_list)
|
||||||
if (! td_list)
|
* (transfer->transcnt + 1));
|
||||||
|
if (! td_list_chunk)
|
||||||
{
|
{
|
||||||
grub_free ((void *) ed);
|
grub_dma_free (ed_chunk);
|
||||||
return GRUB_USB_ERR_INTERNAL;
|
return GRUB_USB_ERR_INTERNAL;
|
||||||
}
|
}
|
||||||
|
td_list = grub_dma_get_virt (td_list_chunk);
|
||||||
|
td_list_addr = grub_dma_get_phys (td_list_chunk);
|
||||||
|
|
||||||
grub_dprintf ("ohci", "alloc=%p\n", td_list);
|
grub_dprintf ("ohci", "alloc=%p/0x%x\n", td_list, td_list_addr);
|
||||||
|
|
||||||
/* Setup all Transfer Descriptors. */
|
/* Setup all Transfer Descriptors. */
|
||||||
for (i = 0; i < transfer->transcnt; i++)
|
for (i = 0; i < transfer->transcnt; i++)
|
||||||
|
@ -307,16 +483,31 @@ grub_ohci_transfer (grub_usb_controller_t dev,
|
||||||
grub_ohci_transaction (&td_list[i], tr->pid, tr->toggle,
|
grub_ohci_transaction (&td_list[i], tr->pid, tr->toggle,
|
||||||
tr->size, tr->data);
|
tr->size, tr->data);
|
||||||
|
|
||||||
td_list[i].next_td = grub_cpu_to_le32 (&td_list[i + 1]);
|
td_list[i].next_td = grub_cpu_to_le32 (td_list_addr
|
||||||
|
+ (i + 1) * sizeof (td_list[0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0 /* Better will be enable interrupt on all TDs. */
|
||||||
|
/* The last-1 TD token we should change to enable interrupt when TD finishes.
|
||||||
|
* As OHCI interrupts are disabled, it does only setting of WDH bit in
|
||||||
|
* HcInterruptStatus register - and that is what we want to safely detect
|
||||||
|
* normal end of all transactions. */
|
||||||
|
td_list[transfer->transcnt - 1].token &= ~(7 << 21);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
td_list[transfer->transcnt].token = 0;
|
||||||
|
td_list[transfer->transcnt].buffer = 0;
|
||||||
|
td_list[transfer->transcnt].buffer_end = 0;
|
||||||
|
td_list[transfer->transcnt].next_td =
|
||||||
|
(grub_uint32_t) &td_list[transfer->transcnt];
|
||||||
|
|
||||||
/* Setup the Endpoint Descriptor. */
|
/* Setup the Endpoint Descriptor. */
|
||||||
|
|
||||||
/* Set the device address. */
|
/* Set the device address. */
|
||||||
target = transfer->devaddr;
|
target = transfer->devaddr;
|
||||||
|
|
||||||
/* Set the endpoint. */
|
/* Set the endpoint. It should be masked, we need 4 bits only. */
|
||||||
target |= transfer->endpoint << 7;
|
target |= (transfer->endpoint & 15) << 7;
|
||||||
|
|
||||||
/* Set the device speed. */
|
/* Set the device speed. */
|
||||||
target |= (transfer->dev->speed == GRUB_USB_SPEED_LOW) << 13;
|
target |= (transfer->dev->speed == GRUB_USB_SPEED_LOW) << 13;
|
||||||
|
@ -324,9 +515,9 @@ grub_ohci_transfer (grub_usb_controller_t dev,
|
||||||
/* Set the maximum packet size. */
|
/* Set the maximum packet size. */
|
||||||
target |= transfer->max << 16;
|
target |= transfer->max << 16;
|
||||||
|
|
||||||
td_head = (grub_uint32_t) td_list;
|
td_head = td_list_addr;
|
||||||
|
|
||||||
td_tail = (grub_uint32_t) &td_list[transfer->transcnt];
|
td_tail = td_list_addr + transfer->transcnt * sizeof (*td_list);
|
||||||
|
|
||||||
ed->target = grub_cpu_to_le32 (target);
|
ed->target = grub_cpu_to_le32 (target);
|
||||||
ed->td_head = grub_cpu_to_le32 (td_head);
|
ed->td_head = grub_cpu_to_le32 (td_head);
|
||||||
|
@ -335,6 +526,30 @@ grub_ohci_transfer (grub_usb_controller_t dev,
|
||||||
|
|
||||||
grub_dprintf ("ohci", "program OHCI\n");
|
grub_dprintf ("ohci", "program OHCI\n");
|
||||||
|
|
||||||
|
/* Disable the Control and Bulk lists. */
|
||||||
|
control = grub_ohci_readreg32 (o, GRUB_OHCI_REG_CONTROL);
|
||||||
|
control &= ~(3 << 4);
|
||||||
|
grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROL, control);
|
||||||
|
|
||||||
|
/* Clear BulkListFilled and ControlListFilled. */
|
||||||
|
status = grub_ohci_readreg32 (o, GRUB_OHCI_REG_CMDSTATUS);
|
||||||
|
status &= ~(3 << 1);
|
||||||
|
grub_ohci_writereg32 (o, GRUB_OHCI_REG_CMDSTATUS, status);
|
||||||
|
|
||||||
|
/* Now we should wait for start of next frame. Because we are not using
|
||||||
|
* interrupt, we reset SF bit and wait when it goes to 1. */
|
||||||
|
/* SF bit reset. (SF bit indicates Start Of Frame (SOF) packet) */
|
||||||
|
grub_ohci_writereg32 (o, GRUB_OHCI_REG_INTSTATUS, (1<<2));
|
||||||
|
/* Wait for new SOF */
|
||||||
|
while ((grub_ohci_readreg32 (o, GRUB_OHCI_REG_INTSTATUS) & 0x4) == 0);
|
||||||
|
/* Now it should be safe to change CONTROL and BULK lists. */
|
||||||
|
|
||||||
|
/* This we do for safety's sake - it should be done in previous call
|
||||||
|
* of grub_ohci_transfer and nobody should change it in meantime...
|
||||||
|
* It should be done before start of control or bulk OHCI list. */
|
||||||
|
o->hcca->donehead = 0;
|
||||||
|
grub_ohci_writereg32 (o, GRUB_OHCI_REG_INTSTATUS, (1 << 1)); /* Clears WDH */
|
||||||
|
|
||||||
/* Program the OHCI to actually transfer. */
|
/* Program the OHCI to actually transfer. */
|
||||||
switch (transfer->type)
|
switch (transfer->type)
|
||||||
{
|
{
|
||||||
|
@ -342,24 +557,22 @@ grub_ohci_transfer (grub_usb_controller_t dev,
|
||||||
{
|
{
|
||||||
grub_dprintf ("ohci", "add to bulk list\n");
|
grub_dprintf ("ohci", "add to bulk list\n");
|
||||||
|
|
||||||
status = grub_ohci_readreg32 (o, GRUB_OHCI_REG_CMDSTATUS);
|
/* Set BulkList Head and Current */
|
||||||
control = grub_ohci_readreg32 (o, GRUB_OHCI_REG_CONTROL);
|
grub_ohci_writereg32 (o, GRUB_OHCI_REG_BULKHEAD, ed_addr);
|
||||||
|
grub_ohci_writereg32 (o, GRUB_OHCI_REG_BULKCURR, 0);
|
||||||
|
|
||||||
/* Disable the Control and Bulk lists. */
|
#define GRUB_OHCI_REG_CONTROL_BULK_ENABLE (1 << 5)
|
||||||
control &= ~(3 << 4);
|
#define GRUB_OHCI_REG_CONTROL_CONTROL_ENABLE (1 << 4)
|
||||||
grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROL, control);
|
|
||||||
|
|
||||||
/* Clear BulkListFilled. */
|
|
||||||
status &= ~(1 << 2);
|
|
||||||
grub_ohci_writereg32 (o, GRUB_OHCI_REG_CMDSTATUS, status);
|
|
||||||
|
|
||||||
grub_ohci_writereg32 (o, GRUB_OHCI_REG_BULKHEAD, (grub_uint32_t) ed);
|
|
||||||
|
|
||||||
/* Enable the Bulk list. */
|
/* Enable the Bulk list. */
|
||||||
control |= 1 << 5;
|
control = grub_ohci_readreg32 (o, GRUB_OHCI_REG_CONTROL);
|
||||||
|
control |= GRUB_OHCI_REG_CONTROL_BULK_ENABLE;
|
||||||
|
control &= ~GRUB_OHCI_REG_CONTROL_CONTROL_ENABLE;
|
||||||
|
|
||||||
grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROL, control);
|
grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROL, control);
|
||||||
|
|
||||||
/* Set BulkListFilled. */
|
/* Set BulkListFilled. */
|
||||||
|
status = grub_ohci_readreg32 (o, GRUB_OHCI_REG_CMDSTATUS);
|
||||||
status |= 1 << 2;
|
status |= 1 << 2;
|
||||||
grub_ohci_writereg32 (o, GRUB_OHCI_REG_CMDSTATUS, status);
|
grub_ohci_writereg32 (o, GRUB_OHCI_REG_CMDSTATUS, status);
|
||||||
|
|
||||||
|
@ -369,24 +582,14 @@ grub_ohci_transfer (grub_usb_controller_t dev,
|
||||||
case GRUB_USB_TRANSACTION_TYPE_CONTROL:
|
case GRUB_USB_TRANSACTION_TYPE_CONTROL:
|
||||||
{
|
{
|
||||||
grub_dprintf ("ohci", "add to control list\n");
|
grub_dprintf ("ohci", "add to control list\n");
|
||||||
status = grub_ohci_readreg32 (o, GRUB_OHCI_REG_CMDSTATUS);
|
|
||||||
control = grub_ohci_readreg32 (o, GRUB_OHCI_REG_CONTROL);
|
|
||||||
|
|
||||||
/* Disable the Control and Bulk lists. */
|
/* Set ControlList Head and Current */
|
||||||
control &= ~(3 << 4);
|
grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROLHEAD, ed_addr);
|
||||||
grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROL, control);
|
grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROLCURR, 0);
|
||||||
|
|
||||||
/* Clear ControlListFilled. */
|
|
||||||
status &= ~(1 << 1);
|
|
||||||
grub_ohci_writereg32 (o, GRUB_OHCI_REG_CMDSTATUS, status);
|
|
||||||
|
|
||||||
grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROLHEAD,
|
|
||||||
(grub_uint32_t) ed);
|
|
||||||
grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROLHEAD+1,
|
|
||||||
(grub_uint32_t) ed);
|
|
||||||
|
|
||||||
/* Enable the Control list. */
|
/* Enable the Control list. */
|
||||||
control |= 1 << 4;
|
control |= GRUB_OHCI_REG_CONTROL_CONTROL_ENABLE;
|
||||||
|
control &= ~GRUB_OHCI_REG_CONTROL_BULK_ENABLE;
|
||||||
grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROL, control);
|
grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROL, control);
|
||||||
|
|
||||||
/* Set ControlListFilled. */
|
/* Set ControlListFilled. */
|
||||||
|
@ -397,37 +600,138 @@ grub_ohci_transfer (grub_usb_controller_t dev,
|
||||||
}
|
}
|
||||||
|
|
||||||
grub_dprintf ("ohci", "wait for completion\n");
|
grub_dprintf ("ohci", "wait for completion\n");
|
||||||
grub_dprintf ("ohci", "control=0x%02x status=0x%02x\n",
|
grub_dprintf ("ohci", "begin: control=0x%02x status=0x%02x\n",
|
||||||
grub_ohci_readreg32 (o, GRUB_OHCI_REG_CONTROL),
|
grub_ohci_readreg32 (o, GRUB_OHCI_REG_CONTROL),
|
||||||
grub_ohci_readreg32 (o, GRUB_OHCI_REG_CMDSTATUS));
|
grub_ohci_readreg32 (o, GRUB_OHCI_REG_CMDSTATUS));
|
||||||
|
grub_dprintf ("ohci","intstatus=0x%02x\n",
|
||||||
|
grub_ohci_readreg32 (o, GRUB_OHCI_REG_INTSTATUS));
|
||||||
|
|
||||||
|
/* Safety measure to avoid a hang. */
|
||||||
|
maxtime = grub_get_time_ms () + 1000;
|
||||||
|
|
||||||
/* Wait until the transfer is completed or STALLs. */
|
/* Wait until the transfer is completed or STALLs. */
|
||||||
while ((ed->td_head & ~0xf) != (ed->td_tail & ~0xf))
|
do
|
||||||
{
|
{
|
||||||
grub_cpu_idle ();
|
/* Check transfer status */
|
||||||
|
intstatus = grub_ohci_readreg32 (o, GRUB_OHCI_REG_INTSTATUS);
|
||||||
|
if ((intstatus & 0x2) != 0)
|
||||||
|
{
|
||||||
|
grub_dprintf ("ohci", "Current HccaDoneHead=0x%08x\n",
|
||||||
|
o->hcca->donehead);
|
||||||
|
/* Remember last successful TD */
|
||||||
|
tderr_addr = grub_le_to_cpu32 (o->hcca->donehead) & ~0xf;
|
||||||
|
/* Reset DoneHead */
|
||||||
|
o->hcca->donehead = 0;
|
||||||
|
grub_ohci_writereg32 (o, GRUB_OHCI_REG_INTSTATUS, (1 << 1));
|
||||||
|
/* if TD is last, finish */
|
||||||
|
if (tderr_addr == td_list_addr
|
||||||
|
+ sizeof (td_list[0]) * (transfer->transcnt - 1))
|
||||||
|
break;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
grub_dprintf ("ohci", "head=0x%02x tail=0x%02x\n", ed->td_head, ed->td_tail);
|
if ((intstatus & 0x10) != 0)
|
||||||
|
{ /* Unrecoverable error - only reset can help...! */
|
||||||
/* Detected a STALL. */
|
err_unrec = 1;
|
||||||
if (ed->td_head & 1)
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
grub_dprintf ("ohci", "complete\n");
|
/* Detected a HALT. */
|
||||||
|
if (grub_le_to_cpu32 (ed->td_head) & 1)
|
||||||
|
break;
|
||||||
|
|
||||||
/* if (ed->td_head & 1) */
|
/* Timeout ? */
|
||||||
/* err = GRUB_USB_ERR_STALL; */
|
if (grub_get_time_ms () > maxtime)
|
||||||
/* else if (ed->td */
|
{
|
||||||
|
/* Disable the Control and Bulk lists. */
|
||||||
|
grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROL,
|
||||||
|
grub_ohci_readreg32 (o, GRUB_OHCI_REG_CONTROL) & ~(3 << 4));
|
||||||
|
err_timeout = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((ed->td_head & ~0xf) == (ed->td_tail & ~0xf))
|
||||||
|
break;
|
||||||
|
|
||||||
if (ed->td_head & 1)
|
grub_cpu_idle ();
|
||||||
|
}
|
||||||
|
while (1);
|
||||||
|
|
||||||
|
grub_dprintf ("ohci", "end: control=0x%02x status=0x%02x\n",
|
||||||
|
grub_ohci_readreg32 (o, GRUB_OHCI_REG_CONTROL),
|
||||||
|
grub_ohci_readreg32 (o, GRUB_OHCI_REG_CMDSTATUS));
|
||||||
|
grub_dprintf ("ohci", "intstatus=0x%02x\n",
|
||||||
|
grub_ohci_readreg32 (o, GRUB_OHCI_REG_INTSTATUS));
|
||||||
|
|
||||||
|
if (!tderr_addr)
|
||||||
|
{
|
||||||
|
/* It means that something wrong happened,
|
||||||
|
* it could be:
|
||||||
|
* - timeout and no TD processed
|
||||||
|
* - some or unrecoverable error and no TD processed
|
||||||
|
* - something unexpected... :-( */
|
||||||
|
/* Try look into DONEHEAD reg., but there should be also zero */
|
||||||
|
grub_dprintf("ohci", "HCCA DoneHead is zero, something is bad!\n");
|
||||||
|
tderr_addr = grub_ohci_readreg32 (o, GRUB_OHCI_REG_DONEHEAD) & ~0xf;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Remember last processed transaction (TD) - it is necessary for
|
||||||
|
* proper setting of toggle bit in next transaction. */
|
||||||
|
transfer->last_trans = ((tderr_addr - td_list_addr) / sizeof (*td_list));
|
||||||
|
grub_dprintf("ohci", "tderr_addr=0x%x, td_list_addr=0x%x,\n",
|
||||||
|
tderr_addr, td_list_addr);
|
||||||
|
|
||||||
|
if ((ed->td_head & ~0xf) == (ed->td_tail & ~0xf))
|
||||||
|
transfer->last_trans = transfer->transcnt - 1;
|
||||||
|
|
||||||
|
/* Check correct value in last_trans */
|
||||||
|
/* It could happen if timeout happens and no TD was retired */
|
||||||
|
if (transfer->last_trans >= transfer->transcnt || !tderr_addr)
|
||||||
|
{
|
||||||
|
grub_dprintf("ohci", "tderr==0 or out of TDs range!\n");
|
||||||
|
grub_dprintf("ohci", "last_trans=%d, transcnt=%d\n",
|
||||||
|
transfer->last_trans, transfer->transcnt);
|
||||||
|
|
||||||
|
/* We should set something valid... */
|
||||||
|
transfer->last_trans = -1; /* Probably no TD done */
|
||||||
|
tderr_addr = td_list_addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* In case of timeout do not detect error from TD */
|
||||||
|
if (err_timeout)
|
||||||
|
{
|
||||||
|
err = GRUB_ERR_TIMEOUT;
|
||||||
|
grub_dprintf("ohci", "Timeout, target=%08x, head=%08x\n",
|
||||||
|
grub_le_to_cpu32(ed->target),
|
||||||
|
grub_le_to_cpu32(ed->td_head));
|
||||||
|
grub_dprintf("ohci", "tail=%08x, next=%08x\n",
|
||||||
|
grub_le_to_cpu32(ed->td_tail),
|
||||||
|
grub_le_to_cpu32(ed->next_ed));
|
||||||
|
}
|
||||||
|
/* In case of unrecoverable error do not detect error from TD */
|
||||||
|
else if (err_unrec)
|
||||||
|
{
|
||||||
|
err = GRUB_USB_ERR_UNRECOVERABLE;
|
||||||
|
grub_dprintf("ohci",
|
||||||
|
"Unrecoverable error, target=%08x, head=%08x\n",
|
||||||
|
grub_le_to_cpu32(ed->target),
|
||||||
|
grub_le_to_cpu32(ed->td_head));
|
||||||
|
grub_dprintf("ohci", "tail=%08x, next=%08x\n",
|
||||||
|
grub_le_to_cpu32(ed->td_tail),
|
||||||
|
grub_le_to_cpu32(ed->next_ed));
|
||||||
|
}
|
||||||
|
else if (grub_le_to_cpu32 (ed->td_head) & 1)
|
||||||
{
|
{
|
||||||
grub_uint8_t errcode;
|
grub_uint8_t errcode;
|
||||||
grub_ohci_td_t tderr;
|
grub_ohci_td_t tderr = NULL;
|
||||||
|
|
||||||
tderr = (grub_ohci_td_t) grub_ohci_readreg32 (o,
|
transfer->last_trans--;
|
||||||
GRUB_OHCI_REG_DONEHEAD);
|
|
||||||
errcode = tderr->token >> 28;
|
tderr = (grub_ohci_td_t) ((char *) td_list
|
||||||
|
+ (tderr_addr - td_list_addr));
|
||||||
|
|
||||||
|
errcode = grub_le_to_cpu32 (tderr->token) >> 28;
|
||||||
|
grub_dprintf ("ohci", "OHCI errcode=0x%02x\n", errcode);
|
||||||
|
|
||||||
switch (errcode)
|
switch (errcode)
|
||||||
{
|
{
|
||||||
|
@ -473,11 +777,17 @@ grub_ohci_transfer (grub_usb_controller_t dev,
|
||||||
case 8:
|
case 8:
|
||||||
/* XXX: Data overrun error. */
|
/* XXX: Data overrun error. */
|
||||||
err = GRUB_USB_ERR_DATA;
|
err = GRUB_USB_ERR_DATA;
|
||||||
|
grub_dprintf ("ohci", "Overrun, failed TD address: %p, index: %d\n",
|
||||||
|
tderr, transfer->last_trans);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 9:
|
case 9:
|
||||||
/* XXX: Data underrun error. */
|
/* XXX: Data underrun error. */
|
||||||
err = GRUB_USB_ERR_DATA;
|
err = GRUB_USB_ERR_DATA;
|
||||||
|
grub_dprintf ("ohci", "Underrun, failed TD address: %p, index: %d\n",
|
||||||
|
tderr, transfer->last_trans);
|
||||||
|
grub_dprintf ("ohci", "Underrun, number of not transferred bytes: %d\n",
|
||||||
|
1 + grub_le_to_cpu32 (tderr->buffer_end) - grub_le_to_cpu32 (tderr->buffer));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 10:
|
case 10:
|
||||||
|
@ -515,12 +825,58 @@ grub_ohci_transfer (grub_usb_controller_t dev,
|
||||||
|
|
||||||
/* Clear BulkListFilled and ControlListFilled. */
|
/* Clear BulkListFilled and ControlListFilled. */
|
||||||
status = grub_ohci_readreg32 (o, GRUB_OHCI_REG_CMDSTATUS);
|
status = grub_ohci_readreg32 (o, GRUB_OHCI_REG_CMDSTATUS);
|
||||||
status &= ~((1 << 2) | (1 << 3));
|
status &= ~(3 << 1);
|
||||||
grub_ohci_writereg32 (o, GRUB_OHCI_REG_CMDSTATUS, status);
|
grub_ohci_writereg32 (o, GRUB_OHCI_REG_CMDSTATUS, status);
|
||||||
|
|
||||||
/* XXX */
|
/* Set ED to be skipped - for safety */
|
||||||
grub_free (td_list);
|
ed->target |= grub_cpu_to_le32 (1 << 14);
|
||||||
grub_free (ed);
|
|
||||||
|
/* Now we should wait for start of next frame.
|
||||||
|
* It is necessary because we will invalidate pointer to ED and it
|
||||||
|
* can be on OHCI active till SOF!
|
||||||
|
* Because we are not using interrupt, we reset SF bit and wait when
|
||||||
|
* it goes to 1. */
|
||||||
|
/* SF bit reset. (SF bit indicates Start Of Frame (SOF) packet) */
|
||||||
|
grub_ohci_writereg32 (o, GRUB_OHCI_REG_INTSTATUS, (1<<2));
|
||||||
|
/* Wait for new SOF */
|
||||||
|
while (((grub_ohci_readreg32 (o, GRUB_OHCI_REG_INTSTATUS) & 0x4) == 0)
|
||||||
|
&& !err_unrec);
|
||||||
|
/* Now it should be safe to change CONTROL and BULK lists. */
|
||||||
|
|
||||||
|
/* Important cleaning. */
|
||||||
|
o->hcca->donehead = 0;
|
||||||
|
grub_ohci_writereg32 (o, GRUB_OHCI_REG_INTSTATUS, (1 << 1)); /* Clears WDH */
|
||||||
|
grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROLHEAD, 0);
|
||||||
|
grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROLCURR, 0);
|
||||||
|
grub_ohci_writereg32 (o, GRUB_OHCI_REG_BULKHEAD, 0);
|
||||||
|
grub_ohci_writereg32 (o, GRUB_OHCI_REG_BULKCURR, 0);
|
||||||
|
|
||||||
|
if (err_unrec)
|
||||||
|
{
|
||||||
|
/* Do OHCI reset in case of unrecoverable error - maybe we will need
|
||||||
|
* do more - re-enumerate bus etc. (?) */
|
||||||
|
|
||||||
|
/* Suspend the OHCI by issuing a reset. */
|
||||||
|
grub_ohci_writereg32 (o, GRUB_OHCI_REG_CMDSTATUS, 1); /* XXX: Magic. */
|
||||||
|
grub_millisleep (1);
|
||||||
|
grub_dprintf ("ohci", "Unrecoverable error - OHCI reset\n");
|
||||||
|
|
||||||
|
/* Misc. resets. */
|
||||||
|
o->hcca->donehead = 0;
|
||||||
|
grub_ohci_writereg32 (o, GRUB_OHCI_REG_INTSTATUS, 0x7f); /* Clears everything */
|
||||||
|
grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROLHEAD, 0);
|
||||||
|
grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROLCURR, 0);
|
||||||
|
grub_ohci_writereg32 (o, GRUB_OHCI_REG_BULKHEAD, 0);
|
||||||
|
grub_ohci_writereg32 (o, GRUB_OHCI_REG_BULKCURR, 0);
|
||||||
|
|
||||||
|
/* Enable the OHCI. */
|
||||||
|
grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROL, (2 << 6));
|
||||||
|
}
|
||||||
|
|
||||||
|
grub_dprintf ("ohci", "OHCI finished, freeing, err=0x%02x\n", err);
|
||||||
|
|
||||||
|
grub_dma_free (td_list_chunk);
|
||||||
|
grub_dma_free (ed_chunk);
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -530,27 +886,29 @@ grub_ohci_portstatus (grub_usb_controller_t dev,
|
||||||
unsigned int port, unsigned int enable)
|
unsigned int port, unsigned int enable)
|
||||||
{
|
{
|
||||||
struct grub_ohci *o = (struct grub_ohci *) dev->data;
|
struct grub_ohci *o = (struct grub_ohci *) dev->data;
|
||||||
grub_uint32_t status;
|
|
||||||
|
|
||||||
/* Reset the port. */
|
grub_dprintf ("ohci", "begin of portstatus=0x%02x\n",
|
||||||
status = grub_ohci_readreg32 (o, GRUB_OHCI_REG_RHUBPORT + port);
|
grub_ohci_readreg32 (o, GRUB_OHCI_REG_RHUBPORT + port));
|
||||||
status |= (1 << 4); /* XXX: Magic. */
|
|
||||||
grub_ohci_writereg32 (o, GRUB_OHCI_REG_RHUBPORT + port, status);
|
grub_ohci_writereg32 (o, GRUB_OHCI_REG_RHUBPORT + port,
|
||||||
grub_millisleep (100);
|
GRUB_OHCI_SET_PORT_RESET);
|
||||||
|
grub_millisleep (50); /* For root hub should be nominaly 50ms */
|
||||||
|
|
||||||
/* End the reset signaling. */
|
/* End the reset signaling. */
|
||||||
status = grub_ohci_readreg32 (o, GRUB_OHCI_REG_RHUBPORT + port);
|
grub_ohci_writereg32 (o, GRUB_OHCI_REG_RHUBPORT + port,
|
||||||
status |= (1 << 20); /* XXX: Magic. */
|
GRUB_OHCI_SET_PORT_RESET_STATUS_CHANGE);
|
||||||
grub_ohci_writereg32 (o, GRUB_OHCI_REG_RHUBPORT + port, status);
|
|
||||||
grub_millisleep (10);
|
grub_millisleep (10);
|
||||||
|
|
||||||
/* Enable the port. */
|
if (enable)
|
||||||
status = grub_ohci_readreg32 (o, GRUB_OHCI_REG_RHUBPORT + port);
|
grub_ohci_writereg32 (o, GRUB_OHCI_REG_RHUBPORT + port,
|
||||||
status |= (enable << 1); /* XXX: Magic. */
|
GRUB_OHCI_SET_PORT_ENABLE);
|
||||||
grub_ohci_writereg32 (o, GRUB_OHCI_REG_RHUBPORT + port, status);
|
else
|
||||||
|
grub_ohci_writereg32 (o, GRUB_OHCI_REG_RHUBPORT + port,
|
||||||
|
GRUB_OHCI_CLEAR_PORT_ENABLE);
|
||||||
|
grub_millisleep (10);
|
||||||
|
|
||||||
status = grub_ohci_readreg32 (o, GRUB_OHCI_REG_RHUBPORT + port);
|
grub_dprintf ("ohci", "end of portstatus=0x%02x\n",
|
||||||
grub_dprintf ("ohci", "portstatus=0x%02x\n", status);
|
grub_ohci_readreg32 (o, GRUB_OHCI_REG_RHUBPORT + port));
|
||||||
|
|
||||||
return GRUB_ERR_NONE;
|
return GRUB_ERR_NONE;
|
||||||
}
|
}
|
||||||
|
@ -587,6 +945,42 @@ grub_ohci_hubports (grub_usb_controller_t dev)
|
||||||
return portinfo & 0xFF;
|
return portinfo & 0xFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static grub_err_t
|
||||||
|
grub_ohci_fini_hw (int noreturn __attribute__ ((unused)))
|
||||||
|
{
|
||||||
|
struct grub_ohci *o;
|
||||||
|
|
||||||
|
for (o = ohci; o; o = o->next)
|
||||||
|
{
|
||||||
|
int i, nports = grub_ohci_readreg32 (o, GRUB_OHCI_REG_RHUBA) & 0xff;
|
||||||
|
for (i = 0; i < nports; i++)
|
||||||
|
grub_ohci_writereg32 (o, GRUB_OHCI_REG_RHUBPORT + i,
|
||||||
|
GRUB_OHCI_CLEAR_PORT_ENABLE);
|
||||||
|
|
||||||
|
grub_ohci_writereg32 (o, GRUB_OHCI_REG_HCCA, 0);
|
||||||
|
grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROLHEAD, 0);
|
||||||
|
grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROLCURR, 0);
|
||||||
|
grub_ohci_writereg32 (o, GRUB_OHCI_REG_BULKHEAD, 0);
|
||||||
|
grub_ohci_writereg32 (o, GRUB_OHCI_REG_BULKCURR, 0);
|
||||||
|
grub_ohci_writereg32 (o, GRUB_OHCI_REG_DONEHEAD, 0);
|
||||||
|
grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROL, 0);
|
||||||
|
grub_ohci_writereg32 (o, GRUB_OHCI_REG_CMDSTATUS, 1);
|
||||||
|
}
|
||||||
|
grub_millisleep (10);
|
||||||
|
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static grub_err_t
|
||||||
|
grub_ohci_restore_hw (void)
|
||||||
|
{
|
||||||
|
struct grub_ohci *o;
|
||||||
|
|
||||||
|
for (o = ohci; o; o = o->next)
|
||||||
|
grub_ohci_writereg32 (o, GRUB_OHCI_REG_HCCA, o->hcca_addr);
|
||||||
|
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static struct grub_usb_controller_dev usb_controller =
|
static struct grub_usb_controller_dev usb_controller =
|
||||||
|
@ -603,9 +997,12 @@ GRUB_MOD_INIT(ohci)
|
||||||
{
|
{
|
||||||
grub_ohci_inithw ();
|
grub_ohci_inithw ();
|
||||||
grub_usb_controller_dev_register (&usb_controller);
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
GRUB_MOD_FINI(ohci)
|
GRUB_MOD_FINI(ohci)
|
||||||
{
|
{
|
||||||
|
grub_ohci_fini_hw (0);
|
||||||
grub_usb_controller_dev_unregister (&usb_controller);
|
grub_usb_controller_dev_unregister (&usb_controller);
|
||||||
}
|
}
|
||||||
|
|
|
@ -174,14 +174,15 @@ grub_uhci_pci_iter (grub_pci_device_t dev,
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
u->iobase = base & GRUB_UHCI_IOMASK;
|
u->iobase = base & GRUB_UHCI_IOMASK;
|
||||||
grub_dprintf ("uhci", "class=0x%02x 0x%02x interface 0x%02x base=0x%x\n",
|
|
||||||
class, subclass, interf, u->iobase);
|
|
||||||
|
|
||||||
/* Reserve a page for the frame list. */
|
/* Reserve a page for the frame list. */
|
||||||
u->framelist = grub_memalign (4096, 4096);
|
u->framelist = grub_memalign (4096, 4096);
|
||||||
if (! u->framelist)
|
if (! u->framelist)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
|
grub_dprintf ("uhci", "class=0x%02x 0x%02x interface 0x%02x base=0x%x framelist=%p\n",
|
||||||
|
class, subclass, interf, u->iobase, u->framelist);
|
||||||
|
|
||||||
/* The framelist pointer of UHCI is only 32 bits, make sure this
|
/* The framelist pointer of UHCI is only 32 bits, make sure this
|
||||||
code works on on 64 bits architectures. */
|
code works on on 64 bits architectures. */
|
||||||
#if GRUB_CPU_SIZEOF_VOID_P == 8
|
#if GRUB_CPU_SIZEOF_VOID_P == 8
|
||||||
|
@ -221,6 +222,9 @@ grub_uhci_pci_iter (grub_pci_device_t dev,
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
grub_dprintf ("uhci", "QH=%p, TD=%p\n",
|
||||||
|
u->qh, u->td);
|
||||||
|
|
||||||
/* Link all Transfer Descriptors in a list of available Transfer
|
/* Link all Transfer Descriptors in a list of available Transfer
|
||||||
Descriptors. */
|
Descriptors. */
|
||||||
for (i = 0; i < 256; i++)
|
for (i = 0; i < 256; i++)
|
||||||
|
@ -328,13 +332,20 @@ grub_free_td (struct grub_uhci *u, grub_uhci_td_t td)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
grub_free_queue (struct grub_uhci *u, grub_uhci_td_t td)
|
grub_free_queue (struct grub_uhci *u, grub_uhci_td_t td,
|
||||||
|
grub_usb_transfer_t transfer)
|
||||||
{
|
{
|
||||||
/* Free the TDs in this queue. */
|
int i; /* Index of TD in transfer */
|
||||||
while (td)
|
|
||||||
|
/* Free the TDs in this queue and set last_trans. */
|
||||||
|
for (i=0; td; i++)
|
||||||
{
|
{
|
||||||
grub_uhci_td_t tdprev;
|
grub_uhci_td_t tdprev;
|
||||||
|
|
||||||
|
/* Check state of TD and possibly set last_trans */
|
||||||
|
if (transfer && (td->linkptr & 1))
|
||||||
|
transfer->last_trans = i;
|
||||||
|
|
||||||
/* Unlink the queue. */
|
/* Unlink the queue. */
|
||||||
tdprev = td;
|
tdprev = td;
|
||||||
td = (grub_uhci_td_t) td->linkptr2;
|
td = (grub_uhci_td_t) td->linkptr2;
|
||||||
|
@ -380,7 +391,7 @@ static grub_uhci_td_t
|
||||||
grub_uhci_transaction (struct grub_uhci *u, unsigned int endp,
|
grub_uhci_transaction (struct grub_uhci *u, unsigned int endp,
|
||||||
grub_transfer_type_t type, unsigned int addr,
|
grub_transfer_type_t type, unsigned int addr,
|
||||||
unsigned int toggle, grub_size_t size,
|
unsigned int toggle, grub_size_t size,
|
||||||
char *data)
|
grub_uint32_t data)
|
||||||
{
|
{
|
||||||
grub_uhci_td_t td;
|
grub_uhci_td_t td;
|
||||||
static const unsigned int tf[] = { 0x69, 0xE1, 0x2D };
|
static const unsigned int tf[] = { 0x69, 0xE1, 0x2D };
|
||||||
|
@ -398,7 +409,7 @@ grub_uhci_transaction (struct grub_uhci *u, unsigned int endp,
|
||||||
}
|
}
|
||||||
|
|
||||||
grub_dprintf ("uhci",
|
grub_dprintf ("uhci",
|
||||||
"transaction: endp=%d, type=%d, addr=%d, toggle=%d, size=%d data=%p td=%p\n",
|
"transaction: endp=%d, type=%d, addr=%d, toggle=%d, size=%d data=0x%x td=%p\n",
|
||||||
endp, type, addr, toggle, size, data, td);
|
endp, type, addr, toggle, size, data, td);
|
||||||
|
|
||||||
/* Don't point to any TD, just terminate. */
|
/* Don't point to any TD, just terminate. */
|
||||||
|
@ -418,7 +429,7 @@ grub_uhci_transaction (struct grub_uhci *u, unsigned int endp,
|
||||||
td->token = ((size << 21) | (toggle << 19) | (endp << 15)
|
td->token = ((size << 21) | (toggle << 19) | (endp << 15)
|
||||||
| (addr << 8) | tf[type]);
|
| (addr << 8) | tf[type]);
|
||||||
|
|
||||||
td->buffer = (grub_uint32_t) data;
|
td->buffer = data;
|
||||||
|
|
||||||
return td;
|
return td;
|
||||||
}
|
}
|
||||||
|
@ -441,6 +452,8 @@ grub_uhci_transfer (grub_usb_controller_t dev,
|
||||||
if (! qh)
|
if (! qh)
|
||||||
return grub_errno;
|
return grub_errno;
|
||||||
|
|
||||||
|
grub_dprintf ("uhci", "transfer, iobase:%08x\n", u->iobase);
|
||||||
|
|
||||||
for (i = 0; i < transfer->transcnt; i++)
|
for (i = 0; i < transfer->transcnt; i++)
|
||||||
{
|
{
|
||||||
grub_usb_transaction_t tr = &transfer->transactions[i];
|
grub_usb_transaction_t tr = &transfer->transactions[i];
|
||||||
|
@ -455,7 +468,7 @@ grub_uhci_transfer (grub_usb_controller_t dev,
|
||||||
td_prev->linkptr = 1;
|
td_prev->linkptr = 1;
|
||||||
|
|
||||||
if (td_first)
|
if (td_first)
|
||||||
grub_free_queue (u, td_first);
|
grub_free_queue (u, td_first, NULL);
|
||||||
|
|
||||||
return GRUB_USB_ERR_INTERNAL;
|
return GRUB_USB_ERR_INTERNAL;
|
||||||
}
|
}
|
||||||
|
@ -548,12 +561,13 @@ grub_uhci_transfer (grub_usb_controller_t dev,
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
|
|
||||||
|
if (err != GRUB_USB_ERR_NONE)
|
||||||
grub_dprintf ("uhci", "transaction failed\n");
|
grub_dprintf ("uhci", "transaction failed\n");
|
||||||
|
|
||||||
/* Place the QH back in the free list and deallocate the associated
|
/* Place the QH back in the free list and deallocate the associated
|
||||||
TDs. */
|
TDs. */
|
||||||
qh->elinkptr = 1;
|
qh->elinkptr = 1;
|
||||||
grub_free_queue (u, td_first);
|
grub_free_queue (u, td_first, transfer);
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -583,6 +597,8 @@ grub_uhci_portstatus (grub_usb_controller_t dev,
|
||||||
unsigned int status;
|
unsigned int status;
|
||||||
grub_uint64_t endtime;
|
grub_uint64_t endtime;
|
||||||
|
|
||||||
|
grub_dprintf ("uhci", "portstatus, iobase:%08x\n", u->iobase);
|
||||||
|
|
||||||
grub_dprintf ("uhci", "enable=%d port=%d\n", enable, port);
|
grub_dprintf ("uhci", "enable=%d port=%d\n", enable, port);
|
||||||
|
|
||||||
if (port == 0)
|
if (port == 0)
|
||||||
|
@ -600,7 +616,7 @@ grub_uhci_portstatus (grub_usb_controller_t dev,
|
||||||
grub_uhci_writereg16 (u, reg, enable << 9);
|
grub_uhci_writereg16 (u, reg, enable << 9);
|
||||||
|
|
||||||
/* Wait for the reset to complete. XXX: How long exactly? */
|
/* Wait for the reset to complete. XXX: How long exactly? */
|
||||||
grub_millisleep (10);
|
grub_millisleep (50); /* For root hub should be nominaly 50ms */
|
||||||
status = grub_uhci_readreg16 (u, reg);
|
status = grub_uhci_readreg16 (u, reg);
|
||||||
grub_uhci_writereg16 (u, reg, status & ~(1 << 9));
|
grub_uhci_writereg16 (u, reg, status & ~(1 << 9));
|
||||||
grub_dprintf ("uhci", "reset completed\n");
|
grub_dprintf ("uhci", "reset completed\n");
|
||||||
|
@ -631,6 +647,8 @@ grub_uhci_detect_dev (grub_usb_controller_t dev, int port)
|
||||||
int reg;
|
int reg;
|
||||||
unsigned int status;
|
unsigned int status;
|
||||||
|
|
||||||
|
grub_dprintf ("uhci", "detect_dev, iobase:%08x\n", u->iobase);
|
||||||
|
|
||||||
if (port == 0)
|
if (port == 0)
|
||||||
reg = GRUB_UHCI_REG_PORTSC1;
|
reg = GRUB_UHCI_REG_PORTSC1;
|
||||||
else if (port == 1)
|
else if (port == 1)
|
||||||
|
|
|
@ -105,10 +105,7 @@ grub_usb_clear_halt (grub_usb_device_t dev, int endpoint)
|
||||||
grub_usb_err_t
|
grub_usb_err_t
|
||||||
grub_usb_set_configuration (grub_usb_device_t dev, int configuration)
|
grub_usb_set_configuration (grub_usb_device_t dev, int configuration)
|
||||||
{
|
{
|
||||||
int i;
|
grub_memset (dev->toggle, 0, sizeof (dev->toggle));
|
||||||
|
|
||||||
for (i = 0; i < 16; i++)
|
|
||||||
dev->toggle[i] = 0;
|
|
||||||
|
|
||||||
return grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_OUT
|
return grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_OUT
|
||||||
| GRUB_USB_REQTYPE_STANDARD
|
| GRUB_USB_REQTYPE_STANDARD
|
||||||
|
@ -163,6 +160,16 @@ grub_usb_device_initialize (grub_usb_device_t dev)
|
||||||
grub_usb_err_t err;
|
grub_usb_err_t err;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
/* First we have to read first 8 bytes only and determine
|
||||||
|
* max. size of packet */
|
||||||
|
dev->descdev.maxsize0 = 0; /* invalidating, for safety only, can be removed if it is sure it is zero here */
|
||||||
|
err = grub_usb_get_descriptor (dev, GRUB_USB_DESCRIPTOR_DEVICE,
|
||||||
|
0, 8, (char *) &dev->descdev);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
/* Now we have valid value in dev->descdev.maxsize0,
|
||||||
|
* so we can read whole device descriptor */
|
||||||
err = grub_usb_get_descriptor (dev, GRUB_USB_DESCRIPTOR_DEVICE,
|
err = grub_usb_get_descriptor (dev, GRUB_USB_DESCRIPTOR_DEVICE,
|
||||||
0, sizeof (struct grub_usb_desc_device),
|
0, sizeof (struct grub_usb_desc_device),
|
||||||
(char *) &dev->descdev);
|
(char *) &dev->descdev);
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <grub/dl.h>
|
#include <grub/dl.h>
|
||||||
|
#include <grub/pci.h>
|
||||||
#include <grub/mm.h>
|
#include <grub/mm.h>
|
||||||
#include <grub/misc.h>
|
#include <grub/misc.h>
|
||||||
#include <grub/usb.h>
|
#include <grub/usb.h>
|
||||||
|
@ -29,30 +30,59 @@ grub_usb_control_msg (grub_usb_device_t dev,
|
||||||
grub_uint8_t request,
|
grub_uint8_t request,
|
||||||
grub_uint16_t value,
|
grub_uint16_t value,
|
||||||
grub_uint16_t index,
|
grub_uint16_t index,
|
||||||
grub_size_t size, char *data)
|
grub_size_t size0, char *data_in)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
grub_usb_transfer_t transfer;
|
grub_usb_transfer_t transfer;
|
||||||
int datablocks;
|
int datablocks;
|
||||||
struct grub_usb_packet_setup setupdata;
|
volatile struct grub_usb_packet_setup *setupdata;
|
||||||
|
grub_uint32_t setupdata_addr;
|
||||||
grub_usb_err_t err;
|
grub_usb_err_t err;
|
||||||
unsigned int max;
|
unsigned int max;
|
||||||
|
struct grub_pci_dma_chunk *data_chunk, *setupdata_chunk;
|
||||||
|
volatile char *data;
|
||||||
|
grub_uint32_t data_addr;
|
||||||
|
grub_size_t size = size0;
|
||||||
|
|
||||||
|
/* FIXME: avoid allocation any kind of buffer in a first place. */
|
||||||
|
data_chunk = grub_memalign_dma32 (128, size ? : 16);
|
||||||
|
if (!data_chunk)
|
||||||
|
return GRUB_USB_ERR_INTERNAL;
|
||||||
|
data = grub_dma_get_virt (data_chunk);
|
||||||
|
data_addr = grub_dma_get_phys (data_chunk);
|
||||||
|
grub_memcpy ((char *) data, data_in, size);
|
||||||
|
|
||||||
grub_dprintf ("usb",
|
grub_dprintf ("usb",
|
||||||
"control: reqtype=0x%02x req=0x%02x val=0x%02x idx=0x%02x size=%d\n",
|
"control: reqtype=0x%02x req=0x%02x val=0x%02x idx=0x%02x size=%d\n",
|
||||||
reqtype, request, value, index, size);
|
reqtype, request, value, index, size);
|
||||||
|
|
||||||
/* Create a transfer. */
|
/* Create a transfer. */
|
||||||
transfer = grub_malloc (sizeof (struct grub_usb_transfer));
|
transfer = grub_malloc (sizeof (*transfer));
|
||||||
if (! transfer)
|
if (! transfer)
|
||||||
|
{
|
||||||
|
grub_dma_free (data_chunk);
|
||||||
return grub_errno;
|
return grub_errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
setupdata_chunk = grub_memalign_dma32 (32, sizeof (*setupdata));
|
||||||
|
if (! setupdata_chunk)
|
||||||
|
{
|
||||||
|
grub_free (transfer);
|
||||||
|
grub_dma_free (data_chunk);
|
||||||
|
return grub_errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
setupdata = grub_dma_get_virt (setupdata_chunk);
|
||||||
|
setupdata_addr = grub_dma_get_phys (setupdata_chunk);
|
||||||
|
|
||||||
/* Determine the maximum packet size. */
|
/* Determine the maximum packet size. */
|
||||||
if (dev->initialized)
|
if (dev->descdev.maxsize0)
|
||||||
max = dev->descdev.maxsize0;
|
max = dev->descdev.maxsize0;
|
||||||
else
|
else
|
||||||
max = 64;
|
max = 64;
|
||||||
|
|
||||||
|
grub_dprintf ("usb", "transfer = %p, dev = %p\n", transfer, dev);
|
||||||
|
|
||||||
datablocks = (size + max - 1) / max;
|
datablocks = (size + max - 1) / max;
|
||||||
|
|
||||||
/* XXX: Discriminate between different types of control
|
/* XXX: Discriminate between different types of control
|
||||||
|
@ -71,18 +101,20 @@ grub_usb_control_msg (grub_usb_device_t dev,
|
||||||
if (! transfer->transactions)
|
if (! transfer->transactions)
|
||||||
{
|
{
|
||||||
grub_free (transfer);
|
grub_free (transfer);
|
||||||
|
grub_dma_free (setupdata_chunk);
|
||||||
|
grub_dma_free (data_chunk);
|
||||||
return grub_errno;
|
return grub_errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Build a Setup packet. XXX: Endianness. */
|
/* Build a Setup packet. XXX: Endianness. */
|
||||||
setupdata.reqtype = reqtype;
|
setupdata->reqtype = reqtype;
|
||||||
setupdata.request = request;
|
setupdata->request = request;
|
||||||
setupdata.value = value;
|
setupdata->value = value;
|
||||||
setupdata.index = index;
|
setupdata->index = index;
|
||||||
setupdata.length = size;
|
setupdata->length = size;
|
||||||
transfer->transactions[0].size = sizeof (setupdata);
|
transfer->transactions[0].size = sizeof (*setupdata);
|
||||||
transfer->transactions[0].pid = GRUB_USB_TRANSFER_TYPE_SETUP;
|
transfer->transactions[0].pid = GRUB_USB_TRANSFER_TYPE_SETUP;
|
||||||
transfer->transactions[0].data = (char *) &setupdata;
|
transfer->transactions[0].data = setupdata_addr;
|
||||||
transfer->transactions[0].toggle = 0;
|
transfer->transactions[0].toggle = 0;
|
||||||
|
|
||||||
/* Now the data... XXX: Is this the right way to transfer control
|
/* Now the data... XXX: Is this the right way to transfer control
|
||||||
|
@ -99,14 +131,14 @@ grub_usb_control_msg (grub_usb_device_t dev,
|
||||||
tr->pid = GRUB_USB_TRANSFER_TYPE_IN;
|
tr->pid = GRUB_USB_TRANSFER_TYPE_IN;
|
||||||
else
|
else
|
||||||
tr->pid = GRUB_USB_TRANSFER_TYPE_OUT;
|
tr->pid = GRUB_USB_TRANSFER_TYPE_OUT;
|
||||||
tr->data = &data[i * max];
|
tr->data = data_addr + i * max;
|
||||||
size -= max;
|
size -= max;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* End with an empty OUT transaction. */
|
/* End with an empty OUT transaction. */
|
||||||
transfer->transactions[datablocks + 1].size = 0;
|
transfer->transactions[datablocks + 1].size = 0;
|
||||||
transfer->transactions[datablocks + 1].data = NULL;
|
transfer->transactions[datablocks + 1].data = 0;
|
||||||
if (reqtype & 128)
|
if ((reqtype & 128) && datablocks)
|
||||||
transfer->transactions[datablocks + 1].pid = GRUB_USB_TRANSFER_TYPE_OUT;
|
transfer->transactions[datablocks + 1].pid = GRUB_USB_TRANSFER_TYPE_OUT;
|
||||||
else
|
else
|
||||||
transfer->transactions[datablocks + 1].pid = GRUB_USB_TRANSFER_TYPE_IN;
|
transfer->transactions[datablocks + 1].pid = GRUB_USB_TRANSFER_TYPE_IN;
|
||||||
|
@ -116,14 +148,19 @@ grub_usb_control_msg (grub_usb_device_t dev,
|
||||||
err = dev->controller.dev->transfer (&dev->controller, transfer);
|
err = dev->controller.dev->transfer (&dev->controller, transfer);
|
||||||
|
|
||||||
grub_free (transfer->transactions);
|
grub_free (transfer->transactions);
|
||||||
|
|
||||||
grub_free (transfer);
|
grub_free (transfer);
|
||||||
|
grub_dma_free (data_chunk);
|
||||||
|
grub_dma_free (setupdata_chunk);
|
||||||
|
|
||||||
|
grub_memcpy (data_in, (char *) data, size0);
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static grub_usb_err_t
|
static grub_usb_err_t
|
||||||
grub_usb_bulk_readwrite (grub_usb_device_t dev,
|
grub_usb_bulk_readwrite (grub_usb_device_t dev,
|
||||||
int endpoint, grub_size_t size, char *data,
|
int endpoint, grub_size_t size0, char *data_in,
|
||||||
grub_transfer_type_t type)
|
grub_transfer_type_t type)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
@ -132,6 +169,19 @@ grub_usb_bulk_readwrite (grub_usb_device_t dev,
|
||||||
unsigned int max;
|
unsigned int max;
|
||||||
grub_usb_err_t err;
|
grub_usb_err_t err;
|
||||||
int toggle = dev->toggle[endpoint];
|
int toggle = dev->toggle[endpoint];
|
||||||
|
volatile char *data;
|
||||||
|
grub_uint32_t data_addr;
|
||||||
|
struct grub_pci_dma_chunk *data_chunk;
|
||||||
|
grub_size_t size = size0;
|
||||||
|
|
||||||
|
/* FIXME: avoid allocation any kind of buffer in a first place. */
|
||||||
|
data_chunk = grub_memalign_dma32 (128, size);
|
||||||
|
if (!data_chunk)
|
||||||
|
return GRUB_USB_ERR_INTERNAL;
|
||||||
|
data = grub_dma_get_virt (data_chunk);
|
||||||
|
data_addr = grub_dma_get_phys (data_chunk);
|
||||||
|
if (type == GRUB_USB_TRANSFER_TYPE_OUT)
|
||||||
|
grub_memcpy ((char *) data, data_in, size);
|
||||||
|
|
||||||
/* Use the maximum packet size given in the endpoint descriptor. */
|
/* Use the maximum packet size given in the endpoint descriptor. */
|
||||||
if (dev->initialized)
|
if (dev->initialized)
|
||||||
|
@ -150,16 +200,20 @@ grub_usb_bulk_readwrite (grub_usb_device_t dev,
|
||||||
/* Create a transfer. */
|
/* Create a transfer. */
|
||||||
transfer = grub_malloc (sizeof (struct grub_usb_transfer));
|
transfer = grub_malloc (sizeof (struct grub_usb_transfer));
|
||||||
if (! transfer)
|
if (! transfer)
|
||||||
|
{
|
||||||
|
grub_dma_free (data_chunk);
|
||||||
return grub_errno;
|
return grub_errno;
|
||||||
|
}
|
||||||
|
|
||||||
datablocks = ((size + max - 1) / max);
|
datablocks = ((size + max - 1) / max);
|
||||||
transfer->transcnt = datablocks;
|
transfer->transcnt = datablocks;
|
||||||
transfer->size = size - 1;
|
transfer->size = size - 1;
|
||||||
transfer->endpoint = endpoint;
|
transfer->endpoint = endpoint & 15;
|
||||||
transfer->devaddr = dev->addr;
|
transfer->devaddr = dev->addr;
|
||||||
transfer->type = GRUB_USB_TRANSACTION_TYPE_BULK;
|
transfer->type = GRUB_USB_TRANSACTION_TYPE_BULK;
|
||||||
transfer->max = max;
|
transfer->max = max;
|
||||||
transfer->dev = dev;
|
transfer->dev = dev;
|
||||||
|
transfer->last_trans = -1; /* Reset index of last processed transaction (TD) */
|
||||||
|
|
||||||
/* Allocate an array of transfer data structures. */
|
/* Allocate an array of transfer data structures. */
|
||||||
transfer->transactions = grub_malloc (transfer->transcnt
|
transfer->transactions = grub_malloc (transfer->transcnt
|
||||||
|
@ -167,6 +221,7 @@ grub_usb_bulk_readwrite (grub_usb_device_t dev,
|
||||||
if (! transfer->transactions)
|
if (! transfer->transactions)
|
||||||
{
|
{
|
||||||
grub_free (transfer);
|
grub_free (transfer);
|
||||||
|
grub_dma_free (data_chunk);
|
||||||
return grub_errno;
|
return grub_errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -181,16 +236,27 @@ grub_usb_bulk_readwrite (grub_usb_device_t dev,
|
||||||
tr->toggle = toggle;
|
tr->toggle = toggle;
|
||||||
toggle = toggle ? 0 : 1;
|
toggle = toggle ? 0 : 1;
|
||||||
tr->pid = type;
|
tr->pid = type;
|
||||||
tr->data = &data[i * max];
|
tr->data = data_addr + i * max;
|
||||||
size -= tr->size;
|
size -= tr->size;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = dev->controller.dev->transfer (&dev->controller, transfer);
|
err = dev->controller.dev->transfer (&dev->controller, transfer);
|
||||||
|
/* We must remember proper toggle value even if some transactions
|
||||||
|
* were not processed - correct value should be inversion of last
|
||||||
|
* processed transaction (TD). */
|
||||||
|
if (transfer->last_trans >= 0)
|
||||||
|
toggle = transfer->transactions[transfer->last_trans].toggle ? 0 : 1;
|
||||||
|
else
|
||||||
|
toggle = dev->toggle[endpoint]; /* Nothing done, take original */
|
||||||
grub_dprintf ("usb", "toggle=%d\n", toggle);
|
grub_dprintf ("usb", "toggle=%d\n", toggle);
|
||||||
dev->toggle[endpoint] = toggle;
|
dev->toggle[endpoint] = toggle;
|
||||||
|
|
||||||
grub_free (transfer->transactions);
|
grub_free (transfer->transactions);
|
||||||
grub_free (transfer);
|
grub_free (transfer);
|
||||||
|
grub_dma_free (data_chunk);
|
||||||
|
|
||||||
|
if (type == GRUB_USB_TRANSFER_TYPE_IN)
|
||||||
|
grub_memcpy (data_in, (char *) data, size0);
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
|
@ -138,8 +138,8 @@ grub_cmd_gptsync (grub_command_t cmd __attribute__ ((unused)),
|
||||||
{
|
{
|
||||||
grub_device_close (dev);
|
grub_device_close (dev);
|
||||||
return grub_error (GRUB_ERR_OUT_OF_RANGE,
|
return grub_error (GRUB_ERR_OUT_OF_RANGE,
|
||||||
"only partitions resding in the first 2TB "
|
"only partitions residing in the first 2TB "
|
||||||
"can be presen in hybrid MBR");
|
"can be present in hybrid MBR");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -243,8 +243,8 @@ GRUB_MOD_INIT(gptsync)
|
||||||
cmd = grub_register_command ("gptsync", grub_cmd_gptsync,
|
cmd = grub_register_command ("gptsync", grub_cmd_gptsync,
|
||||||
N_("DEVICE [PARTITION[+/-[TYPE]]] ..."),
|
N_("DEVICE [PARTITION[+/-[TYPE]]] ..."),
|
||||||
N_("Fill hybrid MBR of GPT drive DEVICE. "
|
N_("Fill hybrid MBR of GPT drive DEVICE. "
|
||||||
"specified partitions will be a part "
|
"Specified partitions will be a part "
|
||||||
"of hybrid mbr. Up to 3 partitions are "
|
"of hybrid MBR. Up to 3 partitions are "
|
||||||
"allowed. TYPE is an MBR type. "
|
"allowed. TYPE is an MBR type. "
|
||||||
"+ means that partition is active. "
|
"+ means that partition is active. "
|
||||||
"Only one partition can be active."));
|
"Only one partition can be active."));
|
||||||
|
|
|
@ -56,6 +56,12 @@ pci_mod_SOURCES = bus/pci.c
|
||||||
pci_mod_CFLAGS = $(COMMON_CFLAGS)
|
pci_mod_CFLAGS = $(COMMON_CFLAGS)
|
||||||
pci_mod_LDFLAGS = $(COMMON_LDFLAGS)
|
pci_mod_LDFLAGS = $(COMMON_LDFLAGS)
|
||||||
|
|
||||||
|
# For cs5536.mod
|
||||||
|
pkglib_MODULES += cs5536.mod
|
||||||
|
cs5536_mod_SOURCES = bus/cs5536.c
|
||||||
|
cs5536_mod_CFLAGS = $(COMMON_CFLAGS)
|
||||||
|
cs5536_mod_LDFLAGS = $(COMMON_LDFLAGS)
|
||||||
|
|
||||||
# For lspci.mod
|
# For lspci.mod
|
||||||
pkglib_MODULES += lspci.mod
|
pkglib_MODULES += lspci.mod
|
||||||
lspci_mod_SOURCES = commands/lspci.c
|
lspci_mod_SOURCES = commands/lspci.c
|
||||||
|
|
|
@ -4,7 +4,8 @@ target_machine=yeeloong
|
||||||
COMMON_CFLAGS += -march=mips3
|
COMMON_CFLAGS += -march=mips3
|
||||||
COMMON_ASFLAGS += -march=mips3
|
COMMON_ASFLAGS += -march=mips3
|
||||||
|
|
||||||
kernel_img_HEADERS += pci.h bitmap.h video.h gfxterm.h font.h bitmap_scale.h bufio.h
|
kernel_img_HEADERS += pci.h bitmap.h video.h gfxterm.h font.h \
|
||||||
|
bitmap_scale.h bufio.h cs5536.h machine/pci.h
|
||||||
|
|
||||||
include $(srcdir)/conf/mips.mk
|
include $(srcdir)/conf/mips.mk
|
||||||
|
|
||||||
|
@ -26,6 +27,7 @@ kernel_img_SOURCES = kern/$(target_cpu)/startup.S \
|
||||||
video/fb/fbfill.c video/fb/fbutil.c video/bitmap.c \
|
video/fb/fbfill.c video/fb/fbutil.c video/bitmap.c \
|
||||||
video/bitmap_scale.c video/sm712.c bus/pci.c bus/bonito.c \
|
video/bitmap_scale.c video/sm712.c bus/pci.c bus/bonito.c \
|
||||||
term/gfxterm.c commands/extcmd.c lib/arg.c \
|
term/gfxterm.c commands/extcmd.c lib/arg.c \
|
||||||
|
bus/cs5536.c \
|
||||||
symlist.c
|
symlist.c
|
||||||
kernel_img_CFLAGS = $(COMMON_CFLAGS) -DUSE_ASCII_FAILBACK
|
kernel_img_CFLAGS = $(COMMON_CFLAGS) -DUSE_ASCII_FAILBACK
|
||||||
kernel_img_ASFLAGS = $(COMMON_ASFLAGS)
|
kernel_img_ASFLAGS = $(COMMON_ASFLAGS)
|
||||||
|
@ -69,5 +71,35 @@ linux_mod_CFLAGS = $(COMMON_CFLAGS)
|
||||||
linux_mod_ASFLAGS = $(COMMON_ASFLAGS)
|
linux_mod_ASFLAGS = $(COMMON_ASFLAGS)
|
||||||
linux_mod_LDFLAGS = $(COMMON_LDFLAGS)
|
linux_mod_LDFLAGS = $(COMMON_LDFLAGS)
|
||||||
|
|
||||||
|
# For usb.mod
|
||||||
|
pkglib_MODULES += usb.mod
|
||||||
|
usb_mod_SOURCES = bus/usb/usb.c bus/usb/usbtrans.c bus/usb/usbhub.c
|
||||||
|
usb_mod_CFLAGS = $(COMMON_CFLAGS)
|
||||||
|
usb_mod_LDFLAGS = $(COMMON_LDFLAGS)
|
||||||
|
|
||||||
|
# For usbtest.mod
|
||||||
|
pkglib_MODULES += usbtest.mod
|
||||||
|
usbtest_mod_SOURCES = commands/usbtest.c
|
||||||
|
usbtest_mod_CFLAGS = $(COMMON_CFLAGS)
|
||||||
|
usbtest_mod_LDFLAGS = $(COMMON_LDFLAGS)
|
||||||
|
|
||||||
|
# For ohci.mod
|
||||||
|
pkglib_MODULES += ohci.mod
|
||||||
|
ohci_mod_SOURCES = bus/usb/ohci.c
|
||||||
|
ohci_mod_CFLAGS = $(COMMON_CFLAGS)
|
||||||
|
ohci_mod_LDFLAGS = $(COMMON_LDFLAGS)
|
||||||
|
|
||||||
|
# For usbms.mod
|
||||||
|
pkglib_MODULES += usbms.mod
|
||||||
|
usbms_mod_SOURCES = disk/usbms.c
|
||||||
|
usbms_mod_CFLAGS = $(COMMON_CFLAGS)
|
||||||
|
usbms_mod_LDFLAGS = $(COMMON_LDFLAGS)
|
||||||
|
|
||||||
|
# For usb_keyboard.mod
|
||||||
|
pkglib_MODULES += usb_keyboard.mod
|
||||||
|
usb_keyboard_mod_SOURCES = term/usb_keyboard.c
|
||||||
|
usb_keyboard_mod_CFLAGS = $(COMMON_CFLAGS)
|
||||||
|
usb_keyboard_mod_LDFLAGS = $(COMMON_LDFLAGS)
|
||||||
|
|
||||||
sbin_SCRIPTS += grub-install
|
sbin_SCRIPTS += grub-install
|
||||||
grub_install_SOURCES = util/grub-install.in
|
grub_install_SOURCES = util/grub-install.in
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include <grub/types.h>
|
#include <grub/types.h>
|
||||||
#include <grub/scsi.h>
|
#include <grub/scsi.h>
|
||||||
#include <grub/scsicmd.h>
|
#include <grub/scsicmd.h>
|
||||||
|
#include <grub/time.h>
|
||||||
|
|
||||||
|
|
||||||
static grub_scsi_dev_t grub_scsi_dev_list;
|
static grub_scsi_dev_t grub_scsi_dev_list;
|
||||||
|
@ -50,7 +51,62 @@ grub_scsi_dev_unregister (grub_scsi_dev_t dev)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Determine the the device is removable and the type of the device
|
/* Check result of previous operation. */
|
||||||
|
static grub_err_t
|
||||||
|
grub_scsi_request_sense (grub_scsi_t scsi)
|
||||||
|
{
|
||||||
|
struct grub_scsi_request_sense rs;
|
||||||
|
struct grub_scsi_request_sense_data rsd;
|
||||||
|
grub_err_t err;
|
||||||
|
|
||||||
|
rs.opcode = grub_scsi_cmd_request_sense;
|
||||||
|
rs.lun = scsi->lun << GRUB_SCSI_LUN_SHIFT;
|
||||||
|
rs.reserved1 = 0;
|
||||||
|
rs.reserved2 = 0;
|
||||||
|
rs.alloc_length = 0x12; /* XXX: Hardcoded for now */
|
||||||
|
rs.control = 0;
|
||||||
|
grub_memset (rs.pad, 0, sizeof(rs.pad));
|
||||||
|
|
||||||
|
err = scsi->dev->read (scsi, sizeof (rs), (char *) &rs,
|
||||||
|
sizeof (rsd), (char *) &rsd);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
/* Self commenting... */
|
||||||
|
static grub_err_t
|
||||||
|
grub_scsi_test_unit_ready (grub_scsi_t scsi)
|
||||||
|
{
|
||||||
|
struct grub_scsi_test_unit_ready tur;
|
||||||
|
grub_err_t err;
|
||||||
|
grub_err_t err_sense;
|
||||||
|
|
||||||
|
tur.opcode = grub_scsi_cmd_test_unit_ready;
|
||||||
|
tur.lun = scsi->lun << GRUB_SCSI_LUN_SHIFT;
|
||||||
|
tur.reserved1 = 0;
|
||||||
|
tur.reserved2 = 0;
|
||||||
|
tur.reserved3 = 0;
|
||||||
|
tur.control = 0;
|
||||||
|
grub_memset (tur.pad, 0, sizeof(tur.pad));
|
||||||
|
|
||||||
|
err = scsi->dev->read (scsi, sizeof (tur), (char *) &tur,
|
||||||
|
0, NULL);
|
||||||
|
|
||||||
|
/* Each SCSI command should be followed by Request Sense.
|
||||||
|
If not so, many devices STALLs or definitely freezes. */
|
||||||
|
err_sense = grub_scsi_request_sense (scsi);
|
||||||
|
if (err_sense != GRUB_ERR_NONE)
|
||||||
|
grub_errno = err;
|
||||||
|
/* err_sense is ignored for now and Request Sense Data also... */
|
||||||
|
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Determine if the device is removable and the type of the device
|
||||||
SCSI. */
|
SCSI. */
|
||||||
static grub_err_t
|
static grub_err_t
|
||||||
grub_scsi_inquiry (grub_scsi_t scsi)
|
grub_scsi_inquiry (grub_scsi_t scsi)
|
||||||
|
@ -58,15 +114,26 @@ grub_scsi_inquiry (grub_scsi_t scsi)
|
||||||
struct grub_scsi_inquiry iq;
|
struct grub_scsi_inquiry iq;
|
||||||
struct grub_scsi_inquiry_data iqd;
|
struct grub_scsi_inquiry_data iqd;
|
||||||
grub_err_t err;
|
grub_err_t err;
|
||||||
|
grub_err_t err_sense;
|
||||||
|
|
||||||
iq.opcode = grub_scsi_cmd_inquiry;
|
iq.opcode = grub_scsi_cmd_inquiry;
|
||||||
iq.lun = scsi->lun << GRUB_SCSI_LUN_SHIFT;
|
iq.lun = scsi->lun << GRUB_SCSI_LUN_SHIFT;
|
||||||
|
iq.page = 0;
|
||||||
iq.reserved = 0;
|
iq.reserved = 0;
|
||||||
iq.alloc_length = 0x24; /* XXX: Hardcoded for now */
|
iq.alloc_length = 0x24; /* XXX: Hardcoded for now */
|
||||||
iq.reserved2 = 0;
|
iq.control = 0;
|
||||||
|
grub_memset (iq.pad, 0, sizeof(iq.pad));
|
||||||
|
|
||||||
err = scsi->dev->read (scsi, sizeof (iq), (char *) &iq,
|
err = scsi->dev->read (scsi, sizeof (iq), (char *) &iq,
|
||||||
sizeof (iqd), (char *) &iqd);
|
sizeof (iqd), (char *) &iqd);
|
||||||
|
|
||||||
|
/* Each SCSI command should be followed by Request Sense.
|
||||||
|
If not so, many devices STALLs or definitely freezes. */
|
||||||
|
err_sense = grub_scsi_request_sense (scsi);
|
||||||
|
if (err_sense != GRUB_ERR_NONE)
|
||||||
|
grub_errno = err;
|
||||||
|
/* err_sense is ignored for now and Request Sense Data also... */
|
||||||
|
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
@ -83,13 +150,27 @@ grub_scsi_read_capacity (grub_scsi_t scsi)
|
||||||
struct grub_scsi_read_capacity rc;
|
struct grub_scsi_read_capacity rc;
|
||||||
struct grub_scsi_read_capacity_data rcd;
|
struct grub_scsi_read_capacity_data rcd;
|
||||||
grub_err_t err;
|
grub_err_t err;
|
||||||
|
grub_err_t err_sense;
|
||||||
|
|
||||||
rc.opcode = grub_scsi_cmd_read_capacity;
|
rc.opcode = grub_scsi_cmd_read_capacity;
|
||||||
rc.lun = scsi->lun << GRUB_SCSI_LUN_SHIFT;
|
rc.lun = scsi->lun << GRUB_SCSI_LUN_SHIFT;
|
||||||
grub_memset (rc.reserved, 0, sizeof (rc.reserved));
|
rc.logical_block_addr = 0;
|
||||||
|
rc.reserved1 = 0;
|
||||||
|
rc.reserved2 = 0;
|
||||||
|
rc.PMI = 0;
|
||||||
|
rc.control = 0;
|
||||||
|
rc.pad = 0;
|
||||||
|
|
||||||
err = scsi->dev->read (scsi, sizeof (rc), (char *) &rc,
|
err = scsi->dev->read (scsi, sizeof (rc), (char *) &rc,
|
||||||
sizeof (rcd), (char *) &rcd);
|
sizeof (rcd), (char *) &rcd);
|
||||||
|
|
||||||
|
/* Each SCSI command should be followed by Request Sense.
|
||||||
|
If not so, many devices STALLs or definitely freezes. */
|
||||||
|
err_sense = grub_scsi_request_sense (scsi);
|
||||||
|
if (err_sense != GRUB_ERR_NONE)
|
||||||
|
grub_errno = err;
|
||||||
|
/* err_sense is ignored for now and Request Sense Data also... */
|
||||||
|
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
@ -107,6 +188,8 @@ grub_scsi_read10 (grub_disk_t disk, grub_disk_addr_t sector,
|
||||||
{
|
{
|
||||||
grub_scsi_t scsi;
|
grub_scsi_t scsi;
|
||||||
struct grub_scsi_read10 rd;
|
struct grub_scsi_read10 rd;
|
||||||
|
grub_err_t err;
|
||||||
|
grub_err_t err_sense;
|
||||||
|
|
||||||
scsi = disk->data;
|
scsi = disk->data;
|
||||||
|
|
||||||
|
@ -118,7 +201,16 @@ grub_scsi_read10 (grub_disk_t disk, grub_disk_addr_t sector,
|
||||||
rd.reserved2 = 0;
|
rd.reserved2 = 0;
|
||||||
rd.pad = 0;
|
rd.pad = 0;
|
||||||
|
|
||||||
return scsi->dev->read (scsi, sizeof (rd), (char *) &rd, size * scsi->blocksize, buf);
|
err = scsi->dev->read (scsi, sizeof (rd), (char *) &rd, size * scsi->blocksize, buf);
|
||||||
|
|
||||||
|
/* Each SCSI command should be followed by Request Sense.
|
||||||
|
If not so, many devices STALLs or definitely freezes. */
|
||||||
|
err_sense = grub_scsi_request_sense (scsi);
|
||||||
|
if (err_sense != GRUB_ERR_NONE)
|
||||||
|
grub_errno = err;
|
||||||
|
/* err_sense is ignored for now and Request Sense Data also... */
|
||||||
|
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Send a SCSI request for DISK: read SIZE sectors starting with
|
/* Send a SCSI request for DISK: read SIZE sectors starting with
|
||||||
|
@ -129,6 +221,8 @@ grub_scsi_read12 (grub_disk_t disk, grub_disk_addr_t sector,
|
||||||
{
|
{
|
||||||
grub_scsi_t scsi;
|
grub_scsi_t scsi;
|
||||||
struct grub_scsi_read12 rd;
|
struct grub_scsi_read12 rd;
|
||||||
|
grub_err_t err;
|
||||||
|
grub_err_t err_sense;
|
||||||
|
|
||||||
scsi = disk->data;
|
scsi = disk->data;
|
||||||
|
|
||||||
|
@ -139,7 +233,16 @@ grub_scsi_read12 (grub_disk_t disk, grub_disk_addr_t sector,
|
||||||
rd.reserved = 0;
|
rd.reserved = 0;
|
||||||
rd.control = 0;
|
rd.control = 0;
|
||||||
|
|
||||||
return scsi->dev->read (scsi, sizeof (rd), (char *) &rd, size * scsi->blocksize, buf);
|
err = scsi->dev->read (scsi, sizeof (rd), (char *) &rd, size * scsi->blocksize, buf);
|
||||||
|
|
||||||
|
/* Each SCSI command should be followed by Request Sense.
|
||||||
|
If not so, many devices STALLs or definitely freezes. */
|
||||||
|
err_sense = grub_scsi_request_sense (scsi);
|
||||||
|
if (err_sense != GRUB_ERR_NONE)
|
||||||
|
grub_errno = err;
|
||||||
|
/* err_sense is ignored for now and Request Sense Data also... */
|
||||||
|
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
|
@ -151,6 +254,8 @@ grub_scsi_write10 (grub_disk_t disk, grub_disk_addr_t sector,
|
||||||
{
|
{
|
||||||
grub_scsi_t scsi;
|
grub_scsi_t scsi;
|
||||||
struct grub_scsi_write10 wr;
|
struct grub_scsi_write10 wr;
|
||||||
|
grub_err_t err;
|
||||||
|
grub_err_t err_sense;
|
||||||
|
|
||||||
scsi = disk->data;
|
scsi = disk->data;
|
||||||
|
|
||||||
|
@ -162,7 +267,16 @@ grub_scsi_write10 (grub_disk_t disk, grub_disk_addr_t sector,
|
||||||
wr.reserved2 = 0;
|
wr.reserved2 = 0;
|
||||||
wr.pad = 0;
|
wr.pad = 0;
|
||||||
|
|
||||||
return scsi->dev->write (scsi, sizeof (wr), (char *) &wr, size * scsi->blocksize, buf);
|
err = scsi->dev->write (scsi, sizeof (wr), (char *) &wr, size * scsi->blocksize, buf);
|
||||||
|
|
||||||
|
/* Each SCSI command should be followed by Request Sense.
|
||||||
|
If not so, many devices STALLs or definitely freezes. */
|
||||||
|
err_sense = grub_scsi_request_sense (scsi);
|
||||||
|
if (err_sense != GRUB_ERR_NONE)
|
||||||
|
grub_errno = err;
|
||||||
|
/* err_sense is ignored for now and Request Sense Data also... */
|
||||||
|
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Send a SCSI request for DISK: write the data stored in BUF to SIZE
|
/* Send a SCSI request for DISK: write the data stored in BUF to SIZE
|
||||||
|
@ -172,7 +286,9 @@ grub_scsi_write12 (grub_disk_t disk, grub_disk_addr_t sector,
|
||||||
grub_size_t size, char *buf)
|
grub_size_t size, char *buf)
|
||||||
{
|
{
|
||||||
grub_scsi_t scsi;
|
grub_scsi_t scsi;
|
||||||
struct grub_scsi_write10 wr;
|
struct grub_scsi_write12 wr;
|
||||||
|
grub_err_t err;
|
||||||
|
grub_err_t err_sense;
|
||||||
|
|
||||||
scsi = disk->data;
|
scsi = disk->data;
|
||||||
|
|
||||||
|
@ -181,9 +297,18 @@ grub_scsi_write12 (grub_disk_t disk, grub_disk_addr_t sector,
|
||||||
wr.lba = grub_cpu_to_be32 (sector);
|
wr.lba = grub_cpu_to_be32 (sector);
|
||||||
wr.size = grub_cpu_to_be32 (size);
|
wr.size = grub_cpu_to_be32 (size);
|
||||||
wr.reserved = 0;
|
wr.reserved = 0;
|
||||||
wr.pad = 0;
|
wr.control = 0;
|
||||||
|
|
||||||
return scsi->dev->write (scsi, sizeof (wr), (char *) &wr, size * scsi->blocksize, buf);
|
err = scsi->dev->write (scsi, sizeof (wr), (char *) &wr, size * scsi->blocksize, buf);
|
||||||
|
|
||||||
|
/* Each SCSI command should be followed by Request Sense.
|
||||||
|
If not so, many devices STALLs or definitely freezes. */
|
||||||
|
err_sense = grub_scsi_request_sense (scsi);
|
||||||
|
if (err_sense != GRUB_ERR_NONE)
|
||||||
|
grub_errno = err;
|
||||||
|
/* err_sense is ignored for now and Request Sense Data also... */
|
||||||
|
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -235,6 +360,7 @@ grub_scsi_open (const char *name, grub_disk_t disk)
|
||||||
grub_err_t err;
|
grub_err_t err;
|
||||||
int len;
|
int len;
|
||||||
int lun;
|
int lun;
|
||||||
|
grub_uint64_t maxtime;
|
||||||
|
|
||||||
scsi = grub_malloc (sizeof (*scsi));
|
scsi = grub_malloc (sizeof (*scsi));
|
||||||
if (! scsi)
|
if (! scsi)
|
||||||
|
@ -292,6 +418,31 @@ grub_scsi_open (const char *name, grub_disk_t disk)
|
||||||
else
|
else
|
||||||
disk->has_partitions = 1;
|
disk->has_partitions = 1;
|
||||||
|
|
||||||
|
|
||||||
|
/* According to USB MS tests specification, issue Test Unit Ready
|
||||||
|
* until OK */
|
||||||
|
maxtime = grub_get_time_ms () + 5000; /* It is safer value */
|
||||||
|
do
|
||||||
|
{
|
||||||
|
/* Timeout is necessary - for example in case when we have
|
||||||
|
* universal card reader with more LUNs and we have only
|
||||||
|
* one card inserted (or none), so only one LUN (or none)
|
||||||
|
* will be ready - and we want not to hang... */
|
||||||
|
if (grub_get_time_ms () > maxtime)
|
||||||
|
{
|
||||||
|
err = GRUB_ERR_READ_ERROR;
|
||||||
|
grub_free (scsi);
|
||||||
|
grub_dprintf ("scsi", "LUN is not ready - timeout\n");
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
err = grub_scsi_test_unit_ready (scsi);
|
||||||
|
}
|
||||||
|
while (err == GRUB_ERR_READ_ERROR);
|
||||||
|
/* Reset grub_errno !
|
||||||
|
* It is set to some error code in loop before... */
|
||||||
|
grub_errno = GRUB_ERR_NONE;
|
||||||
|
|
||||||
|
/* Read capacity of media */
|
||||||
err = grub_scsi_read_capacity (scsi);
|
err = grub_scsi_read_capacity (scsi);
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
|
@ -302,12 +453,14 @@ grub_scsi_open (const char *name, grub_disk_t disk)
|
||||||
|
|
||||||
/* SCSI blocks can be something else than 512, although GRUB
|
/* SCSI blocks can be something else than 512, although GRUB
|
||||||
wants 512 byte blocks. */
|
wants 512 byte blocks. */
|
||||||
disk->total_sectors = ((scsi->size * scsi->blocksize)
|
disk->total_sectors = ((grub_uint64_t)scsi->size
|
||||||
<< GRUB_DISK_SECTOR_BITS);
|
* (grub_uint64_t)scsi->blocksize)
|
||||||
|
>> GRUB_DISK_SECTOR_BITS;
|
||||||
|
|
||||||
grub_dprintf ("scsi", "capacity=%llu, blksize=%d\n",
|
grub_dprintf ("scsi", "blocks=%u, blocksize=%u\n",
|
||||||
(unsigned long long) disk->total_sectors,
|
scsi->size, scsi->blocksize);
|
||||||
scsi->blocksize);
|
grub_dprintf ("scsi", "Disk total 512 sectors = %llu\n",
|
||||||
|
(unsigned long long) disk->total_sectors);
|
||||||
|
|
||||||
return GRUB_ERR_NONE;
|
return GRUB_ERR_NONE;
|
||||||
}
|
}
|
||||||
|
@ -366,6 +519,37 @@ grub_scsi_read (grub_disk_t disk, grub_disk_addr_t sector,
|
||||||
|
|
||||||
/* XXX: Never reached. */
|
/* XXX: Never reached. */
|
||||||
return GRUB_ERR_NONE;
|
return GRUB_ERR_NONE;
|
||||||
|
|
||||||
|
#if 0 /* Workaround - it works - but very slowly, from some reason
|
||||||
|
* unknown to me (specially on OHCI). Do not use it. */
|
||||||
|
/* Split transfer requests to device sector size because */
|
||||||
|
/* some devices are not able to transfer more than 512-1024 bytes */
|
||||||
|
grub_err_t err = GRUB_ERR_NONE;
|
||||||
|
|
||||||
|
for ( ; size; size--)
|
||||||
|
{
|
||||||
|
/* Depending on the type, select a read function. */
|
||||||
|
switch (scsi->devtype)
|
||||||
|
{
|
||||||
|
case grub_scsi_devtype_direct:
|
||||||
|
err = grub_scsi_read10 (disk, sector, 1, buf);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case grub_scsi_devtype_cdrom:
|
||||||
|
err = grub_scsi_read12 (disk, sector, 1, buf);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default: /* This should not happen */
|
||||||
|
return GRUB_ERR_READ_ERROR;
|
||||||
|
}
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
sector++;
|
||||||
|
buf += scsi->blocksize;
|
||||||
|
}
|
||||||
|
|
||||||
|
return err;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static grub_err_t
|
static grub_err_t
|
||||||
|
|
|
@ -84,7 +84,8 @@ grub_usbms_finddevs (void)
|
||||||
struct grub_usb_desc_device *descdev = &usbdev->descdev;
|
struct grub_usb_desc_device *descdev = &usbdev->descdev;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (descdev->class != 0 || descdev->subclass || descdev->protocol != 0)
|
if (descdev->class != 0 || descdev->subclass || descdev->protocol != 0
|
||||||
|
|| descdev->configcnt == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* XXX: Just check configuration 0 for now. */
|
/* XXX: Just check configuration 0 for now. */
|
||||||
|
@ -93,19 +94,31 @@ grub_usbms_finddevs (void)
|
||||||
struct grub_usbms_dev *usbms;
|
struct grub_usbms_dev *usbms;
|
||||||
struct grub_usb_desc_if *interf;
|
struct grub_usb_desc_if *interf;
|
||||||
int j;
|
int j;
|
||||||
grub_uint8_t luns;
|
grub_uint8_t luns = 0;
|
||||||
|
|
||||||
|
grub_dprintf ("usbms", "alive\n");
|
||||||
|
|
||||||
interf = usbdev->config[0].interf[i].descif;
|
interf = usbdev->config[0].interf[i].descif;
|
||||||
|
|
||||||
/* If this is not a USB Mass Storage device with a supported
|
/* If this is not a USB Mass Storage device with a supported
|
||||||
protocol, just skip it. */
|
protocol, just skip it. */
|
||||||
|
grub_dprintf ("usbms", "iterate: interf=%d, class=%d, subclass=%d, protocol=%d\n",
|
||||||
|
i, interf->class, interf->subclass, interf->protocol);
|
||||||
|
|
||||||
if (interf->class != GRUB_USB_CLASS_MASS_STORAGE
|
if (interf->class != GRUB_USB_CLASS_MASS_STORAGE
|
||||||
|| interf->subclass != GRUB_USBMS_SUBCLASS_BULK
|
|| ( interf->subclass != GRUB_USBMS_SUBCLASS_BULK &&
|
||||||
|
/* Experimental support of RBC, MMC-2, UFI, SFF-8070i devices */
|
||||||
|
interf->subclass != GRUB_USBMS_SUBCLASS_RBC &&
|
||||||
|
interf->subclass != GRUB_USBMS_SUBCLASS_MMC2 &&
|
||||||
|
interf->subclass != GRUB_USBMS_SUBCLASS_UFI &&
|
||||||
|
interf->subclass != GRUB_USBMS_SUBCLASS_SFF8070 )
|
||||||
|| interf->protocol != GRUB_USBMS_PROTOCOL_BULK)
|
|| interf->protocol != GRUB_USBMS_PROTOCOL_BULK)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
grub_dprintf ("usbms", "alive\n");
|
||||||
|
|
||||||
devcnt++;
|
devcnt++;
|
||||||
usbms = grub_zalloc (sizeof (struct grub_usbms_dev));
|
usbms = grub_zalloc (sizeof (struct grub_usbms_dev));
|
||||||
if (! usbms)
|
if (! usbms)
|
||||||
|
@ -114,6 +127,8 @@ grub_usbms_finddevs (void)
|
||||||
usbms->dev = usbdev;
|
usbms->dev = usbdev;
|
||||||
usbms->interface = i;
|
usbms->interface = i;
|
||||||
|
|
||||||
|
grub_dprintf ("usbms", "alive\n");
|
||||||
|
|
||||||
/* Iterate over all endpoints of this interface, at least a
|
/* Iterate over all endpoints of this interface, at least a
|
||||||
IN and OUT bulk endpoint are required. */
|
IN and OUT bulk endpoint are required. */
|
||||||
for (j = 0; j < interf->endpointcnt; j++)
|
for (j = 0; j < interf->endpointcnt; j++)
|
||||||
|
@ -125,14 +140,16 @@ grub_usbms_finddevs (void)
|
||||||
{
|
{
|
||||||
/* Bulk IN endpoint. */
|
/* Bulk IN endpoint. */
|
||||||
usbms->in = endp;
|
usbms->in = endp;
|
||||||
grub_usb_clear_halt (usbdev, endp->endp_addr & 128);
|
/* Clear Halt is not possible yet! */
|
||||||
|
/* grub_usb_clear_halt (usbdev, endp->endp_addr); */
|
||||||
usbms->in_maxsz = endp->maxpacket;
|
usbms->in_maxsz = endp->maxpacket;
|
||||||
}
|
}
|
||||||
else if (!(endp->endp_addr & 128) && (endp->attrib & 3) == 2)
|
else if (!(endp->endp_addr & 128) && (endp->attrib & 3) == 2)
|
||||||
{
|
{
|
||||||
/* Bulk OUT endpoint. */
|
/* Bulk OUT endpoint. */
|
||||||
usbms->out = endp;
|
usbms->out = endp;
|
||||||
grub_usb_clear_halt (usbdev, endp->endp_addr & 128);
|
/* Clear Halt is not possible yet! */
|
||||||
|
/* grub_usb_clear_halt (usbdev, endp->endp_addr); */
|
||||||
usbms->out_maxsz = endp->maxpacket;
|
usbms->out_maxsz = endp->maxpacket;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -143,51 +160,63 @@ grub_usbms_finddevs (void)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
grub_dprintf ("usbms", "alive\n");
|
||||||
|
|
||||||
|
/* XXX: Activate the first configuration. */
|
||||||
|
grub_usb_set_configuration (usbdev, 1);
|
||||||
|
|
||||||
/* Query the amount of LUNs. */
|
/* Query the amount of LUNs. */
|
||||||
err = grub_usb_control_msg (usbdev, 0xA1, 254,
|
err = grub_usb_control_msg (usbdev, 0xA1, 254,
|
||||||
0, i, 1, (char *) &luns);
|
0, i, 1, (char *) &luns);
|
||||||
|
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
/* In case of a stall, clear the stall. */
|
/* In case of a stall, clear the stall. */
|
||||||
if (err == GRUB_USB_ERR_STALL)
|
if (err == GRUB_USB_ERR_STALL)
|
||||||
{
|
{
|
||||||
grub_usb_clear_halt (usbdev, usbms->in->endp_addr & 3);
|
grub_usb_clear_halt (usbdev, usbms->in->endp_addr);
|
||||||
grub_usb_clear_halt (usbdev, usbms->out->endp_addr & 3);
|
grub_usb_clear_halt (usbdev, usbms->out->endp_addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Just set the amount of LUNs to one. */
|
/* Just set the amount of LUNs to one. */
|
||||||
grub_errno = GRUB_ERR_NONE;
|
grub_errno = GRUB_ERR_NONE;
|
||||||
usbms->luns = 1;
|
usbms->luns = 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
usbms->luns = luns;
|
/* luns = 0 means one LUN with ID 0 present ! */
|
||||||
|
/* We get from device not number of LUNs but highest
|
||||||
|
* LUN number. LUNs are numbered from 0,
|
||||||
|
* i.e. number of LUNs is luns+1 ! */
|
||||||
|
usbms->luns = luns + 1;
|
||||||
|
|
||||||
/* XXX: Check the magic values, does this really make
|
grub_dprintf ("usbms", "alive\n");
|
||||||
sense? */
|
|
||||||
grub_usb_control_msg (usbdev, (1 << 6) | 1, 255,
|
|
||||||
0, i, 0, 0);
|
|
||||||
|
|
||||||
/* XXX: To make Qemu work? */
|
|
||||||
if (usbms->luns == 0)
|
|
||||||
usbms->luns = 1;
|
|
||||||
|
|
||||||
usbms->next = grub_usbms_dev_list;
|
usbms->next = grub_usbms_dev_list;
|
||||||
grub_usbms_dev_list = usbms;
|
grub_usbms_dev_list = usbms;
|
||||||
|
|
||||||
/* XXX: Activate the first configuration. */
|
#if 0 /* All this part should be probably deleted.
|
||||||
grub_usb_set_configuration (usbdev, 1);
|
* This make trouble on some devices if they are not in
|
||||||
|
* Phase Error state - and there they should be not in such state...
|
||||||
|
* Bulk only mass storage reset procedure should be used only
|
||||||
|
* on place and in time when it is really necessary. */
|
||||||
|
/* Reset recovery procedure */
|
||||||
/* Bulk-Only Mass Storage Reset, after the reset commands
|
/* Bulk-Only Mass Storage Reset, after the reset commands
|
||||||
will be accepted. */
|
will be accepted. */
|
||||||
grub_usbms_reset (usbdev, i);
|
grub_usbms_reset (usbdev, i);
|
||||||
|
grub_usb_clear_halt (usbdev, usbms->in->endp_addr);
|
||||||
|
grub_usb_clear_halt (usbdev, usbms->out->endp_addr);
|
||||||
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
grub_dprintf ("usbms", "alive\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
grub_dprintf ("usbms", "alive\n");
|
||||||
|
|
||||||
grub_usb_iterate (usb_iterate);
|
grub_usb_iterate (usb_iterate);
|
||||||
|
grub_dprintf ("usbms", "alive\n");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -224,7 +253,9 @@ grub_usbms_transfer (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd,
|
||||||
struct grub_usbms_csw status;
|
struct grub_usbms_csw status;
|
||||||
static grub_uint32_t tag = 0;
|
static grub_uint32_t tag = 0;
|
||||||
grub_usb_err_t err = GRUB_USB_ERR_NONE;
|
grub_usb_err_t err = GRUB_USB_ERR_NONE;
|
||||||
|
grub_usb_err_t errCSW = GRUB_USB_ERR_NONE;
|
||||||
int retrycnt = 3 + 1;
|
int retrycnt = 3 + 1;
|
||||||
|
grub_size_t i;
|
||||||
|
|
||||||
retry:
|
retry:
|
||||||
retrycnt--;
|
retrycnt--;
|
||||||
|
@ -237,73 +268,102 @@ grub_usbms_transfer (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd,
|
||||||
cbw.tag = tag++;
|
cbw.tag = tag++;
|
||||||
cbw.transfer_length = grub_cpu_to_le32 (size);
|
cbw.transfer_length = grub_cpu_to_le32 (size);
|
||||||
cbw.flags = (!read_write) << GRUB_USBMS_DIRECTION_BIT;
|
cbw.flags = (!read_write) << GRUB_USBMS_DIRECTION_BIT;
|
||||||
cbw.lun = scsi->lun << GRUB_SCSI_LUN_SHIFT;
|
cbw.lun = scsi->lun; /* In USB MS CBW are LUN bits on another place than in SCSI CDB, both should be set correctly. */
|
||||||
cbw.length = cmdsize;
|
cbw.length = cmdsize;
|
||||||
grub_memcpy (cbw.cbwcb, cmd, cmdsize);
|
grub_memcpy (cbw.cbwcb, cmd, cmdsize);
|
||||||
|
|
||||||
/* Write the request. */
|
/* Debug print of CBW content. */
|
||||||
err = grub_usb_bulk_write (dev->dev, dev->out->endp_addr & 15,
|
grub_dprintf ("usb", "CBW: sign=0x%08x tag=0x%08x len=0x%08x\n",
|
||||||
|
cbw.signature, cbw.tag, cbw.transfer_length);
|
||||||
|
grub_dprintf ("usb", "CBW: flags=0x%02x lun=0x%02x CB_len=0x%02x\n",
|
||||||
|
cbw.flags, cbw.lun, cbw.length);
|
||||||
|
grub_dprintf ("usb", "CBW: cmd:\n %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
|
||||||
|
cbw.cbwcb[ 0], cbw.cbwcb[ 1], cbw.cbwcb[ 2], cbw.cbwcb[ 3],
|
||||||
|
cbw.cbwcb[ 4], cbw.cbwcb[ 5], cbw.cbwcb[ 6], cbw.cbwcb[ 7],
|
||||||
|
cbw.cbwcb[ 8], cbw.cbwcb[ 9], cbw.cbwcb[10], cbw.cbwcb[11],
|
||||||
|
cbw.cbwcb[12], cbw.cbwcb[13], cbw.cbwcb[14], cbw.cbwcb[15]);
|
||||||
|
|
||||||
|
/* Write the request.
|
||||||
|
* XXX: Error recovery is maybe still not fully correct. */
|
||||||
|
err = grub_usb_bulk_write (dev->dev, dev->out->endp_addr,
|
||||||
sizeof (cbw), (char *) &cbw);
|
sizeof (cbw), (char *) &cbw);
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
if (err == GRUB_USB_ERR_STALL)
|
if (err == GRUB_USB_ERR_STALL)
|
||||||
{
|
{
|
||||||
grub_usb_clear_halt (dev->dev, dev->out->endp_addr);
|
grub_usb_clear_halt (dev->dev, dev->out->endp_addr);
|
||||||
goto retry;
|
goto CheckCSW;
|
||||||
}
|
}
|
||||||
return grub_error (GRUB_ERR_IO, "USB Mass Storage request failed");
|
return grub_error (GRUB_ERR_IO, "USB Mass Storage request failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read/write the data. */
|
/* Read/write the data, (maybe) according to specification. */
|
||||||
if (read_write == 0)
|
if (size && (read_write == 0))
|
||||||
{
|
{
|
||||||
err = grub_usb_bulk_read (dev->dev, dev->in->endp_addr & 15, size, buf);
|
err = grub_usb_bulk_read (dev->dev, dev->in->endp_addr, size, buf);
|
||||||
grub_dprintf ("usb", "read: %d %d\n", err, GRUB_USB_ERR_STALL);
|
grub_dprintf ("usb", "read: %d %d\n", err, GRUB_USB_ERR_STALL);
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
if (err == GRUB_USB_ERR_STALL)
|
if (err == GRUB_USB_ERR_STALL)
|
||||||
{
|
|
||||||
grub_usb_clear_halt (dev->dev, dev->in->endp_addr);
|
grub_usb_clear_halt (dev->dev, dev->in->endp_addr);
|
||||||
goto retry;
|
goto CheckCSW;
|
||||||
}
|
|
||||||
return grub_error (GRUB_ERR_READ_ERROR,
|
|
||||||
"can't read from USB Mass Storage device");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
/* Debug print of received data. */
|
||||||
|
grub_dprintf ("usb", "buf:\n");
|
||||||
|
if (size <= 64)
|
||||||
|
for (i=0; i<size; i++)
|
||||||
|
grub_dprintf ("usb", "0x%02x: 0x%02x\n", i, buf[i]);
|
||||||
else
|
else
|
||||||
|
grub_dprintf ("usb", "Too much data for debug print...\n");
|
||||||
|
}
|
||||||
|
else if (size)
|
||||||
{
|
{
|
||||||
err = grub_usb_bulk_write (dev->dev, dev->in->endp_addr & 15, size, buf);
|
err = grub_usb_bulk_write (dev->dev, dev->out->endp_addr, size, buf);
|
||||||
grub_dprintf ("usb", "write: %d %d\n", err, GRUB_USB_ERR_STALL);
|
grub_dprintf ("usb", "write: %d %d\n", err, GRUB_USB_ERR_STALL);
|
||||||
|
grub_dprintf ("usb", "buf:\n");
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
if (err == GRUB_USB_ERR_STALL)
|
if (err == GRUB_USB_ERR_STALL)
|
||||||
|
grub_usb_clear_halt (dev->dev, dev->out->endp_addr);
|
||||||
|
goto CheckCSW;
|
||||||
|
}
|
||||||
|
/* Debug print of sent data. */
|
||||||
|
if (size <= 256)
|
||||||
|
for (i=0; i<size; i++)
|
||||||
|
grub_dprintf ("usb", "0x%02x: 0x%02x\n", i, buf[i]);
|
||||||
|
else
|
||||||
|
grub_dprintf ("usb", "Too much data for debug print...\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read the status - (maybe) according to specification. */
|
||||||
|
CheckCSW:
|
||||||
|
errCSW = grub_usb_bulk_read (dev->dev, dev->in->endp_addr,
|
||||||
|
sizeof (status), (char *) &status);
|
||||||
|
if (errCSW)
|
||||||
{
|
{
|
||||||
|
grub_usb_clear_halt (dev->dev, dev->in->endp_addr);
|
||||||
|
errCSW = grub_usb_bulk_read (dev->dev, dev->in->endp_addr,
|
||||||
|
sizeof (status), (char *) &status);
|
||||||
|
if (errCSW)
|
||||||
|
{ /* Bulk-only reset device. */
|
||||||
|
grub_dprintf ("usb", "Bulk-only reset device - errCSW\n");
|
||||||
|
grub_usbms_reset (dev->dev, dev->interface);
|
||||||
|
grub_usb_clear_halt (dev->dev, dev->in->endp_addr);
|
||||||
grub_usb_clear_halt (dev->dev, dev->out->endp_addr);
|
grub_usb_clear_halt (dev->dev, dev->out->endp_addr);
|
||||||
goto retry;
|
goto retry;
|
||||||
}
|
}
|
||||||
return grub_error (GRUB_ERR_WRITE_ERROR,
|
|
||||||
"can't write to USB Mass Storage device");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read the status. */
|
/* Debug print of CSW content. */
|
||||||
err = grub_usb_bulk_read (dev->dev, dev->in->endp_addr & 15,
|
grub_dprintf ("usb", "CSW: sign=0x%08x tag=0x%08x resid=0x%08x\n",
|
||||||
sizeof (status), (char *) &status);
|
status.signature, status.tag, status.residue);
|
||||||
if (err)
|
grub_dprintf ("usb", "CSW: status=0x%02x\n", status.status);
|
||||||
{
|
|
||||||
if (err == GRUB_USB_ERR_STALL)
|
|
||||||
{
|
|
||||||
grub_usb_clear_halt (dev->dev, dev->in->endp_addr);
|
|
||||||
goto retry;
|
|
||||||
}
|
|
||||||
return grub_error (GRUB_ERR_READ_ERROR,
|
|
||||||
"can't read status from USB Mass Storage device");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* XXX: Magic and check this code. */
|
/* If phase error or not valid signature, do bulk-only reset device. */
|
||||||
if (status.status == 2)
|
if ((status.status == 2) ||
|
||||||
{
|
(status.signature != grub_cpu_to_le32(0x53425355)))
|
||||||
/* XXX: Phase error, reset device. */
|
{ /* Bulk-only reset device. */
|
||||||
|
grub_dprintf ("usb", "Bulk-only reset device - bad status\n");
|
||||||
grub_usbms_reset (dev->dev, dev->interface);
|
grub_usbms_reset (dev->dev, dev->interface);
|
||||||
grub_usb_clear_halt (dev->dev, dev->in->endp_addr);
|
grub_usb_clear_halt (dev->dev, dev->in->endp_addr);
|
||||||
grub_usb_clear_halt (dev->dev, dev->out->endp_addr);
|
grub_usb_clear_halt (dev->dev, dev->out->endp_addr);
|
||||||
|
@ -311,9 +371,13 @@ grub_usbms_transfer (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd,
|
||||||
goto retry;
|
goto retry;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status.status)
|
/* If "command failed" status or data transfer failed -> error */
|
||||||
|
if ((status.status || err) && !read_write)
|
||||||
return grub_error (GRUB_ERR_READ_ERROR,
|
return grub_error (GRUB_ERR_READ_ERROR,
|
||||||
"error communication with USB Mass Storage device");
|
"error communication with USB Mass Storage device");
|
||||||
|
else if ((status.status || err) && read_write)
|
||||||
|
return grub_error (GRUB_ERR_WRITE_ERROR,
|
||||||
|
"error communication with USB Mass Storage device");
|
||||||
|
|
||||||
return GRUB_ERR_NONE;
|
return GRUB_ERR_NONE;
|
||||||
}
|
}
|
||||||
|
|
190
grub-core/include/grub/cs5536.h
Normal file
190
grub-core/include/grub/cs5536.h
Normal file
|
@ -0,0 +1,190 @@
|
||||||
|
/*
|
||||||
|
* GRUB -- GRand Unified Bootloader
|
||||||
|
* Copyright (C) 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef GRUB_CS5536_HEADER
|
||||||
|
#define GRUB_CS5536_HEADER 1
|
||||||
|
|
||||||
|
#ifndef ASM_FILE
|
||||||
|
#include <grub/pci.h>
|
||||||
|
#include <grub/err.h>
|
||||||
|
#include <grub/smbus.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define GRUB_CS5536_PCIID 0x208f1022
|
||||||
|
#define GRUB_CS5536_MSR_MAILBOX_ADDR 0xf4
|
||||||
|
#define GRUB_CS5536_MSR_MAILBOX_DATA0 0xf8
|
||||||
|
#define GRUB_CS5536_MSR_MAILBOX_DATA1 0xfc
|
||||||
|
#define GRUB_CS5536_MSR_IRQ_MAP_BAR 0x80000008
|
||||||
|
#define GRUB_CS5536_MSR_SMB_BAR 0x8000000b
|
||||||
|
|
||||||
|
#define GRUB_CS5536_SMBUS_REGS_SIZE 8
|
||||||
|
#define GRUB_CS5536_GPIO_REGS_SIZE 256
|
||||||
|
#define GRUB_CS5536_MFGPT_REGS_SIZE 64
|
||||||
|
#define GRUB_CS5536_IRQ_MAP_REGS_SIZE 32
|
||||||
|
#define GRUB_CS5536_PM_REGS_SIZE 128
|
||||||
|
#define GRUB_CS5536_ACPI_REGS_SIZE 32
|
||||||
|
|
||||||
|
#define GRUB_CS5536_USB_OPTION_REGS_SIZE 0x1c
|
||||||
|
#define GRUB_CS5536_USB_OPTION_REG_UOCMUX 1
|
||||||
|
#define GRUB_CS5536_USB_OPTION_REG_UOCMUX_PMUX_MASK 0x03
|
||||||
|
#define GRUB_CS5536_USB_OPTION_REG_UOCMUX_PMUX_HC 0x02
|
||||||
|
|
||||||
|
#define GRUB_CS5536_DESTINATION_GLIU 0
|
||||||
|
#define GRUB_CS5536_DESTINATION_GLPCI_SB 1
|
||||||
|
#define GRUB_CS5536_DESTINATION_USB 2
|
||||||
|
#define GRUB_CS5536_DESTINATION_IDE 3
|
||||||
|
#define GRUB_CS5536_DESTINATION_DD 4
|
||||||
|
#define GRUB_CS5536_DESTINATION_ACC 5
|
||||||
|
#define GRUB_CS5536_DESTINATION_GLCP 7
|
||||||
|
|
||||||
|
#define GRUB_CS5536_P2D_DEST_SHIFT 61
|
||||||
|
#define GRUB_CS5536_P2D_LOG_ALIGN 12
|
||||||
|
#define GRUB_CS5536_P2D_ALIGN (1 << GRUB_CS5536_P2D_LOG_ALIGN)
|
||||||
|
#define GRUB_CS5536_P2D_BASE_SHIFT 20
|
||||||
|
#define GRUB_CS5536_P2D_MASK_SHIFT 0
|
||||||
|
|
||||||
|
#define GRUB_CS5536_MSR_GL_IOD_START 0x000100e0
|
||||||
|
#define GRUB_CS5536_IOD_DEST_SHIFT 61
|
||||||
|
#define GRUB_CS5536_IOD_BASE_SHIFT 20
|
||||||
|
#define GRUB_CS5536_IOD_MASK_SHIFT 0
|
||||||
|
#define GRUB_CS5536_IOD_ADDR_MASK 0xfffff
|
||||||
|
|
||||||
|
#define GRUB_CS5536_MSR_GPIO_BAR 0x8000000c
|
||||||
|
#define GRUB_CS5536_MSR_MFGPT_BAR 0x8000000d
|
||||||
|
#define GRUB_CS5536_MSR_ACPI_BAR 0x8000000e
|
||||||
|
#define GRUB_CS5536_MSR_PM_BAR 0x8000000f
|
||||||
|
#define GRUB_CS5536_MSR_DIVIL_LEG_IO 0x80000014
|
||||||
|
#define GRUB_CS5536_MSR_DIVIL_LEG_IO_RTC_ENABLE0 0x00000001
|
||||||
|
#define GRUB_CS5536_MSR_DIVIL_LEG_IO_RTC_ENABLE1 0x00000002
|
||||||
|
#define GRUB_CS5536_MSR_DIVIL_LEG_IO_MODE_X86 0x10000000
|
||||||
|
#define GRUB_CS5536_MSR_DIVIL_LEG_IO_F_REMAP 0x04000000
|
||||||
|
#define GRUB_CS5536_MSR_DIVIL_IRQ_MAPPER_PRIMARY_MASK 0x80000024
|
||||||
|
#define GRUB_CS5536_MSR_DIVIL_IRQ_MAPPER_LPC_MASK 0x80000025
|
||||||
|
#define GRUB_CS5536_DIVIL_LPC_INTERRUPTS 0x1002
|
||||||
|
#define GRUB_CS5536_MSR_DIVIL_LPC_SERIAL_IRQ_CONTROL 0x8000004e
|
||||||
|
#define GRUB_CS5536_MSR_DIVIL_LPC_SERIAL_IRQ_CONTROL_ENABLE 0x80
|
||||||
|
|
||||||
|
#define GRUB_CS5536_MSR_USB_OHCI_BASE 0x40000008
|
||||||
|
#define GRUB_CS5536_MSR_USB_EHCI_BASE 0x40000009
|
||||||
|
#define GRUB_CS5536_MSR_USB_CONTROLLER_BASE 0x4000000a
|
||||||
|
#define GRUB_CS5536_MSR_USB_OPTION_CONTROLLER_BASE 0x4000000b
|
||||||
|
#define GRUB_CS5536_MSR_USB_BASE_ADDR_MASK 0x00ffffff00ULL
|
||||||
|
#define GRUB_CS5536_MSR_USB_BASE_BUS_MASTER 0x0400000000ULL
|
||||||
|
#define GRUB_CS5536_MSR_USB_BASE_MEMORY_ENABLE 0x0200000000ULL
|
||||||
|
#define GRUB_CS5536_MSR_USB_BASE_PME_ENABLED 0x0800000000ULL
|
||||||
|
#define GRUB_CS5536_MSR_USB_BASE_PME_STATUS 0x1000000000ULL
|
||||||
|
#define GRUB_CS5536_MSR_USB_EHCI_BASE_FLDJ_SHIFT 40
|
||||||
|
|
||||||
|
#define GRUB_CS5536_MSR_IDE_IO_BAR 0x60000008
|
||||||
|
#define GRUB_CS5536_MSR_IDE_IO_BAR_UNITS 1
|
||||||
|
#define GRUB_CS5536_MSR_IDE_IO_BAR_ADDR_MASK 0xfffffff0
|
||||||
|
#define GRUB_CS5536_MSR_IDE_CFG 0x60000010
|
||||||
|
#define GRUB_CS5536_MSR_IDE_CFG_CHANNEL_ENABLE 2
|
||||||
|
#define GRUB_CS5536_MSR_IDE_TIMING 0x60000012
|
||||||
|
#define GRUB_CS5536_MSR_IDE_TIMING_PIO0 0x98
|
||||||
|
#define GRUB_CS5536_MSR_IDE_TIMING_DRIVE0_SHIFT 24
|
||||||
|
#define GRUB_CS5536_MSR_IDE_TIMING_DRIVE1_SHIFT 16
|
||||||
|
#define GRUB_CS5536_MSR_IDE_CAS_TIMING 0x60000013
|
||||||
|
#define GRUB_CS5536_MSR_IDE_CAS_TIMING_CMD_PIO0 0x99
|
||||||
|
#define GRUB_CS5536_MSR_IDE_CAS_TIMING_CMD_SHIFT 24
|
||||||
|
#define GRUB_CS5536_MSR_IDE_CAS_TIMING_DRIVE0_SHIFT 6
|
||||||
|
#define GRUB_CS5536_MSR_IDE_CAS_TIMING_DRIVE1_SHIFT 4
|
||||||
|
#define GRUB_CS5536_MSR_IDE_CAS_TIMING_PIO0 2
|
||||||
|
|
||||||
|
#define GRUB_CS5536_MSR_GL_PCI_CTRL 0x00000010
|
||||||
|
#define GRUB_CS5536_MSR_GL_PCI_CTRL_MEMORY_ENABLE 1
|
||||||
|
#define GRUB_CS5536_MSR_GL_PCI_CTRL_IO_ENABLE 2
|
||||||
|
#define GRUB_CS5536_MSR_GL_PCI_CTRL_LATENCY_SHIFT 35
|
||||||
|
#define GRUB_CS5536_MSR_GL_PCI_CTRL_OUT_THR_SHIFT 60
|
||||||
|
#define GRUB_CS5536_MSR_GL_PCI_CTRL_IN_THR_SHIFT 56
|
||||||
|
|
||||||
|
#define GRUB_CS5536_MSR_GL_REGIONS_START 0x00000020
|
||||||
|
#define GRUB_CS5536_MSR_GL_REGIONS_NUM 16
|
||||||
|
#define GRUB_CS5536_MSR_GL_REGION_ENABLE 1
|
||||||
|
#define GRUB_CS5536_MSR_GL_REGION_IO 0x100000000ULL
|
||||||
|
#define GRUB_CS5536_MSR_GL_REGION_BASE_MASK 0xfffff000ULL
|
||||||
|
#define GRUB_CS5536_MSR_GL_REGION_IO_BASE_SHIFT 12
|
||||||
|
#define GRUB_CS5536_MSR_GL_REGION_TOP_MASK 0xfffff00000000000ULL
|
||||||
|
#define GRUB_CS5536_MSR_GL_REGION_IO_TOP_SHIFT 44
|
||||||
|
|
||||||
|
#define GRUB_CS5536_MSR_GL_P2D_START 0x00010020
|
||||||
|
|
||||||
|
#define GRUB_CS5536_SMB_REG_DATA 0x0
|
||||||
|
#define GRUB_CS5536_SMB_REG_STATUS 0x1
|
||||||
|
#define GRUB_CS5536_SMB_REG_STATUS_SDAST (1 << 6)
|
||||||
|
#define GRUB_CS5536_SMB_REG_STATUS_BER (1 << 5)
|
||||||
|
#define GRUB_CS5536_SMB_REG_STATUS_NACK (1 << 4)
|
||||||
|
#define GRUB_CS5536_SMB_REG_CTRL1 0x3
|
||||||
|
#define GRUB_CS5536_SMB_REG_CTRL1_START 0x01
|
||||||
|
#define GRUB_CS5536_SMB_REG_CTRL1_STOP 0x02
|
||||||
|
#define GRUB_CS5536_SMB_REG_CTRL1_ACK 0x10
|
||||||
|
#define GRUB_CS5536_SMB_REG_ADDR 0x4
|
||||||
|
#define GRUB_CS5536_SMB_REG_ADDR_MASTER 0x0
|
||||||
|
#define GRUB_CS5536_SMB_REG_CTRL2 0x5
|
||||||
|
#define GRUB_CS5536_SMB_REG_CTRL2_ENABLE 0x1
|
||||||
|
#define GRUB_CS5536_SMB_REG_CTRL3 0x6
|
||||||
|
|
||||||
|
#ifdef ASM_FILE
|
||||||
|
#define GRUB_ULL(x) x
|
||||||
|
#else
|
||||||
|
#define GRUB_ULL(x) x ## ULL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define GRUB_CS5536_LBAR_ADDR_MASK GRUB_ULL (0x000000000000fff8)
|
||||||
|
#define GRUB_CS5536_LBAR_ENABLE GRUB_ULL (0x0000000100000000)
|
||||||
|
#define GRUB_CS5536_LBAR_MASK_MASK GRUB_ULL (0x0000f00000000000)
|
||||||
|
#define GRUB_CS5536_LBAR_TURN_ON (GRUB_CS5536_LBAR_ENABLE | GRUB_CS5536_LBAR_MASK_MASK)
|
||||||
|
|
||||||
|
/* PMON-compatible LBARs. */
|
||||||
|
#define GRUB_CS5536_LBAR_GPIO 0xb000
|
||||||
|
#define GRUB_CS5536_LBAR_ACC 0xb200
|
||||||
|
#define GRUB_CS5536_LBAR_PM 0xb280
|
||||||
|
#define GRUB_CS5536_LBAR_MFGPT 0xb300
|
||||||
|
#define GRUB_CS5536_LBAR_ACPI 0xb340
|
||||||
|
#define GRUB_CS5536_LBAR_IRQ_MAP 0xb360
|
||||||
|
#define GRUB_CS5536_LBAR_IDE 0xb380
|
||||||
|
#define GRUB_CS5536_LBAR_SMBUS 0xb390
|
||||||
|
|
||||||
|
#define GRUB_GPIO_SMBUS_PINS ((1 << 14) | (1 << 15))
|
||||||
|
#define GRUB_GPIO_REG_OUT_EN 0x4
|
||||||
|
#define GRUB_GPIO_REG_OUT_AUX1 0x10
|
||||||
|
#define GRUB_GPIO_REG_IN_EN 0x20
|
||||||
|
#define GRUB_GPIO_REG_IN_AUX1 0x34
|
||||||
|
|
||||||
|
#ifndef ASM_FILE
|
||||||
|
int EXPORT_FUNC (grub_cs5536_find) (grub_pci_device_t *devp);
|
||||||
|
|
||||||
|
grub_uint64_t EXPORT_FUNC (grub_cs5536_read_msr) (grub_pci_device_t dev,
|
||||||
|
grub_uint32_t addr);
|
||||||
|
void EXPORT_FUNC (grub_cs5536_write_msr) (grub_pci_device_t dev,
|
||||||
|
grub_uint32_t addr,
|
||||||
|
grub_uint64_t val);
|
||||||
|
grub_err_t grub_cs5536_read_spd_byte (grub_port_t smbbase, grub_uint8_t dev,
|
||||||
|
grub_uint8_t addr, grub_uint8_t *res);
|
||||||
|
grub_err_t EXPORT_FUNC (grub_cs5536_read_spd) (grub_port_t smbbase,
|
||||||
|
grub_uint8_t dev,
|
||||||
|
struct grub_smbus_spd *res);
|
||||||
|
grub_err_t grub_cs5536_smbus_wait (grub_port_t smbbase);
|
||||||
|
grub_err_t EXPORT_FUNC (grub_cs5536_init_smbus) (grub_pci_device_t dev,
|
||||||
|
grub_uint16_t divisor,
|
||||||
|
grub_port_t *smbbase);
|
||||||
|
|
||||||
|
void grub_cs5536_init_geode (grub_pci_device_t dev);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
|
@ -80,7 +80,7 @@ grub_pci_device_map_range (grub_pci_device_t dev __attribute__ ((unused)),
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
grub_pci_device_unmap_range (grub_pci_device_t dev __attribute__ ((unused)),
|
grub_pci_device_unmap_range (grub_pci_device_t dev __attribute__ ((unused)),
|
||||||
void *mem __attribute__ ((unused)),
|
volatile void *mem __attribute__ ((unused)),
|
||||||
grub_size_t size __attribute__ ((unused)))
|
grub_size_t size __attribute__ ((unused)))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,16 +19,30 @@
|
||||||
#ifndef GRUB_MACHINE_PCI_H
|
#ifndef GRUB_MACHINE_PCI_H
|
||||||
#define GRUB_MACHINE_PCI_H 1
|
#define GRUB_MACHINE_PCI_H 1
|
||||||
|
|
||||||
|
#ifndef ASM_FILE
|
||||||
#include <grub/types.h>
|
#include <grub/types.h>
|
||||||
#include <grub/cpu/io.h>
|
#include <grub/cpu/io.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define GRUB_YEELOONG_OHCI_PCIID 0x00351033
|
||||||
|
#define GRUB_YEELOONG_EHCI_PCIID 0x00e01033
|
||||||
|
#define GRUB_YEELOONG_OHCI_GHOST_FUNCTION 4
|
||||||
|
#define GRUB_YEELOONG_EHCI_GHOST_FUNCTION 5
|
||||||
|
|
||||||
#define GRUB_PCI_NUM_BUS 1
|
#define GRUB_PCI_NUM_BUS 1
|
||||||
#define GRUB_PCI_NUM_DEVICES 16
|
#define GRUB_PCI_NUM_DEVICES 16
|
||||||
|
|
||||||
#define GRUB_MACHINE_PCI_IO_BASE 0xbfd00000
|
#define GRUB_MACHINE_PCI_IO_BASE 0xbfd00000
|
||||||
#define GRUB_MACHINE_PCI_CONFSPACE 0xbfe80000
|
#define GRUB_MACHINE_PCI_CONFSPACE 0xbfe80000
|
||||||
#define GRUB_MACHINE_PCI_CONF_CTRL_REG (*(volatile grub_uint32_t *) 0xbfe00118)
|
#define GRUB_MACHINE_PCI_CONTROLLER_HEADER 0xbfe00000
|
||||||
|
|
||||||
|
#define GRUB_MACHINE_PCI_CONF_CTRL_REG_ADDR 0xbfe00118
|
||||||
|
|
||||||
|
#ifndef ASM_FILE
|
||||||
|
#define GRUB_MACHINE_PCI_CONF_CTRL_REG (*(volatile grub_uint32_t *) \
|
||||||
|
GRUB_MACHINE_PCI_CONF_CTRL_REG_ADDR)
|
||||||
#define GRUB_MACHINE_PCI_IO_CTRL_REG (*(volatile grub_uint32_t *) 0xbfe00110)
|
#define GRUB_MACHINE_PCI_IO_CTRL_REG (*(volatile grub_uint32_t *) 0xbfe00110)
|
||||||
|
#endif
|
||||||
#define GRUB_MACHINE_PCI_WIN_MASK_SIZE 6
|
#define GRUB_MACHINE_PCI_WIN_MASK_SIZE 6
|
||||||
#define GRUB_MACHINE_PCI_WIN_MASK ((1 << GRUB_MACHINE_PCI_WIN_MASK_SIZE) - 1)
|
#define GRUB_MACHINE_PCI_WIN_MASK ((1 << GRUB_MACHINE_PCI_WIN_MASK_SIZE) - 1)
|
||||||
|
|
||||||
|
@ -46,6 +60,7 @@
|
||||||
#define GRUB_MACHINE_PCI_WIN2_ADDR 0xb4000000
|
#define GRUB_MACHINE_PCI_WIN2_ADDR 0xb4000000
|
||||||
#define GRUB_MACHINE_PCI_WIN3_ADDR 0xb8000000
|
#define GRUB_MACHINE_PCI_WIN3_ADDR 0xb8000000
|
||||||
|
|
||||||
|
#ifndef ASM_FILE
|
||||||
static inline grub_uint32_t
|
static inline grub_uint32_t
|
||||||
grub_pci_read (grub_pci_address_t addr)
|
grub_pci_read (grub_pci_address_t addr)
|
||||||
{
|
{
|
||||||
|
@ -95,11 +110,12 @@ grub_pci_write_byte (grub_pci_address_t addr, grub_uint8_t data)
|
||||||
}
|
}
|
||||||
|
|
||||||
volatile void *
|
volatile void *
|
||||||
grub_pci_device_map_range (grub_pci_device_t dev __attribute__ ((unused)),
|
EXPORT_FUNC (grub_pci_device_map_range) (grub_pci_device_t dev,
|
||||||
grub_addr_t base, grub_size_t size);
|
grub_addr_t base, grub_size_t size);
|
||||||
void
|
void
|
||||||
grub_pci_device_unmap_range (grub_pci_device_t dev __attribute__ ((unused)),
|
EXPORT_FUNC (grub_pci_device_unmap_range) (grub_pci_device_t dev,
|
||||||
volatile void *mem,
|
volatile void *mem,
|
||||||
grub_size_t size __attribute__ ((unused)));
|
grub_size_t size);
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* GRUB_MACHINE_PCI_H */
|
#endif /* GRUB_MACHINE_PCI_H */
|
||||||
|
|
|
@ -19,8 +19,10 @@
|
||||||
#ifndef GRUB_PCI_H
|
#ifndef GRUB_PCI_H
|
||||||
#define GRUB_PCI_H 1
|
#define GRUB_PCI_H 1
|
||||||
|
|
||||||
|
#ifndef ASM_FILE
|
||||||
#include <grub/types.h>
|
#include <grub/types.h>
|
||||||
#include <grub/symbol.h>
|
#include <grub/symbol.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#define GRUB_PCI_ADDR_SPACE_MASK 0x01
|
#define GRUB_PCI_ADDR_SPACE_MASK 0x01
|
||||||
#define GRUB_PCI_ADDR_SPACE_MEMORY 0x00
|
#define GRUB_PCI_ADDR_SPACE_MEMORY 0x00
|
||||||
|
@ -66,6 +68,20 @@
|
||||||
#define GRUB_PCI_REG_MIN_GNT 0x3e
|
#define GRUB_PCI_REG_MIN_GNT 0x3e
|
||||||
#define GRUB_PCI_REG_MAX_LAT 0x3f
|
#define GRUB_PCI_REG_MAX_LAT 0x3f
|
||||||
|
|
||||||
|
#define GRUB_PCI_COMMAND_IO_ENABLED 0x0001
|
||||||
|
#define GRUB_PCI_COMMAND_MEM_ENABLED 0x0002
|
||||||
|
#define GRUB_PCI_COMMAND_BUS_MASTER 0x0004
|
||||||
|
#define GRUB_PCI_COMMAND_PARITY_ERROR 0x0040
|
||||||
|
#define GRUB_PCI_COMMAND_SERR_ENABLE 0x0100
|
||||||
|
|
||||||
|
#define GRUB_PCI_STATUS_CAPABILITIES 0x0010
|
||||||
|
#define GRUB_PCI_STATUS_66MHZ_CAPABLE 0x0020
|
||||||
|
#define GRUB_PCI_STATUS_FAST_B2B_CAPABLE 0x0080
|
||||||
|
|
||||||
|
#define GRUB_PCI_STATUS_DEVSEL_TIMING_SHIFT 9
|
||||||
|
#define GRUB_PCI_STATUS_DEVSEL_TIMING_MASK 0x0600
|
||||||
|
|
||||||
|
#ifndef ASM_FILE
|
||||||
typedef grub_uint32_t grub_pci_id_t;
|
typedef grub_uint32_t grub_pci_id_t;
|
||||||
|
|
||||||
#ifdef GRUB_MACHINE_EMU
|
#ifdef GRUB_MACHINE_EMU
|
||||||
|
@ -107,4 +123,14 @@ grub_pci_address_t EXPORT_FUNC(grub_pci_make_address) (grub_pci_device_t dev,
|
||||||
|
|
||||||
void EXPORT_FUNC(grub_pci_iterate) (grub_pci_iteratefunc_t hook);
|
void EXPORT_FUNC(grub_pci_iterate) (grub_pci_iteratefunc_t hook);
|
||||||
|
|
||||||
|
struct grub_pci_dma_chunk;
|
||||||
|
|
||||||
|
struct grub_pci_dma_chunk *EXPORT_FUNC(grub_memalign_dma32) (grub_size_t align,
|
||||||
|
grub_size_t size);
|
||||||
|
void EXPORT_FUNC(grub_dma_free) (struct grub_pci_dma_chunk *ch);
|
||||||
|
volatile void *EXPORT_FUNC(grub_dma_get_virt) (struct grub_pci_dma_chunk *ch);
|
||||||
|
grub_uint32_t EXPORT_FUNC(grub_dma_get_phys) (struct grub_pci_dma_chunk *ch);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* GRUB_PCI_H */
|
#endif /* GRUB_PCI_H */
|
||||||
|
|
|
@ -25,14 +25,26 @@
|
||||||
#define GRUB_SCSI_REMOVABLE_BIT 7
|
#define GRUB_SCSI_REMOVABLE_BIT 7
|
||||||
#define GRUB_SCSI_LUN_SHIFT 5
|
#define GRUB_SCSI_LUN_SHIFT 5
|
||||||
|
|
||||||
|
struct grub_scsi_test_unit_ready
|
||||||
|
{
|
||||||
|
grub_uint8_t opcode;
|
||||||
|
grub_uint8_t lun; /* 7-5 LUN, 4-0 reserved */
|
||||||
|
grub_uint8_t reserved1;
|
||||||
|
grub_uint8_t reserved2;
|
||||||
|
grub_uint8_t reserved3;
|
||||||
|
grub_uint8_t control;
|
||||||
|
grub_uint8_t pad[6]; /* To be ATAPI compatible */
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
struct grub_scsi_inquiry
|
struct grub_scsi_inquiry
|
||||||
{
|
{
|
||||||
grub_uint8_t opcode;
|
grub_uint8_t opcode;
|
||||||
grub_uint8_t lun;
|
grub_uint8_t lun; /* 7-5 LUN, 4-1 reserved, 0 EVPD */
|
||||||
grub_uint16_t reserved;
|
grub_uint8_t page; /* page code if EVPD=1 */
|
||||||
grub_uint16_t alloc_length;
|
grub_uint8_t reserved;
|
||||||
grub_uint8_t reserved2;
|
grub_uint8_t alloc_length;
|
||||||
grub_uint8_t pad[5];
|
grub_uint8_t control;
|
||||||
|
grub_uint8_t pad[6]; /* To be ATAPI compatible */
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
struct grub_scsi_inquiry_data
|
struct grub_scsi_inquiry_data
|
||||||
|
@ -47,12 +59,42 @@ struct grub_scsi_inquiry_data
|
||||||
char prodrev[4];
|
char prodrev[4];
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
struct grub_scsi_request_sense
|
||||||
|
{
|
||||||
|
grub_uint8_t opcode;
|
||||||
|
grub_uint8_t lun; /* 7-5 LUN, 4-0 reserved */
|
||||||
|
grub_uint8_t reserved1;
|
||||||
|
grub_uint8_t reserved2;
|
||||||
|
grub_uint8_t alloc_length;
|
||||||
|
grub_uint8_t control;
|
||||||
|
grub_uint8_t pad[6]; /* To be ATAPI compatible */
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
struct grub_scsi_request_sense_data
|
||||||
|
{
|
||||||
|
grub_uint8_t error_code; /* 7 Valid, 6-0 Err. code */
|
||||||
|
grub_uint8_t segment_number;
|
||||||
|
grub_uint8_t sense_key; /*7 FileMark, 6 EndOfMedia, 5 ILI, 4-0 sense key */
|
||||||
|
grub_uint32_t information;
|
||||||
|
grub_uint8_t additional_sense_length;
|
||||||
|
grub_uint32_t cmd_specific_info;
|
||||||
|
grub_uint8_t additional_sense_code;
|
||||||
|
grub_uint8_t additional_sense_code_qualifier;
|
||||||
|
grub_uint8_t field_replaceable_unit_code;
|
||||||
|
grub_uint8_t sense_key_specific[3];
|
||||||
|
/* there can be additional sense field */
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
struct grub_scsi_read_capacity
|
struct grub_scsi_read_capacity
|
||||||
{
|
{
|
||||||
grub_uint8_t opcode;
|
grub_uint8_t opcode;
|
||||||
grub_uint8_t lun;
|
grub_uint8_t lun; /* 7-5 LUN, 4-1 reserved, 0 reserved */
|
||||||
grub_uint8_t reserved[8];
|
grub_uint32_t logical_block_addr; /* only if PMI=1 */
|
||||||
grub_uint8_t pad[2];
|
grub_uint8_t reserved1;
|
||||||
|
grub_uint8_t reserved2;
|
||||||
|
grub_uint8_t PMI;
|
||||||
|
grub_uint8_t control;
|
||||||
|
grub_uint16_t pad; /* To be ATAPI compatible */
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
struct grub_scsi_read_capacity_data
|
struct grub_scsi_read_capacity_data
|
||||||
|
@ -105,12 +147,14 @@ struct grub_scsi_write12
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
|
grub_scsi_cmd_test_unit_ready = 0x00,
|
||||||
|
grub_scsi_cmd_request_sense = 0x03,
|
||||||
grub_scsi_cmd_inquiry = 0x12,
|
grub_scsi_cmd_inquiry = 0x12,
|
||||||
grub_scsi_cmd_read_capacity = 0x25,
|
grub_scsi_cmd_read_capacity = 0x25,
|
||||||
grub_scsi_cmd_read10 = 0x28,
|
grub_scsi_cmd_read10 = 0x28,
|
||||||
grub_scsi_cmd_write10 = 0x2a,
|
grub_scsi_cmd_write10 = 0x2a,
|
||||||
grub_scsi_cmd_read12 = 0xa8,
|
grub_scsi_cmd_read12 = 0xa8,
|
||||||
grub_scsi_cmd_write12 = 0xaa
|
grub_scsi_cmd_write12 = 0xaa,
|
||||||
} grub_scsi_cmd_t;
|
} grub_scsi_cmd_t;
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
|
|
70
grub-core/include/grub/smbus.h
Normal file
70
grub-core/include/grub/smbus.h
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
/*
|
||||||
|
* GRUB -- GRand Unified Bootloader
|
||||||
|
* Copyright (C) 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef GRUB_SMBUS_HEADER
|
||||||
|
#define GRUB_SMBUS_HEADER 1
|
||||||
|
|
||||||
|
#define GRUB_SMB_RAM_START_ADDR 0x50
|
||||||
|
#define GRUB_SMB_RAM_NUM_MAX 0x08
|
||||||
|
|
||||||
|
#define GRUB_SMBUS_SPD_MEMORY_TYPE_ADDR 2
|
||||||
|
#define GRUB_SMBUS_SPD_MEMORY_TYPE_DDR2 8
|
||||||
|
#define GRUB_SMBUS_SPD_MEMORY_NUM_BANKS_ADDR 17
|
||||||
|
#define GRUB_SMBUS_SPD_MEMORY_NUM_ROWS_ADDR 3
|
||||||
|
#define GRUB_SMBUS_SPD_MEMORY_NUM_COLUMNS_ADDR 4
|
||||||
|
#define GRUB_SMBUS_SPD_MEMORY_NUM_OF_RANKS_ADDR 5
|
||||||
|
#define GRUB_SMBUS_SPD_MEMORY_NUM_OF_RANKS_MASK 0x7
|
||||||
|
#define GRUB_SMBUS_SPD_MEMORY_CAS_LATENCY_ADDR 18
|
||||||
|
#define GRUB_SMBUS_SPD_MEMORY_CAS_LATENCY_MIN_VALUE 5
|
||||||
|
#define GRUB_SMBUS_SPD_MEMORY_TRAS_ADDR 30
|
||||||
|
#define GRUB_SMBUS_SPD_MEMORY_TRTP_ADDR 38
|
||||||
|
|
||||||
|
#ifndef ASM_FILE
|
||||||
|
|
||||||
|
struct grub_smbus_spd
|
||||||
|
{
|
||||||
|
grub_uint8_t written_size;
|
||||||
|
grub_uint8_t log_total_flash_size;
|
||||||
|
grub_uint8_t memory_type;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
grub_uint8_t unknown[253];
|
||||||
|
struct {
|
||||||
|
grub_uint8_t num_rows;
|
||||||
|
grub_uint8_t num_columns;
|
||||||
|
grub_uint8_t num_of_ranks;
|
||||||
|
grub_uint8_t unused1[12];
|
||||||
|
grub_uint8_t num_of_banks;
|
||||||
|
grub_uint8_t unused2[2];
|
||||||
|
grub_uint8_t cas_latency;
|
||||||
|
grub_uint8_t unused3[9];
|
||||||
|
grub_uint8_t rank_capacity;
|
||||||
|
grub_uint8_t unused4[1];
|
||||||
|
grub_uint8_t tras;
|
||||||
|
grub_uint8_t unused5[7];
|
||||||
|
grub_uint8_t trtp;
|
||||||
|
grub_uint8_t unused6[31];
|
||||||
|
grub_uint8_t part_number[18];
|
||||||
|
grub_uint8_t unused7[165];
|
||||||
|
} ddr2;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
|
@ -35,7 +35,8 @@ typedef enum
|
||||||
GRUB_USB_ERR_NAK,
|
GRUB_USB_ERR_NAK,
|
||||||
GRUB_USB_ERR_BABBLE,
|
GRUB_USB_ERR_BABBLE,
|
||||||
GRUB_USB_ERR_TIMEOUT,
|
GRUB_USB_ERR_TIMEOUT,
|
||||||
GRUB_USB_ERR_BITSTUFF
|
GRUB_USB_ERR_BITSTUFF,
|
||||||
|
GRUB_USB_ERR_UNRECOVERABLE
|
||||||
} grub_usb_err_t;
|
} grub_usb_err_t;
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
|
@ -156,7 +157,7 @@ struct grub_usb_device
|
||||||
int initialized;
|
int initialized;
|
||||||
|
|
||||||
/* Data toggle values (used for bulk transfers only). */
|
/* Data toggle values (used for bulk transfers only). */
|
||||||
int toggle[16];
|
int toggle[256];
|
||||||
|
|
||||||
/* Device-specific data. */
|
/* Device-specific data. */
|
||||||
void *data;
|
void *data;
|
||||||
|
@ -184,7 +185,12 @@ typedef enum
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
GRUB_USBMS_SUBCLASS_BULK = 0x06
|
GRUB_USBMS_SUBCLASS_BULK = 0x06,
|
||||||
|
/* Experimental support for non-pure SCSI devices */
|
||||||
|
GRUB_USBMS_SUBCLASS_RBC = 0x01,
|
||||||
|
GRUB_USBMS_SUBCLASS_MMC2 = 0x02,
|
||||||
|
GRUB_USBMS_SUBCLASS_UFI = 0x04,
|
||||||
|
GRUB_USBMS_SUBCLASS_SFF8070 = 0x05
|
||||||
} grub_usbms_subclass_t;
|
} grub_usbms_subclass_t;
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
|
|
|
@ -37,7 +37,7 @@ struct grub_usb_transaction
|
||||||
int size;
|
int size;
|
||||||
int toggle;
|
int toggle;
|
||||||
grub_transfer_type_t pid;
|
grub_transfer_type_t pid;
|
||||||
char *data;
|
grub_uint32_t data;
|
||||||
};
|
};
|
||||||
typedef struct grub_usb_transaction *grub_usb_transaction_t;
|
typedef struct grub_usb_transaction *grub_usb_transaction_t;
|
||||||
|
|
||||||
|
@ -58,6 +58,9 @@ struct grub_usb_transfer
|
||||||
struct grub_usb_device *dev;
|
struct grub_usb_device *dev;
|
||||||
|
|
||||||
struct grub_usb_transaction *transactions;
|
struct grub_usb_transaction *transactions;
|
||||||
|
|
||||||
|
int last_trans;
|
||||||
|
/* Index of last processed transaction in OHCI/UHCI driver. */
|
||||||
};
|
};
|
||||||
typedef struct grub_usb_transfer *grub_usb_transfer_t;
|
typedef struct grub_usb_transfer *grub_usb_transfer_t;
|
||||||
|
|
||||||
|
@ -86,9 +89,9 @@ typedef struct grub_usb_transfer *grub_usb_transfer_t;
|
||||||
|
|
||||||
#define GRUB_USB_REQ_HUB_GET_PORT_STATUS 0x00
|
#define GRUB_USB_REQ_HUB_GET_PORT_STATUS 0x00
|
||||||
|
|
||||||
#define GRUB_USB_FEATURE_ENDP_HALT 0x01
|
#define GRUB_USB_FEATURE_ENDP_HALT 0x00
|
||||||
#define GRUB_USB_FEATURE_DEV_REMOTE_WU 0x02
|
#define GRUB_USB_FEATURE_DEV_REMOTE_WU 0x01
|
||||||
#define GRUB_USB_FEATURE_TEST_MODE 0x04
|
#define GRUB_USB_FEATURE_TEST_MODE 0x02
|
||||||
|
|
||||||
#define GRUB_USB_HUB_STATUS_CONNECTED (1 << 0)
|
#define GRUB_USB_HUB_STATUS_CONNECTED (1 << 0)
|
||||||
#define GRUB_USB_HUB_STATUS_LOWSPEED (1 << 9)
|
#define GRUB_USB_HUB_STATUS_LOWSPEED (1 << 9)
|
||||||
|
|
|
@ -80,6 +80,86 @@ xgetcwd (void)
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
|
|
||||||
|
/* Statting something on a btrfs filesystem always returns a virtual device
|
||||||
|
major/minor pair rather than the real underlying device, because btrfs
|
||||||
|
can span multiple underlying devices (and even if it's currently only
|
||||||
|
using a single device it can be dynamically extended onto another). We
|
||||||
|
can't deal with the multiple-device case yet, but in the meantime, we can
|
||||||
|
at least cope with the single-device case by scanning
|
||||||
|
/proc/self/mountinfo. */
|
||||||
|
static char *
|
||||||
|
find_root_device_from_mountinfo (const char *dir)
|
||||||
|
{
|
||||||
|
FILE *fp;
|
||||||
|
char *buf = NULL;
|
||||||
|
size_t len = 0;
|
||||||
|
char *ret = NULL;
|
||||||
|
|
||||||
|
fp = fopen ("/proc/self/mountinfo", "r");
|
||||||
|
if (! fp)
|
||||||
|
return NULL; /* fall through to other methods */
|
||||||
|
|
||||||
|
while (getline (&buf, &len, fp) > 0)
|
||||||
|
{
|
||||||
|
int mnt_id, parent_mnt_id;
|
||||||
|
unsigned int major, minor;
|
||||||
|
char enc_root[PATH_MAX], enc_path[PATH_MAX];
|
||||||
|
int count;
|
||||||
|
size_t enc_path_len;
|
||||||
|
const char *sep;
|
||||||
|
char fstype[PATH_MAX], device[PATH_MAX];
|
||||||
|
struct stat st;
|
||||||
|
|
||||||
|
if (sscanf (buf, "%d %d %u:%u %s %s%n",
|
||||||
|
&mnt_id, &parent_mnt_id, &major, &minor, enc_root, enc_path,
|
||||||
|
&count) < 6)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (strcmp (enc_root, "/") != 0)
|
||||||
|
continue; /* only a subtree is mounted */
|
||||||
|
|
||||||
|
enc_path_len = strlen (enc_path);
|
||||||
|
if (strncmp (dir, enc_path, enc_path_len) != 0 ||
|
||||||
|
(dir[enc_path_len] && dir[enc_path_len] != '/'))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* This is a parent of the requested directory. /proc/self/mountinfo
|
||||||
|
is in mount order, so it must be the closest parent we've
|
||||||
|
encountered so far. If it's virtual, return its device node;
|
||||||
|
otherwise, carry on to try to find something closer. */
|
||||||
|
|
||||||
|
free (ret);
|
||||||
|
ret = NULL;
|
||||||
|
|
||||||
|
if (major != 0)
|
||||||
|
continue; /* not a virtual device */
|
||||||
|
|
||||||
|
sep = strstr (buf + count, " - ");
|
||||||
|
if (!sep)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
sep += sizeof (" - ") - 1;
|
||||||
|
if (sscanf (sep, "%s %s", fstype, device) != 2)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (stat (device, &st) < 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!S_ISBLK (st.st_mode))
|
||||||
|
continue; /* not a block device */
|
||||||
|
|
||||||
|
ret = strdup (device);
|
||||||
|
}
|
||||||
|
|
||||||
|
free (buf);
|
||||||
|
fclose (fp);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* __linux__ */
|
||||||
|
|
||||||
#ifdef __MINGW32__
|
#ifdef __MINGW32__
|
||||||
|
|
||||||
static char *
|
static char *
|
||||||
|
@ -366,6 +446,12 @@ grub_guess_root_device (const char *dir)
|
||||||
#else /* !__GNU__ */
|
#else /* !__GNU__ */
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
|
os_dev = find_root_device_from_mountinfo (dir);
|
||||||
|
if (os_dev)
|
||||||
|
return os_dev;
|
||||||
|
#endif /* __linux__ */
|
||||||
|
|
||||||
if (stat (dir, &st) < 0)
|
if (stat (dir, &st) < 0)
|
||||||
grub_util_error ("cannot stat `%s'", dir);
|
grub_util_error ("cannot stat `%s'", dir);
|
||||||
|
|
||||||
|
|
|
@ -413,7 +413,11 @@ devmapper_fail:
|
||||||
if (fd == -1)
|
if (fd == -1)
|
||||||
{
|
{
|
||||||
grub_error (GRUB_ERR_BAD_DEVICE,
|
grub_error (GRUB_ERR_BAD_DEVICE,
|
||||||
|
# if !defined(__NetBSD__)
|
||||||
"cannot open `%s' while attempting to get disk geometry", dev);
|
"cannot open `%s' while attempting to get disk geometry", dev);
|
||||||
|
# else /* defined(__NetBSD__) */
|
||||||
|
"cannot open `%s' while attempting to get disk label", dev);
|
||||||
|
# endif /* !defined(__NetBSD__) */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -425,7 +429,11 @@ devmapper_fail:
|
||||||
# endif /* !defined(__NetBSD__) */
|
# endif /* !defined(__NetBSD__) */
|
||||||
{
|
{
|
||||||
grub_error (GRUB_ERR_BAD_DEVICE,
|
grub_error (GRUB_ERR_BAD_DEVICE,
|
||||||
|
# if !defined(__NetBSD__)
|
||||||
"cannot get disk geometry of `%s'", dev);
|
"cannot get disk geometry of `%s'", dev);
|
||||||
|
# else /* defined(__NetBSD__) */
|
||||||
|
"cannot get disk label of `%s'", dev);
|
||||||
|
# endif /* !defined(__NetBSD__) */
|
||||||
close (fd);
|
close (fd);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1256,22 +1264,28 @@ devmapper_out:
|
||||||
return path;
|
return path;
|
||||||
|
|
||||||
#elif defined(__NetBSD__)
|
#elif defined(__NetBSD__)
|
||||||
/* NetBSD uses "/dev/r[wsc]d[0-9]+[a-z]". */
|
/* NetBSD uses "/dev/r[a-z]+[0-9][a-z]". */
|
||||||
char *path = xstrdup (os_dev);
|
char *path = xstrdup (os_dev);
|
||||||
if (strncmp ("/dev/rwd", path, 8) == 0 ||
|
if (strncmp ("/dev/r", path, sizeof("/dev/r") - 1) == 0 &&
|
||||||
strncmp ("/dev/rsd", path, 8) == 0 ||
|
(path[sizeof("/dev/r") - 1] >= 'a' && path[sizeof("/dev/r") - 1] <= 'z') &&
|
||||||
strncmp ("/dev/rcd", path, 8) == 0)
|
strncmp ("fd", path + sizeof("/dev/r") - 1, sizeof("fd") - 1) != 0) /* not a floppy device name */
|
||||||
{
|
{
|
||||||
char *q;
|
char *p;
|
||||||
q = path + strlen(path) - 1; /* last character */
|
for (p = path + sizeof("/dev/r"); *p >= 'a' && *p <= 'z'; p++);
|
||||||
if (grub_isalpha(*q) && grub_isdigit(*(q-1)))
|
if (grub_isdigit(*p))
|
||||||
{
|
{
|
||||||
|
p++;
|
||||||
|
if ((*p >= 'a' && *p <= 'z') && (*(p+1) == '\0'))
|
||||||
|
{
|
||||||
|
/* path matches the required regular expression and
|
||||||
|
p points to its last character. */
|
||||||
int rawpart = -1;
|
int rawpart = -1;
|
||||||
# ifdef HAVE_GETRAWPARTITION
|
# ifdef HAVE_GETRAWPARTITION
|
||||||
rawpart = getrawpartition();
|
rawpart = getrawpartition();
|
||||||
# endif /* HAVE_GETRAWPARTITION */
|
# endif /* HAVE_GETRAWPARTITION */
|
||||||
if (rawpart >= 0)
|
if (rawpart >= 0)
|
||||||
*q = 'a' + rawpart;
|
*p = 'a' + rawpart;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return path;
|
return path;
|
||||||
|
@ -1429,8 +1443,7 @@ grub_util_biosdisk_get_grub_dev (const char *os_dev)
|
||||||
return name;
|
return name;
|
||||||
# else /* defined(__NetBSD__) */
|
# else /* defined(__NetBSD__) */
|
||||||
/* Since os_dev and convert_system_partition_to_system_disk (os_dev) are
|
/* Since os_dev and convert_system_partition_to_system_disk (os_dev) are
|
||||||
* different, we know that os_dev is of the form /dev/r[wsc]d[0-9]+[a-z]
|
* different, we know that os_dev cannot be a floppy device. */
|
||||||
* and in particular it cannot be a floppy device. */
|
|
||||||
# endif /* !defined(__NetBSD__) */
|
# endif /* !defined(__NetBSD__) */
|
||||||
|
|
||||||
start = find_partition_start (os_dev);
|
start = find_partition_start (os_dev);
|
||||||
|
|
|
@ -180,6 +180,7 @@ kernel = {
|
||||||
mips_yeeloong = video/bitmap.c;
|
mips_yeeloong = video/bitmap.c;
|
||||||
mips_yeeloong = video/bitmap_scale.c;
|
mips_yeeloong = video/bitmap_scale.c;
|
||||||
mips_yeeloong = video/sm712.c;
|
mips_yeeloong = video/sm712.c;
|
||||||
|
mips_yeeloong = bus/cs5536.c;
|
||||||
|
|
||||||
powerpc_ieee1275 = kern/powerpc/ieee1275/startup.S;
|
powerpc_ieee1275 = kern/powerpc/ieee1275/startup.S;
|
||||||
powerpc_ieee1275 = kern/ieee1275/cmain.c;
|
powerpc_ieee1275 = kern/ieee1275/cmain.c;
|
||||||
|
@ -311,6 +312,12 @@ module = {
|
||||||
common;
|
common;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
module = {
|
||||||
|
name = cs5536;
|
||||||
|
source = bus/cs5536.c;
|
||||||
|
i386;
|
||||||
|
};
|
||||||
|
|
||||||
module = {
|
module = {
|
||||||
name = libusb;
|
name = libusb;
|
||||||
source = bus/usb/emu/usb.c;
|
source = bus/usb/emu/usb.c;
|
||||||
|
@ -332,6 +339,7 @@ module = {
|
||||||
source = bus/usb/usbtrans.c;
|
source = bus/usb/usbtrans.c;
|
||||||
source = bus/usb/usbhub.c;
|
source = bus/usb/usbhub.c;
|
||||||
i386;
|
i386;
|
||||||
|
mips_yeeloong;
|
||||||
};
|
};
|
||||||
|
|
||||||
module = {
|
module = {
|
||||||
|
@ -351,6 +359,7 @@ module = {
|
||||||
name = ohci;
|
name = ohci;
|
||||||
source = bus/usb/ohci.c;
|
source = bus/usb/ohci.c;
|
||||||
x86;
|
x86;
|
||||||
|
mips_yeeloong;
|
||||||
};
|
};
|
||||||
|
|
||||||
module = {
|
module = {
|
||||||
|
@ -703,6 +712,7 @@ module = {
|
||||||
name = usbtest;
|
name = usbtest;
|
||||||
source = commands/usbtest.c;
|
source = commands/usbtest.c;
|
||||||
i386_pc;
|
i386_pc;
|
||||||
|
mips_yeeloong;
|
||||||
};
|
};
|
||||||
|
|
||||||
module = {
|
module = {
|
||||||
|
@ -813,6 +823,7 @@ module = {
|
||||||
name = usbms;
|
name = usbms;
|
||||||
source = disk/usbms.c;
|
source = disk/usbms.c;
|
||||||
i386_pc;
|
i386_pc;
|
||||||
|
mips_yeeloong;
|
||||||
};
|
};
|
||||||
|
|
||||||
module = {
|
module = {
|
||||||
|
@ -1522,6 +1533,7 @@ module = {
|
||||||
name = usb_keyboard;
|
name = usb_keyboard;
|
||||||
source = term/usb_keyboard.c;
|
source = term/usb_keyboard.c;
|
||||||
i386_pc;
|
i386_pc;
|
||||||
|
mips_yeeloong;
|
||||||
};
|
};
|
||||||
|
|
||||||
module = {
|
module = {
|
||||||
|
|
|
@ -18,7 +18,6 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <grub/term.h>
|
#include <grub/term.h>
|
||||||
#include <grub/machine/console.h>
|
|
||||||
#include <grub/time.h>
|
#include <grub/time.h>
|
||||||
#include <grub/cpu/io.h>
|
#include <grub/cpu/io.h>
|
||||||
#include <grub/misc.h>
|
#include <grub/misc.h>
|
||||||
|
|
|
@ -107,7 +107,7 @@ prepare_grub_to_access_device ()
|
||||||
|
|
||||||
partmap="`${grub_probe} --device ${device} --target=partmap`"
|
partmap="`${grub_probe} --device ${device} --target=partmap`"
|
||||||
for module in ${partmap} ; do
|
for module in ${partmap} ; do
|
||||||
echo "insmod ${module}"
|
echo "insmod part_${module}"
|
||||||
done
|
done
|
||||||
|
|
||||||
fs="`${grub_probe} --device ${device} --target=fs`"
|
fs="`${grub_probe} --device ${device} --target=fs`"
|
||||||
|
|
|
@ -1254,7 +1254,7 @@ main (int argc, char *argv[])
|
||||||
image_target = &image_targets[i];
|
image_target = &image_targets[i];
|
||||||
if (!image_target)
|
if (!image_target)
|
||||||
{
|
{
|
||||||
printf ("unknown target %s\n", optarg);
|
printf ("unknown target format %s\n", optarg);
|
||||||
usage (1);
|
usage (1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -1323,7 +1323,7 @@ main (int argc, char *argv[])
|
||||||
|
|
||||||
if (!image_target)
|
if (!image_target)
|
||||||
{
|
{
|
||||||
printf ("Target not specified.\n");
|
printf ("Target format not specified (use the -O option).\n");
|
||||||
usage (1);
|
usage (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -82,7 +82,7 @@ hexify (char *hex, grub_uint8_t *bin, grub_size_t n)
|
||||||
int
|
int
|
||||||
main (int argc, char *argv[])
|
main (int argc, char *argv[])
|
||||||
{
|
{
|
||||||
unsigned int c = 10000, buflen = 64, saltlen = 64;
|
unsigned int count = 10000, buflen = 64, saltlen = 64;
|
||||||
char *pass1, *pass2;
|
char *pass1, *pass2;
|
||||||
char *bufhex, *salthex;
|
char *bufhex, *salthex;
|
||||||
gcry_err_code_t gcry_err;
|
gcry_err_code_t gcry_err;
|
||||||
|
@ -107,7 +107,7 @@ main (int argc, char *argv[])
|
||||||
switch (c)
|
switch (c)
|
||||||
{
|
{
|
||||||
case 'c':
|
case 'c':
|
||||||
c = strtoul (optarg, NULL, 0);
|
count = strtoul (optarg, NULL, 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'l':
|
case 'l':
|
||||||
|
@ -277,7 +277,7 @@ main (int argc, char *argv[])
|
||||||
gcry_err = grub_crypto_pbkdf2 (GRUB_MD_SHA512,
|
gcry_err = grub_crypto_pbkdf2 (GRUB_MD_SHA512,
|
||||||
(grub_uint8_t *) pass1, strlen (pass1),
|
(grub_uint8_t *) pass1, strlen (pass1),
|
||||||
salt, saltlen,
|
salt, saltlen,
|
||||||
c, buf, buflen);
|
count, buf, buflen);
|
||||||
memset (pass1, 0, strlen (pass1));
|
memset (pass1, 0, strlen (pass1));
|
||||||
free (pass1);
|
free (pass1);
|
||||||
|
|
||||||
|
@ -297,7 +297,8 @@ main (int argc, char *argv[])
|
||||||
hexify (bufhex, buf, buflen);
|
hexify (bufhex, buf, buflen);
|
||||||
hexify (salthex, salt, saltlen);
|
hexify (salthex, salt, saltlen);
|
||||||
|
|
||||||
printf ("Your PBKDF2 is grub.pbkdf2.sha512.%d.%s.%s\n", c, salthex, bufhex);
|
printf ("Your PBKDF2 is grub.pbkdf2.sha512.%d.%s.%s\n",
|
||||||
|
count, salthex, bufhex);
|
||||||
memset (buf, 0, buflen);
|
memset (buf, 0, buflen);
|
||||||
memset (bufhex, 0, 2 * buflen);
|
memset (bufhex, 0, 2 * buflen);
|
||||||
free (buf);
|
free (buf);
|
||||||
|
|
|
@ -61,8 +61,8 @@ set default="${GRUB_DEFAULT}"
|
||||||
EOF
|
EOF
|
||||||
fi
|
fi
|
||||||
cat <<EOF
|
cat <<EOF
|
||||||
if [ \${prev_saved_entry} ]; then
|
if [ "\${prev_saved_entry}" ]; then
|
||||||
set saved_entry=\${prev_saved_entry}
|
set saved_entry="\${prev_saved_entry}"
|
||||||
save_env saved_entry
|
save_env saved_entry
|
||||||
set prev_saved_entry=
|
set prev_saved_entry=
|
||||||
save_env prev_saved_entry
|
save_env prev_saved_entry
|
||||||
|
@ -70,8 +70,8 @@ if [ \${prev_saved_entry} ]; then
|
||||||
fi
|
fi
|
||||||
|
|
||||||
function savedefault {
|
function savedefault {
|
||||||
if [ -z \${boot_once} ]; then
|
if [ -z "\${boot_once}" ]; then
|
||||||
saved_entry=\${chosen}
|
saved_entry="\${chosen}"
|
||||||
save_env saved_entry
|
save_env saved_entry
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
@ -195,7 +195,7 @@ EOF
|
||||||
esac
|
esac
|
||||||
|
|
||||||
# Gettext variables and module
|
# Gettext variables and module
|
||||||
if [ "x${LANG}" != "xC" ] ; then
|
if [ "x${LANG}" != "xC" ] && [ -d "${locale_dir}" ] ; then
|
||||||
prepare_grub_to_access_device $(${grub_probe} --target=device ${locale_dir})
|
prepare_grub_to_access_device $(${grub_probe} --target=device ${locale_dir})
|
||||||
cat << EOF
|
cat << EOF
|
||||||
set locale_dir=(\$root)$(make_system_path_relative_to_its_root ${locale_dir})
|
set locale_dir=(\$root)$(make_system_path_relative_to_its_root ${locale_dir})
|
||||||
|
|
Loading…
Reference in a new issue