merge mainline into gingold2
This commit is contained in:
commit
4ce9a74332
162 changed files with 8986 additions and 1304 deletions
|
@ -18,7 +18,6 @@ config.log
|
|||
config.status
|
||||
config.sub
|
||||
configure
|
||||
conf/*.mk
|
||||
*.d
|
||||
DISTLIST
|
||||
docs/*.info
|
||||
|
@ -69,6 +68,7 @@ Makefile
|
|||
mod-*.c
|
||||
missing
|
||||
*.pf2
|
||||
*.pp
|
||||
po/*.mo
|
||||
po/grub.pot
|
||||
stamp-h
|
||||
|
@ -91,7 +91,10 @@ texinfo.tex
|
|||
grub-core/lib/libgcrypt-grub
|
||||
**/.deps-util
|
||||
**/.deps-core
|
||||
**/.dirstamp
|
||||
Makefile.util.am
|
||||
grub-core/Makefile.core.am
|
||||
grub-core/Makefile.gcry.am
|
||||
grub-core/Makefile.gcry.def
|
||||
grub-core/*.module
|
||||
grub-core/*.pp
|
||||
|
|
662
ChangeLog
662
ChangeLog
|
@ -1,3 +1,665 @@
|
|||
2010-09-11 Vladimir Serbinenko <phcoder@gmail.com>
|
||||
|
||||
Shutdown using ACPI.
|
||||
|
||||
* grub-core/Makefile.core.def (halt): Add commands/acpihalt.c on i386-pc.
|
||||
* grub-core/commands/acpihalt.c: New file.
|
||||
* grub-core/commands/i386/pc/halt.c (grub_cmd_halt): Call grub_acpi_halt.
|
||||
* include/grub/acpi.h (grub_acpi_fadt): New member pm1a.
|
||||
(grub_acpi_halt): New proto.
|
||||
(GRUB_ACPI_SLP_EN): New const.
|
||||
(GRUB_ACPI_SLP_TYP_OFFSET): Likewise.
|
||||
(GRUB_ACPI_OPCODE_*): New enum.
|
||||
(GRUB_ACPI_EXTOPCODE_*): Likewise.
|
||||
|
||||
2010-09-11 Tristan Gingold <gingold@free.fr>
|
||||
2010-09-11 Robert Millan <rmh.grub@aybabtu.com>
|
||||
2010-09-11 Vladimir Serbinenko <phcoder@gmail.com>
|
||||
|
||||
* commands/lsacpi.c: New file.
|
||||
* grub-core/Makefile.core.def (lsacpi): New module.
|
||||
* include/grub/acpi.h (GRUB_ACPI_FADT_SIGNATURE): New definition.
|
||||
(GRUB_ACPI_MADT_SIGNATURE): Likewise.
|
||||
(grub_acpi_madt_entry_header): New struct.
|
||||
(grub_acpi_madt): Likewise.
|
||||
(grub_acpi_madt_entry_interrupt_override): Likewise.
|
||||
(grub_acpi_madt_entry_sapic): Likewise.
|
||||
(grub_acpi_madt_entry_lsapic): Likewise.
|
||||
(grub_acpi_madt_entry_platform_int_source): Likewise.
|
||||
* include/grub/types.h (PRIxGRUB_UINT32_T): New definition.
|
||||
(PRIuGRUB_UINT32_T): Likewise.
|
||||
(PRIxGRUB_UINT64_T): Likewise.
|
||||
|
||||
2010-09-11 Vladimir Serbinenko <phcoder@gmail.com>
|
||||
|
||||
Implement loading palette on ieee1275_fb.
|
||||
|
||||
* grub-core/video/ieee1275.c (stdout_ihandle): New variable.
|
||||
(have_setcolors): Likewise.
|
||||
(grub_video_ieee1275_init): Fill stdout_ihandle and have_setcolors.
|
||||
(grub_video_ieee1275_setup): Use grub_video_ieee1275_set_palette.
|
||||
(grub_video_ieee1275_set_palette): Implement.
|
||||
|
||||
2010-09-11 Vladimir Serbinenko <phcoder@gmail.com>
|
||||
2010-09-11 Colin Watson <cjwatson@ubuntu.com>
|
||||
|
||||
* util/grub-install.in (grub_partition): New variable.
|
||||
Set prefix_drive on EFI and PC to (,$grub_partition) as last resort.
|
||||
* util/i386/pc/grub-setup.c (setup): Don't touch prefix.
|
||||
Fixes a bug reported by Yves Blusseau.
|
||||
|
||||
2010-09-11 Vladimir Serbinenko <phcoder@gmail.com>
|
||||
|
||||
Fix emu on mipsel.
|
||||
|
||||
* conf/Makefile.common (CFLAGS_PLATFORM): Add -mflush-func
|
||||
=grub_cpu_flush_cache on all mips and not only yeeloong.
|
||||
* configure.ac (COND_mips): New conditional.
|
||||
* grub-core/Makefile.am (KERNEL_HEADER_FILES): Add libgcc on all
|
||||
platforms.
|
||||
* grub-core/kern/emu/cache.S (__mips__): Use _flush_cache.
|
||||
* grub-core/kern/emu/full.c (grub_arch_dl_init_linker)
|
||||
[GRUB_LINKER_HAVE_INIT]: New function.
|
||||
(grub_emu_post_init): Likewise.
|
||||
* grub-core/kern/emu/lite.c (grub_emu_post_init): Likewise.
|
||||
* grub-core/kern/emu/main.c: Use grub_emu_post_init.
|
||||
* include/grub/cache.h (_mips): Include mips/cache.h.
|
||||
* include/grub/disk.h [GRUB_UTIL || GRUB_MACHINE_EMU]: Add missing
|
||||
LVM and RAID prototypes.
|
||||
* include/grub/emu/misc.h (grub_emu_post_init): New proto.
|
||||
* include/grub/mips/time.h (grub_cpu_idle) [GRUB_MACHINE_EMU]: New
|
||||
function.
|
||||
|
||||
2010-09-10 Colin Watson <cjwatson@ubuntu.com>
|
||||
|
||||
* util/grub-install.in: Don't try to verify core.img until after
|
||||
running grub-mkimage to create it.
|
||||
|
||||
2010-09-10 Robert Millan <rmh@gnu.org>
|
||||
|
||||
* util/grub.d/10_hurd.in: Add misc readability checks.
|
||||
* util/grub.d/10_kfreebsd.in: Likewise.
|
||||
* util/grub.d/10_linux.in: Likewise.
|
||||
|
||||
2010-09-10 Colin Watson <cjwatson@ubuntu.com>
|
||||
|
||||
* util/grub-install.in: ${imgext} won't be defined here until the
|
||||
install branch is merged. For the meantime, only verify core.img on
|
||||
i386-pc and sparc64-ieee1275 platforms.
|
||||
|
||||
2010-09-10 Robert Millan <rmh@gnu.org>
|
||||
|
||||
Solaris support in grub_find_zpool_from_dir(). Thanks
|
||||
Seth Goldberg for referring to getextmntent() facility.
|
||||
|
||||
* configure.ac: Check for getextmntent(), `sys/mnttab.h' and
|
||||
`sys/mkdev.h'.
|
||||
* grub-core/kern/emu/misc.c [HAVE_SYS_MNTTAB_H]: Include
|
||||
`<sys/mnttab.h>'.
|
||||
[HAVE_SYS_MKDEV_H]: Include `<sys/mkdev.h>'.
|
||||
[HAVE_GETEXTMNTENT] (grub_find_zpool_from_dir): Add getextmntent()
|
||||
method for finding zpool name.
|
||||
|
||||
2010-09-10 Colin Watson <cjwatson@ubuntu.com>
|
||||
|
||||
grub-fstest needs the host and hostfs modules while other utilities
|
||||
actively require those modules to be absent, so grub-fstest needs
|
||||
its own initialisation and finalisation code.
|
||||
|
||||
* Makefile.am (grub_fstest.pp): New target.
|
||||
(grub_fstest_init.lst): Likewise.
|
||||
(grub_fstest_init.c): Likewise.
|
||||
* Makefile.util.def (grub-fstest): Add grub_fstest_init.c.
|
||||
|
||||
2010-09-10 Robert Millan <rmh@gnu.org>
|
||||
|
||||
* configure.ac: Check for `struct statfs.f_fstypename' and
|
||||
`struct statfs.f_mntfromname'.
|
||||
|
||||
* grub-core/kern/emu/misc.c (grub_find_zpool_from_dir): Conditionalize
|
||||
kFreeBSD-specific code.
|
||||
|
||||
2010-09-10 Robert Millan <rmh@gnu.org>
|
||||
|
||||
* util/grub.d/10_kfreebsd.in: Fix ${kfreebsd_device} initialization
|
||||
on ZFS. Now non-main filesystems are supported as / too.
|
||||
|
||||
2010-09-09 Colin Watson <cjwatson@ubuntu.com>
|
||||
|
||||
* Makefile.util.def (libgrub.a): Move grub-core/kern/emu/hostfs.c
|
||||
and grub-core/disk/host.c to ...
|
||||
(grub-fstest): ... here. Having the host disk implementation
|
||||
present confuses grub-probe and other utility programs.
|
||||
|
||||
* util/grub-mkconfig.in: Only verify readability of grub.cfg.new
|
||||
when writing to a file, not when writing to stdout.
|
||||
|
||||
2010-09-09 BVK Chaitanya <bvk.groups@gmail.com>
|
||||
|
||||
* tests/partmap_test.in: New test for partitions.
|
||||
* Makefile.util.def: Rules for new test.
|
||||
|
||||
2010-09-09 Robert Millan <rmh@gnu.org>
|
||||
|
||||
* util/grub-probe.c (probe): Fix a pair of unhandled error
|
||||
conditions.
|
||||
|
||||
2010-09-09 Robert Millan <rmh@gnu.org>
|
||||
|
||||
Basic Btrfs support (detection and UUID).
|
||||
|
||||
* grub-core/fs/btrfs.c: New file.
|
||||
* Makefile.util.def (library): Register btrfs.c.
|
||||
* grub-core/Makefile.core.def: Likewise.
|
||||
|
||||
2010-09-08 Robert Millan <rmh@gnu.org>
|
||||
|
||||
* util/grub-mkconfig_lib.in (is_path_readable_by_grub): Improve
|
||||
with (optional) parameters to specify device and relative path.
|
||||
* util/grub-install.in: Use is_path_readable_by_grub() to
|
||||
verify readability of a few critical files.
|
||||
* util/grub-mkconfig.in: Use is_path_readable_by_grub() to
|
||||
verify readability of grub.cfg.new.
|
||||
|
||||
2010-09-08 Vladimir Serbinenko <phcoder@gmail.com>
|
||||
|
||||
Split minix.mod into minix.mod and minix2.mod.
|
||||
|
||||
* Makefile.util.def (libgrub.a): Add grub-core/fs/minix2.c.
|
||||
* grub-core/Makefile.core.def (minix2): New module.
|
||||
* grub-core/fs/minix.c: Use definitions instead of runtime version
|
||||
checking.
|
||||
* grub-core/fs/minix2.c: New file.
|
||||
|
||||
2010-09-08 Yves Blusseau <blusseau@zetam.org>
|
||||
|
||||
Add new --boot-directory option to replace --root-directory
|
||||
|
||||
* util/grub-install.in: Add new --boot-directory option
|
||||
* util/grub-reboot.in: Likewise.
|
||||
* util/grub-set-default.in: Likewise.
|
||||
|
||||
2010-09-08 Yves Blusseau <blusseau@zetam.org>
|
||||
|
||||
* util/grub-mkconfig.in: Use new variable.
|
||||
|
||||
2010-09-08 Yves Blusseau <blusseau@zetam.org>
|
||||
|
||||
* configure.ac: Define some useful variables.
|
||||
|
||||
2010-09-08 Vladimir Serbinenko <phcoder@gmail.com>
|
||||
|
||||
* grub-core/kern/ieee1275/cmain.c (grub_ieee1275_find_options): Set
|
||||
GRUB_IEEE1275_FLAG_HAS_CURSORONOFF when appropriate.
|
||||
* grub-core/term/ieee1275/ofconsole.c (grub_ofconsole_setcursor):
|
||||
Use terminfo and don't use cursor-on/cursor-off unless it's known
|
||||
to work.
|
||||
* include/grub/ieee1275/ieee1275.h (grub_ieee1275_flag): New element
|
||||
GRUB_IEEE1275_FLAG_HAS_CURSORONOFF.
|
||||
|
||||
2010-09-08 Colin Watson <cjwatson@ubuntu.com>
|
||||
|
||||
* grub-core/kern/efi/init.c (grub_efi_set_prefix): If the prefix
|
||||
starts with "(,", fill the drive containing the loaded image in
|
||||
between those two characters, but expect that a full partition
|
||||
specification including partition map names will follow.
|
||||
|
||||
2010-09-08 Robert Millan <rmh@gnu.org>
|
||||
|
||||
* configure.ac: Remove `--enable-grub-fstest' option.
|
||||
* Makefile.util.def (grub-fstest): Remove COND_GRUB_FSTEST condition.
|
||||
|
||||
* util/grub-mkconfig_lib.in (is_path_readable_by_grub): Use
|
||||
`grub-fstest' instead of `grub-probe' for readability verification.
|
||||
* util/grub-probe.c (probe): Remove readability verification kludge.
|
||||
|
||||
2010-09-08 Robert Millan <rmh@gnu.org>
|
||||
|
||||
* util/grub-mkconfig.in: Pass `--device ${GRUB_DEVICE}' when
|
||||
initializing `GRUB_FS'.
|
||||
|
||||
2010-09-08 BVK Chaitanya <bvk.groups@gmail.com>
|
||||
|
||||
Not command (!) support to GRUB script.
|
||||
|
||||
* tests/grub_script_not.in: New test.
|
||||
* Makefile.util.def: Rules for new test.
|
||||
|
||||
* grub-core/script/execute.c (grub_script_execute_cmdline): Handle
|
||||
! command as a special case.
|
||||
* grub-core/script/yylex.l (GRUB_PARSER_TOKEN_NOT): Removed.
|
||||
|
||||
2010-09-07 BVK Chaitanya <bvk.groups@gmail.com>
|
||||
|
||||
* grub-core/commands/wildcard.c (wildcard_expand): Fix wrong
|
||||
grub_free.
|
||||
|
||||
2010-09-07 BVK Chaitanya <bvk.groups@gmail.com>
|
||||
|
||||
* docs/grub.texi (Shell-like scripting): Fix @dots to @dots{}.
|
||||
|
||||
2010-09-07 BVK Chaitanya <bvk.groups@gmail.com>
|
||||
|
||||
* docs/grub.texi (Shell-like scripting): Documentation for break,
|
||||
continue, shift and return commands.
|
||||
|
||||
2010-09-06 Vladimir Serbinenko <phcoder@gmail.com>
|
||||
|
||||
Rename CD-ROM to cd on BIOS.
|
||||
|
||||
* grub-core/disk/i386/pc/biosdisk.c (grub_biosdisk_get_drive): Recognise
|
||||
"cd".
|
||||
(grub_biosdisk_call_hook): Call with "cd" instead of arbitrary hdX.
|
||||
|
||||
2010-09-05 Vladimir Serbinenko <phcoder@gmail.com>
|
||||
|
||||
* grub-core/kern/emu/main.c (main): Reinit LVM and RAID.
|
||||
* util/grub-probe.c (main): Likewise.
|
||||
* util/i386/pc/grub-setup.c (main): Likewise.
|
||||
* util/sparc64/ieee1275/grub-setup.c (main): Likewise.
|
||||
Reported and debugged by: alexxy
|
||||
|
||||
2010-09-05 Vladimir Serbinenko <phcoder@gmail.com>
|
||||
|
||||
* grub-core/disk/lvm.c (grub_lvm_scan_device) [GRUB_UTIL]: Output more
|
||||
diagnostic info.
|
||||
|
||||
2010-09-05 Jo Shields <directhex@apebox.org>
|
||||
|
||||
* util/grub.d/30_os-prober.in: Add missing classes.
|
||||
|
||||
2010-09-05 Vladimir Serbinenko <phcoder@gmail.com>
|
||||
|
||||
* docs/grub.texi (Theme file format): Document new position format.
|
||||
|
||||
2010-09-05 Vladimir Serbinenko <phcoder@gmail.com>
|
||||
|
||||
* docs/grub.texi (Theme file format): Replace Box_slice_names.png with
|
||||
a table. Use @code instead of @verbatim.
|
||||
|
||||
2010-09-05 Colin D Bennett <colin@gibibit.com>
|
||||
|
||||
Gfxmenu documentation.
|
||||
|
||||
* docs/grub.texi (Theme file format): New chapter.
|
||||
|
||||
2010-09-05 Szymon Janc <szymon@janc.net.pl>
|
||||
|
||||
* grub-core/Makefile.core.def (xzio): New module.
|
||||
* grub-core/io/xzio.c: New file.
|
||||
* grub-core/lib/xzembed/xz.h: New file (from xembed).
|
||||
* grub-core/lib/xzembed/xz_config.h: Likewise.
|
||||
* grub-core/lib/xzembed/xz_dec_bcj.c: Likewise.
|
||||
* grub-core/lib/xzembed/xz_dec_lzma2.c: Likewise.
|
||||
* grub-core/lib/xzembed/xz_dec_stream.c: Likewise.
|
||||
* grub-core/lib/xzembed/xz_lzma2.h: Likewise.
|
||||
* grub-core/lib/xzembed/xz_private.h: Likewise.
|
||||
* grub-core/lib/xzembed/xz_stream.h: Likewise.
|
||||
* include/grub/file.h (grub_file_filter_id): New compression filter
|
||||
GRUB_FILE_FILTER_XZIO.
|
||||
|
||||
2010-09-05 Vladimir Serbinenko <phcoder@gmail.com>
|
||||
|
||||
* include/grub/file.h (GRUB_FILE_SIZE_UNKNOWN): New definition.
|
||||
* grub-core/disk/loopback.c (grub_loopback_open): Handle unknown file
|
||||
size.
|
||||
|
||||
2010-09-05 Vladimir Serbinenko <phcoder@gmail.com>
|
||||
|
||||
* include/grub/err.h (grub_err_t): Replace GRUB_ERR_BAD_GZIP_DATA with
|
||||
GRUB_ERR_BAD_COMPRESSED_DATA. All users updated.
|
||||
|
||||
2010-09-05 Vladimir Serbinenko <phcoder@gmail.com>
|
||||
|
||||
Uncompressed checksum support.
|
||||
|
||||
* grub-core/commands/hashsum.c (options): Add option --uncompress.
|
||||
(check_list): New parameter uncompress.
|
||||
(grub_cmd_hashsum): Handle --uncompress.
|
||||
|
||||
2010-09-05 Vladimir Serbinenko <phcoder@gmail.com>
|
||||
|
||||
Reintroduce testload.
|
||||
|
||||
* grub-core/commands/minicmd.c (grub_rescue_cmd_testload) [0]: Moved
|
||||
from here ...
|
||||
* grub-core/commands/testload.c (grub_cmd_testload): ... here.
|
||||
(GRUB_MOD_INIT): New function.
|
||||
(GRUB_MOD_FINI): Likewise.
|
||||
* grub-core/Makefile.core.def (testload): New module.
|
||||
|
||||
2010-09-05 Szymon Janc <szymon@janc.net.pl>
|
||||
|
||||
* grub-core/lib/posix_wrap/sys/types.h (bool): Transform into an enum.
|
||||
(uint8_t): New type.
|
||||
(uint16_t): Likewise.
|
||||
(uint32_t): Likewise.
|
||||
(uint64_t): Likewise.
|
||||
|
||||
2010-09-05 Szymon Janc <szymon@janc.net.pl>
|
||||
|
||||
* include/grub/crypto.h (GRUB_MD_CRC32): New definition.
|
||||
|
||||
2010-09-05 Vladimir Serbinenko <phcoder@gmail.com>
|
||||
|
||||
* grub-core/io/gzio.c (grub_gzio_open): Removed "transparent" parameter.
|
||||
Made static.
|
||||
(grub_gzfile_open): Removed. All users updated.
|
||||
(GRUB_MOD_INIT): New function.
|
||||
(GRUB_MOD_FINI): Likewise.
|
||||
* grub-core/kern/file.c (grub_file_filters_all): New variable.
|
||||
(grub_file_filters_enabled): Likewise.
|
||||
(grub_file_open): Handle filters.
|
||||
* grub-core/loader/i386/bsd.c (GRUB_MOD_INIT): Load gzio.
|
||||
* grub-core/normal/main.c (GRUB_MOD_INIT): Likewise.
|
||||
* include/grub/file.h (grub_file_filter_id_t): New type.
|
||||
(grub_file_filter_t): Likewise.
|
||||
(grub_file_filters_all): New extern variable.
|
||||
(grub_file_filters_enabled): Likewise.
|
||||
(grub_file_filter_register): New inline function.
|
||||
(grub_file_filter_unregister): Likewise.
|
||||
(grub_file_filter_disable): Likewise.
|
||||
(grub_file_filter_disable_compression): Likewise.
|
||||
* include/grub/gzio.h: Removed.
|
||||
|
||||
2010-09-04 BVK Chaitanya <bvk.groups@gmail.com>
|
||||
|
||||
Filename expansion support for wildcards in GRUB script.
|
||||
|
||||
* tests/grub_script_expansion.in: New test.
|
||||
* Makefile.util.def: Rule for new test.
|
||||
|
||||
* grub-core/commands/wildcard.c: New file, implements filename
|
||||
expansion support for GRUB script.
|
||||
* grub-core/Makefile.core.def: Rule update for regexp.mod.
|
||||
* grub-core/script/argv.c: Cosmetic changes.
|
||||
* grub-core/script/execute.c (grub_script_arglist_to_argv):
|
||||
Refactored to perform wildcard expansion on arguments.
|
||||
* include/grub/script_sh.h (grub_script_wildcard_translator): New
|
||||
struct.
|
||||
|
||||
* tests/util/grub-shell.in: Fix quoting for read input.
|
||||
|
||||
2010-09-04 BVK Chaitanya <bvk.groups@gmail.com>
|
||||
|
||||
Support for updating environment variables with matched substrings
|
||||
of regexp.
|
||||
|
||||
* tests/grub_cmd_regexp.in: New test.
|
||||
* Makefile.util.def: Rule for new test.
|
||||
|
||||
* grub-core/commands/regexp.c: New option -s to update environment
|
||||
variables with regexp matches.
|
||||
|
||||
2010-09-04 Szymon Janc <szymon@janc.net.pl>
|
||||
|
||||
* include/grub/file.h (grub_file): New member not_easly_seekable.
|
||||
(grub_file_seekable): New inline function.
|
||||
* grub-core/io/gzio.c (test_header): Don't test end magic if file isn't
|
||||
easily seekable.
|
||||
(grub_gzio_open): Set not_easly_seekable.
|
||||
* grub-core/fs/i386/pc/pxe.c (grub_pxefs_open): Set not_easily_seekable.
|
||||
* grub-core/io/bufio.c (grub_bufio_open): Propagate not_easily_seekable.
|
||||
|
||||
2010-09-04 BVK Chaitanya <bvk.groups@gmail.com>
|
||||
|
||||
Support for options to appear multiple times on cmdline.
|
||||
|
||||
* include/grub/lib/arg.h (grub_arg_list_alloc): New prototype.
|
||||
* grub-core/commands/extcmd.c: Support for repeatable option.
|
||||
* grub-core/lib/arg.c (grub_arg_list_alloc): New function for
|
||||
repeatable option support.
|
||||
|
||||
Refactor menuentry into a regular command.
|
||||
|
||||
* grub-core/commands/menuentry.c: New file, menuentry command
|
||||
implementation.
|
||||
* grub-core/Makefile.core.def: Rule update for normal.mod.
|
||||
* grub-core/normal/main.c: Moved menuentry creation to
|
||||
grub-core/commands/menuentry.c.
|
||||
* grub-core/normal/menu.c (grub_menu_execute_entry): Removed.
|
||||
(grub_menu_execute_entry_real): Removed.
|
||||
* grub-core/script/execute.c (grub_script_execute_sourcecode): New
|
||||
function.
|
||||
(grub_script_execute_menuentry): Removed.
|
||||
* grub-core/script/parser.y (menuentry): Removed.
|
||||
* grub-core/script/script.c (grub_script_create_cmdmenu): Removed.
|
||||
* grub-core/script/yylex.l (menuentry): Removed.
|
||||
* include/grub/menu.h (grub_menu_init): New prototype.
|
||||
(grub_menu_fini): New prototype.
|
||||
* include/grub/normal.h (grub_normal_add_menu_entry): Removed.
|
||||
* include/grub/script_sh.h (grub_script_cmd_menuentry): Removed.
|
||||
(grub_script_execute_sourcecode): New prototype.
|
||||
|
||||
2010-09-04 BVK Chaitanya <bvk.groups@gmail.com>
|
||||
|
||||
"return" command for GRUB script functions.
|
||||
|
||||
* tests/grub_script_return.in: New test.
|
||||
* Makefile.util.def: Rules for new test.
|
||||
|
||||
* grub-core/script/execute.c (grub_script_return): New function.
|
||||
* grub-core/script/main.c: Register/unregister return commaond.
|
||||
* include/grub/script_sh.h (grub_script_return): New prototype.
|
||||
|
||||
2010-09-04 BVK Chaitanya <bvk.groups@gmail.com>
|
||||
|
||||
"setparams" command to update positional parameters.
|
||||
|
||||
* tests/grub_script_setparams.in: New test.
|
||||
* Makefile.util.def: Rules for new test.
|
||||
|
||||
* grub-core/script/argv.c (grub_script_argv_make): New function.
|
||||
* grub-core/script/execute.c (replace_scope): New function.
|
||||
(grub_script_setparams): New function.
|
||||
* grub-core/script/lexer.c: Remove unused variables.
|
||||
* grub-core/script/main.c: Register/unregister setparams command.
|
||||
* include/grub/script_sh.h (grub_script_argv_make): New prototype.
|
||||
(grub_script_setparams): New prototype.
|
||||
|
||||
2010-09-04 BVK Chaitanya <bvk.groups@gmail.com>
|
||||
|
||||
* grub-core/normal/completion.c (grub_normal_do_completion): Fix
|
||||
grub_free order.
|
||||
|
||||
2010-09-04 BVK Chaitanya <bvk.groups@gmail.com>
|
||||
|
||||
Support for passing block of commands as an argument to extcmds.
|
||||
|
||||
* Makefile.util.def: Rules for new test.
|
||||
* tests/grub_script_blockarg.in: New test.
|
||||
* grub-core/tests/test_blockarg.c: New file, block argument
|
||||
command used in the test.
|
||||
|
||||
* include/grub/extcmd.h (grub_extcmd_context): New struct.
|
||||
(grub_register_extcmd_prio): New function prototype.
|
||||
(grub_extcmd_dispatcher): New function prototype.
|
||||
* include/grub/command.h (GRUB_COMMAND_FLAG_BLOCKS): New command
|
||||
type.
|
||||
* include/grub/script_sh.h (struct grub_script): New members
|
||||
`children', `next_siblings' and `refcnt' for block arguments and
|
||||
reference counting.
|
||||
(GRUB_SCRIPT_ARG_TYPE_BLOCK): New argument type.
|
||||
(grub_script_arg): New member `script' for block argument.
|
||||
(grub_script_argv): New member `script' for block argument.
|
||||
(grub_parser_param): New member `scripts' for block argument.
|
||||
(grub_script_mem_free): New extern function prototype.
|
||||
(grub_script_ref): New function prototype.
|
||||
(grub_script_unref): New function prototype.
|
||||
|
||||
* grub-core/normal/dyncmd.c (grub_dyncmd_dispatcher): Moved to
|
||||
extcmd form to support block arguments.
|
||||
* grub-core/script/argv.c: Block arguments support.
|
||||
* grub-core/script/execute.c: Likewise.
|
||||
* grub-core/script/lexer.c: Likewise.
|
||||
* grub-core/script/main.c: Likewise.
|
||||
* grub-core/script/script.c: Likewise.
|
||||
* grub-core/script/parser.y: Likewise. New `block' and `block0'
|
||||
non-terminals.
|
||||
|
||||
* grub-core/commands/acpi.c: Update extcmd implementations with
|
||||
grub_extcmd_context_t.
|
||||
* grub-core/commands/cat.c: Likewise.
|
||||
* grub-core/commands/echo.c: Likewise.
|
||||
* grub-core/commands/extcmd.c: Likewise.
|
||||
* grub-core/commands/hashsum.c: Likewise.
|
||||
* grub-core/commands/hdparm.c: Likewise.
|
||||
* grub-core/commands/help.c: Likewise.
|
||||
* grub-core/commands/hexdump.c: Likewise.
|
||||
* grub-core/commands/i386/cpuid.c: Likewise.
|
||||
* grub-core/commands/i386/pc/drivemap.c: Likewise.
|
||||
* grub-core/commands/i386/pc/halt.c: Likewise.
|
||||
* grub-core/commands/i386/pc/sendkey.c: Likewise.
|
||||
* grub-core/commands/iorw.c: Likewise.
|
||||
* grub-core/commands/keystatus.c: Likewise.
|
||||
* grub-core/commands/loadenv.c: Likewise.
|
||||
* grub-core/commands/ls.c: Likewise.
|
||||
* grub-core/commands/lspci.c: Likewise.
|
||||
* grub-core/commands/memrw.c: Likewise.
|
||||
* grub-core/commands/probe.c: Likewise.
|
||||
* grub-core/commands/search_wrap.c: Likewise.
|
||||
* grub-core/commands/setpci.c: Likewise.
|
||||
* grub-core/commands/sleep.c: Likewise.
|
||||
* grub-core/disk/loopback.c: Likewise.
|
||||
* grub-core/hello/hello.c: Likewise.
|
||||
* grub-core/loader/i386/bsd.c: Likewise.
|
||||
* grub-core/loader/xnu.c: Likewise.
|
||||
* grub-core/term/gfxterm.c: Likewise.
|
||||
* grub-core/term/serial.c: Likewise.
|
||||
* grub-core/tests/lib/functional_test.c: Likewise.
|
||||
|
||||
2010-09-04 BVK Chaitanya <bvk.groups@gmail.com>
|
||||
|
||||
Multi-line quoted strings support.
|
||||
|
||||
* grub-core/script/lexer.c (append_newline): Removed.
|
||||
(grub_script_lexer_yywrap): Refactored.
|
||||
(grub_script_lexer_init): Refactored.
|
||||
* grub-core/script/yylex.l (yywrap): New function.
|
||||
(grub_lexer_resplit): New function.
|
||||
(grub_lexer_unput): New function.
|
||||
* include/grub/script_sh.h (grub_lexer_param): New members, unput
|
||||
and resplit.
|
||||
* tests/grub_script_echo1.in: Added few more testcases.
|
||||
|
||||
2010-09-04 Vladimir Serbinenko <phcoder@gmail.com>
|
||||
|
||||
* grub-core/kern/misc.c: Don't add abort alias in utils.
|
||||
Reported by: echoline.
|
||||
|
||||
2010-09-03 BVK Chaitanya <bvk.groups@gmail.com>
|
||||
|
||||
Add missing files into "make dist" tarball for other platforms.
|
||||
|
||||
* gentpl.py (script): Use dist_noinst_DATA instead of EXTRA_DIST.
|
||||
* conf/Makefile.common (dist_noinst_DATA): New variable.
|
||||
* conf/Makefile.extra-dist: Added missing make dist files.
|
||||
* grub-core/Makefile.core.def: Likewise.
|
||||
|
||||
2010-09-03 Vladimir Serbinenko <phcoder@gmail.com>
|
||||
|
||||
Compress grub_prefix.
|
||||
|
||||
* grub-core/boot/i386/pc/lnxboot.S: Use
|
||||
GRUB_KERNEL_I386_PC_MULTIBOOT_SIGNATURE.
|
||||
* grub-core/kern/i386/pc/startup.S: Move grub_prefix to compressed part.
|
||||
* include/grub/offsets.h: Rename GRUB_MACHINE_DATA_END to
|
||||
GRUB_MACHINE_PREFIX_END. All users updated.
|
||||
(GRUB_KERNEL_I386_PC_PREFIX): Set to GRUB_KERNEL_I386_PC_RAW_SIZE.
|
||||
(GRUB_KERNEL_I386_PC_PREFIX_END): Set to GRUB_KERNEL_I386_PC_PREFIX
|
||||
+ 0x40.
|
||||
(GRUB_KERNEL_I386_PC_RAW_SIZE): Decrease.
|
||||
* util/grub-mkimage.c (image_target_desc): Change data_end to
|
||||
prefix_end. All users updated.
|
||||
|
||||
2010-09-03 Vladimir Serbinenko <phcoder@gmail.com>
|
||||
|
||||
* grub-core/loader/i386/bsd.c (grub_freebsd_boot): Set %ebp to sane
|
||||
value.
|
||||
(grub_openbsd_boot): Likewise.
|
||||
(grub_netbsd_boot): Likewise.
|
||||
* grub-core/loader/i386/xnu.c (grub_xnu_boot_resume): Likewise.
|
||||
(grub_xnu_boot): Likewise.
|
||||
|
||||
2010-09-02 Vladimir Serbinenko <phcoder@gmail.com>
|
||||
|
||||
* configure.ac: Clean LIBS variable after tests.
|
||||
|
||||
2010-09-02 Colin Watson <cjwatson@ubuntu.com>
|
||||
|
||||
* INSTALL: Document that libdevmapper needs to be 1.02.34 or later.
|
||||
|
||||
2010-09-02 Vladimir Serbinenko <phcoder@gmail.com>
|
||||
|
||||
* configure.ac: Check for dm_log_with_errno_init in libdevmapper and
|
||||
echo if libdevmapper will be used.
|
||||
|
||||
2010-09-02 Ian Turner <Ian.Turner@deshaw.com>
|
||||
|
||||
* grub-core/fs/i386/pc/pxe.c (grub_pxefs_read): Keep the blocksize
|
||||
constant for the same file.
|
||||
|
||||
2010-09-02 Vladimir Serbinenko <phcoder@gmail.com>
|
||||
|
||||
* grub-core/kern/i386/multiboot_mmap.c: Remove leftover include.
|
||||
|
||||
2010-09-02 Colin Watson <cjwatson@ubuntu.com>
|
||||
|
||||
* .bzrignore: Add *.pp, **/.dirstamp, grub-core/*.module, and
|
||||
grub-core/*.pp.
|
||||
|
||||
2010-09-02 Colin Watson <cjwatson@ubuntu.com>
|
||||
|
||||
Zero %ebp and %edi when entering Linux's 32-bit entry point, as
|
||||
required by the boot protocol.
|
||||
|
||||
* include/grub/i386/relocator.h (struct grub_relocator32_state): Add
|
||||
ebp and edi members.
|
||||
* grub-core/lib/i386/relocator.c (grub_relocator_boot): Handle
|
||||
state.ebp and state.edi.
|
||||
* grub-core/lib/i386/relocator32.S (grub_relocator32_start): Set
|
||||
%ebp and %edi according to grub_relocator32_ebp and
|
||||
grub_relocator32_edi respectively.
|
||||
* grub-core/loader/i386/linux.c (grub_linux_boot): Zero state.ebp
|
||||
and state.edi.
|
||||
|
||||
2010-09-02 Vladimir Serbinenko <phcoder@gmail.com>
|
||||
|
||||
Add i386-pc-pxe image target.
|
||||
|
||||
* util/grub-mkimage.c (image_target_desc): New enum value
|
||||
IMAGE_I386_PC_PXE.
|
||||
(image_targets): New target i386-pc-pxe.
|
||||
(generate_image): Handle i386-pc-pxe image.
|
||||
|
||||
2010-09-02 Vladimir Serbinenko <phcoder@gmail.com>
|
||||
|
||||
Fix grub_pxe_scan.
|
||||
|
||||
* grub-core/fs/i386/pc/pxe.c (grub_pxe_pxenv): Put correct type bangpxe.
|
||||
(grub_pxe_scan): Fix types and pxe_rm_entry computation.
|
||||
All users updated.
|
||||
* include/grub/i386/pc/pxe.h (grub_pxe_bangpxe): New struct.
|
||||
(grub_pxe_pxenv): Correct type.
|
||||
|
||||
2010-09-01 Colin Watson <cjwatson@ubuntu.com>
|
||||
|
||||
* NEWS: Document most of the important changes since 1.98.
|
||||
|
||||
2010-09-01 Colin Watson <cjwatson@ubuntu.com>
|
||||
|
||||
* util/grub-mkrescue.in (usage): Tidy up usage output (and hence
|
||||
generated manual page) a little.
|
||||
|
||||
2010-09-01 Colin Watson <cjwatson@ubuntu.com>
|
||||
|
||||
* docs/grub.texi: Add myself as an author.
|
||||
|
||||
2010-09-01 Vladimir Serbinenko <phcoder@gmail.com>
|
||||
|
||||
* Makefile.util.def (libgrub.a): Add missing sunpc.
|
||||
Reported by: Seth Goldberg.
|
||||
|
||||
2010-08-30 Vladimir Serbinenko <phcoder@gmail.com>
|
||||
|
||||
Interrupt wrapping and code simplifications.
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
2008-01-28 Tristan Gingold <gingold@free.fr>
|
||||
2010-01-18 Robert Millan <rmh.grub@aybabtu.com>
|
||||
2010-08-31 Vladimir Serbinenko <phcoder@gmail.com>
|
||||
|
||||
* commands/lsacpi.c: New file.
|
||||
* grub-core/Makefile.core.def (lsacpi): New module.
|
||||
* include/grub/acpi.h (GRUB_ACPI_FADT_SIGNATURE): New definition.
|
||||
(GRUB_ACPI_MADT_SIGNATURE): Likewise.
|
||||
(grub_acpi_madt_entry_header): New struct.
|
||||
(grub_acpi_madt): Likewise.
|
||||
(grub_acpi_madt_entry_interrupt_override): Likewise.
|
||||
(grub_acpi_madt_entry_sapic): Likewise.
|
||||
(grub_acpi_madt_entry_lsapic): Likewise.
|
||||
(grub_acpi_madt_entry_platform_int_source): Likewise.
|
||||
* include/grub/types.h (PRIxGRUB_UINT32_T): New definition.
|
||||
(PRIuGRUB_UINT32_T): Likewise.
|
||||
(PRIxGRUB_UINT64_T): Likewise.
|
2
INSTALL
2
INSTALL
|
@ -21,7 +21,7 @@ configuring the GRUB.
|
|||
|
||||
On GNU/Linux, you also need:
|
||||
|
||||
* libdevmapper (recommended)
|
||||
* libdevmapper 1.02.34 or later (recommended)
|
||||
|
||||
To build grub-emu, you need:
|
||||
|
||||
|
|
14
Makefile.am
14
Makefile.am
|
@ -44,6 +44,20 @@ libgrub_a_init.c: libgrub_a_init.lst $(top_srcdir)/geninit.sh
|
|||
sh $(top_srcdir)/geninit.sh `cat $<` > $@ || (rm -f $@; exit 1)
|
||||
CLEANFILES += libgrub_a_init.c
|
||||
|
||||
# For grub-fstest
|
||||
grub_fstest.pp: $(grub_fstest_SOURCES)
|
||||
$(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(grub_fstest_CPPFLAGS) $(CPPFLAGS) \
|
||||
-D'GRUB_MOD_INIT(x)=@MARKER@x@' $^ > $@ || (rm -f $@; exit 1)
|
||||
CLEANFILES += grub_fstest.pp
|
||||
|
||||
grub_fstest_init.lst: libgrub.pp grub_fstest.pp
|
||||
cat $^ | grep '@MARKER@' | sed 's/@MARKER@\(.*\)@/\1/g' | sort -u > $@ || (rm -f $@; exit 1)
|
||||
CLEANFILES += grub_fstest_init.lst
|
||||
|
||||
grub_fstest_init.c: grub_fstest_init.lst $(top_srcdir)/geninit.sh
|
||||
sh $(top_srcdir)/geninit.sh `cat $<` > $@ || (rm -f $@; exit 1)
|
||||
CLEANFILES += grub_fstest_init.c
|
||||
|
||||
if COND_GRUB_MKFONT
|
||||
if COND_HAVE_FONT_SOURCE
|
||||
grubdata_DATA = unicode.pf2 ascii.pf2 ascii.h widthspec.h
|
||||
|
|
|
@ -23,7 +23,6 @@ library = {
|
|||
common = grub-core/kern/misc.c;
|
||||
common = grub-core/kern/emu/mm.c;
|
||||
common = grub-core/kern/emu/misc.c;
|
||||
common = grub-core/kern/emu/hostfs.c;
|
||||
common = grub-core/kern/emu/getroot.c;
|
||||
common = grub-core/kern/emu/hostdisk.c;
|
||||
|
||||
|
@ -31,7 +30,6 @@ library = {
|
|||
common = grub-core/commands/extcmd.c;
|
||||
common = grub-core/commands/ls.c;
|
||||
common = grub-core/disk/dmraid_nvidia.c;
|
||||
common = grub-core/disk/host.c;
|
||||
common = grub-core/disk/loopback.c;
|
||||
common = grub-core/disk/lvm.c;
|
||||
common = grub-core/disk/mdraid_linux.c;
|
||||
|
@ -43,6 +41,7 @@ library = {
|
|||
common = grub-core/fs/afs.c;
|
||||
common = grub-core/fs/befs_be.c;
|
||||
common = grub-core/fs/befs.c;
|
||||
common = grub-core/fs/btrfs.c;
|
||||
common = grub-core/fs/cpio.c;
|
||||
common = grub-core/fs/ext2.c;
|
||||
common = grub-core/fs/fat.c;
|
||||
|
@ -52,6 +51,7 @@ library = {
|
|||
common = grub-core/fs/iso9660.c;
|
||||
common = grub-core/fs/jfs.c;
|
||||
common = grub-core/fs/minix.c;
|
||||
common = grub-core/fs/minix2.c;
|
||||
common = grub-core/fs/nilfs2.c;
|
||||
common = grub-core/fs/ntfs.c;
|
||||
common = grub-core/fs/ntfscomp.c;
|
||||
|
@ -88,6 +88,7 @@ library = {
|
|||
common = grub-core/partmap/gpt.c;
|
||||
common = grub-core/partmap/msdos.c;
|
||||
common = grub-core/partmap/sun.c;
|
||||
common = grub-core/partmap/sunpc.c;
|
||||
common = grub-core/script/function.c;
|
||||
common = grub-core/script/lexer.c;
|
||||
common = grub-core/script/main.c;
|
||||
|
@ -178,11 +179,13 @@ program = {
|
|||
program = {
|
||||
name = grub-fstest;
|
||||
mansection = 1;
|
||||
common_nodist = grub_fstest_init.c;
|
||||
common = util/grub-fstest.c;
|
||||
common = grub-core/kern/emu/hostfs.c;
|
||||
common = grub-core/disk/host.c;
|
||||
|
||||
ldadd = libgrub.a;
|
||||
ldadd = '$(LIBINTL) $(LIBDEVMAPPER)';
|
||||
condition = COND_GRUB_FSTEST;
|
||||
};
|
||||
|
||||
program = {
|
||||
|
@ -500,6 +503,48 @@ script = {
|
|||
common = tests/grub_script_shift.in;
|
||||
};
|
||||
|
||||
script = {
|
||||
testcase;
|
||||
name = grub_script_blockarg;
|
||||
common = tests/grub_script_blockarg.in;
|
||||
};
|
||||
|
||||
script = {
|
||||
testcase;
|
||||
name = grub_script_setparams;
|
||||
common = tests/grub_script_setparams.in;
|
||||
};
|
||||
|
||||
script = {
|
||||
testcase;
|
||||
name = grub_script_return;
|
||||
common = tests/grub_script_return.in;
|
||||
};
|
||||
|
||||
script = {
|
||||
testcase;
|
||||
name = grub_cmd_regexp;
|
||||
common = tests/grub_cmd_regexp.in;
|
||||
};
|
||||
|
||||
script = {
|
||||
testcase;
|
||||
name = grub_script_expansion;
|
||||
common = tests/grub_script_expansion.in;
|
||||
};
|
||||
|
||||
script = {
|
||||
testcase;
|
||||
name = grub_script_not;
|
||||
common = tests/grub_script_not.in;
|
||||
};
|
||||
|
||||
script = {
|
||||
testcase;
|
||||
name = partmap_test;
|
||||
common = tests/partmap_test.in;
|
||||
};
|
||||
|
||||
program = {
|
||||
testcase;
|
||||
name = example_unit_test;
|
||||
|
|
89
NEWS
89
NEWS
|
@ -1,9 +1,98 @@
|
|||
New in 1.99:
|
||||
|
||||
* New relocator. Allows for more kernel support and more
|
||||
straightforward loader writing.
|
||||
|
||||
* Handle USB pendrives exposed as floppies.
|
||||
|
||||
* New Automake-based build system.
|
||||
|
||||
* Add `sendkey' command (i386-pc only).
|
||||
|
||||
* ZFS support in `grub-install' and `grub-mkconfig'. Note: complete
|
||||
functionality requires external ZFS implementation (available from
|
||||
grub-extras).
|
||||
|
||||
* Support 1.x versions of mdadm metadata.
|
||||
|
||||
* Fix corruption when reading Reiserfs directory entries.
|
||||
|
||||
* Bidirectional text and diacritics support.
|
||||
|
||||
* Skip LVM snapshots.
|
||||
|
||||
* MIPS Yeeloong firmware port.
|
||||
|
||||
* Change grub-mkdevicemap to emit /dev/disk/by-id/ names where possible
|
||||
on GNU/Linux.
|
||||
|
||||
* Add `grub-mkconfig' support for Xen with Linux.
|
||||
|
||||
* Add `grub-mkconfig' support for initrd images on Fedora 13.
|
||||
|
||||
* Support >3GiB and <16MiB RAM in i386-qemu.
|
||||
|
||||
* Add support for Cirrus 5446 and Bochs video cards.
|
||||
|
||||
* Load more appropriate video drivers automatically in `grub-mkconfig'.
|
||||
|
||||
* USB improvements, including hotplugging/hotunplugging, hub support,
|
||||
and USB serial support.
|
||||
|
||||
* AMD Geode CS5536 support.
|
||||
|
||||
* Extensive updates to the Texinfo documentation.
|
||||
|
||||
* Add `grub-probe' support for the btrfs filesystem, permitting / to
|
||||
reside on btrfs as long as /boot is on a filesystem natively supported
|
||||
by GRUB.
|
||||
|
||||
* Handle symbolic links under /dev/mapper on GNU/Linux.
|
||||
|
||||
* Handle installation across multiple partition table types.
|
||||
|
||||
* Add `cmostest' command (i386/x86_64 only).
|
||||
|
||||
* Add support for DM-RAID disk devices on GNU/Linux.
|
||||
|
||||
* Remove `grub-mkisofs'. `grub-mkrescue' now uses GNU xorriso to build
|
||||
CD images.
|
||||
|
||||
* `grub-mkrescue' support for EFI, coreboot, and QEMU platforms.
|
||||
|
||||
* Unify `grub-mkimage' source code across platforms.
|
||||
|
||||
* Fix VGA (as opposed to VBE) video driver, formerly a terminal driver.
|
||||
|
||||
* Add menu hotkey support.
|
||||
|
||||
* Add support for the nilfs2 filesystem.
|
||||
|
||||
* `grub-probe' and `grub-mkconfig' support for NetBSD.
|
||||
|
||||
* Support setting a background image in `grub-mkconfig'.
|
||||
|
||||
* Support multiple terminals in `grub-mkconfig'.
|
||||
|
||||
* Regexp support.
|
||||
|
||||
* MIPS multiboot2 support.
|
||||
|
||||
* Multiboot2 tag support.
|
||||
|
||||
* sunpc partition table support.
|
||||
|
||||
* Add a number of new language features to GRUB script: `for', `while',
|
||||
`until', `elif', function parameters, `break', `continue', and
|
||||
`shift'.
|
||||
|
||||
* Support nested partition tables. GRUB now prefers to name partitions
|
||||
in the form `(hd0,msdos1,bsd1)' rather than `(hd0,1,a)'.
|
||||
|
||||
* Speed up consecutive hostdisk operations on the same device.
|
||||
|
||||
* Compile parts of `grub-emu' as modules.
|
||||
|
||||
New in 1.98 - 2010-03-06:
|
||||
|
||||
* Multiboot on EFI support.
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
# -*- makefile -*-
|
||||
|
||||
CFLAGS_PLATFORM=
|
||||
|
||||
# Platform specific options
|
||||
if COND_i386_pc
|
||||
CFLAGS_PLATFORM = -mrtd -mregparm=3
|
||||
CFLAGS_PLATFORM += -mrtd -mregparm=3
|
||||
endif
|
||||
if COND_i386_efi
|
||||
LDFLAGS_PLATFORM = -melf_i386
|
||||
|
@ -11,21 +13,24 @@ if COND_x86_64_efi
|
|||
LDFLAGS_PLATFORM = -melf_x86_64
|
||||
endif
|
||||
if COND_i386_qemu
|
||||
CFLAGS_PLATFORM = -mrtd -mregparm=3
|
||||
CFLAGS_PLATFORM += -mrtd -mregparm=3
|
||||
endif
|
||||
if COND_i386_coreboot
|
||||
CFLAGS_PLATFORM = -mrtd -mregparm=3
|
||||
CFLAGS_PLATFORM += -mrtd -mregparm=3
|
||||
endif
|
||||
if COND_i386_ieee1275
|
||||
CFLAGS_PLATFORM = -mrtd -mregparm=3
|
||||
CFLAGS_PLATFORM += -mrtd -mregparm=3
|
||||
endif
|
||||
if COND_mips_yeeloong
|
||||
CFLAGS_PLATFORM = -march=mips3 -mexplicit-relocs -mflush-func=grub_cpu_flush_cache
|
||||
CFLAGS_PLATFORM += -march=mips3 -mexplicit-relocs
|
||||
CPPFLAGS_PLATFORM = -DUSE_ASCII_FAILBACK
|
||||
CCASFLAGS_PLATFORM = -march=mips3
|
||||
endif
|
||||
if COND_mips
|
||||
CFLAGS_PLATFORM += -mflush-func=grub_cpu_flush_cache
|
||||
endif
|
||||
if COND_sparc64_ieee1275
|
||||
CFLAGS_PLATFORM = -mno-app-regs
|
||||
CFLAGS_PLATFORM += -mno-app-regs
|
||||
LDFLAGS_PLATFORM = -melf64_sparc -mno-relax
|
||||
endif
|
||||
|
||||
|
@ -115,6 +120,7 @@ pkglib_SCRIPTS =
|
|||
noinst_PROGRAMS =
|
||||
grubconf_SCRIPTS =
|
||||
noinst_LIBRARIES =
|
||||
dist_noinst_DATA =
|
||||
|
||||
TESTS =
|
||||
EXTRA_DIST =
|
||||
|
|
|
@ -5,6 +5,11 @@ EXTRA_DIST += gentpl.py
|
|||
EXTRA_DIST += Makefile.tpl
|
||||
EXTRA_DIST += Makefile.util.def
|
||||
|
||||
EXTRA_DIST += unicode
|
||||
|
||||
EXTRA_DIST += util/import_gcry.py
|
||||
EXTRA_DIST += util/import_unicode.py
|
||||
|
||||
EXTRA_DIST += docs/man
|
||||
EXTRA_DIST += docs/grub.cfg
|
||||
|
||||
|
@ -26,8 +31,8 @@ EXTRA_DIST += grub-core/genterminallist.sh
|
|||
EXTRA_DIST += grub-core/genparttoollist.sh
|
||||
EXTRA_DIST += grub-core/genemuinitheader.sh
|
||||
|
||||
EXTRA_DIST += grub-core/lib/libgcrypt/cipher
|
||||
EXTRA_DIST += $(shell find $(top_srcdir)/include -name '*.h')
|
||||
EXTRA_DIST += $(shell find $(top_srcdir)/grub-core/gnulib -name '*.h')
|
||||
EXTRA_DIST += $(shell find $(top_srcdir)/grub-core/efiemu -name '*.h')
|
||||
EXTRA_DIST += $(shell find $(top_srcdir)/grub-core/lib/posix_wrap -name '*.h')
|
||||
EXTRA_DIST += $(shell find $(top_srcdir)/grub-core/lib/libgcrypt_wrap -name '*.h')
|
||||
EXTRA_DIST += $(shell find $(top_srcdir)/grub-core/lib -name '*.h')
|
||||
|
|
71
configure.ac
71
configure.ac
|
@ -176,6 +176,19 @@ AC_SUBST(host_kernel)
|
|||
AC_SUBST(target_cpu)
|
||||
AC_SUBST(platform)
|
||||
|
||||
# Define default variables
|
||||
case "$host_os" in
|
||||
netbsd* | openbsd*)
|
||||
# Because /boot is used for the boot block in NetBSD and OpenBSD,
|
||||
bootdirname='' ;;
|
||||
*) bootdirname='boot' ;;
|
||||
esac
|
||||
bootdirname=`echo "$bootdirname" | sed "$program_transform_name"`
|
||||
AC_SUBST(bootdirname)
|
||||
|
||||
grubdirname=`echo "$PACKAGE" | sed "$program_transform_name"`
|
||||
AC_SUBST(grubdirname)
|
||||
|
||||
#
|
||||
# Checks for build programs.
|
||||
#
|
||||
|
@ -264,8 +277,16 @@ else
|
|||
fi
|
||||
|
||||
# Check for functions and headers.
|
||||
AC_CHECK_FUNCS(posix_memalign memalign asprintf vasprintf)
|
||||
AC_CHECK_HEADERS(libzfs.h libnvpair.h sys/param.h sys/mount.h)
|
||||
AC_CHECK_FUNCS(posix_memalign memalign asprintf vasprintf getextmntent)
|
||||
AC_CHECK_HEADERS(libzfs.h libnvpair.h sys/param.h sys/mount.h sys/mnttab.h sys/mkdev.h)
|
||||
|
||||
AC_CHECK_MEMBERS([struct statfs.f_fstypename],,,[$ac_includes_default
|
||||
#include <sys/param.h>
|
||||
#include <sys/mount.h>])
|
||||
|
||||
AC_CHECK_MEMBERS([struct statfs.f_mntfromname],,,[$ac_includes_default
|
||||
#include <sys/param.h>
|
||||
#include <sys/mount.h>])
|
||||
|
||||
# For opendisk() and getrawpartition() on NetBSD.
|
||||
# Used in util/deviceiter.c and in util/hostdisk.c.
|
||||
|
@ -762,19 +783,6 @@ AC_SUBST([enable_grub_emu_usb])
|
|||
AC_SUBST([enable_grub_emu_pci])
|
||||
fi
|
||||
|
||||
AC_ARG_ENABLE([grub-fstest],
|
||||
[AS_HELP_STRING([--enable-grub-fstest],
|
||||
[build and install the `grub-fstest' debugging utility (default=guessed)])])
|
||||
if test x"$enable_grub_fstest" = xno ; then
|
||||
grub_fstest_excuse="explicitly disabled"
|
||||
fi
|
||||
if test x"$grub_fstest_excuse" = x ; then
|
||||
enable_grub_fstest=yes
|
||||
else
|
||||
enable_grub_fstest=no
|
||||
fi
|
||||
AC_SUBST([enable_grub_fstest])
|
||||
|
||||
AC_ARG_ENABLE([grub-mkfont],
|
||||
[AS_HELP_STRING([--enable-grub-mkfont],
|
||||
[build and install the `grub-mkfont' utility (default=guessed)])])
|
||||
|
@ -822,12 +830,23 @@ fi
|
|||
|
||||
if test x"$device_mapper_excuse" = x ; then
|
||||
# Check for device-mapper library.
|
||||
AC_CHECK_LIB([devmapper], [dm_task_create],
|
||||
[LIBDEVMAPPER="-ldevmapper"
|
||||
AC_DEFINE([HAVE_DEVICE_MAPPER], [1],
|
||||
[Define to 1 if you have the devmapper library.])],
|
||||
AC_CHECK_LIB([devmapper], [dm_task_create], [],
|
||||
[device_mapper_excuse="need devmapper library"])
|
||||
fi
|
||||
|
||||
if test x"$device_mapper_excuse" = x ; then
|
||||
# Check for device-mapper library.
|
||||
AC_CHECK_LIB([devmapper], [dm_log_with_errno_init],
|
||||
[],
|
||||
[device_mapper_excuse="need devmapper library"])
|
||||
fi
|
||||
|
||||
if test x"$device_mapper_excuse" = x ; then
|
||||
LIBDEVMAPPER="-ldevmapper";
|
||||
AC_DEFINE([HAVE_DEVICE_MAPPER], [1],
|
||||
[Define to 1 if you have the devmapper library.])
|
||||
fi
|
||||
|
||||
AC_SUBST([LIBDEVMAPPER])
|
||||
|
||||
AC_CHECK_LIB([zfs], [libzfs_init],
|
||||
|
@ -842,6 +861,8 @@ AC_CHECK_LIB([nvpair], [nvlist_print],
|
|||
[Define to 1 if you have the NVPAIR library.])],)
|
||||
AC_SUBST([LIBNVPAIR])
|
||||
|
||||
LIBS=""
|
||||
|
||||
pkglibrootdir='$(libdir)'/`echo $PACKAGE | sed "$program_transform_name"`
|
||||
AC_SUBST(pkglibrootdir)
|
||||
|
||||
|
@ -879,6 +900,7 @@ AM_CONDITIONAL([COND_mips_yeeloong], [test x$target_cpu = xmips -a x$platform =
|
|||
AM_CONDITIONAL([COND_mips_qemu_mips], [test x$target_cpu = xmips -a x$platform = xqemu_mips])
|
||||
AM_CONDITIONAL([COND_sparc64_ieee1275], [test x$target_cpu = xsparc64 -a x$platform = xieee1275])
|
||||
AM_CONDITIONAL([COND_powerpc_ieee1275], [test x$target_cpu = xpowerpc -a x$platform = xieee1275])
|
||||
AM_CONDITIONAL([COND_mips], [test x$target_cpu = xmips])
|
||||
|
||||
AM_CONDITIONAL([COND_HOST_HURD], [test x$host_kernel = xhurd])
|
||||
AM_CONDITIONAL([COND_HOST_LINUX], [test x$host_kernel = xlinux])
|
||||
|
@ -892,7 +914,6 @@ AM_CONDITIONAL([COND_GRUB_EMU_SDL], [test x$enable_grub_emu_sdl = xyes])
|
|||
AM_CONDITIONAL([COND_GRUB_EMU_PCI], [test x$enable_grub_emu_pci = xyes])
|
||||
AM_CONDITIONAL([COND_GRUB_MKFONT], [test x$enable_grub_mkfont = xyes])
|
||||
AM_CONDITIONAL([COND_HAVE_FONT_SOURCE], [test x$FONT_SOURCE != x])
|
||||
AM_CONDITIONAL([COND_GRUB_FSTEST], [test x$enable_grub_fstest = xyes])
|
||||
AM_CONDITIONAL([COND_GRUB_PE2ELF], [test x$TARGET_OBJ2ELF != x])
|
||||
AM_CONDITIONAL([COND_APPLE_CC], [test x$TARGET_APPLE_CC = x1])
|
||||
AM_CONDITIONAL([COND_ENABLE_EFIEMU], [test x$enable_efiemu = xyes])
|
||||
|
@ -942,6 +963,11 @@ else
|
|||
echo PCI support for grub-emu: No "($grub_emu_pci_excuse)"
|
||||
fi
|
||||
fi
|
||||
if test x"$device_mapper_excuse" = x ; then
|
||||
echo With devmapper support: Yes
|
||||
else
|
||||
echo With devmapper support: No "($device_mapper_excuse)"
|
||||
fi
|
||||
if [ x"$enable_mm_debug" = xyes ]; then
|
||||
echo With memory debugging: Yes
|
||||
else
|
||||
|
@ -952,11 +978,6 @@ echo efiemu runtime: Yes
|
|||
else
|
||||
echo efiemu runtime: No "($efiemu_excuse)"
|
||||
fi
|
||||
if [ x"$grub_fstest_excuse" = x ]; then
|
||||
echo grub-fstest: Yes
|
||||
else
|
||||
echo grub-fstest: No "($grub_fstest_excuse)"
|
||||
fi
|
||||
if [ x"$grub_mkfont_excuse" = x ]; then
|
||||
echo grub-mkfont: Yes
|
||||
else
|
||||
|
|
427
docs/grub.texi
427
docs/grub.texi
|
@ -46,6 +46,8 @@ Invariant Sections.
|
|||
@subtitle The GRand Unified Bootloader, version @value{VERSION}, @value{UPDATED}.
|
||||
@author Gordon Matzigkeit
|
||||
@author Yoshinori K. Okuji
|
||||
@author Colin Watson
|
||||
@author Colin D. Bennett
|
||||
@c The following two commands start the copyright page.
|
||||
@page
|
||||
@vskip 0pt plus 1filll
|
||||
|
@ -77,6 +79,7 @@ This edition documents version @value{VERSION}.
|
|||
* Installation:: Installing GRUB on your drive
|
||||
* Booting:: How to boot different operating systems
|
||||
* Configuration:: Writing your own configuration file
|
||||
* Theme file format:: Format of GRUB theme files
|
||||
* Network:: Downloading OS images from a network
|
||||
* Serial terminal:: Using GRUB via a serial line
|
||||
* Vendor power-on keys:: Changing GRUB behaviour on vendor power-on keys
|
||||
|
@ -964,7 +967,6 @@ need to write the whole thing by hand.
|
|||
* Simple configuration:: Recommended for most users
|
||||
* Shell-like scripting:: For power users and developers
|
||||
* Embedded configuration:: Embedding a configuration file into GRUB
|
||||
* Themes:: Graphical menu themes
|
||||
@end menu
|
||||
|
||||
|
||||
|
@ -1126,7 +1128,6 @@ The image will be scaled if necessary to fit the screen.
|
|||
|
||||
@item GRUB_THEME
|
||||
Set a theme for use with the @samp{gfxterm} graphical terminal.
|
||||
@xref{Themes}.
|
||||
|
||||
@item GRUB_GFXPAYLOAD_LINUX
|
||||
Set to @samp{text} to force the Linux kernel to boot in normal text mode,
|
||||
|
@ -1226,8 +1227,10 @@ The @samp{$} character retains its special meaning within double quotes.
|
|||
The backslash retains its special meaning only when followed by one of the
|
||||
following characters: @samp{$}, @samp{"}, @samp{\}, or newline. A
|
||||
backslash-newline pair is treated as a line continuation (that is, it is
|
||||
removed from the input stream and effectively ignored). A double quote may
|
||||
be quoted within double quotes by preceding it with a backslash.
|
||||
removed from the input stream and effectively ignored@footnote{Currently a
|
||||
backslash-newline pair within a variable name is not handled properly, so
|
||||
use this feature with some care.}). A double quote may be quoted within
|
||||
double quotes by preceding it with a backslash.
|
||||
|
||||
@heading Variable expansion
|
||||
|
||||
|
@ -1239,11 +1242,15 @@ which could be interpreted as part of the name.
|
|||
Normal variable names begin with an alphabetic character, followed by zero
|
||||
or more alphanumeric characters.
|
||||
|
||||
Positional variable names consist of one or more digits. These are reserved
|
||||
for future expansion.
|
||||
Positional variable names consist of one or more digits. They represent
|
||||
parameters passed to function calls, with @samp{$1} representing the first
|
||||
parameter, and so on.
|
||||
|
||||
The special variable name @samp{?} expands to the exit status of the most
|
||||
recently executed command.
|
||||
recently executed command. When positional variable names are active, other
|
||||
special variable names @samp{@@}, @samp{*} and @samp{#} are defined and they
|
||||
expand to all positional parameters with necessary quoting, positional
|
||||
parameters without any quoting, and positional parameter count respectively.
|
||||
|
||||
@heading Comments
|
||||
|
||||
|
@ -1304,6 +1311,45 @@ the body.
|
|||
@xref{menuentry}.
|
||||
@end table
|
||||
|
||||
@heading Built-in Commands
|
||||
|
||||
Some built-in commands are also provided by GRUB script to help script
|
||||
writers perform actions that are otherwise not possible. For example, these
|
||||
include commands to jump out of a loop without fully completing it, etc.
|
||||
|
||||
@table @asis
|
||||
@item break [@code{n}]
|
||||
Exit from within a @code{for}, @code{while}, or @code{until} loop. If
|
||||
@code{n} is specified, break @code{n} levels. @code{n} must be greater than
|
||||
or equal to 1. If @code{n} is greater than the number of enclosing loops,
|
||||
all enclosing loops are exited. The return value is 0 unless @code{n} is
|
||||
not greater than or equal to 1.
|
||||
|
||||
@item continue [@code{n}]
|
||||
Resume the next iteration of the enclosing @code{for}, @code{while} or
|
||||
@code{until} loop. If @code{n} is specified, resume at the @code{n}th
|
||||
enclosing loop. @code{n} must be greater than or equal to 1. If @code{n}
|
||||
is greater than the number of enclosing loops, the last enclosing loop (the
|
||||
@dfn{top-level} loop) is resumed. The return value is 0 unless @code{n} is
|
||||
not greater than or equal to 1.
|
||||
|
||||
@item return [@code{n}]
|
||||
Causes a function to exit with the return value specified by @code{n}. If
|
||||
@code{n} is omitted, the return status is that of the last command executed
|
||||
in the function body. If used outside a function the return status is
|
||||
false.
|
||||
|
||||
@item shift [@code{n}]
|
||||
The positional parameters from @code{n}+1 @dots{} are renamed to
|
||||
@code{$1}@dots{}. Parameters represented by the numbers @code{$#} down to
|
||||
@code{$#}-@code{n}+1 are unset. @code{n} must be a non-negative number less
|
||||
than or equal to @code{$#}. If @code{n} is 0, no parameters are changed.
|
||||
If @code{n} is not given, it is assumed to be 1. If @code{n} is greater
|
||||
than @code{$#}, the positional parameters are not changed. The return
|
||||
status is greater than zero if @code{n} is greater than @code{$#} or less
|
||||
than zero; otherwise 0.
|
||||
|
||||
@end table
|
||||
|
||||
@node Embedded configuration
|
||||
@section Embedding a configuration file into GRUB
|
||||
|
@ -1372,9 +1418,372 @@ fi
|
|||
The embedded configuration file may not contain menu entries directly, but
|
||||
may only read them from elsewhere using @command{configfile}.
|
||||
|
||||
@node Theme file format
|
||||
@chapter Theme file format
|
||||
@section Introduction
|
||||
The GRUB graphical menu supports themes that can customize the layout and
|
||||
appearance of the GRUB boot menu. The theme is configured through a plain
|
||||
text file that specifies the layout of the various GUI components (including
|
||||
the boot menu, timeout progress bar, and text messages) as well as the
|
||||
appearance using colors, fonts, and images. Example is available in docs/example_theme.txt
|
||||
|
||||
@section Theme Elements
|
||||
@subsection Colors
|
||||
|
||||
Colors can be specified in several ways:
|
||||
|
||||
@itemize
|
||||
@item HTML-style ``#RRGGBB'' or ``#RGB'' format, where *R*, *G*, and *B* are hexadecimal digits (e.g., ``#8899FF'')
|
||||
@item as comma-separated decimal RGB values (e.g., ``128, 128, 255'')
|
||||
@item with ``SVG 1.0 color names'' (e.g., ``cornflowerblue'') which must be specified in lowercase.
|
||||
@end itemize
|
||||
@subsection Fonts
|
||||
The fonts GRUB uses ``PFF2 font format'' bitmap fonts. Fonts are specified
|
||||
with full font names. Currently there is no
|
||||
provision for a preference list of fonts, or deriving one font from another.
|
||||
Fonts are loaded with the ``loadfont'' command in GRUB. To see the list of
|
||||
loaded fonts, execute the ``lsfonts'' command. If there are too many fonts to
|
||||
fit on screen, do ``set pager=1'' before executing ``lsfonts''.
|
||||
|
||||
|
||||
@subsection Progress Bar
|
||||
|
||||
@float Figure, Pixmap-styled progress bar
|
||||
@c @image{Theme_progress_bar,,,,.png}
|
||||
@end float
|
||||
|
||||
@float Figure, Plain progress bar, drawn with solid color.
|
||||
@c @image{Theme_progress_bar_filled,,,,.png}
|
||||
@end float
|
||||
|
||||
Progress bars are used to display the remaining time before GRUB boots the
|
||||
default menu entry. To create a progress bar that will display the remaining
|
||||
time before automatic boot, simply create a ``progress_bar'' component with
|
||||
the id ``__timeout__''. This indicates to GRUB that the progress bar should
|
||||
be updated as time passes, and it should be made invisible if the countdown to
|
||||
automatic boot is interrupted by the user.
|
||||
|
||||
Progress bars may optionally have text displayed on them. This is controlled
|
||||
through the ``show_text'' property, which can be set to either ``true'' or
|
||||
``false'' to control whether text is displayed. When GRUB is counting down to
|
||||
automatic boot, the text informs the user of the number of seconds remaining.
|
||||
|
||||
|
||||
@subsection Circular Progress Indicator
|
||||
|
||||
@c @image{Theme_circular_progress,,,,.png}
|
||||
|
||||
The circular progress indicator functions similarly to the progress bar. When
|
||||
given an id of ``__timeout__'', GRUB updates the circular progress indicator's
|
||||
value to indicate the time remaining. For the circular progress indicator,
|
||||
there are two images used to render it: the *center* image, and the *tick*
|
||||
image. The center image is rendered in the center of the component, while the
|
||||
tick image is used to render each mark along the circumference of the
|
||||
indicator.
|
||||
|
||||
|
||||
@subsection Labels
|
||||
|
||||
Text labels can be placed on the boot screen. The font, color, and horizontal
|
||||
alignment can be specified for labels. If a label is given the id
|
||||
``__timeout__'', then the ``text'' property for that label is also updated
|
||||
with a message informing the user of the number of seconds remaining until
|
||||
automatic boot. This is useful in case you want the text displayed somewhere
|
||||
else instead of directly on the progress bar.
|
||||
|
||||
|
||||
@subsection Boot Menu
|
||||
|
||||
@c @image{Theme_boot_menu,,,,.png}
|
||||
|
||||
The boot menu where GRUB displays the menu entries from the ``grub.cfg'' file.
|
||||
It is a list of items, where each item has a title and an optional icon. The
|
||||
icon is selected based on the *classes* specified for the menu entry. If
|
||||
there is a PNG file named ``myclass.png'' in the ``grub/themes/icons''
|
||||
directory, it will be displayed for items which have the class *myclass*. The
|
||||
boot menu can be customized in several ways, such as the font and color used
|
||||
for the menu entry title, and by specifying styled boxes for the menu itself
|
||||
and for the selected item highlight.
|
||||
|
||||
|
||||
@subsection Styled Boxes
|
||||
|
||||
One of the most important features for customizing the layout is the use of
|
||||
*styled boxes*. A styled box is composed of 9 rectangular (and potentially
|
||||
empty) regions, which are used to seamlessly draw the styled box on screen:
|
||||
|
||||
@multitable @columnfractions 0.3 0.3 0.3
|
||||
@item Northwest (nw) @tab North (n) @tab Northeast (ne)
|
||||
@item West (w) @tab Center (c) @tab East (e)
|
||||
@item Southwest (sw) @tab South (s) @tab Southeast (se)
|
||||
@end multitable
|
||||
|
||||
To support any size of box on screen, the center slice and the slices for the
|
||||
top, bottom, and sides are all scaled to the correct size for the component on
|
||||
screen, using the following rules:
|
||||
|
||||
@enumerate
|
||||
@item The edge slices (north, south, east, and west) are scaled in the direction of the edge they are adjacent to. For instance, the west slice is scaled vertically.
|
||||
@item The corner slices (northwest, northeast, southeast, and southwest) are not scaled.
|
||||
@item The center slice is scaled to fill the remaining space in the middle.
|
||||
@end enumerate
|
||||
|
||||
As an example of how an image might be sliced up, consider the styled box
|
||||
used for a terminal view.
|
||||
|
||||
@float Figure, An example of the slices (in red) used for a terminal window. This drawing was created and sliced in Inkscape_, as the next section explains.
|
||||
@c @image{Box_slice_example_terminal,,,,.png}
|
||||
@end float
|
||||
|
||||
@subsection Creating Styled Box Images
|
||||
|
||||
The Inkscape_ scalable vector graphics editor is a very useful tool for
|
||||
creating styled box images. One process that works well for slicing a drawing
|
||||
into the necessary image slices is:
|
||||
|
||||
@enumerate
|
||||
@item Create or open the drawing you'd like use.
|
||||
@item Create a new layer on the top of the layer stack. Make it visible. Select this layer as the current layer.
|
||||
@item Draw 9 rectangles on your drawing where you'd like the slices to be. Clear the fill option, and set the stroke to 1 pixel wide solid stroke. The corners of the slices must meet precisely; if it is off by a single pixel, it will probably be evident when the styled box is rendered in the GRUB menu. You should probably go to File | Document Properties | Grids and enable a grid or create a guide (click on one of the rulers next to the drawing and drag over the drawing; release the mouse button to place the guide) to help place the rectangles precisely.
|
||||
@item Right click on the center slice rectangle and choose Object Properties. Change the "Id" to ``slice_c`` and click Set. Repeat this for the remaining 8 rectangles, giving them Id values of ``slice_n``, ``slice_ne``, ``slice_e``, and so on according to the location.
|
||||
@item Save the drawing.
|
||||
@item Select all the slice rectangles. With the slice layer selected, you can simply press Ctrl+A to select all rectangles. The status bar should indicate that 9 rectangles are selected.
|
||||
@item Click the layer hide icon for the slice layer in the layer palette. The rectangles will remain selected, even though they are hidden.
|
||||
@item Choose File | Export Bitmap and check the *Batch export 9 selected objects* box. Make sure that *Hide all except selected* is unchecked. click *Export*. This will create PNG files in the same directory as the drawing, named after the slices. These can now be used for a styled box in a GRUB theme.
|
||||
@end enumerate
|
||||
|
||||
@section Theme File Manual
|
||||
|
||||
The theme file is a plain text file. Lines that begin with ``#`` are ignored
|
||||
and considered comments. (Note: This may not be the case if the previous line
|
||||
ended where a value was expected.)
|
||||
|
||||
The theme file contains two types of statements:
|
||||
@enumerate
|
||||
@item Global properties.
|
||||
@item Component construction.
|
||||
@end enumerate
|
||||
|
||||
@subsection Global Properties
|
||||
|
||||
@subsection Format
|
||||
|
||||
Global properties are specified with the simple format:
|
||||
@itemize
|
||||
@item name1: value1
|
||||
@item name2: "value which may contain spaces"
|
||||
@item name3: #88F
|
||||
@end itemize
|
||||
|
||||
In this example, name3 is assigned a color value.
|
||||
|
||||
|
||||
@subsection Global Property List
|
||||
|
||||
@multitable @columnfractions 0.3 0.6
|
||||
@item title-text @tab Specifies the text to display at the top center of the screen as a title.
|
||||
@item title-font @tab Defines the font used for the title message at the top of the screen.
|
||||
@item title-color @tab Defines the color of the title message.
|
||||
@item message-font @tab Defines the font used for messages, such as when GRUB is unable to automatically boot an entry.
|
||||
@item message-color @tab Defines the color of the message text.
|
||||
@item message-bg-color @tab Defines the background color of the message text area.
|
||||
@item desktop-image @tab Specifies the image to use as the background. It will be scaled to fit the screen size.
|
||||
@item desktop-color @tab Specifies the color for the background if *desktop-image* is not specified.
|
||||
@item terminal-box @tab Specifies the file name pattern for the styled box slices used for the command line terminal window. For example, ``terminal-box: terminal_*.png'' will use the images ``terminal_c.png`` as the center area, ``terminal_n.png`` as the north (top) edge, ``terminal_nw.png`` as the northwest (upper left) corner, and so on. If the image for any slice is not found, it will simply be left empty.
|
||||
@end multitable
|
||||
|
||||
|
||||
@subsection Component Construction
|
||||
|
||||
Greater customizability comes is provided by components. A tree of components
|
||||
forms the user interface. *Containers* are components that can contain other
|
||||
components, and there is always a single root component which is an instance
|
||||
of a *canvas* container.
|
||||
|
||||
Components are created in the theme file by prefixing the type of component
|
||||
with a '+' sign:
|
||||
|
||||
@code{ + label @{ text="GRUB" font="aqui 11" color="#8FF" @} }
|
||||
|
||||
properties of a component are specified as "name = value" (whitespace
|
||||
surrounding tokens is optional and is ignored) where *value* may be:
|
||||
@itemize
|
||||
@item a single word (e.g., ``align = center``, ``color = #FF8080``),
|
||||
@item a quoted string (e.g., ``text = "Hello, World!"``), or
|
||||
@item a tuple (e.g., ``preferred_size = (120, 80)``).
|
||||
@end itemize
|
||||
|
||||
@subsection Component List
|
||||
|
||||
The following is a list of the components and the properties they support.
|
||||
|
||||
@itemize
|
||||
@item label
|
||||
A label displays a line of text.
|
||||
|
||||
Properties:
|
||||
@multitable @columnfractions 0.2 0.7
|
||||
@item text @tab The text to display.
|
||||
@item font @tab The font to use for text display.
|
||||
@item color @tab The color of the text.
|
||||
@item align @tab The horizontal alignment of the text within the component. Options are ``left``, ``center``, and ``right``.
|
||||
@end multitable
|
||||
|
||||
@item image
|
||||
A component that displays an image. The image is scaled to fit the
|
||||
component, although the preferred size defaults to the image's original
|
||||
size unless the ``preferred_size`` property is explicitly set.
|
||||
|
||||
Properties:
|
||||
|
||||
@multitable @columnfractions 0.2 0.7
|
||||
@item file @tab The full path to the image file to load.
|
||||
@end multitable
|
||||
|
||||
@item progress_bar
|
||||
Displays a horizontally oriented progress bar. It can be rendered using
|
||||
simple solid filled rectangles, or using a pair of pixmap styled boxes.
|
||||
|
||||
Properties:
|
||||
|
||||
@multitable @columnfractions 0.2 0.7
|
||||
@item fg_color @tab The foreground color for plain solid color rendering.
|
||||
@item bg_color @tab The background color for plain solid color rendering.
|
||||
@item border_color @tab The border color for plain solid color rendering.
|
||||
@item text_color @tab The text color.
|
||||
@item show_text @tab Boolean value indicating whether or not text should be displayed on the progress bar. If set to *false*, then no text will be displayed on the bar. If set to any other value, text will be displayed on the bar.
|
||||
@item bar_style @tab The styled box specification for the frame of the progress bar. Example: ``progress_frame_*.png``
|
||||
@item highlight_style @tab The styled box specification for the highlighted region of the progress bar. This box will be used to paint just the highlighted region of the bar, and will be increased in size as the bar nears completion. Example: ``progress_hl_*.png``.
|
||||
@item text @tab The text to display on the progress bar. If the progress bar's ID is set to ``__timeout__``, then GRUB will updated this property with an informative message as the timeout approaches.
|
||||
@item value @tab The progress bar current value. Normally not set manually.
|
||||
@item start @tab The progress bar start value. Normally not set manually.
|
||||
@item end @tab The progress bar end value. Normally not set manually.
|
||||
@end multitable
|
||||
|
||||
@item circular_progress
|
||||
Displays a circular progress indicator. The appearance of this component
|
||||
is determined by two images: the *center* image and the *tick* image. The
|
||||
center image is generally larger and will be drawn in the center of the
|
||||
component. Around the circumference of a circle within the component, the
|
||||
tick image will be drawn a certain number of times, depending on the
|
||||
properties of the component.
|
||||
|
||||
Properties:
|
||||
|
||||
@multitable @columnfractions 0.3 0.6
|
||||
@item center_bitmap
|
||||
@tab The file name of the image to draw in the center of the component.
|
||||
@item tick_bitmap
|
||||
@tab The file name of the image to draw for the tick marks.
|
||||
@item num_ticks
|
||||
@tab The number of ticks that make up a full circle.
|
||||
@item ticks_disappear
|
||||
@tab Boolean value indicating whether tick marks should progressively appear,
|
||||
or progressively disappear as *value* approaches *end*. Specify
|
||||
``true`` or ``false``.
|
||||
@item value
|
||||
@tab The progress indicator current value. Normally not set manually.
|
||||
@item start
|
||||
@tab The progress indicator start value. Normally not set manually.
|
||||
@item end
|
||||
@tab The progress indicator end value. Normally not set manually.
|
||||
@end multitable
|
||||
@item boot_menu
|
||||
Displays the GRUB boot menu. It allows selecting items and executing them.
|
||||
|
||||
Properties:
|
||||
|
||||
@multitable @columnfractions 0.4 0.5
|
||||
@item item_font
|
||||
@tab The font to use for the menu item titles.
|
||||
@item selected_item_font
|
||||
@tab The font to use for the selected menu item, or ``inherit`` (the default)
|
||||
to use ``item_font`` for the selected menu item as well.
|
||||
@item item_color
|
||||
@tab The color to use for the menu item titles.
|
||||
@item selected_item_color
|
||||
@tab The color to use for the selected menu item, or ``inherit`` (the default)
|
||||
to use ``item_color`` for the selected menu item as well.
|
||||
@item icon_width
|
||||
@tab The width of menu item icons. Icons are scaled to the specified size.
|
||||
@item icon_height
|
||||
@tab The height of menu item icons.
|
||||
@item item_height
|
||||
@tab The height of each menu item in pixels.
|
||||
@item item_padding
|
||||
@tab The amount of space in pixels to leave on each side of the menu item
|
||||
contents.
|
||||
@item item_icon_space
|
||||
@tab The space between an item's icon and the title text, in pixels.
|
||||
@item item_spacing
|
||||
@tab The amount of space to leave between menu items, in pixels.
|
||||
@item menu_pixmap_style
|
||||
@tab The image file pattern for the menu frame styled box.
|
||||
Example: ``menu_*.png`` (this will use images such as ``menu_c.png``,
|
||||
``menu_w.png``, `menu_nw.png``, etc.)
|
||||
@item selected_item_pixmap_style
|
||||
@tab The image file pattern for the selected item highlight styled box.
|
||||
@item scrollbar
|
||||
@tab Boolean value indicating whether the scroll bar should be drawn if the
|
||||
frame and thumb styled boxes are configured.
|
||||
@item scrollbar_frame
|
||||
@tab The image file pattern for the entire scroll bar.
|
||||
Example: ``scrollbar_*.png``
|
||||
@item scrollbar_thumb
|
||||
@tab The image file pattern for the scroll bar thumb (the part of the scroll
|
||||
bar that moves as scrolling occurs).
|
||||
Example: ``scrollbar_thumb_*.png``
|
||||
@item max_items_shown
|
||||
@tab The maximum number of items to show on the menu. If there are more than
|
||||
*max_items_shown* items in the menu, the list will scroll to make all
|
||||
items accessible.
|
||||
@end multitable
|
||||
|
||||
@item canvas
|
||||
Canvas is a container that allows manual placement of components within it.
|
||||
It does not alter the positions of its child components. It assigns all
|
||||
child components their preferred sizes.
|
||||
|
||||
@item hbox
|
||||
The *hbox* container lays out its children from left to right, giving each
|
||||
one its preferred width. The height of each child is set to the maximum of
|
||||
the preferred heights of all children.
|
||||
|
||||
@item vbox
|
||||
The *vbox* container lays out its children from top to bottom, giving each
|
||||
one its preferred height. The width of each child is set to the maximum of
|
||||
the preferred widths of all children.
|
||||
@end itemize
|
||||
|
||||
|
||||
@subsection Common properties
|
||||
|
||||
The following properties are supported by all components:
|
||||
@table @samp
|
||||
@item left
|
||||
The distance from the left border of container to left border of the object in either of three formats:
|
||||
@multitable @columnfractions 0.2 0.7
|
||||
@item x @tab Value in pixels
|
||||
@item p% @tab Percentage
|
||||
@item p%+x @tab mixture of both
|
||||
@end multitable
|
||||
@item top
|
||||
The distance from the left border of container to left border of the object in same format.
|
||||
@item width
|
||||
The width of object in same format.
|
||||
@item height
|
||||
The height of object in same format.
|
||||
@item id
|
||||
The identifier for the component. This can be any arbitrary string.
|
||||
The ID can be used by scripts to refer to various components in the GUI
|
||||
component tree. Currently, there is one special ID value that GRUB
|
||||
recognizes:
|
||||
|
||||
@multitable @columnfractions 0.2 0.7
|
||||
@item ``__timeout__`` @tab Any component with this ID will have its *text*, *start*, *end*, *value*, and *visible* properties set by GRUB when it is counting down to an automatic boot of the default menu entry.
|
||||
@end multitable
|
||||
@end table
|
||||
|
||||
@node Themes
|
||||
@section Graphical menu themes
|
||||
|
||||
|
||||
@node Network
|
||||
|
|
|
@ -478,7 +478,7 @@ chmod a+x [+ name +]
|
|||
""")
|
||||
|
||||
r += gvar_add("CLEANFILES", "[+ name +]")
|
||||
r += gvar_add("EXTRA_DIST", platform_sources(platform))
|
||||
r += gvar_add("dist_noinst_DATA", platform_sources(platform))
|
||||
return r
|
||||
|
||||
def module_rules():
|
||||
|
|
|
@ -74,6 +74,7 @@ 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/boot.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/libgcc.h
|
||||
|
||||
if COND_i386_pc
|
||||
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/memory.h
|
||||
|
@ -132,7 +133,6 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/font.h
|
|||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/bitmap_scale.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/bufio.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/pci.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/libgcc.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/cs5536.h
|
||||
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/pci.h
|
||||
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/serial.h
|
||||
|
@ -140,11 +140,9 @@ endif
|
|||
|
||||
if COND_powerpc_ieee1275
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ieee1275/ieee1275.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/libgcc.h
|
||||
endif
|
||||
|
||||
if COND_sparc64_ieee1275
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/libgcc.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ieee1275/ieee1275.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/sparc64/ieee1275/ieee1275.h
|
||||
endif
|
||||
|
|
|
@ -137,6 +137,7 @@ kernel = {
|
|||
mips_yeeloong = term/at_keyboard.c;
|
||||
mips_yeeloong = term/serial.c;
|
||||
mips_yeeloong = video/sm712.c;
|
||||
extra_dist = video/sm712_init.c;
|
||||
|
||||
powerpc_ieee1275 = kern/ieee1275/init.c;
|
||||
powerpc_ieee1275 = kern/powerpc/cache.S;
|
||||
|
@ -394,6 +395,7 @@ module = {
|
|||
module = {
|
||||
name = regexp;
|
||||
common = commands/regexp.c;
|
||||
common = commands/wildcard.c;
|
||||
ldadd = libgnulib.a;
|
||||
cflags = '$(CFLAGS_POSIX) $(CFLAGS_GNULIB)';
|
||||
cppflags = '$(CPPFLAGS_POSIX) $(CPPFLAGS_GNULIB)';
|
||||
|
@ -518,6 +520,7 @@ module = {
|
|||
name = halt;
|
||||
nopc = commands/halt.c;
|
||||
i386_pc = commands/i386/pc/halt.c;
|
||||
i386_pc = commands/acpihalt.c;
|
||||
i386_multiboot = lib/i386/halt.c;
|
||||
i386_coreboot = lib/i386/halt.c;
|
||||
i386_qemu = lib/i386/halt.c;
|
||||
|
@ -860,6 +863,11 @@ module = {
|
|||
common = fs/befs_be.c;
|
||||
};
|
||||
|
||||
module = {
|
||||
name = btrfs;
|
||||
common = fs/btrfs.c;
|
||||
};
|
||||
|
||||
module = {
|
||||
name = cpio;
|
||||
common = fs/cpio.c;
|
||||
|
@ -905,6 +913,11 @@ module = {
|
|||
common = fs/minix.c;
|
||||
};
|
||||
|
||||
module = {
|
||||
name = minix2;
|
||||
common = fs/minix2.c;
|
||||
};
|
||||
|
||||
module = {
|
||||
name = nilfs2;
|
||||
common = fs/nilfs2.c;
|
||||
|
@ -1036,6 +1049,9 @@ module = {
|
|||
powerpc = lib/powerpc/relocator_asm.S;
|
||||
powerpc = lib/powerpc/relocator.c;
|
||||
|
||||
extra_dist = lib/i386/relocator_common.S;
|
||||
extra_dist = kern/powerpc/cache_flush.S;
|
||||
|
||||
enable = mips;
|
||||
enable = powerpc;
|
||||
enable = x86;
|
||||
|
@ -1187,6 +1203,8 @@ module = {
|
|||
common = script/lexer.c;
|
||||
common = script/argv.c;
|
||||
|
||||
common = commands/menuentry.c;
|
||||
|
||||
common = unidata.c;
|
||||
common_nodist = grub_script.tab.c;
|
||||
common_nodist = grub_script.yy.c;
|
||||
|
@ -1403,3 +1421,22 @@ module = {
|
|||
name = datehook;
|
||||
common = hook/datehook.c;
|
||||
};
|
||||
|
||||
module = {
|
||||
name = test_blockarg;
|
||||
common = tests/test_blockarg.c;
|
||||
};
|
||||
|
||||
module = {
|
||||
name = xzio;
|
||||
common = io/xzio.c;
|
||||
common = lib/xzembed/xz_dec_bcj.c;
|
||||
common = lib/xzembed/xz_dec_lzma2.c;
|
||||
common = lib/xzembed/xz_dec_stream.c;
|
||||
cppflags = '-I$(srcdir)/lib/posix_wrap -I$(srcdir)/lib/xzembed';
|
||||
};
|
||||
|
||||
module = {
|
||||
name = testload;
|
||||
common = commands/testload.c;
|
||||
};
|
||||
|
|
|
@ -185,7 +185,7 @@ real_code_2:
|
|||
call LOCAL(move_memory)
|
||||
|
||||
/* Check for multiboot signature. */
|
||||
cmpl $MULTIBOOT_HEADER_MAGIC, %ss:(DATA_ADDR + GRUB_KERNEL_MACHINE_DATA_END)
|
||||
cmpl $MULTIBOOT_HEADER_MAGIC, %ss:(DATA_ADDR + GRUB_KERNEL_I386_PC_MULTIBOOT_SIGNATURE)
|
||||
jz 1f
|
||||
|
||||
movl (ramdisk_image - start), %esi
|
||||
|
|
|
@ -23,7 +23,6 @@
|
|||
#include <grub/disk.h>
|
||||
#include <grub/term.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/gzio.h>
|
||||
#include <grub/acpi.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/machine/memory.h>
|
||||
|
@ -458,10 +457,9 @@ free_tables (void)
|
|||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_acpi (struct grub_extcmd *cmd,
|
||||
int argc, char **args)
|
||||
grub_cmd_acpi (struct grub_extcmd_context *ctxt, int argc, char **args)
|
||||
{
|
||||
struct grub_arg_list *state = cmd->state;
|
||||
struct grub_arg_list *state = ctxt->state;
|
||||
struct grub_acpi_rsdp_v10 *rsdp;
|
||||
struct efiemu_acpi_table *cur, *t;
|
||||
grub_err_t err;
|
||||
|
@ -629,7 +627,7 @@ grub_cmd_acpi (struct grub_extcmd *cmd,
|
|||
grub_size_t size;
|
||||
char *buf;
|
||||
|
||||
file = grub_gzfile_open (args[i], 1);
|
||||
file = grub_file_open (args[i]);
|
||||
if (! file)
|
||||
{
|
||||
free_tables ();
|
||||
|
|
266
grub-core/commands/acpihalt.c
Normal file
266
grub-core/commands/acpihalt.c
Normal file
|
@ -0,0 +1,266 @@
|
|||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2010 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GRUB is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <grub/acpi.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/cpu/io.h>
|
||||
|
||||
static inline grub_uint32_t
|
||||
decode_length (const grub_uint8_t *ptr, int *numlen)
|
||||
{
|
||||
int num_bytes, i;
|
||||
grub_uint32_t ret;
|
||||
if (*ptr < 64)
|
||||
{
|
||||
if (numlen)
|
||||
*numlen = 1;
|
||||
return *ptr;
|
||||
}
|
||||
num_bytes = *ptr >> 6;
|
||||
if (numlen)
|
||||
*numlen = num_bytes + 1;
|
||||
ret = *ptr & 0xf;
|
||||
ptr++;
|
||||
for (i = 0; i < num_bytes; i++)
|
||||
{
|
||||
ret |= *ptr << (8 * i + 4);
|
||||
ptr++;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline grub_uint32_t
|
||||
skip_name_string (const grub_uint8_t *ptr, const grub_uint8_t *end)
|
||||
{
|
||||
const grub_uint8_t *ptr0 = ptr;
|
||||
|
||||
while (ptr < end && (*ptr == '^' || *ptr == '\\'))
|
||||
ptr++;
|
||||
switch (*ptr)
|
||||
{
|
||||
case '.':
|
||||
ptr++;
|
||||
ptr += 8;
|
||||
break;
|
||||
case '/':
|
||||
ptr++;
|
||||
ptr += 1 + (*ptr) * 4;
|
||||
break;
|
||||
case 0:
|
||||
ptr++;
|
||||
break;
|
||||
default:
|
||||
ptr += 4;
|
||||
break;
|
||||
}
|
||||
return ptr - ptr0;
|
||||
}
|
||||
|
||||
static inline grub_uint32_t
|
||||
skip_data_ref_object (const grub_uint8_t *ptr, const grub_uint8_t *end)
|
||||
{
|
||||
grub_dprintf ("acpi", "data type = 0x%x\n", *ptr);
|
||||
switch (*ptr)
|
||||
{
|
||||
case GRUB_ACPI_OPCODE_PACKAGE:
|
||||
return 1 + decode_length (ptr + 1, 0);
|
||||
case GRUB_ACPI_OPCODE_ZERO:
|
||||
case GRUB_ACPI_OPCODE_ONES:
|
||||
case GRUB_ACPI_OPCODE_ONE:
|
||||
return 1;
|
||||
case GRUB_ACPI_OPCODE_BYTE_CONST:
|
||||
return 2;
|
||||
case GRUB_ACPI_OPCODE_WORD_CONST:
|
||||
return 3;
|
||||
case GRUB_ACPI_OPCODE_DWORD_CONST:
|
||||
return 5;
|
||||
default:
|
||||
if (*ptr == '^' || *ptr == '\\' || *ptr == '_'
|
||||
|| (*ptr >= 'A' && *ptr <= 'Z'))
|
||||
return skip_name_string (ptr, end);
|
||||
grub_printf ("Unknown opcode 0x%x\n", *ptr);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static inline grub_uint32_t
|
||||
skip_ext_op (const grub_uint8_t *ptr, const grub_uint8_t *end)
|
||||
{
|
||||
const grub_uint8_t *ptr0 = ptr;
|
||||
int add;
|
||||
grub_dprintf ("acpi", "Extended opcode: 0x%x\n", *ptr);
|
||||
switch (*ptr)
|
||||
{
|
||||
case GRUB_ACPI_EXTOPCODE_MUTEX:
|
||||
ptr++;
|
||||
ptr += skip_name_string (ptr, end);
|
||||
ptr++;
|
||||
break;
|
||||
case GRUB_ACPI_EXTOPCODE_OPERATION_REGION:
|
||||
ptr++;
|
||||
ptr += skip_name_string (ptr, end);
|
||||
ptr++;
|
||||
ptr += add = skip_data_ref_object (ptr, end);
|
||||
if (!add)
|
||||
return 0;
|
||||
ptr += add = skip_data_ref_object (ptr, end);
|
||||
if (!add)
|
||||
return 0;
|
||||
break;
|
||||
case GRUB_ACPI_EXTOPCODE_FIELD_OP:
|
||||
ptr++;
|
||||
ptr += decode_length (ptr, 0);
|
||||
break;
|
||||
default:
|
||||
grub_printf ("Unexpected extended opcode: 0x%x\n", *ptr);
|
||||
return 0;
|
||||
}
|
||||
return ptr - ptr0;
|
||||
}
|
||||
|
||||
static int
|
||||
get_sleep_type (grub_uint8_t *table, grub_uint8_t *end)
|
||||
{
|
||||
grub_uint8_t *ptr, *prev;
|
||||
int sleep_type = -1;
|
||||
|
||||
ptr = table + sizeof (struct grub_acpi_table_header);
|
||||
while (ptr < end && prev < ptr)
|
||||
{
|
||||
int add;
|
||||
prev = ptr;
|
||||
grub_dprintf ("acpi", "Opcode %x\n", *ptr);
|
||||
grub_dprintf ("acpi", "Tell %x\n", ptr - table);
|
||||
switch (*ptr)
|
||||
{
|
||||
case GRUB_ACPI_OPCODE_EXTOP:
|
||||
ptr++;
|
||||
ptr += add = skip_ext_op (ptr, end);
|
||||
if (!add)
|
||||
return -1;
|
||||
break;
|
||||
case GRUB_ACPI_OPCODE_NAME:
|
||||
ptr++;
|
||||
if (memcmp (ptr, "_S5_", 4) == 0)
|
||||
{
|
||||
int ll;
|
||||
grub_uint8_t *ptr2 = ptr;
|
||||
ptr2 += 4;
|
||||
if (*ptr2 != 0x12)
|
||||
{
|
||||
grub_printf ("Unknown opcode in _S5: 0x%x\n", *ptr2);
|
||||
return -1;
|
||||
}
|
||||
ptr2++;
|
||||
decode_length (ptr2, &ll);
|
||||
ptr2 += ll;
|
||||
ptr2++;
|
||||
switch (*ptr2)
|
||||
{
|
||||
case GRUB_ACPI_OPCODE_ZERO:
|
||||
sleep_type = 0;
|
||||
break;
|
||||
case GRUB_ACPI_OPCODE_ONE:
|
||||
sleep_type = 1;
|
||||
break;
|
||||
case GRUB_ACPI_OPCODE_BYTE_CONST:
|
||||
sleep_type = ptr2[1];
|
||||
break;
|
||||
default:
|
||||
grub_printf ("Unknown data type in _S5: 0x%x\n", *ptr2);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
ptr += add = skip_name_string (ptr, end);
|
||||
if (!add)
|
||||
return -1;
|
||||
ptr += add = skip_data_ref_object (ptr, end);
|
||||
if (!add)
|
||||
return -1;
|
||||
break;
|
||||
case GRUB_ACPI_OPCODE_SCOPE:
|
||||
case GRUB_ACPI_OPCODE_IF:
|
||||
case GRUB_ACPI_OPCODE_METHOD:
|
||||
{
|
||||
ptr++;
|
||||
ptr += decode_length (ptr, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
grub_dprintf ("acpi", "TYP = %d\n", sleep_type);
|
||||
return sleep_type;
|
||||
}
|
||||
|
||||
void
|
||||
grub_acpi_halt (void)
|
||||
{
|
||||
struct grub_acpi_rsdp_v20 *rsdp2;
|
||||
struct grub_acpi_rsdp_v10 *rsdp1;
|
||||
struct grub_acpi_table_header *rsdt;
|
||||
grub_uint32_t *entry_ptr;
|
||||
|
||||
rsdp2 = grub_acpi_get_rsdpv2 ();
|
||||
if (rsdp2)
|
||||
rsdp1 = &(rsdp2->rsdpv1);
|
||||
else
|
||||
rsdp1 = grub_acpi_get_rsdpv1 ();
|
||||
grub_dprintf ("acpi", "rsdp1=%p\n", rsdp1);
|
||||
if (!rsdp1)
|
||||
return;
|
||||
|
||||
rsdt = (struct grub_acpi_table_header *) rsdp1->rsdt_addr;
|
||||
for (entry_ptr = (grub_uint32_t *) (rsdt + 1);
|
||||
entry_ptr < (grub_uint32_t *) (((grub_uint8_t *) rsdt)
|
||||
+ rsdt->length);
|
||||
entry_ptr++)
|
||||
{
|
||||
if (grub_memcmp ((void *)*entry_ptr, "FACP", 4) == 0)
|
||||
{
|
||||
grub_uint32_t port;
|
||||
struct grub_acpi_fadt *fadt
|
||||
= ((struct grub_acpi_fadt *) *entry_ptr);
|
||||
struct grub_acpi_table_header *dsdt
|
||||
= (struct grub_acpi_table_header *) fadt->dsdt_addr;
|
||||
int sleep_type = -1;
|
||||
|
||||
port = fadt->pm1a;
|
||||
|
||||
grub_dprintf ("acpi", "PM1a port=%x\n", port);
|
||||
|
||||
if (grub_memcmp (dsdt->signature, "DSDT",
|
||||
sizeof (dsdt->signature)) != 0)
|
||||
break;
|
||||
|
||||
sleep_type = get_sleep_type ((grub_uint8_t *) dsdt,
|
||||
(grub_uint8_t *) dsdt + dsdt->length);
|
||||
|
||||
if (sleep_type < 0 || sleep_type >= 8)
|
||||
break;
|
||||
|
||||
grub_dprintf ("acpi", "SLP_TYP = %d, port = 0x%x\n",
|
||||
sleep_type, port);
|
||||
|
||||
grub_outw (GRUB_ACPI_SLP_EN
|
||||
| (sleep_type << GRUB_ACPI_SLP_TYP_OFFSET), port & 0xffff);
|
||||
}
|
||||
}
|
||||
|
||||
grub_printf ("ACPI shutdown failed\n");
|
||||
}
|
|
@ -82,6 +82,7 @@ grub_cmd_blocklist (grub_command_t cmd __attribute__ ((unused)),
|
|||
if (argc < 1)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "no file specified");
|
||||
|
||||
grub_file_filter_disable_compression ();
|
||||
file = grub_file_open (args[0]);
|
||||
if (! file)
|
||||
return grub_errno;
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
#include <grub/disk.h>
|
||||
#include <grub/term.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/gzio.h>
|
||||
#include <grub/extcmd.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
|
@ -33,9 +32,9 @@ static const struct grub_arg_option options[] =
|
|||
};
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_cat (grub_extcmd_t cmd, int argc, char **args)
|
||||
grub_cmd_cat (grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
{
|
||||
struct grub_arg_list *state = cmd->state;
|
||||
struct grub_arg_list *state = ctxt->state;
|
||||
int dos = 0;
|
||||
grub_file_t file;
|
||||
char buf[GRUB_DISK_SECTOR_SIZE];
|
||||
|
@ -48,7 +47,7 @@ grub_cmd_cat (grub_extcmd_t cmd, int argc, char **args)
|
|||
if (argc != 1)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required");
|
||||
|
||||
file = grub_gzfile_open (args[0], 1);
|
||||
file = grub_file_open (args[0]);
|
||||
if (! file)
|
||||
return grub_errno;
|
||||
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
#include <grub/misc.h>
|
||||
#include <grub/file.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/gzio.h>
|
||||
#include <grub/command.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
|
@ -44,8 +43,8 @@ grub_cmd_cmp (grub_command_t cmd __attribute__ ((unused)),
|
|||
grub_printf ("Compare file `%s' with `%s':\n", args[0],
|
||||
args[1]);
|
||||
|
||||
file1 = grub_gzfile_open (args[0], 1);
|
||||
file2 = grub_gzfile_open (args[1], 1);
|
||||
file1 = grub_file_open (args[0]);
|
||||
file2 = grub_file_open (args[1]);
|
||||
if (! file1 || ! file2)
|
||||
goto cleanup;
|
||||
|
||||
|
|
|
@ -38,6 +38,7 @@ grub_cmd_crc (grub_command_t cmd __attribute__ ((unused)),
|
|||
if (argc != 1)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required");
|
||||
|
||||
grub_file_filter_disable_compression ();
|
||||
file = grub_file_open (args[0]);
|
||||
if (! file)
|
||||
return 0;
|
||||
|
|
|
@ -30,9 +30,9 @@ static const struct grub_arg_option options[] =
|
|||
};
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_echo (grub_extcmd_t cmd, int argc, char **args)
|
||||
grub_cmd_echo (grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
{
|
||||
struct grub_arg_list *state = cmd->state;
|
||||
struct grub_arg_list *state = ctxt->state;
|
||||
int newline = 1;
|
||||
int i;
|
||||
|
||||
|
|
|
@ -21,46 +21,55 @@
|
|||
#include <grub/list.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/extcmd.h>
|
||||
#include <grub/script_sh.h>
|
||||
|
||||
static grub_err_t
|
||||
grub_extcmd_dispatcher (struct grub_command *cmd,
|
||||
int argc, char **args)
|
||||
grub_err_t
|
||||
grub_extcmd_dispatcher (struct grub_command *cmd, int argc, char **args,
|
||||
struct grub_script *script)
|
||||
{
|
||||
int new_argc;
|
||||
char **new_args;
|
||||
struct grub_arg_option *parser;
|
||||
struct grub_arg_list *state;
|
||||
int maxargs = 0;
|
||||
struct grub_extcmd_context context;
|
||||
grub_err_t ret;
|
||||
grub_extcmd_t ext;
|
||||
grub_extcmd_t ext = cmd->data;
|
||||
|
||||
ext = cmd->data;
|
||||
parser = (struct grub_arg_option *) ext->options;
|
||||
while (parser && (parser++)->doc)
|
||||
maxargs++;
|
||||
context.state = 0;
|
||||
context.extcmd = ext;
|
||||
context.script = script;
|
||||
|
||||
/* Set up the option state. */
|
||||
state = grub_zalloc (sizeof (struct grub_arg_list) * maxargs);
|
||||
if (! ext->options)
|
||||
{
|
||||
ret = (ext->func) (&context, argc, args);
|
||||
return ret;
|
||||
}
|
||||
|
||||
state = grub_arg_list_alloc (ext, argc, args);
|
||||
if (grub_arg_parse (ext, argc, args, state, &new_args, &new_argc))
|
||||
{
|
||||
ext->state = state;
|
||||
ret = (ext->func) (ext, new_argc, new_args);
|
||||
context.state = state;
|
||||
ret = (ext->func) (&context, new_argc, new_args);
|
||||
grub_free (new_args);
|
||||
grub_free (state);
|
||||
return ret;
|
||||
}
|
||||
else
|
||||
ret = grub_errno;
|
||||
|
||||
grub_free (state);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
return ret;
|
||||
static grub_err_t
|
||||
grub_extcmd_dispatch (struct grub_command *cmd, int argc, char **args)
|
||||
{
|
||||
return grub_extcmd_dispatcher (cmd, argc, args, 0);
|
||||
}
|
||||
|
||||
grub_extcmd_t
|
||||
grub_register_extcmd (const char *name, grub_extcmd_func_t func,
|
||||
unsigned flags, const char *summary,
|
||||
const char *description,
|
||||
const struct grub_arg_option *parser)
|
||||
grub_register_extcmd_prio (const char *name, grub_extcmd_func_t func,
|
||||
unsigned flags, const char *summary,
|
||||
const char *description,
|
||||
const struct grub_arg_option *parser,
|
||||
int prio)
|
||||
{
|
||||
grub_extcmd_t ext;
|
||||
grub_command_t cmd;
|
||||
|
@ -69,8 +78,8 @@ grub_register_extcmd (const char *name, grub_extcmd_func_t func,
|
|||
if (! ext)
|
||||
return 0;
|
||||
|
||||
cmd = grub_register_command_prio (name, grub_extcmd_dispatcher,
|
||||
summary, description, 1);
|
||||
cmd = grub_register_command_prio (name, grub_extcmd_dispatch,
|
||||
summary, description, prio);
|
||||
if (! cmd)
|
||||
{
|
||||
grub_free (ext);
|
||||
|
@ -88,6 +97,16 @@ grub_register_extcmd (const char *name, grub_extcmd_func_t func,
|
|||
return ext;
|
||||
}
|
||||
|
||||
grub_extcmd_t
|
||||
grub_register_extcmd (const char *name, grub_extcmd_func_t func,
|
||||
unsigned flags, const char *summary,
|
||||
const char *description,
|
||||
const struct grub_arg_option *parser)
|
||||
{
|
||||
return grub_register_extcmd_prio (name, func, flags,
|
||||
summary, description, parser, 1);
|
||||
}
|
||||
|
||||
void
|
||||
grub_unregister_extcmd (grub_extcmd_t ext)
|
||||
{
|
||||
|
|
|
@ -32,6 +32,7 @@ static const struct grub_arg_option options[] = {
|
|||
{"prefix", 'p', 0, N_("Base directory for hash list."), N_("DIRECTORY"),
|
||||
ARG_TYPE_STRING},
|
||||
{"keep-going", 'k', 0, N_("Don't stop after first error."), 0, 0},
|
||||
{"uncompress", 'u', 0, N_("Uncompress file before checksumming."), 0, 0},
|
||||
{0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
|
@ -80,7 +81,7 @@ hash_file (grub_file_t file, const gcry_md_spec_t *hash, void *result)
|
|||
|
||||
static grub_err_t
|
||||
check_list (const gcry_md_spec_t *hash, const char *hashfilename,
|
||||
const char *prefix, int keep)
|
||||
const char *prefix, int keep, int uncompress)
|
||||
{
|
||||
grub_file_t hashlist, file;
|
||||
char *buf = NULL;
|
||||
|
@ -115,11 +116,17 @@ check_list (const gcry_md_spec_t *hash, const char *hashfilename,
|
|||
filename = grub_xasprintf ("%s/%s", prefix, p);
|
||||
if (!filename)
|
||||
return grub_errno;
|
||||
if (!uncompress)
|
||||
grub_file_filter_disable_compression ();
|
||||
file = grub_file_open (filename);
|
||||
grub_free (filename);
|
||||
}
|
||||
else
|
||||
file = grub_file_open (p);
|
||||
{
|
||||
if (!uncompress)
|
||||
grub_file_filter_disable_compression ();
|
||||
file = grub_file_open (p);
|
||||
}
|
||||
if (!file)
|
||||
{
|
||||
grub_file_close (hashlist);
|
||||
|
@ -165,19 +172,20 @@ check_list (const gcry_md_spec_t *hash, const char *hashfilename,
|
|||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_hashsum (struct grub_extcmd *cmd,
|
||||
grub_cmd_hashsum (struct grub_extcmd_context *ctxt,
|
||||
int argc, char **args)
|
||||
{
|
||||
struct grub_arg_list *state = cmd->state;
|
||||
struct grub_arg_list *state = ctxt->state;
|
||||
const char *hashname = NULL;
|
||||
const char *prefix = NULL;
|
||||
const gcry_md_spec_t *hash;
|
||||
unsigned i;
|
||||
int keep = state[3].set;
|
||||
int uncompress = state[4].set;
|
||||
unsigned unread = 0;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE (aliases); i++)
|
||||
if (grub_strcmp (cmd->cmd->name, aliases[i].name) == 0)
|
||||
if (grub_strcmp (ctxt->extcmd->cmd->name, aliases[i].name) == 0)
|
||||
hashname = aliases[i].hashname;
|
||||
if (state[0].set)
|
||||
hashname = state[0].arg;
|
||||
|
@ -197,7 +205,7 @@ grub_cmd_hashsum (struct grub_extcmd *cmd,
|
|||
if (argc != 0)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
"--check is incompatible with file list");
|
||||
return check_list (hash, state[1].arg, prefix, keep);
|
||||
return check_list (hash, state[1].arg, prefix, keep, uncompress);
|
||||
}
|
||||
|
||||
for (i = 0; i < (unsigned) argc; i++)
|
||||
|
@ -206,6 +214,8 @@ grub_cmd_hashsum (struct grub_extcmd *cmd,
|
|||
grub_file_t file;
|
||||
grub_err_t err;
|
||||
unsigned j;
|
||||
if (!uncompress)
|
||||
grub_file_filter_disable_compression ();
|
||||
file = grub_file_open (args[i]);
|
||||
if (!file)
|
||||
{
|
||||
|
|
|
@ -270,9 +270,9 @@ static int get_int_arg (const struct grub_arg_list *state)
|
|||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_hdparm (grub_extcmd_t cmd, int argc, char **args) // state????
|
||||
grub_cmd_hdparm (grub_extcmd_context_t ctxt, int argc, char **args) // state????
|
||||
{
|
||||
struct grub_arg_list *state = cmd->state;
|
||||
struct grub_arg_list *state = ctxt->state;
|
||||
|
||||
/* Check command line. */
|
||||
if (argc != 1)
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
#include <grub/charset.h>
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_help (grub_extcmd_t ext __attribute__ ((unused)), int argc,
|
||||
grub_cmd_help (grub_extcmd_context_t ctxt __attribute__ ((unused)), int argc,
|
||||
char **args)
|
||||
{
|
||||
int cnt = 0;
|
||||
|
@ -112,7 +112,8 @@ grub_cmd_help (grub_extcmd_t ext __attribute__ ((unused)), int argc,
|
|||
if (cnt++ > 0)
|
||||
grub_printf ("\n\n");
|
||||
|
||||
if (cmd->flags & GRUB_COMMAND_FLAG_EXTCMD)
|
||||
if ((cmd->flags & GRUB_COMMAND_FLAG_EXTCMD) &&
|
||||
! (cmd->flags & GRUB_COMMAND_FLAG_DYNCMD))
|
||||
grub_arg_show_help ((grub_extcmd_t) cmd->data);
|
||||
else
|
||||
grub_printf ("%s %s %s\n%s\n", _("Usage:"), cmd->name, _(cmd->summary),
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
#include <grub/file.h>
|
||||
#include <grub/disk.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/gzio.h>
|
||||
#include <grub/lib/hexdump.h>
|
||||
#include <grub/extcmd.h>
|
||||
#include <grub/i18n.h>
|
||||
|
@ -34,9 +33,9 @@ static const struct grub_arg_option options[] = {
|
|||
};
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_hexdump (grub_extcmd_t cmd, int argc, char **args)
|
||||
grub_cmd_hexdump (grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
{
|
||||
struct grub_arg_list *state = cmd->state;
|
||||
struct grub_arg_list *state = ctxt->state;
|
||||
char buf[GRUB_DISK_SECTOR_SIZE * 4];
|
||||
grub_ssize_t size, length;
|
||||
grub_disk_addr_t skip;
|
||||
|
@ -89,7 +88,7 @@ grub_cmd_hexdump (grub_extcmd_t cmd, int argc, char **args)
|
|||
{
|
||||
grub_file_t file;
|
||||
|
||||
file = grub_gzfile_open (args[0], 1);
|
||||
file = grub_file_open (args[0]);
|
||||
if (! file)
|
||||
return 0;
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@ static const struct grub_arg_option options[] =
|
|||
unsigned char grub_cpuid_has_longmode = 0;
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_cpuid (grub_extcmd_t cmd __attribute__ ((unused)),
|
||||
grub_cmd_cpuid (grub_extcmd_context_t ctxt __attribute__ ((unused)),
|
||||
int argc __attribute__ ((unused)),
|
||||
char **args __attribute__ ((unused)))
|
||||
{
|
||||
|
|
|
@ -196,13 +196,13 @@ list_mappings (void)
|
|||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_drivemap (struct grub_extcmd *cmd, int argc, char **args)
|
||||
grub_cmd_drivemap (struct grub_extcmd_context *ctxt, int argc, char **args)
|
||||
{
|
||||
if (cmd->state[OPTIDX_LIST].set)
|
||||
if (ctxt->state[OPTIDX_LIST].set)
|
||||
{
|
||||
return list_mappings ();
|
||||
}
|
||||
else if (cmd->state[OPTIDX_RESET].set)
|
||||
else if (ctxt->state[OPTIDX_RESET].set)
|
||||
{
|
||||
/* Reset: just delete all mappings, freeing their memory. */
|
||||
drivemap_node_t *curnode = map_head;
|
||||
|
@ -216,7 +216,7 @@ grub_cmd_drivemap (struct grub_extcmd *cmd, int argc, char **args)
|
|||
map_head = 0;
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
else if (!cmd->state[OPTIDX_SWAP].set && argc == 0)
|
||||
else if (!ctxt->state[OPTIDX_SWAP].set && argc == 0)
|
||||
{
|
||||
/* No arguments */
|
||||
return list_mappings ();
|
||||
|
@ -248,11 +248,11 @@ grub_cmd_drivemap (struct grub_extcmd *cmd, int argc, char **args)
|
|||
}
|
||||
/* Set the mapping for the disk (overwrites any existing mapping). */
|
||||
grub_dprintf ("drivemap", "%s %s (%02x) = %s (%02x)\n",
|
||||
cmd->state[OPTIDX_SWAP].set ? "Swapping" : "Mapping",
|
||||
ctxt->state[OPTIDX_SWAP].set ? "Swapping" : "Mapping",
|
||||
args[1], mapto, args[0], mapfrom);
|
||||
err = drivemap_set (mapto, mapfrom);
|
||||
/* If -s, perform the reverse mapping too (only if the first was OK). */
|
||||
if (cmd->state[OPTIDX_SWAP].set && err == GRUB_ERR_NONE)
|
||||
if (ctxt->state[OPTIDX_SWAP].set && err == GRUB_ERR_NONE)
|
||||
err = drivemap_set (mapfrom, mapto);
|
||||
return err;
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include <grub/extcmd.h>
|
||||
#include <grub/i18n.h>
|
||||
#include <grub/machine/int.h>
|
||||
#include <grub/acpi.h>
|
||||
|
||||
static const struct grub_arg_option options[] =
|
||||
{
|
||||
|
@ -93,13 +94,16 @@ grub_halt (int no_apm)
|
|||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_halt (grub_extcmd_t cmd,
|
||||
grub_cmd_halt (grub_extcmd_context_t ctxt,
|
||||
int argc __attribute__ ((unused)),
|
||||
char **args __attribute__ ((unused)))
|
||||
|
||||
{
|
||||
struct grub_arg_list *state = cmd->state;
|
||||
struct grub_arg_list *state = ctxt->state;
|
||||
int no_apm = 0;
|
||||
|
||||
grub_acpi_halt ();
|
||||
|
||||
if (state[0].set)
|
||||
no_apm = 1;
|
||||
grub_halt (no_apm);
|
||||
|
|
|
@ -284,9 +284,9 @@ grub_sendkey_preboot (int noret __attribute__ ((unused)))
|
|||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_sendkey (grub_extcmd_t cmd, int argc, char **args)
|
||||
grub_cmd_sendkey (grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
{
|
||||
struct grub_arg_list *state = cmd->state;
|
||||
struct grub_arg_list *state = ctxt->state;
|
||||
|
||||
auto int find_key_code (char *key);
|
||||
auto int find_ascii_code (char *key);
|
||||
|
|
|
@ -36,7 +36,7 @@ static const struct grub_arg_option options[] =
|
|||
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_read (grub_extcmd_t cmd, int argc, char **argv)
|
||||
grub_cmd_read (grub_extcmd_context_t ctxt, int argc, char **argv)
|
||||
{
|
||||
grub_target_addr_t addr;
|
||||
grub_uint32_t value = 0;
|
||||
|
@ -46,7 +46,7 @@ grub_cmd_read (grub_extcmd_t cmd, int argc, char **argv)
|
|||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid number of arguments");
|
||||
|
||||
addr = grub_strtoul (argv[0], 0, 0);
|
||||
switch (cmd->cmd->name[sizeof ("in") - 1])
|
||||
switch (ctxt->extcmd->cmd->name[sizeof ("in") - 1])
|
||||
{
|
||||
case 'l':
|
||||
value = grub_inl (addr);
|
||||
|
@ -61,10 +61,10 @@ grub_cmd_read (grub_extcmd_t cmd, int argc, char **argv)
|
|||
break;
|
||||
}
|
||||
|
||||
if (cmd->state[0].set)
|
||||
if (ctxt->state[0].set)
|
||||
{
|
||||
grub_snprintf (buf, sizeof (buf), "%x", value);
|
||||
grub_env_set (cmd->state[0].arg, buf);
|
||||
grub_env_set (ctxt->state[0].arg, buf);
|
||||
}
|
||||
else
|
||||
grub_printf ("0x%x\n", value);
|
||||
|
|
|
@ -34,11 +34,11 @@ static const struct grub_arg_option options[] =
|
|||
#define grub_cur_term_input grub_term_get_current_input ()
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_keystatus (grub_extcmd_t cmd,
|
||||
grub_cmd_keystatus (grub_extcmd_context_t ctxt,
|
||||
int argc __attribute__ ((unused)),
|
||||
char **args __attribute__ ((unused)))
|
||||
{
|
||||
struct grub_arg_list *state = cmd->state;
|
||||
struct grub_arg_list *state = ctxt->state;
|
||||
int expect_mods = 0;
|
||||
int mods;
|
||||
|
||||
|
|
|
@ -56,6 +56,7 @@ open_envblk_file (char *filename)
|
|||
grub_strcpy (filename, prefix);
|
||||
filename[len] = '/';
|
||||
grub_strcpy (filename + len + 1, GRUB_ENVBLK_DEFCFG);
|
||||
grub_file_filter_disable_compression ();
|
||||
file = grub_file_open (filename);
|
||||
grub_free (filename);
|
||||
return file;
|
||||
|
@ -67,6 +68,7 @@ open_envblk_file (char *filename)
|
|||
}
|
||||
}
|
||||
|
||||
grub_file_filter_disable_compression ();
|
||||
return grub_file_open (filename);
|
||||
}
|
||||
|
||||
|
@ -111,11 +113,11 @@ read_envblk_file (grub_file_t file)
|
|||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_load_env (grub_extcmd_t cmd,
|
||||
grub_cmd_load_env (grub_extcmd_context_t ctxt,
|
||||
int argc __attribute__ ((unused)),
|
||||
char **args __attribute__ ((unused)))
|
||||
{
|
||||
struct grub_arg_list *state = cmd->state;
|
||||
struct grub_arg_list *state = ctxt->state;
|
||||
grub_file_t file;
|
||||
grub_envblk_t envblk;
|
||||
|
||||
|
@ -143,11 +145,11 @@ grub_cmd_load_env (grub_extcmd_t cmd,
|
|||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_list_env (grub_extcmd_t cmd,
|
||||
grub_cmd_list_env (grub_extcmd_context_t ctxt,
|
||||
int argc __attribute__ ((unused)),
|
||||
char **args __attribute__ ((unused)))
|
||||
{
|
||||
struct grub_arg_list *state = cmd->state;
|
||||
struct grub_arg_list *state = ctxt->state;
|
||||
grub_file_t file;
|
||||
grub_envblk_t envblk;
|
||||
|
||||
|
@ -280,9 +282,9 @@ write_blocklists (grub_envblk_t envblk, struct blocklist *blocklists,
|
|||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_save_env (grub_extcmd_t cmd, int argc, char **args)
|
||||
grub_cmd_save_env (grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
{
|
||||
struct grub_arg_list *state = cmd->state;
|
||||
struct grub_arg_list *state = ctxt->state;
|
||||
grub_file_t file;
|
||||
grub_envblk_t envblk;
|
||||
struct blocklist *head = 0;
|
||||
|
|
|
@ -105,6 +105,7 @@ grub_ls_list_files (char *dirname, int longlist, int all, int human)
|
|||
|
||||
/* XXX: For ext2fs symlinks are detected as files while they
|
||||
should be reported as directories. */
|
||||
grub_file_filter_disable_compression ();
|
||||
file = grub_file_open (pathname);
|
||||
if (! file)
|
||||
{
|
||||
|
@ -211,6 +212,7 @@ grub_ls_list_files (char *dirname, int longlist, int all, int human)
|
|||
struct grub_dirhook_info info;
|
||||
grub_errno = 0;
|
||||
|
||||
grub_file_filter_disable_compression ();
|
||||
file = grub_file_open (dirname);
|
||||
if (! file)
|
||||
goto fail;
|
||||
|
@ -248,9 +250,9 @@ grub_ls_list_files (char *dirname, int longlist, int all, int human)
|
|||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_ls (grub_extcmd_t cmd, int argc, char **args)
|
||||
grub_cmd_ls (grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
{
|
||||
struct grub_arg_list *state = cmd->state;
|
||||
struct grub_arg_list *state = ctxt->state;
|
||||
|
||||
if (argc == 0)
|
||||
grub_ls_list_devices (state[0].set);
|
||||
|
|
|
@ -211,11 +211,11 @@ grub_lspci_iter (grub_pci_device_t dev, grub_pci_id_t pciid)
|
|||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_lspci (grub_extcmd_t cmd,
|
||||
grub_cmd_lspci (grub_extcmd_context_t ctxt,
|
||||
int argc __attribute__ ((unused)),
|
||||
char **args __attribute__ ((unused)))
|
||||
{
|
||||
iospace = cmd->state[0].set;
|
||||
iospace = ctxt->state[0].set;
|
||||
grub_pci_iterate (grub_lspci_iter);
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ static const struct grub_arg_option options[] =
|
|||
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_read (grub_extcmd_t cmd, int argc, char **argv)
|
||||
grub_cmd_read (grub_extcmd_context_t ctxt, int argc, char **argv)
|
||||
{
|
||||
grub_target_addr_t addr;
|
||||
grub_uint32_t value = 0;
|
||||
|
@ -45,7 +45,7 @@ grub_cmd_read (grub_extcmd_t cmd, int argc, char **argv)
|
|||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid number of arguments");
|
||||
|
||||
addr = grub_strtoul (argv[0], 0, 0);
|
||||
switch (cmd->cmd->name[sizeof ("read_") - 1])
|
||||
switch (ctxt->extcmd->cmd->name[sizeof ("read_") - 1])
|
||||
{
|
||||
case 'd':
|
||||
value = *((volatile grub_uint32_t *) addr);
|
||||
|
@ -60,10 +60,10 @@ grub_cmd_read (grub_extcmd_t cmd, int argc, char **argv)
|
|||
break;
|
||||
}
|
||||
|
||||
if (cmd->state[0].set)
|
||||
if (ctxt->state[0].set)
|
||||
{
|
||||
grub_snprintf (buf, sizeof (buf), "%x", value);
|
||||
grub_env_set (cmd->state[0].arg, buf);
|
||||
grub_env_set (ctxt->state[0].arg, buf);
|
||||
}
|
||||
else
|
||||
grub_printf ("0x%x\n", value);
|
||||
|
|
285
grub-core/commands/menuentry.c
Normal file
285
grub-core/commands/menuentry.c
Normal file
|
@ -0,0 +1,285 @@
|
|||
/* menuentry.c - menuentry command */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2010 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GRUB is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <grub/types.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/err.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/extcmd.h>
|
||||
#include <grub/i18n.h>
|
||||
#include <grub/normal.h>
|
||||
|
||||
static const struct grub_arg_option options[] =
|
||||
{
|
||||
{"class", 1, GRUB_ARG_OPTION_REPEATABLE,
|
||||
N_("Menu entry type."), "STRING", ARG_TYPE_STRING},
|
||||
{"users", 2, 0,
|
||||
N_("Users allowed to boot this entry."), "USERNAME", ARG_TYPE_STRING},
|
||||
{"hotkey", 3, 0,
|
||||
N_("Keyboard key for this entry."), "KEY", ARG_TYPE_STRING},
|
||||
{"source", 4, 0,
|
||||
N_("Menu entry definition as a string."), "STRING", ARG_TYPE_STRING},
|
||||
{0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
static struct
|
||||
{
|
||||
char *name;
|
||||
int key;
|
||||
} hotkey_aliases[] =
|
||||
{
|
||||
{"backspace", '\b'},
|
||||
{"tab", '\t'},
|
||||
{"delete", GRUB_TERM_DC}
|
||||
};
|
||||
|
||||
/* Add a menu entry to the current menu context (as given by the environment
|
||||
variable data slot `menu'). As the configuration file is read, the script
|
||||
parser calls this when a menu entry is to be created. */
|
||||
static grub_err_t
|
||||
append_menu_entry (int argc, const char **args, char **classes,
|
||||
const char *users, const char *hotkey,
|
||||
const char *prefix, const char *sourcecode)
|
||||
{
|
||||
unsigned i;
|
||||
int menu_hotkey = 0;
|
||||
char **menu_args = NULL;
|
||||
char *menu_users = NULL;
|
||||
char *menu_title = NULL;
|
||||
char *menu_sourcecode = NULL;
|
||||
struct grub_menu_entry_class *menu_classes = NULL;
|
||||
|
||||
grub_menu_t menu;
|
||||
grub_menu_entry_t *last;
|
||||
|
||||
menu = grub_env_get_menu ();
|
||||
if (! menu)
|
||||
return grub_error (GRUB_ERR_MENU, "no menu context");
|
||||
|
||||
last = &menu->entry_list;
|
||||
|
||||
menu_sourcecode = grub_xasprintf ("%s%s", prefix ?: "", sourcecode);
|
||||
if (! menu_sourcecode)
|
||||
return grub_errno;
|
||||
|
||||
if (classes)
|
||||
{
|
||||
for (i = 0; classes[i]; i++); /* count # of menuentry classes */
|
||||
menu_classes = grub_zalloc (sizeof (struct grub_menu_entry_class) * i);
|
||||
if (! menu_classes)
|
||||
goto fail;
|
||||
|
||||
for (i = 0; classes[i]; i++)
|
||||
{
|
||||
menu_classes[i].name = grub_strdup (classes[i]);
|
||||
if (! menu_classes[i].name)
|
||||
goto fail;
|
||||
menu_classes[i].next = classes[i + 1] ? &menu_classes[i + 1] : NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (users)
|
||||
{
|
||||
menu_users = grub_strdup (users);
|
||||
if (! menu_users)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (hotkey)
|
||||
{
|
||||
for (i = 0; i < ARRAY_SIZE (hotkey_aliases); i++)
|
||||
if (grub_strcmp (hotkey, hotkey_aliases[i].name) == 0)
|
||||
{
|
||||
menu_hotkey = hotkey_aliases[i].key;
|
||||
break;
|
||||
}
|
||||
if (i == ARRAY_SIZE (hotkey_aliases))
|
||||
menu_hotkey = hotkey[0];
|
||||
}
|
||||
|
||||
if (! argc)
|
||||
{
|
||||
grub_error (GRUB_ERR_MENU, "menuentry is missing title");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
menu_title = grub_strdup (args[0]);
|
||||
if (! menu_title)
|
||||
goto fail;
|
||||
|
||||
/* Save argc, args to pass as parameters to block arg later. */
|
||||
menu_args = grub_malloc (sizeof (char*) * (argc + 1));
|
||||
if (! menu_args)
|
||||
goto fail;
|
||||
|
||||
for (i = 0; args[i]; i++)
|
||||
{
|
||||
menu_args[i] = grub_strdup (args[i]);
|
||||
if (! menu_args[i])
|
||||
goto fail;
|
||||
}
|
||||
menu_args[argc] = NULL;
|
||||
|
||||
/* Add the menu entry at the end of the list. */
|
||||
while (*last)
|
||||
last = &(*last)->next;
|
||||
|
||||
*last = grub_zalloc (sizeof (**last));
|
||||
if (! *last)
|
||||
goto fail;
|
||||
|
||||
(*last)->title = menu_title;
|
||||
(*last)->hotkey = menu_hotkey;
|
||||
(*last)->classes = menu_classes;
|
||||
if (menu_users)
|
||||
(*last)->restricted = 1;
|
||||
(*last)->users = menu_users;
|
||||
(*last)->argc = argc;
|
||||
(*last)->args = menu_args;
|
||||
(*last)->sourcecode = menu_sourcecode;
|
||||
|
||||
menu->size++;
|
||||
return GRUB_ERR_NONE;
|
||||
|
||||
fail:
|
||||
|
||||
grub_free (menu_sourcecode);
|
||||
for (i = 0; menu_classes && menu_classes[i].name; i++)
|
||||
grub_free (menu_classes[i].name);
|
||||
grub_free (menu_classes);
|
||||
|
||||
for (i = 0; menu_args && menu_args[i]; i++)
|
||||
grub_free (menu_args[i]);
|
||||
grub_free (menu_args);
|
||||
|
||||
grub_free (menu_users);
|
||||
grub_free (menu_title);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
static char *
|
||||
setparams_prefix (int argc, char **args)
|
||||
{
|
||||
int i;
|
||||
int j;
|
||||
char *p;
|
||||
char *result;
|
||||
grub_size_t len = 10;
|
||||
static const char *escape_characters = "\"\\";
|
||||
|
||||
auto char *strescpy (char *, const char *, const char *);
|
||||
char * strescpy (char *d, const char *s, const char *escapes)
|
||||
{
|
||||
while (*s)
|
||||
{
|
||||
if (grub_strchr (escapes, *s))
|
||||
*d++ = '\\';
|
||||
*d++ = *s++;
|
||||
}
|
||||
*d = '\0';
|
||||
return d;
|
||||
}
|
||||
|
||||
/* Count resulting string length */
|
||||
for (i = 0; i < argc; i++)
|
||||
{
|
||||
len += 3; /* 3 = 1 space + 2 quotes */
|
||||
p = args[i];
|
||||
while (*p)
|
||||
len += grub_strchr (escape_characters, *p++) ? 2 : 1;
|
||||
}
|
||||
|
||||
result = grub_malloc (len + 2);
|
||||
if (! result)
|
||||
return 0;
|
||||
|
||||
grub_strcpy (result, "setparams");
|
||||
i = 9;
|
||||
|
||||
for (j = 0; j < argc; j++)
|
||||
{
|
||||
result[i++] = ' ';
|
||||
result[i++] = '"';
|
||||
i = strescpy (result + i, args[j], escape_characters) - result;
|
||||
result[i++] = '"';
|
||||
}
|
||||
result[i++] = '\n';
|
||||
result[i] = '\0';
|
||||
return result;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_menuentry (grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
{
|
||||
char ch;
|
||||
char *src;
|
||||
char *prefix;
|
||||
unsigned len;
|
||||
grub_err_t r;
|
||||
|
||||
if (! argc)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "missing arguments");
|
||||
|
||||
if (ctxt->state[3].set && ctxt->script)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "multiple menuentry definitions");
|
||||
|
||||
if (! ctxt->state[3].set && ! ctxt->script)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "no menuentry definition");
|
||||
|
||||
if (! ctxt->script)
|
||||
return append_menu_entry (argc, (const char **) args,
|
||||
ctxt->state[0].args, ctxt->state[1].arg,
|
||||
ctxt->state[2].arg, 0, ctxt->state[3].arg);
|
||||
|
||||
src = args[argc - 1];
|
||||
args[argc - 1] = NULL;
|
||||
|
||||
len = grub_strlen(src);
|
||||
ch = src[len - 1];
|
||||
src[len - 1] = '\0';
|
||||
|
||||
prefix = setparams_prefix (argc - 1, args);
|
||||
if (! prefix)
|
||||
return grub_errno;
|
||||
|
||||
r = append_menu_entry (argc - 1, (const char **) args,
|
||||
ctxt->state[0].args, ctxt->state[1].arg,
|
||||
ctxt->state[2].arg, prefix, src + 1);
|
||||
|
||||
src[len - 1] = ch;
|
||||
args[argc - 1] = src;
|
||||
grub_free (prefix);
|
||||
return r;
|
||||
}
|
||||
|
||||
static grub_extcmd_t cmd;
|
||||
|
||||
void
|
||||
grub_menu_init (void)
|
||||
{
|
||||
cmd = grub_register_extcmd ("menuentry", grub_cmd_menuentry,
|
||||
GRUB_COMMAND_FLAG_BOTH | GRUB_COMMAND_FLAG_BLOCKS,
|
||||
N_("BLOCK"), N_("Define a menuentry."), options);
|
||||
}
|
||||
|
||||
void
|
||||
grub_menu_fini (void)
|
||||
{
|
||||
grub_unregister_extcmd (cmd);
|
||||
}
|
|
@ -142,112 +142,6 @@ grub_mini_cmd_root (struct grub_command *cmd __attribute__ ((unused)),
|
|||
return 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void
|
||||
grub_rescue_cmd_testload (int argc, char *argv[])
|
||||
{
|
||||
grub_file_t file;
|
||||
char *buf;
|
||||
grub_ssize_t size;
|
||||
grub_ssize_t pos;
|
||||
auto void read_func (unsigned long sector, unsigned offset, unsigned len);
|
||||
|
||||
void read_func (unsigned long sector __attribute__ ((unused)),
|
||||
unsigned offset __attribute__ ((unused)),
|
||||
unsigned len __attribute__ ((unused)))
|
||||
{
|
||||
grub_putchar ('.');
|
||||
grub_refresh ();
|
||||
}
|
||||
|
||||
if (argc < 1)
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_ARGUMENT, "no file specified");
|
||||
return;
|
||||
}
|
||||
|
||||
file = grub_file_open (argv[0]);
|
||||
if (! file)
|
||||
return;
|
||||
|
||||
size = grub_file_size (file) & ~(GRUB_DISK_SECTOR_SIZE - 1);
|
||||
if (size == 0)
|
||||
{
|
||||
grub_file_close (file);
|
||||
return;
|
||||
}
|
||||
|
||||
buf = grub_malloc (size);
|
||||
if (! buf)
|
||||
goto fail;
|
||||
|
||||
grub_printf ("Reading %s sequentially", argv[0]);
|
||||
file->read_hook = read_func;
|
||||
if (grub_file_read (file, buf, size) != size)
|
||||
goto fail;
|
||||
grub_printf (" Done.\n");
|
||||
|
||||
/* Read sequentially again. */
|
||||
grub_printf ("Reading %s sequentially again", argv[0]);
|
||||
if (grub_file_seek (file, 0) < 0)
|
||||
goto fail;
|
||||
|
||||
for (pos = 0; pos < size; pos += GRUB_DISK_SECTOR_SIZE)
|
||||
{
|
||||
char sector[GRUB_DISK_SECTOR_SIZE];
|
||||
|
||||
if (grub_file_read (file, sector, GRUB_DISK_SECTOR_SIZE)
|
||||
!= GRUB_DISK_SECTOR_SIZE)
|
||||
goto fail;
|
||||
|
||||
if (grub_memcmp (sector, buf + pos, GRUB_DISK_SECTOR_SIZE) != 0)
|
||||
{
|
||||
grub_printf ("\nDiffers in %d\n", pos);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
grub_printf (" Done.\n");
|
||||
|
||||
/* Read backwards and compare. */
|
||||
grub_printf ("Reading %s backwards", argv[0]);
|
||||
pos = size;
|
||||
while (pos > 0)
|
||||
{
|
||||
char sector[GRUB_DISK_SECTOR_SIZE];
|
||||
|
||||
pos -= GRUB_DISK_SECTOR_SIZE;
|
||||
|
||||
if (grub_file_seek (file, pos) < 0)
|
||||
goto fail;
|
||||
|
||||
if (grub_file_read (file, sector, GRUB_DISK_SECTOR_SIZE)
|
||||
!= GRUB_DISK_SECTOR_SIZE)
|
||||
goto fail;
|
||||
|
||||
if (grub_memcmp (sector, buf + pos, GRUB_DISK_SECTOR_SIZE) != 0)
|
||||
{
|
||||
int i;
|
||||
|
||||
grub_printf ("\nDiffers in %d\n", pos);
|
||||
|
||||
for (i = 0; i < GRUB_DISK_SECTOR_SIZE; i++)
|
||||
grub_putchar (buf[pos + i]);
|
||||
|
||||
if (i)
|
||||
grub_refresh ();
|
||||
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
grub_printf (" Done.\n");
|
||||
|
||||
fail:
|
||||
|
||||
grub_file_close (file);
|
||||
grub_free (buf);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* dump ADDRESS [SIZE] */
|
||||
static grub_err_t
|
||||
grub_mini_cmd_dump (struct grub_command *cmd __attribute__ ((unused)),
|
||||
|
|
|
@ -45,9 +45,9 @@ static const struct grub_arg_option options[] =
|
|||
};
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_probe (grub_extcmd_t cmd, int argc, char **args)
|
||||
grub_cmd_probe (grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
{
|
||||
struct grub_arg_list *state = cmd->state;
|
||||
struct grub_arg_list *state = ctxt->state;
|
||||
grub_device_t dev;
|
||||
grub_fs_t fs;
|
||||
char *ptr;
|
||||
|
|
|
@ -20,37 +20,104 @@
|
|||
#include <grub/dl.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/command.h>
|
||||
#include <grub/err.h>
|
||||
#include <grub/env.h>
|
||||
#include <grub/extcmd.h>
|
||||
#include <grub/i18n.h>
|
||||
#include <grub/script_sh.h>
|
||||
#include <regex.h>
|
||||
|
||||
static const struct grub_arg_option options[] =
|
||||
{
|
||||
{ "set", 's', GRUB_ARG_OPTION_REPEATABLE,
|
||||
N_("Variable names to update with matches."),
|
||||
N_("[NUMBER:]VARNAME"), ARG_TYPE_STRING },
|
||||
{ 0, 0, 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_regexp (grub_command_t cmd __attribute__ ((unused)),
|
||||
int argc, char **args)
|
||||
set_matches (char **varnames, char *str, grub_size_t nmatches,
|
||||
regmatch_t *matches)
|
||||
{
|
||||
int i;
|
||||
char ch;
|
||||
char *p;
|
||||
char *q;
|
||||
grub_err_t err;
|
||||
unsigned long j;
|
||||
|
||||
auto void setvar (char *v, regmatch_t *m);
|
||||
void setvar (char *v, regmatch_t *m)
|
||||
{
|
||||
ch = str[m->rm_eo];
|
||||
str[m->rm_eo] = '\0';
|
||||
err = grub_env_set (v, str + m->rm_so);
|
||||
str[m->rm_eo] = ch;
|
||||
}
|
||||
|
||||
for (i = 0; varnames && varnames[i]; i++)
|
||||
{
|
||||
if (! (p = grub_strchr (varnames[i], ':')))
|
||||
{
|
||||
/* varname w/o index defaults to 1 */
|
||||
if (nmatches < 2 || matches[1].rm_so == -1)
|
||||
grub_env_unset (varnames[i]);
|
||||
else
|
||||
setvar (varnames[i], &matches[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
j = grub_strtoul (varnames[i], &q, 10);
|
||||
if (q != p)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
"invalid variable name format %s", varnames[i]);
|
||||
|
||||
if (nmatches <= j || matches[j].rm_so == -1)
|
||||
grub_env_unset (p + 1);
|
||||
else
|
||||
setvar (p + 1, &matches[j]);
|
||||
}
|
||||
|
||||
if (err != GRUB_ERR_NONE)
|
||||
return err;
|
||||
}
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_regexp (grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
{
|
||||
int argn = 0;
|
||||
int matches = 0;
|
||||
regex_t regex;
|
||||
int ret;
|
||||
grub_size_t s;
|
||||
char *comperr;
|
||||
grub_err_t err;
|
||||
regmatch_t *matches = 0;
|
||||
|
||||
if (argc != 2)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "2 arguments expected");
|
||||
|
||||
ret = regcomp (®ex, args[0], RE_SYNTAX_GNU_AWK);
|
||||
ret = regcomp (®ex, args[0], REG_EXTENDED);
|
||||
if (ret)
|
||||
goto fail;
|
||||
|
||||
ret = regexec (®ex, args[1], 0, 0, 0);
|
||||
matches = grub_zalloc (sizeof (*matches) * (regex.re_nsub + 1));
|
||||
if (! matches)
|
||||
goto fail;
|
||||
|
||||
ret = regexec (®ex, args[1], regex.re_nsub + 1, matches, 0);
|
||||
if (!ret)
|
||||
{
|
||||
err = set_matches (ctxt->state[0].args, args[1],
|
||||
regex.re_nsub + 1, matches);
|
||||
regfree (®ex);
|
||||
return GRUB_ERR_NONE;
|
||||
grub_free (matches);
|
||||
return err;
|
||||
}
|
||||
|
||||
fail:
|
||||
grub_free (matches);
|
||||
s = regerror (ret, ®ex, 0, 0);
|
||||
comperr = grub_malloc (s);
|
||||
if (!comperr)
|
||||
|
@ -65,16 +132,20 @@ grub_cmd_regexp (grub_command_t cmd __attribute__ ((unused)),
|
|||
return err;
|
||||
}
|
||||
|
||||
static grub_command_t cmd;
|
||||
static grub_extcmd_t cmd;
|
||||
|
||||
GRUB_MOD_INIT(regexp)
|
||||
{
|
||||
cmd = grub_register_command ("regexp", grub_cmd_regexp,
|
||||
N_("REGEXP STRING"),
|
||||
N_("Test if REGEXP matches STRING."));
|
||||
cmd = grub_register_extcmd ("regexp", grub_cmd_regexp,
|
||||
GRUB_COMMAND_FLAG_BOTH, N_("REGEXP STRING"),
|
||||
N_("Test if REGEXP matches STRING."), options);
|
||||
|
||||
/* Setup GRUB script wildcard translator. */
|
||||
grub_wildcard_translator = &grub_filename_translator;
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(regexp)
|
||||
{
|
||||
grub_unregister_command (cmd);
|
||||
grub_unregister_extcmd (cmd);
|
||||
grub_wildcard_translator = 0;
|
||||
}
|
||||
|
|
|
@ -54,6 +54,7 @@ FUNC_NAME (const char *key, const char *var, int no_floppy)
|
|||
if (! buf)
|
||||
return 1;
|
||||
|
||||
grub_file_filter_disable_compression ();
|
||||
file = grub_file_open (buf);
|
||||
if (file)
|
||||
{
|
||||
|
|
|
@ -50,9 +50,9 @@ enum options
|
|||
};
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_search (grub_extcmd_t cmd, int argc, char **args)
|
||||
grub_cmd_search (grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
{
|
||||
struct grub_arg_list *state = cmd->state;
|
||||
struct grub_arg_list *state = ctxt->state;
|
||||
const char *var = 0;
|
||||
|
||||
if (argc == 0)
|
||||
|
|
|
@ -155,7 +155,7 @@ grub_setpci_iter (grub_pci_device_t dev, grub_pci_id_t pciid)
|
|||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_setpci (grub_extcmd_t cmd, int argc, char **argv)
|
||||
grub_cmd_setpci (grub_extcmd_context_t ctxt, int argc, char **argv)
|
||||
{
|
||||
const char *ptr;
|
||||
unsigned i;
|
||||
|
@ -163,14 +163,14 @@ grub_cmd_setpci (grub_extcmd_t cmd, int argc, char **argv)
|
|||
pciid_check_value = 0;
|
||||
pciid_check_mask = 0;
|
||||
|
||||
if (cmd->state[0].set)
|
||||
if (ctxt->state[0].set)
|
||||
{
|
||||
ptr = cmd->state[0].arg;
|
||||
ptr = ctxt->state[0].arg;
|
||||
pciid_check_value |= (grub_strtoul (ptr, (char **) &ptr, 16) & 0xffff);
|
||||
if (grub_errno == GRUB_ERR_BAD_NUMBER)
|
||||
{
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
ptr = cmd->state[0].arg;
|
||||
ptr = ctxt->state[0].arg;
|
||||
}
|
||||
else
|
||||
pciid_check_mask |= 0xffff;
|
||||
|
@ -191,11 +191,11 @@ grub_cmd_setpci (grub_extcmd_t cmd, int argc, char **argv)
|
|||
|
||||
check_bus = check_device = check_function = 0;
|
||||
|
||||
if (cmd->state[1].set)
|
||||
if (ctxt->state[1].set)
|
||||
{
|
||||
const char *optr;
|
||||
|
||||
ptr = cmd->state[1].arg;
|
||||
ptr = ctxt->state[1].arg;
|
||||
optr = ptr;
|
||||
bus = grub_strtoul (ptr, (char **) &ptr, 16);
|
||||
if (grub_errno == GRUB_ERR_BAD_NUMBER)
|
||||
|
@ -229,8 +229,8 @@ grub_cmd_setpci (grub_extcmd_t cmd, int argc, char **argv)
|
|||
}
|
||||
}
|
||||
|
||||
if (cmd->state[2].set)
|
||||
varname = cmd->state[2].arg;
|
||||
if (ctxt->state[2].set)
|
||||
varname = ctxt->state[2].arg;
|
||||
else
|
||||
varname = NULL;
|
||||
|
||||
|
|
|
@ -60,9 +60,9 @@ grub_interruptible_millisleep (grub_uint32_t ms)
|
|||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_sleep (grub_extcmd_t cmd, int argc, char **args)
|
||||
grub_cmd_sleep (grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
{
|
||||
struct grub_arg_list *state = cmd->state;
|
||||
struct grub_arg_list *state = ctxt->state;
|
||||
int n;
|
||||
|
||||
if (argc != 1)
|
||||
|
|
|
@ -334,6 +334,7 @@ test_parse (char **args, int *argn, int argc)
|
|||
if (grub_strcmp (args[*argn], "-s") == 0)
|
||||
{
|
||||
grub_file_t file;
|
||||
grub_file_filter_disable_compression ();
|
||||
file = grub_file_open (args[*argn + 1]);
|
||||
update_val (file && (grub_file_size (file) != 0));
|
||||
if (file)
|
||||
|
|
155
grub-core/commands/testload.c
Normal file
155
grub-core/commands/testload.c
Normal file
|
@ -0,0 +1,155 @@
|
|||
/* minicmd.c - commands for the rescue mode */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2003,2005,2006,2007,2009,2010 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GRUB is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <grub/dl.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/err.h>
|
||||
#include <grub/env.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/file.h>
|
||||
#include <grub/disk.h>
|
||||
#include <grub/term.h>
|
||||
#include <grub/loader.h>
|
||||
#include <grub/command.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_testload (struct grub_command *cmd __attribute__ ((unused)),
|
||||
int argc, char *argv[])
|
||||
{
|
||||
grub_file_t file;
|
||||
char *buf;
|
||||
grub_size_t size;
|
||||
grub_off_t pos;
|
||||
auto void NESTED_FUNC_ATTR read_func (grub_disk_addr_t sector, unsigned offset, unsigned len);
|
||||
|
||||
void NESTED_FUNC_ATTR read_func (grub_disk_addr_t sector __attribute__ ((unused)),
|
||||
unsigned offset __attribute__ ((unused)),
|
||||
unsigned len __attribute__ ((unused)))
|
||||
{
|
||||
grub_xputs (".");
|
||||
grub_refresh ();
|
||||
}
|
||||
|
||||
if (argc < 1)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "no file specified");
|
||||
|
||||
file = grub_file_open (argv[0]);
|
||||
if (! file)
|
||||
return grub_errno;
|
||||
|
||||
size = grub_file_size (file) & ~(GRUB_DISK_SECTOR_SIZE - 1);
|
||||
if (size == 0)
|
||||
{
|
||||
grub_file_close (file);
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
buf = grub_malloc (size);
|
||||
if (! buf)
|
||||
goto fail;
|
||||
|
||||
grub_printf ("Reading %s sequentially", argv[0]);
|
||||
file->read_hook = read_func;
|
||||
if (grub_file_read (file, buf, size) != (grub_ssize_t) size)
|
||||
goto fail;
|
||||
grub_printf (" Done.\n");
|
||||
|
||||
/* Read sequentially again. */
|
||||
grub_printf ("Reading %s sequentially again", argv[0]);
|
||||
grub_file_seek (file, 0);
|
||||
|
||||
for (pos = 0; pos < size; pos += GRUB_DISK_SECTOR_SIZE)
|
||||
{
|
||||
char sector[GRUB_DISK_SECTOR_SIZE];
|
||||
|
||||
if (grub_file_read (file, sector, GRUB_DISK_SECTOR_SIZE)
|
||||
!= GRUB_DISK_SECTOR_SIZE)
|
||||
goto fail;
|
||||
|
||||
if (grub_memcmp (sector, buf + pos, GRUB_DISK_SECTOR_SIZE) != 0)
|
||||
{
|
||||
grub_printf ("\nDiffers in %lld\n", (unsigned long long) pos);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
grub_printf (" Done.\n");
|
||||
|
||||
/* Read backwards and compare. */
|
||||
grub_printf ("Reading %s backwards", argv[0]);
|
||||
pos = size;
|
||||
while (pos > 0)
|
||||
{
|
||||
char sector[GRUB_DISK_SECTOR_SIZE];
|
||||
|
||||
pos -= GRUB_DISK_SECTOR_SIZE;
|
||||
|
||||
grub_file_seek (file, pos);
|
||||
|
||||
if (grub_file_read (file, sector, GRUB_DISK_SECTOR_SIZE)
|
||||
!= GRUB_DISK_SECTOR_SIZE)
|
||||
goto fail;
|
||||
|
||||
if (grub_memcmp (sector, buf + pos, GRUB_DISK_SECTOR_SIZE) != 0)
|
||||
{
|
||||
int i;
|
||||
|
||||
grub_printf ("\nDiffers in %lld\n", (unsigned long long) pos);
|
||||
|
||||
for (i = 0; i < GRUB_DISK_SECTOR_SIZE; i++)
|
||||
{
|
||||
grub_printf ("%02x ", buf[pos + i]);
|
||||
if ((i & 15) == 15)
|
||||
grub_printf ("\n");
|
||||
}
|
||||
|
||||
if (i)
|
||||
grub_refresh ();
|
||||
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
grub_printf (" Done.\n");
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
|
||||
fail:
|
||||
|
||||
grub_file_close (file);
|
||||
grub_free (buf);
|
||||
|
||||
if (!grub_errno)
|
||||
grub_error (GRUB_ERR_IO, "bad read");
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
static grub_command_t cmd;
|
||||
|
||||
GRUB_MOD_INIT(testload)
|
||||
{
|
||||
cmd =
|
||||
grub_register_command ("testload", grub_cmd_testload,
|
||||
N_("FILE"),
|
||||
N_("Load the same file in multiple ways."));
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(testload)
|
||||
{
|
||||
grub_unregister_command (cmd);
|
||||
}
|
494
grub-core/commands/wildcard.c
Normal file
494
grub-core/commands/wildcard.c
Normal file
|
@ -0,0 +1,494 @@
|
|||
/* wildcard.c - Wildcard character expansion for GRUB script. */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2010 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GRUB is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <grub/mm.h>
|
||||
#include <grub/fs.h>
|
||||
#include <grub/env.h>
|
||||
#include <grub/file.h>
|
||||
#include <grub/device.h>
|
||||
#include <grub/script_sh.h>
|
||||
|
||||
#include <regex.h>
|
||||
|
||||
static inline int isregexop (char ch);
|
||||
static char ** merge (char **lhs, char **rhs);
|
||||
static char *make_dir (const char *prefix, const char *start, const char *end);
|
||||
static int make_regex (const char *regex_start, const char *regex_end,
|
||||
regex_t *regexp);
|
||||
static void split_path (const char *path, const char **suffix_end, const char **regex_end);
|
||||
static char ** match_devices (const regex_t *regexp, int noparts);
|
||||
static char ** match_files (const char *prefix, const char *suffix_start,
|
||||
const char *suffix_end, const regex_t *regexp);
|
||||
|
||||
static char* wildcard_escape (const char *s);
|
||||
static char* wildcard_unescape (const char *s);
|
||||
static grub_err_t wildcard_expand (const char *s, char ***strs);
|
||||
|
||||
struct grub_script_wildcard_translator grub_filename_translator = {
|
||||
.expand = wildcard_expand,
|
||||
.escape = wildcard_escape,
|
||||
.unescape = wildcard_unescape
|
||||
};
|
||||
|
||||
static char **
|
||||
merge (char **dest, char **ps)
|
||||
{
|
||||
int i;
|
||||
int j;
|
||||
char **p;
|
||||
|
||||
if (! dest)
|
||||
return ps;
|
||||
|
||||
if (! ps)
|
||||
return dest;
|
||||
|
||||
for (i = 0; dest[i]; i++)
|
||||
;
|
||||
for (j = 0; ps[j]; j++)
|
||||
;
|
||||
|
||||
p = grub_realloc (dest, sizeof (char*) * (i + j + 1));
|
||||
if (! p)
|
||||
{
|
||||
grub_free (dest);
|
||||
grub_free (ps);
|
||||
return 0;
|
||||
}
|
||||
|
||||
dest = p;
|
||||
for (j = 0; ps[j]; j++)
|
||||
dest[i++] = ps[j];
|
||||
dest[i] = 0;
|
||||
|
||||
grub_free (ps);
|
||||
return dest;
|
||||
}
|
||||
|
||||
static inline int
|
||||
isregexop (char ch)
|
||||
{
|
||||
return grub_strchr ("*.\\", ch) ? 1 : 0;
|
||||
}
|
||||
|
||||
static char *
|
||||
make_dir (const char *prefix, const char *start, const char *end)
|
||||
{
|
||||
char ch;
|
||||
unsigned i;
|
||||
unsigned n;
|
||||
char *result;
|
||||
|
||||
i = grub_strlen (prefix);
|
||||
n = i + end - start;
|
||||
|
||||
result = grub_malloc (n + 1);
|
||||
if (! result)
|
||||
return 0;
|
||||
|
||||
grub_strcpy (result, prefix);
|
||||
while (start < end && (ch = *start++))
|
||||
if (ch == '\\' && isregexop (*start))
|
||||
result[i++] = *start++;
|
||||
else
|
||||
result[i++] = ch;
|
||||
|
||||
result[i] = '\0';
|
||||
return result;
|
||||
}
|
||||
|
||||
static int
|
||||
make_regex (const char *start, const char *end, regex_t *regexp)
|
||||
{
|
||||
char ch;
|
||||
int i = 0;
|
||||
unsigned len = end - start;
|
||||
char *buffer = grub_malloc (len * 2 + 2 + 1); /* worst case size. */
|
||||
|
||||
if (! buffer)
|
||||
return 1;
|
||||
|
||||
buffer[i++] = '^';
|
||||
while (start < end)
|
||||
{
|
||||
/* XXX Only * expansion for now. */
|
||||
switch ((ch = *start++))
|
||||
{
|
||||
case '\\':
|
||||
buffer[i++] = ch;
|
||||
if (*start != '\0')
|
||||
buffer[i++] = *start++;
|
||||
break;
|
||||
|
||||
case '.':
|
||||
buffer[i++] = '\\';
|
||||
buffer[i++] = '.';
|
||||
break;
|
||||
|
||||
case '*':
|
||||
buffer[i++] = '.';
|
||||
buffer[i++] = '*';
|
||||
break;
|
||||
|
||||
default:
|
||||
buffer[i++] = ch;
|
||||
}
|
||||
}
|
||||
buffer[i++] = '$';
|
||||
buffer[i] = '\0';
|
||||
|
||||
if (regcomp (regexp, buffer, RE_SYNTAX_GNU_AWK))
|
||||
{
|
||||
grub_free (buffer);
|
||||
return 1;
|
||||
}
|
||||
|
||||
grub_free (buffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Split `str' into two parts: (1) dirname that is regexop free (2)
|
||||
dirname that has a regexop. */
|
||||
static void
|
||||
split_path (const char *str, const char **noregexop, const char **regexop)
|
||||
{
|
||||
char ch = 0;
|
||||
int regex = 0;
|
||||
|
||||
const char *end;
|
||||
const char *split; /* points till the end of dirnaname that doesn't
|
||||
need expansion. */
|
||||
|
||||
split = end = str;
|
||||
while ((ch = *end))
|
||||
{
|
||||
if (ch == '\\' && end[1])
|
||||
end++;
|
||||
|
||||
else if (isregexop (ch))
|
||||
regex = 1;
|
||||
|
||||
else if (ch == '/' && ! regex)
|
||||
split = end + 1; /* forward to next regexop-free dirname */
|
||||
|
||||
else if (ch == '/' && regex)
|
||||
break; /* stop at the first dirname with a regexop */
|
||||
|
||||
end++;
|
||||
}
|
||||
|
||||
*regexop = end;
|
||||
if (! regex)
|
||||
*noregexop = end;
|
||||
else
|
||||
*noregexop = split;
|
||||
}
|
||||
|
||||
static char **
|
||||
match_devices (const regex_t *regexp, int noparts)
|
||||
{
|
||||
int i;
|
||||
int ndev;
|
||||
char **devs;
|
||||
|
||||
auto int match (const char *name);
|
||||
int match (const char *name)
|
||||
{
|
||||
char **t;
|
||||
char *buffer;
|
||||
|
||||
/* skip partitions if asked to. */
|
||||
if (noparts && grub_strchr(name, ','))
|
||||
return 0;
|
||||
|
||||
buffer = grub_xasprintf ("(%s)", name);
|
||||
if (! buffer)
|
||||
return 1;
|
||||
|
||||
grub_dprintf ("expand", "matching: %s\n", buffer);
|
||||
if (regexec (regexp, buffer, 0, 0, 0))
|
||||
{
|
||||
grub_free (buffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
t = grub_realloc (devs, sizeof (char*) * (ndev + 2));
|
||||
if (! t)
|
||||
return 1;
|
||||
|
||||
devs = t;
|
||||
devs[ndev++] = buffer;
|
||||
devs[ndev] = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
ndev = 0;
|
||||
devs = 0;
|
||||
|
||||
if (grub_device_iterate (match))
|
||||
goto fail;
|
||||
|
||||
return devs;
|
||||
|
||||
fail:
|
||||
|
||||
for (i = 0; devs && devs[i]; i++)
|
||||
grub_free (devs[i]);
|
||||
|
||||
if (devs)
|
||||
grub_free (devs);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char **
|
||||
match_files (const char *prefix, const char *suffix, const char *end,
|
||||
const regex_t *regexp)
|
||||
{
|
||||
int i;
|
||||
int error;
|
||||
char **files;
|
||||
unsigned nfile;
|
||||
char *dir;
|
||||
const char *path;
|
||||
char *device_name;
|
||||
grub_fs_t fs;
|
||||
grub_device_t dev;
|
||||
|
||||
auto int match (const char *name, const struct grub_dirhook_info *info);
|
||||
int match (const char *name, const struct grub_dirhook_info *info)
|
||||
{
|
||||
char **t;
|
||||
char *buffer;
|
||||
|
||||
/* skip . and .. names */
|
||||
if (grub_strcmp(".", name) == 0 || grub_strcmp("..", name) == 0)
|
||||
return 0;
|
||||
|
||||
grub_dprintf ("expand", "matching: %s in %s\n", name, dir);
|
||||
if (regexec (regexp, name, 0, 0, 0))
|
||||
return 0;
|
||||
|
||||
buffer = grub_xasprintf ("%s%s", dir, name);
|
||||
if (! buffer)
|
||||
return 1;
|
||||
|
||||
t = grub_realloc (files, sizeof (char*) * (nfile + 2));
|
||||
if (! t)
|
||||
{
|
||||
grub_free (buffer);
|
||||
return 1;
|
||||
}
|
||||
|
||||
files = t;
|
||||
files[nfile++] = buffer;
|
||||
files[nfile] = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
nfile = 0;
|
||||
files = 0;
|
||||
dev = 0;
|
||||
device_name = 0;
|
||||
grub_error_push ();
|
||||
|
||||
dir = make_dir (prefix, suffix, end);
|
||||
if (! dir)
|
||||
goto fail;
|
||||
|
||||
device_name = grub_file_get_device_name (dir);
|
||||
dev = grub_device_open (device_name);
|
||||
if (! dev)
|
||||
goto fail;
|
||||
|
||||
fs = grub_fs_probe (dev);
|
||||
if (! fs)
|
||||
goto fail;
|
||||
|
||||
path = grub_strchr (dir, ')');
|
||||
if (! path)
|
||||
goto fail;
|
||||
path++;
|
||||
|
||||
if (fs->dir (dev, path, match))
|
||||
goto fail;
|
||||
|
||||
grub_free (dir);
|
||||
grub_device_close (dev);
|
||||
grub_free (device_name);
|
||||
grub_error_pop ();
|
||||
return files;
|
||||
|
||||
fail:
|
||||
|
||||
if (dir)
|
||||
grub_free (dir);
|
||||
|
||||
for (i = 0; files && files[i]; i++)
|
||||
grub_free (files[i]);
|
||||
|
||||
if (files)
|
||||
grub_free (files);
|
||||
|
||||
if (dev)
|
||||
grub_device_close (dev);
|
||||
|
||||
if (device_name)
|
||||
grub_free (device_name);
|
||||
|
||||
grub_error_pop ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char*
|
||||
wildcard_escape (const char *s)
|
||||
{
|
||||
int i;
|
||||
int len;
|
||||
char ch;
|
||||
char *p;
|
||||
|
||||
len = grub_strlen (s);
|
||||
p = grub_malloc (len * 2 + 1);
|
||||
if (! p)
|
||||
return NULL;
|
||||
|
||||
i = 0;
|
||||
while ((ch = *s++))
|
||||
{
|
||||
if (isregexop (ch))
|
||||
p[i++] = '\\';
|
||||
p[i++] = ch;
|
||||
}
|
||||
p[i] = '\0';
|
||||
return p;
|
||||
}
|
||||
|
||||
static char*
|
||||
wildcard_unescape (const char *s)
|
||||
{
|
||||
int i;
|
||||
int len;
|
||||
char ch;
|
||||
char *p;
|
||||
|
||||
len = grub_strlen (s);
|
||||
p = grub_malloc (len + 1);
|
||||
if (! p)
|
||||
return NULL;
|
||||
|
||||
i = 0;
|
||||
while ((ch = *s++))
|
||||
{
|
||||
if (ch == '\\' && isregexop (*s))
|
||||
p[i++] = *s++;
|
||||
else
|
||||
p[i++] = ch;
|
||||
}
|
||||
p[i] = '\0';
|
||||
return p;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
wildcard_expand (const char *s, char ***strs)
|
||||
{
|
||||
const char *start;
|
||||
const char *regexop;
|
||||
const char *noregexop;
|
||||
char **paths = 0;
|
||||
|
||||
unsigned i;
|
||||
regex_t regexp;
|
||||
|
||||
start = s;
|
||||
while (*start)
|
||||
{
|
||||
split_path (start, &noregexop, ®exop);
|
||||
if (noregexop >= regexop) /* no more wildcards */
|
||||
break;
|
||||
|
||||
if (make_regex (noregexop, regexop, ®exp))
|
||||
goto fail;
|
||||
|
||||
if (paths == 0)
|
||||
{
|
||||
if (start == noregexop) /* device part has regexop */
|
||||
paths = match_devices (®exp, *start != '(');
|
||||
|
||||
else if (*start == '(') /* device part explicit wo regexop */
|
||||
paths = match_files ("", start, noregexop, ®exp);
|
||||
|
||||
else if (*start == '/') /* no device part */
|
||||
{
|
||||
char **r;
|
||||
unsigned n;
|
||||
char *root;
|
||||
char *prefix;
|
||||
|
||||
root = grub_env_get ("root");
|
||||
if (! root)
|
||||
goto fail;
|
||||
|
||||
prefix = grub_xasprintf ("(%s)", root);
|
||||
if (! prefix)
|
||||
goto fail;
|
||||
|
||||
paths = match_files (prefix, start, noregexop, ®exp);
|
||||
grub_free (prefix);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
char **r = 0;
|
||||
|
||||
for (i = 0; paths[i]; i++)
|
||||
{
|
||||
char **p;
|
||||
|
||||
p = match_files (paths[i], start, noregexop, ®exp);
|
||||
if (! p)
|
||||
continue;
|
||||
|
||||
r = merge (r, p);
|
||||
if (! r)
|
||||
goto fail;
|
||||
}
|
||||
paths = r;
|
||||
}
|
||||
|
||||
regfree (®exp);
|
||||
if (! paths)
|
||||
goto done;
|
||||
|
||||
start = regexop;
|
||||
}
|
||||
|
||||
done:
|
||||
|
||||
*strs = paths;
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
|
||||
for (i = 0; paths && paths[i]; i++)
|
||||
grub_free (paths[i]);
|
||||
grub_free (paths);
|
||||
regfree (®exp);
|
||||
return grub_errno;
|
||||
}
|
|
@ -248,6 +248,9 @@ grub_biosdisk_get_drive (const char *name)
|
|||
{
|
||||
unsigned long drive;
|
||||
|
||||
if (name[0] == 'c' && name[1] == 'd' && name[2] == 0 && cd_drive)
|
||||
return cd_drive;
|
||||
|
||||
if ((name[0] != 'f' && name[0] != 'h') || name[1] != 'd')
|
||||
goto fail;
|
||||
|
||||
|
@ -270,6 +273,9 @@ grub_biosdisk_call_hook (int (*hook) (const char *name), int drive)
|
|||
{
|
||||
char name[10];
|
||||
|
||||
if (cd_drive && drive == cd_drive)
|
||||
return hook ("cd");
|
||||
|
||||
grub_snprintf (name, sizeof (name),
|
||||
(drive & 0x80) ? "hd%d" : "fd%d", drive & (~0x80));
|
||||
return hook (name);
|
||||
|
|
|
@ -71,9 +71,9 @@ delete_loopback (const char *name)
|
|||
|
||||
/* The command to add and remove loopback devices. */
|
||||
static grub_err_t
|
||||
grub_cmd_loopback (grub_extcmd_t cmd, int argc, char **args)
|
||||
grub_cmd_loopback (grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
{
|
||||
struct grub_arg_list *state = state = cmd->state;
|
||||
struct grub_arg_list *state = ctxt->state;
|
||||
grub_file_t file;
|
||||
struct grub_loopback *newdev;
|
||||
grub_err_t ret;
|
||||
|
@ -167,8 +167,11 @@ grub_loopback_open (const char *name, grub_disk_t disk)
|
|||
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't open device");
|
||||
|
||||
/* Use the filesize for the disk size, round up to a complete sector. */
|
||||
disk->total_sectors = ((dev->file->size + GRUB_DISK_SECTOR_SIZE - 1)
|
||||
/ GRUB_DISK_SECTOR_SIZE);
|
||||
if (dev->file->size != GRUB_FILE_SIZE_UNKNOWN)
|
||||
disk->total_sectors = ((dev->file->size + GRUB_DISK_SECTOR_SIZE - 1)
|
||||
/ GRUB_DISK_SECTOR_SIZE);
|
||||
else
|
||||
disk->total_sectors = GRUB_DISK_SIZE_UNKNOWN;
|
||||
disk->id = (unsigned long) dev;
|
||||
|
||||
disk->has_partitions = dev->has_partitions;
|
||||
|
|
|
@ -274,6 +274,10 @@ grub_lvm_scan_device (const char *name)
|
|||
struct grub_lvm_vg *vg;
|
||||
struct grub_lvm_pv *pv;
|
||||
|
||||
#ifdef GRUB_UTIL
|
||||
grub_util_info ("scanning %s for LVM", name);
|
||||
#endif
|
||||
|
||||
disk = grub_disk_open (name);
|
||||
if (!disk)
|
||||
return 0;
|
||||
|
@ -294,7 +298,12 @@ grub_lvm_scan_device (const char *name)
|
|||
|
||||
/* Return if we didn't find a label. */
|
||||
if (i == GRUB_LVM_LABEL_SCAN_SECTORS)
|
||||
goto fail;
|
||||
{
|
||||
#ifdef GRUB_UTIL
|
||||
grub_util_info ("no LVM signature found\n");
|
||||
#endif
|
||||
goto fail;
|
||||
}
|
||||
|
||||
pvh = (struct grub_lvm_pv_header *) (buf + grub_le_to_cpu32(lh->offset_xl));
|
||||
|
||||
|
@ -318,6 +327,9 @@ grub_lvm_scan_device (const char *name)
|
|||
grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
|
||||
"we don't support multiple LVM data areas");
|
||||
|
||||
#ifdef GRUB_UTIL
|
||||
grub_util_info ("we don't support multiple LVM data areas\n");
|
||||
#endif
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
@ -344,6 +356,9 @@ grub_lvm_scan_device (const char *name)
|
|||
{
|
||||
grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
|
||||
"unknown LVM metadata header");
|
||||
#ifdef GRUB_UTIL
|
||||
grub_util_info ("unknown LVM metadata header\n");
|
||||
#endif
|
||||
goto fail2;
|
||||
}
|
||||
|
||||
|
@ -364,7 +379,12 @@ grub_lvm_scan_device (const char *name)
|
|||
q++;
|
||||
|
||||
if (q == metadatabuf + mda_size)
|
||||
goto fail2;
|
||||
{
|
||||
#ifdef GRUB_UTIL
|
||||
grub_util_info ("error parsing metadata\n");
|
||||
#endif
|
||||
goto fail2;
|
||||
}
|
||||
|
||||
vgname_len = q - p;
|
||||
vgname = grub_malloc (vgname_len + 1);
|
||||
|
@ -376,7 +396,12 @@ grub_lvm_scan_device (const char *name)
|
|||
|
||||
p = grub_strstr (q, "id = \"");
|
||||
if (p == NULL)
|
||||
goto fail3;
|
||||
{
|
||||
#ifdef GRUB_UTIL
|
||||
grub_util_info ("couldn't find ID\n");
|
||||
#endif
|
||||
goto fail3;
|
||||
}
|
||||
p += sizeof ("id = \"") - 1;
|
||||
grub_memcpy (vg_id, p, GRUB_LVM_ID_STRLEN);
|
||||
vg_id[GRUB_LVM_ID_STRLEN] = '\0';
|
||||
|
@ -399,7 +424,12 @@ grub_lvm_scan_device (const char *name)
|
|||
|
||||
vg->extent_size = grub_lvm_getvalue (&p, "extent_size = ");
|
||||
if (p == NULL)
|
||||
goto fail4;
|
||||
{
|
||||
#ifdef GRUB_UTIL
|
||||
grub_util_info ("unknown extent size\n");
|
||||
#endif
|
||||
goto fail4;
|
||||
}
|
||||
|
||||
vg->lvs = NULL;
|
||||
vg->pvs = NULL;
|
||||
|
@ -439,11 +469,21 @@ grub_lvm_scan_device (const char *name)
|
|||
|
||||
pv->start = grub_lvm_getvalue (&p, "pe_start = ");
|
||||
if (p == NULL)
|
||||
goto pvs_fail;
|
||||
{
|
||||
#ifdef GRUB_UTIL
|
||||
grub_util_info ("unknown pe_start\n");
|
||||
#endif
|
||||
goto pvs_fail;
|
||||
}
|
||||
|
||||
p = grub_strchr (p, '}');
|
||||
if (p == NULL)
|
||||
goto pvs_fail;
|
||||
{
|
||||
#ifdef GRUB_UTIL
|
||||
grub_util_info ("error parsing pe_start\n");
|
||||
#endif
|
||||
goto pvs_fail;
|
||||
}
|
||||
p++;
|
||||
|
||||
pv->disk = NULL;
|
||||
|
@ -500,7 +540,12 @@ grub_lvm_scan_device (const char *name)
|
|||
|
||||
lv->segment_count = grub_lvm_getvalue (&p, "segment_count = ");
|
||||
if (p == NULL)
|
||||
goto lvs_fail;
|
||||
{
|
||||
#ifdef GRUB_UTIL
|
||||
grub_util_info ("unknown segment_count\n");
|
||||
#endif
|
||||
goto lvs_fail;
|
||||
}
|
||||
lv->segments = grub_malloc (sizeof (*seg) * lv->segment_count);
|
||||
seg = lv->segments;
|
||||
|
||||
|
@ -510,14 +555,29 @@ grub_lvm_scan_device (const char *name)
|
|||
|
||||
p = grub_strstr (p, "segment");
|
||||
if (p == NULL)
|
||||
goto lvs_segment_fail;
|
||||
{
|
||||
#ifdef GRUB_UTIL
|
||||
grub_util_info ("unknown segment\n");
|
||||
#endif
|
||||
goto lvs_segment_fail;
|
||||
}
|
||||
|
||||
seg->start_extent = grub_lvm_getvalue (&p, "start_extent = ");
|
||||
if (p == NULL)
|
||||
goto lvs_segment_fail;
|
||||
{
|
||||
#ifdef GRUB_UTIL
|
||||
grub_util_info ("unknown start_extent\n");
|
||||
#endif
|
||||
goto lvs_segment_fail;
|
||||
}
|
||||
seg->extent_count = grub_lvm_getvalue (&p, "extent_count = ");
|
||||
if (p == NULL)
|
||||
goto lvs_segment_fail;
|
||||
{
|
||||
#ifdef GRUB_UTIL
|
||||
grub_util_info ("unknown extent_count\n");
|
||||
#endif
|
||||
goto lvs_segment_fail;
|
||||
}
|
||||
|
||||
if (grub_lvm_checkvalue (&p, "type = ", "snapshot"))
|
||||
{
|
||||
|
@ -528,7 +588,12 @@ grub_lvm_scan_device (const char *name)
|
|||
|
||||
seg->stripe_count = grub_lvm_getvalue (&p, "stripe_count = ");
|
||||
if (p == NULL)
|
||||
goto lvs_segment_fail;
|
||||
{
|
||||
#ifdef GRUB_UTIL
|
||||
grub_util_info ("unknown stripe_count\n");
|
||||
#endif
|
||||
goto lvs_segment_fail;
|
||||
}
|
||||
|
||||
lv->size += seg->extent_count * vg->extent_size;
|
||||
|
||||
|
@ -541,7 +606,12 @@ grub_lvm_scan_device (const char *name)
|
|||
|
||||
p = grub_strstr (p, "stripes = [");
|
||||
if (p == NULL)
|
||||
goto lvs_segment_fail2;
|
||||
{
|
||||
#ifdef GRUB_UTIL
|
||||
grub_util_info ("unknown stripes\n");
|
||||
#endif
|
||||
goto lvs_segment_fail2;
|
||||
}
|
||||
p += sizeof("stripes = [") - 1;
|
||||
|
||||
for (j = 0; j < seg->stripe_count; j++)
|
||||
|
|
132
grub-core/fs/btrfs.c
Normal file
132
grub-core/fs/btrfs.c
Normal file
|
@ -0,0 +1,132 @@
|
|||
/* btrfs.c - B-tree file system. */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2010 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GRUB is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <grub/err.h>
|
||||
#include <grub/file.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/disk.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/types.h>
|
||||
|
||||
#define BTRFS_SIGNATURE "_BHRfS_M"
|
||||
|
||||
struct btrfs_superblock
|
||||
{
|
||||
grub_uint8_t dummy1[32];
|
||||
grub_uint16_t uuid[8];
|
||||
grub_uint8_t dummy2[16];
|
||||
grub_uint8_t signature[sizeof (BTRFS_SIGNATURE) - 1];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct grub_btrfs_data
|
||||
{
|
||||
struct btrfs_superblock sblock;
|
||||
};
|
||||
|
||||
static struct grub_btrfs_data *
|
||||
grub_btrfs_mount (grub_disk_t disk)
|
||||
{
|
||||
struct grub_btrfs_data *data = grub_malloc (sizeof (*data));
|
||||
if (! data)
|
||||
return NULL;
|
||||
|
||||
if (grub_disk_read (disk, 128, 0, sizeof (data->sblock),
|
||||
&data->sblock) != GRUB_ERR_NONE)
|
||||
goto fail;
|
||||
|
||||
if (grub_strncmp ((char *) data->sblock.signature, BTRFS_SIGNATURE, sizeof (BTRFS_SIGNATURE) - 1))
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_FS, "not a Btrfs filesystem");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return data;
|
||||
|
||||
fail:
|
||||
grub_free (data);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_btrfs_open (struct grub_file *file __attribute__ ((unused)),
|
||||
const char *name __attribute__ ((unused)))
|
||||
{
|
||||
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "only detection is supported for Btrfs");
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_btrfs_dir (grub_device_t device,
|
||||
const char *path __attribute__ ((unused)),
|
||||
int (*hook) (const char *filename,
|
||||
const struct grub_dirhook_info *info)
|
||||
__attribute__ ((unused)))
|
||||
{
|
||||
struct grub_btrfs_data *data = grub_btrfs_mount (device->disk);
|
||||
if (grub_errno)
|
||||
return grub_errno;
|
||||
|
||||
grub_free (data);
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_btrfs_uuid (grub_device_t device, char **uuid)
|
||||
{
|
||||
struct grub_btrfs_data *data;
|
||||
|
||||
*uuid = NULL;
|
||||
|
||||
data = grub_btrfs_mount (device->disk);
|
||||
if (! data)
|
||||
return grub_errno;
|
||||
|
||||
*uuid = grub_xasprintf ("%04x%04x-%04x-%04x-%04x-%04x%04x%04x",
|
||||
grub_be_to_cpu16 (data->sblock.uuid[0]),
|
||||
grub_be_to_cpu16 (data->sblock.uuid[1]),
|
||||
grub_be_to_cpu16 (data->sblock.uuid[2]),
|
||||
grub_be_to_cpu16 (data->sblock.uuid[3]),
|
||||
grub_be_to_cpu16 (data->sblock.uuid[4]),
|
||||
grub_be_to_cpu16 (data->sblock.uuid[5]),
|
||||
grub_be_to_cpu16 (data->sblock.uuid[6]),
|
||||
grub_be_to_cpu16 (data->sblock.uuid[7]));
|
||||
|
||||
grub_free (data);
|
||||
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
static struct grub_fs grub_btrfs_fs =
|
||||
{
|
||||
.name = "btrfs",
|
||||
.dir = grub_btrfs_dir,
|
||||
.open = grub_btrfs_open,
|
||||
.uuid = grub_btrfs_uuid,
|
||||
};
|
||||
|
||||
GRUB_MOD_INIT(btrfs)
|
||||
{
|
||||
grub_fs_register (&grub_btrfs_fs);
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(btrfs)
|
||||
{
|
||||
grub_fs_unregister (&grub_btrfs_fs);
|
||||
}
|
|
@ -41,7 +41,7 @@ struct grub_pxe_disk_data
|
|||
grub_uint32_t gateway_ip;
|
||||
};
|
||||
|
||||
struct grub_pxenv *grub_pxe_pxenv;
|
||||
struct grub_pxe_bangpxe *grub_pxe_pxenv;
|
||||
static grub_uint32_t grub_pxe_your_ip;
|
||||
static grub_uint32_t grub_pxe_default_server_ip;
|
||||
static grub_uint32_t grub_pxe_default_gateway_ip;
|
||||
|
@ -58,41 +58,47 @@ struct grub_pxe_data
|
|||
|
||||
static grub_uint32_t pxe_rm_entry = 0;
|
||||
|
||||
static struct grub_pxenv *
|
||||
static struct grub_pxe_bangpxe *
|
||||
grub_pxe_scan (void)
|
||||
{
|
||||
struct grub_bios_int_registers regs;
|
||||
struct grub_pxenv *ret;
|
||||
void *pxe;
|
||||
struct grub_pxenv *pxenv;
|
||||
struct grub_pxe_bangpxe *bangpxe;
|
||||
|
||||
regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT;
|
||||
|
||||
regs.ebx = 0;
|
||||
regs.ecx = 0;
|
||||
regs.eax = 0x5650;
|
||||
regs.es = 0;
|
||||
|
||||
grub_bios_interrupt (0x1a, ®s);
|
||||
|
||||
if ((regs.eax & 0xffff) != 0x564e)
|
||||
return NULL;
|
||||
ret = (struct grub_pxenv *) ((regs.es << 4) + (regs.ebx & 0xffff));
|
||||
if (grub_memcmp (ret->signature, GRUB_PXE_SIGNATURE, sizeof (ret->signature))
|
||||
|
||||
pxenv = (struct grub_pxenv *) ((regs.es << 4) + (regs.ebx & 0xffff));
|
||||
if (grub_memcmp (pxenv->signature, GRUB_PXE_SIGNATURE,
|
||||
sizeof (pxenv->signature))
|
||||
!= 0)
|
||||
return NULL;
|
||||
if (ret->version < 0x201)
|
||||
|
||||
if (pxenv->version < 0x201)
|
||||
return NULL;
|
||||
|
||||
pxe = (void *) ((((ret->pxe_ptr & 0xffff0000) >> 16) << 4)
|
||||
+ (ret->pxe_ptr & 0xffff));
|
||||
if (!pxe)
|
||||
bangpxe = (void *) ((((pxenv->pxe_ptr & 0xffff0000) >> 16) << 4)
|
||||
+ (pxenv->pxe_ptr & 0xffff));
|
||||
|
||||
if (!bangpxe)
|
||||
return NULL;
|
||||
|
||||
/* !PXE */
|
||||
if (*(grub_uint32_t *) pxe != 0x45585021)
|
||||
if (grub_memcmp (bangpxe->signature, GRUB_PXE_BANGPXE_SIGNATURE,
|
||||
sizeof (bangpxe->signature)) != 0)
|
||||
return NULL;
|
||||
|
||||
pxe_rm_entry = ret->rm_entry;
|
||||
return ret;
|
||||
pxe_rm_entry = bangpxe->rm_entry;
|
||||
|
||||
return bangpxe;
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -276,6 +282,7 @@ grub_pxefs_open (struct grub_file *file, const char *name)
|
|||
}
|
||||
|
||||
file->data = data;
|
||||
file->not_easly_seekable = 1;
|
||||
grub_memcpy (file_int, file, sizeof (struct grub_file));
|
||||
curr_file = file_int;
|
||||
|
||||
|
@ -321,7 +328,7 @@ grub_pxefs_read (grub_file_t file, char *buf, grub_size_t len)
|
|||
o.gateway_ip = disk_data->gateway_ip;
|
||||
grub_strcpy ((char *)&o.filename[0], data->filename);
|
||||
o.tftp_port = grub_cpu_to_be16 (GRUB_PXE_TFTP_PORT);
|
||||
o.packet_size = grub_pxe_blksize;
|
||||
o.packet_size = data->block_size;
|
||||
grub_pxe_call (GRUB_PXENV_TFTP_OPEN, &o, pxe_rm_entry);
|
||||
if (o.status)
|
||||
{
|
||||
|
@ -483,7 +490,7 @@ parse_dhcp_vendor (void *vend, int limit)
|
|||
static void
|
||||
grub_pxe_detect (void)
|
||||
{
|
||||
struct grub_pxenv *pxenv;
|
||||
struct grub_pxe_bangpxe *pxenv;
|
||||
struct grub_pxenv_get_cached_info ci;
|
||||
struct grub_pxenv_boot_player *bp;
|
||||
|
||||
|
|
|
@ -25,10 +25,13 @@
|
|||
#include <grub/dl.h>
|
||||
#include <grub/types.h>
|
||||
|
||||
#ifdef MODE_MINIX2
|
||||
#define GRUB_MINIX_MAGIC 0x2468
|
||||
#define GRUB_MINIX_MAGIC_30 0x2478
|
||||
#else
|
||||
#define GRUB_MINIX_MAGIC 0x137F
|
||||
#define GRUB_MINIX2_MAGIC 0x2468
|
||||
#define GRUB_MINIX_MAGIC_30 0x138F
|
||||
#define GRUB_MINIX2_MAGIC_30 0x2478
|
||||
#endif
|
||||
#define GRUB_MINIX_BSIZE 1024U
|
||||
#define GRUB_MINIX_LOG2_BSIZE 1
|
||||
#define GRUB_MINIX_ROOT_INODE 1
|
||||
|
@ -38,20 +41,25 @@
|
|||
#define GRUB_MINIX_IFDIR 0040000U
|
||||
#define GRUB_MINIX_IFLNK 0120000U
|
||||
|
||||
#define GRUB_MINIX_INODE(data,field) (data->version == 1 ? \
|
||||
data->inode. field : data->inode2. field)
|
||||
#define GRUB_MINIX_INODE_ENDIAN(data,field,bits1,bits2) (data->version == 1 ? \
|
||||
grub_le_to_cpu##bits1 (data->inode.field) : \
|
||||
grub_le_to_cpu##bits2 (data->inode2.field))
|
||||
#define GRUB_MINIX_INODE_SIZE(data) GRUB_MINIX_INODE_ENDIAN (data,size,16,32)
|
||||
#define GRUB_MINIX_INODE_MODE(data) GRUB_MINIX_INODE_ENDIAN (data,mode,16,16)
|
||||
#define GRUB_MINIX_INODE_DIR_ZONES(data,blk) GRUB_MINIX_INODE_ENDIAN \
|
||||
(data,dir_zones[blk],16,32)
|
||||
#define GRUB_MINIX_INODE_INDIR_ZONE(data) \
|
||||
GRUB_MINIX_INODE_ENDIAN (data,indir_zone,16,32)
|
||||
#define GRUB_MINIX_INODE_DINDIR_ZONE(data) \
|
||||
GRUB_MINIX_INODE_ENDIAN (data,double_indir_zone,16,32)
|
||||
#define GRUB_MINIX_INODE_BLKSZ(data) (data->version == 1 ? 2 : 4)
|
||||
#ifdef MODE_MINIX2
|
||||
typedef grub_uint32_t grub_minix_uintn_t;
|
||||
#define grub_minix_le_to_cpu_n grub_le_to_cpu32
|
||||
#else
|
||||
typedef grub_uint16_t grub_minix_uintn_t;
|
||||
#define grub_minix_le_to_cpu_n grub_le_to_cpu16
|
||||
#endif
|
||||
|
||||
#define GRUB_MINIX_INODE_BLKSZ(data) sizeof (grub_minix_uintn_t)
|
||||
|
||||
#define GRUB_MINIX_INODE_SIZE(data) (grub_minix_le_to_cpu_n (data->inode.size))
|
||||
#define GRUB_MINIX_INODE_MODE(data) (grub_le_to_cpu16 (data->inode.mode))
|
||||
#define GRUB_MINIX_INODE_DIR_ZONES(data,blk) (grub_minix_le_to_cpu_n \
|
||||
(data->inode.dir_zones[blk]))
|
||||
#define GRUB_MINIX_INODE_INDIR_ZONE(data) (grub_minix_le_to_cpu_n \
|
||||
(data->inode.indir_zone))
|
||||
#define GRUB_MINIX_INODE_DINDIR_ZONE(data) (grub_minix_le_to_cpu_n \
|
||||
(data->inode.double_indir_zone))
|
||||
|
||||
#define GRUB_MINIX_LOG2_ZONESZ (GRUB_MINIX_LOG2_BSIZE \
|
||||
+ grub_le_to_cpu16 (sblock->log2_zone_size))
|
||||
#define GRUB_MINIX_ZONESZ (GRUB_MINIX_BSIZE \
|
||||
|
@ -69,6 +77,7 @@ struct grub_minix_sblock
|
|||
grub_uint16_t magic;
|
||||
};
|
||||
|
||||
#ifndef MODE_MINIX2
|
||||
struct grub_minix_inode
|
||||
{
|
||||
grub_uint16_t mode;
|
||||
|
@ -82,7 +91,9 @@ struct grub_minix_inode
|
|||
grub_uint16_t double_indir_zone;
|
||||
};
|
||||
|
||||
struct grub_minix2_inode
|
||||
#else
|
||||
|
||||
struct grub_minix_inode
|
||||
{
|
||||
grub_uint16_t mode;
|
||||
grub_uint16_t nlinks;
|
||||
|
@ -99,16 +110,16 @@ struct grub_minix2_inode
|
|||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
/* Information about a "mounted" minix filesystem. */
|
||||
struct grub_minix_data
|
||||
{
|
||||
struct grub_minix_sblock sblock;
|
||||
struct grub_minix_inode inode;
|
||||
struct grub_minix2_inode inode2;
|
||||
int ino;
|
||||
int linknest;
|
||||
grub_disk_t disk;
|
||||
int version;
|
||||
int filename_size;
|
||||
};
|
||||
|
||||
|
@ -128,24 +139,12 @@ grub_minix_get_file_block (struct grub_minix_data *data, unsigned int blk)
|
|||
/* Read the block pointer in ZONE, on the offset NUM. */
|
||||
int grub_get_indir (int zone, int num)
|
||||
{
|
||||
if (data->version == 1)
|
||||
{
|
||||
grub_uint16_t indir16;
|
||||
grub_disk_read (data->disk,
|
||||
zone << GRUB_MINIX_LOG2_ZONESZ,
|
||||
sizeof (grub_uint16_t) * num,
|
||||
sizeof (grub_uint16_t), (char *) &indir16);
|
||||
return grub_le_to_cpu16 (indir16);
|
||||
}
|
||||
else
|
||||
{
|
||||
grub_uint32_t indir32;
|
||||
grub_disk_read (data->disk,
|
||||
zone << GRUB_MINIX_LOG2_ZONESZ,
|
||||
sizeof (grub_uint32_t) * num,
|
||||
sizeof (grub_uint32_t), (char *) &indir32);
|
||||
return grub_le_to_cpu32 (indir32);
|
||||
}
|
||||
grub_minix_uintn_t indirn;
|
||||
grub_disk_read (data->disk,
|
||||
zone << GRUB_MINIX_LOG2_ZONESZ,
|
||||
sizeof (grub_minix_uintn_t) * num,
|
||||
sizeof (grub_minix_uintn_t), (char *) &indirn);
|
||||
return grub_minix_le_to_cpu_n (indirn);
|
||||
}
|
||||
|
||||
/* Direct block. */
|
||||
|
@ -259,27 +258,13 @@ grub_minix_read_inode (struct grub_minix_data *data, int ino)
|
|||
+ grub_le_to_cpu16 (sblock->zone_bmap_size))
|
||||
<< GRUB_MINIX_LOG2_BSIZE);
|
||||
|
||||
if (data->version == 1)
|
||||
{
|
||||
block += ino / (GRUB_DISK_SECTOR_SIZE / sizeof (struct grub_minix_inode));
|
||||
int offs = (ino % (GRUB_DISK_SECTOR_SIZE
|
||||
/ sizeof (struct grub_minix_inode))
|
||||
* sizeof (struct grub_minix_inode));
|
||||
|
||||
grub_disk_read (data->disk, block, offs,
|
||||
sizeof (struct grub_minix_inode), &data->inode);
|
||||
}
|
||||
else
|
||||
{
|
||||
block += ino / (GRUB_DISK_SECTOR_SIZE
|
||||
/ sizeof (struct grub_minix2_inode));
|
||||
int offs = (ino
|
||||
% (GRUB_DISK_SECTOR_SIZE / sizeof (struct grub_minix2_inode))
|
||||
* sizeof (struct grub_minix2_inode));
|
||||
|
||||
grub_disk_read (data->disk, block, offs,
|
||||
sizeof (struct grub_minix2_inode),&data->inode2);
|
||||
}
|
||||
block += ino / (GRUB_DISK_SECTOR_SIZE / sizeof (struct grub_minix_inode));
|
||||
int offs = (ino % (GRUB_DISK_SECTOR_SIZE
|
||||
/ sizeof (struct grub_minix_inode))
|
||||
* sizeof (struct grub_minix_inode));
|
||||
|
||||
grub_disk_read (data->disk, block, offs,
|
||||
sizeof (struct grub_minix_inode), &data->inode);
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
@ -424,25 +409,9 @@ grub_minix_mount (grub_disk_t disk)
|
|||
goto fail;
|
||||
|
||||
if (grub_le_to_cpu16 (data->sblock.magic) == GRUB_MINIX_MAGIC)
|
||||
{
|
||||
data->version = 1;
|
||||
data->filename_size = 14;
|
||||
}
|
||||
else if (grub_le_to_cpu16 (data->sblock.magic) == GRUB_MINIX2_MAGIC)
|
||||
{
|
||||
data->version = 2;
|
||||
data->filename_size = 14;
|
||||
}
|
||||
data->filename_size = 14;
|
||||
else if (grub_le_to_cpu16 (data->sblock.magic) == GRUB_MINIX_MAGIC_30)
|
||||
{
|
||||
data->version = 1;
|
||||
data->filename_size = 30;
|
||||
}
|
||||
else if (grub_le_to_cpu16 (data->sblock.magic) == GRUB_MINIX2_MAGIC_30)
|
||||
{
|
||||
data->version = 2;
|
||||
data->filename_size = 30;
|
||||
}
|
||||
data->filename_size = 30;
|
||||
else
|
||||
goto fail;
|
||||
|
||||
|
@ -453,7 +422,11 @@ grub_minix_mount (grub_disk_t disk)
|
|||
|
||||
fail:
|
||||
grub_free (data);
|
||||
#ifdef MODE_MINIX2
|
||||
grub_error (GRUB_ERR_BAD_FS, "not a minix2 filesystem");
|
||||
#else
|
||||
grub_error (GRUB_ERR_BAD_FS, "not a minix filesystem");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -583,32 +556,36 @@ grub_minix_close (grub_file_t file)
|
|||
}
|
||||
|
||||
|
||||
static grub_err_t
|
||||
grub_minix_label (grub_device_t device __attribute ((unused)),
|
||||
char **label __attribute ((unused)))
|
||||
{
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
|
||||
static struct grub_fs grub_minix_fs =
|
||||
{
|
||||
#ifdef MODE_MINIX2
|
||||
.name = "minix2",
|
||||
#else
|
||||
.name = "minix",
|
||||
#endif
|
||||
.dir = grub_minix_dir,
|
||||
.open = grub_minix_open,
|
||||
.read = grub_minix_read,
|
||||
.close = grub_minix_close,
|
||||
.label = grub_minix_label,
|
||||
.next = 0
|
||||
};
|
||||
|
||||
#ifdef MODE_MINIX2
|
||||
GRUB_MOD_INIT(minix2)
|
||||
#else
|
||||
GRUB_MOD_INIT(minix)
|
||||
#endif
|
||||
{
|
||||
grub_fs_register (&grub_minix_fs);
|
||||
my_mod = mod;
|
||||
}
|
||||
|
||||
#ifdef MODE_MINIX2
|
||||
GRUB_MOD_FINI(minix2)
|
||||
#else
|
||||
GRUB_MOD_FINI(minix)
|
||||
#endif
|
||||
{
|
||||
grub_fs_unregister (&grub_minix_fs);
|
||||
}
|
||||
|
|
2
grub-core/fs/minix2.c
Normal file
2
grub-core/fs/minix2.c
Normal file
|
@ -0,0 +1,2 @@
|
|||
#define MODE_MINIX2 1
|
||||
#include "minix.c"
|
|
@ -26,7 +26,6 @@
|
|||
#include <grub/normal.h>
|
||||
#include <grub/file.h>
|
||||
#include <grub/kernel.h>
|
||||
#include <grub/gzio.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
/*
|
||||
|
@ -219,7 +218,7 @@ grub_gettext_translate (const char *orig)
|
|||
return ret;
|
||||
}
|
||||
|
||||
/* This is similar to grub_gzfile_open. */
|
||||
/* This is similar to grub_file_open. */
|
||||
static grub_file_t
|
||||
grub_mofile_open (const char *filename)
|
||||
{
|
||||
|
@ -229,7 +228,7 @@ grub_mofile_open (const char *filename)
|
|||
/* Using fd_mo and not another variable because
|
||||
it's needed for grub_gettext_get_info. */
|
||||
|
||||
fd_mo = grub_gzfile_open (filename, 1);
|
||||
fd_mo = grub_file_open (filename);
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
|
||||
if (!fd_mo)
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
#include <grub/i18n.h>
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_hello (struct grub_extcmd *cmd __attribute__ ((unused)),
|
||||
grub_cmd_hello (grub_extcmd_context_t ctxt __attribute__ ((unused)),
|
||||
int argc __attribute__ ((unused)),
|
||||
char **args __attribute__ ((unused)))
|
||||
{
|
||||
|
|
|
@ -74,6 +74,7 @@ grub_bufio_open (grub_file_t io, int size)
|
|||
file->data = bufio;
|
||||
file->read_hook = 0;
|
||||
file->fs = &grub_bufio_fs;
|
||||
file->not_easly_seekable = io->not_easly_seekable;
|
||||
|
||||
return file;
|
||||
}
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
#include <grub/misc.h>
|
||||
#include <grub/fs.h>
|
||||
#include <grub/file.h>
|
||||
#include <grub/gzio.h>
|
||||
#include <grub/dl.h>
|
||||
|
||||
/*
|
||||
* Window Size
|
||||
|
@ -206,7 +206,7 @@ test_header (grub_file_t file)
|
|||
|| ((hdr.flags & ORIG_NAME) && eat_field (gzio->file, -1))
|
||||
|| ((hdr.flags & COMMENT) && eat_field (gzio->file, -1)))
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_GZIP_DATA, "unsupported gzip format");
|
||||
grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, "unsupported gzip format");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -214,12 +214,14 @@ test_header (grub_file_t file)
|
|||
|
||||
grub_file_seek (gzio->file, grub_file_size (gzio->file) - 4);
|
||||
|
||||
if (grub_file_read (gzio->file, &orig_len, 4) != 4)
|
||||
if (grub_file_seekable (gzio->file))
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_FILE_TYPE, "unsupported gzip format");
|
||||
return 0;
|
||||
if (grub_file_read (gzio->file, &orig_len, 4) != 4)
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_FILE_TYPE, "unsupported gzip format");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* FIXME: this does not handle files whose original size is over 4GB.
|
||||
But how can we know the real original size? */
|
||||
file->size = grub_le_to_cpu32 (orig_len);
|
||||
|
@ -644,7 +646,7 @@ inflate_codes_in_window (grub_file_t file)
|
|||
{
|
||||
if (e == 99)
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_GZIP_DATA,
|
||||
grub_error (GRUB_ERR_BAD_COMPRESSED_DATA,
|
||||
"an unused code found");
|
||||
return 1;
|
||||
}
|
||||
|
@ -683,7 +685,7 @@ inflate_codes_in_window (grub_file_t file)
|
|||
{
|
||||
if (e == 99)
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_GZIP_DATA,
|
||||
grub_error (GRUB_ERR_BAD_COMPRESSED_DATA,
|
||||
"an unused code found");
|
||||
return 1;
|
||||
}
|
||||
|
@ -769,7 +771,7 @@ init_stored_block (grub_file_t file)
|
|||
DUMPBITS (16);
|
||||
NEEDBITS (16);
|
||||
if (gzio->block_len != (int) ((~b) & 0xffff))
|
||||
grub_error (GRUB_ERR_BAD_GZIP_DATA,
|
||||
grub_error (GRUB_ERR_BAD_COMPRESSED_DATA,
|
||||
"the length of a stored block does not match");
|
||||
DUMPBITS (16);
|
||||
|
||||
|
@ -803,7 +805,7 @@ init_fixed_block (grub_file_t file)
|
|||
if (huft_build (l, 288, 257, cplens, cplext, &gzio->tl, &gzio->bl) != 0)
|
||||
{
|
||||
if (grub_errno == GRUB_ERR_NONE)
|
||||
grub_error (GRUB_ERR_BAD_GZIP_DATA,
|
||||
grub_error (GRUB_ERR_BAD_COMPRESSED_DATA,
|
||||
"failed in building a Huffman code table");
|
||||
return;
|
||||
}
|
||||
|
@ -815,7 +817,7 @@ init_fixed_block (grub_file_t file)
|
|||
if (huft_build (l, 30, 0, cpdist, cpdext, &gzio->td, &gzio->bd) > 1)
|
||||
{
|
||||
if (grub_errno == GRUB_ERR_NONE)
|
||||
grub_error (GRUB_ERR_BAD_GZIP_DATA,
|
||||
grub_error (GRUB_ERR_BAD_COMPRESSED_DATA,
|
||||
"failed in building a Huffman code table");
|
||||
huft_free (gzio->tl);
|
||||
gzio->tl = 0;
|
||||
|
@ -862,7 +864,7 @@ init_dynamic_block (grub_file_t file)
|
|||
DUMPBITS (4);
|
||||
if (nl > 286 || nd > 30)
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_GZIP_DATA, "too much data");
|
||||
grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, "too much data");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -880,7 +882,7 @@ init_dynamic_block (grub_file_t file)
|
|||
gzio->bl = 7;
|
||||
if (huft_build (ll, 19, 19, NULL, NULL, &gzio->tl, &gzio->bl) != 0)
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_GZIP_DATA,
|
||||
grub_error (GRUB_ERR_BAD_COMPRESSED_DATA,
|
||||
"failed in building a Huffman code table");
|
||||
return;
|
||||
}
|
||||
|
@ -904,7 +906,7 @@ init_dynamic_block (grub_file_t file)
|
|||
DUMPBITS (2);
|
||||
if ((unsigned) i + j > n)
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_GZIP_DATA, "too many codes found");
|
||||
grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, "too many codes found");
|
||||
return;
|
||||
}
|
||||
while (j--)
|
||||
|
@ -917,7 +919,7 @@ init_dynamic_block (grub_file_t file)
|
|||
DUMPBITS (3);
|
||||
if ((unsigned) i + j > n)
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_GZIP_DATA, "too many codes found");
|
||||
grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, "too many codes found");
|
||||
return;
|
||||
}
|
||||
while (j--)
|
||||
|
@ -932,7 +934,7 @@ init_dynamic_block (grub_file_t file)
|
|||
DUMPBITS (7);
|
||||
if ((unsigned) i + j > n)
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_GZIP_DATA, "too many codes found");
|
||||
grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, "too many codes found");
|
||||
return;
|
||||
}
|
||||
while (j--)
|
||||
|
@ -954,7 +956,7 @@ init_dynamic_block (grub_file_t file)
|
|||
gzio->bl = lbits;
|
||||
if (huft_build (ll, nl, 257, cplens, cplext, &gzio->tl, &gzio->bl) != 0)
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_GZIP_DATA,
|
||||
grub_error (GRUB_ERR_BAD_COMPRESSED_DATA,
|
||||
"failed in building a Huffman code table");
|
||||
return;
|
||||
}
|
||||
|
@ -963,7 +965,7 @@ init_dynamic_block (grub_file_t file)
|
|||
{
|
||||
huft_free (gzio->tl);
|
||||
gzio->tl = 0;
|
||||
grub_error (GRUB_ERR_BAD_GZIP_DATA,
|
||||
grub_error (GRUB_ERR_BAD_COMPRESSED_DATA,
|
||||
"failed in building a Huffman code table");
|
||||
return;
|
||||
}
|
||||
|
@ -1039,7 +1041,7 @@ inflate_window (grub_file_t file)
|
|||
}
|
||||
|
||||
if (gzio->block_type > INFLATE_DYNAMIC)
|
||||
grub_error (GRUB_ERR_BAD_GZIP_DATA,
|
||||
grub_error (GRUB_ERR_BAD_COMPRESSED_DATA,
|
||||
"unknown block type %d", gzio->block_type);
|
||||
|
||||
if (grub_errno != GRUB_ERR_NONE)
|
||||
|
@ -1111,8 +1113,8 @@ initialize_tables (grub_file_t file)
|
|||
/* Open a new decompressing object on the top of IO. If TRANSPARENT is true,
|
||||
even if IO does not contain data compressed by gzip, return a valid file
|
||||
object. Note that this function won't close IO, even if an error occurs. */
|
||||
grub_file_t
|
||||
grub_gzio_open (grub_file_t io, int transparent)
|
||||
static grub_file_t
|
||||
grub_gzio_open (grub_file_t io)
|
||||
{
|
||||
grub_file_t file;
|
||||
grub_gzio_t gzio = 0;
|
||||
|
@ -1135,6 +1137,7 @@ grub_gzio_open (grub_file_t io, int transparent)
|
|||
file->data = gzio;
|
||||
file->read_hook = 0;
|
||||
file->fs = &grub_gzio_fs;
|
||||
file->not_easly_seekable = 1;
|
||||
|
||||
if (! test_header (file))
|
||||
{
|
||||
|
@ -1142,33 +1145,11 @@ grub_gzio_open (grub_file_t io, int transparent)
|
|||
grub_free (file);
|
||||
grub_file_seek (io, 0);
|
||||
|
||||
if (grub_errno == GRUB_ERR_BAD_FILE_TYPE && transparent)
|
||||
if (grub_errno == GRUB_ERR_BAD_FILE_TYPE)
|
||||
{
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
return io;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
/* This is similar to grub_gzio_open, but takes a file name as an argument. */
|
||||
grub_file_t
|
||||
grub_gzfile_open (const char *name, int transparent)
|
||||
{
|
||||
grub_file_t io, file;
|
||||
|
||||
io = grub_file_open (name);
|
||||
if (! io)
|
||||
return 0;
|
||||
|
||||
file = grub_gzio_open (io, transparent);
|
||||
if (! file)
|
||||
{
|
||||
grub_file_close (io);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return file;
|
||||
|
@ -1249,3 +1230,13 @@ static struct grub_fs grub_gzio_fs =
|
|||
.label = 0,
|
||||
.next = 0
|
||||
};
|
||||
|
||||
GRUB_MOD_INIT(gzio)
|
||||
{
|
||||
grub_file_filter_register (GRUB_FILE_FILTER_GZIO, grub_gzio_open);
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(gzio)
|
||||
{
|
||||
grub_file_filter_unregister (GRUB_FILE_FILTER_GZIO);
|
||||
}
|
||||
|
|
353
grub-core/io/xzio.c
Normal file
353
grub-core/io/xzio.c
Normal file
|
@ -0,0 +1,353 @@
|
|||
/* xzio.c - decompression support for xz */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2010 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GRUB is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <grub/err.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/file.h>
|
||||
#include <grub/fs.h>
|
||||
#include <grub/dl.h>
|
||||
|
||||
#include "xz.h"
|
||||
#include "xz_stream.h"
|
||||
|
||||
#define XZBUFSIZ 0x2000
|
||||
#define VLI_MAX_DIGITS 9
|
||||
#define XZ_STREAM_FOOTER_SIZE 12
|
||||
|
||||
struct grub_xzio
|
||||
{
|
||||
grub_file_t file;
|
||||
struct xz_buf buf;
|
||||
struct xz_dec *dec;
|
||||
grub_uint8_t inbuf[XZBUFSIZ];
|
||||
grub_uint8_t outbuf[XZBUFSIZ];
|
||||
grub_off_t saved_offset;
|
||||
};
|
||||
|
||||
typedef struct grub_xzio *grub_xzio_t;
|
||||
static struct grub_fs grub_xzio_fs;
|
||||
|
||||
static grub_size_t
|
||||
decode_vli (const grub_uint8_t buf[], grub_size_t size_max,
|
||||
grub_uint64_t * num)
|
||||
{
|
||||
if (size_max == 0)
|
||||
return 0;
|
||||
|
||||
if (size_max > VLI_MAX_DIGITS)
|
||||
size_max = VLI_MAX_DIGITS;
|
||||
|
||||
*num = buf[0] & 0x7F;
|
||||
grub_size_t i = 0;
|
||||
|
||||
while (buf[i++] & 0x80)
|
||||
{
|
||||
if (i >= size_max || buf[i] == 0x00)
|
||||
return 0;
|
||||
|
||||
*num |= (uint64_t) (buf[i] & 0x7F) << (i * 7);
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
static grub_ssize_t
|
||||
read_vli (grub_file_t file, grub_uint64_t * num)
|
||||
{
|
||||
grub_uint8_t buf[VLI_MAX_DIGITS];
|
||||
grub_ssize_t read;
|
||||
grub_size_t dec;
|
||||
|
||||
read = grub_file_read (file, buf, VLI_MAX_DIGITS);
|
||||
if (read < 0)
|
||||
return -1;
|
||||
|
||||
dec = decode_vli (buf, read, num);
|
||||
grub_file_seek (file, file->offset - (read - dec));
|
||||
return dec;
|
||||
}
|
||||
|
||||
/* Function xz_dec_run() should consume header and ask for more (XZ_OK)
|
||||
* else file is corrupted (or options not supported) or not xz. */
|
||||
static int
|
||||
test_header (grub_file_t file)
|
||||
{
|
||||
grub_xzio_t xzio = file->data;
|
||||
xzio->buf.in_size = grub_file_read (xzio->file, xzio->inbuf,
|
||||
STREAM_HEADER_SIZE);
|
||||
|
||||
if (xzio->buf.in_size != STREAM_HEADER_SIZE)
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_FILE_TYPE, "no xz magic found");
|
||||
return 0;
|
||||
}
|
||||
|
||||
enum xz_ret ret = xz_dec_run (xzio->dec, &xzio->buf);
|
||||
|
||||
if (ret == XZ_FORMAT_ERROR)
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_FILE_TYPE, "no xz magic found");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ret != XZ_OK)
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, "not supported xz options");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Try to find out size of uncompressed data,
|
||||
* also do some footer sanity checks. */
|
||||
static int
|
||||
test_footer (grub_file_t file)
|
||||
{
|
||||
grub_xzio_t xzio = file->data;
|
||||
grub_uint8_t footer[FOOTER_MAGIC_SIZE];
|
||||
grub_uint32_t backsize;
|
||||
grub_uint8_t imarker;
|
||||
grub_uint64_t uncompressed_size_total = 0;
|
||||
grub_uint64_t uncompressed_size;
|
||||
grub_uint64_t records;
|
||||
|
||||
grub_file_seek (xzio->file, xzio->file->size - FOOTER_MAGIC_SIZE);
|
||||
if (grub_file_read (xzio->file, footer, FOOTER_MAGIC_SIZE) !=
|
||||
FOOTER_MAGIC_SIZE
|
||||
|| grub_memcmp (footer, FOOTER_MAGIC, FOOTER_MAGIC_SIZE) != 0)
|
||||
goto ERROR;
|
||||
|
||||
grub_file_seek (xzio->file, xzio->file->size - 8);
|
||||
if (grub_file_read (xzio->file, &backsize, sizeof (backsize))
|
||||
!= sizeof (backsize))
|
||||
goto ERROR;
|
||||
|
||||
/* Calculate real backward size. */
|
||||
backsize = (grub_le_to_cpu32 (backsize) + 1) * 4;
|
||||
|
||||
/* Set file to the beginning of stream index. */
|
||||
grub_file_seek (xzio->file,
|
||||
xzio->file->size - XZ_STREAM_FOOTER_SIZE - backsize);
|
||||
|
||||
/* Test index marker. */
|
||||
if (grub_file_read (xzio->file, &imarker, sizeof (imarker)) !=
|
||||
sizeof (imarker) && imarker != 0x00)
|
||||
goto ERROR;
|
||||
|
||||
if (read_vli (xzio->file, &records) <= 0)
|
||||
goto ERROR;
|
||||
|
||||
for (; records != 0; records--)
|
||||
{
|
||||
if (read_vli (xzio->file, &uncompressed_size) <= 0) /* Ignore unpadded. */
|
||||
goto ERROR;
|
||||
if (read_vli (xzio->file, &uncompressed_size) <= 0) /* Uncompressed. */
|
||||
goto ERROR;
|
||||
|
||||
uncompressed_size_total += uncompressed_size;
|
||||
}
|
||||
|
||||
file->size = uncompressed_size_total;
|
||||
grub_file_seek (xzio->file, STREAM_HEADER_SIZE);
|
||||
return 1;
|
||||
|
||||
ERROR:
|
||||
grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, "bad footer magic");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static grub_file_t
|
||||
grub_xzio_open (grub_file_t io)
|
||||
{
|
||||
grub_file_t file;
|
||||
grub_xzio_t xzio;
|
||||
|
||||
file = (grub_file_t) grub_zalloc (sizeof (*file));
|
||||
if (!file)
|
||||
return 0;
|
||||
|
||||
xzio = grub_zalloc (sizeof (*xzio));
|
||||
if (!xzio)
|
||||
{
|
||||
grub_free (file);
|
||||
return 0;
|
||||
}
|
||||
|
||||
xzio->file = io;
|
||||
xzio->saved_offset = 0;
|
||||
|
||||
file->device = io->device;
|
||||
file->offset = 0;
|
||||
file->data = xzio;
|
||||
file->read_hook = 0;
|
||||
file->fs = &grub_xzio_fs;
|
||||
file->size = GRUB_FILE_SIZE_UNKNOWN;
|
||||
file->not_easly_seekable = 1;
|
||||
|
||||
if (grub_file_tell (xzio->file) != 0)
|
||||
grub_file_seek (xzio->file, 0);
|
||||
|
||||
/* Allocated 64KiB for dictionary.
|
||||
* Decoder will relocate if bigger is needed. */
|
||||
xzio->dec = xz_dec_init (1 << 16);
|
||||
if (!xzio->dec)
|
||||
{
|
||||
grub_free (file);
|
||||
grub_free (xzio);
|
||||
return 0;
|
||||
}
|
||||
|
||||
xzio->buf.in = xzio->inbuf;
|
||||
xzio->buf.in_pos = 0;
|
||||
xzio->buf.in_size = 0;
|
||||
xzio->buf.out = xzio->outbuf;
|
||||
xzio->buf.out_pos = 0;
|
||||
xzio->buf.out_size = XZBUFSIZ;
|
||||
|
||||
if (!test_header (file) || !(grub_file_seekable (io) && test_footer (file)))
|
||||
{
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
grub_file_seek (io, 0);
|
||||
xz_dec_end (xzio->dec);
|
||||
grub_free (xzio);
|
||||
grub_free (file);
|
||||
|
||||
return io;
|
||||
}
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
static grub_ssize_t
|
||||
grub_xzio_read (grub_file_t file, char *buf, grub_size_t len)
|
||||
{
|
||||
grub_ssize_t ret = 0;
|
||||
grub_ssize_t readret;
|
||||
enum xz_ret xzret;
|
||||
grub_xzio_t xzio = file->data;
|
||||
grub_off_t current_offset;
|
||||
|
||||
/* If seek backward need to reset decoder and start from beginning of file.
|
||||
TODO Possible improvement by jumping blocks. */
|
||||
if (file->offset < xzio->saved_offset)
|
||||
{
|
||||
xz_dec_reset (xzio->dec);
|
||||
xzio->saved_offset = 0;
|
||||
xzio->buf.out_pos = 0;
|
||||
xzio->buf.in_pos = 0;
|
||||
xzio->buf.in_size = 0;
|
||||
grub_file_seek (xzio->file, 0);
|
||||
}
|
||||
|
||||
current_offset = xzio->saved_offset;
|
||||
|
||||
while (len > 0)
|
||||
{
|
||||
xzio->buf.out_size = grub_min (file->offset + ret + len - current_offset,
|
||||
XZBUFSIZ);
|
||||
|
||||
/* Feed input. */
|
||||
if (xzio->buf.in_pos == xzio->buf.in_size)
|
||||
{
|
||||
readret = grub_file_read (xzio->file, xzio->inbuf, XZBUFSIZ);
|
||||
if (readret < 0)
|
||||
return -1;
|
||||
xzio->buf.in_size = readret;
|
||||
xzio->buf.in_pos = 0;
|
||||
}
|
||||
|
||||
xzret = xz_dec_run (xzio->dec, &xzio->buf);
|
||||
switch (xzret)
|
||||
{
|
||||
case XZ_MEMLIMIT_ERROR:
|
||||
case XZ_FORMAT_ERROR:
|
||||
case XZ_OPTIONS_ERROR:
|
||||
case XZ_DATA_ERROR:
|
||||
case XZ_BUF_ERROR:
|
||||
grub_error (GRUB_ERR_BAD_COMPRESSED_DATA,
|
||||
"file corrupted or unsupported block options");
|
||||
return -1;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
{
|
||||
grub_off_t new_offset = current_offset + xzio->buf.out_pos;
|
||||
|
||||
if (file->offset <= new_offset)
|
||||
/* Store first chunk of data in buffer. */
|
||||
{
|
||||
grub_size_t delta = new_offset - (file->offset + ret);
|
||||
grub_memmove (buf, xzio->buf.out + (xzio->buf.out_pos - delta),
|
||||
delta);
|
||||
len -= delta;
|
||||
buf += delta;
|
||||
ret += delta;
|
||||
}
|
||||
current_offset = new_offset;
|
||||
}
|
||||
xzio->buf.out_pos = 0;
|
||||
|
||||
if (xzret == XZ_STREAM_END) /* Stream end, EOF. */
|
||||
break;
|
||||
}
|
||||
|
||||
if (ret >= 0)
|
||||
xzio->saved_offset = file->offset + ret;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Release everything, including the underlying file object. */
|
||||
static grub_err_t
|
||||
grub_xzio_close (grub_file_t file)
|
||||
{
|
||||
grub_xzio_t xzio = file->data;
|
||||
|
||||
xz_dec_end (xzio->dec);
|
||||
|
||||
grub_file_close (xzio->file);
|
||||
grub_free (xzio);
|
||||
|
||||
/* Device must not be closed twice. */
|
||||
file->device = 0;
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
static struct grub_fs grub_xzio_fs = {
|
||||
.name = "xzio",
|
||||
.dir = 0,
|
||||
.open = 0,
|
||||
.read = grub_xzio_read,
|
||||
.close = grub_xzio_close,
|
||||
.label = 0,
|
||||
.next = 0
|
||||
};
|
||||
|
||||
GRUB_MOD_INIT (xzio)
|
||||
{
|
||||
grub_file_filter_register (GRUB_FILE_FILTER_XZIO, grub_xzio_open);
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI (xzio)
|
||||
{
|
||||
grub_file_filter_unregister (GRUB_FILE_FILTER_XZIO);
|
||||
}
|
|
@ -66,10 +66,33 @@ grub_efi_set_prefix (void)
|
|||
path = grub_strdup (pptr);
|
||||
}
|
||||
|
||||
if (!device || !path)
|
||||
if ((!device || device[0] == ',' || !device[0]) || !path)
|
||||
image = grub_efi_get_loaded_image (grub_efi_image_handle);
|
||||
if (image && !device)
|
||||
device = grub_efidisk_get_device_name (image->device_handle);
|
||||
if (image)
|
||||
{
|
||||
if (!device)
|
||||
device = grub_efidisk_get_device_name (image->device_handle);
|
||||
else if (device[0] == ',' || !device[0])
|
||||
{
|
||||
/* We have a partition, but still need to fill in the drive. */
|
||||
char *image_device, *comma, *new_device;
|
||||
|
||||
image_device = grub_efidisk_get_device_name (image->device_handle);
|
||||
comma = grub_strchr (image_device, ',');
|
||||
if (comma)
|
||||
{
|
||||
char *drive = grub_strndup (image_device, comma - image_device);
|
||||
new_device = grub_xasprintf ("%s%s", drive, device);
|
||||
grub_free (drive);
|
||||
}
|
||||
else
|
||||
new_device = grub_xasprintf ("%s%s", image_device, device);
|
||||
|
||||
grub_free (image_device);
|
||||
grub_free (device);
|
||||
device = new_device;
|
||||
}
|
||||
}
|
||||
|
||||
if (image && !path)
|
||||
{
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
#include <grub/elf.h>
|
||||
#include <grub/elfload.h>
|
||||
#include <grub/file.h>
|
||||
#include <grub/gzio.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/mm.h>
|
||||
|
||||
|
@ -95,7 +94,7 @@ grub_elf_open (const char *name)
|
|||
grub_file_t file;
|
||||
grub_elf_t elf;
|
||||
|
||||
file = grub_gzfile_open (name, 1);
|
||||
file = grub_file_open (name);
|
||||
if (! file)
|
||||
return 0;
|
||||
|
||||
|
|
|
@ -7,7 +7,20 @@
|
|||
#elif defined(__sparc__)
|
||||
#include "../sparc64/cache.S"
|
||||
#elif defined(__mips__)
|
||||
#include "../mips/cache.S"
|
||||
/* On MIPS we must go through standard functions. */
|
||||
#include <grub/symbol.h>
|
||||
|
||||
FUNCTION (grub_cpu_flush_cache)
|
||||
FUNCTION (grub_arch_sync_caches)
|
||||
.set nomacro
|
||||
.set noreorder
|
||||
lui $t0, %hi(_flush_cache)
|
||||
addui $t0, $t0, %lo(_flush_cache)
|
||||
move $a3, $zero
|
||||
jr $t0
|
||||
nop
|
||||
.set reorder
|
||||
.set macro
|
||||
#elif defined(__powerpc__)
|
||||
#include "../powerpc/cache.S"
|
||||
#else
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include <grub/kernel.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/emu/misc.h>
|
||||
#include <grub/disk.h>
|
||||
|
||||
void
|
||||
grub_register_exported_symbols (void)
|
||||
|
@ -48,3 +49,21 @@ grub_emu_init (void)
|
|||
{
|
||||
grub_no_autoload = 1;
|
||||
}
|
||||
|
||||
#ifdef GRUB_LINKER_HAVE_INIT
|
||||
void
|
||||
grub_arch_dl_init_linker (void)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
grub_emu_post_init (void)
|
||||
{
|
||||
grub_lvm_fini ();
|
||||
grub_mdraid_fini ();
|
||||
grub_raid_fini ();
|
||||
grub_raid_init ();
|
||||
grub_mdraid_init ();
|
||||
grub_lvm_init ();
|
||||
}
|
||||
|
|
|
@ -38,3 +38,8 @@ grub_emu_init (void)
|
|||
{
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
grub_emu_post_init (void)
|
||||
{
|
||||
}
|
||||
|
|
|
@ -197,6 +197,8 @@ main (int argc, char *argv[])
|
|||
|
||||
grub_init_all ();
|
||||
|
||||
grub_emu_post_init ();
|
||||
|
||||
/* Make sure that there is a root device. */
|
||||
if (! root_dev)
|
||||
{
|
||||
|
|
|
@ -61,6 +61,15 @@
|
|||
# include <sys/mount.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_MNTTAB_H
|
||||
# include <stdio.h> /* Needed by sys/mnttab.h. */
|
||||
# include <sys/mnttab.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_MKDEV_H
|
||||
# include <sys/mkdev.h> /* makedev */
|
||||
#endif
|
||||
|
||||
int verbosity;
|
||||
|
||||
void
|
||||
|
@ -282,18 +291,52 @@ grub_get_libzfs_handle (void)
|
|||
void
|
||||
grub_find_zpool_from_dir (const char *dir, char **poolname, char **poolfs)
|
||||
{
|
||||
struct statfs mnt;
|
||||
char *slash;
|
||||
|
||||
*poolname = *poolfs = NULL;
|
||||
|
||||
if (statfs (dir, &mnt) != 0)
|
||||
return;
|
||||
#if defined(HAVE_STRUCT_STATFS_F_FSTYPENAME) && defined(HAVE_STRUCT_STATFS_F_MNTFROMNAME)
|
||||
/* FreeBSD and GNU/kFreeBSD. */
|
||||
{
|
||||
struct statfs mnt;
|
||||
|
||||
if (strcmp (mnt.f_fstypename, "zfs") != 0)
|
||||
return;
|
||||
if (statfs (dir, &mnt) != 0)
|
||||
return;
|
||||
|
||||
*poolname = xstrdup (mnt.f_mntfromname);
|
||||
if (strcmp (mnt.f_fstypename, "zfs") != 0)
|
||||
return;
|
||||
|
||||
*poolname = xstrdup (mnt.f_mntfromname);
|
||||
}
|
||||
#elif defined(HAVE_GETEXTMNTENT)
|
||||
/* Solaris. */
|
||||
{
|
||||
struct stat st;
|
||||
struct extmnttab mnt;
|
||||
|
||||
if (stat (dir, &st) != 0)
|
||||
return;
|
||||
|
||||
FILE *mnttab = fopen ("/etc/mnttab", "r");
|
||||
if (! mnttab)
|
||||
return;
|
||||
|
||||
while (getextmntent (mnttab, &mnt, sizeof (mnt)) == 0)
|
||||
{
|
||||
if (makedev (mnt.mnt_major, mnt.mnt_minor) == st.st_dev
|
||||
&& !strcmp (mnt.mnt_fstype, "zfs"))
|
||||
{
|
||||
*poolname = xstrdup (mnt.mnt_special);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fclose (mnttab);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (! *poolname)
|
||||
return;
|
||||
|
||||
slash = strchr (*poolname, '/');
|
||||
if (slash)
|
||||
|
|
|
@ -24,6 +24,9 @@
|
|||
#include <grub/fs.h>
|
||||
#include <grub/device.h>
|
||||
|
||||
grub_file_filter_t grub_file_filters_all[GRUB_FILE_FILTER_MAX];
|
||||
grub_file_filter_t grub_file_filters_enabled[GRUB_FILE_FILTER_MAX];
|
||||
|
||||
/* Get the device part of the filename NAME. It is enclosed by parentheses. */
|
||||
char *
|
||||
grub_file_get_device_name (const char *name)
|
||||
|
@ -54,14 +57,15 @@ grub_file_get_device_name (const char *name)
|
|||
grub_file_t
|
||||
grub_file_open (const char *name)
|
||||
{
|
||||
grub_device_t device;
|
||||
grub_file_t file = 0;
|
||||
grub_device_t device = 0;
|
||||
grub_file_t file = 0, last_file = 0;
|
||||
char *device_name;
|
||||
char *file_name;
|
||||
grub_file_filter_id_t filter;
|
||||
|
||||
device_name = grub_file_get_device_name (name);
|
||||
if (grub_errno)
|
||||
return 0;
|
||||
goto fail;
|
||||
|
||||
/* Get the file part of NAME. */
|
||||
file_name = grub_strchr (name, ')');
|
||||
|
@ -94,6 +98,19 @@ grub_file_open (const char *name)
|
|||
if ((file->fs->open) (file, file_name) != GRUB_ERR_NONE)
|
||||
goto fail;
|
||||
|
||||
for (filter = 0; file && filter < ARRAY_SIZE (grub_file_filters_enabled);
|
||||
filter++)
|
||||
if (grub_file_filters_enabled[filter])
|
||||
{
|
||||
last_file = file;
|
||||
file = grub_file_filters_enabled[filter] (file);
|
||||
}
|
||||
if (!file)
|
||||
grub_file_close (last_file);
|
||||
|
||||
grub_memcpy (grub_file_filters_enabled, grub_file_filters_all,
|
||||
sizeof (grub_file_filters_enabled));
|
||||
|
||||
return file;
|
||||
|
||||
fail:
|
||||
|
@ -104,6 +121,9 @@ grub_file_open (const char *name)
|
|||
|
||||
grub_free (file);
|
||||
|
||||
grub_memcpy (grub_file_filters_enabled, grub_file_filters_all,
|
||||
sizeof (grub_file_filters_enabled));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -51,7 +51,7 @@ VARIABLE(grub_prefix)
|
|||
* Leave some breathing room for the prefix.
|
||||
*/
|
||||
|
||||
. = _start + GRUB_KERNEL_MACHINE_DATA_END
|
||||
. = _start + GRUB_KERNEL_MACHINE_PREFIX_END
|
||||
|
||||
/*
|
||||
* Support for booting GRUB from a Multiboot boot loader (e.g. GRUB itself).
|
||||
|
|
|
@ -51,7 +51,7 @@ VARIABLE(grub_prefix)
|
|||
* Leave some breathing room for the prefix.
|
||||
*/
|
||||
|
||||
. = _start + GRUB_KERNEL_MACHINE_DATA_END
|
||||
. = _start + GRUB_KERNEL_MACHINE_PREFIX_END
|
||||
|
||||
codestart:
|
||||
movl %eax, EXT_C(grub_ieee1275_entry_fn)
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <grub/machine/init.h>
|
||||
#include <grub/machine/memory.h>
|
||||
#include <grub/types.h>
|
||||
#include <grub/multiboot.h>
|
||||
|
|
|
@ -100,14 +100,6 @@ VARIABLE(grub_install_dos_part)
|
|||
.long 0xFFFFFFFF
|
||||
VARIABLE(grub_install_bsd_part)
|
||||
.long 0xFFFFFFFF
|
||||
VARIABLE(grub_prefix)
|
||||
/* to be filled by grub-mkimage */
|
||||
|
||||
/*
|
||||
* Leave some breathing room for the prefix.
|
||||
*/
|
||||
|
||||
. = _start + GRUB_KERNEL_MACHINE_DATA_END
|
||||
|
||||
#ifdef APPLE_CC
|
||||
bss_start:
|
||||
|
@ -450,6 +442,16 @@ gate_a20_check_state:
|
|||
*/
|
||||
. = _start + GRUB_KERNEL_MACHINE_RAW_SIZE
|
||||
|
||||
. = _start + GRUB_KERNEL_MACHINE_PREFIX
|
||||
VARIABLE(grub_prefix)
|
||||
/* to be filled by grub-mkimage */
|
||||
|
||||
/*
|
||||
* Leave some breathing room for the prefix.
|
||||
*/
|
||||
. = _start + GRUB_KERNEL_MACHINE_PREFIX_END
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* grub_exit()
|
||||
|
|
|
@ -39,7 +39,7 @@ VARIABLE(grub_prefix)
|
|||
* Leave some breathing room for the prefix.
|
||||
*/
|
||||
|
||||
. = _start + GRUB_KERNEL_MACHINE_DATA_END
|
||||
. = _start + GRUB_KERNEL_MACHINE_PREFIX_END
|
||||
|
||||
codestart:
|
||||
/* Relocate to low memory. First we figure out our location.
|
||||
|
|
|
@ -138,11 +138,16 @@ grub_ieee1275_find_options (void)
|
|||
*/
|
||||
|
||||
grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_OFDISK_SDCARD_ONLY);
|
||||
grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_HAS_CURSORONOFF);
|
||||
}
|
||||
|
||||
if (is_qemu)
|
||||
/* OpenFirmware hangs on qemu if one requests any memory below 1.5 MiB. */
|
||||
grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_NO_PRE1_5M_CLAIM);
|
||||
{
|
||||
/* OpenFirmware hangs on qemu if one requests any memory below 1.5 MiB. */
|
||||
grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_NO_PRE1_5M_CLAIM);
|
||||
|
||||
grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_HAS_CURSORONOFF);
|
||||
}
|
||||
|
||||
if (! grub_ieee1275_finddevice ("/rom/boot-rom", &bootrom))
|
||||
{
|
||||
|
|
|
@ -154,7 +154,7 @@ VARIABLE(grub_prefix)
|
|||
* Leave some breathing room for the prefix.
|
||||
*/
|
||||
|
||||
. = _start + GRUB_KERNEL_MACHINE_DATA_END
|
||||
. = _start + GRUB_KERNEL_MACHINE_PREFIX_END
|
||||
#ifdef GRUB_MACHINE_MIPS_YEELOONG
|
||||
VARIABLE (grub_arch_busclock)
|
||||
.long 0
|
||||
|
|
|
@ -990,7 +990,7 @@ grub_abort (void)
|
|||
grub_exit ();
|
||||
}
|
||||
|
||||
#ifndef APPLE_CC
|
||||
#if ! defined (APPLE_CC) && !defined (GRUB_UTIL)
|
||||
/* GCC emits references to abort(). */
|
||||
void abort (void) __attribute__ ((alias ("grub_abort")));
|
||||
#endif
|
||||
|
|
|
@ -39,7 +39,7 @@ VARIABLE(grub_prefix)
|
|||
* Leave some breathing room for the prefix.
|
||||
*/
|
||||
|
||||
. = _start + GRUB_KERNEL_MACHINE_DATA_END
|
||||
. = _start + GRUB_KERNEL_MACHINE_PREFIX_END
|
||||
|
||||
codestart:
|
||||
li 2, 0
|
||||
|
|
|
@ -42,7 +42,7 @@ VARIABLE(grub_prefix)
|
|||
* Leave some breathing room for the prefix.
|
||||
*/
|
||||
|
||||
. = EXT_C(_start) + GRUB_KERNEL_MACHINE_DATA_END
|
||||
. = EXT_C(_start) + GRUB_KERNEL_MACHINE_PREFIX_END
|
||||
|
||||
codestart:
|
||||
/* Copy the modules past the end of the kernel image.
|
||||
|
|
|
@ -209,8 +209,16 @@ parse_option (grub_extcmd_t cmd, int key, char *arg, struct grub_arg_list *usr)
|
|||
if (found == -1)
|
||||
return -1;
|
||||
|
||||
usr[found].set = 1;
|
||||
usr[found].arg = arg;
|
||||
if (opt->flags & GRUB_ARG_OPTION_REPEATABLE)
|
||||
{
|
||||
usr[found].args[usr[found].set++] = arg;
|
||||
usr[found].args[usr[found].set] = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
usr[found].set = 1;
|
||||
usr[found].arg = arg;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -230,10 +238,15 @@ grub_arg_parse (grub_extcmd_t cmd, int argc, char **argv,
|
|||
|
||||
grub_err_t add_arg (char *s)
|
||||
{
|
||||
argl = grub_realloc (argl, (++num) * sizeof (char *));
|
||||
char **p = argl;
|
||||
argl = grub_realloc (argl, (++num + 1) * sizeof (char *));
|
||||
if (! argl)
|
||||
return grub_errno;
|
||||
{
|
||||
grub_free (p);
|
||||
return grub_errno;
|
||||
}
|
||||
argl[num - 1] = s;
|
||||
argl[num] = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -310,8 +323,11 @@ grub_arg_parse (grub_extcmd_t cmd, int argc, char **argv,
|
|||
if (option) {
|
||||
arglen = option - arg - 2;
|
||||
option++;
|
||||
} else
|
||||
} else {
|
||||
arglen = grub_strlen (arg) - 2;
|
||||
if (argv[curarg + 1])
|
||||
option = argv[curarg + 1][0] == '-' ? 0 : argv[++curarg];
|
||||
}
|
||||
|
||||
opt = find_long (cmd->options, arg + 2, arglen);
|
||||
if (! opt)
|
||||
|
@ -390,3 +406,43 @@ grub_arg_parse (grub_extcmd_t cmd, int argc, char **argv,
|
|||
fail:
|
||||
return complete;
|
||||
}
|
||||
|
||||
struct grub_arg_list*
|
||||
grub_arg_list_alloc(grub_extcmd_t extcmd, int argc,
|
||||
char **argv __attribute__((unused)))
|
||||
{
|
||||
int i;
|
||||
char **args;
|
||||
unsigned argcnt;
|
||||
struct grub_arg_list *list;
|
||||
const struct grub_arg_option *options;
|
||||
|
||||
options = extcmd->options;
|
||||
if (! options)
|
||||
return 0;
|
||||
|
||||
argcnt = 0;
|
||||
for (i = 0; options[i].doc; i++)
|
||||
{
|
||||
if (options[i].flags & GRUB_ARG_OPTION_REPEATABLE)
|
||||
argcnt += (argc + 1) / 2 + 1; /* max possible for any option */
|
||||
}
|
||||
|
||||
list = grub_zalloc (sizeof (*list) * i + sizeof (char*) * argcnt);
|
||||
if (! list)
|
||||
return 0;
|
||||
|
||||
args = (char**) (list + i);
|
||||
for (i = 0; options[i].doc; i++)
|
||||
{
|
||||
list[i].set = 0;
|
||||
list[i].arg = 0;
|
||||
|
||||
if (options[i].flags & GRUB_ARG_OPTION_REPEATABLE)
|
||||
{
|
||||
list[i].args = args;
|
||||
args += argc / 2 + 1;
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
|
|
@ -59,7 +59,9 @@ extern grub_uint32_t grub_relocator32_ecx;
|
|||
extern grub_uint32_t grub_relocator32_edx;
|
||||
extern grub_uint32_t grub_relocator32_eip;
|
||||
extern grub_uint32_t grub_relocator32_esp;
|
||||
extern grub_uint32_t grub_relocator32_ebp;
|
||||
extern grub_uint32_t grub_relocator32_esi;
|
||||
extern grub_uint32_t grub_relocator32_edi;
|
||||
|
||||
extern grub_uint8_t grub_relocator64_start;
|
||||
extern grub_uint8_t grub_relocator64_end;
|
||||
|
@ -165,7 +167,9 @@ grub_relocator32_boot (struct grub_relocator *rel,
|
|||
grub_relocator32_edx = state.edx;
|
||||
grub_relocator32_eip = state.eip;
|
||||
grub_relocator32_esp = state.esp;
|
||||
grub_relocator32_ebp = state.ebp;
|
||||
grub_relocator32_esi = state.esi;
|
||||
grub_relocator32_edi = state.edi;
|
||||
|
||||
grub_memmove (get_virtual_current_address (ch), &grub_relocator32_start,
|
||||
RELOCATOR_SIZEOF (32));
|
||||
|
|
|
@ -65,13 +65,27 @@ VARIABLE(grub_relocator32_esp)
|
|||
|
||||
movl %eax, %esp
|
||||
|
||||
/* mov imm32, %eax */
|
||||
.byte 0xb8
|
||||
VARIABLE(grub_relocator32_ebp)
|
||||
.long 0
|
||||
|
||||
movl %eax, %ebp
|
||||
|
||||
/* mov imm32, %eax */
|
||||
.byte 0xb8
|
||||
VARIABLE(grub_relocator32_esi)
|
||||
.long 0
|
||||
|
||||
movl %eax, %esi
|
||||
|
||||
|
||||
/* mov imm32, %eax */
|
||||
.byte 0xb8
|
||||
VARIABLE(grub_relocator32_edi)
|
||||
.long 0
|
||||
|
||||
movl %eax, %edi
|
||||
|
||||
/* mov imm32, %eax */
|
||||
.byte 0xb8
|
||||
VARIABLE(grub_relocator32_eax)
|
||||
|
|
|
@ -22,11 +22,14 @@
|
|||
#include <grub/misc.h>
|
||||
|
||||
typedef grub_size_t size_t;
|
||||
typedef int bool;
|
||||
static const bool true = 1;
|
||||
static const bool false = 0;
|
||||
typedef enum { false = 0, true = 1 } bool;
|
||||
|
||||
#define ULONG_MAX GRUB_ULONG_MAX
|
||||
#define UCHAR_MAX 0xff
|
||||
|
||||
typedef grub_uint8_t uint8_t;
|
||||
typedef grub_uint16_t uint16_t;
|
||||
typedef grub_uint32_t uint32_t;
|
||||
typedef grub_uint64_t uint64_t;
|
||||
|
||||
#endif
|
||||
|
|
180
grub-core/lib/xzembed/xz.h
Normal file
180
grub-core/lib/xzembed/xz.h
Normal file
|
@ -0,0 +1,180 @@
|
|||
/* xz.h - XZ decompressor */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2010 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/>.
|
||||
*/
|
||||
/*
|
||||
* This file is based on code from XZ embedded project
|
||||
* http://tukaani.org/xz/embedded.html
|
||||
*/
|
||||
|
||||
#ifndef XZ_H
|
||||
#define XZ_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* enum xz_ret - Return codes
|
||||
* @XZ_OK: Everything is OK so far. More input or more output
|
||||
* space is required to continue.
|
||||
* @XZ_STREAM_END: Operation finished successfully.
|
||||
* @XZ_MEMLIMIT_ERROR: Not enough memory was preallocated at decoder
|
||||
* initialization time.
|
||||
* @XZ_FORMAT_ERROR: File format was not recognized (wrong magic bytes).
|
||||
* @XZ_OPTIONS_ERROR: This implementation doesn't support the requested
|
||||
* compression options. In the decoder this means that
|
||||
* the header CRC32 matches, but the header itself
|
||||
* specifies something that we don't support.
|
||||
* @XZ_DATA_ERROR: Compressed data is corrupt.
|
||||
* @XZ_BUF_ERROR: Cannot make any progress. Details are slightly
|
||||
* different between multi-call and single-call mode;
|
||||
* more information below.
|
||||
*
|
||||
* In multi-call mode, XZ_BUF_ERROR is returned when two consecutive calls
|
||||
* to XZ code cannot consume any input and cannot produce any new output.
|
||||
* This happens when there is no new input available, or the output buffer
|
||||
* is full while at least one output byte is still pending. Assuming your
|
||||
* code is not buggy, you can get this error only when decoding a compressed
|
||||
* stream that is truncated or otherwise corrupt.
|
||||
*
|
||||
* In single-call mode, XZ_BUF_ERROR is returned only when the output buffer
|
||||
* is too small, or the compressed input is corrupt in a way that makes the
|
||||
* decoder produce more output than the caller expected. When it is
|
||||
* (relatively) clear that the compressed input is truncated, XZ_DATA_ERROR
|
||||
* is used instead of XZ_BUF_ERROR.
|
||||
*/
|
||||
enum xz_ret {
|
||||
XZ_OK,
|
||||
XZ_STREAM_END,
|
||||
XZ_MEMLIMIT_ERROR,
|
||||
XZ_FORMAT_ERROR,
|
||||
XZ_OPTIONS_ERROR,
|
||||
XZ_DATA_ERROR,
|
||||
XZ_BUF_ERROR
|
||||
};
|
||||
|
||||
/**
|
||||
* struct xz_buf - Passing input and output buffers to XZ code
|
||||
* @in: Beginning of the input buffer. This may be NULL if and only
|
||||
* if in_pos is equal to in_size.
|
||||
* @in_pos: Current position in the input buffer. This must not exceed
|
||||
* in_size.
|
||||
* @in_size: Size of the input buffer
|
||||
* @out: Beginning of the output buffer. This may be NULL if and only
|
||||
* if out_pos is equal to out_size.
|
||||
* @out_pos: Current position in the output buffer. This must not exceed
|
||||
* out_size.
|
||||
* @out_size: Size of the output buffer
|
||||
*
|
||||
* Only the contents of the output buffer from out[out_pos] onward, and
|
||||
* the variables in_pos and out_pos are modified by the XZ code.
|
||||
*/
|
||||
struct xz_buf {
|
||||
const uint8_t *in;
|
||||
size_t in_pos;
|
||||
size_t in_size;
|
||||
|
||||
uint8_t *out;
|
||||
size_t out_pos;
|
||||
size_t out_size;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct xz_dec - Opaque type to hold the XZ decoder state
|
||||
*/
|
||||
struct xz_dec;
|
||||
|
||||
/**
|
||||
* xz_dec_init() - Allocate and initialize a XZ decoder state
|
||||
* @dict_max: Maximum size of the LZMA2 dictionary (history buffer) for
|
||||
* multi-call decoding, or special value of zero to indicate
|
||||
* single-call decoding mode.
|
||||
*
|
||||
* If dict_max > 0, the decoder is initialized to work in multi-call mode.
|
||||
* dict_max number of bytes of memory is preallocated for the LZMA2
|
||||
* dictionary. This way there is no risk that xz_dec_run() could run out
|
||||
* of memory, since xz_dec_run() will never allocate any memory. Instead,
|
||||
* if the preallocated dictionary is too small for decoding the given input
|
||||
* stream, xz_dec_run() will return XZ_MEMLIMIT_ERROR. Thus, it is important
|
||||
* to know what kind of data will be decoded to avoid allocating excessive
|
||||
* amount of memory for the dictionary.
|
||||
*
|
||||
* LZMA2 dictionary is always 2^n bytes or 2^n + 2^(n-1) bytes (the latter
|
||||
* sizes are less common in practice). In the kernel, dictionary sizes of
|
||||
* 64 KiB, 128 KiB, 256 KiB, 512 KiB, and 1 MiB are probably the only
|
||||
* reasonable values.
|
||||
*
|
||||
* If dict_max == 0, the decoder is initialized to work in single-call mode.
|
||||
* In single-call mode, xz_dec_run() decodes the whole stream at once. The
|
||||
* caller must provide enough output space or the decoding will fail. The
|
||||
* output space is used as the dictionary buffer, which is why there is
|
||||
* no need to allocate the dictionary as part of the decoder's internal
|
||||
* state.
|
||||
*
|
||||
* Because the output buffer is used as the workspace, streams encoded using
|
||||
* a big dictionary are not a problem in single-call. It is enough that the
|
||||
* output buffer is is big enough to hold the actual uncompressed data; it
|
||||
* can be smaller than the dictionary size stored in the stream headers.
|
||||
*
|
||||
* On success, xz_dec_init() returns a pointer to struct xz_dec, which is
|
||||
* ready to be used with xz_dec_run(). On error, xz_dec_init() returns NULL.
|
||||
*/
|
||||
struct xz_dec * xz_dec_init(uint32_t dict_max);
|
||||
|
||||
/**
|
||||
* xz_dec_run() - Run the XZ decoder
|
||||
* @s: Decoder state allocated using xz_dec_init()
|
||||
* @b: Input and output buffers
|
||||
*
|
||||
* In multi-call mode, this function may return any of the values listed in
|
||||
* enum xz_ret.
|
||||
*
|
||||
* In single-call mode, this function never returns XZ_OK. If an error occurs
|
||||
* in single-call mode (return value is not XZ_STREAM_END), b->in_pos and
|
||||
* b->out_pos are not modified, and the contents of the output buffer from
|
||||
* b->out[b->out_pos] onward are undefined.
|
||||
*
|
||||
* NOTE: In single-call mode, the contents of the output buffer are undefined
|
||||
* also after XZ_BUF_ERROR. This is because with some filter chains, there
|
||||
* may be a second pass over the output buffer, and this pass cannot be
|
||||
* properly done if the output buffer is truncated. Thus, you cannot give
|
||||
* the single-call decoder a too small buffer and then expect to get that
|
||||
* amount valid data from the beginning of the stream. You must use the
|
||||
* multi-call decoder if you don't want to uncompress the whole stream.
|
||||
*/
|
||||
enum xz_ret xz_dec_run(struct xz_dec *s, struct xz_buf *b);
|
||||
|
||||
/**
|
||||
* xz_dec_reset() - Reset an already allocated decoder state
|
||||
* @s: Decoder state allocated using xz_dec_init()
|
||||
*
|
||||
* This function can be used to reset the multi-call decoder state without
|
||||
* freeing and reallocating memory with xz_dec_end() and xz_dec_init().
|
||||
*
|
||||
* In single-call mode, xz_dec_reset() is always called in the beginning of
|
||||
* xz_dec_run(). Thus, explicit call to xz_dec_reset() is useful only in
|
||||
* multi-call mode.
|
||||
*/
|
||||
void xz_dec_reset(struct xz_dec *s);
|
||||
|
||||
/**
|
||||
* xz_dec_end() - Free the memory allocated for the decoder state
|
||||
* @s: Decoder state allocated using xz_dec_init(). If s is NULL,
|
||||
* this function does nothing.
|
||||
*/
|
||||
void xz_dec_end(struct xz_dec *s);
|
||||
|
||||
#endif
|
141
grub-core/lib/xzembed/xz_config.h
Normal file
141
grub-core/lib/xzembed/xz_config.h
Normal file
|
@ -0,0 +1,141 @@
|
|||
/* xz_config.h - Private includes and definitions for userspace use */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2010 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/>.
|
||||
*/
|
||||
/*
|
||||
* This file is based on code from XZ embedded project
|
||||
* http://tukaani.org/xz/embedded.html
|
||||
*/
|
||||
|
||||
#ifndef XZ_CONFIG_H
|
||||
#define XZ_CONFIG_H
|
||||
|
||||
/* Enable BCJ filter decoders. */
|
||||
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
#define XZ_DEC_X86
|
||||
#endif
|
||||
|
||||
#ifdef __powerpc__
|
||||
#define XZ_DEC_POWERPC
|
||||
#endif
|
||||
|
||||
#ifdef __ia64__
|
||||
#define XZ_DEC_IA64
|
||||
#endif
|
||||
|
||||
#ifdef __arm__
|
||||
#define XZ_DEC_ARM
|
||||
#endif
|
||||
|
||||
#ifdef __thumb__
|
||||
#define XZ_DEC_ARMTHUMB
|
||||
#endif
|
||||
|
||||
#ifdef __sparc__
|
||||
#define XZ_DEC_SPARC
|
||||
#endif
|
||||
|
||||
|
||||
#include "xz.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
#define kmalloc(size, flags) malloc(size)
|
||||
#define kfree(ptr) free(ptr)
|
||||
#define vmalloc(size) malloc(size)
|
||||
#define vfree(ptr) free(ptr)
|
||||
|
||||
#define memeq(a, b, size) (memcmp(a, b, size) == 0)
|
||||
#define memzero(buf, size) memset(buf, 0, size)
|
||||
|
||||
#define min(x, y) ((x) < (y) ? (x) : (y))
|
||||
#define min_t(type, x, y) min(x, y)
|
||||
|
||||
/*
|
||||
* Some functions have been marked with __always_inline to keep the
|
||||
* performance reasonable even when the compiler is optimizing for
|
||||
* small code size. You may be able to save a few bytes by #defining
|
||||
* __always_inline to plain inline, but don't complain if the code
|
||||
* becomes slow.
|
||||
*
|
||||
* NOTE: System headers on GNU/Linux may #define this macro already,
|
||||
* so if you want to change it, it you need to #undef it first.
|
||||
*/
|
||||
#ifndef __always_inline
|
||||
# ifdef __GNUC__
|
||||
# define __always_inline \
|
||||
inline __attribute__((__always_inline__))
|
||||
# else
|
||||
# define __always_inline inline
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Some functions are marked to never be inlined to reduce stack usage.
|
||||
* If you don't care about stack usage, you may want to modify this so
|
||||
* that noinline_for_stack is #defined to be empty even when using GCC.
|
||||
* Doing so may save a few bytes in binary size.
|
||||
*/
|
||||
#ifndef noinline_for_stack
|
||||
# ifdef __GNUC__
|
||||
# define noinline_for_stack __attribute__((__noinline__))
|
||||
# else
|
||||
# define noinline_for_stack
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Inline functions to access unaligned unsigned 32-bit integers */
|
||||
static inline uint32_t get_unaligned_le32(const uint8_t *buf)
|
||||
{
|
||||
return (uint32_t)buf[0]
|
||||
| ((uint32_t)buf[1] << 8)
|
||||
| ((uint32_t)buf[2] << 16)
|
||||
| ((uint32_t)buf[3] << 24);
|
||||
}
|
||||
|
||||
static inline uint32_t get_unaligned_be32(const uint8_t *buf)
|
||||
{
|
||||
return (uint32_t)(buf[0] << 24)
|
||||
| ((uint32_t)buf[1] << 16)
|
||||
| ((uint32_t)buf[2] << 8)
|
||||
| (uint32_t)buf[3];
|
||||
}
|
||||
|
||||
static inline void put_unaligned_le32(uint32_t val, uint8_t *buf)
|
||||
{
|
||||
buf[0] = (uint8_t)val;
|
||||
buf[1] = (uint8_t)(val >> 8);
|
||||
buf[2] = (uint8_t)(val >> 16);
|
||||
buf[3] = (uint8_t)(val >> 24);
|
||||
}
|
||||
|
||||
static inline void put_unaligned_be32(uint32_t val, uint8_t *buf)
|
||||
{
|
||||
buf[0] = (uint8_t)(val >> 24);
|
||||
buf[1] = (uint8_t)(val >> 16);
|
||||
buf[2] = (uint8_t)(val >> 8);
|
||||
buf[3] = (uint8_t)val;
|
||||
}
|
||||
|
||||
/*
|
||||
* Use get_unaligned_le32() also for aligned access for simplicity. On
|
||||
* little endian systems, #define get_le32(ptr) (*(const uint32_t *)(ptr))
|
||||
* could save a few bytes in code size.
|
||||
*/
|
||||
#define get_le32 get_unaligned_le32
|
||||
|
||||
#endif
|
569
grub-core/lib/xzembed/xz_dec_bcj.c
Normal file
569
grub-core/lib/xzembed/xz_dec_bcj.c
Normal file
|
@ -0,0 +1,569 @@
|
|||
/* xz_dec_bcj.c - Branch/Call/Jump (BCJ) filter decoders */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2010 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/>.
|
||||
*/
|
||||
/*
|
||||
* This file is based on code from XZ embedded project
|
||||
* http://tukaani.org/xz/embedded.html
|
||||
*/
|
||||
|
||||
#include "xz_private.h"
|
||||
|
||||
struct xz_dec_bcj {
|
||||
/* Type of the BCJ filter being used */
|
||||
enum {
|
||||
BCJ_X86 = 4, /* x86 or x86-64 */
|
||||
BCJ_POWERPC = 5, /* Big endian only */
|
||||
BCJ_IA64 = 6, /* Big or little endian */
|
||||
BCJ_ARM = 7, /* Little endian only */
|
||||
BCJ_ARMTHUMB = 8, /* Little endian only */
|
||||
BCJ_SPARC = 9 /* Big or little endian */
|
||||
} type;
|
||||
|
||||
/*
|
||||
* Return value of the next filter in the chain. We need to preserve
|
||||
* this information across calls, because we must not call the next
|
||||
* filter anymore once it has returned XZ_STREAM_END.
|
||||
*/
|
||||
enum xz_ret ret;
|
||||
|
||||
/* True if we are operating in single-call mode. */
|
||||
bool single_call;
|
||||
|
||||
/*
|
||||
* Absolute position relative to the beginning of the uncompressed
|
||||
* data (in a single .xz Block). We care only about the lowest 32
|
||||
* bits so this doesn't need to be uint64_t even with big files.
|
||||
*/
|
||||
uint32_t pos;
|
||||
|
||||
/* x86 filter state */
|
||||
uint32_t x86_prev_mask;
|
||||
|
||||
/* Temporary space to hold the variables from struct xz_buf */
|
||||
uint8_t *out;
|
||||
size_t out_pos;
|
||||
size_t out_size;
|
||||
|
||||
struct {
|
||||
/* Amount of already filtered data in the beginning of buf */
|
||||
size_t filtered;
|
||||
|
||||
/* Total amount of data currently stored in buf */
|
||||
size_t size;
|
||||
|
||||
/*
|
||||
* Buffer to hold a mix of filtered and unfiltered data. This
|
||||
* needs to be big enough to hold Alignment + 2 * Look-ahead:
|
||||
*
|
||||
* Type Alignment Look-ahead
|
||||
* x86 1 4
|
||||
* PowerPC 4 0
|
||||
* IA-64 16 0
|
||||
* ARM 4 0
|
||||
* ARM-Thumb 2 2
|
||||
* SPARC 4 0
|
||||
*/
|
||||
uint8_t buf[16];
|
||||
} temp;
|
||||
};
|
||||
|
||||
#ifdef XZ_DEC_X86
|
||||
/*
|
||||
* This is macro used to test the most significant byte of a memory address
|
||||
* in an x86 instruction.
|
||||
*/
|
||||
#define bcj_x86_test_msbyte(b) ((b) == 0x00 || (b) == 0xFF)
|
||||
|
||||
static noinline_for_stack size_t bcj_x86(
|
||||
struct xz_dec_bcj *s, uint8_t *buf, size_t size)
|
||||
{
|
||||
static const bool mask_to_allowed_status[8]
|
||||
= { true, true, true, false, true, false, false, false };
|
||||
|
||||
static const uint8_t mask_to_bit_num[8] = { 0, 1, 2, 2, 3, 3, 3, 3 };
|
||||
|
||||
size_t i;
|
||||
size_t prev_pos = (size_t)-1;
|
||||
uint32_t prev_mask = s->x86_prev_mask;
|
||||
uint32_t src;
|
||||
uint32_t dest;
|
||||
uint32_t j;
|
||||
uint8_t b;
|
||||
|
||||
if (size <= 4)
|
||||
return 0;
|
||||
|
||||
size -= 4;
|
||||
for (i = 0; i < size; ++i) {
|
||||
if ((buf[i] & 0xFE) != 0xE8)
|
||||
continue;
|
||||
|
||||
prev_pos = i - prev_pos;
|
||||
if (prev_pos > 3) {
|
||||
prev_mask = 0;
|
||||
} else {
|
||||
prev_mask = (prev_mask << (prev_pos - 1)) & 7;
|
||||
if (prev_mask != 0) {
|
||||
b = buf[i + 4 - mask_to_bit_num[prev_mask]];
|
||||
if (!mask_to_allowed_status[prev_mask]
|
||||
|| bcj_x86_test_msbyte(b)) {
|
||||
prev_pos = i;
|
||||
prev_mask = (prev_mask << 1) | 1;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
prev_pos = i;
|
||||
|
||||
if (bcj_x86_test_msbyte(buf[i + 4])) {
|
||||
src = get_unaligned_le32(buf + i + 1);
|
||||
while (true) {
|
||||
dest = src - (s->pos + (uint32_t)i + 5);
|
||||
if (prev_mask == 0)
|
||||
break;
|
||||
|
||||
j = mask_to_bit_num[prev_mask] * 8;
|
||||
b = (uint8_t)(dest >> (24 - j));
|
||||
if (!bcj_x86_test_msbyte(b))
|
||||
break;
|
||||
|
||||
src = dest ^ (((uint32_t)1 << (32 - j)) - 1);
|
||||
}
|
||||
|
||||
dest &= 0x01FFFFFF;
|
||||
dest |= (uint32_t)0 - (dest & 0x01000000);
|
||||
put_unaligned_le32(dest, buf + i + 1);
|
||||
i += 4;
|
||||
} else {
|
||||
prev_mask = (prev_mask << 1) | 1;
|
||||
}
|
||||
}
|
||||
|
||||
prev_pos = i - prev_pos;
|
||||
s->x86_prev_mask = prev_pos > 3 ? 0 : prev_mask << (prev_pos - 1);
|
||||
return i;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef XZ_DEC_POWERPC
|
||||
static noinline_for_stack size_t bcj_powerpc(
|
||||
struct xz_dec_bcj *s, uint8_t *buf, size_t size)
|
||||
{
|
||||
size_t i;
|
||||
uint32_t instr;
|
||||
|
||||
for (i = 0; i + 4 <= size; i += 4) {
|
||||
instr = get_unaligned_be32(buf + i);
|
||||
if ((instr & 0xFC000003) == 0x48000001) {
|
||||
instr &= 0x03FFFFFC;
|
||||
instr -= s->pos + (uint32_t)i;
|
||||
instr &= 0x03FFFFFC;
|
||||
instr |= 0x48000001;
|
||||
put_unaligned_be32(instr, buf + i);
|
||||
}
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef XZ_DEC_IA64
|
||||
static noinline_for_stack size_t bcj_ia64(
|
||||
struct xz_dec_bcj *s, uint8_t *buf, size_t size)
|
||||
{
|
||||
static const uint8_t branch_table[32] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
4, 4, 6, 6, 0, 0, 7, 7,
|
||||
4, 4, 0, 0, 4, 4, 0, 0
|
||||
};
|
||||
|
||||
/*
|
||||
* The local variables take a little bit stack space, but it's less
|
||||
* than what LZMA2 decoder takes, so it doesn't make sense to reduce
|
||||
* stack usage here without doing that for the LZMA2 decoder too.
|
||||
*/
|
||||
|
||||
/* Loop counters */
|
||||
size_t i;
|
||||
size_t j;
|
||||
|
||||
/* Instruction slot (0, 1, or 2) in the 128-bit instruction word */
|
||||
uint32_t slot;
|
||||
|
||||
/* Bitwise offset of the instruction indicated by slot */
|
||||
uint32_t bit_pos;
|
||||
|
||||
/* bit_pos split into byte and bit parts */
|
||||
uint32_t byte_pos;
|
||||
uint32_t bit_res;
|
||||
|
||||
/* Address part of an instruction */
|
||||
uint32_t addr;
|
||||
|
||||
/* Mask used to detect which instructions to convert */
|
||||
uint32_t mask;
|
||||
|
||||
/* 41-bit instruction stored somewhere in the lowest 48 bits */
|
||||
uint64_t instr;
|
||||
|
||||
/* Instruction normalized with bit_res for easier manipulation */
|
||||
uint64_t norm;
|
||||
|
||||
for (i = 0; i + 16 <= size; i += 16) {
|
||||
mask = branch_table[buf[i] & 0x1F];
|
||||
for (slot = 0, bit_pos = 5; slot < 3; ++slot, bit_pos += 41) {
|
||||
if (((mask >> slot) & 1) == 0)
|
||||
continue;
|
||||
|
||||
byte_pos = bit_pos >> 3;
|
||||
bit_res = bit_pos & 7;
|
||||
instr = 0;
|
||||
for (j = 0; j < 6; ++j)
|
||||
instr |= (uint64_t)(buf[i + j + byte_pos])
|
||||
<< (8 * j);
|
||||
|
||||
norm = instr >> bit_res;
|
||||
|
||||
if (((norm >> 37) & 0x0F) == 0x05
|
||||
&& ((norm >> 9) & 0x07) == 0) {
|
||||
addr = (norm >> 13) & 0x0FFFFF;
|
||||
addr |= ((uint32_t)(norm >> 36) & 1) << 20;
|
||||
addr <<= 4;
|
||||
addr -= s->pos + (uint32_t)i;
|
||||
addr >>= 4;
|
||||
|
||||
norm &= ~((uint64_t)0x8FFFFF << 13);
|
||||
norm |= (uint64_t)(addr & 0x0FFFFF) << 13;
|
||||
norm |= (uint64_t)(addr & 0x100000)
|
||||
<< (36 - 20);
|
||||
|
||||
instr &= (1 << bit_res) - 1;
|
||||
instr |= norm << bit_res;
|
||||
|
||||
for (j = 0; j < 6; j++)
|
||||
buf[i + j + byte_pos]
|
||||
= (uint8_t)(instr >> (8 * j));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef XZ_DEC_ARM
|
||||
static noinline_for_stack size_t bcj_arm(
|
||||
struct xz_dec_bcj *s, uint8_t *buf, size_t size)
|
||||
{
|
||||
size_t i;
|
||||
uint32_t addr;
|
||||
|
||||
for (i = 0; i + 4 <= size; i += 4) {
|
||||
if (buf[i + 3] == 0xEB) {
|
||||
addr = (uint32_t)buf[i] | ((uint32_t)buf[i + 1] << 8)
|
||||
| ((uint32_t)buf[i + 2] << 16);
|
||||
addr <<= 2;
|
||||
addr -= s->pos + (uint32_t)i + 8;
|
||||
addr >>= 2;
|
||||
buf[i] = (uint8_t)addr;
|
||||
buf[i + 1] = (uint8_t)(addr >> 8);
|
||||
buf[i + 2] = (uint8_t)(addr >> 16);
|
||||
}
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef XZ_DEC_ARMTHUMB
|
||||
static noinline_for_stack size_t bcj_armthumb(
|
||||
struct xz_dec_bcj *s, uint8_t *buf, size_t size)
|
||||
{
|
||||
size_t i;
|
||||
uint32_t addr;
|
||||
|
||||
for (i = 0; i + 4 <= size; i += 2) {
|
||||
if ((buf[i + 1] & 0xF8) == 0xF0
|
||||
&& (buf[i + 3] & 0xF8) == 0xF8) {
|
||||
addr = (((uint32_t)buf[i + 1] & 0x07) << 19)
|
||||
| ((uint32_t)buf[i] << 11)
|
||||
| (((uint32_t)buf[i + 3] & 0x07) << 8)
|
||||
| (uint32_t)buf[i + 2];
|
||||
addr <<= 1;
|
||||
addr -= s->pos + (uint32_t)i + 4;
|
||||
addr >>= 1;
|
||||
buf[i + 1] = (uint8_t)(0xF0 | ((addr >> 19) & 0x07));
|
||||
buf[i] = (uint8_t)(addr >> 11);
|
||||
buf[i + 3] = (uint8_t)(0xF8 | ((addr >> 8) & 0x07));
|
||||
buf[i + 2] = (uint8_t)addr;
|
||||
i += 2;
|
||||
}
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef XZ_DEC_SPARC
|
||||
static noinline_for_stack size_t bcj_sparc(
|
||||
struct xz_dec_bcj *s, uint8_t *buf, size_t size)
|
||||
{
|
||||
size_t i;
|
||||
uint32_t instr;
|
||||
|
||||
for (i = 0; i + 4 <= size; i += 4) {
|
||||
instr = get_unaligned_be32(buf + i);
|
||||
if ((instr >> 22) == 0x100 || (instr >> 22) == 0x1FF) {
|
||||
instr <<= 2;
|
||||
instr -= s->pos + (uint32_t)i;
|
||||
instr >>= 2;
|
||||
instr = ((uint32_t)0x40000000 - (instr & 0x400000))
|
||||
| 0x40000000 | (instr & 0x3FFFFF);
|
||||
put_unaligned_be32(instr, buf + i);
|
||||
}
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Apply the selected BCJ filter. Update *pos and s->pos to match the amount
|
||||
* of data that got filtered.
|
||||
*
|
||||
* NOTE: This is implemented as a switch statement to avoid using function
|
||||
* pointers, which could be problematic in the kernel boot code, which must
|
||||
* avoid pointers to static data (at least on x86).
|
||||
*/
|
||||
static void bcj_apply(struct xz_dec_bcj *s,
|
||||
uint8_t *buf, size_t *pos, size_t size)
|
||||
{
|
||||
size_t filtered;
|
||||
|
||||
buf += *pos;
|
||||
size -= *pos;
|
||||
|
||||
switch (s->type) {
|
||||
#ifdef XZ_DEC_X86
|
||||
case BCJ_X86:
|
||||
filtered = bcj_x86(s, buf, size);
|
||||
break;
|
||||
#endif
|
||||
#ifdef XZ_DEC_POWERPC
|
||||
case BCJ_POWERPC:
|
||||
filtered = bcj_powerpc(s, buf, size);
|
||||
break;
|
||||
#endif
|
||||
#ifdef XZ_DEC_IA64
|
||||
case BCJ_IA64:
|
||||
filtered = bcj_ia64(s, buf, size);
|
||||
break;
|
||||
#endif
|
||||
#ifdef XZ_DEC_ARM
|
||||
case BCJ_ARM:
|
||||
filtered = bcj_arm(s, buf, size);
|
||||
break;
|
||||
#endif
|
||||
#ifdef XZ_DEC_ARMTHUMB
|
||||
case BCJ_ARMTHUMB:
|
||||
filtered = bcj_armthumb(s, buf, size);
|
||||
break;
|
||||
#endif
|
||||
#ifdef XZ_DEC_SPARC
|
||||
case BCJ_SPARC:
|
||||
filtered = bcj_sparc(s, buf, size);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
/* Never reached but silence compiler warnings. */
|
||||
filtered = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
*pos += filtered;
|
||||
s->pos += filtered;
|
||||
}
|
||||
|
||||
/*
|
||||
* Flush pending filtered data from temp to the output buffer.
|
||||
* Move the remaining mixture of possibly filtered and unfiltered
|
||||
* data to the beginning of temp.
|
||||
*/
|
||||
static void bcj_flush(struct xz_dec_bcj *s, struct xz_buf *b)
|
||||
{
|
||||
size_t copy_size;
|
||||
|
||||
copy_size = min_t(size_t, s->temp.filtered, b->out_size - b->out_pos);
|
||||
memcpy(b->out + b->out_pos, s->temp.buf, copy_size);
|
||||
b->out_pos += copy_size;
|
||||
|
||||
s->temp.filtered -= copy_size;
|
||||
s->temp.size -= copy_size;
|
||||
memmove(s->temp.buf, s->temp.buf + copy_size, s->temp.size);
|
||||
}
|
||||
|
||||
/*
|
||||
* The BCJ filter functions are primitive in sense that they process the
|
||||
* data in chunks of 1-16 bytes. To hide this issue, this function does
|
||||
* some buffering.
|
||||
*/
|
||||
enum xz_ret xz_dec_bcj_run(struct xz_dec_bcj *s,
|
||||
struct xz_dec_lzma2 *lzma2, struct xz_buf *b)
|
||||
{
|
||||
size_t out_start;
|
||||
|
||||
/*
|
||||
* Flush pending already filtered data to the output buffer. Return
|
||||
* immediatelly if we couldn't flush everything, or if the next
|
||||
* filter in the chain had already returned XZ_STREAM_END.
|
||||
*/
|
||||
if (s->temp.filtered > 0) {
|
||||
bcj_flush(s, b);
|
||||
if (s->temp.filtered > 0)
|
||||
return XZ_OK;
|
||||
|
||||
if (s->ret == XZ_STREAM_END)
|
||||
return XZ_STREAM_END;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we have more output space than what is currently pending in
|
||||
* temp, copy the unfiltered data from temp to the output buffer
|
||||
* and try to fill the output buffer by decoding more data from the
|
||||
* next filter in the chain. Apply the BCJ filter on the new data
|
||||
* in the output buffer. If everything cannot be filtered, copy it
|
||||
* to temp and rewind the output buffer position accordingly.
|
||||
*/
|
||||
if (s->temp.size < b->out_size - b->out_pos) {
|
||||
out_start = b->out_pos;
|
||||
memcpy(b->out + b->out_pos, s->temp.buf, s->temp.size);
|
||||
b->out_pos += s->temp.size;
|
||||
|
||||
s->ret = xz_dec_lzma2_run(lzma2, b);
|
||||
if (s->ret != XZ_STREAM_END
|
||||
&& (s->ret != XZ_OK || s->single_call))
|
||||
return s->ret;
|
||||
|
||||
bcj_apply(s, b->out, &out_start, b->out_pos);
|
||||
|
||||
/*
|
||||
* As an exception, if the next filter returned XZ_STREAM_END,
|
||||
* we can do that too, since the last few bytes that remain
|
||||
* unfiltered are meant to remain unfiltered.
|
||||
*/
|
||||
if (s->ret == XZ_STREAM_END)
|
||||
return XZ_STREAM_END;
|
||||
|
||||
s->temp.size = b->out_pos - out_start;
|
||||
b->out_pos -= s->temp.size;
|
||||
memcpy(s->temp.buf, b->out + b->out_pos, s->temp.size);
|
||||
}
|
||||
|
||||
/*
|
||||
* If we have unfiltered data in temp, try to fill by decoding more
|
||||
* data from the next filter. Apply the BCJ filter on temp. Then we
|
||||
* hopefully can fill the actual output buffer by copying filtered
|
||||
* data from temp. A mix of filtered and unfiltered data may be left
|
||||
* in temp; it will be taken care on the next call to this function.
|
||||
*/
|
||||
if (s->temp.size > 0) {
|
||||
/* Make b->out{,_pos,_size} temporarily point to s->temp. */
|
||||
s->out = b->out;
|
||||
s->out_pos = b->out_pos;
|
||||
s->out_size = b->out_size;
|
||||
b->out = s->temp.buf;
|
||||
b->out_pos = s->temp.size;
|
||||
b->out_size = sizeof(s->temp.buf);
|
||||
|
||||
s->ret = xz_dec_lzma2_run(lzma2, b);
|
||||
|
||||
s->temp.size = b->out_pos;
|
||||
b->out = s->out;
|
||||
b->out_pos = s->out_pos;
|
||||
b->out_size = s->out_size;
|
||||
|
||||
if (s->ret != XZ_OK && s->ret != XZ_STREAM_END)
|
||||
return s->ret;
|
||||
|
||||
bcj_apply(s, s->temp.buf, &s->temp.filtered, s->temp.size);
|
||||
|
||||
/*
|
||||
* If the next filter returned XZ_STREAM_END, we mark that
|
||||
* everything is filtered, since the last unfiltered bytes
|
||||
* of the stream are meant to be left as is.
|
||||
*/
|
||||
if (s->ret == XZ_STREAM_END)
|
||||
s->temp.filtered = s->temp.size;
|
||||
|
||||
bcj_flush(s, b);
|
||||
if (s->temp.filtered > 0)
|
||||
return XZ_OK;
|
||||
}
|
||||
|
||||
return s->ret;
|
||||
}
|
||||
|
||||
struct xz_dec_bcj * xz_dec_bcj_create(bool single_call)
|
||||
{
|
||||
struct xz_dec_bcj *s = kmalloc(sizeof(*s), GFP_KERNEL);
|
||||
if (s != NULL)
|
||||
s->single_call = single_call;
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
enum xz_ret xz_dec_bcj_reset(
|
||||
struct xz_dec_bcj *s, uint8_t id)
|
||||
{
|
||||
switch (id) {
|
||||
#ifdef XZ_DEC_X86
|
||||
case BCJ_X86:
|
||||
#endif
|
||||
#ifdef XZ_DEC_POWERPC
|
||||
case BCJ_POWERPC:
|
||||
#endif
|
||||
#ifdef XZ_DEC_IA64
|
||||
case BCJ_IA64:
|
||||
#endif
|
||||
#ifdef XZ_DEC_ARM
|
||||
case BCJ_ARM:
|
||||
#endif
|
||||
#ifdef XZ_DEC_ARMTHUMB
|
||||
case BCJ_ARMTHUMB:
|
||||
#endif
|
||||
#ifdef XZ_DEC_SPARC
|
||||
case BCJ_SPARC:
|
||||
#endif
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Unsupported Filter ID */
|
||||
return XZ_OPTIONS_ERROR;
|
||||
}
|
||||
|
||||
s->type = id;
|
||||
s->ret = XZ_OK;
|
||||
s->pos = 0;
|
||||
s->x86_prev_mask = 0;
|
||||
s->temp.filtered = 0;
|
||||
s->temp.size = 0;
|
||||
|
||||
return XZ_OK;
|
||||
}
|
1168
grub-core/lib/xzembed/xz_dec_lzma2.c
Normal file
1168
grub-core/lib/xzembed/xz_dec_lzma2.c
Normal file
File diff suppressed because it is too large
Load diff
854
grub-core/lib/xzembed/xz_dec_stream.c
Normal file
854
grub-core/lib/xzembed/xz_dec_stream.c
Normal file
|
@ -0,0 +1,854 @@
|
|||
/* xz_dec_stream.c - .xz Stream decoder */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2010 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/>.
|
||||
*/
|
||||
/*
|
||||
* This file is based on code from XZ embedded project
|
||||
* http://tukaani.org/xz/embedded.html
|
||||
*/
|
||||
|
||||
#include "xz_config.h"
|
||||
#include "xz_private.h"
|
||||
#include "xz_stream.h"
|
||||
|
||||
#include <grub/crypto.h>
|
||||
|
||||
/* Hash used to validate the Index field */
|
||||
struct xz_dec_hash {
|
||||
vli_type unpadded;
|
||||
vli_type uncompressed;
|
||||
uint8_t *crc32_context;
|
||||
};
|
||||
|
||||
struct xz_dec {
|
||||
/* Position in dec_main() */
|
||||
enum {
|
||||
SEQ_STREAM_HEADER,
|
||||
SEQ_BLOCK_START,
|
||||
SEQ_BLOCK_HEADER,
|
||||
SEQ_BLOCK_UNCOMPRESS,
|
||||
SEQ_BLOCK_PADDING,
|
||||
SEQ_BLOCK_CHECK,
|
||||
SEQ_INDEX,
|
||||
SEQ_INDEX_PADDING,
|
||||
SEQ_INDEX_CRC32,
|
||||
SEQ_STREAM_FOOTER
|
||||
} sequence;
|
||||
|
||||
/* Position in variable-length integers and Check fields */
|
||||
uint32_t pos;
|
||||
|
||||
/* Variable-length integer decoded by dec_vli() */
|
||||
vli_type vli;
|
||||
|
||||
/* Saved in_pos and out_pos */
|
||||
size_t in_start;
|
||||
size_t out_start;
|
||||
|
||||
/* CRC32 value in Block or Index */
|
||||
uint32_t crc32_temp; /* need for crc32_validate*/
|
||||
uint8_t *crc32_context;
|
||||
|
||||
/* True if CRC32 is calculated from uncompressed data */
|
||||
bool has_crc32;
|
||||
|
||||
/* True if we are operating in single-call mode. */
|
||||
bool single_call;
|
||||
|
||||
/*
|
||||
* True if the next call to xz_dec_run() is allowed to return
|
||||
* XZ_BUF_ERROR.
|
||||
*/
|
||||
bool allow_buf_error;
|
||||
|
||||
/* Information stored in Block Header */
|
||||
struct {
|
||||
/*
|
||||
* Value stored in the Compressed Size field, or
|
||||
* VLI_UNKNOWN if Compressed Size is not present.
|
||||
*/
|
||||
vli_type compressed;
|
||||
|
||||
/*
|
||||
* Value stored in the Uncompressed Size field, or
|
||||
* VLI_UNKNOWN if Uncompressed Size is not present.
|
||||
*/
|
||||
vli_type uncompressed;
|
||||
|
||||
/* Size of the Block Header field */
|
||||
uint32_t size;
|
||||
} block_header;
|
||||
|
||||
/* Information collected when decoding Blocks */
|
||||
struct {
|
||||
/* Observed compressed size of the current Block */
|
||||
vli_type compressed;
|
||||
|
||||
/* Observed uncompressed size of the current Block */
|
||||
vli_type uncompressed;
|
||||
|
||||
/* Number of Blocks decoded so far */
|
||||
vli_type count;
|
||||
|
||||
/*
|
||||
* Hash calculated from the Block sizes. This is used to
|
||||
* validate the Index field.
|
||||
*/
|
||||
struct xz_dec_hash hash;
|
||||
} block;
|
||||
|
||||
/* Variables needed when verifying the Index field */
|
||||
struct {
|
||||
/* Position in dec_index() */
|
||||
enum {
|
||||
SEQ_INDEX_COUNT,
|
||||
SEQ_INDEX_UNPADDED,
|
||||
SEQ_INDEX_UNCOMPRESSED
|
||||
} sequence;
|
||||
|
||||
/* Size of the Index in bytes */
|
||||
vli_type size;
|
||||
|
||||
/* Number of Records (matches block.count in valid files) */
|
||||
vli_type count;
|
||||
|
||||
/*
|
||||
* Hash calculated from the Records (matches block.hash in
|
||||
* valid files).
|
||||
*/
|
||||
struct xz_dec_hash hash;
|
||||
} index;
|
||||
|
||||
/*
|
||||
* Temporary buffer needed to hold Stream Header, Block Header,
|
||||
* and Stream Footer. The Block Header is the biggest (1 KiB)
|
||||
* so we reserve space according to that. buf[] has to be aligned
|
||||
* to a multiple of four bytes; the size_t variables before it
|
||||
* should guarantee this.
|
||||
*/
|
||||
struct {
|
||||
size_t pos;
|
||||
size_t size;
|
||||
uint8_t buf[1024];
|
||||
} temp;
|
||||
|
||||
struct xz_dec_lzma2 *lzma2;
|
||||
|
||||
#ifdef XZ_DEC_BCJ
|
||||
struct xz_dec_bcj *bcj;
|
||||
bool bcj_active;
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
* Fill s->temp by copying data starting from b->in[b->in_pos]. Caller
|
||||
* must have set s->temp.pos to indicate how much data we are supposed
|
||||
* to copy into s->temp.buf. Return true once s->temp.pos has reached
|
||||
* s->temp.size.
|
||||
*/
|
||||
static bool fill_temp(struct xz_dec *s, struct xz_buf *b)
|
||||
{
|
||||
size_t copy_size = min_t(size_t,
|
||||
b->in_size - b->in_pos, s->temp.size - s->temp.pos);
|
||||
|
||||
memcpy(s->temp.buf + s->temp.pos, b->in + b->in_pos, copy_size);
|
||||
b->in_pos += copy_size;
|
||||
s->temp.pos += copy_size;
|
||||
|
||||
if (s->temp.pos == s->temp.size) {
|
||||
s->temp.pos = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Decode a variable-length integer (little-endian base-128 encoding) */
|
||||
static enum xz_ret dec_vli(struct xz_dec *s,
|
||||
const uint8_t *in, size_t *in_pos, size_t in_size)
|
||||
{
|
||||
uint8_t byte;
|
||||
|
||||
if (s->pos == 0)
|
||||
s->vli = 0;
|
||||
|
||||
while (*in_pos < in_size) {
|
||||
byte = in[*in_pos];
|
||||
++*in_pos;
|
||||
|
||||
s->vli |= (vli_type)(byte & 0x7F) << s->pos;
|
||||
|
||||
if ((byte & 0x80) == 0) {
|
||||
/* Don't allow non-minimal encodings. */
|
||||
if (byte == 0 && s->pos != 0)
|
||||
return XZ_DATA_ERROR;
|
||||
|
||||
s->pos = 0;
|
||||
return XZ_STREAM_END;
|
||||
}
|
||||
|
||||
s->pos += 7;
|
||||
if (s->pos == 7 * VLI_BYTES_MAX)
|
||||
return XZ_DATA_ERROR;
|
||||
}
|
||||
|
||||
return XZ_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Decode the Compressed Data field from a Block. Update and validate
|
||||
* the observed compressed and uncompressed sizes of the Block so that
|
||||
* they don't exceed the values possibly stored in the Block Header
|
||||
* (validation assumes that no integer overflow occurs, since vli_type
|
||||
* is normally uint64_t). Update the CRC32 if presence of the CRC32
|
||||
* field was indicated in Stream Header.
|
||||
*
|
||||
* Once the decoding is finished, validate that the observed sizes match
|
||||
* the sizes possibly stored in the Block Header. Update the hash and
|
||||
* Block count, which are later used to validate the Index field.
|
||||
*/
|
||||
static enum xz_ret dec_block(struct xz_dec *s, struct xz_buf *b)
|
||||
{
|
||||
enum xz_ret ret;
|
||||
|
||||
s->in_start = b->in_pos;
|
||||
s->out_start = b->out_pos;
|
||||
|
||||
#ifdef XZ_DEC_BCJ
|
||||
if (s->bcj_active)
|
||||
ret = xz_dec_bcj_run(s->bcj, s->lzma2, b);
|
||||
else
|
||||
#endif
|
||||
ret = xz_dec_lzma2_run(s->lzma2, b);
|
||||
|
||||
s->block.compressed += b->in_pos - s->in_start;
|
||||
s->block.uncompressed += b->out_pos - s->out_start;
|
||||
|
||||
/*
|
||||
* There is no need to separately check for VLI_UNKNOWN, since
|
||||
* the observed sizes are always smaller than VLI_UNKNOWN.
|
||||
*/
|
||||
if (s->block.compressed > s->block_header.compressed
|
||||
|| s->block.uncompressed
|
||||
> s->block_header.uncompressed)
|
||||
return XZ_DATA_ERROR;
|
||||
|
||||
if (s->has_crc32)
|
||||
GRUB_MD_CRC32->write(s->crc32_context,b->out + s->out_start,
|
||||
b->out_pos - s->out_start);
|
||||
|
||||
if (ret == XZ_STREAM_END) {
|
||||
if (s->block_header.compressed != VLI_UNKNOWN
|
||||
&& s->block_header.compressed
|
||||
!= s->block.compressed)
|
||||
return XZ_DATA_ERROR;
|
||||
|
||||
if (s->block_header.uncompressed != VLI_UNKNOWN
|
||||
&& s->block_header.uncompressed
|
||||
!= s->block.uncompressed)
|
||||
return XZ_DATA_ERROR;
|
||||
|
||||
s->block.hash.unpadded += s->block_header.size
|
||||
+ s->block.compressed;
|
||||
if (s->has_crc32)
|
||||
s->block.hash.unpadded += 4;
|
||||
|
||||
s->block.hash.uncompressed += s->block.uncompressed;
|
||||
|
||||
GRUB_MD_CRC32->write(s->block.hash.crc32_context,
|
||||
(const uint8_t *)&s->block.hash, sizeof(s->block.hash));
|
||||
|
||||
++s->block.count;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Update the Index size and the CRC32 value. */
|
||||
static void index_update(struct xz_dec *s, const struct xz_buf *b)
|
||||
{
|
||||
size_t in_used = b->in_pos - s->in_start;
|
||||
s->index.size += in_used;
|
||||
GRUB_MD_CRC32->write(s->crc32_context,b->in + s->in_start, in_used);
|
||||
}
|
||||
|
||||
/*
|
||||
* Decode the Number of Records, Unpadded Size, and Uncompressed Size
|
||||
* fields from the Index field. That is, Index Padding and CRC32 are not
|
||||
* decoded by this function.
|
||||
*
|
||||
* This can return XZ_OK (more input needed), XZ_STREAM_END (everything
|
||||
* successfully decoded), or XZ_DATA_ERROR (input is corrupt).
|
||||
*/
|
||||
static enum xz_ret dec_index(struct xz_dec *s, struct xz_buf *b)
|
||||
{
|
||||
enum xz_ret ret;
|
||||
|
||||
do {
|
||||
ret = dec_vli(s, b->in, &b->in_pos, b->in_size);
|
||||
if (ret != XZ_STREAM_END) {
|
||||
index_update(s, b);
|
||||
return ret;
|
||||
}
|
||||
|
||||
switch (s->index.sequence) {
|
||||
case SEQ_INDEX_COUNT:
|
||||
s->index.count = s->vli;
|
||||
|
||||
/*
|
||||
* Validate that the Number of Records field
|
||||
* indicates the same number of Records as
|
||||
* there were Blocks in the Stream.
|
||||
*/
|
||||
if (s->index.count != s->block.count)
|
||||
return XZ_DATA_ERROR;
|
||||
|
||||
s->index.sequence = SEQ_INDEX_UNPADDED;
|
||||
break;
|
||||
|
||||
case SEQ_INDEX_UNPADDED:
|
||||
s->index.hash.unpadded += s->vli;
|
||||
s->index.sequence = SEQ_INDEX_UNCOMPRESSED;
|
||||
break;
|
||||
|
||||
case SEQ_INDEX_UNCOMPRESSED:
|
||||
s->index.hash.uncompressed += s->vli;
|
||||
|
||||
GRUB_MD_CRC32->write(s->index.hash.crc32_context,
|
||||
(const uint8_t *)&s->index.hash,
|
||||
sizeof(s->index.hash));
|
||||
|
||||
--s->index.count;
|
||||
s->index.sequence = SEQ_INDEX_UNPADDED;
|
||||
break;
|
||||
}
|
||||
} while (s->index.count > 0);
|
||||
|
||||
return XZ_STREAM_END;
|
||||
}
|
||||
|
||||
/*
|
||||
* Validate that the next four input bytes match the value of s->crc32.
|
||||
* s->pos must be zero when starting to validate the first byte.
|
||||
*/
|
||||
static enum xz_ret crc32_validate(struct xz_dec *s, struct xz_buf *b)
|
||||
{
|
||||
if(s->crc32_temp == 0)
|
||||
{
|
||||
GRUB_MD_CRC32->final(s->crc32_context);
|
||||
s->crc32_temp = get_unaligned_be32(GRUB_MD_CRC32->read(s->crc32_context));
|
||||
}
|
||||
|
||||
do {
|
||||
if (b->in_pos == b->in_size)
|
||||
return XZ_OK;
|
||||
|
||||
if (((s->crc32_temp >> s->pos) & 0xFF) != b->in[b->in_pos++])
|
||||
return XZ_DATA_ERROR;
|
||||
|
||||
s->pos += 8;
|
||||
|
||||
} while (s->pos < 32);
|
||||
|
||||
GRUB_MD_CRC32->init(s->crc32_context);
|
||||
s->crc32_temp = 0;
|
||||
s->pos = 0;
|
||||
|
||||
return XZ_STREAM_END;
|
||||
}
|
||||
|
||||
/* Decode the Stream Header field (the first 12 bytes of the .xz Stream). */
|
||||
static enum xz_ret dec_stream_header(struct xz_dec *s)
|
||||
{
|
||||
if (! memeq(s->temp.buf, HEADER_MAGIC, HEADER_MAGIC_SIZE))
|
||||
return XZ_FORMAT_ERROR;
|
||||
|
||||
uint8_t crc32_context[GRUB_MD_CRC32->contextsize];
|
||||
|
||||
GRUB_MD_CRC32->init(crc32_context);
|
||||
GRUB_MD_CRC32->write(crc32_context,s->temp.buf + HEADER_MAGIC_SIZE, 2);
|
||||
GRUB_MD_CRC32->final(crc32_context);
|
||||
|
||||
uint32_t resultcrc = get_unaligned_be32(GRUB_MD_CRC32->read(crc32_context));
|
||||
uint32_t readcrc = get_unaligned_le32(s->temp.buf + HEADER_MAGIC_SIZE + 2);
|
||||
|
||||
if(resultcrc != readcrc)
|
||||
return XZ_DATA_ERROR;
|
||||
|
||||
/*
|
||||
* Decode the Stream Flags field. Of integrity checks, we support
|
||||
* only none (Check ID = 0) and CRC32 (Check ID = 1).
|
||||
*/
|
||||
if (s->temp.buf[HEADER_MAGIC_SIZE] != 0
|
||||
|| s->temp.buf[HEADER_MAGIC_SIZE + 1] > 1)
|
||||
return XZ_OPTIONS_ERROR;
|
||||
|
||||
s->has_crc32 = s->temp.buf[HEADER_MAGIC_SIZE + 1];
|
||||
|
||||
return XZ_OK;
|
||||
}
|
||||
|
||||
/* Decode the Stream Footer field (the last 12 bytes of the .xz Stream) */
|
||||
static enum xz_ret dec_stream_footer(struct xz_dec *s)
|
||||
{
|
||||
if (! memeq(s->temp.buf + 10, FOOTER_MAGIC, FOOTER_MAGIC_SIZE))
|
||||
return XZ_DATA_ERROR;
|
||||
|
||||
uint8_t crc32_context[GRUB_MD_CRC32->contextsize];
|
||||
|
||||
GRUB_MD_CRC32->init(crc32_context);
|
||||
GRUB_MD_CRC32->write(crc32_context, s->temp.buf + 4, 6);
|
||||
GRUB_MD_CRC32->final(crc32_context);
|
||||
|
||||
uint32_t resultcrc = get_unaligned_be32(GRUB_MD_CRC32->read(crc32_context));
|
||||
uint32_t readcrc = get_unaligned_le32(s->temp.buf);
|
||||
|
||||
if(resultcrc != readcrc)
|
||||
return XZ_DATA_ERROR;
|
||||
|
||||
/*
|
||||
* Validate Backward Size. Note that we never added the size of the
|
||||
* Index CRC32 field to s->index.size, thus we use s->index.size / 4
|
||||
* instead of s->index.size / 4 - 1.
|
||||
*/
|
||||
if ((s->index.size >> 2) != get_le32(s->temp.buf + 4))
|
||||
return XZ_DATA_ERROR;
|
||||
|
||||
if (s->temp.buf[8] != 0 || s->temp.buf[9] != s->has_crc32)
|
||||
return XZ_DATA_ERROR;
|
||||
|
||||
/*
|
||||
* Use XZ_STREAM_END instead of XZ_OK to be more convenient
|
||||
* for the caller.
|
||||
*/
|
||||
return XZ_STREAM_END;
|
||||
}
|
||||
|
||||
/* Decode the Block Header and initialize the filter chain. */
|
||||
static enum xz_ret dec_block_header(struct xz_dec *s)
|
||||
{
|
||||
enum xz_ret ret;
|
||||
|
||||
/*
|
||||
* Validate the CRC32. We know that the temp buffer is at least
|
||||
* eight bytes so this is safe.
|
||||
*/
|
||||
s->temp.size -= 4;
|
||||
|
||||
uint8_t crc32_context[GRUB_MD_CRC32->contextsize];
|
||||
|
||||
GRUB_MD_CRC32->init(crc32_context);
|
||||
GRUB_MD_CRC32->write(crc32_context, s->temp.buf, s->temp.size);
|
||||
GRUB_MD_CRC32->final(crc32_context);
|
||||
|
||||
uint32_t resultcrc = get_unaligned_be32(GRUB_MD_CRC32->read(crc32_context));
|
||||
uint32_t readcrc = get_unaligned_le32(s->temp.buf + s->temp.size);
|
||||
|
||||
if (resultcrc != readcrc)
|
||||
return XZ_DATA_ERROR;
|
||||
|
||||
s->temp.pos = 2;
|
||||
|
||||
/*
|
||||
* Catch unsupported Block Flags. We support only one or two filters
|
||||
* in the chain, so we catch that with the same test.
|
||||
*/
|
||||
#ifdef XZ_DEC_BCJ
|
||||
if (s->temp.buf[1] & 0x3E)
|
||||
#else
|
||||
if (s->temp.buf[1] & 0x3F)
|
||||
#endif
|
||||
return XZ_OPTIONS_ERROR;
|
||||
|
||||
/* Compressed Size */
|
||||
if (s->temp.buf[1] & 0x40) {
|
||||
if (dec_vli(s, s->temp.buf, &s->temp.pos, s->temp.size)
|
||||
!= XZ_STREAM_END)
|
||||
return XZ_DATA_ERROR;
|
||||
|
||||
s->block_header.compressed = s->vli;
|
||||
} else {
|
||||
s->block_header.compressed = VLI_UNKNOWN;
|
||||
}
|
||||
|
||||
/* Uncompressed Size */
|
||||
if (s->temp.buf[1] & 0x80) {
|
||||
if (dec_vli(s, s->temp.buf, &s->temp.pos, s->temp.size)
|
||||
!= XZ_STREAM_END)
|
||||
return XZ_DATA_ERROR;
|
||||
|
||||
s->block_header.uncompressed = s->vli;
|
||||
} else {
|
||||
s->block_header.uncompressed = VLI_UNKNOWN;
|
||||
}
|
||||
|
||||
#ifdef XZ_DEC_BCJ
|
||||
/* If there are two filters, the first one must be a BCJ filter. */
|
||||
s->bcj_active = s->temp.buf[1] & 0x01;
|
||||
if (s->bcj_active) {
|
||||
if (s->temp.size - s->temp.pos < 2)
|
||||
return XZ_OPTIONS_ERROR;
|
||||
|
||||
ret = xz_dec_bcj_reset(s->bcj, s->temp.buf[s->temp.pos++]);
|
||||
if (ret != XZ_OK)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* We don't support custom start offset,
|
||||
* so Size of Properties must be zero.
|
||||
*/
|
||||
if (s->temp.buf[s->temp.pos++] != 0x00)
|
||||
return XZ_OPTIONS_ERROR;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Valid Filter Flags always take at least two bytes. */
|
||||
if (s->temp.size - s->temp.pos < 2)
|
||||
return XZ_DATA_ERROR;
|
||||
|
||||
/* Filter ID = LZMA2 */
|
||||
if (s->temp.buf[s->temp.pos++] != 0x21)
|
||||
return XZ_OPTIONS_ERROR;
|
||||
|
||||
/* Size of Properties = 1-byte Filter Properties */
|
||||
if (s->temp.buf[s->temp.pos++] != 0x01)
|
||||
return XZ_OPTIONS_ERROR;
|
||||
|
||||
/* Filter Properties contains LZMA2 dictionary size. */
|
||||
if (s->temp.size - s->temp.pos < 1)
|
||||
return XZ_DATA_ERROR;
|
||||
|
||||
ret = xz_dec_lzma2_reset(s->lzma2, s->temp.buf[s->temp.pos++]);
|
||||
if (ret != XZ_OK)
|
||||
return ret;
|
||||
|
||||
/* The rest must be Header Padding. */
|
||||
while (s->temp.pos < s->temp.size)
|
||||
if (s->temp.buf[s->temp.pos++] != 0x00)
|
||||
return XZ_OPTIONS_ERROR;
|
||||
|
||||
s->temp.pos = 0;
|
||||
s->block.compressed = 0;
|
||||
s->block.uncompressed = 0;
|
||||
|
||||
return XZ_OK;
|
||||
}
|
||||
|
||||
static enum xz_ret dec_main(struct xz_dec *s, struct xz_buf *b)
|
||||
{
|
||||
enum xz_ret ret;
|
||||
|
||||
/*
|
||||
* Store the start position for the case when we are in the middle
|
||||
* of the Index field.
|
||||
*/
|
||||
s->in_start = b->in_pos;
|
||||
|
||||
while (true) {
|
||||
switch (s->sequence) {
|
||||
case SEQ_STREAM_HEADER:
|
||||
/*
|
||||
* Stream Header is copied to s->temp, and then
|
||||
* decoded from there. This way if the caller
|
||||
* gives us only little input at a time, we can
|
||||
* still keep the Stream Header decoding code
|
||||
* simple. Similar approach is used in many places
|
||||
* in this file.
|
||||
*/
|
||||
if (!fill_temp(s, b))
|
||||
return XZ_OK;
|
||||
|
||||
ret = dec_stream_header(s);
|
||||
if (ret != XZ_OK)
|
||||
return ret;
|
||||
|
||||
s->sequence = SEQ_BLOCK_START;
|
||||
|
||||
case SEQ_BLOCK_START:
|
||||
/* We need one byte of input to continue. */
|
||||
if (b->in_pos == b->in_size)
|
||||
return XZ_OK;
|
||||
|
||||
/* See if this is the beginning of the Index field. */
|
||||
if (b->in[b->in_pos] == 0) {
|
||||
s->in_start = b->in_pos++;
|
||||
s->sequence = SEQ_INDEX;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate the size of the Block Header and
|
||||
* prepare to decode it.
|
||||
*/
|
||||
s->block_header.size
|
||||
= ((uint32_t)b->in[b->in_pos] + 1) * 4;
|
||||
|
||||
s->temp.size = s->block_header.size;
|
||||
s->temp.pos = 0;
|
||||
s->sequence = SEQ_BLOCK_HEADER;
|
||||
|
||||
case SEQ_BLOCK_HEADER:
|
||||
if (!fill_temp(s, b))
|
||||
return XZ_OK;
|
||||
|
||||
ret = dec_block_header(s);
|
||||
if (ret != XZ_OK)
|
||||
return ret;
|
||||
|
||||
s->sequence = SEQ_BLOCK_UNCOMPRESS;
|
||||
|
||||
case SEQ_BLOCK_UNCOMPRESS:
|
||||
ret = dec_block(s, b);
|
||||
if (ret != XZ_STREAM_END)
|
||||
return ret;
|
||||
|
||||
s->sequence = SEQ_BLOCK_PADDING;
|
||||
|
||||
case SEQ_BLOCK_PADDING:
|
||||
/*
|
||||
* Size of Compressed Data + Block Padding
|
||||
* must be a multiple of four. We don't need
|
||||
* s->block.compressed for anything else
|
||||
* anymore, so we use it here to test the size
|
||||
* of the Block Padding field.
|
||||
*/
|
||||
while (s->block.compressed & 3) {
|
||||
if (b->in_pos == b->in_size)
|
||||
return XZ_OK;
|
||||
|
||||
if (b->in[b->in_pos++] != 0)
|
||||
return XZ_DATA_ERROR;
|
||||
|
||||
++s->block.compressed;
|
||||
}
|
||||
|
||||
s->sequence = SEQ_BLOCK_CHECK;
|
||||
|
||||
case SEQ_BLOCK_CHECK:
|
||||
if (s->has_crc32) {
|
||||
ret = crc32_validate(s, b);
|
||||
if (ret != XZ_STREAM_END)
|
||||
return ret;
|
||||
}
|
||||
|
||||
s->sequence = SEQ_BLOCK_START;
|
||||
break;
|
||||
|
||||
case SEQ_INDEX:
|
||||
ret = dec_index(s, b);
|
||||
if (ret != XZ_STREAM_END)
|
||||
return ret;
|
||||
|
||||
s->sequence = SEQ_INDEX_PADDING;
|
||||
|
||||
case SEQ_INDEX_PADDING:
|
||||
while ((s->index.size + (b->in_pos - s->in_start))
|
||||
& 3) {
|
||||
if (b->in_pos == b->in_size) {
|
||||
index_update(s, b);
|
||||
return XZ_OK;
|
||||
}
|
||||
|
||||
if (b->in[b->in_pos++] != 0)
|
||||
return XZ_DATA_ERROR;
|
||||
}
|
||||
|
||||
/* Finish the CRC32 value and Index size. */
|
||||
index_update(s, b);
|
||||
|
||||
/* Compare the hashes to validate the Index field. */
|
||||
if (! memeq(&s->block.hash, &s->index.hash, sizeof(s->block.hash)))
|
||||
return XZ_DATA_ERROR;
|
||||
|
||||
s->sequence = SEQ_INDEX_CRC32;
|
||||
|
||||
case SEQ_INDEX_CRC32:
|
||||
ret = crc32_validate(s, b);
|
||||
if (ret != XZ_STREAM_END)
|
||||
return ret;
|
||||
|
||||
s->temp.size = STREAM_HEADER_SIZE;
|
||||
s->sequence = SEQ_STREAM_FOOTER;
|
||||
|
||||
case SEQ_STREAM_FOOTER:
|
||||
if (!fill_temp(s, b))
|
||||
return XZ_OK;
|
||||
|
||||
return dec_stream_footer(s);
|
||||
}
|
||||
}
|
||||
|
||||
/* Never reached */
|
||||
}
|
||||
|
||||
/*
|
||||
* xz_dec_run() is a wrapper for dec_main() to handle some special cases in
|
||||
* multi-call and single-call decoding.
|
||||
*
|
||||
* In multi-call mode, we must return XZ_BUF_ERROR when it seems clear that we
|
||||
* are not going to make any progress anymore. This is to prevent the caller
|
||||
* from calling us infinitely when the input file is truncated or otherwise
|
||||
* corrupt. Since zlib-style API allows that the caller fills the input buffer
|
||||
* only when the decoder doesn't produce any new output, we have to be careful
|
||||
* to avoid returning XZ_BUF_ERROR too easily: XZ_BUF_ERROR is returned only
|
||||
* after the second consecutive call to xz_dec_run() that makes no progress.
|
||||
*
|
||||
* In single-call mode, if we couldn't decode everything and no error
|
||||
* occurred, either the input is truncated or the output buffer is too small.
|
||||
* Since we know that the last input byte never produces any output, we know
|
||||
* that if all the input was consumed and decoding wasn't finished, the file
|
||||
* must be corrupt. Otherwise the output buffer has to be too small or the
|
||||
* file is corrupt in a way that decoding it produces too big output.
|
||||
*
|
||||
* If single-call decoding fails, we reset b->in_pos and b->out_pos back to
|
||||
* their original values. This is because with some filter chains there won't
|
||||
* be any valid uncompressed data in the output buffer unless the decoding
|
||||
* actually succeeds (that's the price to pay of using the output buffer as
|
||||
* the workspace).
|
||||
*/
|
||||
enum xz_ret xz_dec_run(struct xz_dec *s, struct xz_buf *b)
|
||||
{
|
||||
size_t in_start;
|
||||
size_t out_start;
|
||||
enum xz_ret ret;
|
||||
|
||||
if (s->single_call)
|
||||
xz_dec_reset(s);
|
||||
|
||||
in_start = b->in_pos;
|
||||
out_start = b->out_pos;
|
||||
ret = dec_main(s, b);
|
||||
|
||||
if (s->single_call) {
|
||||
if (ret == XZ_OK)
|
||||
ret = b->in_pos == b->in_size
|
||||
? XZ_DATA_ERROR : XZ_BUF_ERROR;
|
||||
|
||||
if (ret != XZ_STREAM_END) {
|
||||
b->in_pos = in_start;
|
||||
b->out_pos = out_start;
|
||||
}
|
||||
|
||||
} else if (ret == XZ_OK && in_start == b->in_pos
|
||||
&& out_start == b->out_pos) {
|
||||
if (s->allow_buf_error)
|
||||
ret = XZ_BUF_ERROR;
|
||||
|
||||
s->allow_buf_error = true;
|
||||
} else {
|
||||
s->allow_buf_error = false;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct xz_dec * xz_dec_init(uint32_t dict_max)
|
||||
{
|
||||
struct xz_dec *s = kmalloc(sizeof(*s), GFP_KERNEL);
|
||||
if (s == NULL)
|
||||
return NULL;
|
||||
|
||||
/* prepare CRC32 calculators */
|
||||
if(GRUB_MD_CRC32 == NULL)
|
||||
{
|
||||
kfree(s);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
s->crc32_context = kmalloc(GRUB_MD_CRC32->contextsize, GFP_KERNEL);
|
||||
if (s->crc32_context == NULL)
|
||||
{
|
||||
kfree(s);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
s->index.hash.crc32_context = kmalloc(GRUB_MD_CRC32->contextsize, GFP_KERNEL);
|
||||
if (s->index.hash.crc32_context == NULL)
|
||||
{
|
||||
kfree(s->crc32_context);
|
||||
kfree(s);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
s->block.hash.crc32_context = kmalloc(GRUB_MD_CRC32->contextsize, GFP_KERNEL);
|
||||
if (s->block.hash.crc32_context == NULL)
|
||||
{
|
||||
kfree(s->index.hash.crc32_context);
|
||||
kfree(s->crc32_context);
|
||||
kfree(s);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
GRUB_MD_CRC32->init(s->crc32_context);
|
||||
s->crc32_temp = 0;
|
||||
GRUB_MD_CRC32->init(s->index.hash.crc32_context);
|
||||
GRUB_MD_CRC32->init(s->block.hash.crc32_context);
|
||||
|
||||
|
||||
s->single_call = dict_max == 0;
|
||||
|
||||
#ifdef XZ_DEC_BCJ
|
||||
s->bcj = xz_dec_bcj_create(s->single_call);
|
||||
if (s->bcj == NULL)
|
||||
goto error_bcj;
|
||||
#endif
|
||||
|
||||
s->lzma2 = xz_dec_lzma2_create(dict_max);
|
||||
if (s->lzma2 == NULL)
|
||||
goto error_lzma2;
|
||||
|
||||
xz_dec_reset(s);
|
||||
return s;
|
||||
|
||||
error_lzma2:
|
||||
#ifdef XZ_DEC_BCJ
|
||||
xz_dec_bcj_end(s->bcj);
|
||||
error_bcj:
|
||||
#endif
|
||||
kfree(s);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void xz_dec_reset(struct xz_dec *s)
|
||||
{
|
||||
s->sequence = SEQ_STREAM_HEADER;
|
||||
s->allow_buf_error = false;
|
||||
s->pos = 0;
|
||||
|
||||
memzero(&s->block, sizeof(s->block));
|
||||
memzero(&s->index, sizeof(s->index));
|
||||
s->temp.pos = 0;
|
||||
s->temp.size = STREAM_HEADER_SIZE;
|
||||
|
||||
GRUB_MD_CRC32->init(s->crc32_context);
|
||||
s->crc32_temp = 0;
|
||||
GRUB_MD_CRC32->init(s->index.hash.crc32_context);
|
||||
GRUB_MD_CRC32->init(s->block.hash.crc32_context);
|
||||
|
||||
}
|
||||
|
||||
void xz_dec_end(struct xz_dec *s)
|
||||
{
|
||||
if (s != NULL) {
|
||||
xz_dec_lzma2_end(s->lzma2);
|
||||
#ifdef XZ_DEC_BCJ
|
||||
xz_dec_bcj_end(s->bcj);
|
||||
#endif
|
||||
kfree(s);
|
||||
}
|
||||
}
|
236
grub-core/lib/xzembed/xz_lzma2.h
Normal file
236
grub-core/lib/xzembed/xz_lzma2.h
Normal file
|
@ -0,0 +1,236 @@
|
|||
/* xz_lzma2.h - LZMA2 definitions */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2010 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/>.
|
||||
*/
|
||||
/*
|
||||
* This file is based on code from XZ embedded project
|
||||
* http://tukaani.org/xz/embedded.html
|
||||
*/
|
||||
|
||||
#ifndef XZ_LZMA2_H
|
||||
#define XZ_LZMA2_H
|
||||
|
||||
/* dictionary size hard limit
|
||||
* actual size limit is calculated as shown in 5.3.1
|
||||
* http://tukaani.org/xz/xz-file-format.txt
|
||||
*
|
||||
* if bits > 39 dictionary_size = UINT32_MAX
|
||||
* else
|
||||
* dictionary_size = 2 | (bits & 1);
|
||||
* dictionary_size <<= bits / 2 + 11;
|
||||
*
|
||||
* i.e.
|
||||
* 0 - 4 KiB
|
||||
* 6 - 32 KiB
|
||||
* 30 - 128MiB
|
||||
* 39 - 3072 MiB
|
||||
* 40 - 4096 MiB - 1 B
|
||||
* note: implementation supports 39 at maximum
|
||||
*/
|
||||
#define DICT_BIT_SIZE 30
|
||||
|
||||
/* Range coder constants */
|
||||
#define RC_SHIFT_BITS 8
|
||||
#define RC_TOP_BITS 24
|
||||
#define RC_TOP_VALUE (1 << RC_TOP_BITS)
|
||||
#define RC_BIT_MODEL_TOTAL_BITS 11
|
||||
#define RC_BIT_MODEL_TOTAL (1 << RC_BIT_MODEL_TOTAL_BITS)
|
||||
#define RC_MOVE_BITS 5
|
||||
|
||||
/*
|
||||
* Maximum number of position states. A position state is the lowest pb
|
||||
* number of bits of the current uncompressed offset. In some places there
|
||||
* are different sets of probabilities for different position states.
|
||||
*/
|
||||
#define POS_STATES_MAX (1 << 4)
|
||||
|
||||
/*
|
||||
* This enum is used to track which LZMA symbols have occurred most recently
|
||||
* and in which order. This information is used to predict the next symbol.
|
||||
*
|
||||
* Symbols:
|
||||
* - Literal: One 8-bit byte
|
||||
* - Match: Repeat a chunk of data at some distance
|
||||
* - Long repeat: Multi-byte match at a recently seen distance
|
||||
* - Short repeat: One-byte repeat at a recently seen distance
|
||||
*
|
||||
* The symbol names are in from STATE_oldest_older_previous. REP means
|
||||
* either short or long repeated match, and NONLIT means any non-literal.
|
||||
*/
|
||||
enum lzma_state {
|
||||
STATE_LIT_LIT,
|
||||
STATE_MATCH_LIT_LIT,
|
||||
STATE_REP_LIT_LIT,
|
||||
STATE_SHORTREP_LIT_LIT,
|
||||
STATE_MATCH_LIT,
|
||||
STATE_REP_LIT,
|
||||
STATE_SHORTREP_LIT,
|
||||
STATE_LIT_MATCH,
|
||||
STATE_LIT_LONGREP,
|
||||
STATE_LIT_SHORTREP,
|
||||
STATE_NONLIT_MATCH,
|
||||
STATE_NONLIT_REP
|
||||
};
|
||||
|
||||
/* Total number of states */
|
||||
#define STATES 12
|
||||
|
||||
/* The lowest 7 states indicate that the previous state was a literal. */
|
||||
#define LIT_STATES 7
|
||||
|
||||
/* Indicate that the latest symbol was a literal. */
|
||||
static inline void lzma_state_literal(enum lzma_state *state)
|
||||
{
|
||||
if (*state <= STATE_SHORTREP_LIT_LIT)
|
||||
*state = STATE_LIT_LIT;
|
||||
else if (*state <= STATE_LIT_SHORTREP)
|
||||
*state -= 3;
|
||||
else
|
||||
*state -= 6;
|
||||
}
|
||||
|
||||
/* Indicate that the latest symbol was a match. */
|
||||
static inline void lzma_state_match(enum lzma_state *state)
|
||||
{
|
||||
*state = *state < LIT_STATES ? STATE_LIT_MATCH : STATE_NONLIT_MATCH;
|
||||
}
|
||||
|
||||
/* Indicate that the latest state was a long repeated match. */
|
||||
static inline void lzma_state_long_rep(enum lzma_state *state)
|
||||
{
|
||||
*state = *state < LIT_STATES ? STATE_LIT_LONGREP : STATE_NONLIT_REP;
|
||||
}
|
||||
|
||||
/* Indicate that the latest symbol was a short match. */
|
||||
static inline void lzma_state_short_rep(enum lzma_state *state)
|
||||
{
|
||||
*state = *state < LIT_STATES ? STATE_LIT_SHORTREP : STATE_NONLIT_REP;
|
||||
}
|
||||
|
||||
/* Test if the previous symbol was a literal. */
|
||||
static inline bool lzma_state_is_literal(enum lzma_state state)
|
||||
{
|
||||
return state < LIT_STATES;
|
||||
}
|
||||
|
||||
/* Each literal coder is divided in three sections:
|
||||
* - 0x001-0x0FF: Without match byte
|
||||
* - 0x101-0x1FF: With match byte; match bit is 0
|
||||
* - 0x201-0x2FF: With match byte; match bit is 1
|
||||
*
|
||||
* Match byte is used when the previous LZMA symbol was something else than
|
||||
* a literal (that is, it was some kind of match).
|
||||
*/
|
||||
#define LITERAL_CODER_SIZE 0x300
|
||||
|
||||
/* Maximum number of literal coders */
|
||||
#define LITERAL_CODERS_MAX (1 << 4)
|
||||
|
||||
/* Minimum length of a match is two bytes. */
|
||||
#define MATCH_LEN_MIN 2
|
||||
|
||||
/* Match length is encoded with 4, 5, or 10 bits.
|
||||
*
|
||||
* Length Bits
|
||||
* 2-9 4 = Choice=0 + 3 bits
|
||||
* 10-17 5 = Choice=1 + Choice2=0 + 3 bits
|
||||
* 18-273 10 = Choice=1 + Choice2=1 + 8 bits
|
||||
*/
|
||||
#define LEN_LOW_BITS 3
|
||||
#define LEN_LOW_SYMBOLS (1 << LEN_LOW_BITS)
|
||||
#define LEN_MID_BITS 3
|
||||
#define LEN_MID_SYMBOLS (1 << LEN_MID_BITS)
|
||||
#define LEN_HIGH_BITS 8
|
||||
#define LEN_HIGH_SYMBOLS (1 << LEN_HIGH_BITS)
|
||||
#define LEN_SYMBOLS (LEN_LOW_SYMBOLS + LEN_MID_SYMBOLS + LEN_HIGH_SYMBOLS)
|
||||
|
||||
/*
|
||||
* Maximum length of a match is 273 which is a result of the encoding
|
||||
* described above.
|
||||
*/
|
||||
#define MATCH_LEN_MAX (MATCH_LEN_MIN + LEN_SYMBOLS - 1)
|
||||
|
||||
/*
|
||||
* Different sets of probabilities are used for match distances that have
|
||||
* very short match length: Lengths of 2, 3, and 4 bytes have a separate
|
||||
* set of probabilities for each length. The matches with longer length
|
||||
* use a shared set of probabilities.
|
||||
*/
|
||||
#define DIST_STATES 4
|
||||
|
||||
/*
|
||||
* Get the index of the appropriate probability array for decoding
|
||||
* the distance slot.
|
||||
*/
|
||||
static inline uint32_t lzma_get_dist_state(uint32_t len)
|
||||
{
|
||||
return len < DIST_STATES + MATCH_LEN_MIN
|
||||
? len - MATCH_LEN_MIN : DIST_STATES - 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* The highest two bits of a 32-bit match distance are encoded using six bits.
|
||||
* This six-bit value is called a distance slot. This way encoding a 32-bit
|
||||
* value takes 6-36 bits, larger values taking more bits.
|
||||
*/
|
||||
#define DIST_SLOT_BITS 6
|
||||
#define DIST_SLOTS (1 << DIST_SLOT_BITS)
|
||||
|
||||
/* Match distances up to 127 are fully encoded using probabilities. Since
|
||||
* the highest two bits (distance slot) are always encoded using six bits,
|
||||
* the distances 0-3 don't need any additional bits to encode, since the
|
||||
* distance slot itself is the same as the actual distance. DIST_MODEL_START
|
||||
* indicates the first distance slot where at least one additional bit is
|
||||
* needed.
|
||||
*/
|
||||
#define DIST_MODEL_START 4
|
||||
|
||||
/*
|
||||
* Match distances greater than 127 are encoded in three pieces:
|
||||
* - distance slot: the highest two bits
|
||||
* - direct bits: 2-26 bits below the highest two bits
|
||||
* - alignment bits: four lowest bits
|
||||
*
|
||||
* Direct bits don't use any probabilities.
|
||||
*
|
||||
* The distance slot value of 14 is for distances 128-191.
|
||||
*/
|
||||
#define DIST_MODEL_END 14
|
||||
|
||||
/* Distance slots that indicate a distance <= 127. */
|
||||
#define FULL_DISTANCES_BITS (DIST_MODEL_END / 2)
|
||||
#define FULL_DISTANCES (1 << FULL_DISTANCES_BITS)
|
||||
|
||||
/*
|
||||
* For match distances greater than 127, only the highest two bits and the
|
||||
* lowest four bits (alignment) is encoded using probabilities.
|
||||
*/
|
||||
#define ALIGN_BITS 4
|
||||
#define ALIGN_SIZE (1 << ALIGN_BITS)
|
||||
#define ALIGN_MASK (ALIGN_SIZE - 1)
|
||||
|
||||
/* Total number of all probability variables */
|
||||
#define PROBS_TOTAL (1846 + LITERAL_CODERS_MAX * LITERAL_CODER_SIZE)
|
||||
|
||||
/*
|
||||
* LZMA remembers the four most recent match distances. Reusing these
|
||||
* distances tends to take less space than re-encoding the actual
|
||||
* distance value.
|
||||
*/
|
||||
#define REPS 4
|
||||
|
||||
#endif
|
96
grub-core/lib/xzembed/xz_private.h
Normal file
96
grub-core/lib/xzembed/xz_private.h
Normal file
|
@ -0,0 +1,96 @@
|
|||
/* xz_private.h - Private includes and definitions */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2010 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/>.
|
||||
*/
|
||||
/*
|
||||
* This file is based on code from XZ embedded project
|
||||
* http://tukaani.org/xz/embedded.html
|
||||
*/
|
||||
|
||||
#ifndef XZ_PRIVATE_H
|
||||
#define XZ_PRIVATE_H
|
||||
|
||||
/*
|
||||
* For userspace builds, use a separate header to define the required
|
||||
* macros and functions. This makes it easier to adapt the code into
|
||||
* different environments and avoids clutter in the Linux kernel tree.
|
||||
*/
|
||||
#include "xz_config.h"
|
||||
|
||||
/*
|
||||
* If any of the BCJ filter decoders are wanted, define XZ_DEC_BCJ.
|
||||
* XZ_DEC_BCJ is used to enable generic support for BCJ decoders.
|
||||
*/
|
||||
#ifndef XZ_DEC_BCJ
|
||||
# if defined(XZ_DEC_X86) || defined(XZ_DEC_POWERPC) \
|
||||
|| defined(XZ_DEC_IA64) || defined(XZ_DEC_ARM) \
|
||||
|| defined(XZ_DEC_ARM) || defined(XZ_DEC_ARMTHUMB) \
|
||||
|| defined(XZ_DEC_SPARC)
|
||||
# define XZ_DEC_BCJ
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Allocate memory for LZMA2 decoder. xz_dec_lzma2_reset() must be used
|
||||
* before calling xz_dec_lzma2_run().
|
||||
*/
|
||||
struct xz_dec_lzma2 * xz_dec_lzma2_create(
|
||||
uint32_t dict_max);
|
||||
|
||||
/*
|
||||
* Decode the LZMA2 properties (one byte) and reset the decoder. Return
|
||||
* XZ_OK on success, XZ_MEMLIMIT_ERROR if the preallocated dictionary is not
|
||||
* big enough, and XZ_OPTIONS_ERROR if props indicates something that this
|
||||
* decoder doesn't support.
|
||||
*/
|
||||
enum xz_ret xz_dec_lzma2_reset(
|
||||
struct xz_dec_lzma2 *s, uint8_t props);
|
||||
|
||||
/* Decode raw LZMA2 stream from b->in to b->out. */
|
||||
enum xz_ret xz_dec_lzma2_run(
|
||||
struct xz_dec_lzma2 *s, struct xz_buf *b);
|
||||
|
||||
/* Free the memory allocated for the LZMA2 decoder. */
|
||||
void xz_dec_lzma2_end(struct xz_dec_lzma2 *s);
|
||||
|
||||
/*
|
||||
* Allocate memory for BCJ decoders. xz_dec_bcj_reset() must be used before
|
||||
* calling xz_dec_bcj_run().
|
||||
*/
|
||||
struct xz_dec_bcj * xz_dec_bcj_create(bool single_call);
|
||||
|
||||
/*
|
||||
* Decode the Filter ID of a BCJ filter. This implementation doesn't
|
||||
* support custom start offsets, so no decoding of Filter Properties
|
||||
* is needed. Returns XZ_OK if the given Filter ID is supported.
|
||||
* Otherwise XZ_OPTIONS_ERROR is returned.
|
||||
*/
|
||||
enum xz_ret xz_dec_bcj_reset(
|
||||
struct xz_dec_bcj *s, uint8_t id);
|
||||
|
||||
/*
|
||||
* Decode raw BCJ + LZMA2 stream. This must be used only if there actually is
|
||||
* a BCJ filter in the chain. If the chain has only LZMA2, xz_dec_lzma2_run()
|
||||
* must be called directly.
|
||||
*/
|
||||
enum xz_ret xz_dec_bcj_run(struct xz_dec_bcj *s,
|
||||
struct xz_dec_lzma2 *lzma2, struct xz_buf *b);
|
||||
|
||||
/* Free the memory allocated for the BCJ filters. */
|
||||
#define xz_dec_bcj_end(s) kfree(s)
|
||||
|
||||
#endif
|
53
grub-core/lib/xzembed/xz_stream.h
Normal file
53
grub-core/lib/xzembed/xz_stream.h
Normal file
|
@ -0,0 +1,53 @@
|
|||
/* xz_stream.h - Definitions for handling the .xz file format */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2010 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/>.
|
||||
*/
|
||||
/*
|
||||
* This file is based on code from XZ embedded project
|
||||
* http://tukaani.org/xz/embedded.html
|
||||
*/
|
||||
|
||||
#ifndef XZ_STREAM_H
|
||||
#define XZ_STREAM_H
|
||||
|
||||
/*
|
||||
* See the .xz file format specification at
|
||||
* http://tukaani.org/xz/xz-file-format.txt
|
||||
* to understand the container format.
|
||||
*/
|
||||
|
||||
#define STREAM_HEADER_SIZE 12
|
||||
|
||||
#define HEADER_MAGIC "\3757zXZ\0"
|
||||
#define HEADER_MAGIC_SIZE 6
|
||||
|
||||
#define FOOTER_MAGIC "YZ"
|
||||
#define FOOTER_MAGIC_SIZE 2
|
||||
|
||||
/*
|
||||
* Variable-length integer can hold a 63-bit unsigned integer, or a special
|
||||
* value to indicate that the value is unknown.
|
||||
*/
|
||||
typedef uint64_t vli_type;
|
||||
|
||||
#define VLI_MAX ((vli_type)-1 / 2)
|
||||
#define VLI_UNKNOWN ((vli_type)-1)
|
||||
|
||||
/* Maximum encoded size of a VLI */
|
||||
#define VLI_BYTES_MAX (sizeof(vli_type) * 8 / 7)
|
||||
|
||||
#endif
|
|
@ -28,7 +28,6 @@
|
|||
#include <grub/elfload.h>
|
||||
#include <grub/env.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/gzio.h>
|
||||
#include <grub/aout.h>
|
||||
#include <grub/command.h>
|
||||
#include <grub/extcmd.h>
|
||||
|
@ -746,6 +745,7 @@ grub_freebsd_boot (void)
|
|||
grub_memcpy (&stack[9], &bi, sizeof (bi));
|
||||
state.eip = entry;
|
||||
state.esp = stack_target;
|
||||
state.ebp = stack_target;
|
||||
stack[0] = entry; /* "Return" address. */
|
||||
stack[1] = bootflags | FREEBSD_RB_BOOTINFO;
|
||||
stack[2] = bootdev;
|
||||
|
@ -830,7 +830,8 @@ grub_openbsd_boot (void)
|
|||
#endif
|
||||
|
||||
state.eip = entry;
|
||||
state.esp = ((grub_uint8_t *) stack - (grub_uint8_t *) buf0) + buf_target;
|
||||
state.ebp = state.esp
|
||||
= ((grub_uint8_t *) stack - (grub_uint8_t *) buf0) + buf_target;
|
||||
stack[0] = entry;
|
||||
stack[1] = bootflags;
|
||||
stack[2] = openbsd_root;
|
||||
|
@ -1045,6 +1046,7 @@ grub_netbsd_boot (void)
|
|||
|
||||
state.eip = entry;
|
||||
state.esp = stack_target;
|
||||
state.ebp = stack_target;
|
||||
stack[0] = entry;
|
||||
stack[1] = bootflags;
|
||||
stack[2] = 0;
|
||||
|
@ -1323,7 +1325,7 @@ grub_bsd_load (int argc, char *argv[])
|
|||
goto fail;
|
||||
}
|
||||
|
||||
file = grub_gzfile_open (argv[0], 1);
|
||||
file = grub_file_open (argv[0]);
|
||||
if (!file)
|
||||
goto fail;
|
||||
|
||||
|
@ -1369,10 +1371,10 @@ grub_bsd_parse_flags (const struct grub_arg_list *state,
|
|||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_freebsd (grub_extcmd_t cmd, int argc, char *argv[])
|
||||
grub_cmd_freebsd (grub_extcmd_context_t ctxt, int argc, char *argv[])
|
||||
{
|
||||
kernel_type = KERNEL_TYPE_FREEBSD;
|
||||
bootflags = grub_bsd_parse_flags (cmd->state, freebsd_flags);
|
||||
bootflags = grub_bsd_parse_flags (ctxt->state, freebsd_flags);
|
||||
|
||||
if (grub_bsd_load (argc, argv) == GRUB_ERR_NONE)
|
||||
{
|
||||
|
@ -1393,7 +1395,7 @@ grub_cmd_freebsd (grub_extcmd_t cmd, int argc, char *argv[])
|
|||
if (err)
|
||||
return err;
|
||||
|
||||
file = grub_gzfile_open (argv[0], 1);
|
||||
file = grub_file_open (argv[0]);
|
||||
if (! file)
|
||||
return grub_errno;
|
||||
|
||||
|
@ -1426,16 +1428,16 @@ grub_cmd_freebsd (grub_extcmd_t cmd, int argc, char *argv[])
|
|||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_openbsd (grub_extcmd_t cmd, int argc, char *argv[])
|
||||
grub_cmd_openbsd (grub_extcmd_context_t ctxt, int argc, char *argv[])
|
||||
{
|
||||
grub_uint32_t bootdev;
|
||||
|
||||
kernel_type = KERNEL_TYPE_OPENBSD;
|
||||
bootflags = grub_bsd_parse_flags (cmd->state, openbsd_flags);
|
||||
bootflags = grub_bsd_parse_flags (ctxt->state, openbsd_flags);
|
||||
|
||||
if (cmd->state[OPENBSD_ROOT_ARG].set)
|
||||
if (ctxt->state[OPENBSD_ROOT_ARG].set)
|
||||
{
|
||||
const char *arg = cmd->state[OPENBSD_ROOT_ARG].arg;
|
||||
const char *arg = ctxt->state[OPENBSD_ROOT_ARG].arg;
|
||||
int unit, part;
|
||||
if (*(arg++) != 'w' || *(arg++) != 'd')
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
|
@ -1456,7 +1458,7 @@ grub_cmd_openbsd (grub_extcmd_t cmd, int argc, char *argv[])
|
|||
else
|
||||
bootdev = 0;
|
||||
|
||||
if (cmd->state[OPENBSD_SERIAL_ARG].set)
|
||||
if (ctxt->state[OPENBSD_SERIAL_ARG].set)
|
||||
{
|
||||
struct grub_openbsd_bootarg_console serial;
|
||||
char *ptr;
|
||||
|
@ -1465,9 +1467,9 @@ grub_cmd_openbsd (grub_extcmd_t cmd, int argc, char *argv[])
|
|||
|
||||
grub_memset (&serial, 0, sizeof (serial));
|
||||
|
||||
if (cmd->state[OPENBSD_SERIAL_ARG].arg)
|
||||
if (ctxt->state[OPENBSD_SERIAL_ARG].arg)
|
||||
{
|
||||
ptr = cmd->state[OPENBSD_SERIAL_ARG].arg;
|
||||
ptr = ctxt->state[OPENBSD_SERIAL_ARG].arg;
|
||||
if (grub_memcmp (ptr, "com", sizeof ("com") - 1) != 0)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
"only com0-com3 are supported");
|
||||
|
@ -1511,11 +1513,11 @@ grub_cmd_openbsd (grub_extcmd_t cmd, int argc, char *argv[])
|
|||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_netbsd (grub_extcmd_t cmd, int argc, char *argv[])
|
||||
grub_cmd_netbsd (grub_extcmd_context_t ctxt, int argc, char *argv[])
|
||||
{
|
||||
grub_err_t err;
|
||||
kernel_type = KERNEL_TYPE_NETBSD;
|
||||
bootflags = grub_bsd_parse_flags (cmd->state, netbsd_flags);
|
||||
bootflags = grub_bsd_parse_flags (ctxt->state, netbsd_flags);
|
||||
|
||||
if (grub_bsd_load (argc, argv) == GRUB_ERR_NONE)
|
||||
{
|
||||
|
@ -1523,7 +1525,7 @@ grub_cmd_netbsd (grub_extcmd_t cmd, int argc, char *argv[])
|
|||
{
|
||||
grub_file_t file;
|
||||
|
||||
file = grub_gzfile_open (argv[0], 1);
|
||||
file = grub_file_open (argv[0]);
|
||||
if (! file)
|
||||
return grub_errno;
|
||||
|
||||
|
@ -1548,15 +1550,15 @@ grub_cmd_netbsd (grub_extcmd_t cmd, int argc, char *argv[])
|
|||
grub_bsd_add_meta (NETBSD_BTINFO_BOOTPATH, bootpath, sizeof (bootpath));
|
||||
}
|
||||
|
||||
if (cmd->state[NETBSD_ROOT_ARG].set)
|
||||
if (ctxt->state[NETBSD_ROOT_ARG].set)
|
||||
{
|
||||
char root[GRUB_NETBSD_MAX_ROOTDEVICE_LEN];
|
||||
grub_memset (root, 0, sizeof (root));
|
||||
grub_strncpy (root, cmd->state[NETBSD_ROOT_ARG].arg,
|
||||
grub_strncpy (root, ctxt->state[NETBSD_ROOT_ARG].arg,
|
||||
sizeof (root) - 1);
|
||||
grub_bsd_add_meta (NETBSD_BTINFO_ROOTDEVICE, root, sizeof (root));
|
||||
}
|
||||
if (cmd->state[NETBSD_SERIAL_ARG].set)
|
||||
if (ctxt->state[NETBSD_SERIAL_ARG].set)
|
||||
{
|
||||
struct grub_netbsd_btinfo_serial serial;
|
||||
char *ptr;
|
||||
|
@ -1564,9 +1566,9 @@ grub_cmd_netbsd (grub_extcmd_t cmd, int argc, char *argv[])
|
|||
grub_memset (&serial, 0, sizeof (serial));
|
||||
grub_strcpy (serial.devname, "com");
|
||||
|
||||
if (cmd->state[NETBSD_SERIAL_ARG].arg)
|
||||
if (ctxt->state[NETBSD_SERIAL_ARG].arg)
|
||||
{
|
||||
ptr = cmd->state[NETBSD_SERIAL_ARG].arg;
|
||||
ptr = ctxt->state[NETBSD_SERIAL_ARG].arg;
|
||||
if (grub_memcmp (ptr, "com", sizeof ("com") - 1) == 0)
|
||||
{
|
||||
ptr += sizeof ("com") - 1;
|
||||
|
@ -1627,7 +1629,7 @@ grub_cmd_freebsd_loadenv (grub_command_t cmd __attribute__ ((unused)),
|
|||
goto fail;
|
||||
}
|
||||
|
||||
file = grub_gzfile_open (argv[0], 1);
|
||||
file = grub_file_open (argv[0]);
|
||||
if ((!file) || (!file->size))
|
||||
goto fail;
|
||||
|
||||
|
@ -1728,7 +1730,7 @@ grub_cmd_freebsd_module (grub_command_t cmd __attribute__ ((unused)),
|
|||
return 0;
|
||||
}
|
||||
|
||||
file = grub_gzfile_open (argv[0], 1);
|
||||
file = grub_file_open (argv[0]);
|
||||
if ((!file) || (!file->size))
|
||||
goto fail;
|
||||
|
||||
|
@ -1779,7 +1781,7 @@ grub_netbsd_module_load (char *filename, grub_uint32_t type)
|
|||
void *src;
|
||||
grub_err_t err;
|
||||
|
||||
file = grub_gzfile_open (filename, 1);
|
||||
file = grub_file_open (filename);
|
||||
if ((!file) || (!file->size))
|
||||
goto fail;
|
||||
|
||||
|
@ -1865,7 +1867,7 @@ grub_cmd_freebsd_module_elf (grub_command_t cmd __attribute__ ((unused)),
|
|||
return 0;
|
||||
}
|
||||
|
||||
file = grub_gzfile_open (argv[0], 1);
|
||||
file = grub_file_open (argv[0]);
|
||||
if (!file)
|
||||
return grub_errno;
|
||||
if (!file->size)
|
||||
|
@ -1901,7 +1903,7 @@ grub_cmd_openbsd_ramdisk (grub_command_t cmd __attribute__ ((unused)),
|
|||
if (!openbsd_ramdisk.max_size)
|
||||
return grub_error (GRUB_ERR_BAD_OS, "your kOpenBSD doesn't support ramdisk");
|
||||
|
||||
file = grub_gzfile_open (args[0], 1);
|
||||
file = grub_file_open (args[0]);
|
||||
if (! file)
|
||||
return grub_error (GRUB_ERR_FILE_NOT_FOUND,
|
||||
"couldn't load ramdisk");
|
||||
|
@ -1937,6 +1939,9 @@ static grub_command_t cmd_netbsd_module_elf, cmd_openbsd_ramdisk;
|
|||
|
||||
GRUB_MOD_INIT (bsd)
|
||||
{
|
||||
/* Net and OpenBSD kernels are often compressed. */
|
||||
grub_dl_load ("gzio");
|
||||
|
||||
cmd_freebsd = grub_register_extcmd ("kfreebsd", grub_cmd_freebsd,
|
||||
GRUB_COMMAND_FLAG_BOTH,
|
||||
N_("FILE"), N_("Load kernel of FreeBSD."),
|
||||
|
|
|
@ -716,7 +716,7 @@ grub_linux_boot (void)
|
|||
|
||||
/* FIXME. */
|
||||
/* asm volatile ("lidt %0" : : "m" (idt_desc)); */
|
||||
state.ebx = 0;
|
||||
state.ebp = state.edi = state.ebx = 0;
|
||||
state.esi = real_mode_target;
|
||||
state.esp = real_mode_target;
|
||||
state.eip = params->code32_start;
|
||||
|
@ -1069,6 +1069,7 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
|
|||
goto fail;
|
||||
}
|
||||
|
||||
grub_file_filter_disable_compression ();
|
||||
file = grub_file_open (argv[0]);
|
||||
if (! file)
|
||||
goto fail;
|
||||
|
|
|
@ -69,6 +69,7 @@ grub_chainloader_cmd (const char *filename, grub_chainloader_flags_t flags)
|
|||
|
||||
grub_dl_ref (my_mod);
|
||||
|
||||
grub_file_filter_disable_compression ();
|
||||
file = grub_file_open (filename);
|
||||
if (! file)
|
||||
goto fail;
|
||||
|
|
|
@ -401,6 +401,7 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
|
|||
|
||||
addr_min = GRUB_LINUX_BZIMAGE_ADDR + grub_linux16_prot_size;
|
||||
|
||||
grub_file_filter_disable_compression ();
|
||||
file = grub_file_open (argv[0]);
|
||||
if (!file)
|
||||
goto fail;
|
||||
|
|
|
@ -31,7 +31,6 @@
|
|||
#include <grub/charset.h>
|
||||
#include <grub/term.h>
|
||||
#include <grub/command.h>
|
||||
#include <grub/gzio.h>
|
||||
#include <grub/i18n.h>
|
||||
#include <grub/bitmap_scale.h>
|
||||
|
||||
|
@ -535,7 +534,7 @@ grub_cmd_devprop_load (grub_command_t cmd __attribute__ ((unused)),
|
|||
if (argc != 1)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required");
|
||||
|
||||
file = grub_gzfile_open (args[0], 1);
|
||||
file = grub_file_open (args[0]);
|
||||
if (! file)
|
||||
return grub_error (GRUB_ERR_FILE_NOT_FOUND,
|
||||
"couldn't load device-propertie dump");
|
||||
|
@ -836,6 +835,7 @@ grub_xnu_boot_resume (void)
|
|||
struct grub_relocator32_state state;
|
||||
|
||||
state.esp = grub_xnu_stack;
|
||||
state.ebp = grub_xnu_stack;
|
||||
state.eip = grub_xnu_entry_point;
|
||||
state.eax = grub_xnu_arg1;
|
||||
|
||||
|
@ -1114,6 +1114,7 @@ grub_xnu_boot (void)
|
|||
state.eip = grub_xnu_entry_point;
|
||||
state.eax = grub_xnu_arg1;
|
||||
state.esp = grub_xnu_stack;
|
||||
state.ebp = grub_xnu_stack;
|
||||
return grub_relocator32_boot (grub_xnu_relocator, state);
|
||||
}
|
||||
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
#include <grub/cpu/macho.h>
|
||||
#include <grub/machoload.h>
|
||||
#include <grub/file.h>
|
||||
#include <grub/gzio.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/mm.h>
|
||||
|
||||
|
@ -149,7 +148,7 @@ grub_macho_open (const char *name)
|
|||
grub_file_t file;
|
||||
grub_macho_t macho;
|
||||
|
||||
file = grub_gzfile_open (name, 1);
|
||||
file = grub_file_open (name);
|
||||
if (! file)
|
||||
return 0;
|
||||
|
||||
|
|
|
@ -344,6 +344,7 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
|
|||
if (initrd_loaded)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "only one initrd can be loaded.");
|
||||
|
||||
grub_file_filter_disable_compression ();
|
||||
file = grub_file_open (argv[0]);
|
||||
if (! file)
|
||||
return grub_errno;
|
||||
|
|
|
@ -39,7 +39,6 @@
|
|||
#include <grub/dl.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/gzio.h>
|
||||
#include <grub/env.h>
|
||||
#include <grub/cpu/relocator.h>
|
||||
#include <grub/video.h>
|
||||
|
@ -225,7 +224,7 @@ grub_cmd_multiboot (grub_command_t cmd __attribute__ ((unused)),
|
|||
if (argc == 0)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "no kernel specified");
|
||||
|
||||
file = grub_gzfile_open (argv[0], 1);
|
||||
file = grub_file_open (argv[0]);
|
||||
if (! file)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "couldn't open file");
|
||||
|
||||
|
@ -291,9 +290,9 @@ grub_cmd_module (grub_command_t cmd __attribute__ ((unused)),
|
|||
"you need to load the multiboot kernel first");
|
||||
|
||||
if (nounzip)
|
||||
file = grub_file_open (argv[0]);
|
||||
else
|
||||
file = grub_gzfile_open (argv[0], 1);
|
||||
grub_file_filter_disable_compression ();
|
||||
|
||||
file = grub_file_open (argv[0]);
|
||||
if (! file)
|
||||
return grub_errno;
|
||||
|
||||
|
|
|
@ -301,6 +301,7 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
|
|||
goto fail;
|
||||
}
|
||||
|
||||
grub_file_filter_disable_compression ();
|
||||
file = grub_file_open (argv[0]);
|
||||
if (! file)
|
||||
goto fail;
|
||||
|
|
|
@ -305,7 +305,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
|
|||
goto out;
|
||||
}
|
||||
|
||||
file = grub_gzfile_open (argv[0], 1);
|
||||
file = grub_file_open (argv[0]);
|
||||
if (!file)
|
||||
goto out;
|
||||
|
||||
|
@ -393,6 +393,7 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
|
|||
goto fail;
|
||||
}
|
||||
|
||||
grub_file_filter_disable_compression ();
|
||||
file = grub_file_open (argv[0]);
|
||||
if (! file)
|
||||
goto fail;
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue