diff --git a/configure.ac b/configure.ac
index edd184154f7e9aad556b6437b8ec22bc79d5a057..c7888e40f6695ee23a43fb98420d6cbcd3d86622 100644
--- a/configure.ac
+++ b/configure.ac
@@ -31,7 +31,7 @@ dnl (such as BUILD_CC, BUILD_CFLAGS, etc.) for the build type and variables
dnl with the prefix "TARGET_" (such as TARGET_CC, TARGET_CFLAGS, etc.) are
dnl used for the target type. See INSTALL for full list of variables.
-AC_INIT([GRUB],[2.02],[bug-grub@gnu.org])
+AC_INIT([GRUB],[2.03],[bug-grub@gnu.org])
AC_CONFIG_AUX_DIR([build-aux])
@@ -167,6 +167,7 @@ case "$target_cpu"-"$platform" in
mipsel-fuloong) platform=loongson ;;
mipsel-loongson) ;;
arm-uboot) ;;
+ arm-coreboot) ;;
arm-efi) ;;
arm64-efi) ;;
*-emu) ;;
@@ -203,7 +204,8 @@ case "$host_os" in
esac
case "$host_os" in
- cygwin | windows* | mingw32*) have_exec=n ;;
+ cygwin) have_exec=y ;;
+ windows* | mingw32*) have_exec=n ;;
aros*) have_exec=n ;;
*) have_exec=y;;
esac
@@ -373,7 +375,10 @@ case "$host_os" in
;;
*)
AC_CHECK_SIZEOF(off_t)
- test x"$ac_cv_sizeof_off_t" = x8 || AC_MSG_ERROR([Large file support is required]);;
+ if test x"$ac_cv_sizeof_off_t" != x8 ; then
+ AC_CHECK_SIZEOF(off64_t)
+ test x"$ac_cv_sizeof_off64_t" = x8 || AC_MSG_ERROR([Large file support is required])
+ fi;;
esac
if test x$USE_NLS = xno; then
@@ -456,6 +461,16 @@ case "$build_os" in
esac
AC_SUBST(BUILD_EXEEXT)
+# In some build environments like termux /bin/sh is not a valid
+# shebang. Use $SHELL instead if it's executable and /bin/sh isn't
+BUILD_SHEBANG=/bin/sh
+for she in /bin/sh "$SHELL"; do
+ if test -x "$she" ; then
+ BUILD_SHEBANG="$she"
+ fi
+done
+AC_SUBST(BUILD_SHEBANG)
+
# For gnulib.
gl_INIT
@@ -1905,6 +1920,7 @@ AM_CONDITIONAL([COND_mipsel], [test x$target_cpu = xmipsel])
AM_CONDITIONAL([COND_mipseb], [test x$target_cpu = xmips])
AM_CONDITIONAL([COND_arm], [test x$target_cpu = xarm ])
AM_CONDITIONAL([COND_arm_uboot], [test x$target_cpu = xarm -a x$platform = xuboot])
+AM_CONDITIONAL([COND_arm_coreboot], [test x$target_cpu = xarm -a x$platform = xcoreboot])
AM_CONDITIONAL([COND_arm_efi], [test x$target_cpu = xarm -a x$platform = xefi])
AM_CONDITIONAL([COND_arm64], [test x$target_cpu = xarm64 ])
AM_CONDITIONAL([COND_arm64_efi], [test x$target_cpu = xarm64 -a x$platform = xefi])
diff --git a/Makefile.util.def b/Makefile.util.def
index f9caccb9780ffe8d4b31c8a19399ba7bbd308e56..3180ac880a9aa86e94fb47a7386bfa324425bff0 100644
--- a/Makefile.util.def
+++ b/Makefile.util.def
@@ -99,6 +99,7 @@ library = {
common = grub-core/fs/ext2.c;
common = grub-core/fs/fat.c;
common = grub-core/fs/exfat.c;
+ common = grub-core/fs/f2fs.c;
common = grub-core/fs/fshelp.c;
common = grub-core/fs/hfs.c;
common = grub-core/fs/hfsplus.c;
@@ -774,6 +775,12 @@ script = {
common = tests/xfs_test.in;
};
+script = {
+ testcase;
+ name = f2fs_test;
+ common = tests/f2fs_test.in;
+};
+
script = {
testcase;
name = nilfs2_test;
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index 2dfa22a9271bd6624fad9b91ce051ac12202dfbd..9590e87d9c080d6675a9521d91ef6a47d39f2751 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -68,11 +68,11 @@ kernel = {
i386_pc_ldflags = '$(TARGET_IMG_LDFLAGS)';
i386_pc_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x9000';
i386_qemu_ldflags = '$(TARGET_IMG_LDFLAGS)';
- i386_qemu_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x8200';
+ i386_qemu_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x9000';
i386_coreboot_ldflags = '$(TARGET_IMG_LDFLAGS)';
- i386_coreboot_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x8200';
+ i386_coreboot_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x9000';
i386_multiboot_ldflags = '$(TARGET_IMG_LDFLAGS)';
- i386_multiboot_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x8200';
+ i386_multiboot_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x9000';
i386_ieee1275_ldflags = '$(TARGET_IMG_LDFLAGS)';
i386_ieee1275_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x10000';
i386_xen_ldflags = '$(TARGET_IMG_LDFLAGS)';
@@ -92,6 +92,8 @@ kernel = {
emu_cppflags = '$(CPPFLAGS_GNULIB)';
arm_uboot_ldflags = '-Wl,-r,-d';
arm_uboot_stripflags = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version';
+ arm_coreboot_ldflags = '-Wl,-r,-d';
+ arm_coreboot_stripflags = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version';
i386_pc_startup = kern/i386/pc/startup.S;
i386_efi_startup = kern/i386/efi/startup.S;
@@ -105,7 +107,8 @@ kernel = {
mips_startup = kern/mips/startup.S;
sparc64_ieee1275_startup = kern/sparc64/ieee1275/crt0.S;
powerpc_ieee1275_startup = kern/powerpc/ieee1275/startup.S;
- arm_uboot_startup = kern/arm/uboot/startup.S;
+ arm_uboot_startup = kern/arm/startup.S;
+ arm_coreboot_startup = kern/arm/startup.S;
arm_efi_startup = kern/arm/efi/startup.S;
arm64_efi_startup = kern/arm64/efi/startup.S;
@@ -149,6 +152,21 @@ kernel = {
uboot = kern/uboot/init.c;
uboot = kern/uboot/hw.c;
uboot = term/uboot/console.c;
+ arm_uboot = kern/arm/uboot/init.c;
+ arm_uboot = kern/arm/uboot/uboot.S;
+
+ arm_coreboot = kern/arm/coreboot/init.c;
+ arm_coreboot = kern/arm/coreboot/timer.c;
+ arm_coreboot = kern/arm/coreboot/coreboot.S;
+ arm_coreboot = lib/fdt.c;
+ arm_coreboot = bus/fdt.c;
+ arm_coreboot = term/ps2.c;
+ arm_coreboot = term/arm/pl050.c;
+ arm_coreboot = term/arm/cros.c;
+ arm_coreboot = term/arm/cros_ec.c;
+ arm_coreboot = bus/spi/rk3288_spi.c;
+ arm_coreboot = commands/keylayouts.c;
+ arm_coreboot = kern/arm/coreboot/dma.c;
terminfoinkernel = term/terminfo.c;
terminfoinkernel = term/tparm.c;
@@ -164,7 +182,7 @@ kernel = {
i386_multiboot = kern/i386/coreboot/init.c;
i386_qemu = kern/i386/qemu/init.c;
i386_coreboot_multiboot_qemu = term/i386/pc/vga_text.c;
- i386_coreboot = video/i386/coreboot/cbfb.c;
+ coreboot = video/coreboot/cbfb.c;
efi = disk/efi/efidisk.c;
efi = kern/efi/efi.c;
@@ -211,7 +229,6 @@ kernel = {
ia64_efi = kern/ia64/cache.c;
arm_efi = kern/arm/efi/init.c;
- arm_efi = kern/arm/efi/misc.c;
arm_efi = kern/efi/fdt.c;
arm64_efi = kern/arm64/efi/init.c;
@@ -225,8 +242,10 @@ kernel = {
i386_qemu = kern/vga_init.c;
i386_qemu = kern/i386/qemu/mmap.c;
- i386_coreboot = kern/i386/coreboot/mmap.c;
+ coreboot = kern/coreboot/mmap.c;
i386_coreboot = kern/i386/coreboot/cbtable.c;
+ coreboot = kern/coreboot/cbtable.c;
+ arm_coreboot = kern/arm/coreboot/cbtable.c;
i386_multiboot = kern/i386/multiboot_mmap.c;
@@ -238,6 +257,7 @@ kernel = {
mips_qemu_mips = term/ns8250.c;
mips_qemu_mips = term/serial.c;
mips_qemu_mips = term/at_keyboard.c;
+ mips_qemu_mips = term/ps2.c;
mips_qemu_mips = commands/boot.c;
mips_qemu_mips = commands/keylayouts.c;
mips_qemu_mips = term/i386/pc/vga_text.c;
@@ -253,6 +273,7 @@ kernel = {
mips_loongson = bus/pci.c;
mips_loongson = kern/mips/loongson/init.c;
mips_loongson = term/at_keyboard.c;
+ mips_loongson = term/ps2.c;
mips_loongson = commands/boot.c;
mips_loongson = term/serial.c;
mips_loongson = video/sm712.c;
@@ -574,7 +595,10 @@ module = {
module = {
name = ehci;
common = bus/usb/ehci.c;
+ arm_coreboot = bus/usb/ehci-fdt.c;
+ pci = bus/usb/ehci-pci.c;
enable = pci;
+ enable = arm_coreboot;
};
module = {
@@ -641,6 +665,7 @@ module = {
module = {
name = cbtable;
common = kern/i386/coreboot/cbtable.c;
+ common = kern/coreboot/cbtable.c;
enable = i386_pc;
enable = i386_efi;
enable = i386_qemu;
@@ -754,6 +779,7 @@ module = {
enable = arm_efi;
enable = arm64_efi;
enable = arm_uboot;
+ enable = arm_coreboot;
};
module = {
@@ -837,17 +863,14 @@ module = {
efi = lib/efi/halt.c;
ieee1275 = lib/ieee1275/halt.c;
emu = lib/emu/halt.c;
- uboot = lib/uboot/halt.c;
+ uboot = lib/dummy/halt.c;
+ arm_coreboot = lib/dummy/halt.c;
};
module = {
name = reboot;
i386 = lib/i386/reboot.c;
i386 = lib/i386/reboot_trampoline.S;
- ia64_efi = lib/efi/reboot.c;
- x86_64_efi = lib/efi/reboot.c;
- arm_efi = lib/efi/reboot.c;
- arm64_efi = lib/efi/reboot.c;
powerpc_ieee1275 = lib/ieee1275/reboot.c;
sparc64_ieee1275 = lib/ieee1275/reboot.c;
mips_arc = lib/mips/arc/reboot.c;
@@ -855,6 +878,7 @@ module = {
mips_qemu_mips = lib/mips/qemu_mips/reboot.c;
xen = lib/xen/reboot.c;
uboot = lib/uboot/reboot.c;
+ arm_coreboot = lib/dummy/reboot.c;
common = commands/reboot.c;
};
@@ -873,7 +897,6 @@ module = {
module = {
name = hdparm;
common = commands/hdparm.c;
- common = lib/hexdump.c;
enable = pci;
enable = mips_qemu_mips;
};
@@ -1290,6 +1313,11 @@ module = {
common = fs/exfat.c;
};
+module = {
+ name = f2fs;
+ common = fs/f2fs.c;
+};
+
module = {
name = fshelp;
common = fs/fshelp.c;
@@ -1548,7 +1576,8 @@ module = {
name = datetime;
cmos = lib/cmos_datetime.c;
efi = lib/efi/datetime.c;
- uboot = lib/uboot/datetime.c;
+ uboot = lib/dummy/datetime.c;
+ arm_coreboot = lib/dummy/datetime.c;
sparc64_ieee1275 = lib/ieee1275/datetime.c;
powerpc_ieee1275 = lib/ieee1275/datetime.c;
sparc64_ieee1275 = lib/ieee1275/cmos.c;
@@ -1601,8 +1630,6 @@ module = {
module = {
name = linux16;
common = loader/i386/pc/linux.c;
- common = loader/linux.c;
- common = lib/cmdline.c;
enable = x86;
};
@@ -1637,7 +1664,6 @@ module = {
cppflags = "-DGRUB_USE_MULTIBOOT2";
common = loader/multiboot.c;
- common = lib/cmdline.c;
common = loader/multiboot_mbi2.c;
enable = x86;
enable = mips;
@@ -1646,7 +1672,6 @@ module = {
module = {
name = multiboot;
common = loader/multiboot.c;
- common = lib/cmdline.c;
x86 = loader/i386/multiboot_mbi.c;
extra_dist = loader/multiboot_elfxx.c;
enable = x86;
@@ -1654,7 +1679,6 @@ module = {
module = {
name = xen_boot;
- common = lib/cmdline.c;
arm64 = loader/arm64/xen_boot.c;
enable = arm64;
};
@@ -1668,7 +1692,9 @@ module = {
powerpc_ieee1275 = loader/powerpc/ieee1275/linux.c;
sparc64_ieee1275 = loader/sparc64/ieee1275/linux.c;
ia64_efi = loader/ia64/efi/linux.c;
- arm = loader/arm/linux.c;
+ arm_coreboot = loader/arm/linux.c;
+ arm_efi = loader/arm64/linux.c;
+ arm_uboot = loader/arm/linux.c;
arm64 = loader/arm64/linux.c;
common = loader/linux.c;
common = lib/cmdline.c;
@@ -1677,7 +1703,7 @@ module = {
module = {
name = fdt;
- arm64 = loader/arm64/fdt.c;
+ efi = loader/efi/fdt.c;
common = lib/fdt.c;
enable = fdt;
};
@@ -1869,6 +1895,7 @@ module = {
module = {
name = at_keyboard;
common = term/at_keyboard.c;
+ common = term/ps2.c;
enable = x86;
};
@@ -1961,6 +1988,11 @@ module = {
common = tests/example_functional_test.c;
};
+module = {
+ name = strtoull_test;
+ common = tests/strtoull_test.c;
+};
+
module = {
name = setjmp_test;
common = tests/setjmp_test.c;
diff --git a/grub-core/bus/fdt.c b/grub-core/bus/fdt.c
new file mode 100644
index 0000000000000000000000000000000000000000..135da497ba67e7545490e0e73ee3a1fa676a6069
--- /dev/null
+++ b/grub-core/bus/fdt.c
@@ -0,0 +1,256 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2016 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
+
+static const void *dtb;
+static grub_size_t root_address_cells, root_size_cells;
+/* Pointer to this symbol signals invalid mapping. */
+char grub_fdtbus_invalid_mapping[1];
+
+struct grub_fdtbus_dev *devs;
+struct grub_fdtbus_driver *drivers;
+
+int
+grub_fdtbus_is_compatible (const char *compat_string,
+ const struct grub_fdtbus_dev *dev)
+{
+ grub_size_t compatible_size;
+ const char *compatible = grub_fdt_get_prop (dtb, dev->node, "compatible",
+ &compatible_size);
+ if (!compatible)
+ return 0;
+ const char *compatible_end = compatible + compatible_size;
+ while (compatible < compatible_end)
+ {
+ if (grub_strcmp (compat_string, compatible) == 0)
+ return 1;
+ compatible += grub_strlen (compatible) + 1;
+ }
+ return 0;
+}
+
+static void
+fdtbus_scan (struct grub_fdtbus_dev *parent)
+{
+ int node;
+ for (node = grub_fdt_first_node (dtb, parent ? parent->node : 0); node >= 0;
+ node = grub_fdt_next_node (dtb, node))
+ {
+ struct grub_fdtbus_dev *dev;
+ struct grub_fdtbus_driver *driver;
+ dev = grub_zalloc (sizeof (*dev));
+ if (!dev)
+ {
+ grub_print_error ();
+ return;
+ }
+ dev->node = node;
+ dev->next = devs;
+ dev->parent = parent;
+ devs = dev;
+ FOR_LIST_ELEMENTS(driver, drivers)
+ if (!dev->driver && grub_fdtbus_is_compatible (driver->compatible, dev))
+ {
+ grub_dprintf ("fdtbus", "Attaching %s\n", driver->compatible);
+ if (driver->attach (dev) == GRUB_ERR_NONE)
+ {
+ grub_dprintf ("fdtbus", "Attached %s\n", driver->compatible);
+ dev->driver = driver;
+ break;
+ }
+ grub_print_error ();
+ }
+ fdtbus_scan (dev);
+ }
+}
+
+void
+grub_fdtbus_register (struct grub_fdtbus_driver *driver)
+{
+ struct grub_fdtbus_dev *dev;
+ grub_dprintf ("fdtbus", "Registering %s\n", driver->compatible);
+ grub_list_push (GRUB_AS_LIST_P (&drivers),
+ GRUB_AS_LIST (driver));
+ for (dev = devs; dev; dev = dev->next)
+ if (!dev->driver && grub_fdtbus_is_compatible (driver->compatible, dev))
+ {
+ grub_dprintf ("fdtbus", "Attaching %s (%p)\n", driver->compatible, dev);
+ if (driver->attach (dev) == GRUB_ERR_NONE)
+ {
+ grub_dprintf ("fdtbus", "Attached %s\n", driver->compatible);
+ dev->driver = driver;
+ }
+ grub_print_error ();
+ }
+}
+
+void
+grub_fdtbus_unregister (struct grub_fdtbus_driver *driver)
+{
+ grub_list_remove (GRUB_AS_LIST (driver));
+ struct grub_fdtbus_dev *dev;
+ for (dev = devs; dev; dev = dev->next)
+ if (dev->driver == driver)
+ {
+ if (driver->detach)
+ driver->detach(dev);
+ dev->driver = 0;
+ }
+}
+
+void
+grub_fdtbus_init (const void *dtb_in, grub_size_t size)
+{
+ if (!dtb_in || grub_fdt_check_header (dtb_in, size) < 0)
+ grub_fatal ("invalid FDT");
+ dtb = dtb_in;
+ const grub_uint32_t *prop = grub_fdt_get_prop (dtb, 0, "#address-cells", 0);
+ if (prop)
+ root_address_cells = grub_be_to_cpu32 (*prop);
+ else
+ root_address_cells = 1;
+
+ prop = grub_fdt_get_prop (dtb, 0, "#size-cells", 0);
+ if (prop)
+ root_size_cells = grub_be_to_cpu32 (*prop);
+ else
+ root_size_cells = 1;
+
+ fdtbus_scan (0);
+}
+
+static int
+get_address_cells (const struct grub_fdtbus_dev *dev)
+{
+ const grub_uint32_t *prop;
+ if (!dev)
+ return root_address_cells;
+ prop = grub_fdt_get_prop (dtb, dev->node, "#address-cells", 0);
+ if (prop)
+ return grub_be_to_cpu32 (*prop);
+ return 1;
+}
+
+static int
+get_size_cells (const struct grub_fdtbus_dev *dev)
+{
+ const grub_uint32_t *prop;
+ if (!dev)
+ return root_size_cells;
+ prop = grub_fdt_get_prop (dtb, dev->node, "#size-cells", 0);
+ if (prop)
+ return grub_be_to_cpu32 (*prop);
+ return 1;
+}
+
+static grub_uint64_t
+get64 (const grub_uint32_t *reg, grub_size_t cells)
+{
+ grub_uint64_t val = 0;
+ if (cells >= 1)
+ val = grub_be_to_cpu32 (reg[cells - 1]);
+ if (cells >= 2)
+ val |= ((grub_uint64_t) grub_be_to_cpu32 (reg[cells - 2])) << 32;
+ return val;
+}
+
+static volatile void *
+translate (const struct grub_fdtbus_dev *dev, const grub_uint32_t *reg)
+{
+ volatile void *ret;
+ const grub_uint32_t *ranges;
+ grub_size_t ranges_size, cells_per_mapping;
+ grub_size_t parent_address_cells, child_address_cells, child_size_cells;
+ grub_size_t nmappings, i;
+ if (dev == 0)
+ {
+ grub_uint64_t val;
+ val = get64 (reg, root_address_cells);
+ if (sizeof (void *) == 4 && (val >> 32))
+ return grub_fdtbus_invalid_mapping;
+ return (void *) (grub_addr_t) val;
+ }
+ ranges = grub_fdt_get_prop (dtb, dev->node, "ranges", &ranges_size);
+ if (!ranges)
+ return grub_fdtbus_invalid_mapping;
+ if (ranges_size == 0)
+ return translate (dev->parent, reg);
+ parent_address_cells = get_address_cells (dev->parent);
+ child_address_cells = get_address_cells (dev);
+ child_size_cells = get_size_cells (dev);
+ cells_per_mapping = parent_address_cells + child_address_cells + child_size_cells;
+ nmappings = ranges_size / 4 / cells_per_mapping;
+ for (i = 0; i < nmappings; i++)
+ {
+ const grub_uint32_t *child_addr = &ranges[i * cells_per_mapping];
+ const grub_uint32_t *parent_addr = child_addr + child_address_cells;
+ grub_uint64_t child_size = get64 (parent_addr + parent_address_cells, child_size_cells);
+
+ if (child_address_cells > 2 && grub_memcmp (reg, child_addr, (child_address_cells - 2) * 4) != 0)
+ continue;
+ if (get64 (reg, child_address_cells) < get64 (child_addr, child_address_cells))
+ continue;
+
+ grub_uint64_t offset = get64 (reg, child_address_cells) - get64 (child_addr, child_address_cells);
+ if (offset >= child_size)
+ continue;
+
+ ret = translate (dev->parent, parent_addr);
+ if (grub_fdtbus_is_mapping_valid (ret))
+ ret = (volatile char *) ret + offset;
+ return ret;
+ }
+ return grub_fdtbus_invalid_mapping;
+}
+
+volatile void *
+grub_fdtbus_map_reg (const struct grub_fdtbus_dev *dev, int regno, grub_size_t *size)
+{
+ grub_size_t address_cells, size_cells;
+ address_cells = get_address_cells (dev->parent);
+ size_cells = get_size_cells (dev->parent);
+ const grub_uint32_t *reg = grub_fdt_get_prop (dtb, dev->node, "reg", 0);
+ if (size && size_cells)
+ *size = reg[(address_cells + size_cells) * regno + address_cells];
+ if (size && !size_cells)
+ *size = 0;
+ return translate (dev->parent, reg + (address_cells + size_cells) * regno);
+}
+
+const char *
+grub_fdtbus_get_name (const struct grub_fdtbus_dev *dev)
+{
+ return grub_fdt_get_nodename (dtb, dev->node);
+}
+
+const void *
+grub_fdtbus_get_prop (const struct grub_fdtbus_dev *dev,
+ const char *name,
+ grub_uint32_t *len)
+{
+ return grub_fdt_get_prop (dtb, dev->node, name, len);
+}
+
+const void *
+grub_fdtbus_get_fdt (void)
+{
+ return dtb;
+}
diff --git a/grub-core/bus/spi/rk3288_spi.c b/grub-core/bus/spi/rk3288_spi.c
new file mode 100644
index 0000000000000000000000000000000000000000..aacb79ffef103bdbff1bb66dd70229b85b1e8030
--- /dev/null
+++ b/grub-core/bus/spi/rk3288_spi.c
@@ -0,0 +1,103 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ *
+ * Copyright (C) 2012 Google Inc.
+ * Copyright (C) 2016 Free Software Foundation, Inc.
+ *
+ * This is based on depthcharge code.
+ *
+ * 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
+
+static grub_err_t
+spi_send (const struct grub_fdtbus_dev *dev, const void *data, grub_size_t sz)
+{
+ const grub_uint8_t *ptr = data, *end = ptr + sz;
+ volatile grub_uint32_t *spi = grub_fdtbus_map_reg (dev, 0, 0);
+ spi[2] = 0;
+ spi[1] = sz - 1;
+ spi[0] = ((1 << 18) | spi[0]) & ~(1 << 19);
+ spi[2] = 1;
+ while (ptr < end)
+ {
+ while (spi[9] & 2);
+ spi[256] = *ptr++;
+ }
+ while (spi[9] & 1);
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+spi_receive (const struct grub_fdtbus_dev *dev, void *data, grub_size_t sz)
+{
+ grub_uint8_t *ptr = data, *end = ptr + sz;
+ volatile grub_uint32_t *spi = grub_fdtbus_map_reg (dev, 0, 0);
+ spi[2] = 0;
+ spi[1] = sz - 1;
+ spi[0] = ((1 << 19) | spi[0]) & ~(1 << 18);
+ spi[2] = 1;
+ while (ptr < end)
+ {
+ while (spi[9] & 8);
+ *ptr++ = spi[512];
+ }
+ while (spi[9] & 1);
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+spi_start (const struct grub_fdtbus_dev *dev)
+{
+ volatile grub_uint32_t *spi = grub_fdtbus_map_reg (dev, 0, 0);
+ spi[3] = 1;
+ return GRUB_ERR_NONE;
+}
+
+static void
+spi_stop (const struct grub_fdtbus_dev *dev)
+{
+ volatile grub_uint32_t *spi = grub_fdtbus_map_reg (dev, 0, 0);
+ spi[3] = 0;
+}
+
+static grub_err_t
+spi_attach(const struct grub_fdtbus_dev *dev)
+{
+ if (!grub_fdtbus_is_mapping_valid (grub_fdtbus_map_reg (dev, 0, 0)))
+ return GRUB_ERR_IO;
+
+ return GRUB_ERR_NONE;
+}
+
+static struct grub_fdtbus_driver spi =
+{
+ .compatible = "rockchip,rk3288-spi",
+ .attach = spi_attach,
+ .send = spi_send,
+ .receive = spi_receive,
+ .start = spi_start,
+ .stop = spi_stop,
+};
+
+void
+grub_rk3288_spi_init (void)
+{
+ grub_fdtbus_register (&spi);
+}
diff --git a/grub-core/bus/usb/ehci-fdt.c b/grub-core/bus/usb/ehci-fdt.c
new file mode 100644
index 0000000000000000000000000000000000000000..29b50bdd5c30d192cc3cba1d7f466a9bcf321d92
--- /dev/null
+++ b/grub-core/bus/usb/ehci-fdt.c
@@ -0,0 +1,45 @@
+/* ehci.c - EHCI Support. */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2011 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * 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
+
+static grub_err_t
+ehci_attach(const struct grub_fdtbus_dev *dev)
+{
+ grub_dprintf ("ehci", "Found generic-ehci\n");
+
+ grub_ehci_init_device (grub_fdtbus_map_reg (dev, 0, 0));
+ return 0;
+}
+
+struct grub_fdtbus_driver ehci =
+{
+ .compatible = "generic-ehci",
+ .attach = ehci_attach
+};
+
+void
+grub_ehci_pci_scan (void)
+{
+ grub_fdtbus_register (&ehci);
+}
diff --git a/grub-core/bus/usb/ehci-pci.c b/grub-core/bus/usb/ehci-pci.c
new file mode 100644
index 0000000000000000000000000000000000000000..65e6cb57438b7dfa35b80bbbe36a1e50629f025f
--- /dev/null
+++ b/grub-core/bus/usb/ehci-pci.c
@@ -0,0 +1,208 @@
+/* ehci.c - EHCI Support. */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2011 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * 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
+
+#define GRUB_EHCI_PCI_SBRN_REG 0x60
+#define GRUB_EHCI_ADDR_MEM_MASK (~0xff)
+
+/* USBLEGSUP bits and related OS OWNED byte offset */
+enum
+{
+ GRUB_EHCI_BIOS_OWNED = (1 << 16),
+ GRUB_EHCI_OS_OWNED = (1 << 24)
+};
+
+/* PCI iteration function... */
+static int
+grub_ehci_pci_iter (grub_pci_device_t dev, grub_pci_id_t pciid,
+ void *data __attribute__ ((unused)))
+{
+ volatile grub_uint32_t *regs;
+ grub_uint32_t base, base_h;
+ grub_uint32_t eecp_offset;
+ grub_uint32_t usblegsup = 0;
+ grub_uint64_t maxtime;
+ grub_uint32_t interf;
+ grub_uint32_t subclass;
+ grub_uint32_t class;
+ grub_uint8_t release;
+ grub_uint32_t class_code;
+
+ grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: begin\n");
+
+ if (pciid == GRUB_CS5536_PCIID)
+ {
+ grub_uint64_t basereg;
+
+ basereg = grub_cs5536_read_msr (dev, GRUB_CS5536_MSR_USB_EHCI_BASE);
+ if (!(basereg & GRUB_CS5536_MSR_USB_BASE_MEMORY_ENABLE))
+ {
+ /* Shouldn't happen. */
+ grub_dprintf ("ehci", "No EHCI address is assigned\n");
+ return 0;
+ }
+ base = (basereg & GRUB_CS5536_MSR_USB_BASE_ADDR_MASK);
+ basereg |= GRUB_CS5536_MSR_USB_BASE_BUS_MASTER;
+ basereg &= ~GRUB_CS5536_MSR_USB_BASE_PME_ENABLED;
+ basereg &= ~GRUB_CS5536_MSR_USB_BASE_PME_STATUS;
+ basereg &= ~GRUB_CS5536_MSR_USB_BASE_SMI_ENABLE;
+ grub_cs5536_write_msr (dev, GRUB_CS5536_MSR_USB_EHCI_BASE, basereg);
+ }
+ else
+ {
+ grub_pci_address_t addr;
+ addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS);
+ class_code = grub_pci_read (addr) >> 8;
+ interf = class_code & 0xFF;
+ subclass = (class_code >> 8) & 0xFF;
+ class = class_code >> 16;
+
+ /* If this is not an EHCI controller, just return. */
+ if (class != 0x0c || subclass != 0x03 || interf != 0x20)
+ return 0;
+
+ grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: class OK\n");
+
+ /* Check Serial Bus Release Number */
+ addr = grub_pci_make_address (dev, GRUB_EHCI_PCI_SBRN_REG);
+ release = grub_pci_read_byte (addr);
+ if (release != 0x20)
+ {
+ grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: Wrong SBRN: %0x\n",
+ release);
+ return 0;
+ }
+ grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: bus rev. num. OK\n");
+
+ /* Determine EHCI EHCC registers base address. */
+ addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0);
+ base = grub_pci_read (addr);
+ addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG1);
+ base_h = grub_pci_read (addr);
+ /* Stop if registers are mapped above 4G - GRUB does not currently
+ * work with registers mapped above 4G */
+ if (((base & GRUB_PCI_ADDR_MEM_TYPE_MASK) != GRUB_PCI_ADDR_MEM_TYPE_32)
+ && (base_h != 0))
+ {
+ grub_dprintf ("ehci",
+ "EHCI grub_ehci_pci_iter: registers above 4G are not supported\n");
+ return 0;
+ }
+ base &= GRUB_PCI_ADDR_MEM_MASK;
+ if (!base)
+ {
+ grub_dprintf ("ehci",
+ "EHCI: EHCI is not mapped\n");
+ return 0;
+ }
+
+ /* Set bus master - needed for coreboot, VMware, broken BIOSes etc. */
+ addr = grub_pci_make_address (dev, GRUB_PCI_REG_COMMAND);
+ grub_pci_write_word(addr,
+ GRUB_PCI_COMMAND_MEM_ENABLED
+ | GRUB_PCI_COMMAND_BUS_MASTER
+ | grub_pci_read_word(addr));
+
+ grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: 32-bit EHCI OK\n");
+ }
+
+ grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: iobase of EHCC: %08x\n",
+ (base & GRUB_EHCI_ADDR_MEM_MASK));
+
+ regs = grub_pci_device_map_range (dev,
+ (base & GRUB_EHCI_ADDR_MEM_MASK),
+ 0x100);
+
+ /* Is there EECP ? */
+ eecp_offset = (grub_le_to_cpu32 (regs[2]) >> 8) & 0xff;
+
+ /* Determine and change ownership. */
+ /* EECP offset valid in HCCPARAMS */
+ /* Ownership can be changed via EECP only */
+ if (pciid != GRUB_CS5536_PCIID && eecp_offset >= 0x40)
+ {
+ grub_pci_address_t pciaddr_eecp;
+ pciaddr_eecp = grub_pci_make_address (dev, eecp_offset);
+
+ usblegsup = grub_pci_read (pciaddr_eecp);
+ if (usblegsup & GRUB_EHCI_BIOS_OWNED)
+ {
+ grub_boot_time ("Taking ownership of EHCI controller");
+ grub_dprintf ("ehci",
+ "EHCI grub_ehci_pci_iter: EHCI owned by: BIOS\n");
+ /* Ownership change - set OS_OWNED bit */
+ grub_pci_write (pciaddr_eecp, usblegsup | GRUB_EHCI_OS_OWNED);
+ /* Ensure PCI register is written */
+ grub_pci_read (pciaddr_eecp);
+
+ /* Wait for finish of ownership change, EHCI specification
+ * doesn't say how long it can take... */
+ maxtime = grub_get_time_ms () + 1000;
+ while ((grub_pci_read (pciaddr_eecp) & GRUB_EHCI_BIOS_OWNED)
+ && (grub_get_time_ms () < maxtime));
+ if (grub_pci_read (pciaddr_eecp) & GRUB_EHCI_BIOS_OWNED)
+ {
+ grub_dprintf ("ehci",
+ "EHCI grub_ehci_pci_iter: EHCI change ownership timeout");
+ /* Change ownership in "hard way" - reset BIOS ownership */
+ grub_pci_write (pciaddr_eecp, GRUB_EHCI_OS_OWNED);
+ /* Ensure PCI register is written */
+ grub_pci_read (pciaddr_eecp);
+ }
+ }
+ else if (usblegsup & GRUB_EHCI_OS_OWNED)
+ /* XXX: What to do in this case - nothing ? Can it happen ? */
+ grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: EHCI owned by: OS\n");
+ else
+ {
+ grub_dprintf ("ehci",
+ "EHCI grub_ehci_pci_iter: EHCI owned by: NONE\n");
+ /* XXX: What to do in this case ? Can it happen ?
+ * Is code below correct ? */
+ /* Ownership change - set OS_OWNED bit */
+ grub_pci_write (pciaddr_eecp, GRUB_EHCI_OS_OWNED);
+ /* Ensure PCI register is written */
+ grub_pci_read (pciaddr_eecp);
+ }
+
+ /* Disable SMI, just to be sure. */
+ pciaddr_eecp = grub_pci_make_address (dev, eecp_offset + 4);
+ grub_pci_write (pciaddr_eecp, 0);
+ /* Ensure PCI register is written */
+ grub_pci_read (pciaddr_eecp);
+ }
+
+ grub_dprintf ("ehci", "inithw: EHCI grub_ehci_pci_iter: ownership OK\n");
+
+ grub_ehci_init_device (regs);
+ return 0;
+}
+
+void
+grub_ehci_pci_scan (void)
+{
+ grub_pci_iterate (grub_ehci_pci_iter, NULL);
+}
diff --git a/grub-core/bus/usb/ehci.c b/grub-core/bus/usb/ehci.c
index 5f4297bb21ec4c28824abb0c442a87a3dd4a872e..d966fc21002602fab3f1b68668ddcb5bfa639442 100644
--- a/grub-core/bus/usb/ehci.c
+++ b/grub-core/bus/usb/ehci.c
@@ -22,13 +22,10 @@
#include
#include
#include
-#include
-#include
-#include
#include
#include
-#include
#include
+#include
#include
GRUB_MOD_LICENSE ("GPLv3+");
@@ -39,8 +36,6 @@ GRUB_MOD_LICENSE ("GPLv3+");
* - is not supporting interrupt transfers
*/
-#define GRUB_EHCI_PCI_SBRN_REG 0x60
-
/* Capability registers offsets */
enum
{
@@ -54,7 +49,6 @@ enum
#define GRUB_EHCI_EECP_MASK (0xff << 8)
#define GRUB_EHCI_EECP_SHIFT 8
-#define GRUB_EHCI_ADDR_MEM_MASK (~0xff)
#define GRUB_EHCI_POINTER_MASK (~0x1f)
/* Capability register SPARAMS bits */
@@ -85,13 +79,6 @@ enum
#define GRUB_EHCI_QH_EMPTY 1
-/* USBLEGSUP bits and related OS OWNED byte offset */
-enum
-{
- GRUB_EHCI_BIOS_OWNED = (1 << 16),
- GRUB_EHCI_OS_OWNED = (1 << 24)
-};
-
/* Operational registers offsets */
enum
{
@@ -455,9 +442,10 @@ grub_ehci_reset (struct grub_ehci *e)
sync_all_caches (e);
+ grub_dprintf ("ehci", "reset\n");
+
grub_ehci_oper_write32 (e, GRUB_EHCI_COMMAND,
- GRUB_EHCI_CMD_HC_RESET
- | grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND));
+ GRUB_EHCI_CMD_HC_RESET);
/* Ensure command is written */
grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND);
/* XXX: How long time could take reset of HC ? */
@@ -473,116 +461,24 @@ grub_ehci_reset (struct grub_ehci *e)
}
/* PCI iteration function... */
-static int
-grub_ehci_pci_iter (grub_pci_device_t dev, grub_pci_id_t pciid,
- void *data __attribute__ ((unused)))
+void
+grub_ehci_init_device (volatile void *regs)
{
- grub_uint8_t release;
- grub_uint32_t class_code;
- grub_uint32_t interf;
- grub_uint32_t subclass;
- grub_uint32_t class;
- grub_uint32_t base, base_h;
struct grub_ehci *e;
- grub_uint32_t eecp_offset;
grub_uint32_t fp;
int i;
- grub_uint32_t usblegsup = 0;
- grub_uint64_t maxtime;
grub_uint32_t n_ports;
grub_uint8_t caplen;
- grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: begin\n");
-
- if (pciid == GRUB_CS5536_PCIID)
- {
- grub_uint64_t basereg;
-
- basereg = grub_cs5536_read_msr (dev, GRUB_CS5536_MSR_USB_EHCI_BASE);
- if (!(basereg & GRUB_CS5536_MSR_USB_BASE_MEMORY_ENABLE))
- {
- /* Shouldn't happen. */
- grub_dprintf ("ehci", "No EHCI address is assigned\n");
- return 0;
- }
- base = (basereg & GRUB_CS5536_MSR_USB_BASE_ADDR_MASK);
- basereg |= GRUB_CS5536_MSR_USB_BASE_BUS_MASTER;
- basereg &= ~GRUB_CS5536_MSR_USB_BASE_PME_ENABLED;
- basereg &= ~GRUB_CS5536_MSR_USB_BASE_PME_STATUS;
- basereg &= ~GRUB_CS5536_MSR_USB_BASE_SMI_ENABLE;
- grub_cs5536_write_msr (dev, GRUB_CS5536_MSR_USB_EHCI_BASE, basereg);
- }
- else
- {
- grub_pci_address_t addr;
- addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS);
- class_code = grub_pci_read (addr) >> 8;
- interf = class_code & 0xFF;
- subclass = (class_code >> 8) & 0xFF;
- class = class_code >> 16;
-
- /* If this is not an EHCI controller, just return. */
- if (class != 0x0c || subclass != 0x03 || interf != 0x20)
- return 0;
-
- grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: class OK\n");
-
- /* Check Serial Bus Release Number */
- addr = grub_pci_make_address (dev, GRUB_EHCI_PCI_SBRN_REG);
- release = grub_pci_read_byte (addr);
- if (release != 0x20)
- {
- grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: Wrong SBRN: %0x\n",
- release);
- return 0;
- }
- grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: bus rev. num. OK\n");
-
- /* Determine EHCI EHCC registers base address. */
- addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0);
- base = grub_pci_read (addr);
- addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG1);
- base_h = grub_pci_read (addr);
- /* Stop if registers are mapped above 4G - GRUB does not currently
- * work with registers mapped above 4G */
- if (((base & GRUB_PCI_ADDR_MEM_TYPE_MASK) != GRUB_PCI_ADDR_MEM_TYPE_32)
- && (base_h != 0))
- {
- grub_dprintf ("ehci",
- "EHCI grub_ehci_pci_iter: registers above 4G are not supported\n");
- return 0;
- }
- base &= GRUB_PCI_ADDR_MEM_MASK;
- if (!base)
- {
- grub_dprintf ("ehci",
- "EHCI: EHCI is not mapped\n");
- return 0;
- }
-
- /* Set bus master - needed for coreboot, VMware, broken BIOSes etc. */
- addr = grub_pci_make_address (dev, GRUB_PCI_REG_COMMAND);
- grub_pci_write_word(addr,
- GRUB_PCI_COMMAND_MEM_ENABLED
- | GRUB_PCI_COMMAND_BUS_MASTER
- | grub_pci_read_word(addr));
-
- grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: 32-bit EHCI OK\n");
- }
-
/* Allocate memory for the controller and fill basic values. */
e = grub_zalloc (sizeof (*e));
if (!e)
- return 1;
+ return;
e->framelist_chunk = NULL;
e->td_chunk = NULL;
e->qh_chunk = NULL;
- e->iobase_ehcc = grub_pci_device_map_range (dev,
- (base & GRUB_EHCI_ADDR_MEM_MASK),
- 0x100);
+ e->iobase_ehcc = regs;
- grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: iobase of EHCC: %08x\n",
- (base & GRUB_EHCI_ADDR_MEM_MASK));
grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: CAPLEN: %02x\n",
grub_ehci_ehcc_read8 (e, GRUB_EHCI_EHCC_CAPLEN));
grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: VERSION: %04x\n",
@@ -598,7 +494,7 @@ grub_ehci_pci_iter (grub_pci_device_t dev, grub_pci_id_t pciid,
if (caplen & (sizeof (grub_uint32_t) - 1))
{
grub_dprintf ("ehci", "Unaligned caplen\n");
- return 0;
+ return;
}
e->iobase = ((volatile grub_uint32_t *) e->iobase_ehcc
+ (caplen / sizeof (grub_uint32_t)));
@@ -608,8 +504,8 @@ grub_ehci_pci_iter (grub_pci_device_t dev, grub_pci_id_t pciid,
#endif
grub_dprintf ("ehci",
- "EHCI grub_ehci_pci_iter: iobase of oper. regs: %08x\n",
- (base & GRUB_EHCI_ADDR_MEM_MASK) + caplen);
+ "EHCI grub_ehci_pci_iter: iobase of oper. regs: %08llxx\n",
+ (unsigned long long) (grub_addr_t) e->iobase_ehcc + caplen);
grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: COMMAND: %08x\n",
grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND));
grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: STATUS: %08x\n",
@@ -625,10 +521,6 @@ grub_ehci_pci_iter (grub_pci_device_t dev, grub_pci_id_t pciid,
grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: CONFIG_FLAG: %08x\n",
grub_ehci_oper_read32 (e, GRUB_EHCI_CONFIG_FLAG));
- /* Is there EECP ? */
- eecp_offset = (grub_ehci_ehcc_read32 (e, GRUB_EHCI_EHCC_CPARAMS)
- & GRUB_EHCI_EECP_MASK) >> GRUB_EHCI_EECP_SHIFT;
-
/* Check format of data structures requested by EHCI */
/* XXX: In fact it is not used at any place, it is prepared for future
* This implementation uses 32-bits pointers only */
@@ -732,65 +624,6 @@ grub_ehci_pci_iter (grub_pci_device_t dev, grub_pci_id_t pciid,
grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: QH/TD init. OK\n");
- /* Determine and change ownership. */
- /* EECP offset valid in HCCPARAMS */
- /* Ownership can be changed via EECP only */
- if (pciid != GRUB_CS5536_PCIID && eecp_offset >= 0x40)
- {
- grub_pci_address_t pciaddr_eecp;
- pciaddr_eecp = grub_pci_make_address (dev, eecp_offset);
-
- usblegsup = grub_pci_read (pciaddr_eecp);
- if (usblegsup & GRUB_EHCI_BIOS_OWNED)
- {
- grub_boot_time ("Taking ownership of EHCI controller");
- grub_dprintf ("ehci",
- "EHCI grub_ehci_pci_iter: EHCI owned by: BIOS\n");
- /* Ownership change - set OS_OWNED bit */
- grub_pci_write (pciaddr_eecp, usblegsup | GRUB_EHCI_OS_OWNED);
- /* Ensure PCI register is written */
- grub_pci_read (pciaddr_eecp);
-
- /* Wait for finish of ownership change, EHCI specification
- * doesn't say how long it can take... */
- maxtime = grub_get_time_ms () + 1000;
- while ((grub_pci_read (pciaddr_eecp) & GRUB_EHCI_BIOS_OWNED)
- && (grub_get_time_ms () < maxtime));
- if (grub_pci_read (pciaddr_eecp) & GRUB_EHCI_BIOS_OWNED)
- {
- grub_dprintf ("ehci",
- "EHCI grub_ehci_pci_iter: EHCI change ownership timeout");
- /* Change ownership in "hard way" - reset BIOS ownership */
- grub_pci_write (pciaddr_eecp, GRUB_EHCI_OS_OWNED);
- /* Ensure PCI register is written */
- grub_pci_read (pciaddr_eecp);
- }
- }
- else if (usblegsup & GRUB_EHCI_OS_OWNED)
- /* XXX: What to do in this case - nothing ? Can it happen ? */
- grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: EHCI owned by: OS\n");
- else
- {
- grub_dprintf ("ehci",
- "EHCI grub_ehci_pci_iter: EHCI owned by: NONE\n");
- /* XXX: What to do in this case ? Can it happen ?
- * Is code below correct ? */
- /* Ownership change - set OS_OWNED bit */
- grub_pci_write (pciaddr_eecp, GRUB_EHCI_OS_OWNED);
- /* Ensure PCI register is written */
- grub_pci_read (pciaddr_eecp);
- }
-
- /* Disable SMI, just to be sure. */
- pciaddr_eecp = grub_pci_make_address (dev, eecp_offset + 4);
- grub_pci_write (pciaddr_eecp, 0);
- /* Ensure PCI register is written */
- grub_pci_read (pciaddr_eecp);
-
- }
-
- grub_dprintf ("ehci", "inithw: EHCI grub_ehci_pci_iter: ownership OK\n");
-
/* Now we can setup EHCI (maybe...) */
/* Check if EHCI is halted and halt it if not */
@@ -863,8 +696,8 @@ grub_ehci_pci_iter (grub_pci_device_t dev, grub_pci_id_t pciid,
grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: OK at all\n");
grub_dprintf ("ehci",
- "EHCI grub_ehci_pci_iter: iobase of oper. regs: %08x\n",
- (base & GRUB_EHCI_ADDR_MEM_MASK));
+ "EHCI grub_ehci_pci_iter: iobase of oper. regs: %08llx\n",
+ (unsigned long long) (grub_addr_t) regs);
grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: COMMAND: %08x\n",
grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND));
grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: STATUS: %08x\n",
@@ -880,7 +713,7 @@ grub_ehci_pci_iter (grub_pci_device_t dev, grub_pci_id_t pciid,
grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: CONFIG_FLAG: %08x\n",
grub_ehci_oper_read32 (e, GRUB_EHCI_CONFIG_FLAG));
- return 0;
+ return;
fail:
if (e)
@@ -894,7 +727,7 @@ fail:
}
grub_free (e);
- return 0;
+ return;
}
static int
@@ -1891,12 +1724,6 @@ grub_ehci_detect_dev (grub_usb_controller_t dev, int port, int *changed)
}
}
-static void
-grub_ehci_inithw (void)
-{
- grub_pci_iterate (grub_ehci_pci_iter, NULL);
-}
-
static grub_err_t
grub_ehci_restore_hw (void)
{
@@ -1997,7 +1824,7 @@ GRUB_MOD_INIT (ehci)
grub_stop_disk_firmware ();
grub_boot_time ("Initing EHCI hardware");
- grub_ehci_inithw ();
+ grub_ehci_pci_scan ();
grub_boot_time ("Registering EHCI driver");
grub_usb_controller_dev_register (&usb_controller);
grub_boot_time ("EHCI driver registered");
diff --git a/grub-core/bus/usb/usbtrans.c b/grub-core/bus/usb/usbtrans.c
index 9266e49311c4471d0915aebf9fae05509d0fa5c7..85f081fffb3a2aa7354816c79977ae45a79b1c80 100644
--- a/grub-core/bus/usb/usbtrans.c
+++ b/grub-core/bus/usb/usbtrans.c
@@ -18,7 +18,7 @@
*/
#include
-#include
+#include
#include
#include
#include
diff --git a/grub-core/commands/efi/lsefi.c b/grub-core/commands/efi/lsefi.c
index d901c3892630f2500eda9822c712aae278017907..d1ce99af438914692d1b71b0017050689dd73db9 100644
--- a/grub-core/commands/efi/lsefi.c
+++ b/grub-core/commands/efi/lsefi.c
@@ -109,8 +109,10 @@ grub_cmd_lsefi (grub_command_t cmd __attribute__ ((unused)),
status = efi_call_3 (grub_efi_system_table->boot_services->protocols_per_handle,
handle, &protocols, &num_protocols);
- if (status != GRUB_EFI_SUCCESS)
+ if (status != GRUB_EFI_SUCCESS) {
grub_printf ("Unable to retrieve protocols\n");
+ continue;
+ }
for (j = 0; j < num_protocols; j++)
{
for (k = 0; k < ARRAY_SIZE (known_protocols); k++)
diff --git a/grub-core/commands/file.c b/grub-core/commands/file.c
index 12fba99e06a23cb72af67fc4bfb758d97bfa0e67..3ff6d5522d2d572c2af16fec371faeb8e4b28f9d 100644
--- a/grub-core/commands/file.c
+++ b/grub-core/commands/file.c
@@ -27,6 +27,8 @@
#include
#include
#include
+#include
+#include
#include
#include
#include
@@ -383,21 +385,19 @@ grub_cmd_file (grub_extcmd_context_t ctxt, int argc, char **args)
}
case IS_ARM_LINUX:
{
- grub_uint32_t sig, sig_pi;
- if (grub_file_read (file, &sig_pi, 4) != 4)
+ struct linux_arm_kernel_header lh;
+
+ if (grub_file_read (file, &lh, sizeof (lh)) != sizeof (lh))
break;
- /* Raspberry pi. */
- if (sig_pi == grub_cpu_to_le32_compile_time (0xea000006))
+ /* Short forward branch in A32 state (for Raspberry pi kernels). */
+ if (lh.code0 == grub_cpu_to_le32_compile_time (0xea000006))
{
ret = 1;
break;
}
- if (grub_file_seek (file, 0x24) == (grub_size_t) -1)
- break;
- if (grub_file_read (file, &sig, 4) != 4)
- break;
- if (sig == grub_cpu_to_le32_compile_time (0x016f2818))
+ if (lh.magic ==
+ grub_cpu_to_le32_compile_time (GRUB_LINUX_ARM_MAGIC_SIGNATURE))
{
ret = 1;
break;
@@ -406,13 +406,13 @@ grub_cmd_file (grub_extcmd_context_t ctxt, int argc, char **args)
}
case IS_ARM64_LINUX:
{
- grub_uint32_t sig;
+ struct linux_arm64_kernel_header lh;
- if (grub_file_seek (file, 0x38) == (grub_size_t) -1)
+ if (grub_file_read (file, &lh, sizeof (lh)) != sizeof (lh))
break;
- if (grub_file_read (file, &sig, 4) != 4)
- break;
- if (sig == grub_cpu_to_le32_compile_time (0x644d5241))
+
+ if (lh.magic ==
+ grub_cpu_to_le32_compile_time (GRUB_LINUX_ARM64_MAGIC_SIGNATURE))
{
ret = 1;
break;
@@ -497,7 +497,7 @@ grub_cmd_file (grub_extcmd_context_t ctxt, int argc, char **args)
case IS_X86_LINUX32:
case IS_X86_LINUX:
{
- struct linux_kernel_header lh;
+ struct linux_i386_kernel_header lh;
if (grub_file_read (file, &lh, sizeof (lh)) != sizeof (lh))
break;
if (lh.boot_flag != grub_cpu_to_le16_compile_time (0xaa55))
@@ -508,7 +508,7 @@ grub_cmd_file (grub_extcmd_context_t ctxt, int argc, char **args)
/* FIXME: some really old kernels (< 1.3.73) will fail this. */
if (lh.header !=
- grub_cpu_to_le32_compile_time (GRUB_LINUX_MAGIC_SIGNATURE)
+ grub_cpu_to_le32_compile_time (GRUB_LINUX_I386_MAGIC_SIGNATURE)
|| grub_le_to_cpu16 (lh.version) < 0x0200)
break;
@@ -521,7 +521,7 @@ grub_cmd_file (grub_extcmd_context_t ctxt, int argc, char **args)
/* FIXME: 2.03 is not always good enough (Linux 2.4 can be 2.03 and
still not support 32-bit boot. */
if (lh.header !=
- grub_cpu_to_le32_compile_time (GRUB_LINUX_MAGIC_SIGNATURE)
+ grub_cpu_to_le32_compile_time (GRUB_LINUX_I386_MAGIC_SIGNATURE)
|| grub_le_to_cpu16 (lh.version) < 0x0203)
break;
diff --git a/grub-core/commands/i386/coreboot/cb_timestamps.c b/grub-core/commands/i386/coreboot/cb_timestamps.c
index e72f38d6e057dccfb981d6bbc483d2bdd8a06c98..e97ea6bed98b42d4f03f06ab5bc076fadbfee67f 100644
--- a/grub-core/commands/i386/coreboot/cb_timestamps.c
+++ b/grub-core/commands/i386/coreboot/cb_timestamps.c
@@ -20,7 +20,7 @@
#include
#include
#include
-#include
+#include
#include
GRUB_MOD_LICENSE ("GPLv3+");
diff --git a/grub-core/commands/i386/coreboot/cbls.c b/grub-core/commands/i386/coreboot/cbls.c
index e0a10596fe279331cca94172e1f452fdfe18394f..102291f424ab782c6cd3bcd4ae1effd836cd832e 100644
--- a/grub-core/commands/i386/coreboot/cbls.c
+++ b/grub-core/commands/i386/coreboot/cbls.c
@@ -20,7 +20,7 @@
#include
#include
#include
-#include
+#include
#include
GRUB_MOD_LICENSE ("GPLv3+");
diff --git a/grub-core/commands/keylayouts.c b/grub-core/commands/keylayouts.c
index f4b7730208ab8ffafb1b0283294a140248839d7a..f35d3a369bad7125cb04e25f0e32c01c00c673b0 100644
--- a/grub-core/commands/keylayouts.c
+++ b/grub-core/commands/keylayouts.c
@@ -40,7 +40,7 @@ static struct grub_keyboard_layout layout_us = {
/* 0x10 */ 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
/* 0x18 */ 'u', 'v', 'w', 'x', 'y', 'z', '1', '2',
/* 0x20 */ '3', '4', '5', '6', '7', '8', '9', '0',
- /* 0x28 */ '\n', '\e', '\b', '\t', ' ', '-', '=', '[',
+ /* 0x28 */ '\n', GRUB_TERM_ESC, GRUB_TERM_BACKSPACE, GRUB_TERM_TAB, ' ', '-', '=', '[',
/* According to usage table 0x31 should be mapped to '/'
but testing with real keyboard shows that 0x32 is remapped to '/'.
Map 0x31 to 0.
@@ -82,8 +82,8 @@ static struct grub_keyboard_layout layout_us = {
/* 0x10 */ 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
/* 0x18 */ 'U', 'V', 'W', 'X', 'Y', 'Z', '!', '@',
/* 0x20 */ '#', '$', '%', '^', '&', '*', '(', ')',
- /* 0x28 */ '\n' | GRUB_TERM_SHIFT, '\e' | GRUB_TERM_SHIFT,
- /* 0x2a */ '\b' | GRUB_TERM_SHIFT, '\t' | GRUB_TERM_SHIFT,
+ /* 0x28 */ '\n' | GRUB_TERM_SHIFT, GRUB_TERM_ESC | GRUB_TERM_SHIFT,
+ /* 0x2a */ GRUB_TERM_BACKSPACE | GRUB_TERM_SHIFT, GRUB_TERM_TAB | GRUB_TERM_SHIFT,
/* 0x2c */ ' ' | GRUB_TERM_SHIFT, '_', '+', '{',
/* According to usage table 0x31 should be mapped to '/'
but testing with real keyboard shows that 0x32 is remapped to '/'.
diff --git a/grub-core/commands/ls.c b/grub-core/commands/ls.c
index 0eaf836527944ba69d499050ad080f919d3e57ef..c25161cc4f2c6d4fce6781bfac9bf7796fceb0c7 100644
--- a/grub-core/commands/ls.c
+++ b/grub-core/commands/ls.c
@@ -201,6 +201,15 @@ grub_ls_list_files (char *dirname, int longlist, int all, int human)
if (grub_errno == GRUB_ERR_UNKNOWN_FS)
grub_errno = GRUB_ERR_NONE;
+#ifdef GRUB_MACHINE_IEEE1275
+ /*
+ * Close device to prevent a double open in grub_normal_print_device_info().
+ * Otherwise it may lead to hangs on some IEEE 1275 platforms.
+ */
+ grub_device_close (dev);
+ dev = NULL;
+#endif
+
grub_normal_print_device_info (device_name);
}
else if (fs)
diff --git a/grub-core/commands/menuentry.c b/grub-core/commands/menuentry.c
index 58d4dadf6ee4ec392a09d433802803520704cd7b..2c5363da7f549b85ae04d1d88a78db0b85504c51 100644
--- a/grub-core/commands/menuentry.c
+++ b/grub-core/commands/menuentry.c
@@ -52,8 +52,8 @@ static struct
int key;
} hotkey_aliases[] =
{
- {"backspace", '\b'},
- {"tab", '\t'},
+ {"backspace", GRUB_TERM_BACKSPACE},
+ {"tab", GRUB_TERM_TAB},
{"delete", GRUB_TERM_KEY_DC},
{"insert", GRUB_TERM_KEY_INSERT},
{"f1", GRUB_TERM_KEY_F1},
diff --git a/grub-core/disk/ahci.c b/grub-core/disk/ahci.c
index 494a1b7734ef44fef6e887f62b6eb30d0a494284..f2f606423aca4f842f5b16b797a1084cc5791cbb 100644
--- a/grub-core/disk/ahci.c
+++ b/grub-core/disk/ahci.c
@@ -82,6 +82,20 @@ enum grub_ahci_hba_port_command
GRUB_AHCI_HBA_PORT_CMD_FR = 0x4000,
};
+enum grub_ahci_hba_port_int_status
+ {
+ GRUB_AHCI_HBA_PORT_IS_IFS = (1UL << 27),
+ GRUB_AHCI_HBA_PORT_IS_HBDS = (1UL << 28),
+ GRUB_AHCI_HBA_PORT_IS_HBFS = (1UL << 29),
+ GRUB_AHCI_HBA_PORT_IS_TFES = (1UL << 30),
+ };
+
+#define GRUB_AHCI_HBA_PORT_IS_FATAL_MASK ( \
+ GRUB_AHCI_HBA_PORT_IS_IFS | \
+ GRUB_AHCI_HBA_PORT_IS_HBDS | \
+ GRUB_AHCI_HBA_PORT_IS_HBFS | \
+ GRUB_AHCI_HBA_PORT_IS_TFES)
+
struct grub_ahci_hba
{
grub_uint32_t cap;
@@ -1026,7 +1040,8 @@ grub_ahci_readwrite_real (struct grub_ahci_device *dev,
endtime = grub_get_time_ms () + (spinup ? 20000 : 20000);
while ((dev->hba->ports[dev->port].command_issue & 1))
- if (grub_get_time_ms () > endtime)
+ if (grub_get_time_ms () > endtime ||
+ (dev->hba->ports[dev->port].intstatus & GRUB_AHCI_HBA_PORT_IS_FATAL_MASK))
{
grub_dprintf ("ahci", "AHCI status <%x %x %x %x>\n",
dev->hba->ports[dev->port].command_issue,
@@ -1034,7 +1049,10 @@ grub_ahci_readwrite_real (struct grub_ahci_device *dev,
dev->hba->ports[dev->port].intstatus,
dev->hba->ports[dev->port].task_file_data);
dev->hba->ports[dev->port].command_issue = 0;
- err = grub_error (GRUB_ERR_IO, "AHCI transfer timed out");
+ if (dev->hba->ports[dev->port].intstatus & GRUB_AHCI_HBA_PORT_IS_FATAL_MASK)
+ err = grub_error (GRUB_ERR_IO, "AHCI transfer error");
+ else
+ err = grub_error (GRUB_ERR_IO, "AHCI transfer timed out");
if (!reset)
grub_ahci_reset_port (dev, 1);
break;
diff --git a/grub-core/disk/ldm.c b/grub-core/disk/ldm.c
index 0f978ad05079c9535d7ef9bb16462c7d7adeb80e..2a22d2d6c1c3121ec889f33f2aaaf3077723a6c1 100644
--- a/grub-core/disk/ldm.c
+++ b/grub-core/disk/ldm.c
@@ -135,7 +135,7 @@ msdos_has_ldm_partition (grub_disk_t dsk)
return has_ldm;
}
-static const grub_gpt_part_type_t ldm_type = GRUB_GPT_PARTITION_TYPE_LDM;
+static const grub_gpt_part_guid_t ldm_type = GRUB_GPT_PARTITION_TYPE_LDM;
/* Helper for gpt_ldm_sector. */
static int
diff --git a/grub-core/efiemu/i386/loadcore64.c b/grub-core/efiemu/i386/loadcore64.c
index e49d0b6ff17e02e22e09b306d0a6a32a3b083b78..18facf47fd7678007deb730fb71256edff6292ad 100644
--- a/grub-core/efiemu/i386/loadcore64.c
+++ b/grub-core/efiemu/i386/loadcore64.c
@@ -98,6 +98,7 @@ grub_arch_efiemu_relocate_symbols64 (grub_efiemu_segment_t segs,
break;
case R_X86_64_PC32:
+ case R_X86_64_PLT32:
err = grub_efiemu_write_value (addr,
*addr32 + rel->r_addend
+ sym.off
diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c
index 4849c1ceb6533c1b19eb64d754d45d44282b5acb..be195448dbeb55abcfb117723cd2fc6d75e6e344 100644
--- a/grub-core/fs/btrfs.c
+++ b/grub-core/fs/btrfs.c
@@ -175,7 +175,7 @@ struct grub_btrfs_time
{
grub_int64_t sec;
grub_uint32_t nanosec;
-} __attribute__ ((aligned (4)));
+} GRUB_PACKED;
struct grub_btrfs_inode
{
diff --git a/grub-core/fs/ext2.c b/grub-core/fs/ext2.c
index cdce63bcc9d57e82b7a4f6a644803a1d8320935d..b8ad75a0ff7c4f72b67bef123510d99231531daf 100644
--- a/grub-core/fs/ext2.c
+++ b/grub-core/fs/ext2.c
@@ -102,6 +102,7 @@ GRUB_MOD_LICENSE ("GPLv3+");
#define EXT4_FEATURE_INCOMPAT_64BIT 0x0080
#define EXT4_FEATURE_INCOMPAT_MMP 0x0100
#define EXT4_FEATURE_INCOMPAT_FLEX_BG 0x0200
+#define EXT4_FEATURE_INCOMPAT_ENCRYPT 0x10000
/* The set of back-incompatible features this driver DOES support. Add (OR)
* flags here as the related features are implemented into the driver. */
@@ -109,7 +110,8 @@ GRUB_MOD_LICENSE ("GPLv3+");
| EXT4_FEATURE_INCOMPAT_EXTENTS \
| EXT4_FEATURE_INCOMPAT_FLEX_BG \
| EXT2_FEATURE_INCOMPAT_META_BG \
- | EXT4_FEATURE_INCOMPAT_64BIT)
+ | EXT4_FEATURE_INCOMPAT_64BIT \
+ | EXT4_FEATURE_INCOMPAT_ENCRYPT)
/* List of rationales for the ignored "incompatible" features:
* needs_recovery: Not really back-incompatible - was added as such to forbid
* ext2 drivers from mounting an ext3 volume with a dirty
@@ -138,6 +140,7 @@ GRUB_MOD_LICENSE ("GPLv3+");
#define EXT3_JOURNAL_FLAG_DELETED 4
#define EXT3_JOURNAL_FLAG_LAST_TAG 8
+#define EXT4_ENCRYPT_FLAG 0x800
#define EXT4_EXTENTS_FLAG 0x80000
/* The ext2 superblock. */
@@ -706,6 +709,12 @@ grub_ext2_read_symlink (grub_fshelp_node_t node)
grub_ext2_read_inode (diro->data, diro->ino, &diro->inode);
if (grub_errno)
return 0;
+
+ if (diro->inode.flags & grub_cpu_to_le32_compile_time (EXT4_ENCRYPT_FLAG))
+ {
+ grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "symlink is encrypted");
+ return 0;
+ }
}
symlink = grub_malloc (grub_le_to_cpu32 (diro->inode.size) + 1);
@@ -749,6 +758,12 @@ grub_ext2_iterate_dir (grub_fshelp_node_t dir,
return 0;
}
+ if (diro->inode.flags & grub_cpu_to_le32_compile_time (EXT4_ENCRYPT_FLAG))
+ {
+ grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "directory is encrypted");
+ return 0;
+ }
+
/* Search the file. */
while (fpos < grub_le_to_cpu32 (diro->inode.size))
{
@@ -859,6 +874,12 @@ grub_ext2_open (struct grub_file *file, const char *name)
goto fail;
}
+ if (fdiro->inode.flags & grub_cpu_to_le32_compile_time (EXT4_ENCRYPT_FLAG))
+ {
+ err = grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "file is encrypted");
+ goto fail;
+ }
+
grub_memcpy (data->inode, &fdiro->inode, sizeof (struct grub_ext2_inode));
grub_free (fdiro);
diff --git a/grub-core/fs/f2fs.c b/grub-core/fs/f2fs.c
new file mode 100644
index 0000000000000000000000000000000000000000..1cad2615f3c9e65e57a12d18b76f4ecc1caa31d8
--- /dev/null
+++ b/grub-core/fs/f2fs.c
@@ -0,0 +1,1314 @@
+/*
+ * f2fs.c - Flash-Friendly File System
+ *
+ * Written by Jaegeuk Kim
+ *
+ * Copyright (C) 2015 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
+
+GRUB_MOD_LICENSE ("GPLv3+");
+
+/* F2FS Magic Number. */
+#define F2FS_SUPER_MAGIC 0xf2f52010
+
+#define CHECKSUM_OFFSET 4092 /* Must be aligned 4 bytes. */
+#define U32_CHECKSUM_OFFSET (CHECKSUM_OFFSET >> 2)
+#define CRCPOLY_LE 0xedb88320
+
+/* Byte-size offset. */
+#define F2FS_SUPER_OFFSET ((grub_disk_addr_t)1024)
+#define F2FS_SUPER_OFFSET0 (F2FS_SUPER_OFFSET >> GRUB_DISK_SECTOR_BITS)
+#define F2FS_SUPER_OFFSET1 ((F2FS_SUPER_OFFSET + F2FS_BLKSIZE) >> \
+ GRUB_DISK_SECTOR_BITS)
+
+/* 9 bits for 512 bytes. */
+#define F2FS_MIN_LOG_SECTOR_SIZE 9
+
+/* Support only 4KB block. */
+#define F2FS_BLK_BITS 12
+#define F2FS_BLKSIZE (1 << F2FS_BLK_BITS)
+#define F2FS_BLK_SEC_BITS (F2FS_BLK_BITS - GRUB_DISK_SECTOR_BITS)
+
+#define VERSION_LEN 256
+#define F2FS_MAX_EXTENSION 64
+
+#define CP_COMPACT_SUM_FLAG 0x00000004
+#define CP_UMOUNT_FLAG 0x00000001
+
+#define MAX_ACTIVE_LOGS 16
+#define MAX_ACTIVE_NODE_LOGS 8
+#define MAX_ACTIVE_DATA_LOGS 8
+#define NR_CURSEG_DATA_TYPE 3
+#define NR_CURSEG_NODE_TYPE 3
+#define NR_CURSEG_TYPE (NR_CURSEG_DATA_TYPE + NR_CURSEG_NODE_TYPE)
+
+#define ENTRIES_IN_SUM 512
+#define SUMMARY_SIZE 7
+#define SUM_FOOTER_SIZE 5
+#define JENTRY_SIZE (sizeof(struct grub_f2fs_nat_jent))
+#define SUM_ENTRIES_SIZE (SUMMARY_SIZE * ENTRIES_IN_SUM)
+#define SUM_JOURNAL_SIZE (F2FS_BLKSIZE - SUM_FOOTER_SIZE - SUM_ENTRIES_SIZE)
+#define NAT_JOURNAL_ENTRIES ((SUM_JOURNAL_SIZE - 2) / JENTRY_SIZE)
+#define NAT_JOURNAL_RESERVED ((SUM_JOURNAL_SIZE - 2) % JENTRY_SIZE)
+
+#define NAT_ENTRY_SIZE (sizeof(struct grub_f2fs_nat_entry))
+#define NAT_ENTRY_PER_BLOCK (F2FS_BLKSIZE / NAT_ENTRY_SIZE)
+
+#define F2FS_NAME_LEN 255
+#define F2FS_SLOT_LEN 8
+#define NR_DENTRY_IN_BLOCK 214
+#define SIZE_OF_DIR_ENTRY 11 /* By byte. */
+#define BITS_PER_BYTE 8
+#define SIZE_OF_DENTRY_BITMAP ((NR_DENTRY_IN_BLOCK + BITS_PER_BYTE - 1) / \
+ BITS_PER_BYTE)
+#define SIZE_OF_RESERVED (F2FS_BLKSIZE - \
+ ((SIZE_OF_DIR_ENTRY + F2FS_SLOT_LEN) * \
+ NR_DENTRY_IN_BLOCK + SIZE_OF_DENTRY_BITMAP))
+
+#define F2FS_INLINE_XATTR_ADDRS 50 /* 200 bytes for inline xattrs. */
+#define DEF_ADDRS_PER_INODE 923 /* Address Pointers in an Inode. */
+
+#define ADDRS_PER_BLOCK 1018 /* Address Pointers in a Direct Block. */
+#define NIDS_PER_BLOCK 1018 /* Node IDs in an Indirect Block. */
+#define NODE_DIR1_BLOCK (DEF_ADDRS_PER_INODE + 1)
+#define NODE_DIR2_BLOCK (DEF_ADDRS_PER_INODE + 2)
+#define NODE_IND1_BLOCK (DEF_ADDRS_PER_INODE + 3)
+#define NODE_IND2_BLOCK (DEF_ADDRS_PER_INODE + 4)
+#define NODE_DIND_BLOCK (DEF_ADDRS_PER_INODE + 5)
+
+#define MAX_INLINE_DATA (4 * (DEF_ADDRS_PER_INODE - \
+ F2FS_INLINE_XATTR_ADDRS - 1))
+#define NR_INLINE_DENTRY (MAX_INLINE_DATA * BITS_PER_BYTE / \
+ ((SIZE_OF_DIR_ENTRY + F2FS_SLOT_LEN) * \
+ BITS_PER_BYTE + 1))
+#define INLINE_DENTRY_BITMAP_SIZE ((NR_INLINE_DENTRY + BITS_PER_BYTE - 1) / \
+ BITS_PER_BYTE)
+#define INLINE_RESERVED_SIZE (MAX_INLINE_DATA - \
+ ((SIZE_OF_DIR_ENTRY + F2FS_SLOT_LEN) * \
+ NR_INLINE_DENTRY + \
+ INLINE_DENTRY_BITMAP_SIZE))
+#define CURSEG_HOT_DATA 0
+
+#define CKPT_FLAG_SET(ckpt, f) (ckpt)->ckpt_flags & \
+ grub_cpu_to_le32_compile_time (f)
+
+#define F2FS_INLINE_XATTR 0x01 /* File inline xattr flag. */
+#define F2FS_INLINE_DATA 0x02 /* File inline data flag. */
+#define F2FS_INLINE_DENTRY 0x04 /* File inline dentry flag. */
+#define F2FS_DATA_EXIST 0x08 /* File inline data exist flag. */
+#define F2FS_INLINE_DOTS 0x10 /* File having implicit dot dentries. */
+
+#define MAX_VOLUME_NAME 512
+
+enum FILE_TYPE
+{
+ F2FS_FT_UNKNOWN,
+ F2FS_FT_REG_FILE = 1,
+ F2FS_FT_DIR = 2,
+ F2FS_FT_SYMLINK = 7
+};
+
+struct grub_f2fs_superblock
+{
+ grub_uint32_t magic;
+ grub_uint16_t dummy1[2];
+ grub_uint32_t log_sectorsize;
+ grub_uint32_t log_sectors_per_block;
+ grub_uint32_t log_blocksize;
+ grub_uint32_t log_blocks_per_seg;
+ grub_uint32_t segs_per_sec;
+ grub_uint32_t secs_per_zone;
+ grub_uint32_t checksum_offset;
+ grub_uint8_t dummy2[40];
+ grub_uint32_t cp_blkaddr;
+ grub_uint32_t sit_blkaddr;
+ grub_uint32_t nat_blkaddr;
+ grub_uint32_t ssa_blkaddr;
+ grub_uint32_t main_blkaddr;
+ grub_uint32_t root_ino;
+ grub_uint32_t node_ino;
+ grub_uint32_t meta_ino;
+ grub_uint8_t uuid[16];
+ grub_uint16_t volume_name[MAX_VOLUME_NAME];
+ grub_uint32_t extension_count;
+ grub_uint8_t extension_list[F2FS_MAX_EXTENSION][8];
+ grub_uint32_t cp_payload;
+ grub_uint8_t version[VERSION_LEN];
+ grub_uint8_t init_version[VERSION_LEN];
+} GRUB_PACKED;
+
+struct grub_f2fs_checkpoint
+{
+ grub_uint64_t checkpoint_ver;
+ grub_uint64_t user_block_count;
+ grub_uint64_t valid_block_count;
+ grub_uint32_t rsvd_segment_count;
+ grub_uint32_t overprov_segment_count;
+ grub_uint32_t free_segment_count;
+ grub_uint32_t cur_node_segno[MAX_ACTIVE_NODE_LOGS];
+ grub_uint16_t cur_node_blkoff[MAX_ACTIVE_NODE_LOGS];
+ grub_uint32_t cur_data_segno[MAX_ACTIVE_DATA_LOGS];
+ grub_uint16_t cur_data_blkoff[MAX_ACTIVE_DATA_LOGS];
+ grub_uint32_t ckpt_flags;
+ grub_uint32_t cp_pack_total_block_count;
+ grub_uint32_t cp_pack_start_sum;
+ grub_uint32_t valid_node_count;
+ grub_uint32_t valid_inode_count;
+ grub_uint32_t next_free_nid;
+ grub_uint32_t sit_ver_bitmap_bytesize;
+ grub_uint32_t nat_ver_bitmap_bytesize;
+ grub_uint32_t checksum_offset;
+ grub_uint64_t elapsed_time;
+ grub_uint8_t alloc_type[MAX_ACTIVE_LOGS];
+ grub_uint8_t sit_nat_version_bitmap[3900];
+ grub_uint32_t checksum;
+} GRUB_PACKED;
+
+struct grub_f2fs_nat_entry {
+ grub_uint8_t version;
+ grub_uint32_t ino;
+ grub_uint32_t block_addr;
+} GRUB_PACKED;
+
+struct grub_f2fs_nat_jent
+{
+ grub_uint32_t nid;
+ struct grub_f2fs_nat_entry ne;
+} GRUB_PACKED;
+
+struct grub_f2fs_nat_journal {
+ grub_uint16_t n_nats;
+ struct grub_f2fs_nat_jent entries[NAT_JOURNAL_ENTRIES];
+ grub_uint8_t reserved[NAT_JOURNAL_RESERVED];
+} GRUB_PACKED;
+
+struct grub_f2fs_nat_block {
+ struct grub_f2fs_nat_entry ne[NAT_ENTRY_PER_BLOCK];
+} GRUB_PACKED;
+
+struct grub_f2fs_dir_entry
+{
+ grub_uint32_t hash_code;
+ grub_uint32_t ino;
+ grub_uint16_t name_len;
+ grub_uint8_t file_type;
+} GRUB_PACKED;
+
+struct grub_f2fs_inline_dentry
+{
+ grub_uint8_t dentry_bitmap[INLINE_DENTRY_BITMAP_SIZE];
+ grub_uint8_t reserved[INLINE_RESERVED_SIZE];
+ struct grub_f2fs_dir_entry dentry[NR_INLINE_DENTRY];
+ grub_uint8_t filename[NR_INLINE_DENTRY][F2FS_SLOT_LEN];
+} GRUB_PACKED;
+
+struct grub_f2fs_dentry_block {
+ grub_uint8_t dentry_bitmap[SIZE_OF_DENTRY_BITMAP];
+ grub_uint8_t reserved[SIZE_OF_RESERVED];
+ struct grub_f2fs_dir_entry dentry[NR_DENTRY_IN_BLOCK];
+ grub_uint8_t filename[NR_DENTRY_IN_BLOCK][F2FS_SLOT_LEN];
+} GRUB_PACKED;
+
+struct grub_f2fs_inode
+{
+ grub_uint16_t i_mode;
+ grub_uint8_t i_advise;
+ grub_uint8_t i_inline;
+ grub_uint32_t i_uid;
+ grub_uint32_t i_gid;
+ grub_uint32_t i_links;
+ grub_uint64_t i_size;
+ grub_uint64_t i_blocks;
+ grub_uint64_t i_atime;
+ grub_uint64_t i_ctime;
+ grub_uint64_t i_mtime;
+ grub_uint32_t i_atime_nsec;
+ grub_uint32_t i_ctime_nsec;
+ grub_uint32_t i_mtime_nsec;
+ grub_uint32_t i_generation;
+ grub_uint32_t i_current_depth;
+ grub_uint32_t i_xattr_nid;
+ grub_uint32_t i_flags;
+ grub_uint32_t i_pino;
+ grub_uint32_t i_namelen;
+ grub_uint8_t i_name[F2FS_NAME_LEN];
+ grub_uint8_t i_dir_level;
+ grub_uint8_t i_ext[12];
+ grub_uint32_t i_addr[DEF_ADDRS_PER_INODE];
+ grub_uint32_t i_nid[5];
+} GRUB_PACKED;
+
+struct grub_direct_node {
+ grub_uint32_t addr[ADDRS_PER_BLOCK];
+} GRUB_PACKED;
+
+struct grub_indirect_node {
+ grub_uint32_t nid[NIDS_PER_BLOCK];
+} GRUB_PACKED;
+
+struct grub_f2fs_node
+{
+ union
+ {
+ struct grub_f2fs_inode i;
+ struct grub_direct_node dn;
+ struct grub_indirect_node in;
+ /* Should occupy F2FS_BLKSIZE totally. */
+ char buf[F2FS_BLKSIZE - 40];
+ };
+ grub_uint8_t dummy[40];
+} GRUB_PACKED;
+
+struct grub_fshelp_node
+{
+ struct grub_f2fs_data *data;
+ struct grub_f2fs_node inode;
+ grub_uint32_t ino;
+ int inode_read;
+};
+
+struct grub_f2fs_data
+{
+ struct grub_f2fs_superblock sblock;
+ struct grub_f2fs_checkpoint ckpt;
+
+ grub_uint32_t root_ino;
+ grub_uint32_t blocks_per_seg;
+ grub_uint32_t cp_blkaddr;
+ grub_uint32_t nat_blkaddr;
+
+ struct grub_f2fs_nat_journal nat_j;
+ char *nat_bitmap;
+
+ grub_disk_t disk;
+ struct grub_f2fs_node *inode;
+ struct grub_fshelp_node diropen;
+};
+
+struct grub_f2fs_dir_iter_ctx
+{
+ struct grub_f2fs_data *data;
+ grub_fshelp_iterate_dir_hook_t hook;
+ void *hook_data;
+ grub_uint8_t *bitmap;
+ grub_uint8_t (*filename)[F2FS_SLOT_LEN];
+ struct grub_f2fs_dir_entry *dentry;
+ int max;
+};
+
+struct grub_f2fs_dir_ctx
+{
+ grub_fs_dir_hook_t hook;
+ void *hook_data;
+ struct grub_f2fs_data *data;
+};
+
+static grub_dl_t my_mod;
+
+static int
+grub_f2fs_test_bit_le (int nr, const grub_uint8_t *addr)
+{
+ return addr[nr >> 3] & (1 << (nr & 7));
+}
+
+static char *
+get_inline_addr (struct grub_f2fs_inode *inode)
+{
+ return (char *) &inode->i_addr[1];
+}
+
+static grub_uint64_t
+grub_f2fs_file_size (struct grub_f2fs_inode *inode)
+{
+ return grub_le_to_cpu64 (inode->i_size);
+}
+
+static grub_uint32_t
+start_cp_addr (struct grub_f2fs_data *data)
+{
+ struct grub_f2fs_checkpoint *ckpt = &data->ckpt;
+ grub_uint32_t start_addr = data->cp_blkaddr;
+
+ if (!(ckpt->checkpoint_ver & grub_cpu_to_le64_compile_time(1)))
+ return start_addr + data->blocks_per_seg;
+
+ return start_addr;
+}
+
+static grub_uint32_t
+start_sum_block (struct grub_f2fs_data *data)
+{
+ struct grub_f2fs_checkpoint *ckpt = &data->ckpt;
+
+ return start_cp_addr (data) + grub_le_to_cpu32 (ckpt->cp_pack_start_sum);
+}
+
+static grub_uint32_t
+sum_blk_addr (struct grub_f2fs_data *data, int base, int type)
+{
+ struct grub_f2fs_checkpoint *ckpt = &data->ckpt;
+
+ return start_cp_addr (data) +
+ grub_le_to_cpu32 (ckpt->cp_pack_total_block_count) -
+ (base + 1) + type;
+}
+
+static void *
+nat_bitmap_ptr (struct grub_f2fs_data *data)
+{
+ struct grub_f2fs_checkpoint *ckpt = &data->ckpt;
+ grub_uint32_t offset;
+
+ if (grub_le_to_cpu32 (data->sblock.cp_payload) > 0)
+ return ckpt->sit_nat_version_bitmap;
+
+ offset = grub_le_to_cpu32 (ckpt->sit_ver_bitmap_bytesize);
+
+ return ckpt->sit_nat_version_bitmap + offset;
+}
+
+static grub_uint32_t
+get_node_id (struct grub_f2fs_node *rn, int off, int inode_block)
+{
+ if (inode_block)
+ return grub_le_to_cpu32 (rn->i.i_nid[off - NODE_DIR1_BLOCK]);
+
+ return grub_le_to_cpu32 (rn->in.nid[off]);
+}
+
+static grub_err_t
+grub_f2fs_block_read (struct grub_f2fs_data *data, grub_uint32_t blkaddr,
+ void *buf)
+{
+ return grub_disk_read (data->disk,
+ ((grub_disk_addr_t)blkaddr) << F2FS_BLK_SEC_BITS,
+ 0, F2FS_BLKSIZE, buf);
+}
+
+/* CRC32 */
+static grub_uint32_t
+grub_f2fs_cal_crc32 (const void *buf, const grub_uint32_t len)
+{
+ grub_uint32_t crc = F2FS_SUPER_MAGIC;
+ unsigned char *p = (unsigned char *)buf;
+ grub_uint32_t tmp = len;
+ int i;
+
+ while (tmp--)
+ {
+ crc ^= *p++;
+ for (i = 0; i < 8; i++)
+ crc = (crc >> 1) ^ ((crc & 1) ? CRCPOLY_LE : 0);
+ }
+
+ return crc;
+}
+
+static int
+grub_f2fs_crc_valid (grub_uint32_t blk_crc, void *buf, const grub_uint32_t len)
+{
+ grub_uint32_t cal_crc = 0;
+
+ cal_crc = grub_f2fs_cal_crc32 (buf, len);
+
+ return (cal_crc == blk_crc) ? 1 : 0;
+}
+
+static int
+grub_f2fs_test_bit (grub_uint32_t nr, const char *p)
+{
+ int mask;
+
+ p += (nr >> 3);
+ mask = 1 << (7 - (nr & 0x07));
+
+ return mask & *p;
+}
+
+static int
+grub_f2fs_sanity_check_sb (struct grub_f2fs_superblock *sb)
+{
+ grub_uint32_t log_sectorsize, log_sectors_per_block;
+
+ if (sb->magic != grub_cpu_to_le32_compile_time (F2FS_SUPER_MAGIC))
+ return -1;
+
+ if (sb->log_blocksize != grub_cpu_to_le32_compile_time (F2FS_BLK_BITS))
+ return -1;
+
+ log_sectorsize = grub_le_to_cpu32 (sb->log_sectorsize);
+ log_sectors_per_block = grub_le_to_cpu32 (sb->log_sectors_per_block);
+
+ if (log_sectorsize > F2FS_BLK_BITS)
+ return -1;
+
+ if (log_sectorsize < F2FS_MIN_LOG_SECTOR_SIZE)
+ return -1;
+
+ if (log_sectors_per_block + log_sectorsize != F2FS_BLK_BITS)
+ return -1;
+
+ return 0;
+}
+
+static int
+grub_f2fs_read_sb (struct grub_f2fs_data *data, grub_disk_addr_t offset)
+{
+ grub_disk_t disk = data->disk;
+ grub_err_t err;
+
+ /* Read first super block. */
+ err = grub_disk_read (disk, offset, 0, sizeof (data->sblock), &data->sblock);
+ if (err)
+ return -1;
+
+ return grub_f2fs_sanity_check_sb (&data->sblock);
+}
+
+static void *
+validate_checkpoint (struct grub_f2fs_data *data, grub_uint32_t cp_addr,
+ grub_uint64_t *version)
+{
+ grub_uint32_t *cp_page_1, *cp_page_2;
+ struct grub_f2fs_checkpoint *cp_block;
+ grub_uint64_t cur_version = 0, pre_version = 0;
+ grub_uint32_t crc = 0;
+ grub_uint32_t crc_offset;
+ grub_err_t err;
+
+ /* Read the 1st cp block in this CP pack. */
+ cp_page_1 = grub_malloc (F2FS_BLKSIZE);
+ if (!cp_page_1)
+ return NULL;
+
+ err = grub_f2fs_block_read (data, cp_addr, cp_page_1);
+ if (err)
+ goto invalid_cp1;
+
+ cp_block = (struct grub_f2fs_checkpoint *)cp_page_1;
+ crc_offset = grub_le_to_cpu32 (cp_block->checksum_offset);
+ if (crc_offset != CHECKSUM_OFFSET)
+ goto invalid_cp1;
+
+ crc = grub_le_to_cpu32 (*(cp_page_1 + U32_CHECKSUM_OFFSET));
+ if (!grub_f2fs_crc_valid (crc, cp_block, crc_offset))
+ goto invalid_cp1;
+
+ pre_version = grub_le_to_cpu64 (cp_block->checkpoint_ver);
+
+ /* Read the 2nd cp block in this CP pack. */
+ cp_page_2 = grub_malloc (F2FS_BLKSIZE);
+ if (!cp_page_2)
+ goto invalid_cp1;
+
+ cp_addr += grub_le_to_cpu32 (cp_block->cp_pack_total_block_count) - 1;
+
+ err = grub_f2fs_block_read (data, cp_addr, cp_page_2);
+ if (err)
+ goto invalid_cp2;
+
+ cp_block = (struct grub_f2fs_checkpoint *)cp_page_2;
+ crc_offset = grub_le_to_cpu32 (cp_block->checksum_offset);
+ if (crc_offset != CHECKSUM_OFFSET)
+ goto invalid_cp2;
+
+ crc = grub_le_to_cpu32 (*(cp_page_2 + U32_CHECKSUM_OFFSET));
+ if (!grub_f2fs_crc_valid (crc, cp_block, crc_offset))
+ goto invalid_cp2;
+
+ cur_version = grub_le_to_cpu64 (cp_block->checkpoint_ver);
+ if (cur_version == pre_version)
+ {
+ *version = cur_version;
+ grub_free (cp_page_2);
+
+ return cp_page_1;
+ }
+
+ invalid_cp2:
+ grub_free (cp_page_2);
+
+ invalid_cp1:
+ grub_free (cp_page_1);
+
+ return NULL;
+}
+
+static grub_err_t
+grub_f2fs_read_cp (struct grub_f2fs_data *data)
+{
+ void *cp1, *cp2, *cur_page;
+ grub_uint64_t cp1_version = 0, cp2_version = 0;
+ grub_uint64_t cp_start_blk_no;
+
+ /*
+ * Finding out valid cp block involves read both
+ * sets (cp pack1 and cp pack 2).
+ */
+ cp_start_blk_no = data->cp_blkaddr;
+ cp1 = validate_checkpoint (data, cp_start_blk_no, &cp1_version);
+ if (!cp1 && grub_errno)
+ return grub_errno;
+
+ /* The second checkpoint pack should start at the next segment. */
+ cp_start_blk_no += data->blocks_per_seg;
+ cp2 = validate_checkpoint (data, cp_start_blk_no, &cp2_version);
+ if (!cp2 && grub_errno)
+ {
+ grub_free (cp1);
+ return grub_errno;
+ }
+
+ if (cp1 && cp2)
+ cur_page = (cp2_version > cp1_version) ? cp2 : cp1;
+ else if (cp1)
+ cur_page = cp1;
+ else if (cp2)
+ cur_page = cp2;
+ else
+ return grub_error (GRUB_ERR_BAD_FS, "no checkpoints");
+
+ grub_memcpy (&data->ckpt, cur_page, F2FS_BLKSIZE);
+
+ grub_free (cp1);
+ grub_free (cp2);
+
+ return 0;
+}
+
+static grub_err_t
+get_nat_journal (struct grub_f2fs_data *data)
+{
+ grub_uint32_t block;
+ char *buf;
+ grub_err_t err;
+
+ buf = grub_malloc (F2FS_BLKSIZE);
+ if (!buf)
+ return grub_errno;
+
+ if (CKPT_FLAG_SET(&data->ckpt, CP_COMPACT_SUM_FLAG))
+ block = start_sum_block (data);
+ else if (CKPT_FLAG_SET (&data->ckpt, CP_UMOUNT_FLAG))
+ block = sum_blk_addr (data, NR_CURSEG_TYPE, CURSEG_HOT_DATA);
+ else
+ block = sum_blk_addr (data, NR_CURSEG_DATA_TYPE, CURSEG_HOT_DATA);
+
+ err = grub_f2fs_block_read (data, block, buf);
+ if (err)
+ goto fail;
+
+ if (CKPT_FLAG_SET (&data->ckpt, CP_COMPACT_SUM_FLAG))
+ grub_memcpy (&data->nat_j, buf, SUM_JOURNAL_SIZE);
+ else
+ grub_memcpy (&data->nat_j, buf + SUM_ENTRIES_SIZE, SUM_JOURNAL_SIZE);
+
+ fail:
+ grub_free (buf);
+
+ return err;
+}
+
+static grub_uint32_t
+get_blkaddr_from_nat_journal (struct grub_f2fs_data *data, grub_uint32_t nid)
+{
+ grub_uint16_t n = grub_le_to_cpu16 (data->nat_j.n_nats);
+ grub_uint32_t blkaddr = 0;
+ grub_uint16_t i;
+
+ for (i = 0; i < n; i++)
+ {
+ if (grub_le_to_cpu32 (data->nat_j.entries[i].nid) == nid)
+ {
+ blkaddr = grub_le_to_cpu32 (data->nat_j.entries[i].ne.block_addr);
+ break;
+ }
+ }
+
+ return blkaddr;
+}
+
+static grub_uint32_t
+get_node_blkaddr (struct grub_f2fs_data *data, grub_uint32_t nid)
+{
+ struct grub_f2fs_nat_block *nat_block;
+ grub_uint32_t seg_off, block_off, entry_off, block_addr;
+ grub_uint32_t blkaddr;
+ grub_err_t err;
+
+ blkaddr = get_blkaddr_from_nat_journal (data, nid);
+ if (blkaddr)
+ return blkaddr;
+
+ nat_block = grub_malloc (F2FS_BLKSIZE);
+ if (!nat_block)
+ return 0;
+
+ block_off = nid / NAT_ENTRY_PER_BLOCK;
+ entry_off = nid % NAT_ENTRY_PER_BLOCK;
+
+ seg_off = block_off / data->blocks_per_seg;
+ block_addr = data->nat_blkaddr +
+ ((seg_off * data->blocks_per_seg) << 1) +
+ (block_off & (data->blocks_per_seg - 1));
+
+ if (grub_f2fs_test_bit (block_off, data->nat_bitmap))
+ block_addr += data->blocks_per_seg;
+
+ err = grub_f2fs_block_read (data, block_addr, nat_block);
+ if (err)
+ {
+ grub_free (nat_block);
+ return 0;
+ }
+
+ blkaddr = grub_le_to_cpu32 (nat_block->ne[entry_off].block_addr);
+
+ grub_free (nat_block);
+
+ return blkaddr;
+}
+
+static int
+grub_get_node_path (struct grub_f2fs_inode *inode, grub_uint32_t block,
+ grub_uint32_t offset[4], grub_uint32_t noffset[4])
+{
+ grub_uint32_t direct_blks = ADDRS_PER_BLOCK;
+ grub_uint32_t dptrs_per_blk = NIDS_PER_BLOCK;
+ grub_uint32_t indirect_blks = ADDRS_PER_BLOCK * NIDS_PER_BLOCK;
+ grub_uint32_t dindirect_blks = indirect_blks * NIDS_PER_BLOCK;
+ grub_uint32_t direct_index = DEF_ADDRS_PER_INODE;
+ int n = 0;
+ int level = 0;
+
+ if (inode->i_inline & F2FS_INLINE_XATTR)
+ direct_index -= F2FS_INLINE_XATTR_ADDRS;
+
+ noffset[0] = 0;
+
+ if (block < direct_index)
+ {
+ offset[n] = block;
+ goto got;
+ }
+
+ block -= direct_index;
+ if (block < direct_blks)
+ {
+ offset[n++] = NODE_DIR1_BLOCK;
+ noffset[n] = 1;
+ offset[n] = block;
+ level = 1;
+ goto got;
+ }
+
+ block -= direct_blks;
+ if (block < direct_blks)
+ {
+ offset[n++] = NODE_DIR2_BLOCK;
+ noffset[n] = 2;
+ offset[n] = block;
+ level = 1;
+ goto got;
+ }
+
+ block -= direct_blks;
+ if (block < indirect_blks)
+ {
+ offset[n++] = NODE_IND1_BLOCK;
+ noffset[n] = 3;
+ offset[n++] = block / direct_blks;
+ noffset[n] = 4 + offset[n - 1];
+ offset[n] = block % direct_blks;
+ level = 2;
+ goto got;
+ }
+
+ block -= indirect_blks;
+ if (block < indirect_blks)
+ {
+ offset[n++] = NODE_IND2_BLOCK;
+ noffset[n] = 4 + dptrs_per_blk;
+ offset[n++] = block / direct_blks;
+ noffset[n] = 5 + dptrs_per_blk + offset[n - 1];
+ offset[n] = block % direct_blks;
+ level = 2;
+ goto got;
+ }
+
+ block -= indirect_blks;
+ if (block < dindirect_blks)
+ {
+ offset[n++] = NODE_DIND_BLOCK;
+ noffset[n] = 5 + (dptrs_per_blk * 2);
+ offset[n++] = block / indirect_blks;
+ noffset[n] = 6 + (dptrs_per_blk * 2) +
+ offset[n - 1] * (dptrs_per_blk + 1);
+ offset[n++] = (block / direct_blks) % dptrs_per_blk;
+ noffset[n] = 7 + (dptrs_per_blk * 2) +
+ offset[n - 2] * (dptrs_per_blk + 1) + offset[n - 1];
+ offset[n] = block % direct_blks;
+ level = 3;
+ goto got;
+ }
+
+ got:
+ return level;
+}
+
+static grub_err_t
+grub_f2fs_read_node (struct grub_f2fs_data *data,
+ grub_uint32_t nid, struct grub_f2fs_node *np)
+{
+ grub_uint32_t blkaddr;
+
+ blkaddr = get_node_blkaddr (data, nid);
+ if (!blkaddr)
+ return grub_errno;
+
+ return grub_f2fs_block_read (data, blkaddr, np);
+}
+
+static struct grub_f2fs_data *
+grub_f2fs_mount (grub_disk_t disk)
+{
+ struct grub_f2fs_data *data;
+ grub_err_t err;
+
+ data = grub_malloc (sizeof (*data));
+ if (!data)
+ return NULL;
+
+ data->disk = disk;
+
+ if (grub_f2fs_read_sb (data, F2FS_SUPER_OFFSET0))
+ {
+ if (grub_f2fs_read_sb (data, F2FS_SUPER_OFFSET1))
+ {
+ if (grub_errno == GRUB_ERR_NONE)
+ grub_error (GRUB_ERR_BAD_FS,
+ "not a F2FS filesystem (no superblock)");
+ goto fail;
+ }
+ }
+
+ data->root_ino = grub_le_to_cpu32 (data->sblock.root_ino);
+ data->cp_blkaddr = grub_le_to_cpu32 (data->sblock.cp_blkaddr);
+ data->nat_blkaddr = grub_le_to_cpu32 (data->sblock.nat_blkaddr);
+ data->blocks_per_seg = 1 <<
+ grub_le_to_cpu32 (data->sblock.log_blocks_per_seg);
+
+ err = grub_f2fs_read_cp (data);
+ if (err)
+ goto fail;
+
+ data->nat_bitmap = nat_bitmap_ptr (data);
+
+ err = get_nat_journal (data);
+ if (err)
+ goto fail;
+
+ data->diropen.data = data;
+ data->diropen.ino = data->root_ino;
+ data->diropen.inode_read = 1;
+ data->inode = &data->diropen.inode;
+
+ err = grub_f2fs_read_node (data, data->root_ino, data->inode);
+ if (err)
+ goto fail;
+
+ return data;
+
+ fail:
+ grub_free (data);
+
+ return NULL;
+}
+
+/* Guarantee inline_data was handled by caller. */
+static grub_disk_addr_t
+grub_f2fs_get_block (grub_fshelp_node_t node, grub_disk_addr_t block_ofs)
+{
+ struct grub_f2fs_data *data = node->data;
+ struct grub_f2fs_inode *inode = &node->inode.i;
+ grub_uint32_t offset[4], noffset[4], nids[4];
+ struct grub_f2fs_node *node_block;
+ grub_uint32_t block_addr = -1;
+ int level, i;
+
+ level = grub_get_node_path (inode, block_ofs, offset, noffset);
+ if (level == 0)
+ return grub_le_to_cpu32 (inode->i_addr[offset[0]]);
+
+ node_block = grub_malloc (F2FS_BLKSIZE);
+ if (!node_block)
+ return -1;
+
+ nids[1] = get_node_id (&node->inode, offset[0], 1);
+
+ /* Get indirect or direct nodes. */
+ for (i = 1; i <= level; i++)
+ {
+ grub_f2fs_read_node (data, nids[i], node_block);
+ if (grub_errno)
+ goto fail;
+
+ if (i < level)
+ nids[i + 1] = get_node_id (node_block, offset[i], 0);
+ }
+
+ block_addr = grub_le_to_cpu32 (node_block->dn.addr[offset[level]]);
+
+ fail:
+ grub_free (node_block);
+
+ return block_addr;
+}
+
+static grub_ssize_t
+grub_f2fs_read_file (grub_fshelp_node_t node,
+ grub_disk_read_hook_t read_hook, void *read_hook_data,
+ grub_off_t pos, grub_size_t len, char *buf)
+{
+ struct grub_f2fs_inode *inode = &node->inode.i;
+ grub_off_t filesize = grub_f2fs_file_size (inode);
+ char *inline_addr = get_inline_addr (inode);
+
+ if (inode->i_inline & F2FS_INLINE_DATA)
+ {
+ if (filesize > MAX_INLINE_DATA)
+ return -1;
+
+ if (len > filesize - pos)
+ len = filesize - pos;
+
+ grub_memcpy (buf, inline_addr + pos, len);
+ return len;
+ }
+
+ return grub_fshelp_read_file (node->data->disk, node,
+ read_hook, read_hook_data,
+ pos, len, buf, grub_f2fs_get_block,
+ filesize,
+ F2FS_BLK_SEC_BITS, 0);
+}
+
+static char *
+grub_f2fs_read_symlink (grub_fshelp_node_t node)
+{
+ char *symlink;
+ struct grub_fshelp_node *diro = node;
+ grub_uint64_t filesize;
+
+ if (!diro->inode_read)
+ {
+ grub_f2fs_read_node (diro->data, diro->ino, &diro->inode);
+ if (grub_errno)
+ return 0;
+ }
+
+ filesize = grub_f2fs_file_size(&diro->inode.i);
+
+ symlink = grub_malloc (filesize + 1);
+ if (!symlink)
+ return 0;
+
+ grub_f2fs_read_file (diro, 0, 0, 0, filesize, symlink);
+ if (grub_errno)
+ {
+ grub_free (symlink);
+ return 0;
+ }
+
+ symlink[filesize] = '\0';
+
+ return symlink;
+}
+
+static int
+grub_f2fs_check_dentries (struct grub_f2fs_dir_iter_ctx *ctx)
+{
+ struct grub_fshelp_node *fdiro;
+ int i;
+
+ for (i = 0; i < ctx->max;)
+ {
+ char *filename;
+ enum grub_fshelp_filetype type = GRUB_FSHELP_UNKNOWN;
+ enum FILE_TYPE ftype;
+ int name_len;
+ int ret;
+
+ if (grub_f2fs_test_bit_le (i, ctx->bitmap) == 0)
+ {
+ i++;
+ continue;
+ }
+
+ ftype = ctx->dentry[i].file_type;
+ name_len = grub_le_to_cpu16 (ctx->dentry[i].name_len);
+ filename = grub_malloc (name_len + 1);
+ if (!filename)
+ return 0;
+
+ grub_memcpy (filename, ctx->filename[i], name_len);
+ filename[name_len] = 0;
+
+ fdiro = grub_malloc (sizeof (struct grub_fshelp_node));
+ if (!fdiro)
+ {
+ grub_free(filename);
+ return 0;
+ }
+
+ if (ftype == F2FS_FT_DIR)
+ type = GRUB_FSHELP_DIR;
+ else if (ftype == F2FS_FT_SYMLINK)
+ type = GRUB_FSHELP_SYMLINK;
+ else if (ftype == F2FS_FT_REG_FILE)
+ type = GRUB_FSHELP_REG;
+
+ fdiro->data = ctx->data;
+ fdiro->ino = grub_le_to_cpu32 (ctx->dentry[i].ino);
+ fdiro->inode_read = 0;
+
+ ret = ctx->hook (filename, type, fdiro, ctx->hook_data);
+ grub_free(filename);
+ if (ret)
+ return 1;
+
+ i += (name_len + F2FS_SLOT_LEN - 1) / F2FS_SLOT_LEN;
+ }
+
+ return 0;
+}
+
+static int
+grub_f2fs_iterate_inline_dir (struct grub_f2fs_inode *dir,
+ struct grub_f2fs_dir_iter_ctx *ctx)
+{
+ struct grub_f2fs_inline_dentry *de_blk;
+
+ de_blk = (struct grub_f2fs_inline_dentry *) get_inline_addr (dir);
+
+ ctx->bitmap = de_blk->dentry_bitmap;
+ ctx->dentry = de_blk->dentry;
+ ctx->filename = de_blk->filename;
+ ctx->max = NR_INLINE_DENTRY;
+
+ return grub_f2fs_check_dentries (ctx);
+}
+
+static int
+grub_f2fs_iterate_dir (grub_fshelp_node_t dir,
+ grub_fshelp_iterate_dir_hook_t hook, void *hook_data)
+{
+ struct grub_fshelp_node *diro = (struct grub_fshelp_node *) dir;
+ struct grub_f2fs_inode *inode;
+ struct grub_f2fs_dir_iter_ctx ctx = {
+ .data = diro->data,
+ .hook = hook,
+ .hook_data = hook_data
+ };
+ grub_off_t fpos = 0;
+
+ if (!diro->inode_read)
+ {
+ grub_f2fs_read_node (diro->data, diro->ino, &diro->inode);
+ if (grub_errno)
+ return 0;
+ }
+
+ inode = &diro->inode.i;
+
+ if (inode->i_inline & F2FS_INLINE_DENTRY)
+ return grub_f2fs_iterate_inline_dir (inode, &ctx);
+
+ while (fpos < grub_f2fs_file_size (inode))
+ {
+ struct grub_f2fs_dentry_block *de_blk;
+ char *buf;
+ int ret;
+
+ buf = grub_zalloc (F2FS_BLKSIZE);
+ if (!buf)
+ return 0;
+
+ grub_f2fs_read_file (diro, 0, 0, fpos, F2FS_BLKSIZE, buf);
+ if (grub_errno)
+ {
+ grub_free (buf);
+ return 0;
+ }
+
+ de_blk = (struct grub_f2fs_dentry_block *) buf;
+
+ ctx.bitmap = de_blk->dentry_bitmap;
+ ctx.dentry = de_blk->dentry;
+ ctx.filename = de_blk->filename;
+ ctx.max = NR_DENTRY_IN_BLOCK;
+
+ ret = grub_f2fs_check_dentries (&ctx);
+ grub_free (buf);
+ if (ret)
+ return 1;
+
+ fpos += F2FS_BLKSIZE;
+ }
+
+ return 0;
+}
+
+static int
+grub_f2fs_dir_iter (const char *filename, enum grub_fshelp_filetype filetype,
+ grub_fshelp_node_t node, void *data)
+{
+ struct grub_f2fs_dir_ctx *ctx = data;
+ struct grub_dirhook_info info;
+
+ grub_memset (&info, 0, sizeof (info));
+ if (!node->inode_read)
+ {
+ grub_f2fs_read_node (ctx->data, node->ino, &node->inode);
+ if (!grub_errno)
+ node->inode_read = 1;
+ grub_errno = GRUB_ERR_NONE;
+ }
+ if (node->inode_read)
+ {
+ info.mtimeset = 1;
+ info.mtime = grub_le_to_cpu64 (node->inode.i.i_mtime);
+ }
+
+ info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
+ grub_free (node);
+
+ return ctx->hook (filename, &info, ctx->hook_data);
+}
+
+static grub_err_t
+grub_f2fs_dir (grub_device_t device, const char *path,
+ grub_fs_dir_hook_t hook, void *hook_data)
+{
+ struct grub_f2fs_dir_ctx ctx = {
+ .hook = hook,
+ .hook_data = hook_data
+ };
+ struct grub_fshelp_node *fdiro = 0;
+
+ grub_dl_ref (my_mod);
+
+ ctx.data = grub_f2fs_mount (device->disk);
+ if (!ctx.data)
+ goto fail;
+
+ grub_fshelp_find_file (path, &ctx.data->diropen, &fdiro,
+ grub_f2fs_iterate_dir, grub_f2fs_read_symlink,
+ GRUB_FSHELP_DIR);
+ if (grub_errno)
+ goto fail;
+
+ grub_f2fs_iterate_dir (fdiro, grub_f2fs_dir_iter, &ctx);
+
+ fail:
+ if (fdiro != &ctx.data->diropen)
+ grub_free (fdiro);
+ grub_free (ctx.data);
+ grub_dl_unref (my_mod);
+
+ return grub_errno;
+}
+
+/* Open a file named NAME and initialize FILE. */
+static grub_err_t
+grub_f2fs_open (struct grub_file *file, const char *name)
+{
+ struct grub_f2fs_data *data = NULL;
+ struct grub_fshelp_node *fdiro = 0;
+ struct grub_f2fs_inode *inode;
+
+ grub_dl_ref (my_mod);
+
+ data = grub_f2fs_mount (file->device->disk);
+ if (!data)
+ goto fail;
+
+ grub_fshelp_find_file (name, &data->diropen, &fdiro,
+ grub_f2fs_iterate_dir, grub_f2fs_read_symlink,
+ GRUB_FSHELP_REG);
+ if (grub_errno)
+ goto fail;
+
+ if (!fdiro->inode_read)
+ {
+ grub_f2fs_read_node (data, fdiro->ino, &fdiro->inode);
+ if (grub_errno)
+ goto fail;
+ }
+
+ grub_memcpy (data->inode, &fdiro->inode, sizeof (*data->inode));
+ grub_free (fdiro);
+
+ inode = &(data->inode->i);
+ file->size = grub_f2fs_file_size (inode);
+ file->data = data;
+ file->offset = 0;
+
+ if (inode->i_inline & F2FS_INLINE_DATA && file->size > MAX_INLINE_DATA)
+ grub_error (GRUB_ERR_BAD_FS, "corrupted inline_data: need fsck");
+
+ return 0;
+
+ fail:
+ if (fdiro != &data->diropen)
+ grub_free (fdiro);
+ grub_free (data);
+
+ grub_dl_unref (my_mod);
+
+ return grub_errno;
+}
+
+static grub_ssize_t
+grub_f2fs_read (grub_file_t file, char *buf, grub_size_t len)
+{
+ struct grub_f2fs_data *data = (struct grub_f2fs_data *) file->data;
+
+ return grub_f2fs_read_file (&data->diropen,
+ file->read_hook, file->read_hook_data,
+ file->offset, len, buf);
+}
+
+static grub_err_t
+grub_f2fs_close (grub_file_t file)
+{
+ struct grub_f2fs_data *data = (struct grub_f2fs_data *) file->data;
+
+ grub_free (data);
+
+ grub_dl_unref (my_mod);
+
+ return GRUB_ERR_NONE;
+}
+
+static grub_uint8_t *
+grub_f2fs_utf16_to_utf8 (grub_uint16_t *in_buf_le)
+{
+ grub_uint16_t in_buf[MAX_VOLUME_NAME];
+ grub_uint8_t *out_buf;
+ int len = 0;
+
+ out_buf = grub_malloc (MAX_VOLUME_NAME * GRUB_MAX_UTF8_PER_UTF16 + 1);
+ if (!out_buf)
+ return NULL;
+
+ while (*in_buf_le != 0 && len < MAX_VOLUME_NAME) {
+ in_buf[len] = grub_le_to_cpu16 (in_buf_le[len]);
+ len++;
+ }
+
+ *grub_utf16_to_utf8 (out_buf, in_buf, len) = '\0';
+
+ return out_buf;
+}
+
+static grub_err_t
+grub_f2fs_label (grub_device_t device, char **label)
+{
+ struct grub_f2fs_data *data;
+ grub_disk_t disk = device->disk;
+
+ grub_dl_ref (my_mod);
+
+ data = grub_f2fs_mount (disk);
+ if (data)
+ *label = (char *) grub_f2fs_utf16_to_utf8 (data->sblock.volume_name);
+ else
+ *label = NULL;
+
+ grub_free (data);
+ grub_dl_unref (my_mod);
+
+ return grub_errno;
+}
+
+static grub_err_t
+grub_f2fs_uuid (grub_device_t device, char **uuid)
+{
+ struct grub_f2fs_data *data;
+ grub_disk_t disk = device->disk;
+
+ grub_dl_ref (my_mod);
+
+ data = grub_f2fs_mount (disk);
+ if (data)
+ {
+ *uuid =
+ grub_xasprintf
+ ("%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+ data->sblock.uuid[0], data->sblock.uuid[1],
+ data->sblock.uuid[2], data->sblock.uuid[3],
+ data->sblock.uuid[4], data->sblock.uuid[5],
+ data->sblock.uuid[6], data->sblock.uuid[7],
+ data->sblock.uuid[8], data->sblock.uuid[9],
+ data->sblock.uuid[10], data->sblock.uuid[11],
+ data->sblock.uuid[12], data->sblock.uuid[13],
+ data->sblock.uuid[14], data->sblock.uuid[15]);
+ }
+ else
+ *uuid = NULL;
+
+ grub_free (data);
+ grub_dl_unref (my_mod);
+
+ return grub_errno;
+}
+
+static struct grub_fs grub_f2fs_fs = {
+ .name = "f2fs",
+ .dir = grub_f2fs_dir,
+ .open = grub_f2fs_open,
+ .read = grub_f2fs_read,
+ .close = grub_f2fs_close,
+ .label = grub_f2fs_label,
+ .uuid = grub_f2fs_uuid,
+#ifdef GRUB_UTIL
+ .reserved_first_sector = 1,
+ .blocklist_install = 0,
+#endif
+ .next = 0
+};
+
+GRUB_MOD_INIT (f2fs)
+{
+ grub_fs_register (&grub_f2fs_fs);
+ my_mod = mod;
+}
+
+GRUB_MOD_FINI (f2fs)
+{
+ grub_fs_unregister (&grub_f2fs_fs);
+}
diff --git a/grub-core/fs/udf.c b/grub-core/fs/udf.c
index 839bff88963baba7730d788869e1f50481a66a30..00a16098b47aff52a352fa9433e279beae261329 100644
--- a/grub-core/fs/udf.c
+++ b/grub-core/fs/udf.c
@@ -321,6 +321,32 @@ struct grub_udf_partmap
};
} GRUB_PACKED;
+struct grub_udf_pvd
+{
+ struct grub_udf_tag tag;
+ grub_uint32_t seq_num;
+ grub_uint32_t pvd_num;
+ grub_uint8_t ident[32];
+ grub_uint16_t vol_seq_num;
+ grub_uint16_t max_vol_seq_num;
+ grub_uint16_t interchange_level;
+ grub_uint16_t max_interchange_level;
+ grub_uint32_t charset_list;
+ grub_uint32_t max_charset_list;
+ grub_uint8_t volset_ident[128];
+ struct grub_udf_charspec desc_charset;
+ struct grub_udf_charspec expl_charset;
+ struct grub_udf_extent_ad vol_abstract;
+ struct grub_udf_extent_ad vol_copyright;
+ struct grub_udf_regid app_ident;
+ struct grub_udf_timestamp recording_time;
+ struct grub_udf_regid imp_ident;
+ grub_uint8_t imp_use[64];
+ grub_uint32_t pred_vds_loc;
+ grub_uint16_t flags;
+ grub_uint8_t reserved[22];
+} GRUB_PACKED;
+
struct grub_udf_lvd
{
struct grub_udf_tag tag;
@@ -348,6 +374,7 @@ struct grub_udf_aed
struct grub_udf_data
{
grub_disk_t disk;
+ struct grub_udf_pvd pvd;
struct grub_udf_lvd lvd;
struct grub_udf_pd pds[GRUB_UDF_MAX_PDS];
struct grub_udf_partmap *pms[GRUB_UDF_MAX_PMS];
@@ -692,7 +719,17 @@ grub_udf_mount (grub_disk_t disk)
}
tag.tag_ident = U16 (tag.tag_ident);
- if (tag.tag_ident == GRUB_UDF_TAG_IDENT_PD)
+ if (tag.tag_ident == GRUB_UDF_TAG_IDENT_PVD)
+ {
+ if (grub_disk_read (disk, block << lbshift, 0,
+ sizeof (struct grub_udf_pvd),
+ &data->pvd))
+ {
+ grub_error (GRUB_ERR_BAD_FS, "not an UDF filesystem");
+ goto fail;
+ }
+ }
+ else if (tag.tag_ident == GRUB_UDF_TAG_IDENT_PD)
{
if (data->npd >= GRUB_UDF_MAX_PDS)
{
@@ -860,6 +897,25 @@ read_string (const grub_uint8_t *raw, grub_size_t sz, char *outbuf)
return outbuf;
}
+static char *
+read_dstring (const grub_uint8_t *raw, grub_size_t sz)
+{
+ grub_size_t len;
+
+ if (raw[0] == 0) {
+ char *outbuf = grub_malloc (1);
+ if (!outbuf)
+ return NULL;
+ outbuf[0] = 0;
+ return outbuf;
+ }
+
+ len = raw[sz - 1];
+ if (len > sz - 1)
+ len = sz - 1;
+ return read_string (raw, len, NULL);
+}
+
static int
grub_udf_iterate_dir (grub_fshelp_node_t dir,
grub_fshelp_iterate_dir_hook_t hook, void *hook_data)
@@ -1197,7 +1253,7 @@ grub_udf_label (grub_device_t device, char **label)
if (data)
{
- *label = read_string (data->lvd.ident, sizeof (data->lvd.ident), 0);
+ *label = read_dstring (data->lvd.ident, sizeof (data->lvd.ident));
grub_free (data);
}
else
@@ -1206,6 +1262,87 @@ grub_udf_label (grub_device_t device, char **label)
return grub_errno;
}
+static char *
+gen_uuid_from_volset (char *volset_ident)
+{
+ grub_size_t i;
+ grub_size_t len;
+ grub_size_t nonhexpos;
+ grub_uint8_t buf[17];
+ char *uuid;
+
+ len = grub_strlen (volset_ident);
+ if (len < 8)
+ return NULL;
+
+ uuid = grub_malloc (17);
+ if (!uuid)
+ return NULL;
+
+ if (len > 16)
+ len = 16;
+
+ grub_memset (buf, 0, sizeof (buf));
+ grub_memcpy (buf, volset_ident, len);
+
+ nonhexpos = 16;
+ for (i = 0; i < 16; ++i)
+ {
+ if (!grub_isxdigit (buf[i]))
+ {
+ nonhexpos = i;
+ break;
+ }
+ }
+
+ if (nonhexpos < 8)
+ {
+ grub_snprintf (uuid, 17, "%02x%02x%02x%02x%02x%02x%02x%02x",
+ buf[0], buf[1], buf[2], buf[3],
+ buf[4], buf[5], buf[6], buf[7]);
+ }
+ else if (nonhexpos < 16)
+ {
+ for (i = 0; i < 8; ++i)
+ uuid[i] = grub_tolower (buf[i]);
+ grub_snprintf (uuid+8, 9, "%02x%02x%02x%02x",
+ buf[8], buf[9], buf[10], buf[11]);
+ }
+ else
+ {
+ for (i = 0; i < 16; ++i)
+ uuid[i] = grub_tolower (buf[i]);
+ uuid[16] = 0;
+ }
+
+ return uuid;
+}
+
+static grub_err_t
+grub_udf_uuid (grub_device_t device, char **uuid)
+{
+ char *volset_ident;
+ struct grub_udf_data *data;
+ data = grub_udf_mount (device->disk);
+
+ if (data)
+ {
+ volset_ident = read_dstring (data->pvd.volset_ident, sizeof (data->pvd.volset_ident));
+ if (volset_ident)
+ {
+ *uuid = gen_uuid_from_volset (volset_ident);
+ grub_free (volset_ident);
+ }
+ else
+ *uuid = 0;
+ grub_free (data);
+ }
+ else
+ *uuid = 0;
+
+ return grub_errno;
+}
+
static struct grub_fs grub_udf_fs = {
.name = "udf",
.dir = grub_udf_dir,
@@ -1213,6 +1350,7 @@ static struct grub_fs grub_udf_fs = {
.read = grub_udf_read,
.close = grub_udf_close,
.label = grub_udf_label,
+ .uuid = grub_udf_uuid,
#ifdef GRUB_UTIL
.reserved_first_sector = 1,
.blocklist_install = 1,
diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c
index 9f66dd6e4c6491e6b2cbfc7866335b432c824502..3b00c744e23c34243df781baa96e5b1b0d88417d 100644
--- a/grub-core/fs/xfs.c
+++ b/grub-core/fs/xfs.c
@@ -79,9 +79,18 @@ GRUB_MOD_LICENSE ("GPLv3+");
#define XFS_SB_FEAT_INCOMPAT_SPINODES (1 << 1) /* sparse inode chunks */
#define XFS_SB_FEAT_INCOMPAT_META_UUID (1 << 2) /* metadata UUID */
-/* We do not currently verify metadata UUID so it is safe to read such filesystem */
+/*
+ * Directory entries with ftype are explicitly handled by GRUB code.
+ *
+ * We do not currently read the inode btrees, so it is safe to read filesystems
+ * with the XFS_SB_FEAT_INCOMPAT_SPINODES feature.
+ *
+ * We do not currently verify metadata UUID, so it is safe to read filesystems
+ * with the XFS_SB_FEAT_INCOMPAT_META_UUID feature.
+ */
#define XFS_SB_FEAT_INCOMPAT_SUPPORTED \
(XFS_SB_FEAT_INCOMPAT_FTYPE | \
+ XFS_SB_FEAT_INCOMPAT_SPINODES | \
XFS_SB_FEAT_INCOMPAT_META_UUID)
struct grub_xfs_sblock
@@ -828,6 +837,9 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir,
entries = (grub_be_to_cpu32 (tail->leaf_count)
- grub_be_to_cpu32 (tail->leaf_stale));
+ if (!entries)
+ continue;
+
/* Iterate over all entries within this block. */
while ((char *)direntry < (char *)tail)
{
diff --git a/grub-core/fs/zfs/zfs_lz4.c b/grub-core/fs/zfs/zfs_lz4.c
index 2f73449f0d4c63cadc7b5b4388250a4d474594b6..5453822d0258527ba751e551cbb54753f0331043 100644
--- a/grub-core/fs/zfs/zfs_lz4.c
+++ b/grub-core/fs/zfs/zfs_lz4.c
@@ -73,7 +73,6 @@ static int LZ4_uncompress_unknownOutputSize(const char *source, char *dest,
#define U32 grub_uint32_t
#define S32 grub_int32_t
#define U64 grub_uint64_t
-typedef grub_size_t size_t;
typedef struct _U16_S {
U16 v;
@@ -133,10 +132,10 @@ typedef struct _U64_S {
/* Decompression functions */
grub_err_t
-lz4_decompress(void *s_start, void *d_start, size_t s_len, size_t d_len);
+lz4_decompress(void *s_start, void *d_start, grub_size_t s_len, grub_size_t d_len);
grub_err_t
-lz4_decompress(void *s_start, void *d_start, size_t s_len, size_t d_len)
+lz4_decompress(void *s_start, void *d_start, grub_size_t s_len, grub_size_t d_len)
{
const BYTE *src = s_start;
U32 bufsiz = (src[0] << 24) | (src[1] << 16) | (src[2] << 8) |
@@ -167,7 +166,7 @@ LZ4_uncompress_unknownOutputSize(const char *source,
BYTE *const oend = op + maxOutputSize;
BYTE *cpy;
- size_t dec[] = { 0, 3, 2, 3, 0, 0, 0, 0 };
+ grub_size_t dec[] = { 0, 3, 2, 3, 0, 0, 0, 0 };
/* Main Loop */
while (ip < iend) {
@@ -237,8 +236,8 @@ LZ4_uncompress_unknownOutputSize(const char *source,
/* copy repeated sequence */
if unlikely(op - ref < STEPSIZE) {
#if LZ4_ARCH64
- size_t dec2table[] = { 0, 0, 0, -1, 0, 1, 2, 3 };
- size_t dec2 = dec2table[op - ref];
+ grub_size_t dec2table[] = { 0, 0, 0, -1, 0, 1, 2, 3 };
+ grub_size_t dec2 = dec2table[op - ref];
#else
const int dec2 = 0;
#endif
diff --git a/grub-core/io/bufio.c b/grub-core/io/bufio.c
index 22438277d7456358dfc6bcbb51317fd704987738..dbed64744317c2f849fb2bda8fd5a6b142affe91 100644
--- a/grub-core/io/bufio.c
+++ b/grub-core/io/bufio.c
@@ -61,6 +61,13 @@ grub_bufio_open (grub_file_t io, int size)
size = ((io->size > GRUB_BUFIO_MAX_SIZE) ? GRUB_BUFIO_MAX_SIZE :
io->size);
+ /*
+ * Round up size to power of 2 which the binary math to
+ * calculate next_buf in grub_bufio_read() requires.
+ */
+ while (size & (size - 1))
+ size = (size | (size - 1)) + 1;
+
bufio = grub_zalloc (sizeof (struct grub_bufio) + size);
if (! bufio)
{
diff --git a/grub-core/io/gzio.c b/grub-core/io/gzio.c
index 0f2ea6bd845227265eef205c212e7c52ee03ebcf..86ea8cfdea2e0abd1f73c6df4dca58806c8f2d9b 100644
--- a/grub-core/io/gzio.c
+++ b/grub-core/io/gzio.c
@@ -43,6 +43,7 @@
#include
#include
#include
+#include
GRUB_MOD_LICENSE ("GPLv3+");
@@ -94,6 +95,14 @@ struct grub_gzio
struct huft *tl;
/* The distance code table. */
struct huft *td;
+ /* The checksum algorithm */
+ const gcry_md_spec_t *hdesc;
+ /* The wanted checksum */
+ grub_uint32_t orig_checksum;
+ /* The uncompressed length */
+ grub_size_t orig_len;
+ /* Context for checksum calculation */
+ grub_uint8_t *hcontext;
/* The lookup bits for the literal/length code table. */
int bl;
/* The lookup bits for the distance code table. */
@@ -140,24 +149,24 @@ eat_field (grub_file_t file, int len)
#define OLD_GZIP_MAGIC grub_le_to_cpu16 (0x9E1F)
/* Compression methods (see algorithm.doc) */
-#define STORED 0
-#define COMPRESSED 1
-#define PACKED 2
-#define LZHED 3
+#define GRUB_GZ_STORED 0
+#define GRUB_GZ_COMPRESSED 1
+#define GRUB_GZ_PACKED 2
+#define GRUB_GZ_LZHED 3
/* methods 4 to 7 reserved */
-#define DEFLATED 8
-#define MAX_METHODS 9
+#define GRUB_GZ_DEFLATED 8
+#define GRUB_GZ_MAX_METHODS 9
/* gzip flag byte */
-#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */
-#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */
-#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
-#define ORIG_NAME 0x08 /* bit 3 set: original file name present */
-#define COMMENT 0x10 /* bit 4 set: file comment present */
-#define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */
-#define RESERVED 0xC0 /* bit 6,7: reserved */
+#define GRUB_GZ_ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */
+#define GRUB_GZ_CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */
+#define GRUB_GZ_EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
+#define GRUB_GZ_ORIG_NAME 0x08 /* bit 3 set: original file name present */
+#define GRUB_GZ_COMMENT 0x10 /* bit 4 set: file comment present */
+#define GRUB_GZ_ENCRYPTED 0x20 /* bit 5 set: file is encrypted */
+#define GRUB_GZ_RESERVED 0xC0 /* bit 6,7: reserved */
-#define UNSUPPORTED_FLAGS (CONTINUATION | ENCRYPTED | RESERVED)
+#define GRUB_GZ_UNSUPPORTED_FLAGS (GRUB_GZ_CONTINUATION | GRUB_GZ_ENCRYPTED | GRUB_GZ_RESERVED)
/* inflate block codes */
#define INFLATE_STORED 0
@@ -180,7 +189,7 @@ test_gzip_header (grub_file_t file)
grub_uint8_t os_type;
} hdr;
grub_uint16_t extra_len;
- grub_uint32_t orig_len;
+ grub_uint32_t crc32;
grub_gzio_t gzio = file->data;
if (grub_file_tell (gzio->file) != 0)
@@ -201,26 +210,29 @@ test_gzip_header (grub_file_t file)
* problem occurs from here on, then we have corrupt or otherwise
* bad data, and the error should be reported to the user.
*/
- if (hdr.method != DEFLATED
- || (hdr.flags & UNSUPPORTED_FLAGS)
- || ((hdr.flags & EXTRA_FIELD)
+ if (hdr.method != GRUB_GZ_DEFLATED
+ || (hdr.flags & GRUB_GZ_UNSUPPORTED_FLAGS)
+ || ((hdr.flags & GRUB_GZ_EXTRA_FIELD)
&& (grub_file_read (gzio->file, &extra_len, 2) != 2
|| eat_field (gzio->file,
grub_le_to_cpu16 (extra_len))))
- || ((hdr.flags & ORIG_NAME) && eat_field (gzio->file, -1))
- || ((hdr.flags & COMMENT) && eat_field (gzio->file, -1)))
+ || ((hdr.flags & GRUB_GZ_ORIG_NAME) && eat_field (gzio->file, -1))
+ || ((hdr.flags & GRUB_GZ_COMMENT) && eat_field (gzio->file, -1)))
return 0;
gzio->data_offset = grub_file_tell (gzio->file);
/* FIXME: don't do this on not easily seekable files. */
{
- grub_file_seek (gzio->file, grub_file_size (gzio->file) - 4);
- if (grub_file_read (gzio->file, &orig_len, 4) != 4)
+ grub_file_seek (gzio->file, grub_file_size (gzio->file) - 8);
+ if (grub_file_read (gzio->file, &crc32, 4) != 4)
+ return 0;
+ gzio->orig_checksum = grub_le_to_cpu32 (crc32);
+ if (grub_file_read (gzio->file, &gzio->orig_len, 4) != 4)
return 0;
/* FIXME: this does not handle files whose original size is over 4GB.
But how can we know the real original size? */
- file->size = grub_le_to_cpu32 (orig_len);
+ file->size = grub_le_to_cpu32 (gzio->orig_len);
}
initialize_tables (gzio);
@@ -1095,7 +1107,23 @@ inflate_window (grub_gzio_t gzio)
gzio->saved_offset += gzio->wp;
- /* XXX do CRC calculation here! */
+ if (gzio->hcontext)
+ {
+ gzio->hdesc->write (gzio->hcontext, gzio->slide, gzio->wp);
+
+ if (gzio->saved_offset == gzio->orig_len)
+ {
+ grub_uint32_t csum;
+
+ gzio->hdesc->final (gzio->hcontext);
+ csum = grub_get_unaligned32 (gzio->hdesc->read (gzio->hcontext));
+ csum = grub_be_to_cpu32 (csum);
+ if (csum != gzio->orig_checksum)
+ grub_error (GRUB_ERR_BAD_COMPRESSED_DATA,
+ "checksum mismatch %08x/%08x",
+ gzio->orig_checksum, csum);
+ }
+ }
}
@@ -1118,6 +1146,9 @@ initialize_tables (grub_gzio_t gzio)
huft_free (gzio->td);
gzio->tl = NULL;
gzio->td = NULL;
+
+ if (gzio->hcontext)
+ gzio->hdesc->init(gzio->hcontext);
}
@@ -1143,6 +1174,9 @@ grub_gzio_open (grub_file_t io, const char *name __attribute__ ((unused)))
gzio->file = io;
+ gzio->hdesc = GRUB_MD_CRC32;
+ gzio->hcontext = grub_malloc(gzio->hdesc->contextsize);
+
file->device = io->device;
file->data = gzio;
file->fs = &grub_gzio_fs;
@@ -1151,6 +1185,7 @@ grub_gzio_open (grub_file_t io, const char *name __attribute__ ((unused)))
if (! test_gzip_header (file))
{
grub_errno = GRUB_ERR_NONE;
+ grub_free (gzio->hcontext);
grub_free (gzio);
grub_free (file);
grub_file_seek (io, 0);
@@ -1183,7 +1218,7 @@ test_zlib_header (grub_gzio_t gzio)
flg = get_byte (gzio);
/* Check that compression method is DEFLATE. */
- if ((cmf & 0xf) != DEFLATED)
+ if ((cmf & 0xf) != GRUB_GZ_DEFLATED)
{
/* TRANSLATORS: It's about given file having some strange format, not
complete lack of gzip support. */
@@ -1287,6 +1322,7 @@ grub_gzio_close (grub_file_t file)
grub_file_close (gzio->file);
huft_free (gzio->tl);
huft_free (gzio->td);
+ grub_free (gzio->hcontext);
grub_free (gzio);
/* No need to close the same device twice. */
diff --git a/grub-core/kern/arm/cache.c b/grub-core/kern/arm/cache.c
index 34154ccdb0e09d7d9fd91c4164fe8577ce449260..af1c4bbf544f0ebcca5c0f58c847c8dddc1f2e91 100644
--- a/grub-core/kern/arm/cache.c
+++ b/grub-core/kern/arm/cache.c
@@ -29,6 +29,8 @@ void grub_arm_clean_dcache_range_armv6 (grub_addr_t start, grub_addr_t end,
grub_addr_t dlinesz);
void grub_arm_clean_dcache_range_armv7 (grub_addr_t start, grub_addr_t end,
grub_addr_t dlinesz);
+void grub_arm_clean_dcache_range_poc_armv7 (grub_addr_t start, grub_addr_t end,
+ grub_addr_t dlinesz);
void grub_arm_invalidate_icache_range_armv6 (grub_addr_t start, grub_addr_t end,
grub_addr_t dlinesz);
void grub_arm_invalidate_icache_range_armv7 (grub_addr_t start, grub_addr_t end,
@@ -252,6 +254,38 @@ grub_arch_sync_caches (void *address, grub_size_t len)
}
}
+void
+grub_arch_sync_dma_caches (volatile void *address, grub_size_t len)
+{
+ grub_addr_t start = (grub_addr_t) address;
+ grub_addr_t end = start + len;
+
+ if (type == ARCH_UNKNOWN)
+ probe_caches ();
+ start = ALIGN_DOWN (start, grub_arch_cache_max_linesz);
+ end = ALIGN_UP (end, grub_arch_cache_max_linesz);
+ switch (type)
+ {
+ case ARCH_ARMV6:
+ grub_arm_clean_dcache_range_armv6 (start, end, grub_arch_cache_dlinesz);
+ grub_arm_invalidate_icache_range_armv6 (start, end,
+ grub_arch_cache_ilinesz);
+ break;
+ case ARCH_ARMV5_WRITE_THROUGH:
+ case ARCH_ARMV6_UNIFIED:
+ grub_arm_clean_dcache_range_armv6 (start, end, grub_arch_cache_dlinesz);
+ break;
+ case ARCH_ARMV7:
+ grub_arm_clean_dcache_range_poc_armv7 (start, end, grub_arch_cache_dlinesz);
+ grub_arm_invalidate_icache_range_armv7 (start, end,
+ grub_arch_cache_ilinesz);
+ break;
+ /* Pacify GCC. */
+ case ARCH_UNKNOWN:
+ break;
+ }
+}
+
void
grub_arm_disable_caches_mmu (void)
{
diff --git a/grub-core/kern/arm/coreboot/cbtable.c b/grub-core/kern/arm/coreboot/cbtable.c
new file mode 100644
index 0000000000000000000000000000000000000000..8a655bb5cc28fb013674dc792531d8a9ba1c4b85
--- /dev/null
+++ b/grub-core/kern/arm/coreboot/cbtable.c
@@ -0,0 +1,40 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2007,2008,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+");
+
+#pragma GCC diagnostic ignored "-Wcast-align"
+
+grub_linuxbios_table_header_t
+grub_linuxbios_get_tables (void)
+{
+ grub_linuxbios_table_header_t table_header
+ = (grub_linuxbios_table_header_t) grub_arm_saved_registers.r[0];
+
+ if (!grub_linuxbios_check_signature (table_header))
+ return 0;
+
+ return table_header;
+}
diff --git a/grub-core/kern/arm/coreboot/dma.c b/grub-core/kern/arm/coreboot/dma.c
new file mode 100644
index 0000000000000000000000000000000000000000..2c2a6278904631c91bd29b3c4338c606471672fe
--- /dev/null
+++ b/grub-core/kern/arm/coreboot/dma.c
@@ -0,0 +1,59 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2007,2009 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see .
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+struct grub_pci_dma_chunk *
+grub_memalign_dma32 (grub_size_t align, grub_size_t size)
+{
+ void *ret;
+ if (align < 64)
+ align = 64;
+ size = ALIGN_UP (size, align);
+ ret = grub_memalign (align, size);
+ if (!ret)
+ return 0;
+ grub_arch_sync_dma_caches (ret, size);
+ return ret;
+}
+
+void
+grub_dma_free (struct grub_pci_dma_chunk *ch)
+{
+ grub_size_t size = (((struct grub_mm_header *) ch) - 1)->size * GRUB_MM_ALIGN;
+ grub_arch_sync_dma_caches (ch, size);
+ grub_free (ch);
+}
+
+volatile void *
+grub_dma_get_virt (struct grub_pci_dma_chunk *ch)
+{
+ return (void *) ch;
+}
+
+grub_uint32_t
+grub_dma_get_phys (struct grub_pci_dma_chunk *ch)
+{
+ return (grub_uint32_t) (grub_addr_t) ch;
+}
+
diff --git a/grub-core/kern/arm/coreboot/init.c b/grub-core/kern/arm/coreboot/init.c
new file mode 100644
index 0000000000000000000000000000000000000000..8d8c5b8291eff9743b0325b76f851d52509b1f4f
--- /dev/null
+++ b/grub-core/kern/arm/coreboot/init.c
@@ -0,0 +1,151 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2002,2003,2004,2005,2006,2007,2008,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
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+extern grub_uint8_t _start[];
+extern grub_uint8_t _end[];
+extern grub_uint8_t _edata[];
+grub_addr_t start_of_ram = ~(grub_addr_t)0;
+
+void __attribute__ ((noreturn))
+grub_exit (void)
+{
+ /* We can't use grub_fatal() in this function. This would create an infinite
+ loop, since grub_fatal() calls grub_abort() which in turn calls grub_exit(). */
+ while (1)
+ grub_cpu_idle ();
+}
+
+static grub_uint64_t modend;
+static int have_memory = 0;
+
+/* Helper for grub_machine_init. */
+static int
+heap_init (grub_uint64_t addr, grub_uint64_t size, grub_memory_type_t type,
+ void *data __attribute__ ((unused)))
+{
+ grub_uint64_t begin = addr, end = addr + size;
+
+#if GRUB_CPU_SIZEOF_VOID_P == 4
+ /* Restrict ourselves to 32-bit memory space. */
+ if (begin > GRUB_ULONG_MAX)
+ return 0;
+ if (end > GRUB_ULONG_MAX)
+ end = GRUB_ULONG_MAX;
+#endif
+
+ if (start_of_ram > begin)
+ start_of_ram = begin;
+
+ if (type != GRUB_MEMORY_AVAILABLE)
+ return 0;
+
+ if (modend && begin < modend)
+ {
+ if (begin < (grub_addr_t)_start)
+ {
+ grub_mm_init_region ((void *) (grub_addr_t) begin, (grub_size_t) ((grub_addr_t)_start - begin));
+ have_memory = 1;
+ }
+ begin = modend;
+ }
+
+ /* Avoid DMA problems. */
+ if (end >= 0xfe000000)
+ end = 0xfe000000;
+
+ if (end <= begin)
+ return 0;
+
+ grub_mm_init_region ((void *) (grub_addr_t) begin, (grub_size_t) (end - begin));
+
+ have_memory = 1;
+
+ return 0;
+}
+
+void
+grub_machine_init (void)
+{
+ struct grub_module_header *header;
+ void *dtb = 0;
+ grub_size_t dtb_size = 0;
+
+ modend = grub_modules_get_end ();
+
+ grub_video_coreboot_fb_early_init ();
+
+ grub_machine_mmap_iterate (heap_init, NULL);
+ if (!have_memory)
+ grub_fatal ("No memory found");
+
+ grub_video_coreboot_fb_late_init ();
+
+ grub_font_init ();
+ grub_gfxterm_init ();
+
+ FOR_MODULES (header)
+ if (header->type == OBJ_TYPE_DTB)
+ {
+ char *dtb_orig_addr, *dtb_copy;
+ dtb_orig_addr = (char *) header + sizeof (struct grub_module_header);
+
+ dtb_size = header->size - sizeof (struct grub_module_header);
+ dtb = dtb_copy = grub_malloc (dtb_size);
+ grub_memmove (dtb_copy, dtb_orig_addr, dtb_size);
+ break;
+ }
+ if (!dtb)
+ grub_fatal ("No DTB found");
+ grub_fdtbus_init (dtb, dtb_size);
+
+ grub_rk3288_spi_init ();
+
+ grub_machine_timer_init ();
+ grub_cros_init ();
+ grub_pl050_init ();
+}
+
+void
+grub_machine_get_bootlocation (char **device __attribute__ ((unused)),
+ char **path __attribute__ ((unused)))
+{
+}
+
+void
+grub_machine_fini (int flags __attribute__ ((unused)))
+{
+}
diff --git a/grub-core/kern/arm/coreboot/timer.c b/grub-core/kern/arm/coreboot/timer.c
new file mode 100644
index 0000000000000000000000000000000000000000..d97b844f8487c064922a552a5ea4d5f220031dba
--- /dev/null
+++ b/grub-core/kern/arm/coreboot/timer.c
@@ -0,0 +1,101 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2016 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
+
+grub_uint64_t
+grub_armv7_get_timer_value(void);
+
+grub_uint32_t
+grub_armv7_get_timer_frequency(void);
+
+grub_uint32_t
+grub_arm_pfr1(void);
+
+static int have_timer = 0;
+static volatile grub_uint32_t *sp804_regs;
+
+static grub_uint64_t
+sp804_get_time_ms (void)
+{
+ static grub_uint32_t high, last_low;
+ grub_uint32_t low = ~sp804_regs[1];
+ if (last_low > low)
+ high++;
+ last_low = low;
+ return grub_divmod64 ((((grub_uint64_t) high) << 32) | low,
+ 1000, 0);
+}
+
+static grub_err_t
+sp804_attach(const struct grub_fdtbus_dev *dev)
+{
+ if (have_timer)
+ return GRUB_ERR_NONE;
+ sp804_regs = grub_fdtbus_map_reg (dev, 0, 0);
+ if (!grub_fdtbus_is_mapping_valid (sp804_regs))
+ return grub_error (GRUB_ERR_IO, "could not map sp804: %p", sp804_regs);
+ grub_install_get_time_ms (sp804_get_time_ms);
+ have_timer = 1;
+ return GRUB_ERR_NONE;
+}
+
+struct grub_fdtbus_driver sp804 =
+{
+ .compatible = "arm,sp804",
+ .attach = sp804_attach
+};
+
+static grub_uint32_t timer_frequency_in_khz;
+
+static grub_uint64_t
+generic_get_time_ms (void)
+{
+ return grub_divmod64 (grub_armv7_get_timer_value(), timer_frequency_in_khz, 0);
+}
+
+static int
+try_generic_timer (void)
+{
+ if (((grub_arm_pfr1 () >> 16) & 0xf) != 1)
+ return 0;
+ grub_printf ("freq = %x\n", grub_armv7_get_timer_frequency());
+ timer_frequency_in_khz = 0x016e3600 / 1000; //grub_armv7_get_timer_frequency() / 1000;
+ if (timer_frequency_in_khz == 0)
+ return 0;
+ grub_install_get_time_ms (generic_get_time_ms);
+ have_timer = 1;
+ return 1;
+}
+
+void
+grub_machine_timer_init (void)
+{
+ grub_fdtbus_register (&sp804);
+
+ if (!have_timer)
+ try_generic_timer ();
+ if (!have_timer)
+ grub_fatal ("No timer found");
+}
diff --git a/grub-core/kern/arm/efi/misc.c b/grub-core/kern/arm/efi/misc.c
deleted file mode 100644
index 7cd41842ae7662018c2ce5ff847aeb250572ec85..0000000000000000000000000000000000000000
--- a/grub-core/kern/arm/efi/misc.c
+++ /dev/null
@@ -1,202 +0,0 @@
-/* misc.c - various system functions for an arm-based EFI system */
-/*
- * 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
-
-static inline grub_size_t
-page_align (grub_size_t size)
-{
- return (size + (1 << 12) - 1) & (~((1 << 12) - 1));
-}
-
-/* Find the optimal number of pages for the memory map. Is it better to
- move this code to efi/mm.c? */
-static grub_efi_uintn_t
-find_mmap_size (void)
-{
- static grub_efi_uintn_t mmap_size = 0;
-
- if (mmap_size != 0)
- return mmap_size;
-
- mmap_size = (1 << 12);
- while (1)
- {
- int ret;
- grub_efi_memory_descriptor_t *mmap;
- grub_efi_uintn_t desc_size;
-
- mmap = grub_malloc (mmap_size);
- if (! mmap)
- return 0;
-
- ret = grub_efi_get_memory_map (&mmap_size, mmap, 0, &desc_size, 0);
- grub_free (mmap);
-
- if (ret < 0)
- {
- grub_error (GRUB_ERR_IO, "cannot get memory map");
- return 0;
- }
- else if (ret > 0)
- break;
-
- mmap_size += (1 << 12);
- }
-
- /* Increase the size a bit for safety, because GRUB allocates more on
- later, and EFI itself may allocate more. */
- mmap_size += (1 << 12);
-
- return page_align (mmap_size);
-}
-
-#define NEXT_MEMORY_DESCRIPTOR(desc, size) \
- ((grub_efi_memory_descriptor_t *) ((char *) (desc) + (size)))
-#define PAGE_SHIFT 12
-
-void *
-grub_efi_allocate_loader_memory (grub_uint32_t min_offset, grub_uint32_t size)
-{
- grub_efi_uintn_t desc_size;
- grub_efi_memory_descriptor_t *mmap, *mmap_end;
- grub_efi_uintn_t mmap_size, tmp_mmap_size;
- grub_efi_memory_descriptor_t *desc;
- void *mem = NULL;
- grub_addr_t min_start = 0;
-
- mmap_size = find_mmap_size();
- if (!mmap_size)
- return NULL;
-
- mmap = grub_malloc(mmap_size);
- if (!mmap)
- return NULL;
-
- tmp_mmap_size = mmap_size;
- if (grub_efi_get_memory_map (&tmp_mmap_size, mmap, 0, &desc_size, 0) <= 0)
- {
- grub_error (GRUB_ERR_IO, "cannot get memory map");
- goto fail;
- }
-
- mmap_end = NEXT_MEMORY_DESCRIPTOR (mmap, tmp_mmap_size);
- /* Find lowest accessible RAM location */
- {
- int found = 0;
- for (desc = mmap ; !found && (desc < mmap_end) ;
- desc = NEXT_MEMORY_DESCRIPTOR(desc, desc_size))
- {
- switch (desc->type)
- {
- case GRUB_EFI_CONVENTIONAL_MEMORY:
- case GRUB_EFI_LOADER_CODE:
- case GRUB_EFI_LOADER_DATA:
- min_start = desc->physical_start + min_offset;
- found = 1;
- break;
- default:
- break;
- }
- }
- }
-
- /* First, find free pages for the real mode code
- and the memory map buffer. */
- for (desc = mmap ; desc < mmap_end ;
- desc = NEXT_MEMORY_DESCRIPTOR(desc, desc_size))
- {
- grub_uint64_t start, end;
-
- grub_dprintf("mm", "%s: 0x%08x bytes @ 0x%08x\n",
- __FUNCTION__,
- (grub_uint32_t) (desc->num_pages << PAGE_SHIFT),
- (grub_uint32_t) (desc->physical_start));
-
- if (desc->type != GRUB_EFI_CONVENTIONAL_MEMORY)
- continue;
-
- start = desc->physical_start;
- end = start + (desc->num_pages << PAGE_SHIFT);
- grub_dprintf("mm", "%s: start=0x%016llx, end=0x%016llx\n",
- __FUNCTION__, start, end);
- start = start < min_start ? min_start : start;
- if (start + size > end)
- continue;
- grub_dprintf("mm", "%s: let's allocate some (0x%x) pages @ 0x%08x...\n",
- __FUNCTION__, (size >> PAGE_SHIFT), (grub_addr_t) start);
- mem = grub_efi_allocate_pages (start, (size >> PAGE_SHIFT) + 1);
- grub_dprintf("mm", "%s: retval=0x%08x\n",
- __FUNCTION__, (grub_addr_t) mem);
- if (! mem)
- {
- grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate memory");
- goto fail;
- }
- break;
- }
-
- if (! mem)
- {
- grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate memory");
- goto fail;
- }
-
- grub_free (mmap);
- return mem;
-
- fail:
- grub_free (mmap);
- return NULL;
-}
-
-grub_err_t
-grub_efi_prepare_platform (void)
-{
- grub_efi_uintn_t mmap_size;
- grub_efi_uintn_t map_key;
- grub_efi_uintn_t desc_size;
- grub_efi_uint32_t desc_version;
- grub_efi_memory_descriptor_t *mmap_buf;
- grub_err_t err;
-
- /*
- * Cloned from IA64
- * Must be done after grub_machine_fini because map_key is used by
- *exit_boot_services.
- */
- mmap_size = find_mmap_size ();
- if (! mmap_size)
- return GRUB_ERR_OUT_OF_MEMORY;
- mmap_buf = grub_efi_allocate_pages (0, page_align (mmap_size) >> 12);
- if (! mmap_buf)
- return GRUB_ERR_OUT_OF_MEMORY;
-
- err = grub_efi_finish_boot_services (&mmap_size, mmap_buf, &map_key,
- &desc_size, &desc_version);
- if (err != GRUB_ERR_NONE)
- return err;
-
- return GRUB_ERR_NONE;
-}
diff --git a/grub-core/kern/arm/uboot/init.c b/grub-core/kern/arm/uboot/init.c
new file mode 100644
index 0000000000000000000000000000000000000000..2a6aa3fdd3dd049848015f6c67dfc0f30a79a9c4
--- /dev/null
+++ b/grub-core/kern/arm/uboot/init.c
@@ -0,0 +1,70 @@
+/* init.c - generic U-Boot initialization and finalization */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2016 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
+
+extern int (*grub_uboot_syscall_ptr) (int, int *, ...);
+
+grub_uint32_t
+grub_uboot_get_machine_type (void)
+{
+ return grub_arm_saved_registers.r[1];
+}
+
+grub_addr_t
+grub_uboot_get_boot_data (void)
+{
+ return grub_arm_saved_registers.r[2];
+}
+
+int
+grub_uboot_api_init (void)
+{
+ struct api_signature *start, *end;
+ struct api_signature *p;
+ grub_addr_t grub_uboot_search_hint = grub_arm_saved_registers.sp;
+ if (grub_uboot_search_hint)
+ {
+ /* Extended search range to work around Trim Slice U-Boot issue */
+ start = (struct api_signature *) ((grub_uboot_search_hint & ~0x000fffff)
+ - 0x00500000);
+ end =
+ (struct api_signature *) ((grub_addr_t) start + UBOOT_API_SEARCH_LEN -
+ API_SIG_MAGLEN + 0x00500000);
+ }
+ else
+ {
+ start = 0;
+ end = (struct api_signature *) (256 * 1024 * 1024);
+ }
+
+ /* Structure alignment is (at least) 8 bytes */
+ for (p = start; p < end; p = (void *) ((grub_addr_t) p + 8))
+ {
+ if (grub_memcmp (&(p->magic), API_SIG_MAGIC, API_SIG_MAGLEN) == 0)
+ {
+ grub_uboot_syscall_ptr = p->syscall;
+ return p->version;
+ }
+ }
+
+ return 0;
+}
diff --git a/grub-core/kern/coreboot/cbtable.c b/grub-core/kern/coreboot/cbtable.c
new file mode 100644
index 0000000000000000000000000000000000000000..aec63dbd1209e4c3cbbe165d54a78277ea72f361
--- /dev/null
+++ b/grub-core/kern/coreboot/cbtable.c
@@ -0,0 +1,72 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2007,2008,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
+
+#pragma GCC diagnostic ignored "-Wcast-align"
+
+/* Helper for grub_linuxbios_table_iterate. */
+int
+grub_linuxbios_check_signature (grub_linuxbios_table_header_t tbl_header)
+{
+ if (! grub_memcmp (tbl_header->signature, "LBIO", 4))
+ return 1;
+
+ return 0;
+}
+
+grub_err_t
+grub_linuxbios_table_iterate (int (*hook) (grub_linuxbios_table_item_t,
+ void *),
+ void *hook_data)
+{
+ grub_linuxbios_table_header_t table_header = grub_linuxbios_get_tables ();
+ grub_linuxbios_table_item_t table_item;
+
+ if (!table_header)
+ return 0;
+
+signature_found:
+
+ table_item =
+ (grub_linuxbios_table_item_t) ((char *) table_header +
+ table_header->header_size);
+ for (; table_item < (grub_linuxbios_table_item_t) ((char *) table_header
+ + table_header->header_size
+ + table_header->table_size);
+ table_item = (grub_linuxbios_table_item_t) ((char *) table_item + table_item->size))
+ {
+ if (table_item->tag == GRUB_LINUXBIOS_MEMBER_LINK
+ && grub_linuxbios_check_signature ((grub_linuxbios_table_header_t) (grub_addr_t)
+ *(grub_uint64_t *) (table_item + 1)))
+ {
+ table_header = (grub_linuxbios_table_header_t) (grub_addr_t)
+ *(grub_uint64_t *) (table_item + 1);
+ goto signature_found;
+ }
+ if (hook (table_item, hook_data))
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/grub-core/kern/i386/coreboot/mmap.c b/grub-core/kern/coreboot/mmap.c
similarity index 97%
rename from grub-core/kern/i386/coreboot/mmap.c
rename to grub-core/kern/coreboot/mmap.c
index 4d29f6b7d90591939cf5d837b39c5d259a55efb0..caf8f7cef1b4552c720eb3b7ca355eb6cec32955 100644
--- a/grub-core/kern/i386/coreboot/mmap.c
+++ b/grub-core/kern/coreboot/mmap.c
@@ -16,8 +16,8 @@
* along with GRUB. If not, see .
*/
-#include
-#include
+#include
+#include
#include
#include
#include
@@ -49,6 +49,7 @@ iterate_linuxbios_table (grub_linuxbios_table_item_t table_item, void *data)
{
grub_uint64_t start = mem_region->addr;
grub_uint64_t end = mem_region->addr + mem_region->size;
+#ifdef __i386__
/* Mark region 0xa0000 - 0x100000 as reserved. */
if (start < 0x100000 && end >= 0xa0000
&& mem_region->type == GRUB_MACHINE_MEMORY_AVAILABLE)
@@ -75,6 +76,7 @@ iterate_linuxbios_table (grub_linuxbios_table_item_t table_item, void *data)
if (end <= start)
continue;
}
+#endif
if (ctx->hook (start, end - start,
/* Multiboot mmaps match with the coreboot mmap
definition. Therefore, we can just pass type
diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c
index d467785fc6ce0763ec1392a65d6b30f1747ab5c4..708581fcbde007fc0174be636771b401d5e69ea2 100644
--- a/grub-core/kern/efi/efi.c
+++ b/grub-core/kern/efi/efi.c
@@ -154,6 +154,15 @@ grub_efi_get_loaded_image (grub_efi_handle_t image_handle)
GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
}
+void
+grub_reboot (void)
+{
+ grub_machine_fini (GRUB_LOADER_FLAG_NORETURN);
+ efi_call_4 (grub_efi_system_table->runtime_services->reset_system,
+ GRUB_EFI_RESET_COLD, GRUB_EFI_SUCCESS, 0, NULL);
+ for (;;) ;
+}
+
void
grub_exit (void)
{
diff --git a/grub-core/kern/efi/init.c b/grub-core/kern/efi/init.c
index 2c31847bf6db77fab377c90e7ed36897439d6027..3dfdf2d22b02ae8847a3e19a175517d2d71544fa 100644
--- a/grub-core/kern/efi/init.c
+++ b/grub-core/kern/efi/init.c
@@ -80,4 +80,5 @@ grub_efi_fini (void)
{
grub_efidisk_fini ();
grub_console_fini ();
+ grub_efi_memory_fini ();
}
diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c
index 20a47aaf5d0df376090510ddb8337ecc8aa18e98..42ad7c570a5532c4f6a5bef9d1ff3295f413aa11 100644
--- a/grub-core/kern/efi/mm.c
+++ b/grub-core/kern/efi/mm.c
@@ -49,38 +49,86 @@ static grub_efi_uintn_t finish_desc_size;
static grub_efi_uint32_t finish_desc_version;
int grub_efi_is_finished = 0;
+/*
+ * We need to roll back EFI allocations on exit. Remember allocations that
+ * we'll free on exit.
+ */
+struct efi_allocation;
+struct efi_allocation {
+ grub_efi_physical_address_t address;
+ grub_efi_uint64_t pages;
+ struct efi_allocation *next;
+};
+static struct efi_allocation *efi_allocated_memory;
+
+static void
+grub_efi_store_alloc (grub_efi_physical_address_t address,
+ grub_efi_uintn_t pages)
+{
+ grub_efi_boot_services_t *b;
+ struct efi_allocation *alloc;
+ grub_efi_status_t status;
+
+ b = grub_efi_system_table->boot_services;
+ status = efi_call_3 (b->allocate_pool, GRUB_EFI_LOADER_DATA,
+ sizeof(*alloc), (void**)&alloc);
+
+ if (status == GRUB_EFI_SUCCESS)
+ {
+ alloc->next = efi_allocated_memory;
+ alloc->address = address;
+ alloc->pages = pages;
+ efi_allocated_memory = alloc;
+ }
+ else
+ grub_printf ("Could not malloc memory to remember EFI allocation. "
+ "Exiting GRUB won't free all memory.\n");
+}
+
+static void
+grub_efi_drop_alloc (grub_efi_physical_address_t address,
+ grub_efi_uintn_t pages)
+{
+ struct efi_allocation *ea, *eap;
+ grub_efi_boot_services_t *b;
+
+ b = grub_efi_system_table->boot_services;
+
+ for (eap = NULL, ea = efi_allocated_memory; ea; eap = ea, ea = ea->next)
+ {
+ if (ea->address != address || ea->pages != pages)
+ continue;
+
+ /* Remove the current entry from the list. */
+ if (eap)
+ eap->next = ea->next;
+ else
+ efi_allocated_memory = ea->next;
+
+ /* Then free the memory backing it. */
+ efi_call_1 (b->free_pool, ea);
+
+ /* And leave, we're done. */
+ break;
+ }
+}
+
/* Allocate pages. Return the pointer to the first of allocated pages. */
void *
-grub_efi_allocate_pages (grub_efi_physical_address_t address,
- grub_efi_uintn_t pages)
+grub_efi_allocate_pages_real (grub_efi_physical_address_t address,
+ grub_efi_uintn_t pages,
+ grub_efi_allocate_type_t alloctype,
+ grub_efi_memory_type_t memtype)
{
- grub_efi_allocate_type_t type;
grub_efi_status_t status;
grub_efi_boot_services_t *b;
-#if 1
/* Limit the memory access to less than 4GB for 32-bit platforms. */
if (address > GRUB_EFI_MAX_USABLE_ADDRESS)
return 0;
-#endif
-
-#if 1
- if (address == 0)
- {
- type = GRUB_EFI_ALLOCATE_MAX_ADDRESS;
- address = GRUB_EFI_MAX_USABLE_ADDRESS;
- }
- else
- type = GRUB_EFI_ALLOCATE_ADDRESS;
-#else
- if (address == 0)
- type = GRUB_EFI_ALLOCATE_ANY_PAGES;
- else
- type = GRUB_EFI_ALLOCATE_ADDRESS;
-#endif
b = grub_efi_system_table->boot_services;
- status = efi_call_4 (b->allocate_pages, type, GRUB_EFI_LOADER_DATA, pages, &address);
+ status = efi_call_4 (b->allocate_pages, alloctype, memtype, pages, &address);
if (status != GRUB_EFI_SUCCESS)
return 0;
@@ -89,15 +137,34 @@ grub_efi_allocate_pages (grub_efi_physical_address_t address,
/* Uggh, the address 0 was allocated... This is too annoying,
so reallocate another one. */
address = GRUB_EFI_MAX_USABLE_ADDRESS;
- status = efi_call_4 (b->allocate_pages, type, GRUB_EFI_LOADER_DATA, pages, &address);
+ status = efi_call_4 (b->allocate_pages, alloctype, memtype, pages, &address);
grub_efi_free_pages (0, pages);
if (status != GRUB_EFI_SUCCESS)
return 0;
}
+ grub_efi_store_alloc (address, pages);
+
return (void *) ((grub_addr_t) address);
}
+void *
+grub_efi_allocate_any_pages (grub_efi_uintn_t pages)
+{
+ return grub_efi_allocate_pages_real (GRUB_EFI_MAX_USABLE_ADDRESS,
+ pages, GRUB_EFI_ALLOCATE_MAX_ADDRESS,
+ GRUB_EFI_LOADER_DATA);
+}
+
+void *
+grub_efi_allocate_fixed (grub_efi_physical_address_t address,
+ grub_efi_uintn_t pages)
+{
+ return grub_efi_allocate_pages_real (address, pages,
+ GRUB_EFI_ALLOCATE_ADDRESS,
+ GRUB_EFI_LOADER_DATA);
+}
+
/* Free pages starting from ADDRESS. */
void
grub_efi_free_pages (grub_efi_physical_address_t address,
@@ -107,6 +174,8 @@ grub_efi_free_pages (grub_efi_physical_address_t address,
b = grub_efi_system_table->boot_services;
efi_call_2 (b->free_pages, address, pages);
+
+ grub_efi_drop_alloc (address, pages);
}
#if defined (__i386__) || defined (__x86_64__)
@@ -217,6 +286,30 @@ grub_efi_finish_boot_services (grub_efi_uintn_t *outbuf_size, void *outbuf,
return GRUB_ERR_NONE;
}
+/*
+ * To obtain the UEFI memory map, we must pass a buffer of sufficient size
+ * to hold the entire map. This function returns a sane start value for
+ * buffer size.
+ */
+grub_efi_uintn_t
+grub_efi_find_mmap_size (void)
+{
+ grub_efi_uintn_t mmap_size = 0;
+ grub_efi_uintn_t desc_size;
+
+ if (grub_efi_get_memory_map (&mmap_size, NULL, NULL, &desc_size, 0) < 0)
+ {
+ grub_error (GRUB_ERR_IO, "cannot get EFI memory map size");
+ return 0;
+ }
+
+ /*
+ * Add an extra page, since UEFI can alter the memory map itself on
+ * callbacks or explicit calls, including console output.
+ */
+ return ALIGN_UP (mmap_size + GRUB_EFI_PAGE_SIZE, GRUB_EFI_PAGE_SIZE);
+}
+
/* Get the memory map as defined in the EFI spec. Return 1 if successful,
return 0 if partial, or return -1 if an error occurs. */
int
@@ -402,7 +495,9 @@ add_memory_regions (grub_efi_memory_descriptor_t *memory_map,
pages = required_pages;
}
- addr = grub_efi_allocate_pages (start, pages);
+ addr = grub_efi_allocate_pages_real (start, pages,
+ GRUB_EFI_ALLOCATE_ADDRESS,
+ GRUB_EFI_LOADER_CODE);
if (! addr)
grub_fatal ("cannot allocate conventional memory %p with %u pages",
(void *) ((grub_addr_t) start),
@@ -419,6 +514,20 @@ add_memory_regions (grub_efi_memory_descriptor_t *memory_map,
grub_fatal ("too little memory");
}
+void
+grub_efi_memory_fini (void)
+{
+ /*
+ * Free all stale allocations. grub_efi_free_pages() will remove
+ * the found entry from the list and it will always find the first
+ * list entry (efi_allocated_memory is the list start). Hence we
+ * remove all entries from the list until none is left altogether.
+ */
+ while (efi_allocated_memory)
+ grub_efi_free_pages (efi_allocated_memory->address,
+ efi_allocated_memory->pages);
+}
+
#if 0
/* Print the memory map. */
static void
@@ -454,8 +563,7 @@ grub_efi_mm_init (void)
int mm_status;
/* Prepare a memory region to store two memory maps. */
- memory_map = grub_efi_allocate_pages (0,
- 2 * BYTES_TO_PAGES (MEMORY_MAP_SIZE));
+ memory_map = grub_efi_allocate_any_pages (2 * BYTES_TO_PAGES (MEMORY_MAP_SIZE));
if (! memory_map)
grub_fatal ("cannot allocate memory");
@@ -473,7 +581,7 @@ grub_efi_mm_init (void)
/* Freeing/allocating operations may increase memory map size. */
map_size += desc_size * 32;
- memory_map = grub_efi_allocate_pages (0, 2 * BYTES_TO_PAGES (map_size));
+ memory_map = grub_efi_allocate_any_pages (2 * BYTES_TO_PAGES (map_size));
if (! memory_map)
grub_fatal ("cannot allocate memory");
@@ -525,3 +633,34 @@ grub_efi_mm_init (void)
grub_efi_free_pages ((grub_addr_t) memory_map,
2 * BYTES_TO_PAGES (MEMORY_MAP_SIZE));
}
+
+#if defined (__aarch64__) || defined (__arm__)
+grub_err_t
+grub_efi_get_ram_base(grub_addr_t *base_addr)
+{
+ grub_efi_memory_descriptor_t *memory_map, *desc;
+ grub_efi_uintn_t memory_map_size, desc_size;
+ int ret;
+
+ memory_map_size = grub_efi_find_mmap_size();
+
+ memory_map = grub_malloc (memory_map_size);
+ if (! memory_map)
+ return GRUB_ERR_OUT_OF_MEMORY;
+ ret = grub_efi_get_memory_map (&memory_map_size, memory_map, NULL,
+ &desc_size, NULL);
+
+ if (ret < 1)
+ return GRUB_ERR_BUG;
+
+ for (desc = memory_map, *base_addr = GRUB_UINT_MAX;
+ (grub_addr_t) desc < ((grub_addr_t) memory_map + memory_map_size);
+ desc = NEXT_MEMORY_DESCRIPTOR (desc, desc_size))
+ if (desc->attribute & GRUB_EFI_MEMORY_WB)
+ *base_addr = grub_min (*base_addr, desc->physical_start);
+
+ grub_free(memory_map);
+
+ return GRUB_ERR_NONE;
+}
+#endif
diff --git a/grub-core/kern/i386/coreboot/cbtable.c b/grub-core/kern/i386/coreboot/cbtable.c
index 1669bc0ca23a2fe5dcfb8e2b6c973ddb5e27e880..34a2b59be1ffa926e9dcc931140695cc82be223c 100644
--- a/grub-core/kern/i386/coreboot/cbtable.c
+++ b/grub-core/kern/i386/coreboot/cbtable.c
@@ -17,7 +17,7 @@
*/
#include
-#include
+#include
#include
#include
#include
@@ -25,59 +25,20 @@
GRUB_MOD_LICENSE ("GPLv3+");
-/* Helper for grub_linuxbios_table_iterate. */
-static int
-check_signature (grub_linuxbios_table_header_t tbl_header)
-{
- if (! grub_memcmp (tbl_header->signature, "LBIO", 4))
- return 1;
-
- return 0;
-}
-
-grub_err_t
-grub_linuxbios_table_iterate (int (*hook) (grub_linuxbios_table_item_t,
- void *),
- void *hook_data)
+grub_linuxbios_table_header_t
+grub_linuxbios_get_tables (void)
{
grub_linuxbios_table_header_t table_header;
- grub_linuxbios_table_item_t table_item;
-
/* Assuming table_header is aligned to its size (8 bytes). */
-
for (table_header = (grub_linuxbios_table_header_t) 0x500;
table_header < (grub_linuxbios_table_header_t) 0x1000; table_header++)
- if (check_signature (table_header))
- goto signature_found;
+ if (grub_linuxbios_check_signature (table_header))
+ return table_header;
for (table_header = (grub_linuxbios_table_header_t) 0xf0000;
table_header < (grub_linuxbios_table_header_t) 0x100000; table_header++)
- if (check_signature (table_header))
- goto signature_found;
-
- return 0;
-
-signature_found:
-
- table_item =
- (grub_linuxbios_table_item_t) ((char *) table_header +
- table_header->header_size);
- for (; table_item < (grub_linuxbios_table_item_t) ((char *) table_header
- + table_header->header_size
- + table_header->table_size);
- table_item = (grub_linuxbios_table_item_t) ((char *) table_item + table_item->size))
- {
- if (table_item->tag == GRUB_LINUXBIOS_MEMBER_LINK
- && check_signature ((grub_linuxbios_table_header_t) (grub_addr_t)
- *(grub_uint64_t *) (table_item + 1)))
- {
- table_header = (grub_linuxbios_table_header_t) (grub_addr_t)
- *(grub_uint64_t *) (table_item + 1);
- goto signature_found;
- }
- if (hook (table_item, hook_data))
- return 1;
- }
+ if (grub_linuxbios_check_signature (table_header))
+ return table_header;
return 0;
}
diff --git a/grub-core/kern/i386/tsc.c b/grub-core/kern/i386/tsc.c
index 2e85289d848946da8260b826ed36114557299278..f266eb13185f20dd4c8f67fdffa9a4790d9e01da 100644
--- a/grub-core/kern/i386/tsc.c
+++ b/grub-core/kern/i386/tsc.c
@@ -68,7 +68,7 @@ grub_tsc_init (void)
#ifdef GRUB_MACHINE_XEN
(void) (grub_tsc_calibrate_from_xen () || calibrate_tsc_hardcode());
#elif defined (GRUB_MACHINE_EFI)
- (void) (grub_tsc_calibrate_from_pit () || grub_tsc_calibrate_from_pmtimer () || grub_tsc_calibrate_from_efi() || calibrate_tsc_hardcode());
+ (void) (grub_tsc_calibrate_from_pmtimer () || grub_tsc_calibrate_from_pit () || grub_tsc_calibrate_from_efi() || calibrate_tsc_hardcode());
#elif defined (GRUB_MACHINE_COREBOOT)
(void) (grub_tsc_calibrate_from_pmtimer () || grub_tsc_calibrate_from_pit () || calibrate_tsc_hardcode());
#else
diff --git a/grub-core/kern/ieee1275/ieee1275.c b/grub-core/kern/ieee1275/ieee1275.c
index 98217029f458dcef3a5b227b300762ff14cf8c52..86f81a3c4671be293d823cd3235a66dff9774faa 100644
--- a/grub-core/kern/ieee1275/ieee1275.c
+++ b/grub-core/kern/ieee1275/ieee1275.c
@@ -19,6 +19,7 @@
#include
#include
+#include
#define IEEE1275_PHANDLE_INVALID ((grub_ieee1275_cell_t) -1)
#define IEEE1275_IHANDLE_INVALID ((grub_ieee1275_cell_t) 0)
@@ -482,6 +483,91 @@ grub_ieee1275_close (grub_ieee1275_ihandle_t ihandle)
return 0;
}
+int
+grub_ieee1275_decode_unit4 (grub_ieee1275_ihandle_t ihandle,
+ void *addr, grub_size_t size,
+ grub_uint32_t *phy_lo, grub_uint32_t *phy_hi,
+ grub_uint32_t *lun_lo, grub_uint32_t *lun_hi)
+{
+ struct decode_args
+ {
+ struct grub_ieee1275_common_hdr common;
+ grub_ieee1275_cell_t method;
+ grub_ieee1275_cell_t ihandle;
+ grub_ieee1275_cell_t size;
+ grub_ieee1275_cell_t addr;
+ grub_ieee1275_cell_t catch_result;
+ grub_ieee1275_cell_t tgt_h;
+ grub_ieee1275_cell_t tgt_l;
+ grub_ieee1275_cell_t lun_h;
+ grub_ieee1275_cell_t lun_l;
+ }
+ args;
+
+ INIT_IEEE1275_COMMON (&args.common, "call-method", 4, 5);
+ args.method = (grub_ieee1275_cell_t) "decode-unit";
+ args.ihandle = ihandle;
+ args.size = size;
+ args.addr = (grub_ieee1275_cell_t) addr;
+ args.catch_result = 1;
+
+ if ((IEEE1275_CALL_ENTRY_FN (&args) == -1) || (args.catch_result))
+ {
+ grub_error (GRUB_ERR_OUT_OF_RANGE, "decode-unit failed\n");
+ return -1;
+ }
+
+ *phy_lo = args.tgt_l;
+ *phy_hi = args.tgt_h;
+ *lun_lo = args.lun_l;
+ *lun_hi = args.lun_h;
+ return 0;
+}
+
+char *
+grub_ieee1275_encode_uint4 (grub_ieee1275_ihandle_t ihandle,
+ grub_uint32_t phy_lo, grub_uint32_t phy_hi,
+ grub_uint32_t lun_lo, grub_uint32_t lun_hi,
+ grub_size_t *size)
+{
+ char *addr;
+ struct encode_args
+ {
+ struct grub_ieee1275_common_hdr common;
+ grub_ieee1275_cell_t method;
+ grub_ieee1275_cell_t ihandle;
+ grub_ieee1275_cell_t tgt_h;
+ grub_ieee1275_cell_t tgt_l;
+ grub_ieee1275_cell_t lun_h;
+ grub_ieee1275_cell_t lun_l;
+ grub_ieee1275_cell_t catch_result;
+ grub_ieee1275_cell_t size;
+ grub_ieee1275_cell_t addr;
+ }
+ args;
+
+ INIT_IEEE1275_COMMON (&args.common, "call-method", 6, 3);
+ args.method = (grub_ieee1275_cell_t) "encode-unit";
+ args.ihandle = ihandle;
+
+ args.tgt_l = phy_lo;
+ args.tgt_h = phy_hi;
+ args.lun_l = lun_lo;
+ args.lun_h = lun_hi;
+ args.catch_result = 1;
+
+ if ((IEEE1275_CALL_ENTRY_FN (&args) == -1) || (args.catch_result))
+ {
+ grub_error (GRUB_ERR_OUT_OF_RANGE, "encode-unit failed\n");
+ return 0;
+ }
+
+ addr = (void *)args.addr;
+ *size = args.size;
+ addr = grub_strdup ((char *)args.addr);
+ return addr;
+}
+
int
grub_ieee1275_claim (grub_addr_t addr, grub_size_t size, unsigned int align,
grub_addr_t *result)
@@ -607,3 +693,117 @@ grub_ieee1275_milliseconds (grub_uint32_t *msecs)
*msecs = args.msecs;
return 0;
}
+
+int
+grub_ieee1275_set_address (grub_ieee1275_ihandle_t ihandle,
+ grub_uint32_t target, grub_uint32_t lun)
+{
+ struct set_address
+ {
+ struct grub_ieee1275_common_hdr common;
+ grub_ieee1275_cell_t method;
+ grub_ieee1275_cell_t ihandle;
+ grub_ieee1275_cell_t tgt;
+ grub_ieee1275_cell_t lun;
+ grub_ieee1275_cell_t catch_result;
+ }
+ args;
+
+ INIT_IEEE1275_COMMON (&args.common, "call-method", 4, 1);
+
+ /*
+ * IEEE 1275-1994 Standard for Boot (Initialization Configuration)
+ * Firmware: Core Requirements and Practices
+ * E.3.2.2 Bus-specific methods for bus nodes
+ *
+ * A package implementing the scsi-2 device type shall implement the
+ * following bus-specific method:
+ *
+ * set-address ( unit# target# -- )
+ * Sets the SCSI target number (0x0..0xf) and unit number (0..7) to which
+ * subsequent commands apply.
+ */
+ args.method = (grub_ieee1275_cell_t) "set-address";
+ args.ihandle = ihandle;
+ args.tgt = target;
+ args.lun = lun;
+
+ if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
+ return -1;
+
+ return args.catch_result;
+}
+
+int
+grub_ieee1275_no_data_command (grub_ieee1275_ihandle_t ihandle,
+ const void *cmd_addr, grub_ssize_t *result)
+{
+ struct set_address
+ {
+ struct grub_ieee1275_common_hdr common;
+ grub_ieee1275_cell_t method;
+ grub_ieee1275_cell_t ihandle;
+ grub_ieee1275_cell_t cmd_addr;
+ grub_ieee1275_cell_t error;
+ grub_ieee1275_cell_t catch_result;
+ }
+ args;
+
+ INIT_IEEE1275_COMMON (&args.common, "call-method", 3, 2);
+
+ /*
+ * IEEE 1275-1994 Standard for Boot (Initialization Configuration)
+ * Firmware: Core Requirements and Practices
+ *
+ * E.3.2.2 Bus-specific methods for bus nodes
+ *
+ * A package implementing the scsi-2 device type shall implement the
+ * following bus-specific method:
+ *
+ * no-data-command ( cmd-addr -- error? )
+ * Executes a simple SCSI command, automatically retrying under
+ * certain conditions. cmd-addr is the address of a 6-byte command buffer
+ * containing an SCSI command that does not have a data transfer phase.
+ * Executes the command, retrying indefinitely with the same retry criteria
+ * as retry-command.
+ *
+ * error? is nonzero if an error occurred, zero otherwise.
+ * NOTE no-data-command is a convenience function. It provides
+ * no capabilities that are not present in retry-command, but for
+ * those commands that meet its restrictions, it is easier to use.
+ */
+ args.method = (grub_ieee1275_cell_t) "no-data-command";
+ args.ihandle = ihandle;
+ args.cmd_addr = (grub_ieee1275_cell_t) cmd_addr;
+
+ if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
+ return -1;
+
+ if (result)
+ *result = args.error;
+
+ return args.catch_result;
+}
+
+int
+grub_ieee1275_get_block_size (grub_ieee1275_ihandle_t ihandle)
+{
+ 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 size;
+ } args;
+
+ INIT_IEEE1275_COMMON (&args.common, "call-method", 2, 2);
+ args.method = (grub_ieee1275_cell_t) "block-size";
+ args.ihandle = ihandle;
+ args.result = 1;
+
+ if ((IEEE1275_CALL_ENTRY_FN (&args) == -1) || (args.result))
+ return 0;
+
+ return args.size;
+}
diff --git a/grub-core/kern/ieee1275/init.c b/grub-core/kern/ieee1275/init.c
index 12590225eca1483066ea5e7b7443cea3198f6d9b..0d8ebf58b95e220b233e043d2b380007b48e1235 100644
--- a/grub-core/kern/ieee1275/init.c
+++ b/grub-core/kern/ieee1275/init.c
@@ -94,28 +94,12 @@ void
grub_machine_get_bootlocation (char **device, char **path)
{
char *bootpath;
- grub_ssize_t bootpath_size;
char *filename;
char *type;
- if (grub_ieee1275_get_property_length (grub_ieee1275_chosen, "bootpath",
- &bootpath_size)
- || bootpath_size <= 0)
- {
- /* Should never happen. */
- grub_printf ("/chosen/bootpath property missing!\n");
- return;
- }
-
- bootpath = (char *) grub_malloc ((grub_size_t) bootpath_size + 64);
+ bootpath = grub_ieee1275_get_boot_dev ();
if (! bootpath)
- {
- grub_print_error ();
- return;
- }
- grub_ieee1275_get_property (grub_ieee1275_chosen, "bootpath", bootpath,
- (grub_size_t) bootpath_size + 1, 0);
- bootpath[bootpath_size] = '\0';
+ return;
/* Transform an OF device path to a GRUB path. */
@@ -126,6 +110,8 @@ grub_machine_get_bootlocation (char **device, char **path)
char *ptr;
dev = grub_ieee1275_get_aliasdevname (bootpath);
canon = grub_ieee1275_canonicalise_devname (dev);
+ if (! canon)
+ return;
ptr = canon + grub_strlen (canon) - 1;
while (ptr > canon && (*ptr == ',' || *ptr == ':'))
ptr--;
diff --git a/grub-core/kern/ieee1275/openfw.c b/grub-core/kern/ieee1275/openfw.c
index ddb778340e4ab74148898b32cd27139fd4f1465b..62929d983bfaa2c83158ee4fe6797125c6d6b844 100644
--- a/grub-core/kern/ieee1275/openfw.c
+++ b/grub-core/kern/ieee1275/openfw.c
@@ -561,3 +561,30 @@ grub_ieee1275_canonicalise_devname (const char *path)
return NULL;
}
+char *
+grub_ieee1275_get_boot_dev (void)
+{
+ char *bootpath;
+ grub_ssize_t bootpath_size;
+
+ if (grub_ieee1275_get_property_length (grub_ieee1275_chosen, "bootpath",
+ &bootpath_size)
+ || bootpath_size <= 0)
+ {
+ /* Should never happen. */
+ grub_printf ("/chosen/bootpath property missing!\n");
+ return NULL;
+ }
+
+ bootpath = (char *) grub_malloc ((grub_size_t) bootpath_size + 64);
+ if (! bootpath)
+ {
+ grub_print_error ();
+ return NULL;
+ }
+ grub_ieee1275_get_property (grub_ieee1275_chosen, "bootpath", bootpath,
+ (grub_size_t) bootpath_size + 1, 0);
+ bootpath[bootpath_size] = '\0';
+
+ return bootpath;
+}
diff --git a/grub-core/kern/misc.c b/grub-core/kern/misc.c
index d1a54df6c12e3358e07aa86366c65af22ca3af5c..3b633d51f4c63e2983e8b3419dc057437224fb93 100644
--- a/grub-core/kern/misc.c
+++ b/grub-core/kern/misc.c
@@ -391,12 +391,13 @@ grub_strtoull (const char *str, char **end, int base)
unsigned long digit;
digit = grub_tolower (*str) - '0';
- if (digit > 9)
- {
- digit += '0' - 'a' + 10;
- if (digit >= (unsigned long) base)
- break;
- }
+ if (digit >= 'a' - '0')
+ digit += '0' - 'a' + 10;
+ else if (digit > 9)
+ break;
+
+ if (digit >= (unsigned long) base)
+ break;
found = 1;
diff --git a/grub-core/kern/sparc64/ieee1275/ieee1275.c b/grub-core/kern/sparc64/ieee1275/ieee1275.c
index 53be692c3d88940572d423ceb09e4187372fcb5b..5a59aaf06193442fa5ec7a537c9cfb10dd3081aa 100644
--- a/grub-core/kern/sparc64/ieee1275/ieee1275.c
+++ b/grub-core/kern/sparc64/ieee1275/ieee1275.c
@@ -89,3 +89,59 @@ grub_ieee1275_alloc_physmem (grub_addr_t *paddr, grub_size_t size,
return args.catch_result;
}
+
+grub_uint64_t
+grub_ieee1275_num_blocks (grub_ieee1275_ihandle_t ihandle)
+{
+ struct nblocks_args_ieee1275
+ {
+ struct grub_ieee1275_common_hdr common;
+ grub_ieee1275_cell_t method;
+ grub_ieee1275_cell_t ihandle;
+ grub_ieee1275_cell_t catch_result;
+ grub_ieee1275_cell_t blocks;
+ }
+ args;
+
+ INIT_IEEE1275_COMMON (&args.common, "call-method", 2, 2);
+ args.method = (grub_ieee1275_cell_t) "#blocks";
+ args.ihandle = ihandle;
+ args.catch_result = 1;
+
+ if ((IEEE1275_CALL_ENTRY_FN (&args) == -1) || (args.catch_result != 0))
+ return -1;
+
+ /*
+ * If the number of blocks exceeds the range of an unsigned number,
+ * return 0 to alert the caller to try the #blocks64 command.
+ */
+ if (args.blocks >= 0xffffffffULL)
+ return 0;
+
+ return args.blocks;
+}
+
+grub_uint64_t
+grub_ieee1275_num_blocks64 (grub_ieee1275_ihandle_t ihandle)
+{
+ struct nblocks_args_ieee1275
+ {
+ struct grub_ieee1275_common_hdr common;
+ grub_ieee1275_cell_t method;
+ grub_ieee1275_cell_t ihandle;
+ grub_ieee1275_cell_t catch_result;
+ grub_ieee1275_cell_t hi_blocks;
+ grub_ieee1275_cell_t lo_blocks;
+ }
+ args;
+
+ INIT_IEEE1275_COMMON (&args.common, "call-method", 2, 3);
+ args.method = (grub_ieee1275_cell_t) "#blocks64";
+ args.ihandle = ihandle;
+ args.catch_result = 1;
+
+ if ((IEEE1275_CALL_ENTRY_FN (&args) == -1) || (args.catch_result != 0))
+ return -1;
+
+ return ((args.hi_blocks << 32) | (args.lo_blocks));
+}
diff --git a/grub-core/kern/uboot/init.c b/grub-core/kern/uboot/init.c
index 5dcc106ed9bcc1fa2cdbe2ba6cbb9e709420ceb3..3e338645c573aa707343235029d9fc45d515a9dc 100644
--- a/grub-core/kern/uboot/init.c
+++ b/grub-core/kern/uboot/init.c
@@ -36,30 +36,14 @@
extern char __bss_start[];
extern char _end[];
extern grub_size_t grub_total_module_size;
-extern int (*grub_uboot_syscall_ptr) (int, int *, ...);
static unsigned long timer_start;
-extern grub_uint32_t grub_uboot_machine_type;
-extern grub_addr_t grub_uboot_boot_data;
-
void
grub_exit (void)
{
grub_uboot_return (0);
}
-grub_uint32_t
-grub_uboot_get_machine_type (void)
-{
- return grub_uboot_machine_type;
-}
-
-grub_addr_t
-grub_uboot_get_boot_data (void)
-{
- return grub_uboot_boot_data;
-}
-
static grub_uint64_t
uboot_timer_ms (void)
{
diff --git a/grub-core/kern/uboot/uboot.c b/grub-core/kern/uboot/uboot.c
index 6800a4beb1c4e83ef9f4ac5da872d2557d8471e1..cf0168e62ddd26db50efd2351499fa7f74fce26c 100644
--- a/grub-core/kern/uboot/uboot.c
+++ b/grub-core/kern/uboot/uboot.c
@@ -39,48 +39,13 @@
* returns: 0 if the call not found, 1 if serviced
*/
-extern int (*grub_uboot_syscall_ptr) (int, int *, ...);
extern int grub_uboot_syscall (int, int *, ...);
-extern grub_addr_t grub_uboot_search_hint;
static struct sys_info uboot_sys_info;
static struct mem_region uboot_mem_info[5];
static struct device_info * devices;
static int num_devices;
-int
-grub_uboot_api_init (void)
-{
- struct api_signature *start, *end;
- struct api_signature *p;
-
- if (grub_uboot_search_hint)
- {
- /* Extended search range to work around Trim Slice U-Boot issue */
- start = (struct api_signature *) ((grub_uboot_search_hint & ~0x000fffff)
- - 0x00500000);
- end =
- (struct api_signature *) ((grub_addr_t) start + UBOOT_API_SEARCH_LEN -
- API_SIG_MAGLEN + 0x00500000);
- }
- else
- {
- start = 0;
- end = (struct api_signature *) (256 * 1024 * 1024);
- }
-
- /* Structure alignment is (at least) 8 bytes */
- for (p = start; p < end; p = (void *) ((grub_addr_t) p + 8))
- {
- if (grub_memcmp (&(p->magic), API_SIG_MAGIC, API_SIG_MAGLEN) == 0)
- {
- grub_uboot_syscall_ptr = p->syscall;
- return p->version;
- }
- }
-
- return 0;
-}
/*
* All functions below are wrappers around the grub_uboot_syscall() function
diff --git a/grub-core/kern/x86_64/dl.c b/grub-core/kern/x86_64/dl.c
index 44069067312a890b4e3ebb5130861ed23572bc54..3a73e6e6ce2c5aefc33313e583cb259ea9bc2645 100644
--- a/grub-core/kern/x86_64/dl.c
+++ b/grub-core/kern/x86_64/dl.c
@@ -70,6 +70,7 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr,
break;
case R_X86_64_PC32:
+ case R_X86_64_PLT32:
{
grub_int64_t value;
value = ((grub_int32_t) *addr32) + rel->r_addend + sym->st_value -
diff --git a/grub-core/lib/crypto.c b/grub-core/lib/crypto.c
index 683a8aaa711c4eab0208d116cd7275a6ac678986..ca334d5a40e0716bdc9afbb79135c47d174532da 100644
--- a/grub-core/lib/crypto.c
+++ b/grub-core/lib/crypto.c
@@ -462,7 +462,7 @@ grub_password_get (char buf[], unsigned buf_size)
if (key == '\n' || key == '\r')
break;
- if (key == '\e')
+ if (key == GRUB_TERM_ESC)
{
cur_len = 0;
break;
@@ -487,7 +487,7 @@ grub_password_get (char buf[], unsigned buf_size)
grub_xputs ("\n");
grub_refresh ();
- return (key != '\e');
+ return (key != GRUB_TERM_ESC);
}
#endif
diff --git a/grub-core/lib/uboot/datetime.c b/grub-core/lib/dummy/datetime.c
similarity index 91%
rename from grub-core/lib/uboot/datetime.c
rename to grub-core/lib/dummy/datetime.c
index 4be716928a55b789510dfdcdd1833e29e5cd11fe..cf693fc6b621376b5cae0ca0a74b4421799b5a9e 100644
--- a/grub-core/lib/uboot/datetime.c
+++ b/grub-core/lib/dummy/datetime.c
@@ -18,7 +18,6 @@
#include
#include
-#include
#include
#include
@@ -30,12 +29,12 @@ grub_err_t
grub_get_datetime (struct grub_datetime *datetime __attribute__ ((unused)))
{
return grub_error (GRUB_ERR_INVALID_COMMAND,
- "can\'t get datetime using U-Boot");
+ "can\'t get datetime on this machine");
}
grub_err_t
grub_set_datetime (struct grub_datetime * datetime __attribute__ ((unused)))
{
return grub_error (GRUB_ERR_INVALID_COMMAND,
- "can\'t set datetime using U-Boot");
+ "can\'t set datetime on this machine");
}
diff --git a/grub-core/lib/uboot/halt.c b/grub-core/lib/dummy/halt.c
similarity index 100%
rename from grub-core/lib/uboot/halt.c
rename to grub-core/lib/dummy/halt.c
diff --git a/grub-core/lib/efi/reboot.c b/grub-core/lib/dummy/reboot.c
similarity index 77%
rename from grub-core/lib/efi/reboot.c
rename to grub-core/lib/dummy/reboot.c
index 7de8bcb5d6ea128dd406001d970d18ff00ea0f3c..b8cbed8f8117ca9c53cc2087dee87ae68876d64f 100644
--- a/grub-core/lib/efi/reboot.c
+++ b/grub-core/lib/dummy/reboot.c
@@ -1,6 +1,6 @@
/*
* GRUB -- GRand Unified Bootloader
- * Copyright (C) 2011 Free Software Foundation, Inc.
+ * 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
@@ -16,10 +16,8 @@
* along with GRUB. If not, see .
*/
-#include
-#include
-#include
#include
+#include
#include
#include
@@ -27,7 +25,8 @@ void
grub_reboot (void)
{
grub_machine_fini (GRUB_LOADER_FLAG_NORETURN);
- efi_call_4 (grub_efi_system_table->runtime_services->reset_system,
- GRUB_EFI_RESET_COLD, GRUB_EFI_SUCCESS, 0, NULL);
- for (;;) ;
+
+ /* Just stop here */
+
+ while (1);
}
diff --git a/grub-core/lib/fdt.c b/grub-core/lib/fdt.c
index b5d520f208886aa663d4aac36cec9b43a2d0da42..0d371c5633e84bbf47114bfe2c23427982e25192 100644
--- a/grub-core/lib/fdt.c
+++ b/grub-core/lib/fdt.c
@@ -41,11 +41,6 @@ GRUB_MOD_LICENSE ("GPLv3+");
(2 * sizeof(grub_uint32_t) \
+ ALIGN_UP (grub_strlen (name) + 1, sizeof(grub_uint32_t)))
-/* Size needed by a property entry: 1 token (FDT_PROPERTY), plus len and nameoff
- fields, plus the property value, plus padding if needed. */
-#define prop_entry_size(prop_len) \
- (3 * sizeof(grub_uint32_t) + ALIGN_UP(prop_len, sizeof(grub_uint32_t)))
-
#define SKIP_NODE_NAME(name, token, end) \
name = (char *) ((token) + 1); \
while (name < (char *) end) \
@@ -86,7 +81,7 @@ static grub_uint32_t *get_next_node (const void *fdt, char *node_name)
case FDT_PROP:
/* Skip property token and following data (len, nameoff and property
value). */
- token += prop_entry_size(grub_be_to_cpu32(*(token + 1)))
+ token += grub_fdt_prop_entry_size(grub_be_to_cpu32(*(token + 1)))
/ sizeof(*token);
break;
case FDT_NOP:
@@ -102,13 +97,13 @@ static grub_uint32_t *get_next_node (const void *fdt, char *node_name)
static int get_mem_rsvmap_size (const void *fdt)
{
int size = 0;
- grub_uint64_t *ptr = (void *) ((grub_addr_t) fdt
- + grub_fdt_get_off_mem_rsvmap (fdt));
+ grub_unaligned_uint64_t *ptr = (void *) ((grub_addr_t) fdt
+ + grub_fdt_get_off_mem_rsvmap (fdt));
do
{
size += 2 * sizeof(*ptr);
- if (!*ptr && !*(ptr + 1))
+ if (!ptr[0].val && !ptr[1].val)
return size;
ptr += 2;
} while ((grub_addr_t) ptr <= (grub_addr_t) fdt + grub_fdt_get_totalsize (fdt)
@@ -150,7 +145,7 @@ static int add_subnode (void *fdt, int parentoffset, const char *name)
{
case FDT_PROP:
/* Skip len, nameoff and property value. */
- token += prop_entry_size(grub_be_to_cpu32(*(token + 1)))
+ token += grub_fdt_prop_entry_size(grub_be_to_cpu32(*(token + 1)))
/ sizeof(*token);
break;
case FDT_BEGIN_NODE:
@@ -229,7 +224,7 @@ static int rearrange_blocks (void *fdt, unsigned int clearance)
return 0;
}
-static grub_uint32_t *find_prop (void *fdt, unsigned int nodeoffset,
+static grub_uint32_t *find_prop (const void *fdt, unsigned int nodeoffset,
const char *name)
{
grub_uint32_t *prop = (void *) ((grub_addr_t) fdt
@@ -249,12 +244,12 @@ static grub_uint32_t *find_prop (void *fdt, unsigned int nodeoffset,
&& !grub_strcmp (name, (char *) fdt +
grub_fdt_get_off_dt_strings (fdt) + nameoff))
{
- if (prop + prop_entry_size(grub_be_to_cpu32(*(prop + 1)))
+ if (prop + grub_fdt_prop_entry_size(grub_be_to_cpu32(*(prop + 1)))
/ sizeof (*prop) >= end)
return NULL;
return prop;
}
- prop += prop_entry_size(grub_be_to_cpu32(*(prop + 1))) / sizeof (*prop);
+ prop += grub_fdt_prop_entry_size(grub_be_to_cpu32(*(prop + 1))) / sizeof (*prop);
}
else if (grub_be_to_cpu32(*prop) == FDT_NOP)
prop++;
@@ -268,9 +263,9 @@ static grub_uint32_t *find_prop (void *fdt, unsigned int nodeoffset,
the size allocated for the FDT; if this function is called before the other
functions in this file and returns success, the other functions are
guaranteed not to access memory locations outside the allocated memory. */
-int grub_fdt_check_header_nosize (void *fdt)
+int grub_fdt_check_header_nosize (const void *fdt)
{
- if (((grub_addr_t) fdt & 0x7) || (grub_fdt_get_magic (fdt) != FDT_MAGIC)
+ if (((grub_addr_t) fdt & 0x3) || (grub_fdt_get_magic (fdt) != FDT_MAGIC)
|| (grub_fdt_get_version (fdt) < FDT_SUPPORTED_VERSION)
|| (grub_fdt_get_last_comp_version (fdt) > FDT_SUPPORTED_VERSION)
|| (grub_fdt_get_off_dt_struct (fdt) & 0x00000003)
@@ -286,7 +281,7 @@ int grub_fdt_check_header_nosize (void *fdt)
return 0;
}
-int grub_fdt_check_header (void *fdt, unsigned int size)
+int grub_fdt_check_header (const void *fdt, unsigned int size)
{
if (size < sizeof (grub_fdt_header_t)
|| (grub_fdt_get_totalsize (fdt) > size)
@@ -295,52 +290,105 @@ int grub_fdt_check_header (void *fdt, unsigned int size)
return 0;
}
+static const grub_uint32_t *
+advance_token (const void *fdt, const grub_uint32_t *token, const grub_uint32_t *end, int skip_current)
+{
+ for (; token < end; skip_current = 0)
+ {
+ switch (grub_be_to_cpu32 (*token))
+ {
+ case FDT_BEGIN_NODE:
+ if (skip_current)
+ {
+ token = get_next_node (fdt, (char *) (token + 1));
+ continue;
+ }
+ char *ptr;
+ for (ptr = (char *) (token + 1); *ptr && ptr < (char *) end; ptr++)
+ ;
+ if (ptr >= (char *) end)
+ return 0;
+ return token;
+ case FDT_PROP:
+ /* Skip property token and following data (len, nameoff and property
+ value). */
+ if (token >= end - 1)
+ return 0;
+ token += grub_fdt_prop_entry_size(grub_be_to_cpu32(*(token + 1)))
+ / sizeof(*token);
+ break;
+ case FDT_NOP:
+ token++;
+ break;
+ default:
+ return 0;
+ }
+ }
+ return 0;
+}
+
+int grub_fdt_next_node (const void *fdt, unsigned int currentoffset)
+{
+ const grub_uint32_t *token = (const grub_uint32_t *) fdt + (currentoffset + grub_fdt_get_off_dt_struct (fdt)) / 4;
+ token = advance_token (fdt, token, (const void *) struct_end (fdt), 1);
+ if (!token)
+ return -1;
+ return (int) ((grub_addr_t) token - (grub_addr_t) fdt
+ - grub_fdt_get_off_dt_struct (fdt));
+}
+
+int grub_fdt_first_node (const void *fdt, unsigned int parentoffset)
+{
+ const grub_uint32_t *token, *end;
+ char *node_name;
+
+ if (parentoffset & 0x3)
+ return -1;
+ token = (const void *) ((grub_addr_t) fdt + grub_fdt_get_off_dt_struct(fdt)
+ + parentoffset);
+ end = (const void *) struct_end (fdt);
+ if ((token >= end) || (grub_be_to_cpu32(*token) != FDT_BEGIN_NODE))
+ return -1;
+ SKIP_NODE_NAME(node_name, token, end);
+ token = advance_token (fdt, token, end, 0);
+ if (!token)
+ return -1;
+ return (int) ((grub_addr_t) token - (grub_addr_t) fdt
+ - grub_fdt_get_off_dt_struct (fdt));
+}
+
/* Find a direct sub-node of a given parent node. */
int grub_fdt_find_subnode (const void *fdt, unsigned int parentoffset,
const char *name)
{
- grub_uint32_t *token, *end;
- char *node_name;
+ const grub_uint32_t *token, *end;
+ const char *node_name;
+ int skip_current = 0;
if (parentoffset & 0x3)
return -1;
- token = (void *) ((grub_addr_t) fdt + grub_fdt_get_off_dt_struct(fdt)
+ token = (const void *) ((grub_addr_t) fdt + grub_fdt_get_off_dt_struct(fdt)
+ parentoffset);
- end = (void *) struct_end (fdt);
+ end = (const void *) struct_end (fdt);
if ((token >= end) || (grub_be_to_cpu32(*token) != FDT_BEGIN_NODE))
return -1;
SKIP_NODE_NAME(node_name, token, end);
- while (token < end)
- {
- switch (grub_be_to_cpu32(*token))
- {
- case FDT_BEGIN_NODE:
- node_name = (char *) (token + 1);
- if (node_name + grub_strlen (name) >= (char *) end)
- return -1;
- if (!grub_strcmp (node_name, name))
- return (int) ((grub_addr_t) token - (grub_addr_t) fdt
- - grub_fdt_get_off_dt_struct (fdt));
- token = get_next_node (fdt, node_name);
- if (!token)
- return -1;
- break;
- case FDT_PROP:
- /* Skip property token and following data (len, nameoff and property
- value). */
- if (token >= end - 1)
- return -1;
- token += prop_entry_size(grub_be_to_cpu32(*(token + 1)))
- / sizeof(*token);
- break;
- case FDT_NOP:
- token++;
- break;
- default:
- return -1;
- }
+ while (1) {
+ token = advance_token (fdt, token, end, skip_current);
+ if (!token)
+ return -1;
+ skip_current = 1;
+ node_name = (const char *) token + 4;
+ if (grub_strcmp (node_name, name) == 0)
+ return (int) ((grub_addr_t) token - (grub_addr_t) fdt
+ - grub_fdt_get_off_dt_struct (fdt));
}
- return -1;
+}
+
+const char *
+grub_fdt_get_nodename (const void *fdt, unsigned int nodeoffset)
+{
+ return (const char *) fdt + grub_fdt_get_off_dt_struct(fdt) + nodeoffset + 4;
}
int grub_fdt_add_subnode (void *fdt, unsigned int parentoffset,
@@ -359,6 +407,24 @@ int grub_fdt_add_subnode (void *fdt, unsigned int parentoffset,
return add_subnode (fdt, parentoffset, name);
}
+const void *
+grub_fdt_get_prop (const void *fdt, unsigned int nodeoffset, const char *name,
+ grub_uint32_t *len)
+{
+ grub_uint32_t *prop;
+ if ((nodeoffset >= grub_fdt_get_size_dt_struct (fdt)) || (nodeoffset & 0x3)
+ || (grub_be_to_cpu32(*(grub_uint32_t *) ((grub_addr_t) fdt
+ + grub_fdt_get_off_dt_struct (fdt) + nodeoffset))
+ != FDT_BEGIN_NODE))
+ return 0;
+ prop = find_prop (fdt, nodeoffset, name);
+ if (!prop)
+ return 0;
+ if (len)
+ *len = grub_be_to_cpu32 (*(prop + 1));
+ return prop + 3;
+}
+
int grub_fdt_set_prop (void *fdt, unsigned int nodeoffset, const char *name,
const void *val, grub_uint32_t len)
{
@@ -396,12 +462,12 @@ int grub_fdt_set_prop (void *fdt, unsigned int nodeoffset, const char *name,
unsigned int needed_space = 0;
if (!prop)
- needed_space = prop_entry_size(len);
+ needed_space = grub_fdt_prop_entry_size(len);
if (!prop_name_present)
needed_space += grub_strlen (name) + 1;
if (needed_space > get_free_space (fdt))
return -1;
- if (rearrange_blocks (fdt, !prop ? prop_entry_size(len) : 0) < 0)
+ if (rearrange_blocks (fdt, !prop ? grub_fdt_prop_entry_size(len) : 0) < 0)
return -1;
}
if (!prop_name_present) {
@@ -418,10 +484,10 @@ int grub_fdt_set_prop (void *fdt, unsigned int nodeoffset, const char *name,
+ sizeof(grub_uint32_t));
prop = (void *) (node_name + ALIGN_UP(grub_strlen(node_name) + 1, 4));
- grub_memmove (prop + prop_entry_size(len) / sizeof(*prop), prop,
+ grub_memmove (prop + grub_fdt_prop_entry_size(len) / sizeof(*prop), prop,
struct_end(fdt) - (grub_addr_t) prop);
grub_fdt_set_size_dt_struct (fdt, grub_fdt_get_size_dt_struct (fdt)
- + prop_entry_size(len));
+ + grub_fdt_prop_entry_size(len));
*prop = grub_cpu_to_be32_compile_time (FDT_PROP);
*(prop + 2) = grub_cpu_to_be32 (nameoff);
}
@@ -429,7 +495,7 @@ int grub_fdt_set_prop (void *fdt, unsigned int nodeoffset, const char *name,
/* Insert padding bytes at the end of the value; if they are not needed, they
will be overwritten by the following memcpy. */
- *(prop + prop_entry_size(len) / sizeof(grub_uint32_t) - 1) = 0;
+ *(prop + grub_fdt_prop_entry_size(len) / sizeof(grub_uint32_t) - 1) = 0;
grub_memcpy (prop + 3, val, len);
return 0;
diff --git a/grub-core/lib/i386/reboot.c b/grub-core/lib/i386/reboot.c
index a234244dce5b4c5afd5c68e579c4519a870cda36..dce0b563dcd39ce7acc6d5ec0cc759e67c8c8b87 100644
--- a/grub-core/lib/i386/reboot.c
+++ b/grub-core/lib/i386/reboot.c
@@ -16,6 +16,8 @@
* along with GRUB. If not, see .
*/
+#ifndef GRUB_MACHINE_EFI
+
#include
#include
#include
@@ -58,3 +60,5 @@ grub_reboot (void)
while (1);
}
+
+#endif /* GRUB_MACHINE_EFI */
diff --git a/grub-core/lib/libgcrypt/cipher/crc.c b/grub-core/lib/libgcrypt/cipher/crc.c
index 9e406f1b19b4d1d49c1ba5140c47d630972c0d8e..28454f8ab728c657d0b440371765030deb35a407 100644
--- a/grub-core/lib/libgcrypt/cipher/crc.c
+++ b/grub-core/lib/libgcrypt/cipher/crc.c
@@ -28,116 +28,8 @@
#include "cipher.h"
#include "bithelp.h"
+#include "bufhelp.h"
-/* Table of CRCs of all 8-bit messages. Generated by running code
- from RFC 1952 modified to print out the table. */
-static u32 crc32_table[256] = {
- 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
- 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
- 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
- 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
- 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
- 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
- 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
- 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
- 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
- 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
- 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
- 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
- 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
- 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
- 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
- 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
- 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
- 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
- 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
- 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
- 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
- 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
- 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
- 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
- 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
- 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
- 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
- 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
- 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
- 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
- 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
- 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
- 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
- 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
- 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
- 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
- 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
- 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
- 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
- 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
- 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
- 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
- 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
-};
-
-/*
- * The following function was extracted from RFC 1952 by Simon
- * Josefsson, for the Shishi project, and modified to be compatible
- * with the modified CRC-32 used by RFC 1510, and subsequently
- * modified for GNU Libgcrypt to allow it to be used for calculating
- * both unmodified CRC-32 and modified CRC-32 values. Original
- * copyright and notice from the document follows:
- *
- * Copyright (c) 1996 L. Peter Deutsch
- *
- * Permission is granted to copy and distribute this document for
- * any purpose and without charge, including translations into
- * other languages and incorporation into compilations, provided
- * that the copyright notice and this notice are preserved, and
- * that any substantive changes or deletions from the original are
- * clearly marked.
- *
- * The copyright on RFCs, and consequently the function below, are
- * supposedly also retroactively claimed by the Internet Society
- * (according to rfc-editor@rfc-editor.org), with the following
- * copyright notice:
- *
- * Copyright (C) The Internet Society. All Rights Reserved.
- *
- * This document and translations of it may be copied and furnished
- * to others, and derivative works that comment on or otherwise
- * explain it or assist in its implementation may be prepared,
- * copied, published and distributed, in whole or in part, without
- * restriction of any kind, provided that the above copyright
- * notice and this paragraph are included on all such copies and
- * derivative works. However, this document itself may not be
- * modified in any way, such as by removing the copyright notice or
- * references to the Internet Society or other Internet
- * organizations, except as needed for the purpose of developing
- * Internet standards in which case the procedures for copyrights
- * defined in the Internet Standards process must be followed, or
- * as required to translate it into languages other than English.
- *
- * The limited permissions granted above are perpetual and will not be
- * revoked by the Internet Society or its successors or assigns.
- *
- * This document and the information contained herein is provided
- * on an "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET
- * ENGINEERING TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE
- * OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY
- * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A
- * PARTICULAR PURPOSE.
- *
- */
-static u32
-update_crc32 (u32 crc, const void *buf_arg, size_t len)
-{
- const char *buf = buf_arg;
- size_t n;
-
- for (n = 0; n < len; n++)
- crc = crc32_table[(crc ^ buf[n]) & 0xff] ^ (crc >> 8);
-
- return crc;
-}
typedef struct
{
@@ -146,8 +38,302 @@ typedef struct
}
CRC_CONTEXT;
+
+/*
+ * Code generated by universal_crc by Danjel McGougan
+ *
+ * CRC parameters used:
+ * bits: 32
+ * poly: 0x04c11db7
+ * init: 0xffffffff
+ * xor: 0xffffffff
+ * reverse: true
+ * non-direct: false
+ *
+ * CRC of the string "123456789" is 0xcbf43926
+ */
+
+static const u32 crc32_table[1024] = {
+ 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
+ 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
+ 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
+ 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
+ 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
+ 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
+ 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
+ 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
+ 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
+ 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
+ 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
+ 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
+ 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
+ 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
+ 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+ 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
+ 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
+ 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
+ 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
+ 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
+ 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
+ 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
+ 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
+ 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
+ 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
+ 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
+ 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
+ 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
+ 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
+ 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+ 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
+ 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
+ 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
+ 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
+ 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
+ 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
+ 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
+ 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
+ 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
+ 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
+ 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
+ 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
+ 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
+ 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
+ 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+ 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
+ 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
+ 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
+ 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
+ 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
+ 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
+ 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
+ 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
+ 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
+ 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
+ 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
+ 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
+ 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
+ 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
+ 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+ 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
+ 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
+ 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
+ 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
+ 0x00000000, 0x191b3141, 0x32366282, 0x2b2d53c3,
+ 0x646cc504, 0x7d77f445, 0x565aa786, 0x4f4196c7,
+ 0xc8d98a08, 0xd1c2bb49, 0xfaefe88a, 0xe3f4d9cb,
+ 0xacb54f0c, 0xb5ae7e4d, 0x9e832d8e, 0x87981ccf,
+ 0x4ac21251, 0x53d92310, 0x78f470d3, 0x61ef4192,
+ 0x2eaed755, 0x37b5e614, 0x1c98b5d7, 0x05838496,
+ 0x821b9859, 0x9b00a918, 0xb02dfadb, 0xa936cb9a,
+ 0xe6775d5d, 0xff6c6c1c, 0xd4413fdf, 0xcd5a0e9e,
+ 0x958424a2, 0x8c9f15e3, 0xa7b24620, 0xbea97761,
+ 0xf1e8e1a6, 0xe8f3d0e7, 0xc3de8324, 0xdac5b265,
+ 0x5d5daeaa, 0x44469feb, 0x6f6bcc28, 0x7670fd69,
+ 0x39316bae, 0x202a5aef, 0x0b07092c, 0x121c386d,
+ 0xdf4636f3, 0xc65d07b2, 0xed705471, 0xf46b6530,
+ 0xbb2af3f7, 0xa231c2b6, 0x891c9175, 0x9007a034,
+ 0x179fbcfb, 0x0e848dba, 0x25a9de79, 0x3cb2ef38,
+ 0x73f379ff, 0x6ae848be, 0x41c51b7d, 0x58de2a3c,
+ 0xf0794f05, 0xe9627e44, 0xc24f2d87, 0xdb541cc6,
+ 0x94158a01, 0x8d0ebb40, 0xa623e883, 0xbf38d9c2,
+ 0x38a0c50d, 0x21bbf44c, 0x0a96a78f, 0x138d96ce,
+ 0x5ccc0009, 0x45d73148, 0x6efa628b, 0x77e153ca,
+ 0xbabb5d54, 0xa3a06c15, 0x888d3fd6, 0x91960e97,
+ 0xded79850, 0xc7cca911, 0xece1fad2, 0xf5facb93,
+ 0x7262d75c, 0x6b79e61d, 0x4054b5de, 0x594f849f,
+ 0x160e1258, 0x0f152319, 0x243870da, 0x3d23419b,
+ 0x65fd6ba7, 0x7ce65ae6, 0x57cb0925, 0x4ed03864,
+ 0x0191aea3, 0x188a9fe2, 0x33a7cc21, 0x2abcfd60,
+ 0xad24e1af, 0xb43fd0ee, 0x9f12832d, 0x8609b26c,
+ 0xc94824ab, 0xd05315ea, 0xfb7e4629, 0xe2657768,
+ 0x2f3f79f6, 0x362448b7, 0x1d091b74, 0x04122a35,
+ 0x4b53bcf2, 0x52488db3, 0x7965de70, 0x607eef31,
+ 0xe7e6f3fe, 0xfefdc2bf, 0xd5d0917c, 0xcccba03d,
+ 0x838a36fa, 0x9a9107bb, 0xb1bc5478, 0xa8a76539,
+ 0x3b83984b, 0x2298a90a, 0x09b5fac9, 0x10aecb88,
+ 0x5fef5d4f, 0x46f46c0e, 0x6dd93fcd, 0x74c20e8c,
+ 0xf35a1243, 0xea412302, 0xc16c70c1, 0xd8774180,
+ 0x9736d747, 0x8e2de606, 0xa500b5c5, 0xbc1b8484,
+ 0x71418a1a, 0x685abb5b, 0x4377e898, 0x5a6cd9d9,
+ 0x152d4f1e, 0x0c367e5f, 0x271b2d9c, 0x3e001cdd,
+ 0xb9980012, 0xa0833153, 0x8bae6290, 0x92b553d1,
+ 0xddf4c516, 0xc4eff457, 0xefc2a794, 0xf6d996d5,
+ 0xae07bce9, 0xb71c8da8, 0x9c31de6b, 0x852aef2a,
+ 0xca6b79ed, 0xd37048ac, 0xf85d1b6f, 0xe1462a2e,
+ 0x66de36e1, 0x7fc507a0, 0x54e85463, 0x4df36522,
+ 0x02b2f3e5, 0x1ba9c2a4, 0x30849167, 0x299fa026,
+ 0xe4c5aeb8, 0xfdde9ff9, 0xd6f3cc3a, 0xcfe8fd7b,
+ 0x80a96bbc, 0x99b25afd, 0xb29f093e, 0xab84387f,
+ 0x2c1c24b0, 0x350715f1, 0x1e2a4632, 0x07317773,
+ 0x4870e1b4, 0x516bd0f5, 0x7a468336, 0x635db277,
+ 0xcbfad74e, 0xd2e1e60f, 0xf9ccb5cc, 0xe0d7848d,
+ 0xaf96124a, 0xb68d230b, 0x9da070c8, 0x84bb4189,
+ 0x03235d46, 0x1a386c07, 0x31153fc4, 0x280e0e85,
+ 0x674f9842, 0x7e54a903, 0x5579fac0, 0x4c62cb81,
+ 0x8138c51f, 0x9823f45e, 0xb30ea79d, 0xaa1596dc,
+ 0xe554001b, 0xfc4f315a, 0xd7626299, 0xce7953d8,
+ 0x49e14f17, 0x50fa7e56, 0x7bd72d95, 0x62cc1cd4,
+ 0x2d8d8a13, 0x3496bb52, 0x1fbbe891, 0x06a0d9d0,
+ 0x5e7ef3ec, 0x4765c2ad, 0x6c48916e, 0x7553a02f,
+ 0x3a1236e8, 0x230907a9, 0x0824546a, 0x113f652b,
+ 0x96a779e4, 0x8fbc48a5, 0xa4911b66, 0xbd8a2a27,
+ 0xf2cbbce0, 0xebd08da1, 0xc0fdde62, 0xd9e6ef23,
+ 0x14bce1bd, 0x0da7d0fc, 0x268a833f, 0x3f91b27e,
+ 0x70d024b9, 0x69cb15f8, 0x42e6463b, 0x5bfd777a,
+ 0xdc656bb5, 0xc57e5af4, 0xee530937, 0xf7483876,
+ 0xb809aeb1, 0xa1129ff0, 0x8a3fcc33, 0x9324fd72,
+ 0x00000000, 0x01c26a37, 0x0384d46e, 0x0246be59,
+ 0x0709a8dc, 0x06cbc2eb, 0x048d7cb2, 0x054f1685,
+ 0x0e1351b8, 0x0fd13b8f, 0x0d9785d6, 0x0c55efe1,
+ 0x091af964, 0x08d89353, 0x0a9e2d0a, 0x0b5c473d,
+ 0x1c26a370, 0x1de4c947, 0x1fa2771e, 0x1e601d29,
+ 0x1b2f0bac, 0x1aed619b, 0x18abdfc2, 0x1969b5f5,
+ 0x1235f2c8, 0x13f798ff, 0x11b126a6, 0x10734c91,
+ 0x153c5a14, 0x14fe3023, 0x16b88e7a, 0x177ae44d,
+ 0x384d46e0, 0x398f2cd7, 0x3bc9928e, 0x3a0bf8b9,
+ 0x3f44ee3c, 0x3e86840b, 0x3cc03a52, 0x3d025065,
+ 0x365e1758, 0x379c7d6f, 0x35dac336, 0x3418a901,
+ 0x3157bf84, 0x3095d5b3, 0x32d36bea, 0x331101dd,
+ 0x246be590, 0x25a98fa7, 0x27ef31fe, 0x262d5bc9,
+ 0x23624d4c, 0x22a0277b, 0x20e69922, 0x2124f315,
+ 0x2a78b428, 0x2bbade1f, 0x29fc6046, 0x283e0a71,
+ 0x2d711cf4, 0x2cb376c3, 0x2ef5c89a, 0x2f37a2ad,
+ 0x709a8dc0, 0x7158e7f7, 0x731e59ae, 0x72dc3399,
+ 0x7793251c, 0x76514f2b, 0x7417f172, 0x75d59b45,
+ 0x7e89dc78, 0x7f4bb64f, 0x7d0d0816, 0x7ccf6221,
+ 0x798074a4, 0x78421e93, 0x7a04a0ca, 0x7bc6cafd,
+ 0x6cbc2eb0, 0x6d7e4487, 0x6f38fade, 0x6efa90e9,
+ 0x6bb5866c, 0x6a77ec5b, 0x68315202, 0x69f33835,
+ 0x62af7f08, 0x636d153f, 0x612bab66, 0x60e9c151,
+ 0x65a6d7d4, 0x6464bde3, 0x662203ba, 0x67e0698d,
+ 0x48d7cb20, 0x4915a117, 0x4b531f4e, 0x4a917579,
+ 0x4fde63fc, 0x4e1c09cb, 0x4c5ab792, 0x4d98dda5,
+ 0x46c49a98, 0x4706f0af, 0x45404ef6, 0x448224c1,
+ 0x41cd3244, 0x400f5873, 0x4249e62a, 0x438b8c1d,
+ 0x54f16850, 0x55330267, 0x5775bc3e, 0x56b7d609,
+ 0x53f8c08c, 0x523aaabb, 0x507c14e2, 0x51be7ed5,
+ 0x5ae239e8, 0x5b2053df, 0x5966ed86, 0x58a487b1,
+ 0x5deb9134, 0x5c29fb03, 0x5e6f455a, 0x5fad2f6d,
+ 0xe1351b80, 0xe0f771b7, 0xe2b1cfee, 0xe373a5d9,
+ 0xe63cb35c, 0xe7fed96b, 0xe5b86732, 0xe47a0d05,
+ 0xef264a38, 0xeee4200f, 0xeca29e56, 0xed60f461,
+ 0xe82fe2e4, 0xe9ed88d3, 0xebab368a, 0xea695cbd,
+ 0xfd13b8f0, 0xfcd1d2c7, 0xfe976c9e, 0xff5506a9,
+ 0xfa1a102c, 0xfbd87a1b, 0xf99ec442, 0xf85cae75,
+ 0xf300e948, 0xf2c2837f, 0xf0843d26, 0xf1465711,
+ 0xf4094194, 0xf5cb2ba3, 0xf78d95fa, 0xf64fffcd,
+ 0xd9785d60, 0xd8ba3757, 0xdafc890e, 0xdb3ee339,
+ 0xde71f5bc, 0xdfb39f8b, 0xddf521d2, 0xdc374be5,
+ 0xd76b0cd8, 0xd6a966ef, 0xd4efd8b6, 0xd52db281,
+ 0xd062a404, 0xd1a0ce33, 0xd3e6706a, 0xd2241a5d,
+ 0xc55efe10, 0xc49c9427, 0xc6da2a7e, 0xc7184049,
+ 0xc25756cc, 0xc3953cfb, 0xc1d382a2, 0xc011e895,
+ 0xcb4dafa8, 0xca8fc59f, 0xc8c97bc6, 0xc90b11f1,
+ 0xcc440774, 0xcd866d43, 0xcfc0d31a, 0xce02b92d,
+ 0x91af9640, 0x906dfc77, 0x922b422e, 0x93e92819,
+ 0x96a63e9c, 0x976454ab, 0x9522eaf2, 0x94e080c5,
+ 0x9fbcc7f8, 0x9e7eadcf, 0x9c381396, 0x9dfa79a1,
+ 0x98b56f24, 0x99770513, 0x9b31bb4a, 0x9af3d17d,
+ 0x8d893530, 0x8c4b5f07, 0x8e0de15e, 0x8fcf8b69,
+ 0x8a809dec, 0x8b42f7db, 0x89044982, 0x88c623b5,
+ 0x839a6488, 0x82580ebf, 0x801eb0e6, 0x81dcdad1,
+ 0x8493cc54, 0x8551a663, 0x8717183a, 0x86d5720d,
+ 0xa9e2d0a0, 0xa820ba97, 0xaa6604ce, 0xaba46ef9,
+ 0xaeeb787c, 0xaf29124b, 0xad6fac12, 0xacadc625,
+ 0xa7f18118, 0xa633eb2f, 0xa4755576, 0xa5b73f41,
+ 0xa0f829c4, 0xa13a43f3, 0xa37cfdaa, 0xa2be979d,
+ 0xb5c473d0, 0xb40619e7, 0xb640a7be, 0xb782cd89,
+ 0xb2cddb0c, 0xb30fb13b, 0xb1490f62, 0xb08b6555,
+ 0xbbd72268, 0xba15485f, 0xb853f606, 0xb9919c31,
+ 0xbcde8ab4, 0xbd1ce083, 0xbf5a5eda, 0xbe9834ed,
+ 0x00000000, 0xb8bc6765, 0xaa09c88b, 0x12b5afee,
+ 0x8f629757, 0x37def032, 0x256b5fdc, 0x9dd738b9,
+ 0xc5b428ef, 0x7d084f8a, 0x6fbde064, 0xd7018701,
+ 0x4ad6bfb8, 0xf26ad8dd, 0xe0df7733, 0x58631056,
+ 0x5019579f, 0xe8a530fa, 0xfa109f14, 0x42acf871,
+ 0xdf7bc0c8, 0x67c7a7ad, 0x75720843, 0xcdce6f26,
+ 0x95ad7f70, 0x2d111815, 0x3fa4b7fb, 0x8718d09e,
+ 0x1acfe827, 0xa2738f42, 0xb0c620ac, 0x087a47c9,
+ 0xa032af3e, 0x188ec85b, 0x0a3b67b5, 0xb28700d0,
+ 0x2f503869, 0x97ec5f0c, 0x8559f0e2, 0x3de59787,
+ 0x658687d1, 0xdd3ae0b4, 0xcf8f4f5a, 0x7733283f,
+ 0xeae41086, 0x525877e3, 0x40edd80d, 0xf851bf68,
+ 0xf02bf8a1, 0x48979fc4, 0x5a22302a, 0xe29e574f,
+ 0x7f496ff6, 0xc7f50893, 0xd540a77d, 0x6dfcc018,
+ 0x359fd04e, 0x8d23b72b, 0x9f9618c5, 0x272a7fa0,
+ 0xbafd4719, 0x0241207c, 0x10f48f92, 0xa848e8f7,
+ 0x9b14583d, 0x23a83f58, 0x311d90b6, 0x89a1f7d3,
+ 0x1476cf6a, 0xaccaa80f, 0xbe7f07e1, 0x06c36084,
+ 0x5ea070d2, 0xe61c17b7, 0xf4a9b859, 0x4c15df3c,
+ 0xd1c2e785, 0x697e80e0, 0x7bcb2f0e, 0xc377486b,
+ 0xcb0d0fa2, 0x73b168c7, 0x6104c729, 0xd9b8a04c,
+ 0x446f98f5, 0xfcd3ff90, 0xee66507e, 0x56da371b,
+ 0x0eb9274d, 0xb6054028, 0xa4b0efc6, 0x1c0c88a3,
+ 0x81dbb01a, 0x3967d77f, 0x2bd27891, 0x936e1ff4,
+ 0x3b26f703, 0x839a9066, 0x912f3f88, 0x299358ed,
+ 0xb4446054, 0x0cf80731, 0x1e4da8df, 0xa6f1cfba,
+ 0xfe92dfec, 0x462eb889, 0x549b1767, 0xec277002,
+ 0x71f048bb, 0xc94c2fde, 0xdbf98030, 0x6345e755,
+ 0x6b3fa09c, 0xd383c7f9, 0xc1366817, 0x798a0f72,
+ 0xe45d37cb, 0x5ce150ae, 0x4e54ff40, 0xf6e89825,
+ 0xae8b8873, 0x1637ef16, 0x048240f8, 0xbc3e279d,
+ 0x21e91f24, 0x99557841, 0x8be0d7af, 0x335cb0ca,
+ 0xed59b63b, 0x55e5d15e, 0x47507eb0, 0xffec19d5,
+ 0x623b216c, 0xda874609, 0xc832e9e7, 0x708e8e82,
+ 0x28ed9ed4, 0x9051f9b1, 0x82e4565f, 0x3a58313a,
+ 0xa78f0983, 0x1f336ee6, 0x0d86c108, 0xb53aa66d,
+ 0xbd40e1a4, 0x05fc86c1, 0x1749292f, 0xaff54e4a,
+ 0x322276f3, 0x8a9e1196, 0x982bbe78, 0x2097d91d,
+ 0x78f4c94b, 0xc048ae2e, 0xd2fd01c0, 0x6a4166a5,
+ 0xf7965e1c, 0x4f2a3979, 0x5d9f9697, 0xe523f1f2,
+ 0x4d6b1905, 0xf5d77e60, 0xe762d18e, 0x5fdeb6eb,
+ 0xc2098e52, 0x7ab5e937, 0x680046d9, 0xd0bc21bc,
+ 0x88df31ea, 0x3063568f, 0x22d6f961, 0x9a6a9e04,
+ 0x07bda6bd, 0xbf01c1d8, 0xadb46e36, 0x15080953,
+ 0x1d724e9a, 0xa5ce29ff, 0xb77b8611, 0x0fc7e174,
+ 0x9210d9cd, 0x2aacbea8, 0x38191146, 0x80a57623,
+ 0xd8c66675, 0x607a0110, 0x72cfaefe, 0xca73c99b,
+ 0x57a4f122, 0xef189647, 0xfdad39a9, 0x45115ecc,
+ 0x764dee06, 0xcef18963, 0xdc44268d, 0x64f841e8,
+ 0xf92f7951, 0x41931e34, 0x5326b1da, 0xeb9ad6bf,
+ 0xb3f9c6e9, 0x0b45a18c, 0x19f00e62, 0xa14c6907,
+ 0x3c9b51be, 0x842736db, 0x96929935, 0x2e2efe50,
+ 0x2654b999, 0x9ee8defc, 0x8c5d7112, 0x34e11677,
+ 0xa9362ece, 0x118a49ab, 0x033fe645, 0xbb838120,
+ 0xe3e09176, 0x5b5cf613, 0x49e959fd, 0xf1553e98,
+ 0x6c820621, 0xd43e6144, 0xc68bceaa, 0x7e37a9cf,
+ 0xd67f4138, 0x6ec3265d, 0x7c7689b3, 0xc4caeed6,
+ 0x591dd66f, 0xe1a1b10a, 0xf3141ee4, 0x4ba87981,
+ 0x13cb69d7, 0xab770eb2, 0xb9c2a15c, 0x017ec639,
+ 0x9ca9fe80, 0x241599e5, 0x36a0360b, 0x8e1c516e,
+ 0x866616a7, 0x3eda71c2, 0x2c6fde2c, 0x94d3b949,
+ 0x090481f0, 0xb1b8e695, 0xa30d497b, 0x1bb12e1e,
+ 0x43d23e48, 0xfb6e592d, 0xe9dbf6c3, 0x516791a6,
+ 0xccb0a91f, 0x740cce7a, 0x66b96194, 0xde0506f1
+};
+
/* CRC32 */
+static inline u32
+crc32_next (u32 crc, byte data)
+{
+ return (crc >> 8) ^ crc32_table[(crc & 0xff) ^ data];
+}
+
+/*
+ * Process 4 bytes in one go
+ */
+static inline u32
+crc32_next4 (u32 crc, u32 data)
+{
+ crc ^= data;
+ crc = crc32_table[(crc & 0xff) + 0x300] ^
+ crc32_table[((crc >> 8) & 0xff) + 0x200] ^
+ crc32_table[((crc >> 16) & 0xff) + 0x100] ^
+ crc32_table[(crc >> 24) & 0xff];
+ return crc;
+}
+
static void
crc32_init (void *context)
{
@@ -156,12 +342,40 @@ crc32_init (void *context)
}
static void
-crc32_write (void *context, const void *inbuf, size_t inlen)
+crc32_write (void *context, const void *inbuf_arg, size_t inlen)
{
CRC_CONTEXT *ctx = (CRC_CONTEXT *) context;
- if (!inbuf)
+ const byte *inbuf = inbuf_arg;
+ u32 crc;
+
+ if (!inbuf || !inlen)
return;
- ctx->CRC = update_crc32 (ctx->CRC, inbuf, inlen);
+
+ crc = ctx->CRC;
+
+ while (inlen >= 16)
+ {
+ inlen -= 16;
+ crc = crc32_next4(crc, buf_get_le32(&inbuf[0]));
+ crc = crc32_next4(crc, buf_get_le32(&inbuf[4]));
+ crc = crc32_next4(crc, buf_get_le32(&inbuf[8]));
+ crc = crc32_next4(crc, buf_get_le32(&inbuf[12]));
+ inbuf += 16;
+ }
+
+ while (inlen >= 4)
+ {
+ inlen -= 4;
+ crc = crc32_next4(crc, buf_get_le32(inbuf));
+ inbuf += 4;
+ }
+
+ while (inlen--)
+ {
+ crc = crc32_next(crc, *inbuf++);
+ }
+
+ ctx->CRC = crc;
}
static byte *
@@ -176,13 +390,12 @@ crc32_final (void *context)
{
CRC_CONTEXT *ctx = (CRC_CONTEXT *) context;
ctx->CRC ^= 0xffffffffL;
- ctx->buf[0] = (ctx->CRC >> 24) & 0xFF;
- ctx->buf[1] = (ctx->CRC >> 16) & 0xFF;
- ctx->buf[2] = (ctx->CRC >> 8) & 0xFF;
- ctx->buf[3] = (ctx->CRC ) & 0xFF;
+ buf_put_be32 (ctx->buf, ctx->CRC);
}
/* CRC32 a'la RFC 1510 */
+/* CRC of the string "123456789" is 0x2dfd2d88 */
+
static void
crc32rfc1510_init (void *context)
{
@@ -194,82 +407,366 @@ static void
crc32rfc1510_final (void *context)
{
CRC_CONTEXT *ctx = (CRC_CONTEXT *) context;
- ctx->buf[0] = (ctx->CRC >> 24) & 0xFF;
- ctx->buf[1] = (ctx->CRC >> 16) & 0xFF;
- ctx->buf[2] = (ctx->CRC >> 8) & 0xFF;
- ctx->buf[3] = (ctx->CRC ) & 0xFF;
+ buf_put_be32(ctx->buf, ctx->CRC);
}
/* CRC24 a'la RFC 2440 */
/*
- * The following CRC 24 routines are adapted from RFC 2440, which has
- * the following copyright notice:
+ * Code generated by universal_crc by Danjel McGougan
*
- * Copyright (C) The Internet Society (1998). All Rights Reserved.
+ * CRC parameters used:
+ * bits: 24
+ * poly: 0x864cfb
+ * init: 0xb704ce
+ * xor: 0x000000
+ * reverse: false
+ * non-direct: false
*
- * This document and translations of it may be copied and furnished
- * to others, and derivative works that comment on or otherwise
- * explain it or assist in its implementation may be prepared,
- * copied, published and distributed, in whole or in part, without
- * restriction of any kind, provided that the above copyright notice
- * and this paragraph are included on all such copies and derivative
- * works. However, this document itself may not be modified in any
- * way, such as by removing the copyright notice or references to
- * the Internet Society or other Internet organizations, except as
- * needed for the purpose of developing Internet standards in which
- * case the procedures for copyrights defined in the Internet
- * Standards process must be followed, or as required to translate
- * it into languages other than English.
- *
- * The limited permissions granted above are perpetual and will not be
- * revoked by the Internet Society or its successors or assigns.
- *
- * This document and the information contained herein is provided on
- * an "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET
- * ENGINEERING TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE
- * OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY
- * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR
- * PURPOSE.
+ * CRC of the string "123456789" is 0x21cf02
+ */
+
+static const u32 crc24_table[1024] =
+{
+ 0x00000000, 0x00fb4c86, 0x000dd58a, 0x00f6990c,
+ 0x00e1e693, 0x001aaa15, 0x00ec3319, 0x00177f9f,
+ 0x003981a1, 0x00c2cd27, 0x0034542b, 0x00cf18ad,
+ 0x00d86732, 0x00232bb4, 0x00d5b2b8, 0x002efe3e,
+ 0x00894ec5, 0x00720243, 0x00849b4f, 0x007fd7c9,
+ 0x0068a856, 0x0093e4d0, 0x00657ddc, 0x009e315a,
+ 0x00b0cf64, 0x004b83e2, 0x00bd1aee, 0x00465668,
+ 0x005129f7, 0x00aa6571, 0x005cfc7d, 0x00a7b0fb,
+ 0x00e9d10c, 0x00129d8a, 0x00e40486, 0x001f4800,
+ 0x0008379f, 0x00f37b19, 0x0005e215, 0x00feae93,
+ 0x00d050ad, 0x002b1c2b, 0x00dd8527, 0x0026c9a1,
+ 0x0031b63e, 0x00cafab8, 0x003c63b4, 0x00c72f32,
+ 0x00609fc9, 0x009bd34f, 0x006d4a43, 0x009606c5,
+ 0x0081795a, 0x007a35dc, 0x008cacd0, 0x0077e056,
+ 0x00591e68, 0x00a252ee, 0x0054cbe2, 0x00af8764,
+ 0x00b8f8fb, 0x0043b47d, 0x00b52d71, 0x004e61f7,
+ 0x00d2a319, 0x0029ef9f, 0x00df7693, 0x00243a15,
+ 0x0033458a, 0x00c8090c, 0x003e9000, 0x00c5dc86,
+ 0x00eb22b8, 0x00106e3e, 0x00e6f732, 0x001dbbb4,
+ 0x000ac42b, 0x00f188ad, 0x000711a1, 0x00fc5d27,
+ 0x005beddc, 0x00a0a15a, 0x00563856, 0x00ad74d0,
+ 0x00ba0b4f, 0x004147c9, 0x00b7dec5, 0x004c9243,
+ 0x00626c7d, 0x009920fb, 0x006fb9f7, 0x0094f571,
+ 0x00838aee, 0x0078c668, 0x008e5f64, 0x007513e2,
+ 0x003b7215, 0x00c03e93, 0x0036a79f, 0x00cdeb19,
+ 0x00da9486, 0x0021d800, 0x00d7410c, 0x002c0d8a,
+ 0x0002f3b4, 0x00f9bf32, 0x000f263e, 0x00f46ab8,
+ 0x00e31527, 0x001859a1, 0x00eec0ad, 0x00158c2b,
+ 0x00b23cd0, 0x00497056, 0x00bfe95a, 0x0044a5dc,
+ 0x0053da43, 0x00a896c5, 0x005e0fc9, 0x00a5434f,
+ 0x008bbd71, 0x0070f1f7, 0x008668fb, 0x007d247d,
+ 0x006a5be2, 0x00911764, 0x00678e68, 0x009cc2ee,
+ 0x00a44733, 0x005f0bb5, 0x00a992b9, 0x0052de3f,
+ 0x0045a1a0, 0x00beed26, 0x0048742a, 0x00b338ac,
+ 0x009dc692, 0x00668a14, 0x00901318, 0x006b5f9e,
+ 0x007c2001, 0x00876c87, 0x0071f58b, 0x008ab90d,
+ 0x002d09f6, 0x00d64570, 0x0020dc7c, 0x00db90fa,
+ 0x00ccef65, 0x0037a3e3, 0x00c13aef, 0x003a7669,
+ 0x00148857, 0x00efc4d1, 0x00195ddd, 0x00e2115b,
+ 0x00f56ec4, 0x000e2242, 0x00f8bb4e, 0x0003f7c8,
+ 0x004d963f, 0x00b6dab9, 0x004043b5, 0x00bb0f33,
+ 0x00ac70ac, 0x00573c2a, 0x00a1a526, 0x005ae9a0,
+ 0x0074179e, 0x008f5b18, 0x0079c214, 0x00828e92,
+ 0x0095f10d, 0x006ebd8b, 0x00982487, 0x00636801,
+ 0x00c4d8fa, 0x003f947c, 0x00c90d70, 0x003241f6,
+ 0x00253e69, 0x00de72ef, 0x0028ebe3, 0x00d3a765,
+ 0x00fd595b, 0x000615dd, 0x00f08cd1, 0x000bc057,
+ 0x001cbfc8, 0x00e7f34e, 0x00116a42, 0x00ea26c4,
+ 0x0076e42a, 0x008da8ac, 0x007b31a0, 0x00807d26,
+ 0x009702b9, 0x006c4e3f, 0x009ad733, 0x00619bb5,
+ 0x004f658b, 0x00b4290d, 0x0042b001, 0x00b9fc87,
+ 0x00ae8318, 0x0055cf9e, 0x00a35692, 0x00581a14,
+ 0x00ffaaef, 0x0004e669, 0x00f27f65, 0x000933e3,
+ 0x001e4c7c, 0x00e500fa, 0x001399f6, 0x00e8d570,
+ 0x00c62b4e, 0x003d67c8, 0x00cbfec4, 0x0030b242,
+ 0x0027cddd, 0x00dc815b, 0x002a1857, 0x00d154d1,
+ 0x009f3526, 0x006479a0, 0x0092e0ac, 0x0069ac2a,
+ 0x007ed3b5, 0x00859f33, 0x0073063f, 0x00884ab9,
+ 0x00a6b487, 0x005df801, 0x00ab610d, 0x00502d8b,
+ 0x00475214, 0x00bc1e92, 0x004a879e, 0x00b1cb18,
+ 0x00167be3, 0x00ed3765, 0x001bae69, 0x00e0e2ef,
+ 0x00f79d70, 0x000cd1f6, 0x00fa48fa, 0x0001047c,
+ 0x002ffa42, 0x00d4b6c4, 0x00222fc8, 0x00d9634e,
+ 0x00ce1cd1, 0x00355057, 0x00c3c95b, 0x003885dd,
+ 0x00000000, 0x00488f66, 0x00901ecd, 0x00d891ab,
+ 0x00db711c, 0x0093fe7a, 0x004b6fd1, 0x0003e0b7,
+ 0x00b6e338, 0x00fe6c5e, 0x0026fdf5, 0x006e7293,
+ 0x006d9224, 0x00251d42, 0x00fd8ce9, 0x00b5038f,
+ 0x006cc771, 0x00244817, 0x00fcd9bc, 0x00b456da,
+ 0x00b7b66d, 0x00ff390b, 0x0027a8a0, 0x006f27c6,
+ 0x00da2449, 0x0092ab2f, 0x004a3a84, 0x0002b5e2,
+ 0x00015555, 0x0049da33, 0x00914b98, 0x00d9c4fe,
+ 0x00d88ee3, 0x00900185, 0x0048902e, 0x00001f48,
+ 0x0003ffff, 0x004b7099, 0x0093e132, 0x00db6e54,
+ 0x006e6ddb, 0x0026e2bd, 0x00fe7316, 0x00b6fc70,
+ 0x00b51cc7, 0x00fd93a1, 0x0025020a, 0x006d8d6c,
+ 0x00b44992, 0x00fcc6f4, 0x0024575f, 0x006cd839,
+ 0x006f388e, 0x0027b7e8, 0x00ff2643, 0x00b7a925,
+ 0x0002aaaa, 0x004a25cc, 0x0092b467, 0x00da3b01,
+ 0x00d9dbb6, 0x009154d0, 0x0049c57b, 0x00014a1d,
+ 0x004b5141, 0x0003de27, 0x00db4f8c, 0x0093c0ea,
+ 0x0090205d, 0x00d8af3b, 0x00003e90, 0x0048b1f6,
+ 0x00fdb279, 0x00b53d1f, 0x006dacb4, 0x002523d2,
+ 0x0026c365, 0x006e4c03, 0x00b6dda8, 0x00fe52ce,
+ 0x00279630, 0x006f1956, 0x00b788fd, 0x00ff079b,
+ 0x00fce72c, 0x00b4684a, 0x006cf9e1, 0x00247687,
+ 0x00917508, 0x00d9fa6e, 0x00016bc5, 0x0049e4a3,
+ 0x004a0414, 0x00028b72, 0x00da1ad9, 0x009295bf,
+ 0x0093dfa2, 0x00db50c4, 0x0003c16f, 0x004b4e09,
+ 0x0048aebe, 0x000021d8, 0x00d8b073, 0x00903f15,
+ 0x00253c9a, 0x006db3fc, 0x00b52257, 0x00fdad31,
+ 0x00fe4d86, 0x00b6c2e0, 0x006e534b, 0x0026dc2d,
+ 0x00ff18d3, 0x00b797b5, 0x006f061e, 0x00278978,
+ 0x002469cf, 0x006ce6a9, 0x00b47702, 0x00fcf864,
+ 0x0049fbeb, 0x0001748d, 0x00d9e526, 0x00916a40,
+ 0x00928af7, 0x00da0591, 0x0002943a, 0x004a1b5c,
+ 0x0096a282, 0x00de2de4, 0x0006bc4f, 0x004e3329,
+ 0x004dd39e, 0x00055cf8, 0x00ddcd53, 0x00954235,
+ 0x002041ba, 0x0068cedc, 0x00b05f77, 0x00f8d011,
+ 0x00fb30a6, 0x00b3bfc0, 0x006b2e6b, 0x0023a10d,
+ 0x00fa65f3, 0x00b2ea95, 0x006a7b3e, 0x0022f458,
+ 0x002114ef, 0x00699b89, 0x00b10a22, 0x00f98544,
+ 0x004c86cb, 0x000409ad, 0x00dc9806, 0x00941760,
+ 0x0097f7d7, 0x00df78b1, 0x0007e91a, 0x004f667c,
+ 0x004e2c61, 0x0006a307, 0x00de32ac, 0x0096bdca,
+ 0x00955d7d, 0x00ddd21b, 0x000543b0, 0x004dccd6,
+ 0x00f8cf59, 0x00b0403f, 0x0068d194, 0x00205ef2,
+ 0x0023be45, 0x006b3123, 0x00b3a088, 0x00fb2fee,
+ 0x0022eb10, 0x006a6476, 0x00b2f5dd, 0x00fa7abb,
+ 0x00f99a0c, 0x00b1156a, 0x006984c1, 0x00210ba7,
+ 0x00940828, 0x00dc874e, 0x000416e5, 0x004c9983,
+ 0x004f7934, 0x0007f652, 0x00df67f9, 0x0097e89f,
+ 0x00ddf3c3, 0x00957ca5, 0x004ded0e, 0x00056268,
+ 0x000682df, 0x004e0db9, 0x00969c12, 0x00de1374,
+ 0x006b10fb, 0x00239f9d, 0x00fb0e36, 0x00b38150,
+ 0x00b061e7, 0x00f8ee81, 0x00207f2a, 0x0068f04c,
+ 0x00b134b2, 0x00f9bbd4, 0x00212a7f, 0x0069a519,
+ 0x006a45ae, 0x0022cac8, 0x00fa5b63, 0x00b2d405,
+ 0x0007d78a, 0x004f58ec, 0x0097c947, 0x00df4621,
+ 0x00dca696, 0x009429f0, 0x004cb85b, 0x0004373d,
+ 0x00057d20, 0x004df246, 0x009563ed, 0x00ddec8b,
+ 0x00de0c3c, 0x0096835a, 0x004e12f1, 0x00069d97,
+ 0x00b39e18, 0x00fb117e, 0x002380d5, 0x006b0fb3,
+ 0x0068ef04, 0x00206062, 0x00f8f1c9, 0x00b07eaf,
+ 0x0069ba51, 0x00213537, 0x00f9a49c, 0x00b12bfa,
+ 0x00b2cb4d, 0x00fa442b, 0x0022d580, 0x006a5ae6,
+ 0x00df5969, 0x0097d60f, 0x004f47a4, 0x0007c8c2,
+ 0x00042875, 0x004ca713, 0x009436b8, 0x00dcb9de,
+ 0x00000000, 0x00d70983, 0x00555f80, 0x00825603,
+ 0x0051f286, 0x0086fb05, 0x0004ad06, 0x00d3a485,
+ 0x0059a88b, 0x008ea108, 0x000cf70b, 0x00dbfe88,
+ 0x00085a0d, 0x00df538e, 0x005d058d, 0x008a0c0e,
+ 0x00491c91, 0x009e1512, 0x001c4311, 0x00cb4a92,
+ 0x0018ee17, 0x00cfe794, 0x004db197, 0x009ab814,
+ 0x0010b41a, 0x00c7bd99, 0x0045eb9a, 0x0092e219,
+ 0x0041469c, 0x00964f1f, 0x0014191c, 0x00c3109f,
+ 0x006974a4, 0x00be7d27, 0x003c2b24, 0x00eb22a7,
+ 0x00388622, 0x00ef8fa1, 0x006dd9a2, 0x00bad021,
+ 0x0030dc2f, 0x00e7d5ac, 0x006583af, 0x00b28a2c,
+ 0x00612ea9, 0x00b6272a, 0x00347129, 0x00e378aa,
+ 0x00206835, 0x00f761b6, 0x007537b5, 0x00a23e36,
+ 0x00719ab3, 0x00a69330, 0x0024c533, 0x00f3ccb0,
+ 0x0079c0be, 0x00aec93d, 0x002c9f3e, 0x00fb96bd,
+ 0x00283238, 0x00ff3bbb, 0x007d6db8, 0x00aa643b,
+ 0x0029a4ce, 0x00fead4d, 0x007cfb4e, 0x00abf2cd,
+ 0x00785648, 0x00af5fcb, 0x002d09c8, 0x00fa004b,
+ 0x00700c45, 0x00a705c6, 0x002553c5, 0x00f25a46,
+ 0x0021fec3, 0x00f6f740, 0x0074a143, 0x00a3a8c0,
+ 0x0060b85f, 0x00b7b1dc, 0x0035e7df, 0x00e2ee5c,
+ 0x00314ad9, 0x00e6435a, 0x00641559, 0x00b31cda,
+ 0x003910d4, 0x00ee1957, 0x006c4f54, 0x00bb46d7,
+ 0x0068e252, 0x00bfebd1, 0x003dbdd2, 0x00eab451,
+ 0x0040d06a, 0x0097d9e9, 0x00158fea, 0x00c28669,
+ 0x001122ec, 0x00c62b6f, 0x00447d6c, 0x009374ef,
+ 0x001978e1, 0x00ce7162, 0x004c2761, 0x009b2ee2,
+ 0x00488a67, 0x009f83e4, 0x001dd5e7, 0x00cadc64,
+ 0x0009ccfb, 0x00dec578, 0x005c937b, 0x008b9af8,
+ 0x00583e7d, 0x008f37fe, 0x000d61fd, 0x00da687e,
+ 0x00506470, 0x00876df3, 0x00053bf0, 0x00d23273,
+ 0x000196f6, 0x00d69f75, 0x0054c976, 0x0083c0f5,
+ 0x00a9041b, 0x007e0d98, 0x00fc5b9b, 0x002b5218,
+ 0x00f8f69d, 0x002fff1e, 0x00ada91d, 0x007aa09e,
+ 0x00f0ac90, 0x0027a513, 0x00a5f310, 0x0072fa93,
+ 0x00a15e16, 0x00765795, 0x00f40196, 0x00230815,
+ 0x00e0188a, 0x00371109, 0x00b5470a, 0x00624e89,
+ 0x00b1ea0c, 0x0066e38f, 0x00e4b58c, 0x0033bc0f,
+ 0x00b9b001, 0x006eb982, 0x00ecef81, 0x003be602,
+ 0x00e84287, 0x003f4b04, 0x00bd1d07, 0x006a1484,
+ 0x00c070bf, 0x0017793c, 0x00952f3f, 0x004226bc,
+ 0x00918239, 0x00468bba, 0x00c4ddb9, 0x0013d43a,
+ 0x0099d834, 0x004ed1b7, 0x00cc87b4, 0x001b8e37,
+ 0x00c82ab2, 0x001f2331, 0x009d7532, 0x004a7cb1,
+ 0x00896c2e, 0x005e65ad, 0x00dc33ae, 0x000b3a2d,
+ 0x00d89ea8, 0x000f972b, 0x008dc128, 0x005ac8ab,
+ 0x00d0c4a5, 0x0007cd26, 0x00859b25, 0x005292a6,
+ 0x00813623, 0x00563fa0, 0x00d469a3, 0x00036020,
+ 0x0080a0d5, 0x0057a956, 0x00d5ff55, 0x0002f6d6,
+ 0x00d15253, 0x00065bd0, 0x00840dd3, 0x00530450,
+ 0x00d9085e, 0x000e01dd, 0x008c57de, 0x005b5e5d,
+ 0x0088fad8, 0x005ff35b, 0x00dda558, 0x000aacdb,
+ 0x00c9bc44, 0x001eb5c7, 0x009ce3c4, 0x004bea47,
+ 0x00984ec2, 0x004f4741, 0x00cd1142, 0x001a18c1,
+ 0x009014cf, 0x00471d4c, 0x00c54b4f, 0x001242cc,
+ 0x00c1e649, 0x0016efca, 0x0094b9c9, 0x0043b04a,
+ 0x00e9d471, 0x003eddf2, 0x00bc8bf1, 0x006b8272,
+ 0x00b826f7, 0x006f2f74, 0x00ed7977, 0x003a70f4,
+ 0x00b07cfa, 0x00677579, 0x00e5237a, 0x00322af9,
+ 0x00e18e7c, 0x003687ff, 0x00b4d1fc, 0x0063d87f,
+ 0x00a0c8e0, 0x0077c163, 0x00f59760, 0x00229ee3,
+ 0x00f13a66, 0x002633e5, 0x00a465e6, 0x00736c65,
+ 0x00f9606b, 0x002e69e8, 0x00ac3feb, 0x007b3668,
+ 0x00a892ed, 0x007f9b6e, 0x00fdcd6d, 0x002ac4ee,
+ 0x00000000, 0x00520936, 0x00a4126c, 0x00f61b5a,
+ 0x004825d8, 0x001a2cee, 0x00ec37b4, 0x00be3e82,
+ 0x006b0636, 0x00390f00, 0x00cf145a, 0x009d1d6c,
+ 0x002323ee, 0x00712ad8, 0x00873182, 0x00d538b4,
+ 0x00d60c6c, 0x0084055a, 0x00721e00, 0x00201736,
+ 0x009e29b4, 0x00cc2082, 0x003a3bd8, 0x006832ee,
+ 0x00bd0a5a, 0x00ef036c, 0x00191836, 0x004b1100,
+ 0x00f52f82, 0x00a726b4, 0x00513dee, 0x000334d8,
+ 0x00ac19d8, 0x00fe10ee, 0x00080bb4, 0x005a0282,
+ 0x00e43c00, 0x00b63536, 0x00402e6c, 0x0012275a,
+ 0x00c71fee, 0x009516d8, 0x00630d82, 0x003104b4,
+ 0x008f3a36, 0x00dd3300, 0x002b285a, 0x0079216c,
+ 0x007a15b4, 0x00281c82, 0x00de07d8, 0x008c0eee,
+ 0x0032306c, 0x0060395a, 0x00962200, 0x00c42b36,
+ 0x00111382, 0x00431ab4, 0x00b501ee, 0x00e708d8,
+ 0x0059365a, 0x000b3f6c, 0x00fd2436, 0x00af2d00,
+ 0x00a37f36, 0x00f17600, 0x00076d5a, 0x0055646c,
+ 0x00eb5aee, 0x00b953d8, 0x004f4882, 0x001d41b4,
+ 0x00c87900, 0x009a7036, 0x006c6b6c, 0x003e625a,
+ 0x00805cd8, 0x00d255ee, 0x00244eb4, 0x00764782,
+ 0x0075735a, 0x00277a6c, 0x00d16136, 0x00836800,
+ 0x003d5682, 0x006f5fb4, 0x009944ee, 0x00cb4dd8,
+ 0x001e756c, 0x004c7c5a, 0x00ba6700, 0x00e86e36,
+ 0x005650b4, 0x00045982, 0x00f242d8, 0x00a04bee,
+ 0x000f66ee, 0x005d6fd8, 0x00ab7482, 0x00f97db4,
+ 0x00474336, 0x00154a00, 0x00e3515a, 0x00b1586c,
+ 0x006460d8, 0x003669ee, 0x00c072b4, 0x00927b82,
+ 0x002c4500, 0x007e4c36, 0x0088576c, 0x00da5e5a,
+ 0x00d96a82, 0x008b63b4, 0x007d78ee, 0x002f71d8,
+ 0x00914f5a, 0x00c3466c, 0x00355d36, 0x00675400,
+ 0x00b26cb4, 0x00e06582, 0x00167ed8, 0x004477ee,
+ 0x00fa496c, 0x00a8405a, 0x005e5b00, 0x000c5236,
+ 0x0046ff6c, 0x0014f65a, 0x00e2ed00, 0x00b0e436,
+ 0x000edab4, 0x005cd382, 0x00aac8d8, 0x00f8c1ee,
+ 0x002df95a, 0x007ff06c, 0x0089eb36, 0x00dbe200,
+ 0x0065dc82, 0x0037d5b4, 0x00c1ceee, 0x0093c7d8,
+ 0x0090f300, 0x00c2fa36, 0x0034e16c, 0x0066e85a,
+ 0x00d8d6d8, 0x008adfee, 0x007cc4b4, 0x002ecd82,
+ 0x00fbf536, 0x00a9fc00, 0x005fe75a, 0x000dee6c,
+ 0x00b3d0ee, 0x00e1d9d8, 0x0017c282, 0x0045cbb4,
+ 0x00eae6b4, 0x00b8ef82, 0x004ef4d8, 0x001cfdee,
+ 0x00a2c36c, 0x00f0ca5a, 0x0006d100, 0x0054d836,
+ 0x0081e082, 0x00d3e9b4, 0x0025f2ee, 0x0077fbd8,
+ 0x00c9c55a, 0x009bcc6c, 0x006dd736, 0x003fde00,
+ 0x003cead8, 0x006ee3ee, 0x0098f8b4, 0x00caf182,
+ 0x0074cf00, 0x0026c636, 0x00d0dd6c, 0x0082d45a,
+ 0x0057ecee, 0x0005e5d8, 0x00f3fe82, 0x00a1f7b4,
+ 0x001fc936, 0x004dc000, 0x00bbdb5a, 0x00e9d26c,
+ 0x00e5805a, 0x00b7896c, 0x00419236, 0x00139b00,
+ 0x00ada582, 0x00ffacb4, 0x0009b7ee, 0x005bbed8,
+ 0x008e866c, 0x00dc8f5a, 0x002a9400, 0x00789d36,
+ 0x00c6a3b4, 0x0094aa82, 0x0062b1d8, 0x0030b8ee,
+ 0x00338c36, 0x00618500, 0x00979e5a, 0x00c5976c,
+ 0x007ba9ee, 0x0029a0d8, 0x00dfbb82, 0x008db2b4,
+ 0x00588a00, 0x000a8336, 0x00fc986c, 0x00ae915a,
+ 0x0010afd8, 0x0042a6ee, 0x00b4bdb4, 0x00e6b482,
+ 0x00499982, 0x001b90b4, 0x00ed8bee, 0x00bf82d8,
+ 0x0001bc5a, 0x0053b56c, 0x00a5ae36, 0x00f7a700,
+ 0x00229fb4, 0x00709682, 0x00868dd8, 0x00d484ee,
+ 0x006aba6c, 0x0038b35a, 0x00cea800, 0x009ca136,
+ 0x009f95ee, 0x00cd9cd8, 0x003b8782, 0x00698eb4,
+ 0x00d7b036, 0x0085b900, 0x0073a25a, 0x0021ab6c,
+ 0x00f493d8, 0x00a69aee, 0x005081b4, 0x00028882,
+ 0x00bcb600, 0x00eebf36, 0x0018a46c, 0x004aad5a
+};
+
+static inline
+u32 crc24_init (void)
+{
+ return 0xce04b7;
+}
+
+static inline
+u32 crc24_next (u32 crc, byte data)
+{
+ return (crc >> 8) ^ crc24_table[(crc & 0xff) ^ data];
+}
+
+/*
+ * Process 4 bytes in one go
*/
+static inline
+u32 crc24_next4 (u32 crc, u32 data)
+{
+ crc ^= data;
+ crc = crc24_table[(crc & 0xff) + 0x300] ^
+ crc24_table[((crc >> 8) & 0xff) + 0x200] ^
+ crc24_table[((crc >> 16) & 0xff) + 0x100] ^
+ crc24_table[(crc >> 24) & 0xff];
+ return crc;
+}
-#define CRC24_INIT 0xb704ceL
-#define CRC24_POLY 0x1864cfbL
+static inline
+u32 crc24_final (u32 crc)
+{
+ return crc & 0xffffff;
+}
static void
crc24rfc2440_init (void *context)
{
CRC_CONTEXT *ctx = (CRC_CONTEXT *) context;
- ctx->CRC = CRC24_INIT;
+ ctx->CRC = crc24_init();
}
static void
crc24rfc2440_write (void *context, const void *inbuf_arg, size_t inlen)
{
const unsigned char *inbuf = inbuf_arg;
- int i;
CRC_CONTEXT *ctx = (CRC_CONTEXT *) context;
+ u32 crc;
- if (!inbuf)
+ if (!inbuf || !inlen)
return;
- while (inlen--) {
- ctx->CRC ^= (*inbuf++) << 16;
- for (i = 0; i < 8; i++) {
- ctx->CRC <<= 1;
- if (ctx->CRC & 0x1000000)
- ctx->CRC ^= CRC24_POLY;
+ crc = ctx->CRC;
+
+ while (inlen >= 16)
+ {
+ inlen -= 16;
+ crc = crc24_next4(crc, buf_get_le32(&inbuf[0]));
+ crc = crc24_next4(crc, buf_get_le32(&inbuf[4]));
+ crc = crc24_next4(crc, buf_get_le32(&inbuf[8]));
+ crc = crc24_next4(crc, buf_get_le32(&inbuf[12]));
+ inbuf += 16;
}
- }
+
+ while (inlen >= 4)
+ {
+ inlen -= 4;
+ crc = crc24_next4(crc, buf_get_le32(inbuf));
+ inbuf += 4;
+ }
+
+ while (inlen--)
+ {
+ crc = crc24_next(crc, *inbuf++);
+ }
+
+ ctx->CRC = crc;
}
static void
crc24rfc2440_final (void *context)
{
CRC_CONTEXT *ctx = (CRC_CONTEXT *) context;
- ctx->buf[0] = (ctx->CRC >> 16) & 0xFF;
- ctx->buf[1] = (ctx->CRC >> 8) & 0xFF;
- ctx->buf[2] = (ctx->CRC ) & 0xFF;
+ ctx->CRC = crc24_final(ctx->CRC);
+ buf_put_le32 (ctx->buf, ctx->CRC);
}
gcry_md_spec_t _gcry_digest_spec_crc32 =
diff --git a/grub-core/loader/arm/linux.c b/grub-core/loader/arm/linux.c
index 5b39f02bb2e592d85639891db6eb68a97ce12dfa..b4f609d2d01184b8d0a3e5aff448725f80a36a93 100644
--- a/grub-core/loader/arm/linux.c
+++ b/grub-core/loader/arm/linux.c
@@ -42,21 +42,18 @@ static grub_size_t linux_size;
static char *linux_args;
static grub_uint32_t machine_type;
-static void *fdt_addr;
+static const void *current_fdt;
typedef void (*kernel_entry_t) (int, unsigned long, void *);
-#define LINUX_ZIMAGE_OFFSET 0x24
-#define LINUX_ZIMAGE_MAGIC 0x016f2818
-
#define LINUX_PHYS_OFFSET (0x00008000)
#define LINUX_INITRD_PHYS_OFFSET (LINUX_PHYS_OFFSET + 0x02000000)
#define LINUX_FDT_PHYS_OFFSET (LINUX_INITRD_PHYS_OFFSET - 0x10000)
static grub_size_t
-get_atag_size (grub_uint32_t *atag)
+get_atag_size (const grub_uint32_t *atag)
{
- grub_uint32_t *atag0 = atag;
+ const grub_uint32_t *atag0 = atag;
while (atag[0] && atag[1])
atag += atag[0];
return atag - atag0;
@@ -68,10 +65,11 @@ get_atag_size (grub_uint32_t *atag)
* Merges in command line parameters and sets up initrd addresses.
*/
static grub_err_t
-linux_prepare_atag (void)
+linux_prepare_atag (void *target_atag)
{
- grub_uint32_t *atag_orig = (grub_uint32_t *) fdt_addr;
- grub_uint32_t *tmp_atag, *from, *to;
+ const grub_uint32_t *atag_orig = (const grub_uint32_t *) current_fdt;
+ grub_uint32_t *tmp_atag, *to;
+ const grub_uint32_t *from;
grub_size_t tmp_size;
grub_size_t arg_size = grub_strlen (linux_args);
char *cmdline_orig = NULL;
@@ -142,7 +140,7 @@ linux_prepare_atag (void)
to += 2;
/* Copy updated FDT to its launch location */
- grub_memcpy (atag_orig, tmp_atag, sizeof (grub_uint32_t) * (to - tmp_atag));
+ grub_memcpy (target_atag, tmp_atag, sizeof (grub_uint32_t) * (to - tmp_atag));
grub_free (tmp_atag);
grub_dprintf ("loader", "ATAG updated for Linux boot\n");
@@ -156,19 +154,19 @@ linux_prepare_atag (void)
* Merges in command line parameters and sets up initrd addresses.
*/
static grub_err_t
-linux_prepare_fdt (void)
+linux_prepare_fdt (void *target_fdt)
{
int node;
int retval;
int tmp_size;
void *tmp_fdt;
- tmp_size = grub_fdt_get_totalsize (fdt_addr) + 0x100 + grub_strlen (linux_args);
+ tmp_size = grub_fdt_get_totalsize (current_fdt) + 0x100 + grub_strlen (linux_args);
tmp_fdt = grub_malloc (tmp_size);
if (!tmp_fdt)
return grub_errno;
- grub_memcpy (tmp_fdt, fdt_addr, grub_fdt_get_totalsize (fdt_addr));
+ grub_memcpy (tmp_fdt, current_fdt, grub_fdt_get_totalsize (current_fdt));
grub_fdt_set_totalsize (tmp_fdt, tmp_size);
/* Find or create '/chosen' node */
@@ -209,7 +207,7 @@ linux_prepare_fdt (void)
}
/* Copy updated FDT to its launch location */
- grub_memcpy (fdt_addr, tmp_fdt, tmp_size);
+ grub_memcpy (target_fdt, tmp_fdt, tmp_size);
grub_free (tmp_fdt);
grub_dprintf ("loader", "FDT updated for Linux boot\n");
@@ -226,16 +224,17 @@ linux_boot (void)
{
kernel_entry_t linuxmain;
int fdt_valid, atag_valid;
+ void *target_fdt = 0;
- fdt_valid = (fdt_addr && grub_fdt_check_header_nosize (fdt_addr) == 0);
- atag_valid = ((((grub_uint16_t *) fdt_addr)[3] & ~3) == 0x5440
- && *((grub_uint32_t *) fdt_addr));
+ fdt_valid = (current_fdt && grub_fdt_check_header_nosize (current_fdt) == 0);
+ atag_valid = ((((const grub_uint16_t *) current_fdt)[3] & ~3) == 0x5440
+ && *((const grub_uint32_t *) current_fdt));
grub_dprintf ("loader", "atag: %p, %x, %x, %s, %s\n",
- fdt_addr,
- ((grub_uint16_t *) fdt_addr)[3],
- *((grub_uint32_t *) fdt_addr),
- (char *) fdt_addr,
- (char *) fdt_addr + 1);
+ current_fdt,
+ ((const grub_uint16_t *) current_fdt)[3],
+ *((const grub_uint32_t *) current_fdt),
+ (const char *) current_fdt,
+ (const char *) current_fdt + 1);
if (!fdt_valid && machine_type == GRUB_ARM_MACHINE_TYPE_FDT)
return grub_error (GRUB_ERR_FILE_NOT_FOUND,
@@ -245,23 +244,40 @@ linux_boot (void)
grub_dprintf ("loader", "Kernel at: 0x%x\n", linux_addr);
+ if (fdt_valid || atag_valid)
+ {
+#ifdef GRUB_MACHINE_EFI
+ grub_size_t size;
+ if (fdt_valid)
+ size = grub_fdt_get_totalsize (current_fdt);
+ else
+ size = 4 * get_atag_size (current_fdt);
+ size += grub_strlen (linux_args) + 256;
+ target_fdt = grub_efi_allocate_loader_memory (LINUX_FDT_PHYS_OFFSET, size);
+ if (!target_fdt)
+ return grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
+#else
+ target_fdt = (void *) LINUX_FDT_ADDRESS;
+#endif
+ }
+
if (fdt_valid)
{
grub_err_t err;
- err = linux_prepare_fdt ();
+ err = linux_prepare_fdt (target_fdt);
if (err)
return err;
- grub_dprintf ("loader", "FDT @ 0x%p\n", fdt_addr);
+ grub_dprintf ("loader", "FDT @ %p\n", target_fdt);
}
else if (atag_valid)
{
grub_err_t err;
- err = linux_prepare_atag ();
+ err = linux_prepare_atag (target_fdt);
if (err)
return err;
- grub_dprintf ("loader", "ATAG @ 0x%p\n", fdt_addr);
+ grub_dprintf ("loader", "ATAG @ %p\n", target_fdt);
}
grub_dprintf ("loader", "Jumping to Linux...\n");
@@ -274,18 +290,9 @@ linux_boot (void)
*/
linuxmain = (kernel_entry_t) linux_addr;
-#ifdef GRUB_MACHINE_EFI
- {
- grub_err_t err;
- err = grub_efi_prepare_platform();
- if (err != GRUB_ERR_NONE)
- return err;
- }
-#endif
-
grub_arm_disable_caches_mmu ();
- linuxmain (0, machine_type, fdt_addr);
+ linuxmain (0, machine_type, target_fdt);
return grub_error (GRUB_ERR_BAD_OS, "Linux call returned");
}
@@ -296,17 +303,12 @@ linux_boot (void)
static grub_err_t
linux_load (const char *filename, grub_file_t file)
{
+ struct linux_arm_kernel_header *lh;
int size;
size = grub_file_size (file);
-#ifdef GRUB_MACHINE_EFI
- linux_addr = (grub_addr_t) grub_efi_allocate_loader_memory (LINUX_PHYS_OFFSET, size);
- if (!linux_addr)
- return grub_errno;
-#else
linux_addr = LINUX_ADDRESS;
-#endif
grub_dprintf ("loader", "Loading Linux to 0x%08x\n",
(grub_addr_t) linux_addr);
@@ -318,9 +320,10 @@ linux_load (const char *filename, grub_file_t file)
return grub_errno;
}
- if (size > LINUX_ZIMAGE_OFFSET + 4
- && *(grub_uint32_t *) (linux_addr + LINUX_ZIMAGE_OFFSET)
- == LINUX_ZIMAGE_MAGIC)
+ lh = (void *) linux_addr;
+
+ if ((grub_size_t) size > sizeof (*lh) &&
+ lh->magic == GRUB_LINUX_ARM_MAGIC_SIGNATURE)
;
else if (size > 0x8000 && *(grub_uint32_t *) (linux_addr) == 0xea000006
&& machine_type == GRUB_ARM_MACHINE_TYPE_RASPBERRY_PI)
@@ -410,20 +413,7 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
size = grub_get_initrd_size (&initrd_ctx);
-#ifdef GRUB_MACHINE_EFI
- if (initrd_start)
- grub_efi_free_pages (initrd_start,
- (initrd_end - initrd_start + 0xfff) >> 12);
- initrd_start = (grub_addr_t) grub_efi_allocate_loader_memory (LINUX_INITRD_PHYS_OFFSET, size);
-
- if (!initrd_start)
- {
- grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
- goto fail;
- }
-#else
initrd_start = LINUX_INITRD_ADDRESS;
-#endif
grub_dprintf ("loader", "Loading initrd to 0x%08x\n",
(grub_addr_t) initrd_start);
@@ -444,11 +434,26 @@ fail:
static grub_err_t
load_dtb (grub_file_t dtb, int size)
{
- if ((grub_file_read (dtb, fdt_addr, size) != size)
- || (grub_fdt_check_header (fdt_addr, size) != 0))
- return grub_error (GRUB_ERR_BAD_OS, N_("invalid device tree"));
+ void *new_fdt = grub_zalloc (size);
+ if (!new_fdt)
+ return grub_errno;
+ grub_dprintf ("loader", "Loading device tree to %p\n",
+ new_fdt);
+ if ((grub_file_read (dtb, new_fdt, size) != size)
+ || (grub_fdt_check_header (new_fdt, size) != 0))
+ {
+ grub_free (new_fdt);
+ return grub_error (GRUB_ERR_BAD_OS, N_("invalid device tree"));
+ }
+
+ grub_fdt_set_totalsize (new_fdt, size);
+ current_fdt = new_fdt;
+ /*
+ * We've successfully loaded an FDT, so any machine type passed
+ * from firmware is now obsolete.
+ */
+ machine_type = GRUB_ARM_MACHINE_TYPE_FDT;
- grub_fdt_set_totalsize (fdt_addr, size);
return GRUB_ERR_NONE;
}
@@ -464,42 +469,13 @@ grub_cmd_devicetree (grub_command_t cmd __attribute__ ((unused)),
dtb = grub_file_open (argv[0]);
if (!dtb)
- goto out;
+ return grub_errno;
size = grub_file_size (dtb);
if (size == 0)
- {
- grub_error (GRUB_ERR_BAD_OS, "empty file");
- goto out;
- }
-
-#ifdef GRUB_MACHINE_EFI
- fdt_addr = grub_efi_allocate_loader_memory (LINUX_FDT_PHYS_OFFSET, size);
- if (!fdt_addr)
- {
- grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
- goto out;
- }
-#else
- fdt_addr = (void *) LINUX_FDT_ADDRESS;
-#endif
-
- grub_dprintf ("loader", "Loading device tree to 0x%08x\n",
- (grub_addr_t) fdt_addr);
- load_dtb (dtb, size);
- if (grub_errno != GRUB_ERR_NONE)
- {
- fdt_addr = NULL;
- goto out;
- }
-
- /*
- * We've successfully loaded an FDT, so any machine type passed
- * from firmware is now obsolete.
- */
- machine_type = GRUB_ARM_MACHINE_TYPE_FDT;
-
- out:
+ grub_error (GRUB_ERR_BAD_OS, "empty file");
+ else
+ load_dtb (dtb, size);
grub_file_close (dtb);
return grub_errno;
@@ -517,7 +493,7 @@ GRUB_MOD_INIT (linux)
/* TRANSLATORS: DTB stands for device tree blob. */
0, N_("Load DTB file."));
my_mod = mod;
- fdt_addr = (void *) grub_arm_firmware_get_boot_data ();
+ current_fdt = (const void *) grub_arm_firmware_get_boot_data ();
machine_type = grub_arm_firmware_get_machine_type ();
}
diff --git a/grub-core/loader/arm64/linux.c b/grub-core/loader/arm64/linux.c
index 9519d2e4d3ec1229a76eb4bce773c78c7af24a6e..1f86229f86b01e4700bb13c9f936490ea9ac859f 100644
--- a/grub-core/loader/arm64/linux.c
+++ b/grub-core/loader/arm64/linux.c
@@ -26,8 +26,9 @@
#include
#include
#include
-#include
#include
+#include
+#include
#include
#include
#include
@@ -47,18 +48,16 @@ static grub_addr_t initrd_start;
static grub_addr_t initrd_end;
grub_err_t
-grub_arm64_uefi_check_image (struct grub_arm64_linux_kernel_header * lh)
+grub_armxx_efi_linux_check_image (struct linux_armxx_kernel_header * lh)
{
- if (lh->magic != GRUB_ARM64_LINUX_MAGIC)
+ if (lh->magic != GRUB_LINUX_ARMXX_MAGIC_SIGNATURE)
return grub_error(GRUB_ERR_BAD_OS, "invalid magic number");
- if ((lh->code0 & 0xffff) != GRUB_EFI_PE_MAGIC)
+ if ((lh->code0 & 0xffff) != GRUB_PE32_MAGIC)
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
N_("plain image kernel not supported - rebuild with CONFIG_(U)EFI_STUB enabled"));
grub_dprintf ("linux", "UEFI stub kernel:\n");
- grub_dprintf ("linux", "text_offset = 0x%012llx\n",
- (long long unsigned) lh->text_offset);
grub_dprintf ("linux", "PE/COFF header @ %08x\n", lh->hdr_offset);
return GRUB_ERR_NONE;
@@ -86,8 +85,8 @@ finalize_params_linux (void)
/* Set initrd info */
if (initrd_start && initrd_end > initrd_start)
{
- grub_dprintf ("linux", "Initrd @ 0x%012lx-0x%012lx\n",
- initrd_start, initrd_end);
+ grub_dprintf ("linux", "Initrd @ %p-%p\n",
+ (void *) initrd_start, (void *) initrd_end);
retval = grub_fdt_set_prop64 (fdt, node, "linux,initrd-start",
initrd_start);
@@ -110,7 +109,7 @@ failure:
}
grub_err_t
-grub_arm64_uefi_boot_image (grub_addr_t addr, grub_size_t size, char *args)
+grub_armxx_efi_linux_boot_image (grub_addr_t addr, grub_size_t size, char *args)
{
grub_efi_memory_mapped_device_path_t *mempath;
grub_efi_handle_t image_handle;
@@ -148,8 +147,7 @@ grub_arm64_uefi_boot_image (grub_addr_t addr, grub_size_t size, char *args)
loaded_image->load_options_size = len =
(grub_strlen (args) + 1) * sizeof (grub_efi_char16_t);
loaded_image->load_options =
- grub_efi_allocate_pages (0,
- GRUB_EFI_BYTES_TO_PAGES (loaded_image->load_options_size));
+ grub_efi_allocate_any_pages (GRUB_EFI_BYTES_TO_PAGES (loaded_image->load_options_size));
if (!loaded_image->load_options)
return grub_errno;
@@ -162,7 +160,7 @@ grub_arm64_uefi_boot_image (grub_addr_t addr, grub_size_t size, char *args)
/* When successful, not reached */
b->unload_image (image_handle);
- grub_efi_free_pages ((grub_efi_physical_address_t) loaded_image->load_options,
+ grub_efi_free_pages ((grub_addr_t) loaded_image->load_options,
GRUB_EFI_BYTES_TO_PAGES (loaded_image->load_options_size));
return grub_errno;
@@ -174,8 +172,8 @@ grub_linux_boot (void)
if (finalize_params_linux () != GRUB_ERR_NONE)
return grub_errno;
- return (grub_arm64_uefi_boot_image((grub_addr_t)kernel_addr,
- kernel_size, linux_args));
+ return (grub_armxx_efi_linux_boot_image((grub_addr_t)kernel_addr,
+ kernel_size, linux_args));
}
static grub_err_t
@@ -189,12 +187,48 @@ grub_linux_unload (void)
initrd_start = initrd_end = 0;
grub_free (linux_args);
if (kernel_addr)
- grub_efi_free_pages ((grub_efi_physical_address_t) kernel_addr,
+ grub_efi_free_pages ((grub_addr_t) kernel_addr,
GRUB_EFI_BYTES_TO_PAGES (kernel_size));
grub_fdt_unload ();
return GRUB_ERR_NONE;
}
+/*
+ * As per linux/Documentation/arm/Booting
+ * ARM initrd needs to be covered by kernel linear mapping,
+ * so place it in the first 512MB of DRAM.
+ *
+ * As per linux/Documentation/arm64/booting.txt
+ * ARM64 initrd needs to be contained entirely within a 1GB aligned window
+ * of up to 32GB of size that covers the kernel image as well.
+ * Since the EFI stub loader will attempt to load the kernel near start of
+ * RAM, place the buffer in the first 32GB of RAM.
+ */
+#ifdef __arm__
+#define INITRD_MAX_ADDRESS_OFFSET (512U * 1024 * 1024)
+#else /* __aarch64__ */
+#define INITRD_MAX_ADDRESS_OFFSET (32ULL * 1024 * 1024 * 1024)
+#endif
+
+/*
+ * This function returns a pointer to a legally allocated initrd buffer,
+ * or NULL if unsuccessful
+ */
+static void *
+allocate_initrd_mem (int initrd_pages)
+{
+ grub_addr_t max_addr;
+
+ if (grub_efi_get_ram_base (&max_addr) != GRUB_ERR_NONE)
+ return NULL;
+
+ max_addr += INITRD_MAX_ADDRESS_OFFSET - 1;
+
+ return grub_efi_allocate_pages_real (max_addr, initrd_pages,
+ GRUB_EFI_ALLOCATE_MAX_ADDRESS,
+ GRUB_EFI_LOADER_DATA);
+}
+
static grub_err_t
grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
int argc, char *argv[])
@@ -223,7 +257,8 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
grub_dprintf ("linux", "Loading initrd\n");
initrd_pages = (GRUB_EFI_BYTES_TO_PAGES (initrd_size));
- initrd_mem = grub_efi_allocate_pages (0, initrd_pages);
+ initrd_mem = allocate_initrd_mem (initrd_pages);
+
if (!initrd_mem)
{
grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
@@ -241,8 +276,7 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
fail:
grub_initrd_close (&initrd_ctx);
if (initrd_mem && !initrd_start)
- grub_efi_free_pages ((grub_efi_physical_address_t) initrd_mem,
- initrd_pages);
+ grub_efi_free_pages ((grub_addr_t) initrd_mem, initrd_pages);
return grub_errno;
}
@@ -252,7 +286,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
int argc, char *argv[])
{
grub_file_t file = 0;
- struct grub_arm64_linux_kernel_header lh;
+ struct linux_armxx_kernel_header lh;
grub_dl_ref (my_mod);
@@ -271,13 +305,13 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
if (grub_file_read (file, &lh, sizeof (lh)) < (long) sizeof (lh))
return grub_errno;
- if (grub_arm64_uefi_check_image (&lh) != GRUB_ERR_NONE)
+ if (grub_armxx_efi_linux_check_image (&lh) != GRUB_ERR_NONE)
goto fail;
grub_loader_unset();
grub_dprintf ("linux", "kernel file size: %lld\n", (long long) kernel_size);
- kernel_addr = grub_efi_allocate_pages (0, GRUB_EFI_BYTES_TO_PAGES (kernel_size));
+ kernel_addr = grub_efi_allocate_any_pages (GRUB_EFI_BYTES_TO_PAGES (kernel_size));
grub_dprintf ("linux", "kernel numpages: %lld\n",
(long long) GRUB_EFI_BYTES_TO_PAGES (kernel_size));
if (!kernel_addr)
@@ -329,7 +363,7 @@ fail:
grub_free (linux_args);
if (kernel_addr && !loaded)
- grub_efi_free_pages ((grub_efi_physical_address_t) kernel_addr,
+ grub_efi_free_pages ((grub_addr_t) kernel_addr,
GRUB_EFI_BYTES_TO_PAGES (kernel_size));
return grub_errno;
diff --git a/grub-core/loader/arm64/xen_boot.c b/grub-core/loader/arm64/xen_boot.c
index a914eb8e2df24ebaab41a2eb0ed205bcebafcf5d..1003a0b9997a46ea7e5106da02ef77e9be3a21fc 100644
--- a/grub-core/loader/arm64/xen_boot.c
+++ b/grub-core/loader/arm64/xen_boot.c
@@ -27,9 +27,10 @@
#include
#include
#include
-#include
#include
#include
+#include
+#include
#include /* required by struct xen_hypervisor_header */
#include
#include
@@ -66,7 +67,7 @@ typedef enum module_type module_type_t;
struct xen_hypervisor_header
{
- struct grub_arm64_linux_kernel_header efi_head;
+ struct linux_arm64_kernel_header efi_head;
/* This is always PE\0\0. */
grub_uint8_t signature[GRUB_PE32_SIGNATURE_SIZE];
@@ -115,6 +116,17 @@ prepare_xen_hypervisor_params (void *xen_boot_fdt)
if (chosen_node < 1)
return grub_error (GRUB_ERR_IO, "failed to get chosen node in FDT");
+ /*
+ * The address and size are always written using 64-bits value. Set
+ * #address-cells and #size-cells accordingly.
+ */
+ retval = grub_fdt_set_prop32 (xen_boot_fdt, chosen_node, "#address-cells", 2);
+ if (retval)
+ return grub_error (GRUB_ERR_IO, "failed to set #address-cells");
+ retval = grub_fdt_set_prop32 (xen_boot_fdt, chosen_node, "#size-cells", 2);
+ if (retval)
+ return grub_error (GRUB_ERR_IO, "failed to set #size-cells");
+
grub_dprintf ("xen_loader",
"Xen Hypervisor cmdline : %s @ %p size:%d\n",
xen_hypervisor->cmdline, xen_hypervisor->cmdline,
@@ -156,7 +168,7 @@ prepare_xen_module_params (struct xen_boot_binary *module, void *xen_boot_fdt)
grub_fdt_add_subnode (xen_boot_fdt, chosen_node, module_name);
retval = grub_fdt_set_prop (xen_boot_fdt, module_node, "compatible",
- MODULE_CUSTOM_COMPATIBLE, sizeof(MODULE_CUSTOM_COMPATIBLE) - 1);
+ MODULE_CUSTOM_COMPATIBLE, sizeof(MODULE_CUSTOM_COMPATIBLE));
if (retval)
return grub_error (GRUB_ERR_IO, "failed to update FDT");
@@ -253,9 +265,9 @@ xen_boot (void)
if (err)
return err;
- return grub_arm64_uefi_boot_image (xen_hypervisor->start,
- xen_hypervisor->size,
- xen_hypervisor->cmdline);
+ return grub_armxx_efi_linux_boot_image (xen_hypervisor->start,
+ xen_hypervisor->size,
+ xen_hypervisor->cmdline);
}
static void
@@ -324,10 +336,9 @@ xen_boot_binary_load (struct xen_boot_binary *binary, grub_file_t file,
grub_dprintf ("xen_loader", "Xen_boot file size: 0x%lx\n", binary->size);
binary->start
- = (grub_addr_t) grub_efi_allocate_pages (0,
- GRUB_EFI_BYTES_TO_PAGES
- (binary->size +
- binary->align));
+ = (grub_addr_t) grub_efi_allocate_any_pages (GRUB_EFI_BYTES_TO_PAGES
+ (binary->size +
+ binary->align));
if (!binary->start)
{
grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
@@ -379,6 +390,20 @@ grub_cmd_xen_module (grub_command_t cmd __attribute__((unused)),
struct xen_boot_binary *module = NULL;
grub_file_t file = 0;
+ int nounzip = 0;
+
+ if (!argc)
+ {
+ grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
+ goto fail;
+ }
+
+ if (grub_strcmp (argv[0], "--nounzip") == 0)
+ {
+ argv++;
+ argc--;
+ nounzip = 1;
+ }
if (!argc)
{
@@ -403,6 +428,8 @@ grub_cmd_xen_module (grub_command_t cmd __attribute__((unused)),
grub_dprintf ("xen_loader", "Init module and node info\n");
+ if (nounzip)
+ grub_file_filter_disable_compression ();
file = grub_file_open (argv[0]);
if (!file)
goto fail;
@@ -441,8 +468,8 @@ grub_cmd_xen_hypervisor (grub_command_t cmd __attribute__ ((unused)),
if (grub_file_read (file, &sh, sizeof (sh)) != (long) sizeof (sh))
goto fail;
- if (grub_arm64_uefi_check_image
- ((struct grub_arm64_linux_kernel_header *) &sh) != GRUB_ERR_NONE)
+ if (grub_armxx_efi_linux_check_image
+ ((struct linux_armxx_kernel_header *) &sh) != GRUB_ERR_NONE)
goto fail;
grub_file_seek (file, 0);
diff --git a/grub-core/loader/arm64/fdt.c b/grub-core/loader/efi/fdt.c
similarity index 79%
rename from grub-core/loader/arm64/fdt.c
rename to grub-core/loader/efi/fdt.c
index db49cf64991764686c3f643e5289abbd4874a559..a4c6e8036454c1a53deefad791133488281462ea 100644
--- a/grub-core/loader/arm64/fdt.c
+++ b/grub-core/loader/efi/fdt.c
@@ -18,26 +18,33 @@
#include
#include
-#include
#include
#include
#include
#include
#include
+#include
+#include
static void *loaded_fdt;
static void *fdt;
+#define FDT_ADDR_CELLS_STRING "#address-cells"
+#define FDT_SIZE_CELLS_STRING "#size-cells"
+#define FDT_ADDR_SIZE_EXTRA ((2 * grub_fdt_prop_entry_size (sizeof(grub_uint32_t))) + \
+ sizeof (FDT_ADDR_CELLS_STRING) + \
+ sizeof (FDT_SIZE_CELLS_STRING))
+
void *
grub_fdt_load (grub_size_t additional_size)
{
void *raw_fdt;
- grub_size_t size;
+ unsigned int size;
if (fdt)
{
size = GRUB_EFI_BYTES_TO_PAGES (grub_fdt_get_totalsize (fdt));
- grub_efi_free_pages ((grub_efi_physical_address_t) fdt, size);
+ grub_efi_free_pages ((grub_addr_t) fdt, size);
}
if (loaded_fdt)
@@ -45,12 +52,15 @@ grub_fdt_load (grub_size_t additional_size)
else
raw_fdt = grub_efi_get_firmware_fdt();
- size =
- raw_fdt ? grub_fdt_get_totalsize (raw_fdt) : GRUB_FDT_EMPTY_TREE_SZ;
+ if (raw_fdt)
+ size = grub_fdt_get_totalsize (raw_fdt);
+ else
+ size = GRUB_FDT_EMPTY_TREE_SZ + FDT_ADDR_SIZE_EXTRA;
+
size += additional_size;
- grub_dprintf ("linux", "allocating %ld bytes for fdt\n", size);
- fdt = grub_efi_allocate_pages (0, GRUB_EFI_BYTES_TO_PAGES (size));
+ grub_dprintf ("linux", "allocating %d bytes for fdt\n", size);
+ fdt = grub_efi_allocate_any_pages (GRUB_EFI_BYTES_TO_PAGES (size));
if (!fdt)
return NULL;
@@ -62,6 +72,8 @@ grub_fdt_load (grub_size_t additional_size)
else
{
grub_fdt_create_empty_tree (fdt, size);
+ grub_fdt_set_prop32 (fdt, 0, FDT_ADDR_CELLS_STRING, 2);
+ grub_fdt_set_prop32 (fdt, 0, FDT_SIZE_CELLS_STRING, 2);
}
return fdt;
}
@@ -88,7 +100,7 @@ grub_fdt_unload (void) {
if (!fdt) {
return;
}
- grub_efi_free_pages ((grub_efi_physical_address_t) fdt,
+ grub_efi_free_pages ((grub_addr_t) fdt,
GRUB_EFI_BYTES_TO_PAGES (grub_fdt_get_totalsize (fdt)));
fdt = NULL;
}
diff --git a/grub-core/loader/i386/linux.c b/grub-core/loader/i386/linux.c
index 083f9417cb65e509e673dba09a71616c5661ab05..9b53d3168f9bb78eab7a124518e83915183912b9 100644
--- a/grub-core/loader/i386/linux.c
+++ b/grub-core/loader/i386/linux.c
@@ -306,6 +306,12 @@ grub_linux_setup_video (struct linux_kernel_params *params)
params->lfb_line_len = mode_info.pitch;
params->lfb_base = (grub_size_t) framebuffer;
+
+#if defined (GRUB_MACHINE_EFI) && defined (__x86_64__)
+ params->ext_lfb_base = (grub_size_t) (((grub_uint64_t)(grub_size_t) framebuffer) >> 32);
+ params->capabilities |= VIDEO_CAPABILITY_64BIT_BASE;
+#endif
+
params->lfb_size = ALIGN_UP (params->lfb_line_len * params->lfb_height, 65536);
params->red_mask_size = mode_info.red_mask_size;
@@ -678,7 +684,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
int argc, char *argv[])
{
grub_file_t file = 0;
- struct linux_kernel_header lh;
+ struct linux_i386_kernel_header lh;
grub_uint8_t setup_sects;
grub_size_t real_size, prot_size, prot_file_size;
grub_ssize_t len;
@@ -721,7 +727,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
/* FIXME: 2.03 is not always good enough (Linux 2.4 can be 2.03 and
still not support 32-bit boot. */
- if (lh.header != grub_cpu_to_le32_compile_time (GRUB_LINUX_MAGIC_SIGNATURE)
+ if (lh.header != grub_cpu_to_le32_compile_time (GRUB_LINUX_I386_MAGIC_SIGNATURE)
|| grub_le_to_cpu16 (lh.version) < 0x0203)
{
grub_error (GRUB_ERR_BAD_OS, "version too old for 32-bit boot"
diff --git a/grub-core/loader/i386/multiboot_mbi.c b/grub-core/loader/i386/multiboot_mbi.c
index fd7b41b0cad4f26d1170d70692ac1ac27fd6bd73..dc98dbcae258b340e155c64f1f73213ac724806a 100644
--- a/grub-core/loader/i386/multiboot_mbi.c
+++ b/grub-core/loader/i386/multiboot_mbi.c
@@ -239,7 +239,7 @@ grub_multiboot_get_mbi_size (void)
ret = sizeof (struct multiboot_info) + ALIGN_UP (cmdline_size, 4)
+ modcnt * sizeof (struct multiboot_mod_list) + total_modcmd
+ ALIGN_UP (sizeof(PACKAGE_STRING), 4)
- + grub_get_multiboot_mmap_count () * sizeof (struct multiboot_mmap_entry)
+ + grub_multiboot_get_mmap_count () * sizeof (struct multiboot_mmap_entry)
+ elf_sec_entsize * elf_sec_num
+ 256 * sizeof (struct multiboot_color)
#if GRUB_MACHINE_HAS_VBE || GRUB_MACHINE_HAS_VGA_TEXT
@@ -542,7 +542,7 @@ grub_multiboot_make_mbi (grub_uint32_t *target)
mbi->mods_count = 0;
}
- mmap_size = grub_get_multiboot_mmap_count ()
+ mmap_size = grub_multiboot_get_mmap_count ()
* sizeof (struct multiboot_mmap_entry);
grub_fill_multiboot_mmap ((struct multiboot_mmap_entry *) ptrorig);
mbi->mmap_length = mmap_size;
diff --git a/grub-core/loader/i386/pc/chainloader.c b/grub-core/loader/i386/pc/chainloader.c
index c79c4fe0fc99a876b3e92f0a24f16cd636e00a0d..ef3a322b78cf10a406c0420780f821e2e1d1b284 100644
--- a/grub-core/loader/i386/pc/chainloader.c
+++ b/grub-core/loader/i386/pc/chainloader.c
@@ -19,6 +19,7 @@
#include
#include
+#include
#include
#include
#include
@@ -86,9 +87,16 @@ grub_chainloader_unload (void)
void
grub_chainloader_patch_bpb (void *bs, grub_device_t dev, grub_uint8_t dl)
{
- grub_uint32_t part_start = 0;
+ grub_uint32_t part_start = 0, heads = 0, sectors = 0;
if (dev && dev->disk)
- part_start = grub_partition_get_start (dev->disk->partition);
+ {
+ part_start = grub_partition_get_start (dev->disk->partition);
+ if (dev->disk->data)
+ {
+ heads = ((struct grub_biosdisk_data *)(dev->disk->data))->heads;
+ sectors = ((struct grub_biosdisk_data *)(dev->disk->data))->sectors;
+ }
+ }
if (grub_memcmp ((char *) &((struct grub_ntfs_bpb *) bs)->oem_name,
"NTFS", 4) == 0)
{
@@ -117,7 +125,7 @@ grub_chainloader_patch_bpb (void *bs, grub_device_t dev, grub_uint8_t dl)
if (bpb->num_reserved_sectors == 0)
break;
- if (bpb->num_total_sectors_16 == 0 || bpb->num_total_sectors_32 == 0)
+ if (bpb->num_total_sectors_16 == 0 && bpb->num_total_sectors_32 == 0)
break;
if (bpb->num_fats == 0)
@@ -127,12 +135,20 @@ grub_chainloader_patch_bpb (void *bs, grub_device_t dev, grub_uint8_t dl)
{
bpb->num_hidden_sectors = grub_cpu_to_le32 (part_start);
bpb->version_specific.fat12_or_fat16.num_ph_drive = dl;
+ if (sectors)
+ bpb->sectors_per_track = grub_cpu_to_le16 (sectors);
+ if (heads)
+ bpb->num_heads = grub_cpu_to_le16 (heads);
return;
}
if (bpb->version_specific.fat32.sectors_per_fat_32)
{
bpb->num_hidden_sectors = grub_cpu_to_le32 (part_start);
bpb->version_specific.fat32.num_ph_drive = dl;
+ if (sectors)
+ bpb->sectors_per_track = grub_cpu_to_le16 (sectors);
+ if (heads)
+ bpb->num_heads = grub_cpu_to_le16 (heads);
return;
}
break;
diff --git a/grub-core/loader/i386/pc/linux.c b/grub-core/loader/i386/pc/linux.c
index a293b17aa101b308635bbed4086ae1547b91b884..b69cb7a3a7f8a9ca96a91a78c47fa1515e628699 100644
--- a/grub-core/loader/i386/pc/linux.c
+++ b/grub-core/loader/i386/pc/linux.c
@@ -121,7 +121,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
int argc, char *argv[])
{
grub_file_t file = 0;
- struct linux_kernel_header lh;
+ struct linux_i386_kernel_header lh;
grub_uint8_t setup_sects;
grub_size_t real_size;
grub_ssize_t len;
@@ -169,7 +169,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
maximal_cmdline_size = 256;
- if (lh.header == grub_cpu_to_le32_compile_time (GRUB_LINUX_MAGIC_SIGNATURE)
+ if (lh.header == grub_cpu_to_le32_compile_time (GRUB_LINUX_I386_MAGIC_SIGNATURE)
&& grub_le_to_cpu16 (lh.version) >= 0x0200)
{
grub_linux_is_bzimage = (lh.loadflags & GRUB_LINUX_FLAG_BIG_KERNEL);
@@ -322,7 +322,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
goto fail;
}
- if (lh.header != grub_cpu_to_le32_compile_time (GRUB_LINUX_MAGIC_SIGNATURE)
+ if (lh.header != grub_cpu_to_le32_compile_time (GRUB_LINUX_I386_MAGIC_SIGNATURE)
|| grub_le_to_cpu16 (lh.version) < 0x0200)
/* Clear the heap space. */
grub_memset (grub_linux_real_chunk
@@ -387,7 +387,7 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
{
grub_size_t size = 0;
grub_addr_t addr_max, addr_min;
- struct linux_kernel_header *lh;
+ struct linux_i386_kernel_header *lh;
grub_uint8_t *initrd_chunk;
grub_addr_t initrd_addr;
grub_err_t err;
@@ -405,9 +405,9 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
goto fail;
}
- lh = (struct linux_kernel_header *) grub_linux_real_chunk;
+ lh = (struct linux_i386_kernel_header *) grub_linux_real_chunk;
- if (!(lh->header == grub_cpu_to_le32_compile_time (GRUB_LINUX_MAGIC_SIGNATURE)
+ if (!(lh->header == grub_cpu_to_le32_compile_time (GRUB_LINUX_I386_MAGIC_SIGNATURE)
&& grub_le_to_cpu16 (lh->version) >= 0x0200))
{
grub_error (GRUB_ERR_BAD_OS, "the kernel is too old for initrd");
diff --git a/grub-core/loader/i386/xen_file.c b/grub-core/loader/i386/xen_file.c
index 99fad4cadae42ab09497babca15cd9606557fcd2..77a93e7b228316e1df731e01e51e67f9225b4482 100644
--- a/grub-core/loader/i386/xen_file.c
+++ b/grub-core/loader/i386/xen_file.c
@@ -26,7 +26,7 @@ grub_elf_t
grub_xen_file (grub_file_t file)
{
grub_elf_t elf;
- struct linux_kernel_header lh;
+ struct linux_i386_kernel_header lh;
grub_file_t off_file;
grub_uint32_t payload_offset, payload_length;
grub_uint8_t magic[6];
@@ -43,7 +43,7 @@ grub_xen_file (grub_file_t file)
goto fail;
if (lh.boot_flag != grub_cpu_to_le16_compile_time (0xaa55)
- || lh.header != grub_cpu_to_le32_compile_time (GRUB_LINUX_MAGIC_SIGNATURE)
+ || lh.header != grub_cpu_to_le32_compile_time (GRUB_LINUX_I386_MAGIC_SIGNATURE)
|| grub_le_to_cpu16 (lh.version) < 0x0208)
{
grub_error (GRUB_ERR_BAD_OS, "version too old for xen boot");
diff --git a/grub-core/loader/ia64/efi/linux.c b/grub-core/loader/ia64/efi/linux.c
index efaa42ccdd2bf74321de20cf5033a80676cc7dc3..750330d4572d0dcd09d02b4b75c1f03045fa897b 100644
--- a/grub-core/loader/ia64/efi/linux.c
+++ b/grub-core/loader/ia64/efi/linux.c
@@ -252,7 +252,7 @@ allocate_pages (grub_uint64_t align, grub_uint64_t size_pages,
aligned_start += align;
if (aligned_start + size > end)
continue;
- mem = grub_efi_allocate_pages (aligned_start, size_pages);
+ mem = grub_efi_allocate_fixed (aligned_start, size_pages);
if (! mem)
{
grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate memory");
@@ -326,7 +326,7 @@ grub_linux_boot (void)
mmap_size = find_mmap_size ();
if (! mmap_size)
return grub_errno;
- mmap_buf = grub_efi_allocate_pages (0, page_align (mmap_size) >> 12);
+ mmap_buf = grub_efi_allocate_any_pages (page_align (mmap_size) >> 12);
if (! mmap_buf)
return grub_error (GRUB_ERR_IO, "cannot allocate memory map");
err = grub_efi_finish_boot_services (&mmap_size, mmap_buf, &map_key,
@@ -422,7 +422,7 @@ grub_load_elf64 (grub_file_t file, void *buffer, const char *filename)
relocate = grub_env_get ("linux_relocate");
if (!relocate || grub_strcmp (relocate, "force") != 0)
{
- kernel_mem = grub_efi_allocate_pages (low_addr, kernel_pages);
+ kernel_mem = grub_efi_allocate_fixed (low_addr, kernel_pages);
reloc_offset = 0;
}
/* Try to relocate. */
@@ -524,7 +524,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
len += grub_strlen (argv[i]) + 1;
len += sizeof (struct ia64_boot_param) + 512; /* Room for extensions. */
boot_param_pages = page_align (len) >> 12;
- boot_param = grub_efi_allocate_pages (0, boot_param_pages);
+ boot_param = grub_efi_allocate_any_pages (boot_param_pages);
if (boot_param == 0)
{
grub_error (GRUB_ERR_OUT_OF_MEMORY,
@@ -589,7 +589,7 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
grub_dprintf ("linux", "Loading initrd\n");
initrd_pages = (page_align (initrd_size) >> 12);
- initrd_mem = grub_efi_allocate_pages (0, initrd_pages);
+ initrd_mem = grub_efi_allocate_any_pages (initrd_pages);
if (! initrd_mem)
{
grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate pages");
diff --git a/grub-core/loader/multiboot.c b/grub-core/loader/multiboot.c
index bd9d5b3e698588db594a2c334d715e0e883bab92..40c67e82489ec3ecf891ae564cde810bf280b242 100644
--- a/grub-core/loader/multiboot.c
+++ b/grub-core/loader/multiboot.c
@@ -28,7 +28,15 @@
#include
#include
+#ifdef GRUB_USE_MULTIBOOT2
+#include
+#define GRUB_MULTIBOOT_CONSOLE_FRAMEBUFFER GRUB_MULTIBOOT2_CONSOLE_FRAMEBUFFER
+#define GRUB_MULTIBOOT_CONSOLE_EGA_TEXT GRUB_MULTIBOOT2_CONSOLE_EGA_TEXT
+#define GRUB_MULTIBOOT(x) grub_multiboot2_ ## x
+#else
#include
+#define GRUB_MULTIBOOT(x) grub_multiboot_ ## x
+#endif
#include
#include
#include
@@ -49,8 +57,8 @@ GRUB_MOD_LICENSE ("GPLv3+");
#include
#endif
-struct grub_relocator *grub_multiboot_relocator = NULL;
-grub_uint32_t grub_multiboot_payload_eip;
+struct grub_relocator *GRUB_MULTIBOOT (relocator) = NULL;
+grub_uint32_t GRUB_MULTIBOOT (payload_eip);
#if defined (GRUB_MACHINE_PCBIOS) || defined (GRUB_MACHINE_MULTIBOOT) || defined (GRUB_MACHINE_COREBOOT) || defined (GRUB_MACHINE_QEMU)
#define DEFAULT_VIDEO_MODE "text"
#else
@@ -78,7 +86,7 @@ count_hook (grub_uint64_t addr __attribute__ ((unused)),
/* Return the length of the Multiboot mmap that will be needed to allocate
our platform's map. */
grub_uint32_t
-grub_get_multiboot_mmap_count (void)
+GRUB_MULTIBOOT (get_mmap_count) (void)
{
grub_size_t count = 0;
@@ -88,7 +96,7 @@ grub_get_multiboot_mmap_count (void)
}
grub_err_t
-grub_multiboot_set_video_mode (void)
+GRUB_MULTIBOOT (set_video_mode) (void)
{
grub_err_t err;
const char *modevar;
@@ -130,9 +138,12 @@ static void
efi_boot (struct grub_relocator *rel,
grub_uint32_t target)
{
+#ifdef GRUB_USE_MULTIBOOT2
+ struct grub_relocator_efi_state state_efi = MULTIBOOT2_EFI_INITIAL_STATE;
+#else
struct grub_relocator_efi_state state_efi = MULTIBOOT_EFI_INITIAL_STATE;
-
- state_efi.MULTIBOOT_EFI_ENTRY_REGISTER = grub_multiboot_payload_eip;
+#endif
+ state_efi.MULTIBOOT_EFI_ENTRY_REGISTER = GRUB_MULTIBOOT (payload_eip);
state_efi.MULTIBOOT_EFI_MBI_REGISTER = target;
grub_relocator_efi_boot (rel, state_efi);
@@ -164,19 +175,23 @@ static grub_err_t
grub_multiboot_boot (void)
{
grub_err_t err;
+
+#ifdef GRUB_USE_MULTIBOOT2
+ struct grub_relocator32_state state = MULTIBOOT2_INITIAL_STATE;
+#else
struct grub_relocator32_state state = MULTIBOOT_INITIAL_STATE;
+#endif
+ state.MULTIBOOT_ENTRY_REGISTER = GRUB_MULTIBOOT (payload_eip);
- state.MULTIBOOT_ENTRY_REGISTER = grub_multiboot_payload_eip;
-
- err = grub_multiboot_make_mbi (&state.MULTIBOOT_MBI_REGISTER);
+ err = GRUB_MULTIBOOT (make_mbi) (&state.MULTIBOOT_MBI_REGISTER);
if (err)
return err;
if (grub_efi_is_finished)
- normal_boot (grub_multiboot_relocator, state);
+ normal_boot (GRUB_MULTIBOOT (relocator), state);
else
- efi_boot (grub_multiboot_relocator, state.MULTIBOOT_MBI_REGISTER);
+ efi_boot (GRUB_MULTIBOOT (relocator), state.MULTIBOOT_MBI_REGISTER);
/* Not reached. */
return GRUB_ERR_NONE;
@@ -185,10 +200,10 @@ grub_multiboot_boot (void)
static grub_err_t
grub_multiboot_unload (void)
{
- grub_multiboot_free_mbi ();
+ GRUB_MULTIBOOT (free_mbi) ();
- grub_relocator_unload (grub_multiboot_relocator);
- grub_multiboot_relocator = NULL;
+ grub_relocator_unload (GRUB_MULTIBOOT (relocator));
+ GRUB_MULTIBOOT (relocator) = NULL;
grub_dl_unref (my_mod);
@@ -207,7 +222,7 @@ static grub_uint64_t highest_load;
/* Load ELF32 or ELF64. */
grub_err_t
-grub_multiboot_load_elf (mbi_load_data_t *mld)
+GRUB_MULTIBOOT (load_elf) (mbi_load_data_t *mld)
{
if (grub_multiboot_is_elf32 (mld->buffer))
return grub_multiboot_load_elf32 (mld);
@@ -218,9 +233,9 @@ grub_multiboot_load_elf (mbi_load_data_t *mld)
}
grub_err_t
-grub_multiboot_set_console (int console_type, int accepted_consoles,
- int width, int height, int depth,
- int console_req)
+GRUB_MULTIBOOT (set_console) (int console_type, int accepted_consoles,
+ int width, int height, int depth,
+ int console_req)
{
console_required = console_req;
if (!(accepted_consoles
@@ -313,19 +328,19 @@ grub_cmd_multiboot (grub_command_t cmd __attribute__ ((unused)),
grub_dl_ref (my_mod);
/* Skip filename. */
- grub_multiboot_init_mbi (argc - 1, argv + 1);
+ GRUB_MULTIBOOT (init_mbi) (argc - 1, argv + 1);
- grub_relocator_unload (grub_multiboot_relocator);
- grub_multiboot_relocator = grub_relocator_new ();
+ grub_relocator_unload (GRUB_MULTIBOOT (relocator));
+ GRUB_MULTIBOOT (relocator) = grub_relocator_new ();
- if (!grub_multiboot_relocator)
+ if (!GRUB_MULTIBOOT (relocator))
goto fail;
- err = grub_multiboot_load (file, argv[0]);
+ err = GRUB_MULTIBOOT (load) (file, argv[0]);
if (err)
goto fail;
- grub_multiboot_set_bootdev ();
+ GRUB_MULTIBOOT (set_bootdev) ();
grub_loader_set (grub_multiboot_boot, grub_multiboot_unload, 0);
@@ -335,8 +350,8 @@ grub_cmd_multiboot (grub_command_t cmd __attribute__ ((unused)),
if (grub_errno != GRUB_ERR_NONE)
{
- grub_relocator_unload (grub_multiboot_relocator);
- grub_multiboot_relocator = NULL;
+ grub_relocator_unload (GRUB_MULTIBOOT (relocator));
+ GRUB_MULTIBOOT (relocator) = NULL;
grub_dl_unref (my_mod);
}
@@ -368,7 +383,7 @@ grub_cmd_module (grub_command_t cmd __attribute__ ((unused)),
if (argc == 0)
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
- if (!grub_multiboot_relocator)
+ if (!GRUB_MULTIBOOT (relocator))
return grub_error (GRUB_ERR_BAD_ARGUMENT,
N_("you need to load the kernel first"));
@@ -389,7 +404,7 @@ grub_cmd_module (grub_command_t cmd __attribute__ ((unused)),
if (size)
{
grub_relocator_chunk_t ch;
- err = grub_relocator_alloc_chunk_align (grub_multiboot_relocator, &ch,
+ err = grub_relocator_alloc_chunk_align (GRUB_MULTIBOOT (relocator), &ch,
lowest_addr, (0xffffffff - size) + 1,
size, MULTIBOOT_MOD_ALIGN,
GRUB_RELOCATOR_PREFERENCE_NONE, 1);
@@ -407,7 +422,7 @@ grub_cmd_module (grub_command_t cmd __attribute__ ((unused)),
target = 0;
}
- err = grub_multiboot_add_module (target, size, argc - 1, argv + 1);
+ err = GRUB_MULTIBOOT (add_module) (target, size, argc - 1, argv + 1);
if (err)
{
grub_file_close (file);
diff --git a/grub-core/loader/multiboot_elfxx.c b/grub-core/loader/multiboot_elfxx.c
index 5e649ed2545bee3fbe9602c9d97079160dc6420a..70cd1db513e679f0e02e06dc2de24747a62b88ba 100644
--- a/grub-core/loader/multiboot_elfxx.c
+++ b/grub-core/loader/multiboot_elfxx.c
@@ -57,9 +57,9 @@ CONCAT(grub_multiboot_load_elf, XX) (mbi_load_data_t *mld)
char *phdr_base;
grub_err_t err;
grub_relocator_chunk_t ch;
- grub_uint32_t load_offset, load_size;
+ grub_uint32_t load_offset = 0, load_size;
int i;
- void *source;
+ void *source = NULL;
if (ehdr->e_ident[EI_MAG0] != ELFMAG0
|| ehdr->e_ident[EI_MAG1] != ELFMAG1
@@ -97,38 +97,38 @@ CONCAT(grub_multiboot_load_elf, XX) (mbi_load_data_t *mld)
return grub_error (GRUB_ERR_BAD_OS, "segment crosses 4 GiB border");
#endif
- load_size = highest_load - mld->link_base_addr;
-
if (mld->relocatable)
{
+ load_size = highest_load - mld->link_base_addr;
+
+ grub_dprintf ("multiboot_loader", "align=0x%lx, preference=0x%x, "
+ "load_size=0x%x, avoid_efi_boot_services=%d\n",
+ (long) mld->align, mld->preference, load_size,
+ mld->avoid_efi_boot_services);
+
if (load_size > mld->max_addr || mld->min_addr > mld->max_addr - load_size)
return grub_error (GRUB_ERR_BAD_OS, "invalid min/max address and/or load size");
- err = grub_relocator_alloc_chunk_align (grub_multiboot_relocator, &ch,
+ err = grub_relocator_alloc_chunk_align (GRUB_MULTIBOOT (relocator), &ch,
mld->min_addr, mld->max_addr - load_size,
load_size, mld->align ? mld->align : 1,
mld->preference, mld->avoid_efi_boot_services);
+
+ if (err)
+ {
+ grub_dprintf ("multiboot_loader", "Cannot allocate memory for OS image\n");
+ return err;
+ }
+
+ mld->load_base_addr = get_physical_target_address (ch);
+ source = get_virtual_current_address (ch);
}
else
- err = grub_relocator_alloc_chunk_addr (grub_multiboot_relocator, &ch,
- mld->link_base_addr, load_size);
+ mld->load_base_addr = mld->link_base_addr;
- if (err)
- {
- grub_dprintf ("multiboot_loader", "Cannot allocate memory for OS image\n");
- return err;
- }
-
- mld->load_base_addr = get_physical_target_address (ch);
- source = get_virtual_current_address (ch);
-
- grub_dprintf ("multiboot_loader", "link_base_addr=0x%x, load_base_addr=0x%x, "
- "load_size=0x%x, relocatable=%d\n", mld->link_base_addr,
- mld->load_base_addr, load_size, mld->relocatable);
-
- if (mld->relocatable)
- grub_dprintf ("multiboot_loader", "align=0x%lx, preference=0x%x, avoid_efi_boot_services=%d\n",
- (long) mld->align, mld->preference, mld->avoid_efi_boot_services);
+ grub_dprintf ("multiboot_loader", "relocatable=%d, link_base_addr=0x%x, "
+ "load_base_addr=0x%x\n", mld->relocatable,
+ mld->link_base_addr, mld->load_base_addr);
/* Load every loadable segment in memory. */
for (i = 0; i < ehdr->e_phnum; i++)
@@ -139,7 +139,24 @@ CONCAT(grub_multiboot_load_elf, XX) (mbi_load_data_t *mld)
grub_dprintf ("multiboot_loader", "segment %d: paddr=0x%lx, memsz=0x%lx, vaddr=0x%lx\n",
i, (long) phdr(i)->p_paddr, (long) phdr(i)->p_memsz, (long) phdr(i)->p_vaddr);
- load_offset = phdr(i)->p_paddr - mld->link_base_addr;
+ if (mld->relocatable)
+ {
+ load_offset = phdr(i)->p_paddr - mld->link_base_addr;
+ grub_dprintf ("multiboot_loader", "segment %d: load_offset=0x%x\n", i, load_offset);
+ }
+ else
+ {
+ err = grub_relocator_alloc_chunk_addr (GRUB_MULTIBOOT (relocator), &ch,
+ phdr(i)->p_paddr, phdr(i)->p_memsz);
+
+ if (err)
+ {
+ grub_dprintf ("multiboot_loader", "Cannot allocate memory for OS image\n");
+ return err;
+ }
+
+ source = get_virtual_current_address (ch);
+ }
if (phdr(i)->p_filesz != 0)
{
@@ -167,7 +184,7 @@ CONCAT(grub_multiboot_load_elf, XX) (mbi_load_data_t *mld)
if (phdr(i)->p_vaddr <= ehdr->e_entry
&& phdr(i)->p_vaddr + phdr(i)->p_memsz > ehdr->e_entry)
{
- grub_multiboot_payload_eip = (ehdr->e_entry - phdr(i)->p_vaddr)
+ GRUB_MULTIBOOT (payload_eip) = (ehdr->e_entry - phdr(i)->p_vaddr)
+ phdr(i)->p_paddr;
#ifdef MULTIBOOT_LOAD_ELF64
# ifdef __mips
@@ -191,7 +208,7 @@ CONCAT(grub_multiboot_load_elf, XX) (mbi_load_data_t *mld)
#if defined (__i386__) || defined (__x86_64__)
#elif defined (__mips)
- grub_multiboot_payload_eip |= 0x80000000;
+ GRUB_MULTIBOOT (payload_eip) |= 0x80000000;
#else
#error Please complete this
#endif
@@ -238,7 +255,7 @@ CONCAT(grub_multiboot_load_elf, XX) (mbi_load_data_t *mld)
if (sh->sh_size == 0)
continue;
- err = grub_relocator_alloc_chunk_align (grub_multiboot_relocator, &ch, 0,
+ err = grub_relocator_alloc_chunk_align (GRUB_MULTIBOOT (relocator), &ch, 0,
(0xffffffff - sh->sh_size) + 1,
sh->sh_size, sh->sh_addralign,
GRUB_RELOCATOR_PREFERENCE_NONE,
@@ -264,8 +281,8 @@ CONCAT(grub_multiboot_load_elf, XX) (mbi_load_data_t *mld)
}
sh->sh_addr = target;
}
- grub_multiboot_add_elfsyms (ehdr->e_shnum, ehdr->e_shentsize,
- ehdr->e_shstrndx, shdr);
+ GRUB_MULTIBOOT (add_elfsyms) (ehdr->e_shnum, ehdr->e_shentsize,
+ ehdr->e_shstrndx, shdr);
}
#undef phdr
diff --git a/grub-core/loader/multiboot_mbi2.c b/grub-core/loader/multiboot_mbi2.c
index b0679a9f6c9848d81cb74cf799ad3a7b235d937c..4df6595954d889028e4525bb66b42cf391f4c9ce 100644
--- a/grub-core/loader/multiboot_mbi2.c
+++ b/grub-core/loader/multiboot_mbi2.c
@@ -22,7 +22,7 @@
#include
#include
#endif
-#include
+#include
#include
#include
#include
@@ -71,7 +71,7 @@ static int keep_bs = 0;
static grub_uint32_t load_base_addr;
void
-grub_multiboot_add_elfsyms (grub_size_t num, grub_size_t entsize,
+grub_multiboot2_add_elfsyms (grub_size_t num, grub_size_t entsize,
unsigned shndx, void *data)
{
elf_sec_num = num;
@@ -90,17 +90,17 @@ find_header (grub_properly_aligned_t *buffer, grub_ssize_t len)
((char *) header <= (char *) buffer + len - 12);
header = (struct multiboot_header *) ((grub_uint32_t *) header + MULTIBOOT_HEADER_ALIGN / 4))
{
- if (header->magic == MULTIBOOT_HEADER_MAGIC
+ if (header->magic == MULTIBOOT2_HEADER_MAGIC
&& !(header->magic + header->architecture
+ header->header_length + header->checksum)
- && header->architecture == MULTIBOOT_ARCHITECTURE_CURRENT)
+ && header->architecture == MULTIBOOT2_ARCHITECTURE_CURRENT)
return header;
}
return NULL;
}
grub_err_t
-grub_multiboot_load (grub_file_t file, const char *filename)
+grub_multiboot2_load (grub_file_t file, const char *filename)
{
grub_ssize_t len;
struct multiboot_header *header;
@@ -112,7 +112,7 @@ grub_multiboot_load (grub_file_t file, const char *filename)
grub_addr_t entry = 0, efi_entry = 0;
grub_uint32_t console_required = 0;
struct multiboot_header_tag_framebuffer *fbtag = NULL;
- int accepted_consoles = GRUB_MULTIBOOT_CONSOLE_EGA_TEXT;
+ int accepted_consoles = GRUB_MULTIBOOT2_CONSOLE_EGA_TEXT;
mbi_load_data_t mld;
mld.mbi_ver = 2;
@@ -210,7 +210,7 @@ grub_multiboot_load (grub_file_t file, const char *filename)
case MULTIBOOT_HEADER_TAG_CONSOLE_FLAGS:
if (!(((struct multiboot_header_tag_console_flags *) tag)->console_flags
& MULTIBOOT_CONSOLE_FLAGS_EGA_TEXT_SUPPORTED))
- accepted_consoles &= ~GRUB_MULTIBOOT_CONSOLE_EGA_TEXT;
+ accepted_consoles &= ~GRUB_MULTIBOOT2_CONSOLE_EGA_TEXT;
if (((struct multiboot_header_tag_console_flags *) tag)->console_flags
& MULTIBOOT_CONSOLE_FLAGS_CONSOLE_REQUIRED)
console_required = 1;
@@ -218,7 +218,7 @@ grub_multiboot_load (grub_file_t file, const char *filename)
case MULTIBOOT_HEADER_TAG_FRAMEBUFFER:
fbtag = (struct multiboot_header_tag_framebuffer *) tag;
- accepted_consoles |= GRUB_MULTIBOOT_CONSOLE_FRAMEBUFFER;
+ accepted_consoles |= GRUB_MULTIBOOT2_CONSOLE_FRAMEBUFFER;
break;
case MULTIBOOT_HEADER_TAG_RELOCATABLE:
@@ -295,13 +295,13 @@ grub_multiboot_load (grub_file_t file, const char *filename)
return grub_error (GRUB_ERR_BAD_OS, "invalid min/max address and/or load size");
}
- err = grub_relocator_alloc_chunk_align (grub_multiboot_relocator, &ch,
+ err = grub_relocator_alloc_chunk_align (grub_multiboot2_relocator, &ch,
mld.min_addr, mld.max_addr - code_size,
code_size, mld.align ? mld.align : 1,
mld.preference, keep_bs);
}
else
- err = grub_relocator_alloc_chunk_addr (grub_multiboot_relocator,
+ err = grub_relocator_alloc_chunk_addr (grub_multiboot2_relocator,
&ch, load_addr, code_size);
if (err)
{
@@ -343,7 +343,7 @@ grub_multiboot_load (grub_file_t file, const char *filename)
mld.file = file;
mld.filename = filename;
mld.avoid_efi_boot_services = keep_bs;
- err = grub_multiboot_load_elf (&mld);
+ err = grub_multiboot2_load_elf (&mld);
if (err)
{
grub_free (mld.buffer);
@@ -354,9 +354,9 @@ grub_multiboot_load (grub_file_t file, const char *filename)
load_base_addr = mld.load_base_addr;
if (keep_bs && efi_entry_specified)
- grub_multiboot_payload_eip = efi_entry;
+ grub_multiboot2_payload_eip = efi_entry;
else if (entry_specified)
- grub_multiboot_payload_eip = entry;
+ grub_multiboot2_payload_eip = entry;
if (mld.relocatable)
{
@@ -370,20 +370,20 @@ grub_multiboot_load (grub_file_t file, const char *filename)
* 64-bit int here.
*/
if (mld.load_base_addr >= mld.link_base_addr)
- grub_multiboot_payload_eip += mld.load_base_addr - mld.link_base_addr;
+ grub_multiboot2_payload_eip += mld.load_base_addr - mld.link_base_addr;
else
- grub_multiboot_payload_eip -= mld.link_base_addr - mld.load_base_addr;
+ grub_multiboot2_payload_eip -= mld.link_base_addr - mld.load_base_addr;
}
if (fbtag)
- err = grub_multiboot_set_console (GRUB_MULTIBOOT_CONSOLE_FRAMEBUFFER,
- accepted_consoles,
- fbtag->width, fbtag->height,
- fbtag->depth, console_required);
+ err = grub_multiboot2_set_console (GRUB_MULTIBOOT2_CONSOLE_FRAMEBUFFER,
+ accepted_consoles,
+ fbtag->width, fbtag->height,
+ fbtag->depth, console_required);
else
- err = grub_multiboot_set_console (GRUB_MULTIBOOT_CONSOLE_EGA_TEXT,
- accepted_consoles,
- 0, 0, 0, console_required);
+ err = grub_multiboot2_set_console (GRUB_MULTIBOOT2_CONSOLE_EGA_TEXT,
+ accepted_consoles,
+ 0, 0, 0, console_required);
return err;
}
@@ -459,7 +459,7 @@ net_size (void)
}
static grub_size_t
-grub_multiboot_get_mbi_size (void)
+grub_multiboot2_get_mbi_size (void)
{
#ifdef GRUB_MACHINE_EFI
if (!keep_bs && !efi_mmap_size)
@@ -478,7 +478,7 @@ grub_multiboot_get_mbi_size (void)
+ ALIGN_UP (sizeof (struct multiboot_tag_elf_sections), MULTIBOOT_TAG_ALIGN)
+ ALIGN_UP (elf_sec_entsize * elf_sec_num, MULTIBOOT_TAG_ALIGN)
+ ALIGN_UP ((sizeof (struct multiboot_tag_mmap)
- + grub_get_multiboot_mmap_count ()
+ + grub_multiboot2_get_mmap_count ()
* sizeof (struct multiboot_mmap_entry)), MULTIBOOT_TAG_ALIGN)
+ ALIGN_UP (sizeof (struct multiboot_tag_framebuffer), MULTIBOOT_TAG_ALIGN)
+ ALIGN_UP (sizeof (struct multiboot_tag_old_acpi)
@@ -522,7 +522,7 @@ grub_fill_multiboot_mmap (struct multiboot_tag_mmap *tag)
tag->type = MULTIBOOT_TAG_TYPE_MMAP;
tag->size = sizeof (struct multiboot_tag_mmap)
- + sizeof (struct multiboot_mmap_entry) * grub_get_multiboot_mmap_count ();
+ + sizeof (struct multiboot_mmap_entry) * grub_multiboot2_get_mmap_count ();
tag->entry_size = sizeof (struct multiboot_mmap_entry);
tag->entry_version = 0;
@@ -588,7 +588,7 @@ retrieve_video_parameters (grub_properly_aligned_t **ptrorig)
struct multiboot_tag_framebuffer *tag
= (struct multiboot_tag_framebuffer *) *ptrorig;
- err = grub_multiboot_set_video_mode ();
+ err = grub_multiboot2_set_video_mode ();
if (err)
{
grub_print_error ();
@@ -731,7 +731,7 @@ retrieve_video_parameters (grub_properly_aligned_t **ptrorig)
}
grub_err_t
-grub_multiboot_make_mbi (grub_uint32_t *target)
+grub_multiboot2_make_mbi (grub_uint32_t *target)
{
grub_properly_aligned_t *ptrorig;
grub_properly_aligned_t *mbistart;
@@ -739,11 +739,11 @@ grub_multiboot_make_mbi (grub_uint32_t *target)
grub_size_t bufsize;
grub_relocator_chunk_t ch;
- bufsize = grub_multiboot_get_mbi_size ();
+ bufsize = grub_multiboot2_get_mbi_size ();
COMPILE_TIME_ASSERT (MULTIBOOT_TAG_ALIGN % sizeof (grub_properly_aligned_t) == 0);
- err = grub_relocator_alloc_chunk_align (grub_multiboot_relocator, &ch,
+ err = grub_relocator_alloc_chunk_align (grub_multiboot2_relocator, &ch,
0, 0xffffffff - bufsize,
bufsize, MULTIBOOT_TAG_ALIGN,
GRUB_RELOCATOR_PREFERENCE_NONE, 1);
@@ -1039,7 +1039,7 @@ grub_multiboot_make_mbi (grub_uint32_t *target)
}
void
-grub_multiboot_free_mbi (void)
+grub_multiboot2_free_mbi (void)
{
struct module *cur, *next;
@@ -1061,11 +1061,11 @@ grub_multiboot_free_mbi (void)
}
grub_err_t
-grub_multiboot_init_mbi (int argc, char *argv[])
+grub_multiboot2_init_mbi (int argc, char *argv[])
{
grub_ssize_t len = 0;
- grub_multiboot_free_mbi ();
+ grub_multiboot2_free_mbi ();
len = grub_loader_cmdline_size (argc, argv);
@@ -1081,7 +1081,7 @@ grub_multiboot_init_mbi (int argc, char *argv[])
}
grub_err_t
-grub_multiboot_add_module (grub_addr_t start, grub_size_t size,
+grub_multiboot2_add_module (grub_addr_t start, grub_size_t size,
int argc, char *argv[])
{
struct module *newmod;
@@ -1119,7 +1119,7 @@ grub_multiboot_add_module (grub_addr_t start, grub_size_t size,
}
void
-grub_multiboot_set_bootdev (void)
+grub_multiboot2_set_bootdev (void)
{
grub_device_t dev;
diff --git a/grub-core/net/arp.c b/grub-core/net/arp.c
index 4b68c4151a11db214602f74e111e7552801d8450..54306e3b16d25fe5d3bdf9502683822237be488d 100644
--- a/grub-core/net/arp.c
+++ b/grub-core/net/arp.c
@@ -111,8 +111,8 @@ grub_net_arp_send_request (struct grub_net_network_level_interface *inf,
}
grub_err_t
-grub_net_arp_receive (struct grub_net_buff *nb,
- struct grub_net_card *card)
+grub_net_arp_receive (struct grub_net_buff *nb, struct grub_net_card *card,
+ grub_uint16_t *vlantag)
{
struct arppkt *arp_packet = (struct arppkt *) nb->data;
grub_net_network_level_address_t sender_addr, target_addr;
@@ -138,6 +138,14 @@ grub_net_arp_receive (struct grub_net_buff *nb,
FOR_NET_NETWORK_LEVEL_INTERFACES (inf)
{
+ /* Verify vlantag id */
+ if (inf->card == card && inf->vlantag != *vlantag)
+ {
+ grub_dprintf ("net", "invalid vlantag! %x != %x\n",
+ inf->vlantag, *vlantag);
+ break;
+ }
+
/* Am I the protocol address target? */
if (grub_net_addr_cmp (&inf->address, &target_addr) == 0
&& arp_packet->op == grub_cpu_to_be16_compile_time (ARP_REQUEST))
diff --git a/grub-core/net/drivers/ieee1275/ofnet.c b/grub-core/net/drivers/ieee1275/ofnet.c
index a78d164db1a0abbaf0417f70dc7180b9b2c4df76..002446be1c385934762824a965806ffb75f422a0 100644
--- a/grub-core/net/drivers/ieee1275/ofnet.c
+++ b/grub-core/net/drivers/ieee1275/ofnet.c
@@ -153,11 +153,11 @@ grub_ieee1275_parse_bootpath (const char *devpath, char *bootpath,
char *comma_char = 0;
char *equal_char = 0;
grub_size_t field_counter = 0;
-
grub_net_network_level_address_t client_addr, gateway_addr, subnet_mask;
grub_net_link_level_address_t hw_addr;
grub_net_interface_flags_t flags = 0;
struct grub_net_network_level_interface *inter = NULL;
+ grub_uint16_t vlantag = 0;
hw_addr.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET;
@@ -175,6 +175,11 @@ grub_ieee1275_parse_bootpath (const char *devpath, char *bootpath,
*equal_char = 0;
grub_env_set_net_property ((*card)->name, args, equal_char + 1,
grub_strlen(equal_char + 1));
+
+ if ((grub_strcmp (args, "vtag") == 0) &&
+ (grub_strlen (equal_char + 1) == 8))
+ vlantag = grub_strtoul (equal_char + 1 + 4, 0, 16);
+
*equal_char = '=';
}
else
@@ -213,8 +218,10 @@ grub_ieee1275_parse_bootpath (const char *devpath, char *bootpath,
hw_addr.mac, sizeof(hw_addr.mac), 0);
inter = grub_net_add_addr ((*card)->name, *card, &client_addr, &hw_addr,
flags);
+ inter->vlantag = vlantag;
grub_net_add_ipv4_local (inter,
__builtin_ctz (~grub_le_to_cpu32 (subnet_mask.ipv4)));
+
}
if (gateway_addr.ipv4 != 0)
diff --git a/grub-core/net/ethernet.c b/grub-core/net/ethernet.c
index c397b1b348ce559070cabe1e0b6e28e4dbf254d8..4d7ceed6f93c7e87019546b544a4365a504f5f9f 100644
--- a/grub-core/net/ethernet.c
+++ b/grub-core/net/ethernet.c
@@ -18,6 +18,7 @@
#include
#include
+#include
#include
#include
#include
@@ -56,10 +57,17 @@ send_ethernet_packet (struct grub_net_network_level_interface *inf,
{
struct etherhdr *eth;
grub_err_t err;
+ grub_uint8_t etherhdr_size;
+ grub_uint16_t vlantag_id = VLANTAG_IDENTIFIER;
- COMPILE_TIME_ASSERT (sizeof (*eth) < GRUB_NET_MAX_LINK_HEADER_SIZE);
+ etherhdr_size = sizeof (*eth);
+ COMPILE_TIME_ASSERT (sizeof (*eth) + 4 < GRUB_NET_MAX_LINK_HEADER_SIZE);
- err = grub_netbuff_push (nb, sizeof (*eth));
+ /* Increase ethernet header in case of vlantag */
+ if (inf->vlantag != 0)
+ etherhdr_size += 4;
+
+ err = grub_netbuff_push (nb, etherhdr_size);
if (err)
return err;
eth = (struct etherhdr *) nb->data;
@@ -76,6 +84,19 @@ send_ethernet_packet (struct grub_net_network_level_interface *inf,
return err;
inf->card->opened = 1;
}
+
+ /* Check and add a vlan-tag if needed. */
+ if (inf->vlantag != 0)
+ {
+ /* Move eth type to the right */
+ grub_memcpy ((char *) nb->data + etherhdr_size - 2,
+ (char *) nb->data + etherhdr_size - 6, 2);
+
+ /* Add the tag in the middle */
+ grub_memcpy ((char *) nb->data + etherhdr_size - 6, &vlantag_id, 2);
+ grub_memcpy ((char *) nb->data + etherhdr_size - 4, (char *) &(inf->vlantag), 2);
+ }
+
return inf->card->driver->send (inf->card, nb);
}
@@ -90,10 +111,25 @@ grub_net_recv_ethernet_packet (struct grub_net_buff *nb,
grub_net_link_level_address_t hwaddress;
grub_net_link_level_address_t src_hwaddress;
grub_err_t err;
+ grub_uint8_t etherhdr_size = sizeof (*eth);
+ grub_uint16_t vlantag = 0;
+
+
+ /* Check if a vlan-tag is present. If so, the ethernet header is 4 bytes */
+ /* longer than the original one. The vlantag id is extracted and the header */
+ /* is reseted to the original size. */
+ if (grub_get_unaligned16 (nb->data + etherhdr_size - 2) == VLANTAG_IDENTIFIER)
+ {
+ vlantag = grub_get_unaligned16 (nb->data + etherhdr_size);
+ etherhdr_size += 4;
+ /* Move eth type to the original position */
+ grub_memcpy((char *) nb->data + etherhdr_size - 6,
+ (char *) nb->data + etherhdr_size - 2, 2);
+ }
eth = (struct etherhdr *) nb->data;
type = grub_be_to_cpu16 (eth->type);
- err = grub_netbuff_pull (nb, sizeof (*eth));
+ err = grub_netbuff_pull (nb, etherhdr_size);
if (err)
return err;
@@ -121,13 +157,14 @@ grub_net_recv_ethernet_packet (struct grub_net_buff *nb,
{
/* ARP packet. */
case GRUB_NET_ETHERTYPE_ARP:
- grub_net_arp_receive (nb, card);
+ grub_net_arp_receive (nb, card, &vlantag);
grub_netbuff_free (nb);
return GRUB_ERR_NONE;
/* IP packet. */
case GRUB_NET_ETHERTYPE_IP:
case GRUB_NET_ETHERTYPE_IP6:
- return grub_net_recv_ip_packets (nb, card, &hwaddress, &src_hwaddress);
+ return grub_net_recv_ip_packets (nb, card, &hwaddress, &src_hwaddress,
+ &vlantag);
}
grub_netbuff_free (nb);
return GRUB_ERR_NONE;
diff --git a/grub-core/net/ip.c b/grub-core/net/ip.c
index aba4f89087bc14b1fe28a77794dd6792beb0bf36..7c95cc7464a09af4b223c94d6653a03f0dbee062 100644
--- a/grub-core/net/ip.c
+++ b/grub-core/net/ip.c
@@ -228,12 +228,13 @@ handle_dgram (struct grub_net_buff *nb,
grub_net_ip_protocol_t proto,
const grub_net_network_level_address_t *source,
const grub_net_network_level_address_t *dest,
+ grub_uint16_t *vlantag,
grub_uint8_t ttl)
{
struct grub_net_network_level_interface *inf = NULL;
grub_err_t err;
int multicast = 0;
-
+
/* DHCP needs special treatment since we don't know IP yet. */
{
struct udphdr *udph;
@@ -293,6 +294,15 @@ handle_dgram (struct grub_net_buff *nb,
&& grub_net_addr_cmp (&inf->address, dest) == 0
&& grub_net_hwaddr_cmp (&inf->hwaddress, hwaddress) == 0)
break;
+
+ /* Verify vlantag id */
+ if (inf->card == card && inf->vlantag != *vlantag)
+ {
+ grub_dprintf ("net", "invalid vlantag! %x != %x\n",
+ inf->vlantag, *vlantag);
+ break;
+ }
+
/* Solicited node multicast. */
if (inf->card == card
&& inf->address.type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6
@@ -383,7 +393,8 @@ static grub_err_t
grub_net_recv_ip4_packets (struct grub_net_buff *nb,
struct grub_net_card *card,
const grub_net_link_level_address_t *hwaddress,
- const grub_net_link_level_address_t *src_hwaddress)
+ const grub_net_link_level_address_t *src_hwaddress,
+ grub_uint16_t *vlantag)
{
struct iphdr *iph = (struct iphdr *) nb->data;
grub_err_t err;
@@ -458,7 +469,7 @@ grub_net_recv_ip4_packets (struct grub_net_buff *nb,
dest.ipv4 = iph->dest;
return handle_dgram (nb, card, src_hwaddress, hwaddress, iph->protocol,
- &source, &dest, iph->ttl);
+ &source, &dest, vlantag, iph->ttl);
}
for (prev = &reassembles, rsm = *prev; rsm; prev = &rsm->next, rsm = *prev)
@@ -594,7 +605,7 @@ grub_net_recv_ip4_packets (struct grub_net_buff *nb,
dest.ipv4 = dst;
return handle_dgram (ret, card, src_hwaddress,
- hwaddress, proto, &source, &dest,
+ hwaddress, proto, &source, &dest, vlantag,
ttl);
}
}
@@ -652,7 +663,8 @@ static grub_err_t
grub_net_recv_ip6_packets (struct grub_net_buff *nb,
struct grub_net_card *card,
const grub_net_link_level_address_t *hwaddress,
- const grub_net_link_level_address_t *src_hwaddress)
+ const grub_net_link_level_address_t *src_hwaddress,
+ grub_uint16_t *vlantag)
{
struct ip6hdr *iph = (struct ip6hdr *) nb->data;
grub_err_t err;
@@ -703,21 +715,24 @@ grub_net_recv_ip6_packets (struct grub_net_buff *nb,
grub_memcpy (dest.ipv6, &iph->dest, sizeof (dest.ipv6));
return handle_dgram (nb, card, src_hwaddress, hwaddress, iph->protocol,
- &source, &dest, iph->ttl);
+ &source, &dest, vlantag, iph->ttl);
}
grub_err_t
grub_net_recv_ip_packets (struct grub_net_buff *nb,
struct grub_net_card *card,
const grub_net_link_level_address_t *hwaddress,
- const grub_net_link_level_address_t *src_hwaddress)
+ const grub_net_link_level_address_t *src_hwaddress,
+ grub_uint16_t *vlantag)
{
struct iphdr *iph = (struct iphdr *) nb->data;
if ((iph->verhdrlen >> 4) == 4)
- return grub_net_recv_ip4_packets (nb, card, hwaddress, src_hwaddress);
+ return grub_net_recv_ip4_packets (nb, card, hwaddress, src_hwaddress,
+ vlantag);
if ((iph->verhdrlen >> 4) == 6)
- return grub_net_recv_ip6_packets (nb, card, hwaddress, src_hwaddress);
+ return grub_net_recv_ip6_packets (nb, card, hwaddress, src_hwaddress,
+ vlantag);
grub_dprintf ("net", "Bad IP version: %d\n", (iph->verhdrlen >> 4));
grub_netbuff_free (nb);
return GRUB_ERR_NONE;
diff --git a/grub-core/normal/auth.c b/grub-core/normal/auth.c
index 7338f8245e3a9bbe47e821fb43c2b699b9527ffb..6be678c0de1ac236b60f765e767ae43d113b1117 100644
--- a/grub-core/normal/auth.c
+++ b/grub-core/normal/auth.c
@@ -166,13 +166,13 @@ grub_username_get (char buf[], unsigned buf_size)
if (key == '\n' || key == '\r')
break;
- if (key == '\e')
+ if (key == GRUB_TERM_ESC)
{
cur_len = 0;
break;
}
- if (key == '\b')
+ if (key == GRUB_TERM_BACKSPACE)
{
if (cur_len)
{
@@ -197,7 +197,7 @@ grub_username_get (char buf[], unsigned buf_size)
grub_xputs ("\n");
grub_refresh ();
- return (key != '\e');
+ return (key != GRUB_TERM_ESC);
}
grub_err_t
diff --git a/grub-core/normal/cmdline.c b/grub-core/normal/cmdline.c
index a36180d75305f421e96903a46acb9dd99af06572..c037d5050ed2b34fa3b2ac0c7564e4208ca143c4 100644
--- a/grub-core/normal/cmdline.c
+++ b/grub-core/normal/cmdline.c
@@ -626,12 +626,12 @@ grub_cmdline_get (const char *prompt_translated)
cl_insert (cl_terms, nterms, &lpos, &llen, &max_len, &buf, kill_buf);
break;
- case '\e':
+ case GRUB_TERM_ESC:
grub_free (cl_terms);
grub_free (buf);
return 0;
- case '\b':
+ case GRUB_TERM_BACKSPACE:
if (lpos > 0)
{
lpos--;
diff --git a/grub-core/normal/crypto.c b/grub-core/normal/crypto.c
index 2bfd67c8ef388097701a7415df3cd7321c6a1e57..e6d345f33458a167e703235d611afdd8c2a245b0 100644
--- a/grub-core/normal/crypto.c
+++ b/grub-core/normal/crypto.c
@@ -147,8 +147,8 @@ read_crypto_list (const char *prefix)
if (! cur->modname)
{
grub_errno = GRUB_ERR_NONE;
- grub_free (cur);
grub_free (cur->name);
+ grub_free (cur);
continue;
}
cur->next = crypto_specs;
diff --git a/grub-core/normal/menu.c b/grub-core/normal/menu.c
index 719e2fb1c260b16d96cea2b787d7f7e592b428b7..e7a83c2d6e2aaa8248ed739b28f2c6be76622eb4 100644
--- a/grub-core/normal/menu.c
+++ b/grub-core/normal/menu.c
@@ -763,7 +763,7 @@ run_menu (grub_menu_t menu, int nested, int *auto_boot)
*auto_boot = 0;
return current_entry;
- case '\e':
+ case GRUB_TERM_ESC:
if (nested)
{
menu_fini ();
diff --git a/grub-core/normal/menu_entry.c b/grub-core/normal/menu_entry.c
index eeeee5580abea9798278ef85cf417366cf4f0e0a..cdf3590a3646ce4be0caf99cafedcbc38cbe51e4 100644
--- a/grub-core/normal/menu_entry.c
+++ b/grub-core/normal/menu_entry.c
@@ -1403,7 +1403,7 @@ grub_menu_entry_run (grub_menu_entry_t entry)
goto fail;
break;
- case '\e':
+ case GRUB_TERM_ESC:
destroy_screen (screen);
return;
diff --git a/grub-core/osdep/linux/ofpath.c b/grub-core/osdep/linux/ofpath.c
index a79682a5e31e1b4e77d9b99f55cc5a1fca9e159b..a6153d359546d237933cba0f300e7d59fdb1007b 100644
--- a/grub-core/osdep/linux/ofpath.c
+++ b/grub-core/osdep/linux/ofpath.c
@@ -38,6 +38,46 @@
#include
#include
+#ifdef __sparc__
+typedef enum
+ {
+ GRUB_OFPATH_SPARC_WWN_ADDR = 1,
+ GRUB_OFPATH_SPARC_TGT_LUN,
+ } ofpath_sparc_addressing;
+
+struct ofpath_sparc_hba
+{
+ grub_uint32_t device_id;
+ ofpath_sparc_addressing addressing;
+};
+
+static struct ofpath_sparc_hba sparc_lsi_hba[] = {
+ /* Rhea, Jasper 320, LSI53C1020/1030. */
+ {0x30, GRUB_OFPATH_SPARC_TGT_LUN},
+ /* SAS-1068E. */
+ {0x50, GRUB_OFPATH_SPARC_TGT_LUN},
+ /* SAS-1064E. */
+ {0x56, GRUB_OFPATH_SPARC_TGT_LUN},
+ /* Pandora SAS-1068E. */
+ {0x58, GRUB_OFPATH_SPARC_TGT_LUN},
+ /* Aspen, Invader, LSI SAS-3108. */
+ {0x5d, GRUB_OFPATH_SPARC_TGT_LUN},
+ /* Niwot, SAS 2108. */
+ {0x79, GRUB_OFPATH_SPARC_TGT_LUN},
+ /* Erie, Falcon, LSI SAS 2008. */
+ {0x72, GRUB_OFPATH_SPARC_WWN_ADDR},
+ /* LSI WarpDrive 6203. */
+ {0x7e, GRUB_OFPATH_SPARC_WWN_ADDR},
+ /* LSI SAS 2308. */
+ {0x87, GRUB_OFPATH_SPARC_WWN_ADDR},
+ /* LSI SAS 3008. */
+ {0x97, GRUB_OFPATH_SPARC_WWN_ADDR},
+ {0, 0}
+};
+
+static const int LSI_VENDOR_ID = 0x1000;
+#endif
+
#ifdef OFPATH_STANDALONE
#define xmalloc malloc
void
@@ -120,6 +160,8 @@ find_obppath (const char *sysfs_path_orig)
#endif
fd = open(path, O_RDONLY);
+
+#ifndef __sparc__
if (fd < 0 || fstat (fd, &st) < 0)
{
if (fd >= 0)
@@ -127,6 +169,7 @@ find_obppath (const char *sysfs_path_orig)
snprintf(path, path_size, "%s/devspec", sysfs_path);
fd = open(path, O_RDONLY);
}
+#endif
if (fd < 0 || fstat (fd, &st) < 0)
{
@@ -307,6 +350,55 @@ of_path_of_ide(const char *sys_devname __attribute__((unused)), const char *devi
return ret;
}
+#ifdef __sparc__
+static char *
+of_path_of_nvme(const char *sys_devname __attribute__((unused)),
+ const char *device,
+ const char *devnode __attribute__((unused)),
+ const char *devicenode)
+{
+ char *sysfs_path, *of_path, disk[MAX_DISK_CAT];
+ const char *digit_string, *part_end;
+
+ digit_string = trailing_digits (device);
+ part_end = devicenode + strlen (devicenode) - 1;
+
+ if ((*digit_string != '\0') && (*part_end == 'p'))
+ {
+ /* We have a partition number, strip it off. */
+ int part;
+ char *nvmedev, *end;
+
+ nvmedev = strdup (devicenode);
+
+ if (!nvmedev)
+ return NULL;
+
+ end = nvmedev + strlen (nvmedev) - 1;
+ /* Remove the p. */
+ *end = '\0';
+ sscanf (digit_string, "%d", &part);
+ snprintf (disk, sizeof (disk), "/disk@1:%c", 'a' + (part - 1));
+ sysfs_path = block_device_get_sysfs_path_and_link (nvmedev);
+ free (nvmedev);
+ }
+ else
+ {
+ /* We do not have the parition. */
+ snprintf (disk, sizeof (disk), "/disk@1");
+ sysfs_path = block_device_get_sysfs_path_and_link (device);
+ }
+
+ of_path = find_obppath (sysfs_path);
+
+ if (of_path)
+ strcat (of_path, disk);
+
+ free (sysfs_path);
+ return of_path;
+}
+#endif
+
static int
vendor_is_ATA(const char *path)
{
@@ -335,6 +427,64 @@ vendor_is_ATA(const char *path)
return (memcmp(bufcont, "ATA", 3) == 0);
}
+#ifdef __sparc__
+static void
+check_hba_identifiers (const char *sysfs_path, int *vendor, int *device_id)
+{
+ char *ed = strstr (sysfs_path, "host");
+ size_t path_size;
+ char *p, *path;
+ char buf[8];
+ int fd;
+
+ if (!ed)
+ return;
+
+ p = xstrdup (sysfs_path);
+ ed = strstr (p, "host");
+
+ *ed = '\0';
+
+ path_size = (strlen (p) + sizeof ("vendor"));
+ path = xmalloc (path_size);
+
+ if (!path)
+ goto out;
+
+ snprintf (path, path_size, "%svendor", p);
+ fd = open (path, O_RDONLY);
+
+ if (fd < 0)
+ goto out;
+
+ memset (buf, 0, sizeof (buf));
+
+ if (read (fd, buf, sizeof (buf) - 1) < 0)
+ goto out;
+
+ close (fd);
+ sscanf (buf, "%x", vendor);
+
+ snprintf (path, path_size, "%sdevice", p);
+ fd = open (path, O_RDONLY);
+
+ if (fd < 0)
+ goto out;
+
+ memset (buf, 0, sizeof (buf));
+
+ if (read (fd, buf, sizeof (buf) - 1) < 0)
+ goto out;
+
+ close (fd);
+ sscanf (buf, "%x", device_id);
+
+ out:
+ free (path);
+ free (p);
+}
+#endif
+
static void
check_sas (const char *sysfs_path, int *tgt, unsigned long int *sas_address)
{
@@ -396,7 +546,7 @@ of_path_of_scsi(const char *sys_devname __attribute__((unused)), const char *dev
{
const char *p, *digit_string, *disk_name;
int host, bus, tgt, lun;
- unsigned long int sas_address;
+ unsigned long int sas_address = 0;
char *sysfs_path, disk[MAX_DISK_CAT - sizeof ("/fp@0,0")];
char *of_path;
@@ -413,9 +563,8 @@ of_path_of_scsi(const char *sys_devname __attribute__((unused)), const char *dev
}
of_path = find_obppath(sysfs_path);
- free (sysfs_path);
if (!of_path)
- return NULL;
+ goto out;
if (strstr (of_path, "qlc"))
strcat (of_path, "/fp@0,0");
@@ -444,6 +593,46 @@ of_path_of_scsi(const char *sys_devname __attribute__((unused)), const char *dev
}
else
{
+#ifdef __sparc__
+ ofpath_sparc_addressing addressing = GRUB_OFPATH_SPARC_TGT_LUN;
+ int vendor = 0, device_id = 0;
+ char *optr = disk;
+
+ check_hba_identifiers (sysfs_path, &vendor, &device_id);
+
+ if (vendor == LSI_VENDOR_ID)
+ {
+ struct ofpath_sparc_hba *lsi_hba;
+
+ /*
+ * Over time different OF addressing schemes have been supported.
+ * There is no generic addressing scheme that works across
+ * every HBA.
+ */
+ for (lsi_hba = sparc_lsi_hba; lsi_hba->device_id; lsi_hba++)
+ if (lsi_hba->device_id == device_id)
+ {
+ addressing = lsi_hba->addressing;
+ break;
+ }
+ }
+
+ if (addressing == GRUB_OFPATH_SPARC_WWN_ADDR)
+ optr += snprintf (disk, sizeof (disk), "/%s@w%lx,%x", disk_name,
+ sas_address, lun);
+ else
+ optr += snprintf (disk, sizeof (disk), "/%s@%x,%x", disk_name, tgt,
+ lun);
+
+ if (*digit_string != '\0')
+ {
+ int part;
+
+ sscanf (digit_string, "%d", &part);
+ snprintf (optr, sizeof (disk) - (optr - disk - 1), ":%c", 'a'
+ + (part - 1));
+ }
+#else
if (lun == 0)
{
int sas_id = 0;
@@ -491,8 +680,12 @@ of_path_of_scsi(const char *sys_devname __attribute__((unused)), const char *dev
}
free (lunstr);
}
+#endif
}
strcat(of_path, disk);
+
+ out:
+ free (sysfs_path);
return of_path;
}
@@ -537,6 +730,11 @@ grub_util_devname_to_ofpath (const char *sys_devname)
/* All the models I've seen have a devalias "floppy".
New models have no floppy at all. */
ofpath = xstrdup ("floppy");
+#ifdef __sparc__
+ else if (device[0] == 'n' && device[1] == 'v' && device[2] == 'm'
+ && device[3] == 'e')
+ ofpath = of_path_of_nvme (name_buf, device, devnode, devicenode);
+#endif
else
{
grub_util_warn (_("unknown device type %s"), device);
diff --git a/grub-core/osdep/unix/exec.c b/grub-core/osdep/unix/exec.c
index 935ff120ebe117f7492715813789db364ef1b12f..db3259f6504d5d5958cfa330bfd4a8b12b64f970 100644
--- a/grub-core/osdep/unix/exec.c
+++ b/grub-core/osdep/unix/exec.c
@@ -99,7 +99,7 @@ grub_util_exec_redirect_all (const char *const *argv, const char *stdin_file,
{
fd = open (stdin_file, O_RDONLY);
if (fd < 0)
- exit (127);
+ _exit (127);
dup2 (fd, STDIN_FILENO);
close (fd);
}
@@ -108,7 +108,7 @@ grub_util_exec_redirect_all (const char *const *argv, const char *stdin_file,
{
fd = open (stdout_file, O_WRONLY | O_CREAT, 0700);
if (fd < 0)
- exit (127);
+ _exit (127);
dup2 (fd, STDOUT_FILENO);
close (fd);
}
@@ -117,7 +117,7 @@ grub_util_exec_redirect_all (const char *const *argv, const char *stdin_file,
{
fd = open (stderr_file, O_WRONLY | O_CREAT, 0700);
if (fd < 0)
- exit (127);
+ _exit (127);
dup2 (fd, STDERR_FILENO);
close (fd);
}
@@ -126,7 +126,7 @@ grub_util_exec_redirect_all (const char *const *argv, const char *stdin_file,
setenv ("LC_ALL", "C", 1);
execvp ((char *) argv[0], (char **) argv);
- exit (127);
+ _exit (127);
}
waitpid (pid, &status, 0);
if (!WIFEXITED (status))
diff --git a/grub-core/osdep/unix/getroot.c b/grub-core/osdep/unix/getroot.c
index 4bf37b027be660a14994fb316f08dd478490c4e2..3046e22cc012d1012add87931a018043e3ecc714 100644
--- a/grub-core/osdep/unix/getroot.c
+++ b/grub-core/osdep/unix/getroot.c
@@ -428,8 +428,11 @@ grub_find_device (const char *dir, dev_t dev)
{
#ifdef __linux__
/* Skip device names like /dev/dm-0, which are short-hand aliases
- to more descriptive device names, e.g. those under /dev/mapper */
- if (ent->d_name[0] == 'd' &&
+ to more descriptive device names, e.g. those under /dev/mapper.
+ Also, don't skip devices which names start with dm-[0-9] in
+ directories below /dev, e.g. /dev/mapper/dm-0-luks. */
+ if (strcmp (dir, "/dev") == 0 &&
+ ent->d_name[0] == 'd' &&
ent->d_name[1] == 'm' &&
ent->d_name[2] == '-' &&
ent->d_name[3] >= '0' &&
diff --git a/grub-core/osdep/unix/hostdisk.c b/grub-core/osdep/unix/hostdisk.c
index 2a8c5882e3d10b98bc305a116f8cca06acfe89f5..5450cf4166e04c2cfab806e93dfa63c6abdb9698 100644
--- a/grub-core/osdep/unix/hostdisk.c
+++ b/grub-core/osdep/unix/hostdisk.c
@@ -77,11 +77,19 @@ grub_util_get_fd_size (grub_util_fd_t fd, const char *name, unsigned *log_secsiz
int
grub_util_fd_seek (grub_util_fd_t fd, grub_uint64_t off)
{
+#if SIZEOF_OFF_T == 8
off_t offset = (off_t) off;
if (lseek (fd, offset, SEEK_SET) != offset)
return -1;
+#elif SIZEOF_OFF64_T == 8
+ off64_t offset = (off64_t) off;
+ if (lseek64 (fd, offset, SEEK_SET) != offset)
+ return -1;
+#else
+#error "No large file support"
+#endif
return 0;
}
diff --git a/grub-core/osdep/unix/platform.c b/grub-core/osdep/unix/platform.c
index a3fcfcacaa814d3ab62104f0dd406ef0c2163613..ca448bc11a05b9e0c6203a799ff62ab1dd75274f 100644
--- a/grub-core/osdep/unix/platform.c
+++ b/grub-core/osdep/unix/platform.c
@@ -78,19 +78,20 @@ get_ofpathname (const char *dev)
dev);
}
-static void
+static int
grub_install_remove_efi_entries_by_distributor (const char *efi_distributor)
{
int fd;
pid_t pid = grub_util_exec_pipe ((const char * []){ "efibootmgr", NULL }, &fd);
char *line = NULL;
size_t len = 0;
+ int rc;
if (!pid)
{
grub_util_warn (_("Unable to open stream from %s: %s"),
"efibootmgr", strerror (errno));
- return;
+ return errno;
}
FILE *fp = fdopen (fd, "r");
@@ -98,7 +99,7 @@ grub_install_remove_efi_entries_by_distributor (const char *efi_distributor)
{
grub_util_warn (_("Unable to open stream from %s: %s"),
"efibootmgr", strerror (errno));
- return;
+ return errno;
}
line = xmalloc (80);
@@ -119,23 +120,25 @@ grub_install_remove_efi_entries_by_distributor (const char *efi_distributor)
bootnum = line + sizeof ("Boot") - 1;
bootnum[4] = '\0';
if (!verbosity)
- grub_util_exec ((const char * []){ "efibootmgr", "-q",
+ rc = grub_util_exec ((const char * []){ "efibootmgr", "-q",
"-b", bootnum, "-B", NULL });
else
- grub_util_exec ((const char * []){ "efibootmgr",
+ rc = grub_util_exec ((const char * []){ "efibootmgr",
"-b", bootnum, "-B", NULL });
}
free (line);
+ return rc;
}
-void
+int
grub_install_register_efi (grub_device_t efidir_grub_dev,
const char *efifile_path,
const char *efi_distributor)
{
const char * efidir_disk;
int efidir_part;
+ int ret;
efidir_disk = grub_util_biosdisk_get_osdev (efidir_grub_dev->disk);
efidir_part = efidir_grub_dev->disk->partition ? efidir_grub_dev->disk->partition->number + 1 : 1;
@@ -151,23 +154,26 @@ grub_install_register_efi (grub_device_t efidir_grub_dev,
grub_util_exec ((const char * []){ "modprobe", "-q", "efivars", NULL });
#endif
/* Delete old entries from the same distributor. */
- grub_install_remove_efi_entries_by_distributor (efi_distributor);
+ ret = grub_install_remove_efi_entries_by_distributor (efi_distributor);
+ if (ret)
+ return ret;
char *efidir_part_str = xasprintf ("%d", efidir_part);
if (!verbosity)
- grub_util_exec ((const char * []){ "efibootmgr", "-q",
+ ret = grub_util_exec ((const char * []){ "efibootmgr", "-q",
"-c", "-d", efidir_disk,
"-p", efidir_part_str, "-w",
"-L", efi_distributor, "-l",
efifile_path, NULL });
else
- grub_util_exec ((const char * []){ "efibootmgr",
+ ret = grub_util_exec ((const char * []){ "efibootmgr",
"-c", "-d", efidir_disk,
"-p", efidir_part_str, "-w",
"-L", efi_distributor, "-l",
efifile_path, NULL });
free (efidir_part_str);
+ return ret;
}
void
diff --git a/grub-core/partmap/gpt.c b/grub-core/partmap/gpt.c
index 83bcba7791421825da6922a7ee346f4fd5fcd7a4..103f6796f39f38209b0f554842aa6697faa5df2f 100644
--- a/grub-core/partmap/gpt.c
+++ b/grub-core/partmap/gpt.c
@@ -33,10 +33,10 @@ static grub_uint8_t grub_gpt_magic[8] =
0x45, 0x46, 0x49, 0x20, 0x50, 0x41, 0x52, 0x54
};
-static const grub_gpt_part_type_t grub_gpt_partition_type_empty = GRUB_GPT_PARTITION_TYPE_EMPTY;
+static const grub_gpt_part_guid_t grub_gpt_partition_type_empty = GRUB_GPT_PARTITION_TYPE_EMPTY;
#ifdef GRUB_UTIL
-static const grub_gpt_part_type_t grub_gpt_partition_type_bios_boot = GRUB_GPT_PARTITION_TYPE_BIOS_BOOT;
+static const grub_gpt_part_guid_t grub_gpt_partition_type_bios_boot = GRUB_GPT_PARTITION_TYPE_BIOS_BOOT;
#endif
/* 512 << 7 = 65536 byte sectors. */
diff --git a/grub-core/term/arm/cros.c b/grub-core/term/arm/cros.c
new file mode 100644
index 0000000000000000000000000000000000000000..1ff9f8ccfb8270884ba962a05ca99df4c6ed1f41
--- /dev/null
+++ b/grub-core/term/arm/cros.c
@@ -0,0 +1,125 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ *
+ * Copyright (C) 2012 Google Inc.
+ * Copyright (C) 2016 Free Software Foundation, Inc.
+ *
+ * This is based on depthcharge code.
+ *
+ * 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
+
+struct grub_ps2_state ps2_state;
+
+struct grub_cros_ec_keyscan old_scan;
+
+static const struct grub_fdtbus_dev *cros_ec;
+
+static grub_uint8_t map_code[GRUB_CROS_EC_KEYSCAN_COLS][GRUB_CROS_EC_KEYSCAN_ROWS];
+
+static grub_uint8_t e0_translate[16] =
+ {
+ 0x1c, 0x1d, 0x35, 0x00,
+ 0x38, 0x00, 0x47, 0x48,
+ 0x49, 0x4b, 0x4d, 0x4f,
+ 0x50, 0x51, 0x52, 0x53,
+ };
+
+/* If there is a character pending, return it;
+ otherwise return GRUB_TERM_NO_KEY. */
+static int
+grub_cros_keyboard_getkey (struct grub_term_input *term __attribute__ ((unused)))
+{
+ struct grub_cros_ec_keyscan scan;
+ int i, j;
+ if (grub_cros_ec_scan_keyboard (cros_ec, &scan) < 0)
+ return GRUB_TERM_NO_KEY;
+ for (i = 0; i < GRUB_CROS_EC_KEYSCAN_COLS; i++)
+ if (scan.data[i] ^ old_scan.data[i])
+ for (j = 0; j < GRUB_CROS_EC_KEYSCAN_ROWS; j++)
+ if ((scan.data[i] ^ old_scan.data[i]) & (1 << j))
+ {
+ grub_uint8_t code = map_code[i][j];
+ int ret;
+ grub_uint8_t brk = 0;
+ if (!(scan.data[i] & (1 << j)))
+ brk = 0x80;
+ grub_dprintf ("cros_keyboard", "key <%d, %d> code %x\n", i, j, code);
+ if (code < 0x60)
+ ret = grub_ps2_process_incoming_byte (&ps2_state, code | brk);
+ else if (code >= 0x60 && code < 0x70 && e0_translate[code - 0x60])
+ {
+ grub_ps2_process_incoming_byte (&ps2_state, 0xe0);
+ ret = grub_ps2_process_incoming_byte (&ps2_state, e0_translate[code - 0x60] | brk);
+ }
+ else
+ ret = GRUB_TERM_NO_KEY;
+ old_scan.data[i] ^= (1 << j);
+ if (ret != GRUB_TERM_NO_KEY)
+ return ret;
+ }
+ return GRUB_TERM_NO_KEY;
+}
+
+static struct grub_term_input grub_cros_keyboard_term =
+ {
+ .name = "cros_keyboard",
+ .getkey = grub_cros_keyboard_getkey
+ };
+
+static grub_err_t
+cros_attach (const struct grub_fdtbus_dev *dev)
+{
+ grub_size_t keymap_size, i;
+ const grub_uint8_t *keymap = grub_fdtbus_get_prop (dev, "linux,keymap", &keymap_size);
+
+ if (!dev->parent || !grub_cros_ec_validate (dev->parent))
+ return GRUB_ERR_IO;
+
+ if (keymap)
+ {
+ for (i = 0; i + 3 < keymap_size; i += 4)
+ if (keymap[i+1] < GRUB_CROS_EC_KEYSCAN_COLS && keymap[i] < GRUB_CROS_EC_KEYSCAN_ROWS
+ && keymap[i+2] == 0 && keymap[i+3] < 0x80)
+ map_code[keymap[i+1]][keymap[i]] = keymap[i+3];
+ }
+
+ cros_ec = dev->parent;
+ ps2_state.current_set = 1;
+ ps2_state.at_keyboard_status = 0;
+ grub_term_register_input ("cros_keyboard", &grub_cros_keyboard_term);
+ return GRUB_ERR_NONE;
+}
+
+static struct grub_fdtbus_driver cros =
+{
+ .compatible = "google,cros-ec-keyb",
+ .attach = cros_attach
+};
+
+void
+grub_cros_init (void)
+{
+ grub_fdtbus_register (&cros);
+}
diff --git a/grub-core/term/arm/cros_ec.c b/grub-core/term/arm/cros_ec.c
new file mode 100644
index 0000000000000000000000000000000000000000..f4144818b5bfdb9a512316ccc321586d539653ac
--- /dev/null
+++ b/grub-core/term/arm/cros_ec.c
@@ -0,0 +1,238 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ *
+ * Copyright (C) 2012 Google Inc.
+ * Copyright (C) 2016 Free Software Foundation, Inc.
+ *
+ * This is based on depthcharge code.
+ *
+ * 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
+
+static const grub_uint64_t FRAMING_TIMEOUT_MS = 300;
+
+static const grub_uint8_t EC_FRAMING_BYTE = 0xec;
+
+#define EC_CMD_MKBP_STATE 0x60
+#define EC_CMD_VERSION0 0xdc
+
+static grub_uint64_t last_transfer;
+
+static void
+stop_bus (const struct grub_fdtbus_dev *spi)
+{
+ spi->driver->stop (spi);
+ last_transfer = grub_get_time_ms ();
+}
+
+static int
+wait_for_frame (const struct grub_fdtbus_dev *spi)
+{
+ grub_uint64_t start = grub_get_time_ms ();
+ grub_uint8_t byte;
+ do
+ {
+ if (spi->driver->receive (spi, &byte, 1))
+ return -1;
+ if (byte != EC_FRAMING_BYTE &&
+ grub_get_time_ms () - start > FRAMING_TIMEOUT_MS)
+ {
+ grub_dprintf ("cros", "Timeout waiting for framing byte.\n");
+ return -1;
+ }
+ }
+ while (byte != EC_FRAMING_BYTE);
+ return 0;
+}
+
+/*
+ * Calculate a simple 8-bit checksum of a data block
+ *
+ * @param data Data block to checksum
+ * @param size Size of data block in bytes
+ * @return checksum value (0 to 255)
+ */
+static grub_uint8_t
+cros_ec_calc_checksum (const void *data, int size)
+{
+ grub_uint8_t csum;
+ const grub_uint8_t *bytes = data;
+ int i;
+
+ for (i = csum = 0; i < size; i++)
+ csum += bytes[i];
+ return csum & 0xff;
+}
+
+enum
+{
+ /* response, arglen */
+ CROS_EC_SPI_IN_HDR_SIZE = 2,
+ /* version, cmd, arglen */
+ CROS_EC_SPI_OUT_HDR_SIZE = 3
+};
+
+static grub_uint8_t busbuf[256];
+#define MSG_BYTES ((int)sizeof (busbuf))
+
+static int
+ec_command (const struct grub_fdtbus_dev *dev, int cmd, int cmd_version,
+ const void *dout, int dout_len, void *din, int din_len)
+{
+ const struct grub_fdtbus_dev *spi = dev->parent;
+ grub_uint8_t *bytes;
+
+ /* Header + data + checksum. */
+ grub_uint32_t out_bytes = CROS_EC_SPI_OUT_HDR_SIZE + dout_len + 1;
+ grub_uint32_t in_bytes = CROS_EC_SPI_IN_HDR_SIZE + din_len + 1;
+
+ /*
+ * Sanity-check I/O sizes given transaction overhead in internal
+ * buffers.
+ */
+ if (out_bytes > MSG_BYTES)
+ {
+ grub_dprintf ("cros", "Cannot send %d bytes\n", dout_len);
+ return -1;
+ }
+ if (in_bytes > MSG_BYTES)
+ {
+ grub_dprintf ("cros", "Cannot receive %d bytes\n", din_len);
+ return -1;
+ }
+
+ /* Prepare the output. */
+ bytes = busbuf;
+ *bytes++ = EC_CMD_VERSION0 + cmd_version;
+ *bytes++ = cmd;
+ *bytes++ = dout_len;
+ grub_memcpy (bytes, dout, dout_len);
+ bytes += dout_len;
+
+ *bytes++ = cros_ec_calc_checksum (busbuf,
+ CROS_EC_SPI_OUT_HDR_SIZE + dout_len);
+
+ /* Depthcharge uses 200 us here but GRUB timer resolution is only 1ms,
+ decrease this when we increase timer resolution. */
+ while (grub_get_time_ms () - last_transfer < 1)
+ ;
+
+ if (spi->driver->start (spi))
+ return -1;
+
+ /* Allow EC to ramp up clock after being awoken. */
+ /* Depthcharge only waits 100 us here but GRUB timer resolution is only 1ms,
+ decrease this when we increase timer resolution. */
+ grub_millisleep (1);
+
+ if (spi->driver->send (spi, busbuf, out_bytes))
+ {
+ stop_bus (spi);
+ return -1;
+ }
+
+ /* Wait until the EC is ready. */
+ if (wait_for_frame (spi))
+ {
+ stop_bus (spi);
+ return -1;
+ }
+
+ /* Read the response code and the data length. */
+ bytes = busbuf;
+ if (spi->driver->receive (spi, bytes, 2))
+ {
+ stop_bus (spi);
+ return -1;
+ }
+ grub_uint8_t result = *bytes++;
+ grub_uint8_t length = *bytes++;
+
+ /* Make sure there's enough room for the data. */
+ if (CROS_EC_SPI_IN_HDR_SIZE + length + 1 > MSG_BYTES)
+ {
+ grub_dprintf ("cros", "Received length %#02x too large\n", length);
+ stop_bus (spi);
+ return -1;
+ }
+
+ /* Read the data and the checksum, and finish up. */
+ if (spi->driver->receive (spi, bytes, length + 1))
+ {
+ stop_bus (spi);
+ return -1;
+ }
+ bytes += length;
+ int expected = *bytes++;
+ stop_bus (spi);
+
+ /* Check the integrity of the response. */
+ if (result != 0)
+ {
+ grub_dprintf ("cros", "Received bad result code %d\n", result);
+ return -result;
+ }
+
+ int csum = cros_ec_calc_checksum (busbuf,
+ CROS_EC_SPI_IN_HDR_SIZE + length);
+
+ if (csum != expected)
+ {
+ grub_dprintf ("cros", "Invalid checksum rx %#02x, calced %#02x\n",
+ expected, csum);
+ return -1;
+ }
+
+ /* If the caller wants the response, copy it out for them. */
+ if (length < din_len)
+ din_len = length;
+ if (din)
+ {
+ grub_memcpy (din, (grub_uint8_t *) busbuf + CROS_EC_SPI_IN_HDR_SIZE, din_len);
+ }
+
+ return din_len;
+}
+
+int
+grub_cros_ec_scan_keyboard (const struct grub_fdtbus_dev *dev, struct grub_cros_ec_keyscan *scan)
+{
+ if (ec_command (dev, EC_CMD_MKBP_STATE, 0, NULL, 0, scan,
+ sizeof (*scan)) < (int) sizeof (*scan))
+ return -1;
+
+ return 0;
+}
+
+int
+grub_cros_ec_validate (const struct grub_fdtbus_dev *dev)
+{
+ if (!grub_fdtbus_is_compatible("google,cros-ec-spi", dev))
+ return 0;
+ if (!dev->parent)
+ return 0;
+ if (!dev->parent->driver)
+ return 0;
+ if (!dev->parent->driver->send
+ || !dev->parent->driver->receive)
+ return 0;
+ return 1;
+}
+
diff --git a/grub-core/term/arm/pl050.c b/grub-core/term/arm/pl050.c
new file mode 100644
index 0000000000000000000000000000000000000000..e4cda305666df20eba26e10d74b879361e83d6ea
--- /dev/null
+++ b/grub-core/term/arm/pl050.c
@@ -0,0 +1,189 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2007,2008,2009 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see .
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+static volatile grub_uint32_t *pl050_regs;
+
+struct grub_ps2_state ps2_state;
+
+static void
+keyboard_controller_wait_until_ready (void)
+{
+ while (! (pl050_regs[1] & 0x40));
+}
+
+static grub_uint8_t
+wait_ack (void)
+{
+ grub_uint64_t endtime;
+ grub_uint8_t ack;
+
+ endtime = grub_get_time_ms () + 20;
+ do
+ ack = pl050_regs[2];
+ while (ack != GRUB_AT_ACK && ack != GRUB_AT_NACK
+ && grub_get_time_ms () < endtime);
+ return ack;
+}
+
+
+static int
+write_mode (int mode)
+{
+ unsigned i;
+ for (i = 0; i < GRUB_AT_TRIES; i++)
+ {
+ grub_uint8_t ack;
+ keyboard_controller_wait_until_ready ();
+ pl050_regs[2] = 0xf0;
+ keyboard_controller_wait_until_ready ();
+ pl050_regs[2] = mode;
+ keyboard_controller_wait_until_ready ();
+ ack = wait_ack ();
+ if (ack == GRUB_AT_NACK)
+ continue;
+ if (ack == GRUB_AT_ACK)
+ break;
+ return 0;
+ }
+
+ return (i != GRUB_AT_TRIES);
+}
+
+static int
+query_mode (void)
+{
+ grub_uint8_t ret;
+ int e;
+
+ e = write_mode (0);
+ if (!e)
+ return 0;
+
+ keyboard_controller_wait_until_ready ();
+
+ do
+ ret = pl050_regs[2];
+ while (ret == GRUB_AT_ACK);
+
+ /* QEMU translates the set even in no-translate mode. */
+ if (ret == 0x43 || ret == 1)
+ return 1;
+ if (ret == 0x41 || ret == 2)
+ return 2;
+ if (ret == 0x3f || ret == 3)
+ return 3;
+ return 0;
+}
+
+static void
+set_scancodes (void)
+{
+ write_mode (2);
+ ps2_state.current_set = query_mode ();
+ grub_dprintf ("atkeyb", "returned set %d\n", ps2_state.current_set);
+ if (ps2_state.current_set == 2)
+ return;
+
+ write_mode (1);
+ ps2_state.current_set = query_mode ();
+ grub_dprintf ("atkeyb", "returned set %d\n", ps2_state.current_set);
+ if (ps2_state.current_set == 1)
+ return;
+ grub_dprintf ("atkeyb", "no supported scancode set found\n");
+}
+
+static void
+keyboard_controller_led (grub_uint8_t leds)
+{
+ keyboard_controller_wait_until_ready ();
+ pl050_regs[2] = 0xed;
+ keyboard_controller_wait_until_ready ();
+ pl050_regs[2] = leds & 0x7;
+}
+
+/* If there is a character pending, return it;
+ otherwise return GRUB_TERM_NO_KEY. */
+static int
+grub_pl050_keyboard_getkey (struct grub_term_input *term __attribute__ ((unused)))
+{
+ grub_uint8_t at_key;
+ int ret;
+ grub_uint8_t old_led;
+
+ if (!(pl050_regs[1] & 0x10))
+ return -1;
+ at_key = pl050_regs[2];
+ old_led = ps2_state.led_status;
+
+ ret = grub_ps2_process_incoming_byte (&ps2_state, at_key);
+ if (old_led != ps2_state.led_status)
+ keyboard_controller_led (ps2_state.led_status);
+ return ret;
+}
+
+static struct grub_term_input grub_pl050_keyboard_term =
+ {
+ .name = "pl050_keyboard",
+ .getkey = grub_pl050_keyboard_getkey
+ };
+
+static grub_err_t
+pl050_attach(const struct grub_fdtbus_dev *dev)
+{
+ const grub_uint32_t *reg;
+ reg = grub_fdtbus_get_prop (dev, "reg", 0);
+
+ /* Mouse. Nothing to do. */
+ if (grub_be_to_cpu32 (*reg) == 0x7000)
+ return 0;
+
+ pl050_regs = grub_fdtbus_map_reg (dev, 0, 0);
+
+ if (!grub_fdtbus_is_mapping_valid (pl050_regs))
+ return grub_error (GRUB_ERR_IO, "could not map pl050");
+
+ ps2_state.at_keyboard_status = 0;
+ set_scancodes ();
+ keyboard_controller_led (ps2_state.led_status);
+
+ grub_term_register_input ("pl050_keyboard", &grub_pl050_keyboard_term);
+ return GRUB_ERR_NONE;
+}
+
+struct grub_fdtbus_driver pl050 =
+{
+ .compatible = "arm,pl050",
+ .attach = pl050_attach
+};
+
+void
+grub_pl050_init (void)
+{
+ grub_fdtbus_register (&pl050);
+}
diff --git a/grub-core/term/at_keyboard.c b/grub-core/term/at_keyboard.c
index b4ea9ff7e637f59c653b86cea79d4d664c78af84..f0a986eb176aef6c4fe3f5a65c646756e5bbde56 100644
--- a/grub-core/term/at_keyboard.c
+++ b/grub-core/term/at_keyboard.c
@@ -22,215 +22,26 @@
#include
#include
#include
-#include
#include
#include
+#include
GRUB_MOD_LICENSE ("GPLv3+");
-static short at_keyboard_status = 0;
-static int e0_received = 0;
-static int f0_received = 0;
-
-static grub_uint8_t led_status;
-
-#define KEYBOARD_LED_SCROLL (1 << 0)
-#define KEYBOARD_LED_NUM (1 << 1)
-#define KEYBOARD_LED_CAPS (1 << 2)
-
static grub_uint8_t grub_keyboard_controller_orig;
static grub_uint8_t grub_keyboard_orig_set;
-static grub_uint8_t current_set;
-
-static void
-grub_keyboard_controller_init (void);
-
-static const grub_uint8_t set1_mapping[128] =
- {
- /* 0x00 */ 0 /* Unused */, GRUB_KEYBOARD_KEY_ESCAPE,
- /* 0x02 */ GRUB_KEYBOARD_KEY_1, GRUB_KEYBOARD_KEY_2,
- /* 0x04 */ GRUB_KEYBOARD_KEY_3, GRUB_KEYBOARD_KEY_4,
- /* 0x06 */ GRUB_KEYBOARD_KEY_5, GRUB_KEYBOARD_KEY_6,
- /* 0x08 */ GRUB_KEYBOARD_KEY_7, GRUB_KEYBOARD_KEY_8,
- /* 0x0a */ GRUB_KEYBOARD_KEY_9, GRUB_KEYBOARD_KEY_0,
- /* 0x0c */ GRUB_KEYBOARD_KEY_DASH, GRUB_KEYBOARD_KEY_EQUAL,
- /* 0x0e */ GRUB_KEYBOARD_KEY_BACKSPACE, GRUB_KEYBOARD_KEY_TAB,
- /* 0x10 */ GRUB_KEYBOARD_KEY_Q, GRUB_KEYBOARD_KEY_W,
- /* 0x12 */ GRUB_KEYBOARD_KEY_E, GRUB_KEYBOARD_KEY_R,
- /* 0x14 */ GRUB_KEYBOARD_KEY_T, GRUB_KEYBOARD_KEY_Y,
- /* 0x16 */ GRUB_KEYBOARD_KEY_U, GRUB_KEYBOARD_KEY_I,
- /* 0x18 */ GRUB_KEYBOARD_KEY_O, GRUB_KEYBOARD_KEY_P,
- /* 0x1a */ GRUB_KEYBOARD_KEY_LBRACKET, GRUB_KEYBOARD_KEY_RBRACKET,
- /* 0x1c */ GRUB_KEYBOARD_KEY_ENTER, GRUB_KEYBOARD_KEY_LEFT_CTRL,
- /* 0x1e */ GRUB_KEYBOARD_KEY_A, GRUB_KEYBOARD_KEY_S,
- /* 0x20 */ GRUB_KEYBOARD_KEY_D, GRUB_KEYBOARD_KEY_F,
- /* 0x22 */ GRUB_KEYBOARD_KEY_G, GRUB_KEYBOARD_KEY_H,
- /* 0x24 */ GRUB_KEYBOARD_KEY_J, GRUB_KEYBOARD_KEY_K,
- /* 0x26 */ GRUB_KEYBOARD_KEY_L, GRUB_KEYBOARD_KEY_SEMICOLON,
- /* 0x28 */ GRUB_KEYBOARD_KEY_DQUOTE, GRUB_KEYBOARD_KEY_RQUOTE,
- /* 0x2a */ GRUB_KEYBOARD_KEY_LEFT_SHIFT, GRUB_KEYBOARD_KEY_BACKSLASH,
- /* 0x2c */ GRUB_KEYBOARD_KEY_Z, GRUB_KEYBOARD_KEY_X,
- /* 0x2e */ GRUB_KEYBOARD_KEY_C, GRUB_KEYBOARD_KEY_V,
- /* 0x30 */ GRUB_KEYBOARD_KEY_B, GRUB_KEYBOARD_KEY_N,
- /* 0x32 */ GRUB_KEYBOARD_KEY_M, GRUB_KEYBOARD_KEY_COMMA,
- /* 0x34 */ GRUB_KEYBOARD_KEY_DOT, GRUB_KEYBOARD_KEY_SLASH,
- /* 0x36 */ GRUB_KEYBOARD_KEY_RIGHT_SHIFT, GRUB_KEYBOARD_KEY_NUMMUL,
- /* 0x38 */ GRUB_KEYBOARD_KEY_LEFT_ALT, GRUB_KEYBOARD_KEY_SPACE,
- /* 0x3a */ GRUB_KEYBOARD_KEY_CAPS_LOCK, GRUB_KEYBOARD_KEY_F1,
- /* 0x3c */ GRUB_KEYBOARD_KEY_F2, GRUB_KEYBOARD_KEY_F3,
- /* 0x3e */ GRUB_KEYBOARD_KEY_F4, GRUB_KEYBOARD_KEY_F5,
- /* 0x40 */ GRUB_KEYBOARD_KEY_F6, GRUB_KEYBOARD_KEY_F7,
- /* 0x42 */ GRUB_KEYBOARD_KEY_F8, GRUB_KEYBOARD_KEY_F9,
- /* 0x44 */ GRUB_KEYBOARD_KEY_F10, GRUB_KEYBOARD_KEY_NUM_LOCK,
- /* 0x46 */ GRUB_KEYBOARD_KEY_SCROLL_LOCK, GRUB_KEYBOARD_KEY_NUM7,
- /* 0x48 */ GRUB_KEYBOARD_KEY_NUM8, GRUB_KEYBOARD_KEY_NUM9,
- /* 0x4a */ GRUB_KEYBOARD_KEY_NUMMINUS, GRUB_KEYBOARD_KEY_NUM4,
- /* 0x4c */ GRUB_KEYBOARD_KEY_NUM5, GRUB_KEYBOARD_KEY_NUM6,
- /* 0x4e */ GRUB_KEYBOARD_KEY_NUMPLUS, GRUB_KEYBOARD_KEY_NUM1,
- /* 0x50 */ GRUB_KEYBOARD_KEY_NUM2, GRUB_KEYBOARD_KEY_NUM3,
- /* 0x52 */ GRUB_KEYBOARD_KEY_NUM0, GRUB_KEYBOARD_KEY_NUMDOT,
- /* 0x54 */ 0, 0,
- /* 0x56 */ GRUB_KEYBOARD_KEY_102ND, GRUB_KEYBOARD_KEY_F11,
- /* 0x58 */ GRUB_KEYBOARD_KEY_F12, 0,
- /* 0x5a */ 0, 0,
- /* 0x5c */ 0, 0,
- /* 0x5e */ 0, 0,
- /* 0x60 */ 0, 0,
- /* 0x62 */ 0, 0,
- /* OLPC keys. Just mapped to normal keys. */
- /* 0x64 */ 0, GRUB_KEYBOARD_KEY_UP,
- /* 0x66 */ GRUB_KEYBOARD_KEY_DOWN, GRUB_KEYBOARD_KEY_LEFT,
- /* 0x68 */ GRUB_KEYBOARD_KEY_RIGHT, 0,
- /* 0x6a */ 0, 0,
- /* 0x6c */ 0, 0,
- /* 0x6e */ 0, 0,
- /* 0x70 */ 0, 0,
- /* 0x72 */ 0, GRUB_KEYBOARD_KEY_JP_RO,
- /* 0x74 */ 0, 0,
- /* 0x76 */ 0, 0,
- /* 0x78 */ 0, 0,
- /* 0x7a */ 0, 0,
- /* 0x7c */ 0, GRUB_KEYBOARD_KEY_JP_YEN,
- /* 0x7e */ GRUB_KEYBOARD_KEY_KPCOMMA
- };
-
-static const struct
-{
- grub_uint8_t from, to;
-} set1_e0_mapping[] =
- {
- {0x1c, GRUB_KEYBOARD_KEY_NUMENTER},
- {0x1d, GRUB_KEYBOARD_KEY_RIGHT_CTRL},
- {0x35, GRUB_KEYBOARD_KEY_NUMSLASH },
- {0x38, GRUB_KEYBOARD_KEY_RIGHT_ALT},
- {0x47, GRUB_KEYBOARD_KEY_HOME},
- {0x48, GRUB_KEYBOARD_KEY_UP},
- {0x49, GRUB_KEYBOARD_KEY_PPAGE},
- {0x4b, GRUB_KEYBOARD_KEY_LEFT},
- {0x4d, GRUB_KEYBOARD_KEY_RIGHT},
- {0x4f, GRUB_KEYBOARD_KEY_END},
- {0x50, GRUB_KEYBOARD_KEY_DOWN},
- {0x51, GRUB_KEYBOARD_KEY_NPAGE},
- {0x52, GRUB_KEYBOARD_KEY_INSERT},
- {0x53, GRUB_KEYBOARD_KEY_DELETE},
- };
-
-static const grub_uint8_t set2_mapping[256] =
- {
- /* 0x00 */ 0, GRUB_KEYBOARD_KEY_F9,
- /* 0x02 */ 0, GRUB_KEYBOARD_KEY_F5,
- /* 0x04 */ GRUB_KEYBOARD_KEY_F3, GRUB_KEYBOARD_KEY_F1,
- /* 0x06 */ GRUB_KEYBOARD_KEY_F2, GRUB_KEYBOARD_KEY_F12,
- /* 0x08 */ 0, GRUB_KEYBOARD_KEY_F10,
- /* 0x0a */ GRUB_KEYBOARD_KEY_F8, GRUB_KEYBOARD_KEY_F6,
- /* 0x0c */ GRUB_KEYBOARD_KEY_F4, GRUB_KEYBOARD_KEY_TAB,
- /* 0x0e */ GRUB_KEYBOARD_KEY_RQUOTE, 0,
- /* 0x10 */ 0, GRUB_KEYBOARD_KEY_LEFT_ALT,
- /* 0x12 */ GRUB_KEYBOARD_KEY_LEFT_SHIFT, 0,
- /* 0x14 */ GRUB_KEYBOARD_KEY_LEFT_CTRL, GRUB_KEYBOARD_KEY_Q,
- /* 0x16 */ GRUB_KEYBOARD_KEY_1, 0,
- /* 0x18 */ 0, 0,
- /* 0x1a */ GRUB_KEYBOARD_KEY_Z, GRUB_KEYBOARD_KEY_S,
- /* 0x1c */ GRUB_KEYBOARD_KEY_A, GRUB_KEYBOARD_KEY_W,
- /* 0x1e */ GRUB_KEYBOARD_KEY_2, 0,
- /* 0x20 */ 0, GRUB_KEYBOARD_KEY_C,
- /* 0x22 */ GRUB_KEYBOARD_KEY_X, GRUB_KEYBOARD_KEY_D,
- /* 0x24 */ GRUB_KEYBOARD_KEY_E, GRUB_KEYBOARD_KEY_4,
- /* 0x26 */ GRUB_KEYBOARD_KEY_3, 0,
- /* 0x28 */ 0, GRUB_KEYBOARD_KEY_SPACE,
- /* 0x2a */ GRUB_KEYBOARD_KEY_V, GRUB_KEYBOARD_KEY_F,
- /* 0x2c */ GRUB_KEYBOARD_KEY_T, GRUB_KEYBOARD_KEY_R,
- /* 0x2e */ GRUB_KEYBOARD_KEY_5, 0,
- /* 0x30 */ 0, GRUB_KEYBOARD_KEY_N,
- /* 0x32 */ GRUB_KEYBOARD_KEY_B, GRUB_KEYBOARD_KEY_H,
- /* 0x34 */ GRUB_KEYBOARD_KEY_G, GRUB_KEYBOARD_KEY_Y,
- /* 0x36 */ GRUB_KEYBOARD_KEY_6, 0,
- /* 0x38 */ 0, 0,
- /* 0x3a */ GRUB_KEYBOARD_KEY_M, GRUB_KEYBOARD_KEY_J,
- /* 0x3c */ GRUB_KEYBOARD_KEY_U, GRUB_KEYBOARD_KEY_7,
- /* 0x3e */ GRUB_KEYBOARD_KEY_8, 0,
- /* 0x40 */ 0, GRUB_KEYBOARD_KEY_COMMA,
- /* 0x42 */ GRUB_KEYBOARD_KEY_K, GRUB_KEYBOARD_KEY_I,
- /* 0x44 */ GRUB_KEYBOARD_KEY_O, GRUB_KEYBOARD_KEY_0,
- /* 0x46 */ GRUB_KEYBOARD_KEY_9, 0,
- /* 0x48 */ 0, GRUB_KEYBOARD_KEY_DOT,
- /* 0x4a */ GRUB_KEYBOARD_KEY_SLASH, GRUB_KEYBOARD_KEY_L,
- /* 0x4c */ GRUB_KEYBOARD_KEY_SEMICOLON, GRUB_KEYBOARD_KEY_P,
- /* 0x4e */ GRUB_KEYBOARD_KEY_DASH, 0,
- /* 0x50 */ 0, GRUB_KEYBOARD_KEY_JP_RO,
- /* 0x52 */ GRUB_KEYBOARD_KEY_DQUOTE, 0,
- /* 0x54 */ GRUB_KEYBOARD_KEY_LBRACKET, GRUB_KEYBOARD_KEY_EQUAL,
- /* 0x56 */ 0, 0,
- /* 0x58 */ GRUB_KEYBOARD_KEY_CAPS_LOCK, GRUB_KEYBOARD_KEY_RIGHT_SHIFT,
- /* 0x5a */ GRUB_KEYBOARD_KEY_ENTER, GRUB_KEYBOARD_KEY_RBRACKET,
- /* 0x5c */ 0, GRUB_KEYBOARD_KEY_BACKSLASH,
- /* 0x5e */ 0, 0,
- /* 0x60 */ 0, GRUB_KEYBOARD_KEY_102ND,
- /* 0x62 */ 0, 0,
- /* 0x64 */ 0, 0,
- /* 0x66 */ GRUB_KEYBOARD_KEY_BACKSPACE, 0,
- /* 0x68 */ 0, GRUB_KEYBOARD_KEY_NUM1,
- /* 0x6a */ GRUB_KEYBOARD_KEY_JP_YEN, GRUB_KEYBOARD_KEY_NUM4,
- /* 0x6c */ GRUB_KEYBOARD_KEY_NUM7, GRUB_KEYBOARD_KEY_KPCOMMA,
- /* 0x6e */ 0, 0,
- /* 0x70 */ GRUB_KEYBOARD_KEY_NUM0, GRUB_KEYBOARD_KEY_NUMDOT,
- /* 0x72 */ GRUB_KEYBOARD_KEY_NUM2, GRUB_KEYBOARD_KEY_NUM5,
- /* 0x74 */ GRUB_KEYBOARD_KEY_NUM6, GRUB_KEYBOARD_KEY_NUM8,
- /* 0x76 */ GRUB_KEYBOARD_KEY_ESCAPE, GRUB_KEYBOARD_KEY_NUM_LOCK,
- /* 0x78 */ GRUB_KEYBOARD_KEY_F11, GRUB_KEYBOARD_KEY_NUMPLUS,
- /* 0x7a */ GRUB_KEYBOARD_KEY_NUM3, GRUB_KEYBOARD_KEY_NUMMINUS,
- /* 0x7c */ GRUB_KEYBOARD_KEY_NUMMUL, GRUB_KEYBOARD_KEY_NUM9,
- /* 0x7e */ GRUB_KEYBOARD_KEY_SCROLL_LOCK, 0,
- /* 0x80 */ 0, 0,
- /* 0x82 */ 0, GRUB_KEYBOARD_KEY_F7,
- };
-
-static const struct
-{
- grub_uint8_t from, to;
-} set2_e0_mapping[] =
- {
- {0x11, GRUB_KEYBOARD_KEY_RIGHT_ALT},
- {0x14, GRUB_KEYBOARD_KEY_RIGHT_CTRL},
- {0x4a, GRUB_KEYBOARD_KEY_NUMSLASH},
- {0x5a, GRUB_KEYBOARD_KEY_NUMENTER},
- {0x69, GRUB_KEYBOARD_KEY_END},
- {0x6b, GRUB_KEYBOARD_KEY_LEFT},
- {0x6c, GRUB_KEYBOARD_KEY_HOME},
- {0x70, GRUB_KEYBOARD_KEY_INSERT},
- {0x71, GRUB_KEYBOARD_KEY_DELETE},
- {0x72, GRUB_KEYBOARD_KEY_DOWN},
- {0x74, GRUB_KEYBOARD_KEY_RIGHT},
- {0x75, GRUB_KEYBOARD_KEY_UP},
- {0x7a, GRUB_KEYBOARD_KEY_NPAGE},
- {0x7d, GRUB_KEYBOARD_KEY_PPAGE},
- };
+struct grub_ps2_state ps2_state;
static int ping_sent;
+static void
+grub_keyboard_controller_init (void);
+
static void
keyboard_controller_wait_until_ready (void)
{
+ /* 50 us would be enough but our current time resolution is 1ms. */
+ grub_millisleep (1);
while (! KEYBOARD_COMMAND_ISREADY (grub_inb (KEYBOARD_REG_STATUS)));
}
@@ -241,10 +52,11 @@ wait_ack (void)
grub_uint8_t ack;
endtime = grub_get_time_ms () + 20;
- do
+ do {
+ keyboard_controller_wait_until_ready ();
ack = grub_inb (KEYBOARD_REG_DATA);
- while (ack != GRUB_AT_ACK && ack != GRUB_AT_NACK
- && grub_get_time_ms () < endtime);
+ } while (ack != GRUB_AT_ACK && ack != GRUB_AT_NACK
+ && grub_get_time_ms () < endtime);
return ack;
}
@@ -326,12 +138,10 @@ query_mode (void)
if (!e)
return 0;
- keyboard_controller_wait_until_ready ();
-
- do
+ do {
+ keyboard_controller_wait_until_ready ();
ret = grub_inb (KEYBOARD_REG_DATA);
- while (ret == GRUB_AT_ACK);
-
+ } while (ret == GRUB_AT_ACK);
/* QEMU translates the set even in no-translate mode. */
if (ret == 0x43 || ret == 1)
return 1;
@@ -350,28 +160,32 @@ set_scancodes (void)
if (!grub_keyboard_orig_set)
{
grub_dprintf ("atkeyb", "No sets support assumed\n");
- current_set = 1;
+ ps2_state.current_set = 1;
return;
}
#if !USE_SCANCODE_SET
- current_set = 1;
+ ps2_state.current_set = 1;
return;
#else
grub_keyboard_controller_write (grub_keyboard_controller_orig
- & ~KEYBOARD_AT_TRANSLATE);
+ & ~KEYBOARD_AT_TRANSLATE
+ & ~KEYBOARD_AT_DISABLE);
+
+ keyboard_controller_wait_until_ready ();
+ grub_outb (KEYBOARD_COMMAND_ENABLE, KEYBOARD_REG_DATA);
write_mode (2);
- current_set = query_mode ();
- grub_dprintf ("atkeyb", "returned set %d\n", current_set);
- if (current_set == 2)
+ ps2_state.current_set = query_mode ();
+ grub_dprintf ("atkeyb", "returned set %d\n", ps2_state.current_set);
+ if (ps2_state.current_set == 2)
return;
write_mode (1);
- current_set = query_mode ();
- grub_dprintf ("atkeyb", "returned set %d\n", current_set);
- if (current_set == 1)
+ ps2_state.current_set = query_mode ();
+ grub_dprintf ("atkeyb", "returned set %d\n", ps2_state.current_set);
+ if (ps2_state.current_set == 1)
return;
grub_dprintf ("atkeyb", "no supported scancode set found\n");
#endif
@@ -386,164 +200,10 @@ keyboard_controller_led (grub_uint8_t leds)
grub_outb (leds & 0x7, KEYBOARD_REG_DATA);
}
-static int
-fetch_key (int *is_break)
-{
- int was_ext = 0;
- grub_uint8_t at_key;
- int ret = 0;
-
- if (! KEYBOARD_ISREADY (grub_inb (KEYBOARD_REG_STATUS)))
- return -1;
- at_key = grub_inb (KEYBOARD_REG_DATA);
- /* May happen if no keyboard is connected. Just ignore this. */
- if (at_key == 0xff)
- return -1;
- if (at_key == 0xe0)
- {
- e0_received = 1;
- return -1;
- }
-
- if ((current_set == 2 || current_set == 3) && at_key == 0xf0)
- {
- f0_received = 1;
- return -1;
- }
-
- /* Setting LEDs may generate ACKs. */
- if (at_key == GRUB_AT_ACK)
- return -1;
-
- was_ext = e0_received;
- e0_received = 0;
-
- switch (current_set)
- {
- case 1:
- *is_break = !!(at_key & 0x80);
- if (!was_ext)
- ret = set1_mapping[at_key & 0x7f];
- else
- {
- unsigned i;
- for (i = 0; i < ARRAY_SIZE (set1_e0_mapping); i++)
- if (set1_e0_mapping[i].from == (at_key & 0x7f))
- {
- ret = set1_e0_mapping[i].to;
- break;
- }
- }
- break;
- case 2:
- *is_break = f0_received;
- f0_received = 0;
- if (!was_ext)
- ret = set2_mapping[at_key];
- else
- {
- unsigned i;
- for (i = 0; i < ARRAY_SIZE (set2_e0_mapping); i++)
- if (set2_e0_mapping[i].from == at_key)
- {
- ret = set2_e0_mapping[i].to;
- break;
- }
- }
- break;
- default:
- return -1;
- }
- if (!ret)
- {
- if (was_ext)
- grub_dprintf ("atkeyb", "Unknown key 0xe0+0x%02x from set %d\n",
- at_key, current_set);
- else
- grub_dprintf ("atkeyb", "Unknown key 0x%02x from set %d\n",
- at_key, current_set);
- return -1;
- }
- return ret;
-}
-
-/* FIXME: This should become an interrupt service routine. For now
- it's just used to catch events from control keys. */
-static int
-grub_keyboard_isr (grub_keyboard_key_t key, int is_break)
-{
- if (!is_break)
- switch (key)
- {
- case GRUB_KEYBOARD_KEY_LEFT_SHIFT:
- at_keyboard_status |= GRUB_TERM_STATUS_LSHIFT;
- return 1;
- case GRUB_KEYBOARD_KEY_RIGHT_SHIFT:
- at_keyboard_status |= GRUB_TERM_STATUS_RSHIFT;
- return 1;
- case GRUB_KEYBOARD_KEY_LEFT_CTRL:
- at_keyboard_status |= GRUB_TERM_STATUS_LCTRL;
- return 1;
- case GRUB_KEYBOARD_KEY_RIGHT_CTRL:
- at_keyboard_status |= GRUB_TERM_STATUS_RCTRL;
- return 1;
- case GRUB_KEYBOARD_KEY_RIGHT_ALT:
- at_keyboard_status |= GRUB_TERM_STATUS_RALT;
- return 1;
- case GRUB_KEYBOARD_KEY_LEFT_ALT:
- at_keyboard_status |= GRUB_TERM_STATUS_LALT;
- return 1;
- default:
- return 0;
- }
- else
- switch (key)
- {
- case GRUB_KEYBOARD_KEY_LEFT_SHIFT:
- at_keyboard_status &= ~GRUB_TERM_STATUS_LSHIFT;
- return 1;
- case GRUB_KEYBOARD_KEY_RIGHT_SHIFT:
- at_keyboard_status &= ~GRUB_TERM_STATUS_RSHIFT;
- return 1;
- case GRUB_KEYBOARD_KEY_LEFT_CTRL:
- at_keyboard_status &= ~GRUB_TERM_STATUS_LCTRL;
- return 1;
- case GRUB_KEYBOARD_KEY_RIGHT_CTRL:
- at_keyboard_status &= ~GRUB_TERM_STATUS_RCTRL;
- return 1;
- case GRUB_KEYBOARD_KEY_RIGHT_ALT:
- at_keyboard_status &= ~GRUB_TERM_STATUS_RALT;
- return 1;
- case GRUB_KEYBOARD_KEY_LEFT_ALT:
- at_keyboard_status &= ~GRUB_TERM_STATUS_LALT;
- return 1;
- default:
- return 0;
- }
-}
-
-/* If there is a raw key pending, return it; otherwise return -1. */
-static int
-grub_keyboard_getkey (void)
-{
- int key;
- int is_break = 0;
-
- key = fetch_key (&is_break);
- if (key == -1)
- return -1;
-
- if (grub_keyboard_isr (key, is_break))
- return -1;
- if (is_break)
- return -1;
- return key;
-}
-
int
grub_at_keyboard_is_alive (void)
{
- if (current_set != 0)
+ if (ps2_state.current_set != 0)
return 1;
if (ping_sent
&& KEYBOARD_COMMAND_ISREADY (grub_inb (KEYBOARD_REG_STATUS))
@@ -566,51 +226,28 @@ grub_at_keyboard_is_alive (void)
static int
grub_at_keyboard_getkey (struct grub_term_input *term __attribute__ ((unused)))
{
- int code;
+ grub_uint8_t at_key;
+ int ret;
+ grub_uint8_t old_led;
if (!grub_at_keyboard_is_alive ())
return GRUB_TERM_NO_KEY;
- code = grub_keyboard_getkey ();
- if (code == -1)
- return GRUB_TERM_NO_KEY;
-#ifdef DEBUG_AT_KEYBOARD
- grub_dprintf ("atkeyb", "Detected key 0x%x\n", code);
-#endif
- switch (code)
- {
- case GRUB_KEYBOARD_KEY_CAPS_LOCK:
- at_keyboard_status ^= GRUB_TERM_STATUS_CAPS;
- led_status ^= KEYBOARD_LED_CAPS;
- keyboard_controller_led (led_status);
+ if (! KEYBOARD_ISREADY (grub_inb (KEYBOARD_REG_STATUS)))
+ return -1;
+ at_key = grub_inb (KEYBOARD_REG_DATA);
+ old_led = ps2_state.led_status;
-#ifdef DEBUG_AT_KEYBOARD
- grub_dprintf ("atkeyb", "caps_lock = %d\n", !!(at_keyboard_status & GRUB_KEYBOARD_STATUS_CAPS_LOCK));
-#endif
- return GRUB_TERM_NO_KEY;
- case GRUB_KEYBOARD_KEY_NUM_LOCK:
- at_keyboard_status ^= GRUB_TERM_STATUS_NUM;
- led_status ^= KEYBOARD_LED_NUM;
- keyboard_controller_led (led_status);
-
-#ifdef DEBUG_AT_KEYBOARD
- grub_dprintf ("atkeyb", "num_lock = %d\n", !!(at_keyboard_status & GRUB_KEYBOARD_STATUS_NUM_LOCK));
-#endif
- return GRUB_TERM_NO_KEY;
- case GRUB_KEYBOARD_KEY_SCROLL_LOCK:
- at_keyboard_status ^= GRUB_TERM_STATUS_SCROLL;
- led_status ^= KEYBOARD_LED_SCROLL;
- keyboard_controller_led (led_status);
- return GRUB_TERM_NO_KEY;
- default:
- return grub_term_map_key (code, at_keyboard_status);
- }
+ ret = grub_ps2_process_incoming_byte (&ps2_state, at_key);
+ if (old_led != ps2_state.led_status)
+ keyboard_controller_led (ps2_state.led_status);
+ return ret;
}
static void
grub_keyboard_controller_init (void)
{
- at_keyboard_status = 0;
+ ps2_state.at_keyboard_status = 0;
/* Drain input buffer. */
while (1)
{
@@ -632,13 +269,13 @@ grub_keyboard_controller_init (void)
grub_keyboard_orig_set = query_mode ();
#endif
set_scancodes ();
- keyboard_controller_led (led_status);
+ keyboard_controller_led (ps2_state.led_status);
}
static grub_err_t
grub_keyboard_controller_fini (struct grub_term_input *term __attribute__ ((unused)))
{
- if (current_set == 0)
+ if (ps2_state.current_set == 0)
return GRUB_ERR_NONE;
if (grub_keyboard_orig_set)
write_mode (grub_keyboard_orig_set);
@@ -655,7 +292,7 @@ grub_at_fini_hw (int noreturn __attribute__ ((unused)))
static grub_err_t
grub_at_restore_hw (void)
{
- if (current_set == 0)
+ if (ps2_state.current_set == 0)
return GRUB_ERR_NONE;
/* Drain input buffer. */
@@ -668,7 +305,7 @@ grub_at_restore_hw (void)
grub_inb (KEYBOARD_REG_DATA);
}
set_scancodes ();
- keyboard_controller_led (led_status);
+ keyboard_controller_led (ps2_state.led_status);
return GRUB_ERR_NONE;
}
diff --git a/grub-core/term/efi/console.c b/grub-core/term/efi/console.c
index 7d31095b1ef8d01886a0516343f2e5c5601265dd..4840cc59d3f68944fb2ca6b40cc6488e74b5da02 100644
--- a/grub-core/term/efi/console.c
+++ b/grub-core/term/efi/console.c
@@ -104,7 +104,7 @@ const unsigned efi_codes[] =
GRUB_TERM_KEY_DC, GRUB_TERM_KEY_PPAGE, GRUB_TERM_KEY_NPAGE, GRUB_TERM_KEY_F1,
GRUB_TERM_KEY_F2, GRUB_TERM_KEY_F3, GRUB_TERM_KEY_F4, GRUB_TERM_KEY_F5,
GRUB_TERM_KEY_F6, GRUB_TERM_KEY_F7, GRUB_TERM_KEY_F8, GRUB_TERM_KEY_F9,
- GRUB_TERM_KEY_F10, GRUB_TERM_KEY_F11, GRUB_TERM_KEY_F12, '\e'
+ GRUB_TERM_KEY_F10, GRUB_TERM_KEY_F11, GRUB_TERM_KEY_F12, GRUB_TERM_ESC
};
static int
@@ -122,6 +122,9 @@ grub_efi_translate_key (grub_efi_input_key_t key)
else
return key.unicode_char;
}
+ /* Some devices send enter with scan_code 0x0d (F3) and unicode_char 0x0d. */
+ else if (key.scan_code == '\r' && key.unicode_char == '\r')
+ return key.unicode_char;
else if (key.scan_code < ARRAY_SIZE (efi_codes))
return efi_codes[key.scan_code];
diff --git a/grub-core/term/i386/coreboot/cbmemc.c b/grub-core/term/i386/coreboot/cbmemc.c
index 25e64a05c03286f644b39398e9e68cbdde333510..cea9b84315bdaf3b1238acc915f35ba6148ffbcf 100644
--- a/grub-core/term/i386/coreboot/cbmemc.c
+++ b/grub-core/term/i386/coreboot/cbmemc.c
@@ -23,17 +23,20 @@
#include
#include
#include
-#include
+#include
#include
#include
GRUB_MOD_LICENSE ("GPLv3+");
+#define CURSOR_MASK ((1 << 28) - 1)
+#define OVERFLOW (1 << 31)
+
struct grub_linuxbios_cbmemc
{
grub_uint32_t size;
- grub_uint32_t pointer;
- char data[0];
+ grub_uint32_t cursor;
+ char body[0];
};
static struct grub_linuxbios_cbmemc *cbmemc;
@@ -41,11 +44,20 @@ static struct grub_linuxbios_cbmemc *cbmemc;
static void
put (struct grub_term_output *term __attribute__ ((unused)), const int c)
{
+ grub_uint32_t flags, cursor;
if (!cbmemc)
return;
- if (cbmemc->pointer < cbmemc->size)
- cbmemc->data[cbmemc->pointer] = c;
- cbmemc->pointer++;
+ flags = cbmemc->cursor & ~CURSOR_MASK;
+ cursor = cbmemc->cursor & CURSOR_MASK;
+ if (cursor >= cbmemc->size)
+ return;
+ cbmemc->body[cursor++] = c;
+ if (cursor >= cbmemc->size)
+ {
+ cursor = 0;
+ flags |= OVERFLOW;
+ }
+ cbmemc->cursor = flags | cursor;
}
struct grub_terminfo_output_state grub_cbmemc_terminfo_output =
@@ -87,21 +99,29 @@ 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;
+ grub_size_t size, cursor;
+ struct grub_linuxbios_cbmemc *real_cbmemc;
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;
+ real_cbmemc = cbmemc;
cbmemc = 0;
- grub_xnputs (str, len);
- cbmemc = cbmemc_saved;
+ cursor = real_cbmemc->cursor & CURSOR_MASK;
+ if (!(real_cbmemc->cursor & OVERFLOW) && cursor < real_cbmemc->size)
+ size = cursor;
+ else
+ size = real_cbmemc->size;
+ if (real_cbmemc->cursor & OVERFLOW)
+ {
+ if (cursor > size)
+ cursor = 0;
+ grub_xnputs(real_cbmemc->body + cursor, size - cursor);
+ grub_xnputs(real_cbmemc->body, cursor);
+ }
+ else
+ grub_xnputs(real_cbmemc->body, size);
+ cbmemc = real_cbmemc;
return 0;
}
diff --git a/grub-core/term/i386/pc/console.c b/grub-core/term/i386/pc/console.c
index 28de46b576a667fd40c5852b16a4bcc3ea681849..f6142a2dea8036f5301c81a9e2fbd5ddbff5fd90 100644
--- a/grub-core/term/i386/pc/console.c
+++ b/grub-core/term/i386/pc/console.c
@@ -204,7 +204,7 @@ static int
grub_console_getkey (struct grub_term_input *term __attribute__ ((unused)))
{
const grub_uint16_t bypass_table[] = {
- 0x0100 | '\e', 0x0f00 | '\t', 0x0e00 | '\b', 0x1c00 | '\r', 0x1c00 | '\n'
+ 0x0100 | GRUB_TERM_ESC, 0x0f00 | GRUB_TERM_TAB, 0x0e00 | GRUB_TERM_BACKSPACE, 0x1c00 | '\r', 0x1c00 | '\n'
};
struct grub_bios_int_registers regs;
unsigned i;
diff --git a/grub-core/term/ps2.c b/grub-core/term/ps2.c
new file mode 100644
index 0000000000000000000000000000000000000000..7ae4e9f2f8cd4a0ba4405c21581f906f7b458379
--- /dev/null
+++ b/grub-core/term/ps2.c
@@ -0,0 +1,387 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2007,2008,2009 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see .
+ */
+
+#include
+#include