diff options
author | Linaro Packagers <linaro-pkg@lists.launchpad.net> | 2013-03-22 00:15:54 +0000 |
---|---|---|
committer | Fathi Boudra <fathi.boudra@linaro.org> | 2013-03-30 17:41:16 +0200 |
commit | f669aab440f422bab26c810579760b9d95b1c018 (patch) | |
tree | 3ed8554363cc3cc2fb78523787b5a8be494858a5 /grub-core | |
parent | a658a0c5e3a4fe5c61fc9ae26417a33e0f69efff (diff) | |
parent | e7f59a65345484ede230500400b774db8c9a6d6f (diff) |
Imported Debian patch 2.00+bzr4618+20130322-0linaro1HEADdebian/2.00+bzr4618+20130322-0linaro1master
Diffstat (limited to 'grub-core')
35 files changed, 1446 insertions, 310 deletions
diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am index 5624f9e..6fa0a14 100644 --- a/grub-core/Makefile.am +++ b/grub-core/Makefile.am @@ -98,29 +98,30 @@ if COND_i386_pc KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/kernel.h KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/pxe.h KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/int.h -KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/pit.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/tsc.h endif if COND_i386_efi KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/efi.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/disk.h -KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/pit.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/tsc.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/pci.h endif if COND_i386_coreboot -KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/pit.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/tsc.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/coreboot/lbio.h KERNEL_HEADER_FILES += $(top_builddir)/include/grub/i386/pc/int.h endif if COND_i386_multiboot -KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/pit.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/tsc.h KERNEL_HEADER_FILES += $(top_builddir)/include/grub/i386/pc/int.h endif if COND_i386_qemu KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/pci.h -KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/pit.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/tsc.h endif if COND_i386_ieee1275 @@ -128,13 +129,13 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ieee1275/ieee1275.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/terminfo.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/lib/arg.h -KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/pit.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/tsc.h endif if COND_x86_64_efi KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/efi.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/disk.h -KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/pit.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/tsc.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/pci.h endif @@ -143,11 +144,6 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/efi.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/disk.h endif -if COND_arm_uboot -KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/uboot/uboot.h -KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/uboot/disk.h -endif - if COND_mips KERNEL_HEADER_FILES += $(top_builddir)/include/grub/cpu/kernel.h endif @@ -215,6 +211,13 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/lib/arg.h endif +if COND_arm_uboot +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/uboot/uboot.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/uboot/disk.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/lib/arg.h +endif + if COND_emu KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/datetime.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/emu/misc.h diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 6bdd53c..dce64f9 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -106,7 +106,6 @@ kernel = { noemu_nodist = symlist.c; - i386_pc = kern/generic/rtc_get_time_ms.c; mips = kern/generic/rtc_get_time_ms.c; ieee1275 = disk/ieee1275/ofdisk.c; @@ -127,8 +126,6 @@ kernel = { i386_coreboot_multiboot_qemu = kern/i386/coreboot/init.c; i386_coreboot_multiboot_qemu = term/i386/pc/vga_text.c; - x86 = kern/i386/pit.c; - efi = disk/efi/efidisk.c; efi = kern/efi/efi.c; efi = kern/efi/init.c; @@ -461,6 +458,12 @@ module = { }; module = { + name = usbserial_usbdebug; + common = bus/usb/serial/usbdebug_late.c; + enable = usb; +}; + +module = { name = uhci; common = bus/usb/uhci.c; enable = x86; @@ -517,12 +520,36 @@ module = { }; module = { + name = cmosdump; + common = commands/i386/cmosdump.c; + enable = cmos; +}; + +module = { name = iorw; common = commands/iorw.c; enable = x86; }; module = { + name = cbtime; + common = commands/i386/coreboot/cb_timestamps.c; + enable = i386_coreboot; +}; + +module = { + name = cbls; + common = commands/i386/coreboot/cbls.c; + enable = i386_coreboot; +}; + +module = { + name = cbmemc; + common = term/i386/coreboot/cbmemc.c; + enable = i386_coreboot; +}; + +module = { name = regexp; common = commands/regexp.c; common = commands/wildcard.c; @@ -608,8 +635,6 @@ module = { module = { name = cat; common = commands/cat.c; - arm_uboot = lib/arg.c; - arm_uboot = commands/extcmd.c; }; module = { @@ -1397,9 +1422,9 @@ module = { module = { name = linux16; - i386_pc = loader/i386/pc/linux.c; - i386_pc = lib/cmdline.c; - enable = i386_pc; + common = loader/i386/pc/linux.c; + common = lib/cmdline.c; + enable = x86; }; module = { @@ -1883,6 +1908,12 @@ module = { }; module = { + name = boottime; + common = commands/boottime.c; + condition = COND_ENABLE_BOOT_TIME_STATS; +}; + +module = { name = adler32; common = lib/adler32.c; }; diff --git a/grub-core/bus/usb/ehci.c b/grub-core/bus/usb/ehci.c index 9215866..41d29cb 100644 --- a/grub-core/bus/usb/ehci.c +++ b/grub-core/bus/usb/ehci.c @@ -715,6 +715,7 @@ grub_ehci_pci_iter (grub_pci_device_t dev, grub_pci_id_t pciid, usblegsup = grub_pci_read (pciaddr_eecp); if (usblegsup & GRUB_EHCI_BIOS_OWNED) { + grub_boot_time ("Taking ownership of EHCI port"); grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: EHCI owned by: BIOS\n"); /* Ownership change - set OS_OWNED bit */ @@ -741,6 +742,7 @@ grub_ehci_pci_iter (grub_pci_device_t dev, grub_pci_id_t pciid, /* Ensure PCI register is written */ grub_pci_read (pciaddr_eecp); } + grub_boot_time ("Ownership of EHCI port taken"); } else if (usblegsup & GRUB_EHCI_OS_OWNED) /* XXX: What to do in this case - nothing ? Can it happen ? */ @@ -1697,6 +1699,8 @@ grub_ehci_portstatus (grub_usb_controller_t dev, grub_dprintf ("ehci", "portstatus: enable\n"); + grub_boot_time ("Resetting port %d", port); + /* Now we will do reset - if HIGH speed device connected, it will * result in Enabled state, otherwise port remains disabled. */ /* Set RESET bit for 50ms */ @@ -1710,6 +1714,7 @@ grub_ehci_portstatus (grub_usb_controller_t dev, if (grub_get_time_ms () > endtime) return grub_error (GRUB_ERR_IO, "portstatus: EHCI Timed out - reset port"); + grub_boot_time ("Port %d reset", port); /* Remember "we did the reset" - needed by detect_dev */ e->reset |= (1 << port); /* Test if port enabled, i.e. HIGH speed device connected */ @@ -1909,8 +1914,11 @@ GRUB_MOD_INIT (ehci) { COMPILE_TIME_ASSERT (sizeof (struct grub_ehci_td) == 64); COMPILE_TIME_ASSERT (sizeof (struct grub_ehci_qh) == 96); + grub_boot_time ("Initing EHCI hardware"); grub_ehci_inithw (); + grub_boot_time ("Registering EHCI driver"); grub_usb_controller_dev_register (&usb_controller); + grub_boot_time ("EHCI driver registered"); grub_loader_register_preboot_hook (grub_ehci_fini_hw, grub_ehci_restore_hw, GRUB_LOADER_PREBOOT_HOOK_PRIO_DISK); } diff --git a/grub-core/bus/usb/serial/common.c b/grub-core/bus/usb/serial/common.c index 55d1884..8e94c7d 100644 --- a/grub-core/bus/usb/serial/common.c +++ b/grub-core/bus/usb/serial/common.c @@ -42,7 +42,8 @@ static int usbnum = 0; int grub_usbserial_attach (grub_usb_device_t usbdev, int configno, int interfno, - struct grub_serial_driver *driver) + struct grub_serial_driver *driver, int in_endp, + int out_endp) { struct grub_serial_port *port; int j; @@ -51,7 +52,7 @@ grub_usbserial_attach (grub_usb_device_t usbdev, int configno, int interfno, interf = usbdev->config[configno].interf[interfno].descif; - port = grub_malloc (sizeof (*port)); + port = grub_zalloc (sizeof (*port)); if (!port) { grub_print_error (); @@ -73,12 +74,16 @@ grub_usbserial_attach (grub_usb_device_t usbdev, int configno, int interfno, struct grub_usb_desc_endp *endp; endp = &usbdev->config[0].interf[interfno].descendp[j]; - if ((endp->endp_addr & 128) && (endp->attrib & 3) == 2) + if ((endp->endp_addr & 128) && (endp->attrib & 3) == 2 + && (in_endp == GRUB_USB_SERIAL_ENDPOINT_LAST_MATCHING + || in_endp == endp->endp_addr)) { /* Bulk IN endpoint. */ port->in_endp = endp; } - else if (!(endp->endp_addr & 128) && (endp->attrib & 3) == 2) + else if (!(endp->endp_addr & 128) && (endp->attrib & 3) == 2 + && (out_endp == GRUB_USB_SERIAL_ENDPOINT_LAST_MATCHING + || out_endp == endp->endp_addr)) { /* Bulk OUT endpoint. */ port->out_endp = endp; @@ -119,7 +124,7 @@ grub_usbserial_fetch (struct grub_serial_port *port, grub_size_t header_size) if (port->bufstart < port->bufend) return port->buf[port->bufstart++]; - err = grub_usb_bulk_read_extended (port->usbdev, port->in_endp->endp_addr, + err = grub_usb_bulk_read_extended (port->usbdev, port->in_endp, sizeof (port->buf), port->buf, 10, &actual); if (err != GRUB_USB_ERR_NONE) diff --git a/grub-core/bus/usb/serial/ftdi.c b/grub-core/bus/usb/serial/ftdi.c index 15ea8fb..25c1d6f 100644 --- a/grub-core/bus/usb/serial/ftdi.c +++ b/grub-core/bus/usb/serial/ftdi.c @@ -128,7 +128,7 @@ ftdi_hw_put (struct grub_serial_port *port, const int c) real_config (port); - grub_usb_bulk_write (port->usbdev, port->out_endp->endp_addr, 1, &cc); + grub_usb_bulk_write (port->usbdev, port->out_endp, 1, &cc); } static grub_err_t @@ -193,7 +193,9 @@ grub_ftdi_attach (grub_usb_device_t usbdev, int configno, int interfno) return 0; return grub_usbserial_attach (usbdev, configno, interfno, - &grub_ftdi_driver); + &grub_ftdi_driver, + GRUB_USB_SERIAL_ENDPOINT_LAST_MATCHING, + GRUB_USB_SERIAL_ENDPOINT_LAST_MATCHING); } static struct grub_usb_attach_desc attach_hook = diff --git a/grub-core/bus/usb/serial/pl2303.c b/grub-core/bus/usb/serial/pl2303.c index 5433763..92b00ef 100644 --- a/grub-core/bus/usb/serial/pl2303.c +++ b/grub-core/bus/usb/serial/pl2303.c @@ -146,7 +146,7 @@ pl2303_hw_put (struct grub_serial_port *port, const int c) real_config (port); - grub_usb_bulk_write (port->usbdev, port->out_endp->endp_addr, 1, &cc); + grub_usb_bulk_write (port->usbdev, port->out_endp, 1, &cc); } static grub_err_t @@ -208,7 +208,9 @@ grub_pl2303_attach (grub_usb_device_t usbdev, int configno, int interfno) return 0; return grub_usbserial_attach (usbdev, configno, interfno, - &grub_pl2303_driver); + &grub_pl2303_driver, + GRUB_USB_SERIAL_ENDPOINT_LAST_MATCHING, + GRUB_USB_SERIAL_ENDPOINT_LAST_MATCHING); } static struct grub_usb_attach_desc attach_hook = diff --git a/grub-core/bus/usb/serial/usbdebug_late.c b/grub-core/bus/usb/serial/usbdebug_late.c new file mode 100644 index 0000000..e88ba13 --- /dev/null +++ b/grub-core/bus/usb/serial/usbdebug_late.c @@ -0,0 +1,93 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2000,2001,2002,2003,2004,2005,2007,2008,2009,2010,2013 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/serial.h> +#include <grub/types.h> +#include <grub/dl.h> +#include <grub/misc.h> +#include <grub/mm.h> +#include <grub/usb.h> +#include <grub/usbserial.h> +#include <grub/i18n.h> + +GRUB_MOD_LICENSE ("GPLv3+"); + + +/* Fetch a key. */ +static int +usbdebug_late_hw_fetch (struct grub_serial_port *port) +{ + return grub_usbserial_fetch (port, 0); +} + +/* Put a character. */ +static void +usbdebug_late_hw_put (struct grub_serial_port *port, const int c) +{ + char cc = c; + + grub_usb_bulk_write (port->usbdev, port->out_endp, 1, &cc); +} + +static grub_err_t +usbdebug_late_hw_configure (struct grub_serial_port *port __attribute__ ((unused)), + struct grub_serial_config *config __attribute__ ((unused))) +{ + return GRUB_ERR_NONE; +} + +static struct grub_serial_driver grub_usbdebug_late_driver = + { + .configure = usbdebug_late_hw_configure, + .fetch = usbdebug_late_hw_fetch, + .put = usbdebug_late_hw_put, + .fini = grub_usbserial_fini + }; + +static int +grub_usbdebug_late_attach (grub_usb_device_t usbdev, int configno, int interfno) +{ + grub_usb_err_t err; + struct grub_usb_desc_debug debugdesc; + + err = grub_usb_get_descriptor (usbdev, GRUB_USB_DESCRIPTOR_DEBUG, configno, + sizeof (debugdesc), (char *) &debugdesc); + if (err) + return 0; + + return grub_usbserial_attach (usbdev, configno, interfno, + &grub_usbdebug_late_driver, + debugdesc.in_endp, debugdesc.out_endp); +} + +static struct grub_usb_attach_desc attach_hook = +{ + .class = 0xff, + .hook = grub_usbdebug_late_attach +}; + +GRUB_MOD_INIT(usbserial_usbdebug_late) +{ + grub_usb_register_attach_hook_class (&attach_hook); +} + +GRUB_MOD_FINI(usbserial_usbdebug_late) +{ + grub_serial_unregister_driver (&grub_usbdebug_late_driver); + grub_usb_unregister_attach_hook_class (&attach_hook); +} diff --git a/grub-core/bus/usb/usb.c b/grub-core/bus/usb/usb.c index 6fbf134..024190e 100644 --- a/grub-core/bus/usb/usb.c +++ b/grub-core/bus/usb/usb.c @@ -26,46 +26,8 @@ GRUB_MOD_LICENSE ("GPLv3+"); -static grub_usb_controller_dev_t grub_usb_list; static struct grub_usb_attach_desc *attach_hooks; -/* Iterate over all controllers found by the driver. */ -static int -grub_usb_controller_dev_register_iter (grub_usb_controller_t dev, void *data) -{ - grub_usb_controller_dev_t usb = data; - - dev->dev = usb; - - /* Enable the ports of the USB Root Hub. */ - grub_usb_root_hub (dev); - - return 0; -} - -void -grub_usb_controller_dev_register (grub_usb_controller_dev_t usb) -{ - usb->next = grub_usb_list; - grub_usb_list = usb; - - if (usb->iterate) - usb->iterate (grub_usb_controller_dev_register_iter, usb); -} - -void -grub_usb_controller_dev_unregister (grub_usb_controller_dev_t usb) -{ - grub_usb_controller_dev_t *p, q; - - for (p = &grub_usb_list, q = *p; q; p = &(q->next), q = q->next) - if (q == usb) - { - *p = q->next; - break; - } -} - #if 0 /* Context for grub_usb_controller_iterate. */ struct grub_usb_controller_iterate_ctx @@ -147,31 +109,6 @@ grub_usb_get_descriptor (grub_usb_device_t dev, 0, size, data); } -struct grub_usb_desc_endp * -grub_usb_get_endpdescriptor (grub_usb_device_t usbdev, int addr) -{ - int i; - - for (i = 0; i < usbdev->config[0].descconf->numif; i++) - { - struct grub_usb_desc_if *interf; - int j; - - interf = usbdev->config[0].interf[i].descif; - - for (j = 0; j < interf->endpointcnt; j++) - { - struct grub_usb_desc_endp *endp; - endp = &usbdev->config[0].interf[i].descendp[j]; - - if (endp->endp_addr == addr) - return endp; - } - } - - return NULL; -} - grub_usb_err_t grub_usb_device_initialize (grub_usb_device_t dev) { @@ -287,8 +224,13 @@ void grub_usb_device_attach (grub_usb_device_t dev) continue; for (desc = attach_hooks; desc; desc = desc->next) - if (interf->class == desc->class && desc->hook (dev, 0, i)) - dev->config[0].interf[i].attached = 1; + if (interf->class == desc->class) + { + grub_boot_time ("Probing USB device driver class %x", desc->class); + if (desc->hook (dev, 0, i)) + dev->config[0].interf[i].attached = 1; + grub_boot_time ("Probed USB device driver class %x", desc->class); + } if (dev->config[0].interf[i].attached) continue; @@ -297,14 +239,20 @@ void grub_usb_device_attach (grub_usb_device_t dev) { case GRUB_USB_CLASS_MASS_STORAGE: grub_dl_load ("usbms"); + grub_print_error (); break; case GRUB_USB_CLASS_HID: grub_dl_load ("usb_keyboard"); + grub_print_error (); break; case 0xff: /* FIXME: don't load useless modules. */ grub_dl_load ("usbserial_ftdi"); + grub_print_error (); grub_dl_load ("usbserial_pl2303"); + grub_print_error (); + grub_dl_load ("usbserial_usbdebug"); + grub_print_error (); break; } } diff --git a/grub-core/bus/usb/usbhub.c b/grub-core/bus/usb/usbhub.c index 3927f51..6fc9d02 100644 --- a/grub-core/bus/usb/usbhub.c +++ b/grub-core/bus/usb/usbhub.c @@ -29,6 +29,7 @@ static struct grub_usb_device *grub_usb_devs[GRUB_USBHUB_MAX_DEVICES]; static int rescan = 0; +static int npending = 0; struct grub_usb_hub { @@ -36,10 +37,12 @@ struct grub_usb_hub grub_usb_controller_t controller; int nports; struct grub_usb_device **devices; + struct grub_usb_hub_port *ports; grub_usb_device_t dev; }; static struct grub_usb_hub *hubs; +static grub_usb_controller_dev_t grub_usb_list; /* Add a device that currently has device number 0 and resides on CONTROLLER, the Hub reported that the device speed is SPEED. */ @@ -52,6 +55,8 @@ grub_usb_hub_add_dev (grub_usb_controller_t controller, int i; grub_usb_err_t err; + grub_boot_time ("Attaching USB device"); + dev = grub_zalloc (sizeof (struct grub_usb_device)); if (! dev) return NULL; @@ -108,8 +113,12 @@ grub_usb_hub_add_dev (grub_usb_controller_t controller, /* Wait "recovery interval", spec. says 2ms */ grub_millisleep (2); + + grub_boot_time ("Probing USB device driver"); grub_usb_device_attach (dev); + + grub_boot_time ("Attached USB device"); return dev; } @@ -139,10 +148,15 @@ grub_usb_add_hub (grub_usb_device_t dev) grub_dprintf ("usb", "Hub set configuration\n"); grub_usb_set_configuration (dev, 1); - dev->children = grub_zalloc (hubdesc.portcnt * sizeof (dev->children[0])); - if (!dev->children) - return GRUB_USB_ERR_INTERNAL; dev->nports = hubdesc.portcnt; + dev->children = grub_zalloc (hubdesc.portcnt * sizeof (dev->children[0])); + dev->ports = grub_zalloc (dev->nports * sizeof (dev->ports[0])); + if (!dev->children || !dev->ports) + { + grub_free (dev->children); + grub_free (dev->ports); + return GRUB_USB_ERR_INTERNAL; + } /* Power on all Hub ports. */ for (i = 1; i <= hubdesc.portcnt; i++) @@ -173,7 +187,7 @@ grub_usb_add_hub (grub_usb_device_t dev) if (len > sizeof (dev->statuschange)) len = sizeof (dev->statuschange); dev->hub_transfer - = grub_usb_bulk_read_background (dev, endp->endp_addr, len, + = grub_usb_bulk_read_background (dev, endp, len, (char *) &dev->statuschange); break; } @@ -190,47 +204,24 @@ attach_root_port (struct grub_usb_hub *hub, int portno, { grub_usb_device_t dev; grub_err_t err; - int total, i; - grub_usb_speed_t current_speed = GRUB_USB_SPEED_NONE; - int changed=0; - -#if 0 -/* Specification does not say about disabling of port when device - * connected. If disabling is really necessary for some devices, - * delete this #if 0 and related #endif */ - /* Disable the port. XXX: Why? */ - err = hub->controller->dev->portstatus (hub->controller, portno, 0); - if (err) - return; -#endif - /* Wait for completion of insertion and stable power (USB spec.) - * Should be at least 100ms, some devices requires more... - * There is also another thing - some devices have worse contacts - * and connected signal is unstable for some time - we should handle - * it - but prevent deadlock in case when device is too faulty... */ - for (total = i = 0; (i < 250) && (total < 2000); i++, total++) - { - grub_millisleep (1); - current_speed = hub->controller->dev->detect_dev - (hub->controller, portno, &changed); - if (current_speed == GRUB_USB_SPEED_NONE) - i = 0; - } - grub_dprintf ("usb", "total=%d\n", total); - if (total >= 2000) - return; + + grub_boot_time ("After detect_dev"); /* Enable the port. */ err = hub->controller->dev->portstatus (hub->controller, portno, 1); if (err) return; hub->controller->dev->pending_reset = grub_get_time_ms () + 5000; + npending++; grub_millisleep (10); + grub_boot_time ("Port enabled"); + /* Enable the port and create a device. */ dev = grub_usb_hub_add_dev (hub->controller, speed, portno, 0); hub->controller->dev->pending_reset = 0; + npending--; if (! dev) return; @@ -239,14 +230,20 @@ attach_root_port (struct grub_usb_hub *hub, int portno, /* If the device is a Hub, scan it for more devices. */ if (dev->descdev.class == 0x09) grub_usb_add_hub (dev); + + grub_boot_time ("Attached root port"); } -grub_usb_err_t -grub_usb_root_hub (grub_usb_controller_t controller) +/* Iterate over all controllers found by the driver. */ +static int +grub_usb_controller_dev_register_iter (grub_usb_controller_t controller, void *data) { - int i; + grub_usb_controller_dev_t usb = data; struct grub_usb_hub *hub; - int changed=0; + + controller->dev = usb; + + grub_boot_time ("Registering USB root hub"); hub = grub_malloc (sizeof (*hub)); if (!hub) @@ -267,27 +264,122 @@ grub_usb_root_hub (grub_usb_controller_t controller) /* Query the number of ports the root Hub has. */ hub->nports = controller->dev->hubports (controller); hub->devices = grub_zalloc (sizeof (hub->devices[0]) * hub->nports); - if (!hub->devices) + hub->ports = grub_zalloc (sizeof (hub->ports[0]) * hub->nports); + if (!hub->devices || !hub->ports) { + grub_free (hub->devices); + grub_free (hub->ports); grub_free (hub->controller); grub_free (hub); - return GRUB_USB_ERR_INTERNAL; + grub_print_error (); + return 0; } - for (i = 0; i < hub->nports; i++) + return 0; +} + +void +grub_usb_controller_dev_unregister (grub_usb_controller_dev_t usb) +{ + grub_usb_controller_dev_t *p, q; + + for (p = &grub_usb_list, q = *p; q; p = &(q->next), q = q->next) + if (q == usb) + { + *p = q->next; + break; + } +} + +void +grub_usb_controller_dev_register (grub_usb_controller_dev_t usb) +{ + int portno; + int continue_waiting = 0; + struct grub_usb_hub *hub; + + usb->next = grub_usb_list; + grub_usb_list = usb; + + if (usb->iterate) + usb->iterate (grub_usb_controller_dev_register_iter, usb); + + grub_boot_time ("waiting for stable power on USB root\n"); + + while (1) { - grub_usb_speed_t speed; - if (!controller->dev->pending_reset) - { - speed = controller->dev->detect_dev (hub->controller, i, - &changed); - - if (speed != GRUB_USB_SPEED_NONE) - attach_root_port (hub, i, speed); - } + for (hub = hubs; hub; hub = hub->next) + if (hub->controller->dev == usb) + { + /* Wait for completion of insertion and stable power (USB spec.) + * Should be at least 100ms, some devices requires more... + * There is also another thing - some devices have worse contacts + * and connected signal is unstable for some time - we should handle + * it - but prevent deadlock in case when device is too faulty... */ + for (portno = 0; portno < hub->nports; portno++) + { + grub_usb_speed_t speed; + int changed = 0; + + speed = hub->controller->dev->detect_dev (hub->controller, portno, + &changed); + + if (hub->ports[portno].state == PORT_STATE_NORMAL + && speed != GRUB_USB_SPEED_NONE) + { + hub->ports[portno].soft_limit_time = grub_get_time_ms () + 250; + hub->ports[portno].hard_limit_time = hub->ports[portno].soft_limit_time + 1750; + hub->ports[portno].state = PORT_STATE_WAITING_FOR_STABLE_POWER; + grub_boot_time ("Scheduling stable power wait for port %p:%d", + usb, portno); + continue_waiting++; + continue; + } + + if (hub->ports[portno].state == PORT_STATE_WAITING_FOR_STABLE_POWER + && speed == GRUB_USB_SPEED_NONE) + { + hub->ports[portno].soft_limit_time = grub_get_time_ms () + 250; + continue; + } + if (hub->ports[portno].state == PORT_STATE_WAITING_FOR_STABLE_POWER + && grub_get_time_ms () > hub->ports[portno].soft_limit_time) + { + hub->ports[portno].state = PORT_STATE_STABLE_POWER; + grub_boot_time ("Got stable power wait for port %p:%d", + usb, portno); + continue_waiting--; + continue; + } + if (hub->ports[portno].state == PORT_STATE_WAITING_FOR_STABLE_POWER + && grub_get_time_ms () > hub->ports[portno].hard_limit_time) + { + hub->ports[portno].state = PORT_STATE_FAILED_DEVICE; + continue_waiting--; + continue; + } + } + } + if (!continue_waiting) + break; + grub_millisleep (1); } - return GRUB_USB_ERR_NONE; + grub_boot_time ("After the stable power wait on USB root"); + + for (hub = hubs; hub; hub = hub->next) + if (hub->controller->dev == usb) + for (portno = 0; portno < hub->nports; portno++) + if (hub->ports[portno].state == PORT_STATE_STABLE_POWER) + { + grub_usb_speed_t speed; + int changed = 0; + hub->ports[portno].state = PORT_STATE_NORMAL; + speed = hub->controller->dev->detect_dev (hub->controller, portno, &changed); + attach_root_port (hub, portno, speed); + } + + grub_boot_time ("USB root hub registered"); } static void detach_device (grub_usb_device_t dev); @@ -319,6 +411,71 @@ detach_device (grub_usb_device_t dev) grub_usb_devs[dev->addr] = 0; } +static int +wait_power_nonroot_hub (grub_usb_device_t dev) +{ + grub_usb_err_t err; + int continue_waiting = 0; + unsigned i; + + for (i = 1; i <= dev->nports; i++) + if (dev->ports[i - 1].state == PORT_STATE_WAITING_FOR_STABLE_POWER) + { + grub_uint64_t tm; + grub_uint32_t current_status = 0; + + /* Get the port status. */ + err = grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_IN + | GRUB_USB_REQTYPE_CLASS + | GRUB_USB_REQTYPE_TARGET_OTHER), + GRUB_USB_REQ_GET_STATUS, + 0, i, + sizeof (current_status), + (char *) ¤t_status); + if (err) + { + dev->ports[i - 1].state = PORT_STATE_FAILED_DEVICE; + continue; + } + tm = grub_get_time_ms (); + if (!(current_status & GRUB_USB_HUB_STATUS_PORT_CONNECTED)) + dev->ports[i - 1].soft_limit_time = tm + 250; + if (tm >= dev->ports[i - 1].soft_limit_time) + { + if (dev->controller.dev->pending_reset) + continue; + /* Now do reset of port. */ + grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_OUT + | GRUB_USB_REQTYPE_CLASS + | GRUB_USB_REQTYPE_TARGET_OTHER), + GRUB_USB_REQ_SET_FEATURE, + GRUB_USB_HUB_FEATURE_PORT_RESET, + i, 0, 0); + dev->ports[i - 1].state = PORT_STATE_NORMAL; + grub_boot_time ("Resetting port %p:%d", dev, i - 1); + + rescan = 1; + /* We cannot reset more than one device at the same time ! + * Resetting more devices together results in very bad + * situation: more than one device has default address 0 + * at the same time !!! + * Additionaly, we cannot perform another reset + * anywhere on the same OHCI controller until + * we will finish addressing of reseted device ! */ + dev->controller.dev->pending_reset = grub_get_time_ms () + 5000; + npending++; + continue; + } + if (tm >= dev->ports[i - 1].hard_limit_time) + { + dev->ports[i - 1].state = PORT_STATE_FAILED_DEVICE; + continue; + } + continue_waiting = 1; + } + return continue_waiting && dev->controller.dev->pending_reset == 0; +} + static void poll_nonroot_hub (grub_usb_device_t dev) { @@ -326,7 +483,6 @@ poll_nonroot_hub (grub_usb_device_t dev) unsigned i; grub_uint8_t changed; grub_size_t actual, len; - int j, total; if (!dev->hub_transfer) return; @@ -342,7 +498,7 @@ poll_nonroot_hub (grub_usb_device_t dev) if (len > sizeof (dev->statuschange)) len = sizeof (dev->statuschange); dev->hub_transfer - = grub_usb_bulk_read_background (dev, dev->hub_endpoint->endp_addr, len, + = grub_usb_bulk_read_background (dev, dev->hub_endpoint, len, (char *) &dev->statuschange); if (err || actual == 0 || changed == 0) @@ -352,9 +508,9 @@ poll_nonroot_hub (grub_usb_device_t dev) for (i = 1; i <= dev->nports; i++) { grub_uint32_t status; - grub_uint32_t current_status = 0; - if (!(changed & (1 << i))) + if (!(changed & (1 << i)) + || dev->ports[i - 1].state == PORT_STATE_WAITING_FOR_STABLE_POWER) continue; /* Get the port status. */ @@ -407,52 +563,19 @@ poll_nonroot_hub (grub_usb_device_t dev) /* Connected and status of connection changed ? */ if (status & GRUB_USB_HUB_STATUS_PORT_CONNECTED) { + grub_boot_time ("Before the stable power wait portno=%d", i); /* A device is actually connected to this port. */ - /* Wait for completion of insertion and stable power (USB spec.) - * Should be at least 100ms, some devices requires more... - * There is also another thing - some devices have worse contacts - * and connected signal is unstable for some time - we should handle - * it - but prevent deadlock in case when device is too faulty... */ - for (total = j = 0; (j < 250) && (total < 2000); j++, total++) - { - grub_millisleep (1); - /* Get the port status. */ - err = grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_IN - | GRUB_USB_REQTYPE_CLASS - | GRUB_USB_REQTYPE_TARGET_OTHER), - GRUB_USB_REQ_GET_STATUS, - 0, i, - sizeof (current_status), - (char *) ¤t_status); - if (err) - { - total = 2000; - break; - } - if (!(current_status & GRUB_USB_HUB_STATUS_PORT_CONNECTED)) - j = 0; - } - grub_dprintf ("usb", "(non-root) total=%d\n", total); - if (total >= 2000) - continue; - - /* Now do reset of port. */ - grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_OUT - | GRUB_USB_REQTYPE_CLASS - | GRUB_USB_REQTYPE_TARGET_OTHER), - GRUB_USB_REQ_SET_FEATURE, - GRUB_USB_HUB_FEATURE_PORT_RESET, - i, 0, 0); - rescan = 1; - /* We cannot reset more than one device at the same time ! - * Resetting more devices together results in very bad - * situation: more than one device has default address 0 - * at the same time !!! - * Additionaly, we cannot perform another reset - * anywhere on the same OHCI controller until - * we will finish addressing of reseted device ! */ - dev->controller.dev->pending_reset = grub_get_time_ms () + 5000; - return; + /* Wait for completion of insertion and stable power (USB spec.) + * Should be at least 100ms, some devices requires more... + * There is also another thing - some devices have worse contacts + * and connected signal is unstable for some time - we should handle + * it - but prevent deadlock in case when device is too faulty... */ + dev->ports[i - 1].soft_limit_time = grub_get_time_ms () + 250; + dev->ports[i - 1].hard_limit_time = dev->ports[i - 1].soft_limit_time + 1750; + dev->ports[i - 1].state = PORT_STATE_WAITING_FOR_STABLE_POWER; + grub_boot_time ("Scheduling stable power wait for port %p:%d", + dev, i - 1); + continue; } } @@ -464,6 +587,8 @@ poll_nonroot_hub (grub_usb_device_t dev) GRUB_USB_REQ_CLEAR_FEATURE, GRUB_USB_HUB_FEATURE_C_PORT_RESET, i, 0, 0); + grub_boot_time ("Port %d reset", i); + if (status & GRUB_USB_HUB_STATUS_PORT_CONNECTED) { grub_usb_speed_t speed; @@ -485,7 +610,11 @@ poll_nonroot_hub (grub_usb_device_t dev) /* Add the device and assign a device address to it. */ next_dev = grub_usb_hub_add_dev (&dev->controller, speed, i, dev->addr); - dev->controller.dev->pending_reset = 0; + if (dev->controller.dev->pending_reset) + { + dev->controller.dev->pending_reset = 0; + npending--; + } if (! next_dev) continue; @@ -500,7 +629,7 @@ poll_nonroot_hub (grub_usb_device_t dev) } void -grub_usb_poll_devices (void) +grub_usb_poll_devices (int wait_for_completion) { struct grub_usb_hub *hub; int i; @@ -514,7 +643,7 @@ grub_usb_poll_devices (void) grub_usb_speed_t speed = GRUB_USB_SPEED_NONE; int changed = 0; - if (!hub->controller->dev->pending_reset) + if (hub->controller->dev->pending_reset) { /* Check for possible timeout */ if (grub_get_time_ms () > hub->controller->dev->pending_reset) @@ -522,6 +651,7 @@ grub_usb_poll_devices (void) /* Something went wrong, reset device was not * addressed properly, timeout happened */ hub->controller->dev->pending_reset = 0; + npending--; speed = hub->controller->dev->detect_dev (hub->controller, i, &changed); } @@ -548,11 +678,26 @@ grub_usb_poll_devices (void) if (dev && dev->descdev.class == 0x09) poll_nonroot_hub (dev); } - if (!rescan) + + while (1) + { + int continue_waiting = 0; + for (i = 0; i < GRUB_USBHUB_MAX_DEVICES; i++) + { + grub_usb_device_t dev = grub_usb_devs[i]; + + if (dev && dev->descdev.class == 0x09) + continue_waiting = continue_waiting || wait_power_nonroot_hub (dev); + } + if (!continue_waiting) + break; + grub_millisleep (1); + } + + if (!(rescan || (npending && wait_for_completion))) break; - grub_millisleep (50); + grub_millisleep (25); } - } int diff --git a/grub-core/bus/usb/usbtrans.c b/grub-core/bus/usb/usbtrans.c index 154c72d..4b6a32e 100644 --- a/grub-core/bus/usb/usbtrans.c +++ b/grub-core/bus/usb/usbtrans.c @@ -25,6 +25,19 @@ #include <grub/usbtrans.h> #include <grub/time.h> + +static inline unsigned int +grub_usb_bulk_maxpacket (grub_usb_device_t dev, + struct grub_usb_desc_endp *endpoint) +{ + /* Use the maximum packet size given in the endpoint descriptor. */ + if (dev->initialized && endpoint) + return endpoint->maxpacket; + + return 64; +} + + static grub_usb_err_t grub_usb_execute_and_wait_transfer (grub_usb_device_t dev, grub_usb_transfer_t transfer, @@ -199,7 +212,8 @@ grub_usb_control_msg (grub_usb_device_t dev, static grub_usb_transfer_t grub_usb_bulk_setup_readwrite (grub_usb_device_t dev, - int endpoint, grub_size_t size0, char *data_in, + struct grub_usb_desc_endp *endpoint, + grub_size_t size0, char *data_in, grub_transfer_type_t type) { int i; @@ -210,7 +224,7 @@ grub_usb_bulk_setup_readwrite (grub_usb_device_t dev, grub_uint32_t data_addr; struct grub_pci_dma_chunk *data_chunk; grub_size_t size = size0; - int toggle = dev->toggle[endpoint]; + int toggle = dev->toggle[endpoint->endp_addr]; grub_dprintf ("usb", "bulk: size=0x%02lx type=%d\n", (unsigned long) size, type); @@ -249,7 +263,7 @@ grub_usb_bulk_setup_readwrite (grub_usb_device_t dev, datablocks = ((size + max - 1) / max); transfer->transcnt = datablocks; transfer->size = size - 1; - transfer->endpoint = endpoint; + transfer->endpoint = endpoint->endp_addr; transfer->devaddr = dev->addr; transfer->type = GRUB_USB_TRANSACTION_TYPE_BULK; transfer->dir = type; @@ -315,7 +329,8 @@ grub_usb_bulk_finish_readwrite (grub_usb_transfer_t transfer) static grub_usb_err_t grub_usb_bulk_readwrite (grub_usb_device_t dev, - int endpoint, grub_size_t size0, char *data_in, + struct grub_usb_desc_endp *endpoint, + grub_size_t size0, char *data_in, grub_transfer_type_t type, int timeout, grub_size_t *actual) { @@ -333,6 +348,7 @@ grub_usb_bulk_readwrite (grub_usb_device_t dev, return err; } +<<<<<<< TREE grub_usb_err_t grub_usb_bulk_write (grub_usb_device_t dev, int endpoint, grub_size_t size, char *data) @@ -350,6 +366,13 @@ grub_usb_bulk_write (grub_usb_device_t dev, grub_usb_err_t grub_usb_bulk_read (grub_usb_device_t dev, int endpoint, grub_size_t size, char *data) +======= +static grub_usb_err_t +grub_usb_bulk_readwrite_packetize (grub_usb_device_t dev, + struct grub_usb_desc_endp *endpoint, + grub_transfer_type_t type, + grub_size_t size, char *data) +>>>>>>> MERGE-SOURCE { grub_size_t actual, transferred; grub_usb_err_t err; @@ -373,6 +396,29 @@ grub_usb_bulk_read (grub_usb_device_t dev, } grub_usb_err_t +<<<<<<< TREE +======= +grub_usb_bulk_write (grub_usb_device_t dev, + struct grub_usb_desc_endp *endpoint, + grub_size_t size, char *data) +{ + return grub_usb_bulk_readwrite_packetize (dev, endpoint, + GRUB_USB_TRANSFER_TYPE_OUT, + size, data); +} + +grub_usb_err_t +grub_usb_bulk_read (grub_usb_device_t dev, + struct grub_usb_desc_endp *endpoint, + grub_size_t size, char *data) +{ + return grub_usb_bulk_readwrite_packetize (dev, endpoint, + GRUB_USB_TRANSFER_TYPE_IN, + size, data); +} + +grub_usb_err_t +>>>>>>> MERGE-SOURCE grub_usb_check_transfer (grub_usb_transfer_t transfer, grub_size_t *actual) { grub_usb_err_t err; @@ -390,7 +436,8 @@ grub_usb_check_transfer (grub_usb_transfer_t transfer, grub_size_t *actual) grub_usb_transfer_t grub_usb_bulk_read_background (grub_usb_device_t dev, - int endpoint, grub_size_t size, void *data) + struct grub_usb_desc_endp *endpoint, + grub_size_t size, void *data) { grub_usb_err_t err; grub_usb_transfer_t transfer; @@ -417,7 +464,8 @@ grub_usb_cancel_transfer (grub_usb_transfer_t transfer) grub_usb_err_t grub_usb_bulk_read_extended (grub_usb_device_t dev, - int endpoint, grub_size_t size, char *data, + struct grub_usb_desc_endp *endpoint, + grub_size_t size, char *data, int timeout, grub_size_t *actual) { return grub_usb_bulk_readwrite (dev, endpoint, size, data, diff --git a/grub-core/commands/boottime.c b/grub-core/commands/boottime.c new file mode 100644 index 0000000..7370d27 --- /dev/null +++ b/grub-core/commands/boottime.c @@ -0,0 +1,65 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <grub/dl.h> +#include <grub/misc.h> +#include <grub/command.h> +#include <grub/i18n.h> + +GRUB_MOD_LICENSE ("GPLv3+"); + + +static grub_err_t +grub_cmd_boottime (struct grub_command *cmd __attribute__ ((unused)), + int argc __attribute__ ((unused)), + char *argv[] __attribute__ ((unused))) +{ + struct grub_boot_time *cur; + grub_uint64_t last_time = 0, start_time = 0; + if (!grub_boot_time_head) + { + grub_puts_ (N_("No boot time statistics is available\n")); + return 0; + } + start_time = last_time = grub_boot_time_head->tp; + for (cur = grub_boot_time_head; cur; cur = cur->next) + { + grub_uint32_t tmabs = cur->tp - start_time; + grub_uint32_t tmrel = cur->tp - last_time; + last_time = cur->tp; + + grub_printf ("%3d.%03ds %2d.%03ds %s:%d %s\n", + tmabs / 1000, tmabs % 1000, tmrel / 1000, tmrel % 1000, cur->file, cur->line, + cur->msg); + } + return 0; +} + +static grub_command_t cmd_boottime; + +GRUB_MOD_INIT(boottime) +{ + cmd_boottime = + grub_register_command ("boottime", grub_cmd_boottime, + 0, N_("Get boot time statistics.")); +} + +GRUB_MOD_FINI(boottime) +{ + grub_unregister_command (cmd_boottime); +} diff --git a/grub-core/commands/i386/cmosdump.c b/grub-core/commands/i386/cmosdump.c new file mode 100644 index 0000000..952d200 --- /dev/null +++ b/grub-core/commands/i386/cmosdump.c @@ -0,0 +1,64 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2009,2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <grub/dl.h> +#include <grub/command.h> +#include <grub/misc.h> +#include <grub/cmos.h> +#include <grub/i18n.h> + +GRUB_MOD_LICENSE ("GPLv3+"); + +static grub_err_t +grub_cmd_cmosdump (struct grub_command *cmd __attribute__ ((unused)), + int argc __attribute__ ((unused)), char *argv[] __attribute__ ((unused))) +{ + int i; + + for (i = 0; i < 256; i++) + { + grub_err_t err; + grub_uint8_t value; + if ((i & 0xf) == 0) + grub_printf ("%02x: ", i); + + err = grub_cmos_read (i, &value); + if (err) + return err; + + grub_printf ("%02x ", value); + if ((i & 0xf) == 0xf) + grub_printf ("\n"); + } + return GRUB_ERR_NONE; +} + +static grub_command_t cmd; + + +GRUB_MOD_INIT(cmosdump) +{ + cmd = grub_register_command ("cmosdump", grub_cmd_cmosdump, + 0, + N_("Dump CMOS contents.")); +} + +GRUB_MOD_FINI(cmosdump) +{ + grub_unregister_command (cmd); +} diff --git a/grub-core/commands/i386/coreboot/cb_timestamps.c b/grub-core/commands/i386/coreboot/cb_timestamps.c new file mode 100644 index 0000000..5299ad4 --- /dev/null +++ b/grub-core/commands/i386/coreboot/cb_timestamps.c @@ -0,0 +1,118 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <grub/dl.h> +#include <grub/misc.h> +#include <grub/command.h> +#include <grub/i18n.h> +#include <grub/i386/coreboot/lbio.h> +#include <grub/i386/tsc.h> + +GRUB_MOD_LICENSE ("GPLv3+"); + +static grub_uint32_t +tsc2ms (grub_uint64_t tsc) +{ + grub_uint64_t ah = tsc >> 32; + grub_uint64_t al = tsc & 0xffffffff; + + return ((al * grub_tsc_rate) >> 32) + ah * grub_tsc_rate; +} + +static const char *descs[] = { + [1] = "romstage", + [2] = "before RAM init", + [3] = "after RAM init", + [4] = "end of romstage", + [8] = "start of RAM copy", + [9] = "end of RAM copy", + [10] = "start of ramstage", + [30] = "device enumerate", + [40] = "device configure", + [50] = "device enable", + [60] = "device initialize", + [70] = "device done", + [75] = "CBMEM POST", + [80] = "writing tables", + [90] = "loading payload", + [98] = "wake jump", + [99] = "selfboot jump", +}; + +static int +iterate_linuxbios_table (grub_linuxbios_table_item_t table_item, + void *data) +{ + int *available = data; + grub_uint64_t last_tsc = 0; + struct grub_linuxbios_timestamp_table *ts_table; + unsigned i; + + if (table_item->tag != GRUB_LINUXBIOS_MEMBER_TIMESTAMPS) + return 0; + + *available = 1; + ts_table = (struct grub_linuxbios_timestamp_table *) (grub_addr_t) + *(grub_uint64_t *) (table_item + 1); + + for (i = 0; i < ts_table->used; i++) + { + grub_uint32_t tmabs = tsc2ms (ts_table->entries[i].tsc); + grub_uint32_t tmrel = tsc2ms (ts_table->entries[i].tsc - last_tsc); + last_tsc = ts_table->entries[i].tsc; + + grub_printf ("%3d.%03ds %2d.%03ds %02d %s\n", + tmabs / 1000, tmabs % 1000, tmrel / 1000, tmrel % 1000, + ts_table->entries[i].id, + (ts_table->entries[i].id < ARRAY_SIZE (descs) + && descs[ts_table->entries[i].id]) + ? descs[ts_table->entries[i].id] : ""); + } + return 1; +} + + +static grub_err_t +grub_cmd_coreboot_boottime (struct grub_command *cmd __attribute__ ((unused)), + int argc __attribute__ ((unused)), + char *argv[] __attribute__ ((unused))) +{ + int available = 0; + + grub_linuxbios_table_iterate (iterate_linuxbios_table, &available); + if (!available) + { + grub_puts_ (N_("No boot time statistics is available\n")); + return 0; + } + return 0; +} + +static grub_command_t cmd_boottime; + +GRUB_MOD_INIT(cbtime) +{ + cmd_boottime = + grub_register_command ("coreboot_boottime", grub_cmd_coreboot_boottime, + 0, N_("Get coreboot boot time statistics.")); +} + +GRUB_MOD_FINI(cbtime) +{ + grub_unregister_command (cmd_boottime); +} diff --git a/grub-core/commands/i386/coreboot/cbls.c b/grub-core/commands/i386/coreboot/cbls.c new file mode 100644 index 0000000..dc46d55 --- /dev/null +++ b/grub-core/commands/i386/coreboot/cbls.c @@ -0,0 +1,128 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <grub/dl.h> +#include <grub/misc.h> +#include <grub/command.h> +#include <grub/i18n.h> +#include <grub/i386/coreboot/lbio.h> +#include <grub/i386/tsc.h> + +GRUB_MOD_LICENSE ("GPLv3+"); + +static const char *console_descs[] = { + "8250 UART", + "VGA", + "BTEXT", + "CBMEM console", + "SROM", + "EHCI debug", + "memory-mapped 8250 UART" +}; + +static const char *descs[] = { + [GRUB_LINUXBIOS_MEMBER_MEMORY] = "memory map (`lsmmap' to list)", + [GRUB_LINUXBIOS_MEMBER_MAINBOARD] = "mainboard", + [4] = "version", + [5] = "extra version", + [6] = "build", + [7] = "compile time", + [8] = "compile by", + [9] = "compile host", + [0xa] = "compile domain", + [0xb] = "compiler", + [0xc] = "linker", + [0xd] = "assembler", + [0xf] = "serial", + [GRUB_LINUXBIOS_MEMBER_CONSOLE] = "console", + [0x12] = "framebuffer", + [0x13] = "GPIO", + [0x15] = "VDAT", + [GRUB_LINUXBIOS_MEMBER_TIMESTAMPS] = "timestamps (`coreboot_boottime' to list)", + [GRUB_LINUXBIOS_MEMBER_CBMEMC] = "CBMEM console (`cbmem' to list)", + [0x18] = "MRC cache", + [0x19] = "VBNV", + [0xc8] = "CMOS option table", + [0xc9] = "CMOS option", + [0xca] = "CMOS option enum", + [0xcb] = "CMOS option defaults", + [0xcc] = "CMOS checksum", +}; + +static int +iterate_linuxbios_table (grub_linuxbios_table_item_t table_item, + void *data __attribute__ ((unused))) +{ + if (table_item->tag < ARRAY_SIZE (descs) && descs[table_item->tag]) + grub_printf ("tag=%02x size=%02x %s", + table_item->tag, table_item->size, descs[table_item->tag]); + else + grub_printf ("tag=%02x size=%02x", + table_item->tag, table_item->size); + + switch (table_item->tag) + { + case GRUB_LINUXBIOS_MEMBER_MAINBOARD: + { + struct grub_linuxbios_mainboard *mb; + mb = (struct grub_linuxbios_mainboard *) (table_item + 1); + grub_printf (": vendor=`%s' part_number=`%s'", + mb->strings + mb->vendor, + mb->strings + mb->part_number); + break; + } + case 0x04 ... 0x0d: + grub_printf (": `%s'", (char *) (table_item + 1)); + break; + case GRUB_LINUXBIOS_MEMBER_CONSOLE: + { + grub_uint16_t *val = (grub_uint16_t *) (table_item + 1); + grub_printf (": id=%d", *val); + if (*val < ARRAY_SIZE (console_descs) + && console_descs[*val]) + grub_printf (" %s", console_descs[*val]); + } + } + grub_printf ("\n"); + + return 0; +} + + +static grub_err_t +grub_cmd_lscoreboot (struct grub_command *cmd __attribute__ ((unused)), + int argc __attribute__ ((unused)), + char *argv[] __attribute__ ((unused))) +{ + grub_linuxbios_table_iterate (iterate_linuxbios_table, 0); + return 0; +} + +static grub_command_t cmd; + +GRUB_MOD_INIT(cbls) +{ + cmd = + grub_register_command ("lscoreboot", grub_cmd_lscoreboot, + 0, N_("List coreboot tables.")); +} + +GRUB_MOD_FINI(cbls) +{ + grub_unregister_command (cmd); +} diff --git a/grub-core/commands/keystatus.c b/grub-core/commands/keystatus.c index 0925c6a..460cf4e 100644 --- a/grub-core/commands/keystatus.c +++ b/grub-core/commands/keystatus.c @@ -42,7 +42,7 @@ grub_getkeystatus (void) grub_term_input_t term; if (grub_term_poll_usb) - grub_term_poll_usb (); + grub_term_poll_usb (0); FOR_ACTIVE_TERM_INPUTS(term) { diff --git a/grub-core/commands/lsacpi.c b/grub-core/commands/lsacpi.c index 07c3f0d..0824914 100644 --- a/grub-core/commands/lsacpi.c +++ b/grub-core/commands/lsacpi.c @@ -44,7 +44,8 @@ static void disp_acpi_table (struct grub_acpi_table_header *t) { print_field (t->signature); - grub_printf ("%4" PRIuGRUB_UINT32_T "B rev=%u OEM=", t->length, t->revision); + grub_printf ("%4" PRIuGRUB_UINT32_T "B rev=%u chksum=0x%02x (%s) OEM=", t->length, t->revision, t->checksum, + grub_byte_checksum (t, t->length) == 0 ? "valid" : "invalid"); print_field (t->oemid); print_field (t->oemtable); grub_printf ("OEMrev=%08" PRIxGRUB_UINT32_T " ", t->oemrev); @@ -66,39 +67,87 @@ disp_madt_table (struct grub_acpi_madt *t) d = t->entries; for (;len > 0; len -= d->len, d = (void *) ((grub_uint8_t *) d + d->len)) { - grub_printf (" type=%x l=%u ", d->type, d->len); - switch (d->type) { + case GRUB_ACPI_MADT_ENTRY_TYPE_LAPIC: + { + struct grub_acpi_madt_entry_lapic *dt = (void *) d; + grub_printf (" LAPIC ACPI_ID=%02x APIC_ID=%02x Flags=%08x\n", + dt->acpiid, dt->apicid, dt->flags); + if (dt->hdr.len != sizeof (*dt)) + grub_printf (" table size mismatch %d != %d\n", dt->hdr.len, + (int) sizeof (*dt)); + break; + } + + case GRUB_ACPI_MADT_ENTRY_TYPE_IOAPIC: + { + struct grub_acpi_madt_entry_ioapic *dt = (void *) d; + grub_printf (" IOAPIC ID=%02x address=%08x GSI=%08x\n", + dt->id, dt->address, dt->global_sys_interrupt); + if (dt->hdr.len != sizeof (*dt)) + grub_printf (" table size mismatch %d != %d\n", dt->hdr.len, + (int) sizeof (*dt)); + if (dt->pad) + grub_printf (" non-zero pad: %02x\n", dt->pad); + break; + } + case GRUB_ACPI_MADT_ENTRY_TYPE_INTERRUPT_OVERRIDE: { struct grub_acpi_madt_entry_interrupt_override *dt = (void *) d; - grub_printf ("Int Override bus=%x src=%x GSI=%08x Flags=%04x\n", + grub_printf (" Int Override bus=%x src=%x GSI=%08x Flags=%04x\n", dt->bus, dt->source, dt->global_sys_interrupt, dt->flags); + if (dt->hdr.len != sizeof (*dt)) + grub_printf (" table size mismatch %d != %d\n", dt->hdr.len, + (int) sizeof (*dt)); } break; + + case GRUB_ACPI_MADT_ENTRY_TYPE_LAPIC_NMI: + { + struct grub_acpi_madt_entry_lapic_nmi *dt = (void *) d; + grub_printf (" LAPIC_NMI ACPI_ID=%02x Flags=%04x lint=%02x\n", + dt->acpiid, dt->flags, dt->lint); + if (dt->hdr.len != sizeof (*dt)) + grub_printf (" table size mismatch %d != %d\n", dt->hdr.len, + (int) sizeof (*dt)); + break; + } + case GRUB_ACPI_MADT_ENTRY_TYPE_SAPIC: { struct grub_acpi_madt_entry_sapic *dt = (void *) d; - grub_printf ("IOSAPIC Id=%02x GSI=%08x Addr=%016" PRIxGRUB_UINT64_T + grub_printf (" IOSAPIC Id=%02x GSI=%08x Addr=%016" PRIxGRUB_UINT64_T "\n", dt->id, dt->global_sys_interrupt_base, dt->addr); + if (dt->hdr.len != sizeof (*dt)) + grub_printf (" table size mismatch %d != %d\n", dt->hdr.len, + (int) sizeof (*dt)); + if (dt->pad) + grub_printf (" non-zero pad: %02x\n", dt->pad); + } break; case GRUB_ACPI_MADT_ENTRY_TYPE_LSAPIC: { struct grub_acpi_madt_entry_lsapic *dt = (void *) d; - grub_printf ("LSAPIC ProcId=%02x ID=%02x EID=%02x Flags=%x", + grub_printf (" LSAPIC ProcId=%02x ID=%02x EID=%02x Flags=%x", dt->cpu_id, dt->id, dt->eid, dt->flags); if (dt->flags & GRUB_ACPI_MADT_ENTRY_SAPIC_FLAGS_ENABLED) grub_printf (" Enabled\n"); else grub_printf (" Disabled\n"); if (d->len > sizeof (struct grub_acpi_madt_entry_sapic)) - grub_printf (" UID val=%08x, Str=%s\n", dt->cpu_uid, + grub_printf (" UID val=%08x, Str=%s\n", dt->cpu_uid, dt->cpu_uid_str); + if (dt->hdr.len != sizeof (*dt) + grub_strlen ((char *) dt->cpu_uid_str) + 1) + grub_printf (" table size mismatch %d != %d\n", dt->hdr.len, + (int) sizeof (*dt)); + if (dt->pad[0] || dt->pad[1] || dt->pad[2]) + grub_printf (" non-zero pad: %02x%02x%02x\n", dt->pad[0], dt->pad[1], dt->pad[2]); } break; case GRUB_ACPI_MADT_ENTRY_TYPE_PLATFORM_INT_SOURCE: @@ -107,17 +156,18 @@ disp_madt_table (struct grub_acpi_madt *t) static const char * const platint_type[] = {"Nul", "PMI", "INIT", "CPEI"}; - grub_printf ("Platform INT flags=%04x type=%02x (%s)" + grub_printf (" Platform INT flags=%04x type=%02x (%s)" " ID=%02x EID=%02x\n", dt->flags, dt->inttype, (dt->inttype < ARRAY_SIZE (platint_type)) ? platint_type[dt->inttype] : "??", dt->cpu_id, dt->cpu_eid); - grub_printf (" IOSAPIC Vec=%02x GSI=%08x source flags=%08x\n", + grub_printf (" IOSAPIC Vec=%02x GSI=%08x source flags=%08x\n", dt->sapic_vector, dt->global_sys_int, dt->src_flags); } break; default: + grub_printf (" type=%x l=%u ", d->type, d->len); grub_printf (" ??\n"); } } @@ -182,7 +232,7 @@ static void disp_acpi_rsdpv1 (struct grub_acpi_rsdp_v10 *rsdp) { print_field (rsdp->signature); - grub_printf ("chksum:%02x, OEM-ID: ", rsdp->checksum); + grub_printf ("chksum:%02x (%s), OEM-ID: ", rsdp->checksum, grub_byte_checksum (rsdp, sizeof (*rsdp)) == 0 ? "valid" : "invalid"); print_field (rsdp->oemid); grub_printf ("rev=%d\n", rsdp->revision); grub_printf ("RSDT=%08" PRIxGRUB_UINT32_T "\n", rsdp->rsdt_addr); @@ -192,8 +242,13 @@ static void disp_acpi_rsdpv2 (struct grub_acpi_rsdp_v20 *rsdp) { disp_acpi_rsdpv1 (&rsdp->rsdpv1); - grub_printf ("len=%d XSDT=%016" PRIxGRUB_UINT64_T "\n", rsdp->length, + grub_printf ("len=%d chksum=%02x (%s) XSDT=%016" PRIxGRUB_UINT64_T "\n", rsdp->length, rsdp->checksum, grub_byte_checksum (rsdp, rsdp->length) == 0 ? "valid" : "invalid", rsdp->xsdt_addr); + if (rsdp->length != sizeof (*rsdp)) + grub_printf (" length mismatch %d != %d\n", rsdp->length, + (int) sizeof (*rsdp)); + if (rsdp->reserved[0] || rsdp->reserved[1] || rsdp->reserved[2]) + grub_printf (" non-zero reserved %02x%02x%02x\n", rsdp->reserved[0], rsdp->reserved[1], rsdp->reserved[2]); } static const struct grub_arg_option options[] = { diff --git a/grub-core/commands/terminal.c b/grub-core/commands/terminal.c index 425a411..3002186 100644 --- a/grub-core/commands/terminal.c +++ b/grub-core/commands/terminal.c @@ -108,9 +108,9 @@ handle_command (int argc, char **args, struct abstract_terminal **enabled, if (term) break; if (again) - return grub_error (GRUB_ERR_BAD_ARGUMENT, + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("terminal `%s' isn't found"), - args[i]); + args[i]); for (aut = autoloads; aut; aut = aut->next) if (grub_strcmp (args[i], aut->name) == 0 || (grub_strcmp (args[i], "ofconsole") == 0 @@ -126,6 +126,14 @@ handle_command (int argc, char **args, struct abstract_terminal **enabled, grub_errno = GRUB_ERR_NONE; break; } + if (grub_memcmp (args[i], "serial_usb", + sizeof ("serial_usb") - 1) == 0 + && grub_term_poll_usb) + { + grub_term_poll_usb (1); + again = 1; + continue; + } if (!aut) return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("terminal `%s' isn't found"), diff --git a/grub-core/commands/usbtest.c b/grub-core/commands/usbtest.c index af35b8c..01cdca9 100644 --- a/grub-core/commands/usbtest.c +++ b/grub-core/commands/usbtest.c @@ -196,7 +196,7 @@ grub_cmd_usbtest (grub_command_t cmd __attribute__ ((unused)), int argc __attribute__ ((unused)), char **args __attribute__ ((unused))) { - grub_usb_poll_devices (); + grub_usb_poll_devices (1); grub_printf ("USB devices:\n\n"); grub_usb_iterate (usb_iterate, NULL); diff --git a/grub-core/commands/verify.c b/grub-core/commands/verify.c index d399d0f..c5e69eb 100644 --- a/grub-core/commands/verify.c +++ b/grub-core/commands/verify.c @@ -124,7 +124,10 @@ struct signature_v4_header const char *hashes[] = { "md5", "sha1", "ripemd160", - [0x0a] = "sha512" + [0x08] = "sha256", + [0x09] = "sha384", + [0x0a] = "sha512", + [0x0b] = "sha224" }; struct diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c index ce755c3..f39c1ab 100644 --- a/grub-core/disk/cryptodisk.c +++ b/grub-core/disk/cryptodisk.c @@ -875,7 +875,10 @@ grub_cryptodisk_scan_device (const char *name, /* Try to open disk. */ source = grub_disk_open (name); if (!source) - return grub_errno; + { + grub_print_error (); + return 0; + } err = grub_cryptodisk_scan_device_real (name, source); diff --git a/grub-core/disk/ieee1275/ofdisk.c b/grub-core/disk/ieee1275/ofdisk.c index 644bbd2..2130cb1 100644 --- a/grub-core/disk/ieee1275/ofdisk.c +++ b/grub-core/disk/ieee1275/ofdisk.c @@ -349,6 +349,14 @@ grub_ofdisk_open (const char *name, grub_disk_t disk) return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a block device"); } + grub_uint32_t block_size = 0; + if (grub_ofdisk_get_block_size (devpath, &block_size) == 0) + { + for (disk->log_sector_size = 0; + (1U << disk->log_sector_size) < block_size; + disk->log_sector_size++); + } + /* XXX: There is no property to read the number of blocks. There should be a property `#blocks', but it is not there. Perhaps it is possible to use seek for this. */ @@ -415,7 +423,7 @@ grub_ofdisk_prepare (grub_disk_t disk, grub_disk_addr_t sector) last_devpath = disk->data; } - pos = sector << GRUB_DISK_SECTOR_BITS; + pos = sector << disk->log_sector_size; grub_ieee1275_seek (last_ihandle, pos, &status); if (status < 0) @@ -434,9 +442,9 @@ grub_ofdisk_read (grub_disk_t disk, grub_disk_addr_t sector, err = grub_ofdisk_prepare (disk, sector); if (err) return err; - grub_ieee1275_read (last_ihandle, buf, size << GRUB_DISK_SECTOR_BITS, + grub_ieee1275_read (last_ihandle, buf, size << disk->log_sector_size, &actual); - if (actual != (grub_ssize_t) (size << GRUB_DISK_SECTOR_BITS)) + if (actual != (grub_ssize_t) (size << disk->log_sector_size)) return grub_error (GRUB_ERR_READ_ERROR, N_("failure reading sector 0x%llx " "from `%s'"), (unsigned long long) sector, @@ -454,9 +462,9 @@ grub_ofdisk_write (grub_disk_t disk, grub_disk_addr_t sector, err = grub_ofdisk_prepare (disk, sector); if (err) return err; - grub_ieee1275_write (last_ihandle, buf, size << GRUB_DISK_SECTOR_BITS, + grub_ieee1275_write (last_ihandle, buf, size << disk->log_sector_size, &actual); - if (actual != (grub_ssize_t) (size << GRUB_DISK_SECTOR_BITS)) + if (actual != (grub_ssize_t) (size << disk->log_sector_size)) return grub_error (GRUB_ERR_WRITE_ERROR, N_("failure writing sector 0x%llx " "to `%s'"), (unsigned long long) sector, @@ -493,3 +501,44 @@ grub_ofdisk_fini (void) grub_disk_dev_unregister (&grub_ofdisk_dev); } + +grub_err_t +grub_ofdisk_get_block_size (const char *device, grub_uint32_t *block_size) +{ + struct size_args_ieee1275 + { + struct grub_ieee1275_common_hdr common; + grub_ieee1275_cell_t method; + grub_ieee1275_cell_t ihandle; + grub_ieee1275_cell_t result; + grub_ieee1275_cell_t size1; + grub_ieee1275_cell_t size2; + } args_ieee1275; + + if (last_ihandle) + grub_ieee1275_close (last_ihandle); + + last_ihandle = 0; + last_devpath = NULL; + + grub_ieee1275_open (device, &last_ihandle); + if (! last_ihandle) + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't open device"); + + INIT_IEEE1275_COMMON (&args_ieee1275.common, "call-method", 2, 2); + args_ieee1275.method = (grub_ieee1275_cell_t) "block-size"; + args_ieee1275.ihandle = last_ihandle; + args_ieee1275.result = 1; + + *block_size = GRUB_DISK_SECTOR_SIZE; + + if ((IEEE1275_CALL_ENTRY_FN (&args_ieee1275) == -1) || (args_ieee1275.result)) + grub_dprintf ("disk", "can't get block size\n"); + else + if (args_ieee1275.size1 + && !(args_ieee1275.size1 & (args_ieee1275.size1 - 1)) + && args_ieee1275.size1 >= 512 && args_ieee1275.size1 <= 16384) + *block_size = args_ieee1275.size1; + + return 0; +} diff --git a/grub-core/disk/usbms.c b/grub-core/disk/usbms.c index 50f0caf..da01be3 100644 --- a/grub-core/disk/usbms.c +++ b/grub-core/disk/usbms.c @@ -151,6 +151,8 @@ grub_usbms_attach (grub_usb_device_t usbdev, int configno, int interfno) unsigned curnum; grub_usb_err_t err = GRUB_ERR_NONE; + grub_boot_time ("Attaching USB mass storage"); + if (first_available_slot == ARRAY_SIZE (grub_usbms_devices)) return 0; @@ -246,6 +248,8 @@ grub_usbms_attach (grub_usb_device_t usbdev, int configno, int interfno) usbdev->config[configno].interf[interfno].detach_hook = grub_usbms_detach; + grub_boot_time ("Attached USB mass storage"); + #if 0 /* All this part should be probably deleted. * This make trouble on some devices if they are not in * Phase Error state - and there they should be not in such state... @@ -273,7 +277,7 @@ grub_usbms_iterate (grub_scsi_dev_iterate_hook_t hook, void *hook_data, if (pull != GRUB_DISK_PULL_NONE) return 0; - grub_usb_poll_devices (); + grub_usb_poll_devices (1); for (i = 0; i < ARRAY_SIZE (grub_usbms_devices); i++) if (grub_usbms_devices[i]) @@ -326,7 +330,7 @@ grub_usbms_transfer_bo (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd, /* Write the request. * XXX: Error recovery is maybe still not fully correct. */ - err = grub_usb_bulk_write (dev->dev, dev->out->endp_addr, + err = grub_usb_bulk_write (dev->dev, dev->out, sizeof (cbw), (char *) &cbw); if (err) { @@ -341,7 +345,7 @@ grub_usbms_transfer_bo (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd, /* Read/write the data, (maybe) according to specification. */ if (size && (read_write == 0)) { - err = grub_usb_bulk_read (dev->dev, dev->in->endp_addr, size, buf); + err = grub_usb_bulk_read (dev->dev, dev->in, size, buf); grub_dprintf ("usb", "read: %d %d\n", err, GRUB_USB_ERR_STALL); if (err) { @@ -362,7 +366,7 @@ grub_usbms_transfer_bo (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd, } else if (size) { - err = grub_usb_bulk_write (dev->dev, dev->out->endp_addr, size, buf); + err = grub_usb_bulk_write (dev->dev, dev->out, size, buf); grub_dprintf ("usb", "write: %d %d\n", err, GRUB_USB_ERR_STALL); grub_dprintf ("usb", "First 16 bytes of sent data:\n %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", buf[ 0], buf[ 1], buf[ 2], buf[ 3], @@ -388,12 +392,12 @@ grub_usbms_transfer_bo (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd, /* Read the status - (maybe) according to specification. */ CheckCSW: - errCSW = grub_usb_bulk_read (dev->dev, dev->in->endp_addr, + errCSW = grub_usb_bulk_read (dev->dev, dev->in, 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, + errCSW = grub_usb_bulk_read (dev->dev, dev->in, sizeof (status), (char *) &status); if (errCSW) { /* Bulk-only reset device. */ @@ -476,7 +480,7 @@ grub_usbms_transfer_cbi (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd, else if (dev->protocol == GRUB_USBMS_PROTOCOL_CBI) { /* Try to get status from interrupt pipe */ - err = grub_usb_bulk_read (dev->dev, dev->intrpt->endp_addr, + err = grub_usb_bulk_read (dev->dev, dev->intrpt, 2, (char*)&status); grub_dprintf ("usb", "CBI cmdcb setup status: err=%d, status=0x%x\n", err, status); } @@ -487,7 +491,7 @@ grub_usbms_transfer_cbi (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd, /* Read/write the data, (maybe) according to specification. */ if (size && (read_write == 0)) { - err = grub_usb_bulk_read (dev->dev, dev->in->endp_addr, size, buf); + err = grub_usb_bulk_read (dev->dev, dev->in, size, buf); grub_dprintf ("usb", "read: %d\n", err); if (err) { @@ -498,7 +502,7 @@ grub_usbms_transfer_cbi (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd, } else if (size) { - err = grub_usb_bulk_write (dev->dev, dev->out->endp_addr, size, buf); + err = grub_usb_bulk_write (dev->dev, dev->out, size, buf); grub_dprintf ("usb", "write: %d\n", err); if (err) { @@ -517,7 +521,7 @@ grub_usbms_transfer_cbi (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd, * (we do not it yet) - ? */ if (dev->protocol == GRUB_USBMS_PROTOCOL_CBI) { /* Check status in interrupt pipe */ - err = grub_usb_bulk_read (dev->dev, dev->intrpt->endp_addr, + err = grub_usb_bulk_read (dev->dev, dev->intrpt, 2, (char*)&status); grub_dprintf ("usb", "read status: %d\n", err); if (err) @@ -607,7 +611,8 @@ grub_usbms_open (int id, int devnum, struct grub_scsi *scsi) return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not USB Mass Storage device"); - grub_usb_poll_devices (); + if (!grub_usbms_devices[devnum]) + grub_usb_poll_devices (1); if (!grub_usbms_devices[devnum]) return grub_error (GRUB_ERR_UNKNOWN_DEVICE, diff --git a/grub-core/fs/fshelp.c b/grub-core/fs/fshelp.c index 7e557c3..11a1259 100644 --- a/grub-core/fs/fshelp.c +++ b/grub-core/fs/fshelp.c @@ -147,6 +147,7 @@ find_file (const char *currpath, grub_fshelp_node_t currroot, free_node (ctx->currnode, ctx); free_node (ctx->oldnode, ctx); ctx->currnode = 0; + ctx->oldnode = 0; return grub_error (GRUB_ERR_SYMLINK_LOOP, N_("too deep nesting of symlinks")); } @@ -158,6 +159,7 @@ find_file (const char *currpath, grub_fshelp_node_t currroot, if (!symlink) { free_node (ctx->oldnode, ctx); + ctx->oldnode = 0; return grub_errno; } @@ -177,12 +179,16 @@ find_file (const char *currpath, grub_fshelp_node_t currroot, if (grub_errno) { free_node (ctx->oldnode, ctx); + ctx->oldnode = 0; return grub_errno; } } if (ctx->oldnode != ctx->currnode) - free_node (ctx->oldnode, ctx); + { + free_node (ctx->oldnode, ctx); + ctx->oldnode = 0; + } /* Found the node! */ if (! next || *next == '\0') diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c index 49d2a89..aee1582 100644 --- a/grub-core/fs/xfs.c +++ b/grub-core/fs/xfs.c @@ -295,9 +295,7 @@ grub_xfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) nrec = grub_be_to_cpu16 (node->inode.data.btree.numrecs); keys = &node->inode.data.btree.keys[0]; if (node->inode.fork_offset) - recoffset = (node->inode.fork_offset - - ((char *) &node->inode.data.btree.keys - (char *) &node->inode)) - / (2 * sizeof (grub_uint64_t)); + recoffset = (node->inode.fork_offset - 1) / 2; else recoffset = ((1 << node->data->sblock.log2_inode) - ((char *) &node->inode.data.btree.keys diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c index 5b0aa65..d06b6ae 100644 --- a/grub-core/kern/dl.c +++ b/grub-core/kern/dl.c @@ -648,7 +648,10 @@ grub_dl_load_core (void *addr, grub_size_t size) grub_dprintf ("modules", "module name: %s\n", mod->name); grub_dprintf ("modules", "init function: %p\n", mod->init); + + grub_boot_time ("Initing module %s", mod->name); grub_dl_call_init (mod); + grub_boot_time ("Module %s inited", mod->name); if (grub_dl_add (mod)) { diff --git a/grub-core/kern/elfXX.c b/grub-core/kern/elfXX.c new file mode 100644 index 0000000..b35e235 --- /dev/null +++ b/grub-core/kern/elfXX.c @@ -0,0 +1,144 @@ +int +grub_elf_is_elfXX (grub_elf_t elf) +{ + return elf->ehdr.ehdrXX.e_ident[EI_CLASS] == ELFCLASSXX; +} + +grub_err_t +grub_elfXX_load_phdrs (grub_elf_t elf) +{ + grub_ssize_t phdrs_size; + + if (elf->phdrs) + return GRUB_ERR_NONE; + + phdrs_size = elf->ehdr.ehdrXX.e_phnum * elf->ehdr.ehdrXX.e_phentsize; + + grub_dprintf ("elf", "Loading program headers at 0x%llx, size 0x%lx.\n", + (unsigned long long) elf->ehdr.ehdrXX.e_phoff, + (unsigned long) phdrs_size); + + elf->phdrs = grub_malloc (phdrs_size); + if (! elf->phdrs) + return grub_errno; + + if ((grub_file_seek (elf->file, elf->ehdr.ehdrXX.e_phoff) == (grub_off_t) -1) + || (grub_file_read (elf->file, elf->phdrs, phdrs_size) != phdrs_size)) + { + if (!grub_errno) + grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"), + elf->filename); + return grub_errno; + } + + return GRUB_ERR_NONE; +} + +/* Calculate the amount of memory spanned by the segments. */ +grub_size_t +grub_elfXX_size (grub_elf_t elf, + ElfXX_Addr *base, grub_uintXX_t *max_align) +{ + ElfXX_Addr segments_start = (ElfXX_Addr) -1; + ElfXX_Addr segments_end = 0; + int nr_phdrs = 0; + grub_uint32_t curr_align = 1; + ElfXX_Phdr *phdr; + + /* Run through the program headers to calculate the total memory size we + * should claim. */ + FOR_ELFXX_PHDRS (elf, phdr) + { + /* Only consider loadable segments. */ + if (phdr->p_type != PT_LOAD) + continue; + nr_phdrs++; + if (phdr->p_paddr < segments_start) + segments_start = phdr->p_paddr; + if (phdr->p_paddr + phdr->p_memsz > segments_end) + segments_end = phdr->p_paddr + phdr->p_memsz; + if (curr_align < phdr->p_align) + curr_align = phdr->p_align; + } + + if (base) + *base = 0; + + if (nr_phdrs == 0) + { + grub_error (GRUB_ERR_BAD_OS, "no program headers present"); + return 0; + } + + if (segments_end < segments_start) + { + /* Very bad addresses. */ + grub_error (GRUB_ERR_BAD_OS, "bad program header load addresses"); + return 0; + } + + if (base) + *base = segments_start; + if (max_align) + *max_align = curr_align; + return segments_end - segments_start; +} + +grub_err_t +grub_elfXX_load (grub_elf_t elf, const char *filename, + void *load_offset, enum grub_elf_load_flags load_flags, + grub_addr_t *base, grub_size_t *size) +{ + grub_addr_t load_base = (grub_addr_t) -1ULL; + grub_size_t load_size = 0; + ElfXX_Phdr *phdr; + + FOR_ELFXX_PHDRS(elf, phdr) + { + grub_addr_t load_addr; + + if (phdr->p_type != PT_LOAD && !((load_flags & GRUB_ELF_LOAD_FLAGS_LOAD_PT_DYNAMIC) && phdr->p_type == PT_DYNAMIC)) + continue; + + load_addr = (grub_addr_t) phdr->p_paddr; + if (load_flags & GRUB_ELF_LOAD_FLAGS_28BITS) + load_addr &= 0xFFFFFFF; + load_addr += (grub_addr_t) load_offset; + + if (load_addr < load_base) + load_base = load_addr; + + grub_dprintf ("elf", "Loading segment at 0x%llx, size 0x%llx\n", + (unsigned long long) load_addr, + (unsigned long long) phdr->p_memsz); + + if (grub_file_seek (elf->file, phdr->p_offset) == (grub_off_t) -1) + return grub_errno; + + if (phdr->p_filesz) + { + grub_ssize_t read; + read = grub_file_read (elf->file, (void *) load_addr, phdr->p_filesz); + if (read != (grub_ssize_t) phdr->p_filesz) + { + if (!grub_errno) + grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"), + filename); + return grub_errno; + } + } + + if (phdr->p_filesz < phdr->p_memsz) + grub_memset ((void *) (long) (load_addr + phdr->p_filesz), + 0, phdr->p_memsz - phdr->p_filesz); + + load_size += phdr->p_memsz; + } + + if (base) + *base = load_base; + if (size) + *size = load_size; + + return grub_errno; +} diff --git a/grub-core/kern/i386/coreboot/mmap.c b/grub-core/kern/i386/coreboot/mmap.c index ae4af08..a062a59 100644 --- a/grub-core/kern/i386/coreboot/mmap.c +++ b/grub-core/kern/i386/coreboot/mmap.c @@ -32,7 +32,7 @@ check_signature (grub_linuxbios_table_header_t tbl_header) return 0; } -static grub_err_t +grub_err_t grub_linuxbios_table_iterate (int (*hook) (grub_linuxbios_table_item_t, void *), void *hook_data) diff --git a/grub-core/kern/i386/pit.c b/grub-core/kern/i386/pit.c deleted file mode 100644 index 092481a..0000000 --- a/grub-core/kern/i386/pit.c +++ /dev/null @@ -1,49 +0,0 @@ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 2008 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/i386/io.h> -#include <grub/i386/pit.h> - -void -grub_pit_wait (grub_uint16_t tics) -{ - /* Disable timer2 gate and speaker. */ - grub_outb (grub_inb (GRUB_PIT_SPEAKER_PORT) - & ~ (GRUB_PIT_SPK_DATA | GRUB_PIT_SPK_TMR2), - GRUB_PIT_SPEAKER_PORT); - - /* Set tics. */ - grub_outb (GRUB_PIT_CTRL_SELECT_2 | GRUB_PIT_CTRL_READLOAD_WORD, - GRUB_PIT_CTRL); - grub_outb (tics & 0xff, GRUB_PIT_COUNTER_2); - grub_outb (tics >> 8, GRUB_PIT_COUNTER_2); - - /* Enable timer2 gate, keep speaker disabled. */ - grub_outb ((grub_inb (GRUB_PIT_SPEAKER_PORT) & ~ GRUB_PIT_SPK_DATA) - | GRUB_PIT_SPK_TMR2, - GRUB_PIT_SPEAKER_PORT); - - /* Wait. */ - while ((grub_inb (GRUB_PIT_SPEAKER_PORT) & GRUB_PIT_SPK_TMR2_LATCH) == 0x00); - - /* Disable timer2 gate and speaker. */ - grub_outb (grub_inb (GRUB_PIT_SPEAKER_PORT) - & ~ (GRUB_PIT_SPK_DATA | GRUB_PIT_SPK_TMR2), - GRUB_PIT_SPEAKER_PORT); -} diff --git a/grub-core/kern/main.c b/grub-core/kern/main.c index 99477c7..19dc988 100644 --- a/grub-core/kern/main.c +++ b/grub-core/kern/main.c @@ -30,10 +30,10 @@ #include <grub/reader.h> #include <grub/parser.h> -/* This is actualy platform-independant but used only on some platforms. */ -#if defined (GRUB_MACHINE_MIPS_LOONGSON) || \ - defined (GRUB_MACHINE_MIPS_QEMU_MIPS) || defined (GRUB_MACHINE_SPARC64) || \ - defined (GRUB_MACHINE_ARM) +#ifdef GRUB_MACHINE_PCBIOS +#include <grub/machine/memory.h> +#endif + grub_addr_t grub_modules_get_end (void) { @@ -47,7 +47,6 @@ grub_modules_get_end (void) return grub_modbase + modinfo->size; } -#endif /* Load all modules in core. */ static void @@ -69,6 +68,8 @@ grub_load_modules (void) } } +static char *load_config; + static void grub_load_config (void) { @@ -78,9 +79,17 @@ grub_load_config (void) /* Not an embedded config, skip. */ if (header->type != OBJ_TYPE_CONFIG) continue; - - grub_parser_execute ((char *) header + - sizeof (struct grub_module_header)); + + load_config = grub_malloc (header->size - sizeof (struct grub_module_header) + 1); + if (!load_config) + { + grub_print_error (); + break; + } + grub_memcpy (load_config, (char *) header + + sizeof (struct grub_module_header), + header->size - sizeof (struct grub_module_header)); + load_config[header->size - sizeof (struct grub_module_header)] = 0; break; } } @@ -170,7 +179,16 @@ grub_set_prefix_and_root (void) else grub_free (fwdevice); if (fwpath && !path) - path = fwpath; + { + grub_size_t len = grub_strlen (fwpath); + while (len > 1 && fwpath[len - 1] == '/') + fwpath[--len] = 0; + if (len >= sizeof (GRUB_TARGET_CPU "-" GRUB_PLATFORM) - 1 + && grub_memcmp (fwpath + len - (sizeof (GRUB_TARGET_CPU "-" GRUB_PLATFORM) - 1), GRUB_TARGET_CPU "-" GRUB_PLATFORM, + sizeof (GRUB_TARGET_CPU "-" GRUB_PLATFORM) - 1) == 0) + fwpath[len - (sizeof (GRUB_TARGET_CPU "-" GRUB_PLATFORM) - 1)] = 0; + path = fwpath; + } else grub_free (fwpath); if (device) @@ -205,6 +223,30 @@ grub_load_normal_mode (void) grub_command_execute ("normal", 0, 0); } +static void +reclaim_module_space (void) +{ + grub_addr_t modstart, modend; + + if (!grub_modbase) + return; + +#ifdef GRUB_MACHINE_PCBIOS + modstart = GRUB_MEMORY_MACHINE_DECOMPRESSION_ADDR; +#else + modstart = grub_modbase; +#endif + modend = grub_modules_get_end (); + grub_modbase = 0; + +#if GRUB_KERNEL_PRELOAD_SPACE_REUSABLE + grub_mm_init_region ((void *) modstart, modend - modstart); +#else + (void) modstart; + (void) modend; +#endif +} + /* The main routine. */ void __attribute__ ((noreturn)) grub_main (void) @@ -212,11 +254,17 @@ grub_main (void) /* First of all, initialize the machine. */ grub_machine_init (); + grub_boot_time ("After machine init."); + /* Hello. */ grub_setcolorstate (GRUB_TERM_COLOR_HIGHLIGHT); grub_printf ("Welcome to GRUB!\n\n"); grub_setcolorstate (GRUB_TERM_COLOR_STANDARD); + grub_load_config (); + + grub_boot_time ("Before loading embedded modules."); + /* Load pre-loaded modules and free the space. */ grub_register_exported_symbols (); #ifdef GRUB_LINKER_HAVE_INIT @@ -224,15 +272,28 @@ grub_main (void) #endif grub_load_modules (); + grub_boot_time ("After loading embedded modules."); + /* It is better to set the root device as soon as possible, for convenience. */ grub_set_prefix_and_root (); grub_env_export ("root"); grub_env_export ("prefix"); + /* Reclaim space used for modules. */ + reclaim_module_space (); + + grub_boot_time ("After reclaiming module space."); + grub_register_core_commands (); - grub_load_config (); + grub_boot_time ("Before execution of embedded config."); + + if (load_config) + grub_parser_execute (load_config); + + grub_boot_time ("After execution of embedded config. Attempt to go to normal mode"); + grub_load_normal_mode (); grub_rescue_run (); } diff --git a/grub-core/kern/misc.c b/grub-core/kern/misc.c index c3203a0..143b52c 100644 --- a/grub-core/kern/misc.c +++ b/grub-core/kern/misc.c @@ -1138,3 +1138,42 @@ void __deregister_frame_info (void) } #endif +#if BOOT_TIME_STATS + +#include <grub/time.h> + +struct grub_boot_time *grub_boot_time_head; +static struct grub_boot_time **boot_time_last = &grub_boot_time_head; + +void +grub_real_boot_time (const char *file, + const int line, + const char *fmt, ...) +{ + struct grub_boot_time *n; + va_list args; + + grub_error_push (); + n = grub_malloc (sizeof (*n)); + if (!n) + { + grub_errno = 0; + grub_error_pop (); + return; + } + n->file = file; + n->line = line; + n->tp = grub_get_time_ms (); + n->next = 0; + + va_start (args, fmt); + n->msg = grub_xvasprintf (fmt, args); + va_end (args); + + *boot_time_last = n; + boot_time_last = &n->next; + + grub_errno = 0; + grub_error_pop (); +} +#endif diff --git a/grub-core/kern/term.c b/grub-core/kern/term.c index 34096bc..ad79566 100644 --- a/grub-core/kern/term.c +++ b/grub-core/kern/term.c @@ -32,7 +32,7 @@ struct grub_term_input *grub_term_inputs; grub_uint8_t grub_term_normal_color; grub_uint8_t grub_term_highlight_color; -void (*grub_term_poll_usb) (void) = NULL; +void (*grub_term_poll_usb) (int wait_for_completion) = NULL; void (*grub_net_poll_cards_idle) (void) = NULL; /* Put a Unicode character. */ @@ -90,7 +90,7 @@ grub_getkey_noblock (void) grub_term_input_t term; if (grub_term_poll_usb) - grub_term_poll_usb (); + grub_term_poll_usb (0); if (grub_net_poll_cards_idle) grub_net_poll_cards_idle (); diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c index 07f337d..9aaa3b2 100644 --- a/grub-core/normal/main.c +++ b/grub-core/normal/main.c @@ -296,6 +296,8 @@ grub_normal_execute (const char *config, int nested, int batch) grub_register_variable_hook ("prefix", NULL, read_lists_hook); } + grub_boot_time ("Executing config file"); + if (config) { menu = read_config_file (config); @@ -304,10 +306,14 @@ grub_normal_execute (const char *config, int nested, int batch) grub_errno = GRUB_ERR_NONE; } + grub_boot_time ("Executed config file"); + if (! batch) { if (menu && menu->size) { + + grub_boot_time ("Entering menu"); grub_show_menu (menu, nested, 0); if (nested) grub_normal_free_menu (menu); @@ -319,12 +325,15 @@ grub_normal_execute (const char *config, int nested, int batch) void grub_enter_normal_mode (const char *config) { + grub_boot_time ("Entering normal mode"); nested_level++; grub_normal_execute (config, 0, 0); + grub_boot_time ("Entering shell"); grub_cmdline_run (0); nested_level--; if (grub_normal_exit_level) grub_normal_exit_level--; + grub_boot_time ("Exiting normal mode"); } /* Enter normal mode from rescue mode. */ @@ -504,6 +513,8 @@ GRUB_MOD_INIT(normal) { unsigned i; + grub_boot_time ("Preparing normal module"); + /* Previously many modules depended on gzio. Be nice to user and load it. */ grub_dl_load ("gzio"); grub_errno = 0; @@ -556,6 +567,8 @@ GRUB_MOD_INIT(normal) grub_env_export ("grub_cpu"); grub_env_set ("grub_platform", GRUB_PLATFORM); grub_env_export ("grub_platform"); + + grub_boot_time ("Normal module prepared"); } GRUB_MOD_FINI(normal) diff --git a/grub-core/normal/term.c b/grub-core/normal/term.c index dc03268..507f996 100644 --- a/grub-core/normal/term.c +++ b/grub-core/normal/term.c @@ -979,20 +979,21 @@ grub_ucs4_count_lines (const grub_uint32_t * str, } void -grub_xputs_normal (const char *str) +grub_xnputs (const char *str, grub_size_t msg_len) { grub_uint32_t *unicode_str = NULL, *unicode_last_position; int backlog = 0; grub_term_output_t term; grub_error_push (); - grub_utf8_to_ucs4_alloc (str, &unicode_str, - &unicode_last_position); + + unicode_str = grub_malloc (msg_len * sizeof (grub_uint32_t)); + grub_error_pop (); if (!unicode_str) { - for (; *str; str++) + for (; msg_len--; str++, msg_len++) { struct grub_unicode_glyph c = { @@ -1021,6 +1022,10 @@ grub_xputs_normal (const char *str) return; } + msg_len = grub_utf8_to_ucs4 (unicode_str, msg_len, + (grub_uint8_t *) str, -1, 0); + unicode_last_position = unicode_str + msg_len; + FOR_ACTIVE_TERM_OUTPUTS(term) { int cur; @@ -1045,6 +1050,12 @@ grub_xputs_normal (const char *str) } void +grub_xputs_normal (const char *str) +{ + grub_xnputs (str, grub_strlen (str)); +} + +void grub_cls (void) { struct grub_term_output *term; diff --git a/grub-core/term/i386/coreboot/cbmemc.c b/grub-core/term/i386/coreboot/cbmemc.c new file mode 100644 index 0000000..c58d671 --- /dev/null +++ b/grub-core/term/i386/coreboot/cbmemc.c @@ -0,0 +1,127 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 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/term.h> +#include <grub/types.h> +#include <grub/misc.h> +#include <grub/mm.h> +#include <grub/time.h> +#include <grub/terminfo.h> +#include <grub/dl.h> +#include <grub/machine/lbio.h> +#include <grub/command.h> +#include <grub/normal.h> + +GRUB_MOD_LICENSE ("GPLv3+"); + +struct grub_linuxbios_cbmemc +{ + grub_uint32_t size; + grub_uint32_t pointer; + char data[0]; +}; + +static struct grub_linuxbios_cbmemc *cbmemc; + +static void +put (struct grub_term_output *term __attribute__ ((unused)), const int c) +{ + if (!cbmemc) + return; + if (cbmemc->pointer < cbmemc->size) + cbmemc->data[cbmemc->pointer] = c; + cbmemc->pointer++; +} + +struct grub_terminfo_output_state grub_cbmemc_terminfo_output = + { + .put = put, + .width = 80, + .height = 24 + }; + +static struct grub_term_output grub_cbmemc_term_output = + { + .name = "cbmemc", + .init = grub_terminfo_output_init, + .fini = 0, + .putchar = grub_terminfo_putchar, + .getxy = grub_terminfo_getxy, + .getwh = grub_terminfo_getwh, + .gotoxy = grub_terminfo_gotoxy, + .cls = grub_terminfo_cls, + .setcolorstate = grub_terminfo_setcolorstate, + .setcursor = grub_terminfo_setcursor, + .flags = GRUB_TERM_CODE_TYPE_ASCII, + .data = &grub_cbmemc_terminfo_output, + }; + +static int +iterate_linuxbios_table (grub_linuxbios_table_item_t table_item, + void *data __attribute__ ((unused))) +{ + if (table_item->tag != GRUB_LINUXBIOS_MEMBER_CBMEMC) + return 0; + cbmemc = (struct grub_linuxbios_cbmemc *) (grub_addr_t) + *(grub_uint64_t *) (table_item + 1); + return 1; +} + +static grub_err_t +grub_cmd_cbmemc (struct grub_command *cmd __attribute__ ((unused)), + int argc __attribute__ ((unused)), + char *argv[] __attribute__ ((unused))) +{ + grub_size_t len; + char *str; + struct grub_linuxbios_cbmemc *cbmemc_saved; + + if (!cbmemc) + return grub_error (GRUB_ERR_IO, "no CBMEM console found"); + + len = cbmemc->pointer; + if (len > cbmemc->size) + len = cbmemc->size; + str = cbmemc->data; + cbmemc_saved = cbmemc; + cbmemc = 0; + grub_xnputs (str, len); + cbmemc = cbmemc_saved; + return 0; +} + +static grub_command_t cmd; + +GRUB_MOD_INIT (cbmemc) +{ + grub_linuxbios_table_iterate (iterate_linuxbios_table, 0); + + if (cbmemc) + grub_term_register_output ("cbmemc", &grub_cbmemc_term_output); + + cmd = + grub_register_command ("cbmemc", grub_cmd_cbmemc, + 0, N_("Show CBMEM console content.")); +} + + +GRUB_MOD_FINI (cbmemc) +{ + grub_term_unregister_output (&grub_cbmemc_term_output); + grub_unregister_command (cmd); +} diff --git a/grub-core/term/usb_keyboard.c b/grub-core/term/usb_keyboard.c index ae00936..3b74846 100644 --- a/grub-core/term/usb_keyboard.c +++ b/grub-core/term/usb_keyboard.c @@ -244,7 +244,7 @@ grub_usb_keyboard_attach (grub_usb_device_t usbdev, int configno, int interfno) #endif data->transfer = grub_usb_bulk_read_background (usbdev, - data->endp->endp_addr, + data->endp, sizeof (data->report), (char *) data->report); if (!data->transfer) @@ -394,7 +394,7 @@ grub_usb_keyboard_getkey (struct grub_term_input *term) sizeof (termdata->report)); termdata->transfer = grub_usb_bulk_read_background (termdata->usbdev, - termdata->endp->endp_addr, + termdata->endp, sizeof (termdata->report), (char *) termdata->report); if (!termdata->transfer) |