Merge pull request #14 from coreos/gnu

Merge upstream GRUB changes
This commit is contained in:
Michael Marineau 2015-08-13 13:32:56 -07:00
commit 91391dc52b
86 changed files with 1883 additions and 1032 deletions

View file

@ -48,6 +48,7 @@ library = {
common = grub-core/partmap/gpt.c; common = grub-core/partmap/gpt.c;
common = grub-core/partmap/msdos.c; common = grub-core/partmap/msdos.c;
common = grub-core/fs/proc.c; common = grub-core/fs/proc.c;
common = grub-core/fs/archelp.c;
}; };
library = { library = {
@ -91,7 +92,6 @@ library = {
common = grub-core/fs/bfs.c; common = grub-core/fs/bfs.c;
common = grub-core/fs/btrfs.c; common = grub-core/fs/btrfs.c;
common = grub-core/fs/cbfs.c; common = grub-core/fs/cbfs.c;
common = grub-core/fs/archelp.c;
common = grub-core/fs/cpio.c; common = grub-core/fs/cpio.c;
common = grub-core/fs/cpio_be.c; common = grub-core/fs/cpio_be.c;
common = grub-core/fs/odc.c; common = grub-core/fs/odc.c;

5
NEWS
View file

@ -17,6 +17,7 @@ New in 2.02:
files. files.
* ZFS features support. * ZFS features support.
* ZFS LZ4 support. * ZFS LZ4 support.
* XFS V5 format support.
* New/improved terminal and video support: * New/improved terminal and video support:
* Monochrome text (matching `hercules' in GRUB Legacy). * Monochrome text (matching `hercules' in GRUB Legacy).
@ -145,6 +146,10 @@ New in 2.02:
Python 2.6. Python 2.6.
* modinfo.sh contains build information now. * modinfo.sh contains build information now.
* Added many new tests to improve robustness. * Added many new tests to improve robustness.
* Target is built without libgcc now. Necessary builtins are reimplemented
directly. This removes requirement for target-specific runtime on build
system.
* emu libusb support removed (was broken and unmaintained).
* Revision control moved to git. * Revision control moved to git.

View file

@ -93,7 +93,7 @@ else
fi fi
grub_cv_prog_objcopy_absolute=yes grub_cv_prog_objcopy_absolute=yes
for link_addr in 0x2000 0x8000 0x7C00; do for link_addr in 0x2000 0x8000 0x7C00; do
if AC_TRY_COMMAND([${CC-cc} ${CFLAGS} -nostdlib ${TARGET_IMG_LDFLAGS_AC} ${TARGET_IMG_BASE_LDOPT},$link_addr conftest.o -o conftest.exec]); then : if AC_TRY_COMMAND([${CC-cc} ${TARGET_CFLAGS} ${TARGET_LDFLAGS} -nostdlib ${TARGET_IMG_LDFLAGS_AC} ${TARGET_IMG_BASE_LDOPT},$link_addr conftest.o -o conftest.exec]); then :
else else
AC_MSG_ERROR([${CC-cc} cannot link at address $link_addr]) AC_MSG_ERROR([${CC-cc} cannot link at address $link_addr])
fi fi

View file

@ -17,6 +17,9 @@ endif
if COND_arm64 if COND_arm64
CFLAGS_PLATFORM += -mcmodel=large CFLAGS_PLATFORM += -mcmodel=large
endif endif
if COND_powerpc_ieee1275
CFLAGS_PLATFORM += -mcpu=powerpc
endif
#FIXME: discover and check XEN headers #FIXME: discover and check XEN headers
CPPFLAGS_XEN = -I/usr/include CPPFLAGS_XEN = -I/usr/include

View file

@ -5,6 +5,7 @@ EXTRA_DIST += gentpl.py
EXTRA_DIST += Makefile.util.def EXTRA_DIST += Makefile.util.def
EXTRA_DIST += Makefile.utilgcry.def EXTRA_DIST += Makefile.utilgcry.def
EXTRA_DIST += asm-tests
EXTRA_DIST += unicode EXTRA_DIST += unicode
EXTRA_DIST += util/import_gcry.py EXTRA_DIST += util/import_gcry.py

View file

@ -116,6 +116,7 @@ if test "x$with_platform" = x; then
x86_64-*) platform=pc ;; x86_64-*) platform=pc ;;
powerpc-*) platform=ieee1275 ;; powerpc-*) platform=ieee1275 ;;
powerpc64-*) platform=ieee1275 ;; powerpc64-*) platform=ieee1275 ;;
powerpc64le-*) platform=ieee1275 ;;
sparc64-*) platform=ieee1275 ;; sparc64-*) platform=ieee1275 ;;
mipsel-*) platform=loongson ;; mipsel-*) platform=loongson ;;
mips-*) platform=arc ;; mips-*) platform=arc ;;
@ -138,6 +139,7 @@ case "$target_cpu"-"$platform" in
x86_64-none) ;; x86_64-none) ;;
x86_64-*) target_cpu=i386 ;; x86_64-*) target_cpu=i386 ;;
powerpc64-ieee1275) target_cpu=powerpc ;; powerpc64-ieee1275) target_cpu=powerpc ;;
powerpc64le-ieee1275) target_cpu=powerpc ;;
esac esac
# Check if the platform is supported, make final adjustments. # Check if the platform is supported, make final adjustments.
@ -560,6 +562,41 @@ AC_COMPILE_IFELSE(
]])], ]])],
[grub_cv_cc_target_clang=no], [grub_cv_cc_target_clang=yes])]) [grub_cv_cc_target_clang=no], [grub_cv_cc_target_clang=yes])])
if test x$target_cpu = xpowerpc; then
AC_CACHE_CHECK([for options to get big-endian compilation], grub_cv_target_cc_big_endian, [
grub_cv_target_cc_big_endian=no
for cand in "-target powerpc -Wl,-EB" "-target powerpc" \
"-target powerpc-linux-gnu -Wl,-EB" "-target powerpc-linux-gnu" \
"-mbig-endian"; do
if test x"$grub_cv_target_cc_big_endian" != xno ; then
break
fi
CFLAGS="$TARGET_CFLAGS $cand -Werror"
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
#if defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && (__ORDER_BIG_ENDIAN__ != __BYTE_ORDER__)
#error still little endian
#endif
asm (".globl start; start:");
void __main (void);
void __main (void) {}
int main (void);
]], [[]])],
[grub_cv_target_cc_big_endian="$cand"], [])
done
])
if test x"$grub_cv_target_cc_big_endian" = xno ; then
AC_MSG_ERROR([could not force big-endian])
fi
skip_linkflags="$(echo "$grub_cv_target_cc_big_endian"|sed 's@-Wl,-EB@@')"
TARGET_CFLAGS="$TARGET_CFLAGS $skip_linkflags"
TARGET_CPPFLAGS="$TARGET_CPPFLAGS $skip_linkflags"
TARGET_CCASFLAGS="$TARGET_CCASFLAGS $skip_linkflags"
TARGET_LDFLAGS="$TARGET_LDFLAGS $grub_cv_target_cc_big_endian"
fi
AC_CACHE_CHECK([for options to compile assembly], [grub_cv_cc_target_asm_compile], [ AC_CACHE_CHECK([for options to compile assembly], [grub_cv_cc_target_asm_compile], [
test_program= test_program=
case "x$target_cpu-$platform" in case "x$target_cpu-$platform" in
@ -686,9 +723,9 @@ if test x"$platform" != xemu ; then
AC_CACHE_CHECK([for options to get soft-float], grub_cv_target_cc_soft_float, [ AC_CACHE_CHECK([for options to get soft-float], grub_cv_target_cc_soft_float, [
grub_cv_target_cc_soft_float=no grub_cv_target_cc_soft_float=no
if test "x$target_cpu" = xarm64; then if test "x$target_cpu" = xarm64; then
CFLAGS="$TARGET_CFLAGS -march=armv8-a+nofp+nosimd -Werror" CFLAGS="$TARGET_CFLAGS -mgeneral-regs-only -Werror"
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])], AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])],
[grub_cv_target_cc_soft_float="-march=armv8-a+nofp+nosimd"], []) [grub_cv_target_cc_soft_float="-mgeneral-regs-only"], [])
fi fi
if test "x$target_cpu" = xia64; then if test "x$target_cpu" = xia64; then
CFLAGS="$TARGET_CFLAGS -mno-inline-float-divide -mno-inline-sqrt -Werror" CFLAGS="$TARGET_CFLAGS -mno-inline-float-divide -mno-inline-sqrt -Werror"
@ -720,15 +757,7 @@ if test x"$platform" != xemu ; then
TARGET_CFLAGS="$TARGET_CFLAGS $grub_cv_target_cc_soft_float" TARGET_CFLAGS="$TARGET_CFLAGS $grub_cv_target_cc_soft_float"
;; ;;
esac esac
case x"$grub_cv_target_cc_soft_float" in
x"-march=armv8-a+nofp+nosimd")
# +nosimd disables also the cache opcodes that we need in asm.
TARGET_CCASFLAGS="$TARGET_CCASFLAGS -march=armv8-a+nofp"
;;
*)
TARGET_CCASFLAGS="$TARGET_CCASFLAGS $grub_cv_target_cc_soft_float" TARGET_CCASFLAGS="$TARGET_CCASFLAGS $grub_cv_target_cc_soft_float"
;;
esac
fi fi
@ -1152,7 +1181,7 @@ fi
# Check for libgcc symbols # Check for libgcc symbols
if test x"$platform" = xemu; then if test x"$platform" = xemu; then
AC_CHECK_FUNCS(__udivsi3 __umodsi3 __divsi3 __modsi3 __divdi3 __moddi3 __udivdi3 __umoddi3 __ctzdi2 __ctzsi2 __aeabi_uidiv __aeabi_uidivmod __aeabi_idiv __aeabi_idivmod __aeabi_ulcmp __muldi3 __aeabi_lmul __aeabi_memcpy __aeabi_memset __aeabi_lasr __aeabi_llsl __aeabi_llsr _restgpr_14_x __ucmpdi2 __ashldi3 __ashrdi3 __lshrdi3 __bswapsi2 __bswapdi2 __bzero __register_frame_info __deregister_frame_info ___chkstk_ms __chkstk_ms) AC_CHECK_FUNCS(__udivsi3 __umodsi3 __divsi3 __modsi3 __divdi3 __moddi3 __udivdi3 __umoddi3 __ctzdi2 __ctzsi2 __aeabi_uidiv __aeabi_uidivmod __aeabi_idiv __aeabi_idivmod __aeabi_ulcmp __muldi3 __aeabi_lmul __aeabi_memcpy __aeabi_memcpy4 __aeabi_memcpy8 __aeabi_memclr __aeabi_memclr4 __aeabi_memclr8 __aeabi_memset __aeabi_lasr __aeabi_llsl __aeabi_llsr _restgpr_14_x __ucmpdi2 __ashldi3 __ashrdi3 __lshrdi3 __bswapsi2 __bswapdi2 __bzero __register_frame_info __deregister_frame_info ___chkstk_ms __chkstk_ms)
fi fi
if test "x$TARGET_APPLE_LINKER" = x1 ; then if test "x$TARGET_APPLE_LINKER" = x1 ; then

View file

@ -5162,8 +5162,10 @@ by @var{shortname} which can be used to remove it (@pxref{net_del_route}).
Perform configuration of @var{card} using DHCP protocol. If no card name Perform configuration of @var{card} using DHCP protocol. If no card name
is specified, try to configure all existing cards. If configuration was is specified, try to configure all existing cards. If configuration was
successful, interface with name @var{card}@samp{:dhcp} and configured successful, interface with name @var{card}@samp{:dhcp} and configured
address is added to @var{card}. If server provided gateway information in address is added to @var{card}.
DHCP ACK packet, it is added as route entry with the name @var{card}@samp{:dhcp:gw}. Additionally the following DHCP options are recognized and processed: @comment If server provided gateway information in
@comment DHCP ACK packet, it is added as route entry with the name @var{card}@samp{:dhcp:gw}.
Additionally the following DHCP options are recognized and processed:
@table @samp @table @samp
@item 1 (Subnet Mask) @item 1 (Subnet Mask)
@ -5426,10 +5428,12 @@ In order to enable authentication support, the @samp{superusers} environment
variable must be set to a list of usernames, separated by any of spaces, variable must be set to a list of usernames, separated by any of spaces,
commas, semicolons, pipes, or ampersands. Superusers are permitted to use commas, semicolons, pipes, or ampersands. Superusers are permitted to use
the GRUB command line, edit menu entries, and execute any menu entry. If the GRUB command line, edit menu entries, and execute any menu entry. If
@samp{superusers} is set, then use of the command line is automatically @samp{superusers} is set, then use of the command line and editing of menu
restricted to superusers. entries are automatically restricted to superusers. Setting @samp{superusers}
to empty string effectively disables both access to CLI and editing of menu
entries.
Other users may be given access to specific menu entries by giving a list of Other users may be allowed to execute specific menu entries by giving a list of
usernames (as above) using the @option{--users} option to the usernames (as above) using the @option{--users} option to the
@samp{menuentry} command (@pxref{menuentry}). If the @option{--unrestricted} @samp{menuentry} command (@pxref{menuentry}). If the @option{--unrestricted}
option is used for a menu entry, then that entry is unrestricted. option is used for a menu entry, then that entry is unrestricted.

View file

@ -82,7 +82,7 @@ GROUPS["softdiv"] = GROUPS["arm"] + ["ia64_efi"]
GROUPS["no_softdiv"] = GRUB_PLATFORMS[:] GROUPS["no_softdiv"] = GRUB_PLATFORMS[:]
for i in GROUPS["softdiv"]: GROUPS["no_softdiv"].remove(i) for i in GROUPS["softdiv"]: GROUPS["no_softdiv"].remove(i)
# Miscelaneous groups schedulded to disappear in future # Miscellaneous groups scheduled to disappear in future
GROUPS["i386_coreboot_multiboot_qemu"] = ["i386_coreboot", "i386_multiboot", "i386_qemu"] GROUPS["i386_coreboot_multiboot_qemu"] = ["i386_coreboot", "i386_multiboot", "i386_qemu"]
GROUPS["nopc"] = GRUB_PLATFORMS[:]; GROUPS["nopc"].remove("i386_pc") GROUPS["nopc"] = GRUB_PLATFORMS[:]; GROUPS["nopc"].remove("i386_pc")
@ -834,6 +834,20 @@ def data(defn, platform):
var_add("dist_" + installdir(defn) + "_DATA", platform_sources(defn, platform)) var_add("dist_" + installdir(defn) + "_DATA", platform_sources(defn, platform))
gvar_add("dist_noinst_DATA", extra_dist(defn)) gvar_add("dist_noinst_DATA", extra_dist(defn))
def transform_data(defn, platform):
name = defn['name']
var_add(installdir(defn) + "_DATA", name)
rule(name, "$(top_builddir)/config.status " + platform_sources(defn, platform) + platform_dependencies(defn, platform), """
(for x in """ + platform_sources(defn, platform) + """; do cat $(srcdir)/"$$x"; done) | $(top_builddir)/config.status --file=$@:-
chmod a+x """ + name + """
""")
gvar_add("CLEANFILES", name)
gvar_add("EXTRA_DIST", extra_dist(defn))
gvar_add("dist_noinst_DATA", platform_sources(defn, platform))
def script(defn, platform): def script(defn, platform):
name = defn['name'] name = defn['name']
@ -881,6 +895,7 @@ rules("library", library)
rules("program", program) rules("program", program)
rules("script", script) rules("script", script)
rules("data", data) rules("data", data)
rules("transform_data", transform_data)
write_output(section='decl') write_output(section='decl')
write_output() write_output()

View file

@ -1,43 +1,43 @@
AutoGen definitions Makefile.tpl; AutoGen definitions Makefile.tpl;
script = { transform_data = {
installdir = noinst; installdir = noinst;
name = gensyminfo.sh; name = gensyminfo.sh;
common = gensyminfo.sh.in; common = gensyminfo.sh.in;
}; };
script = { transform_data = {
installdir = noinst; installdir = noinst;
name = genmod.sh; name = genmod.sh;
common = genmod.sh.in; common = genmod.sh.in;
}; };
script = { transform_data = {
installdir = noinst; installdir = noinst;
name = modinfo.sh; name = modinfo.sh;
common = modinfo.sh.in; common = modinfo.sh.in;
}; };
script = { transform_data = {
installdir = platform; installdir = platform;
name = gmodule.pl; name = gmodule.pl;
common = gmodule.pl.in; common = gmodule.pl.in;
}; };
script = { transform_data = {
installdir = platform; installdir = platform;
name = gdb_grub; name = gdb_grub;
common = gdb_grub.in; common = gdb_grub.in;
}; };
script = { transform_data = {
installdir = platform; installdir = platform;
name = grub.chrp; name = grub.chrp;
common = boot/powerpc/grub.chrp.in; common = boot/powerpc/grub.chrp.in;
enable = powerpc_ieee1275; enable = powerpc_ieee1275;
}; };
script = { transform_data = {
installdir = platform; installdir = platform;
name = bootinfo.txt; name = bootinfo.txt;
common = boot/powerpc/bootinfo.txt.in; common = boot/powerpc/bootinfo.txt.in;

View file

@ -344,7 +344,7 @@ printhex:
nop nop
srl $t1, $a0, 28 srl $t1, $a0, 28
addiu $t1, $t1, -10 addiu $t1, $t1, -10
blt $t1, $zero, 2f bltz $t1, 2f
sll $a0, $a0, 4 sll $a0, $a0, 4
addiu $t1, $t1, 'A'-10-'0' addiu $t1, $t1, 'A'-10-'0'
2: addiu $t1, $t1, '0'+10 2: addiu $t1, $t1, '0'+10
@ -398,7 +398,7 @@ read_spd:
move $t2, $a0 move $t2, $a0
move $t3, $ra move $t3, $ra
lui $a0, %hi(read_spd_fail) lui $a0, %hi(read_spd_fail)
addiu $a0, $a0, %hi(read_spd_fail) addiu $a0, $a0, %lo(read_spd_fail)
/* Send START. */ /* Send START. */
lui $t0, %hi(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1 + GRUB_MACHINE_PCI_IO_BASE_2F) lui $t0, %hi(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1 + GRUB_MACHINE_PCI_IO_BASE_2F)
@ -547,7 +547,7 @@ gpio_dump:
#endif #endif
gpio_dump_end: gpio_dump_end:
.p2align .p2align 3
write_dumpreg: write_dumpreg:
ld $t2, 0($t6) ld $t2, 0($t6)

View file

@ -21,7 +21,6 @@
#include <grub/offsets.h> #include <grub/offsets.h>
#include <grub/machine/memory.h> #include <grub/machine/memory.h>
#include <grub/machine/kernel.h> #include <grub/machine/kernel.h>
#include <grub/cpu/kernel.h>
#include <grub/offsets.h> #include <grub/offsets.h>
#define BASE_ADDR 8 #define BASE_ADDR 8
@ -33,7 +32,6 @@
.globl __start, _start, start .globl __start, _start, start
.set noreorder .set noreorder
.set nomacro .set nomacro
mips_attributes
__start: __start:
_start: _start:
start: start:

View file

@ -55,7 +55,7 @@ grub_pci_device_map_range (grub_pci_device_t dev, grub_addr_t base,
int err; int err;
err = pci_device_map_range (dev, base, size, PCI_DEV_MAP_FLAG_WRITABLE, &addr); err = pci_device_map_range (dev, base, size, PCI_DEV_MAP_FLAG_WRITABLE, &addr);
if (err) if (err)
grub_util_error ("mapping 0x%llx failed (error %d)\n", grub_util_error ("mapping 0x%llx failed (error %d)",
(unsigned long long) base, err); (unsigned long long) base, err);
return addr; return addr;
} }

View file

@ -750,7 +750,10 @@ grub_ohci_setup_transfer (grub_usb_controller_t dev,
{ {
cdata->td_head_virt = grub_ohci_alloc_td (o); cdata->td_head_virt = grub_ohci_alloc_td (o);
if (!cdata->td_head_virt) if (!cdata->td_head_virt)
{
grub_free (cdata);
return GRUB_USB_ERR_INTERNAL; /* We don't need de-allocate ED */ return GRUB_USB_ERR_INTERNAL; /* We don't need de-allocate ED */
}
/* We can set td_head only when ED is not active, i.e. /* We can set td_head only when ED is not active, i.e.
* when it is newly allocated. */ * when it is newly allocated. */
cdata->ed_virt->td_head cdata->ed_virt->td_head

View file

@ -311,8 +311,8 @@ grub_usb_bulk_finish_readwrite (grub_usb_transfer_t transfer)
transfer->size + 1); transfer->size + 1);
grub_free (transfer->transactions); grub_free (transfer->transactions);
grub_free (transfer);
grub_dma_free (transfer->data_chunk); grub_dma_free (transfer->data_chunk);
grub_free (transfer);
} }
static grub_usb_err_t static grub_usb_err_t

View file

@ -180,8 +180,10 @@ grub_acpi_create_ebda (void)
struct grub_acpi_rsdp_v20 *v2; struct grub_acpi_rsdp_v20 *v2;
ebda = (grub_uint8_t *) (grub_addr_t) ((*((grub_uint16_t *)0x40e)) << 4); ebda = (grub_uint8_t *) (grub_addr_t) ((*((grub_uint16_t *)0x40e)) << 4);
grub_dprintf ("acpi", "EBDA @%p\n", ebda);
if (ebda) if (ebda)
ebda_kb_len = *(grub_uint16_t *) ebda; ebda_kb_len = *(grub_uint16_t *) ebda;
grub_dprintf ("acpi", "EBDA length 0x%x\n", ebda_kb_len);
if (ebda_kb_len > 16) if (ebda_kb_len > 16)
ebda_kb_len = 0; ebda_kb_len = 0;
ctx.ebda_len = (ebda_kb_len + 1) << 10; ctx.ebda_len = (ebda_kb_len + 1) << 10;
@ -495,6 +497,8 @@ grub_cmd_acpi (struct grub_extcmd_context *ctxt, int argc, char **args)
if (! rsdp) if (! rsdp)
rsdp = grub_machine_acpi_get_rsdpv1 (); rsdp = grub_machine_acpi_get_rsdpv1 ();
grub_dprintf ("acpi", "RSDP @%p\n", rsdp);
if (rsdp) if (rsdp)
{ {
grub_uint32_t *entry_ptr; grub_uint32_t *entry_ptr;

View file

@ -39,9 +39,17 @@ static const char *descs[] = {
[2] = "before RAM init", [2] = "before RAM init",
[3] = "after RAM init", [3] = "after RAM init",
[4] = "end of romstage", [4] = "end of romstage",
[5] = "start of verified boot",
[6] = "end of verified boot",
[8] = "start of RAM copy", [8] = "start of RAM copy",
[9] = "end of RAM copy", [9] = "end of RAM copy",
[10] = "start of ramstage", [10] = "start of ramstage",
[11] = "start of bootblock",
[12] = "end of bootblock",
[13] = "starting to load romstage",
[14] = "finished loading romstage",
[15] = "starting LZMA decompress (ignore for x86)",
[16] = "finished LZMA decompress (ignore for x86)",
[30] = "device enumerate", [30] = "device enumerate",
[40] = "device configure", [40] = "device configure",
[50] = "device enable", [50] = "device enable",

View file

@ -29,14 +29,15 @@ grub_machine_acpi_get_rsdpv1 (void)
grub_dprintf ("acpi", "Looking for RSDP. Scanning EBDA\n"); grub_dprintf ("acpi", "Looking for RSDP. Scanning EBDA\n");
ebda = (grub_uint8_t *) ((* ((grub_uint16_t *) 0x40e)) << 4); ebda = (grub_uint8_t *) ((* ((grub_uint16_t *) 0x40e)) << 4);
ebda_len = * (grub_uint16_t *) ebda; ebda_len = * (grub_uint16_t *) ebda;
if (! ebda_len) if (! ebda_len) /* FIXME do we really need this check? */
return 0; goto scan_bios;
for (ptr = ebda; ptr < ebda + 0x400; ptr += 16) for (ptr = ebda; ptr < ebda + 0x400; ptr += 16)
if (grub_memcmp (ptr, GRUB_RSDP_SIGNATURE, GRUB_RSDP_SIGNATURE_SIZE) == 0 if (grub_memcmp (ptr, GRUB_RSDP_SIGNATURE, GRUB_RSDP_SIGNATURE_SIZE) == 0
&& grub_byte_checksum (ptr, sizeof (struct grub_acpi_rsdp_v10)) == 0 && grub_byte_checksum (ptr, sizeof (struct grub_acpi_rsdp_v10)) == 0
&& ((struct grub_acpi_rsdp_v10 *) ptr)->revision == 0) && ((struct grub_acpi_rsdp_v10 *) ptr)->revision == 0)
return (struct grub_acpi_rsdp_v10 *) ptr; return (struct grub_acpi_rsdp_v10 *) ptr;
scan_bios:
grub_dprintf ("acpi", "Looking for RSDP. Scanning BIOS\n"); grub_dprintf ("acpi", "Looking for RSDP. Scanning BIOS\n");
for (ptr = (grub_uint8_t *) 0xe0000; ptr < (grub_uint8_t *) 0x100000; for (ptr = (grub_uint8_t *) 0xe0000; ptr < (grub_uint8_t *) 0x100000;
ptr += 16) ptr += 16)
@ -56,8 +57,8 @@ grub_machine_acpi_get_rsdpv2 (void)
grub_dprintf ("acpi", "Looking for RSDP. Scanning EBDA\n"); grub_dprintf ("acpi", "Looking for RSDP. Scanning EBDA\n");
ebda = (grub_uint8_t *) ((* ((grub_uint16_t *) 0x40e)) << 4); ebda = (grub_uint8_t *) ((* ((grub_uint16_t *) 0x40e)) << 4);
ebda_len = * (grub_uint16_t *) ebda; ebda_len = * (grub_uint16_t *) ebda;
if (! ebda_len) if (! ebda_len) /* FIXME do we really need this check? */
return 0; goto scan_bios;
for (ptr = ebda; ptr < ebda + 0x400; ptr += 16) for (ptr = ebda; ptr < ebda + 0x400; ptr += 16)
if (grub_memcmp (ptr, GRUB_RSDP_SIGNATURE, GRUB_RSDP_SIGNATURE_SIZE) == 0 if (grub_memcmp (ptr, GRUB_RSDP_SIGNATURE, GRUB_RSDP_SIGNATURE_SIZE) == 0
&& grub_byte_checksum (ptr, sizeof (struct grub_acpi_rsdp_v10)) == 0 && grub_byte_checksum (ptr, sizeof (struct grub_acpi_rsdp_v10)) == 0
@ -67,6 +68,7 @@ grub_machine_acpi_get_rsdpv2 (void)
== 0) == 0)
return (struct grub_acpi_rsdp_v20 *) ptr; return (struct grub_acpi_rsdp_v20 *) ptr;
scan_bios:
grub_dprintf ("acpi", "Looking for RSDP. Scanning BIOS\n"); grub_dprintf ("acpi", "Looking for RSDP. Scanning BIOS\n");
for (ptr = (grub_uint8_t *) 0xe0000; ptr < (grub_uint8_t *) 0x100000; for (ptr = (grub_uint8_t *) 0xe0000; ptr < (grub_uint8_t *) 0x100000;
ptr += 16) ptr += 16)

View file

@ -104,7 +104,10 @@ grub_cmd_password (grub_command_t cmd __attribute__ ((unused)),
pass->c = grub_strtoul (ptr, &ptr, 0); pass->c = grub_strtoul (ptr, &ptr, 0);
if (grub_errno) if (grub_errno)
{
grub_free (pass);
return grub_errno; return grub_errno;
}
if (*ptr != '.') if (*ptr != '.')
{ {
grub_free (pass); grub_free (pass);

View file

@ -251,10 +251,10 @@ try (struct search_ctx *ctx)
/* Cache entry was outdated. Remove it. */ /* Cache entry was outdated. Remove it. */
if (!ctx->count) if (!ctx->count)
{ {
*prev = cache_ent->next;
grub_free (cache_ent->key); grub_free (cache_ent->key);
grub_free (cache_ent->value); grub_free (cache_ent->value);
grub_free (cache_ent); grub_free (cache_ent);
*prev = cache_ent->next;
} }
} }

View file

@ -181,7 +181,10 @@ grub_cmd_search (grub_extcmd_context_t ctxt, int argc, char **args)
var = "root"; var = "root";
} }
else else
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected")); {
grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected"));
goto out;
}
if (state[SEARCH_LABEL].set) if (state[SEARCH_LABEL].set)
grub_search_label (id, var, state[SEARCH_NO_FLOPPY].set, grub_search_label (id, var, state[SEARCH_NO_FLOPPY].set,
@ -199,8 +202,10 @@ grub_cmd_search (grub_extcmd_context_t ctxt, int argc, char **args)
grub_search_fs_file (id, var, state[SEARCH_NO_FLOPPY].set, grub_search_fs_file (id, var, state[SEARCH_NO_FLOPPY].set,
hints, nhints); hints, nhints);
else else
return grub_error (GRUB_ERR_INVALID_COMMAND, "unspecified search type"); grub_error (GRUB_ERR_INVALID_COMMAND, "unspecified search type");
out:
grub_free (hints);
return grub_errno; return grub_errno;
} }

View file

@ -195,7 +195,7 @@ grub_ahci_pciinit (grub_pci_device_t dev,
addr = grub_pci_make_address (dev, GRUB_PCI_REG_COMMAND); addr = grub_pci_make_address (dev, GRUB_PCI_REG_COMMAND);
grub_pci_write_word (addr, grub_pci_read_word (addr) grub_pci_write_word (addr, grub_pci_read_word (addr)
| GRUB_PCI_COMMAND_MEM_ENABLED); | GRUB_PCI_COMMAND_MEM_ENABLED | GRUB_PCI_COMMAND_BUS_MASTER);
hba = grub_pci_device_map_range (dev, bar & GRUB_PCI_ADDR_MEM_MASK, hba = grub_pci_device_map_range (dev, bar & GRUB_PCI_ADDR_MEM_MASK,
sizeof (*hba)); sizeof (*hba));
@ -355,7 +355,7 @@ grub_ahci_pciinit (grub_pci_device_t dev,
if (adevs[i]) if (adevs[i])
{ {
adevs[i]->hba->ports[adevs[i]->port].sata_error = adevs[i]->hba->ports[adevs[i]->port].sata_error; adevs[i]->hba->ports[adevs[i]->port].sata_error = adevs[i]->hba->ports[adevs[i]->port].sata_error;
grub_dprintf ("ahci", "err: %x\n", grub_dprintf ("ahci", "port: %d, err: %x\n", adevs[i]->port,
adevs[i]->hba->ports[adevs[i]->port].sata_error); adevs[i]->hba->ports[adevs[i]->port].sata_error);
adevs[i]->command_list_chunk = grub_memalign_dma32 (1024, sizeof (struct grub_ahci_cmd_head) * 32); adevs[i]->command_list_chunk = grub_memalign_dma32 (1024, sizeof (struct grub_ahci_cmd_head) * 32);
@ -440,7 +440,7 @@ grub_ahci_pciinit (grub_pci_device_t dev,
adevs[i]->hba->ports[adevs[i]->port].intstatus = ~0; adevs[i]->hba->ports[adevs[i]->port].intstatus = ~0;
// adevs[i]->hba->ports[adevs[i]->port].fbs = 0; // adevs[i]->hba->ports[adevs[i]->port].fbs = 0;
grub_dprintf ("ahci", "err: %x\n", grub_dprintf ("ahci", "port: %d, err: %x\n", adevs[i]->port,
adevs[i]->hba->ports[adevs[i]->port].sata_error); adevs[i]->hba->ports[adevs[i]->port].sata_error);
adevs[i]->rfis = grub_memalign_dma32 (4096, adevs[i]->rfis = grub_memalign_dma32 (4096,
@ -480,7 +480,7 @@ grub_ahci_pciinit (grub_pci_device_t dev,
for (i = 0; i < nports; i++) for (i = 0; i < nports; i++)
if (adevs[i]) if (adevs[i])
{ {
grub_dprintf ("ahci", "err: %x\n", grub_dprintf ("ahci", "port: %d, err: %x\n", adevs[i]->port,
adevs[i]->hba->ports[adevs[i]->port].sata_error); adevs[i]->hba->ports[adevs[i]->port].sata_error);
fr_running |= (1 << i); fr_running |= (1 << i);
@ -488,7 +488,7 @@ grub_ahci_pciinit (grub_pci_device_t dev,
adevs[i]->hba->ports[adevs[i]->port].command |= GRUB_AHCI_HBA_PORT_CMD_POWER_ON; adevs[i]->hba->ports[adevs[i]->port].command |= GRUB_AHCI_HBA_PORT_CMD_POWER_ON;
adevs[i]->hba->ports[adevs[i]->port].command |= 1 << 28; adevs[i]->hba->ports[adevs[i]->port].command |= 1 << 28;
grub_dprintf ("ahci", "err: %x\n", grub_dprintf ("ahci", "port: %d, err: %x\n", adevs[i]->port,
adevs[i]->hba->ports[adevs[i]->port].sata_error); adevs[i]->hba->ports[adevs[i]->port].sata_error);
} }
@ -515,26 +515,26 @@ grub_ahci_pciinit (grub_pci_device_t dev,
for (i = 0; i < nports; i++) for (i = 0; i < nports; i++)
if (adevs[i]) if (adevs[i])
{ {
grub_dprintf ("ahci", "err: %x\n", grub_dprintf ("ahci", "port %d, err: %x\n", adevs[i]->port,
adevs[i]->hba->ports[adevs[i]->port].sata_error); adevs[i]->hba->ports[adevs[i]->port].sata_error);
adevs[i]->hba->ports[adevs[i]->port].command |= GRUB_AHCI_HBA_PORT_CMD_POWER_ON; adevs[i]->hba->ports[adevs[i]->port].command |= GRUB_AHCI_HBA_PORT_CMD_POWER_ON;
adevs[i]->hba->ports[adevs[i]->port].command |= GRUB_AHCI_HBA_PORT_CMD_SPIN_UP; adevs[i]->hba->ports[adevs[i]->port].command |= GRUB_AHCI_HBA_PORT_CMD_SPIN_UP;
grub_dprintf ("ahci", "err: %x\n", grub_dprintf ("ahci", "port %d, err: %x\n", adevs[i]->port,
adevs[i]->hba->ports[adevs[i]->port].sata_error); adevs[i]->hba->ports[adevs[i]->port].sata_error);
adevs[i]->hba->ports[adevs[i]->port].sata_error = ~0; adevs[i]->hba->ports[adevs[i]->port].sata_error = ~0;
grub_dprintf ("ahci", "err: %x\n", grub_dprintf ("ahci", "port %d, err: %x\n", adevs[i]->port,
adevs[i]->hba->ports[adevs[i]->port].sata_error); adevs[i]->hba->ports[adevs[i]->port].sata_error);
grub_dprintf ("ahci", "offset: %x, tfd:%x, CMD: %x\n", grub_dprintf ("ahci", "port %d, offset: %x, tfd:%x, CMD: %x\n", adevs[i]->port,
(int) ((char *) &adevs[i]->hba->ports[adevs[i]->port].task_file_data - (int) ((char *) &adevs[i]->hba->ports[adevs[i]->port].task_file_data -
(char *) adevs[i]->hba), (char *) adevs[i]->hba),
adevs[i]->hba->ports[adevs[i]->port].task_file_data, adevs[i]->hba->ports[adevs[i]->port].task_file_data,
adevs[i]->hba->ports[adevs[i]->port].command); adevs[i]->hba->ports[adevs[i]->port].command);
grub_dprintf ("ahci", "err: %x\n", grub_dprintf ("ahci", "port %d, err: %x\n", adevs[i]->port,
adevs[i]->hba->ports[adevs[i]->port].sata_error); adevs[i]->hba->ports[adevs[i]->port].sata_error);
} }
@ -542,17 +542,19 @@ grub_ahci_pciinit (grub_pci_device_t dev,
for (i = 0; i < nports; i++) for (i = 0; i < nports; i++)
if (adevs[i]) if (adevs[i])
{ {
grub_dprintf ("ahci", "offset: %x, tfd:%x, CMD: %x\n", grub_dprintf ("ahci", "port %d, offset: %x, tfd:%x, CMD: %x\n", adevs[i]->port,
(int) ((char *) &adevs[i]->hba->ports[adevs[i]->port].task_file_data - (int) ((char *) &adevs[i]->hba->ports[adevs[i]->port].task_file_data -
(char *) adevs[i]->hba), (char *) adevs[i]->hba),
adevs[i]->hba->ports[adevs[i]->port].task_file_data, adevs[i]->hba->ports[adevs[i]->port].task_file_data,
adevs[i]->hba->ports[adevs[i]->port].command); adevs[i]->hba->ports[adevs[i]->port].command);
grub_dprintf ("ahci", "err: %x\n", grub_dprintf ("ahci", "port: %d, err: %x\n", adevs[i]->port,
adevs[i]->hba->ports[adevs[i]->port].sata_error); adevs[i]->hba->ports[adevs[i]->port].sata_error);
adevs[i]->hba->ports[adevs[i]->port].command adevs[i]->hba->ports[adevs[i]->port].command
= (adevs[i]->hba->ports[adevs[i]->port].command & 0x0fffffff) | (1 << 28) | 2 | 4; = (adevs[i]->hba->ports[adevs[i]->port].command & 0x0fffffff) | (1 << 28)
| GRUB_AHCI_HBA_PORT_CMD_SPIN_UP
| GRUB_AHCI_HBA_PORT_CMD_POWER_ON;
/* struct grub_disk_ata_pass_through_parms parms2; /* struct grub_disk_ata_pass_through_parms parms2;
grub_memset (&parms2, 0, sizeof (parms2)); grub_memset (&parms2, 0, sizeof (parms2));
@ -565,14 +567,14 @@ grub_ahci_pciinit (grub_pci_device_t dev,
while (grub_get_time_ms () < endtime) while (grub_get_time_ms () < endtime)
{ {
for (i = 0; i < nports; i++) for (i = 0; i < nports; i++)
if (adevs[i] && (adevs[i]->hba->ports[adevs[i]->port].task_file_data & 0x88)) if (adevs[i] && (adevs[i]->hba->ports[adevs[i]->port].task_file_data & (GRUB_ATA_STATUS_BUSY | GRUB_ATA_STATUS_DRQ)))
break; break;
if (i == nports) if (i == nports)
break; break;
} }
for (i = 0; i < nports; i++) for (i = 0; i < nports; i++)
if (adevs[i] && (adevs[i]->hba->ports[adevs[i]->port].task_file_data & 0x88)) if (adevs[i] && (adevs[i]->hba->ports[adevs[i]->port].task_file_data & (GRUB_ATA_STATUS_BUSY | GRUB_ATA_STATUS_DRQ)))
{ {
grub_dprintf ("ahci", "port %d is busy\n", i); grub_dprintf ("ahci", "port %d is busy\n", i);
failed_adevs[i] = adevs[i]; failed_adevs[i] = adevs[i];
@ -1002,7 +1004,7 @@ grub_ahci_readwrite_real (struct grub_ahci_device *dev,
if (parms->write) if (parms->write)
grub_memcpy ((char *) grub_dma_get_virt (bufc), parms->buffer, parms->size); grub_memcpy ((char *) grub_dma_get_virt (bufc), parms->buffer, parms->size);
grub_dprintf ("ahci", "AHCI command schedulded\n"); grub_dprintf ("ahci", "AHCI command scheduled\n");
grub_dprintf ("ahci", "AHCI tfd = %x\n", grub_dprintf ("ahci", "AHCI tfd = %x\n",
dev->hba->ports[dev->port].task_file_data); dev->hba->ports[dev->port].task_file_data);
grub_dprintf ("ahci", "AHCI inten = %x\n", grub_dprintf ("ahci", "AHCI inten = %x\n",

View file

@ -1007,7 +1007,7 @@ grub_diskfilter_vg_register (struct grub_diskfilter_vg *vg)
struct grub_diskfilter_vg * struct grub_diskfilter_vg *
grub_diskfilter_make_raid (grub_size_t uuidlen, char *uuid, int nmemb, grub_diskfilter_make_raid (grub_size_t uuidlen, char *uuid, int nmemb,
char *name, grub_uint64_t disk_size, const char *name, grub_uint64_t disk_size,
grub_uint64_t stripe_size, grub_uint64_t stripe_size,
int layout, int level) int layout, int level)
{ {

View file

@ -172,7 +172,7 @@ grub_dmraid_nv_detect (grub_disk_t disk,
return grub_diskfilter_make_raid (sizeof (sb.array.signature), return grub_diskfilter_make_raid (sizeof (sb.array.signature),
uuid, sb.array.total_volumes, uuid, sb.array.total_volumes,
NULL, disk_size, "nv", disk_size,
sb.array.stripe_block_size, sb.array.stripe_block_size,
GRUB_RAID_LAYOUT_LEFT_ASYMMETRIC, GRUB_RAID_LAYOUT_LEFT_ASYMMETRIC,
level); level);

View file

@ -43,47 +43,6 @@ static struct grub_efidisk_data *fd_devices;
static struct grub_efidisk_data *hd_devices; static struct grub_efidisk_data *hd_devices;
static struct grub_efidisk_data *cd_devices; static struct grub_efidisk_data *cd_devices;
/* Duplicate a device path. */
static grub_efi_device_path_t *
duplicate_device_path (const grub_efi_device_path_t *dp)
{
grub_efi_device_path_t *p;
grub_size_t total_size = 0;
for (p = (grub_efi_device_path_t *) dp;
;
p = GRUB_EFI_NEXT_DEVICE_PATH (p))
{
total_size += GRUB_EFI_DEVICE_PATH_LENGTH (p);
if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (p))
break;
}
p = grub_malloc (total_size);
if (! p)
return 0;
grub_memcpy (p, dp, total_size);
return p;
}
/* Return the device path node right before the end node. */
static grub_efi_device_path_t *
find_last_device_path (const grub_efi_device_path_t *dp)
{
grub_efi_device_path_t *next, *p;
if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp))
return 0;
for (p = (grub_efi_device_path_t *) dp, next = GRUB_EFI_NEXT_DEVICE_PATH (p);
! GRUB_EFI_END_ENTIRE_DEVICE_PATH (next);
p = next, next = GRUB_EFI_NEXT_DEVICE_PATH (next))
;
return p;
}
static struct grub_efidisk_data * static struct grub_efidisk_data *
make_devices (void) make_devices (void)
{ {
@ -110,7 +69,7 @@ make_devices (void)
if (! dp) if (! dp)
continue; continue;
ldp = find_last_device_path (dp); ldp = grub_efi_find_last_device_path (dp);
if (! ldp) if (! ldp)
/* This is empty. Why? */ /* This is empty. Why? */
continue; continue;
@ -150,11 +109,11 @@ find_parent_device (struct grub_efidisk_data *devices,
grub_efi_device_path_t *dp, *ldp; grub_efi_device_path_t *dp, *ldp;
struct grub_efidisk_data *parent; struct grub_efidisk_data *parent;
dp = duplicate_device_path (d->device_path); dp = grub_efi_duplicate_device_path (d->device_path);
if (! dp) if (! dp)
return 0; return 0;
ldp = find_last_device_path (dp); ldp = grub_efi_find_last_device_path (dp);
ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE; ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE;
ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE; ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE;
ldp->length = sizeof (*ldp); ldp->length = sizeof (*ldp);
@ -180,11 +139,11 @@ is_child (struct grub_efidisk_data *child,
grub_efi_device_path_t *dp, *ldp; grub_efi_device_path_t *dp, *ldp;
int ret; int ret;
dp = duplicate_device_path (child->device_path); dp = grub_efi_duplicate_device_path (child->device_path);
if (! dp) if (! dp)
return 0; return 0;
ldp = find_last_device_path (dp); ldp = grub_efi_find_last_device_path (dp);
ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE; ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE;
ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE; ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE;
ldp->length = sizeof (*ldp); ldp->length = sizeof (*ldp);
@ -207,8 +166,8 @@ add_device (struct grub_efidisk_data **devices, struct grub_efidisk_data *d)
{ {
int ret; int ret;
ret = grub_efi_compare_device_paths (find_last_device_path ((*p)->device_path), ret = grub_efi_compare_device_paths (grub_efi_find_last_device_path ((*p)->device_path),
find_last_device_path (d->device_path)); grub_efi_find_last_device_path (d->device_path));
if (ret == 0) if (ret == 0)
ret = grub_efi_compare_device_paths ((*p)->device_path, ret = grub_efi_compare_device_paths ((*p)->device_path,
d->device_path); d->device_path);
@ -795,7 +754,7 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle)
if (! dp) if (! dp)
return 0; return 0;
ldp = find_last_device_path (dp); ldp = grub_efi_find_last_device_path (dp);
if (! ldp) if (! ldp)
return 0; return 0;
@ -810,14 +769,14 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle)
/* It is necessary to duplicate the device path so that GRUB /* It is necessary to duplicate the device path so that GRUB
can overwrite it. */ can overwrite it. */
dup_dp = duplicate_device_path (dp); dup_dp = grub_efi_duplicate_device_path (dp);
if (! dup_dp) if (! dup_dp)
return 0; return 0;
while (1) while (1)
{ {
grub_efi_device_path_t *dup_ldp; grub_efi_device_path_t *dup_ldp;
dup_ldp = find_last_device_path (dup_dp); dup_ldp = grub_efi_find_last_device_path (dup_dp);
if (!(GRUB_EFI_DEVICE_PATH_TYPE (dup_ldp) == GRUB_EFI_MEDIA_DEVICE_PATH_TYPE if (!(GRUB_EFI_DEVICE_PATH_TYPE (dup_ldp) == GRUB_EFI_MEDIA_DEVICE_PATH_TYPE
&& (GRUB_EFI_DEVICE_PATH_SUBTYPE (dup_ldp) == GRUB_EFI_CDROM_DEVICE_PATH_SUBTYPE && (GRUB_EFI_DEVICE_PATH_SUBTYPE (dup_ldp) == GRUB_EFI_CDROM_DEVICE_PATH_SUBTYPE
|| GRUB_EFI_DEVICE_PATH_SUBTYPE (dup_ldp) == GRUB_EFI_HARD_DRIVE_DEVICE_PATH_SUBTYPE))) || GRUB_EFI_DEVICE_PATH_SUBTYPE (dup_ldp) == GRUB_EFI_HARD_DRIVE_DEVICE_PATH_SUBTYPE)))

View file

@ -160,7 +160,7 @@ grub_lvm_detect (grub_disk_t disk,
"we don't support multiple LVM data areas"); "we don't support multiple LVM data areas");
#ifdef GRUB_UTIL #ifdef GRUB_UTIL
grub_util_info ("we don't support multiple LVM data areas\n"); grub_util_info ("we don't support multiple LVM data areas");
#endif #endif
goto fail; goto fail;
} }
@ -189,7 +189,7 @@ grub_lvm_detect (grub_disk_t disk,
grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
"unknown LVM metadata header"); "unknown LVM metadata header");
#ifdef GRUB_UTIL #ifdef GRUB_UTIL
grub_util_info ("unknown LVM metadata header\n"); grub_util_info ("unknown LVM metadata header");
#endif #endif
goto fail2; goto fail2;
} }
@ -213,7 +213,7 @@ grub_lvm_detect (grub_disk_t disk,
if (q == metadatabuf + mda_size) if (q == metadatabuf + mda_size)
{ {
#ifdef GRUB_UTIL #ifdef GRUB_UTIL
grub_util_info ("error parsing metadata\n"); grub_util_info ("error parsing metadata");
#endif #endif
goto fail2; goto fail2;
} }
@ -230,7 +230,7 @@ grub_lvm_detect (grub_disk_t disk,
if (p == NULL) if (p == NULL)
{ {
#ifdef GRUB_UTIL #ifdef GRUB_UTIL
grub_util_info ("couldn't find ID\n"); grub_util_info ("couldn't find ID");
#endif #endif
goto fail3; goto fail3;
} }
@ -258,7 +258,7 @@ grub_lvm_detect (grub_disk_t disk,
if (p == NULL) if (p == NULL)
{ {
#ifdef GRUB_UTIL #ifdef GRUB_UTIL
grub_util_info ("unknown extent size\n"); grub_util_info ("unknown extent size");
#endif #endif
goto fail4; goto fail4;
} }
@ -306,7 +306,7 @@ grub_lvm_detect (grub_disk_t disk,
if (p == NULL) if (p == NULL)
{ {
#ifdef GRUB_UTIL #ifdef GRUB_UTIL
grub_util_info ("unknown pe_start\n"); grub_util_info ("unknown pe_start");
#endif #endif
goto pvs_fail; goto pvs_fail;
} }
@ -315,7 +315,7 @@ grub_lvm_detect (grub_disk_t disk,
if (p == NULL) if (p == NULL)
{ {
#ifdef GRUB_UTIL #ifdef GRUB_UTIL
grub_util_info ("error parsing pe_start\n"); grub_util_info ("error parsing pe_start");
#endif #endif
goto pvs_fail; goto pvs_fail;
} }
@ -402,7 +402,7 @@ grub_lvm_detect (grub_disk_t disk,
if (p == NULL) if (p == NULL)
{ {
#ifdef GRUB_UTIL #ifdef GRUB_UTIL
grub_util_info ("couldn't find ID\n"); grub_util_info ("couldn't find ID");
#endif #endif
goto lvs_fail; goto lvs_fail;
} }
@ -422,7 +422,7 @@ grub_lvm_detect (grub_disk_t disk,
if (p == NULL) if (p == NULL)
{ {
#ifdef GRUB_UTIL #ifdef GRUB_UTIL
grub_util_info ("unknown segment_count\n"); grub_util_info ("unknown segment_count");
#endif #endif
goto lvs_fail; goto lvs_fail;
} }
@ -436,7 +436,7 @@ grub_lvm_detect (grub_disk_t disk,
if (p == NULL) if (p == NULL)
{ {
#ifdef GRUB_UTIL #ifdef GRUB_UTIL
grub_util_info ("unknown segment\n"); grub_util_info ("unknown segment");
#endif #endif
goto lvs_segment_fail; goto lvs_segment_fail;
} }
@ -445,7 +445,7 @@ grub_lvm_detect (grub_disk_t disk,
if (p == NULL) if (p == NULL)
{ {
#ifdef GRUB_UTIL #ifdef GRUB_UTIL
grub_util_info ("unknown start_extent\n"); grub_util_info ("unknown start_extent");
#endif #endif
goto lvs_segment_fail; goto lvs_segment_fail;
} }
@ -453,7 +453,7 @@ grub_lvm_detect (grub_disk_t disk,
if (p == NULL) if (p == NULL)
{ {
#ifdef GRUB_UTIL #ifdef GRUB_UTIL
grub_util_info ("unknown extent_count\n"); grub_util_info ("unknown extent_count");
#endif #endif
goto lvs_segment_fail; goto lvs_segment_fail;
} }
@ -475,7 +475,7 @@ grub_lvm_detect (grub_disk_t disk,
if (p == NULL) if (p == NULL)
{ {
#ifdef GRUB_UTIL #ifdef GRUB_UTIL
grub_util_info ("unknown stripe_count\n"); grub_util_info ("unknown stripe_count");
#endif #endif
goto lvs_segment_fail; goto lvs_segment_fail;
} }
@ -491,7 +491,7 @@ grub_lvm_detect (grub_disk_t disk,
if (p == NULL) if (p == NULL)
{ {
#ifdef GRUB_UTIL #ifdef GRUB_UTIL
grub_util_info ("unknown stripes\n"); grub_util_info ("unknown stripes");
#endif #endif
goto lvs_segment_fail2; goto lvs_segment_fail2;
} }
@ -533,7 +533,7 @@ grub_lvm_detect (grub_disk_t disk,
if (p == NULL) if (p == NULL)
{ {
#ifdef GRUB_UTIL #ifdef GRUB_UTIL
grub_util_info ("unknown mirror_count\n"); grub_util_info ("unknown mirror_count");
#endif #endif
goto lvs_segment_fail; goto lvs_segment_fail;
} }
@ -545,7 +545,7 @@ grub_lvm_detect (grub_disk_t disk,
if (p == NULL) if (p == NULL)
{ {
#ifdef GRUB_UTIL #ifdef GRUB_UTIL
grub_util_info ("unknown mirrors\n"); grub_util_info ("unknown mirrors");
#endif #endif
goto lvs_segment_fail2; goto lvs_segment_fail2;
} }
@ -607,7 +607,7 @@ grub_lvm_detect (grub_disk_t disk,
if (p == NULL) if (p == NULL)
{ {
#ifdef GRUB_UTIL #ifdef GRUB_UTIL
grub_util_info ("unknown device_count\n"); grub_util_info ("unknown device_count");
#endif #endif
goto lvs_segment_fail; goto lvs_segment_fail;
} }
@ -618,7 +618,7 @@ grub_lvm_detect (grub_disk_t disk,
if (p == NULL) if (p == NULL)
{ {
#ifdef GRUB_UTIL #ifdef GRUB_UTIL
grub_util_info ("unknown stripe_size\n"); grub_util_info ("unknown stripe_size");
#endif #endif
goto lvs_segment_fail; goto lvs_segment_fail;
} }
@ -631,7 +631,7 @@ grub_lvm_detect (grub_disk_t disk,
if (p == NULL) if (p == NULL)
{ {
#ifdef GRUB_UTIL #ifdef GRUB_UTIL
grub_util_info ("unknown raids\n"); grub_util_info ("unknown raids");
#endif #endif
goto lvs_segment_fail2; goto lvs_segment_fail2;
} }
@ -678,7 +678,7 @@ grub_lvm_detect (grub_disk_t disk,
p2 = grub_strchr (p, '"'); p2 = grub_strchr (p, '"');
if (p2) if (p2)
*p2 = 0; *p2 = 0;
grub_util_info ("unknown LVM type %s\n", p); grub_util_info ("unknown LVM type %s", p);
if (p2) if (p2)
*p2 ='"'; *p2 ='"';
#endif #endif

View file

@ -615,9 +615,10 @@ grub_scsi_open (const char *name, grub_disk_t disk)
if (scsi->blocksize & (scsi->blocksize - 1) || !scsi->blocksize) if (scsi->blocksize & (scsi->blocksize - 1) || !scsi->blocksize)
{ {
grub_free (scsi); grub_error (GRUB_ERR_IO, "invalid sector size %d",
return grub_error (GRUB_ERR_IO, "invalid sector size %d",
scsi->blocksize); scsi->blocksize);
grub_free (scsi);
return grub_errno;
} }
for (disk->log_sector_size = 0; for (disk->log_sector_size = 0;
(1U << disk->log_sector_size) < scsi->blocksize; (1U << disk->log_sector_size) < scsi->blocksize;

View file

@ -34,12 +34,12 @@ canonicalize (char *name)
iptr++; iptr++;
if (iptr[0] == '.' && (iptr[1] == '/' || iptr[1] == 0)) if (iptr[0] == '.' && (iptr[1] == '/' || iptr[1] == 0))
{ {
iptr += 2; iptr++;
continue; continue;
} }
if (iptr[0] == '.' && iptr[1] == '.' && (iptr[2] == '/' || iptr[2] == 0)) if (iptr[0] == '.' && iptr[1] == '.' && (iptr[2] == '/' || iptr[2] == 0))
{ {
iptr += 3; iptr += 2;
if (optr == name) if (optr == name)
continue; continue;
for (optr -= 2; optr >= name && *optr != '/'; optr--); for (optr -= 2; optr >= name && *optr != '/'; optr--);
@ -249,9 +249,10 @@ grub_archelp_open (struct grub_archelp_data *data,
while (1) while (1)
{ {
grub_uint32_t mode; grub_uint32_t mode;
grub_int32_t mtime;
int restart; int restart;
if (arcops->find_file (data, &fn, NULL, &mode)) if (arcops->find_file (data, &fn, &mtime, &mode))
goto fail; goto fail;
if (mode == GRUB_ARCHELP_ATTR_END) if (mode == GRUB_ARCHELP_ATTR_END)

View file

@ -29,6 +29,7 @@
#include <grub/dl.h> #include <grub/dl.h>
#include <grub/types.h> #include <grub/types.h>
#include <grub/i18n.h> #include <grub/i18n.h>
#include <grub/fshelp.h>
GRUB_MOD_LICENSE ("GPLv3+"); GRUB_MOD_LICENSE ("GPLv3+");
@ -561,10 +562,10 @@ iterate_in_b_tree (grub_disk_t disk,
} }
static int static int
bfs_strcmp (const char *a, const char *b, grub_size_t alen, grub_size_t blen) bfs_strcmp (const char *a, const char *b, grub_size_t alen)
{ {
char ac, bc; char ac, bc;
while (blen && alen) while (*b && alen)
{ {
if (*a != *b) if (*a != *b)
break; break;
@ -572,11 +573,10 @@ bfs_strcmp (const char *a, const char *b, grub_size_t alen, grub_size_t blen)
a++; a++;
b++; b++;
alen--; alen--;
blen--;
} }
ac = alen ? *a : 0; ac = alen ? *a : 0;
bc = blen ? *b : 0; bc = *b;
#ifdef MODE_AFS #ifdef MODE_AFS
return (int) (grub_int8_t) ac - (int) (grub_int8_t) bc; return (int) (grub_int8_t) ac - (int) (grub_int8_t) bc;
@ -589,7 +589,6 @@ static grub_err_t
find_in_b_tree (grub_disk_t disk, find_in_b_tree (grub_disk_t disk,
const struct grub_bfs_superblock *sb, const struct grub_bfs_superblock *sb,
const struct grub_bfs_inode *ino, const char *name, const struct grub_bfs_inode *ino, const char *name,
grub_size_t name_len,
grub_uint64_t * res) grub_uint64_t * res)
{ {
struct grub_bfs_btree_header head; struct grub_bfs_btree_header head;
@ -637,7 +636,7 @@ find_in_b_tree (grub_disk_t disk,
end = grub_bfs_to_cpu16 (keylen_idx[(i | (1 << j))]); end = grub_bfs_to_cpu16 (keylen_idx[(i | (1 << j))]);
if (grub_bfs_to_cpu_treehead (node->total_key_len) <= end) if (grub_bfs_to_cpu_treehead (node->total_key_len) <= end)
end = grub_bfs_to_cpu_treehead (node->total_key_len); end = grub_bfs_to_cpu_treehead (node->total_key_len);
cmp = bfs_strcmp (key_data + start, name, end - start, name_len); cmp = bfs_strcmp (key_data + start, name, end - start);
if (cmp == 0 && level == 0) if (cmp == 0 && level == 0)
{ {
*res = grub_bfs_to_cpu64 (key_values[i | (1 << j)].val); *res = grub_bfs_to_cpu64 (key_values[i | (1 << j)].val);
@ -658,7 +657,7 @@ find_in_b_tree (grub_disk_t disk,
end = grub_bfs_to_cpu16 (keylen_idx[0]); end = grub_bfs_to_cpu16 (keylen_idx[0]);
if (grub_bfs_to_cpu_treehead (node->total_key_len) <= end) if (grub_bfs_to_cpu_treehead (node->total_key_len) <= end)
end = grub_bfs_to_cpu_treehead (node->total_key_len); end = grub_bfs_to_cpu_treehead (node->total_key_len);
cmp = bfs_strcmp (key_data, name, end, name_len); cmp = bfs_strcmp (key_data, name, end);
if (cmp == 0 && level == 0) if (cmp == 0 && level == 0)
{ {
*res = grub_bfs_to_cpu64 (key_values[0].val); *res = grub_bfs_to_cpu64 (key_values[0].val);
@ -707,127 +706,119 @@ find_in_b_tree (grub_disk_t disk,
} }
} }
struct grub_fshelp_node
{
grub_disk_t disk;
const struct grub_bfs_superblock *sb;
struct grub_bfs_inode ino;
};
static grub_err_t static grub_err_t
hop_level (grub_disk_t disk, lookup_file (grub_fshelp_node_t dir,
const struct grub_bfs_superblock *sb, const char *name,
struct grub_bfs_inode *ino, const char *name, grub_fshelp_node_t *foundnode,
const char *name_end) enum grub_fshelp_filetype *foundtype)
{ {
grub_err_t err; grub_err_t err;
struct grub_bfs_inode *new_ino;
grub_uint64_t res = 0; grub_uint64_t res = 0;
if (((grub_bfs_to_cpu32 (ino->mode) & ATTR_TYPE) != ATTR_DIR)) err = find_in_b_tree (dir->disk, dir->sb, &dir->ino, name, &res);
return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory"));
err = find_in_b_tree (disk, sb, ino, name, name_end - name, &res);
if (err) if (err)
return err; return err;
return grub_disk_read (disk, res *foundnode = grub_malloc (sizeof (struct grub_fshelp_node));
<< (grub_bfs_to_cpu32 (sb->log2_bsize) if (!*foundnode)
return grub_errno;
(*foundnode)->disk = dir->disk;
(*foundnode)->sb = dir->sb;
new_ino = &(*foundnode)->ino;
if (grub_disk_read (dir->disk, res
<< (grub_bfs_to_cpu32 (dir->sb->log2_bsize)
- GRUB_DISK_SECTOR_BITS), 0, - GRUB_DISK_SECTOR_BITS), 0,
sizeof (*ino), (char *) ino); sizeof (*new_ino), (char *) new_ino))
{
grub_free (*foundnode);
return grub_errno;
}
switch (grub_bfs_to_cpu32 (new_ino->mode) & ATTR_TYPE)
{
default:
case ATTR_REG:
*foundtype = GRUB_FSHELP_REG;
break;
case ATTR_DIR:
*foundtype = GRUB_FSHELP_DIR;
break;
case ATTR_LNK:
*foundtype = GRUB_FSHELP_SYMLINK;
break;
}
return GRUB_ERR_NONE;
}
static char *
read_symlink (grub_fshelp_node_t node)
{
char *alloc = NULL;
grub_err_t err;
#ifndef MODE_AFS
if (!(grub_bfs_to_cpu32 (node->ino.flags) & LONG_SYMLINK))
{
alloc = grub_malloc (sizeof (node->ino.inplace_link) + 1);
if (!alloc)
{
return NULL;
}
grub_memcpy (alloc, node->ino.inplace_link,
sizeof (node->ino.inplace_link));
alloc[sizeof (node->ino.inplace_link)] = 0;
}
else
#endif
{
grub_size_t symsize = grub_bfs_to_cpu64 (node->ino.size);
alloc = grub_malloc (symsize + 1);
if (!alloc)
return NULL;
err = read_bfs_file (node->disk, node->sb, &node->ino, 0, alloc, symsize, 0, 0);
if (err)
{
grub_free (alloc);
return NULL;
}
alloc[symsize] = 0;
}
return alloc;
} }
static grub_err_t static grub_err_t
find_file (const char *path, grub_disk_t disk, find_file (const char *path, grub_disk_t disk,
const struct grub_bfs_superblock *sb, struct grub_bfs_inode *ino) const struct grub_bfs_superblock *sb, struct grub_bfs_inode *ino,
enum grub_fshelp_filetype exptype)
{ {
const char *ptr, *next = path;
char *alloc = NULL;
char *wptr;
grub_err_t err; grub_err_t err;
struct grub_bfs_inode old_ino; struct grub_fshelp_node root = {
unsigned symlinks_max = 32; .disk = disk,
.sb = sb,
};
struct grub_fshelp_node *found;
err = read_extent (disk, sb, &sb->root_dir, 0, 0, ino, err = read_extent (disk, sb, &sb->root_dir, 0, 0, &root.ino,
sizeof (*ino)); sizeof (root.ino));
if (err) if (err)
return err; return err;
err = grub_fshelp_find_file_lookup (path, &root, &found, lookup_file, read_symlink, exptype);
if (!err)
grub_memcpy (ino, &found->ino, sizeof (*ino));
while (1) if (&root != found)
{ grub_free (found);
ptr = next;
while (*ptr == '/')
ptr++;
if (*ptr == 0)
{
grub_free (alloc);
return GRUB_ERR_NONE;
}
for (next = ptr; *next && *next != '/'; next++);
grub_memcpy (&old_ino, ino, sizeof (old_ino));
err = hop_level (disk, sb, ino, ptr, next);
if (err)
return err; return err;
if (((grub_bfs_to_cpu32 (ino->mode) & ATTR_TYPE) == ATTR_LNK))
{
char *old_alloc = alloc;
if (--symlinks_max == 0)
{
grub_free (alloc);
return grub_error (GRUB_ERR_SYMLINK_LOOP,
N_("too deep nesting of symlinks"));
}
#ifndef MODE_AFS
if (grub_bfs_to_cpu32 (ino->flags) & LONG_SYMLINK)
#endif
{
grub_size_t symsize = grub_bfs_to_cpu64 (ino->size);
alloc = grub_malloc (grub_strlen (next)
+ symsize + 1);
if (!alloc)
{
grub_free (alloc);
return grub_errno;
}
grub_free (old_alloc);
err = read_bfs_file (disk, sb, ino, 0, alloc, symsize, 0, 0);
if (err)
{
grub_free (alloc);
return err;
}
alloc[symsize] = 0;
}
#ifndef MODE_AFS
else
{
alloc = grub_malloc (grub_strlen (next)
+ sizeof (ino->inplace_link) + 1);
if (!alloc)
{
grub_free (alloc);
return grub_errno;
}
grub_free (old_alloc);
grub_memcpy (alloc, ino->inplace_link,
sizeof (ino->inplace_link));
alloc[sizeof (ino->inplace_link)] = 0;
}
#endif
if (alloc[0] == '/')
{
err = read_extent (disk, sb, &sb->root_dir, 0, 0, ino,
sizeof (*ino));
if (err)
{
grub_free (alloc);
return err;
}
}
else
grub_memcpy (ino, &old_ino, sizeof (old_ino));
wptr = alloc + grub_strlen (alloc);
if (next)
wptr = grub_stpcpy (wptr, next);
*wptr = 0;
next = alloc;
continue;
}
}
} }
static grub_err_t static grub_err_t
@ -909,11 +900,9 @@ grub_bfs_dir (grub_device_t device, const char *path,
{ {
struct grub_bfs_inode ino; struct grub_bfs_inode ino;
err = find_file (path, device->disk, &ctx.sb, &ino); err = find_file (path, device->disk, &ctx.sb, &ino, GRUB_FSHELP_DIR);
if (err) if (err)
return err; return err;
if (((grub_bfs_to_cpu32 (ino.mode) & ATTR_TYPE) != ATTR_DIR))
return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory"));
iterate_in_b_tree (device->disk, &ctx.sb, &ino, grub_bfs_dir_iter, iterate_in_b_tree (device->disk, &ctx.sb, &ino, grub_bfs_dir_iter,
&ctx); &ctx);
} }
@ -934,11 +923,9 @@ grub_bfs_open (struct grub_file *file, const char *name)
{ {
struct grub_bfs_inode ino; struct grub_bfs_inode ino;
struct grub_bfs_data *data; struct grub_bfs_data *data;
err = find_file (name, file->device->disk, &sb, &ino); err = find_file (name, file->device->disk, &sb, &ino, GRUB_FSHELP_REG);
if (err) if (err)
return err; return err;
if (((grub_bfs_to_cpu32 (ino.mode) & ATTR_TYPE) != ATTR_REG))
return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a regular file"));
data = grub_zalloc (sizeof (struct grub_bfs_data)); data = grub_zalloc (sizeof (struct grub_bfs_data));
if (!data) if (!data)
@ -1034,7 +1021,7 @@ read_bfs_attr (grub_disk_t disk,
if (err) if (err)
return -1; return -1;
err = find_in_b_tree (disk, sb, ino, name, grub_strlen (name), &res); err = find_in_b_tree (disk, sb, ino, name, &res);
if (err) if (err)
return -1; return -1;
grub_disk_read (disk, res grub_disk_read (disk, res

View file

@ -538,8 +538,9 @@ grub_ext2_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
shift = 2; shift = 2;
goto indirect; goto indirect;
} }
return grub_error (GRUB_ERR_BAD_FS, grub_error (GRUB_ERR_BAD_FS,
"ext2fs doesn't support quadruple indirect blocks"); "ext2fs doesn't support quadruple indirect blocks");
return -1;
indirect: indirect:
do { do {
@ -554,7 +555,7 @@ indirect:
& ((1 << log_perblock) - 1)) & ((1 << log_perblock) - 1))
* sizeof (indir), * sizeof (indir),
sizeof (indir), &indir)) sizeof (indir), &indir))
return grub_errno; return -1;
} while (shift--); } while (shift--);
return grub_le_to_cpu32 (indir); return grub_le_to_cpu32 (indir);

View file

@ -31,6 +31,7 @@
#else #else
#include <grub/exfat.h> #include <grub/exfat.h>
#endif #endif
#include <grub/fshelp.h>
#include <grub/i18n.h> #include <grub/i18n.h>
GRUB_MOD_LICENSE ("GPLv3+"); GRUB_MOD_LICENSE ("GPLv3+");
@ -173,8 +174,6 @@ struct grub_fat_data
#ifndef MODE_EXFAT #ifndef MODE_EXFAT
grub_uint32_t root_sector; grub_uint32_t root_sector;
grub_uint32_t num_root_sectors; grub_uint32_t num_root_sectors;
#else
int is_contiguous;
#endif #endif
int cluster_bits; int cluster_bits;
@ -182,13 +181,22 @@ struct grub_fat_data
grub_uint32_t cluster_sector; grub_uint32_t cluster_sector;
grub_uint32_t num_clusters; grub_uint32_t num_clusters;
grub_uint32_t uuid;
};
struct grub_fshelp_node {
grub_disk_t disk;
struct grub_fat_data *data;
grub_uint8_t attr; grub_uint8_t attr;
grub_ssize_t file_size; grub_ssize_t file_size;
grub_uint32_t file_cluster; grub_uint32_t file_cluster;
grub_uint32_t cur_cluster_num; grub_uint32_t cur_cluster_num;
grub_uint32_t cur_cluster; grub_uint32_t cur_cluster;
grub_uint32_t uuid; #ifdef MODE_EXFAT
int is_contiguous;
#endif
}; };
static grub_dl_t my_mod; static grub_dl_t my_mod;
@ -427,13 +435,6 @@ grub_fat_mount (grub_disk_t disk)
(void) magic; (void) magic;
#endif #endif
/* Start from the root directory. */
data->file_cluster = data->root_cluster;
data->cur_cluster_num = ~0U;
data->attr = GRUB_FAT_ATTR_DIRECTORY;
#ifdef MODE_EXFAT
data->is_contiguous = 0;
#endif
return data; return data;
fail: fail:
@ -444,7 +445,7 @@ grub_fat_mount (grub_disk_t disk)
} }
static grub_ssize_t static grub_ssize_t
grub_fat_read_data (grub_disk_t disk, struct grub_fat_data *data, grub_fat_read_data (grub_disk_t disk, grub_fshelp_node_t node,
grub_disk_read_hook_t read_hook, void *read_hook_data, grub_disk_read_hook_t read_hook, void *read_hook_data,
grub_off_t offset, grub_size_t len, char *buf) grub_off_t offset, grub_size_t len, char *buf)
{ {
@ -457,13 +458,13 @@ grub_fat_read_data (grub_disk_t disk, struct grub_fat_data *data,
#ifndef MODE_EXFAT #ifndef MODE_EXFAT
/* This is a special case. FAT12 and FAT16 doesn't have the root directory /* This is a special case. FAT12 and FAT16 doesn't have the root directory
in clusters. */ in clusters. */
if (data->file_cluster == ~0U) if (node->file_cluster == ~0U)
{ {
size = (data->num_root_sectors << GRUB_DISK_SECTOR_BITS) - offset; size = (node->data->num_root_sectors << GRUB_DISK_SECTOR_BITS) - offset;
if (size > len) if (size > len)
size = len; size = len;
if (grub_disk_read (disk, data->root_sector, offset, size, buf)) if (grub_disk_read (disk, node->data->root_sector, offset, size, buf))
return -1; return -1;
return size; return size;
@ -471,12 +472,12 @@ grub_fat_read_data (grub_disk_t disk, struct grub_fat_data *data,
#endif #endif
#ifdef MODE_EXFAT #ifdef MODE_EXFAT
if (data->is_contiguous) if (node->is_contiguous)
{ {
/* Read the data here. */ /* Read the data here. */
sector = (data->cluster_sector sector = (node->data->cluster_sector
+ ((data->file_cluster - 2) + ((node->file_cluster - 2)
<< data->cluster_bits)); << node->data->cluster_bits));
disk->read_hook = read_hook; disk->read_hook = read_hook;
disk->read_hook_data = read_hook_data; disk->read_hook_data = read_hook_data;
@ -491,53 +492,53 @@ grub_fat_read_data (grub_disk_t disk, struct grub_fat_data *data,
#endif #endif
/* Calculate the logical cluster number and offset. */ /* Calculate the logical cluster number and offset. */
logical_cluster_bits = (data->cluster_bits logical_cluster_bits = (node->data->cluster_bits
+ GRUB_DISK_SECTOR_BITS); + GRUB_DISK_SECTOR_BITS);
logical_cluster = offset >> logical_cluster_bits; logical_cluster = offset >> logical_cluster_bits;
offset &= (1ULL << logical_cluster_bits) - 1; offset &= (1ULL << logical_cluster_bits) - 1;
if (logical_cluster < data->cur_cluster_num) if (logical_cluster < node->cur_cluster_num)
{ {
data->cur_cluster_num = 0; node->cur_cluster_num = 0;
data->cur_cluster = data->file_cluster; node->cur_cluster = node->file_cluster;
} }
while (len) while (len)
{ {
while (logical_cluster > data->cur_cluster_num) while (logical_cluster > node->cur_cluster_num)
{ {
/* Find next cluster. */ /* Find next cluster. */
grub_uint32_t next_cluster; grub_uint32_t next_cluster;
grub_uint32_t fat_offset; grub_uint32_t fat_offset;
switch (data->fat_size) switch (node->data->fat_size)
{ {
case 32: case 32:
fat_offset = data->cur_cluster << 2; fat_offset = node->cur_cluster << 2;
break; break;
case 16: case 16:
fat_offset = data->cur_cluster << 1; fat_offset = node->cur_cluster << 1;
break; break;
default: default:
/* case 12: */ /* case 12: */
fat_offset = data->cur_cluster + (data->cur_cluster >> 1); fat_offset = node->cur_cluster + (node->cur_cluster >> 1);
break; break;
} }
/* Read the FAT. */ /* Read the FAT. */
if (grub_disk_read (disk, data->fat_sector, fat_offset, if (grub_disk_read (disk, node->data->fat_sector, fat_offset,
(data->fat_size + 7) >> 3, (node->data->fat_size + 7) >> 3,
(char *) &next_cluster)) (char *) &next_cluster))
return -1; return -1;
next_cluster = grub_le_to_cpu32 (next_cluster); next_cluster = grub_le_to_cpu32 (next_cluster);
switch (data->fat_size) switch (node->data->fat_size)
{ {
case 16: case 16:
next_cluster &= 0xFFFF; next_cluster &= 0xFFFF;
break; break;
case 12: case 12:
if (data->cur_cluster & 1) if (node->cur_cluster & 1)
next_cluster >>= 4; next_cluster >>= 4;
next_cluster &= 0x0FFF; next_cluster &= 0x0FFF;
@ -545,27 +546,27 @@ grub_fat_read_data (grub_disk_t disk, struct grub_fat_data *data,
} }
grub_dprintf ("fat", "fat_size=%d, next_cluster=%u\n", grub_dprintf ("fat", "fat_size=%d, next_cluster=%u\n",
data->fat_size, next_cluster); node->data->fat_size, next_cluster);
/* Check the end. */ /* Check the end. */
if (next_cluster >= data->cluster_eof_mark) if (next_cluster >= node->data->cluster_eof_mark)
return ret; return ret;
if (next_cluster < 2 || next_cluster >= data->num_clusters) if (next_cluster < 2 || next_cluster >= node->data->num_clusters)
{ {
grub_error (GRUB_ERR_BAD_FS, "invalid cluster %u", grub_error (GRUB_ERR_BAD_FS, "invalid cluster %u",
next_cluster); next_cluster);
return -1; return -1;
} }
data->cur_cluster = next_cluster; node->cur_cluster = next_cluster;
data->cur_cluster_num++; node->cur_cluster_num++;
} }
/* Read the data here. */ /* Read the data here. */
sector = (data->cluster_sector sector = (node->data->cluster_sector
+ ((data->cur_cluster - 2) + ((node->cur_cluster - 2)
<< data->cluster_bits)); << node->data->cluster_bits));
size = (1 << logical_cluster_bits) - offset; size = (1 << logical_cluster_bits) - offset;
if (size > len) if (size > len)
size = len; size = len;
@ -631,7 +632,7 @@ grub_fat_iterate_fini (struct grub_fat_iterate_context *ctxt)
#ifdef MODE_EXFAT #ifdef MODE_EXFAT
static grub_err_t static grub_err_t
grub_fat_iterate_dir_next (grub_disk_t disk, struct grub_fat_data *data, grub_fat_iterate_dir_next (grub_fshelp_node_t node,
struct grub_fat_iterate_context *ctxt) struct grub_fat_iterate_context *ctxt)
{ {
grub_memset (&ctxt->dir, 0, sizeof (ctxt->dir)); grub_memset (&ctxt->dir, 0, sizeof (ctxt->dir));
@ -641,7 +642,7 @@ grub_fat_iterate_dir_next (grub_disk_t disk, struct grub_fat_data *data,
ctxt->offset += sizeof (dir); ctxt->offset += sizeof (dir);
if (grub_fat_read_data (disk, data, 0, 0, ctxt->offset, sizeof (dir), if (grub_fat_read_data (node->disk, node, 0, 0, ctxt->offset, sizeof (dir),
(char *) &dir) (char *) &dir)
!= sizeof (dir)) != sizeof (dir))
break; break;
@ -663,7 +664,7 @@ grub_fat_iterate_dir_next (grub_disk_t disk, struct grub_fat_data *data,
{ {
struct grub_fat_dir_entry sec; struct grub_fat_dir_entry sec;
ctxt->offset += sizeof (sec); ctxt->offset += sizeof (sec);
if (grub_fat_read_data (disk, data, 0, 0, if (grub_fat_read_data (node->disk, node, 0, 0,
ctxt->offset, sizeof (sec), (char *) &sec) ctxt->offset, sizeof (sec), (char *) &sec)
!= sizeof (sec)) != sizeof (sec))
break; break;
@ -727,7 +728,7 @@ grub_fat_iterate_dir_next (grub_disk_t disk, struct grub_fat_data *data,
#else #else
static grub_err_t static grub_err_t
grub_fat_iterate_dir_next (grub_disk_t disk, struct grub_fat_data *data, grub_fat_iterate_dir_next (grub_fshelp_node_t node,
struct grub_fat_iterate_context *ctxt) struct grub_fat_iterate_context *ctxt)
{ {
char *filep = 0; char *filep = 0;
@ -742,7 +743,7 @@ grub_fat_iterate_dir_next (grub_disk_t disk, struct grub_fat_data *data,
ctxt->offset += sizeof (ctxt->dir); ctxt->offset += sizeof (ctxt->dir);
/* Read a directory entry. */ /* Read a directory entry. */
if (grub_fat_read_data (disk, data, 0, 0, if (grub_fat_read_data (node->disk, node, 0, 0,
ctxt->offset, sizeof (ctxt->dir), ctxt->offset, sizeof (ctxt->dir),
(char *) &ctxt->dir) (char *) &ctxt->dir)
!= sizeof (ctxt->dir) || ctxt->dir.name[0] == 0) != sizeof (ctxt->dir) || ctxt->dir.name[0] == 0)
@ -829,6 +830,8 @@ grub_fat_iterate_dir_next (grub_disk_t disk, struct grub_fat_data *data,
i--; i--;
} }
/* XXX should we check that dir position is 0 or 1? */
if (i > 2 || filep[0] != '.' || (i == 2 && filep[1] != '.'))
*filep++ = '.'; *filep++ = '.';
for (i = 8; i < 11 && ctxt->dir.name[i]; i++) for (i = 8; i < 11 && ctxt->dir.name[i]; i++)
@ -851,62 +854,20 @@ grub_fat_iterate_dir_next (grub_disk_t disk, struct grub_fat_data *data,
#endif #endif
/* Find the underlying directory or file in PATH and return the static grub_err_t lookup_file (grub_fshelp_node_t node,
next path. If there is no next path or an error occurs, return NULL. const char *name,
If HOOK is specified, call it with each file name. */ grub_fshelp_node_t *foundnode,
static char * enum grub_fshelp_filetype *foundtype)
grub_fat_find_dir (grub_disk_t disk, struct grub_fat_data *data,
const char *path, const char *origpath,
grub_fs_dir_hook_t hook, void *hook_data)
{ {
char *dirname, *dirp;
int call_hook;
int found = 0;
struct grub_fat_iterate_context ctxt;
grub_err_t err; grub_err_t err;
struct grub_fat_iterate_context ctxt;
if (! (data->attr & GRUB_FAT_ATTR_DIRECTORY))
{
grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory"));
return 0;
}
/* Extract a directory name. */
while (*path == '/')
path++;
dirp = grub_strchr (path, '/');
if (dirp)
{
unsigned len = dirp - path;
dirname = grub_malloc (len + 1);
if (! dirname)
goto fail;
grub_memcpy (dirname, path, len);
dirname[len] = '\0';
}
else
/* This is actually a file. */
dirname = grub_strdup (path);
call_hook = (! dirp && hook);
err = grub_fat_iterate_init (&ctxt); err = grub_fat_iterate_init (&ctxt);
if (err) if (err)
{ return err;
grub_free (dirname);
return 0;
}
while (!(err = grub_fat_iterate_dir_next (disk, data, &ctxt))) while (!(err = grub_fat_iterate_dir_next (node, &ctxt)))
{ {
struct grub_dirhook_info info;
grub_memset (&info, 0, sizeof (info));
info.dir = !! (ctxt.dir.attr & GRUB_FAT_ATTR_DIRECTORY);
info.case_insensitive = 1;
#ifdef MODE_EXFAT #ifdef MODE_EXFAT
if (!ctxt.dir.have_stream) if (!ctxt.dir.have_stream)
@ -915,33 +876,33 @@ grub_fat_find_dir (grub_disk_t disk, struct grub_fat_data *data,
if (ctxt.dir.attr & GRUB_FAT_ATTR_VOLUME_ID) if (ctxt.dir.attr & GRUB_FAT_ATTR_VOLUME_ID)
continue; continue;
#endif #endif
if (*dirname == '\0' && call_hook)
{
if (hook (ctxt.filename, &info, hook_data))
break;
else
continue;
}
if (grub_strcasecmp (dirname, ctxt.filename) == 0) if (grub_strcasecmp (name, ctxt.filename) == 0)
{ {
found = 1; *foundnode = grub_malloc (sizeof (struct grub_fshelp_node));
data->attr = ctxt.dir.attr; if (!*foundnode)
return grub_errno;
(*foundnode)->attr = ctxt.dir.attr;
#ifdef MODE_EXFAT #ifdef MODE_EXFAT
data->file_size = ctxt.dir.file_size; (*foundnode)->file_size = ctxt.dir.file_size;
data->file_cluster = ctxt.dir.first_cluster; (*foundnode)->file_cluster = ctxt.dir.first_cluster;
data->is_contiguous = ctxt.dir.is_contiguous; (*foundnode)->is_contiguous = ctxt.dir.is_contiguous;
#else #else
data->file_size = grub_le_to_cpu32 (ctxt.dir.file_size); (*foundnode)->file_size = grub_le_to_cpu32 (ctxt.dir.file_size);
data->file_cluster = ((grub_le_to_cpu16 (ctxt.dir.first_cluster_high) << 16) (*foundnode)->file_cluster = ((grub_le_to_cpu16 (ctxt.dir.first_cluster_high) << 16)
| grub_le_to_cpu16 (ctxt.dir.first_cluster_low)); | grub_le_to_cpu16 (ctxt.dir.first_cluster_low));
/* If directory points to root, starting cluster is 0 */
if (!(*foundnode)->file_cluster)
(*foundnode)->file_cluster = node->data->root_cluster;
#endif #endif
data->cur_cluster_num = ~0U; (*foundnode)->cur_cluster_num = ~0U;
(*foundnode)->data = node->data;
(*foundnode)->disk = node->disk;
if (call_hook) *foundtype = ((*foundnode)->attr & GRUB_FAT_ATTR_DIRECTORY) ? GRUB_FSHELP_DIR : GRUB_FSHELP_REG;
hook (ctxt.filename, &info, hook_data);
break; grub_fat_iterate_fini (&ctxt);
return GRUB_ERR_NONE;
} }
} }
@ -949,13 +910,8 @@ grub_fat_find_dir (grub_disk_t disk, struct grub_fat_data *data,
if (err == GRUB_ERR_EOF) if (err == GRUB_ERR_EOF)
err = 0; err = 0;
if (grub_errno == GRUB_ERR_NONE && ! found && !call_hook) return err;
grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"), origpath);
fail:
grub_free (dirname);
return found ? dirp : 0;
} }
static grub_err_t static grub_err_t
@ -964,9 +920,9 @@ grub_fat_dir (grub_device_t device, const char *path, grub_fs_dir_hook_t hook,
{ {
struct grub_fat_data *data = 0; struct grub_fat_data *data = 0;
grub_disk_t disk = device->disk; grub_disk_t disk = device->disk;
grub_size_t len; grub_fshelp_node_t found = NULL;
char *dirname = 0; grub_err_t err;
char *p; struct grub_fat_iterate_context ctxt;
grub_dl_ref (my_mod); grub_dl_ref (my_mod);
@ -974,27 +930,53 @@ grub_fat_dir (grub_device_t device, const char *path, grub_fs_dir_hook_t hook,
if (! data) if (! data)
goto fail; goto fail;
/* Make sure that DIRNAME terminates with '/'. */ struct grub_fshelp_node root = {
len = grub_strlen (path); .data = data,
dirname = grub_malloc (len + 1 + 1); .disk = disk,
if (! dirname) .attr = GRUB_FAT_ATTR_DIRECTORY,
goto fail; .file_size = 0,
grub_memcpy (dirname, path, len); .file_cluster = data->root_cluster,
p = dirname + len; .cur_cluster_num = ~0U,
if (path[len - 1] != '/') .cur_cluster = 0,
*p++ = '/'; #ifdef MODE_EXFAT
*p = '\0'; .is_contiguous = 0,
p = dirname; #endif
};
do err = grub_fshelp_find_file_lookup (path, &root, &found, lookup_file, NULL, GRUB_FSHELP_DIR);
if (err)
goto fail;
err = grub_fat_iterate_init (&ctxt);
if (err)
goto fail;
while (!(err = grub_fat_iterate_dir_next (found, &ctxt)))
{ {
p = grub_fat_find_dir (disk, data, p, path, hook, hook_data); struct grub_dirhook_info info;
grub_memset (&info, 0, sizeof (info));
info.dir = !! (ctxt.dir.attr & GRUB_FAT_ATTR_DIRECTORY);
info.case_insensitive = 1;
#ifdef MODE_EXFAT
if (!ctxt.dir.have_stream)
continue;
#else
if (ctxt.dir.attr & GRUB_FAT_ATTR_VOLUME_ID)
continue;
#endif
if (hook (ctxt.filename, &info, hook_data))
break;
} }
while (p && grub_errno == GRUB_ERR_NONE); grub_fat_iterate_fini (&ctxt);
if (err == GRUB_ERR_EOF)
err = 0;
fail: fail:
if (found != &root)
grub_free (found);
grub_free (dirname);
grub_free (data); grub_free (data);
grub_dl_unref (my_mod); grub_dl_unref (my_mod);
@ -1006,35 +988,43 @@ static grub_err_t
grub_fat_open (grub_file_t file, const char *name) grub_fat_open (grub_file_t file, const char *name)
{ {
struct grub_fat_data *data = 0; struct grub_fat_data *data = 0;
char *p = (char *) name; grub_fshelp_node_t found = NULL;
grub_err_t err;
grub_disk_t disk = file->device->disk;
grub_dl_ref (my_mod); grub_dl_ref (my_mod);
data = grub_fat_mount (file->device->disk); data = grub_fat_mount (disk);
if (! data) if (! data)
goto fail; goto fail;
do struct grub_fshelp_node root = {
{ .data = data,
p = grub_fat_find_dir (file->device->disk, data, p, name, 0, 0); .disk = disk,
if (grub_errno != GRUB_ERR_NONE) .attr = GRUB_FAT_ATTR_DIRECTORY,
goto fail; .file_size = 0,
} .file_cluster = data->root_cluster,
while (p); .cur_cluster_num = ~0U,
.cur_cluster = 0,
#ifdef MODE_EXFAT
.is_contiguous = 0,
#endif
};
if (data->attr & GRUB_FAT_ATTR_DIRECTORY) err = grub_fshelp_find_file_lookup (name, &root, &found, lookup_file, NULL, GRUB_FSHELP_REG);
{ if (err)
grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a regular file"));
goto fail; goto fail;
}
file->data = data; file->data = found;
file->size = data->file_size; file->size = found->file_size;
return GRUB_ERR_NONE; return GRUB_ERR_NONE;
fail: fail:
if (found != &root)
grub_free (found);
grub_free (data); grub_free (data);
grub_dl_unref (my_mod); grub_dl_unref (my_mod);
@ -1053,7 +1043,10 @@ grub_fat_read (grub_file_t file, char *buf, grub_size_t len)
static grub_err_t static grub_err_t
grub_fat_close (grub_file_t file) grub_fat_close (grub_file_t file)
{ {
grub_free (file->data); grub_fshelp_node_t node = file->data;
grub_free (node->data);
grub_free (node);
grub_dl_unref (my_mod); grub_dl_unref (my_mod);
@ -1066,20 +1059,29 @@ grub_fat_label (grub_device_t device, char **label)
{ {
struct grub_fat_dir_entry dir; struct grub_fat_dir_entry dir;
grub_ssize_t offset = -sizeof(dir); grub_ssize_t offset = -sizeof(dir);
struct grub_fat_data *data;
grub_disk_t disk = device->disk; grub_disk_t disk = device->disk;
struct grub_fshelp_node root = {
.disk = disk,
.attr = GRUB_FAT_ATTR_DIRECTORY,
.file_size = 0,
.cur_cluster_num = ~0U,
.cur_cluster = 0,
.is_contiguous = 0,
};
data = grub_fat_mount (disk); root.data = grub_fat_mount (disk);
if (! data) if (! root.data)
return grub_errno; return grub_errno;
root.file_cluster = root.data->root_cluster;
*label = NULL; *label = NULL;
while (1) while (1)
{ {
offset += sizeof (dir); offset += sizeof (dir);
if (grub_fat_read_data (disk, data, 0, 0, if (grub_fat_read_data (disk, &root, 0, 0,
offset, sizeof (dir), (char *) &dir) offset, sizeof (dir), (char *) &dir)
!= sizeof (dir)) != sizeof (dir))
break; break;
@ -1099,7 +1101,7 @@ grub_fat_label (grub_device_t device, char **label)
* GRUB_MAX_UTF8_PER_UTF16 + 1); * GRUB_MAX_UTF8_PER_UTF16 + 1);
if (!*label) if (!*label)
{ {
grub_free (data); grub_free (root.data);
return grub_errno; return grub_errno;
} }
chc = dir.type_specific.volume_label.character_count; chc = dir.type_specific.volume_label.character_count;
@ -1111,7 +1113,7 @@ grub_fat_label (grub_device_t device, char **label)
} }
} }
grub_free (data); grub_free (root.data);
return grub_errno; return grub_errno;
} }
@ -1120,30 +1122,32 @@ grub_fat_label (grub_device_t device, char **label)
static grub_err_t static grub_err_t
grub_fat_label (grub_device_t device, char **label) grub_fat_label (grub_device_t device, char **label)
{ {
struct grub_fat_data *data;
grub_disk_t disk = device->disk; grub_disk_t disk = device->disk;
grub_err_t err; grub_err_t err;
struct grub_fat_iterate_context ctxt; struct grub_fat_iterate_context ctxt;
struct grub_fshelp_node root = {
.disk = disk,
.attr = GRUB_FAT_ATTR_DIRECTORY,
.file_size = 0,
.cur_cluster_num = ~0U,
.cur_cluster = 0,
};
*label = 0; *label = 0;
grub_dl_ref (my_mod); grub_dl_ref (my_mod);
data = grub_fat_mount (disk); root.data = grub_fat_mount (disk);
if (! data) if (! root.data)
goto fail; goto fail;
if (! (data->attr & GRUB_FAT_ATTR_DIRECTORY)) root.file_cluster = root.data->root_cluster;
{
grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory"));
goto fail;
}
err = grub_fat_iterate_init (&ctxt); err = grub_fat_iterate_init (&ctxt);
if (err) if (err)
goto fail; goto fail;
while (!(err = grub_fat_iterate_dir_next (disk, data, &ctxt))) while (!(err = grub_fat_iterate_dir_next (&root, &ctxt)))
if ((ctxt.dir.attr & ~GRUB_FAT_ATTR_ARCHIVE) == GRUB_FAT_ATTR_VOLUME_ID) if ((ctxt.dir.attr & ~GRUB_FAT_ATTR_ARCHIVE) == GRUB_FAT_ATTR_VOLUME_ID)
{ {
*label = grub_strdup (ctxt.filename); *label = grub_strdup (ctxt.filename);
@ -1156,7 +1160,7 @@ grub_fat_label (grub_device_t device, char **label)
grub_dl_unref (my_mod); grub_dl_unref (my_mod);
grub_free (data); grub_free (root.data);
return grub_errno; return grub_errno;
} }

View file

@ -30,169 +30,287 @@ GRUB_MOD_LICENSE ("GPLv3+");
typedef int (*iterate_dir_func) (grub_fshelp_node_t dir, typedef int (*iterate_dir_func) (grub_fshelp_node_t dir,
grub_fshelp_iterate_dir_hook_t hook, grub_fshelp_iterate_dir_hook_t hook,
void *data); void *data);
typedef grub_err_t (*lookup_file_func) (grub_fshelp_node_t dir,
const char *name,
grub_fshelp_node_t *foundnode,
enum grub_fshelp_filetype *foundtype);
typedef char *(*read_symlink_func) (grub_fshelp_node_t node); typedef char *(*read_symlink_func) (grub_fshelp_node_t node);
struct stack_element {
struct stack_element *parent;
grub_fshelp_node_t node;
enum grub_fshelp_filetype type;
};
/* Context for grub_fshelp_find_file. */ /* Context for grub_fshelp_find_file. */
struct grub_fshelp_find_file_ctx struct grub_fshelp_find_file_ctx
{ {
/* Inputs. */
const char *path; const char *path;
grub_fshelp_node_t rootnode, currroot, currnode, oldnode; grub_fshelp_node_t rootnode;
enum grub_fshelp_filetype foundtype;
/* Global options. */
int symlinknest; int symlinknest;
const char *name;
const char *next; /* Current file being traversed and its parents. */
enum grub_fshelp_filetype type; struct stack_element *currnode;
}; };
/* Helper for find_file_iter. */ /* Helper for find_file_iter. */
static void static void
free_node (grub_fshelp_node_t node, struct grub_fshelp_find_file_ctx *ctx) free_node (grub_fshelp_node_t node, struct grub_fshelp_find_file_ctx *ctx)
{ {
if (node != ctx->rootnode && node != ctx->currroot) if (node != ctx->rootnode)
grub_free (node); grub_free (node);
} }
static void
pop_element (struct grub_fshelp_find_file_ctx *ctx)
{
struct stack_element *el;
el = ctx->currnode;
ctx->currnode = el->parent;
free_node (el->node, ctx);
grub_free (el);
}
static void
free_stack (struct grub_fshelp_find_file_ctx *ctx)
{
while (ctx->currnode)
pop_element (ctx);
}
static void
go_up_a_level (struct grub_fshelp_find_file_ctx *ctx)
{
if (!ctx->currnode->parent)
return;
pop_element (ctx);
}
static grub_err_t
push_node (struct grub_fshelp_find_file_ctx *ctx, grub_fshelp_node_t node, enum grub_fshelp_filetype filetype)
{
struct stack_element *nst;
nst = grub_malloc (sizeof (*nst));
if (!nst)
return grub_errno;
nst->node = node;
nst->type = filetype & ~GRUB_FSHELP_CASE_INSENSITIVE;
nst->parent = ctx->currnode;
ctx->currnode = nst;
return GRUB_ERR_NONE;
}
static grub_err_t
go_to_root (struct grub_fshelp_find_file_ctx *ctx)
{
free_stack (ctx);
return push_node (ctx, ctx->rootnode, GRUB_FSHELP_DIR);
}
struct grub_fshelp_find_file_iter_ctx
{
const char *name;
grub_fshelp_node_t *foundnode;
enum grub_fshelp_filetype *foundtype;
};
/* Helper for grub_fshelp_find_file. */ /* Helper for grub_fshelp_find_file. */
static int static int
find_file_iter (const char *filename, enum grub_fshelp_filetype filetype, find_file_iter (const char *filename, enum grub_fshelp_filetype filetype,
grub_fshelp_node_t node, void *data) grub_fshelp_node_t node, void *data)
{ {
struct grub_fshelp_find_file_ctx *ctx = data; struct grub_fshelp_find_file_iter_ctx *ctx = data;
if (filetype == GRUB_FSHELP_UNKNOWN || if (filetype == GRUB_FSHELP_UNKNOWN ||
((filetype & GRUB_FSHELP_CASE_INSENSITIVE) ((filetype & GRUB_FSHELP_CASE_INSENSITIVE)
? grub_strncasecmp (ctx->name, filename, ctx->next - ctx->name) ? grub_strcasecmp (ctx->name, filename)
: grub_strncmp (ctx->name, filename, ctx->next - ctx->name)) : grub_strcmp (ctx->name, filename)))
|| filename[ctx->next - ctx->name])
{ {
grub_free (node); grub_free (node);
return 0; return 0;
} }
/* The node is found, stop iterating over the nodes. */ /* The node is found, stop iterating over the nodes. */
ctx->type = filetype & ~GRUB_FSHELP_CASE_INSENSITIVE; *ctx->foundnode = node;
ctx->oldnode = ctx->currnode; *ctx->foundtype = filetype;
ctx->currnode = node;
return 1; return 1;
} }
static grub_err_t static grub_err_t
find_file (const char *currpath, grub_fshelp_node_t currroot, directory_find_file (grub_fshelp_node_t node, const char *name, grub_fshelp_node_t *foundnode,
grub_fshelp_node_t *currfound, enum grub_fshelp_filetype *foundtype, iterate_dir_func iterate_dir)
iterate_dir_func iterate_dir, read_symlink_func read_symlink, {
int found;
struct grub_fshelp_find_file_iter_ctx ctx = {
.foundnode = foundnode,
.foundtype = foundtype,
.name = name
};
found = iterate_dir (node, find_file_iter, &ctx);
if (! found)
{
if (grub_errno)
return grub_errno;
}
return GRUB_ERR_NONE;
}
static grub_err_t
find_file (char *currpath,
iterate_dir_func iterate_dir, lookup_file_func lookup_file,
read_symlink_func read_symlink,
struct grub_fshelp_find_file_ctx *ctx) struct grub_fshelp_find_file_ctx *ctx)
{ {
ctx->currroot = currroot; char *name, *next;
ctx->name = currpath; grub_err_t err;
ctx->type = GRUB_FSHELP_DIR; for (name = currpath; ; name = next)
ctx->currnode = currroot;
ctx->oldnode = currroot;
for (;;)
{ {
int found; char c;
grub_fshelp_node_t foundnode = NULL;
enum grub_fshelp_filetype foundtype = 0;
/* Remove all leading slashes. */ /* Remove all leading slashes. */
while (*ctx->name == '/') while (*name == '/')
ctx->name++; name++;
/* Found the node! */ /* Found the node! */
if (! *ctx->name) if (! *name)
{
*currfound = ctx->currnode;
ctx->foundtype = ctx->type;
return 0; return 0;
}
/* Extract the actual part from the pathname. */ /* Extract the actual part from the pathname. */
for (ctx->next = ctx->name; *ctx->next && *ctx->next != '/'; ctx->next++); for (next = name; *next && *next != '/'; next++);
/* At this point it is expected that the current node is a /* At this point it is expected that the current node is a
directory, check if this is true. */ directory, check if this is true. */
if (ctx->type != GRUB_FSHELP_DIR) if (ctx->currnode->type != GRUB_FSHELP_DIR)
{
free_node (ctx->currnode, ctx);
ctx->currnode = 0;
return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory")); return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory"));
/* Don't rely on fs providing actual . in the listing. */
if (next - name == 1 && name[0] == '.')
continue;
/* Don't rely on fs providing actual .. in the listing. */
if (next - name == 2 && name[0] == '.' && name[1] == '.')
{
go_up_a_level (ctx);
continue;
} }
/* Iterate over the directory. */ /* Iterate over the directory. */
found = iterate_dir (ctx->currnode, find_file_iter, ctx); c = *next;
if (! found) *next = '\0';
{ if (lookup_file)
free_node (ctx->currnode, ctx); err = lookup_file (ctx->currnode->node, name, &foundnode, &foundtype);
ctx->currnode = 0; else
if (grub_errno) err = directory_find_file (ctx->currnode->node, name, &foundnode, &foundtype, iterate_dir);
return grub_errno; *next = c;
if (err)
return err;
if (!foundnode)
break; break;
}
push_node (ctx, foundnode, foundtype);
/* Read in the symlink and follow it. */ /* Read in the symlink and follow it. */
if (ctx->type == GRUB_FSHELP_SYMLINK) if (ctx->currnode->type == GRUB_FSHELP_SYMLINK)
{ {
char *symlink; char *symlink;
const char *next;
/* Test if the symlink does not loop. */ /* Test if the symlink does not loop. */
if (++ctx->symlinknest == 8) if (++ctx->symlinknest == 8)
{
free_node (ctx->currnode, ctx);
free_node (ctx->oldnode, ctx);
ctx->currnode = 0;
ctx->oldnode = 0;
return grub_error (GRUB_ERR_SYMLINK_LOOP, return grub_error (GRUB_ERR_SYMLINK_LOOP,
N_("too deep nesting of symlinks")); N_("too deep nesting of symlinks"));
}
symlink = read_symlink (ctx->currnode); symlink = read_symlink (ctx->currnode->node);
free_node (ctx->currnode, ctx);
ctx->currnode = 0;
if (!symlink) if (!symlink)
{
free_node (ctx->oldnode, ctx);
ctx->oldnode = 0;
return grub_errno; return grub_errno;
}
/* The symlink is an absolute path, go back to the root inode. */ /* The symlink is an absolute path, go back to the root inode. */
if (symlink[0] == '/') if (symlink[0] == '/')
{ {
free_node (ctx->oldnode, ctx); err = go_to_root (ctx);
ctx->oldnode = ctx->rootnode; if (err)
return err;
}
else
{
/* Get from symlink to containing directory. */
go_up_a_level (ctx);
} }
/* Lookup the node the symlink points to. */ /* Lookup the node the symlink points to. */
next = ctx->next; find_file (symlink, iterate_dir, lookup_file, read_symlink, ctx);
find_file (symlink, ctx->oldnode, &ctx->currnode,
iterate_dir, read_symlink, ctx);
ctx->next = next;
ctx->type = ctx->foundtype;
grub_free (symlink); grub_free (symlink);
if (grub_errno) if (grub_errno)
{
free_node (ctx->oldnode, ctx);
ctx->oldnode = 0;
return grub_errno; return grub_errno;
} }
} }
if (ctx->oldnode != ctx->currnode)
{
free_node (ctx->oldnode, ctx);
ctx->oldnode = 0;
}
ctx->name = ctx->next;
}
return grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"), return grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"),
ctx->path); ctx->path);
} }
static grub_err_t
grub_fshelp_find_file_real (const char *path, grub_fshelp_node_t rootnode,
grub_fshelp_node_t *foundnode,
iterate_dir_func iterate_dir,
lookup_file_func lookup_file,
read_symlink_func read_symlink,
enum grub_fshelp_filetype expecttype)
{
struct grub_fshelp_find_file_ctx ctx = {
.path = path,
.rootnode = rootnode,
.symlinknest = 0,
.currnode = 0
};
grub_err_t err;
enum grub_fshelp_filetype foundtype;
char *duppath;
if (!path || path[0] != '/')
{
return grub_error (GRUB_ERR_BAD_FILENAME, N_("invalid file name `%s'"), path);
}
err = go_to_root (&ctx);
if (err)
return err;
duppath = grub_strdup (path);
if (!duppath)
return grub_errno;
err = find_file (duppath, iterate_dir, lookup_file, read_symlink, &ctx);
grub_free (duppath);
if (err)
{
free_stack (&ctx);
return err;
}
*foundnode = ctx.currnode->node;
foundtype = ctx.currnode->type;
/* Avoid the node being freed. */
ctx.currnode->node = 0;
free_stack (&ctx);
/* Check if the node that was found was of the expected type. */
if (expecttype == GRUB_FSHELP_REG && foundtype != expecttype)
return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a regular file"));
else if (expecttype == GRUB_FSHELP_DIR && foundtype != expecttype)
return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory"));
return 0;
}
/* Lookup the node PATH. The node ROOTNODE describes the root of the /* Lookup the node PATH. The node ROOTNODE describes the root of the
directory tree. The node found is returned in FOUNDNODE, which is directory tree. The node found is returned in FOUNDNODE, which is
either a ROOTNODE or a new malloc'ed node. ITERATE_DIR is used to either a ROOTNODE or a new malloc'ed node. ITERATE_DIR is used to
@ -207,31 +325,23 @@ grub_fshelp_find_file (const char *path, grub_fshelp_node_t rootnode,
read_symlink_func read_symlink, read_symlink_func read_symlink,
enum grub_fshelp_filetype expecttype) enum grub_fshelp_filetype expecttype)
{ {
struct grub_fshelp_find_file_ctx ctx = { return grub_fshelp_find_file_real (path, rootnode, foundnode,
.path = path, iterate_dir, NULL,
.rootnode = rootnode, read_symlink, expecttype);
.foundtype = GRUB_FSHELP_DIR,
.symlinknest = 0
};
grub_err_t err;
if (!path || path[0] != '/') }
{
grub_error (GRUB_ERR_BAD_FILENAME, N_("invalid file name `%s'"), path);
return grub_errno;
}
err = find_file (path, rootnode, foundnode, iterate_dir, read_symlink, &ctx); grub_err_t
if (err) grub_fshelp_find_file_lookup (const char *path, grub_fshelp_node_t rootnode,
return err; grub_fshelp_node_t *foundnode,
lookup_file_func lookup_file,
read_symlink_func read_symlink,
enum grub_fshelp_filetype expecttype)
{
return grub_fshelp_find_file_real (path, rootnode, foundnode,
NULL, lookup_file,
read_symlink, expecttype);
/* Check if the node that was found was of the expected type. */
if (expecttype == GRUB_FSHELP_REG && ctx.foundtype != expecttype)
return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a regular file"));
else if (expecttype == GRUB_FSHELP_DIR && ctx.foundtype != expecttype)
return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory"));
return 0;
} }
/* Read LEN bytes from the file NODE on disk DISK into the buffer BUF, /* Read LEN bytes from the file NODE on disk DISK into the buffer BUF,

View file

@ -29,6 +29,7 @@
#include <grub/types.h> #include <grub/types.h>
#include <grub/hfs.h> #include <grub/hfs.h>
#include <grub/i18n.h> #include <grub/i18n.h>
#include <grub/fshelp.h>
GRUB_MOD_LICENSE ("GPLv3+"); GRUB_MOD_LICENSE ("GPLv3+");
@ -1125,90 +1126,81 @@ utf8_to_macroman (grub_uint8_t *to, const char *from)
return optr - to; return optr - to;
} }
union grub_hfs_anyrec {
struct grub_hfs_filerec frec;
struct grub_hfs_dirrec dir;
};
struct grub_fshelp_node
{
struct grub_hfs_data *data;
union grub_hfs_anyrec fdrec;
grub_uint32_t inode;
};
static grub_err_t
lookup_file (grub_fshelp_node_t dir,
const char *name,
grub_fshelp_node_t *foundnode,
enum grub_fshelp_filetype *foundtype)
{
struct grub_hfs_catalog_key key;
grub_ssize_t slen;
union grub_hfs_anyrec fdrec;
key.parent_dir = grub_cpu_to_be32 (dir->inode);
slen = utf8_to_macroman (key.str, name);
if (slen < 0)
/* Not found */
return GRUB_ERR_NONE;
key.strlen = slen;
/* Lookup this node. */
if (! grub_hfs_find_node (dir->data, (char *) &key, dir->data->cat_root,
0, (char *) &fdrec.frec, sizeof (fdrec.frec)))
/* Not found */
return GRUB_ERR_NONE;
*foundnode = grub_malloc (sizeof (struct grub_fshelp_node));
if (!*foundnode)
return grub_errno;
(*foundnode)->inode = grub_be_to_cpu32 (fdrec.dir.dirid);
(*foundnode)->fdrec = fdrec;
(*foundnode)->data = dir->data;
*foundtype = (fdrec.frec.type == GRUB_HFS_FILETYPE_DIR) ? GRUB_FSHELP_DIR : GRUB_FSHELP_REG;
return GRUB_ERR_NONE;
}
/* Find a file or directory with the pathname PATH in the filesystem /* Find a file or directory with the pathname PATH in the filesystem
DATA. Return the file record in RETDATA when it is non-zero. DATA. Return the file record in RETDATA when it is non-zero.
Return the directory number in RETINODE when it is non-zero. */ Return the directory number in RETINODE when it is non-zero. */
static grub_err_t static grub_err_t
grub_hfs_find_dir (struct grub_hfs_data *data, const char *path, grub_hfs_find_dir (struct grub_hfs_data *data, const char *path,
struct grub_hfs_filerec *retdata, int *retinode) grub_fshelp_node_t *found,
enum grub_fshelp_filetype exptype)
{ {
int inode = data->rootdir; struct grub_fshelp_node root = {
char *next; .data = data,
char *origpath; .inode = data->rootdir,
union { .fdrec = {
struct grub_hfs_filerec frec; .frec = {
struct grub_hfs_dirrec dir; .type = GRUB_HFS_FILETYPE_DIR
} fdrec;
fdrec.frec.type = GRUB_HFS_FILETYPE_DIR;
if (path[0] != '/')
{
grub_error (GRUB_ERR_BAD_FILENAME, N_("invalid file name `%s'"), path);
return 0;
} }
}
};
grub_err_t err;
origpath = grub_strdup (path); err = grub_fshelp_find_file_lookup (path, &root, found, lookup_file, NULL, exptype);
if (!origpath)
if (&root == *found)
{
*found = grub_malloc (sizeof (root));
if (!*found)
return grub_errno; return grub_errno;
grub_memcpy (*found, &root, sizeof (root));
path = origpath;
while (*path == '/')
path++;
while (path && grub_strlen (path))
{
grub_ssize_t slen;
if (fdrec.frec.type != GRUB_HFS_FILETYPE_DIR)
{
grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory"));
goto fail;
} }
return err;
/* Isolate a part of the path. */
next = grub_strchr (path, '/');
if (next)
{
while (*next == '/')
*(next++) = '\0';
}
struct grub_hfs_catalog_key key;
key.parent_dir = grub_cpu_to_be32 (inode);
slen = utf8_to_macroman (key.str, path);
if (slen < 0)
{
grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"), path);
goto fail;
}
key.strlen = slen;
/* Lookup this node. */
if (! grub_hfs_find_node (data, (char *) &key, data->cat_root,
0, (char *) &fdrec.frec, sizeof (fdrec.frec)))
{
grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"), origpath);
goto fail;
}
if (grub_errno)
goto fail;
inode = grub_be_to_cpu32 (fdrec.dir.dirid);
path = next;
}
if (retdata)
grub_memcpy (retdata, &fdrec.frec, sizeof (fdrec.frec));
if (retinode)
*retinode = inode;
fail:
grub_free (origpath);
return grub_errno;
} }
struct grub_hfs_dir_hook_ctx struct grub_hfs_dir_hook_ctx
@ -1266,15 +1258,13 @@ static grub_err_t
grub_hfs_dir (grub_device_t device, const char *path, grub_fs_dir_hook_t hook, grub_hfs_dir (grub_device_t device, const char *path, grub_fs_dir_hook_t hook,
void *hook_data) void *hook_data)
{ {
int inode;
struct grub_hfs_data *data; struct grub_hfs_data *data;
struct grub_hfs_filerec frec;
struct grub_hfs_dir_hook_ctx ctx = struct grub_hfs_dir_hook_ctx ctx =
{ {
.hook = hook, .hook = hook,
.hook_data = hook_data .hook_data = hook_data
}; };
grub_fshelp_node_t found = NULL;
grub_dl_ref (my_mod); grub_dl_ref (my_mod);
@ -1283,18 +1273,13 @@ grub_hfs_dir (grub_device_t device, const char *path, grub_fs_dir_hook_t hook,
goto fail; goto fail;
/* First the directory ID for the directory. */ /* First the directory ID for the directory. */
if (grub_hfs_find_dir (data, path, &frec, &inode)) if (grub_hfs_find_dir (data, path, &found, GRUB_FSHELP_DIR))
goto fail; goto fail;
if (frec.type != GRUB_HFS_FILETYPE_DIR) grub_hfs_iterate_dir (data, data->cat_root, found->inode, grub_hfs_dir_hook, &ctx);
{
grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory"));
goto fail;
}
grub_hfs_iterate_dir (data, data->cat_root, inode, grub_hfs_dir_hook, &ctx);
fail: fail:
grub_free (found);
grub_free (data); grub_free (data);
grub_dl_unref (my_mod); grub_dl_unref (my_mod);
@ -1308,7 +1293,7 @@ static grub_err_t
grub_hfs_open (struct grub_file *file, const char *name) grub_hfs_open (struct grub_file *file, const char *name)
{ {
struct grub_hfs_data *data; struct grub_hfs_data *data;
struct grub_hfs_filerec frec; grub_fshelp_node_t found = NULL;
grub_dl_ref (my_mod); grub_dl_ref (my_mod);
@ -1320,29 +1305,23 @@ grub_hfs_open (struct grub_file *file, const char *name)
return grub_errno; return grub_errno;
} }
if (grub_hfs_find_dir (data, name, &frec, 0)) if (grub_hfs_find_dir (data, name, &found, GRUB_FSHELP_REG))
{ {
grub_free (data); grub_free (data);
grub_dl_unref (my_mod); grub_dl_unref (my_mod);
return grub_errno; return grub_errno;
} }
if (frec.type != GRUB_HFS_FILETYPE_FILE) grub_memcpy (data->extents, found->fdrec.frec.extents, sizeof (grub_hfs_datarecord_t));
{ file->size = grub_be_to_cpu32 (found->fdrec.frec.size);
grub_free (data); data->size = grub_be_to_cpu32 (found->fdrec.frec.size);
grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a regular file")); data->fileid = grub_be_to_cpu32 (found->fdrec.frec.fileid);
grub_dl_unref (my_mod);
return grub_errno;
}
grub_memcpy (data->extents, frec.extents, sizeof (grub_hfs_datarecord_t));
file->size = grub_be_to_cpu32 (frec.size);
data->size = grub_be_to_cpu32 (frec.size);
data->fileid = grub_be_to_cpu32 (frec.fileid);
file->offset = 0; file->offset = 0;
file->data = data; file->data = data;
grub_free (found);
return 0; return 0;
} }

View file

@ -22,6 +22,7 @@
#include <grub/file.h> #include <grub/file.h>
#include <grub/mm.h> #include <grub/mm.h>
#include <grub/dl.h> #include <grub/dl.h>
#include <grub/archelp.h>
GRUB_MOD_LICENSE ("GPLv3+"); GRUB_MOD_LICENSE ("GPLv3+");
@ -74,6 +75,44 @@ grub_procdev_write (grub_disk_t disk __attribute ((unused)),
return GRUB_ERR_OUT_OF_RANGE; return GRUB_ERR_OUT_OF_RANGE;
} }
struct grub_archelp_data
{
struct grub_procfs_entry *entry, *next_entry;
};
static void
grub_procfs_rewind (struct grub_archelp_data *data)
{
data->entry = NULL;
data->next_entry = grub_procfs_entries;
}
static grub_err_t
grub_procfs_find_file (struct grub_archelp_data *data, char **name,
grub_int32_t *mtime,
grub_uint32_t *mode)
{
data->entry = data->next_entry;
if (!data->entry)
{
*mode = GRUB_ARCHELP_ATTR_END;
return GRUB_ERR_NONE;
}
data->next_entry = data->entry->next;
*mode = GRUB_ARCHELP_ATTR_FILE | GRUB_ARCHELP_ATTR_NOTIME;
*name = grub_strdup (data->entry->name);
*mtime = 0;
if (!*name)
return grub_errno;
return GRUB_ERR_NONE;
}
static struct grub_archelp_ops arcops =
{
.find_file = grub_procfs_find_file,
.rewind = grub_procfs_rewind
};
static grub_ssize_t static grub_ssize_t
grub_procfs_read (grub_file_t file, char *buf, grub_size_t len) grub_procfs_read (grub_file_t file, char *buf, grub_size_t len)
{ {
@ -99,44 +138,35 @@ static grub_err_t
grub_procfs_dir (grub_device_t device, const char *path, grub_procfs_dir (grub_device_t device, const char *path,
grub_fs_dir_hook_t hook, void *hook_data) grub_fs_dir_hook_t hook, void *hook_data)
{ {
const char *ptr; struct grub_archelp_data data;
struct grub_dirhook_info info;
struct grub_procfs_entry *entry;
grub_memset (&info, 0, sizeof (info));
/* Check if the disk is our dummy disk. */ /* Check if the disk is our dummy disk. */
if (grub_strcmp (device->disk->name, "proc")) if (grub_strcmp (device->disk->name, "proc"))
return grub_error (GRUB_ERR_BAD_FS, "not a procfs"); return grub_error (GRUB_ERR_BAD_FS, "not a procfs");
for (ptr = path; *ptr == '/'; ptr++);
if (*ptr) grub_procfs_rewind (&data);
return 0;
FOR_LIST_ELEMENTS((entry), (grub_procfs_entries)) return grub_archelp_dir (&data, &arcops,
if (hook (entry->name, &info, hook_data)) path, hook, hook_data);
return 0;
return 0;
} }
static grub_err_t static grub_err_t
grub_procfs_open (struct grub_file *file, const char *path) grub_procfs_open (struct grub_file *file, const char *path)
{ {
const char *pathptr; grub_err_t err;
struct grub_procfs_entry *entry; struct grub_archelp_data data;
for (pathptr = path; *pathptr == '/'; pathptr++);
FOR_LIST_ELEMENTS((entry), (grub_procfs_entries))
if (grub_strcmp (pathptr, entry->name) == 0)
{
grub_size_t sz; grub_size_t sz;
file->data = entry->get_contents (&sz);
grub_procfs_rewind (&data);
err = grub_archelp_open (&data, &arcops, path);
if (err)
return err;
file->data = data.entry->get_contents (&sz);
if (!file->data) if (!file->data)
return grub_errno; return grub_errno;
file->size = sz; file->size = sz;
return GRUB_ERR_NONE; return GRUB_ERR_NONE;
}
return grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"), path);
} }
static struct grub_disk_dev grub_procfs_dev = { static struct grub_disk_dev grub_procfs_dev = {

View file

@ -783,12 +783,30 @@ grub_reiserfs_iterate_dir (grub_fshelp_node_t item,
struct grub_reiserfs_key entry_key; struct grub_reiserfs_key entry_key;
enum grub_fshelp_filetype entry_type; enum grub_fshelp_filetype entry_type;
char *entry_name; char *entry_name;
char *entry_name_end = 0;
char c;
if (!(entry_state & GRUB_REISERFS_VISIBLE_MASK)) if (!(entry_state & GRUB_REISERFS_VISIBLE_MASK))
continue; continue;
entry_name = (((char *) directory_headers) entry_name = (((char *) directory_headers)
+ grub_le_to_cpu16 (directory_header->location)); + grub_le_to_cpu16 (directory_header->location));
if (entry_number == 0)
{
entry_name_end = (char *) block_header
+ grub_le_to_cpu16 (item_headers[block_position].item_location)
+ grub_le_to_cpu16 (item_headers[block_position].item_size);
}
else
{
entry_name_end = (((char *) directory_headers)
+ grub_le_to_cpu16 (directory_headers[entry_number - 1].location));
}
if (entry_name_end < entry_name || entry_name_end > (char *) block_header + block_size)
{
entry_name_end = (char *) block_header + block_size;
}
entry_key.directory_id = directory_header->directory_id; entry_key.directory_id = directory_header->directory_id;
entry_key.object_id = directory_header->object_id; entry_key.object_id = directory_header->object_id;
entry_key.u.v2.offset_type = 0; entry_key.u.v2.offset_type = 0;
@ -935,7 +953,7 @@ grub_reiserfs_iterate_dir (grub_fshelp_node_t item,
else else
{ {
/* Pseudo file ".." never has stat block. */ /* Pseudo file ".." never has stat block. */
if (grub_strcmp (entry_name, "..")) if (entry_name_end == entry_name + 2 && grub_memcmp (entry_name, "..", 2) != 0)
grub_dprintf ("reiserfs", grub_dprintf ("reiserfs",
"Warning : %s has no stat block !\n", "Warning : %s has no stat block !\n",
entry_name); entry_name);
@ -943,18 +961,21 @@ grub_reiserfs_iterate_dir (grub_fshelp_node_t item,
goto next; goto next;
} }
} }
c = *entry_name_end;
*entry_name_end = 0;
if (hook (entry_name, entry_type, entry_item, hook_data)) if (hook (entry_name, entry_type, entry_item, hook_data))
{ {
*entry_name_end = c;
grub_dprintf ("reiserfs", "Found : %s, type=%d\n", grub_dprintf ("reiserfs", "Found : %s, type=%d\n",
entry_name, entry_type); entry_name, entry_type);
ret = 1; ret = 1;
goto found; goto found;
} }
*entry_name_end = c;
next: next:
*entry_name = 0; /* Make sure next entry name (which is just ;
before this one in disk order) stops before
the current one. */
} }
if (next_offset == 0) if (next_offset == 0)

View file

@ -34,6 +34,50 @@ GRUB_MOD_LICENSE ("GPLv3+");
#define XFS_INODE_FORMAT_EXT 2 #define XFS_INODE_FORMAT_EXT 2
#define XFS_INODE_FORMAT_BTREE 3 #define XFS_INODE_FORMAT_BTREE 3
/* Superblock version field flags */
#define XFS_SB_VERSION_NUMBITS 0x000f
#define XFS_SB_VERSION_ATTRBIT 0x0010
#define XFS_SB_VERSION_NLINKBIT 0x0020
#define XFS_SB_VERSION_QUOTABIT 0x0040
#define XFS_SB_VERSION_ALIGNBIT 0x0080
#define XFS_SB_VERSION_DALIGNBIT 0x0100
#define XFS_SB_VERSION_LOGV2BIT 0x0400
#define XFS_SB_VERSION_SECTORBIT 0x0800
#define XFS_SB_VERSION_EXTFLGBIT 0x1000
#define XFS_SB_VERSION_DIRV2BIT 0x2000
#define XFS_SB_VERSION_MOREBITSBIT 0x8000
#define XFS_SB_VERSION_BITS_SUPPORTED \
(XFS_SB_VERSION_NUMBITS | \
XFS_SB_VERSION_ATTRBIT | \
XFS_SB_VERSION_NLINKBIT | \
XFS_SB_VERSION_QUOTABIT | \
XFS_SB_VERSION_ALIGNBIT | \
XFS_SB_VERSION_DALIGNBIT | \
XFS_SB_VERSION_LOGV2BIT | \
XFS_SB_VERSION_SECTORBIT | \
XFS_SB_VERSION_EXTFLGBIT | \
XFS_SB_VERSION_DIRV2BIT | \
XFS_SB_VERSION_MOREBITSBIT)
/* Recognized xfs format versions */
#define XFS_SB_VERSION_4 4 /* Good old XFS filesystem */
#define XFS_SB_VERSION_5 5 /* CRC enabled filesystem */
/* features2 field flags */
#define XFS_SB_VERSION2_LAZYSBCOUNTBIT 0x00000002 /* Superblk counters */
#define XFS_SB_VERSION2_ATTR2BIT 0x00000008 /* Inline attr rework */
#define XFS_SB_VERSION2_PROJID32BIT 0x00000080 /* 32-bit project ids */
#define XFS_SB_VERSION2_FTYPE 0x00000200 /* inode type in dir */
#define XFS_SB_VERSION2_BITS_SUPPORTED \
(XFS_SB_VERSION2_LAZYSBCOUNTBIT | \
XFS_SB_VERSION2_ATTR2BIT | \
XFS_SB_VERSION2_PROJID32BIT | \
XFS_SB_VERSION2_FTYPE)
/* incompat feature flags */
#define XFS_SB_FEAT_INCOMPAT_FTYPE (1 << 0) /* filetype in dirent */
#define XFS_SB_FEAT_INCOMPAT_SUPPORTED \
(XFS_SB_FEAT_INCOMPAT_FTYPE)
struct grub_xfs_sblock struct grub_xfs_sblock
{ {
@ -45,7 +89,9 @@ struct grub_xfs_sblock
grub_uint64_t rootino; grub_uint64_t rootino;
grub_uint8_t unused3[20]; grub_uint8_t unused3[20];
grub_uint32_t agsize; grub_uint32_t agsize;
grub_uint8_t unused4[20]; grub_uint8_t unused4[12];
grub_uint16_t version;
grub_uint8_t unused5[6];
grub_uint8_t label[12]; grub_uint8_t label[12];
grub_uint8_t log2_bsize; grub_uint8_t log2_bsize;
grub_uint8_t log2_sect; grub_uint8_t log2_sect;
@ -54,12 +100,19 @@ struct grub_xfs_sblock
grub_uint8_t log2_agblk; grub_uint8_t log2_agblk;
grub_uint8_t unused6[67]; grub_uint8_t unused6[67];
grub_uint8_t log2_dirblk; grub_uint8_t log2_dirblk;
grub_uint8_t unused7[7];
grub_uint32_t features2;
grub_uint8_t unused8[4];
grub_uint32_t sb_features_compat;
grub_uint32_t sb_features_ro_compat;
grub_uint32_t sb_features_incompat;
grub_uint32_t sb_features_log_incompat;
} GRUB_PACKED; } GRUB_PACKED;
struct grub_xfs_dir_header struct grub_xfs_dir_header
{ {
grub_uint8_t count; grub_uint8_t count;
grub_uint8_t smallino; grub_uint8_t largeino;
union union
{ {
grub_uint32_t i4; grub_uint32_t i4;
@ -67,21 +120,29 @@ struct grub_xfs_dir_header
} GRUB_PACKED parent; } GRUB_PACKED parent;
} GRUB_PACKED; } GRUB_PACKED;
/* Structure for directory entry inlined in the inode */
struct grub_xfs_dir_entry struct grub_xfs_dir_entry
{ {
grub_uint8_t len; grub_uint8_t len;
grub_uint16_t offset; grub_uint16_t offset;
char name[1]; char name[1];
/* Inode number follows, 32 bits. */ /* Inode number follows, 32 / 64 bits. */
} GRUB_PACKED; } GRUB_PACKED;
/* Structure for directory entry in a block */
struct grub_xfs_dir2_entry struct grub_xfs_dir2_entry
{ {
grub_uint64_t inode; grub_uint64_t inode;
grub_uint8_t len; grub_uint8_t len;
} GRUB_PACKED; } GRUB_PACKED;
typedef grub_uint32_t grub_xfs_extent[4]; struct grub_xfs_extent
{
/* This should be a bitfield but bietfields are unportable, so just have
a raw array and functions extracting useful info from it.
*/
grub_uint32_t raw[4];
} GRUB_PACKED;
struct grub_xfs_btree_node struct grub_xfs_btree_node
{ {
@ -90,7 +151,8 @@ struct grub_xfs_btree_node
grub_uint16_t numrecs; grub_uint16_t numrecs;
grub_uint64_t left; grub_uint64_t left;
grub_uint64_t right; grub_uint64_t right;
grub_uint64_t keys[1]; /* In V5 here follow crc, uuid, etc. */
/* Then follow keys and block pointers */
} GRUB_PACKED; } GRUB_PACKED;
struct grub_xfs_btree_root struct grub_xfs_btree_root
@ -123,19 +185,11 @@ struct grub_xfs_inode
grub_uint16_t unused3; grub_uint16_t unused3;
grub_uint8_t fork_offset; grub_uint8_t fork_offset;
grub_uint8_t unused4[17]; grub_uint8_t unused4[17];
union
{
char raw[156];
struct dir
{
struct grub_xfs_dir_header dirhead;
struct grub_xfs_dir_entry direntry[1];
} dir;
grub_xfs_extent extents[XFS_INODE_EXTENTS];
struct grub_xfs_btree_root btree;
} GRUB_PACKED data;
} GRUB_PACKED; } GRUB_PACKED;
#define XFS_V2_INODE_SIZE sizeof(struct grub_xfs_inode)
#define XFS_V3_INODE_SIZE (XFS_V2_INODE_SIZE + 76)
struct grub_xfs_dirblock_tail struct grub_xfs_dirblock_tail
{ {
grub_uint32_t leaf_count; grub_uint32_t leaf_count;
@ -157,6 +211,8 @@ struct grub_xfs_data
int pos; int pos;
int bsize; int bsize;
grub_uint32_t agsize; grub_uint32_t agsize;
unsigned int hasftype:1;
unsigned int hascrc:1;
struct grub_fshelp_node diropen; struct grub_fshelp_node diropen;
}; };
@ -164,6 +220,71 @@ static grub_dl_t my_mod;
static int grub_xfs_sb_hascrc(struct grub_xfs_data *data)
{
return (data->sblock.version & grub_cpu_to_be16_compile_time(XFS_SB_VERSION_NUMBITS)) ==
grub_cpu_to_be16_compile_time(XFS_SB_VERSION_5);
}
static int grub_xfs_sb_hasftype(struct grub_xfs_data *data)
{
if ((data->sblock.version & grub_cpu_to_be16_compile_time(XFS_SB_VERSION_NUMBITS)) ==
grub_cpu_to_be16_compile_time(XFS_SB_VERSION_5) &&
data->sblock.sb_features_incompat & grub_cpu_to_be32_compile_time(XFS_SB_FEAT_INCOMPAT_FTYPE))
return 1;
if (data->sblock.version & grub_cpu_to_be16_compile_time(XFS_SB_VERSION_MOREBITSBIT) &&
data->sblock.features2 & grub_cpu_to_be32_compile_time(XFS_SB_VERSION2_FTYPE))
return 1;
return 0;
}
static int grub_xfs_sb_valid(struct grub_xfs_data *data)
{
grub_dprintf("xfs", "Validating superblock\n");
if (grub_strncmp ((char *) (data->sblock.magic), "XFSB", 4)
|| data->sblock.log2_bsize < GRUB_DISK_SECTOR_BITS
|| ((int) data->sblock.log2_bsize
+ (int) data->sblock.log2_dirblk) >= 27)
{
grub_error (GRUB_ERR_BAD_FS, "not a XFS filesystem");
return 0;
}
if ((data->sblock.version & grub_cpu_to_be16_compile_time(XFS_SB_VERSION_NUMBITS)) ==
grub_cpu_to_be16_compile_time(XFS_SB_VERSION_5))
{
grub_dprintf("xfs", "XFS v5 superblock detected\n");
if (data->sblock.sb_features_incompat &
grub_cpu_to_be32_compile_time(~XFS_SB_FEAT_INCOMPAT_SUPPORTED))
{
grub_error (GRUB_ERR_BAD_FS, "XFS filesystem has unsupported "
"incompatible features");
return 0;
}
return 1;
}
else if ((data->sblock.version & grub_cpu_to_be16_compile_time(XFS_SB_VERSION_NUMBITS)) ==
grub_cpu_to_be16_compile_time(XFS_SB_VERSION_4))
{
grub_dprintf("xfs", "XFS v4 superblock detected\n");
if (!(data->sblock.version & grub_cpu_to_be16_compile_time(XFS_SB_VERSION_DIRV2BIT)))
{
grub_error (GRUB_ERR_BAD_FS, "XFS filesystem without V2 directories "
"is unsupported");
return 0;
}
if (data->sblock.version & grub_cpu_to_be16_compile_time(~XFS_SB_VERSION_BITS_SUPPORTED) ||
(data->sblock.version & grub_cpu_to_be16_compile_time(XFS_SB_VERSION_MOREBITSBIT) &&
data->sblock.features2 & grub_cpu_to_be16_compile_time(~XFS_SB_VERSION2_BITS_SUPPORTED)))
{
grub_error (GRUB_ERR_BAD_FS, "XFS filesystem has unsupported version "
"bits");
return 0;
}
return 1;
}
return 0;
}
/* Filetype information as used in inodes. */ /* Filetype information as used in inodes. */
#define FILETYPE_INO_MASK 0170000 #define FILETYPE_INO_MASK 0170000
#define FILETYPE_INO_REG 0100000 #define FILETYPE_INO_REG 0100000
@ -180,14 +301,14 @@ static inline grub_uint64_t
GRUB_XFS_INO_INOINAG (struct grub_xfs_data *data, GRUB_XFS_INO_INOINAG (struct grub_xfs_data *data,
grub_uint64_t ino) grub_uint64_t ino)
{ {
return (grub_be_to_cpu64 (ino) & ((1LL << GRUB_XFS_INO_AGBITS (data)) - 1)); return (ino & ((1LL << GRUB_XFS_INO_AGBITS (data)) - 1));
} }
static inline grub_uint64_t static inline grub_uint64_t
GRUB_XFS_INO_AG (struct grub_xfs_data *data, GRUB_XFS_INO_AG (struct grub_xfs_data *data,
grub_uint64_t ino) grub_uint64_t ino)
{ {
return (grub_be_to_cpu64 (ino) >> GRUB_XFS_INO_AGBITS (data)); return (ino >> GRUB_XFS_INO_AGBITS (data));
} }
static inline grub_disk_addr_t static inline grub_disk_addr_t
@ -198,37 +319,25 @@ GRUB_XFS_FSB_TO_BLOCK (struct grub_xfs_data *data, grub_disk_addr_t fsb)
} }
static inline grub_uint64_t static inline grub_uint64_t
GRUB_XFS_EXTENT_OFFSET (grub_xfs_extent *exts, int ex) GRUB_XFS_EXTENT_OFFSET (struct grub_xfs_extent *exts, int ex)
{ {
return ((grub_be_to_cpu32 (exts[ex][0]) & ~(1 << 31)) << 23 return ((grub_be_to_cpu32 (exts[ex].raw[0]) & ~(1 << 31)) << 23
| grub_be_to_cpu32 (exts[ex][1]) >> 9); | grub_be_to_cpu32 (exts[ex].raw[1]) >> 9);
} }
static inline grub_uint64_t static inline grub_uint64_t
GRUB_XFS_EXTENT_BLOCK (grub_xfs_extent *exts, int ex) GRUB_XFS_EXTENT_BLOCK (struct grub_xfs_extent *exts, int ex)
{ {
return ((grub_uint64_t) (grub_be_to_cpu32 (exts[ex][1]) return ((grub_uint64_t) (grub_be_to_cpu32 (exts[ex].raw[1])
& (0x1ff)) << 43 & (0x1ff)) << 43
| (grub_uint64_t) grub_be_to_cpu32 (exts[ex][2]) << 11 | (grub_uint64_t) grub_be_to_cpu32 (exts[ex].raw[2]) << 11
| grub_be_to_cpu32 (exts[ex][3]) >> 21); | grub_be_to_cpu32 (exts[ex].raw[3]) >> 21);
} }
static inline grub_uint64_t static inline grub_uint64_t
GRUB_XFS_EXTENT_SIZE (grub_xfs_extent *exts, int ex) GRUB_XFS_EXTENT_SIZE (struct grub_xfs_extent *exts, int ex)
{ {
return (grub_be_to_cpu32 (exts[ex][3]) & ((1 << 21) - 1)); return (grub_be_to_cpu32 (exts[ex].raw[3]) & ((1 << 21) - 1));
}
static inline int
GRUB_XFS_ROUND_TO_DIRENT (int pos)
{
return ((((pos) + 8 - 1) / 8) * 8);
}
static inline int
GRUB_XFS_NEXT_DIRENT (int pos, int len)
{
return (pos) + GRUB_XFS_ROUND_TO_DIRENT (8 + 1 + len + 2);
} }
@ -255,6 +364,109 @@ grub_xfs_inode_offset (struct grub_xfs_data *data,
data->sblock.log2_inode); data->sblock.log2_inode);
} }
static inline grub_size_t
grub_xfs_inode_size(struct grub_xfs_data *data)
{
return (grub_size_t)1 << data->sblock.log2_inode;
}
/*
* Returns size occupied by XFS inode stored in memory - we store struct
* grub_fshelp_node there but on disk inode size may be actually larger than
* struct grub_xfs_inode so we need to account for that so that we can read
* from disk directly into in-memory structure.
*/
static inline grub_size_t
grub_xfs_fshelp_size(struct grub_xfs_data *data)
{
return sizeof (struct grub_fshelp_node) - sizeof (struct grub_xfs_inode)
+ grub_xfs_inode_size(data);
}
/* This should return void * but XFS code is error-prone with alignment, so
return char to retain cast-align.
*/
static char *
grub_xfs_inode_data(struct grub_xfs_inode *inode)
{
if (inode->version <= 2)
return ((char *)inode) + XFS_V2_INODE_SIZE;
return ((char *)inode) + XFS_V3_INODE_SIZE;
}
static struct grub_xfs_dir_entry *
grub_xfs_inline_de(struct grub_xfs_dir_header *head)
{
/*
With small inode numbers the header is 4 bytes smaller because of
smaller parent pointer
*/
return (struct grub_xfs_dir_entry *)
(((char *) head) + sizeof(struct grub_xfs_dir_header) -
(head->largeino ? 0 : sizeof(grub_uint32_t)));
}
static grub_uint8_t *
grub_xfs_inline_de_inopos(struct grub_xfs_data *data,
struct grub_xfs_dir_entry *de)
{
return ((grub_uint8_t *)(de + 1)) + de->len - 1 + (data->hasftype ? 1 : 0);
}
static struct grub_xfs_dir_entry *
grub_xfs_inline_next_de(struct grub_xfs_data *data,
struct grub_xfs_dir_header *head,
struct grub_xfs_dir_entry *de)
{
char *p = (char *)de + sizeof(struct grub_xfs_dir_entry) - 1 + de->len;
p += head->largeino ? sizeof(grub_uint64_t) : sizeof(grub_uint32_t);
if (data->hasftype)
p++;
return (struct grub_xfs_dir_entry *)p;
}
static struct grub_xfs_dirblock_tail *
grub_xfs_dir_tail(struct grub_xfs_data *data, void *dirblock)
{
int dirblksize = 1 << (data->sblock.log2_bsize + data->sblock.log2_dirblk);
return (struct grub_xfs_dirblock_tail *)
((char *)dirblock + dirblksize - sizeof (struct grub_xfs_dirblock_tail));
}
static struct grub_xfs_dir2_entry *
grub_xfs_first_de(struct grub_xfs_data *data, void *dirblock)
{
if (data->hascrc)
return (struct grub_xfs_dir2_entry *)((char *)dirblock + 64);
return (struct grub_xfs_dir2_entry *)((char *)dirblock + 16);
}
static struct grub_xfs_dir2_entry *
grub_xfs_next_de(struct grub_xfs_data *data, struct grub_xfs_dir2_entry *de)
{
int size = sizeof (struct grub_xfs_dir2_entry) + de->len + 2 /* Tag */;
if (data->hasftype)
size++; /* File type */
return (struct grub_xfs_dir2_entry *)(((char *)de) + ALIGN_UP(size, 8));
}
/* This should return void * but XFS code is error-prone with alignment, so
return char to retain cast-align.
*/
static char *
grub_xfs_btree_keys(struct grub_xfs_data *data,
struct grub_xfs_btree_node *leaf)
{
char *keys = (char *)(leaf + 1);
if (data->hascrc)
keys += 48; /* skip crc, uuid, ... */
return keys;
}
static grub_err_t static grub_err_t
grub_xfs_read_inode (struct grub_xfs_data *data, grub_uint64_t ino, grub_xfs_read_inode (struct grub_xfs_data *data, grub_uint64_t ino,
@ -263,9 +475,11 @@ grub_xfs_read_inode (struct grub_xfs_data *data, grub_uint64_t ino,
grub_uint64_t block = grub_xfs_inode_block (data, ino); grub_uint64_t block = grub_xfs_inode_block (data, ino);
int offset = grub_xfs_inode_offset (data, ino); int offset = grub_xfs_inode_offset (data, ino);
grub_dprintf("xfs", "Reading inode (%"PRIuGRUB_UINT64_T") - %"PRIuGRUB_UINT64_T", %d\n",
ino, block, offset);
/* Read the inode. */ /* Read the inode. */
if (grub_disk_read (data->disk, block, offset, if (grub_disk_read (data->disk, block, offset, grub_xfs_inode_size(data),
1 << data->sblock.log2_inode, inode)) inode))
return grub_errno; return grub_errno;
if (grub_strncmp ((char *) inode->magic, "IN", 2)) if (grub_strncmp ((char *) inode->magic, "IN", 2))
@ -274,32 +488,39 @@ grub_xfs_read_inode (struct grub_xfs_data *data, grub_uint64_t ino,
return 0; return 0;
} }
static grub_uint64_t
get_fsb (const void *keys, int idx)
{
const char *p = (const char *) keys + sizeof(grub_uint64_t) * idx;
return grub_be_to_cpu64 (grub_get_unaligned64 (p));
}
static grub_disk_addr_t static grub_disk_addr_t
grub_xfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) grub_xfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
{ {
struct grub_xfs_btree_node *leaf = 0; struct grub_xfs_btree_node *leaf = 0;
int ex, nrec; int ex, nrec;
grub_xfs_extent *exts; struct grub_xfs_extent *exts;
grub_uint64_t ret = 0; grub_uint64_t ret = 0;
if (node->inode.format == XFS_INODE_FORMAT_BTREE) if (node->inode.format == XFS_INODE_FORMAT_BTREE)
{ {
const grub_uint64_t *keys; struct grub_xfs_btree_root *root;
const char *keys;
int recoffset; int recoffset;
leaf = grub_malloc (node->data->bsize); leaf = grub_malloc (node->data->bsize);
if (leaf == 0) if (leaf == 0)
return 0; return 0;
nrec = grub_be_to_cpu16 (node->inode.data.btree.numrecs); root = (struct grub_xfs_btree_root *) grub_xfs_inode_data(&node->inode);
keys = &node->inode.data.btree.keys[0]; nrec = grub_be_to_cpu16 (root->numrecs);
keys = (char *) &root->keys[0];
if (node->inode.fork_offset) if (node->inode.fork_offset)
recoffset = (node->inode.fork_offset - 1) / 2; recoffset = (node->inode.fork_offset - 1) / 2;
else else
recoffset = ((1 << node->data->sblock.log2_inode) recoffset = (grub_xfs_inode_size(node->data)
- ((char *) &node->inode.data.btree.keys - ((char *) keys - (char *) &node->inode))
- (char *) &node->inode))
/ (2 * sizeof (grub_uint64_t)); / (2 * sizeof (grub_uint64_t));
do do
{ {
@ -307,7 +528,7 @@ grub_xfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
for (i = 0; i < nrec; i++) for (i = 0; i < nrec; i++)
{ {
if (fileblock < grub_be_to_cpu64 (keys[i])) if (fileblock < get_fsb(keys, i))
break; break;
} }
@ -317,12 +538,16 @@ grub_xfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
grub_free (leaf); grub_free (leaf);
return 0; return 0;
} }
if (grub_disk_read (node->data->disk, if (grub_disk_read (node->data->disk,
GRUB_XFS_FSB_TO_BLOCK (node->data, grub_be_to_cpu64 (keys[i - 1 + recoffset])) << (node->data->sblock.log2_bsize - GRUB_DISK_SECTOR_BITS), GRUB_XFS_FSB_TO_BLOCK (node->data, get_fsb (keys, i - 1 + recoffset)) << (node->data->sblock.log2_bsize - GRUB_DISK_SECTOR_BITS),
0, node->data->bsize, leaf)) 0, node->data->bsize, leaf))
return 0; return 0;
if (grub_strncmp ((char *) leaf->magic, "BMAP", 4)) if ((!node->data->hascrc &&
grub_strncmp ((char *) leaf->magic, "BMAP", 4)) ||
(node->data->hascrc &&
grub_strncmp ((char *) leaf->magic, "BMA3", 4)))
{ {
grub_free (leaf); grub_free (leaf);
grub_error (GRUB_ERR_BAD_FS, "not a correct XFS BMAP node"); grub_error (GRUB_ERR_BAD_FS, "not a correct XFS BMAP node");
@ -330,18 +555,18 @@ grub_xfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
} }
nrec = grub_be_to_cpu16 (leaf->numrecs); nrec = grub_be_to_cpu16 (leaf->numrecs);
keys = &leaf->keys[0]; keys = grub_xfs_btree_keys(node->data, leaf);
recoffset = ((node->data->bsize - ((char *) &leaf->keys recoffset = ((node->data->bsize - ((char *) keys
- (char *) leaf)) - (char *) leaf))
/ (2 * sizeof (grub_uint64_t))); / (2 * sizeof (grub_uint64_t)));
} }
while (leaf->level); while (leaf->level);
exts = (grub_xfs_extent *) keys; exts = (struct grub_xfs_extent *) keys;
} }
else if (node->inode.format == XFS_INODE_FORMAT_EXT) else if (node->inode.format == XFS_INODE_FORMAT_EXT)
{ {
nrec = grub_be_to_cpu32 (node->inode.nextents); nrec = grub_be_to_cpu32 (node->inode.nextents);
exts = &node->inode.data.extents[0]; exts = (struct grub_xfs_extent *) grub_xfs_inode_data(&node->inode);
} }
else else
{ {
@ -380,12 +605,12 @@ grub_xfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
static grub_ssize_t static grub_ssize_t
grub_xfs_read_file (grub_fshelp_node_t node, grub_xfs_read_file (grub_fshelp_node_t node,
grub_disk_read_hook_t read_hook, void *read_hook_data, grub_disk_read_hook_t read_hook, void *read_hook_data,
grub_off_t pos, grub_size_t len, char *buf) grub_off_t pos, grub_size_t len, char *buf, grub_uint32_t header_size)
{ {
return grub_fshelp_read_file (node->data->disk, node, return grub_fshelp_read_file (node->data->disk, node,
read_hook, read_hook_data, read_hook, read_hook_data,
pos, len, buf, grub_xfs_read_block, pos, len, buf, grub_xfs_read_block,
grub_be_to_cpu64 (node->inode.size), grub_be_to_cpu64 (node->inode.size) + header_size,
node->data->sblock.log2_bsize node->data->sblock.log2_bsize
- GRUB_DISK_SECTOR_BITS, 0); - GRUB_DISK_SECTOR_BITS, 0);
} }
@ -394,23 +619,34 @@ grub_xfs_read_file (grub_fshelp_node_t node,
static char * static char *
grub_xfs_read_symlink (grub_fshelp_node_t node) grub_xfs_read_symlink (grub_fshelp_node_t node)
{ {
int size = grub_be_to_cpu64 (node->inode.size); grub_ssize_t size = grub_be_to_cpu64 (node->inode.size);
if (size < 0)
{
grub_error (GRUB_ERR_BAD_FS, "invalid symlink");
return 0;
}
switch (node->inode.format) switch (node->inode.format)
{ {
case XFS_INODE_FORMAT_INO: case XFS_INODE_FORMAT_INO:
return grub_strndup (node->inode.data.raw, size); return grub_strndup (grub_xfs_inode_data(&node->inode), size);
case XFS_INODE_FORMAT_EXT: case XFS_INODE_FORMAT_EXT:
{ {
char *symlink; char *symlink;
grub_ssize_t numread; grub_ssize_t numread;
int off = 0;
if (node->data->hascrc)
off = 56;
symlink = grub_malloc (size + 1); symlink = grub_malloc (size + 1);
if (!symlink) if (!symlink)
return 0; return 0;
numread = grub_xfs_read_file (node, 0, 0, 0, size, symlink); node->inode.size = grub_be_to_cpu64 (size + off);
numread = grub_xfs_read_file (node, 0, 0, off, size, symlink, off);
if (numread != size) if (numread != size)
{ {
grub_free (symlink); grub_free (symlink);
@ -456,9 +692,7 @@ static int iterate_dir_call_hook (grub_uint64_t ino, const char *filename,
struct grub_fshelp_node *fdiro; struct grub_fshelp_node *fdiro;
grub_err_t err; grub_err_t err;
fdiro = grub_malloc (sizeof (struct grub_fshelp_node) fdiro = grub_malloc (grub_xfs_fshelp_size(ctx->diro->data) + 1);
- sizeof (struct grub_xfs_inode)
+ (1 << ctx->diro->data->sblock.log2_inode) + 1);
if (!fdiro) if (!fdiro)
{ {
grub_print_error (); grub_print_error ();
@ -496,24 +730,18 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir,
{ {
case XFS_INODE_FORMAT_INO: case XFS_INODE_FORMAT_INO:
{ {
struct grub_xfs_dir_entry *de = &diro->inode.data.dir.direntry[0]; struct grub_xfs_dir_header *head = (struct grub_xfs_dir_header *) grub_xfs_inode_data(&diro->inode);
int smallino = !diro->inode.data.dir.dirhead.smallino; struct grub_xfs_dir_entry *de = grub_xfs_inline_de(head);
int smallino = !head->largeino;
int i; int i;
grub_uint64_t parent; grub_uint64_t parent;
/* If small inode numbers are used to pack the direntry, the /* If small inode numbers are used to pack the direntry, the
parent inode number is small too. */ parent inode number is small too. */
if (smallino) if (smallino)
{ parent = grub_be_to_cpu32 (head->parent.i4);
parent = grub_be_to_cpu32 (diro->inode.data.dir.dirhead.parent.i4);
parent = grub_cpu_to_be64 (parent);
/* The header is a bit smaller than usual. */
de = (struct grub_xfs_dir_entry *) ((char *) de - 4);
}
else else
{ parent = grub_be_to_cpu64 (head->parent.i8);
parent = diro->inode.data.dir.dirhead.parent.i8;
}
/* Synthesize the direntries for `.' and `..'. */ /* Synthesize the direntries for `.' and `..'. */
if (iterate_dir_call_hook (diro->ino, ".", &ctx)) if (iterate_dir_call_hook (diro->ino, ".", &ctx))
@ -522,12 +750,10 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir,
if (iterate_dir_call_hook (parent, "..", &ctx)) if (iterate_dir_call_hook (parent, "..", &ctx))
return 1; return 1;
for (i = 0; i < diro->inode.data.dir.dirhead.count; i++) for (i = 0; i < head->count; i++)
{ {
grub_uint64_t ino; grub_uint64_t ino;
grub_uint8_t *inopos = (((grub_uint8_t *) de) grub_uint8_t *inopos = grub_xfs_inline_de_inopos(dir->data, de);
+ sizeof (struct grub_xfs_dir_entry)
+ de->len - 1);
grub_uint8_t c; grub_uint8_t c;
/* inopos might be unaligned. */ /* inopos might be unaligned. */
@ -545,7 +771,6 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir,
| (((grub_uint64_t) inopos[5]) << 16) | (((grub_uint64_t) inopos[5]) << 16)
| (((grub_uint64_t) inopos[6]) << 8) | (((grub_uint64_t) inopos[6]) << 8)
| (((grub_uint64_t) inopos[7]) << 0); | (((grub_uint64_t) inopos[7]) << 0);
ino = grub_cpu_to_be64 (ino);
c = de->name[de->len]; c = de->name[de->len];
de->name[de->len] = '\0'; de->name[de->len] = '\0';
@ -553,10 +778,7 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir,
return 1; return 1;
de->name[de->len] = c; de->name[de->len] = c;
de = ((struct grub_xfs_dir_entry *) de = grub_xfs_inline_next_de(dir->data, head, de);
(((char *) de)+ sizeof (struct grub_xfs_dir_entry) + de->len
+ ((smallino ? sizeof (grub_uint32_t)
: sizeof (grub_uint64_t))) - 1));
} }
break; break;
} }
@ -583,19 +805,15 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir,
>> dirblk_log2); >> dirblk_log2);
blk++) blk++)
{ {
/* The header is skipped, the first direntry is stored struct grub_xfs_dir2_entry *direntry =
from byte 16. */ grub_xfs_first_de(dir->data, dirblock);
int pos = 16;
int entries; int entries;
int tail_start = (dirblk_size struct grub_xfs_dirblock_tail *tail =
- sizeof (struct grub_xfs_dirblock_tail)); grub_xfs_dir_tail(dir->data, dirblock);
struct grub_xfs_dirblock_tail *tail;
tail = (struct grub_xfs_dirblock_tail *) &dirblock[tail_start];
numread = grub_xfs_read_file (dir, 0, 0, numread = grub_xfs_read_file (dir, 0, 0,
blk << dirblk_log2, blk << dirblk_log2,
dirblk_size, dirblock); dirblk_size, dirblock, 0);
if (numread != dirblk_size) if (numread != dirblk_size)
return 0; return 0;
@ -603,14 +821,11 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir,
- grub_be_to_cpu32 (tail->leaf_stale)); - grub_be_to_cpu32 (tail->leaf_stale));
/* Iterate over all entries within this block. */ /* Iterate over all entries within this block. */
while (pos < (dirblk_size while ((char *)direntry < (char *)tail)
- (int) sizeof (struct grub_xfs_dir2_entry)))
{ {
struct grub_xfs_dir2_entry *direntry;
grub_uint8_t *freetag; grub_uint8_t *freetag;
char *filename; char *filename;
direntry = (struct grub_xfs_dir2_entry *) &dirblock[pos];
freetag = (grub_uint8_t *) direntry; freetag = (grub_uint8_t *) direntry;
if (grub_get_unaligned16 (freetag) == 0XFFFF) if (grub_get_unaligned16 (freetag) == 0XFFFF)
@ -618,17 +833,20 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir,
grub_uint8_t *skip = (freetag + sizeof (grub_uint16_t)); grub_uint8_t *skip = (freetag + sizeof (grub_uint16_t));
/* This entry is not used, go to the next one. */ /* This entry is not used, go to the next one. */
pos += grub_be_to_cpu16 (grub_get_unaligned16 (skip)); direntry = (struct grub_xfs_dir2_entry *)
(((char *)direntry) +
grub_be_to_cpu16 (grub_get_unaligned16 (skip)));
continue; continue;
} }
filename = &dirblock[pos + sizeof (*direntry)]; filename = (char *)(direntry + 1);
/* The byte after the filename is for the tag, which /* The byte after the filename is for the filetype, padding, or
is not used by GRUB. So it can be overwritten. */ tag, which is not used by GRUB. So it can be overwritten. */
filename[direntry->len] = '\0'; filename[direntry->len] = '\0';
if (iterate_dir_call_hook (direntry->inode, filename, &ctx)) if (iterate_dir_call_hook (grub_be_to_cpu64(direntry->inode),
filename, &ctx))
{ {
grub_free (dirblock); grub_free (dirblock);
return 1; return 1;
@ -641,8 +859,7 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir,
break; break;
/* Select the next directory entry. */ /* Select the next directory entry. */
pos = GRUB_XFS_NEXT_DIRENT (pos, direntry->len); direntry = grub_xfs_next_de(dir->data, direntry);
pos = GRUB_XFS_ROUND_TO_DIRENT (pos);
} }
} }
grub_free (dirblock); grub_free (dirblock);
@ -667,36 +884,35 @@ grub_xfs_mount (grub_disk_t disk)
if (!data) if (!data)
return 0; return 0;
grub_dprintf("xfs", "Reading sb\n");
/* Read the superblock. */ /* Read the superblock. */
if (grub_disk_read (disk, 0, 0, if (grub_disk_read (disk, 0, 0,
sizeof (struct grub_xfs_sblock), &data->sblock)) sizeof (struct grub_xfs_sblock), &data->sblock))
goto fail; goto fail;
if (grub_strncmp ((char *) (data->sblock.magic), "XFSB", 4) if (!grub_xfs_sb_valid(data))
|| data->sblock.log2_bsize < GRUB_DISK_SECTOR_BITS
|| ((int) data->sblock.log2_bsize
+ (int) data->sblock.log2_dirblk) >= 27)
{
grub_error (GRUB_ERR_BAD_FS, "not a XFS filesystem");
goto fail; goto fail;
}
data = grub_realloc (data, data = grub_realloc (data,
sizeof (struct grub_xfs_data) sizeof (struct grub_xfs_data)
- sizeof (struct grub_xfs_inode) - sizeof (struct grub_xfs_inode)
+ (1 << data->sblock.log2_inode) + 1); + grub_xfs_inode_size(data) + 1);
if (! data) if (! data)
goto fail; goto fail;
data->diropen.data = data; data->diropen.data = data;
data->diropen.ino = data->sblock.rootino; data->diropen.ino = grub_be_to_cpu64(data->sblock.rootino);
data->diropen.inode_read = 1; data->diropen.inode_read = 1;
data->bsize = grub_be_to_cpu32 (data->sblock.bsize); data->bsize = grub_be_to_cpu32 (data->sblock.bsize);
data->agsize = grub_be_to_cpu32 (data->sblock.agsize); data->agsize = grub_be_to_cpu32 (data->sblock.agsize);
data->hasftype = grub_xfs_sb_hasftype(data);
data->hascrc = grub_xfs_sb_hascrc(data);
data->disk = disk; data->disk = disk;
data->pos = 0; data->pos = 0;
grub_dprintf("xfs", "Reading root ino %"PRIuGRUB_UINT64_T"\n",
grub_cpu_to_be64(data->sblock.rootino));
grub_xfs_read_inode (data, data->diropen.ino, &data->diropen.inode); grub_xfs_read_inode (data, data->diropen.ino, &data->diropen.inode);
@ -799,10 +1015,7 @@ grub_xfs_open (struct grub_file *file, const char *name)
if (fdiro != &data->diropen) if (fdiro != &data->diropen)
{ {
grub_memcpy (&data->diropen, fdiro, grub_memcpy (&data->diropen, fdiro, grub_xfs_fshelp_size(data));
sizeof (struct grub_fshelp_node)
- sizeof (struct grub_xfs_inode)
+ (1 << data->sblock.log2_inode));
grub_free (fdiro); grub_free (fdiro);
} }
@ -832,7 +1045,7 @@ grub_xfs_read (grub_file_t file, char *buf, grub_size_t len)
return grub_xfs_read_file (&data->diropen, return grub_xfs_read_file (&data->diropen,
file->read_hook, file->read_hook_data, file->read_hook, file->read_hook_data,
file->offset, len, buf); file->offset, len, buf, 0);
} }

View file

@ -280,7 +280,12 @@ grub_crypto_cipher_handle_t (*grub_zfs_load_key) (const struct grub_zfs_key *key
*/ */
#define MAX_SUPPORTED_FEATURE_STRLEN 50 #define MAX_SUPPORTED_FEATURE_STRLEN 50
static const char *spa_feature_names[] = { static const char *spa_feature_names[] = {
"org.illumos:lz4_compress",NULL "org.illumos:lz4_compress",
"com.delphix:hole_birth",
"com.delphix:embedded_data",
"com.delphix:extensible_dataset",
"org.open-zfs:large_blocks",
NULL
}; };
static int static int
@ -1751,7 +1756,7 @@ zio_read_gang (blkptr_t * bp, grub_zfs_endian_t endian, dva_t * dva, void *buf,
for (i = 0; i < SPA_GBH_NBLKPTRS; i++) for (i = 0; i < SPA_GBH_NBLKPTRS; i++)
{ {
if (zio_gb->zg_blkptr[i].blk_birth == 0) if (BP_IS_HOLE(&zio_gb->zg_blkptr[i]))
continue; continue;
err = zio_read_data (&zio_gb->zg_blkptr[i], endian, buf, data); err = zio_read_data (&zio_gb->zg_blkptr[i], endian, buf, data);
@ -1800,6 +1805,39 @@ zio_read_data (blkptr_t * bp, grub_zfs_endian_t endian, void *buf,
return err; return err;
} }
/*
* buf must be at least BPE_GET_PSIZE(bp) bytes long (which will never be
* more than BPE_PAYLOAD_SIZE bytes).
*/
static grub_err_t
decode_embedded_bp_compressed(const blkptr_t *bp, void *buf)
{
grub_size_t psize, i;
grub_uint8_t *buf8 = buf;
grub_uint64_t w = 0;
const grub_uint64_t *bp64 = (const grub_uint64_t *)bp;
psize = BPE_GET_PSIZE(bp);
/*
* Decode the words of the block pointer into the byte array.
* Low bits of first word are the first byte (little endian).
*/
for (i = 0; i < psize; i++)
{
if (i % sizeof (w) == 0)
{
/* beginning of a word */
w = *bp64;
bp64++;
if (!BPE_IS_PAYLOADWORD(bp, bp64))
bp64++;
}
buf8[i] = BF64_GET(w, (i % sizeof (w)) * 8, 8);
}
return GRUB_ERR_NONE;
}
/* /*
* Read in a block of data, verify its checksum, decompress if needed, * Read in a block of data, verify its checksum, decompress if needed,
* and put the uncompressed data in buf. * and put the uncompressed data in buf.
@ -1818,12 +1856,26 @@ zio_read (blkptr_t *bp, grub_zfs_endian_t endian, void **buf,
*buf = NULL; *buf = NULL;
checksum = (grub_zfs_to_cpu64((bp)->blk_prop, endian) >> 40) & 0xff; checksum = (grub_zfs_to_cpu64((bp)->blk_prop, endian) >> 40) & 0xff;
comp = (grub_zfs_to_cpu64((bp)->blk_prop, endian)>>32) & 0xff; comp = (grub_zfs_to_cpu64((bp)->blk_prop, endian)>>32) & 0x7f;
encrypted = ((grub_zfs_to_cpu64((bp)->blk_prop, endian) >> 60) & 3); encrypted = ((grub_zfs_to_cpu64((bp)->blk_prop, endian) >> 60) & 3);
if (BP_IS_EMBEDDED(bp))
{
if (BPE_GET_ETYPE(bp) != BP_EMBEDDED_TYPE_DATA)
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
"unsupported embedded BP (type=%u)\n",
BPE_GET_ETYPE(bp));
lsize = BPE_GET_LSIZE(bp);
psize = BF64_GET_SB(grub_zfs_to_cpu64 ((bp)->blk_prop, endian), 25, 7, 0, 1);
}
else
{
lsize = (BP_IS_HOLE(bp) ? 0 : lsize = (BP_IS_HOLE(bp) ? 0 :
(((grub_zfs_to_cpu64 ((bp)->blk_prop, endian) & 0xffff) + 1) (((grub_zfs_to_cpu64 ((bp)->blk_prop, endian) & 0xffff) + 1)
<< SPA_MINBLOCKSHIFT)); << SPA_MINBLOCKSHIFT));
psize = get_psize (bp, endian); psize = get_psize (bp, endian);
}
grub_dprintf("zfs", "zio_read: E %d: size %" PRIdGRUB_SSIZE "/%"
PRIdGRUB_SSIZE "\n", (int)BP_IS_EMBEDDED(bp), lsize, psize);
if (size) if (size)
*size = lsize; *size = lsize;
@ -1837,25 +1889,32 @@ zio_read (blkptr_t *bp, grub_zfs_endian_t endian, void **buf,
"compression algorithm %s not supported\n", decomp_table[comp].name); "compression algorithm %s not supported\n", decomp_table[comp].name);
if (comp != ZIO_COMPRESS_OFF) if (comp != ZIO_COMPRESS_OFF)
{
/* It's not really necessary to align to 16, just for safety. */ /* It's not really necessary to align to 16, just for safety. */
compbuf = grub_malloc (ALIGN_UP (psize, 16)); compbuf = grub_malloc (ALIGN_UP (psize, 16));
if (! compbuf)
return grub_errno;
}
else else
compbuf = *buf = grub_malloc (lsize); compbuf = *buf = grub_malloc (lsize);
if (! compbuf)
return grub_errno;
grub_dprintf ("zfs", "endian = %d\n", endian); grub_dprintf ("zfs", "endian = %d\n", endian);
if (BP_IS_EMBEDDED(bp))
err = decode_embedded_bp_compressed(bp, compbuf);
else
{
err = zio_read_data (bp, endian, compbuf, data); err = zio_read_data (bp, endian, compbuf, data);
/* FIXME is it really necessary? */
if (comp != ZIO_COMPRESS_OFF)
grub_memset (compbuf + psize, 0, ALIGN_UP (psize, 16) - psize);
}
if (err) if (err)
{ {
grub_free (compbuf); grub_free (compbuf);
*buf = NULL; *buf = NULL;
return err; return err;
} }
grub_memset (compbuf, 0, ALIGN_UP (psize, 16) - psize);
if (!BP_IS_EMBEDDED(bp))
{
err = zio_checksum_verify (zc, checksum, endian, err = zio_checksum_verify (zc, checksum, endian,
compbuf, psize); compbuf, psize);
if (err) if (err)
@ -1865,6 +1924,7 @@ zio_read (blkptr_t *bp, grub_zfs_endian_t endian, void **buf,
*buf = NULL; *buf = NULL;
return err; return err;
} }
}
if (encrypted) if (encrypted)
{ {
@ -2013,10 +2073,10 @@ dmu_read (dnode_end_t * dn, grub_uint64_t blkid, void **buf,
*/ */
static grub_err_t static grub_err_t
mzap_lookup (mzap_phys_t * zapobj, grub_zfs_endian_t endian, mzap_lookup (mzap_phys_t * zapobj, grub_zfs_endian_t endian,
grub_uint16_t objsize, const char *name, grub_uint64_t * value, grub_uint32_t objsize, const char *name, grub_uint64_t * value,
int case_insensitive) int case_insensitive)
{ {
grub_uint16_t i, chunks; grub_uint32_t i, chunks;
mzap_ent_phys_t *mzap_ent = zapobj->mz_chunk; mzap_ent_phys_t *mzap_ent = zapobj->mz_chunk;
if (objsize < MZAP_ENT_LEN) if (objsize < MZAP_ENT_LEN)
@ -2428,7 +2488,7 @@ zap_lookup (dnode_end_t * zap_dnode, const char *name, grub_uint64_t *val,
struct grub_zfs_data *data, int case_insensitive) struct grub_zfs_data *data, int case_insensitive)
{ {
grub_uint64_t block_type; grub_uint64_t block_type;
grub_uint16_t size; grub_uint32_t size;
void *zapbuf; void *zapbuf;
grub_err_t err; grub_err_t err;
grub_zfs_endian_t endian; grub_zfs_endian_t endian;
@ -2436,7 +2496,7 @@ zap_lookup (dnode_end_t * zap_dnode, const char *name, grub_uint64_t *val,
grub_dprintf ("zfs", "looking for '%s'\n", name); grub_dprintf ("zfs", "looking for '%s'\n", name);
/* Read in the first block of the zap object data. */ /* Read in the first block of the zap object data. */
size = grub_zfs_to_cpu16 (zap_dnode->dn.dn_datablkszsec, size = (grub_uint32_t) grub_zfs_to_cpu16 (zap_dnode->dn.dn_datablkszsec,
zap_dnode->endian) << SPA_MINBLOCKSHIFT; zap_dnode->endian) << SPA_MINBLOCKSHIFT;
err = dmu_read (zap_dnode, 0, &zapbuf, &endian, data); err = dmu_read (zap_dnode, 0, &zapbuf, &endian, data);
if (err) if (err)
@ -2822,7 +2882,10 @@ dnode_get_path (struct subvolume *subvol, const char *path_in, dnode_end_t *dn,
err = dmu_read (&(dnode_path->dn), block, &t, 0, data); err = dmu_read (&(dnode_path->dn), block, &t, 0, data);
if (err) if (err)
{
grub_free (sym_value);
return err; return err;
}
movesize = sym_sz - block * blksz; movesize = sym_sz - block * blksz;
if (movesize > blksz) if (movesize > blksz)
@ -3022,7 +3085,7 @@ get_filesystem_dnode (dnode_end_t * mosmdn, char *fsname,
grub_dprintf ("zfs", "alive\n"); grub_dprintf ("zfs", "alive\n");
err = dnode_get (mosmdn, objnum, DMU_OT_DSL_DIR, mdn, data); err = dnode_get (mosmdn, objnum, 0, mdn, data);
if (err) if (err)
return err; return err;
@ -3055,7 +3118,7 @@ get_filesystem_dnode (dnode_end_t * mosmdn, char *fsname,
if (err) if (err)
return err; return err;
err = dnode_get (mosmdn, objnum, DMU_OT_DSL_DIR, mdn, data); err = dnode_get (mosmdn, objnum, 0, mdn, data);
if (err) if (err)
return err; return err;
@ -3210,8 +3273,7 @@ dnode_get_fullpath (const char *fullpath, struct subvolume *subvol,
grub_dprintf ("zfs", "endian = %d\n", subvol->mdn.endian); grub_dprintf ("zfs", "endian = %d\n", subvol->mdn.endian);
err = dnode_get (&(data->mos), headobj, DMU_OT_DSL_DATASET, &subvol->mdn, err = dnode_get (&(data->mos), headobj, 0, &subvol->mdn, data);
data);
if (err) if (err)
{ {
grub_free (fsname); grub_free (fsname);
@ -3607,7 +3669,12 @@ zfs_mount (grub_device_t dev)
if (ub->ub_version >= SPA_VERSION_FEATURES && if (ub->ub_version >= SPA_VERSION_FEATURES &&
check_mos_features(&((objset_phys_t *) osp)->os_meta_dnode,ub_endian, check_mos_features(&((objset_phys_t *) osp)->os_meta_dnode,ub_endian,
data) != 0) data) != 0)
{
grub_error (GRUB_ERR_BAD_FS, "Unsupported features in pool");
grub_free (osp);
zfs_unmount (data);
return NULL; return NULL;
}
/* Got the MOS. Save it at the memory addr MOS. */ /* Got the MOS. Save it at the memory addr MOS. */
grub_memmove (&(data->mos.dn), &((objset_phys_t *) osp)->os_meta_dnode, grub_memmove (&(data->mos.dn), &((objset_phys_t *) osp)->os_meta_dnode,
@ -3905,7 +3972,7 @@ fill_fs_info (struct grub_dirhook_info *info,
{ {
headobj = grub_zfs_to_cpu64 (((dsl_dir_phys_t *) DN_BONUS (&mdn.dn))->dd_head_dataset_obj, mdn.endian); headobj = grub_zfs_to_cpu64 (((dsl_dir_phys_t *) DN_BONUS (&mdn.dn))->dd_head_dataset_obj, mdn.endian);
err = dnode_get (&(data->mos), headobj, DMU_OT_DSL_DATASET, &mdn, data); err = dnode_get (&(data->mos), headobj, 0, &mdn, data);
if (err) if (err)
{ {
grub_dprintf ("zfs", "failed here\n"); grub_dprintf ("zfs", "failed here\n");

View file

@ -67,7 +67,7 @@ grub_machine_fini (int flags)
b = grub_efi_system_table->boot_services; b = grub_efi_system_table->boot_services;
efi_call_3 (b->set_timer, tmr_evt, GRUB_EFI_TIMER_PERIODIC, 0); efi_call_3 (b->set_timer, tmr_evt, GRUB_EFI_TIMER_CANCEL, 0);
efi_call_1 (b->close_event, tmr_evt); efi_call_1 (b->close_event, tmr_evt);
grub_efi_fini (); grub_efi_fini ();

View file

@ -381,9 +381,24 @@ __aeabi_idiv (grub_int32_t a, grub_int32_t b)
__attribute__ ((alias ("__divsi3"))); __attribute__ ((alias ("__divsi3")));
void *__aeabi_memcpy (void *dest, const void *src, grub_size_t n) void *__aeabi_memcpy (void *dest, const void *src, grub_size_t n)
__attribute__ ((alias ("grub_memcpy"))); __attribute__ ((alias ("grub_memcpy")));
void *__aeabi_memcpy4 (void *dest, const void *src, grub_size_t n)
__attribute__ ((alias ("grub_memcpy")));
void *__aeabi_memcpy8 (void *dest, const void *src, grub_size_t n)
__attribute__ ((alias ("grub_memcpy")));
void *__aeabi_memset (void *s, int c, grub_size_t n) void *__aeabi_memset (void *s, int c, grub_size_t n)
__attribute__ ((alias ("memset"))); __attribute__ ((alias ("memset")));
void
__aeabi_memclr (void *s, grub_size_t n)
{
grub_memset (s, 0, n);
}
void __aeabi_memclr4 (void *s, grub_size_t n)
__attribute__ ((alias ("__aeabi_memclr")));
void __aeabi_memclr8 (void *s, grub_size_t n)
__attribute__ ((alias ("__aeabi_memclr")));
int int
__aeabi_ulcmp (grub_uint64_t a, grub_uint64_t b) __aeabi_ulcmp (grub_uint64_t a, grub_uint64_t b)
{ {

View file

@ -27,6 +27,7 @@
#include <grub/term.h> #include <grub/term.h>
#include <grub/kernel.h> #include <grub/kernel.h>
#include <grub/mm.h> #include <grub/mm.h>
#include <grub/loader.h>
/* The handle of GRUB itself. Filled in by the startup code. */ /* The handle of GRUB itself. Filled in by the startup code. */
grub_efi_handle_t grub_efi_image_handle; grub_efi_handle_t grub_efi_image_handle;
@ -156,7 +157,7 @@ grub_efi_get_loaded_image (grub_efi_handle_t image_handle)
void void
grub_exit (void) grub_exit (void)
{ {
grub_efi_fini (); grub_machine_fini (GRUB_LOADER_FLAG_NORETURN);
efi_call_4 (grub_efi_system_table->boot_services->exit, efi_call_4 (grub_efi_system_table->boot_services->exit,
grub_efi_image_handle, GRUB_EFI_SUCCESS, 0, 0); grub_efi_image_handle, GRUB_EFI_SUCCESS, 0, 0);
for (;;) ; for (;;) ;
@ -205,6 +206,7 @@ grub_efi_set_variable(const char *var, const grub_efi_guid_t *guid,
| GRUB_EFI_VARIABLE_BOOTSERVICE_ACCESS | GRUB_EFI_VARIABLE_BOOTSERVICE_ACCESS
| GRUB_EFI_VARIABLE_RUNTIME_ACCESS), | GRUB_EFI_VARIABLE_RUNTIME_ACCESS),
datasize, data); datasize, data);
grub_free (var16);
if (status == GRUB_EFI_SUCCESS) if (status == GRUB_EFI_SUCCESS)
return GRUB_ERR_NONE; return GRUB_ERR_NONE;
@ -236,8 +238,11 @@ grub_efi_get_variable (const char *var, const grub_efi_guid_t *guid,
status = efi_call_5 (r->get_variable, var16, guid, NULL, &datasize, NULL); status = efi_call_5 (r->get_variable, var16, guid, NULL, &datasize, NULL);
if (!datasize) if (status != GRUB_EFI_BUFFER_TOO_SMALL || !datasize)
{
grub_free (var16);
return NULL; return NULL;
}
data = grub_malloc (datasize); data = grub_malloc (datasize);
if (!data) if (!data)
@ -422,6 +427,47 @@ grub_efi_get_device_path (grub_efi_handle_t handle)
GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL); GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
} }
/* Return the device path node right before the end node. */
grub_efi_device_path_t *
grub_efi_find_last_device_path (const grub_efi_device_path_t *dp)
{
grub_efi_device_path_t *next, *p;
if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp))
return 0;
for (p = (grub_efi_device_path_t *) dp, next = GRUB_EFI_NEXT_DEVICE_PATH (p);
! GRUB_EFI_END_ENTIRE_DEVICE_PATH (next);
p = next, next = GRUB_EFI_NEXT_DEVICE_PATH (next))
;
return p;
}
/* Duplicate a device path. */
grub_efi_device_path_t *
grub_efi_duplicate_device_path (const grub_efi_device_path_t *dp)
{
grub_efi_device_path_t *p;
grub_size_t total_size = 0;
for (p = (grub_efi_device_path_t *) dp;
;
p = GRUB_EFI_NEXT_DEVICE_PATH (p))
{
total_size += GRUB_EFI_DEVICE_PATH_LENGTH (p);
if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (p))
break;
}
p = grub_malloc (total_size);
if (! p)
return 0;
grub_memcpy (p, dp, total_size);
return p;
}
static void static void
dump_vendor_path (const char *type, grub_efi_vendor_device_path_t *vendor) dump_vendor_path (const char *type, grub_efi_vendor_device_path_t *vendor)
{ {

View file

@ -422,7 +422,7 @@ read_device_map (const char *dev_map)
char buf[1024]; /* XXX */ char buf[1024]; /* XXX */
int lineno = 0; int lineno = 0;
if (dev_map[0] == '\0') if (!dev_map || dev_map[0] == '\0')
{ {
grub_util_info ("no device.map"); grub_util_info ("no device.map");
return; return;

View file

@ -1,10 +1,8 @@
#include <grub/symbol.h> #include <grub/symbol.h>
#include <grub/cpu/kernel.h>
.set noreorder .set noreorder
.set nomacro .set nomacro
mips_attributes
FUNCTION (grub_arch_sync_caches) FUNCTION (grub_arch_sync_caches)
#include "cache_flush.S" #include "cache_flush.S"

View file

@ -21,7 +21,6 @@
#include <grub/offsets.h> #include <grub/offsets.h>
#include <grub/machine/memory.h> #include <grub/machine/memory.h>
#include <grub/machine/kernel.h> #include <grub/machine/kernel.h>
#include <grub/cpu/kernel.h>
#include <grub/offsets.h> #include <grub/offsets.h>
#define BASE_ADDR 8 #define BASE_ADDR 8
@ -29,7 +28,6 @@
.globl __start, _start, start .globl __start, _start, start
.set noreorder .set noreorder
.set nomacro .set nomacro
mips_attributes
__start: __start:
_start: _start:
start: start:

View file

@ -17,8 +17,10 @@
*/ */
#include <grub/symbol.h> #include <grub/symbol.h>
#include <grub/dl.h>
.file "setjmp.S" .file "setjmp.S"
GRUB_MOD_LICENSE "GPLv3+"
.text .text
/* /*

View file

@ -64,7 +64,6 @@ extern grub_uint64_t grub_relocator64_rbx;
extern grub_uint64_t grub_relocator64_rcx; extern grub_uint64_t grub_relocator64_rcx;
extern grub_uint64_t grub_relocator64_rdx; extern grub_uint64_t grub_relocator64_rdx;
extern grub_uint64_t grub_relocator64_rip; extern grub_uint64_t grub_relocator64_rip;
extern grub_uint64_t grub_relocator64_rip_addr;
extern grub_uint64_t grub_relocator64_rsp; extern grub_uint64_t grub_relocator64_rsp;
extern grub_uint64_t grub_relocator64_rsi; extern grub_uint64_t grub_relocator64_rsi;
extern grub_addr_t grub_relocator64_cr3; extern grub_addr_t grub_relocator64_cr3;

View file

@ -17,13 +17,11 @@
*/ */
#include <grub/symbol.h> #include <grub/symbol.h>
#include <grub/cpu/kernel.h>
.p2align 4 /* force 16-byte alignment */ .p2align 4 /* force 16-byte alignment */
.set noreorder .set noreorder
.set nomacro .set nomacro
mips_attributes
VARIABLE (grub_relocator_forward_start) VARIABLE (grub_relocator_forward_start)
move $a0, $9 move $a0, $9

View file

@ -362,7 +362,7 @@ grub_reed_solomon_add_redundancy (void *buffer, grub_size_t data_size,
/* Nothing to do. */ /* Nothing to do. */
if (!rs) if (!rs)
return; goto exit;
init_powx (); init_powx ();
@ -388,6 +388,7 @@ grub_reed_solomon_add_redundancy (void *buffer, grub_size_t data_size,
#ifndef TEST #ifndef TEST
assert (grub_memcmp (tmp, buffer, data_size) == 0); assert (grub_memcmp (tmp, buffer, data_size) == 0);
#endif #endif
exit:
free (tmp); free (tmp);
} }
#endif #endif

View file

@ -772,7 +772,7 @@ print_escaped (struct output_buffer *outbuf,
if (err) if (err)
return err; return err;
outbuf->buf[outbuf->ptr++] = '\''; outbuf->buf[outbuf->ptr++] = '\'';
for (ptr = from; *ptr; ptr++) for (ptr = from; *ptr && ptr < to; ptr++)
{ {
if (*ptr == '\'') if (*ptr == '\'')
{ {
@ -874,7 +874,9 @@ print_config (struct output_buffer *outbuf,
print_string ("#"); print_string ("#");
print_file (outbuf, menu, filename, NULL); print_file (outbuf, menu, filename, NULL);
print_string (" "); print_string (" ");
print (outbuf, newname, grub_strlen (newname)); err = print (outbuf, newname, grub_strlen (newname));
if (err)
return err;
print_string (":\n"); print_string (":\n");
for (menuptr = menu; menuptr; menuptr = menuptr->parent, depth++) for (menuptr = menu; menuptr; menuptr = menuptr->parent, depth++)
@ -944,8 +946,8 @@ write_entry (struct output_buffer *outbuf,
{ {
case KERNEL_LINUX: case KERNEL_LINUX:
{ {
char *ptr; const char *ptr;
char *initrd = NULL; const char *initrd = NULL, *initrde= NULL;
for (ptr = curentry->append; ptr && *ptr; ptr++) for (ptr = curentry->append; ptr && *ptr; ptr++)
if ((ptr == curentry->append || grub_isspace (ptr[-1])) if ((ptr == curentry->append || grub_isspace (ptr[-1]))
&& grub_strncasecmp (ptr, "initrd=", sizeof ("initrd=") - 1) && grub_strncasecmp (ptr, "initrd=", sizeof ("initrd=") - 1)
@ -953,12 +955,8 @@ write_entry (struct output_buffer *outbuf,
break; break;
if (ptr && *ptr) if (ptr && *ptr)
{ {
char *ptr2; initrd = ptr + sizeof ("initrd=") - 1;
initrd = grub_strdup(ptr + sizeof ("initrd=") - 1); for (initrde = initrd; *initrde && !grub_isspace (*initrde); initrde++);
if (!initrd)
return grub_errno;
for (ptr2 = initrd; *ptr2 && !grub_isspace (*ptr2); ptr2++);
*ptr2 = 0;
} }
print_string (" if test x$grub_platform = xpc; then " print_string (" if test x$grub_platform = xpc; then "
"linux_suffix=16; else linux_suffix= ; fi\n"); "linux_suffix=16; else linux_suffix= ; fi\n");
@ -966,7 +964,11 @@ write_entry (struct output_buffer *outbuf,
print_file (outbuf, menu, curentry->kernel_file, NULL); print_file (outbuf, menu, curentry->kernel_file, NULL);
print_string (" "); print_string (" ");
if (curentry->append) if (curentry->append)
print (outbuf, curentry->append, grub_strlen (curentry->append)); {
err = print (outbuf, curentry->append, grub_strlen (curentry->append));
if (err)
return err;
}
print_string ("\n"); print_string ("\n");
if (initrd || curentry->initrds) if (initrd || curentry->initrds)
{ {
@ -974,7 +976,7 @@ write_entry (struct output_buffer *outbuf,
print_string (" initrd$linux_suffix "); print_string (" initrd$linux_suffix ");
if (initrd) if (initrd)
{ {
print_file (outbuf, menu, initrd, NULL); print_file (outbuf, menu, initrd, initrde);
print_string (" "); print_string (" ");
} }
for (lst = curentry->initrds; lst; lst = lst->next) for (lst = curentry->initrds; lst; lst = lst->next)
@ -985,7 +987,6 @@ write_entry (struct output_buffer *outbuf,
print_string ("\n"); print_string ("\n");
} }
grub_free (initrd);
} }
break; break;
case KERNEL_CHAINLOADER: case KERNEL_CHAINLOADER:
@ -1197,7 +1198,6 @@ write_entry (struct output_buffer *outbuf,
ptr++; ptr++;
i386e = ptr; i386e = ptr;
} }
if (lme)
*lme = '\0'; *lme = '\0';
if (paee) if (paee)
*paee = '\0'; *paee = '\0';

View file

@ -33,12 +33,6 @@
GRUB_MOD_LICENSE ("GPLv3+"); GRUB_MOD_LICENSE ("GPLv3+");
#define GRUB_EFI_PAGE_SHIFT 12
#define BYTES_TO_PAGES(bytes) (((bytes) + 0xfff) >> GRUB_EFI_PAGE_SHIFT)
#define GRUB_EFI_PE_MAGIC 0x5A4D
static grub_efi_guid_t fdt_guid = GRUB_EFI_DEVICE_TREE_GUID;
static grub_dl_t my_mod; static grub_dl_t my_mod;
static int loaded; static int loaded;
@ -58,6 +52,7 @@ static void *
get_firmware_fdt (void) get_firmware_fdt (void)
{ {
grub_efi_configuration_table_t *tables; grub_efi_configuration_table_t *tables;
grub_efi_guid_t fdt_guid = GRUB_EFI_DEVICE_TREE_GUID;
void *firmware_fdt = NULL; void *firmware_fdt = NULL;
unsigned int i; unsigned int i;
@ -75,8 +70,8 @@ get_firmware_fdt (void)
return firmware_fdt; return firmware_fdt;
} }
static void void *
get_fdt (void) grub_linux_get_fdt (void)
{ {
void *raw_fdt; void *raw_fdt;
grub_size_t size; grub_size_t size;
@ -99,7 +94,7 @@ get_fdt (void)
grub_dprintf ("linux", "allocating %ld bytes for fdt\n", size); grub_dprintf ("linux", "allocating %ld bytes for fdt\n", size);
fdt = grub_efi_allocate_pages (0, BYTES_TO_PAGES (size)); fdt = grub_efi_allocate_pages (0, BYTES_TO_PAGES (size));
if (!fdt) if (!fdt)
return; return NULL;
if (raw_fdt) if (raw_fdt)
{ {
@ -110,10 +105,11 @@ get_fdt (void)
{ {
grub_fdt_create_empty_tree (fdt, size); grub_fdt_create_empty_tree (fdt, size);
} }
return fdt;
} }
static grub_err_t grub_err_t
check_kernel (struct grub_arm64_linux_kernel_header *lh) grub_arm64_uefi_check_image (struct grub_arm64_linux_kernel_header * lh)
{ {
if (lh->magic != GRUB_ARM64_LINUX_MAGIC) if (lh->magic != GRUB_ARM64_LINUX_MAGIC)
return grub_error(GRUB_ERR_BAD_OS, "invalid magic number"); return grub_error(GRUB_ERR_BAD_OS, "invalid magic number");
@ -131,14 +127,14 @@ check_kernel (struct grub_arm64_linux_kernel_header *lh)
} }
static grub_err_t static grub_err_t
finalize_params (void) finalize_params_linux (void)
{ {
grub_efi_boot_services_t *b; grub_efi_boot_services_t *b;
grub_efi_guid_t fdt_guid = GRUB_EFI_DEVICE_TREE_GUID;
grub_efi_status_t status; grub_efi_status_t status;
int node, retval; int node, retval;
get_fdt (); if (!grub_linux_get_fdt ())
if (!fdt)
goto failure; goto failure;
node = grub_fdt_find_subnode (fdt, 0, "chosen"); node = grub_fdt_find_subnode (fdt, 0, "chosen");
@ -240,21 +236,16 @@ out:
return grub_errno; return grub_errno;
} }
static grub_err_t grub_err_t
grub_linux_boot (void) grub_arm64_uefi_boot_image (grub_addr_t addr, grub_size_t size, char *args)
{ {
grub_efi_memory_mapped_device_path_t *mempath; grub_efi_memory_mapped_device_path_t *mempath;
grub_efi_handle_t image_handle; grub_efi_handle_t image_handle;
grub_efi_boot_services_t *b; grub_efi_boot_services_t *b;
grub_efi_status_t status; grub_efi_status_t status;
grub_err_t retval;
grub_efi_loaded_image_t *loaded_image; grub_efi_loaded_image_t *loaded_image;
int len; int len;
retval = finalize_params();
if (retval != GRUB_ERR_NONE)
return retval;
mempath = grub_malloc (2 * sizeof (grub_efi_memory_mapped_device_path_t)); mempath = grub_malloc (2 * sizeof (grub_efi_memory_mapped_device_path_t));
if (!mempath) if (!mempath)
return grub_errno; return grub_errno;
@ -263,8 +254,8 @@ grub_linux_boot (void)
mempath[0].header.subtype = GRUB_EFI_MEMORY_MAPPED_DEVICE_PATH_SUBTYPE; mempath[0].header.subtype = GRUB_EFI_MEMORY_MAPPED_DEVICE_PATH_SUBTYPE;
mempath[0].header.length = grub_cpu_to_le16_compile_time (sizeof (*mempath)); mempath[0].header.length = grub_cpu_to_le16_compile_time (sizeof (*mempath));
mempath[0].memory_type = GRUB_EFI_LOADER_DATA; mempath[0].memory_type = GRUB_EFI_LOADER_DATA;
mempath[0].start_address = (grub_addr_t) kernel_addr; mempath[0].start_address = addr;
mempath[0].end_address = (grub_addr_t) kernel_addr + kernel_size; mempath[0].end_address = addr + size;
mempath[1].header.type = GRUB_EFI_END_DEVICE_PATH_TYPE; mempath[1].header.type = GRUB_EFI_END_DEVICE_PATH_TYPE;
mempath[1].header.subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE; mempath[1].header.subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE;
@ -273,16 +264,16 @@ grub_linux_boot (void)
b = grub_efi_system_table->boot_services; b = grub_efi_system_table->boot_services;
status = b->load_image (0, grub_efi_image_handle, status = b->load_image (0, grub_efi_image_handle,
(grub_efi_device_path_t *) mempath, (grub_efi_device_path_t *) mempath,
kernel_addr, kernel_size, &image_handle); (void *) addr, size, &image_handle);
if (status != GRUB_EFI_SUCCESS) if (status != GRUB_EFI_SUCCESS)
return grub_error (GRUB_ERR_BAD_OS, "cannot load image"); return grub_error (GRUB_ERR_BAD_OS, "cannot load image");
grub_dprintf ("linux", "linux command line: '%s'\n", linux_args); grub_dprintf ("linux", "linux command line: '%s'\n", args);
/* Convert command line to UCS-2 */ /* Convert command line to UCS-2 */
loaded_image = grub_efi_get_loaded_image (image_handle); loaded_image = grub_efi_get_loaded_image (image_handle);
loaded_image->load_options_size = len = loaded_image->load_options_size = len =
(grub_strlen (linux_args) + 1) * sizeof (grub_efi_char16_t); (grub_strlen (args) + 1) * sizeof (grub_efi_char16_t);
loaded_image->load_options = loaded_image->load_options =
grub_efi_allocate_pages (0, grub_efi_allocate_pages (0,
BYTES_TO_PAGES (loaded_image->load_options_size)); BYTES_TO_PAGES (loaded_image->load_options_size));
@ -291,9 +282,9 @@ grub_linux_boot (void)
loaded_image->load_options_size = loaded_image->load_options_size =
2 * grub_utf8_to_utf16 (loaded_image->load_options, len, 2 * grub_utf8_to_utf16 (loaded_image->load_options, len,
(grub_uint8_t *) linux_args, len, NULL); (grub_uint8_t *) args, len, NULL);
grub_dprintf("linux", "starting image %p\n", image_handle); grub_dprintf ("linux", "starting image %p\n", image_handle);
status = b->start_image (image_handle, 0, NULL); status = b->start_image (image_handle, 0, NULL);
/* When successful, not reached */ /* When successful, not reached */
@ -304,6 +295,16 @@ grub_linux_boot (void)
return grub_errno; return grub_errno;
} }
static grub_err_t
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));
}
static grub_err_t static grub_err_t
grub_linux_unload (void) grub_linux_unload (void)
{ {
@ -400,7 +401,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
if (grub_file_read (file, &lh, sizeof (lh)) < (long) sizeof (lh)) if (grub_file_read (file, &lh, sizeof (lh)) < (long) sizeof (lh))
return grub_errno; return grub_errno;
if (check_kernel (&lh) != GRUB_ERR_NONE) if (grub_arm64_uefi_check_image (&lh) != GRUB_ERR_NONE)
goto fail; goto fail;
grub_loader_unset(); grub_loader_unset();

View file

@ -350,8 +350,6 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
} }
loaded_image->device_handle = dev_handle; loaded_image->device_handle = dev_handle;
grub_file_close (file);
if (argc > 1) if (argc > 1)
{ {
int i, len; int i, len;
@ -381,6 +379,9 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
loaded_image->load_options_size = len; loaded_image->load_options_size = len;
} }
grub_file_close (file);
grub_device_close (dev);
grub_loader_set (grub_chainloader_boot, grub_chainloader_unload, 0); grub_loader_set (grub_chainloader_boot, grub_chainloader_unload, 0);
return 0; return 0;

View file

@ -84,11 +84,11 @@ SUFFIX (grub_freebsd_load_elfmodule_obj) (struct grub_relocator *relocator,
grub_size_t chunk_size = 0; grub_size_t chunk_size = 0;
void *chunk_src; void *chunk_src;
curload = module = ALIGN_PAGE (*kern_end);
err = read_headers (file, argv[0], &e, &shdr); err = read_headers (file, argv[0], &e, &shdr);
if (err) if (err)
return err; goto out;
curload = module = ALIGN_PAGE (*kern_end);
for (s = (Elf_Shdr *) shdr; s < (Elf_Shdr *) ((char *) shdr for (s = (Elf_Shdr *) shdr; s < (Elf_Shdr *) ((char *) shdr
+ e.e_shnum * e.e_shentsize); + e.e_shnum * e.e_shentsize);
@ -109,7 +109,7 @@ SUFFIX (grub_freebsd_load_elfmodule_obj) (struct grub_relocator *relocator,
err = grub_relocator_alloc_chunk_addr (relocator, &ch, err = grub_relocator_alloc_chunk_addr (relocator, &ch,
module, chunk_size); module, chunk_size);
if (err) if (err)
return err; goto out;
chunk_src = get_virtual_current_address (ch); chunk_src = get_virtual_current_address (ch);
} }
@ -135,7 +135,7 @@ SUFFIX (grub_freebsd_load_elfmodule_obj) (struct grub_relocator *relocator,
err = load (file, argv[0], (grub_uint8_t *) chunk_src + curload - *kern_end, err = load (file, argv[0], (grub_uint8_t *) chunk_src + curload - *kern_end,
s->sh_offset, s->sh_size); s->sh_offset, s->sh_size);
if (err) if (err)
return err; goto out;
break; break;
case SHT_NOBITS: case SHT_NOBITS:
grub_memset ((grub_uint8_t *) chunk_src + curload - *kern_end, 0, grub_memset ((grub_uint8_t *) chunk_src + curload - *kern_end, 0,
@ -159,6 +159,8 @@ SUFFIX (grub_freebsd_load_elfmodule_obj) (struct grub_relocator *relocator,
| FREEBSD_MODINFOMD_SHDR, | FREEBSD_MODINFOMD_SHDR,
shdr, e.e_shnum * e.e_shentsize); shdr, e.e_shnum * e.e_shentsize);
out:
grub_free (shdr);
return err; return err;
} }
@ -177,11 +179,11 @@ SUFFIX (grub_freebsd_load_elfmodule) (struct grub_relocator *relocator,
grub_size_t chunk_size = 0; grub_size_t chunk_size = 0;
void *chunk_src; void *chunk_src;
curload = module = ALIGN_PAGE (*kern_end);
err = read_headers (file, argv[0], &e, &shdr); err = read_headers (file, argv[0], &e, &shdr);
if (err) if (err)
return err; goto out;
curload = module = ALIGN_PAGE (*kern_end);
for (s = (Elf_Shdr *) shdr; s < (Elf_Shdr *) ((char *) shdr for (s = (Elf_Shdr *) shdr; s < (Elf_Shdr *) ((char *) shdr
+ e.e_shnum * e.e_shentsize); + e.e_shnum * e.e_shentsize);
@ -207,7 +209,7 @@ SUFFIX (grub_freebsd_load_elfmodule) (struct grub_relocator *relocator,
err = grub_relocator_alloc_chunk_addr (relocator, &ch, err = grub_relocator_alloc_chunk_addr (relocator, &ch,
module, chunk_size); module, chunk_size);
if (err) if (err)
return err; goto out;
chunk_src = get_virtual_current_address (ch); chunk_src = get_virtual_current_address (ch);
} }
@ -235,7 +237,7 @@ SUFFIX (grub_freebsd_load_elfmodule) (struct grub_relocator *relocator,
+ s->sh_addr - *kern_end, + s->sh_addr - *kern_end,
s->sh_offset, s->sh_size); s->sh_offset, s->sh_size);
if (err) if (err)
return err; goto out;
break; break;
case SHT_NOBITS: case SHT_NOBITS:
grub_memset ((grub_uint8_t *) chunk_src + module grub_memset ((grub_uint8_t *) chunk_src + module
@ -265,6 +267,10 @@ SUFFIX (grub_freebsd_load_elfmodule) (struct grub_relocator *relocator,
grub_freebsd_add_meta_module (argv[0], FREEBSD_MODTYPE_ELF_MODULE, grub_freebsd_add_meta_module (argv[0], FREEBSD_MODTYPE_ELF_MODULE,
argc - 1, argv + 1, module, argc - 1, argv + 1, module,
curload - module); curload - module);
out:
grub_free (shdr);
if (err)
return err;
return SUFFIX (grub_freebsd_load_elf_meta) (relocator, file, argv[0], kern_end); return SUFFIX (grub_freebsd_load_elf_meta) (relocator, file, argv[0], kern_end);
} }
@ -292,13 +298,13 @@ SUFFIX (grub_freebsd_load_elf_meta) (struct grub_relocator *relocator,
err = read_headers (file, filename, &e, &shdr); err = read_headers (file, filename, &e, &shdr);
if (err) if (err)
return err; goto out;
err = grub_bsd_add_meta (FREEBSD_MODINFO_METADATA | err = grub_bsd_add_meta (FREEBSD_MODINFO_METADATA |
FREEBSD_MODINFOMD_ELFHDR, &e, FREEBSD_MODINFOMD_ELFHDR, &e,
sizeof (e)); sizeof (e));
if (err) if (err)
return err; goto out;
for (s = (Elf_Shdr *) shdr; s < (Elf_Shdr *) (shdr for (s = (Elf_Shdr *) shdr; s < (Elf_Shdr *) (shdr
+ e.e_shnum * e.e_shentsize); + e.e_shnum * e.e_shentsize);
@ -307,7 +313,10 @@ SUFFIX (grub_freebsd_load_elf_meta) (struct grub_relocator *relocator,
break; break;
if (s >= (Elf_Shdr *) ((char *) shdr if (s >= (Elf_Shdr *) ((char *) shdr
+ e.e_shnum * e.e_shentsize)) + e.e_shnum * e.e_shentsize))
return grub_error (GRUB_ERR_BAD_OS, N_("no symbol table")); {
err = grub_error (GRUB_ERR_BAD_OS, N_("no symbol table"));
goto out;
}
symoff = s->sh_offset; symoff = s->sh_offset;
symsize = s->sh_size; symsize = s->sh_size;
symentsize = s->sh_entsize; symentsize = s->sh_entsize;
@ -325,7 +334,7 @@ SUFFIX (grub_freebsd_load_elf_meta) (struct grub_relocator *relocator,
err = grub_relocator_alloc_chunk_addr (relocator, &ch, err = grub_relocator_alloc_chunk_addr (relocator, &ch,
symtarget, chunk_size); symtarget, chunk_size);
if (err) if (err)
return err; goto out;
sym_chunk = get_virtual_current_address (ch); sym_chunk = get_virtual_current_address (ch);
} }
@ -337,28 +346,38 @@ SUFFIX (grub_freebsd_load_elf_meta) (struct grub_relocator *relocator,
curload += sizeof (grub_freebsd_addr_t); curload += sizeof (grub_freebsd_addr_t);
if (grub_file_seek (file, symoff) == (grub_off_t) -1) if (grub_file_seek (file, symoff) == (grub_off_t) -1)
return grub_errno; {
err = grub_errno;
goto out;
}
sym = (Elf_Sym *) curload; sym = (Elf_Sym *) curload;
if (grub_file_read (file, curload, symsize) != (grub_ssize_t) symsize) if (grub_file_read (file, curload, symsize) != (grub_ssize_t) symsize)
{ {
if (! grub_errno) if (! grub_errno)
return grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), err = grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
filename); filename);
return grub_errno; else
err = grub_errno;
goto out;
} }
curload += symsize; curload += symsize;
*((grub_freebsd_addr_t *) curload) = strsize; *((grub_freebsd_addr_t *) curload) = strsize;
curload += sizeof (grub_freebsd_addr_t); curload += sizeof (grub_freebsd_addr_t);
if (grub_file_seek (file, stroff) == (grub_off_t) -1) if (grub_file_seek (file, stroff) == (grub_off_t) -1)
return grub_errno; {
err = grub_errno;
goto out;
}
str = (char *) curload; str = (char *) curload;
if (grub_file_read (file, curload, strsize) != (grub_ssize_t) strsize) if (grub_file_read (file, curload, strsize) != (grub_ssize_t) strsize)
{ {
if (! grub_errno) if (! grub_errno)
return grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), err = grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
filename); filename);
return grub_errno; else
err = grub_errno;
goto out;
} }
for (i = 0; for (i = 0;
@ -378,18 +397,20 @@ SUFFIX (grub_freebsd_load_elf_meta) (struct grub_relocator *relocator,
FREEBSD_MODINFOMD_DYNAMIC, &dynamic, FREEBSD_MODINFOMD_DYNAMIC, &dynamic,
sizeof (dynamic)); sizeof (dynamic));
if (err) if (err)
return err; goto out;
} }
err = grub_bsd_add_meta (FREEBSD_MODINFO_METADATA | err = grub_bsd_add_meta (FREEBSD_MODINFO_METADATA |
FREEBSD_MODINFOMD_SSYM, &symstart, FREEBSD_MODINFOMD_SSYM, &symstart,
sizeof (symstart)); sizeof (symstart));
if (err) if (err)
return err; goto out;
err = grub_bsd_add_meta (FREEBSD_MODINFO_METADATA | err = grub_bsd_add_meta (FREEBSD_MODINFO_METADATA |
FREEBSD_MODINFOMD_ESYM, &symend, FREEBSD_MODINFOMD_ESYM, &symend,
sizeof (symend)); sizeof (symend));
out:
grub_free (shdr);
if (err) if (err)
return err; return err;
@ -417,7 +438,10 @@ SUFFIX (grub_netbsd_load_elf_meta) (struct grub_relocator *relocator,
err = read_headers (file, filename, &e, &shdr); err = read_headers (file, filename, &e, &shdr);
if (err) if (err)
return err; {
grub_free (shdr);
return grub_errno;
}
for (s = (Elf_Shdr *) shdr; s < (Elf_Shdr *) (shdr for (s = (Elf_Shdr *) shdr; s < (Elf_Shdr *) (shdr
+ e.e_shnum * e.e_shentsize); + e.e_shnum * e.e_shentsize);
@ -426,7 +450,10 @@ SUFFIX (grub_netbsd_load_elf_meta) (struct grub_relocator *relocator,
break; break;
if (s >= (Elf_Shdr *) ((char *) shdr if (s >= (Elf_Shdr *) ((char *) shdr
+ e.e_shnum * e.e_shentsize)) + e.e_shnum * e.e_shentsize))
{
grub_free (shdr);
return GRUB_ERR_NONE; return GRUB_ERR_NONE;
}
symsize = s->sh_size; symsize = s->sh_size;
symsh = s; symsh = s;
s = (Elf_Shdr *) (shdr + e.e_shentsize * s->sh_link); s = (Elf_Shdr *) (shdr + e.e_shentsize * s->sh_link);
@ -443,7 +470,7 @@ SUFFIX (grub_netbsd_load_elf_meta) (struct grub_relocator *relocator,
err = grub_relocator_alloc_chunk_addr (relocator, &ch, err = grub_relocator_alloc_chunk_addr (relocator, &ch,
symtarget, chunk_size); symtarget, chunk_size);
if (err) if (err)
return err; goto out;
sym_chunk = get_virtual_current_address (ch); sym_chunk = get_virtual_current_address (ch);
} }
@ -482,29 +509,41 @@ SUFFIX (grub_netbsd_load_elf_meta) (struct grub_relocator *relocator,
} }
if (grub_file_seek (file, symsh->sh_offset) == (grub_off_t) -1) if (grub_file_seek (file, symsh->sh_offset) == (grub_off_t) -1)
return grub_errno; {
err = grub_errno;
goto out;
}
if (grub_file_read (file, curload, symsize) != (grub_ssize_t) symsize) if (grub_file_read (file, curload, symsize) != (grub_ssize_t) symsize)
{ {
if (! grub_errno) if (! grub_errno)
return grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), err = grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
filename); filename);
return grub_errno; else
err = grub_errno;
goto out;
} }
curload += ALIGN_UP (symsize, sizeof (grub_freebsd_addr_t)); curload += ALIGN_UP (symsize, sizeof (grub_freebsd_addr_t));
if (grub_file_seek (file, strsh->sh_offset) == (grub_off_t) -1) if (grub_file_seek (file, strsh->sh_offset) == (grub_off_t) -1)
return grub_errno; {
err = grub_errno;
goto out;
}
if (grub_file_read (file, curload, strsize) != (grub_ssize_t) strsize) if (grub_file_read (file, curload, strsize) != (grub_ssize_t) strsize)
{ {
if (! grub_errno) if (! grub_errno)
return grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), err = grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
filename); filename);
return grub_errno; else
err = grub_errno;
goto out;
} }
err = grub_bsd_add_meta (NETBSD_BTINFO_SYMTAB, err = grub_bsd_add_meta (NETBSD_BTINFO_SYMTAB,
&symtab, &symtab,
sizeof (symtab)); sizeof (symtab));
out:
grub_free (shdr);
if (err) if (err)
return err; return err;
@ -530,7 +569,10 @@ SUFFIX(grub_openbsd_find_ramdisk) (grub_file_t file,
err = read_headers (file, filename, &e, &shdr); err = read_headers (file, filename, &e, &shdr);
if (err) if (err)
{
grub_free (shdr);
return err; return err;
}
for (s = (Elf_Shdr *) shdr; s < (Elf_Shdr *) (shdr for (s = (Elf_Shdr *) shdr; s < (Elf_Shdr *) (shdr
+ e.e_shnum * e.e_shentsize); + e.e_shnum * e.e_shentsize);
@ -583,7 +625,11 @@ SUFFIX(grub_openbsd_find_ramdisk) (grub_file_t file,
} }
if (grub_file_seek (file, stroff) == (grub_off_t) -1) if (grub_file_seek (file, stroff) == (grub_off_t) -1)
{
grub_free (syms);
grub_free (strs);
return grub_errno; return grub_errno;
}
if (grub_file_read (file, strs, strsize) != (grub_ssize_t) strsize) if (grub_file_read (file, strs, strsize) != (grub_ssize_t) strsize)
{ {
grub_free (syms); grub_free (syms);

View file

@ -70,7 +70,6 @@ static grub_addr_t prot_mode_target;
static void *initrd_mem; static void *initrd_mem;
static grub_addr_t initrd_mem_target; static grub_addr_t initrd_mem_target;
static grub_size_t prot_init_space; static grub_size_t prot_init_space;
static grub_uint32_t initrd_pages;
static struct grub_relocator *relocator = NULL; static struct grub_relocator *relocator = NULL;
static void *efi_mmap_buf; static void *efi_mmap_buf;
static grub_size_t maximal_cmdline_size; static grub_size_t maximal_cmdline_size;
@ -1048,7 +1047,7 @@ static grub_err_t
grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
int argc, char *argv[]) int argc, char *argv[])
{ {
grub_size_t size = 0; grub_size_t size = 0, aligned_size = 0;
grub_addr_t addr_min, addr_max; grub_addr_t addr_min, addr_max;
grub_addr_t addr; grub_addr_t addr;
grub_err_t err; grub_err_t err;
@ -1070,8 +1069,7 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
goto fail; goto fail;
size = grub_get_initrd_size (&initrd_ctx); size = grub_get_initrd_size (&initrd_ctx);
aligned_size = ALIGN_UP (size, 4096);
initrd_pages = (page_align (size) >> 12);
/* Get the highest address available for the initrd. */ /* Get the highest address available for the initrd. */
if (grub_le_to_cpu16 (linux_params.version) >= 0x0203) if (grub_le_to_cpu16 (linux_params.version) >= 0x0203)
@ -1099,7 +1097,7 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
addr_min = (grub_addr_t) prot_mode_target + prot_init_space; addr_min = (grub_addr_t) prot_mode_target + prot_init_space;
/* Put the initrd as high as possible, 4KiB aligned. */ /* Put the initrd as high as possible, 4KiB aligned. */
addr = (addr_max - size) & ~0xFFF; addr = (addr_max - aligned_size) & ~0xFFF;
if (addr < addr_min) if (addr < addr_min)
{ {
@ -1110,7 +1108,8 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
{ {
grub_relocator_chunk_t ch; grub_relocator_chunk_t ch;
err = grub_relocator_alloc_chunk_align (relocator, &ch, err = grub_relocator_alloc_chunk_align (relocator, &ch,
addr_min, addr, size, 0x1000, addr_min, addr, aligned_size,
0x1000,
GRUB_RELOCATOR_PREFERENCE_HIGH, GRUB_RELOCATOR_PREFERENCE_HIGH,
1); 1);
if (err) if (err)

View file

@ -269,9 +269,9 @@ grub_xnu_devprop_add_property (struct grub_xnu_devprop_device_descriptor *dev,
prop->data = grub_malloc (prop->length); prop->data = grub_malloc (prop->length);
if (!prop->data) if (!prop->data)
{ {
grub_free (prop);
grub_free (prop->name); grub_free (prop->name);
grub_free (prop->name16); grub_free (prop->name16);
grub_free (prop);
return grub_errno; return grub_errno;
} }
grub_memcpy (prop->data, data, prop->length); grub_memcpy (prop->data, data, prop->length);

View file

@ -161,6 +161,9 @@ grub_initrd_init (int argc, char *argv[],
for (i = 0; i < argc; i++) for (i = 0; i < argc; i++)
{ {
const char *fname = argv[i]; const char *fname = argv[i];
initrd_ctx->size = ALIGN_UP (initrd_ctx->size, 4);
if (grub_memcmp (argv[i], "newc:", 5) == 0) if (grub_memcmp (argv[i], "newc:", 5) == 0)
{ {
const char *ptr, *eptr; const char *ptr, *eptr;
@ -205,11 +208,12 @@ grub_initrd_init (int argc, char *argv[],
initrd_ctx->nfiles++; initrd_ctx->nfiles++;
initrd_ctx->components[i].size initrd_ctx->components[i].size
= grub_file_size (initrd_ctx->components[i].file); = grub_file_size (initrd_ctx->components[i].file);
initrd_ctx->size += ALIGN_UP (initrd_ctx->components[i].size, 4); initrd_ctx->size += initrd_ctx->components[i].size;
} }
if (newc) if (newc)
{ {
initrd_ctx->size = ALIGN_UP (initrd_ctx->size, 4);
initrd_ctx->size += ALIGN_UP (sizeof (struct newc_head) initrd_ctx->size += ALIGN_UP (sizeof (struct newc_head)
+ sizeof ("TRAILER!!!") - 1, 4); + sizeof ("TRAILER!!!") - 1, 4);
free_dir (root); free_dir (root);
@ -248,10 +252,12 @@ grub_initrd_load (struct grub_linux_initrd_context *initrd_ctx,
int i; int i;
int newc = 0; int newc = 0;
struct dir *root = 0; struct dir *root = 0;
grub_ssize_t cursize = 0;
for (i = 0; i < initrd_ctx->nfiles; i++) for (i = 0; i < initrd_ctx->nfiles; i++)
{ {
grub_ssize_t cursize; grub_memset (ptr, 0, ALIGN_UP_OVERHEAD (cursize, 4));
ptr += ALIGN_UP_OVERHEAD (cursize, 4);
if (initrd_ctx->components[i].newc_name) if (initrd_ctx->components[i].newc_name)
{ {
@ -283,11 +289,13 @@ grub_initrd_load (struct grub_linux_initrd_context *initrd_ctx,
return grub_errno; return grub_errno;
} }
ptr += cursize; ptr += cursize;
grub_memset (ptr, 0, ALIGN_UP_OVERHEAD (cursize, 4));
ptr += ALIGN_UP_OVERHEAD (cursize, 4);
} }
if (newc) if (newc)
{
grub_memset (ptr, 0, ALIGN_UP_OVERHEAD (cursize, 4));
ptr += ALIGN_UP_OVERHEAD (cursize, 4);
ptr = make_header (ptr, "TRAILER!!!", sizeof ("TRAILER!!!") - 1, 0, 0); ptr = make_header (ptr, "TRAILER!!!", sizeof ("TRAILER!!!") - 1, 0, 0);
}
free_dir (root); free_dir (root);
root = 0; root = 0;
return GRUB_ERR_NONE; return GRUB_ERR_NONE;

View file

@ -333,6 +333,7 @@ grub_cmd_module (grub_command_t cmd __attribute__ ((unused)),
return grub_errno; return grub_errno;
#ifndef GRUB_USE_MULTIBOOT2 #ifndef GRUB_USE_MULTIBOOT2
lowest_addr = 0x100000;
if (grub_multiboot_quirks & GRUB_MULTIBOOT_QUIRK_MODULES_AFTER_KERNEL) if (grub_multiboot_quirks & GRUB_MULTIBOOT_QUIRK_MODULES_AFTER_KERNEL)
lowest_addr = ALIGN_UP (highest_load + 1048576, 4096); lowest_addr = ALIGN_UP (highest_load + 1048576, 4096);
#endif #endif

View file

@ -169,7 +169,10 @@ CONCAT(grub_multiboot_load_elf, XX) (grub_file_t file, const char *filename, voi
return grub_errno; return grub_errno;
if (grub_file_seek (file, ehdr->e_shoff) == (grub_off_t) -1) if (grub_file_seek (file, ehdr->e_shoff) == (grub_off_t) -1)
{
grub_free (shdr);
return grub_errno; return grub_errno;
}
if (grub_file_read (file, shdr, ehdr->e_shnum * ehdr->e_shentsize) if (grub_file_read (file, shdr, ehdr->e_shnum * ehdr->e_shentsize)
!= (grub_ssize_t) ehdr->e_shnum * ehdr->e_shentsize) != (grub_ssize_t) ehdr->e_shnum * ehdr->e_shentsize)

View file

@ -157,6 +157,12 @@ grub_net_configure_by_dhcp_ack (const char *name,
hwaddr.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; hwaddr.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET;
inter = grub_net_add_addr (name, card, &addr, &hwaddr, flags); inter = grub_net_add_addr (name, card, &addr, &hwaddr, flags);
#if 0
/* This is likely based on misunderstanding. gateway_ip refers to
address of BOOTP relay and should not be used after BOOTP transaction
is complete.
See RFC1542, 3.4 Interpretation of the 'giaddr' field
*/
if (bp->gateway_ip) if (bp->gateway_ip)
{ {
grub_net_network_level_netaddress_t target; grub_net_network_level_netaddress_t target;
@ -178,6 +184,7 @@ grub_net_configure_by_dhcp_ack (const char *name,
target.ipv4.masksize = 32; target.ipv4.masksize = 32;
grub_net_add_route (name, target, inter); grub_net_add_route (name, target, inter);
} }
#endif
if (size > OFFSET_OF (boot_file, bp)) if (size > OFFSET_OF (boot_file, bp))
grub_env_set_net_property (name, "boot_file", bp->boot_file, grub_env_set_net_property (name, "boot_file", bp->boot_file,

View file

@ -262,7 +262,7 @@ recv_hook (grub_net_udp_socket_t sock __attribute__ ((unused)),
grub_netbuff_free (nb); grub_netbuff_free (nb);
return GRUB_ERR_NONE; return GRUB_ERR_NONE;
} }
for (i = 0; i < grub_cpu_to_be16 (head->qdcount); i++) for (i = 0; i < grub_be_to_cpu16 (head->qdcount); i++)
{ {
if (ptr >= nb->tail) if (ptr >= nb->tail)
{ {
@ -277,7 +277,7 @@ recv_hook (grub_net_udp_socket_t sock __attribute__ ((unused)),
ptr += 4; ptr += 4;
} }
*data->addresses = grub_malloc (sizeof ((*data->addresses)[0]) *data->addresses = grub_malloc (sizeof ((*data->addresses)[0])
* grub_cpu_to_be16 (head->ancount)); * grub_be_to_cpu16 (head->ancount));
if (!*data->addresses) if (!*data->addresses)
{ {
grub_errno = GRUB_ERR_NONE; grub_errno = GRUB_ERR_NONE;
@ -286,7 +286,7 @@ recv_hook (grub_net_udp_socket_t sock __attribute__ ((unused)),
} }
reparse_ptr = ptr; reparse_ptr = ptr;
reparse: reparse:
for (i = 0, ptr = reparse_ptr; i < grub_cpu_to_be16 (head->ancount); i++) for (i = 0, ptr = reparse_ptr; i < grub_be_to_cpu16 (head->ancount); i++)
{ {
int ignored = 0; int ignored = 0;
grub_uint8_t class; grub_uint8_t class;

View file

@ -142,9 +142,80 @@ get_card_packet (struct grub_net_card *dev)
return nb; return nb;
} }
static grub_err_t
open_card (struct grub_net_card *dev)
{
grub_efi_simple_network_t *net;
/* Try to reopen SNP exlusively to close any active MNP protocol instance
that may compete for packet polling
*/
net = grub_efi_open_protocol (dev->efi_handle, &net_io_guid,
GRUB_EFI_OPEN_PROTOCOL_BY_EXCLUSIVE);
if (net)
{
if (net->mode->state == GRUB_EFI_NETWORK_STOPPED
&& efi_call_1 (net->start, net) != GRUB_EFI_SUCCESS)
return grub_error (GRUB_ERR_NET_NO_CARD, "%s: net start failed",
dev->name);
if (net->mode->state == GRUB_EFI_NETWORK_STOPPED)
return grub_error (GRUB_ERR_NET_NO_CARD, "%s: card stopped",
dev->name);
if (net->mode->state == GRUB_EFI_NETWORK_STARTED
&& efi_call_3 (net->initialize, net, 0, 0) != GRUB_EFI_SUCCESS)
return grub_error (GRUB_ERR_NET_NO_CARD, "%s: net initialize failed",
dev->name);
/* Enable hardware receive filters if driver declares support for it.
We need unicast and broadcast and additionaly all nodes and
solicited multicast for IPv6. Solicited multicast is per-IPv6
address and we currently do not have API to do it so simply
try to enable receive of all multicast packets or evertyhing in
the worst case (i386 PXE driver always enables promiscuous too).
This does trust firmware to do what it claims to do.
*/
if (net->mode->receive_filter_mask)
{
grub_uint32_t filters = GRUB_EFI_SIMPLE_NETWORK_RECEIVE_UNICAST |
GRUB_EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST |
GRUB_EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;
filters &= net->mode->receive_filter_mask;
if (!(filters & GRUB_EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST))
filters |= (net->mode->receive_filter_mask &
GRUB_EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS);
efi_call_6 (net->receive_filters, net, filters, 0, 0, 0, NULL);
}
efi_call_4 (grub_efi_system_table->boot_services->close_protocol,
dev->efi_net, &net_io_guid,
grub_efi_image_handle, dev->efi_handle);
dev->efi_net = net;
}
/* If it failed we just try to run as best as we can */
return GRUB_ERR_NONE;
}
static void
close_card (struct grub_net_card *dev)
{
efi_call_1 (dev->efi_net->shutdown, dev->efi_net);
efi_call_1 (dev->efi_net->stop, dev->efi_net);
efi_call_4 (grub_efi_system_table->boot_services->close_protocol,
dev->efi_net, &net_io_guid,
grub_efi_image_handle, dev->efi_handle);
}
static struct grub_net_card_driver efidriver = static struct grub_net_card_driver efidriver =
{ {
.name = "efinet", .name = "efinet",
.open = open_card,
.close = close_card,
.send = send_card_buffer, .send = send_card_buffer,
.recv = get_card_packet .recv = get_card_packet
}; };
@ -174,6 +245,29 @@ grub_efinet_findcards (void)
{ {
grub_efi_simple_network_t *net; grub_efi_simple_network_t *net;
struct grub_net_card *card; struct grub_net_card *card;
grub_efi_device_path_t *dp, *parent = NULL, *child = NULL;
/* EDK2 UEFI PXE driver creates IPv4 and IPv6 messaging devices as
children of main MAC messaging device. We only need one device with
bound SNP per physical card, otherwise they compete with each other
when polling for incoming packets.
*/
dp = grub_efi_get_device_path (*handle);
if (!dp)
continue;
for (; ! GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp); dp = GRUB_EFI_NEXT_DEVICE_PATH (dp))
{
parent = child;
child = dp;
}
if (child
&& GRUB_EFI_DEVICE_PATH_TYPE (child) == GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE
&& (GRUB_EFI_DEVICE_PATH_SUBTYPE (child) == GRUB_EFI_IPV4_DEVICE_PATH_SUBTYPE
|| GRUB_EFI_DEVICE_PATH_SUBTYPE (child) == GRUB_EFI_IPV6_DEVICE_PATH_SUBTYPE)
&& parent
&& GRUB_EFI_DEVICE_PATH_TYPE (parent) == GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE
&& GRUB_EFI_DEVICE_PATH_SUBTYPE (parent) == GRUB_EFI_MAC_ADDRESS_DEVICE_PATH_SUBTYPE)
continue;
net = grub_efi_open_protocol (*handle, &net_io_guid, net = grub_efi_open_protocol (*handle, &net_io_guid,
GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL); GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
@ -251,7 +345,33 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device,
if (! cdp) if (! cdp)
continue; continue;
if (grub_efi_compare_device_paths (dp, cdp) != 0) if (grub_efi_compare_device_paths (dp, cdp) != 0)
{
grub_efi_device_path_t *ldp, *dup_dp, *dup_ldp;
int match;
/* EDK2 UEFI PXE driver creates pseudo devices with type IPv4/IPv6
as children of Ethernet card and binds PXE and Load File protocols
to it. Loaded Image Device Path protocol will point to these pseudo
devices. We skip them when enumerating cards, so here we need to
find matching MAC device.
*/
ldp = grub_efi_find_last_device_path (dp);
if (GRUB_EFI_DEVICE_PATH_TYPE (ldp) != GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE
|| (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_IPV4_DEVICE_PATH_SUBTYPE
&& GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_IPV6_DEVICE_PATH_SUBTYPE))
continue; continue;
dup_dp = grub_efi_duplicate_device_path (dp);
if (!dup_dp)
continue;
dup_ldp = grub_efi_find_last_device_path (dup_dp);
dup_ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE;
dup_ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE;
dup_ldp->length = sizeof (*dup_ldp);
match = grub_efi_compare_device_paths (dup_dp, cdp) == 0;
grub_free (dup_dp);
if (!match)
continue;
}
pxe = grub_efi_open_protocol (hnd, &pxe_io_guid, pxe = grub_efi_open_protocol (hnd, &pxe_io_guid,
GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL); GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
if (! pxe) if (! pxe)

View file

@ -389,6 +389,7 @@ grub_cmdline_get (const char *prompt_translated)
if (!unicode_msg) if (!unicode_msg)
{ {
grub_free (buf); grub_free (buf);
grub_free (cl_terms);
return 0; return 0;
} }
msg_len = grub_utf8_to_ucs4 (unicode_msg, msg_len - 1, msg_len = grub_utf8_to_ucs4 (unicode_msg, msg_len - 1,

View file

@ -64,7 +64,10 @@ grub_env_new_context (int export_all)
return grub_errno; return grub_errno;
menu = grub_zalloc (sizeof (*menu)); menu = grub_zalloc (sizeof (*menu));
if (! menu) if (! menu)
{
grub_free (context);
return grub_errno; return grub_errno;
}
context->prev = grub_current_context; context->prev = grub_current_context;
grub_current_context = context; grub_current_context = context;

View file

@ -316,9 +316,9 @@ get_btrfs_fs_prefix (const char *mount_path)
tree_id = sargs.buf[2]; tree_id = sargs.buf[2];
br = (struct grub_btrfs_root_backref *) (sargs.buf + 4); br = (struct grub_btrfs_root_backref *) (sargs.buf + 4);
inode_id = br->inode_id; inode_id = grub_le_to_cpu64 (br->inode_id);
name = br->name; name = br->name;
namelen = br->n; namelen = grub_le_to_cpu16 (br->n);
} }
else else
{ {
@ -345,7 +345,7 @@ get_btrfs_fs_prefix (const char *mount_path)
ir = (struct grub_btrfs_inode_ref *) (sargs.buf + 4); ir = (struct grub_btrfs_inode_ref *) (sargs.buf + 4);
name = ir->name; name = ir->name;
namelen = ir->n; namelen = grub_le_to_cpu16 (ir->n);
} }
old = ret; old = ret;
ret = xmalloc (namelen + (old ? strlen (old) : 0) + 2); ret = xmalloc (namelen + (old ? strlen (old) : 0) + 2);

View file

@ -539,7 +539,7 @@ grub_util_devname_to_ofpath (const char *sys_devname)
ofpath = xstrdup ("floppy"); ofpath = xstrdup ("floppy");
else else
{ {
grub_util_warn (_("unknown device type %s\n"), device); grub_util_warn (_("unknown device type %s"), device);
ofpath = NULL; ofpath = NULL;
} }

View file

@ -544,6 +544,7 @@ grub_guess_root_devices (const char *dir_in)
if (stat (dir, &st) < 0) if (stat (dir, &st) < 0)
grub_util_error (_("cannot stat `%s': %s"), dir, strerror (errno)); grub_util_error (_("cannot stat `%s': %s"), dir, strerror (errno));
free (dir);
dev = st.st_dev; dev = st.st_dev;

View file

@ -51,7 +51,10 @@ grub_make_system_path_relative_to_its_root (const char *path)
#ifdef __linux__ #ifdef __linux__
ret = grub_make_system_path_relative_to_its_root_os (p); ret = grub_make_system_path_relative_to_its_root_os (p);
if (ret) if (ret)
{
free (p);
return ret; return ret;
}
#endif #endif
/* For ZFS sub-pool filesystems. */ /* For ZFS sub-pool filesystems. */

View file

@ -173,7 +173,10 @@ grub_efiserial_init (void)
port->name = grub_malloc (sizeof ("efiXXXXXXXXXXXXXXXXXXXX")); port->name = grub_malloc (sizeof ("efiXXXXXXXXXXXXXXXXXXXX"));
if (!port->name) if (!port->name)
{
grub_free (port);
return; return;
}
grub_snprintf (port->name, sizeof ("efiXXXXXXXXXXXXXXXXXXXX"), grub_snprintf (port->name, sizeof ("efiXXXXXXXXXXXXXXXXXXXX"),
"efi%d", num_serial++); "efi%d", num_serial++);

View file

@ -23,6 +23,10 @@
#define GRUB_ARM64_LINUX_MAGIC 0x644d5241 /* 'ARM\x64' */ #define GRUB_ARM64_LINUX_MAGIC 0x644d5241 /* 'ARM\x64' */
#define GRUB_EFI_PAGE_SHIFT 12
#define BYTES_TO_PAGES(bytes) (((bytes) + 0xfff) >> GRUB_EFI_PAGE_SHIFT)
#define GRUB_EFI_PE_MAGIC 0x5A4D
/* From linux/Documentation/arm64/booting.txt */ /* From linux/Documentation/arm64/booting.txt */
struct grub_arm64_linux_kernel_header struct grub_arm64_linux_kernel_header
{ {
@ -38,4 +42,11 @@ struct grub_arm64_linux_kernel_header
grub_uint32_t hdr_offset; /* Offset of PE/COFF header */ grub_uint32_t hdr_offset; /* Offset of PE/COFF header */
}; };
/* Declare the functions for getting dtb and checking/booting image */
void *grub_linux_get_fdt (void);
grub_err_t grub_arm64_uefi_check_image (struct grub_arm64_linux_kernel_header
*lh);
grub_err_t grub_arm64_uefi_boot_image (grub_addr_t addr, grub_size_t size,
char *args);
#endif /* ! GRUB_LINUX_CPU_HEADER */ #endif /* ! GRUB_LINUX_CPU_HEADER */

View file

@ -115,11 +115,36 @@ void *
EXPORT_FUNC (__aeabi_memcpy) (void *dest, const void *src, grub_size_t n); EXPORT_FUNC (__aeabi_memcpy) (void *dest, const void *src, grub_size_t n);
#endif #endif
#ifdef HAVE___AEABI_MEMCPY4
void *
EXPORT_FUNC (__aeabi_memcpy4) (void *dest, const void *src, grub_size_t n);
#endif
#ifdef HAVE___AEABI_MEMCPY8
void *
EXPORT_FUNC (__aeabi_memcpy8) (void *dest, const void *src, grub_size_t n);
#endif
#ifdef HAVE___AEABI_MEMSET #ifdef HAVE___AEABI_MEMSET
void * void *
EXPORT_FUNC(__aeabi_memset) (void *s, int c, grub_size_t n); EXPORT_FUNC(__aeabi_memset) (void *s, int c, grub_size_t n);
#endif #endif
#ifdef HAVE___AEABI_MEMCLR
void *
EXPORT_FUNC(__aeabi_memclr) (void *s, grub_size_t n);
#endif
#ifdef HAVE___AEABI_MEMCLR4
void *
EXPORT_FUNC(__aeabi_memclr4) (void *s, grub_size_t n);
#endif
#ifdef HAVE___AEABI_MEMCLR8
void *
EXPORT_FUNC(__aeabi_memclr8) (void *s, grub_size_t n);
#endif
#ifdef HAVE___AEABI_LASR #ifdef HAVE___AEABI_LASR
grub_uint64_t grub_uint64_t
EXPORT_FUNC (__aeabi_lasr) (grub_uint64_t u, int b); EXPORT_FUNC (__aeabi_lasr) (grub_uint64_t u, int b);

View file

@ -88,7 +88,14 @@ EXPORT_FUNC (__aeabi_lmul) (grub_uint64_t a, grub_uint64_t b);
void * void *
EXPORT_FUNC (__aeabi_memcpy) (void *dest, const void *src, grub_size_t n); EXPORT_FUNC (__aeabi_memcpy) (void *dest, const void *src, grub_size_t n);
void * void *
EXPORT_FUNC (__aeabi_memcpy4) (void *dest, const void *src, grub_size_t n);
void *
EXPORT_FUNC (__aeabi_memcpy8) (void *dest, const void *src, grub_size_t n);
void *
EXPORT_FUNC(__aeabi_memset) (void *s, int c, grub_size_t n); EXPORT_FUNC(__aeabi_memset) (void *s, int c, grub_size_t n);
void EXPORT_FUNC(__aeabi_memclr) (void *s, grub_size_t n);
void EXPORT_FUNC(__aeabi_memclr4) (void *s, grub_size_t n);
void EXPORT_FUNC(__aeabi_memclr8) (void *s, grub_size_t n);
grub_uint64_t grub_uint64_t
EXPORT_FUNC (__aeabi_lasr) (grub_uint64_t u, int b); EXPORT_FUNC (__aeabi_lasr) (grub_uint64_t u, int b);

View file

@ -172,7 +172,7 @@ grub_diskfilter_unregister (grub_diskfilter_t diskfilter)
struct grub_diskfilter_vg * struct grub_diskfilter_vg *
grub_diskfilter_make_raid (grub_size_t uuidlen, char *uuid, int nmemb, grub_diskfilter_make_raid (grub_size_t uuidlen, char *uuid, int nmemb,
char *name, grub_uint64_t disk_size, const char *name, grub_uint64_t disk_size,
grub_uint64_t stripe_size, grub_uint64_t stripe_size,
int layout, int level); int layout, int level);

View file

@ -1501,17 +1501,31 @@ enum
GRUB_EFI_NETWORK_INITIALIZED, GRUB_EFI_NETWORK_INITIALIZED,
}; };
enum
{
GRUB_EFI_SIMPLE_NETWORK_RECEIVE_UNICAST = 0x01,
GRUB_EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST = 0x02,
GRUB_EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST = 0x04,
GRUB_EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS = 0x08,
GRUB_EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST = 0x10,
};
struct grub_efi_simple_network struct grub_efi_simple_network
{ {
grub_uint64_t revision; grub_uint64_t revision;
grub_efi_status_t (*start) (struct grub_efi_simple_network *this); grub_efi_status_t (*start) (struct grub_efi_simple_network *this);
void (*stop) (void); grub_efi_status_t (*stop) (struct grub_efi_simple_network *this);
grub_efi_status_t (*initialize) (struct grub_efi_simple_network *this, grub_efi_status_t (*initialize) (struct grub_efi_simple_network *this,
grub_efi_uintn_t extra_rx, grub_efi_uintn_t extra_rx,
grub_efi_uintn_t extra_tx); grub_efi_uintn_t extra_tx);
void (*reset) (void); void (*reset) (void);
void (*shutdown) (void); grub_efi_status_t (*shutdown) (struct grub_efi_simple_network *this);
void (*receive_filters) (void); grub_efi_status_t (*receive_filters) (struct grub_efi_simple_network *this,
grub_uint32_t enable,
grub_uint32_t disable,
grub_efi_boolean_t reset_mcast_filter,
grub_efi_uintn_t mcast_filter_count,
grub_efi_mac_address_t *mcast_filter);
void (*station_address) (void); void (*station_address) (void);
void (*statistics) (void); void (*statistics) (void);
void (*mcastiptomac) (void); void (*mcastiptomac) (void);

View file

@ -56,6 +56,10 @@ void EXPORT_FUNC(grub_efi_print_device_path) (grub_efi_device_path_t *dp);
char *EXPORT_FUNC(grub_efi_get_filename) (grub_efi_device_path_t *dp); char *EXPORT_FUNC(grub_efi_get_filename) (grub_efi_device_path_t *dp);
grub_efi_device_path_t * grub_efi_device_path_t *
EXPORT_FUNC(grub_efi_get_device_path) (grub_efi_handle_t handle); EXPORT_FUNC(grub_efi_get_device_path) (grub_efi_handle_t handle);
grub_efi_device_path_t *
EXPORT_FUNC(grub_efi_find_last_device_path) (const grub_efi_device_path_t *dp);
grub_efi_device_path_t *
EXPORT_FUNC(grub_efi_duplicate_device_path) (const grub_efi_device_path_t *dp);
grub_err_t EXPORT_FUNC (grub_efi_finish_boot_services) (grub_efi_uintn_t *outbuf_size, void *outbuf, grub_err_t EXPORT_FUNC (grub_efi_finish_boot_services) (grub_efi_uintn_t *outbuf_size, void *outbuf,
grub_efi_uintn_t *map_key, grub_efi_uintn_t *map_key,
grub_efi_uintn_t *efi_desc_size, grub_efi_uintn_t *efi_desc_size,

View file

@ -117,4 +117,16 @@ int grub_fdt_set_prop (void *fdt, unsigned int nodeoffset, const char *name,
grub_fdt_set_prop ((fdt), (nodeoffset), (name), &_val, 8); \ grub_fdt_set_prop ((fdt), (nodeoffset), (name), &_val, 8); \
}) })
/* Setup "reg" property for
* #address-cells = <0x2>
* #size-cells = <0x2>
*/
#define grub_fdt_set_reg64(fdt, nodeoffset, addr, size) \
({ \
grub_uint64_t reg_64[2]; \
reg_64[0] = grub_cpu_to_be64(addr); \
reg_64[1] = grub_cpu_to_be64(size); \
grub_fdt_set_prop ((fdt), (nodeoffset), "reg", reg_64, 16); \
})
#endif /* ! GRUB_FDT_HEADER */ #endif /* ! GRUB_FDT_HEADER */

View file

@ -62,6 +62,17 @@ EXPORT_FUNC(grub_fshelp_find_file) (const char *path,
enum grub_fshelp_filetype expect); enum grub_fshelp_filetype expect);
grub_err_t
EXPORT_FUNC(grub_fshelp_find_file_lookup) (const char *path,
grub_fshelp_node_t rootnode,
grub_fshelp_node_t *foundnode,
grub_err_t (*lookup_file) (grub_fshelp_node_t dir,
const char *name,
grub_fshelp_node_t *foundnode,
enum grub_fshelp_filetype *foundtype),
char *(*read_symlink) (grub_fshelp_node_t node),
enum grub_fshelp_filetype expect);
/* Read LEN bytes from the file NODE on disk DISK into the buffer BUF, /* Read LEN bytes from the file NODE on disk DISK into the buffer BUF,
beginning with the block POS. READ_HOOK should be set before beginning with the block POS. READ_HOOK should be set before
reading a block from the file. GET_BLOCK is used to translate file reading a block from the file. GET_BLOCK is used to translate file

View file

@ -21,8 +21,4 @@
#include <grub/symbol.h> #include <grub/symbol.h>
#ifdef ASM_FILE
#define mips_attributes .gnu_attribute 4, 3
#endif
#endif /* ! GRUB_KERNEL_MACHINE_HEADER */ #endif /* ! GRUB_KERNEL_MACHINE_HEADER */

View file

@ -126,7 +126,7 @@ typedef struct zio_cksum {
* +-------+-------+-------+-------+-------+-------+-------+-------+ * +-------+-------+-------+-------+-------+-------+-------+-------+
* 5 |G| offset3 | * 5 |G| offset3 |
* +-------+-------+-------+-------+-------+-------+-------+-------+ * +-------+-------+-------+-------+-------+-------+-------+-------+
* 6 |BDX|lvl| type | cksum | comp | PSIZE | LSIZE | * 6 |BDX|lvl| type | cksum |E| comp| PSIZE | LSIZE |
* +-------+-------+-------+-------+-------+-------+-------+-------+ * +-------+-------+-------+-------+-------+-------+-------+-------+
* 7 | padding | * 7 | padding |
* +-------+-------+-------+-------+-------+-------+-------+-------+ * +-------+-------+-------+-------+-------+-------+-------+-------+
@ -160,7 +160,8 @@ typedef struct zio_cksum {
* G gang block indicator * G gang block indicator
* B byteorder (endianness) * B byteorder (endianness)
* D dedup * D dedup
* X unused * X encryption
* E blkptr_t contains embedded data
* lvl level of indirection * lvl level of indirection
* type DMU object type * type DMU object type
* phys birth txg of block allocation; zero if same as logical birth txg * phys birth txg of block allocation; zero if same as logical birth txg
@ -203,8 +204,8 @@ typedef struct blkptr {
#define BP_SET_LSIZE(bp, x) \ #define BP_SET_LSIZE(bp, x) \
BF64_SET_SB((bp)->blk_prop, 0, 16, SPA_MINBLOCKSHIFT, 1, x) BF64_SET_SB((bp)->blk_prop, 0, 16, SPA_MINBLOCKSHIFT, 1, x)
#define BP_GET_COMPRESS(bp) BF64_GET((bp)->blk_prop, 32, 8) #define BP_GET_COMPRESS(bp) BF64_GET((bp)->blk_prop, 32, 7)
#define BP_SET_COMPRESS(bp, x) BF64_SET((bp)->blk_prop, 32, 8, x) #define BP_SET_COMPRESS(bp, x) BF64_SET((bp)->blk_prop, 32, 7, x)
#define BP_GET_CHECKSUM(bp) BF64_GET((bp)->blk_prop, 40, 8) #define BP_GET_CHECKSUM(bp) BF64_GET((bp)->blk_prop, 40, 8)
#define BP_SET_CHECKSUM(bp, x) BF64_SET((bp)->blk_prop, 40, 8, x) #define BP_SET_CHECKSUM(bp, x) BF64_SET((bp)->blk_prop, 40, 8, x)
@ -215,6 +216,8 @@ typedef struct blkptr {
#define BP_GET_LEVEL(bp) BF64_GET((bp)->blk_prop, 56, 5) #define BP_GET_LEVEL(bp) BF64_GET((bp)->blk_prop, 56, 5)
#define BP_SET_LEVEL(bp, x) BF64_SET((bp)->blk_prop, 56, 5, x) #define BP_SET_LEVEL(bp, x) BF64_SET((bp)->blk_prop, 56, 5, x)
#define BP_IS_EMBEDDED(bp) BF64_GET((bp)->blk_prop, 39, 1)
#define BP_GET_PROP_BIT_61(bp) BF64_GET((bp)->blk_prop, 61, 1) #define BP_GET_PROP_BIT_61(bp) BF64_GET((bp)->blk_prop, 61, 1)
#define BP_SET_PROP_BIT_61(bp, x) BF64_SET((bp)->blk_prop, 61, 1, x) #define BP_SET_PROP_BIT_61(bp, x) BF64_SET((bp)->blk_prop, 61, 1, x)
@ -277,9 +280,27 @@ typedef struct blkptr {
(zcp)->zc_word[3] = w3; \ (zcp)->zc_word[3] = w3; \
} }
#define BPE_GET_ETYPE(bp) BP_GET_CHECKSUM(bp)
#define BPE_GET_LSIZE(bp) \
BF64_GET_SB((bp)->blk_prop, 0, 25, 0, 1)
#define BPE_GET_PSIZE(bp) \
BF64_GET_SB((bp)->blk_prop, 25, 7, 0, 1)
typedef enum bp_embedded_type {
BP_EMBEDDED_TYPE_DATA,
NUM_BP_EMBEDDED_TYPES
} bp_embedded_type_t;
#define BPE_NUM_WORDS 14
#define BPE_PAYLOAD_SIZE (BPE_NUM_WORDS * sizeof(grub_uint64_t))
#define BPE_IS_PAYLOADWORD(bp, wp) \
((wp) != &(bp)->blk_prop && (wp) != &(bp)->blk_birth)
#define BP_IDENTITY(bp) (&(bp)->blk_dva[0]) #define BP_IDENTITY(bp) (&(bp)->blk_dva[0])
#define BP_IS_GANG(bp) DVA_GET_GANG(BP_IDENTITY(bp)) #define BP_IS_GANG(bp) DVA_GET_GANG(BP_IDENTITY(bp))
#define BP_IS_HOLE(bp) ((bp)->blk_birth == 0) #define DVA_IS_EMPTY(dva) ((dva)->dva_word[0] == 0ULL && \
(dva)->dva_word[1] == 0ULL)
#define BP_IS_HOLE(bp) DVA_IS_EMPTY(BP_IDENTITY(bp))
/* BP_IS_RAIDZ(bp) assumes no block compression */ /* BP_IS_RAIDZ(bp) assumes no block compression */
#define BP_IS_RAIDZ(bp) (DVA_GET_ASIZE(&(bp)->blk_dva[0]) > \ #define BP_IS_RAIDZ(bp) (DVA_GET_ASIZE(&(bp)->blk_dva[0]) > \

View file

@ -156,9 +156,6 @@ struct multiboot_header_tag_module_align
multiboot_uint16_t type; multiboot_uint16_t type;
multiboot_uint16_t flags; multiboot_uint16_t flags;
multiboot_uint32_t size; multiboot_uint32_t size;
multiboot_uint32_t width;
multiboot_uint32_t height;
multiboot_uint32_t depth;
}; };
struct multiboot_color struct multiboot_color

Binary file not shown.

View file

@ -40,6 +40,10 @@ case x"$fs" in
MINLOGSECSIZE=9 MINLOGSECSIZE=9
# OS LIMITATION: GNU/Linux doesn't accept > 4096 # OS LIMITATION: GNU/Linux doesn't accept > 4096
MAXLOGSECSIZE=12;; MAXLOGSECSIZE=12;;
xxfs_crc)
MINLOGSECSIZE=9
# OS LIMITATION: GNU/Linux doesn't accept > 1024
MAXLOGSECSIZE=10;;
xzfs*) xzfs*)
# OS LIMITATION: zfs-fuse hangs when creating zpool with sectors <=256B. # OS LIMITATION: zfs-fuse hangs when creating zpool with sectors <=256B.
MINLOGSECSIZE=9 MINLOGSECSIZE=9
@ -142,6 +146,10 @@ for ((LOGSECSIZE=MINLOGSECSIZE;LOGSECSIZE<=MAXLOGSECSIZE;LOGSECSIZE=LOGSECSIZE +
MINBLKSIZE=$SECSIZE MINBLKSIZE=$SECSIZE
# OS Limitation: GNU/Linux doesn't accept > 4096 # OS Limitation: GNU/Linux doesn't accept > 4096
MAXBLKSIZE=4096;; MAXBLKSIZE=4096;;
xxfs_crc)
# OS Limitation: GNU/Linux doesn't accept != 1024
MINBLKSIZE=1024
MAXBLKSIZE=1024;;
xudf) xudf)
MINBLKSIZE=1024 MINBLKSIZE=1024
MAXBLKSIZE=4096;; MAXBLKSIZE=4096;;
@ -289,7 +297,7 @@ for ((LOGSECSIZE=MINLOGSECSIZE;LOGSECSIZE<=MAXLOGSECSIZE;LOGSECSIZE=LOGSECSIZE +
x"ufs1" | x"ufs1_sun" | x"ufs2") x"ufs1" | x"ufs1_sun" | x"ufs2")
FSLABEL="grubtest""ieurrucnenreeiurueurewf";; FSLABEL="grubtest""ieurrucnenreeiurueurewf";;
# FS LIMITATION: XFS label is at most 12 UTF-8 characters # FS LIMITATION: XFS label is at most 12 UTF-8 characters
x"xfs") x"xfs"|x"xfs_crc")
FSLABEL="géт 😁к";; FSLABEL="géт 😁к";;
# FS LIMITATION: FAT labels limited to 11 characters, no international characters or lowercase # FS LIMITATION: FAT labels limited to 11 characters, no international characters or lowercase
x"vfat"* | xmsdos*) x"vfat"* | xmsdos*)
@ -467,7 +475,7 @@ for ((LOGSECSIZE=MINLOGSECSIZE;LOGSECSIZE<=MAXLOGSECSIZE;LOGSECSIZE=LOGSECSIZE +
case x"$fs" in case x"$fs" in
# FIXME: Not sure about BtrFS, NTFS, JFS, AFS, UDF and SFS. Check it. # FIXME: Not sure about BtrFS, NTFS, JFS, AFS, UDF and SFS. Check it.
# FS LIMITATION: as far as I know those FS don't store their last modification date. # FS LIMITATION: as far as I know those FS don't store their last modification date.
x"jfs_caseins" | x"jfs" | x"xfs"| x"btrfs"* | x"reiserfs_old" | x"reiserfs" \ x"jfs_caseins" | x"jfs" | x"xfs" | x"xfs_crc" | x"btrfs"* | x"reiserfs_old" | x"reiserfs" \
| x"bfs" | x"afs" \ | x"bfs" | x"afs" \
| x"tarfs" | x"cpio_"* | x"minix" | x"minix2" \ | x"tarfs" | x"cpio_"* | x"minix" | x"minix2" \
| x"minix3" | x"ntfs"* | x"udf" | x"sfs"*) | x"minix3" | x"ntfs"* | x"udf" | x"sfs"*)
@ -760,7 +768,10 @@ for ((LOGSECSIZE=MINLOGSECSIZE;LOGSECSIZE<=MAXLOGSECSIZE;LOGSECSIZE=LOGSECSIZE +
xext*) xext*)
MKE2FS_DEVICE_SECTSIZE=$SECSIZE "mkfs.$fs" -b $BLKSIZE -L "$FSLABEL" -q "${LODEVICES[0]}" ;; MKE2FS_DEVICE_SECTSIZE=$SECSIZE "mkfs.$fs" -b $BLKSIZE -L "$FSLABEL" -q "${LODEVICES[0]}" ;;
xxfs) xxfs)
"mkfs.xfs" -b size=$BLKSIZE -s size=$SECSIZE -L "$FSLABEL" -q "${LODEVICES[0]}" ;; "mkfs.xfs" -m crc=0 -b size=$BLKSIZE -s size=$SECSIZE -L "$FSLABEL" -q "${LODEVICES[0]}" ;;
xxfs_crc)
MOUNTFS="xfs"
"mkfs.xfs" -m crc=1 -b size=$BLKSIZE -s size=$SECSIZE -L "$FSLABEL" -q "${LODEVICES[0]}" ;;
*) *)
echo "Add appropriate mkfs command here" echo "Add appropriate mkfs command here"
exit 1 exit 1
@ -1123,6 +1134,37 @@ for ((LOGSECSIZE=MINLOGSECSIZE;LOGSECSIZE<=MAXLOGSECSIZE;LOGSECSIZE=LOGSECSIZE +
fi fi
fi fi
case x"$fs" in
x"zfs"*)
LSROUT=$(run_grubfstest ls -- -la "($GRUBDEVICE)/grub fs@/.");;
*)
LSROUT=$(run_grubfstest ls -- -la "($GRUBDEVICE)/.");;
esac
if echo "$LSROUT" | grep -F " $BASEFILE" | grep "$BLOCKCNT" > /dev/null; then
:
else
echo DOT IN ROOTDIR FAIL
echo "$LSROUT"
TZ=UTC ls --time-style=+%Y%m%d%H%M%S.%N -l "$MNTPOINTRO"
exit 1
fi
case x"$fs" in
x"zfs"*)
;;
*)
LSROUT=$(run_grubfstest ls -- -la "($GRUBDEVICE)/..");
if echo "$LSROUT" | grep -F " $BASEFILE" | grep "$BLOCKCNT" > /dev/null; then
:
else
echo DOTDOT IN ROOTDIR FAIL
echo "$LSROUT"
TZ=UTC ls --time-style=+%Y%m%d%H%M%S.%N -l "$MNTPOINTRO"
exit 1
fi
;;
esac
case x"$fs" in case x"$fs" in
x"zfs"*) x"zfs"*)
LSROUT=$(run_grubfstest ls -- -l "($GRUBDEVICE)/grub fs@/////sdir");; LSROUT=$(run_grubfstest ls -- -l "($GRUBDEVICE)/grub fs@/////sdir");;
@ -1153,6 +1195,36 @@ for ((LOGSECSIZE=MINLOGSECSIZE;LOGSECSIZE<=MAXLOGSECSIZE;LOGSECSIZE=LOGSECSIZE +
exit 1 exit 1
fi fi
case x"$fs" in
x"zfs"*)
LSROUT=$(run_grubfstest ls -- -l "($GRUBDEVICE)/grub fs@/sdir/.");;
*)
LSROUT=$(run_grubfstest ls -- -l "($GRUBDEVICE)/sdir/.");;
esac
if echo "$LSROUT" | grep -F " 2.img" | grep $BLOCKCNT > /dev/null; then
:
else
echo DOT IN SUBDIR FAIL
echo "$LSROUT"
TZ=UTC ls --time-style=+%Y%m%d%H%M%S.%N -l "$MNTPOINTRO/$OSDIR/sdir"
exit 1
fi
case x"$fs" in
x"zfs"*)
LSROUT=$(run_grubfstest ls -- -l "($GRUBDEVICE)/grub fs@/sdir/../sdir");;
*)
LSROUT=$(run_grubfstest ls -- -l "($GRUBDEVICE)/sdir/../sdir");;
esac
if echo "$LSROUT" | grep -F " 2.img" | grep $BLOCKCNT > /dev/null; then
:
else
echo DOTDOT IN SUBDIR FAIL
echo "$LSROUT"
TZ=UTC ls --time-style=+%Y%m%d%H%M%S.%N -l "$MNTPOINTRO/$OSDIR/ssdir"
exit 1
fi
LSOUT=`run_grubfstest ls -- -l "($GRUBDEVICE)"` LSOUT=`run_grubfstest ls -- -l "($GRUBDEVICE)"`
if [ x"$NOFSLABEL" = xy ]; then if [ x"$NOFSLABEL" = xy ]; then
: :

View file

@ -16,4 +16,5 @@ if ! which mkfs.xfs >/dev/null 2>&1; then
fi fi
"@builddir@/grub-fs-tester" xfs_crc
"@builddir@/grub-fs-tester" xfs "@builddir@/grub-fs-tester" xfs

View file

@ -494,7 +494,7 @@ grub_install_make_image_wrap_file (const char *dir, const char *prefix,
tgt = grub_install_get_image_target (mkimage_target); tgt = grub_install_get_image_target (mkimage_target);
if (!tgt) if (!tgt)
grub_util_error (_("unknown target format %s\n"), mkimage_target); grub_util_error (_("unknown target format %s"), mkimage_target);
grub_install_generate_image (dir, prefix, fp, outname, grub_install_generate_image (dir, prefix, fp, outname,
modules.entries, memdisk_path, modules.entries, memdisk_path,
@ -902,7 +902,7 @@ grub_install_get_target (const char *src)
{ {
char *fn; char *fn;
grub_util_fd_t f; grub_util_fd_t f;
char buf[2048]; char buf[8192];
ssize_t r; ssize_t r;
char *c, *pl, *p; char *c, *pl, *p;
size_t i; size_t i;

View file

@ -773,7 +773,7 @@ bless (grub_device_t dev, const char *path, int x86)
err = grub_mac_bless_inode (dev, st.st_ino, S_ISDIR (st.st_mode), x86); err = grub_mac_bless_inode (dev, st.st_ino, S_ISDIR (st.st_mode), x86);
if (err) if (err)
grub_util_error ("%s", grub_errmsg); grub_util_error ("%s", grub_errmsg);
grub_util_info ("blessed\n"); grub_util_info ("blessed");
} }
static void static void
@ -1070,7 +1070,7 @@ main (int argc, char *argv[])
efidir_is_mac = 1; efidir_is_mac = 1;
if (!efidir_is_mac && grub_strcmp (fs->name, "fat") != 0) if (!efidir_is_mac && grub_strcmp (fs->name, "fat") != 0)
grub_util_error (_("%s doesn't look like an EFI partition.\n"), efidir); grub_util_error (_("%s doesn't look like an EFI partition"), efidir);
/* The EFI specification requires that an EFI System Partition must /* The EFI specification requires that an EFI System Partition must
contain an "EFI" subdirectory, and that OS loaders are stored in contain an "EFI" subdirectory, and that OS loaders are stored in
@ -1271,7 +1271,7 @@ main (int argc, char *argv[])
if (!config.is_cryptodisk_enabled && have_cryptodisk) if (!config.is_cryptodisk_enabled && have_cryptodisk)
grub_util_error (_("attempt to install to encrypted disk without cryptodisk enabled. " grub_util_error (_("attempt to install to encrypted disk without cryptodisk enabled. "
"Set `%s' in file `%s'."), "GRUB_ENABLE_CRYPTODISK=y", "Set `%s' in file `%s'"), "GRUB_ENABLE_CRYPTODISK=y",
grub_util_get_config_filename ()); grub_util_get_config_filename ());
if (disk_module && grub_strcmp (disk_module, "ata") == 0) if (disk_module && grub_strcmp (disk_module, "ata") == 0)
@ -1727,7 +1727,7 @@ main (int argc, char *argv[])
grub_elf = grub_util_path_concat (2, core_services, "grub.elf"); grub_elf = grub_util_path_concat (2, core_services, "grub.elf");
grub_install_copy_file (imgfile, grub_elf, 1); grub_install_copy_file (imgfile, grub_elf, 1);
f = grub_util_fopen (mach_kernel, "r+"); f = grub_util_fopen (mach_kernel, "a+");
if (!f) if (!f)
grub_util_error (_("Can't create file: %s"), strerror (errno)); grub_util_error (_("Can't create file: %s"), strerror (errno));
fclose (f); fclose (f);

View file

@ -140,7 +140,7 @@ process_input_dir (const char *input_dir, enum grub_install_plat platform)
prefix = xasprintf ("/%s", subdir); prefix = xasprintf ("/%s", subdir);
if (!targets[platform].mkimage_target) if (!targets[platform].mkimage_target)
grub_util_error (_("unsupported platform %s\n"), platsub); grub_util_error (_("unsupported platform %s"), platsub);
grub_cfg = grub_util_path_concat (2, grubdir, "grub.cfg"); grub_cfg = grub_util_path_concat (2, grubdir, "grub.cfg");
cfg = grub_util_fopen (grub_cfg, "wb"); cfg = grub_util_fopen (grub_cfg, "wb");

View file

@ -451,6 +451,12 @@ main (int argc, char *argv[])
int i; int i;
for (i = 1; i < argc; i++) for (i = 1; i < argc; i++)
{ {
if (strcmp (argv[i], "-output") == 0) {
argp_argv[argp_argc++] = (char *) "--output";
i++;
argp_argv[argp_argc++] = argv[i];
continue;
}
switch (args_to_eat (argv[i])) switch (args_to_eat (argv[i]))
{ {
case 2: case 2:

View file

@ -279,7 +279,7 @@ write_reloc_section (FILE* fp, const char *name, char *image,
break; break;
#endif #endif
default: default:
grub_util_error ("unknown pe relocation type %d\n", pe_rel->type); grub_util_error ("unknown pe relocation type %d", pe_rel->type);
} }
if (type == if (type ==

View file

@ -429,7 +429,7 @@ probe (const char *path, char **device_names, char delim)
if (print == PRINT_HINT_STR) if (print == PRINT_HINT_STR)
{ {
const char *osdev = grub_util_biosdisk_get_osdev (dev->disk); const char *osdev = grub_util_biosdisk_get_osdev (dev->disk);
const char *ofpath = osdev ? grub_util_devname_to_ofpath (osdev) : 0; char *ofpath = osdev ? grub_util_devname_to_ofpath (osdev) : 0;
char *biosname, *bare, *efi; char *biosname, *bare, *efi;
const char *map; const char *map;
@ -443,6 +443,7 @@ probe (const char *path, char **device_names, char delim)
grub_util_fprint_full_disk_name (stdout, tmp, dev); grub_util_fprint_full_disk_name (stdout, tmp, dev);
printf ("' "); printf ("' ");
free (tmp); free (tmp);
free (ofpath);
} }
biosname = grub_util_guess_bios_drive (*curdev); biosname = grub_util_guess_bios_drive (*curdev);
@ -485,23 +486,18 @@ probe (const char *path, char **device_names, char delim)
printf (" "); printf (" ");
else else
printf ("\n"); printf ("\n");
grub_device_close (dev);
continue;
} }
if ((print == PRINT_COMPATIBILITY_HINT || print == PRINT_BIOS_HINT else if ((print == PRINT_COMPATIBILITY_HINT || print == PRINT_BIOS_HINT
|| print == PRINT_IEEE1275_HINT || print == PRINT_BAREMETAL_HINT || print == PRINT_IEEE1275_HINT || print == PRINT_BAREMETAL_HINT
|| print == PRINT_EFI_HINT || print == PRINT_ARC_HINT) || print == PRINT_EFI_HINT || print == PRINT_ARC_HINT)
&& dev->disk->dev->id != GRUB_DISK_DEVICE_HOSTDISK_ID) && dev->disk->dev->id != GRUB_DISK_DEVICE_HOSTDISK_ID)
{ {
grub_util_fprint_full_disk_name (stdout, dev->disk->name, dev); grub_util_fprint_full_disk_name (stdout, dev->disk->name, dev);
putchar (delim); putchar (delim);
grub_device_close (dev);
continue;
} }
if (print == PRINT_COMPATIBILITY_HINT) else if (print == PRINT_COMPATIBILITY_HINT)
{ {
const char *map; const char *map;
char *biosname; char *biosname;
@ -519,16 +515,14 @@ probe (const char *path, char **device_names, char delim)
{ {
grub_util_fprint_full_disk_name (stdout, biosname, dev); grub_util_fprint_full_disk_name (stdout, biosname, dev);
putchar (delim); putchar (delim);
}
free (biosname); free (biosname);
grub_device_close (dev);
/* Compatibility hint is one device only. */ /* Compatibility hint is one device only. */
if (biosname) grub_device_close (dev);
break; break;
continue; }
} }
if (print == PRINT_BIOS_HINT) else if (print == PRINT_BIOS_HINT)
{ {
char *biosname; char *biosname;
biosname = grub_util_guess_bios_drive (*curdev); biosname = grub_util_guess_bios_drive (*curdev);
@ -536,12 +530,10 @@ probe (const char *path, char **device_names, char delim)
{ {
grub_util_fprint_full_disk_name (stdout, biosname, dev); grub_util_fprint_full_disk_name (stdout, biosname, dev);
putchar (delim); putchar (delim);
}
free (biosname); free (biosname);
grub_device_close (dev);
continue;
} }
if (print == PRINT_IEEE1275_HINT) }
else if (print == PRINT_IEEE1275_HINT)
{ {
const char *osdev = grub_util_biosdisk_get_osdev (dev->disk); const char *osdev = grub_util_biosdisk_get_osdev (dev->disk);
char *ofpath = grub_util_devname_to_ofpath (osdev); char *ofpath = grub_util_devname_to_ofpath (osdev);
@ -565,11 +557,8 @@ probe (const char *path, char **device_names, char delim)
free (ofpath); free (ofpath);
putchar (delim); putchar (delim);
} }
grub_device_close (dev);
continue;
} }
if (print == PRINT_EFI_HINT) else if (print == PRINT_EFI_HINT)
{ {
char *biosname; char *biosname;
const char *map; const char *map;
@ -585,14 +574,11 @@ probe (const char *path, char **device_names, char delim)
{ {
grub_util_fprint_full_disk_name (stdout, biosname, dev); grub_util_fprint_full_disk_name (stdout, biosname, dev);
putchar (delim); putchar (delim);
}
free (biosname); free (biosname);
grub_device_close (dev); }
continue;
} }
if (print == PRINT_BAREMETAL_HINT) else if (print == PRINT_BAREMETAL_HINT)
{ {
char *biosname; char *biosname;
const char *map; const char *map;
@ -609,14 +595,11 @@ probe (const char *path, char **device_names, char delim)
{ {
grub_util_fprint_full_disk_name (stdout, biosname, dev); grub_util_fprint_full_disk_name (stdout, biosname, dev);
putchar (delim); putchar (delim);
}
free (biosname); free (biosname);
grub_device_close (dev); }
continue;
} }
if (print == PRINT_ARC_HINT) else if (print == PRINT_ARC_HINT)
{ {
const char *map; const char *map;
@ -626,46 +609,28 @@ probe (const char *path, char **device_names, char delim)
grub_util_fprint_full_disk_name (stdout, map, dev); grub_util_fprint_full_disk_name (stdout, map, dev);
putchar (delim); putchar (delim);
} }
/* FIXME */
grub_device_close (dev);
continue;
} }
if (print == PRINT_ABSTRACTION) else if (print == PRINT_ABSTRACTION)
{
probe_abstraction (dev->disk, delim); probe_abstraction (dev->disk, delim);
grub_device_close (dev);
continue;
}
if (print == PRINT_CRYPTODISK_UUID) else if (print == PRINT_CRYPTODISK_UUID)
{
probe_cryptodisk_uuid (dev->disk, delim); probe_cryptodisk_uuid (dev->disk, delim);
grub_device_close (dev);
continue;
}
if (print == PRINT_PARTMAP) else if (print == PRINT_PARTMAP)
{
/* Check if dev->disk itself is contained in a partmap. */ /* Check if dev->disk itself is contained in a partmap. */
probe_partmap (dev->disk, delim); probe_partmap (dev->disk, delim);
grub_device_close (dev);
continue;
}
if (print == PRINT_MSDOS_PARTTYPE) else if (print == PRINT_MSDOS_PARTTYPE)
{ {
if (dev->disk->partition if (dev->disk->partition
&& strcmp(dev->disk->partition->partmap->name, "msdos") == 0) && strcmp(dev->disk->partition->partmap->name, "msdos") == 0)
printf ("%02x", dev->disk->partition->msdostype); printf ("%02x", dev->disk->partition->msdostype);
putchar (delim); putchar (delim);
grub_device_close (dev);
continue;
} }
if (print == PRINT_GPT_PARTTYPE) else if (print == PRINT_GPT_PARTTYPE)
{ {
if (dev->disk->partition if (dev->disk->partition
&& strcmp (dev->disk->partition->partmap->name, "gpt") == 0) && strcmp (dev->disk->partition->partmap->name, "gpt") == 0)
@ -694,9 +659,9 @@ probe (const char *path, char **device_names, char delim)
dev->disk->partition = p; dev->disk->partition = p;
} }
putchar (delim); putchar (delim);
grub_device_close (dev);
continue;
} }
grub_device_close (dev);
} }
end: end:

View file

@ -823,7 +823,7 @@ compress_kernel (const struct grub_install_image_target_desc *image_target, char
if (image_target->flags & PLATFORM_FLAGS_DECOMPRESSORS if (image_target->flags & PLATFORM_FLAGS_DECOMPRESSORS
&& (comp != GRUB_COMPRESSION_NONE)) && (comp != GRUB_COMPRESSION_NONE))
grub_util_error (_("unknown compression %d\n"), comp); grub_util_error (_("unknown compression %d"), comp);
*core_img = xmalloc (kernel_size); *core_img = xmalloc (kernel_size);
memcpy (*core_img, kernel_img, kernel_size); memcpy (*core_img, kernel_img, kernel_size);
@ -1234,7 +1234,7 @@ grub_install_generate_image (const char *dir, const char *prefix,
name = "none_decompress.img"; name = "none_decompress.img";
break; break;
default: default:
grub_util_error (_("unknown compression %d\n"), comp); grub_util_error (_("unknown compression %d"), comp);
} }
decompress_path = grub_util_get_path (dir, name); decompress_path = grub_util_get_path (dir, name);