mirror of
https://git.savannah.gnu.org/git/grub.git
synced 2026-10-21 06:49:35 +00:00
Merge branch 'master' into andrey/ext4_inline_data
Conflicts: grub-core/fs/ext2.c
This commit is contained in:
commit
e897f83635
527 files changed
+21786
-6418
No files matched your search
+36
-21
@@ -26,20 +26,26 @@ CFLAGS_LIBRARY += $(CFLAGS_PLATFORM) -fno-builtin
|
||||
CPPFLAGS_LIBRARY += $(CPPFLAGS_PLATFORM)
|
||||
CCASFLAGS_LIBRARY += $(CCASFLAGS_PLATFORM)
|
||||
|
||||
build-grub-pep2elf: $(top_srcdir)/util/grub-pe2elf.c $(top_srcdir)/grub-core/kern/emu/misc.c $(top_srcdir)/util/misc.c
|
||||
$(BUILD_CC) -o $@ -I$(top_srcdir)/include $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) -DGRUB_BUILD=1 -DGRUB_TARGET_WORDSIZE=64 -DGRUB_UTIL=1 -DGRUB_BUILD_PROGRAM_NAME=\"build-grub-pep2elf\" $^
|
||||
build-grub-pep2elf$(BUILD_EXEEXT): $(top_srcdir)/util/grub-pe2elf.c $(top_srcdir)/grub-core/kern/emu/misc.c $(top_srcdir)/util/misc.c
|
||||
$(BUILD_CC) -o $@ -I$(top_srcdir)/include $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) $(BUILD_LDFLAGS) -DGRUB_BUILD=1 -DGRUB_TARGET_WORDSIZE=64 -DGRUB_UTIL=1 -DGRUB_BUILD_PROGRAM_NAME=\"build-grub-pep2elf\" $^
|
||||
CLEANFILES += build-grub-pep2elf$(BUILD_EXEEXT)
|
||||
|
||||
build-grub-pe2elf: $(top_srcdir)/util/grub-pe2elf.c $(top_srcdir)/grub-core/kern/emu/misc.c $(top_srcdir)/util/misc.c
|
||||
$(BUILD_CC) -o $@ -I$(top_srcdir)/include $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) -DGRUB_BUILD=1 -DGRUB_TARGET_WORDSIZE=32 -DGRUB_UTIL=1 -DGRUB_BUILD_PROGRAM_NAME=\"build-grub-pe2elf\" $^
|
||||
build-grub-pe2elf$(BUILD_EXEEXT): $(top_srcdir)/util/grub-pe2elf.c $(top_srcdir)/grub-core/kern/emu/misc.c $(top_srcdir)/util/misc.c
|
||||
$(BUILD_CC) -o $@ -I$(top_srcdir)/include $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) $(BUILD_LDFLAGS) -DGRUB_BUILD=1 -DGRUB_TARGET_WORDSIZE=32 -DGRUB_UTIL=1 -DGRUB_BUILD_PROGRAM_NAME=\"build-grub-pe2elf\" $^
|
||||
CLEANFILES += build-grub-pe2elf$(BUILD_EXEEXT)
|
||||
|
||||
# gentrigtables
|
||||
gentrigtables: gentrigtables.c
|
||||
$(BUILD_CC) -o $@ -I$(top_srcdir)/include $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) $< $(BUILD_LIBM)
|
||||
CLEANFILES += gentrigtables
|
||||
gentrigtables$(BUILD_EXEEXT): gentrigtables.c
|
||||
$(BUILD_CC) -o $@ -I$(top_srcdir)/include $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) $(BUILD_LDFLAGS) $< $(BUILD_LIBM)
|
||||
CLEANFILES += gentrigtables$(BUILD_EXEEXT)
|
||||
|
||||
build-grub-module-verifier$(BUILD_EXEEXT): $(top_srcdir)/util/grub-module-verifier.c $(top_srcdir)/util/grub-module-verifier32.c $(top_srcdir)/util/grub-module-verifier64.c $(top_srcdir)/grub-core/kern/emu/misc.c $(top_srcdir)/util/misc.c
|
||||
$(BUILD_CC) -o $@ -I$(top_srcdir)/include $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) $(BUILD_LDFLAGS) -DGRUB_BUILD=1 -DGRUB_UTIL=1 -DGRUB_BUILD_PROGRAM_NAME=\"build-grub-module-verifier\" $^
|
||||
CLEANFILES += build-grub-module-verifier$(BUILD_EXEEXT)
|
||||
|
||||
# trigtables.c
|
||||
trigtables.c: gentrigtables gentrigtables.c $(top_srcdir)/configure.ac
|
||||
./gentrigtables > $@
|
||||
trigtables.c: gentrigtables$(BUILD_EXEEXT) gentrigtables.c $(top_srcdir)/configure.ac
|
||||
./gentrigtables$(BUILD_EXEEXT) > $@
|
||||
CLEANFILES += trigtables.c
|
||||
|
||||
# XXX Use Automake's LEX & YACC support
|
||||
@@ -74,6 +80,11 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i18n.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/kernel.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/list.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/misc.h
|
||||
if COND_emu
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/compiler-rt-emu.h
|
||||
else
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/compiler-rt.h
|
||||
endif
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/mm.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/parser.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/partition.h
|
||||
@@ -81,9 +92,6 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/term.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/time.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/mm_private.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/net.h
|
||||
if !COND_clang
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/libgcc.h
|
||||
endif
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/memory.h
|
||||
|
||||
if COND_i386_pc
|
||||
@@ -97,7 +105,9 @@ if COND_i386_efi
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/efi.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/disk.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/tsc.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/acpi.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/pci.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/pmtimer.h
|
||||
endif
|
||||
|
||||
if COND_i386_coreboot
|
||||
@@ -108,11 +118,12 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/video_fb.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/gfxterm.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/font.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/bufio.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/acpi.h
|
||||
endif
|
||||
|
||||
if COND_i386_multiboot
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/tsc.h
|
||||
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/i386/pc/int.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/acpi.h
|
||||
endif
|
||||
|
||||
if COND_i386_qemu
|
||||
@@ -151,11 +162,14 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/efi.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/disk.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/tsc.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/pci.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/acpi.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/pmtimer.h
|
||||
endif
|
||||
|
||||
if COND_ia64_efi
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/efi.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/disk.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/acpi.h
|
||||
endif
|
||||
|
||||
if COND_mips
|
||||
@@ -222,17 +236,21 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/uboot/uboot.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/uboot/disk.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/lib/arg.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/arm/system.h
|
||||
endif
|
||||
|
||||
if COND_arm_efi
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/arm/efi/loader.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/efi.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/disk.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/arm/system.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/acpi.h
|
||||
endif
|
||||
|
||||
if COND_arm64_efi
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/efi.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/disk.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/acpi.h
|
||||
endif
|
||||
|
||||
if COND_emu
|
||||
@@ -245,9 +263,6 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h
|
||||
if COND_GRUB_EMU_SDL
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/sdl.h
|
||||
endif
|
||||
if COND_GRUB_EMU_USB
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/libusb.h
|
||||
endif
|
||||
if COND_GRUB_EMU_PCI
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/libpciaccess.h
|
||||
endif
|
||||
@@ -291,12 +306,12 @@ grub_emu-grub_emu_init.$(OBJEXT):grub_emu_init.h
|
||||
kern/emu/grub_emu_dyn-main.$(OBJEXT):grub_emu_init.h
|
||||
grub_emu_dyn-grub_emu_init.$(OBJEXT):grub_emu_init.h
|
||||
|
||||
grub_emu_init.h: genemuinitheader.sh $(MOD_FILES)
|
||||
rm -f $@; echo $(MOD_FILES) | sh $(srcdir)/genemuinitheader.sh $(TARGET_NM) > $@
|
||||
grub_emu_init.h: genemuinitheader.sh $(MODULE_FILES)
|
||||
rm -f $@; echo $(MODULE_FILES) | sh $(srcdir)/genemuinitheader.sh $(TARGET_NM) > $@
|
||||
CLEANFILES += grub_emu_init.h
|
||||
|
||||
grub_emu_init.c: grub_emu_init.h genemuinit.sh $(MOD_FILES)
|
||||
rm -f $@; echo $(MOD_FILES) | sh $(srcdir)/genemuinit.sh $(TARGET_NM) > $@
|
||||
grub_emu_init.c: grub_emu_init.h genemuinit.sh $(MODULE_FILES)
|
||||
rm -f $@; echo $(MODULE_FILES) | sh $(srcdir)/genemuinit.sh $(TARGET_NM) > $@
|
||||
CLEANFILES += grub_emu_init.c
|
||||
endif
|
||||
|
||||
@@ -381,7 +396,7 @@ moddep.lst: syminfo.lst genmoddep.awk video.lst
|
||||
platform_DATA += moddep.lst
|
||||
CLEANFILES += config.log syminfo.lst moddep.lst
|
||||
|
||||
$(MOD_FILES): %.mod : genmod.sh moddep.lst %.module$(EXEEXT)
|
||||
$(MOD_FILES): %.mod : genmod.sh moddep.lst %.module$(EXEEXT) build-grub-module-verifier$(BUILD_EXEEXT)
|
||||
TARGET_OBJ2ELF=@TARGET_OBJ2ELF@ sh $^ $@
|
||||
platform_DATA += $(MOD_FILES)
|
||||
platform_DATA += modinfo.sh
|
||||
|
||||
+108
-51
@@ -1,43 +1,43 @@
|
||||
AutoGen definitions Makefile.tpl;
|
||||
|
||||
script = {
|
||||
transform_data = {
|
||||
installdir = noinst;
|
||||
name = gensyminfo.sh;
|
||||
common = gensyminfo.sh.in;
|
||||
};
|
||||
|
||||
script = {
|
||||
transform_data = {
|
||||
installdir = noinst;
|
||||
name = genmod.sh;
|
||||
common = genmod.sh.in;
|
||||
};
|
||||
|
||||
script = {
|
||||
transform_data = {
|
||||
installdir = noinst;
|
||||
name = modinfo.sh;
|
||||
common = modinfo.sh.in;
|
||||
};
|
||||
|
||||
script = {
|
||||
transform_data = {
|
||||
installdir = platform;
|
||||
name = gmodule.pl;
|
||||
common = gmodule.pl.in;
|
||||
};
|
||||
|
||||
script = {
|
||||
transform_data = {
|
||||
installdir = platform;
|
||||
name = gdb_grub;
|
||||
common = gdb_grub.in;
|
||||
};
|
||||
|
||||
script = {
|
||||
transform_data = {
|
||||
installdir = platform;
|
||||
name = grub.chrp;
|
||||
common = boot/powerpc/grub.chrp.in;
|
||||
enable = powerpc_ieee1275;
|
||||
};
|
||||
|
||||
script = {
|
||||
transform_data = {
|
||||
installdir = platform;
|
||||
name = bootinfo.txt;
|
||||
common = boot/powerpc/bootinfo.txt.in;
|
||||
@@ -59,14 +59,11 @@ kernel = {
|
||||
ia64_efi_ldflags = '-Wl,-r,-d';
|
||||
ia64_efi_stripflags = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version';
|
||||
|
||||
x86_64_xen_cppflags = '$(CPPFLAGS_XEN)';
|
||||
i386_xen_cppflags = '$(CPPFLAGS_XEN)';
|
||||
|
||||
arm_efi_ldflags = '-Wl,-r,-d';
|
||||
arm_efi_stripflags = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version';
|
||||
|
||||
arm64_efi_ldflags = '-Wl,-r,-d';
|
||||
arm64_efi_stripflags = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version';
|
||||
arm64_efi_stripflags = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version -R .eh_frame';
|
||||
|
||||
i386_pc_ldflags = '$(TARGET_IMG_LDFLAGS)';
|
||||
i386_pc_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x9000';
|
||||
@@ -83,8 +80,6 @@ kernel = {
|
||||
x86_64_xen_ldflags = '$(TARGET_IMG_LDFLAGS)';
|
||||
x86_64_xen_ldflags = '$(TARGET_IMG_BASE_LDOPT),0';
|
||||
|
||||
ldadd = '$(LDADD_KERNEL)';
|
||||
|
||||
mips_loongson_ldflags = '-Wl,-Ttext,0x80200000';
|
||||
powerpc_ieee1275_ldflags = '-Wl,-Ttext,0x200000';
|
||||
sparc64_ieee1275_ldflags = '-Wl,-Ttext,0x4400';
|
||||
@@ -95,7 +90,7 @@ kernel = {
|
||||
i386_qemu_cppflags = '-DGRUB_BOOT_MACHINE_LINK_ADDR=$(GRUB_BOOT_MACHINE_LINK_ADDR)';
|
||||
emu_cflags = '$(CFLAGS_GNULIB)';
|
||||
emu_cppflags = '$(CPPFLAGS_GNULIB)';
|
||||
arm_uboot_ldflags = '-Wl,-Ttext=0x08000000';
|
||||
arm_uboot_ldflags = '-Wl,-r,-d';
|
||||
arm_uboot_stripflags = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version';
|
||||
|
||||
i386_pc_startup = kern/i386/pc/startup.S;
|
||||
@@ -132,6 +127,7 @@ kernel = {
|
||||
common = kern/rescue_reader.c;
|
||||
common = kern/term.c;
|
||||
|
||||
noemu = kern/compiler-rt.c;
|
||||
noemu = kern/mm.c;
|
||||
noemu = kern/time.c;
|
||||
noemu = kern/generic/millisleep.c;
|
||||
@@ -159,6 +155,8 @@ kernel = {
|
||||
terminfoinkernel = commands/extcmd.c;
|
||||
terminfoinkernel = lib/arg.c;
|
||||
|
||||
softdiv = lib/division.c;
|
||||
|
||||
i386 = kern/i386/dl.c;
|
||||
i386_xen = kern/i386/dl.c;
|
||||
|
||||
@@ -173,8 +171,20 @@ kernel = {
|
||||
efi = kern/efi/init.c;
|
||||
efi = kern/efi/mm.c;
|
||||
efi = term/efi/console.c;
|
||||
efi = kern/acpi.c;
|
||||
efi = kern/efi/acpi.c;
|
||||
i386_coreboot = kern/i386/pc/acpi.c;
|
||||
i386_multiboot = kern/i386/pc/acpi.c;
|
||||
i386_coreboot = kern/acpi.c;
|
||||
i386_multiboot = kern/acpi.c;
|
||||
|
||||
x86 = kern/i386/tsc.c;
|
||||
x86 = kern/i386/tsc_pit.c;
|
||||
i386_efi = kern/i386/efi/tsc.c;
|
||||
x86_64_efi = kern/i386/efi/tsc.c;
|
||||
i386_efi = kern/i386/tsc_pmtimer.c;
|
||||
i386_coreboot = kern/i386/tsc_pmtimer.c;
|
||||
x86_64_efi = kern/i386/tsc_pmtimer.c;
|
||||
|
||||
i386_efi = kern/i386/efi/init.c;
|
||||
i386_efi = bus/pci.c;
|
||||
@@ -186,6 +196,7 @@ kernel = {
|
||||
x86_64_efi = bus/pci.c;
|
||||
|
||||
xen = kern/i386/tsc.c;
|
||||
xen = kern/i386/xen/tsc.c;
|
||||
x86_64_xen = kern/x86_64/xen/hypercall.S;
|
||||
i386_xen = kern/i386/xen/hypercall.S;
|
||||
xen = kern/xen/init.c;
|
||||
@@ -202,7 +213,7 @@ kernel = {
|
||||
arm_efi = kern/arm/efi/init.c;
|
||||
arm_efi = kern/arm/efi/misc.c;
|
||||
|
||||
arm64_efi = kern/arm/efi/init.c;
|
||||
arm64_efi = kern/arm64/efi/init.c;
|
||||
|
||||
i386_pc = kern/i386/pc/init.c;
|
||||
i386_pc = kern/i386/pc/mmap.c;
|
||||
@@ -252,6 +263,7 @@ kernel = {
|
||||
|
||||
powerpc_ieee1275 = kern/powerpc/cache.S;
|
||||
powerpc_ieee1275 = kern/powerpc/dl.c;
|
||||
powerpc_ieee1275 = kern/powerpc/compiler-rt.S;
|
||||
|
||||
sparc64_ieee1275 = kern/sparc64/cache.S;
|
||||
sparc64_ieee1275 = kern/sparc64/dl.c;
|
||||
@@ -263,7 +275,7 @@ kernel = {
|
||||
arm = kern/arm/cache_armv7.S;
|
||||
extra_dist = kern/arm/cache.S;
|
||||
arm = kern/arm/cache.c;
|
||||
arm = kern/arm/misc.S;
|
||||
arm = kern/arm/compiler-rt.S;
|
||||
|
||||
arm64 = kern/arm64/cache.c;
|
||||
arm64 = kern/arm64/cache_flush.S;
|
||||
@@ -441,13 +453,13 @@ image = {
|
||||
common = lib/xzembed/xz_dec_bcj.c;
|
||||
common = lib/xzembed/xz_dec_lzma2.c;
|
||||
common = lib/xzembed/xz_dec_stream.c;
|
||||
common = kern/compiler-rt.c;
|
||||
|
||||
cppflags = '-I$(srcdir)/lib/posix_wrap -I$(srcdir)/lib/xzembed -DGRUB_EMBED_DECOMPRESSOR=1';
|
||||
|
||||
objcopyflags = '-O binary';
|
||||
mips_ldflags = '$(TARGET_LDFLAGS_STATIC_LIBGCC) -Wl,-Ttext,$(TARGET_DECOMPRESSOR_LINK_ADDR)';
|
||||
ldadd = '$(TARGET_LIBGCC)';
|
||||
cflags = '-Wno-unreachable-code $(TARGET_LDFLAGS_STATIC_LIBGCC)';
|
||||
mips_ldflags = '-Wl,-Ttext,$(TARGET_DECOMPRESSOR_LINK_ADDR)';
|
||||
cflags = '-Wno-unreachable-code';
|
||||
enable = mips;
|
||||
};
|
||||
|
||||
@@ -459,9 +471,7 @@ image = {
|
||||
cppflags = '-DGRUB_EMBED_DECOMPRESSOR=1';
|
||||
|
||||
objcopyflags = '-O binary';
|
||||
mips_ldflags = '$(TARGET_LDFLAGS_STATIC_LIBGCC) -Wl,-Ttext,$(TARGET_DECOMPRESSOR_LINK_ADDR)';
|
||||
ldadd = '$(TARGET_LIBGCC)';
|
||||
cflags = '$(TARGET_LDFLAGS_STATIC_LIBGCC)';
|
||||
mips_ldflags = '-Wl,-Ttext,$(TARGET_DECOMPRESSOR_LINK_ADDR)';
|
||||
enable = mips;
|
||||
};
|
||||
|
||||
@@ -479,7 +489,7 @@ image = {
|
||||
name = fwstart;
|
||||
mips_loongson = boot/mips/loongson/fwstart.S;
|
||||
objcopyflags = '-O binary';
|
||||
ldflags = '$(TARGET_LDFLAGS_STATIC_LIBGCC) $(TARGET_LIBGCC) -Wl,-N,-S,-Ttext,0xbfc00000,-Bstatic';
|
||||
ldflags = '-Wl,-N,-S,-Ttext,0xbfc00000,-Bstatic';
|
||||
enable = mips_loongson;
|
||||
};
|
||||
|
||||
@@ -487,7 +497,7 @@ image = {
|
||||
name = fwstart_fuloong2f;
|
||||
mips_loongson = boot/mips/loongson/fuloong2f.S;
|
||||
objcopyflags = '-O binary';
|
||||
ldflags = '$(TARGET_LDFLAGS_STATIC_LIBGCC) $(TARGET_LIBGCC) -Wl,-N,-S,-Ttext,0xbfc00000,-Bstatic';
|
||||
ldflags = '-Wl,-N,-S,-Ttext,0xbfc00000,-Bstatic';
|
||||
enable = mips_loongson;
|
||||
};
|
||||
|
||||
@@ -509,13 +519,6 @@ module = {
|
||||
enable = x86;
|
||||
};
|
||||
|
||||
module = {
|
||||
name = libusb;
|
||||
emu = bus/usb/emu/usb.c;
|
||||
enable = emu;
|
||||
condition = COND_GRUB_EMU_USB;
|
||||
};
|
||||
|
||||
module = {
|
||||
name = lsspd;
|
||||
mips_loongson = commands/mips/loongson/lsspd.c;
|
||||
@@ -530,13 +533,6 @@ module = {
|
||||
enable = usb;
|
||||
};
|
||||
|
||||
module = {
|
||||
name = emuusb;
|
||||
common = bus/usb/usb.c;
|
||||
enable = emu;
|
||||
condition = COND_GRUB_EMU_USB;
|
||||
};
|
||||
|
||||
module = {
|
||||
name = usbserial_common;
|
||||
common = bus/usb/serial/common.c;
|
||||
@@ -618,7 +614,6 @@ module = {
|
||||
module = {
|
||||
name = lsxen;
|
||||
common = commands/xen/lsxen.c;
|
||||
cppflags = '$(CPPFLAGS_XEN)';
|
||||
|
||||
enable = xen;
|
||||
};
|
||||
@@ -683,10 +678,8 @@ module = {
|
||||
name = acpi;
|
||||
|
||||
common = commands/acpi.c;
|
||||
efi = commands/efi/acpi.c;
|
||||
i386_pc = commands/i386/pc/acpi.c;
|
||||
i386_coreboot = commands/i386/pc/acpi.c;
|
||||
i386_multiboot = commands/i386/pc/acpi.c;
|
||||
i386_pc = kern/acpi.c;
|
||||
i386_pc = kern/i386/pc/acpi.c;
|
||||
|
||||
enable = efi;
|
||||
enable = i386_pc;
|
||||
@@ -839,7 +832,6 @@ module = {
|
||||
i386_coreboot = lib/i386/halt.c;
|
||||
i386_qemu = lib/i386/halt.c;
|
||||
xen = lib/xen/halt.c;
|
||||
xen_cppflags = '$(CPPFLAGS_XEN)';
|
||||
efi = lib/efi/halt.c;
|
||||
ieee1275 = lib/ieee1275/halt.c;
|
||||
emu = lib/emu/halt.c;
|
||||
@@ -860,7 +852,6 @@ module = {
|
||||
mips_loongson = lib/mips/loongson/reboot.c;
|
||||
mips_qemu_mips = lib/mips/qemu_mips/reboot.c;
|
||||
xen = lib/xen/reboot.c;
|
||||
xen_cppflags = '$(CPPFLAGS_XEN)';
|
||||
uboot = lib/uboot/reboot.c;
|
||||
common = commands/reboot.c;
|
||||
};
|
||||
@@ -1462,7 +1453,6 @@ module = {
|
||||
module = {
|
||||
name = gfxmenu;
|
||||
common = gfxmenu/gfxmenu.c;
|
||||
common = gfxmenu/model.c;
|
||||
common = gfxmenu/view.c;
|
||||
common = gfxmenu/font.c;
|
||||
common = gfxmenu/icon_manager.c;
|
||||
@@ -1541,7 +1531,6 @@ module = {
|
||||
i386_xen = lib/i386/xen/relocator.S;
|
||||
x86_64_xen = lib/x86_64/xen/relocator.S;
|
||||
xen = lib/i386/relocator_common_c.c;
|
||||
xen_cppflags = '$(CPPFLAGS_XEN)';
|
||||
|
||||
extra_dist = lib/i386/relocator_common.S;
|
||||
extra_dist = kern/powerpc/cache_flush.S;
|
||||
@@ -1562,7 +1551,6 @@ module = {
|
||||
sparc64_ieee1275 = lib/ieee1275/cmos.c;
|
||||
powerpc_ieee1275 = lib/ieee1275/cmos.c;
|
||||
xen = lib/xen/datetime.c;
|
||||
xen_cppflags = '$(CPPFLAGS_XEN)';
|
||||
|
||||
mips_arc = lib/arc/datetime.c;
|
||||
enable = noemu;
|
||||
@@ -1661,30 +1649,68 @@ module = {
|
||||
enable = x86;
|
||||
};
|
||||
|
||||
module = {
|
||||
name = xen_boot;
|
||||
common = lib/cmdline.c;
|
||||
arm64 = loader/arm64/xen_boot.c;
|
||||
enable = arm64;
|
||||
};
|
||||
|
||||
module = {
|
||||
name = linux;
|
||||
x86 = loader/i386/linux.c;
|
||||
xen = loader/i386/xen.c;
|
||||
xen_cppflags = '$(CPPFLAGS_XEN)';
|
||||
i386_pc = lib/i386/pc/vesa_modes_table.c;
|
||||
mips = loader/mips/linux.c;
|
||||
powerpc_ieee1275 = loader/powerpc/ieee1275/linux.c;
|
||||
sparc64_ieee1275 = loader/sparc64/ieee1275/linux.c;
|
||||
ia64_efi = loader/ia64/efi/linux.c;
|
||||
arm = loader/arm/linux.c;
|
||||
arm = lib/fdt.c;
|
||||
arm64 = loader/arm64/linux.c;
|
||||
common = loader/linux.c;
|
||||
common = lib/cmdline.c;
|
||||
enable = noemu;
|
||||
};
|
||||
|
||||
module = {
|
||||
name = fdt;
|
||||
arm64 = loader/arm64/fdt.c;
|
||||
common = lib/fdt.c;
|
||||
enable = fdt;
|
||||
};
|
||||
|
||||
module = {
|
||||
name = xnu;
|
||||
x86 = loader/xnu_resume.c;
|
||||
x86 = loader/i386/xnu.c;
|
||||
x86 = loader/xnu.c;
|
||||
|
||||
enable = x86;
|
||||
/* Code is pretty generic but relies on RNG which
|
||||
is available only on few platforms. It's not a
|
||||
big deal as xnu needs ACPI anyway and we have
|
||||
RNG on all platforms with ACPI.
|
||||
*/
|
||||
enable = i386_multiboot;
|
||||
enable = i386_coreboot;
|
||||
enable = i386_pc;
|
||||
enable = i386_efi;
|
||||
enable = x86_64_efi;
|
||||
};
|
||||
|
||||
module = {
|
||||
name = random;
|
||||
x86 = lib/i386/random.c;
|
||||
common = lib/random.c;
|
||||
|
||||
i386_multiboot = kern/i386/tsc_pmtimer.c;
|
||||
i386_coreboot = kern/i386/tsc_pmtimer.c;
|
||||
i386_pc = kern/i386/tsc_pmtimer.c;
|
||||
|
||||
enable = i386_multiboot;
|
||||
enable = i386_coreboot;
|
||||
enable = i386_pc;
|
||||
enable = i386_efi;
|
||||
enable = x86_64_efi;
|
||||
};
|
||||
|
||||
module = {
|
||||
@@ -1968,11 +1994,42 @@ module = {
|
||||
enable = xen;
|
||||
};
|
||||
|
||||
module = {
|
||||
name = div;
|
||||
common = lib/division.c;
|
||||
enable = no_softdiv;
|
||||
};
|
||||
|
||||
module = {
|
||||
name = div_test;
|
||||
common = tests/div_test.c;
|
||||
};
|
||||
|
||||
module = {
|
||||
name = mul_test;
|
||||
common = tests/mul_test.c;
|
||||
};
|
||||
|
||||
module = {
|
||||
name = shift_test;
|
||||
common = tests/shift_test.c;
|
||||
};
|
||||
|
||||
module = {
|
||||
name = cmp_test;
|
||||
common = tests/cmp_test.c;
|
||||
};
|
||||
|
||||
module = {
|
||||
name = ctz_test;
|
||||
common = tests/ctz_test.c;
|
||||
};
|
||||
|
||||
module = {
|
||||
name = bswap_test;
|
||||
common = tests/bswap_test.c;
|
||||
};
|
||||
|
||||
module = {
|
||||
name = videotest_checksum;
|
||||
common = tests/videotest_checksum.c;
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
#include <grub/decompressor.h>
|
||||
|
||||
void *
|
||||
memset (void *s, int c, grub_size_t len)
|
||||
grub_memset (void *s, int c, grub_size_t len)
|
||||
{
|
||||
grub_uint8_t *ptr;
|
||||
for (ptr = s; len; ptr++, len--)
|
||||
@@ -68,15 +68,6 @@ grub_memcmp (const void *s1, const void *s2, grub_size_t n)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int memcmp (const void *s1, const void *s2, grub_size_t n)
|
||||
__attribute__ ((alias ("grub_memcmp")));
|
||||
|
||||
void *memmove (void *dest, const void *src, grub_size_t n)
|
||||
__attribute__ ((alias ("grub_memmove")));
|
||||
|
||||
void *memcpy (void *dest, const void *src, grub_size_t n)
|
||||
__attribute__ ((alias ("grub_memmove")));
|
||||
|
||||
void *grub_decompressor_scratch;
|
||||
|
||||
void
|
||||
|
||||
@@ -165,8 +165,8 @@ start:
|
||||
* this area.
|
||||
*/
|
||||
|
||||
. = _start + GRUB_BOOT_MACHINE_BPB_START
|
||||
. = _start + 4
|
||||
.org GRUB_BOOT_MACHINE_BPB_START
|
||||
.org 4
|
||||
#endif
|
||||
#ifdef HYBRID_BOOT
|
||||
floppy
|
||||
@@ -174,23 +174,23 @@ start:
|
||||
scratch
|
||||
#endif
|
||||
|
||||
. = _start + GRUB_BOOT_MACHINE_BPB_END
|
||||
.org GRUB_BOOT_MACHINE_BPB_END
|
||||
/*
|
||||
* End of BIOS parameter block.
|
||||
*/
|
||||
|
||||
kernel_address:
|
||||
LOCAL(kernel_address):
|
||||
.word GRUB_BOOT_MACHINE_KERNEL_ADDR
|
||||
|
||||
#ifndef HYBRID_BOOT
|
||||
. = _start + GRUB_BOOT_MACHINE_KERNEL_SECTOR
|
||||
kernel_sector:
|
||||
.org GRUB_BOOT_MACHINE_KERNEL_SECTOR
|
||||
LOCAL(kernel_sector):
|
||||
.long 1
|
||||
kernel_sector_high:
|
||||
LOCAL(kernel_sector_high):
|
||||
.long 0
|
||||
#endif
|
||||
|
||||
. = _start + GRUB_BOOT_MACHINE_BOOT_DRIVE
|
||||
.org GRUB_BOOT_MACHINE_BOOT_DRIVE
|
||||
boot_drive:
|
||||
.byte 0xff /* the disk to load kernel from */
|
||||
/* 0xff means use the boot drive */
|
||||
@@ -208,7 +208,7 @@ LOCAL(after_BPB):
|
||||
* possible boot drive. If GRUB is installed into a floppy,
|
||||
* this does nothing (only jump).
|
||||
*/
|
||||
. = _start + GRUB_BOOT_MACHINE_DRIVE_CHECK
|
||||
.org GRUB_BOOT_MACHINE_DRIVE_CHECK
|
||||
boot_drive_check:
|
||||
jmp 3f /* grub-setup may overwrite this jump */
|
||||
testb $0x80, %dl
|
||||
@@ -275,7 +275,7 @@ real_start:
|
||||
andw $1, %cx
|
||||
jz LOCAL(chs_mode)
|
||||
|
||||
lba_mode:
|
||||
LOCAL(lba_mode):
|
||||
xorw %ax, %ax
|
||||
movw %ax, 4(%si)
|
||||
|
||||
@@ -290,9 +290,9 @@ lba_mode:
|
||||
movw $0x0010, (%si)
|
||||
|
||||
/* the absolute address */
|
||||
movl kernel_sector, %ebx
|
||||
movl LOCAL(kernel_sector), %ebx
|
||||
movl %ebx, 8(%si)
|
||||
movl kernel_sector_high, %ebx
|
||||
movl LOCAL(kernel_sector_high), %ebx
|
||||
movl %ebx, 12(%si)
|
||||
|
||||
/* the segment of buffer address */
|
||||
@@ -361,13 +361,13 @@ LOCAL(final_init):
|
||||
|
||||
setup_sectors:
|
||||
/* load logical sector start (top half) */
|
||||
movl kernel_sector_high, %eax
|
||||
movl LOCAL(kernel_sector_high), %eax
|
||||
|
||||
orl %eax, %eax
|
||||
jnz LOCAL(geometry_error)
|
||||
|
||||
/* load logical sector start (bottom half) */
|
||||
movl kernel_sector, %eax
|
||||
movl LOCAL(kernel_sector), %eax
|
||||
|
||||
/* zero %edx */
|
||||
xorl %edx, %edx
|
||||
@@ -452,7 +452,7 @@ LOCAL(copy_buffer):
|
||||
popa
|
||||
|
||||
/* boot kernel */
|
||||
jmp *(kernel_address)
|
||||
jmp *(LOCAL(kernel_address))
|
||||
|
||||
/* END OF MAIN LOOP */
|
||||
|
||||
@@ -511,13 +511,13 @@ LOCAL(message):
|
||||
*/
|
||||
|
||||
#ifdef HYBRID_BOOT
|
||||
. = _start + 0x1b0
|
||||
kernel_sector:
|
||||
.org 0x1b0
|
||||
LOCAL(kernel_sector):
|
||||
.long 1
|
||||
kernel_sector_high:
|
||||
LOCAL(kernel_sector_high):
|
||||
.long 0
|
||||
#endif
|
||||
. = _start + GRUB_BOOT_MACHINE_WINDOWS_NT_MAGIC
|
||||
.org GRUB_BOOT_MACHINE_WINDOWS_NT_MAGIC
|
||||
nt_magic:
|
||||
.long 0
|
||||
.word 0
|
||||
@@ -528,7 +528,7 @@ nt_magic:
|
||||
* sneaky, huh?
|
||||
*/
|
||||
|
||||
. = _start + GRUB_BOOT_MACHINE_PART_START
|
||||
.org GRUB_BOOT_MACHINE_PART_START
|
||||
|
||||
#ifndef HYBRID_BOOT
|
||||
floppy
|
||||
@@ -536,7 +536,7 @@ nt_magic:
|
||||
scratch
|
||||
#endif
|
||||
|
||||
. = _start + GRUB_BOOT_MACHINE_PART_END
|
||||
.org GRUB_BOOT_MACHINE_PART_END
|
||||
|
||||
/* the last 2 bytes in the sector 0 contain the signature */
|
||||
.word GRUB_BOOT_MACHINE_SIGNATURE
|
||||
@@ -43,7 +43,7 @@ _start:
|
||||
LOCAL(next):
|
||||
jmp 1f
|
||||
|
||||
. = start + 8
|
||||
.org 8
|
||||
|
||||
bi_pvd:
|
||||
.long 0 /* LBA of primary volume descriptor. */
|
||||
@@ -168,6 +168,6 @@ err_noboot_msg:
|
||||
err_cdfail_msg:
|
||||
.ascii "cdrom read fails\0"
|
||||
|
||||
. = start + 0x7FF
|
||||
.org 0x7FF
|
||||
|
||||
.byte 0
|
||||
@@ -362,7 +362,7 @@ LOCAL(message):
|
||||
.word 0
|
||||
.word 0
|
||||
|
||||
. = _start + 0x200 - GRUB_BOOT_MACHINE_LIST_SIZE
|
||||
.org 0x200 - GRUB_BOOT_MACHINE_LIST_SIZE
|
||||
LOCAL(firstlist): /* this label has to be before the first list entry!!! */
|
||||
/* fill the first data listing with the default */
|
||||
blocklist_default_start:
|
||||
|
||||
@@ -41,7 +41,7 @@ data_start:
|
||||
xorl %ebp, %ebp
|
||||
jmp LOCAL(linux_next)
|
||||
|
||||
. = data_start + 0x1F1
|
||||
.org 0x1F1
|
||||
|
||||
setup_sects:
|
||||
.byte CODE_SECTORS
|
||||
@@ -292,4 +292,4 @@ LOCAL(fail):
|
||||
err_int15_msg:
|
||||
.ascii "move memory fails\0"
|
||||
|
||||
. = _start + CODE_SECTORS * 512
|
||||
.org (CODE_SECTORS * 512 + 512)
|
||||
@@ -38,5 +38,5 @@ start:
|
||||
/* This region is a junk. Do you say that this is wasteful?
|
||||
But I like that the memory layout of the body is consistent
|
||||
among different kernels rather than scamping just for 1.5KB. */
|
||||
. = _start + 0x8200 - 0x7C00 - 0x200 - 1
|
||||
.org 0x8200 - 0x7C00 - 0x200 - 1
|
||||
.byte 0
|
||||
@@ -50,23 +50,23 @@ LOCAL (base):
|
||||
* This is a special data area.
|
||||
*/
|
||||
|
||||
. = _start + GRUB_DECOMPRESSOR_MACHINE_COMPRESSED_SIZE
|
||||
.org GRUB_DECOMPRESSOR_MACHINE_COMPRESSED_SIZE
|
||||
LOCAL(compressed_size):
|
||||
.long 0
|
||||
. = _start + GRUB_DECOMPRESSOR_MACHINE_UNCOMPRESSED_SIZE
|
||||
.org GRUB_DECOMPRESSOR_MACHINE_UNCOMPRESSED_SIZE
|
||||
LOCAL(uncompressed_size):
|
||||
.long 0
|
||||
|
||||
. = _start + GRUB_KERNEL_I386_PC_REED_SOLOMON_REDUNDANCY
|
||||
.org GRUB_KERNEL_I386_PC_REED_SOLOMON_REDUNDANCY
|
||||
reed_solomon_redundancy:
|
||||
.long 0
|
||||
. = _start + GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_LENGTH
|
||||
.org GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_LENGTH
|
||||
.short (LOCAL(reed_solomon_part) - _start)
|
||||
|
||||
/*
|
||||
* This is the area for all of the special variables.
|
||||
*/
|
||||
. = _start + GRUB_DECOMPRESSOR_I386_PC_BOOT_DEVICE
|
||||
.org GRUB_DECOMPRESSOR_I386_PC_BOOT_DEVICE
|
||||
LOCAL(boot_dev):
|
||||
.byte 0xFF, 0xFF, 0xFF
|
||||
LOCAL(boot_drive):
|
||||
@@ -89,13 +89,13 @@ LOCAL (codestart):
|
||||
sti /* we're safe again */
|
||||
|
||||
/* save the boot drive */
|
||||
ADDR32 movb %dl, LOCAL(boot_drive)
|
||||
movb %dl, LOCAL(boot_drive)
|
||||
|
||||
/* reset disk system (%ah = 0) */
|
||||
int $0x13
|
||||
|
||||
/* transition to protected mode */
|
||||
DATA32 call real_to_prot
|
||||
calll real_to_prot
|
||||
|
||||
/* The ".code32" directive takes GAS out of 16-bit mode. */
|
||||
.code32
|
||||
@@ -149,7 +149,7 @@ gate_a20_try_bios:
|
||||
movw $0x2401, %ax
|
||||
int $0x15
|
||||
|
||||
DATA32 call real_to_prot
|
||||
calll real_to_prot
|
||||
.code32
|
||||
|
||||
popl %ebp
|
||||
|
||||
@@ -31,7 +31,7 @@ _start:
|
||||
|
||||
jmp 1f
|
||||
|
||||
. = _start + GRUB_BOOT_I386_QEMU_CORE_ENTRY_ADDR
|
||||
.org GRUB_BOOT_I386_QEMU_CORE_ENTRY_ADDR
|
||||
VARIABLE(grub_core_entry_addr)
|
||||
.long 0
|
||||
1:
|
||||
@@ -48,8 +48,9 @@ VARIABLE(grub_core_entry_addr)
|
||||
/* Transition to protected mode. We use pushl to force generation
|
||||
of a flat return address. */
|
||||
pushl $1f
|
||||
DATA32 jmp real_to_prot
|
||||
jmp real_to_prot
|
||||
.code32
|
||||
1:
|
||||
/* Ensure A20 is enabled. We're in qemu, so control port A works
|
||||
and there is no need to wait since there is no real logic, it's
|
||||
all emulated. */
|
||||
@@ -57,7 +58,6 @@ VARIABLE(grub_core_entry_addr)
|
||||
andb $(~0x03), %al
|
||||
orb $0x02, %al
|
||||
outb $0x92
|
||||
1:
|
||||
movl EXT_C(grub_core_entry_addr), %edx
|
||||
jmp *%edx
|
||||
|
||||
@@ -66,9 +66,9 @@ VARIABLE(grub_core_entry_addr)
|
||||
/* Intel, in its infinite wisdom, decided to put the i8086 entry point
|
||||
*right here* and this is why we need this kludge. */
|
||||
|
||||
. = GRUB_BOOT_MACHINE_SIZE - 16
|
||||
.org GRUB_BOOT_MACHINE_SIZE - 16
|
||||
|
||||
.code16
|
||||
|
||||
jmp _start
|
||||
. = GRUB_BOOT_MACHINE_SIZE
|
||||
.org GRUB_BOOT_MACHINE_SIZE
|
||||
@@ -162,7 +162,7 @@ retry_cs5536:
|
||||
|
||||
b continue
|
||||
|
||||
. = start + GRUB_CPU_LOONGSON_FLASH_TLB_REFILL - GRUB_CPU_LOONGSON_FLASH_START
|
||||
.org GRUB_CPU_LOONGSON_FLASH_TLB_REFILL - GRUB_CPU_LOONGSON_FLASH_START
|
||||
tlb_refill:
|
||||
mfc0 $s1, GRUB_CPU_LOONGSON_COP0_EPC
|
||||
mfc0 $s2, GRUB_CPU_LOONGSON_COP0_BADVADDR
|
||||
@@ -196,13 +196,13 @@ tlb_refill:
|
||||
b fatal
|
||||
addiu $a0, $a0, %lo(unhandled_tlb_refill)
|
||||
|
||||
. = start + GRUB_CPU_LOONGSON_FLASH_CACHE_ERROR - GRUB_CPU_LOONGSON_FLASH_START
|
||||
.org GRUB_CPU_LOONGSON_FLASH_CACHE_ERROR - GRUB_CPU_LOONGSON_FLASH_START
|
||||
cache_error:
|
||||
lui $a0, %hi(unhandled_cache_error)
|
||||
b fatal
|
||||
addiu $a0, $a0, %lo(unhandled_cache_error)
|
||||
|
||||
. = start + GRUB_CPU_LOONGSON_FLASH_OTHER_EXCEPTION - GRUB_CPU_LOONGSON_FLASH_START
|
||||
.org GRUB_CPU_LOONGSON_FLASH_OTHER_EXCEPTION - GRUB_CPU_LOONGSON_FLASH_START
|
||||
other_exception:
|
||||
mfc0 $s0, GRUB_CPU_LOONGSON_COP0_CAUSE
|
||||
mfc0 $s1, GRUB_CPU_LOONGSON_COP0_EPC
|
||||
@@ -344,7 +344,7 @@ printhex:
|
||||
nop
|
||||
srl $t1, $a0, 28
|
||||
addiu $t1, $t1, -10
|
||||
blt $t1, $zero, 2f
|
||||
bltz $t1, 2f
|
||||
sll $a0, $a0, 4
|
||||
addiu $t1, $t1, 'A'-10-'0'
|
||||
2: addiu $t1, $t1, '0'+10
|
||||
@@ -398,7 +398,7 @@ read_spd:
|
||||
move $t2, $a0
|
||||
move $t3, $ra
|
||||
lui $a0, %hi(read_spd_fail)
|
||||
addiu $a0, $a0, %hi(read_spd_fail)
|
||||
addiu $a0, $a0, %lo(read_spd_fail)
|
||||
|
||||
/* Send START. */
|
||||
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
|
||||
gpio_dump_end:
|
||||
|
||||
.p2align
|
||||
.p2align 3
|
||||
|
||||
write_dumpreg:
|
||||
ld $t2, 0($t6)
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <grub/machine/memory.h>
|
||||
#include <grub/machine/kernel.h>
|
||||
#include <grub/offsets.h>
|
||||
#include <grub/mips/asm.h>
|
||||
|
||||
#define BASE_ADDR 8
|
||||
|
||||
@@ -39,13 +40,13 @@ start:
|
||||
bal codestart
|
||||
nop
|
||||
base:
|
||||
. = _start + GRUB_DECOMPRESSOR_MACHINE_COMPRESSED_SIZE
|
||||
.org GRUB_DECOMPRESSOR_MACHINE_COMPRESSED_SIZE
|
||||
compressed_size:
|
||||
.long 0
|
||||
. = _start + GRUB_DECOMPRESSOR_MACHINE_UNCOMPRESSED_SIZE
|
||||
.org GRUB_DECOMPRESSOR_MACHINE_UNCOMPRESSED_SIZE
|
||||
uncompressed_size:
|
||||
.long 0
|
||||
. = _start + GRUB_DECOMPRESSOR_MACHINE_UNCOMPRESSED_ADDR
|
||||
.org GRUB_DECOMPRESSOR_MACHINE_UNCOMPRESSED_ADDR
|
||||
uncompressed_addr:
|
||||
.long 0
|
||||
codestart:
|
||||
@@ -118,50 +119,50 @@ parsestr:
|
||||
move $v0, $zero
|
||||
move $t3, $t1
|
||||
3:
|
||||
lb $t4, 0($t2)
|
||||
lb $t5, 0($t3)
|
||||
lb GRUB_ASM_T4, 0($t2)
|
||||
lb GRUB_ASM_T5, 0($t3)
|
||||
addiu $t2, $t2, 1
|
||||
addiu $t3, $t3, 1
|
||||
beq $t5, $zero, 1f
|
||||
beq GRUB_ASM_T5, $zero, 1f
|
||||
nop
|
||||
beq $t5, $t4, 3b
|
||||
beq GRUB_ASM_T5, GRUB_ASM_T4, 3b
|
||||
nop
|
||||
bne $t4, $zero, 1f
|
||||
bne GRUB_ASM_T4, $zero, 1f
|
||||
nop
|
||||
|
||||
addiu $t3, $t3, 0xffff
|
||||
digcont:
|
||||
lb $t5, 0($t3)
|
||||
lb GRUB_ASM_T5, 0($t3)
|
||||
/* Substract '0' from digit. */
|
||||
addiu $t5, $t5, 0xffd0
|
||||
bltz $t5, 1f
|
||||
addiu GRUB_ASM_T5, GRUB_ASM_T5, 0xffd0
|
||||
bltz GRUB_ASM_T5, 1f
|
||||
nop
|
||||
addiu $t4, $t5, 0xfff7
|
||||
bgtz $t4, 1f
|
||||
addiu GRUB_ASM_T4, GRUB_ASM_T5, 0xfff7
|
||||
bgtz GRUB_ASM_T4, 1f
|
||||
nop
|
||||
/* Multiply $v0 by 10 with bitshifts. */
|
||||
sll $v0, $v0, 1
|
||||
sll $t4, $v0, 2
|
||||
addu $v0, $v0, $t4
|
||||
addu $v0, $v0, $t5
|
||||
sll GRUB_ASM_T4, $v0, 2
|
||||
addu $v0, $v0, GRUB_ASM_T4
|
||||
addu $v0, $v0, GRUB_ASM_T5
|
||||
addiu $t3, $t3, 1
|
||||
b digcont
|
||||
nop
|
||||
1:
|
||||
jr $ra
|
||||
nop
|
||||
busclockstr: .asciiz "busclock="
|
||||
cpuclockstr: .asciiz "cpuclock="
|
||||
memsizestr: .asciiz "memsize="
|
||||
highmemsizestr: .asciiz "highmemsize="
|
||||
machtype_yeeloong_str1: .asciiz "machtype=8.9"
|
||||
machtype_yeeloong_str2: .asciiz "machtype=lemote-yeeloong-"
|
||||
machtype_fuloong2f_str: .asciiz "machtype=lemote-fuloong-2f"
|
||||
machtype_fuloong2e_str: .asciiz "machtype=lemote-fuloong-2e"
|
||||
pmon_yeeloong_str: .asciiz "PMON_VER=LM8"
|
||||
pmon_fuloong2f_str: .asciiz "PMON_VER=LM6"
|
||||
pmon_yeeloong_verstr: .asciiz "Version=LM8"
|
||||
pmon_fuloong2f_verstr: .asciiz "Version=LM6"
|
||||
busclockstr: .asciz "busclock="
|
||||
cpuclockstr: .asciz "cpuclock="
|
||||
memsizestr: .asciz "memsize="
|
||||
highmemsizestr: .asciz "highmemsize="
|
||||
machtype_yeeloong_str1: .asciz "machtype=8.9"
|
||||
machtype_yeeloong_str2: .asciz "machtype=lemote-yeeloong-"
|
||||
machtype_fuloong2f_str: .asciz "machtype=lemote-fuloong-2f"
|
||||
machtype_fuloong2e_str: .asciz "machtype=lemote-fuloong-2e"
|
||||
pmon_yeeloong_str: .asciz "PMON_VER=LM8"
|
||||
pmon_fuloong2f_str: .asciz "PMON_VER=LM6"
|
||||
pmon_yeeloong_verstr: .asciz "Version=LM8"
|
||||
pmon_fuloong2f_verstr: .asciz "Version=LM6"
|
||||
.p2align 2
|
||||
|
||||
argdone:
|
||||
@@ -182,10 +183,10 @@ argdone:
|
||||
b argdone
|
||||
addiu $a1, $a1, 4
|
||||
do_check:
|
||||
lb $t4, 0($t7)
|
||||
beq $t4, $zero, 1f
|
||||
lb GRUB_ASM_T4, 0($t7)
|
||||
beq GRUB_ASM_T4, $zero, 1f
|
||||
lb $t3, 0($t6)
|
||||
bne $t3, $t4, 2f
|
||||
bne $t3, GRUB_ASM_T4, 2f
|
||||
addiu $t6, $t6, 1
|
||||
b do_check
|
||||
addiu $t7, $t7, 1
|
||||
@@ -222,8 +223,8 @@ cmdlinedone:
|
||||
|
||||
1:
|
||||
beq $t1, $t3, 2f
|
||||
lb $t4, 0($t2)
|
||||
sb $t4, 0($t1)
|
||||
lb GRUB_ASM_T4, 0($t2)
|
||||
sb GRUB_ASM_T4, 0($t1)
|
||||
addiu $t1, $t1, 1
|
||||
b 1b
|
||||
addiu $t2, $t2, 1
|
||||
|
||||
@@ -41,18 +41,18 @@ pic_base:
|
||||
* After loading in that block we will execute it by jumping to the
|
||||
* load address plus the size of the prepended A.OUT header (32 bytes).
|
||||
*/
|
||||
. = _start + GRUB_BOOT_MACHINE_BOOT_DEVPATH
|
||||
.org GRUB_BOOT_MACHINE_BOOT_DEVPATH
|
||||
boot_path:
|
||||
. = _start + GRUB_BOOT_MACHINE_KERNEL_BYTE
|
||||
kernel_byte: .xword (2 << 9)
|
||||
.org GRUB_BOOT_MACHINE_KERNEL_BYTE
|
||||
boot_path_end:
|
||||
kernel_byte: .xword (2 << 9)
|
||||
kernel_address: .word GRUB_BOOT_MACHINE_KERNEL_ADDR
|
||||
#else
|
||||
#define boot_path (_start + 512 + SCRATCH_PAD_BOOT_SIZE)
|
||||
#define boot_path_end (_start + 1024)
|
||||
#include <grub/offsets.h>
|
||||
|
||||
. = _start + 8
|
||||
.org 8
|
||||
kernel_byte: .xword (2 << 9)
|
||||
kernel_size: .word 512
|
||||
kernel_address: .word GRUB_BOOT_SPARC64_IEEE1275_IMAGE_ADDRESS
|
||||
@@ -224,7 +224,7 @@ bootpath_known:
|
||||
#else
|
||||
nop
|
||||
#endif
|
||||
. = _start + GRUB_BOOT_MACHINE_CODE_END
|
||||
.org GRUB_BOOT_MACHINE_CODE_END
|
||||
|
||||
/* the last 4 bytes in the sector 0 contain the signature */
|
||||
.word GRUB_BOOT_MACHINE_SIGNATURE
|
||||
@@ -136,7 +136,7 @@ lastlist:
|
||||
.word 0
|
||||
.word 0
|
||||
|
||||
. = _start + (0x200 - GRUB_BOOT_SPARC64_IEEE1275_LIST_SIZE)
|
||||
.org (0x200 - GRUB_BOOT_SPARC64_IEEE1275_LIST_SIZE)
|
||||
blocklist_default_start:
|
||||
.word 0
|
||||
.word 2
|
||||
|
||||
@@ -55,7 +55,8 @@ grub_pci_device_map_range (grub_pci_device_t dev, grub_addr_t base,
|
||||
int err;
|
||||
err = pci_device_map_range (dev, base, size, PCI_DEV_MAP_FLAG_WRITABLE, &addr);
|
||||
if (err)
|
||||
grub_util_error ("mapping 0x%x failed (error %d)\n", base, err);
|
||||
grub_util_error ("mapping 0x%llx failed (error %d)",
|
||||
(unsigned long long) base, err);
|
||||
return addr;
|
||||
}
|
||||
|
||||
@@ -66,12 +67,12 @@ grub_pci_device_unmap_range (grub_pci_device_t dev, void *mem,
|
||||
pci_device_unmap_range (dev, mem, size);
|
||||
}
|
||||
|
||||
GRUB_MOD_INIT (pci)
|
||||
GRUB_MOD_INIT (emupci)
|
||||
{
|
||||
pci_system_init ();
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI (pci)
|
||||
GRUB_MOD_FINI (emupci)
|
||||
{
|
||||
pci_system_cleanup ();
|
||||
}
|
||||
+82
-33
@@ -29,6 +29,7 @@
|
||||
#include <grub/loader.h>
|
||||
#include <grub/cs5536.h>
|
||||
#include <grub/disk.h>
|
||||
#include <grub/cache.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
@@ -337,6 +338,21 @@ struct grub_ehci
|
||||
|
||||
static struct grub_ehci *ehci;
|
||||
|
||||
static void
|
||||
sync_all_caches (struct grub_ehci *e)
|
||||
{
|
||||
if (!e)
|
||||
return;
|
||||
if (e->td_virt)
|
||||
grub_arch_sync_dma_caches (e->td_virt, sizeof (struct grub_ehci_td) *
|
||||
GRUB_EHCI_N_TD);
|
||||
if (e->qh_virt)
|
||||
grub_arch_sync_dma_caches (e->qh_virt, sizeof (struct grub_ehci_qh) *
|
||||
GRUB_EHCI_N_QH);
|
||||
if (e->framelist_virt)
|
||||
grub_arch_sync_dma_caches (e->framelist_virt, 4096);
|
||||
}
|
||||
|
||||
/* EHCC registers access functions */
|
||||
static inline grub_uint32_t
|
||||
grub_ehci_ehcc_read32 (struct grub_ehci *e, grub_uint32_t addr)
|
||||
@@ -437,6 +453,8 @@ grub_ehci_reset (struct grub_ehci *e)
|
||||
{
|
||||
grub_uint64_t maxtime;
|
||||
|
||||
sync_all_caches (e);
|
||||
|
||||
grub_ehci_oper_write32 (e, GRUB_EHCI_COMMAND,
|
||||
GRUB_EHCI_CMD_HC_RESET
|
||||
| grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND));
|
||||
@@ -670,23 +688,23 @@ grub_ehci_pci_iter (grub_pci_device_t dev, grub_pci_id_t pciid,
|
||||
for (i = 0; i < (GRUB_EHCI_N_TD - 1); i++)
|
||||
{
|
||||
e->td_virt[i].link_td = e->td_phys + (i + 1) * sizeof (struct grub_ehci_td);
|
||||
e->td_virt[i].next_td = grub_cpu_to_le32 (GRUB_EHCI_TERMINATE);
|
||||
e->td_virt[i].alt_next_td = grub_cpu_to_le32 (GRUB_EHCI_TERMINATE);
|
||||
e->td_virt[i].next_td = grub_cpu_to_le32_compile_time (GRUB_EHCI_TERMINATE);
|
||||
e->td_virt[i].alt_next_td = grub_cpu_to_le32_compile_time (GRUB_EHCI_TERMINATE);
|
||||
}
|
||||
e->td_virt[GRUB_EHCI_N_TD - 1].next_td =
|
||||
grub_cpu_to_le32 (GRUB_EHCI_TERMINATE);
|
||||
grub_cpu_to_le32_compile_time (GRUB_EHCI_TERMINATE);
|
||||
e->td_virt[GRUB_EHCI_N_TD - 1].alt_next_td =
|
||||
grub_cpu_to_le32 (GRUB_EHCI_TERMINATE);
|
||||
grub_cpu_to_le32_compile_time (GRUB_EHCI_TERMINATE);
|
||||
e->tdfree_virt = e->td_virt;
|
||||
/* Set Terminate in first QH, which is used in framelist */
|
||||
e->qh_virt[0].qh_hptr = grub_cpu_to_le32 (GRUB_EHCI_TERMINATE | GRUB_EHCI_HPTR_TYPE_QH);
|
||||
e->qh_virt[0].td_overlay.next_td = grub_cpu_to_le32 (GRUB_EHCI_TERMINATE);
|
||||
e->qh_virt[0].qh_hptr = grub_cpu_to_le32_compile_time (GRUB_EHCI_TERMINATE | GRUB_EHCI_HPTR_TYPE_QH);
|
||||
e->qh_virt[0].td_overlay.next_td = grub_cpu_to_le32_compile_time (GRUB_EHCI_TERMINATE);
|
||||
e->qh_virt[0].td_overlay.alt_next_td =
|
||||
grub_cpu_to_le32 (GRUB_EHCI_TERMINATE);
|
||||
grub_cpu_to_le32_compile_time (GRUB_EHCI_TERMINATE);
|
||||
/* Also set Halted bit in token */
|
||||
e->qh_virt[0].td_overlay.token = grub_cpu_to_le32 (GRUB_EHCI_STATUS_HALTED);
|
||||
e->qh_virt[0].td_overlay.token = grub_cpu_to_le32_compile_time (GRUB_EHCI_STATUS_HALTED);
|
||||
/* Set the H bit in first QH used for AL */
|
||||
e->qh_virt[1].ep_char = grub_cpu_to_le32 (GRUB_EHCI_H);
|
||||
e->qh_virt[1].ep_char = grub_cpu_to_le32_compile_time (GRUB_EHCI_H);
|
||||
/* Set Terminate into TD in rest of QHs and set horizontal link
|
||||
* pointer to itself - these QHs will be used for asynchronous
|
||||
* schedule and they should have valid value in horiz. link */
|
||||
@@ -697,12 +715,12 @@ grub_ehci_pci_iter (grub_pci_device_t dev, grub_pci_id_t pciid,
|
||||
e->qh_chunk) &
|
||||
GRUB_EHCI_POINTER_MASK) | GRUB_EHCI_HPTR_TYPE_QH);
|
||||
e->qh_virt[i].td_overlay.next_td =
|
||||
grub_cpu_to_le32 (GRUB_EHCI_TERMINATE);
|
||||
grub_cpu_to_le32_compile_time (GRUB_EHCI_TERMINATE);
|
||||
e->qh_virt[i].td_overlay.alt_next_td =
|
||||
grub_cpu_to_le32 (GRUB_EHCI_TERMINATE);
|
||||
grub_cpu_to_le32_compile_time (GRUB_EHCI_TERMINATE);
|
||||
/* Also set Halted bit in token */
|
||||
e->qh_virt[i].td_overlay.token =
|
||||
grub_cpu_to_le32 (GRUB_EHCI_STATUS_HALTED);
|
||||
grub_cpu_to_le32_compile_time (GRUB_EHCI_STATUS_HALTED);
|
||||
}
|
||||
|
||||
/* Note: QH 0 and QH 1 are reserved and must not be used anywhere.
|
||||
@@ -840,6 +858,8 @@ grub_ehci_pci_iter (grub_pci_device_t dev, grub_pci_id_t pciid,
|
||||
e->next = ehci;
|
||||
ehci = e;
|
||||
|
||||
sync_all_caches (e);
|
||||
|
||||
grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: OK at all\n");
|
||||
|
||||
grub_dprintf ("ehci",
|
||||
@@ -991,7 +1011,7 @@ grub_ehci_find_qh (struct grub_ehci *e, grub_usb_transfer_t transfer)
|
||||
target = ((transfer->endpoint << GRUB_EHCI_EP_NUM_OFF) |
|
||||
transfer->devaddr) & GRUB_EHCI_TARGET_MASK;
|
||||
target = grub_cpu_to_le32 (target);
|
||||
mask = grub_cpu_to_le32 (GRUB_EHCI_TARGET_MASK);
|
||||
mask = grub_cpu_to_le32_compile_time (GRUB_EHCI_TARGET_MASK);
|
||||
|
||||
/* low speed interrupt transfers are linked to the periodic */
|
||||
/* schedule, everything else to the asynchronous schedule */
|
||||
@@ -1020,6 +1040,7 @@ grub_ehci_find_qh (struct grub_ehci *e, grub_usb_transfer_t transfer)
|
||||
/* Found proper existing (and linked) QH, do setup of QH */
|
||||
grub_dprintf ("ehci", "find_qh: found, QH=%p\n", qh_iter);
|
||||
grub_ehci_setup_qh (qh_iter, transfer);
|
||||
sync_all_caches (e);
|
||||
return qh_iter;
|
||||
}
|
||||
|
||||
@@ -1121,7 +1142,7 @@ grub_ehci_free_tds (struct grub_ehci *e, grub_ehci_td_t td,
|
||||
token = grub_le_to_cpu32 (td->token);
|
||||
to_transfer = (token & GRUB_EHCI_TOTAL_MASK) >> GRUB_EHCI_TOTAL_OFF;
|
||||
|
||||
/* Check state of TD - if it did not transfered
|
||||
/* Check state of TD - if it did not transfer
|
||||
* whole data then set last_trans - it should be last executed TD
|
||||
* in case when something went wrong. */
|
||||
if (transfer && (td->size != to_transfer))
|
||||
@@ -1200,7 +1221,7 @@ grub_ehci_transaction (struct grub_ehci *e,
|
||||
grub_memset ((void *) td, 0, sizeof (struct grub_ehci_td));
|
||||
|
||||
/* Don't point to any TD yet, just terminate. */
|
||||
td->next_td = grub_cpu_to_le32 (GRUB_EHCI_TERMINATE);
|
||||
td->next_td = grub_cpu_to_le32_compile_time (GRUB_EHCI_TERMINATE);
|
||||
/* Set alternate pointer. When short packet occurs, alternate TD
|
||||
* will not be really fetched because it is not active. But don't
|
||||
* forget, EHCI will try to fetch alternate TD every scan of AL
|
||||
@@ -1289,16 +1310,28 @@ grub_ehci_setup_transfer (grub_usb_controller_t dev,
|
||||
grub_ehci_td_t td_prev = NULL;
|
||||
int i;
|
||||
struct grub_ehci_transfer_controller_data *cdata;
|
||||
grub_uint32_t status;
|
||||
|
||||
sync_all_caches (e);
|
||||
|
||||
/* Check if EHCI is running and AL is enabled */
|
||||
if ((grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS)
|
||||
& GRUB_EHCI_ST_HC_HALTED) != 0)
|
||||
status = grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS);
|
||||
if ((status & GRUB_EHCI_ST_HC_HALTED) != 0)
|
||||
/* XXX: Fix it: Currently we don't do anything to restart EHCI */
|
||||
return GRUB_USB_ERR_INTERNAL;
|
||||
if ((grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS)
|
||||
{
|
||||
grub_dprintf ("ehci", "setup_transfer: halted, status = 0x%x\n",
|
||||
status);
|
||||
return GRUB_USB_ERR_INTERNAL;
|
||||
}
|
||||
status = grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS);
|
||||
if ((status
|
||||
& (GRUB_EHCI_ST_AS_STATUS | GRUB_EHCI_ST_PS_STATUS)) == 0)
|
||||
/* XXX: Fix it: Currently we don't do anything to restart EHCI */
|
||||
return GRUB_USB_ERR_INTERNAL;
|
||||
{
|
||||
grub_dprintf ("ehci", "setup_transfer: no AS/PS, status = 0x%x\n",
|
||||
status);
|
||||
return GRUB_USB_ERR_INTERNAL;
|
||||
}
|
||||
|
||||
/* Allocate memory for controller transfer data. */
|
||||
cdata = grub_malloc (sizeof (*cdata));
|
||||
@@ -1310,6 +1343,7 @@ grub_ehci_setup_transfer (grub_usb_controller_t dev,
|
||||
cdata->qh_virt = grub_ehci_find_qh (e, transfer);
|
||||
if (!cdata->qh_virt)
|
||||
{
|
||||
grub_dprintf ("ehci", "setup_transfer: no QH\n");
|
||||
grub_free (cdata);
|
||||
return GRUB_USB_ERR_INTERNAL;
|
||||
}
|
||||
@@ -1319,15 +1353,16 @@ grub_ehci_setup_transfer (grub_usb_controller_t dev,
|
||||
cdata->td_alt_virt = grub_ehci_alloc_td (e);
|
||||
if (!cdata->td_alt_virt)
|
||||
{
|
||||
grub_dprintf ("ehci", "setup_transfer: no TDs\n");
|
||||
grub_free (cdata);
|
||||
return GRUB_USB_ERR_INTERNAL;
|
||||
}
|
||||
/* Fill whole alternate TD by zeros (= inactive) and set
|
||||
* Terminate bits and Halt bit */
|
||||
grub_memset ((void *) cdata->td_alt_virt, 0, sizeof (struct grub_ehci_td));
|
||||
cdata->td_alt_virt->next_td = grub_cpu_to_le32 (GRUB_EHCI_TERMINATE);
|
||||
cdata->td_alt_virt->alt_next_td = grub_cpu_to_le32 (GRUB_EHCI_TERMINATE);
|
||||
cdata->td_alt_virt->token = grub_cpu_to_le32 (GRUB_EHCI_STATUS_HALTED);
|
||||
cdata->td_alt_virt->next_td = grub_cpu_to_le32_compile_time (GRUB_EHCI_TERMINATE);
|
||||
cdata->td_alt_virt->alt_next_td = grub_cpu_to_le32_compile_time (GRUB_EHCI_TERMINATE);
|
||||
cdata->td_alt_virt->token = grub_cpu_to_le32_compile_time (GRUB_EHCI_STATUS_HALTED);
|
||||
|
||||
/* Allocate appropriate number of TDs and set */
|
||||
for (i = 0; i < transfer->transcnt; i++)
|
||||
@@ -1345,6 +1380,7 @@ grub_ehci_setup_transfer (grub_usb_controller_t dev,
|
||||
grub_ehci_free_tds (e, cdata->td_first_virt, NULL, &actual);
|
||||
|
||||
grub_free (cdata);
|
||||
grub_dprintf ("ehci", "setup_transfer: no TD\n");
|
||||
return GRUB_USB_ERR_INTERNAL;
|
||||
}
|
||||
|
||||
@@ -1364,7 +1400,7 @@ grub_ehci_setup_transfer (grub_usb_controller_t dev,
|
||||
cdata->td_last_virt = td;
|
||||
cdata->td_last_phys = grub_dma_virt2phys (td, e->td_chunk);
|
||||
/* Last TD should not have set alternate TD */
|
||||
cdata->td_last_virt->alt_next_td = grub_cpu_to_le32 (GRUB_EHCI_TERMINATE);
|
||||
cdata->td_last_virt->alt_next_td = grub_cpu_to_le32_compile_time (GRUB_EHCI_TERMINATE);
|
||||
|
||||
grub_dprintf ("ehci", "setup_transfer: cdata=%p, qh=%p\n",
|
||||
cdata,cdata->qh_virt);
|
||||
@@ -1377,14 +1413,16 @@ grub_ehci_setup_transfer (grub_usb_controller_t dev,
|
||||
/* Start transfer: */
|
||||
/* Unlink possible alternate pointer in QH */
|
||||
cdata->qh_virt->td_overlay.alt_next_td =
|
||||
grub_cpu_to_le32 (GRUB_EHCI_TERMINATE);
|
||||
grub_cpu_to_le32_compile_time (GRUB_EHCI_TERMINATE);
|
||||
/* Link new TDs with QH via next_td */
|
||||
cdata->qh_virt->td_overlay.next_td =
|
||||
grub_cpu_to_le32 (grub_dma_virt2phys
|
||||
(cdata->td_first_virt, e->td_chunk));
|
||||
/* Reset Active and Halted bits in QH to activate Advance Queue,
|
||||
* i.e. reset token */
|
||||
cdata->qh_virt->td_overlay.token = grub_cpu_to_le32 (0);
|
||||
cdata->qh_virt->td_overlay.token = grub_cpu_to_le32_compile_time (0);
|
||||
|
||||
sync_all_caches (e);
|
||||
|
||||
/* Finito */
|
||||
transfer->controller_data = cdata;
|
||||
@@ -1408,9 +1446,9 @@ grub_ehci_pre_finish_transfer (grub_usb_transfer_t transfer)
|
||||
* safely manipulate with QH TD part. */
|
||||
cdata->qh_virt->td_overlay.token = (cdata->qh_virt->td_overlay.token
|
||||
|
|
||||
grub_cpu_to_le32
|
||||
grub_cpu_to_le32_compile_time
|
||||
(GRUB_EHCI_STATUS_HALTED)) &
|
||||
grub_cpu_to_le32 (~GRUB_EHCI_STATUS_ACTIVE);
|
||||
grub_cpu_to_le32_compile_time (~GRUB_EHCI_STATUS_ACTIVE);
|
||||
|
||||
/* Print debug data here if necessary */
|
||||
|
||||
@@ -1434,6 +1472,8 @@ grub_ehci_parse_notrun (grub_usb_controller_t dev,
|
||||
grub_ehci_free_td (e, cdata->td_alt_virt);
|
||||
grub_free (cdata);
|
||||
|
||||
sync_all_caches (e);
|
||||
|
||||
/* Additionally, do something with EHCI to make it running (what?) */
|
||||
/* Try enable EHCI and AL */
|
||||
grub_ehci_oper_write32 (e, GRUB_EHCI_COMMAND,
|
||||
@@ -1469,6 +1509,8 @@ grub_ehci_parse_halt (grub_usb_controller_t dev,
|
||||
grub_ehci_free_td (e, cdata->td_alt_virt);
|
||||
grub_free (cdata);
|
||||
|
||||
sync_all_caches (e);
|
||||
|
||||
/* Evaluation of error code - currently we don't have GRUB USB error
|
||||
* codes for some EHCI states, GRUB_USB_ERR_DATA is used for them.
|
||||
* Order of evaluation is critical, specially bubble/stall. */
|
||||
@@ -1502,6 +1544,8 @@ grub_ehci_parse_success (grub_usb_controller_t dev,
|
||||
grub_ehci_free_td (e, cdata->td_alt_virt);
|
||||
grub_free (cdata);
|
||||
|
||||
sync_all_caches (e);
|
||||
|
||||
return GRUB_USB_ERR_NONE;
|
||||
}
|
||||
|
||||
@@ -1515,6 +1559,8 @@ grub_ehci_check_transfer (grub_usb_controller_t dev,
|
||||
transfer->controller_data;
|
||||
grub_uint32_t token, token_ftd;
|
||||
|
||||
sync_all_caches (e);
|
||||
|
||||
grub_dprintf ("ehci",
|
||||
"check_transfer: EHCI STATUS=%08x, cdata=%p, qh=%p\n",
|
||||
grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS),
|
||||
@@ -1581,6 +1627,9 @@ grub_ehci_cancel_transfer (grub_usb_controller_t dev,
|
||||
int i;
|
||||
grub_uint64_t maxtime;
|
||||
grub_uint32_t qh_phys;
|
||||
|
||||
sync_all_caches (e);
|
||||
|
||||
grub_uint32_t interrupt =
|
||||
cdata->qh_virt->ep_cap & GRUB_EHCI_SMASK_MASK;
|
||||
|
||||
@@ -1600,6 +1649,7 @@ grub_ehci_cancel_transfer (grub_usb_controller_t dev,
|
||||
grub_ehci_free_tds (e, cdata->td_first_virt, transfer, &actual);
|
||||
grub_ehci_free_td (e, cdata->td_alt_virt);
|
||||
grub_free (cdata);
|
||||
sync_all_caches (e);
|
||||
grub_dprintf ("ehci", "cancel_transfer: end - EHCI not running\n");
|
||||
return GRUB_USB_ERR_NONE;
|
||||
}
|
||||
@@ -1622,6 +1672,8 @@ grub_ehci_cancel_transfer (grub_usb_controller_t dev,
|
||||
/* Unlink QH from AL */
|
||||
e->qh_virt[i].qh_hptr = cdata->qh_virt->qh_hptr;
|
||||
|
||||
sync_all_caches (e);
|
||||
|
||||
/* If this is an interrupt transfer, we just wait for the periodic
|
||||
* schedule to advance a few times and then assume that the EHCI
|
||||
* controller has read the updated QH. */
|
||||
@@ -1676,6 +1728,8 @@ grub_ehci_cancel_transfer (grub_usb_controller_t dev,
|
||||
|
||||
grub_dprintf ("ehci", "cancel_transfer: end\n");
|
||||
|
||||
sync_all_caches (e);
|
||||
|
||||
return GRUB_USB_ERR_NONE;
|
||||
}
|
||||
|
||||
@@ -1777,11 +1831,6 @@ grub_ehci_detect_dev (grub_usb_controller_t dev, int port, int *changed)
|
||||
|
||||
status = grub_ehci_port_read (e, port);
|
||||
|
||||
grub_dprintf ("ehci", "detect_dev: EHCI STATUS: %08x\n",
|
||||
grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS));
|
||||
grub_dprintf ("ehci", "detect_dev: iobase=%p, port=%d, status=0x%02x\n",
|
||||
e->iobase, port, status);
|
||||
|
||||
/* Connect Status Change bit - it detects change of connection */
|
||||
if (status & GRUB_EHCI_PORT_CONNECT_CH)
|
||||
{
|
||||
|
||||
@@ -1,203 +0,0 @@
|
||||
/* usb.c -- libusb USB support for GRUB. */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2008 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GRUB is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/mm.h>
|
||||
#include <usb.h>
|
||||
#include <grub/usb.h>
|
||||
#include <grub/dl.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
|
||||
static struct grub_usb_controller_dev usb_controller =
|
||||
{
|
||||
.name = "libusb"
|
||||
};
|
||||
|
||||
static struct grub_usb_device *grub_usb_devs[128];
|
||||
|
||||
struct usb_bus *busses;
|
||||
|
||||
static grub_err_t
|
||||
grub_libusb_devices (void)
|
||||
|
||||
{
|
||||
struct usb_bus *bus;
|
||||
int last = 0;
|
||||
|
||||
busses = usb_get_busses();
|
||||
|
||||
for (bus = busses; bus; bus = bus->next)
|
||||
{
|
||||
struct usb_device *usbdev;
|
||||
struct grub_usb_device *dev;
|
||||
|
||||
for (usbdev = bus->devices; usbdev; usbdev = usbdev->next)
|
||||
{
|
||||
struct usb_device_descriptor *desc = &usbdev->descriptor;
|
||||
grub_err_t err;
|
||||
|
||||
if (! desc->bcdUSB)
|
||||
continue;
|
||||
|
||||
dev = grub_malloc (sizeof (*dev));
|
||||
if (! dev)
|
||||
return grub_errno;
|
||||
|
||||
dev->data = usbdev;
|
||||
|
||||
/* Fill in all descriptors. */
|
||||
err = grub_usb_device_initialize (dev);
|
||||
if (err)
|
||||
{
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Register the device. */
|
||||
grub_usb_devs[last++] = dev;
|
||||
}
|
||||
}
|
||||
|
||||
return GRUB_USB_ERR_NONE;
|
||||
}
|
||||
|
||||
void
|
||||
grub_usb_poll_devices (void)
|
||||
{
|
||||
/* TODO: recheck grub_usb_devs */
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
grub_usb_iterate (grub_usb_iterate_hook_t hook, void *hook_data)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 128; i++)
|
||||
{
|
||||
if (grub_usb_devs[i])
|
||||
{
|
||||
if (hook (grub_usb_devs[i], hook_data))
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
grub_usb_err_t
|
||||
grub_usb_root_hub (grub_usb_controller_t controller __attribute__((unused)))
|
||||
{
|
||||
return GRUB_USB_ERR_NONE;
|
||||
}
|
||||
|
||||
grub_usb_err_t
|
||||
grub_usb_control_msg (grub_usb_device_t dev, grub_uint8_t reqtype,
|
||||
grub_uint8_t request, grub_uint16_t value,
|
||||
grub_uint16_t idx, grub_size_t size, char *data)
|
||||
{
|
||||
usb_dev_handle *devh;
|
||||
struct usb_device *d = dev->data;
|
||||
|
||||
devh = usb_open (d);
|
||||
if (usb_control_msg (devh, reqtype, request,
|
||||
value, idx, data, size, 20) < 0)
|
||||
{
|
||||
usb_close (devh);
|
||||
return GRUB_USB_ERR_STALL;
|
||||
}
|
||||
|
||||
usb_close (devh);
|
||||
|
||||
return GRUB_USB_ERR_NONE;
|
||||
}
|
||||
|
||||
grub_usb_err_t
|
||||
grub_usb_bulk_read (grub_usb_device_t dev,
|
||||
int endpoint, grub_size_t size, char *data)
|
||||
{
|
||||
usb_dev_handle *devh;
|
||||
struct usb_device *d = dev->data;
|
||||
|
||||
devh = usb_open (d);
|
||||
if (usb_claim_interface (devh, 0) < 1)
|
||||
{
|
||||
usb_close (devh);
|
||||
return GRUB_USB_ERR_STALL;
|
||||
}
|
||||
|
||||
if (usb_bulk_read (devh, endpoint, data, size, 20) < 1)
|
||||
{
|
||||
usb_close (devh);
|
||||
return GRUB_USB_ERR_STALL;
|
||||
}
|
||||
|
||||
usb_release_interface (devh, 0);
|
||||
usb_close (devh);
|
||||
|
||||
return GRUB_USB_ERR_NONE;
|
||||
}
|
||||
|
||||
grub_usb_err_t
|
||||
grub_usb_bulk_write (grub_usb_device_t dev,
|
||||
int endpoint, grub_size_t size, char *data)
|
||||
{
|
||||
usb_dev_handle *devh;
|
||||
struct usb_device *d = dev->data;
|
||||
|
||||
devh = usb_open (d);
|
||||
if (usb_claim_interface (devh, 0) < 0)
|
||||
goto fail;
|
||||
|
||||
if (usb_bulk_write (devh, endpoint, data, size, 20) < 0)
|
||||
goto fail;
|
||||
|
||||
if (usb_release_interface (devh, 0) < 0)
|
||||
goto fail;
|
||||
|
||||
usb_close (devh);
|
||||
|
||||
return GRUB_USB_ERR_NONE;
|
||||
|
||||
fail:
|
||||
usb_close (devh);
|
||||
return GRUB_USB_ERR_STALL;
|
||||
}
|
||||
|
||||
GRUB_MOD_INIT (libusb)
|
||||
{
|
||||
usb_init();
|
||||
usb_find_busses();
|
||||
usb_find_devices();
|
||||
|
||||
if (grub_libusb_devices ())
|
||||
return;
|
||||
|
||||
grub_usb_controller_dev_register (&usb_controller);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI (libusb)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -314,7 +314,7 @@ grub_ohci_pci_iter (grub_pci_device_t dev, grub_pci_id_t pciid,
|
||||
grub_memset ((void *) o->ed_ctrl, 0, sizeof (struct grub_ohci_ed)
|
||||
* GRUB_OHCI_CTRL_EDS);
|
||||
for (j=0; j < GRUB_OHCI_CTRL_EDS; j++)
|
||||
o->ed_ctrl[j].target = grub_cpu_to_le32 (1 << 14); /* skip */
|
||||
o->ed_ctrl[j].target = grub_cpu_to_le32_compile_time (1 << 14); /* skip */
|
||||
|
||||
grub_dprintf ("ohci", "EDs-C: chunk=%p, virt=%p, phys=0x%02x\n",
|
||||
o->ed_ctrl_chunk, o->ed_ctrl, o->ed_ctrl_addr);
|
||||
@@ -329,7 +329,7 @@ grub_ohci_pci_iter (grub_pci_device_t dev, grub_pci_id_t pciid,
|
||||
/* Preset EDs */
|
||||
grub_memset ((void*)o->ed_bulk, 0, sizeof(struct grub_ohci_ed) * GRUB_OHCI_BULK_EDS);
|
||||
for (j=0; j < GRUB_OHCI_BULK_EDS; j++)
|
||||
o->ed_bulk[j].target = grub_cpu_to_le32 (1 << 14); /* skip */
|
||||
o->ed_bulk[j].target = grub_cpu_to_le32_compile_time (1 << 14); /* skip */
|
||||
|
||||
grub_dprintf ("ohci", "EDs-B: chunk=%p, virt=%p, phys=0x%02x\n",
|
||||
o->ed_bulk_chunk, o->ed_bulk, o->ed_bulk_addr);
|
||||
@@ -750,7 +750,10 @@ grub_ohci_setup_transfer (grub_usb_controller_t dev,
|
||||
{
|
||||
cdata->td_head_virt = grub_ohci_alloc_td (o);
|
||||
if (!cdata->td_head_virt)
|
||||
return GRUB_USB_ERR_INTERNAL; /* We don't need de-allocate ED */
|
||||
{
|
||||
grub_free (cdata);
|
||||
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.
|
||||
* when it is newly allocated. */
|
||||
cdata->ed_virt->td_head
|
||||
@@ -1349,10 +1352,10 @@ grub_ohci_fini_hw (int noreturn __attribute__ ((unused)))
|
||||
/* Set skip in all EDs */
|
||||
if (o->ed_bulk)
|
||||
for (i=0; i < GRUB_OHCI_BULK_EDS; i++)
|
||||
o->ed_bulk[i].target |= grub_cpu_to_le32 (1 << 14); /* skip */
|
||||
o->ed_bulk[i].target |= grub_cpu_to_le32_compile_time (1 << 14); /* skip */
|
||||
if (o->ed_ctrl)
|
||||
for (i=0; i < GRUB_OHCI_CTRL_EDS; i++)
|
||||
o->ed_ctrl[i].target |= grub_cpu_to_le32 (1 << 14); /* skip */
|
||||
o->ed_ctrl[i].target |= grub_cpu_to_le32_compile_time (1 << 14); /* skip */
|
||||
|
||||
/* We should wait for next SOF to be sure that all EDs are
|
||||
* unaccessed by OHCI. But OHCI can be non-functional, so
|
||||
|
||||
@@ -625,9 +625,7 @@ grub_uhci_check_transfer (grub_usb_controller_t dev,
|
||||
return GRUB_USB_ERR_NONE;
|
||||
}
|
||||
|
||||
grub_dprintf ("uhci", "t status=0x%02x\n", errtd->ctrl_status);
|
||||
|
||||
if (!(errtd->ctrl_status & (1 << 23)))
|
||||
if (errtd && !(errtd->ctrl_status & (1 << 23)))
|
||||
{
|
||||
grub_usb_err_t err = GRUB_USB_ERR_NONE;
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <grub/usb.h>
|
||||
#include <grub/usbtrans.h>
|
||||
#include <grub/time.h>
|
||||
#include <grub/cache.h>
|
||||
|
||||
|
||||
static inline unsigned int
|
||||
@@ -31,7 +32,7 @@ grub_usb_bulk_maxpacket (grub_usb_device_t dev,
|
||||
struct grub_usb_desc_endp *endpoint)
|
||||
{
|
||||
/* Use the maximum packet size given in the endpoint descriptor. */
|
||||
if (dev->initialized && endpoint)
|
||||
if (dev->initialized && endpoint && (unsigned int) endpoint->maxpacket)
|
||||
return endpoint->maxpacket;
|
||||
|
||||
return 64;
|
||||
@@ -101,6 +102,8 @@ grub_usb_control_msg (grub_usb_device_t dev,
|
||||
data_addr = grub_dma_get_phys (data_chunk);
|
||||
grub_memcpy ((char *) data, data_in, size);
|
||||
|
||||
grub_arch_sync_dma_caches (data, size);
|
||||
|
||||
grub_dprintf ("usb",
|
||||
"control: reqtype=0x%02x req=0x%02x val=0x%02x idx=0x%02x size=%lu\n",
|
||||
reqtype, request, value, index, (unsigned long)size);
|
||||
@@ -161,6 +164,8 @@ grub_usb_control_msg (grub_usb_device_t dev,
|
||||
setupdata->value = value;
|
||||
setupdata->index = index;
|
||||
setupdata->length = size;
|
||||
grub_arch_sync_dma_caches (setupdata, sizeof (*setupdata));
|
||||
|
||||
transfer->transactions[0].size = sizeof (*setupdata);
|
||||
transfer->transactions[0].pid = GRUB_USB_TRANSFER_TYPE_SETUP;
|
||||
transfer->transactions[0].data = setupdata_addr;
|
||||
@@ -202,11 +207,13 @@ grub_usb_control_msg (grub_usb_device_t dev,
|
||||
grub_free (transfer->transactions);
|
||||
|
||||
grub_free (transfer);
|
||||
grub_dma_free (data_chunk);
|
||||
grub_dma_free (setupdata_chunk);
|
||||
|
||||
grub_arch_sync_dma_caches (data, size0);
|
||||
grub_memcpy (data_in, (char *) data, size0);
|
||||
|
||||
grub_dma_free (data_chunk);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -236,7 +243,10 @@ grub_usb_bulk_setup_readwrite (grub_usb_device_t dev,
|
||||
data = grub_dma_get_virt (data_chunk);
|
||||
data_addr = grub_dma_get_phys (data_chunk);
|
||||
if (type == GRUB_USB_TRANSFER_TYPE_OUT)
|
||||
grub_memcpy ((char *) data, data_in, size);
|
||||
{
|
||||
grub_memcpy ((char *) data, data_in, size);
|
||||
grub_arch_sync_dma_caches (data, size);
|
||||
}
|
||||
|
||||
/* Create a transfer. */
|
||||
transfer = grub_malloc (sizeof (struct grub_usb_transfer));
|
||||
@@ -306,13 +316,17 @@ grub_usb_bulk_finish_readwrite (grub_usb_transfer_t transfer)
|
||||
dev->toggle[transfer->endpoint] = toggle;
|
||||
|
||||
if (transfer->dir == GRUB_USB_TRANSFER_TYPE_IN)
|
||||
grub_memcpy (transfer->data, (void *)
|
||||
grub_dma_get_virt (transfer->data_chunk),
|
||||
transfer->size + 1);
|
||||
{
|
||||
grub_arch_sync_dma_caches (grub_dma_get_virt (transfer->data_chunk),
|
||||
transfer->size + 1);
|
||||
grub_memcpy (transfer->data, (void *)
|
||||
grub_dma_get_virt (transfer->data_chunk),
|
||||
transfer->size + 1);
|
||||
}
|
||||
|
||||
grub_free (transfer->transactions);
|
||||
grub_free (transfer);
|
||||
grub_dma_free (transfer->data_chunk);
|
||||
grub_free (transfer);
|
||||
}
|
||||
|
||||
static grub_usb_err_t
|
||||
|
||||
+13
-17
@@ -61,18 +61,6 @@ static const struct grub_arg_option options[] = {
|
||||
{0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
/* Simple checksum by summing all bytes. Used by ACPI and SMBIOS. */
|
||||
grub_uint8_t
|
||||
grub_byte_checksum (void *base, grub_size_t size)
|
||||
{
|
||||
grub_uint8_t *ptr;
|
||||
grub_uint8_t ret = 0;
|
||||
for (ptr = (grub_uint8_t *) base; ptr < ((grub_uint8_t *) base) + size;
|
||||
ptr++)
|
||||
ret += *ptr;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* rev1 is 1 if ACPIv1 is to be generated, 0 otherwise.
|
||||
rev2 contains the revision of ACPIv2+ to generate or 0 if none. */
|
||||
static int rev1, rev2;
|
||||
@@ -131,6 +119,8 @@ grub_acpi_get_rsdpv1 (void)
|
||||
return grub_machine_acpi_get_rsdpv1 ();
|
||||
}
|
||||
|
||||
#if defined (__i386__) || defined (__x86_64__)
|
||||
|
||||
static inline int
|
||||
iszero (grub_uint8_t *reg, int size)
|
||||
{
|
||||
@@ -141,7 +131,6 @@ iszero (grub_uint8_t *reg, int size)
|
||||
return 1;
|
||||
}
|
||||
|
||||
#if defined (__i386__) || defined (__x86_64__)
|
||||
/* Context for grub_acpi_create_ebda. */
|
||||
struct grub_acpi_create_ebda_ctx {
|
||||
int ebda_len;
|
||||
@@ -179,8 +168,10 @@ grub_acpi_create_ebda (void)
|
||||
struct grub_acpi_rsdp_v20 *v2;
|
||||
|
||||
ebda = (grub_uint8_t *) (grub_addr_t) ((*((grub_uint16_t *)0x40e)) << 4);
|
||||
grub_dprintf ("acpi", "EBDA @%p\n", ebda);
|
||||
if (ebda)
|
||||
ebda_kb_len = *(grub_uint16_t *) ebda;
|
||||
grub_dprintf ("acpi", "EBDA length 0x%x\n", ebda_kb_len);
|
||||
if (ebda_kb_len > 16)
|
||||
ebda_kb_len = 0;
|
||||
ctx.ebda_len = (ebda_kb_len + 1) << 10;
|
||||
@@ -227,7 +218,7 @@ grub_acpi_create_ebda (void)
|
||||
grub_dprintf ("acpi", "Copying rsdpv2 to %p\n", target);
|
||||
v2inebda = target;
|
||||
target += v2->length;
|
||||
target = (grub_uint8_t *) ((((grub_addr_t) target - 1) | 0xf) + 1);
|
||||
target = (grub_uint8_t *) ALIGN_UP((grub_addr_t) target, 16);
|
||||
v2 = 0;
|
||||
break;
|
||||
}
|
||||
@@ -246,7 +237,7 @@ grub_acpi_create_ebda (void)
|
||||
grub_dprintf ("acpi", "Copying rsdpv1 to %p\n", target);
|
||||
v1inebda = target;
|
||||
target += sizeof (struct grub_acpi_rsdp_v10);
|
||||
target = (grub_uint8_t *) ((((grub_addr_t) target - 1) | 0xf) + 1);
|
||||
target = (grub_uint8_t *) ALIGN_UP((grub_addr_t) target, 16);
|
||||
v1 = 0;
|
||||
break;
|
||||
}
|
||||
@@ -265,7 +256,7 @@ grub_acpi_create_ebda (void)
|
||||
grub_memcpy (target, v2, v2->length);
|
||||
v2inebda = target;
|
||||
target += v2->length;
|
||||
target = (grub_uint8_t *) ((((grub_addr_t) target - 1) | 0xf) + 1);
|
||||
target = (grub_uint8_t *) ALIGN_UP((grub_addr_t) target, 16);
|
||||
v2 = 0;
|
||||
break;
|
||||
}
|
||||
@@ -282,7 +273,7 @@ grub_acpi_create_ebda (void)
|
||||
grub_memcpy (target, v1, sizeof (struct grub_acpi_rsdp_v10));
|
||||
v1inebda = target;
|
||||
target += sizeof (struct grub_acpi_rsdp_v10);
|
||||
target = (grub_uint8_t *) ((((grub_addr_t) target - 1) | 0xf) + 1);
|
||||
target = (grub_uint8_t *) ALIGN_UP((grub_addr_t) target, 16);
|
||||
v1 = 0;
|
||||
break;
|
||||
}
|
||||
@@ -494,6 +485,8 @@ grub_cmd_acpi (struct grub_extcmd_context *ctxt, int argc, char **args)
|
||||
if (! rsdp)
|
||||
rsdp = grub_machine_acpi_get_rsdpv1 ();
|
||||
|
||||
grub_dprintf ("acpi", "RSDP @%p\n", rsdp);
|
||||
|
||||
if (rsdp)
|
||||
{
|
||||
grub_uint32_t *entry_ptr;
|
||||
@@ -600,6 +593,9 @@ grub_cmd_acpi (struct grub_extcmd_context *ctxt, int argc, char **args)
|
||||
if (! table->addr)
|
||||
{
|
||||
free_tables ();
|
||||
grub_free (exclude);
|
||||
grub_free (load_only);
|
||||
grub_free (table);
|
||||
return grub_errno;
|
||||
}
|
||||
table->next = acpi_tables;
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
|
||||
#define grub_dprintf(cond, args...) printf ( args )
|
||||
#define grub_printf printf
|
||||
#define grub_util_fopen fopen
|
||||
#define grub_memcmp memcmp
|
||||
typedef uint64_t grub_uint64_t;
|
||||
typedef uint32_t grub_uint32_t;
|
||||
typedef uint16_t grub_uint16_t;
|
||||
@@ -135,6 +137,49 @@ skip_data_ref_object (const grub_uint8_t *ptr, const grub_uint8_t *end)
|
||||
}
|
||||
}
|
||||
|
||||
static inline grub_uint32_t
|
||||
skip_term (const grub_uint8_t *ptr, const grub_uint8_t *end)
|
||||
{
|
||||
grub_uint32_t add;
|
||||
const grub_uint8_t *ptr0 = ptr;
|
||||
|
||||
switch(*ptr)
|
||||
{
|
||||
case GRUB_ACPI_OPCODE_ADD:
|
||||
case GRUB_ACPI_OPCODE_AND:
|
||||
case GRUB_ACPI_OPCODE_CONCAT:
|
||||
case GRUB_ACPI_OPCODE_CONCATRES:
|
||||
case GRUB_ACPI_OPCODE_DIVIDE:
|
||||
case GRUB_ACPI_OPCODE_INDEX:
|
||||
case GRUB_ACPI_OPCODE_LSHIFT:
|
||||
case GRUB_ACPI_OPCODE_MOD:
|
||||
case GRUB_ACPI_OPCODE_MULTIPLY:
|
||||
case GRUB_ACPI_OPCODE_NAND:
|
||||
case GRUB_ACPI_OPCODE_NOR:
|
||||
case GRUB_ACPI_OPCODE_OR:
|
||||
case GRUB_ACPI_OPCODE_RSHIFT:
|
||||
case GRUB_ACPI_OPCODE_SUBTRACT:
|
||||
case GRUB_ACPI_OPCODE_TOSTRING:
|
||||
case GRUB_ACPI_OPCODE_XOR:
|
||||
/*
|
||||
* Parameters for these opcodes: TermArg, TermArg Target, see ACPI
|
||||
* spec r5.0, page 828f.
|
||||
*/
|
||||
ptr++;
|
||||
ptr += add = skip_term (ptr, end);
|
||||
if (!add)
|
||||
return 0;
|
||||
ptr += add = skip_term (ptr, end);
|
||||
if (!add)
|
||||
return 0;
|
||||
ptr += skip_name_string (ptr, end);
|
||||
break;
|
||||
default:
|
||||
return skip_data_ref_object (ptr, end);
|
||||
}
|
||||
return ptr - ptr0;
|
||||
}
|
||||
|
||||
static inline grub_uint32_t
|
||||
skip_ext_op (const grub_uint8_t *ptr, const grub_uint8_t *end)
|
||||
{
|
||||
@@ -156,10 +201,10 @@ skip_ext_op (const grub_uint8_t *ptr, const grub_uint8_t *end)
|
||||
ptr++;
|
||||
ptr += skip_name_string (ptr, end);
|
||||
ptr++;
|
||||
ptr += add = skip_data_ref_object (ptr, end);
|
||||
ptr += add = skip_term (ptr, end);
|
||||
if (!add)
|
||||
return 0;
|
||||
ptr += add = skip_data_ref_object (ptr, end);
|
||||
ptr += add = skip_term (ptr, end);
|
||||
if (!add)
|
||||
return 0;
|
||||
break;
|
||||
@@ -180,6 +225,7 @@ skip_ext_op (const grub_uint8_t *ptr, const grub_uint8_t *end)
|
||||
return ptr - ptr0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
get_sleep_type (grub_uint8_t *table, grub_uint8_t *ptr, grub_uint8_t *end,
|
||||
grub_uint8_t *scope, int scope_len)
|
||||
@@ -202,6 +248,7 @@ get_sleep_type (grub_uint8_t *table, grub_uint8_t *ptr, grub_uint8_t *end,
|
||||
if (!add)
|
||||
return -1;
|
||||
break;
|
||||
case GRUB_ACPI_OPCODE_CREATE_DWORD_FIELD:
|
||||
case GRUB_ACPI_OPCODE_CREATE_WORD_FIELD:
|
||||
case GRUB_ACPI_OPCODE_CREATE_BYTE_FIELD:
|
||||
{
|
||||
@@ -214,8 +261,8 @@ get_sleep_type (grub_uint8_t *table, grub_uint8_t *ptr, grub_uint8_t *end,
|
||||
}
|
||||
case GRUB_ACPI_OPCODE_NAME:
|
||||
ptr++;
|
||||
if ((!scope || memcmp (scope, "\\", scope_len) == 0) &&
|
||||
(memcmp (ptr, "_S5_", 4) == 0 || memcmp (ptr, "\\_S5_", 4) == 0))
|
||||
if ((!scope || grub_memcmp (scope, "\\", scope_len) == 0) &&
|
||||
(grub_memcmp (ptr, "_S5_", 4) == 0 || grub_memcmp (ptr, "\\_S5_", 4) == 0))
|
||||
{
|
||||
int ll;
|
||||
grub_uint8_t *ptr2 = ptr;
|
||||
@@ -250,6 +297,17 @@ get_sleep_type (grub_uint8_t *table, grub_uint8_t *ptr, grub_uint8_t *end,
|
||||
if (!add)
|
||||
return -1;
|
||||
break;
|
||||
case GRUB_ACPI_OPCODE_ALIAS:
|
||||
ptr++;
|
||||
/* We need to skip two name strings */
|
||||
ptr += add = skip_name_string (ptr, end);
|
||||
if (!add)
|
||||
return -1;
|
||||
ptr += add = skip_name_string (ptr, end);
|
||||
if (!add)
|
||||
return -1;
|
||||
break;
|
||||
|
||||
case GRUB_ACPI_OPCODE_SCOPE:
|
||||
{
|
||||
int scope_sleep_type;
|
||||
|
||||
@@ -56,7 +56,7 @@ GRUB_MOD_INIT(boottime)
|
||||
{
|
||||
cmd_boottime =
|
||||
grub_register_command ("boottime", grub_cmd_boottime,
|
||||
0, N_("Get boot time statistics."));
|
||||
0, N_("Show boot time statistics."));
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(boottime)
|
||||
|
||||
@@ -23,6 +23,8 @@
|
||||
#include <grub/i18n.h>
|
||||
#include <grub/disk.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
static grub_err_t
|
||||
grub_rescue_cmd_info (struct grub_command *cmd __attribute__ ((unused)),
|
||||
int argc __attribute__ ((unused)),
|
||||
|
||||
@@ -140,10 +140,13 @@ grub_cmd_cat (grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
grub_setcolorstate (GRUB_TERM_COLOR_STANDARD);
|
||||
}
|
||||
|
||||
grub_setcolorstate (GRUB_TERM_COLOR_HIGHLIGHT);
|
||||
for (j = 0; j < utcount; j++)
|
||||
grub_printf ("<%x>", (unsigned int) utbuf[j]);
|
||||
grub_setcolorstate (GRUB_TERM_COLOR_STANDARD);
|
||||
if (utcount)
|
||||
{
|
||||
grub_setcolorstate (GRUB_TERM_COLOR_HIGHLIGHT);
|
||||
for (j = 0; j < utcount; j++)
|
||||
grub_printf ("<%x>", (unsigned int) utbuf[j]);
|
||||
grub_setcolorstate (GRUB_TERM_COLOR_STANDARD);
|
||||
}
|
||||
|
||||
grub_xputs ("\n");
|
||||
grub_refresh ();
|
||||
|
||||
@@ -51,7 +51,7 @@ grub_cmd_lsefimmap (grub_command_t cmd __attribute__ ((unused)),
|
||||
|
||||
grub_printf
|
||||
("Type Physical start - end #Pages "
|
||||
" Size Attributes\n");
|
||||
" Size Attributes\n");
|
||||
memory_map_end = ADD_MEMORY_DESCRIPTOR (memory_map, map_size);
|
||||
for (desc = memory_map;
|
||||
desc < memory_map_end;
|
||||
@@ -74,7 +74,8 @@ grub_cmd_lsefimmap (grub_command_t cmd __attribute__ ((unused)),
|
||||
"ACPI-nvs",
|
||||
"MMIO ",
|
||||
"IO-ports",
|
||||
"PAL-code"
|
||||
"PAL-code",
|
||||
"persist ",
|
||||
};
|
||||
if (desc->type < ARRAY_SIZE (types_str))
|
||||
grub_printf ("%s ", types_str[desc->type]);
|
||||
@@ -87,21 +88,29 @@ grub_cmd_lsefimmap (grub_command_t cmd __attribute__ ((unused)),
|
||||
desc->physical_start + (desc->num_pages << 12) - 1,
|
||||
desc->num_pages);
|
||||
|
||||
size = desc->num_pages;
|
||||
size <<= (12 - 10);
|
||||
if (size < 1024)
|
||||
grub_printf (" %4" PRIuGRUB_UINT64_T "KB", size);
|
||||
size = desc->num_pages << 12; /* 4 KiB page size */
|
||||
/*
|
||||
* Since size is a multiple of 4 KiB, no need to handle units
|
||||
* of just Bytes (which would use a mask of 0x3ff).
|
||||
*
|
||||
* 14 characters would support the largest possible number of 4 KiB
|
||||
* pages that are not a multiple of larger units (e.g., MiB):
|
||||
* 17592186044415 (0xffffff_fffff000), but that uses a lot of
|
||||
* whitespace for a rare case. 6 characters usually suffices;
|
||||
* columns will be off if not, but this is preferable to rounding.
|
||||
*/
|
||||
if (size & 0xfffff)
|
||||
grub_printf (" %6" PRIuGRUB_UINT64_T "KiB", size >> 10);
|
||||
else if (size & 0x3fffffff)
|
||||
grub_printf (" %6" PRIuGRUB_UINT64_T "MiB", size >> 20);
|
||||
else if (size & 0xffffffffff)
|
||||
grub_printf (" %6" PRIuGRUB_UINT64_T "GiB", size >> 30);
|
||||
else if (size & 0x3ffffffffffff)
|
||||
grub_printf (" %6" PRIuGRUB_UINT64_T "TiB", size >> 40);
|
||||
else if (size & 0xfffffffffffffff)
|
||||
grub_printf (" %6" PRIuGRUB_UINT64_T "PiB", size >> 50);
|
||||
else
|
||||
{
|
||||
size /= 1024;
|
||||
if (size < 1024)
|
||||
grub_printf (" %4" PRIuGRUB_UINT64_T "MB", size);
|
||||
else
|
||||
{
|
||||
size /= 1024;
|
||||
grub_printf (" %4" PRIuGRUB_UINT64_T "GB", size);
|
||||
}
|
||||
}
|
||||
grub_printf (" %6" PRIuGRUB_UINT64_T "EiB", size >> 60);
|
||||
|
||||
attr = desc->attribute;
|
||||
if (attr & GRUB_EFI_MEMORY_RUNTIME)
|
||||
@@ -122,6 +131,12 @@ grub_cmd_lsefimmap (grub_command_t cmd __attribute__ ((unused)),
|
||||
grub_printf (" RP");
|
||||
if (attr & GRUB_EFI_MEMORY_XP)
|
||||
grub_printf (" XP");
|
||||
if (attr & GRUB_EFI_MEMORY_NV)
|
||||
grub_printf (" NV");
|
||||
if (attr & GRUB_EFI_MEMORY_MORE_RELIABLE)
|
||||
grub_printf (" MR");
|
||||
if (attr & GRUB_EFI_MEMORY_RO)
|
||||
grub_printf (" RO");
|
||||
|
||||
grub_printf ("\n");
|
||||
}
|
||||
|
||||
@@ -37,10 +37,20 @@ static const struct guid_mapping guid_mappings[] =
|
||||
{
|
||||
{ GRUB_EFI_ACPI_20_TABLE_GUID, "ACPI-2.0"},
|
||||
{ GRUB_EFI_ACPI_TABLE_GUID, "ACPI-1.0"},
|
||||
{ GRUB_EFI_CRC32_GUIDED_SECTION_EXTRACTION_GUID,
|
||||
"CRC32 GUIDED SECTION EXTRACTION"},
|
||||
{ GRUB_EFI_DEBUG_IMAGE_INFO_TABLE_GUID, "DEBUG IMAGE INFO"},
|
||||
{ GRUB_EFI_DXE_SERVICES_TABLE_GUID, "DXE SERVICES"},
|
||||
{ GRUB_EFI_HCDP_TABLE_GUID, "HCDP"},
|
||||
{ GRUB_EFI_HOB_LIST_GUID, "HOB LIST"},
|
||||
{ GRUB_EFI_LZMA_CUSTOM_DECOMPRESS_GUID, "LZMA CUSTOM DECOMPRESS"},
|
||||
{ GRUB_EFI_MEMORY_TYPE_INFORMATION_GUID, "MEMORY TYPE INFO"},
|
||||
{ GRUB_EFI_MPS_TABLE_GUID, "MPS"},
|
||||
{ GRUB_EFI_SAL_TABLE_GUID, "SAL"},
|
||||
{ GRUB_EFI_SMBIOS_TABLE_GUID, "SMBIOS"},
|
||||
{ GRUB_EFI_MPS_TABLE_GUID, "MPS"},
|
||||
{ GRUB_EFI_HCDP_TABLE_GUID, "HCDP"}
|
||||
{ GRUB_EFI_SYSTEM_RESOURCE_TABLE_GUID, "SYSTEM RESOURCE TABLE"},
|
||||
{ GRUB_EFI_TIANO_CUSTOM_DECOMPRESS_GUID, "TIANO CUSTOM DECOMPRESS"},
|
||||
{ GRUB_EFI_TSC_FREQUENCY_GUID, "TSC FREQUENCY"},
|
||||
};
|
||||
|
||||
static grub_err_t
|
||||
@@ -52,6 +62,7 @@ grub_cmd_lsefisystab (struct grub_command *cmd __attribute__ ((unused)),
|
||||
grub_efi_configuration_table_t *t;
|
||||
unsigned int i;
|
||||
|
||||
grub_printf ("Address: %p\n", st);
|
||||
grub_printf ("Signature: %016" PRIxGRUB_UINT64_T " revision: %08x\n",
|
||||
st->hdr.signature, st->hdr.revision);
|
||||
{
|
||||
|
||||
+68
-30
@@ -36,62 +36,66 @@ GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
static const struct grub_arg_option options[] = {
|
||||
{"is-i386-xen-pae-domu", 0, 0,
|
||||
N_("Check if FILE can be booted as i386 PAE xen unprivilegied guest"),
|
||||
N_("Check if FILE can be booted as i386 PAE Xen unprivileged guest kernel"),
|
||||
0, 0},
|
||||
{"is-x86_64-xen-domu", 0, 0,
|
||||
N_("Check if FILE can be booted as x86_64 xen unprivilegied guest"), 0, 0},
|
||||
N_("Check if FILE can be booted as x86_64 Xen unprivileged guest kernel"), 0, 0},
|
||||
{"is-x86-xen-dom0", 0, 0,
|
||||
N_("Check if FILE can be used as xen x86 privilegied guest kernel"), 0, 0},
|
||||
N_("Check if FILE can be used as Xen x86 privileged guest kernel"), 0, 0},
|
||||
{"is-x86-multiboot", 0, 0,
|
||||
N_("Check if FILE can be used as x86 multiboot kernel"), 0, 0},
|
||||
{"is-x86-multiboot2", 0, 0,
|
||||
N_("Check if FILE can be used as x86 multiboot2 kernel"), 0, 0},
|
||||
{"is-arm-linux", 0, 0,
|
||||
N_("Check if FILE is ARM linux"), 0, 0},
|
||||
N_("Check if FILE is ARM Linux"), 0, 0},
|
||||
{"is-arm64-linux", 0, 0,
|
||||
N_("Check if FILE is ARM64 Linux"), 0, 0},
|
||||
{"is-ia64-linux", 0, 0,
|
||||
N_("Check if FILE is IA64 linux"), 0, 0},
|
||||
N_("Check if FILE is IA64 Linux"), 0, 0},
|
||||
{"is-mips-linux", 0, 0,
|
||||
N_("Check if FILE is MIPS linux"), 0, 0},
|
||||
N_("Check if FILE is MIPS Linux"), 0, 0},
|
||||
{"is-mipsel-linux", 0, 0,
|
||||
N_("Check if FILE is MIPSEL linux"), 0, 0},
|
||||
N_("Check if FILE is MIPSEL Linux"), 0, 0},
|
||||
{"is-sparc64-linux", 0, 0,
|
||||
N_("Check if FILE is SPARC64 linux"), 0, 0},
|
||||
N_("Check if FILE is SPARC64 Linux"), 0, 0},
|
||||
{"is-powerpc-linux", 0, 0,
|
||||
N_("Check if FILE is POWERPC linux"), 0, 0},
|
||||
N_("Check if FILE is POWERPC Linux"), 0, 0},
|
||||
{"is-x86-linux", 0, 0,
|
||||
N_("Check if FILE is x86 linux"), 0, 0},
|
||||
N_("Check if FILE is x86 Linux"), 0, 0},
|
||||
{"is-x86-linux32", 0, 0,
|
||||
N_("Check if FILE is x86 linux supporting 32-bit protocol"), 0, 0},
|
||||
N_("Check if FILE is x86 Linux supporting 32-bit protocol"), 0, 0},
|
||||
{"is-x86-kfreebsd", 0, 0,
|
||||
N_("Check if FILE is x86 kfreebsd"), 0, 0},
|
||||
N_("Check if FILE is x86 kFreeBSD"), 0, 0},
|
||||
{"is-i386-kfreebsd", 0, 0,
|
||||
N_("Check if FILE is i386 kfreebsd"), 0, 0},
|
||||
N_("Check if FILE is i386 kFreeBSD"), 0, 0},
|
||||
{"is-x86_64-kfreebsd", 0, 0,
|
||||
N_("Check if FILE is x86_64 kfreebsd"), 0, 0},
|
||||
N_("Check if FILE is x86_64 kFreeBSD"), 0, 0},
|
||||
|
||||
{"is-x86-knetbsd", 0, 0,
|
||||
N_("Check if FILE is x86 knetbsd"), 0, 0},
|
||||
N_("Check if FILE is x86 kNetBSD"), 0, 0},
|
||||
{"is-i386-knetbsd", 0, 0,
|
||||
N_("Check if FILE is i386 knetbsd"), 0, 0},
|
||||
N_("Check if FILE is i386 kNetBSD"), 0, 0},
|
||||
{"is-x86_64-knetbsd", 0, 0,
|
||||
N_("Check if FILE is x86_64 knetbsd"), 0, 0},
|
||||
N_("Check if FILE is x86_64 kNetBSD"), 0, 0},
|
||||
|
||||
{"is-i386-efi", 0, 0,
|
||||
N_("Check if FILE is i386 EFI file"), 0, 0},
|
||||
{"is-x86_64-efi", 0, 0,
|
||||
N_("Check if FILE is x86-64 EFI file"), 0, 0},
|
||||
N_("Check if FILE is x86_64 EFI file"), 0, 0},
|
||||
{"is-ia64-efi", 0, 0,
|
||||
N_("Check if FILE is IA64 EFI file"), 0, 0},
|
||||
{"is-arm64-efi", 0, 0,
|
||||
N_("Check if FILE is ARM64 EFI file"), 0, 0},
|
||||
{"is-arm-efi", 0, 0,
|
||||
N_("Check if FILE is ARM EFI file"), 0, 0},
|
||||
{"is-hibernated-hiberfil", 0, 0,
|
||||
N_("Check if FILE is hiberfil.sys in hibernated state"), 0, 0},
|
||||
{"is-x86_64-xnu", 0, 0,
|
||||
N_("Check if FILE is x86_64 xnu (Mac OS X kernel)"), 0, 0},
|
||||
N_("Check if FILE is x86_64 XNU (Mac OS X kernel)"), 0, 0},
|
||||
{"is-i386-xnu", 0, 0,
|
||||
N_("Check if FILE is i386 xnu (Mac OS X kernel)"), 0, 0},
|
||||
N_("Check if FILE is i386 XNU (Mac OS X kernel)"), 0, 0},
|
||||
{"is-xnu-hibr", 0, 0,
|
||||
N_("Check if FILE is xnu (Mac OS X kernel) hibernated image"), 0, 0},
|
||||
N_("Check if FILE is XNU (Mac OS X kernel) hibernated image"), 0, 0},
|
||||
{"is-x86-bios-bootsector", 0, 0,
|
||||
N_("Check if FILE is BIOS bootsector"), 0, 0},
|
||||
{0, 0, 0, 0, 0, 0}
|
||||
@@ -105,6 +109,7 @@ enum
|
||||
IS_MULTIBOOT,
|
||||
IS_MULTIBOOT2,
|
||||
IS_ARM_LINUX,
|
||||
IS_ARM64_LINUX,
|
||||
IS_IA64_LINUX,
|
||||
IS_MIPS_LINUX,
|
||||
IS_MIPSEL_LINUX,
|
||||
@@ -121,6 +126,7 @@ enum
|
||||
IS_32_EFI,
|
||||
IS_64_EFI,
|
||||
IS_IA_EFI,
|
||||
IS_ARM64_EFI,
|
||||
IS_ARM_EFI,
|
||||
IS_HIBERNATED,
|
||||
IS_XNU64,
|
||||
@@ -377,14 +383,40 @@ grub_cmd_file (grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
}
|
||||
case IS_ARM_LINUX:
|
||||
{
|
||||
grub_uint32_t sig;
|
||||
grub_uint32_t sig, sig_pi;
|
||||
if (grub_file_read (file, &sig_pi, 4) != 4)
|
||||
break;
|
||||
/* Raspberry pi. */
|
||||
if (sig_pi == grub_cpu_to_le32_compile_time (0xea000006))
|
||||
{
|
||||
ret = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (grub_file_seek (file, 0x24) == (grub_size_t) -1)
|
||||
break;
|
||||
if (grub_file_read (file, &sig, 4) != 4)
|
||||
break;
|
||||
if (sig != grub_cpu_to_le32_compile_time (0x016f2818))
|
||||
if (sig == grub_cpu_to_le32_compile_time (0x016f2818))
|
||||
{
|
||||
ret = 1;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IS_ARM64_LINUX:
|
||||
{
|
||||
grub_uint32_t sig;
|
||||
|
||||
if (grub_file_seek (file, 0x38) == (grub_size_t) -1)
|
||||
break;
|
||||
ret = 1;
|
||||
if (grub_file_read (file, &sig, 4) != 4)
|
||||
break;
|
||||
if (sig == grub_cpu_to_le32_compile_time (0x644d5241))
|
||||
{
|
||||
ret = 1;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IS_PAE_DOMU ... IS_DOM0:
|
||||
@@ -444,8 +476,8 @@ grub_cmd_file (grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
be at least 12 bytes and aligned on a 4-byte boundary. */
|
||||
for (header = buffer;
|
||||
((char *) header <=
|
||||
(char *) buffer + len - (type == IS_MULTIBOOT2 ? 16 : 12))
|
||||
|| (header = 0); header += step)
|
||||
(char *) buffer + len - (type == IS_MULTIBOOT2 ? 16 : 12));
|
||||
header += step)
|
||||
{
|
||||
if (header[0] == magic
|
||||
&& !(grub_le_to_cpu32 (header[0])
|
||||
@@ -453,11 +485,12 @@ grub_cmd_file (grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
+ grub_le_to_cpu32 (header[2])
|
||||
+ (type == IS_MULTIBOOT2
|
||||
? grub_le_to_cpu32 (header[3]) : 0)))
|
||||
break;
|
||||
{
|
||||
ret = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (header != 0)
|
||||
ret = 1;
|
||||
grub_free (buffer);
|
||||
break;
|
||||
}
|
||||
@@ -535,6 +568,7 @@ grub_cmd_file (grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
case IS_32_EFI:
|
||||
case IS_64_EFI:
|
||||
case IS_IA_EFI:
|
||||
case IS_ARM64_EFI:
|
||||
case IS_ARM_EFI:
|
||||
{
|
||||
char signature[4];
|
||||
@@ -573,11 +607,15 @@ grub_cmd_file (grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
&& coff_head.machine !=
|
||||
grub_cpu_to_le16_compile_time (GRUB_PE32_MACHINE_IA64))
|
||||
break;
|
||||
if (type == IS_ARM64_EFI
|
||||
&& coff_head.machine !=
|
||||
grub_cpu_to_le16_compile_time (GRUB_PE32_MACHINE_ARM64))
|
||||
break;
|
||||
if (type == IS_ARM_EFI
|
||||
&& coff_head.machine !=
|
||||
grub_cpu_to_le16_compile_time (GRUB_PE32_MACHINE_ARMTHUMB_MIXED))
|
||||
break;
|
||||
if (type == IS_64_EFI || type == IS_64_EFI)
|
||||
if (type == IS_IA_EFI || type == IS_64_EFI || type == IS_ARM64_EFI)
|
||||
{
|
||||
struct grub_pe64_optional_header o64;
|
||||
if (grub_file_read (file, &o64, sizeof (o64)) != sizeof (o64))
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
|
||||
#include <grub/fileid.h>
|
||||
#include <grub/elfload.h>
|
||||
#include <grub/misc.h>
|
||||
|
||||
#pragma GCC diagnostic ignored "-Wcast-align"
|
||||
|
||||
@@ -39,10 +40,10 @@ grub_file_check_netbsdXX (grub_elf_t elf)
|
||||
return 0;
|
||||
|
||||
if (grub_file_seek (elf->file, elf->ehdr.ehdrXX.e_shoff) == (grub_off_t) -1)
|
||||
return 0;
|
||||
goto fail;
|
||||
|
||||
if (grub_file_read (elf->file, s0, shsize) != (grub_ssize_t) shsize)
|
||||
return 0;
|
||||
goto fail;
|
||||
|
||||
s = (Elf_Shdr *) ((char *) s0 + elf->ehdr.ehdrXX.e_shstrndx * shentsize);
|
||||
stroff = s->sh_offset;
|
||||
@@ -53,18 +54,21 @@ grub_file_check_netbsdXX (grub_elf_t elf)
|
||||
char name[sizeof(".note.netbsd.ident")];
|
||||
grub_memset (name, 0, sizeof (name));
|
||||
if (grub_file_seek (elf->file, stroff + s->sh_name) == (grub_off_t) -1)
|
||||
return grub_errno;
|
||||
goto fail;
|
||||
|
||||
if (grub_file_read (elf->file, name, sizeof (name)) != (grub_ssize_t) sizeof (name))
|
||||
{
|
||||
if (grub_errno)
|
||||
return grub_errno;
|
||||
goto fail;
|
||||
continue;
|
||||
}
|
||||
if (grub_memcmp (name, ".note.netbsd.ident",
|
||||
sizeof(".note.netbsd.ident")) != 0)
|
||||
continue;
|
||||
grub_free (s0);
|
||||
return 1;
|
||||
}
|
||||
fail:
|
||||
grub_free (s0);
|
||||
return 0;
|
||||
}
|
||||
@@ -101,7 +101,7 @@ grub_cmd_gptsync (grub_command_t cmd __attribute__ ((unused)),
|
||||
}
|
||||
|
||||
/* Check if it is valid. */
|
||||
if (mbr.signature != grub_cpu_to_le16 (GRUB_PC_PARTITION_SIGNATURE))
|
||||
if (mbr.signature != grub_cpu_to_le16_compile_time (GRUB_PC_PARTITION_SIGNATURE))
|
||||
{
|
||||
grub_device_close (dev);
|
||||
return grub_error (GRUB_ERR_BAD_PART_TABLE, "no signature");
|
||||
@@ -216,7 +216,7 @@ grub_cmd_gptsync (grub_command_t cmd __attribute__ ((unused)),
|
||||
first_sector--;
|
||||
mbr.entries[0].flag = 0;
|
||||
mbr.entries[0].type = GRUB_PC_PARTITION_TYPE_GPT_DISK;
|
||||
mbr.entries[0].start = grub_cpu_to_le32 (1);
|
||||
mbr.entries[0].start = grub_cpu_to_le32_compile_time (1);
|
||||
lba_to_chs (1,
|
||||
&(mbr.entries[0].start_sector),
|
||||
&(mbr.entries[0].start_cylinder),
|
||||
@@ -227,7 +227,7 @@ grub_cmd_gptsync (grub_command_t cmd __attribute__ ((unused)),
|
||||
&(mbr.entries[0].end_head));
|
||||
mbr.entries[0].length = grub_cpu_to_le32 (first_sector);
|
||||
|
||||
mbr.signature = grub_cpu_to_le16 (GRUB_PC_PARTITION_SIGNATURE);
|
||||
mbr.signature = grub_cpu_to_le16_compile_time (GRUB_PC_PARTITION_SIGNATURE);
|
||||
|
||||
if (grub_disk_write (dev->disk, 0, 0, sizeof (mbr), &mbr))
|
||||
{
|
||||
@@ -235,6 +235,8 @@ grub_cmd_gptsync (grub_command_t cmd __attribute__ ((unused)),
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
grub_device_close (dev);
|
||||
|
||||
grub_printf_ (N_("New MBR is written to `%s'\n"), args[0]);
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
|
||||
@@ -329,6 +329,7 @@ grub_cmd_hdparm (grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
break;
|
||||
}
|
||||
default:
|
||||
grub_disk_close (disk);
|
||||
return grub_error (GRUB_ERR_IO, "not an ATA device");
|
||||
}
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ GRUB_MOD_INIT(cmosdump)
|
||||
{
|
||||
cmd = grub_register_command ("cmosdump", grub_cmd_cmosdump,
|
||||
0,
|
||||
N_("Dump CMOS contents."));
|
||||
N_("Show raw dump of the CMOS contents."));
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(cmosdump)
|
||||
|
||||
@@ -45,7 +45,7 @@ static grub_err_t
|
||||
grub_cmd_cmostest (struct grub_command *cmd __attribute__ ((unused)),
|
||||
int argc, char *argv[])
|
||||
{
|
||||
int byte, bit;
|
||||
int byte = 0, bit = 0;
|
||||
grub_err_t err;
|
||||
grub_uint8_t value;
|
||||
|
||||
@@ -67,7 +67,7 @@ static grub_err_t
|
||||
grub_cmd_cmosclean (struct grub_command *cmd __attribute__ ((unused)),
|
||||
int argc, char *argv[])
|
||||
{
|
||||
int byte, bit;
|
||||
int byte = 0, bit = 0;
|
||||
grub_err_t err;
|
||||
grub_uint8_t value;
|
||||
|
||||
@@ -85,7 +85,7 @@ static grub_err_t
|
||||
grub_cmd_cmosset (struct grub_command *cmd __attribute__ ((unused)),
|
||||
int argc, char *argv[])
|
||||
{
|
||||
int byte, bit;
|
||||
int byte = 0, bit = 0;
|
||||
grub_err_t err;
|
||||
grub_uint8_t value;
|
||||
|
||||
@@ -109,9 +109,10 @@ GRUB_MOD_INIT(cmostest)
|
||||
N_("Test bit at BYTE:BIT in CMOS."));
|
||||
cmd_clean = grub_register_command ("cmosclean", grub_cmd_cmosclean,
|
||||
N_("BYTE:BIT"),
|
||||
N_("Clean bit at BYTE:BIT in CMOS."));
|
||||
N_("Clear bit at BYTE:BIT in CMOS."));
|
||||
cmd_set = grub_register_command ("cmosset", grub_cmd_cmosset,
|
||||
N_("BYTE:BIT"),
|
||||
/* TRANSLATORS: A bit may be either set (1) or clear (0). */
|
||||
N_("Set bit at BYTE:BIT in CMOS."));
|
||||
}
|
||||
|
||||
|
||||
@@ -39,9 +39,17 @@ static const char *descs[] = {
|
||||
[2] = "before RAM init",
|
||||
[3] = "after RAM init",
|
||||
[4] = "end of romstage",
|
||||
[5] = "start of verified boot",
|
||||
[6] = "end of verified boot",
|
||||
[8] = "start of RAM copy",
|
||||
[9] = "end of RAM copy",
|
||||
[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",
|
||||
[40] = "device configure",
|
||||
[50] = "device enable",
|
||||
@@ -109,7 +117,7 @@ GRUB_MOD_INIT(cbtime)
|
||||
{
|
||||
cmd_boottime =
|
||||
grub_register_command ("coreboot_boottime", grub_cmd_coreboot_boottime,
|
||||
0, N_("Get coreboot boot time statistics."));
|
||||
0, N_("Show coreboot boot time statistics."));
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(cbtime)
|
||||
|
||||
@@ -107,6 +107,14 @@ grub_cmd_play (grub_command_t cmd __attribute__ ((unused)),
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
if (!tempo)
|
||||
{
|
||||
grub_file_close (file);
|
||||
grub_error (GRUB_ERR_BAD_ARGUMENT, N_("Invalid tempo in %s"),
|
||||
args[0]);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
tempo = grub_le_to_cpu32 (tempo);
|
||||
grub_dprintf ("play","tempo = %d\n", tempo);
|
||||
|
||||
@@ -131,6 +139,13 @@ grub_cmd_play (grub_command_t cmd __attribute__ ((unused)),
|
||||
|
||||
tempo = grub_strtoul (args[0], &end, 0);
|
||||
|
||||
if (!tempo)
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_ARGUMENT, N_("Invalid tempo in %s"),
|
||||
args[0]);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
if (*end)
|
||||
/* Was not a number either, assume it was supposed to be a file name. */
|
||||
return grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"), args[0]);
|
||||
|
||||
@@ -292,7 +292,7 @@ find_key_code (char *key)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < sizeof (keysym_table) / sizeof (keysym_table[0]); i++)
|
||||
for (i = 0; i < ARRAY_SIZE(keysym_table); i++)
|
||||
{
|
||||
if (keysym_table[i].unshifted_name
|
||||
&& grub_strcmp (key, keysym_table[i].unshifted_name) == 0)
|
||||
@@ -311,7 +311,7 @@ find_ascii_code (char *key)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < sizeof (keysym_table) / sizeof (keysym_table[0]); i++)
|
||||
for (i = 0; i < ARRAY_SIZE(keysym_table); i++)
|
||||
{
|
||||
if (keysym_table[i].unshifted_name
|
||||
&& grub_strcmp (key, keysym_table[i].unshifted_name) == 0)
|
||||
@@ -352,15 +352,13 @@ grub_cmd_sendkey (grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < sizeof (simple_flag_offsets)
|
||||
/ sizeof (simple_flag_offsets[0]); i++)
|
||||
for (i = 0; i < ARRAY_SIZE(simple_flag_offsets); i++)
|
||||
grub_sendkey_set_simple_flag (simple_flag_offsets[i],
|
||||
grub_sendkey_parse_op(state[i]));
|
||||
}
|
||||
|
||||
/* Set noled. */
|
||||
noled = (state[sizeof (simple_flag_offsets)
|
||||
/ sizeof (simple_flag_offsets[0])].set);
|
||||
noled = (state[ARRAY_SIZE(simple_flag_offsets)].set);
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
@@ -173,8 +173,10 @@ grub_term_map_key (grub_keyboard_key_t code, int status)
|
||||
|
||||
key = map_key_core (code, status, &alt_gr_consumed);
|
||||
|
||||
if (key == 0 || key == GRUB_TERM_SHIFT)
|
||||
if (key == 0 || key == GRUB_TERM_SHIFT) {
|
||||
grub_printf ("Unknown key 0x%x detected\n", code);
|
||||
return GRUB_TERM_NO_KEY;
|
||||
}
|
||||
|
||||
if (status & GRUB_TERM_STATUS_CAPS)
|
||||
{
|
||||
|
||||
@@ -57,14 +57,20 @@ legacy_file (const char *filename)
|
||||
|
||||
file = grub_file_open (filename);
|
||||
if (! file)
|
||||
return grub_errno;
|
||||
{
|
||||
grub_free (suffix);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
menu = grub_env_get_menu ();
|
||||
if (! menu)
|
||||
{
|
||||
menu = grub_zalloc (sizeof (*menu));
|
||||
if (! menu)
|
||||
return grub_errno;
|
||||
{
|
||||
grub_free (suffix);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
grub_env_set_menu (menu);
|
||||
}
|
||||
@@ -77,6 +83,7 @@ legacy_file (const char *filename)
|
||||
if (!buf && grub_errno)
|
||||
{
|
||||
grub_file_close (file);
|
||||
grub_free (suffix);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
@@ -173,6 +180,8 @@ legacy_file (const char *filename)
|
||||
if (!args)
|
||||
{
|
||||
grub_file_close (file);
|
||||
grub_free (suffix);
|
||||
grub_free (entrysrc);
|
||||
return grub_errno;
|
||||
}
|
||||
args[0] = entryname;
|
||||
@@ -244,6 +253,7 @@ grub_cmd_legacy_kernel (struct grub_command *mycmd __attribute__ ((unused)),
|
||||
struct grub_command *cmd;
|
||||
char **cutargs;
|
||||
int cutargc;
|
||||
grub_err_t err = GRUB_ERR_NONE;
|
||||
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
@@ -305,6 +315,8 @@ grub_cmd_legacy_kernel (struct grub_command *mycmd __attribute__ ((unused)),
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
|
||||
|
||||
cutargs = grub_malloc (sizeof (cutargs[0]) * (argc - 1));
|
||||
if (!cutargs)
|
||||
return grub_errno;
|
||||
cutargc = argc - 1;
|
||||
grub_memcpy (cutargs + 1, args + 2, sizeof (cutargs[0]) * (argc - 2));
|
||||
cutargs[0] = args[0];
|
||||
@@ -324,7 +336,7 @@ grub_cmd_legacy_kernel (struct grub_command *mycmd __attribute__ ((unused)),
|
||||
if (!(cmd->func) (cmd, cutargc, cutargs))
|
||||
{
|
||||
kernel_type = LINUX;
|
||||
return GRUB_ERR_NONE;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
@@ -339,7 +351,7 @@ grub_cmd_legacy_kernel (struct grub_command *mycmd __attribute__ ((unused)),
|
||||
if (!(cmd->func) (cmd, argc, args))
|
||||
{
|
||||
kernel_type = MULTIBOOT;
|
||||
return GRUB_ERR_NONE;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
@@ -376,6 +388,8 @@ grub_cmd_legacy_kernel (struct grub_command *mycmd __attribute__ ((unused)),
|
||||
if (part && grub_strcmp (part->partmap->name, "msdos") == 0)
|
||||
bsd_slice = part->number;
|
||||
}
|
||||
if (dev)
|
||||
grub_device_close (dev);
|
||||
}
|
||||
|
||||
/* k*BSD didn't really work well with grub-legacy. */
|
||||
@@ -402,7 +416,7 @@ grub_cmd_legacy_kernel (struct grub_command *mycmd __attribute__ ((unused)),
|
||||
if (!(cmd->func) (cmd, cutargc, cutargs))
|
||||
{
|
||||
kernel_type = KFREEBSD;
|
||||
return GRUB_ERR_NONE;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
@@ -411,6 +425,8 @@ grub_cmd_legacy_kernel (struct grub_command *mycmd __attribute__ ((unused)),
|
||||
char **bsdargs;
|
||||
int bsdargc;
|
||||
char bsddevname[sizeof ("wdXXXXXXXXXXXXY")];
|
||||
int found = 0;
|
||||
|
||||
if (bsd_device == -1)
|
||||
{
|
||||
bsdargs = cutargs;
|
||||
@@ -421,6 +437,11 @@ grub_cmd_legacy_kernel (struct grub_command *mycmd __attribute__ ((unused)),
|
||||
char rbuf[3] = "-r";
|
||||
bsdargc = cutargc + 2;
|
||||
bsdargs = grub_malloc (sizeof (bsdargs[0]) * bsdargc);
|
||||
if (!bsdargs)
|
||||
{
|
||||
err = grub_errno;
|
||||
goto out;
|
||||
}
|
||||
grub_memcpy (bsdargs, args, argc * sizeof (bsdargs[0]));
|
||||
bsdargs[argc] = rbuf;
|
||||
bsdargs[argc + 1] = bsddevname;
|
||||
@@ -436,7 +457,8 @@ grub_cmd_legacy_kernel (struct grub_command *mycmd __attribute__ ((unused)),
|
||||
if (!(cmd->func) (cmd, bsdargc, bsdargs))
|
||||
{
|
||||
kernel_type = KNETBSD;
|
||||
return GRUB_ERR_NONE;
|
||||
found = 1;
|
||||
goto free_bsdargs;
|
||||
}
|
||||
}
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
@@ -449,20 +471,28 @@ grub_cmd_legacy_kernel (struct grub_command *mycmd __attribute__ ((unused)),
|
||||
if (!(cmd->func) (cmd, bsdargc, bsdargs))
|
||||
{
|
||||
kernel_type = KOPENBSD;
|
||||
return GRUB_ERR_NONE;
|
||||
found = 1;
|
||||
goto free_bsdargs;
|
||||
}
|
||||
}
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
free_bsdargs:
|
||||
if (bsdargs != cutargs)
|
||||
grub_free (bsdargs);
|
||||
if (found)
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
while (0);
|
||||
|
||||
return grub_error (GRUB_ERR_BAD_OS, "couldn't load file %s",
|
||||
args[0]);
|
||||
err = grub_error (GRUB_ERR_BAD_OS, "couldn't load file %s",
|
||||
args[0]);
|
||||
out:
|
||||
grub_free (cutargs);
|
||||
return err;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
@@ -523,15 +553,17 @@ grub_cmd_legacy_initrdnounzip (struct grub_command *mycmd __attribute__ ((unused
|
||||
char **newargs;
|
||||
grub_err_t err;
|
||||
char nounzipbuf[10] = "--nounzip";
|
||||
|
||||
cmd = grub_command_find ("module");
|
||||
if (!cmd)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("can't find command `%s'"),
|
||||
"module");
|
||||
|
||||
newargs = grub_malloc ((argc + 1) * sizeof (newargs[0]));
|
||||
if (!newargs)
|
||||
return grub_errno;
|
||||
grub_memcpy (newargs + 1, args, argc * sizeof (newargs[0]));
|
||||
newargs[0] = nounzipbuf;
|
||||
cmd = grub_command_find ("module");
|
||||
if (!cmd)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("can't find command `%s'"),
|
||||
"module");
|
||||
|
||||
err = cmd->func (cmd, argc + 1, newargs);
|
||||
grub_free (newargs);
|
||||
@@ -580,7 +612,7 @@ check_password_md5_real (const char *entered,
|
||||
GRUB_MD_MD5->write (ctx, entered, enteredlen);
|
||||
digest = GRUB_MD_MD5->read (ctx);
|
||||
GRUB_MD_MD5->final (ctx);
|
||||
memcpy (alt_result, digest, MD5_HASHLEN);
|
||||
grub_memcpy (alt_result, digest, MD5_HASHLEN);
|
||||
|
||||
GRUB_MD_MD5->init (ctx);
|
||||
GRUB_MD_MD5->write (ctx, entered, enteredlen);
|
||||
@@ -596,7 +628,7 @@ check_password_md5_real (const char *entered,
|
||||
|
||||
for (i = 0; i < 1000; i++)
|
||||
{
|
||||
memcpy (alt_result, digest, 16);
|
||||
grub_memcpy (alt_result, digest, 16);
|
||||
|
||||
GRUB_MD_MD5->init (ctx);
|
||||
if ((i & 1) != 0)
|
||||
|
||||
@@ -263,7 +263,7 @@ check_blocklists (grub_envblk_t envblk, struct blocklist *blocklists,
|
||||
for (q = p->next; q; q = q->next)
|
||||
{
|
||||
grub_disk_addr_t s1, s2;
|
||||
grub_disk_addr_t e1, e2, t;
|
||||
grub_disk_addr_t e1, e2;
|
||||
|
||||
s1 = p->sector;
|
||||
e1 = s1 + ((p->length + GRUB_DISK_SECTOR_SIZE - 1) >> GRUB_DISK_SECTOR_BITS);
|
||||
@@ -271,16 +271,7 @@ check_blocklists (grub_envblk_t envblk, struct blocklist *blocklists,
|
||||
s2 = q->sector;
|
||||
e2 = s2 + ((q->length + GRUB_DISK_SECTOR_SIZE - 1) >> GRUB_DISK_SECTOR_BITS);
|
||||
|
||||
if (s2 > s1)
|
||||
{
|
||||
t = s2;
|
||||
s2 = s1;
|
||||
s1 = t;
|
||||
t = e2;
|
||||
e2 = e1;
|
||||
e1 = t;
|
||||
}
|
||||
if (e1 > s2)
|
||||
if (s1 < e2 && s2 < e1)
|
||||
{
|
||||
/* This might be actually valid, but it is unbelievable that
|
||||
any filesystem makes such a silly allocation. */
|
||||
@@ -455,7 +446,7 @@ GRUB_MOD_INIT(loadenv)
|
||||
{
|
||||
cmd_load =
|
||||
grub_register_extcmd ("load_env", grub_cmd_load_env, 0,
|
||||
N_("[-f FILE] [-s|--skip-sig] [whitelisted_variable_name] [...]"),
|
||||
N_("[-f FILE] [-s|--skip-sig] [variable_name_to_whitelist] [...]"),
|
||||
N_("Load variables from environment block file."),
|
||||
options);
|
||||
cmd_list =
|
||||
|
||||
@@ -37,6 +37,8 @@ static const char *names[] =
|
||||
is required to save accross hibernations. */
|
||||
[GRUB_MEMORY_NVS] = N_("ACPI non-volatile storage RAM"),
|
||||
[GRUB_MEMORY_BADRAM] = N_("faulty RAM (BadRAM)"),
|
||||
[GRUB_MEMORY_PERSISTENT] = N_("persistent RAM"),
|
||||
[GRUB_MEMORY_PERSISTENT_LEGACY] = N_("persistent RAM (legacy)"),
|
||||
[GRUB_MEMORY_COREBOOT_TABLES] = N_("RAM holding coreboot tables"),
|
||||
[GRUB_MEMORY_CODE] = N_("RAM holding firmware code")
|
||||
};
|
||||
|
||||
@@ -37,7 +37,7 @@ struct find_node_context
|
||||
grub_uint64_t inode_found;
|
||||
char *dirname;
|
||||
enum
|
||||
{ NONE, FILE, DIR } found;
|
||||
{ FOUND_NONE, FOUND_FILE, FOUND_DIR } found;
|
||||
};
|
||||
|
||||
static int
|
||||
@@ -53,13 +53,13 @@ find_inode (const char *filename,
|
||||
&& grub_strcasecmp (ctx->dirname, filename) == 0)))
|
||||
{
|
||||
ctx->inode_found = info->inode;
|
||||
ctx->found = info->dir ? DIR : FILE;
|
||||
ctx->found = info->dir ? FOUND_DIR : FOUND_FILE;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
grub_err_t
|
||||
grub_mac_bless_inode (grub_device_t dev, grub_uint64_t inode, int is_dir,
|
||||
grub_mac_bless_inode (grub_device_t dev, grub_uint32_t inode, int is_dir,
|
||||
int intel)
|
||||
{
|
||||
grub_err_t err;
|
||||
@@ -106,7 +106,7 @@ grub_mac_bless_inode (grub_device_t dev, grub_uint64_t inode, int is_dir,
|
||||
ablk_size = grub_be_to_cpu32 (volheader.hfs.blksz);
|
||||
ablk_start = grub_be_to_cpu16 (volheader.hfs.first_block);
|
||||
embedded_offset = (ablk_start
|
||||
+ extent_start
|
||||
+ ((grub_uint64_t) extent_start)
|
||||
* (ablk_size >> GRUB_DISK_SECTOR_BITS));
|
||||
|
||||
err =
|
||||
@@ -174,8 +174,8 @@ grub_mac_bless_file (grub_device_t dev, const char *path_in, int intel)
|
||||
}
|
||||
grub_free (path);
|
||||
|
||||
return grub_mac_bless_inode (dev, ctx.inode_found, (ctx.found == DIR),
|
||||
intel);
|
||||
return grub_mac_bless_inode (dev, (grub_uint32_t) ctx.inode_found,
|
||||
(ctx.found == FOUND_DIR), intel);
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
@@ -183,7 +183,7 @@ grub_cmd_macbless (grub_command_t cmd, int argc, char **args)
|
||||
{
|
||||
char *device_name;
|
||||
char *path = 0;
|
||||
grub_device_t dev;
|
||||
grub_device_t dev = 0;
|
||||
grub_err_t err;
|
||||
|
||||
if (argc != 1)
|
||||
@@ -197,13 +197,12 @@ grub_cmd_macbless (grub_command_t cmd, int argc, char **args)
|
||||
else
|
||||
path = path + 1;
|
||||
|
||||
if (!path || *path == 0 || !device_name)
|
||||
if (!path || *path == 0 || !dev)
|
||||
{
|
||||
if (dev)
|
||||
grub_device_close (dev);
|
||||
|
||||
grub_free (device_name);
|
||||
grub_free (path);
|
||||
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid argument");
|
||||
}
|
||||
|
||||
@@ -57,6 +57,7 @@ get_uuid (const char *name, char **uuid, int getnative)
|
||||
if (!dev->disk)
|
||||
{
|
||||
grub_dprintf ("nativedisk", "Skipping non-disk\n");
|
||||
grub_device_close (dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -90,6 +91,7 @@ get_uuid (const char *name, char **uuid, int getnative)
|
||||
case GRUB_DISK_DEVICE_MEMDISK_ID:
|
||||
grub_dprintf ("nativedisk", "Skipping native disk %s\n",
|
||||
dev->disk->name);
|
||||
grub_device_close (dev);
|
||||
return 0;
|
||||
|
||||
/* FIXME: those probably need special handling. */
|
||||
@@ -196,7 +198,10 @@ grub_cmd_nativedisk (grub_command_t cmd __attribute__ ((unused)),
|
||||
return grub_errno;
|
||||
|
||||
if (get_uuid (NULL, &uuid_root, 0))
|
||||
return grub_errno;
|
||||
{
|
||||
grub_free (mods);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
prefdev = grub_file_get_device_name (prefix);
|
||||
if (grub_errno)
|
||||
@@ -208,6 +213,8 @@ grub_cmd_nativedisk (grub_command_t cmd __attribute__ ((unused)),
|
||||
if (get_uuid (prefdev, &uuid_prefix, 0))
|
||||
{
|
||||
grub_free (uuid_root);
|
||||
grub_free (prefdev);
|
||||
grub_free (mods);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
@@ -287,12 +294,15 @@ grub_cmd_nativedisk (grub_command_t cmd __attribute__ ((unused)),
|
||||
}
|
||||
grub_free (uuid_root);
|
||||
grub_free (uuid_prefix);
|
||||
grub_free (prefdev);
|
||||
grub_free (mods);
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
|
||||
fail:
|
||||
grub_free (uuid_root);
|
||||
grub_free (uuid_prefix);
|
||||
grub_free (prefdev);
|
||||
|
||||
for (i = 0; i < mods_loaded; i++)
|
||||
if (mods[i])
|
||||
@@ -300,6 +310,8 @@ grub_cmd_nativedisk (grub_command_t cmd __attribute__ ((unused)),
|
||||
mods[i]->fini = 0;
|
||||
grub_dl_unload (mods[i]);
|
||||
}
|
||||
grub_free (mods);
|
||||
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
|
||||
@@ -133,7 +133,7 @@ show_help (grub_device_t dev)
|
||||
}
|
||||
}
|
||||
if (! found)
|
||||
grub_printf_ (N_("Sorry no parttool is available for %s\n"),
|
||||
grub_printf_ (N_("Sorry, no parttool is available for %s\n"),
|
||||
dev->disk->partition->partmap->name);
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
@@ -243,11 +243,19 @@ grub_cmd_parttool (grub_command_t cmd __attribute__ ((unused)),
|
||||
}
|
||||
|
||||
if (argc == 1)
|
||||
return show_help (dev);
|
||||
{
|
||||
err = show_help (dev);
|
||||
grub_device_close (dev);
|
||||
return err;
|
||||
}
|
||||
|
||||
for (i = 1; i < argc; i++)
|
||||
if (grub_strcmp (args[i], "help") == 0)
|
||||
return show_help (dev);
|
||||
{
|
||||
err = show_help (dev);
|
||||
grub_device_close (dev);
|
||||
return err;
|
||||
}
|
||||
|
||||
parsed = (int *) grub_zalloc (argc * sizeof (int));
|
||||
|
||||
@@ -274,8 +282,12 @@ grub_cmd_parttool (grub_command_t cmd __attribute__ ((unused)),
|
||||
break;
|
||||
}
|
||||
if (! cur)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("unknown argument `%s'"),
|
||||
{
|
||||
grub_free (parsed);
|
||||
grub_device_close (dev);
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("unknown argument `%s'"),
|
||||
args[i]);
|
||||
}
|
||||
ptool = cur;
|
||||
pargs = (struct grub_parttool_args *)
|
||||
grub_zalloc (ptool->nargs * sizeof (struct grub_parttool_args));
|
||||
|
||||
@@ -45,6 +45,7 @@ check_password (const char *user, const char *entered, void *pin)
|
||||
grub_uint8_t *buf;
|
||||
struct pbkdf2_password *pass = pin;
|
||||
gcry_err_code_t err;
|
||||
grub_err_t ret;
|
||||
|
||||
buf = grub_malloc (pass->buflen);
|
||||
if (!buf)
|
||||
@@ -55,17 +56,17 @@ check_password (const char *user, const char *entered, void *pin)
|
||||
pass->salt, pass->saltlen, pass->c,
|
||||
buf, pass->buflen);
|
||||
if (err)
|
||||
ret = grub_crypto_gcry_error (err);
|
||||
else if (grub_crypto_memcmp (buf, pass->expected, pass->buflen) != 0)
|
||||
ret = GRUB_ACCESS_DENIED;
|
||||
else
|
||||
{
|
||||
grub_free (buf);
|
||||
return grub_crypto_gcry_error (err);
|
||||
grub_auth_authenticate (user);
|
||||
ret = GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
if (grub_crypto_memcmp (buf, pass->expected, pass->buflen) != 0)
|
||||
return GRUB_ACCESS_DENIED;
|
||||
|
||||
grub_auth_authenticate (user);
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
grub_free (buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int
|
||||
@@ -104,7 +105,10 @@ grub_cmd_password (grub_command_t cmd __attribute__ ((unused)),
|
||||
|
||||
pass->c = grub_strtoul (ptr, &ptr, 0);
|
||||
if (grub_errno)
|
||||
return grub_errno;
|
||||
{
|
||||
grub_free (pass);
|
||||
return grub_errno;
|
||||
}
|
||||
if (*ptr != '.')
|
||||
{
|
||||
grub_free (pass);
|
||||
|
||||
@@ -166,7 +166,7 @@ GRUB_MOD_INIT(pcidump)
|
||||
{
|
||||
cmd = grub_register_extcmd ("pcidump", grub_cmd_pcidump, 0,
|
||||
N_("[-s POSITION] [-d DEVICE]"),
|
||||
N_("Dump PCI configuration space."), options);
|
||||
N_("Show raw dump of the PCI configuration space."), options);
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(pcidump)
|
||||
|
||||
@@ -64,7 +64,7 @@ iterate_device (const char *name, void *data)
|
||||
/* Skip floppy drives when requested. */
|
||||
if (ctx->no_floppy &&
|
||||
name[0] == 'f' && name[1] == 'd' && name[2] >= '0' && name[2] <= '9')
|
||||
return 0;
|
||||
return 1;
|
||||
|
||||
#ifdef DO_SEARCH_FS_UUID
|
||||
#define compare_fn grub_strcasecmp
|
||||
@@ -210,10 +210,10 @@ try (struct search_ctx *ctx)
|
||||
/* Cache entry was outdated. Remove it. */
|
||||
if (!ctx->count)
|
||||
{
|
||||
*prev = cache_ent->next;
|
||||
grub_free (cache_ent->key);
|
||||
grub_free (cache_ent->value);
|
||||
grub_free (cache_ent);
|
||||
*prev = cache_ent->next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -175,7 +175,10 @@ grub_cmd_search (grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
var = "root";
|
||||
}
|
||||
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)
|
||||
grub_search_label (id, var, state[SEARCH_NO_FLOPPY].set,
|
||||
@@ -187,8 +190,10 @@ grub_cmd_search (grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
grub_search_fs_file (id, var, state[SEARCH_NO_FLOPPY].set,
|
||||
hints, nhints);
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -47,14 +47,14 @@ syslinux_file_getline (char **line, int cont __attribute__ ((unused)),
|
||||
static const struct grub_arg_option options[] =
|
||||
{
|
||||
{"root", 'r', 0,
|
||||
N_("root directory of the syslinux disk (default /)."),
|
||||
N_("root directory of the syslinux disk [default=/]."),
|
||||
N_("DIR"), ARG_TYPE_STRING},
|
||||
{"cwd", 'c', 0,
|
||||
N_("home directory of the syslinux config (default directory of configfile)."),
|
||||
N_("current directory of syslinux [default is parent directory of input file]."),
|
||||
N_("DIR"), ARG_TYPE_STRING},
|
||||
{"isolinux", 'i', 0, N_("assume isolinux."), 0, 0},
|
||||
{"pxelinux", 'p', 0, N_("assume pxelinux."), 0, 0},
|
||||
{"syslinux", 's', 0, N_("assume syslinux."), 0, 0},
|
||||
{"isolinux", 'i', 0, N_("assume input is an isolinux configuration file."), 0, 0},
|
||||
{"pxelinux", 'p', 0, N_("assume input is a pxelinux configuration file."), 0, 0},
|
||||
{"syslinux", 's', 0, N_("assume input is a syslinux configuration file."), 0, 0},
|
||||
{0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
@@ -119,7 +119,10 @@ syslinux_file (grub_extcmd_context_t ctxt, const char *filename)
|
||||
{
|
||||
menu = grub_zalloc (sizeof (*menu));
|
||||
if (! menu)
|
||||
return grub_errno;
|
||||
{
|
||||
grub_free (result);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
grub_env_set_menu (menu);
|
||||
}
|
||||
@@ -183,25 +186,25 @@ GRUB_MOD_INIT(syslinuxcfg)
|
||||
N_("FILE"),
|
||||
/* TRANSLATORS: "syslinux config" means
|
||||
"config as used by syslinux". */
|
||||
N_("Parse syslinux config in same context"),
|
||||
N_("Execute syslinux config in same context"),
|
||||
options);
|
||||
cmd_configfile
|
||||
= grub_register_extcmd ("syslinux_configfile",
|
||||
grub_cmd_syslinux_source, 0,
|
||||
N_("FILE"),
|
||||
N_("Parse syslinux config in new context"),
|
||||
N_("Execute syslinux config in new context"),
|
||||
options);
|
||||
cmd_source_extract
|
||||
= grub_register_extcmd ("extract_syslinux_entries_source",
|
||||
grub_cmd_syslinux_source, 0,
|
||||
N_("FILE"),
|
||||
N_("Parse syslinux config in same context taking only menu entries"),
|
||||
N_("Execute syslinux config in same context taking only menu entries"),
|
||||
options);
|
||||
cmd_configfile_extract
|
||||
= grub_register_extcmd ("extract_syslinux_entries_configfile",
|
||||
grub_cmd_syslinux_source, 0,
|
||||
N_("FILE"),
|
||||
N_("Parse syslinux config in new context taking only menu entries"),
|
||||
N_("Execute syslinux config in new context taking only menu entries"),
|
||||
options);
|
||||
}
|
||||
|
||||
|
||||
@@ -332,7 +332,7 @@ test_parse (char **args, int *argn, int argc)
|
||||
get_fileinfo (args[*argn + 1], &ctx);
|
||||
update_val (ctx.file_exists && ctx.file_info.dir, &ctx);
|
||||
(*argn) += 2;
|
||||
return ctx.or || ctx.and;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (grub_strcmp (args[*argn], "-e") == 0)
|
||||
@@ -340,7 +340,7 @@ test_parse (char **args, int *argn, int argc)
|
||||
get_fileinfo (args[*argn + 1], &ctx);
|
||||
update_val (ctx.file_exists, &ctx);
|
||||
(*argn) += 2;
|
||||
return ctx.or || ctx.and;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (grub_strcmp (args[*argn], "-f") == 0)
|
||||
@@ -349,7 +349,7 @@ test_parse (char **args, int *argn, int argc)
|
||||
/* FIXME: check for other types. */
|
||||
update_val (ctx.file_exists && ! ctx.file_info.dir, &ctx);
|
||||
(*argn) += 2;
|
||||
return ctx.or || ctx.and;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (grub_strcmp (args[*argn], "-s") == 0)
|
||||
@@ -362,7 +362,7 @@ test_parse (char **args, int *argn, int argc)
|
||||
grub_file_close (file);
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
(*argn) += 2;
|
||||
return ctx.or || ctx.and;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* String tests. */
|
||||
|
||||
@@ -80,7 +80,7 @@ grub_cmd_tr (grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
} else if (argc > 3)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "too many parameters");
|
||||
|
||||
if (argc <= 0 && (!s1 || !s2 || !input))
|
||||
if (!s1 || !s2 || !input)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "missing parameters");
|
||||
|
||||
if (grub_strlen (s1) != grub_strlen (s2))
|
||||
|
||||
+82
-26
@@ -33,6 +33,13 @@
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
struct grub_verified
|
||||
{
|
||||
grub_file_t file;
|
||||
void *buf;
|
||||
};
|
||||
typedef struct grub_verified *grub_verified_t;
|
||||
|
||||
enum
|
||||
{
|
||||
OPTION_SKIP_SIG = 0
|
||||
@@ -41,7 +48,7 @@ enum
|
||||
static const struct grub_arg_option options[] =
|
||||
{
|
||||
{"skip-sig", 's', 0,
|
||||
N_("Skip signature-checking of the signature file."), 0, ARG_TYPE_NONE},
|
||||
N_("Skip signature-checking of the public key file."), 0, ARG_TYPE_NONE},
|
||||
{0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
@@ -301,7 +308,7 @@ grub_load_public_key (grub_file_t f)
|
||||
if (!sk)
|
||||
goto fail;
|
||||
|
||||
grub_memset (fingerprint_context, 0, sizeof (fingerprint_context));
|
||||
grub_memset (fingerprint_context, 0, GRUB_MD_SHA1->contextsize);
|
||||
GRUB_MD_SHA1->init (fingerprint_context);
|
||||
GRUB_MD_SHA1->write (fingerprint_context, "\x99", 1);
|
||||
len_be = grub_cpu_to_be16 (len);
|
||||
@@ -317,19 +324,19 @@ grub_load_public_key (grub_file_t f)
|
||||
if (grub_file_read (f, &l, sizeof (l)) != sizeof (l))
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature"));
|
||||
goto fail;
|
||||
break;
|
||||
}
|
||||
|
||||
lb = (grub_be_to_cpu16 (l) + GRUB_CHAR_BIT - 1) / GRUB_CHAR_BIT;
|
||||
if (lb > READBUF_SIZE - sizeof (grub_uint16_t))
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature"));
|
||||
goto fail;
|
||||
break;
|
||||
}
|
||||
if (grub_file_read (f, buffer + sizeof (grub_uint16_t), lb) != (grub_ssize_t) lb)
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature"));
|
||||
goto fail;
|
||||
break;
|
||||
}
|
||||
grub_memcpy (buffer, &l, sizeof (l));
|
||||
|
||||
@@ -339,10 +346,16 @@ grub_load_public_key (grub_file_t f)
|
||||
buffer, lb + sizeof (grub_uint16_t), 0))
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature"));
|
||||
goto fail;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i < pkalgos[pk].nmpipub)
|
||||
{
|
||||
grub_free (sk);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
GRUB_MD_SHA1->final (fingerprint_context);
|
||||
|
||||
grub_memcpy (sk->fingerprint, GRUB_MD_SHA1->read (fingerprint_context), 20);
|
||||
@@ -447,7 +460,7 @@ grub_verify_signature_real (char *buf, grub_size_t size,
|
||||
grub_err_t err;
|
||||
grub_size_t i;
|
||||
gcry_mpi_t mpis[10];
|
||||
grub_uint8_t type;
|
||||
grub_uint8_t type = 0;
|
||||
|
||||
err = read_packet_header (sig, &type, &len);
|
||||
if (err)
|
||||
@@ -802,19 +815,39 @@ grub_cmd_verify_signature (grub_extcmd_context_t ctxt,
|
||||
|
||||
static int sec = 0;
|
||||
|
||||
static void
|
||||
verified_free (grub_verified_t verified)
|
||||
{
|
||||
if (verified)
|
||||
{
|
||||
grub_free (verified->buf);
|
||||
grub_free (verified);
|
||||
}
|
||||
}
|
||||
|
||||
static grub_ssize_t
|
||||
verified_read (struct grub_file *file, char *buf, grub_size_t len)
|
||||
{
|
||||
grub_memcpy (buf, (char *) file->data + file->offset, len);
|
||||
grub_verified_t verified = file->data;
|
||||
|
||||
grub_memcpy (buf, (char *) verified->buf + file->offset, len);
|
||||
return len;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
verified_close (struct grub_file *file)
|
||||
{
|
||||
grub_free (file->data);
|
||||
grub_verified_t verified = file->data;
|
||||
|
||||
grub_file_close (verified->file);
|
||||
verified_free (verified);
|
||||
file->data = 0;
|
||||
return GRUB_ERR_NONE;
|
||||
|
||||
/* device and name are freed by parent */
|
||||
file->device = 0;
|
||||
file->name = 0;
|
||||
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
struct grub_fs verified_fs =
|
||||
@@ -832,10 +865,13 @@ grub_pubkey_open (grub_file_t io, const char *filename)
|
||||
grub_err_t err;
|
||||
grub_file_filter_t curfilt[GRUB_FILE_FILTER_MAX];
|
||||
grub_file_t ret;
|
||||
grub_verified_t verified;
|
||||
|
||||
if (!sec)
|
||||
return io;
|
||||
if (io->device->disk && io->device->disk->id == GRUB_DISK_DEVICE_MEMDISK_ID)
|
||||
if (io->device->disk &&
|
||||
(io->device->disk->dev->id == GRUB_DISK_DEVICE_MEMDISK_ID
|
||||
|| io->device->disk->dev->id == GRUB_DISK_DEVICE_PROCFS_ID))
|
||||
return io;
|
||||
fsuf = grub_malloc (grub_strlen (filename) + sizeof (".sig"));
|
||||
if (!fsuf)
|
||||
@@ -855,7 +891,10 @@ grub_pubkey_open (grub_file_t io, const char *filename)
|
||||
|
||||
ret = grub_malloc (sizeof (*ret));
|
||||
if (!ret)
|
||||
return NULL;
|
||||
{
|
||||
grub_file_close (sig);
|
||||
return NULL;
|
||||
}
|
||||
*ret = *io;
|
||||
|
||||
ret->fs = &verified_fs;
|
||||
@@ -864,29 +903,46 @@ grub_pubkey_open (grub_file_t io, const char *filename)
|
||||
{
|
||||
grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
|
||||
"big file signature isn't implemented yet");
|
||||
return NULL;
|
||||
}
|
||||
ret->data = grub_malloc (ret->size);
|
||||
if (!ret->data)
|
||||
{
|
||||
grub_file_close (sig);
|
||||
grub_free (ret);
|
||||
return NULL;
|
||||
}
|
||||
if (grub_file_read (io, ret->data, ret->size) != (grub_ssize_t) ret->size)
|
||||
verified = grub_malloc (sizeof (*verified));
|
||||
if (!verified)
|
||||
{
|
||||
grub_file_close (sig);
|
||||
grub_free (ret);
|
||||
return NULL;
|
||||
}
|
||||
verified->buf = grub_malloc (ret->size);
|
||||
if (!verified->buf)
|
||||
{
|
||||
grub_file_close (sig);
|
||||
grub_free (verified);
|
||||
grub_free (ret);
|
||||
return NULL;
|
||||
}
|
||||
if (grub_file_read (io, verified->buf, ret->size) != (grub_ssize_t) ret->size)
|
||||
{
|
||||
if (!grub_errno)
|
||||
grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"),
|
||||
filename);
|
||||
grub_file_close (sig);
|
||||
verified_free (verified);
|
||||
grub_free (ret);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
err = grub_verify_signature_real (ret->data, ret->size, 0, sig, NULL);
|
||||
err = grub_verify_signature_real (verified->buf, ret->size, 0, sig, NULL);
|
||||
grub_file_close (sig);
|
||||
if (err)
|
||||
return NULL;
|
||||
io->device = 0;
|
||||
io->name = 0;
|
||||
grub_file_close (io);
|
||||
{
|
||||
verified_free (verified);
|
||||
grub_free (ret);
|
||||
return NULL;
|
||||
}
|
||||
verified->file = io;
|
||||
ret->data = verified;
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -966,14 +1022,14 @@ GRUB_MOD_INIT(verify)
|
||||
options);
|
||||
cmd_trust = grub_register_extcmd ("trust", grub_cmd_trust, 0,
|
||||
N_("[-s|--skip-sig] PUBKEY_FILE"),
|
||||
N_("Add PKFILE to trusted keys."),
|
||||
N_("Add PUBKEY_FILE to trusted keys."),
|
||||
options);
|
||||
cmd_list = grub_register_command ("list_trusted", grub_cmd_list,
|
||||
0,
|
||||
N_("List trusted keys."));
|
||||
N_("Show the list of trusted keys."));
|
||||
cmd_distrust = grub_register_command ("distrust", grub_cmd_distrust,
|
||||
N_("PUBKEY_ID"),
|
||||
N_("Remove KEYID from trusted keys."));
|
||||
N_("Remove PUBKEY_ID from trusted keys."));
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(verify)
|
||||
|
||||
@@ -245,7 +245,10 @@ match_devices_iter (const char *name, void *data)
|
||||
|
||||
t = grub_realloc (ctx->devs, sizeof (char*) * (ctx->ndev + 2));
|
||||
if (! t)
|
||||
return 1;
|
||||
{
|
||||
grub_free (buffer);
|
||||
return 1;
|
||||
}
|
||||
|
||||
ctx->devs = t;
|
||||
ctx->devs[ctx->ndev++] = buffer;
|
||||
@@ -290,7 +293,8 @@ struct match_files_ctx
|
||||
|
||||
/* Helper for match_files. */
|
||||
static int
|
||||
match_files_iter (const char *name, const struct grub_dirhook_info *info,
|
||||
match_files_iter (const char *name,
|
||||
const struct grub_dirhook_info *info __attribute__((unused)),
|
||||
void *data)
|
||||
{
|
||||
struct match_files_ctx *ctx = data;
|
||||
|
||||
@@ -78,9 +78,9 @@ static grub_command_t cmd_ls, cmd_cat;
|
||||
GRUB_MOD_INIT (lsxen)
|
||||
{
|
||||
cmd_ls = grub_register_command ("xen_ls", grub_cmd_lsxen, N_("[DIR]"),
|
||||
N_("List XEN storage."));
|
||||
N_("List Xen storage."));
|
||||
cmd_cat = grub_register_command ("xen_cat", grub_cmd_catxen, N_("[DIR]"),
|
||||
N_("List XEN storage."));
|
||||
N_("List Xen storage."));
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI (lsxen)
|
||||
|
||||
@@ -72,13 +72,13 @@ AF_merge (const gcry_md_spec_t * hash, grub_uint8_t * src, grub_uint8_t * dst,
|
||||
grub_size_t i;
|
||||
grub_uint8_t *bufblock;
|
||||
|
||||
if (hash->mdlen > GRUB_CRYPTO_MAX_MDLEN || hash->mdlen == 0)
|
||||
return GPG_ERR_INV_ARG;
|
||||
|
||||
bufblock = grub_zalloc (blocksize);
|
||||
if (bufblock == NULL)
|
||||
return GPG_ERR_OUT_OF_MEMORY;
|
||||
|
||||
if (hash->mdlen > GRUB_CRYPTO_MAX_MDLEN)
|
||||
return GPG_ERR_INV_ARG;
|
||||
|
||||
grub_memset (bufblock, 0, blocksize);
|
||||
for (i = 0; i < blocknumbers - 1; i++)
|
||||
{
|
||||
|
||||
+51
-28
@@ -32,7 +32,7 @@ GRUB_MOD_LICENSE ("GPLv3+");
|
||||
struct grub_ahci_cmd_head
|
||||
{
|
||||
grub_uint32_t config;
|
||||
grub_uint32_t transfered;
|
||||
grub_uint32_t transferred;
|
||||
grub_uint64_t command_table_base;
|
||||
grub_uint32_t unused[4];
|
||||
};
|
||||
@@ -194,13 +194,11 @@ grub_ahci_pciinit (grub_pci_device_t dev,
|
||||
return 0;
|
||||
|
||||
addr = grub_pci_make_address (dev, GRUB_PCI_REG_COMMAND);
|
||||
grub_pci_write_word (addr, grub_pci_read_word (addr) |
|
||||
GRUB_PCI_COMMAND_IO_ENABLED
|
||||
| GRUB_PCI_COMMAND_MEM_ENABLED
|
||||
| GRUB_PCI_COMMAND_BUS_MASTER);
|
||||
grub_pci_write_word (addr, grub_pci_read_word (addr)
|
||||
| GRUB_PCI_COMMAND_MEM_ENABLED | GRUB_PCI_COMMAND_BUS_MASTER);
|
||||
|
||||
hba = grub_pci_device_map_range (dev, bar & GRUB_PCI_ADDR_MEM_MASK,
|
||||
sizeof (hba));
|
||||
sizeof (*hba));
|
||||
grub_dprintf ("ahci", "dev: %x:%x.%x\n", dev.bus, dev.device, dev.function);
|
||||
|
||||
grub_dprintf ("ahci", "tfd[0]: %x\n",
|
||||
@@ -324,7 +322,7 @@ grub_ahci_pciinit (grub_pci_device_t dev,
|
||||
|
||||
grub_dprintf ("ahci", "GLC:%x\n", hba->global_control);
|
||||
|
||||
nports = (hba->cap & GRUB_AHCI_HBA_CAP_NPORTS_MASK) + 1;
|
||||
nports = (GRUB_AHCI_HBA_CAP_NPORTS_MASK) + 1;
|
||||
|
||||
grub_dprintf ("ahci", "%d AHCI ports, PI = 0x%x\n", nports,
|
||||
hba->ports_implemented);
|
||||
@@ -357,10 +355,10 @@ grub_ahci_pciinit (grub_pci_device_t dev,
|
||||
if (adevs[i])
|
||||
{
|
||||
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]->command_list_chunk = grub_memalign_dma32 (1024, sizeof (struct grub_ahci_cmd_head));
|
||||
adevs[i]->command_list_chunk = grub_memalign_dma32 (1024, sizeof (struct grub_ahci_cmd_head) * 32);
|
||||
if (!adevs[i]->command_list_chunk)
|
||||
{
|
||||
adevs[i] = 0;
|
||||
@@ -378,6 +376,12 @@ grub_ahci_pciinit (grub_pci_device_t dev,
|
||||
|
||||
adevs[i]->command_list = grub_dma_get_virt (adevs[i]->command_list_chunk);
|
||||
adevs[i]->command_table = grub_dma_get_virt (adevs[i]->command_table_chunk);
|
||||
|
||||
grub_memset ((void *) adevs[i]->command_list, 0,
|
||||
sizeof (struct grub_ahci_cmd_table));
|
||||
grub_memset ((void *) adevs[i]->command_table, 0,
|
||||
sizeof (struct grub_ahci_cmd_head) * 32);
|
||||
|
||||
adevs[i]->command_list->command_table_base
|
||||
= grub_dma_get_phys (adevs[i]->command_table_chunk);
|
||||
|
||||
@@ -436,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].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]->rfis = grub_memalign_dma32 (4096,
|
||||
@@ -450,6 +454,7 @@ grub_ahci_pciinit (grub_pci_device_t dev,
|
||||
adevs[i]->hba->ports[adevs[i]->port].fis_base = grub_dma_get_phys (adevs[i]->rfis);
|
||||
adevs[i]->hba->ports[adevs[i]->port].command_list_base
|
||||
= grub_dma_get_phys (adevs[i]->command_list_chunk);
|
||||
adevs[i]->hba->ports[adevs[i]->port].command_issue = 0;
|
||||
adevs[i]->hba->ports[adevs[i]->port].command |= GRUB_AHCI_HBA_PORT_CMD_FRE;
|
||||
}
|
||||
|
||||
@@ -475,7 +480,7 @@ grub_ahci_pciinit (grub_pci_device_t dev,
|
||||
for (i = 0; i < nports; 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);
|
||||
fr_running |= (1 << i);
|
||||
|
||||
@@ -483,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 |= 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);
|
||||
}
|
||||
|
||||
@@ -510,26 +515,26 @@ grub_ahci_pciinit (grub_pci_device_t dev,
|
||||
for (i = 0; i < nports; 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].command |= GRUB_AHCI_HBA_PORT_CMD_POWER_ON;
|
||||
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 = ~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);
|
||||
|
||||
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 -
|
||||
(char *) adevs[i]->hba),
|
||||
adevs[i]->hba->ports[adevs[i]->port].task_file_data,
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -537,17 +542,19 @@ grub_ahci_pciinit (grub_pci_device_t dev,
|
||||
for (i = 0; i < nports; 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 -
|
||||
(char *) adevs[i]->hba),
|
||||
adevs[i]->hba->ports[adevs[i]->port].task_file_data,
|
||||
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].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;
|
||||
grub_memset (&parms2, 0, sizeof (parms2));
|
||||
@@ -560,14 +567,14 @@ grub_ahci_pciinit (grub_pci_device_t dev,
|
||||
while (grub_get_time_ms () < endtime)
|
||||
{
|
||||
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;
|
||||
if (i == nports)
|
||||
break;
|
||||
}
|
||||
|
||||
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);
|
||||
failed_adevs[i] = adevs[i];
|
||||
@@ -596,6 +603,9 @@ grub_ahci_pciinit (grub_pci_device_t dev,
|
||||
failed_adevs[i] = adevs[i];
|
||||
adevs[i] = 0;
|
||||
}
|
||||
|
||||
grub_dprintf ("ahci", "cleaning up failed devs\n");
|
||||
|
||||
for (i = 0; i < nports; i++)
|
||||
if (failed_adevs[i] && (fr_running & (1 << i)))
|
||||
failed_adevs[i]->hba->ports[failed_adevs[i]->port].command &= ~GRUB_AHCI_HBA_PORT_CMD_FRE;
|
||||
@@ -621,6 +631,10 @@ grub_ahci_pciinit (grub_pci_device_t dev,
|
||||
if (adevs[i] && (adevs[i]->hba->ports[adevs[i]->port].sig >> 16) == 0xeb14)
|
||||
adevs[i]->atapi = 1;
|
||||
|
||||
addr = grub_pci_make_address (dev, GRUB_PCI_REG_COMMAND);
|
||||
grub_pci_write_word (addr, grub_pci_read_word (addr)
|
||||
| GRUB_PCI_COMMAND_BUS_MASTER);
|
||||
|
||||
for (i = 0; i < nports; i++)
|
||||
if (adevs[i])
|
||||
{
|
||||
@@ -847,6 +861,12 @@ grub_ahci_reset_port (struct grub_ahci_device *dev, int force)
|
||||
{
|
||||
struct grub_disk_ata_pass_through_parms parms2;
|
||||
dev->hba->ports[dev->port].command &= ~GRUB_AHCI_HBA_PORT_CMD_ST;
|
||||
dev->hba->ports[dev->port].command_issue = 0;
|
||||
dev->command_list[0].config = 0;
|
||||
dev->command_table[0].prdt[0].unused = 0;
|
||||
dev->command_table[0].prdt[0].size = 0;
|
||||
dev->command_table[0].prdt[0].data_base = 0;
|
||||
|
||||
endtime = grub_get_time_ms () + 1000;
|
||||
while ((dev->hba->ports[dev->port].command & GRUB_AHCI_HBA_PORT_CMD_CR))
|
||||
if (grub_get_time_ms () > endtime)
|
||||
@@ -914,7 +934,10 @@ grub_ahci_readwrite_real (struct grub_ahci_device *dev,
|
||||
if (parms->size > GRUB_AHCI_PRDT_MAX_CHUNK_LENGTH)
|
||||
return grub_error (GRUB_ERR_BUG, "too big data buffer");
|
||||
|
||||
bufc = grub_memalign_dma32 (1024, parms->size + (parms->size & 1));
|
||||
if (parms->size)
|
||||
bufc = grub_memalign_dma32 (1024, parms->size + (parms->size & 1));
|
||||
else
|
||||
bufc = grub_memalign_dma32 (1024, 512);
|
||||
|
||||
grub_dprintf ("ahci", "AHCI tfd = %x, CL=%p\n",
|
||||
dev->hba->ports[dev->port].task_file_data,
|
||||
@@ -924,14 +947,14 @@ grub_ahci_readwrite_real (struct grub_ahci_device *dev,
|
||||
= (5 << GRUB_AHCI_CONFIG_CFIS_LENGTH_SHIFT)
|
||||
// | GRUB_AHCI_CONFIG_CLEAR_R_OK
|
||||
| (0 << GRUB_AHCI_CONFIG_PMP_SHIFT)
|
||||
| (1 << GRUB_AHCI_CONFIG_PRDT_LENGTH_SHIFT)
|
||||
| ((parms->size ? 1 : 0) << GRUB_AHCI_CONFIG_PRDT_LENGTH_SHIFT)
|
||||
| (parms->cmdsize ? GRUB_AHCI_CONFIG_ATAPI : 0)
|
||||
| (parms->write ? GRUB_AHCI_CONFIG_WRITE : GRUB_AHCI_CONFIG_READ)
|
||||
| (parms->taskfile.cmd == 8 ? (1 << 8) : 0);
|
||||
grub_dprintf ("ahci", "AHCI tfd = %x\n",
|
||||
dev->hba->ports[dev->port].task_file_data);
|
||||
|
||||
dev->command_list[0].transfered = 0;
|
||||
dev->command_list[0].transferred = 0;
|
||||
dev->command_list[0].command_table_base
|
||||
= grub_dma_get_phys (dev->command_table_chunk);
|
||||
|
||||
@@ -981,7 +1004,7 @@ grub_ahci_readwrite_real (struct grub_ahci_device *dev,
|
||||
if (parms->write)
|
||||
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",
|
||||
dev->hba->ports[dev->port].task_file_data);
|
||||
grub_dprintf ("ahci", "AHCI inten = %x\n",
|
||||
@@ -1001,7 +1024,7 @@ grub_ahci_readwrite_real (struct grub_ahci_device *dev,
|
||||
grub_dprintf ("ahci", "AHCI tfd = %x\n",
|
||||
dev->hba->ports[dev->port].task_file_data);
|
||||
|
||||
endtime = grub_get_time_ms () + (spinup ? 10000 : 5000);
|
||||
endtime = grub_get_time_ms () + (spinup ? 20000 : 20000);
|
||||
while ((dev->hba->ports[dev->port].command_issue & 1))
|
||||
if (grub_get_time_ms () > endtime)
|
||||
{
|
||||
@@ -1021,7 +1044,7 @@ grub_ahci_readwrite_real (struct grub_ahci_device *dev,
|
||||
dev->hba->ports[dev->port].command_issue,
|
||||
dev->hba->ports[dev->port].intstatus,
|
||||
dev->hba->ports[dev->port].task_file_data,
|
||||
dev->command_list[0].transfered,
|
||||
dev->command_list[0].transferred,
|
||||
dev->hba->ports[dev->port].sata_error,
|
||||
((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x00],
|
||||
((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x18]);
|
||||
|
||||
@@ -216,6 +216,12 @@ grub_ata_setaddress (struct grub_ata *dev,
|
||||
unsigned int head;
|
||||
unsigned int sect;
|
||||
|
||||
if (dev->sectors_per_track == 0
|
||||
|| dev->heads == 0)
|
||||
return grub_error (GRUB_ERR_OUT_OF_RANGE,
|
||||
"sector %d cannot be addressed "
|
||||
"using CHS addressing", sector);
|
||||
|
||||
/* Calculate the sector, cylinder and head to use. */
|
||||
sect = ((grub_uint32_t) sector % dev->sectors_per_track) + 1;
|
||||
cylinder = (((grub_uint32_t) sector / dev->sectors_per_track)
|
||||
|
||||
+61
-37
@@ -25,6 +25,7 @@
|
||||
#include <grub/fs.h>
|
||||
#include <grub/file.h>
|
||||
#include <grub/procfs.h>
|
||||
#include <grub/partition.h>
|
||||
|
||||
#ifdef GRUB_UTIL
|
||||
#include <grub/emu/hostdisk.h>
|
||||
@@ -110,20 +111,23 @@ grub_crypto_pcbc_decrypt (grub_crypto_cipher_handle_t cipher,
|
||||
{
|
||||
grub_uint8_t *inptr, *outptr, *end;
|
||||
grub_uint8_t ivt[GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE];
|
||||
if (cipher->cipher->blocksize > GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE)
|
||||
return GPG_ERR_INV_ARG;
|
||||
grub_size_t blocksize;
|
||||
if (!cipher->cipher->decrypt)
|
||||
return GPG_ERR_NOT_SUPPORTED;
|
||||
if (size % cipher->cipher->blocksize != 0)
|
||||
blocksize = cipher->cipher->blocksize;
|
||||
if (blocksize == 0 || (((blocksize - 1) & blocksize) != 0)
|
||||
|| ((size & (blocksize - 1)) != 0))
|
||||
return GPG_ERR_INV_ARG;
|
||||
if (blocksize > GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE)
|
||||
return GPG_ERR_INV_ARG;
|
||||
end = (grub_uint8_t *) in + size;
|
||||
for (inptr = in, outptr = out; inptr < end;
|
||||
inptr += cipher->cipher->blocksize, outptr += cipher->cipher->blocksize)
|
||||
inptr += blocksize, outptr += blocksize)
|
||||
{
|
||||
grub_memcpy (ivt, inptr, cipher->cipher->blocksize);
|
||||
grub_memcpy (ivt, inptr, blocksize);
|
||||
cipher->cipher->decrypt (cipher->ctx, outptr, inptr);
|
||||
grub_crypto_xor (outptr, outptr, iv, cipher->cipher->blocksize);
|
||||
grub_crypto_xor (iv, ivt, outptr, cipher->cipher->blocksize);
|
||||
grub_crypto_xor (outptr, outptr, iv, blocksize);
|
||||
grub_crypto_xor (iv, ivt, outptr, blocksize);
|
||||
}
|
||||
return GPG_ERR_NO_ERROR;
|
||||
}
|
||||
@@ -135,20 +139,23 @@ grub_crypto_pcbc_encrypt (grub_crypto_cipher_handle_t cipher,
|
||||
{
|
||||
grub_uint8_t *inptr, *outptr, *end;
|
||||
grub_uint8_t ivt[GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE];
|
||||
if (cipher->cipher->blocksize > GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE)
|
||||
return GPG_ERR_INV_ARG;
|
||||
if (!cipher->cipher->decrypt)
|
||||
grub_size_t blocksize;
|
||||
if (!cipher->cipher->encrypt)
|
||||
return GPG_ERR_NOT_SUPPORTED;
|
||||
if (size % cipher->cipher->blocksize != 0)
|
||||
blocksize = cipher->cipher->blocksize;
|
||||
if (blocksize > GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE)
|
||||
return GPG_ERR_INV_ARG;
|
||||
if (blocksize == 0 || (((blocksize - 1) & blocksize) != 0)
|
||||
|| ((size & (blocksize - 1)) != 0))
|
||||
return GPG_ERR_INV_ARG;
|
||||
end = (grub_uint8_t *) in + size;
|
||||
for (inptr = in, outptr = out; inptr < end;
|
||||
inptr += cipher->cipher->blocksize, outptr += cipher->cipher->blocksize)
|
||||
inptr += blocksize, outptr += blocksize)
|
||||
{
|
||||
grub_memcpy (ivt, inptr, cipher->cipher->blocksize);
|
||||
grub_crypto_xor (outptr, outptr, iv, cipher->cipher->blocksize);
|
||||
grub_memcpy (ivt, inptr, blocksize);
|
||||
grub_crypto_xor (outptr, outptr, iv, blocksize);
|
||||
cipher->cipher->encrypt (cipher->ctx, outptr, inptr);
|
||||
grub_crypto_xor (iv, ivt, outptr, cipher->cipher->blocksize);
|
||||
grub_crypto_xor (iv, ivt, outptr, blocksize);
|
||||
}
|
||||
return GPG_ERR_NO_ERROR;
|
||||
}
|
||||
@@ -372,11 +379,13 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
|
||||
break;
|
||||
case GRUB_CRYPTODISK_MODE_ECB:
|
||||
if (do_encrypt)
|
||||
grub_crypto_ecb_encrypt (dev->cipher, data + i, data + i,
|
||||
(1U << dev->log_sector_size));
|
||||
err = grub_crypto_ecb_encrypt (dev->cipher, data + i, data + i,
|
||||
(1U << dev->log_sector_size));
|
||||
else
|
||||
grub_crypto_ecb_decrypt (dev->cipher, data + i, data + i,
|
||||
(1U << dev->log_sector_size));
|
||||
err = grub_crypto_ecb_decrypt (dev->cipher, data + i, data + i,
|
||||
(1U << dev->log_sector_size));
|
||||
if (err)
|
||||
return err;
|
||||
break;
|
||||
default:
|
||||
return GPG_ERR_NOT_IMPLEMENTED;
|
||||
@@ -710,6 +719,7 @@ grub_cryptodisk_insert (grub_cryptodisk_t newdev, const char *name,
|
||||
newdev->id = last_cryptodisk_id++;
|
||||
newdev->source_id = source->id;
|
||||
newdev->source_dev_id = source->dev->id;
|
||||
newdev->partition_start = grub_partition_get_start (source->partition);
|
||||
newdev->next = cryptodisk_list;
|
||||
cryptodisk_list = newdev;
|
||||
|
||||
@@ -732,7 +742,9 @@ grub_cryptodisk_get_by_source_disk (grub_disk_t disk)
|
||||
grub_cryptodisk_t dev;
|
||||
for (dev = cryptodisk_list; dev != NULL; dev = dev->next)
|
||||
if (dev->source_id == disk->id && dev->source_dev_id == disk->dev->id)
|
||||
return dev;
|
||||
if ((disk->partition && grub_partition_get_start (disk->partition) == dev->partition_start) ||
|
||||
(!disk->partition && dev->partition_start == 0))
|
||||
return dev;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -753,6 +765,7 @@ grub_cryptodisk_cheat_insert (grub_cryptodisk_t newdev, const char *name,
|
||||
newdev->cheat_fd = GRUB_UTIL_FD_INVALID;
|
||||
newdev->source_id = source->id;
|
||||
newdev->source_dev_id = source->dev->id;
|
||||
newdev->partition_start = grub_partition_get_start (source->partition);
|
||||
newdev->id = last_cryptodisk_id++;
|
||||
newdev->next = cryptodisk_list;
|
||||
cryptodisk_list = newdev;
|
||||
@@ -762,25 +775,26 @@ grub_cryptodisk_cheat_insert (grub_cryptodisk_t newdev, const char *name,
|
||||
|
||||
void
|
||||
grub_util_cryptodisk_get_abstraction (grub_disk_t disk,
|
||||
void (*cb) (const char *val))
|
||||
void (*cb) (const char *val, void *data),
|
||||
void *data)
|
||||
{
|
||||
grub_cryptodisk_t dev = (grub_cryptodisk_t) disk->data;
|
||||
|
||||
cb ("cryptodisk");
|
||||
cb (dev->modname);
|
||||
cb ("cryptodisk", data);
|
||||
cb (dev->modname, data);
|
||||
|
||||
if (dev->cipher)
|
||||
cb (dev->cipher->cipher->modname);
|
||||
cb (dev->cipher->cipher->modname, data);
|
||||
if (dev->secondary_cipher)
|
||||
cb (dev->secondary_cipher->cipher->modname);
|
||||
cb (dev->secondary_cipher->cipher->modname, data);
|
||||
if (dev->essiv_cipher)
|
||||
cb (dev->essiv_cipher->cipher->modname);
|
||||
cb (dev->essiv_cipher->cipher->modname, data);
|
||||
if (dev->hash)
|
||||
cb (dev->hash->modname);
|
||||
cb (dev->hash->modname, data);
|
||||
if (dev->essiv_hash)
|
||||
cb (dev->essiv_hash->modname);
|
||||
cb (dev->essiv_hash->modname, data);
|
||||
if (dev->iv_hash)
|
||||
cb (dev->iv_hash->modname);
|
||||
cb (dev->iv_hash->modname, data);
|
||||
}
|
||||
|
||||
const char *
|
||||
@@ -955,33 +969,43 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
grub_disk_t disk;
|
||||
grub_cryptodisk_t dev;
|
||||
char *diskname;
|
||||
char *disklast;
|
||||
char *disklast = NULL;
|
||||
grub_size_t len;
|
||||
|
||||
search_uuid = NULL;
|
||||
check_boot = state[2].set;
|
||||
diskname = args[0];
|
||||
if (diskname[0] == '(' && *(disklast = &diskname[grub_strlen (diskname) - 1]) == ')')
|
||||
len = grub_strlen (diskname);
|
||||
if (len && diskname[0] == '(' && diskname[len - 1] == ')')
|
||||
{
|
||||
disklast = &diskname[len - 1];
|
||||
*disklast = '\0';
|
||||
disk = grub_disk_open (diskname + 1);
|
||||
*disklast = ')';
|
||||
diskname++;
|
||||
}
|
||||
else
|
||||
disk = grub_disk_open (diskname);
|
||||
|
||||
disk = grub_disk_open (diskname);
|
||||
if (!disk)
|
||||
return grub_errno;
|
||||
{
|
||||
if (disklast)
|
||||
*disklast = ')';
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
dev = grub_cryptodisk_get_by_source_disk (disk);
|
||||
if (dev)
|
||||
{
|
||||
grub_dprintf ("cryptodisk", "already mounted as crypto%lu\n", dev->id);
|
||||
grub_disk_close (disk);
|
||||
if (disklast)
|
||||
*disklast = ')';
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
err = grub_cryptodisk_scan_device_real (args[0], disk);
|
||||
err = grub_cryptodisk_scan_device_real (diskname, disk);
|
||||
|
||||
grub_disk_close (disk);
|
||||
if (disklast)
|
||||
*disklast = ')';
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
+152
-18
@@ -71,10 +71,12 @@ is_lv_readable (struct grub_diskfilter_lv *lv, int easily)
|
||||
case GRUB_DISKFILTER_RAID6:
|
||||
if (!easily)
|
||||
need--;
|
||||
/* Fallthrough. */
|
||||
case GRUB_DISKFILTER_RAID4:
|
||||
case GRUB_DISKFILTER_RAID5:
|
||||
if (!easily)
|
||||
need--;
|
||||
/* Fallthrough. */
|
||||
case GRUB_DISKFILTER_STRIPED:
|
||||
break;
|
||||
|
||||
@@ -354,7 +356,8 @@ grub_diskfilter_memberlist (grub_disk_t disk)
|
||||
|
||||
void
|
||||
grub_diskfilter_get_partmap (grub_disk_t disk,
|
||||
void (*cb) (const char *pm))
|
||||
void (*cb) (const char *pm, void *data),
|
||||
void *data)
|
||||
{
|
||||
struct grub_diskfilter_lv *lv = disk->data;
|
||||
struct grub_diskfilter_pv *pv;
|
||||
@@ -376,7 +379,7 @@ grub_diskfilter_get_partmap (grub_disk_t disk,
|
||||
continue;
|
||||
}
|
||||
for (s = 0; pv->partmaps[s]; s++)
|
||||
cb (pv->partmaps[s]);
|
||||
cb (pv->partmaps[s], data);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -482,6 +485,96 @@ grub_diskfilter_read_node (const struct grub_diskfilter_node *node,
|
||||
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "unknown node '%s'", node->name);
|
||||
}
|
||||
|
||||
|
||||
static grub_err_t
|
||||
validate_segment (struct grub_diskfilter_segment *seg);
|
||||
|
||||
static grub_err_t
|
||||
validate_lv (struct grub_diskfilter_lv *lv)
|
||||
{
|
||||
unsigned int i;
|
||||
if (!lv)
|
||||
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "unknown volume");
|
||||
|
||||
if (!lv->vg || lv->vg->extent_size == 0)
|
||||
return grub_error (GRUB_ERR_READ_ERROR, "invalid volume");
|
||||
|
||||
for (i = 0; i < lv->segment_count; i++)
|
||||
{
|
||||
grub_err_t err;
|
||||
err = validate_segment (&lv->segments[i]);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
|
||||
static grub_err_t
|
||||
validate_node (const struct grub_diskfilter_node *node)
|
||||
{
|
||||
/* Check whether we actually know the physical volume we want to
|
||||
read from. */
|
||||
if (node->pv)
|
||||
return GRUB_ERR_NONE;
|
||||
if (node->lv)
|
||||
return validate_lv (node->lv);
|
||||
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "unknown node '%s'", node->name);
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
validate_segment (struct grub_diskfilter_segment *seg)
|
||||
{
|
||||
grub_err_t err;
|
||||
|
||||
if (seg->stripe_size == 0 || seg->node_count == 0)
|
||||
return grub_error(GRUB_ERR_BAD_FS, "invalid segment");
|
||||
|
||||
switch (seg->type)
|
||||
{
|
||||
case GRUB_DISKFILTER_RAID10:
|
||||
{
|
||||
grub_uint8_t near, far;
|
||||
near = seg->layout & 0xFF;
|
||||
far = (seg->layout >> 8) & 0xFF;
|
||||
if ((seg->layout >> 16) == 0 && far == 0)
|
||||
return grub_error(GRUB_ERR_BAD_FS, "invalid segment");
|
||||
if (near > seg->node_count)
|
||||
return grub_error(GRUB_ERR_BAD_FS, "invalid segment");
|
||||
break;
|
||||
}
|
||||
|
||||
case GRUB_DISKFILTER_STRIPED:
|
||||
case GRUB_DISKFILTER_MIRROR:
|
||||
break;
|
||||
|
||||
case GRUB_DISKFILTER_RAID4:
|
||||
case GRUB_DISKFILTER_RAID5:
|
||||
if (seg->node_count <= 1)
|
||||
return grub_error(GRUB_ERR_BAD_FS, "invalid segment");
|
||||
break;
|
||||
|
||||
case GRUB_DISKFILTER_RAID6:
|
||||
if (seg->node_count <= 2)
|
||||
return grub_error(GRUB_ERR_BAD_FS, "invalid segment");
|
||||
break;
|
||||
|
||||
default:
|
||||
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
|
||||
"unsupported RAID level %d", seg->type);
|
||||
}
|
||||
|
||||
unsigned i;
|
||||
for (i = 0; i < seg->node_count; i++)
|
||||
{
|
||||
err = validate_node (&seg->nodes[i]);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
return GRUB_ERR_NONE;
|
||||
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
read_segment (struct grub_diskfilter_segment *seg, grub_disk_addr_t sector,
|
||||
grub_size_t size, char *buf)
|
||||
@@ -493,6 +586,7 @@ read_segment (struct grub_diskfilter_segment *seg, grub_disk_addr_t sector,
|
||||
if (seg->node_count == 1)
|
||||
return grub_diskfilter_read_node (&seg->nodes[0],
|
||||
sector, size, buf);
|
||||
/* Fallthrough. */
|
||||
case GRUB_DISKFILTER_MIRROR:
|
||||
case GRUB_DISKFILTER_RAID10:
|
||||
{
|
||||
@@ -847,6 +941,23 @@ grub_diskfilter_vg_register (struct grub_diskfilter_vg *vg)
|
||||
|
||||
for (lv = vg->lvs; lv; lv = lv->next)
|
||||
{
|
||||
grub_err_t err;
|
||||
|
||||
/* RAID 1 and single-disk RAID 0 don't use a chunksize but code
|
||||
assumes one so set one. */
|
||||
for (i = 0; i < lv->segment_count; i++)
|
||||
{
|
||||
if (lv->segments[i].type == 1)
|
||||
lv->segments[i].stripe_size = 64;
|
||||
if (lv->segments[i].type == GRUB_DISKFILTER_STRIPED
|
||||
&& lv->segments[i].node_count == 1
|
||||
&& lv->segments[i].stripe_size == 0)
|
||||
lv->segments[i].stripe_size = 64;
|
||||
}
|
||||
|
||||
err = validate_lv(lv);
|
||||
if (err)
|
||||
return err;
|
||||
lv->number = lv_num++;
|
||||
|
||||
if (lv->fullname)
|
||||
@@ -887,12 +998,6 @@ grub_diskfilter_vg_register (struct grub_diskfilter_vg *vg)
|
||||
lv->fullname = tmp;
|
||||
}
|
||||
}
|
||||
/* RAID 1 doesn't use a chunksize but code assumes one so set
|
||||
one. */
|
||||
for (i = 0; i < lv->segment_count; i++)
|
||||
if (lv->segments[i].type == 1)
|
||||
lv->segments[i].stripe_size = 64;
|
||||
lv->vg = vg;
|
||||
}
|
||||
/* Add our new array to the list. */
|
||||
vg->next = array_list;
|
||||
@@ -902,7 +1007,7 @@ grub_diskfilter_vg_register (struct grub_diskfilter_vg *vg)
|
||||
|
||||
struct grub_diskfilter_vg *
|
||||
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,
|
||||
int layout, int level)
|
||||
{
|
||||
@@ -925,6 +1030,11 @@ grub_diskfilter_make_raid (grub_size_t uuidlen, char *uuid, int nmemb,
|
||||
n = layout & 0xFF;
|
||||
if (n == 1)
|
||||
n = (layout >> 8) & 0xFF;
|
||||
if (n == 0)
|
||||
{
|
||||
grub_free (uuid);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
totsize = grub_divmod64 (nmemb * disk_size, n, 0);
|
||||
}
|
||||
@@ -938,6 +1048,7 @@ grub_diskfilter_make_raid (grub_size_t uuidlen, char *uuid, int nmemb,
|
||||
break;
|
||||
|
||||
default:
|
||||
grub_free (uuid);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -951,7 +1062,7 @@ grub_diskfilter_make_raid (grub_size_t uuidlen, char *uuid, int nmemb,
|
||||
array->lvs->segments->extent_count = totsize;
|
||||
}
|
||||
|
||||
if (array->lvs->segments
|
||||
if (array->lvs && array->lvs->segments
|
||||
&& array->lvs->segments->raid_member_size > disk_size)
|
||||
array->lvs->segments->raid_member_size = disk_size;
|
||||
|
||||
@@ -960,7 +1071,10 @@ grub_diskfilter_make_raid (grub_size_t uuidlen, char *uuid, int nmemb,
|
||||
}
|
||||
array = grub_zalloc (sizeof (*array));
|
||||
if (!array)
|
||||
return NULL;
|
||||
{
|
||||
grub_free (uuid);
|
||||
return NULL;
|
||||
}
|
||||
array->uuid = uuid;
|
||||
array->uuid_len = uuidlen;
|
||||
if (name)
|
||||
@@ -982,8 +1096,16 @@ grub_diskfilter_make_raid (grub_size_t uuidlen, char *uuid, int nmemb,
|
||||
goto fail;
|
||||
array->lvs->segment_count = 1;
|
||||
array->lvs->visible = 1;
|
||||
array->lvs->name = array->name;
|
||||
array->lvs->fullname = array->name;
|
||||
if (array->name)
|
||||
{
|
||||
array->lvs->name = grub_strdup (array->name);
|
||||
if (!array->lvs->name)
|
||||
goto fail;
|
||||
array->lvs->fullname = grub_strdup (array->name);
|
||||
if (!array->lvs->fullname)
|
||||
goto fail;
|
||||
}
|
||||
array->lvs->vg = array;
|
||||
|
||||
array->lvs->idname = grub_malloc (sizeof ("mduuid/") + 2 * uuidlen);
|
||||
if (!array->lvs->idname)
|
||||
@@ -1033,13 +1155,26 @@ grub_diskfilter_make_raid (grub_size_t uuidlen, char *uuid, int nmemb,
|
||||
return array;
|
||||
|
||||
fail:
|
||||
grub_free (array->lvs);
|
||||
if (array->lvs)
|
||||
{
|
||||
grub_free (array->lvs->name);
|
||||
grub_free (array->lvs->fullname);
|
||||
grub_free (array->lvs->idname);
|
||||
if (array->lvs->segments)
|
||||
{
|
||||
grub_free (array->lvs->segments->nodes);
|
||||
grub_free (array->lvs->segments);
|
||||
}
|
||||
grub_free (array->lvs);
|
||||
}
|
||||
while (array->pvs)
|
||||
{
|
||||
pv = array->pvs->next;
|
||||
grub_free (array->pvs);
|
||||
array->pvs = pv;
|
||||
}
|
||||
grub_free (array->name);
|
||||
grub_free (array->uuid);
|
||||
grub_free (array);
|
||||
return NULL;
|
||||
}
|
||||
@@ -1142,10 +1277,9 @@ free_array (void)
|
||||
{
|
||||
unsigned i;
|
||||
vg->lvs = lv->next;
|
||||
if (lv->name != lv->fullname)
|
||||
grub_free (lv->fullname);
|
||||
if (lv->name != vg->name)
|
||||
grub_free (lv->name);
|
||||
grub_free (lv->fullname);
|
||||
grub_free (lv->name);
|
||||
grub_free (lv->idname);
|
||||
for (i = 0; i < lv->segment_count; i++)
|
||||
grub_free (lv->segments[i].nodes);
|
||||
grub_free (lv->segments);
|
||||
|
||||
@@ -99,6 +99,8 @@ grub_dmraid_nv_detect (grub_disk_t disk,
|
||||
struct grub_nv_super sb;
|
||||
int level;
|
||||
grub_uint64_t disk_size;
|
||||
grub_uint32_t capacity;
|
||||
grub_uint8_t total_volumes;
|
||||
char *uuid;
|
||||
|
||||
if (disk->partition)
|
||||
@@ -124,11 +126,17 @@ grub_dmraid_nv_detect (grub_disk_t disk,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
capacity = grub_le_to_cpu32 (sb.capacity);
|
||||
total_volumes = sb.array.total_volumes;
|
||||
|
||||
switch (sb.array.raid_level)
|
||||
{
|
||||
case NV_LEVEL_0:
|
||||
level = 0;
|
||||
disk_size = sb.capacity / sb.array.total_volumes;
|
||||
if (total_volumes == 0)
|
||||
/* Not RAID. */
|
||||
return NULL;
|
||||
disk_size = capacity / total_volumes;
|
||||
break;
|
||||
|
||||
case NV_LEVEL_1:
|
||||
@@ -138,7 +146,10 @@ grub_dmraid_nv_detect (grub_disk_t disk,
|
||||
|
||||
case NV_LEVEL_5:
|
||||
level = 5;
|
||||
disk_size = sb.capacity / (sb.array.total_volumes - 1);
|
||||
if (total_volumes == 0 || total_volumes == 1)
|
||||
/* Not RAID. */
|
||||
return NULL;
|
||||
disk_size = capacity / (total_volumes - 1);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -161,7 +172,7 @@ grub_dmraid_nv_detect (grub_disk_t disk,
|
||||
|
||||
return grub_diskfilter_make_raid (sizeof (sb.array.signature),
|
||||
uuid, sb.array.total_volumes,
|
||||
NULL, disk_size,
|
||||
"nv", disk_size,
|
||||
sb.array.stripe_block_size,
|
||||
GRUB_RAID_LAYOUT_LEFT_ASYMMETRIC,
|
||||
level);
|
||||
|
||||
@@ -43,47 +43,6 @@ static struct grub_efidisk_data *fd_devices;
|
||||
static struct grub_efidisk_data *hd_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 *
|
||||
make_devices (void)
|
||||
{
|
||||
@@ -110,7 +69,7 @@ make_devices (void)
|
||||
if (! dp)
|
||||
continue;
|
||||
|
||||
ldp = find_last_device_path (dp);
|
||||
ldp = grub_efi_find_last_device_path (dp);
|
||||
if (! ldp)
|
||||
/* This is empty. Why? */
|
||||
continue;
|
||||
@@ -126,6 +85,12 @@ make_devices (void)
|
||||
{
|
||||
/* Uggh. */
|
||||
grub_free (handles);
|
||||
while (devices)
|
||||
{
|
||||
d = devices->next;
|
||||
grub_free (devices);
|
||||
devices = d;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -150,11 +115,11 @@ find_parent_device (struct grub_efidisk_data *devices,
|
||||
grub_efi_device_path_t *dp, *ldp;
|
||||
struct grub_efidisk_data *parent;
|
||||
|
||||
dp = duplicate_device_path (d->device_path);
|
||||
dp = grub_efi_duplicate_device_path (d->device_path);
|
||||
if (! dp)
|
||||
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->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE;
|
||||
ldp->length = sizeof (*ldp);
|
||||
@@ -180,11 +145,11 @@ is_child (struct grub_efidisk_data *child,
|
||||
grub_efi_device_path_t *dp, *ldp;
|
||||
int ret;
|
||||
|
||||
dp = duplicate_device_path (child->device_path);
|
||||
dp = grub_efi_duplicate_device_path (child->device_path);
|
||||
if (! dp)
|
||||
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->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE;
|
||||
ldp->length = sizeof (*ldp);
|
||||
@@ -207,8 +172,8 @@ add_device (struct grub_efidisk_data **devices, struct grub_efidisk_data *d)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = grub_efi_compare_device_paths (find_last_device_path ((*p)->device_path),
|
||||
find_last_device_path (d->device_path));
|
||||
ret = grub_efi_compare_device_paths (grub_efi_find_last_device_path ((*p)->device_path),
|
||||
grub_efi_find_last_device_path (d->device_path));
|
||||
if (ret == 0)
|
||||
ret = grub_efi_compare_device_paths ((*p)->device_path,
|
||||
d->device_path);
|
||||
@@ -333,6 +298,21 @@ name_devices (struct grub_efidisk_data *devices)
|
||||
if (! dp)
|
||||
continue;
|
||||
|
||||
/* Ghosts proudly presented by Apple. */
|
||||
if (GRUB_EFI_DEVICE_PATH_TYPE (dp) == GRUB_EFI_MEDIA_DEVICE_PATH_TYPE
|
||||
&& GRUB_EFI_DEVICE_PATH_SUBTYPE (dp)
|
||||
== GRUB_EFI_VENDOR_MEDIA_DEVICE_PATH_SUBTYPE)
|
||||
{
|
||||
grub_efi_vendor_device_path_t *vendor = (grub_efi_vendor_device_path_t *) dp;
|
||||
const struct grub_efi_guid apple = GRUB_EFI_VENDOR_APPLE_GUID;
|
||||
|
||||
if (vendor->header.length == sizeof (*vendor)
|
||||
&& grub_memcmp (&vendor->vendor_guid, &apple,
|
||||
sizeof (vendor->vendor_guid)) == 0
|
||||
&& find_parent_device (devices, d))
|
||||
continue;
|
||||
}
|
||||
|
||||
m = d->block_io->media;
|
||||
if (GRUB_EFI_DEVICE_PATH_TYPE (dp) == GRUB_EFI_ACPI_DEVICE_PATH_TYPE
|
||||
&& GRUB_EFI_DEVICE_PATH_SUBTYPE (dp)
|
||||
@@ -513,8 +493,15 @@ grub_efidisk_open (const char *name, struct grub_disk *disk)
|
||||
m = d->block_io->media;
|
||||
/* FIXME: Probably it is better to store the block size in the disk,
|
||||
and total sectors should be replaced with total blocks. */
|
||||
grub_dprintf ("efidisk", "m = %p, last block = %llx, block size = %x\n",
|
||||
m, (unsigned long long) m->last_block, m->block_size);
|
||||
grub_dprintf ("efidisk",
|
||||
"m = %p, last block = %llx, block size = %x, io align = %x\n",
|
||||
m, (unsigned long long) m->last_block, m->block_size,
|
||||
m->io_align);
|
||||
|
||||
/* Ensure required buffer alignment is a power of two (or is zero). */
|
||||
if (m->io_align & (m->io_align - 1))
|
||||
return grub_error (GRUB_ERR_IO, "invalid buffer alignment %d", m->io_align);
|
||||
|
||||
disk->total_sectors = m->last_block + 1;
|
||||
/* Don't increase this value due to bug in some EFI. */
|
||||
disk->max_agglomerate = 0xa0000 >> (GRUB_DISK_CACHE_BITS + GRUB_DISK_SECTOR_BITS);
|
||||
@@ -544,15 +531,42 @@ grub_efidisk_readwrite (struct grub_disk *disk, grub_disk_addr_t sector,
|
||||
{
|
||||
struct grub_efidisk_data *d;
|
||||
grub_efi_block_io_t *bio;
|
||||
grub_efi_status_t status;
|
||||
grub_size_t io_align, num_bytes;
|
||||
char *aligned_buf;
|
||||
|
||||
d = disk->data;
|
||||
bio = d->block_io;
|
||||
|
||||
return efi_call_5 ((wr ? bio->write_blocks : bio->read_blocks), bio,
|
||||
bio->media->media_id,
|
||||
(grub_efi_uint64_t) sector,
|
||||
(grub_efi_uintn_t) size << disk->log_sector_size,
|
||||
buf);
|
||||
/* Set alignment to 1 if 0 specified */
|
||||
io_align = bio->media->io_align ? bio->media->io_align : 1;
|
||||
num_bytes = size << disk->log_sector_size;
|
||||
|
||||
if ((grub_addr_t) buf & (io_align - 1))
|
||||
{
|
||||
aligned_buf = grub_memalign (io_align, num_bytes);
|
||||
if (! aligned_buf)
|
||||
return GRUB_EFI_OUT_OF_RESOURCES;
|
||||
if (wr)
|
||||
grub_memcpy (aligned_buf, buf, num_bytes);
|
||||
}
|
||||
else
|
||||
{
|
||||
aligned_buf = buf;
|
||||
}
|
||||
|
||||
status = efi_call_5 ((wr ? bio->write_blocks : bio->read_blocks), bio,
|
||||
bio->media->media_id, (grub_efi_uint64_t) sector,
|
||||
(grub_efi_uintn_t) num_bytes, aligned_buf);
|
||||
|
||||
if ((grub_addr_t) buf & (io_align - 1))
|
||||
{
|
||||
if (!wr)
|
||||
grub_memcpy (buf, aligned_buf, num_bytes);
|
||||
grub_free (aligned_buf);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
@@ -567,7 +581,9 @@ grub_efidisk_read (struct grub_disk *disk, grub_disk_addr_t sector,
|
||||
|
||||
status = grub_efidisk_readwrite (disk, sector, size, buf, 0);
|
||||
|
||||
if (status != GRUB_EFI_SUCCESS)
|
||||
if (status == GRUB_EFI_NO_MEDIA)
|
||||
return grub_error (GRUB_ERR_OUT_OF_RANGE, N_("no media in `%s'"), disk->name);
|
||||
else if (status != GRUB_EFI_SUCCESS)
|
||||
return grub_error (GRUB_ERR_READ_ERROR,
|
||||
N_("failure reading sector 0x%llx from `%s'"),
|
||||
(unsigned long long) sector,
|
||||
@@ -588,7 +604,9 @@ grub_efidisk_write (struct grub_disk *disk, grub_disk_addr_t sector,
|
||||
|
||||
status = grub_efidisk_readwrite (disk, sector, size, (char *) buf, 1);
|
||||
|
||||
if (status != GRUB_EFI_SUCCESS)
|
||||
if (status == GRUB_EFI_NO_MEDIA)
|
||||
return grub_error (GRUB_ERR_OUT_OF_RANGE, N_("no media in `%s'"), disk->name);
|
||||
else if (status != GRUB_EFI_SUCCESS)
|
||||
return grub_error (GRUB_ERR_WRITE_ERROR,
|
||||
N_("failure writing sector 0x%llx to `%s'"),
|
||||
(unsigned long long) sector, disk->name);
|
||||
@@ -780,7 +798,7 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle)
|
||||
if (! dp)
|
||||
return 0;
|
||||
|
||||
ldp = find_last_device_path (dp);
|
||||
ldp = grub_efi_find_last_device_path (dp);
|
||||
if (! ldp)
|
||||
return 0;
|
||||
|
||||
@@ -788,7 +806,6 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle)
|
||||
&& (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) == GRUB_EFI_CDROM_DEVICE_PATH_SUBTYPE
|
||||
|| GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) == GRUB_EFI_HARD_DRIVE_DEVICE_PATH_SUBTYPE))
|
||||
{
|
||||
int is_cdrom = 0;
|
||||
struct grub_efidisk_get_device_name_ctx ctx;
|
||||
char *dev_name;
|
||||
grub_efi_device_path_t *dup_dp;
|
||||
@@ -796,22 +813,19 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle)
|
||||
|
||||
/* It is necessary to duplicate the device path so that GRUB
|
||||
can overwrite it. */
|
||||
dup_dp = duplicate_device_path (dp);
|
||||
dup_dp = grub_efi_duplicate_device_path (dp);
|
||||
if (! dup_dp)
|
||||
return 0;
|
||||
|
||||
while (1)
|
||||
{
|
||||
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
|
||||
&& (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)))
|
||||
break;
|
||||
|
||||
if (GRUB_EFI_DEVICE_PATH_SUBTYPE (dup_ldp) == GRUB_EFI_CDROM_DEVICE_PATH_SUBTYPE)
|
||||
is_cdrom = 1;
|
||||
|
||||
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);
|
||||
@@ -846,10 +860,13 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle)
|
||||
|
||||
if (! ctx.partition_name)
|
||||
{
|
||||
/* No partition found. In most cases partition is embed in
|
||||
the root path anyway, so this is not critical.
|
||||
This happens only if partition is on partmap that GRUB
|
||||
doesn't need to access root.
|
||||
*/
|
||||
grub_disk_close (parent);
|
||||
if (is_cdrom)
|
||||
return grub_strdup (device_name);
|
||||
return 0;
|
||||
return grub_strdup (device_name);
|
||||
}
|
||||
|
||||
dev_name = grub_xasprintf ("%s,%s", parent->name,
|
||||
|
||||
+38
-10
@@ -212,7 +212,8 @@ grub_util_get_geli_uuid (const char *dev)
|
||||
|
||||
s = grub_util_get_fd_size (fd, dev, &log_secsize);
|
||||
s >>= log_secsize;
|
||||
grub_util_fd_seek (fd, (s << log_secsize) - 512);
|
||||
if (grub_util_fd_seek (fd, (s << log_secsize) - 512) < 0)
|
||||
grub_util_error ("%s", _("couldn't read ELI metadata"));
|
||||
|
||||
uuid = xmalloc (GRUB_MD_SHA256->mdlen * 2 + 1);
|
||||
if (grub_util_fd_read (fd, (void *) &hdr, 512) < 0)
|
||||
@@ -225,13 +226,16 @@ grub_util_get_geli_uuid (const char *dev)
|
||||
|
||||
/* Look for GELI magic sequence. */
|
||||
if (grub_memcmp (header->magic, GELI_MAGIC, sizeof (GELI_MAGIC))
|
||||
|| grub_le_to_cpu32 (header->version) > 5
|
||||
|| grub_le_to_cpu32 (header->version) > 7
|
||||
|| grub_le_to_cpu32 (header->version) < 1)
|
||||
grub_util_error ("%s", _("wrong ELI magic or version"));
|
||||
|
||||
err = make_uuid ((void *) &hdr, uuid);
|
||||
if (err)
|
||||
return NULL;
|
||||
{
|
||||
grub_free (uuid);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return uuid;
|
||||
}
|
||||
@@ -265,7 +269,7 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
|
||||
|
||||
/* Look for GELI magic sequence. */
|
||||
if (grub_memcmp (header.magic, GELI_MAGIC, sizeof (GELI_MAGIC))
|
||||
|| grub_le_to_cpu32 (header.version) > 5
|
||||
|| grub_le_to_cpu32 (header.version) > 7
|
||||
|| grub_le_to_cpu32 (header.version) < 1)
|
||||
{
|
||||
grub_dprintf ("geli", "wrong magic %02x\n", header.magic[0]);
|
||||
@@ -332,19 +336,29 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
|
||||
{
|
||||
secondary_cipher = grub_crypto_cipher_open (ciph);
|
||||
if (!secondary_cipher)
|
||||
return NULL;
|
||||
{
|
||||
grub_crypto_cipher_close (cipher);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (grub_le_to_cpu16 (header.keylen) > 1024)
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid keysize %d",
|
||||
grub_le_to_cpu16 (header.keylen));
|
||||
grub_crypto_cipher_close (cipher);
|
||||
grub_crypto_cipher_close (secondary_cipher);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
newdev = grub_zalloc (sizeof (struct grub_cryptodisk));
|
||||
if (!newdev)
|
||||
return NULL;
|
||||
{
|
||||
grub_crypto_cipher_close (cipher);
|
||||
grub_crypto_cipher_close (secondary_cipher);
|
||||
return NULL;
|
||||
}
|
||||
newdev->cipher = cipher;
|
||||
newdev->secondary_cipher = secondary_cipher;
|
||||
newdev->offset = 0;
|
||||
@@ -391,6 +405,7 @@ recover_key (grub_disk_t source, grub_cryptodisk_t dev)
|
||||
grub_uint8_t geomkey[GRUB_CRYPTO_MAX_MDLEN];
|
||||
grub_uint8_t verify_key[GRUB_CRYPTO_MAX_MDLEN];
|
||||
grub_uint8_t zero[GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE];
|
||||
grub_uint8_t geli_cipher_key[64];
|
||||
char passphrase[MAX_PASSPHRASE] = "";
|
||||
unsigned i;
|
||||
gcry_err_code_t gcry_err;
|
||||
@@ -514,6 +529,19 @@ recover_key (grub_disk_t source, grub_cryptodisk_t dev)
|
||||
continue;
|
||||
grub_printf_ (N_("Slot %d opened\n"), i);
|
||||
|
||||
if (grub_le_to_cpu32 (header.version) >= 7)
|
||||
{
|
||||
/* GELI >=7 uses the cipher_key */
|
||||
grub_memcpy (geli_cipher_key, candidate_key.cipher_key,
|
||||
sizeof (candidate_key.cipher_key));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* GELI <=6 uses the iv_key */
|
||||
grub_memcpy (geli_cipher_key, candidate_key.iv_key,
|
||||
sizeof (candidate_key.iv_key));
|
||||
}
|
||||
|
||||
/* Set the master key. */
|
||||
if (!dev->rekey)
|
||||
{
|
||||
@@ -530,13 +558,13 @@ recover_key (grub_disk_t source, grub_cryptodisk_t dev)
|
||||
grub_size_t real_keysize = keysize;
|
||||
if (grub_le_to_cpu16 (header.alg) == 0x16)
|
||||
real_keysize *= 2;
|
||||
/* For a reason I don't know, the IV key is used in rekeying. */
|
||||
grub_memcpy (dev->rekey_key, candidate_key.iv_key,
|
||||
sizeof (candidate_key.iv_key));
|
||||
|
||||
grub_memcpy (dev->rekey_key, geli_cipher_key,
|
||||
sizeof (geli_cipher_key));
|
||||
dev->rekey_derived_size = real_keysize;
|
||||
dev->last_rekey = -1;
|
||||
COMPILE_TIME_ASSERT (sizeof (dev->rekey_key)
|
||||
>= sizeof (candidate_key.iv_key));
|
||||
>= sizeof (geli_cipher_key));
|
||||
}
|
||||
|
||||
dev->iv_prefix_len = sizeof (candidate_key.iv_key);
|
||||
|
||||
@@ -382,7 +382,8 @@ grub_biosdisk_open (const char *name, grub_disk_t disk)
|
||||
/* Some buggy BIOSes doesn't return the total sectors
|
||||
correctly but returns zero. So if it is zero, compute
|
||||
it by C/H/S returned by the LBA BIOS call. */
|
||||
total_sectors = drp->cylinders * drp->heads * drp->sectors;
|
||||
total_sectors = ((grub_uint64_t) drp->cylinders)
|
||||
* drp->heads * drp->sectors;
|
||||
if (drp->bytes_per_sector
|
||||
&& !(drp->bytes_per_sector & (drp->bytes_per_sector - 1))
|
||||
&& drp->bytes_per_sector >= 512
|
||||
@@ -419,8 +420,14 @@ grub_biosdisk_open (const char *name, grub_disk_t disk)
|
||||
}
|
||||
}
|
||||
|
||||
if (data->sectors == 0)
|
||||
data->sectors = 63;
|
||||
if (data->heads == 0)
|
||||
data->heads = 255;
|
||||
|
||||
if (! total_sectors)
|
||||
total_sectors = data->cylinders * data->heads * data->sectors;
|
||||
total_sectors = ((grub_uint64_t) data->cylinders)
|
||||
* data->heads * data->sectors;
|
||||
}
|
||||
|
||||
disk->total_sectors = total_sectors;
|
||||
@@ -455,6 +462,14 @@ grub_biosdisk_rw (int cmd, grub_disk_t disk,
|
||||
{
|
||||
struct grub_biosdisk_data *data = disk->data;
|
||||
|
||||
/* VirtualBox fails with sectors above 2T on CDs.
|
||||
Since even BD-ROMS are never that big anyway, return error. */
|
||||
if ((data->flags & GRUB_BIOSDISK_FLAG_CDROM)
|
||||
&& (sector >> 32))
|
||||
return grub_error (GRUB_ERR_OUT_OF_RANGE,
|
||||
N_("attempt to read or write outside of disk `%s'"),
|
||||
disk->name);
|
||||
|
||||
if (data->flags & GRUB_BIOSDISK_FLAG_LBA)
|
||||
{
|
||||
struct grub_biosdisk_dap *dap;
|
||||
|
||||
@@ -113,6 +113,11 @@ grub_nand_open (const char *name, grub_disk_t disk)
|
||||
}
|
||||
|
||||
data->block_size = (args.size1 >> GRUB_DISK_SECTOR_BITS);
|
||||
if (!data->block_size)
|
||||
{
|
||||
grub_error (GRUB_ERR_UNKNOWN_DEVICE, "invalid block size");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
INIT_IEEE1275_COMMON (&args.common, "call-method", 2, 3);
|
||||
args.method = (grub_ieee1275_cell_t) "size";
|
||||
|
||||
@@ -34,7 +34,8 @@ struct ofdisk_hash_ent
|
||||
char *open_path;
|
||||
char *grub_devpath;
|
||||
int is_boot;
|
||||
int is_cdrom;
|
||||
int is_removable;
|
||||
int block_size_fails;
|
||||
/* Pointer to shortest available name on nodes representing canonical names,
|
||||
otherwise NULL. */
|
||||
const char *shortest;
|
||||
@@ -42,6 +43,10 @@ struct ofdisk_hash_ent
|
||||
struct ofdisk_hash_ent *next;
|
||||
};
|
||||
|
||||
static grub_err_t
|
||||
grub_ofdisk_get_block_size (const char *device, grub_uint32_t *block_size,
|
||||
struct ofdisk_hash_ent *op);
|
||||
|
||||
#define OFDISK_HASH_SZ 8
|
||||
static struct ofdisk_hash_ent *ofdisk_hash[OFDISK_HASH_SZ];
|
||||
|
||||
@@ -123,7 +128,7 @@ ofdisk_hash_add_real (char *devpath)
|
||||
}
|
||||
|
||||
static int
|
||||
check_string_cdrom (const char *str)
|
||||
check_string_removable (const char *str)
|
||||
{
|
||||
const char *ptr = grub_strrchr (str, '/');
|
||||
|
||||
@@ -131,7 +136,7 @@ check_string_cdrom (const char *str)
|
||||
ptr++;
|
||||
else
|
||||
ptr = str;
|
||||
return (grub_strncmp (ptr, "cdrom", 5) == 0);
|
||||
return (grub_strncmp (ptr, "cdrom", 5) == 0 || grub_strncmp (ptr, "fd", 2) == 0);
|
||||
}
|
||||
|
||||
static struct ofdisk_hash_ent *
|
||||
@@ -147,8 +152,8 @@ ofdisk_hash_add (char *devpath, char *curcan)
|
||||
{
|
||||
p->shortest = p->devpath;
|
||||
p->grub_shortest = p->grub_devpath;
|
||||
if (check_string_cdrom (devpath))
|
||||
p->is_cdrom = 1;
|
||||
if (check_string_removable (devpath))
|
||||
p->is_removable = 1;
|
||||
return p;
|
||||
}
|
||||
|
||||
@@ -158,8 +163,8 @@ ofdisk_hash_add (char *devpath, char *curcan)
|
||||
else
|
||||
grub_free (curcan);
|
||||
|
||||
if (check_string_cdrom (devpath) || check_string_cdrom (curcan))
|
||||
pcan->is_cdrom = 1;
|
||||
if (check_string_removable (devpath) || check_string_removable (curcan))
|
||||
pcan->is_removable = 1;
|
||||
|
||||
if (!pcan)
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
@@ -222,7 +227,10 @@ dev_iterate (const struct grub_ieee1275_devalias *alias)
|
||||
|
||||
if (grub_ieee1275_open (alias->path, &ihandle))
|
||||
return;
|
||||
|
||||
|
||||
/* This method doesn't need memory allocation for the table. Open
|
||||
firmware takes care of all memory management and the result table
|
||||
stays in memory and is never freed. */
|
||||
INIT_IEEE1275_COMMON (&args.common, "call-method", 2, 3);
|
||||
args.method = (grub_ieee1275_cell_t) "vscsi-report-luns";
|
||||
args.ihandle = ihandle;
|
||||
@@ -255,6 +263,82 @@ dev_iterate (const struct grub_ieee1275_devalias *alias)
|
||||
grub_free (buf);
|
||||
return;
|
||||
}
|
||||
else if (grub_strcmp (alias->type, "sas_ioa") == 0)
|
||||
{
|
||||
/* The method returns the number of disks and a table where
|
||||
* each ID is 64-bit long. Example of sas paths:
|
||||
* /pci@80000002000001f/pci1014,034A@0/sas/disk@c05db70800
|
||||
* /pci@80000002000001f/pci1014,034A@0/sas/disk@a05db70800
|
||||
* /pci@80000002000001f/pci1014,034A@0/sas/disk@805db70800 */
|
||||
|
||||
struct sas_children
|
||||
{
|
||||
struct grub_ieee1275_common_hdr common;
|
||||
grub_ieee1275_cell_t method;
|
||||
grub_ieee1275_cell_t ihandle;
|
||||
grub_ieee1275_cell_t max;
|
||||
grub_ieee1275_cell_t table;
|
||||
grub_ieee1275_cell_t catch_result;
|
||||
grub_ieee1275_cell_t nentries;
|
||||
}
|
||||
args;
|
||||
char *buf, *bufptr;
|
||||
unsigned i;
|
||||
grub_uint64_t *table;
|
||||
grub_uint16_t table_size;
|
||||
grub_ieee1275_ihandle_t ihandle;
|
||||
|
||||
buf = grub_malloc (grub_strlen (alias->path) +
|
||||
sizeof ("/disk@7766554433221100"));
|
||||
if (!buf)
|
||||
return;
|
||||
bufptr = grub_stpcpy (buf, alias->path);
|
||||
|
||||
/* Power machines documentation specify 672 as maximum SAS disks in
|
||||
one system. Using a slightly larger value to be safe. */
|
||||
table_size = 768;
|
||||
table = grub_malloc (table_size * sizeof (grub_uint64_t));
|
||||
|
||||
if (!table)
|
||||
{
|
||||
grub_free (buf);
|
||||
return;
|
||||
}
|
||||
|
||||
if (grub_ieee1275_open (alias->path, &ihandle))
|
||||
{
|
||||
grub_free (buf);
|
||||
grub_free (table);
|
||||
return;
|
||||
}
|
||||
|
||||
INIT_IEEE1275_COMMON (&args.common, "call-method", 4, 2);
|
||||
args.method = (grub_ieee1275_cell_t) "get-sas-children";
|
||||
args.ihandle = ihandle;
|
||||
args.max = table_size;
|
||||
args.table = (grub_ieee1275_cell_t) table;
|
||||
args.catch_result = 0;
|
||||
args.nentries = 0;
|
||||
|
||||
if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
|
||||
{
|
||||
grub_ieee1275_close (ihandle);
|
||||
grub_free (table);
|
||||
grub_free (buf);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < args.nentries; i++)
|
||||
{
|
||||
grub_snprintf (bufptr, sizeof ("/disk@7766554433221100"),
|
||||
"/disk@%" PRIxGRUB_UINT64_T, table[i]);
|
||||
dev_iterate_real (buf, buf);
|
||||
}
|
||||
|
||||
grub_ieee1275_close (ihandle);
|
||||
grub_free (table);
|
||||
grub_free (buf);
|
||||
}
|
||||
|
||||
if (!grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_NO_TREE_SCANNING_FOR_DISKS)
|
||||
&& grub_strcmp (alias->type, "block") == 0)
|
||||
@@ -330,7 +414,7 @@ grub_ofdisk_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data,
|
||||
}
|
||||
}
|
||||
|
||||
if (!ent->is_boot && ent->is_cdrom)
|
||||
if (!ent->is_boot && ent->is_removable)
|
||||
continue;
|
||||
|
||||
if (hook (ent->grub_shortest, hook_data))
|
||||
@@ -375,6 +459,8 @@ grub_ofdisk_open (const char *name, grub_disk_t disk)
|
||||
/* XXX: This should be large enough for any possible case. */
|
||||
char prop[64];
|
||||
grub_ssize_t actual;
|
||||
grub_uint32_t block_size = 0;
|
||||
grub_err_t err;
|
||||
|
||||
if (grub_strncmp (name, "ieee1275/", sizeof ("ieee1275/") - 1) != 0)
|
||||
return grub_error (GRUB_ERR_UNKNOWN_DEVICE,
|
||||
@@ -405,14 +491,6 @@ grub_ofdisk_open (const char *name, grub_disk_t disk)
|
||||
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a block device");
|
||||
}
|
||||
|
||||
grub_uint32_t block_size = 0;
|
||||
if (grub_ofdisk_get_block_size (devpath, &block_size) == 0)
|
||||
{
|
||||
for (disk->log_sector_size = 0;
|
||||
(1U << disk->log_sector_size) < block_size;
|
||||
disk->log_sector_size++);
|
||||
}
|
||||
|
||||
/* XXX: There is no property to read the number of blocks. There
|
||||
should be a property `#blocks', but it is not there. Perhaps it
|
||||
is possible to use seek for this. */
|
||||
@@ -423,14 +501,31 @@ grub_ofdisk_open (const char *name, grub_disk_t disk)
|
||||
op = ofdisk_hash_find (devpath);
|
||||
if (!op)
|
||||
op = ofdisk_hash_add (devpath, NULL);
|
||||
else
|
||||
grub_free (devpath);
|
||||
if (!op)
|
||||
return grub_errno;
|
||||
{
|
||||
grub_free (devpath);
|
||||
return grub_errno;
|
||||
}
|
||||
disk->id = (unsigned long) op;
|
||||
disk->data = op->open_path;
|
||||
|
||||
err = grub_ofdisk_get_block_size (devpath, &block_size, op);
|
||||
if (err)
|
||||
{
|
||||
grub_free (devpath);
|
||||
return err;
|
||||
}
|
||||
if (block_size != 0)
|
||||
{
|
||||
for (disk->log_sector_size = 0;
|
||||
(1U << disk->log_sector_size) < block_size;
|
||||
disk->log_sector_size++);
|
||||
}
|
||||
else
|
||||
disk->log_sector_size = 9;
|
||||
}
|
||||
|
||||
grub_free (devpath);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -589,8 +684,9 @@ grub_ofdisk_init (void)
|
||||
grub_disk_dev_register (&grub_ofdisk_dev);
|
||||
}
|
||||
|
||||
grub_err_t
|
||||
grub_ofdisk_get_block_size (const char *device, grub_uint32_t *block_size)
|
||||
static grub_err_t
|
||||
grub_ofdisk_get_block_size (const char *device, grub_uint32_t *block_size,
|
||||
struct ofdisk_hash_ent *op)
|
||||
{
|
||||
struct size_args_ieee1275
|
||||
{
|
||||
@@ -612,20 +708,34 @@ grub_ofdisk_get_block_size (const char *device, grub_uint32_t *block_size)
|
||||
if (! last_ihandle)
|
||||
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't open device");
|
||||
|
||||
*block_size = 0;
|
||||
|
||||
if (op->block_size_fails >= 2)
|
||||
return GRUB_ERR_NONE;
|
||||
|
||||
INIT_IEEE1275_COMMON (&args_ieee1275.common, "call-method", 2, 2);
|
||||
args_ieee1275.method = (grub_ieee1275_cell_t) "block-size";
|
||||
args_ieee1275.ihandle = last_ihandle;
|
||||
args_ieee1275.result = 1;
|
||||
|
||||
*block_size = GRUB_DISK_SECTOR_SIZE;
|
||||
|
||||
if ((IEEE1275_CALL_ENTRY_FN (&args_ieee1275) == -1) || (args_ieee1275.result))
|
||||
grub_dprintf ("disk", "can't get block size\n");
|
||||
else
|
||||
if (args_ieee1275.size1
|
||||
&& !(args_ieee1275.size1 & (args_ieee1275.size1 - 1))
|
||||
&& args_ieee1275.size1 >= 512 && args_ieee1275.size1 <= 16384)
|
||||
if (IEEE1275_CALL_ENTRY_FN (&args_ieee1275) == -1)
|
||||
{
|
||||
grub_dprintf ("disk", "can't get block size: failed call-method\n");
|
||||
op->block_size_fails++;
|
||||
}
|
||||
else if (args_ieee1275.result)
|
||||
{
|
||||
grub_dprintf ("disk", "can't get block size: %lld\n",
|
||||
(long long) args_ieee1275.result);
|
||||
op->block_size_fails++;
|
||||
}
|
||||
else if (args_ieee1275.size1
|
||||
&& !(args_ieee1275.size1 & (args_ieee1275.size1 - 1))
|
||||
&& args_ieee1275.size1 >= 512 && args_ieee1275.size1 <= 16384)
|
||||
{
|
||||
op->block_size_fails = 0;
|
||||
*block_size = args_ieee1275.size1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -963,7 +963,7 @@ grub_util_ldm_embed (struct grub_disk *disk, unsigned int *nsectors,
|
||||
|
||||
if (embed_type != GRUB_EMBED_PCBIOS)
|
||||
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
|
||||
"LDM curently supports only PC-BIOS embedding");
|
||||
"LDM currently supports only PC-BIOS embedding");
|
||||
if (disk->partition)
|
||||
return grub_error (GRUB_ERR_BUG, "disk isn't LDM");
|
||||
pv = grub_diskfilter_get_pv_from_disk (disk, &vg);
|
||||
@@ -1012,7 +1012,7 @@ grub_util_ldm_embed (struct grub_disk *disk, unsigned int *nsectors,
|
||||
usable for bootloaders (called generically
|
||||
"embedding zone") and this operation is
|
||||
called "embedding". */
|
||||
N_("your LDM embedding Partition is too small;"
|
||||
N_("your LDM Embedding Partition is too small;"
|
||||
" embedding won't be possible"));
|
||||
*nsectors = lv->size;
|
||||
if (*nsectors > max_nsectors)
|
||||
|
||||
+16
-3
@@ -143,6 +143,7 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid keysize %d",
|
||||
grub_be_to_cpu32 (header.keyBytes));
|
||||
grub_crypto_cipher_close (cipher);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -181,9 +182,10 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
|
||||
}
|
||||
if (cipher->cipher->blocksize != GRUB_CRYPTODISK_GF_BYTES)
|
||||
{
|
||||
grub_crypto_cipher_close (cipher);
|
||||
grub_error (GRUB_ERR_BAD_ARGUMENT, "Unsupported XTS block size: %d",
|
||||
cipher->cipher->blocksize);
|
||||
grub_crypto_cipher_close (cipher);
|
||||
grub_crypto_cipher_close (secondary_cipher);
|
||||
return NULL;
|
||||
}
|
||||
if (secondary_cipher->cipher->blocksize != GRUB_CRYPTODISK_GF_BYTES)
|
||||
@@ -191,6 +193,7 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
|
||||
grub_crypto_cipher_close (cipher);
|
||||
grub_error (GRUB_ERR_BAD_ARGUMENT, "Unsupported XTS block size: %d",
|
||||
secondary_cipher->cipher->blocksize);
|
||||
grub_crypto_cipher_close (secondary_cipher);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
@@ -200,9 +203,9 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
|
||||
cipheriv = ciphermode + sizeof ("lrw-") - 1;
|
||||
if (cipher->cipher->blocksize != GRUB_CRYPTODISK_GF_BYTES)
|
||||
{
|
||||
grub_crypto_cipher_close (cipher);
|
||||
grub_error (GRUB_ERR_BAD_ARGUMENT, "Unsupported LRW block size: %d",
|
||||
cipher->cipher->blocksize);
|
||||
grub_crypto_cipher_close (cipher);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
@@ -225,6 +228,7 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
|
||||
|| cipher->cipher->blocksize == 0)
|
||||
grub_error (GRUB_ERR_BAD_ARGUMENT, "Unsupported benbi blocksize: %d",
|
||||
cipher->cipher->blocksize);
|
||||
/* FIXME should we return an error here? */
|
||||
for (benbi_log = 0;
|
||||
(cipher->cipher->blocksize << benbi_log) < GRUB_DISK_SECTOR_SIZE;
|
||||
benbi_log++);
|
||||
@@ -243,6 +247,7 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
|
||||
if (!essiv_hash)
|
||||
{
|
||||
grub_crypto_cipher_close (cipher);
|
||||
grub_crypto_cipher_close (secondary_cipher);
|
||||
grub_error (GRUB_ERR_FILE_NOT_FOUND,
|
||||
"Couldn't load %s hash", hash_str);
|
||||
return NULL;
|
||||
@@ -251,12 +256,14 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
|
||||
if (!essiv_cipher)
|
||||
{
|
||||
grub_crypto_cipher_close (cipher);
|
||||
grub_crypto_cipher_close (secondary_cipher);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
grub_crypto_cipher_close (cipher);
|
||||
grub_crypto_cipher_close (secondary_cipher);
|
||||
grub_error (GRUB_ERR_BAD_ARGUMENT, "Unknown IV mode: %s",
|
||||
cipheriv);
|
||||
return NULL;
|
||||
@@ -276,7 +283,12 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
|
||||
|
||||
newdev = grub_zalloc (sizeof (struct grub_cryptodisk));
|
||||
if (!newdev)
|
||||
return NULL;
|
||||
{
|
||||
grub_crypto_cipher_close (cipher);
|
||||
grub_crypto_cipher_close (essiv_cipher);
|
||||
grub_crypto_cipher_close (secondary_cipher);
|
||||
return NULL;
|
||||
}
|
||||
newdev->cipher = cipher;
|
||||
newdev->offset = grub_be_to_cpu32 (header.payloadOffset);
|
||||
newdev->source_disk = NULL;
|
||||
@@ -451,6 +463,7 @@ luks_recover_key (grub_disk_t source,
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
grub_free (split_key);
|
||||
return GRUB_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
|
||||
+41
-34
@@ -65,7 +65,7 @@ grub_lvm_checkvalue (char **p, char *str, char *tmpl)
|
||||
static int
|
||||
grub_lvm_check_flag (char *p, const char *str, const char *flag)
|
||||
{
|
||||
int len_str = grub_strlen (str), len_flag = grub_strlen (flag);
|
||||
grub_size_t len_str = grub_strlen (str), len_flag = grub_strlen (flag);
|
||||
while (1)
|
||||
{
|
||||
char *q;
|
||||
@@ -111,7 +111,8 @@ grub_lvm_detect (grub_disk_t disk,
|
||||
struct grub_lvm_disk_locn *dlocn;
|
||||
struct grub_lvm_mda_header *mdah;
|
||||
struct grub_lvm_raw_locn *rlocn;
|
||||
unsigned int i, j, vgname_len;
|
||||
unsigned int i, j;
|
||||
grub_size_t vgname_len;
|
||||
struct grub_diskfilter_vg *vg;
|
||||
struct grub_diskfilter_pv *pv;
|
||||
|
||||
@@ -159,7 +160,7 @@ grub_lvm_detect (grub_disk_t disk,
|
||||
"we don't support multiple LVM data areas");
|
||||
|
||||
#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
|
||||
goto fail;
|
||||
}
|
||||
@@ -188,7 +189,7 @@ grub_lvm_detect (grub_disk_t disk,
|
||||
grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
|
||||
"unknown LVM metadata header");
|
||||
#ifdef GRUB_UTIL
|
||||
grub_util_info ("unknown LVM metadata header\n");
|
||||
grub_util_info ("unknown LVM metadata header");
|
||||
#endif
|
||||
goto fail2;
|
||||
}
|
||||
@@ -212,7 +213,7 @@ grub_lvm_detect (grub_disk_t disk,
|
||||
if (q == metadatabuf + mda_size)
|
||||
{
|
||||
#ifdef GRUB_UTIL
|
||||
grub_util_info ("error parsing metadata\n");
|
||||
grub_util_info ("error parsing metadata");
|
||||
#endif
|
||||
goto fail2;
|
||||
}
|
||||
@@ -229,7 +230,7 @@ grub_lvm_detect (grub_disk_t disk,
|
||||
if (p == NULL)
|
||||
{
|
||||
#ifdef GRUB_UTIL
|
||||
grub_util_info ("couldn't find ID\n");
|
||||
grub_util_info ("couldn't find ID");
|
||||
#endif
|
||||
goto fail3;
|
||||
}
|
||||
@@ -257,7 +258,7 @@ grub_lvm_detect (grub_disk_t disk,
|
||||
if (p == NULL)
|
||||
{
|
||||
#ifdef GRUB_UTIL
|
||||
grub_util_info ("unknown extent size\n");
|
||||
grub_util_info ("unknown extent size");
|
||||
#endif
|
||||
goto fail4;
|
||||
}
|
||||
@@ -273,7 +274,7 @@ grub_lvm_detect (grub_disk_t disk,
|
||||
/* Add all the pvs to the volume group. */
|
||||
while (1)
|
||||
{
|
||||
int s;
|
||||
grub_ssize_t s;
|
||||
while (grub_isspace (*p))
|
||||
p++;
|
||||
|
||||
@@ -305,7 +306,7 @@ grub_lvm_detect (grub_disk_t disk,
|
||||
if (p == NULL)
|
||||
{
|
||||
#ifdef GRUB_UTIL
|
||||
grub_util_info ("unknown pe_start\n");
|
||||
grub_util_info ("unknown pe_start");
|
||||
#endif
|
||||
goto pvs_fail;
|
||||
}
|
||||
@@ -314,7 +315,7 @@ grub_lvm_detect (grub_disk_t disk,
|
||||
if (p == NULL)
|
||||
{
|
||||
#ifdef GRUB_UTIL
|
||||
grub_util_info ("error parsing pe_start\n");
|
||||
grub_util_info ("error parsing pe_start");
|
||||
#endif
|
||||
goto pvs_fail;
|
||||
}
|
||||
@@ -332,15 +333,15 @@ grub_lvm_detect (grub_disk_t disk,
|
||||
}
|
||||
}
|
||||
|
||||
p = grub_strstr (p, "logical_volumes");
|
||||
p = grub_strstr (p, "logical_volumes {");
|
||||
if (p)
|
||||
{
|
||||
p += sizeof ("logical_volumes = ") - 1;
|
||||
p += sizeof ("logical_volumes {") - 1;
|
||||
|
||||
/* And add all the lvs to the volume group. */
|
||||
while (1)
|
||||
{
|
||||
int s;
|
||||
grub_ssize_t s;
|
||||
int skip_lv = 0;
|
||||
struct grub_diskfilter_lv *lv;
|
||||
struct grub_diskfilter_segment *seg;
|
||||
@@ -401,7 +402,7 @@ grub_lvm_detect (grub_disk_t disk,
|
||||
if (p == NULL)
|
||||
{
|
||||
#ifdef GRUB_UTIL
|
||||
grub_util_info ("couldn't find ID\n");
|
||||
grub_util_info ("couldn't find ID");
|
||||
#endif
|
||||
goto lvs_fail;
|
||||
}
|
||||
@@ -421,11 +422,11 @@ grub_lvm_detect (grub_disk_t disk,
|
||||
if (p == NULL)
|
||||
{
|
||||
#ifdef GRUB_UTIL
|
||||
grub_util_info ("unknown segment_count\n");
|
||||
grub_util_info ("unknown segment_count");
|
||||
#endif
|
||||
goto lvs_fail;
|
||||
}
|
||||
lv->segments = grub_malloc (sizeof (*seg) * lv->segment_count);
|
||||
lv->segments = grub_zalloc (sizeof (*seg) * lv->segment_count);
|
||||
seg = lv->segments;
|
||||
|
||||
for (i = 0; i < lv->segment_count; i++)
|
||||
@@ -435,7 +436,7 @@ grub_lvm_detect (grub_disk_t disk,
|
||||
if (p == NULL)
|
||||
{
|
||||
#ifdef GRUB_UTIL
|
||||
grub_util_info ("unknown segment\n");
|
||||
grub_util_info ("unknown segment");
|
||||
#endif
|
||||
goto lvs_segment_fail;
|
||||
}
|
||||
@@ -444,7 +445,7 @@ grub_lvm_detect (grub_disk_t disk,
|
||||
if (p == NULL)
|
||||
{
|
||||
#ifdef GRUB_UTIL
|
||||
grub_util_info ("unknown start_extent\n");
|
||||
grub_util_info ("unknown start_extent");
|
||||
#endif
|
||||
goto lvs_segment_fail;
|
||||
}
|
||||
@@ -452,7 +453,7 @@ grub_lvm_detect (grub_disk_t disk,
|
||||
if (p == NULL)
|
||||
{
|
||||
#ifdef GRUB_UTIL
|
||||
grub_util_info ("unknown extent_count\n");
|
||||
grub_util_info ("unknown extent_count");
|
||||
#endif
|
||||
goto lvs_segment_fail;
|
||||
}
|
||||
@@ -474,7 +475,7 @@ grub_lvm_detect (grub_disk_t disk,
|
||||
if (p == NULL)
|
||||
{
|
||||
#ifdef GRUB_UTIL
|
||||
grub_util_info ("unknown stripe_count\n");
|
||||
grub_util_info ("unknown stripe_count");
|
||||
#endif
|
||||
goto lvs_segment_fail;
|
||||
}
|
||||
@@ -490,7 +491,7 @@ grub_lvm_detect (grub_disk_t disk,
|
||||
if (p == NULL)
|
||||
{
|
||||
#ifdef GRUB_UTIL
|
||||
grub_util_info ("unknown stripes\n");
|
||||
grub_util_info ("unknown stripes");
|
||||
#endif
|
||||
goto lvs_segment_fail2;
|
||||
}
|
||||
@@ -532,7 +533,7 @@ grub_lvm_detect (grub_disk_t disk,
|
||||
if (p == NULL)
|
||||
{
|
||||
#ifdef GRUB_UTIL
|
||||
grub_util_info ("unknown mirror_count\n");
|
||||
grub_util_info ("unknown mirror_count");
|
||||
#endif
|
||||
goto lvs_segment_fail;
|
||||
}
|
||||
@@ -544,7 +545,7 @@ grub_lvm_detect (grub_disk_t disk,
|
||||
if (p == NULL)
|
||||
{
|
||||
#ifdef GRUB_UTIL
|
||||
grub_util_info ("unknown mirrors\n");
|
||||
grub_util_info ("unknown mirrors");
|
||||
#endif
|
||||
goto lvs_segment_fail2;
|
||||
}
|
||||
@@ -576,13 +577,17 @@ grub_lvm_detect (grub_disk_t disk,
|
||||
if (is_pvmove)
|
||||
seg->node_count = 1;
|
||||
}
|
||||
else if (grub_memcmp (p, "raid", sizeof ("raid") - 1)
|
||||
== 0 && (p[sizeof ("raid") - 1] >= '4'
|
||||
&& p[sizeof ("raid") - 1] <= '6')
|
||||
else if (grub_memcmp (p, "raid", sizeof ("raid") - 1) == 0
|
||||
&& ((p[sizeof ("raid") - 1] >= '4'
|
||||
&& p[sizeof ("raid") - 1] <= '6')
|
||||
|| p[sizeof ("raid") - 1] == '1')
|
||||
&& p[sizeof ("raidX") - 1] == '"')
|
||||
{
|
||||
switch (p[sizeof ("raid") - 1])
|
||||
{
|
||||
case '1':
|
||||
seg->type = GRUB_DISKFILTER_MIRROR;
|
||||
break;
|
||||
case '4':
|
||||
seg->type = GRUB_DISKFILTER_RAID4;
|
||||
seg->layout = GRUB_RAID_LAYOUT_LEFT_ASYMMETRIC;
|
||||
@@ -602,21 +607,23 @@ grub_lvm_detect (grub_disk_t disk,
|
||||
if (p == NULL)
|
||||
{
|
||||
#ifdef GRUB_UTIL
|
||||
grub_util_info ("unknown device_count\n");
|
||||
grub_util_info ("unknown device_count");
|
||||
#endif
|
||||
goto lvs_segment_fail;
|
||||
}
|
||||
|
||||
seg->stripe_size = grub_lvm_getvalue (&p, "stripe_size = ");
|
||||
if (p == NULL)
|
||||
if (seg->type != GRUB_DISKFILTER_MIRROR)
|
||||
{
|
||||
seg->stripe_size = grub_lvm_getvalue (&p, "stripe_size = ");
|
||||
if (p == NULL)
|
||||
{
|
||||
#ifdef GRUB_UTIL
|
||||
grub_util_info ("unknown stripe_size\n");
|
||||
grub_util_info ("unknown stripe_size");
|
||||
#endif
|
||||
goto lvs_segment_fail;
|
||||
goto lvs_segment_fail;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
seg->nodes = grub_zalloc (sizeof (seg->nodes[0])
|
||||
* seg->node_count);
|
||||
|
||||
@@ -624,7 +631,7 @@ grub_lvm_detect (grub_disk_t disk,
|
||||
if (p == NULL)
|
||||
{
|
||||
#ifdef GRUB_UTIL
|
||||
grub_util_info ("unknown mirrors\n");
|
||||
grub_util_info ("unknown raids");
|
||||
#endif
|
||||
goto lvs_segment_fail2;
|
||||
}
|
||||
@@ -671,7 +678,7 @@ grub_lvm_detect (grub_disk_t disk,
|
||||
p2 = grub_strchr (p, '"');
|
||||
if (p2)
|
||||
*p2 = 0;
|
||||
grub_util_info ("unknown LVM type %s\n", p);
|
||||
grub_util_info ("unknown LVM type %s", p);
|
||||
if (p2)
|
||||
*p2 ='"';
|
||||
#endif
|
||||
|
||||
@@ -33,16 +33,16 @@ GRUB_MOD_LICENSE ("GPLv3+");
|
||||
#define grub_md_to_cpu64 grub_be_to_cpu64
|
||||
#define grub_md_to_cpu32 grub_be_to_cpu32
|
||||
#define grub_md_to_cpu16 grub_be_to_cpu16
|
||||
#define grub_cpu_to_md64_compile_time grub_cpu_to_be64
|
||||
#define grub_cpu_to_md32_compile_time grub_cpu_to_be32
|
||||
#define grub_cpu_to_md16_compile_time grub_cpu_to_be16
|
||||
#define grub_cpu_to_md64_compile_time grub_cpu_to_be64_compile_time
|
||||
#define grub_cpu_to_md32_compile_time grub_cpu_to_be32_compile_time
|
||||
#define grub_cpu_to_md16_compile_time grub_cpu_to_be16_compile_time
|
||||
#else
|
||||
#define grub_md_to_cpu64 grub_le_to_cpu64
|
||||
#define grub_md_to_cpu32 grub_le_to_cpu32
|
||||
#define grub_md_to_cpu16 grub_le_to_cpu16
|
||||
#define grub_cpu_to_md64_compile_time grub_cpu_to_le64
|
||||
#define grub_cpu_to_md32_compile_time grub_cpu_to_le32
|
||||
#define grub_cpu_to_md16_compile_time grub_cpu_to_le16
|
||||
#define grub_cpu_to_md64_compile_time grub_cpu_to_le64_compile_time
|
||||
#define grub_cpu_to_md32_compile_time grub_cpu_to_le32_compile_time
|
||||
#define grub_cpu_to_md16_compile_time grub_cpu_to_le16_compile_time
|
||||
#endif
|
||||
|
||||
#define RESERVED_BYTES (64 * 1024)
|
||||
|
||||
@@ -34,9 +34,9 @@ static unsigned powx_inv[256];
|
||||
static const grub_uint8_t poly = 0x1d;
|
||||
|
||||
static void
|
||||
grub_raid_block_mulx (unsigned mul, char *buf, int size)
|
||||
grub_raid_block_mulx (unsigned mul, char *buf, grub_size_t size)
|
||||
{
|
||||
int i;
|
||||
grub_size_t i;
|
||||
grub_uint8_t *p;
|
||||
|
||||
p = (grub_uint8_t *) buf;
|
||||
@@ -63,6 +63,16 @@ grub_raid6_init_table (void)
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned
|
||||
mod_255 (unsigned x)
|
||||
{
|
||||
while (x > 0xff)
|
||||
x = (x >> 8) + (x & 0xff);
|
||||
if (x == 0xff)
|
||||
return 0;
|
||||
return x;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_raid6_recover (struct grub_diskfilter_segment *array, int disknr, int p,
|
||||
char *buf, grub_disk_addr_t sector, grub_size_t size)
|
||||
@@ -162,11 +172,11 @@ grub_raid6_recover (struct grub_diskfilter_segment *array, int disknr, int p,
|
||||
|
||||
grub_crypto_xor (qbuf, qbuf, buf, size);
|
||||
|
||||
c = ((255 ^ bad1)
|
||||
+ (255 ^ powx_inv[(powx[bad2 + (bad1 ^ 255)] ^ 1)])) % 255;
|
||||
c = mod_255((255 ^ bad1)
|
||||
+ (255 ^ powx_inv[(powx[bad2 + (bad1 ^ 255)] ^ 1)]));
|
||||
grub_raid_block_mulx (c, qbuf, size);
|
||||
|
||||
c = ((unsigned) bad2 + c) % 255;
|
||||
c = mod_255((unsigned) bad2 + c);
|
||||
grub_raid_block_mulx (c, pbuf, size);
|
||||
|
||||
grub_crypto_xor (pbuf, pbuf, qbuf, size);
|
||||
|
||||
@@ -201,7 +201,7 @@ grub_scsi_read_capacity16 (grub_scsi_t scsi)
|
||||
rc.opcode = grub_scsi_cmd_read_capacity16;
|
||||
rc.lun = (scsi->lun << GRUB_SCSI_LUN_SHIFT) | 0x10;
|
||||
rc.logical_block_addr = 0;
|
||||
rc.alloc_len = grub_cpu_to_be32 (sizeof (rcd));
|
||||
rc.alloc_len = grub_cpu_to_be32_compile_time (sizeof (rcd));
|
||||
rc.PMI = 0;
|
||||
rc.control = 0;
|
||||
|
||||
@@ -615,9 +615,10 @@ grub_scsi_open (const char *name, grub_disk_t disk)
|
||||
|
||||
if (scsi->blocksize & (scsi->blocksize - 1) || !scsi->blocksize)
|
||||
{
|
||||
grub_error (GRUB_ERR_IO, "invalid sector size %d",
|
||||
scsi->blocksize);
|
||||
grub_free (scsi);
|
||||
return grub_error (GRUB_ERR_IO, "invalid sector size %d",
|
||||
scsi->blocksize);
|
||||
return grub_errno;
|
||||
}
|
||||
for (disk->log_sector_size = 0;
|
||||
(1U << disk->log_sector_size) < scsi->blocksize;
|
||||
|
||||
@@ -307,7 +307,7 @@ grub_usbms_transfer_bo (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd,
|
||||
|
||||
/* Setup the request. */
|
||||
grub_memset (&cbw, 0, sizeof (cbw));
|
||||
cbw.signature = grub_cpu_to_le32 (0x43425355);
|
||||
cbw.signature = grub_cpu_to_le32_compile_time (0x43425355);
|
||||
cbw.tag = tag;
|
||||
cbw.transfer_length = grub_cpu_to_le32 (size);
|
||||
cbw.flags = (!read_write) << GRUB_USBMS_DIRECTION_BIT;
|
||||
@@ -414,7 +414,7 @@ CheckCSW:
|
||||
|
||||
/* If phase error or not valid signature, do bulk-only reset device. */
|
||||
if ((status.status == 2) ||
|
||||
(status.signature != grub_cpu_to_le32(0x53425355)))
|
||||
(status.signature != grub_cpu_to_le32_compile_time(0x53425355)))
|
||||
{ /* Bulk-only reset device. */
|
||||
grub_dprintf ("usb", "Bulk-only reset device - bad status\n");
|
||||
grub_usbms_reset (dev);
|
||||
|
||||
@@ -40,6 +40,7 @@ struct virtdisk
|
||||
grub_xen_evtchn_t evtchn;
|
||||
void *dma_page;
|
||||
grub_xen_grant_t dma_grant;
|
||||
struct virtdisk *compat_next;
|
||||
};
|
||||
|
||||
#define xen_wmb() mb()
|
||||
@@ -47,6 +48,7 @@ struct virtdisk
|
||||
|
||||
static struct virtdisk *virtdisks;
|
||||
static grub_size_t vdiskcnt;
|
||||
struct virtdisk *compat_head;
|
||||
|
||||
static int
|
||||
grub_virtdisk_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data,
|
||||
@@ -66,20 +68,32 @@ grub_virtdisk_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data,
|
||||
static grub_err_t
|
||||
grub_virtdisk_open (const char *name, grub_disk_t disk)
|
||||
{
|
||||
grub_size_t i;
|
||||
int i;
|
||||
grub_uint32_t secsize;
|
||||
char fdir[200];
|
||||
char *buf;
|
||||
int num = -1;
|
||||
struct virtdisk *vd;
|
||||
|
||||
for (i = 0; i < vdiskcnt; i++)
|
||||
if (grub_strcmp (name, virtdisks[i].fullname) == 0)
|
||||
/* For compatibility with pv-grub legacy menu.lst accept hdX as disk name */
|
||||
if (name[0] == 'h' && name[1] == 'd' && name[2])
|
||||
{
|
||||
num = grub_strtoul (name + 2, 0, 10);
|
||||
if (grub_errno)
|
||||
{
|
||||
grub_errno = 0;
|
||||
num = -1;
|
||||
}
|
||||
}
|
||||
for (i = 0, vd = compat_head; vd; vd = vd->compat_next, i++)
|
||||
if (i == num || grub_strcmp (name, vd->fullname) == 0)
|
||||
break;
|
||||
if (i == vdiskcnt)
|
||||
if (!vd)
|
||||
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a virtdisk");
|
||||
disk->data = &virtdisks[i];
|
||||
disk->id = i;
|
||||
disk->data = vd;
|
||||
disk->id = vd - virtdisks;
|
||||
|
||||
grub_snprintf (fdir, sizeof (fdir), "%s/sectors", virtdisks[i].backend_dir);
|
||||
grub_snprintf (fdir, sizeof (fdir), "%s/sectors", vd->backend_dir);
|
||||
buf = grub_xenstore_get_file (fdir, NULL);
|
||||
if (!buf)
|
||||
return grub_errno;
|
||||
@@ -87,8 +101,7 @@ grub_virtdisk_open (const char *name, grub_disk_t disk)
|
||||
if (grub_errno)
|
||||
return grub_errno;
|
||||
|
||||
grub_snprintf (fdir, sizeof (fdir), "%s/sector-size",
|
||||
virtdisks[i].backend_dir);
|
||||
grub_snprintf (fdir, sizeof (fdir), "%s/sector-size", vd->backend_dir);
|
||||
buf = grub_xenstore_get_file (fdir, NULL);
|
||||
if (!buf)
|
||||
return grub_errno;
|
||||
@@ -264,6 +277,7 @@ fill (const char *dir, void *data)
|
||||
grub_err_t err;
|
||||
void *buf;
|
||||
struct evtchn_alloc_unbound alloc_unbound;
|
||||
struct virtdisk **prev = &compat_head, *vd = compat_head;
|
||||
|
||||
/* Shouldn't happen unles some hotplug happened. */
|
||||
if (vdiskcnt >= *ctr)
|
||||
@@ -374,6 +388,19 @@ fill (const char *dir, void *data)
|
||||
|
||||
virtdisks[vdiskcnt].frontend_dir = grub_strdup (fdir);
|
||||
|
||||
/* For compatibility with pv-grub maintain linked list sorted by handle
|
||||
value in increasing order. This allows mapping of (hdX) disk names
|
||||
from legacy menu.lst */
|
||||
while (vd)
|
||||
{
|
||||
if (vd->handle > virtdisks[vdiskcnt].handle)
|
||||
break;
|
||||
prev = &vd->compat_next;
|
||||
vd = vd->compat_next;
|
||||
}
|
||||
virtdisks[vdiskcnt].compat_next = vd;
|
||||
*prev = &virtdisks[vdiskcnt];
|
||||
|
||||
vdiskcnt++;
|
||||
return 0;
|
||||
|
||||
|
||||
@@ -154,7 +154,10 @@ grub_efiemu_init_segments (grub_efiemu_segment_t *segs, const Elf_Ehdr *e)
|
||||
s->sh_flags & SHF_EXECINSTR ? GRUB_EFI_RUNTIME_SERVICES_CODE
|
||||
: GRUB_EFI_RUNTIME_SERVICES_DATA);
|
||||
if (seg->handle < 0)
|
||||
return grub_errno;
|
||||
{
|
||||
grub_free (seg);
|
||||
return grub_errno;
|
||||
}
|
||||
seg->off = 0;
|
||||
}
|
||||
|
||||
@@ -343,7 +346,7 @@ SUFFIX (grub_efiemu_loadcore_init) (void *core, const char *filename,
|
||||
return grub_error (GRUB_ERR_BAD_MODULE, N_("this ELF file is not of the right type"));
|
||||
|
||||
/* Make sure that every section is within the core. */
|
||||
if ((grub_size_t) core_size < e->e_shoff + e->e_shentsize * e->e_shnum)
|
||||
if ((grub_size_t) core_size < e->e_shoff + (grub_uint32_t) e->e_shentsize * e->e_shnum)
|
||||
return grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
|
||||
filename);
|
||||
|
||||
|
||||
@@ -196,7 +196,7 @@ grub_efiemu_load_file (const char *filename)
|
||||
{
|
||||
grub_file_close (file);
|
||||
grub_efiemu_unload ();
|
||||
return grub_errno;
|
||||
return err;
|
||||
}
|
||||
|
||||
grub_dprintf ("efiemu", "mm initialized\n");
|
||||
|
||||
+22
-3
@@ -99,7 +99,8 @@ grub_efiemu_request_memalign (grub_size_t align, grub_size_t size,
|
||||
grub_size_t align_overhead;
|
||||
struct grub_efiemu_memrequest *ret, *cur, *prev;
|
||||
/* Check that the request is correct */
|
||||
if (type >= GRUB_EFI_MAX_MEMORY_TYPE || type <= GRUB_EFI_LOADER_CODE)
|
||||
if (type <= GRUB_EFI_LOADER_CODE || type == GRUB_EFI_PERSISTENT_MEMORY ||
|
||||
type >= GRUB_EFI_MAX_MEMORY_TYPE)
|
||||
return -2;
|
||||
|
||||
/* Add new size to requested size */
|
||||
@@ -166,6 +167,13 @@ efiemu_alloc_requests (void)
|
||||
GRUB_EFI_MEMORY_MAPPED_IO,
|
||||
GRUB_EFI_MEMORY_MAPPED_IO_PORT_SPACE,
|
||||
GRUB_EFI_PAL_CODE
|
||||
|
||||
/*
|
||||
* These are not allocatable:
|
||||
* GRUB_EFI_RESERVED_MEMORY_TYPE
|
||||
* GRUB_EFI_PERSISTENT_MEMORY
|
||||
* >= GRUB_EFI_MAX_MEMORY_TYPE
|
||||
*/
|
||||
};
|
||||
|
||||
/* Compute total memory needed */
|
||||
@@ -402,6 +410,10 @@ fill_hook (grub_uint64_t addr, grub_uint64_t size, grub_memory_type_t type,
|
||||
return grub_efiemu_add_to_mmap (addr, size,
|
||||
GRUB_EFI_ACPI_MEMORY_NVS);
|
||||
|
||||
case GRUB_MEMORY_PERSISTENT:
|
||||
case GRUB_MEMORY_PERSISTENT_LEGACY:
|
||||
return grub_efiemu_add_to_mmap (addr, size,
|
||||
GRUB_EFI_PERSISTENT_MEMORY);
|
||||
default:
|
||||
grub_dprintf ("efiemu",
|
||||
"Unknown memory type %d. Assuming unusable\n", type);
|
||||
@@ -445,7 +457,7 @@ grub_efiemu_mmap_iterate (grub_memory_hook_t hook, void *hook_data)
|
||||
case GRUB_EFI_MEMORY_MAPPED_IO:
|
||||
case GRUB_EFI_MEMORY_MAPPED_IO_PORT_SPACE:
|
||||
case GRUB_EFI_PAL_CODE:
|
||||
case GRUB_EFI_MAX_MEMORY_TYPE:
|
||||
default:
|
||||
hook (efiemu_mmap[i].physical_start, efiemu_mmap[i].num_pages * 4096,
|
||||
GRUB_MEMORY_RESERVED, hook_data);
|
||||
break;
|
||||
@@ -468,6 +480,12 @@ grub_efiemu_mmap_iterate (grub_memory_hook_t hook, void *hook_data)
|
||||
hook (efiemu_mmap[i].physical_start, efiemu_mmap[i].num_pages * 4096,
|
||||
GRUB_MEMORY_NVS, hook_data);
|
||||
break;
|
||||
|
||||
case GRUB_EFI_PERSISTENT_MEMORY:
|
||||
hook (efiemu_mmap[i].physical_start, efiemu_mmap[i].num_pages * 4096,
|
||||
GRUB_MEMORY_PERSISTENT, hook_data);
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -503,7 +521,8 @@ grub_efiemu_mmap_sort_and_uniq (void)
|
||||
[GRUB_EFI_ACPI_MEMORY_NVS] = 3,
|
||||
[GRUB_EFI_MEMORY_MAPPED_IO] = 4,
|
||||
[GRUB_EFI_MEMORY_MAPPED_IO_PORT_SPACE] = 4,
|
||||
[GRUB_EFI_PAL_CODE] = 4
|
||||
[GRUB_EFI_PAL_CODE] = 4,
|
||||
[GRUB_EFI_PERSISTENT_MEMORY] = 4
|
||||
};
|
||||
|
||||
int i, j, k, done;
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include <grub/err.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/types.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/efiemu/efiemu.h>
|
||||
#include <grub/crypto.h>
|
||||
|
||||
@@ -82,10 +83,16 @@ SUFFIX (grub_efiemu_prepare) (struct grub_efiemu_prepare_hook *prepare_hooks,
|
||||
((grub_uint8_t *) grub_efiemu_mm_obtain_request (handle) + off);
|
||||
|
||||
/* Put pointer to the list of configuration tables in system table */
|
||||
grub_efiemu_write_value
|
||||
(&(SUFFIX (grub_efiemu_system_table)->configuration_table), 0,
|
||||
conftable_handle, 0, 1,
|
||||
sizeof (SUFFIX (grub_efiemu_system_table)->configuration_table));
|
||||
err = grub_efiemu_write_value
|
||||
(&(SUFFIX (grub_efiemu_system_table)->configuration_table), 0,
|
||||
conftable_handle, 0, 1,
|
||||
sizeof (SUFFIX (grub_efiemu_system_table)->configuration_table));
|
||||
if (err)
|
||||
{
|
||||
grub_efiemu_unload ();
|
||||
return err;
|
||||
}
|
||||
|
||||
SUFFIX(grub_efiemu_system_table)->num_table_entries = cntconftables;
|
||||
|
||||
/* Fill the list of configuration tables */
|
||||
|
||||
@@ -777,6 +777,7 @@ grub_font_get_glyph_internal (grub_font_t font, grub_uint32_t code)
|
||||
if (grub_file_read (font->file, glyph->bitmap, len) != len)
|
||||
{
|
||||
remove_font (font);
|
||||
grub_free (glyph);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -1285,7 +1286,7 @@ blit_comb (const struct grub_unicode_glyph *glyph_id,
|
||||
- grub_font_get_xheight (combining_glyphs[i]->font) - 1;
|
||||
if (space <= 0)
|
||||
space = 1 + (grub_font_get_xheight (main_glyph->font)) / 8;
|
||||
|
||||
/* Fallthrough. */
|
||||
case GRUB_UNICODE_STACK_ATTACHED_ABOVE:
|
||||
do_blit (combining_glyphs[i], targetx,
|
||||
-(ctx.bounds.height + ctx.bounds.y + space
|
||||
@@ -1326,6 +1327,7 @@ blit_comb (const struct grub_unicode_glyph *glyph_id,
|
||||
+ combining_glyphs[i]->height);
|
||||
if (space <= 0)
|
||||
space = 1 + (grub_font_get_xheight (main_glyph->font)) / 8;
|
||||
/* Fallthrough. */
|
||||
|
||||
case GRUB_UNICODE_STACK_ATTACHED_BELOW:
|
||||
do_blit (combining_glyphs[i], targetx, -(ctx.bounds.y - space),
|
||||
|
||||
@@ -34,12 +34,12 @@ canonicalize (char *name)
|
||||
iptr++;
|
||||
if (iptr[0] == '.' && (iptr[1] == '/' || iptr[1] == 0))
|
||||
{
|
||||
iptr += 2;
|
||||
iptr++;
|
||||
continue;
|
||||
}
|
||||
if (iptr[0] == '.' && iptr[1] == '.' && (iptr[2] == '/' || iptr[2] == 0))
|
||||
{
|
||||
iptr += 3;
|
||||
iptr += 2;
|
||||
if (optr == name)
|
||||
continue;
|
||||
for (optr -= 2; optr >= name && *optr != '/'; optr--);
|
||||
@@ -249,9 +249,10 @@ grub_archelp_open (struct grub_archelp_data *data,
|
||||
while (1)
|
||||
{
|
||||
grub_uint32_t mode;
|
||||
grub_int32_t mtime;
|
||||
int restart;
|
||||
|
||||
if (arcops->find_file (data, &fn, NULL, &mode))
|
||||
if (arcops->find_file (data, &fn, &mtime, &mode))
|
||||
goto fail;
|
||||
|
||||
if (mode == GRUB_ARCHELP_ATTR_END)
|
||||
|
||||
+104
-117
@@ -29,6 +29,7 @@
|
||||
#include <grub/dl.h>
|
||||
#include <grub/types.h>
|
||||
#include <grub/i18n.h>
|
||||
#include <grub/fshelp.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
@@ -561,10 +562,10 @@ iterate_in_b_tree (grub_disk_t disk,
|
||||
}
|
||||
|
||||
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;
|
||||
while (blen && alen)
|
||||
while (*b && alen)
|
||||
{
|
||||
if (*a != *b)
|
||||
break;
|
||||
@@ -572,11 +573,10 @@ bfs_strcmp (const char *a, const char *b, grub_size_t alen, grub_size_t blen)
|
||||
a++;
|
||||
b++;
|
||||
alen--;
|
||||
blen--;
|
||||
}
|
||||
|
||||
ac = alen ? *a : 0;
|
||||
bc = blen ? *b : 0;
|
||||
bc = *b;
|
||||
|
||||
#ifdef MODE_AFS
|
||||
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,
|
||||
const struct grub_bfs_superblock *sb,
|
||||
const struct grub_bfs_inode *ino, const char *name,
|
||||
grub_size_t name_len,
|
||||
grub_uint64_t * res)
|
||||
{
|
||||
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))]);
|
||||
if (grub_bfs_to_cpu_treehead (node->total_key_len) <= end)
|
||||
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)
|
||||
{
|
||||
*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]);
|
||||
if (grub_bfs_to_cpu_treehead (node->total_key_len) <= end)
|
||||
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)
|
||||
{
|
||||
*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
|
||||
hop_level (grub_disk_t disk,
|
||||
const struct grub_bfs_superblock *sb,
|
||||
struct grub_bfs_inode *ino, const char *name,
|
||||
const char *name_end)
|
||||
lookup_file (grub_fshelp_node_t dir,
|
||||
const char *name,
|
||||
grub_fshelp_node_t *foundnode,
|
||||
enum grub_fshelp_filetype *foundtype)
|
||||
{
|
||||
grub_err_t err;
|
||||
struct grub_bfs_inode *new_ino;
|
||||
grub_uint64_t res = 0;
|
||||
|
||||
if (((grub_bfs_to_cpu32 (ino->mode) & ATTR_TYPE) != ATTR_DIR))
|
||||
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);
|
||||
err = find_in_b_tree (dir->disk, dir->sb, &dir->ino, name, &res);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return grub_disk_read (disk, res
|
||||
<< (grub_bfs_to_cpu32 (sb->log2_bsize)
|
||||
- GRUB_DISK_SECTOR_BITS), 0,
|
||||
sizeof (*ino), (char *) ino);
|
||||
*foundnode = grub_malloc (sizeof (struct grub_fshelp_node));
|
||||
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,
|
||||
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
|
||||
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;
|
||||
struct grub_bfs_inode old_ino;
|
||||
unsigned symlinks_max = 32;
|
||||
struct grub_fshelp_node root = {
|
||||
.disk = disk,
|
||||
.sb = sb,
|
||||
};
|
||||
struct grub_fshelp_node *found;
|
||||
|
||||
err = read_extent (disk, sb, &sb->root_dir, 0, 0, ino,
|
||||
sizeof (*ino));
|
||||
err = read_extent (disk, sb, &sb->root_dir, 0, 0, &root.ino,
|
||||
sizeof (root.ino));
|
||||
if (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)
|
||||
{
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
if (&root != found)
|
||||
grub_free (found);
|
||||
return err;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
@@ -909,11 +900,9 @@ grub_bfs_dir (grub_device_t device, const char *path,
|
||||
|
||||
{
|
||||
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)
|
||||
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,
|
||||
&ctx);
|
||||
}
|
||||
@@ -934,11 +923,9 @@ grub_bfs_open (struct grub_file *file, const char *name)
|
||||
{
|
||||
struct grub_bfs_inode ino;
|
||||
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)
|
||||
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));
|
||||
if (!data)
|
||||
@@ -1034,7 +1021,7 @@ read_bfs_attr (grub_disk_t disk,
|
||||
if (err)
|
||||
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)
|
||||
return -1;
|
||||
grub_disk_read (disk, res
|
||||
|
||||
+35
-18
@@ -680,6 +680,8 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr,
|
||||
grub_uint64_t stripen;
|
||||
grub_uint64_t stripe_offset;
|
||||
grub_uint64_t off = addr - grub_le_to_cpu64 (key->offset);
|
||||
grub_uint64_t chunk_stripe_length;
|
||||
grub_uint16_t nstripes;
|
||||
unsigned redundancy = 1;
|
||||
unsigned i, j;
|
||||
|
||||
@@ -690,15 +692,17 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr,
|
||||
"couldn't find the chunk descriptor");
|
||||
}
|
||||
|
||||
nstripes = grub_le_to_cpu16 (chunk->nstripes) ? : 1;
|
||||
chunk_stripe_length = grub_le_to_cpu64 (chunk->stripe_length) ? : 512;
|
||||
grub_dprintf ("btrfs", "chunk 0x%" PRIxGRUB_UINT64_T
|
||||
"+0x%" PRIxGRUB_UINT64_T
|
||||
" (%d stripes (%d substripes) of %"
|
||||
PRIxGRUB_UINT64_T ")\n",
|
||||
grub_le_to_cpu64 (key->offset),
|
||||
grub_le_to_cpu64 (chunk->size),
|
||||
grub_le_to_cpu16 (chunk->nstripes),
|
||||
nstripes,
|
||||
grub_le_to_cpu16 (chunk->nsubstripes),
|
||||
grub_le_to_cpu64 (chunk->stripe_length));
|
||||
chunk_stripe_length);
|
||||
|
||||
switch (grub_le_to_cpu64 (chunk->type)
|
||||
& ~GRUB_BTRFS_CHUNK_TYPE_BITS_DONTCARE)
|
||||
@@ -708,8 +712,10 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr,
|
||||
grub_uint64_t stripe_length;
|
||||
grub_dprintf ("btrfs", "single\n");
|
||||
stripe_length = grub_divmod64 (grub_le_to_cpu64 (chunk->size),
|
||||
grub_le_to_cpu16 (chunk->nstripes),
|
||||
nstripes,
|
||||
NULL);
|
||||
if (stripe_length == 0)
|
||||
stripe_length = 512;
|
||||
stripen = grub_divmod64 (off, stripe_length, &stripe_offset);
|
||||
csize = (stripen + 1) * stripe_length - off;
|
||||
break;
|
||||
@@ -730,33 +736,34 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr,
|
||||
grub_uint64_t low;
|
||||
grub_dprintf ("btrfs", "RAID0\n");
|
||||
middle = grub_divmod64 (off,
|
||||
grub_le_to_cpu64 (chunk->stripe_length),
|
||||
chunk_stripe_length,
|
||||
&low);
|
||||
|
||||
high = grub_divmod64 (middle, grub_le_to_cpu16 (chunk->nstripes),
|
||||
high = grub_divmod64 (middle, nstripes,
|
||||
&stripen);
|
||||
stripe_offset =
|
||||
low + grub_le_to_cpu64 (chunk->stripe_length) * high;
|
||||
csize = grub_le_to_cpu64 (chunk->stripe_length) - low;
|
||||
low + chunk_stripe_length * high;
|
||||
csize = chunk_stripe_length - low;
|
||||
break;
|
||||
}
|
||||
case GRUB_BTRFS_CHUNK_TYPE_RAID10:
|
||||
{
|
||||
grub_uint64_t middle, high;
|
||||
grub_uint64_t low;
|
||||
grub_uint16_t nsubstripes;
|
||||
nsubstripes = grub_le_to_cpu16 (chunk->nsubstripes) ? : 1;
|
||||
middle = grub_divmod64 (off,
|
||||
grub_le_to_cpu64 (chunk->stripe_length),
|
||||
chunk_stripe_length,
|
||||
&low);
|
||||
|
||||
high = grub_divmod64 (middle,
|
||||
grub_le_to_cpu16 (chunk->nstripes)
|
||||
/ grub_le_to_cpu16 (chunk->nsubstripes),
|
||||
nstripes / nsubstripes ? : 1,
|
||||
&stripen);
|
||||
stripen *= grub_le_to_cpu16 (chunk->nsubstripes);
|
||||
redundancy = grub_le_to_cpu16 (chunk->nsubstripes);
|
||||
stripe_offset = low + grub_le_to_cpu64 (chunk->stripe_length)
|
||||
stripen *= nsubstripes;
|
||||
redundancy = nsubstripes;
|
||||
stripe_offset = low + chunk_stripe_length
|
||||
* high;
|
||||
csize = grub_le_to_cpu64 (chunk->stripe_length) - low;
|
||||
csize = chunk_stripe_length - low;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@@ -1051,7 +1058,7 @@ grub_btrfs_extent_read (struct grub_btrfs_data *data,
|
||||
|
||||
data->extend = data->extstart + grub_le_to_cpu64 (data->extent->size);
|
||||
if (data->extent->type == GRUB_BTRFS_EXTENT_REGULAR
|
||||
&& (char *) &data->extent + elemsize
|
||||
&& (char *) data->extent + elemsize
|
||||
>= (char *) &data->extent->filled + sizeof (data->extent->filled))
|
||||
data->extend =
|
||||
data->extstart + grub_le_to_cpu64 (data->extent->filled);
|
||||
@@ -1104,7 +1111,12 @@ grub_btrfs_extent_read (struct grub_btrfs_data *data,
|
||||
- (grub_uint8_t *) data->extent),
|
||||
extoff, buf, csize)
|
||||
!= (grub_ssize_t) csize)
|
||||
return -1;
|
||||
{
|
||||
if (!grub_errno)
|
||||
grub_error (GRUB_ERR_BAD_COMPRESSED_DATA,
|
||||
"premature end of compressed");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else if (data->extent->compression == GRUB_BTRFS_COMPRESSION_LZO)
|
||||
{
|
||||
@@ -1158,7 +1170,12 @@ grub_btrfs_extent_read (struct grub_btrfs_data *data,
|
||||
grub_free (tmp);
|
||||
|
||||
if (ret != (grub_ssize_t) csize)
|
||||
return -1;
|
||||
{
|
||||
if (!grub_errno)
|
||||
grub_error (GRUB_ERR_BAD_COMPRESSED_DATA,
|
||||
"premature end of compressed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -1191,7 +1208,7 @@ get_root (struct grub_btrfs_data *data, struct grub_btrfs_key *key,
|
||||
struct grub_btrfs_key key_out, key_in;
|
||||
struct grub_btrfs_root_item ri;
|
||||
|
||||
key_in.object_id = GRUB_BTRFS_ROOT_VOL_OBJECTID;
|
||||
key_in.object_id = grub_cpu_to_le64_compile_time (GRUB_BTRFS_ROOT_VOL_OBJECTID);
|
||||
key_in.offset = 0;
|
||||
key_in.type = GRUB_BTRFS_ITEM_TYPE_ROOT_ITEM;
|
||||
err = lower_bound (data, &key_in, &key_out,
|
||||
|
||||
+15
-4
@@ -74,8 +74,7 @@ grub_cbfs_find_file (struct grub_archelp_data *data, char **name,
|
||||
(void) mtime;
|
||||
offset = grub_be_to_cpu32 (hd.offset);
|
||||
|
||||
if (mode)
|
||||
*mode = GRUB_ARCHELP_ATTR_FILE | GRUB_ARCHELP_ATTR_NOTIME;
|
||||
*mode = GRUB_ARCHELP_ATTR_FILE | GRUB_ARCHELP_ATTR_NOTIME;
|
||||
|
||||
namesize = offset;
|
||||
if (namesize >= sizeof (hd))
|
||||
@@ -144,11 +143,14 @@ static struct grub_archelp_data *
|
||||
grub_cbfs_mount (grub_disk_t disk)
|
||||
{
|
||||
struct cbfs_file hd;
|
||||
struct grub_archelp_data *data;
|
||||
struct grub_archelp_data *data = NULL;
|
||||
grub_uint32_t ptr;
|
||||
grub_off_t header_off;
|
||||
struct cbfs_header head;
|
||||
|
||||
if (grub_disk_get_size (disk) == GRUB_DISK_SIZE_UNKNOWN)
|
||||
goto fail;
|
||||
|
||||
if (grub_disk_read (disk, grub_disk_get_size (disk) - 1,
|
||||
GRUB_DISK_SECTOR_SIZE - sizeof (ptr),
|
||||
sizeof (ptr), &ptr))
|
||||
@@ -193,6 +195,7 @@ grub_cbfs_mount (grub_disk_t disk)
|
||||
return data;
|
||||
|
||||
fail:
|
||||
grub_free (data);
|
||||
grub_error (GRUB_ERR_BAD_FS, "not a cbfs filesystem");
|
||||
return 0;
|
||||
}
|
||||
@@ -341,8 +344,16 @@ init_cbfsdisk (void)
|
||||
|
||||
ptr = *(grub_uint32_t *) 0xfffffffc;
|
||||
head = (struct cbfs_header *) (grub_addr_t) ptr;
|
||||
grub_dprintf ("cbfs", "head=%p\n", head);
|
||||
|
||||
if (!validate_head (head))
|
||||
/* coreboot current supports only ROMs <= 16 MiB. Bigger ROMs will
|
||||
have problems as RCBA is 18 MiB below end of 32-bit typically,
|
||||
so either memory map would have to be rearranged or we'd need to support
|
||||
reading ROMs through controller directly.
|
||||
*/
|
||||
if (ptr < 0xff000000
|
||||
|| 0xffffffff - ptr < (grub_uint32_t) sizeof (*head) + 0xf
|
||||
|| !validate_head (head))
|
||||
return;
|
||||
|
||||
cbfsdisk_size = ALIGN_UP (grub_be_to_cpu32 (head->romsize),
|
||||
|
||||
@@ -61,8 +61,15 @@ grub_cpio_find_file (struct grub_archelp_data *data, char **name,
|
||||
modeval = read_number (hd.mode, ARRAY_SIZE (hd.mode));
|
||||
namesize = read_number (hd.namesize, ARRAY_SIZE (hd.namesize));
|
||||
|
||||
if (mode)
|
||||
*mode = modeval;
|
||||
/* Don't allow negative numbers. */
|
||||
if (namesize >= 0x80000000)
|
||||
{
|
||||
/* Probably a corruption, don't attempt to recover. */
|
||||
*mode = GRUB_ARCHELP_ATTR_END;
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
*mode = modeval;
|
||||
|
||||
*name = grub_malloc (namesize + 1);
|
||||
if (*name == NULL)
|
||||
|
||||
+79
-10
@@ -103,6 +103,7 @@ GRUB_MOD_LICENSE ("GPLv3+");
|
||||
#define EXT2_FEATURE_INCOMPAT_META_BG 0x0010
|
||||
#define EXT4_FEATURE_INCOMPAT_EXTENTS 0x0040 /* Extents used */
|
||||
#define EXT4_FEATURE_INCOMPAT_64BIT 0x0080
|
||||
#define EXT4_FEATURE_INCOMPAT_MMP 0x0100
|
||||
#define EXT4_FEATURE_INCOMPAT_FLEX_BG 0x0200
|
||||
#define EXT4_FEATURE_INCOMPAT_EA_INODE 0x0400 /* EA in inode */
|
||||
#define EXT4_FEATURE_INCOMPAT_DIRDATA 0x1000 /* data in dirent */
|
||||
@@ -115,6 +116,7 @@ GRUB_MOD_LICENSE ("GPLv3+");
|
||||
#define EXT2_DRIVER_SUPPORTED_INCOMPAT ( EXT2_FEATURE_INCOMPAT_FILETYPE \
|
||||
| EXT4_FEATURE_INCOMPAT_EXTENTS \
|
||||
| EXT4_FEATURE_INCOMPAT_FLEX_BG \
|
||||
| EXT2_FEATURE_INCOMPAT_META_BG \
|
||||
| EXT4_FEATURE_INCOMPAT_64BIT \
|
||||
| EXT4_FEATURE_INCOMPAT_INLINE_DATA)
|
||||
/* List of rationales for the ignored "incompatible" features:
|
||||
@@ -123,8 +125,13 @@ GRUB_MOD_LICENSE ("GPLv3+");
|
||||
* journal because they will ignore the journal, but the next
|
||||
* ext3 driver to mount the volume will find the journal and
|
||||
* replay it, potentially corrupting the metadata written by
|
||||
* the ext2 drivers. Safe to ignore for this RO driver. */
|
||||
#define EXT2_DRIVER_IGNORED_INCOMPAT ( EXT3_FEATURE_INCOMPAT_RECOVER )
|
||||
* the ext2 drivers. Safe to ignore for this RO driver.
|
||||
* mmp: Not really back-incompatible - was added as such to
|
||||
* avoid multiple read-write mounts. Safe to ignore for this
|
||||
* RO driver.
|
||||
*/
|
||||
#define EXT2_DRIVER_IGNORED_INCOMPAT ( EXT3_FEATURE_INCOMPAT_RECOVER \
|
||||
| EXT4_FEATURE_INCOMPAT_MMP)
|
||||
|
||||
|
||||
#define EXT3_JOURNAL_MAGIC_NUMBER 0xc03b3998U
|
||||
@@ -368,6 +375,35 @@ static grub_dl_t my_mod;
|
||||
|
||||
|
||||
|
||||
/* Check is a = b^x for some x. */
|
||||
static inline int
|
||||
is_power_of (grub_uint64_t a, grub_uint32_t b)
|
||||
{
|
||||
grub_uint64_t c;
|
||||
/* Prevent overflow assuming b < 8. */
|
||||
if (a >= (1LL << 60))
|
||||
return 0;
|
||||
for (c = 1; c <= a; c *= b);
|
||||
return (c == a);
|
||||
}
|
||||
|
||||
|
||||
static inline int
|
||||
group_has_super_block (struct grub_ext2_data *data, grub_uint64_t group)
|
||||
{
|
||||
if (!(data->sblock.feature_ro_compat
|
||||
& grub_cpu_to_le32_compile_time(EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER)))
|
||||
return 1;
|
||||
/* Algorithm looked up in Linux source. */
|
||||
if (group <= 1)
|
||||
return 1;
|
||||
/* Even number is never a power of odd number. */
|
||||
if (!(group & 1))
|
||||
return 0;
|
||||
return (is_power_of(group, 7) || is_power_of(group, 5) ||
|
||||
is_power_of(group, 3));
|
||||
}
|
||||
|
||||
/* Inline data is stored using inline extended attributes. Attributes consist
|
||||
of entry and value. Entries start after inode proper, following 4 bytes
|
||||
magic header. Each entry is 4 bytes aligned, end of list is marked with
|
||||
@@ -431,13 +467,36 @@ grub_ext2_find_inline_data (struct grub_fshelp_node *node, grub_size_t isize,
|
||||
/* Read into BLKGRP the blockgroup descriptor of blockgroup GROUP of
|
||||
the mounted filesystem DATA. */
|
||||
inline static grub_err_t
|
||||
grub_ext2_blockgroup (struct grub_ext2_data *data, int group,
|
||||
grub_ext2_blockgroup (struct grub_ext2_data *data, grub_uint64_t group,
|
||||
struct grub_ext2_block_group *blkgrp)
|
||||
{
|
||||
grub_uint64_t full_offset = (group << data->log_group_desc_size);
|
||||
grub_uint64_t block, offset;
|
||||
block = (full_offset >> LOG2_BLOCK_SIZE (data));
|
||||
offset = (full_offset & ((1 << LOG2_BLOCK_SIZE (data)) - 1));
|
||||
if ((data->sblock.feature_incompat
|
||||
& grub_cpu_to_le32_compile_time (EXT2_FEATURE_INCOMPAT_META_BG))
|
||||
&& block >= grub_le_to_cpu32(data->sblock.first_meta_bg))
|
||||
{
|
||||
grub_uint64_t first_block_group;
|
||||
/* Find the first block group for which a descriptor
|
||||
is stored in given block. */
|
||||
first_block_group = (block << (LOG2_BLOCK_SIZE (data)
|
||||
- data->log_group_desc_size));
|
||||
|
||||
block = (first_block_group
|
||||
* grub_le_to_cpu32(data->sblock.blocks_per_group));
|
||||
|
||||
if (group_has_super_block (data, first_block_group))
|
||||
block++;
|
||||
}
|
||||
else
|
||||
/* Superblock. */
|
||||
block++;
|
||||
return grub_disk_read (data->disk,
|
||||
((grub_le_to_cpu32 (data->sblock.first_data_block) + 1)
|
||||
<< LOG2_EXT2_BLOCK_SIZE (data)),
|
||||
group << data->log_group_desc_size,
|
||||
((grub_le_to_cpu32 (data->sblock.first_data_block)
|
||||
+ block)
|
||||
<< LOG2_EXT2_BLOCK_SIZE (data)), offset,
|
||||
sizeof (struct grub_ext2_block_group), blkgrp);
|
||||
}
|
||||
|
||||
@@ -576,11 +635,16 @@ grub_ext2_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
|
||||
shift = 2;
|
||||
goto indirect;
|
||||
}
|
||||
return grub_error (GRUB_ERR_BAD_FS,
|
||||
"ext2fs doesn't support quadruple indirect blocks");
|
||||
grub_error (GRUB_ERR_BAD_FS,
|
||||
"ext2fs doesn't support quadruple indirect blocks");
|
||||
return -1;
|
||||
|
||||
indirect:
|
||||
do {
|
||||
/* If the indirect block is zero, all child blocks are absent
|
||||
(i.e. filled with zeros.) */
|
||||
if (indir == 0)
|
||||
return 0;
|
||||
if (grub_disk_read (data->disk,
|
||||
((grub_disk_addr_t) grub_le_to_cpu32 (indir))
|
||||
<< log2_blksz,
|
||||
@@ -588,7 +652,7 @@ indirect:
|
||||
& ((1 << log_perblock) - 1))
|
||||
* sizeof (indir),
|
||||
sizeof (indir), &indir))
|
||||
return grub_errno;
|
||||
return -1;
|
||||
} while (shift--);
|
||||
|
||||
return grub_le_to_cpu32 (indir);
|
||||
@@ -737,7 +801,12 @@ grub_ext2_mount (grub_disk_t disk)
|
||||
|
||||
/* Make sure this is an ext2 filesystem. */
|
||||
if (data->sblock.magic != grub_cpu_to_le16_compile_time (EXT2_MAGIC)
|
||||
|| grub_le_to_cpu32 (data->sblock.log2_block_size) >= 16)
|
||||
|| grub_le_to_cpu32 (data->sblock.log2_block_size) >= 16
|
||||
|| data->sblock.inodes_per_group == 0
|
||||
/* 20 already means 1GiB blocks. We don't want to deal with blocks overflowing int32. */
|
||||
|| grub_le_to_cpu32 (data->sblock.log2_block_size) > 20
|
||||
|| EXT2_INODE_SIZE (data) == 0
|
||||
|| EXT2_BLOCK_SIZE (data) / EXT2_INODE_SIZE (data) == 0)
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_FS, "not an ext2 filesystem");
|
||||
goto fail;
|
||||
|
||||
+175
-171
@@ -31,6 +31,7 @@
|
||||
#else
|
||||
#include <grub/exfat.h>
|
||||
#endif
|
||||
#include <grub/fshelp.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
@@ -173,8 +174,6 @@ struct grub_fat_data
|
||||
#ifndef MODE_EXFAT
|
||||
grub_uint32_t root_sector;
|
||||
grub_uint32_t num_root_sectors;
|
||||
#else
|
||||
int is_contiguous;
|
||||
#endif
|
||||
|
||||
int cluster_bits;
|
||||
@@ -182,13 +181,22 @@ struct grub_fat_data
|
||||
grub_uint32_t cluster_sector;
|
||||
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_ssize_t file_size;
|
||||
grub_uint32_t file_cluster;
|
||||
grub_uint32_t cur_cluster_num;
|
||||
grub_uint32_t cur_cluster;
|
||||
|
||||
grub_uint32_t uuid;
|
||||
#ifdef MODE_EXFAT
|
||||
int is_contiguous;
|
||||
#endif
|
||||
};
|
||||
|
||||
static grub_dl_t my_mod;
|
||||
@@ -427,13 +435,6 @@ grub_fat_mount (grub_disk_t disk)
|
||||
(void) magic;
|
||||
#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;
|
||||
|
||||
fail:
|
||||
@@ -444,7 +445,7 @@ grub_fat_mount (grub_disk_t disk)
|
||||
}
|
||||
|
||||
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_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
|
||||
/* This is a special case. FAT12 and FAT16 doesn't have the root directory
|
||||
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)
|
||||
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 size;
|
||||
@@ -471,12 +472,12 @@ grub_fat_read_data (grub_disk_t disk, struct grub_fat_data *data,
|
||||
#endif
|
||||
|
||||
#ifdef MODE_EXFAT
|
||||
if (data->is_contiguous)
|
||||
if (node->is_contiguous)
|
||||
{
|
||||
/* Read the data here. */
|
||||
sector = (data->cluster_sector
|
||||
+ ((data->file_cluster - 2)
|
||||
<< data->cluster_bits));
|
||||
sector = (node->data->cluster_sector
|
||||
+ ((node->file_cluster - 2)
|
||||
<< node->data->cluster_bits));
|
||||
|
||||
disk->read_hook = read_hook;
|
||||
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
|
||||
|
||||
/* Calculate the logical cluster number and offset. */
|
||||
logical_cluster_bits = (data->cluster_bits
|
||||
logical_cluster_bits = (node->data->cluster_bits
|
||||
+ GRUB_DISK_SECTOR_BITS);
|
||||
logical_cluster = offset >> logical_cluster_bits;
|
||||
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;
|
||||
data->cur_cluster = data->file_cluster;
|
||||
node->cur_cluster_num = 0;
|
||||
node->cur_cluster = node->file_cluster;
|
||||
}
|
||||
|
||||
while (len)
|
||||
{
|
||||
while (logical_cluster > data->cur_cluster_num)
|
||||
while (logical_cluster > node->cur_cluster_num)
|
||||
{
|
||||
/* Find next cluster. */
|
||||
grub_uint32_t next_cluster;
|
||||
grub_uint32_t fat_offset;
|
||||
|
||||
switch (data->fat_size)
|
||||
switch (node->data->fat_size)
|
||||
{
|
||||
case 32:
|
||||
fat_offset = data->cur_cluster << 2;
|
||||
fat_offset = node->cur_cluster << 2;
|
||||
break;
|
||||
case 16:
|
||||
fat_offset = data->cur_cluster << 1;
|
||||
fat_offset = node->cur_cluster << 1;
|
||||
break;
|
||||
default:
|
||||
/* case 12: */
|
||||
fat_offset = data->cur_cluster + (data->cur_cluster >> 1);
|
||||
fat_offset = node->cur_cluster + (node->cur_cluster >> 1);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Read the FAT. */
|
||||
if (grub_disk_read (disk, data->fat_sector, fat_offset,
|
||||
(data->fat_size + 7) >> 3,
|
||||
if (grub_disk_read (disk, node->data->fat_sector, fat_offset,
|
||||
(node->data->fat_size + 7) >> 3,
|
||||
(char *) &next_cluster))
|
||||
return -1;
|
||||
|
||||
next_cluster = grub_le_to_cpu32 (next_cluster);
|
||||
switch (data->fat_size)
|
||||
switch (node->data->fat_size)
|
||||
{
|
||||
case 16:
|
||||
next_cluster &= 0xFFFF;
|
||||
break;
|
||||
case 12:
|
||||
if (data->cur_cluster & 1)
|
||||
if (node->cur_cluster & 1)
|
||||
next_cluster >>= 4;
|
||||
|
||||
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",
|
||||
data->fat_size, next_cluster);
|
||||
node->data->fat_size, next_cluster);
|
||||
|
||||
/* Check the end. */
|
||||
if (next_cluster >= data->cluster_eof_mark)
|
||||
if (next_cluster >= node->data->cluster_eof_mark)
|
||||
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",
|
||||
next_cluster);
|
||||
return -1;
|
||||
}
|
||||
|
||||
data->cur_cluster = next_cluster;
|
||||
data->cur_cluster_num++;
|
||||
node->cur_cluster = next_cluster;
|
||||
node->cur_cluster_num++;
|
||||
}
|
||||
|
||||
/* Read the data here. */
|
||||
sector = (data->cluster_sector
|
||||
+ ((data->cur_cluster - 2)
|
||||
<< data->cluster_bits));
|
||||
sector = (node->data->cluster_sector
|
||||
+ ((node->cur_cluster - 2)
|
||||
<< node->data->cluster_bits));
|
||||
size = (1 << logical_cluster_bits) - offset;
|
||||
if (size > len)
|
||||
size = len;
|
||||
@@ -631,7 +632,7 @@ grub_fat_iterate_fini (struct grub_fat_iterate_context *ctxt)
|
||||
|
||||
#ifdef MODE_EXFAT
|
||||
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)
|
||||
{
|
||||
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);
|
||||
|
||||
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)
|
||||
!= sizeof (dir))
|
||||
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;
|
||||
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)
|
||||
!= sizeof (sec))
|
||||
break;
|
||||
@@ -680,7 +681,7 @@ grub_fat_iterate_dir_next (grub_disk_t disk, struct grub_fat_data *data,
|
||||
ctxt->dir.file_size
|
||||
= grub_cpu_to_le64 (sec.type_specific.stream_extension.file_size);
|
||||
ctxt->dir.have_stream = 1;
|
||||
ctxt->dir.is_contiguous = !!(dir.type_specific.stream_extension.flags
|
||||
ctxt->dir.is_contiguous = !!(sec.type_specific.stream_extension.flags
|
||||
& grub_cpu_to_le16_compile_time (FLAG_CONTIGUOUS));
|
||||
break;
|
||||
case 0xc1:
|
||||
@@ -727,7 +728,7 @@ grub_fat_iterate_dir_next (grub_disk_t disk, struct grub_fat_data *data,
|
||||
#else
|
||||
|
||||
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)
|
||||
{
|
||||
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);
|
||||
|
||||
/* 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),
|
||||
(char *) &ctxt->dir)
|
||||
!= sizeof (ctxt->dir) || ctxt->dir.name[0] == 0)
|
||||
@@ -829,7 +830,9 @@ grub_fat_iterate_dir_next (grub_disk_t disk, struct grub_fat_data *data,
|
||||
i--;
|
||||
}
|
||||
|
||||
*filep++ = '.';
|
||||
/* XXX should we check that dir position is 0 or 1? */
|
||||
if (i > 2 || filep[0] != '.' || (i == 2 && filep[1] != '.'))
|
||||
*filep++ = '.';
|
||||
|
||||
for (i = 8; i < 11 && ctxt->dir.name[i]; i++)
|
||||
*filep++ = grub_tolower (ctxt->dir.name[i]);
|
||||
@@ -851,62 +854,20 @@ grub_fat_iterate_dir_next (grub_disk_t disk, struct grub_fat_data *data,
|
||||
|
||||
#endif
|
||||
|
||||
/* Find the underlying directory or file in PATH and return the
|
||||
next path. If there is no next path or an error occurs, return NULL.
|
||||
If HOOK is specified, call it with each file name. */
|
||||
static char *
|
||||
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)
|
||||
static grub_err_t lookup_file (grub_fshelp_node_t node,
|
||||
const char *name,
|
||||
grub_fshelp_node_t *foundnode,
|
||||
enum grub_fshelp_filetype *foundtype)
|
||||
{
|
||||
char *dirname, *dirp;
|
||||
int call_hook;
|
||||
int found = 0;
|
||||
struct grub_fat_iterate_context ctxt;
|
||||
grub_err_t err;
|
||||
|
||||
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);
|
||||
struct grub_fat_iterate_context ctxt;
|
||||
|
||||
err = grub_fat_iterate_init (&ctxt);
|
||||
if (err)
|
||||
{
|
||||
grub_free (dirname);
|
||||
return 0;
|
||||
}
|
||||
return err;
|
||||
|
||||
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
|
||||
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)
|
||||
continue;
|
||||
#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;
|
||||
data->attr = ctxt.dir.attr;
|
||||
*foundnode = grub_malloc (sizeof (struct grub_fshelp_node));
|
||||
if (!*foundnode)
|
||||
return grub_errno;
|
||||
(*foundnode)->attr = ctxt.dir.attr;
|
||||
#ifdef MODE_EXFAT
|
||||
data->file_size = ctxt.dir.file_size;
|
||||
data->file_cluster = ctxt.dir.first_cluster;
|
||||
data->is_contiguous = ctxt.dir.is_contiguous;
|
||||
(*foundnode)->file_size = ctxt.dir.file_size;
|
||||
(*foundnode)->file_cluster = ctxt.dir.first_cluster;
|
||||
(*foundnode)->is_contiguous = ctxt.dir.is_contiguous;
|
||||
#else
|
||||
data->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_size = grub_le_to_cpu32 (ctxt.dir.file_size);
|
||||
(*foundnode)->file_cluster = ((grub_le_to_cpu16 (ctxt.dir.first_cluster_high) << 16)
|
||||
| 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
|
||||
data->cur_cluster_num = ~0U;
|
||||
(*foundnode)->cur_cluster_num = ~0U;
|
||||
(*foundnode)->data = node->data;
|
||||
(*foundnode)->disk = node->disk;
|
||||
|
||||
if (call_hook)
|
||||
hook (ctxt.filename, &info, hook_data);
|
||||
*foundtype = ((*foundnode)->attr & GRUB_FAT_ATTR_DIRECTORY) ? GRUB_FSHELP_DIR : GRUB_FSHELP_REG;
|
||||
|
||||
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)
|
||||
err = 0;
|
||||
|
||||
if (grub_errno == GRUB_ERR_NONE && ! found && !call_hook)
|
||||
grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"), origpath);
|
||||
return err;
|
||||
|
||||
fail:
|
||||
grub_free (dirname);
|
||||
|
||||
return found ? dirp : 0;
|
||||
}
|
||||
|
||||
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;
|
||||
grub_disk_t disk = device->disk;
|
||||
grub_size_t len;
|
||||
char *dirname = 0;
|
||||
char *p;
|
||||
grub_fshelp_node_t found = NULL;
|
||||
grub_err_t err;
|
||||
struct grub_fat_iterate_context ctxt;
|
||||
|
||||
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)
|
||||
goto fail;
|
||||
|
||||
/* Make sure that DIRNAME terminates with '/'. */
|
||||
len = grub_strlen (path);
|
||||
dirname = grub_malloc (len + 1 + 1);
|
||||
if (! dirname)
|
||||
goto fail;
|
||||
grub_memcpy (dirname, path, len);
|
||||
p = dirname + len;
|
||||
if (path[len - 1] != '/')
|
||||
*p++ = '/';
|
||||
*p = '\0';
|
||||
p = dirname;
|
||||
struct grub_fshelp_node root = {
|
||||
.data = data,
|
||||
.disk = disk,
|
||||
.attr = GRUB_FAT_ATTR_DIRECTORY,
|
||||
.file_size = 0,
|
||||
.file_cluster = data->root_cluster,
|
||||
.cur_cluster_num = ~0U,
|
||||
.cur_cluster = 0,
|
||||
#ifdef MODE_EXFAT
|
||||
.is_contiguous = 0,
|
||||
#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:
|
||||
if (found != &root)
|
||||
grub_free (found);
|
||||
|
||||
grub_free (dirname);
|
||||
grub_free (data);
|
||||
|
||||
grub_dl_unref (my_mod);
|
||||
@@ -1006,35 +988,43 @@ static grub_err_t
|
||||
grub_fat_open (grub_file_t file, const char *name)
|
||||
{
|
||||
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);
|
||||
|
||||
data = grub_fat_mount (file->device->disk);
|
||||
data = grub_fat_mount (disk);
|
||||
if (! data)
|
||||
goto fail;
|
||||
|
||||
do
|
||||
{
|
||||
p = grub_fat_find_dir (file->device->disk, data, p, name, 0, 0);
|
||||
if (grub_errno != GRUB_ERR_NONE)
|
||||
goto fail;
|
||||
}
|
||||
while (p);
|
||||
struct grub_fshelp_node root = {
|
||||
.data = data,
|
||||
.disk = disk,
|
||||
.attr = GRUB_FAT_ATTR_DIRECTORY,
|
||||
.file_size = 0,
|
||||
.file_cluster = data->root_cluster,
|
||||
.cur_cluster_num = ~0U,
|
||||
.cur_cluster = 0,
|
||||
#ifdef MODE_EXFAT
|
||||
.is_contiguous = 0,
|
||||
#endif
|
||||
};
|
||||
|
||||
if (data->attr & GRUB_FAT_ATTR_DIRECTORY)
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a regular file"));
|
||||
goto fail;
|
||||
}
|
||||
err = grub_fshelp_find_file_lookup (name, &root, &found, lookup_file, NULL, GRUB_FSHELP_REG);
|
||||
if (err)
|
||||
goto fail;
|
||||
|
||||
file->data = data;
|
||||
file->size = data->file_size;
|
||||
file->data = found;
|
||||
file->size = found->file_size;
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
|
||||
fail:
|
||||
|
||||
if (found != &root)
|
||||
grub_free (found);
|
||||
|
||||
grub_free (data);
|
||||
|
||||
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
|
||||
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);
|
||||
|
||||
@@ -1066,20 +1059,29 @@ grub_fat_label (grub_device_t device, char **label)
|
||||
{
|
||||
struct grub_fat_dir_entry dir;
|
||||
grub_ssize_t offset = -sizeof(dir);
|
||||
struct grub_fat_data *data;
|
||||
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);
|
||||
if (! data)
|
||||
root.data = grub_fat_mount (disk);
|
||||
if (! root.data)
|
||||
return grub_errno;
|
||||
|
||||
root.file_cluster = root.data->root_cluster;
|
||||
|
||||
*label = NULL;
|
||||
|
||||
while (1)
|
||||
{
|
||||
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)
|
||||
!= sizeof (dir))
|
||||
break;
|
||||
@@ -1099,7 +1101,7 @@ grub_fat_label (grub_device_t device, char **label)
|
||||
* GRUB_MAX_UTF8_PER_UTF16 + 1);
|
||||
if (!*label)
|
||||
{
|
||||
grub_free (data);
|
||||
grub_free (root.data);
|
||||
return grub_errno;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -1120,30 +1122,32 @@ grub_fat_label (grub_device_t device, char **label)
|
||||
static grub_err_t
|
||||
grub_fat_label (grub_device_t device, char **label)
|
||||
{
|
||||
struct grub_fat_data *data;
|
||||
grub_disk_t disk = device->disk;
|
||||
grub_err_t err;
|
||||
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;
|
||||
|
||||
grub_dl_ref (my_mod);
|
||||
|
||||
data = grub_fat_mount (disk);
|
||||
if (! data)
|
||||
root.data = grub_fat_mount (disk);
|
||||
if (! root.data)
|
||||
goto fail;
|
||||
|
||||
if (! (data->attr & GRUB_FAT_ATTR_DIRECTORY))
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory"));
|
||||
return 0;
|
||||
}
|
||||
root.file_cluster = root.data->root_cluster;
|
||||
|
||||
err = grub_fat_iterate_init (&ctxt);
|
||||
if (err)
|
||||
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)
|
||||
{
|
||||
*label = grub_strdup (ctxt.filename);
|
||||
@@ -1156,7 +1160,7 @@ grub_fat_label (grub_device_t device, char **label)
|
||||
|
||||
grub_dl_unref (my_mod);
|
||||
|
||||
grub_free (data);
|
||||
grub_free (root.data);
|
||||
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
+224
-107
@@ -30,169 +30,287 @@ GRUB_MOD_LICENSE ("GPLv3+");
|
||||
typedef int (*iterate_dir_func) (grub_fshelp_node_t dir,
|
||||
grub_fshelp_iterate_dir_hook_t hook,
|
||||
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);
|
||||
|
||||
struct stack_element {
|
||||
struct stack_element *parent;
|
||||
grub_fshelp_node_t node;
|
||||
enum grub_fshelp_filetype type;
|
||||
};
|
||||
|
||||
/* Context for grub_fshelp_find_file. */
|
||||
struct grub_fshelp_find_file_ctx
|
||||
{
|
||||
/* Inputs. */
|
||||
const char *path;
|
||||
grub_fshelp_node_t rootnode, currroot, currnode, oldnode;
|
||||
enum grub_fshelp_filetype foundtype;
|
||||
grub_fshelp_node_t rootnode;
|
||||
|
||||
/* Global options. */
|
||||
int symlinknest;
|
||||
const char *name;
|
||||
const char *next;
|
||||
enum grub_fshelp_filetype type;
|
||||
|
||||
/* Current file being traversed and its parents. */
|
||||
struct stack_element *currnode;
|
||||
};
|
||||
|
||||
/* Helper for find_file_iter. */
|
||||
static void
|
||||
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);
|
||||
}
|
||||
|
||||
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. */
|
||||
static int
|
||||
find_file_iter (const char *filename, enum grub_fshelp_filetype filetype,
|
||||
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 ||
|
||||
((filetype & GRUB_FSHELP_CASE_INSENSITIVE)
|
||||
? grub_strncasecmp (ctx->name, filename, ctx->next - ctx->name)
|
||||
: grub_strncmp (ctx->name, filename, ctx->next - ctx->name))
|
||||
|| filename[ctx->next - ctx->name])
|
||||
? grub_strcasecmp (ctx->name, filename)
|
||||
: grub_strcmp (ctx->name, filename)))
|
||||
{
|
||||
grub_free (node);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* The node is found, stop iterating over the nodes. */
|
||||
ctx->type = filetype & ~GRUB_FSHELP_CASE_INSENSITIVE;
|
||||
ctx->oldnode = ctx->currnode;
|
||||
ctx->currnode = node;
|
||||
|
||||
*ctx->foundnode = node;
|
||||
*ctx->foundtype = filetype;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
find_file (const char *currpath, grub_fshelp_node_t currroot,
|
||||
grub_fshelp_node_t *currfound,
|
||||
iterate_dir_func iterate_dir, read_symlink_func read_symlink,
|
||||
directory_find_file (grub_fshelp_node_t node, const char *name, grub_fshelp_node_t *foundnode,
|
||||
enum grub_fshelp_filetype *foundtype, iterate_dir_func iterate_dir)
|
||||
{
|
||||
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)
|
||||
{
|
||||
ctx->currroot = currroot;
|
||||
ctx->name = currpath;
|
||||
ctx->type = GRUB_FSHELP_DIR;
|
||||
ctx->currnode = currroot;
|
||||
ctx->oldnode = currroot;
|
||||
|
||||
for (;;)
|
||||
char *name, *next;
|
||||
grub_err_t err;
|
||||
for (name = currpath; ; name = next)
|
||||
{
|
||||
int found;
|
||||
char c;
|
||||
grub_fshelp_node_t foundnode = NULL;
|
||||
enum grub_fshelp_filetype foundtype = 0;
|
||||
|
||||
/* Remove all leading slashes. */
|
||||
while (*ctx->name == '/')
|
||||
ctx->name++;
|
||||
while (*name == '/')
|
||||
name++;
|
||||
|
||||
/* Found the node! */
|
||||
if (! *ctx->name)
|
||||
{
|
||||
*currfound = ctx->currnode;
|
||||
ctx->foundtype = ctx->type;
|
||||
return 0;
|
||||
}
|
||||
if (! *name)
|
||||
return 0;
|
||||
|
||||
/* 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
|
||||
directory, check if this is true. */
|
||||
if (ctx->type != GRUB_FSHELP_DIR)
|
||||
if (ctx->currnode->type != GRUB_FSHELP_DIR)
|
||||
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] == '.')
|
||||
{
|
||||
free_node (ctx->currnode, ctx);
|
||||
ctx->currnode = 0;
|
||||
return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory"));
|
||||
go_up_a_level (ctx);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Iterate over the directory. */
|
||||
found = iterate_dir (ctx->currnode, find_file_iter, ctx);
|
||||
if (! found)
|
||||
{
|
||||
free_node (ctx->currnode, ctx);
|
||||
ctx->currnode = 0;
|
||||
if (grub_errno)
|
||||
return grub_errno;
|
||||
c = *next;
|
||||
*next = '\0';
|
||||
if (lookup_file)
|
||||
err = lookup_file (ctx->currnode->node, name, &foundnode, &foundtype);
|
||||
else
|
||||
err = directory_find_file (ctx->currnode->node, name, &foundnode, &foundtype, iterate_dir);
|
||||
*next = c;
|
||||
|
||||
break;
|
||||
}
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (!foundnode)
|
||||
break;
|
||||
|
||||
push_node (ctx, foundnode, foundtype);
|
||||
|
||||
/* Read in the symlink and follow it. */
|
||||
if (ctx->type == GRUB_FSHELP_SYMLINK)
|
||||
if (ctx->currnode->type == GRUB_FSHELP_SYMLINK)
|
||||
{
|
||||
char *symlink;
|
||||
const char *next;
|
||||
|
||||
/* Test if the symlink does not loop. */
|
||||
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,
|
||||
N_("too deep nesting of symlinks"));
|
||||
}
|
||||
return grub_error (GRUB_ERR_SYMLINK_LOOP,
|
||||
N_("too deep nesting of symlinks"));
|
||||
|
||||
symlink = read_symlink (ctx->currnode);
|
||||
free_node (ctx->currnode, ctx);
|
||||
ctx->currnode = 0;
|
||||
symlink = read_symlink (ctx->currnode->node);
|
||||
|
||||
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. */
|
||||
if (symlink[0] == '/')
|
||||
{
|
||||
free_node (ctx->oldnode, ctx);
|
||||
ctx->oldnode = ctx->rootnode;
|
||||
err = go_to_root (ctx);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Get from symlink to containing directory. */
|
||||
go_up_a_level (ctx);
|
||||
}
|
||||
|
||||
|
||||
/* Lookup the node the symlink points to. */
|
||||
next = ctx->next;
|
||||
find_file (symlink, ctx->oldnode, &ctx->currnode,
|
||||
iterate_dir, read_symlink, ctx);
|
||||
ctx->next = next;
|
||||
ctx->type = ctx->foundtype;
|
||||
find_file (symlink, iterate_dir, lookup_file, read_symlink, ctx);
|
||||
grub_free (symlink);
|
||||
|
||||
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"),
|
||||
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
|
||||
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
|
||||
@@ -207,31 +325,23 @@ grub_fshelp_find_file (const char *path, grub_fshelp_node_t rootnode,
|
||||
read_symlink_func read_symlink,
|
||||
enum grub_fshelp_filetype expecttype)
|
||||
{
|
||||
struct grub_fshelp_find_file_ctx ctx = {
|
||||
.path = path,
|
||||
.rootnode = rootnode,
|
||||
.foundtype = GRUB_FSHELP_DIR,
|
||||
.symlinknest = 0
|
||||
};
|
||||
grub_err_t err;
|
||||
return grub_fshelp_find_file_real (path, rootnode, foundnode,
|
||||
iterate_dir, NULL,
|
||||
read_symlink, expecttype);
|
||||
|
||||
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);
|
||||
if (err)
|
||||
return err;
|
||||
grub_err_t
|
||||
grub_fshelp_find_file_lookup (const char *path, grub_fshelp_node_t rootnode,
|
||||
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,
|
||||
@@ -252,6 +362,13 @@ grub_fshelp_read_file (grub_disk_t disk, grub_fshelp_node_t node,
|
||||
grub_disk_addr_t i, blockcnt;
|
||||
int blocksize = 1 << (log2blocksize + GRUB_DISK_SECTOR_BITS);
|
||||
|
||||
if (pos > filesize)
|
||||
{
|
||||
grub_error (GRUB_ERR_OUT_OF_RANGE,
|
||||
N_("attempt to read past the end of file"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Adjust LEN so it we can't read past the end of the file. */
|
||||
if (pos + len > filesize)
|
||||
len = filesize - pos;
|
||||
|
||||
+100
-100
@@ -29,6 +29,7 @@
|
||||
#include <grub/types.h>
|
||||
#include <grub/hfs.h>
|
||||
#include <grub/i18n.h>
|
||||
#include <grub/fshelp.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
@@ -330,6 +331,7 @@ grub_hfs_mount (grub_disk_t disk)
|
||||
|
||||
/* Check if this is a HFS filesystem. */
|
||||
if (grub_be_to_cpu16 (data->sblock.magic) != GRUB_HFS_MAGIC
|
||||
|| data->sblock.blksz == 0
|
||||
|| (data->sblock.blksz & grub_cpu_to_be32_compile_time (0xc00001ff)))
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_FS, "not an HFS filesystem");
|
||||
@@ -367,9 +369,14 @@ grub_hfs_mount (grub_disk_t disk)
|
||||
data->cat_root = grub_be_to_cpu32 (treehead.head.root_node);
|
||||
data->cat_size = grub_be_to_cpu16 (treehead.head.node_size);
|
||||
|
||||
if (data->cat_size == 0
|
||||
|| data->blksz < data->cat_size
|
||||
|| data->blksz < data->ext_size)
|
||||
goto fail;
|
||||
|
||||
/* Lookup the root directory node in the catalog tree using the
|
||||
volume name. */
|
||||
key.parent_dir = grub_cpu_to_be32 (1);
|
||||
key.parent_dir = grub_cpu_to_be32_compile_time (1);
|
||||
key.strlen = data->sblock.volname[0];
|
||||
grub_strcpy ((char *) key.str, (char *) (data->sblock.volname + 1));
|
||||
|
||||
@@ -686,6 +693,7 @@ grub_hfs_iterate_records (struct grub_hfs_data *data, int type, int idx,
|
||||
int i;
|
||||
struct grub_hfs_extent *dat;
|
||||
int blk;
|
||||
grub_uint16_t reccnt;
|
||||
|
||||
dat = (struct grub_hfs_extent *) (type == 0
|
||||
? (&data->sblock.catalog_recs)
|
||||
@@ -704,8 +712,12 @@ grub_hfs_iterate_records (struct grub_hfs_data *data, int type, int idx,
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
reccnt = grub_be_to_cpu16 (node->node.reccnt);
|
||||
if (reccnt > (nodesize >> 1))
|
||||
reccnt = (nodesize >> 1);
|
||||
|
||||
/* Iterate over all records in this node. */
|
||||
for (i = 0; i < grub_be_to_cpu16 (node->node.reccnt); i++)
|
||||
for (i = 0; i < reccnt; i++)
|
||||
{
|
||||
int pos = (nodesize >> 1) - 1 - i;
|
||||
struct pointer
|
||||
@@ -713,16 +725,19 @@ grub_hfs_iterate_records (struct grub_hfs_data *data, int type, int idx,
|
||||
grub_uint8_t keylen;
|
||||
grub_uint8_t key;
|
||||
} GRUB_PACKED *pnt;
|
||||
pnt = (struct pointer *) (grub_be_to_cpu16 (node->offsets[pos])
|
||||
+ node->rawnode);
|
||||
grub_uint16_t off = grub_be_to_cpu16 (node->offsets[pos]);
|
||||
if (off > nodesize - sizeof(*pnt))
|
||||
continue;
|
||||
pnt = (struct pointer *) (off + node->rawnode);
|
||||
if (nodesize < (grub_size_t) off + pnt->keylen + 1)
|
||||
continue;
|
||||
|
||||
struct grub_hfs_record rec =
|
||||
{
|
||||
&pnt->key,
|
||||
pnt->keylen,
|
||||
&pnt->key + pnt->keylen +(pnt->keylen + 1) % 2,
|
||||
nodesize - grub_be_to_cpu16 (node->offsets[pos])
|
||||
- pnt->keylen - 1
|
||||
nodesize - off - pnt->keylen - 1
|
||||
};
|
||||
|
||||
if (node_hook (&node->node, &rec, hook_arg))
|
||||
@@ -1111,90 +1126,81 @@ utf8_to_macroman (grub_uint8_t *to, const char *from)
|
||||
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
|
||||
DATA. Return the file record in RETDATA when it is non-zero.
|
||||
Return the directory number in RETINODE when it is non-zero. */
|
||||
static grub_err_t
|
||||
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;
|
||||
char *next;
|
||||
char *origpath;
|
||||
union {
|
||||
struct grub_hfs_filerec frec;
|
||||
struct grub_hfs_dirrec 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;
|
||||
struct grub_fshelp_node root = {
|
||||
.data = data,
|
||||
.inode = data->rootdir,
|
||||
.fdrec = {
|
||||
.frec = {
|
||||
.type = GRUB_HFS_FILETYPE_DIR
|
||||
}
|
||||
}
|
||||
};
|
||||
grub_err_t err;
|
||||
|
||||
origpath = grub_strdup (path);
|
||||
if (!origpath)
|
||||
return grub_errno;
|
||||
err = grub_fshelp_find_file_lookup (path, &root, found, lookup_file, NULL, exptype);
|
||||
|
||||
path = origpath;
|
||||
while (*path == '/')
|
||||
path++;
|
||||
|
||||
while (path && grub_strlen (path))
|
||||
if (&root == *found)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
*found = grub_malloc (sizeof (root));
|
||||
if (!*found)
|
||||
return grub_errno;
|
||||
grub_memcpy (*found, &root, sizeof (root));
|
||||
}
|
||||
|
||||
if (retdata)
|
||||
grub_memcpy (retdata, &fdrec.frec, sizeof (fdrec.frec));
|
||||
|
||||
if (retinode)
|
||||
*retinode = inode;
|
||||
|
||||
fail:
|
||||
grub_free (origpath);
|
||||
return grub_errno;
|
||||
return err;
|
||||
}
|
||||
|
||||
struct grub_hfs_dir_hook_ctx
|
||||
@@ -1252,16 +1258,14 @@ static grub_err_t
|
||||
grub_hfs_dir (grub_device_t device, const char *path, grub_fs_dir_hook_t hook,
|
||||
void *hook_data)
|
||||
{
|
||||
int inode;
|
||||
|
||||
struct grub_hfs_data *data;
|
||||
struct grub_hfs_filerec frec;
|
||||
struct grub_hfs_dir_hook_ctx ctx =
|
||||
{
|
||||
.hook = hook,
|
||||
.hook_data = hook_data
|
||||
};
|
||||
|
||||
grub_fshelp_node_t found = NULL;
|
||||
|
||||
grub_dl_ref (my_mod);
|
||||
|
||||
data = grub_hfs_mount (device->disk);
|
||||
@@ -1269,18 +1273,13 @@ grub_hfs_dir (grub_device_t device, const char *path, grub_fs_dir_hook_t hook,
|
||||
goto fail;
|
||||
|
||||
/* 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;
|
||||
|
||||
if (frec.type != GRUB_HFS_FILETYPE_DIR)
|
||||
{
|
||||
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);
|
||||
grub_hfs_iterate_dir (data, data->cat_root, found->inode, grub_hfs_dir_hook, &ctx);
|
||||
|
||||
fail:
|
||||
grub_free (found);
|
||||
grub_free (data);
|
||||
|
||||
grub_dl_unref (my_mod);
|
||||
@@ -1294,35 +1293,36 @@ static grub_err_t
|
||||
grub_hfs_open (struct grub_file *file, const char *name)
|
||||
{
|
||||
struct grub_hfs_data *data;
|
||||
struct grub_hfs_filerec frec;
|
||||
|
||||
grub_fshelp_node_t found = NULL;
|
||||
|
||||
grub_dl_ref (my_mod);
|
||||
|
||||
data = grub_hfs_mount (file->device->disk);
|
||||
|
||||
if (grub_hfs_find_dir (data, name, &frec, 0))
|
||||
if (!data)
|
||||
{
|
||||
grub_free (data);
|
||||
grub_dl_unref (my_mod);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
if (frec.type != GRUB_HFS_FILETYPE_FILE)
|
||||
if (grub_hfs_find_dir (data, name, &found, GRUB_FSHELP_REG))
|
||||
{
|
||||
grub_free (data);
|
||||
grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a regular file"));
|
||||
grub_free (found);
|
||||
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);
|
||||
grub_memcpy (data->extents, found->fdrec.frec.extents, sizeof (grub_hfs_datarecord_t));
|
||||
file->size = grub_be_to_cpu32 (found->fdrec.frec.size);
|
||||
data->size = grub_be_to_cpu32 (found->fdrec.frec.size);
|
||||
data->fileid = grub_be_to_cpu32 (found->fdrec.frec.fileid);
|
||||
file->offset = 0;
|
||||
|
||||
file->data = data;
|
||||
|
||||
grub_free (found);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
+18
-6
@@ -336,6 +336,9 @@ grub_hfsplus_mount (grub_disk_t disk)
|
||||
data->case_sensitive = ((magic == GRUB_HFSPLUSX_MAGIC) &&
|
||||
(header.key_compare == GRUB_HFSPLUSX_BINARYCOMPARE));
|
||||
|
||||
if (data->catalog_tree.nodesize < 2)
|
||||
goto fail;
|
||||
|
||||
if (grub_hfsplus_read_file (&data->extoverflow_tree.file, 0, 0,
|
||||
sizeof (struct grub_hfsplus_btnode),
|
||||
sizeof (header), (char *) &header) <= 0)
|
||||
@@ -350,6 +353,9 @@ grub_hfsplus_mount (grub_disk_t disk)
|
||||
data->extoverflow_tree.root = grub_be_to_cpu32 (header.root);
|
||||
data->extoverflow_tree.nodesize = grub_be_to_cpu16 (header.nodesize);
|
||||
|
||||
if (data->extoverflow_tree.nodesize < 2)
|
||||
goto fail;
|
||||
|
||||
if (grub_hfsplus_read_file (&data->attr_tree.file, 0, 0,
|
||||
sizeof (struct grub_hfsplus_btnode),
|
||||
sizeof (header), (char *) &header) <= 0)
|
||||
@@ -723,7 +729,10 @@ list_nodes (void *record, void *hook_arg)
|
||||
|
||||
/* If the name is obviously invalid, skip this node. */
|
||||
if (catkey->name[i] == 0)
|
||||
return 0;
|
||||
{
|
||||
grub_free (filename);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
*grub_utf16_to_utf8 ((grub_uint8_t *) filename, catkey->name,
|
||||
@@ -745,7 +754,10 @@ list_nodes (void *record, void *hook_arg)
|
||||
callback function. */
|
||||
node = grub_malloc (sizeof (*node));
|
||||
if (!node)
|
||||
return 1;
|
||||
{
|
||||
grub_free (filename);
|
||||
return 1;
|
||||
}
|
||||
node->data = ctx->dir->data;
|
||||
node->compressed = 0;
|
||||
node->cbuf = 0;
|
||||
@@ -780,8 +792,8 @@ grub_hfsplus_iterate_dir (grub_fshelp_node_t dir,
|
||||
};
|
||||
|
||||
struct grub_hfsplus_key_internal intern;
|
||||
struct grub_hfsplus_btnode *node;
|
||||
grub_disk_addr_t ptr;
|
||||
struct grub_hfsplus_btnode *node = NULL;
|
||||
grub_disk_addr_t ptr = 0;
|
||||
|
||||
{
|
||||
struct grub_fshelp_node *fsnode;
|
||||
@@ -964,8 +976,8 @@ grub_hfsplus_label (grub_device_t device, char **label)
|
||||
struct grub_hfsplus_catkey *catkey;
|
||||
int i, label_len;
|
||||
struct grub_hfsplus_key_internal intern;
|
||||
struct grub_hfsplus_btnode *node;
|
||||
grub_disk_addr_t ptr;
|
||||
struct grub_hfsplus_btnode *node = NULL;
|
||||
grub_disk_addr_t ptr = 0;
|
||||
|
||||
*label = 0;
|
||||
|
||||
|
||||
@@ -156,8 +156,12 @@ hfsplus_read_compressed_real (struct grub_hfsplus_file *node,
|
||||
if (ts > node->size - (pos & ~(HFSPLUS_COMPRESS_BLOCK_SIZE)))
|
||||
ts = node->size - (pos & ~(HFSPLUS_COMPRESS_BLOCK_SIZE));
|
||||
if (grub_zlib_decompress (tmp_buf, sz, 0,
|
||||
node->cbuf, ts) < 0)
|
||||
node->cbuf, ts) != (grub_ssize_t) ts)
|
||||
{
|
||||
if (!grub_errno)
|
||||
grub_error (GRUB_ERR_BAD_COMPRESSED_DATA,
|
||||
"premature end of compressed");
|
||||
|
||||
grub_free (tmp_buf);
|
||||
return -1;
|
||||
}
|
||||
@@ -288,8 +292,14 @@ hfsplus_open_compressed_real (struct grub_hfsplus_file *node)
|
||||
if (grub_zlib_decompress ((char *) (cmp_head + 1),
|
||||
grub_cpu_to_be64 (attr_head->size)
|
||||
- sizeof (*cmp_head), 0,
|
||||
node->cbuf, node->size) < 0)
|
||||
return grub_errno;
|
||||
node->cbuf, node->size)
|
||||
!= (grub_ssize_t) node->size)
|
||||
{
|
||||
if (!grub_errno)
|
||||
grub_error (GRUB_ERR_BAD_COMPRESSED_DATA,
|
||||
"premature end of compressed");
|
||||
return grub_errno;
|
||||
}
|
||||
node->compressed = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -750,19 +750,15 @@ grub_iso9660_iterate_dir (grub_fshelp_node_t dir,
|
||||
|
||||
if (dir->data->joliet && !ctx.filename)
|
||||
{
|
||||
char *oldname, *semicolon;
|
||||
char *semicolon;
|
||||
|
||||
oldname = name;
|
||||
ctx.filename = grub_iso9660_convert_string
|
||||
((grub_uint8_t *) oldname, dirent.namelen >> 1);
|
||||
((grub_uint8_t *) name, dirent.namelen >> 1);
|
||||
|
||||
semicolon = grub_strrchr (ctx.filename, ';');
|
||||
if (semicolon)
|
||||
*semicolon = '\0';
|
||||
|
||||
if (ctx.filename_alloc)
|
||||
grub_free (oldname);
|
||||
|
||||
ctx.filename_alloc = 1;
|
||||
}
|
||||
|
||||
@@ -959,14 +955,15 @@ grub_iso9660_read (grub_file_t file, char *buf, grub_size_t len)
|
||||
{
|
||||
struct grub_iso9660_data *data =
|
||||
(struct grub_iso9660_data *) file->data;
|
||||
grub_err_t err;
|
||||
|
||||
/* XXX: The file is stored in as a single extent. */
|
||||
data->disk->read_hook = file->read_hook;
|
||||
data->disk->read_hook_data = file->read_hook_data;
|
||||
read_node (data->node, file->offset, len, buf);
|
||||
err = read_node (data->node, file->offset, len, buf);
|
||||
data->disk->read_hook = NULL;
|
||||
|
||||
if (grub_errno)
|
||||
if (err || grub_errno)
|
||||
return -1;
|
||||
|
||||
return len;
|
||||
|
||||
+48
-32
@@ -65,7 +65,6 @@ typedef grub_uint16_t grub_minix_uintn_t;
|
||||
#define grub_minix_to_cpu_n grub_minix_to_cpu16
|
||||
#endif
|
||||
|
||||
#define GRUB_MINIX_INODE_BLKSZ(data) sizeof (grub_minix_uintn_t)
|
||||
#ifdef MODE_MINIX3
|
||||
typedef grub_uint32_t grub_minix_ino_t;
|
||||
#define grub_minix_to_cpu_ino grub_minix_to_cpu32
|
||||
@@ -83,19 +82,6 @@ typedef grub_uint16_t grub_minix_ino_t;
|
||||
#define GRUB_MINIX_INODE_DINDIR_ZONE(data) (grub_minix_to_cpu_n \
|
||||
(data->inode.double_indir_zone))
|
||||
|
||||
#ifndef MODE_MINIX3
|
||||
#define GRUB_MINIX_LOG2_ZONESZ (GRUB_MINIX_LOG2_BSIZE \
|
||||
+ grub_minix_to_cpu16 (data->sblock.log2_zone_size))
|
||||
#endif
|
||||
#define GRUB_MINIX_ZONESZ ((grub_uint64_t) data->block_size << \
|
||||
(GRUB_DISK_SECTOR_BITS + grub_minix_to_cpu16 (data->sblock.log2_zone_size)))
|
||||
|
||||
#ifdef MODE_MINIX3
|
||||
#define GRUB_MINIX_ZONE2SECT(zone) ((zone) * data->block_size)
|
||||
#else
|
||||
#define GRUB_MINIX_ZONE2SECT(zone) ((zone) << GRUB_MINIX_LOG2_ZONESZ)
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef MODE_MINIX3
|
||||
struct grub_minix_sblock
|
||||
@@ -172,6 +158,7 @@ struct grub_minix_data
|
||||
{
|
||||
struct grub_minix_sblock sblock;
|
||||
struct grub_minix_inode inode;
|
||||
grub_uint32_t block_per_zone;
|
||||
grub_minix_ino_t ino;
|
||||
int linknest;
|
||||
grub_disk_t disk;
|
||||
@@ -184,15 +171,32 @@ static grub_dl_t my_mod;
|
||||
static grub_err_t grub_minix_find_file (struct grub_minix_data *data,
|
||||
const char *path);
|
||||
|
||||
#ifdef MODE_MINIX3
|
||||
static inline grub_disk_addr_t
|
||||
grub_minix_zone2sect (struct grub_minix_data *data, grub_minix_uintn_t zone)
|
||||
{
|
||||
return ((grub_disk_addr_t) zone) * data->block_size;
|
||||
}
|
||||
#else
|
||||
static inline grub_disk_addr_t
|
||||
grub_minix_zone2sect (struct grub_minix_data *data, grub_minix_uintn_t zone)
|
||||
{
|
||||
int log2_zonesz = (GRUB_MINIX_LOG2_BSIZE
|
||||
+ grub_minix_to_cpu16 (data->sblock.log2_zone_size));
|
||||
return (((grub_disk_addr_t) zone) << log2_zonesz);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* Read the block pointer in ZONE, on the offset NUM. */
|
||||
static grub_minix_uintn_t
|
||||
grub_get_indir (struct grub_minix_data *data,
|
||||
grub_get_indir (struct grub_minix_data *data,
|
||||
grub_minix_uintn_t zone,
|
||||
grub_minix_uintn_t num)
|
||||
{
|
||||
grub_minix_uintn_t indirn;
|
||||
grub_disk_read (data->disk,
|
||||
GRUB_MINIX_ZONE2SECT(zone),
|
||||
grub_minix_zone2sect(data, zone),
|
||||
sizeof (grub_minix_uintn_t) * num,
|
||||
sizeof (grub_minix_uintn_t), (char *) &indirn);
|
||||
return grub_minix_to_cpu_n (indirn);
|
||||
@@ -202,8 +206,6 @@ static grub_minix_uintn_t
|
||||
grub_minix_get_file_block (struct grub_minix_data *data, unsigned int blk)
|
||||
{
|
||||
grub_minix_uintn_t indir;
|
||||
const grub_uint32_t block_per_zone = (GRUB_MINIX_ZONESZ
|
||||
/ GRUB_MINIX_INODE_BLKSZ (data));
|
||||
|
||||
/* Direct block. */
|
||||
if (blk < GRUB_MINIX_INODE_DIR_BLOCKS)
|
||||
@@ -211,33 +213,33 @@ grub_minix_get_file_block (struct grub_minix_data *data, unsigned int blk)
|
||||
|
||||
/* Indirect block. */
|
||||
blk -= GRUB_MINIX_INODE_DIR_BLOCKS;
|
||||
if (blk < block_per_zone)
|
||||
if (blk < data->block_per_zone)
|
||||
{
|
||||
indir = grub_get_indir (data, GRUB_MINIX_INODE_INDIR_ZONE (data), blk);
|
||||
return indir;
|
||||
}
|
||||
|
||||
/* Double indirect block. */
|
||||
blk -= block_per_zone;
|
||||
if (blk < block_per_zone * block_per_zone)
|
||||
blk -= data->block_per_zone;
|
||||
if (blk < (grub_uint64_t) data->block_per_zone * (grub_uint64_t) data->block_per_zone)
|
||||
{
|
||||
indir = grub_get_indir (data, GRUB_MINIX_INODE_DINDIR_ZONE (data),
|
||||
blk / block_per_zone);
|
||||
blk / data->block_per_zone);
|
||||
|
||||
indir = grub_get_indir (data, indir, blk % block_per_zone);
|
||||
indir = grub_get_indir (data, indir, blk % data->block_per_zone);
|
||||
|
||||
return indir;
|
||||
}
|
||||
|
||||
#if defined (MODE_MINIX3) || defined (MODE_MINIX2)
|
||||
blk -= block_per_zone * block_per_zone;
|
||||
if (blk < ((grub_uint64_t) block_per_zone * (grub_uint64_t) block_per_zone
|
||||
* (grub_uint64_t) block_per_zone))
|
||||
blk -= data->block_per_zone * data->block_per_zone;
|
||||
if (blk < ((grub_uint64_t) data->block_per_zone * (grub_uint64_t) data->block_per_zone
|
||||
* (grub_uint64_t) data->block_per_zone))
|
||||
{
|
||||
indir = grub_get_indir (data, grub_minix_to_cpu_n (data->inode.triple_indir_zone),
|
||||
(blk / block_per_zone) / block_per_zone);
|
||||
indir = grub_get_indir (data, indir, (blk / block_per_zone) % block_per_zone);
|
||||
indir = grub_get_indir (data, indir, blk % block_per_zone);
|
||||
(blk / data->block_per_zone) / data->block_per_zone);
|
||||
indir = grub_get_indir (data, indir, (blk / data->block_per_zone) % data->block_per_zone);
|
||||
indir = grub_get_indir (data, indir, blk % data->block_per_zone);
|
||||
|
||||
return indir;
|
||||
}
|
||||
@@ -262,6 +264,13 @@ grub_minix_read_file (struct grub_minix_data *data,
|
||||
grub_uint32_t posblock;
|
||||
grub_uint32_t blockoff;
|
||||
|
||||
if (pos > GRUB_MINIX_INODE_SIZE (data))
|
||||
{
|
||||
grub_error (GRUB_ERR_OUT_OF_RANGE,
|
||||
N_("attempt to read past the end of file"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Adjust len so it we can't read past the end of the file. */
|
||||
if (len + pos > GRUB_MINIX_INODE_SIZE (data))
|
||||
len = GRUB_MINIX_INODE_SIZE (data) - pos;
|
||||
@@ -278,7 +287,7 @@ grub_minix_read_file (struct grub_minix_data *data,
|
||||
|
||||
for (i = posblock; i < blockcnt; i++)
|
||||
{
|
||||
grub_disk_addr_t blknr;
|
||||
grub_minix_uintn_t blknr;
|
||||
grub_uint64_t blockend = data->block_size << GRUB_DISK_SECTOR_BITS;
|
||||
grub_off_t skipfirst = 0;
|
||||
|
||||
@@ -307,7 +316,7 @@ grub_minix_read_file (struct grub_minix_data *data,
|
||||
data->disk->read_hook = read_hook;
|
||||
data->disk->read_hook_data = read_hook_data;
|
||||
grub_disk_read (data->disk,
|
||||
GRUB_MINIX_ZONE2SECT(blknr),
|
||||
grub_minix_zone2sect(data, blknr),
|
||||
skipfirst, blockend, buf);
|
||||
data->disk->read_hook = 0;
|
||||
if (grub_errno)
|
||||
@@ -333,7 +342,8 @@ grub_minix_read_inode (struct grub_minix_data *data, grub_minix_ino_t ino)
|
||||
|
||||
/* The first inode in minix is inode 1. */
|
||||
ino--;
|
||||
block = GRUB_MINIX_ZONE2SECT (2 + grub_minix_to_cpu16 (sblock->inode_bmap_size)
|
||||
block = grub_minix_zone2sect (data,
|
||||
2 + grub_minix_to_cpu16 (sblock->inode_bmap_size)
|
||||
+ grub_minix_to_cpu16 (sblock->zone_bmap_size));
|
||||
block += ino / (GRUB_DISK_SECTOR_SIZE / sizeof (struct grub_minix_inode));
|
||||
int offs = (ino % (GRUB_DISK_SECTOR_SIZE
|
||||
@@ -508,6 +518,12 @@ grub_minix_mount (grub_disk_t disk)
|
||||
data->block_size = 2;
|
||||
#endif
|
||||
|
||||
data->block_per_zone = (((grub_uint64_t) data->block_size << \
|
||||
(GRUB_DISK_SECTOR_BITS + grub_minix_to_cpu16 (data->sblock.log2_zone_size)))
|
||||
/ sizeof (grub_minix_uintn_t));
|
||||
if (!data->block_per_zone)
|
||||
goto fail;
|
||||
|
||||
return data;
|
||||
|
||||
fail:
|
||||
|
||||
@@ -724,6 +724,10 @@ grub_nilfs2_valid_sb (struct grub_nilfs2_super_block *sbp)
|
||||
if (grub_le_to_cpu32 (sbp->s_rev_level) != NILFS_SUPORT_REV)
|
||||
return 0;
|
||||
|
||||
/* 20 already means 1GiB blocks. We don't want to deal with blocks overflowing int32. */
|
||||
if (grub_le_to_cpu32 (sbp->s_log_block_size) > 20)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
+8
-1
@@ -618,7 +618,10 @@ list_file (struct grub_ntfs_file *diro, grub_uint8_t *pos,
|
||||
|
||||
ustr = get_utf8 (np, ns);
|
||||
if (ustr == NULL)
|
||||
return 0;
|
||||
{
|
||||
grub_free (fdiro);
|
||||
return 0;
|
||||
}
|
||||
if (namespace)
|
||||
type |= GRUB_FSHELP_CASE_INSENSITIVE;
|
||||
|
||||
@@ -917,12 +920,16 @@ grub_ntfs_mount (grub_disk_t disk)
|
||||
|
||||
if (bpb.clusters_per_mft > 0)
|
||||
data->mft_size = ((grub_disk_addr_t) bpb.clusters_per_mft) << data->log_spc;
|
||||
else if (-bpb.clusters_per_mft < GRUB_NTFS_BLK_SHR || -bpb.clusters_per_mft >= 31)
|
||||
goto fail;
|
||||
else
|
||||
data->mft_size = 1ULL << (-bpb.clusters_per_mft - GRUB_NTFS_BLK_SHR);
|
||||
|
||||
if (bpb.clusters_per_index > 0)
|
||||
data->idx_size = (((grub_disk_addr_t) bpb.clusters_per_index)
|
||||
<< data->log_spc);
|
||||
else if (-bpb.clusters_per_index < GRUB_NTFS_BLK_SHR || -bpb.clusters_per_index >= 31)
|
||||
goto fail;
|
||||
else
|
||||
data->idx_size = 1ULL << (-bpb.clusters_per_index - GRUB_NTFS_BLK_SHR);
|
||||
|
||||
|
||||
@@ -104,7 +104,7 @@ decomp_block (struct grub_ntfs_comp *cc, grub_uint8_t *dest)
|
||||
if (tag & 1)
|
||||
{
|
||||
grub_uint32_t i, len, delta, code, lmask, dshift;
|
||||
grub_uint16_t word;
|
||||
grub_uint16_t word = 0;
|
||||
|
||||
if (decomp_get16 (cc, &word))
|
||||
return grub_errno;
|
||||
|
||||
+57
-27
@@ -22,6 +22,7 @@
|
||||
#include <grub/file.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/archelp.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
@@ -74,6 +75,44 @@ grub_procdev_write (grub_disk_t disk __attribute ((unused)),
|
||||
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
|
||||
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_fs_dir_hook_t hook, void *hook_data)
|
||||
{
|
||||
const char *ptr;
|
||||
struct grub_dirhook_info info;
|
||||
struct grub_procfs_entry *entry;
|
||||
|
||||
grub_memset (&info, 0, sizeof (info));
|
||||
struct grub_archelp_data data;
|
||||
|
||||
/* Check if the disk is our dummy disk. */
|
||||
if (grub_strcmp (device->disk->name, "proc"))
|
||||
return grub_error (GRUB_ERR_BAD_FS, "not a procfs");
|
||||
for (ptr = path; *ptr == '/'; ptr++);
|
||||
if (*ptr)
|
||||
return 0;
|
||||
FOR_LIST_ELEMENTS((entry), (grub_procfs_entries))
|
||||
if (hook (entry->name, &info, hook_data))
|
||||
return 0;
|
||||
return 0;
|
||||
|
||||
grub_procfs_rewind (&data);
|
||||
|
||||
return grub_archelp_dir (&data, &arcops,
|
||||
path, hook, hook_data);
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_procfs_open (struct grub_file *file, const char *path)
|
||||
{
|
||||
const char *pathptr;
|
||||
struct grub_procfs_entry *entry;
|
||||
grub_err_t err;
|
||||
struct grub_archelp_data data;
|
||||
grub_size_t sz;
|
||||
|
||||
for (pathptr = path; *pathptr == '/'; pathptr++);
|
||||
grub_procfs_rewind (&data);
|
||||
|
||||
FOR_LIST_ELEMENTS((entry), (grub_procfs_entries))
|
||||
if (grub_strcmp (pathptr, entry->name) == 0)
|
||||
{
|
||||
grub_size_t sz;
|
||||
file->data = entry->get_contents (&sz);
|
||||
if (!file->data)
|
||||
return grub_errno;
|
||||
file->size = sz;
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
return grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"), path);
|
||||
err = grub_archelp_open (&data, &arcops, path);
|
||||
if (err)
|
||||
return err;
|
||||
file->data = data.entry->get_contents (&sz);
|
||||
if (!file->data)
|
||||
return grub_errno;
|
||||
file->size = sz;
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static struct grub_disk_dev grub_procfs_dev = {
|
||||
|
||||
+32
-11
@@ -365,7 +365,7 @@ grub_reiserfs_set_key_offset (struct grub_reiserfs_key *key,
|
||||
key->u.v1.offset = grub_cpu_to_le32 (value);
|
||||
else
|
||||
key->u.v2.offset_type \
|
||||
= ((key->u.v2.offset_type & grub_cpu_to_le64 (15ULL << 60))
|
||||
= ((key->u.v2.offset_type & grub_cpu_to_le64_compile_time (15ULL << 60))
|
||||
| grub_cpu_to_le64 (value & (~0ULL >> 4)));
|
||||
}
|
||||
|
||||
@@ -412,7 +412,7 @@ grub_reiserfs_set_key_type (struct grub_reiserfs_key *key,
|
||||
key->u.v1.type = grub_cpu_to_le32 (type);
|
||||
else
|
||||
key->u.v2.offset_type
|
||||
= ((key->u.v2.offset_type & grub_cpu_to_le64 (~0ULL >> 4))
|
||||
= ((key->u.v2.offset_type & grub_cpu_to_le64_compile_time (~0ULL >> 4))
|
||||
| grub_cpu_to_le64 ((grub_uint64_t) type << 60));
|
||||
|
||||
assert (grub_reiserfs_get_key_type (key) == grub_type);
|
||||
@@ -783,12 +783,30 @@ grub_reiserfs_iterate_dir (grub_fshelp_node_t item,
|
||||
struct grub_reiserfs_key entry_key;
|
||||
enum grub_fshelp_filetype entry_type;
|
||||
char *entry_name;
|
||||
char *entry_name_end = 0;
|
||||
char c;
|
||||
|
||||
if (!(entry_state & GRUB_REISERFS_VISIBLE_MASK))
|
||||
continue;
|
||||
|
||||
entry_name = (((char *) directory_headers)
|
||||
+ 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.object_id = directory_header->object_id;
|
||||
entry_key.u.v2.offset_type = 0;
|
||||
@@ -935,7 +953,7 @@ grub_reiserfs_iterate_dir (grub_fshelp_node_t item,
|
||||
else
|
||||
{
|
||||
/* 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",
|
||||
"Warning : %s has no stat block !\n",
|
||||
entry_name);
|
||||
@@ -943,18 +961,21 @@ grub_reiserfs_iterate_dir (grub_fshelp_node_t item,
|
||||
goto next;
|
||||
}
|
||||
}
|
||||
|
||||
c = *entry_name_end;
|
||||
*entry_name_end = 0;
|
||||
if (hook (entry_name, entry_type, entry_item, hook_data))
|
||||
{
|
||||
*entry_name_end = c;
|
||||
grub_dprintf ("reiserfs", "Found : %s, type=%d\n",
|
||||
entry_name, entry_type);
|
||||
ret = 1;
|
||||
goto found;
|
||||
}
|
||||
*entry_name_end = c;
|
||||
|
||||
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)
|
||||
@@ -997,8 +1018,8 @@ grub_reiserfs_open (struct grub_file *file, const char *name)
|
||||
data = grub_reiserfs_mount (file->device->disk);
|
||||
if (! data)
|
||||
goto fail;
|
||||
key.directory_id = grub_cpu_to_le32 (1);
|
||||
key.object_id = grub_cpu_to_le32 (2);
|
||||
key.directory_id = grub_cpu_to_le32_compile_time (1);
|
||||
key.object_id = grub_cpu_to_le32_compile_time (2);
|
||||
key.u.v2.offset_type = 0;
|
||||
grub_reiserfs_set_key_type (&key, GRUB_REISERFS_DIRECTORY, 2);
|
||||
grub_reiserfs_set_key_offset (&key, 1);
|
||||
@@ -1090,7 +1111,7 @@ grub_reiserfs_read_real (struct grub_fshelp_node *node,
|
||||
switch (found.type)
|
||||
{
|
||||
case GRUB_REISERFS_DIRECT:
|
||||
block = found.block_number * (block_size >> GRUB_DISK_SECTOR_BITS);
|
||||
block = ((grub_disk_addr_t) found.block_number) * (block_size >> GRUB_DISK_SECTOR_BITS);
|
||||
grub_dprintf ("reiserfs_blocktype", "D: %u\n", (unsigned) block);
|
||||
if (initial_position < current_position + item_size)
|
||||
{
|
||||
@@ -1289,8 +1310,8 @@ grub_reiserfs_dir (grub_device_t device, const char *path,
|
||||
data = grub_reiserfs_mount (device->disk);
|
||||
if (! data)
|
||||
goto fail;
|
||||
root_key.directory_id = grub_cpu_to_le32 (1);
|
||||
root_key.object_id = grub_cpu_to_le32 (2);
|
||||
root_key.directory_id = grub_cpu_to_le32_compile_time (1);
|
||||
root_key.object_id = grub_cpu_to_le32_compile_time (2);
|
||||
root_key.u.v2.offset_type = 0;
|
||||
grub_reiserfs_set_key_type (&root_key, GRUB_REISERFS_DIRECTORY, 2);
|
||||
grub_reiserfs_set_key_offset (&root_key, 1);
|
||||
|
||||
+11
-6
@@ -173,10 +173,11 @@ grub_sfs_read_extent (struct grub_sfs_data *data, unsigned int block,
|
||||
struct grub_sfs_btree *tree;
|
||||
int i;
|
||||
grub_uint32_t next;
|
||||
grub_size_t blocksize = GRUB_DISK_SECTOR_SIZE << data->log_blocksize;
|
||||
|
||||
treeblock = grub_malloc (GRUB_DISK_SECTOR_SIZE << data->log_blocksize);
|
||||
if (!block)
|
||||
return 0;
|
||||
treeblock = grub_malloc (blocksize);
|
||||
if (!treeblock)
|
||||
return grub_errno;
|
||||
|
||||
next = grub_be_to_cpu32 (data->rblock.btree);
|
||||
tree = (struct grub_sfs_btree *) treeblock;
|
||||
@@ -184,17 +185,21 @@ grub_sfs_read_extent (struct grub_sfs_data *data, unsigned int block,
|
||||
/* Handle this level in the btree. */
|
||||
do
|
||||
{
|
||||
grub_uint16_t nnodes;
|
||||
grub_disk_read (data->disk,
|
||||
((grub_disk_addr_t) next) << data->log_blocksize,
|
||||
0, GRUB_DISK_SECTOR_SIZE << data->log_blocksize,
|
||||
treeblock);
|
||||
0, blocksize, treeblock);
|
||||
if (grub_errno)
|
||||
{
|
||||
grub_free (treeblock);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
for (i = grub_be_to_cpu16 (tree->nodes) - 1; i >= 0; i--)
|
||||
nnodes = grub_be_to_cpu16 (tree->nodes);
|
||||
if (nnodes * (grub_uint32_t) (tree)->nodesize > blocksize)
|
||||
break;
|
||||
|
||||
for (i = (int) nnodes - 1; i >= 0; i--)
|
||||
{
|
||||
|
||||
#define EXTNODE(tree, index) \
|
||||
|
||||
@@ -986,6 +986,7 @@ grub_udf_read_symlink (grub_fshelp_node_t node)
|
||||
case 1:
|
||||
if (ptr[1])
|
||||
goto fail;
|
||||
/* Fallthrough. */
|
||||
case 2:
|
||||
/* in 4 bytes. out: 1 byte. */
|
||||
optr = out;
|
||||
|
||||
+10
-3
@@ -394,7 +394,7 @@ grub_ufs_read_file (struct grub_ufs_data *data,
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
grub_memset (buf, UFS_BLKSZ (sblock) - skipfirst, 0);
|
||||
grub_memset (buf, 0, blockend);
|
||||
|
||||
buf += UFS_BLKSZ (sblock) - skipfirst;
|
||||
}
|
||||
@@ -465,7 +465,13 @@ grub_ufs_lookup_symlink (struct grub_ufs_data *data, int ino)
|
||||
&& INODE_SIZE (data) <= sizeof (data->inode.symlink))
|
||||
grub_strcpy (symlink, (char *) data->inode.symlink);
|
||||
else
|
||||
grub_ufs_read_file (data, 0, 0, 0, sz, symlink);
|
||||
{
|
||||
if (grub_ufs_read_file (data, 0, 0, 0, sz, symlink) < 0)
|
||||
{
|
||||
grub_free(symlink);
|
||||
return grub_errno;
|
||||
}
|
||||
}
|
||||
symlink[sz] = '\0';
|
||||
|
||||
/* The symlink is an absolute path, go back to the root inode. */
|
||||
@@ -604,7 +610,8 @@ grub_ufs_mount (grub_disk_t disk)
|
||||
endiannesses. */
|
||||
if (data->sblock.magic == grub_cpu_to_ufs32_compile_time (GRUB_UFS_MAGIC)
|
||||
&& data->sblock.bsize != 0
|
||||
&& ((data->sblock.bsize & (data->sblock.bsize - 1)) == 0))
|
||||
&& ((data->sblock.bsize & (data->sblock.bsize - 1)) == 0)
|
||||
&& data->sblock.ino_per_group != 0)
|
||||
{
|
||||
for (data->log2_blksz = 0;
|
||||
(1U << data->log2_blksz) < grub_ufs_to_cpu32 (data->sblock.bsize);
|
||||
|
||||
+340
-124
@@ -34,6 +34,50 @@ GRUB_MOD_LICENSE ("GPLv3+");
|
||||
#define XFS_INODE_FORMAT_EXT 2
|
||||
#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
|
||||
{
|
||||
@@ -45,7 +89,9 @@ struct grub_xfs_sblock
|
||||
grub_uint64_t rootino;
|
||||
grub_uint8_t unused3[20];
|
||||
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 log2_bsize;
|
||||
grub_uint8_t log2_sect;
|
||||
@@ -54,12 +100,19 @@ struct grub_xfs_sblock
|
||||
grub_uint8_t log2_agblk;
|
||||
grub_uint8_t unused6[67];
|
||||
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;
|
||||
|
||||
struct grub_xfs_dir_header
|
||||
{
|
||||
grub_uint8_t count;
|
||||
grub_uint8_t smallino;
|
||||
grub_uint8_t largeino;
|
||||
union
|
||||
{
|
||||
grub_uint32_t i4;
|
||||
@@ -67,21 +120,29 @@ struct grub_xfs_dir_header
|
||||
} GRUB_PACKED parent;
|
||||
} GRUB_PACKED;
|
||||
|
||||
/* Structure for directory entry inlined in the inode */
|
||||
struct grub_xfs_dir_entry
|
||||
{
|
||||
grub_uint8_t len;
|
||||
grub_uint16_t offset;
|
||||
char name[1];
|
||||
/* Inode number follows, 32 bits. */
|
||||
/* Inode number follows, 32 / 64 bits. */
|
||||
} GRUB_PACKED;
|
||||
|
||||
/* Structure for directory entry in a block */
|
||||
struct grub_xfs_dir2_entry
|
||||
{
|
||||
grub_uint64_t inode;
|
||||
grub_uint8_t len;
|
||||
} 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
|
||||
{
|
||||
@@ -90,21 +151,22 @@ struct grub_xfs_btree_node
|
||||
grub_uint16_t numrecs;
|
||||
grub_uint64_t left;
|
||||
grub_uint64_t right;
|
||||
grub_uint64_t keys[1];
|
||||
} GRUB_PACKED;
|
||||
/* In V5 here follow crc, uuid, etc. */
|
||||
/* Then follow keys and block pointers */
|
||||
} GRUB_PACKED;
|
||||
|
||||
struct grub_xfs_btree_root
|
||||
{
|
||||
grub_uint16_t level;
|
||||
grub_uint16_t numrecs;
|
||||
grub_uint64_t keys[1];
|
||||
} GRUB_PACKED;
|
||||
} GRUB_PACKED;
|
||||
|
||||
struct grub_xfs_time
|
||||
{
|
||||
grub_uint32_t sec;
|
||||
grub_uint32_t nanosec;
|
||||
} GRUB_PACKED;
|
||||
} GRUB_PACKED;
|
||||
|
||||
struct grub_xfs_inode
|
||||
{
|
||||
@@ -123,19 +185,11 @@ struct grub_xfs_inode
|
||||
grub_uint16_t unused3;
|
||||
grub_uint8_t fork_offset;
|
||||
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;
|
||||
|
||||
#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
|
||||
{
|
||||
grub_uint32_t leaf_count;
|
||||
@@ -157,6 +211,8 @@ struct grub_xfs_data
|
||||
int pos;
|
||||
int bsize;
|
||||
grub_uint32_t agsize;
|
||||
unsigned int hasftype:1;
|
||||
unsigned int hascrc:1;
|
||||
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. */
|
||||
#define FILETYPE_INO_MASK 0170000
|
||||
#define FILETYPE_INO_REG 0100000
|
||||
@@ -180,14 +301,14 @@ static inline grub_uint64_t
|
||||
GRUB_XFS_INO_INOINAG (struct grub_xfs_data *data,
|
||||
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
|
||||
GRUB_XFS_INO_AG (struct grub_xfs_data *data,
|
||||
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
|
||||
@@ -198,37 +319,25 @@ GRUB_XFS_FSB_TO_BLOCK (struct grub_xfs_data *data, grub_disk_addr_t fsb)
|
||||
}
|
||||
|
||||
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
|
||||
| grub_be_to_cpu32 (exts[ex][1]) >> 9);
|
||||
return ((grub_be_to_cpu32 (exts[ex].raw[0]) & ~(1 << 31)) << 23
|
||||
| grub_be_to_cpu32 (exts[ex].raw[1]) >> 9);
|
||||
}
|
||||
|
||||
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
|
||||
| (grub_uint64_t) grub_be_to_cpu32 (exts[ex][2]) << 11
|
||||
| grub_be_to_cpu32 (exts[ex][3]) >> 21);
|
||||
| (grub_uint64_t) grub_be_to_cpu32 (exts[ex].raw[2]) << 11
|
||||
| grub_be_to_cpu32 (exts[ex].raw[3]) >> 21);
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
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);
|
||||
return (grub_be_to_cpu32 (exts[ex].raw[3]) & ((1 << 21) - 1));
|
||||
}
|
||||
|
||||
|
||||
@@ -255,6 +364,109 @@ grub_xfs_inode_offset (struct grub_xfs_data *data,
|
||||
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
|
||||
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);
|
||||
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. */
|
||||
if (grub_disk_read (data->disk, block, offset,
|
||||
1 << data->sblock.log2_inode, inode))
|
||||
if (grub_disk_read (data->disk, block, offset, grub_xfs_inode_size(data),
|
||||
inode))
|
||||
return grub_errno;
|
||||
|
||||
if (grub_strncmp ((char *) inode->magic, "IN", 2))
|
||||
@@ -274,40 +488,47 @@ grub_xfs_read_inode (struct grub_xfs_data *data, grub_uint64_t ino,
|
||||
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
|
||||
grub_xfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
|
||||
{
|
||||
struct grub_xfs_btree_node *leaf = 0;
|
||||
int ex, nrec;
|
||||
grub_xfs_extent *exts;
|
||||
struct grub_xfs_extent *exts;
|
||||
grub_uint64_t ret = 0;
|
||||
|
||||
if (node->inode.format == XFS_INODE_FORMAT_BTREE)
|
||||
{
|
||||
const grub_uint64_t *keys;
|
||||
struct grub_xfs_btree_root *root;
|
||||
const char *keys;
|
||||
int recoffset;
|
||||
|
||||
leaf = grub_malloc (node->data->bsize);
|
||||
if (leaf == 0)
|
||||
return 0;
|
||||
|
||||
nrec = grub_be_to_cpu16 (node->inode.data.btree.numrecs);
|
||||
keys = &node->inode.data.btree.keys[0];
|
||||
root = (struct grub_xfs_btree_root *) grub_xfs_inode_data(&node->inode);
|
||||
nrec = grub_be_to_cpu16 (root->numrecs);
|
||||
keys = (char *) &root->keys[0];
|
||||
if (node->inode.fork_offset)
|
||||
recoffset = (node->inode.fork_offset - 1) / 2;
|
||||
else
|
||||
recoffset = ((1 << node->data->sblock.log2_inode)
|
||||
- ((char *) &node->inode.data.btree.keys
|
||||
- (char *) &node->inode))
|
||||
/ (2 * sizeof (grub_uint64_t));
|
||||
recoffset = (grub_xfs_inode_size(node->data)
|
||||
- ((char *) keys - (char *) &node->inode))
|
||||
/ (2 * sizeof (grub_uint64_t));
|
||||
do
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < nrec; i++)
|
||||
{
|
||||
if (fileblock < grub_be_to_cpu64 (keys[i]))
|
||||
if (fileblock < get_fsb(keys, i))
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -317,12 +538,16 @@ grub_xfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
|
||||
grub_free (leaf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
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))
|
||||
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_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);
|
||||
keys = &leaf->keys[0];
|
||||
recoffset = ((node->data->bsize - ((char *) &leaf->keys
|
||||
keys = grub_xfs_btree_keys(node->data, leaf);
|
||||
recoffset = ((node->data->bsize - ((char *) keys
|
||||
- (char *) leaf))
|
||||
/ (2 * sizeof (grub_uint64_t)));
|
||||
}
|
||||
while (leaf->level);
|
||||
exts = (grub_xfs_extent *) keys;
|
||||
exts = (struct grub_xfs_extent *) keys;
|
||||
}
|
||||
else if (node->inode.format == XFS_INODE_FORMAT_EXT)
|
||||
{
|
||||
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
|
||||
{
|
||||
@@ -379,13 +604,13 @@ grub_xfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
|
||||
POS. Return the amount of read bytes in READ. */
|
||||
static grub_ssize_t
|
||||
grub_xfs_read_file (grub_fshelp_node_t node,
|
||||
grub_disk_read_hook_t read_hook, void *read_hook_data,
|
||||
grub_off_t pos, grub_size_t len, char *buf)
|
||||
grub_disk_read_hook_t read_hook, void *read_hook_data,
|
||||
grub_off_t pos, grub_size_t len, char *buf, grub_uint32_t header_size)
|
||||
{
|
||||
return grub_fshelp_read_file (node->data->disk, node,
|
||||
read_hook, read_hook_data,
|
||||
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
|
||||
- GRUB_DISK_SECTOR_BITS, 0);
|
||||
}
|
||||
@@ -394,23 +619,34 @@ grub_xfs_read_file (grub_fshelp_node_t node,
|
||||
static char *
|
||||
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)
|
||||
{
|
||||
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:
|
||||
{
|
||||
char *symlink;
|
||||
grub_ssize_t numread;
|
||||
int off = 0;
|
||||
|
||||
if (node->data->hascrc)
|
||||
off = 56;
|
||||
|
||||
symlink = grub_malloc (size + 1);
|
||||
if (!symlink)
|
||||
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)
|
||||
{
|
||||
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;
|
||||
grub_err_t err;
|
||||
|
||||
fdiro = grub_malloc (sizeof (struct grub_fshelp_node)
|
||||
- sizeof (struct grub_xfs_inode)
|
||||
+ (1 << ctx->diro->data->sblock.log2_inode) + 1);
|
||||
fdiro = grub_malloc (grub_xfs_fshelp_size(ctx->diro->data) + 1);
|
||||
if (!fdiro)
|
||||
{
|
||||
grub_print_error ();
|
||||
@@ -496,24 +730,18 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir,
|
||||
{
|
||||
case XFS_INODE_FORMAT_INO:
|
||||
{
|
||||
struct grub_xfs_dir_entry *de = &diro->inode.data.dir.direntry[0];
|
||||
int smallino = !diro->inode.data.dir.dirhead.smallino;
|
||||
struct grub_xfs_dir_header *head = (struct grub_xfs_dir_header *) grub_xfs_inode_data(&diro->inode);
|
||||
struct grub_xfs_dir_entry *de = grub_xfs_inline_de(head);
|
||||
int smallino = !head->largeino;
|
||||
int i;
|
||||
grub_uint64_t parent;
|
||||
|
||||
/* If small inode numbers are used to pack the direntry, the
|
||||
parent inode number is small too. */
|
||||
if (smallino)
|
||||
{
|
||||
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);
|
||||
}
|
||||
parent = grub_be_to_cpu32 (head->parent.i4);
|
||||
else
|
||||
{
|
||||
parent = diro->inode.data.dir.dirhead.parent.i8;
|
||||
}
|
||||
parent = grub_be_to_cpu64 (head->parent.i8);
|
||||
|
||||
/* Synthesize the direntries for `.' and `..'. */
|
||||
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))
|
||||
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_uint8_t *inopos = (((grub_uint8_t *) de)
|
||||
+ sizeof (struct grub_xfs_dir_entry)
|
||||
+ de->len - 1);
|
||||
grub_uint8_t *inopos = grub_xfs_inline_de_inopos(dir->data, de);
|
||||
grub_uint8_t c;
|
||||
|
||||
/* inopos might be unaligned. */
|
||||
@@ -545,18 +771,17 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir,
|
||||
| (((grub_uint64_t) inopos[5]) << 16)
|
||||
| (((grub_uint64_t) inopos[6]) << 8)
|
||||
| (((grub_uint64_t) inopos[7]) << 0);
|
||||
ino = grub_cpu_to_be64 (ino);
|
||||
|
||||
c = de->name[de->len];
|
||||
de->name[de->len] = '\0';
|
||||
if (iterate_dir_call_hook (ino, de->name, &ctx))
|
||||
return 1;
|
||||
{
|
||||
de->name[de->len] = c;
|
||||
return 1;
|
||||
}
|
||||
de->name[de->len] = c;
|
||||
|
||||
de = ((struct grub_xfs_dir_entry *)
|
||||
(((char *) de)+ sizeof (struct grub_xfs_dir_entry) + de->len
|
||||
+ ((smallino ? sizeof (grub_uint32_t)
|
||||
: sizeof (grub_uint64_t))) - 1));
|
||||
de = grub_xfs_inline_next_de(dir->data, head, de);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -583,19 +808,15 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir,
|
||||
>> dirblk_log2);
|
||||
blk++)
|
||||
{
|
||||
/* The header is skipped, the first direntry is stored
|
||||
from byte 16. */
|
||||
int pos = 16;
|
||||
struct grub_xfs_dir2_entry *direntry =
|
||||
grub_xfs_first_de(dir->data, dirblock);
|
||||
int entries;
|
||||
int tail_start = (dirblk_size
|
||||
- sizeof (struct grub_xfs_dirblock_tail));
|
||||
|
||||
struct grub_xfs_dirblock_tail *tail;
|
||||
tail = (struct grub_xfs_dirblock_tail *) &dirblock[tail_start];
|
||||
struct grub_xfs_dirblock_tail *tail =
|
||||
grub_xfs_dir_tail(dir->data, dirblock);
|
||||
|
||||
numread = grub_xfs_read_file (dir, 0, 0,
|
||||
blk << dirblk_log2,
|
||||
dirblk_size, dirblock);
|
||||
dirblk_size, dirblock, 0);
|
||||
if (numread != dirblk_size)
|
||||
return 0;
|
||||
|
||||
@@ -603,14 +824,11 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir,
|
||||
- grub_be_to_cpu32 (tail->leaf_stale));
|
||||
|
||||
/* Iterate over all entries within this block. */
|
||||
while (pos < (dirblk_size
|
||||
- (int) sizeof (struct grub_xfs_dir2_entry)))
|
||||
while ((char *)direntry < (char *)tail)
|
||||
{
|
||||
struct grub_xfs_dir2_entry *direntry;
|
||||
grub_uint8_t *freetag;
|
||||
char *filename;
|
||||
|
||||
direntry = (struct grub_xfs_dir2_entry *) &dirblock[pos];
|
||||
freetag = (grub_uint8_t *) direntry;
|
||||
|
||||
if (grub_get_unaligned16 (freetag) == 0XFFFF)
|
||||
@@ -618,17 +836,20 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir,
|
||||
grub_uint8_t *skip = (freetag + sizeof (grub_uint16_t));
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
filename = &dirblock[pos + sizeof (*direntry)];
|
||||
/* The byte after the filename is for the tag, which
|
||||
is not used by GRUB. So it can be overwritten. */
|
||||
filename = (char *)(direntry + 1);
|
||||
/* The byte after the filename is for the filetype, padding, or
|
||||
tag, which is not used by GRUB. So it can be overwritten. */
|
||||
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);
|
||||
return 1;
|
||||
@@ -641,8 +862,7 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir,
|
||||
break;
|
||||
|
||||
/* Select the next directory entry. */
|
||||
pos = GRUB_XFS_NEXT_DIRENT (pos, direntry->len);
|
||||
pos = GRUB_XFS_ROUND_TO_DIRENT (pos);
|
||||
direntry = grub_xfs_next_de(dir->data, direntry);
|
||||
}
|
||||
}
|
||||
grub_free (dirblock);
|
||||
@@ -667,36 +887,35 @@ grub_xfs_mount (grub_disk_t disk)
|
||||
if (!data)
|
||||
return 0;
|
||||
|
||||
grub_dprintf("xfs", "Reading sb\n");
|
||||
/* Read the superblock. */
|
||||
if (grub_disk_read (disk, 0, 0,
|
||||
sizeof (struct grub_xfs_sblock), &data->sblock))
|
||||
goto fail;
|
||||
|
||||
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");
|
||||
goto fail;
|
||||
}
|
||||
if (!grub_xfs_sb_valid(data))
|
||||
goto fail;
|
||||
|
||||
data = grub_realloc (data,
|
||||
sizeof (struct grub_xfs_data)
|
||||
- sizeof (struct grub_xfs_inode)
|
||||
+ (1 << data->sblock.log2_inode) + 1);
|
||||
+ grub_xfs_inode_size(data) + 1);
|
||||
|
||||
if (! data)
|
||||
goto fail;
|
||||
|
||||
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->bsize = grub_be_to_cpu32 (data->sblock.bsize);
|
||||
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->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);
|
||||
|
||||
@@ -799,10 +1018,7 @@ grub_xfs_open (struct grub_file *file, const char *name)
|
||||
|
||||
if (fdiro != &data->diropen)
|
||||
{
|
||||
grub_memcpy (&data->diropen, fdiro,
|
||||
sizeof (struct grub_fshelp_node)
|
||||
- sizeof (struct grub_xfs_inode)
|
||||
+ (1 << data->sblock.log2_inode));
|
||||
grub_memcpy (&data->diropen, fdiro, grub_xfs_fshelp_size(data));
|
||||
grub_free (fdiro);
|
||||
}
|
||||
|
||||
@@ -832,7 +1048,7 @@ grub_xfs_read (grub_file_t file, char *buf, grub_size_t len)
|
||||
|
||||
return grub_xfs_read_file (&data->diropen,
|
||||
file->read_hook, file->read_hook_data,
|
||||
file->offset, len, buf);
|
||||
file->offset, len, buf, 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
+141
-51
@@ -252,7 +252,6 @@ struct grub_zfs_data
|
||||
|
||||
uberblock_t current_uberblock;
|
||||
|
||||
int mounted;
|
||||
grub_uint64_t guid;
|
||||
};
|
||||
|
||||
@@ -281,21 +280,30 @@ grub_crypto_cipher_handle_t (*grub_zfs_load_key) (const struct grub_zfs_key *key
|
||||
*/
|
||||
#define MAX_SUPPORTED_FEATURE_STRLEN 50
|
||||
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
|
||||
check_feature(const char *name, grub_uint64_t val, struct grub_zfs_dir_ctx *ctx);
|
||||
static int
|
||||
static grub_err_t
|
||||
check_mos_features(dnode_phys_t *mosmdn_phys,grub_zfs_endian_t endian,struct grub_zfs_data* data );
|
||||
|
||||
static grub_err_t
|
||||
zlib_decompress (void *s, void *d,
|
||||
grub_size_t slen, grub_size_t dlen)
|
||||
{
|
||||
if (grub_zlib_decompress (s, slen, 0, d, dlen) < 0)
|
||||
return grub_errno;
|
||||
return GRUB_ERR_NONE;
|
||||
if (grub_zlib_decompress (s, slen, 0, d, dlen) == (grub_ssize_t) dlen)
|
||||
return GRUB_ERR_NONE;
|
||||
|
||||
if (!grub_errno)
|
||||
grub_error (GRUB_ERR_BAD_COMPRESSED_DATA,
|
||||
"premature end of compressed");
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
@@ -953,7 +961,7 @@ nvpair_value (const char *nvp,char **val,
|
||||
static grub_err_t
|
||||
check_pool_label (struct grub_zfs_data *data,
|
||||
struct grub_zfs_device_desc *diskdesc,
|
||||
int *inserted)
|
||||
int *inserted, int original)
|
||||
{
|
||||
grub_uint64_t pool_state, txg = 0;
|
||||
char *nvlist,*features;
|
||||
@@ -1077,11 +1085,12 @@ check_pool_label (struct grub_zfs_data *data,
|
||||
|
||||
grub_dprintf ("zfs", "check 11 passed\n");
|
||||
|
||||
if (data->mounted && data->guid != poolguid)
|
||||
return grub_error (GRUB_ERR_BAD_FS, "another zpool");
|
||||
else
|
||||
if (original)
|
||||
data->guid = poolguid;
|
||||
|
||||
if (data->guid != poolguid)
|
||||
return grub_error (GRUB_ERR_BAD_FS, "another zpool");
|
||||
|
||||
{
|
||||
char *nv;
|
||||
nv = grub_zfs_nvlist_lookup_nvlist (nvlist, ZPOOL_CONFIG_VDEV_TREE);
|
||||
@@ -1182,7 +1191,7 @@ scan_disk (grub_device_t dev, struct grub_zfs_data *data,
|
||||
}
|
||||
grub_dprintf ("zfs", "label ok %d\n", label);
|
||||
|
||||
err = check_pool_label (data, &desc, inserted);
|
||||
err = check_pool_label (data, &desc, inserted, original);
|
||||
if (err || !*inserted)
|
||||
{
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
@@ -1497,6 +1506,9 @@ read_device (grub_uint64_t offset, struct grub_zfs_device_desc *desc,
|
||||
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
|
||||
"raidz%d is not supported", desc->nparity);
|
||||
|
||||
if (desc->n_children <= desc->nparity || desc->n_children < 1)
|
||||
return grub_error(GRUB_ERR_BAD_FS, "too little devices for given parity");
|
||||
|
||||
orig_s = (((len + (1 << desc->ashift) - 1) >> desc->ashift)
|
||||
+ (desc->n_children - desc->nparity) - 1);
|
||||
s = orig_s;
|
||||
@@ -1744,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++)
|
||||
{
|
||||
if (zio_gb->zg_blkptr[i].blk_birth == 0)
|
||||
if (BP_IS_HOLE(&zio_gb->zg_blkptr[i]))
|
||||
continue;
|
||||
|
||||
err = zio_read_data (&zio_gb->zg_blkptr[i], endian, buf, data);
|
||||
@@ -1793,6 +1805,39 @@ zio_read_data (blkptr_t * bp, grub_zfs_endian_t endian, void *buf,
|
||||
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,
|
||||
* and put the uncompressed data in buf.
|
||||
@@ -1811,12 +1856,26 @@ zio_read (blkptr_t *bp, grub_zfs_endian_t endian, void **buf,
|
||||
*buf = NULL;
|
||||
|
||||
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);
|
||||
lsize = (BP_IS_HOLE(bp) ? 0 :
|
||||
(((grub_zfs_to_cpu64 ((bp)->blk_prop, endian) & 0xffff) + 1)
|
||||
<< SPA_MINBLOCKSHIFT));
|
||||
psize = get_psize (bp, endian);
|
||||
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 :
|
||||
(((grub_zfs_to_cpu64 ((bp)->blk_prop, endian) & 0xffff) + 1)
|
||||
<< SPA_MINBLOCKSHIFT));
|
||||
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)
|
||||
*size = lsize;
|
||||
@@ -1830,33 +1889,41 @@ zio_read (blkptr_t *bp, grub_zfs_endian_t endian, void **buf,
|
||||
"compression algorithm %s not supported\n", decomp_table[comp].name);
|
||||
|
||||
if (comp != ZIO_COMPRESS_OFF)
|
||||
{
|
||||
/* It's not really necessary to align to 16, just for safety. */
|
||||
compbuf = grub_malloc (ALIGN_UP (psize, 16));
|
||||
if (! compbuf)
|
||||
return grub_errno;
|
||||
}
|
||||
/* It's not really necessary to align to 16, just for safety. */
|
||||
compbuf = grub_malloc (ALIGN_UP (psize, 16));
|
||||
else
|
||||
compbuf = *buf = grub_malloc (lsize);
|
||||
if (! compbuf)
|
||||
return grub_errno;
|
||||
|
||||
grub_dprintf ("zfs", "endian = %d\n", endian);
|
||||
err = zio_read_data (bp, endian, compbuf, data);
|
||||
if (BP_IS_EMBEDDED(bp))
|
||||
err = decode_embedded_bp_compressed(bp, compbuf);
|
||||
else
|
||||
{
|
||||
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)
|
||||
{
|
||||
grub_free (compbuf);
|
||||
*buf = NULL;
|
||||
return err;
|
||||
}
|
||||
grub_memset (compbuf, 0, ALIGN_UP (psize, 16) - psize);
|
||||
|
||||
err = zio_checksum_verify (zc, checksum, endian,
|
||||
compbuf, psize);
|
||||
if (err)
|
||||
if (!BP_IS_EMBEDDED(bp))
|
||||
{
|
||||
grub_dprintf ("zfs", "incorrect checksum\n");
|
||||
grub_free (compbuf);
|
||||
*buf = NULL;
|
||||
return err;
|
||||
err = zio_checksum_verify (zc, checksum, endian,
|
||||
compbuf, psize);
|
||||
if (err)
|
||||
{
|
||||
grub_dprintf ("zfs", "incorrect checksum\n");
|
||||
grub_free (compbuf);
|
||||
*buf = NULL;
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
if (encrypted)
|
||||
@@ -1968,7 +2035,7 @@ dmu_read (dnode_end_t * dn, grub_uint64_t blkid, void **buf,
|
||||
dn->endian)
|
||||
<< SPA_MINBLOCKSHIFT;
|
||||
*buf = grub_malloc (size);
|
||||
if (*buf)
|
||||
if (!*buf)
|
||||
{
|
||||
err = grub_errno;
|
||||
break;
|
||||
@@ -2006,12 +2073,14 @@ dmu_read (dnode_end_t * dn, grub_uint64_t blkid, void **buf,
|
||||
*/
|
||||
static grub_err_t
|
||||
mzap_lookup (mzap_phys_t * zapobj, grub_zfs_endian_t endian,
|
||||
int objsize, const char *name, grub_uint64_t * value,
|
||||
grub_uint32_t objsize, const char *name, grub_uint64_t * value,
|
||||
int case_insensitive)
|
||||
{
|
||||
int i, chunks;
|
||||
grub_uint32_t i, chunks;
|
||||
mzap_ent_phys_t *mzap_ent = zapobj->mz_chunk;
|
||||
|
||||
if (objsize < MZAP_ENT_LEN)
|
||||
return grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"), name);
|
||||
chunks = objsize / MZAP_ENT_LEN - 1;
|
||||
for (i = 0; i < chunks; i++)
|
||||
{
|
||||
@@ -2419,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)
|
||||
{
|
||||
grub_uint64_t block_type;
|
||||
int size;
|
||||
grub_uint32_t size;
|
||||
void *zapbuf;
|
||||
grub_err_t err;
|
||||
grub_zfs_endian_t endian;
|
||||
@@ -2427,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);
|
||||
|
||||
/* 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;
|
||||
err = dmu_read (zap_dnode, 0, &zapbuf, &endian, data);
|
||||
if (err)
|
||||
@@ -2800,6 +2869,9 @@ dnode_get_path (struct subvolume *subvol, const char *path_in, dnode_end_t *dn,
|
||||
dnode_path->dn.endian)
|
||||
<< SPA_MINBLOCKSHIFT);
|
||||
|
||||
if (blksz == 0)
|
||||
return grub_error(GRUB_ERR_BAD_FS, "0-sized block");
|
||||
|
||||
sym_value = grub_malloc (sym_sz);
|
||||
if (!sym_value)
|
||||
return grub_errno;
|
||||
@@ -2810,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);
|
||||
if (err)
|
||||
return err;
|
||||
{
|
||||
grub_free (sym_value);
|
||||
return err;
|
||||
}
|
||||
|
||||
movesize = sym_sz - block * blksz;
|
||||
if (movesize > blksz)
|
||||
@@ -2825,6 +2900,8 @@ dnode_get_path (struct subvolume *subvol, const char *path_in, dnode_end_t *dn,
|
||||
if (!path_buf)
|
||||
{
|
||||
grub_free (oldpathbuf);
|
||||
if (free_symval)
|
||||
grub_free (sym_value);
|
||||
return grub_errno;
|
||||
}
|
||||
grub_memcpy (path, sym_value, sym_sz);
|
||||
@@ -3008,7 +3085,7 @@ get_filesystem_dnode (dnode_end_t * mosmdn, char *fsname,
|
||||
|
||||
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)
|
||||
return err;
|
||||
|
||||
@@ -3041,7 +3118,7 @@ get_filesystem_dnode (dnode_end_t * mosmdn, char *fsname,
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = dnode_get (mosmdn, objnum, DMU_OT_DSL_DIR, mdn, data);
|
||||
err = dnode_get (mosmdn, objnum, 0, mdn, data);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
@@ -3055,7 +3132,7 @@ make_mdn (dnode_end_t * mdn, struct grub_zfs_data *data)
|
||||
{
|
||||
void *osp;
|
||||
blkptr_t *bp;
|
||||
grub_size_t ospsize;
|
||||
grub_size_t ospsize = 0;
|
||||
grub_err_t err;
|
||||
|
||||
grub_dprintf ("zfs", "endian = %d\n", mdn->endian);
|
||||
@@ -3196,8 +3273,7 @@ dnode_get_fullpath (const char *fullpath, struct subvolume *subvol,
|
||||
|
||||
grub_dprintf ("zfs", "endian = %d\n", subvol->mdn.endian);
|
||||
|
||||
err = dnode_get (&(data->mos), headobj, DMU_OT_DSL_DATASET, &subvol->mdn,
|
||||
data);
|
||||
err = dnode_get (&(data->mos), headobj, 0, &subvol->mdn, data);
|
||||
if (err)
|
||||
{
|
||||
grub_free (fsname);
|
||||
@@ -3593,8 +3669,13 @@ zfs_mount (grub_device_t dev)
|
||||
if (ub->ub_version >= SPA_VERSION_FEATURES &&
|
||||
check_mos_features(&((objset_phys_t *) osp)->os_meta_dnode,ub_endian,
|
||||
data) != 0)
|
||||
return NULL;
|
||||
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_FS, "Unsupported features in pool");
|
||||
grub_free (osp);
|
||||
zfs_unmount (data);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Got the MOS. Save it at the memory addr MOS. */
|
||||
grub_memmove (&(data->mos.dn), &((objset_phys_t *) osp)->os_meta_dnode,
|
||||
DNODE_SIZE);
|
||||
@@ -3602,8 +3683,6 @@ zfs_mount (grub_device_t dev)
|
||||
ub_endian) >> 63) & 1;
|
||||
grub_free (osp);
|
||||
|
||||
data->mounted = 1;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
@@ -3794,6 +3873,12 @@ grub_zfs_read (grub_file_t file, char *buf, grub_size_t len)
|
||||
blksz = grub_zfs_to_cpu16 (data->dnode.dn.dn_datablkszsec,
|
||||
data->dnode.endian) << SPA_MINBLOCKSHIFT;
|
||||
|
||||
if (blksz == 0)
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_FS, "0-sized block");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Entire Dnode is too big to fit into the space available. We
|
||||
* will need to read it in chunks. This could be optimized to
|
||||
@@ -3887,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);
|
||||
|
||||
err = dnode_get (&(data->mos), headobj, DMU_OT_DSL_DATASET, &mdn, data);
|
||||
err = dnode_get (&(data->mos), headobj, 0, &mdn, data);
|
||||
if (err)
|
||||
{
|
||||
grub_dprintf ("zfs", "failed here\n");
|
||||
@@ -3965,7 +4050,12 @@ iterate_zap (const char *name, grub_uint64_t val, struct grub_zfs_dir_ctx *ctx)
|
||||
dnode_end_t dn;
|
||||
grub_memset (&info, 0, sizeof (info));
|
||||
|
||||
dnode_get (&(ctx->data->subvol.mdn), val, 0, &dn, ctx->data);
|
||||
err = dnode_get (&(ctx->data->subvol.mdn), val, 0, &dn, ctx->data);
|
||||
if (err)
|
||||
{
|
||||
grub_print_error ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (dn.dn.dn_bonustype == DMU_OT_SA)
|
||||
{
|
||||
@@ -4186,11 +4276,11 @@ check_feature (const char *name, grub_uint64_t val,
|
||||
* errnum: Failure.
|
||||
*/
|
||||
|
||||
static int
|
||||
static grub_err_t
|
||||
check_mos_features(dnode_phys_t *mosmdn_phys,grub_zfs_endian_t endian,struct grub_zfs_data* data )
|
||||
{
|
||||
grub_uint64_t objnum;
|
||||
grub_uint8_t errnum = 0;
|
||||
grub_err_t errnum = 0;
|
||||
dnode_end_t dn,mosmdn;
|
||||
mzap_phys_t* mzp;
|
||||
grub_zfs_endian_t endianzap;
|
||||
|
||||
Loaded 100 of 527 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user