From e7f59a65345484ede230500400b774db8c9a6d6f Mon Sep 17 00:00:00 2001 From: Fathi Boudra Date: Sat, 30 Mar 2013 17:41:12 +0200 Subject: Imported Upstream version 2.00+bzr4618+20130322 --- ChangeLog | 384 +++++++++++++++++++++++ config.h.in | 5 + configure.ac | 19 ++ grub-core/Makefile.am | 27 +- grub-core/Makefile.core.def | 47 ++- grub-core/bus/usb/ehci.c | 8 + grub-core/bus/usb/serial/common.c | 15 +- grub-core/bus/usb/serial/ftdi.c | 6 +- grub-core/bus/usb/serial/pl2303.c | 6 +- grub-core/bus/usb/serial/usbdebug_late.c | 93 ++++++ grub-core/bus/usb/usb.c | 78 +---- grub-core/bus/usb/usbhub.c | 355 ++++++++++++++------- grub-core/bus/usb/usbtrans.c | 60 +++- grub-core/commands/boottime.c | 65 ++++ grub-core/commands/i386/cmosdump.c | 64 ++++ grub-core/commands/i386/coreboot/cb_timestamps.c | 118 +++++++ grub-core/commands/i386/coreboot/cbls.c | 128 ++++++++ grub-core/commands/keystatus.c | 2 +- grub-core/commands/lsacpi.c | 77 ++++- grub-core/commands/terminal.c | 12 +- grub-core/commands/usbtest.c | 2 +- grub-core/commands/verify.c | 5 +- grub-core/disk/cryptodisk.c | 5 +- grub-core/disk/ieee1275/ofdisk.c | 59 +++- grub-core/disk/usbms.c | 27 +- grub-core/fs/fshelp.c | 8 +- grub-core/fs/xfs.c | 4 +- grub-core/kern/dl.c | 3 + grub-core/kern/elfXX.c | 144 +++++++++ grub-core/kern/i386/coreboot/mmap.c | 2 +- grub-core/kern/i386/pit.c | 49 --- grub-core/kern/main.c | 81 ++++- grub-core/kern/misc.c | 39 +++ grub-core/kern/term.c | 4 +- grub-core/normal/main.c | 13 + grub-core/normal/term.c | 19 +- grub-core/term/i386/coreboot/cbmemc.c | 127 ++++++++ grub-core/term/usb_keyboard.c | 4 +- include/grub/acpi.h | 31 +- include/grub/boottime.h | 0 include/grub/i386/coreboot/lbio.h | 30 ++ include/grub/ieee1275/ofdisk.h | 3 + include/grub/kernel.h | 25 ++ include/grub/misc.h | 20 ++ include/grub/normal.h | 3 + include/grub/term.h | 2 +- include/grub/usb.h | 31 +- include/grub/usbdesc.h | 9 + include/grub/usbserial.h | 7 +- po/POTFILES.in | 1 - 50 files changed, 2004 insertions(+), 322 deletions(-) create mode 100644 grub-core/bus/usb/serial/usbdebug_late.c create mode 100644 grub-core/commands/boottime.c create mode 100644 grub-core/commands/i386/cmosdump.c create mode 100644 grub-core/commands/i386/coreboot/cb_timestamps.c create mode 100644 grub-core/commands/i386/coreboot/cbls.c create mode 100644 grub-core/kern/elfXX.c delete mode 100644 grub-core/kern/i386/pit.c create mode 100644 grub-core/term/i386/coreboot/cbmemc.c create mode 100644 include/grub/boottime.h diff --git a/ChangeLog b/ChangeLog index 74ef434..bcc2f92 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,387 @@ +2013-03-20 Vladimir Serbinenko + + * grub-core/commands/verify.c (hashes): Add several hashes + from the spec. + +2013-03-20 Vladimir Serbinenko + + Slight improve in USB-related boot-time checkpoints. + +2013-03-20 Vladimir Serbinenko + + * grub-core/commands/boottime.c: Fix copyright header. + +2013-03-20 Vladimir Serbinenko + + New commands cbmemc, lscoreboot, coreboot_boottime to inspect + coreboot tables content. Support for cbmemc. + +2013-03-20 Vladimir Serbinenko + + Fix a conflict between ports structures with 2 controllers of + same kind. + +2013-03-20 Vladimir Serbinenko + + * include/grub/boottime.h: Add missing file. + +2013-03-19 Vladimir Serbinenko + + Initialize USB ports in parallel to speed-up boot. + +2013-03-19 Vladimir Serbinenko + + Fix USB devices not being detected when requested + due to delayed attach. + +2013-03-19 Vladimir Serbinenko + + Implement boot time analysis framework. + +2013-03-19 Vladimir Serbinenko + + Remove get_endpoint_descriptor and change all functions needing + descriptor to just receive it as argument rather than endpoint + address. + +2013-03-19 Aleš Nesrsta + + Better estimate the maximum USB transfer size. + +2013-03-17 Vladimir Serbinenko + + Resend a packet if we got the wrong buffer in status. + +2013-03-10 Vladimir Serbinenko + + * grub-core/loader/i386/bsdXX.c (grub_openbsd_find_ramdisk): Use + multiplication rather than division. + +2013-03-10 Vladimir Serbinenko + + * grub-core/lib/arg.c (grub_arg_list_alloc): Use shifts rather + than divisions. + +2013-03-10 Vladimir Serbinenko + + * grub-core/commands/verify.c (grub_verify_signature): Use unsigned + operations to have intended shifts and not divisions. + +2013-03-10 Vladimir Serbinenko + + * grub-core/loader/i386/pc/plan9.c (fill_disk): Fix types to use + intended shifts rather than division. + +2013-03-10 Vladimir Serbinenko + + * include/grub/datetime.h (grub_datetime2unixtime): Fix unixtime + computation for some years before epoch. Avode confusing division + while on it. + +2013-03-10 Vladimir Serbinenko + + * grub-core/video/i386/pc/vbe.c + (grub_video_vbe_print_adapter_specific_info): Replace division by + shifts. + +2013-03-10 Vladimir Serbinenko + + Adjust types in gdb module to have intended unsigned shifts rather than + signed divisions. + +2013-03-10 Vladimir Serbinenko + + * grub-core/fs/hfs.c (grub_hfs_read_file): Avoid divmod64 since the + maximum size is 4G - 1 on hfs + +2013-03-10 Vladimir Serbinenko + + Avoid costly 64-bit division in grub_get_time_ms on most platforms. + +2013-03-10 Vladimir Serbinenko + + * grub-core/fs/fshelp.c (grub_fshelp_log2blksize): Remove now unused + function. + +2013-03-07 Andrey Borzenkov + + * grub-core/fs/iso9660.c (add_part): Remove always_inline attribute + causing gcc error with gcc 4.7.1. + +2013-03-07 Nickolai Zeldovich + + * grub-core/commands/acpi.c (grub_acpi_create_ebda): Don't + dereference null pointer. While the code is technically correct, gcc + may eliminate a null check if pointer is already dereferenced. + +2013-03-07 Nickolai Zeldovich + + * grub-core/normal/crypto.c (read_crypto_list): Fix incorrect + OOM check. + * grub-core/normal/term.c (read_terminal_list): Likewise. + +2013-03-07 Vladimir Serbinenko + + Lift up core size limits on some platforms. Fix potential memory + corruption with big core on small memory systems. Document remaining + limits. + +2013-03-05 Vladimir Serbinenko + + * grub-core/term/terminfo.c (grub_terminfo_cls): Issue an explicit + gotoxy to 0,0. + +2013-03-03 Vladimir Serbinenko + + Remove all trampoline support. Add -Wtrampolines when + present. Remove symbols used for trampolines to make + link fail if trampolines are present. + +2013-03-03 Vladimir Serbinenko + + * grub-core/script/execute.c (grub_script_arglist_to_argv): Move + append out of its parent. + +2013-03-03 Vladimir Serbinenko + + * grub-core/commands/regexp.c (set_matches): Move setvar out of its + parent. + +2013-03-03 Vladimir Serbinenko + + * grub-core/kern/env.c, include/grub/env.h: Change iterator through + all vars to a macro. All users updated. + +2013-03-03 Vladimir Serbinenko + + * grub-core/disk/ieee1275/nand.c: Fix compilation on + i386-ieee1275. + +2013-03-02 Vladimir Serbinenko + + * include/grub/cmos.h: Handle high CMOS addresses on sparc64. + +2013-03-02 Vladimir Serbinenko + + * include/grub/mips/loongson/cmos.h: Fix high CMOS addresses. + +2013-03-02 Vladimir Serbinenko + + Move to more hookless approach in IEEE1275 devices handling. + +2013-03-02 Vladimir Serbinenko + + * grub-core/kern/term.c (grub_term_normal_color), + (grub_term_highlight_color): Add back lost defaults. + +2013-03-02 Vladimir Serbinenko + + Make elfload not use hooks. Opt for flags and iterators instead. + +2013-03-02 Vladimir Serbinenko + + * grub-core/lib/ia64/longjmp.S: Fix the name of longjmp function. + * grub-core/lib/ia64/setjmp.S: Fix the name of setjmp function. + +2013-03-02 Vladimir Serbinenko + + * grub-core/script/execute.c (gettext_append): Remove nested functions. + +2013-03-02 Vladimir Serbinenko + + * grub-core/normal/charset.c (grub_bidi_logical_to_visual): Add + hook pass-through parameter. All users updated and unnested. + +2013-03-02 Vladimir Serbinenko + + * grub-core/commands/loadenv.c (grub_cmd_list_env): Move print_var + out of its parent. + +2013-03-02 Vladimir Serbinenko + + * grub-core/fs/hfs.c: Remove nested functions. + +2013-03-01 Vladimir Serbinenko + + * grub-core/fs/hfsplus.c (grub_hfsplus_btree_iterate_node): Pass + the context through. + (grub_hfsplus_iterate_dir): Move nested function out of its parent. + +2013-03-01 Vladimir Serbinenko + + * util/grub-editenv.c (list_variables): Move print_var out of its + parent. + +2013-03-01 Vladimir Serbinenko + + * grub-core/kern/emu/hostdisk.c (read_device_map): Remove nested + function. + +2013-03-01 Vladimir Serbinenko + + * grub-core/gentrigtables.c: Make tables const. + +2013-03-01 Vladimir Serbinenko + + Remove nested functions from videoinfo iterators. + +2013-03-01 Vladimir Serbinenko + + * grub-core/loader/i386/pc/linux.c (grub_cmd_linux): Fix compilation + for 64-bit platforms. + +2013-03-01 Vladimir Serbinenko + + * grub-core/disk/efi/efidisk.c: Transform iterate_child_devices into + a FOR_CHILDREN macro. + +2013-03-01 Vladimir Serbinenko + + * grub-core/kern/main.c (grub_set_prefix_and_root): Strip trailing + platform from firmware path. + +2013-02-28 Vladimir Serbinenko + + Enable linux16 on non-BIOS systems for i.a. memtest. + + * grub-core/loader/i386/pc/linux.c (grub_cmd_linux): Handle hole at 0 + correctly. + * grub-core/Makefile.core.def (linux16): Enable on all x86 flavours. + +2013-02-28 Vladimir Serbinenko + + * grub-core/kern/i386/coreboot/mmap.c (grub_linuxbios_table_iterate): + Fix end of table condition. + +2013-02-28 Vladimir Serbinenko + + * grub-core/lib/arg.c (grub_arg_show_help): Move showargs + out of its parent. + +2013-02-28 Vladimir Serbinenko + + * grub-core/fs/jfs.c: Remove nested functions. + +2013-02-28 Vladimir Serbinenko + + * grub-core/fs/minix.c: Remove nested functions. + +2013-02-28 Vladimir Serbinenko + + * grub-core/fs/iso9660.c: Remove nested functions. + +2013-02-28 Vladimir Serbinenko + + * grub-core/commands/parttool.c (grub_cmd_parttool): Move show_help out + of parent function. + +2013-02-28 Vladimir Serbinenko + + * util/grub-fstest.c: Remove nested functions. + +2013-02-27 Vladimir Serbinenko + + * grub-core/loader/machoXX.c: Remove nested functions. + +2013-02-27 Colin Watson + + Remove nested functions from disk and file read hooks. + + * include/grub/disk.h (grub_disk_read_hook_t): New type. + (struct grub_disk): Add read_hook_data member. + * include/grub/file.h (struct grub_file): Likewise. + * include/grub/fshelp.h (grub_fshelp_read_file): Add read_hook_data + argument. + + Update all callers. + +2012-02-27 Andrey Borzenkov + + * grub-core/partmap/msdos.c (grub_partition_msdos_iterate): + Fix off by one error in enumerating extended partitions. + +2013-02-26 Andrey Borzenkov + + * grub-core/disk/efi/efidisk.c(grub_efidisk_get_device_name): Fix + memory leak if device name is not found. + +2013-02-25 Andrey Borzenkov + + * grub-core/normal/menu_entry.c (update_screen): remove + unused variable `off' which caused scroll down arrow to be always shown. + +2013-02-25 Andrey Borzenkov + + * grub-core/normal/menu_entry.c (insert_string): fix off by one + access to unallocated memory. + +2013-02-25 Andrey Borzenkov + + * Makefile.util.def: Add partmap/msdos.c to common library. + * include/grub/msdos_partition.h: Add GRUB_PC_PARTITION_TYPE_LDM + * grub-core/disk/ldm.c: Check for existence of + GRUB_PC_PARTITION_TYPE_LDM. + +2013-02-25 Vladimir Serbinenko + + * grub-core/normal/misc.c (grub_normal_print_device_info): Use KiB to display + sizes and display sector size. + +2013-02-24 Vladimir Serbinenko + + Implement new command cmosdump. + +2013-02-19 Paulo Flabiano Smorigo + + Support Openfirmware disks with non-512B sectors. + + * grub-core/disk/ieee1275/ofdisk.c (grub_ofdisk_open): Get the block + size of the disk. + * (grub_ofdisk_get_block_size): New function. + * (grub_ofdisk_prepare): Use the correct block size. + * (grub_ofdisk_read): Likewise. + * (grub_ofdisk_write): Likewise. + * include/grub/ieee1275/ofdisk.h (grub_ofdisk_get_block_size): + New proto. + +2013-02-06 Vladimir Serbinenko + + * grub-core/commands/lsacpi.c: Fix types on 64-bit platform. + +2013-02-04 Vladimir Serbinenko + + * grub-core/disk/cryptodisk.c (grub_cryptodisk_scan_device): Don't stop + on first error. + +2013-02-01 Vladimir Serbinenko + + * grub-core/fs/fshelp.c (find_file): Set oldnode to zero after + freeing it. + +2013-02-01 Vladimir Serbinenko + + Implement USBDebug (full USB stack variant). + +2013-02-01 Vladimir Serbinenko + + * grub-core/commands/lsacpi.c: Show more info. Hide some boring parts + unless they have unexpected values. + +2013-02-01 Vladimir Serbinenko + + * grub-core/bus/usb/usb.c (grub_usb_device_attach): Add missing + grub_print_error. + +2013-02-01 Vladimir Serbinenko + + * grub-core/bus/usb/serial/common.c (grub_usbserial_attach): Fix missing + zero-out of port structure. + +2013-01-30 Vladimir Serbinenko + + * grub-core/fs/xfs.c (grub_xfs_read_block): Fix computation in presence + of extended attributes. + 2013-01-27 Andrey Borzenkov * util/grub-install.in: change misleading comment about diff --git a/config.h.in b/config.h.in index a7eaf19..e965615 100644 --- a/config.h.in +++ b/config.h.in @@ -5,6 +5,11 @@ #if defined(__PPC__) && !defined(__powerpc__) #define __powerpc__ 1 #endif + +/* Define to 1 to enable disk cache statistics. */ +#define DISK_CACHE_STATS @DISK_CACHE_STATS@ +#define BOOT_TIME_STATS @BOOT_TIME_STATS@ + #if defined (GRUB_UTIL) || !defined (GRUB_MACHINE) #include #define NESTED_FUNC_ATTR diff --git a/configure.ac b/configure.ac index 45a3289..b78fe9c 100644 --- a/configure.ac +++ b/configure.ac @@ -815,6 +815,17 @@ else fi AC_SUBST([DISK_CACHE_STATS]) +AC_ARG_ENABLE([boot-time], + AS_HELP_STRING([--enable-boot-time], + [enable boot time statistics collection])) + +if test x$enable_boot_time = xyes; then + BOOT_TIME_STATS=1 +else + BOOT_TIME_STATS=0 +fi +AC_SUBST([BOOT_TIME_STATS]) + AC_ARG_ENABLE([grub-emu-usb], [AS_HELP_STRING([--enable-grub-emu-usb], [build and install the `grub-emu' debugging utility with USB support (default=guessed)])]) @@ -1178,6 +1189,7 @@ AM_CONDITIONAL([COND_GRUB_PE2ELF], [test x$TARGET_OBJ2ELF != x]) AM_CONDITIONAL([COND_APPLE_CC], [test x$TARGET_APPLE_CC = x1]) AM_CONDITIONAL([COND_ENABLE_EFIEMU], [test x$enable_efiemu = xyes]) AM_CONDITIONAL([COND_ENABLE_CACHE_STATS], [test x$DISK_CACHE_STATS = x1]) +AM_CONDITIONAL([COND_ENABLE_BOOT_TIME_STATS], [test x$BOOT_TIME_STATS = x1]) AM_CONDITIONAL([COND_HAVE_ASM_USCORE], [test x$HAVE_ASM_USCORE = x1]) AM_CONDITIONAL([COND_CYGWIN], [test x$host_os = xcygwin]) @@ -1250,6 +1262,13 @@ echo With disk cache statistics: Yes else echo With disk cache statistics: No fi + +if [ x"$enable_boot_time" = xyes ]; then +echo With boot time statistics: Yes +else +echo With boot time statistics: No +fi + if [ x"$efiemu_excuse" = x ]; then echo efiemu runtime: Yes else 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; @@ -460,6 +457,12 @@ module = { enable = usb; }; +module = { + name = usbserial_usbdebug; + common = bus/usb/serial/usbdebug_late.c; + enable = usb; +}; + module = { name = uhci; common = bus/usb/uhci.c; @@ -516,12 +519,36 @@ module = { enable = cmos; }; +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; @@ -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 = { @@ -1882,6 +1907,12 @@ module = { condition = COND_ENABLE_CACHE_STATS; }; +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 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +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 #include + +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 . + */ + +#include +#include +#include +#include + +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 . + */ + +#include +#include +#include +#include +#include + +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 . + */ + +#include +#include +#include +#include +#include +#include + +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 . + */ + +#include +#include +#include +#include +#include +#include + +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 . - */ - -#include -#include -#include - -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 #include -/* 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 +#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 + +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; @@ -1044,6 +1049,12 @@ grub_xputs_normal (const char *str) grub_free (unicode_str); } +void +grub_xputs_normal (const char *str) +{ + grub_xnputs (str, grub_strlen (str)); +} + void grub_cls (void) { 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 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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) diff --git a/include/grub/acpi.h b/include/grub/acpi.h index ee0a108..52d190c 100644 --- a/include/grub/acpi.h +++ b/include/grub/acpi.h @@ -88,12 +88,32 @@ struct grub_acpi_madt enum { + GRUB_ACPI_MADT_ENTRY_TYPE_LAPIC = 0, + GRUB_ACPI_MADT_ENTRY_TYPE_IOAPIC = 1, GRUB_ACPI_MADT_ENTRY_TYPE_INTERRUPT_OVERRIDE = 2, + GRUB_ACPI_MADT_ENTRY_TYPE_LAPIC_NMI = 4, GRUB_ACPI_MADT_ENTRY_TYPE_SAPIC = 6, GRUB_ACPI_MADT_ENTRY_TYPE_LSAPIC = 7, GRUB_ACPI_MADT_ENTRY_TYPE_PLATFORM_INT_SOURCE = 8 }; +struct grub_acpi_madt_entry_lapic +{ + struct grub_acpi_madt_entry_header hdr; + grub_uint8_t acpiid; + grub_uint8_t apicid; + grub_uint32_t flags; +}; + +struct grub_acpi_madt_entry_ioapic +{ + struct grub_acpi_madt_entry_header hdr; + grub_uint8_t id; + grub_uint8_t pad; + grub_uint32_t address; + grub_uint32_t global_sys_interrupt; +}; + struct grub_acpi_madt_entry_interrupt_override { struct grub_acpi_madt_entry_header hdr; @@ -101,7 +121,16 @@ struct grub_acpi_madt_entry_interrupt_override grub_uint8_t source; grub_uint32_t global_sys_interrupt; grub_uint16_t flags; -}; +} __attribute__ ((packed)); + + +struct grub_acpi_madt_entry_lapic_nmi +{ + struct grub_acpi_madt_entry_header hdr; + grub_uint8_t acpiid; + grub_uint16_t flags; + grub_uint8_t lint; +} __attribute__ ((packed)); struct grub_acpi_madt_entry_sapic { diff --git a/include/grub/boottime.h b/include/grub/boottime.h new file mode 100644 index 0000000..e69de29 diff --git a/include/grub/i386/coreboot/lbio.h b/include/grub/i386/coreboot/lbio.h index aa18539..b84e812 100644 --- a/include/grub/i386/coreboot/lbio.h +++ b/include/grub/i386/coreboot/lbio.h @@ -27,11 +27,36 @@ struct grub_linuxbios_table_header }; typedef struct grub_linuxbios_table_header *grub_linuxbios_table_header_t; +struct grub_linuxbios_timestamp_entry +{ + grub_uint32_t id; + grub_uint64_t tsc; +} __attribute__((packed)); + +struct grub_linuxbios_timestamp_table +{ + grub_uint64_t base_tsc; + grub_uint32_t capacity; + grub_uint32_t used; + struct grub_linuxbios_timestamp_entry entries[0]; +} __attribute__((packed)); + +struct grub_linuxbios_mainboard +{ + grub_uint8_t vendor; + grub_uint8_t part_number; + char strings[0]; +}; + struct grub_linuxbios_table_item { #define GRUB_LINUXBIOS_MEMBER_UNUSED 0x00 #define GRUB_LINUXBIOS_MEMBER_MEMORY 0x01 +#define GRUB_LINUXBIOS_MEMBER_MAINBOARD 0x03 +#define GRUB_LINUXBIOS_MEMBER_CONSOLE 0x10 #define GRUB_LINUXBIOS_MEMBER_LINK 0x11 +#define GRUB_LINUXBIOS_MEMBER_TIMESTAMPS 0x16 +#define GRUB_LINUXBIOS_MEMBER_CBMEMC 0x17 grub_uint32_t tag; grub_uint32_t size; }; @@ -46,4 +71,9 @@ struct grub_linuxbios_mem_region }; typedef struct grub_linuxbios_mem_region *mem_region_t; +grub_err_t +EXPORT_FUNC(grub_linuxbios_table_iterate) (int (*hook) (grub_linuxbios_table_item_t, + void *), + void *hook_data); + #endif diff --git a/include/grub/ieee1275/ofdisk.h b/include/grub/ieee1275/ofdisk.h index 2f69e3f..3f58317 100644 --- a/include/grub/ieee1275/ofdisk.h +++ b/include/grub/ieee1275/ofdisk.h @@ -22,4 +22,7 @@ extern void grub_ofdisk_init (void); extern void grub_ofdisk_fini (void); +extern grub_err_t grub_ofdisk_get_block_size (const char *device, + grub_uint32_t *block_size); + #endif /* ! GRUB_INIT_HEADER */ diff --git a/include/grub/kernel.h b/include/grub/kernel.h index 23e4f02..5b7ddda 100644 --- a/include/grub/kernel.h +++ b/include/grub/kernel.h @@ -64,6 +64,29 @@ struct grub_module_info64 grub_uint64_t size; }; +#ifndef GRUB_UTIL +/* Space isn't reusable on some platforms. */ +/* On Qemu the preload space is readonly. */ +/* On emu there is no preload space. */ +/* On ieee1275 our code assumes that heap is p=v which isn't guaranteed for module space. */ +#if defined (GRUB_MACHINE_QEMU) || defined (GRUB_MACHINE_EMU) \ + || defined (GRUB_MACHINE_EFI) \ + || (defined (GRUB_MACHINE_IEEE1275) && !defined (__sparc__)) +#define GRUB_KERNEL_PRELOAD_SPACE_REUSABLE 0 +#endif + +#if defined (GRUB_MACHINE_PCBIOS) || defined (GRUB_MACHINE_COREBOOT) \ + || defined (GRUB_MACHINE_MULTIBOOT) || defined (GRUB_MACHINE_MIPS_QEMU_MIPS) \ + || defined (GRUB_MACHINE_MIPS_LOONGSON) || defined (GRUB_MACHINE_ARC) \ + || defined (__sparc__) || defined (GRUB_MACHINE_ARM) +/* FIXME: stack is between 2 heap regions. Move it. */ +#define GRUB_KERNEL_PRELOAD_SPACE_REUSABLE 1 +#endif + +#ifndef GRUB_KERNEL_PRELOAD_SPACE_REUSABLE +#error "Please check if preload space is reusable on this platform!" +#endif + #if GRUB_TARGET_SIZEOF_VOID_P == 8 #define grub_module_info grub_module_info64 #else @@ -82,6 +105,8 @@ extern grub_addr_t EXPORT_VAR (grub_modbase); grub_addr_t grub_modules_get_end (void); +#endif + /* The start point of the C code. */ void grub_main (void) __attribute__ ((noreturn)); diff --git a/include/grub/misc.h b/include/grub/misc.h index 33e6b73..82276ad 100644 --- a/include/grub/misc.h +++ b/include/grub/misc.h @@ -462,4 +462,24 @@ grub_error_load (const struct grub_error_saved *save) grub_errno = save->grub_errno; } +#if BOOT_TIME_STATS +struct grub_boot_time +{ + struct grub_boot_time *next; + grub_uint64_t tp; + const char *file; + int line; + char *msg; +}; + +extern struct grub_boot_time *EXPORT_VAR(grub_boot_time_head); + +void EXPORT_FUNC(grub_real_boot_time) (const char *file, + const int line, + const char *fmt, ...) __attribute__ ((format (printf, 3, 4))); +#define grub_boot_time(fmt, args...) grub_real_boot_time(GRUB_FILE, __LINE__, fmt, ## args) +#else +#define grub_boot_time(fmt, args...) +#endif + #endif /* ! GRUB_MISC_HEADER */ diff --git a/include/grub/normal.h b/include/grub/normal.h index 416faa4..4fcc3da 100644 --- a/include/grub/normal.h +++ b/include/grub/normal.h @@ -141,6 +141,9 @@ void grub_normal_free_menu (grub_menu_t menu); void grub_normal_auth_init (void); void grub_normal_auth_fini (void); +void +grub_xnputs (const char *str, grub_size_t msg_len); + grub_command_t grub_dyncmd_get_cmd (grub_command_t cmd); diff --git a/include/grub/term.h b/include/grub/term.h index 84f5766..655a5e3 100644 --- a/include/grub/term.h +++ b/include/grub/term.h @@ -467,7 +467,7 @@ grub_print_spaces (struct grub_term_output *term, int number_spaces) grub_putcode (' ', term); } -extern void (*EXPORT_VAR (grub_term_poll_usb)) (void); +extern void (*EXPORT_VAR (grub_term_poll_usb)) (int wait_for_completion); #define GRUB_TERM_REPEAT_PRE_INTERVAL 400 #define GRUB_TERM_REPEAT_INTERVAL 50 diff --git a/include/grub/usb.h b/include/grub/usb.h index cefa8b6..718ed33 100644 --- a/include/grub/usb.h +++ b/include/grub/usb.h @@ -63,9 +63,6 @@ grub_usb_err_t grub_usb_get_descriptor (grub_usb_device_t dev, grub_uint8_t type, grub_uint8_t index, grub_size_t size, char *data); -struct grub_usb_desc_endp * -grub_usb_get_endpdescriptor (grub_usb_device_t usbdev, int addr); - grub_usb_err_t grub_usb_clear_halt (grub_usb_device_t dev, int endpoint); @@ -87,10 +84,12 @@ grub_usb_err_t grub_usb_control_msg (grub_usb_device_t dev, grub_uint8_t reqtype grub_usb_err_t grub_usb_bulk_read (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); grub_usb_err_t grub_usb_bulk_write (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); grub_usb_err_t grub_usb_root_hub (grub_usb_controller_t controller); @@ -164,6 +163,18 @@ struct grub_usb_configuration struct grub_usb_interface interf[32]; }; +struct grub_usb_hub_port +{ + grub_uint64_t soft_limit_time; + grub_uint64_t hard_limit_time; + enum { + PORT_STATE_NORMAL = 0, + PORT_STATE_WAITING_FOR_STABLE_POWER = 1, + PORT_STATE_FAILED_DEVICE = 2, + PORT_STATE_STABLE_POWER = 3, + } state; +}; + struct grub_usb_device { /* The device descriptor of this device. */ @@ -198,6 +209,8 @@ struct grub_usb_device /* Number of hub ports. */ unsigned nports; + struct grub_usb_hub_port *ports; + grub_usb_transfer_t hub_transfer; grub_uint32_t statuschange; @@ -285,16 +298,18 @@ struct grub_usb_attach_desc void grub_usb_register_attach_hook_class (struct grub_usb_attach_desc *desc); void grub_usb_unregister_attach_hook_class (struct grub_usb_attach_desc *desc); -void grub_usb_poll_devices (void); +void grub_usb_poll_devices (int wait_for_completion); void grub_usb_device_attach (grub_usb_device_t dev); 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); 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 grub_usb_check_transfer (grub_usb_transfer_t trans, grub_size_t *actual); void diff --git a/include/grub/usbdesc.h b/include/grub/usbdesc.h index 84b723a..7d14152 100644 --- a/include/grub/usbdesc.h +++ b/include/grub/usbdesc.h @@ -28,6 +28,7 @@ typedef enum { GRUB_USB_DESCRIPTOR_STRING, GRUB_USB_DESCRIPTOR_INTERFACE, GRUB_USB_DESCRIPTOR_ENDPOINT, + GRUB_USB_DESCRIPTOR_DEBUG = 10, GRUB_USB_DESCRIPTOR_HUB = 0x29 } grub_usb_descriptor_t; @@ -111,6 +112,14 @@ struct grub_usb_desc_str grub_uint16_t str[0]; } __attribute__ ((packed)); +struct grub_usb_desc_debug +{ + grub_uint8_t length; + grub_uint8_t type; + grub_uint8_t in_endp; + grub_uint8_t out_endp; +} __attribute__ ((packed)); + struct grub_usb_usb_hubdesc { grub_uint8_t length; diff --git a/include/grub/usbserial.h b/include/grub/usbserial.h index 7420125..f81f97a 100644 --- a/include/grub/usbserial.h +++ b/include/grub/usbserial.h @@ -27,7 +27,12 @@ void grub_usbserial_detach (grub_usb_device_t usbdev, int configno, 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); +enum + { + GRUB_USB_SERIAL_ENDPOINT_LAST_MATCHING = -1 + }; int grub_usbserial_fetch (struct grub_serial_port *port, grub_size_t header_size); diff --git a/po/POTFILES.in b/po/POTFILES.in index 01cc53c..f2368fd 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -327,7 +327,6 @@ ./grub-core/kern/i386/multiboot_mmap.c ./grub-core/kern/i386/pc/init.c ./grub-core/kern/i386/pc/mmap.c -./grub-core/kern/i386/pit.c ./grub-core/kern/i386/qemu/mmap.c ./grub-core/kern/i386/tsc.c ./grub-core/kern/ia64/dl.c -- cgit v1.2.3