* Makefile.util.def (libgrubmods.a): Add grub-core/fs/exfat.c.
* grub-core/Makefile.core.def (exfat): New module.
* grub-core/fs/exfat.c: New file.
* grub-core/fs/fat.c (GRUB_FAT_DIR_ENTRY_SIZE): Removed.
(GRUB_FAT_ATTR_*): Make into an enum.
(GRUB_FAT_ATTR_LONG_NAME) [MODE_EXFAT]: Removed.
(GRUB_FAT_ATTR_VALID) [MODE_EXFAT]: Remove GRUB_FAT_ATTR_VOLUME_ID.
(GRUB_FAT_ATTR_VOLUME_ID) [MODE_EXFAT]: Removed.
(GRUB_FAT_MAXFILE): Removed.
(grub_exfat_bpb) [MODE_EXFAT]: New struct.
(grub_current_fat_bpb_t): New type.
(grub_fat_dir_entry) [MODE_EXFAT]: New struct.
(grub_fat_dir_node) [MODE_EXFAT]: New struct.
(grub_fat_dir_node_t): New type.
(grub_fat_data) [MODE_EXFAT]: Remove root_sector and num_root_sectors.
(fat_log2) [MODE_EXFAT]: Removed.
(grub_fat_mount): Use grub_current_fat_bpb_t. Add some sanity checks.
(grub_fat_mount) [MODE_EXFAT]: Handle ExFAT.
(grub_fat_iterate_dir) [MODE_EXFAT]: New function.
(grub_fat_find_dir) [MODE_EXFAT]: Handle ExFAT.
(grub_fat_label) [MODE_EXFAT]: New function.
(grub_fat_fs) [MODE_EXFAT]: Set name to "exfat" and
reserved_first_sector to 0.
docs/stamp-vti
docs/version.texi
*.elf
+example_grub_script_test
+example_scripted_test
+example_unit_test
*.exec
genkernsyms.sh
gensymlist.sh
gentrigtables
grub-bin2h
-grub-dumpbios
+grub_cmd_echo
+grub_cmd_regexp
grub-editenv
grub-emu
grub_emu_init.c
grub_probe_init.c
grub_probe_init.h
grub-reboot
+grub_script_blanklines
+grub_script_blockarg
+grub_script_break
grub-script-check
grub_script_check_init.c
grub_script_check_init.h
+grub_script_comments
+grub_script_continue
+grub_script_dollar
+grub_script_echo1
+grub_script_echo_keywords
+grub_script_expansion
+grub_script_final_semicolon
+grub_script_for1
+grub_script_functions
+grub_script_if
+grub_script_not
+grub_script_return
+grub_script_setparams
+grub_script_shift
+grub_script_vars1
+grub_script_while1
grub_script.tab.c
grub_script.tab.h
grub_script.yy.c
*.mod
mod-*.c
missing
+partmap_test
*.pf2
*.pp
po/*.mo
grub-core/contrib
grub-core/genmod.sh
grub-core/gensyminfo.sh
+grub-core/modinfo.sh
grub-core/*.module
grub-core/*.pp
util/bash-completion.d/grub
widthspec.h
docs/stamp-1
docs/version-dev.texi
+Makefile.utilgcry.def
+2011-10-19 Vladimir Serbinenko <phcoder@gmail.com>
+
+ ExFAT support.
+
+ * Makefile.util.def (libgrubmods.a): Add grub-core/fs/exfat.c.
+ * grub-core/Makefile.core.def (exfat): New module.
+ * grub-core/fs/exfat.c: New file.
+ * grub-core/fs/fat.c (GRUB_FAT_DIR_ENTRY_SIZE): Removed.
+ (GRUB_FAT_ATTR_*): Make into an enum.
+ (GRUB_FAT_ATTR_LONG_NAME) [MODE_EXFAT]: Removed.
+ (GRUB_FAT_ATTR_VALID) [MODE_EXFAT]: Remove GRUB_FAT_ATTR_VOLUME_ID.
+ (GRUB_FAT_ATTR_VOLUME_ID) [MODE_EXFAT]: Removed.
+ (GRUB_FAT_MAXFILE): Removed.
+ (grub_exfat_bpb) [MODE_EXFAT]: New struct.
+ (grub_current_fat_bpb_t): New type.
+ (grub_fat_dir_entry) [MODE_EXFAT]: New struct.
+ (grub_fat_dir_node) [MODE_EXFAT]: New struct.
+ (grub_fat_dir_node_t): New type.
+ (grub_fat_data) [MODE_EXFAT]: Remove root_sector and num_root_sectors.
+ (fat_log2) [MODE_EXFAT]: Removed.
+ (grub_fat_mount): Use grub_current_fat_bpb_t. Add some sanity checks.
+ (grub_fat_mount) [MODE_EXFAT]: Handle ExFAT.
+ (grub_fat_iterate_dir) [MODE_EXFAT]: New function.
+ (grub_fat_find_dir) [MODE_EXFAT]: Handle ExFAT.
+ (grub_fat_label) [MODE_EXFAT]: New function.
+ (grub_fat_fs) [MODE_EXFAT]: Set name to "exfat" and
+ reserved_first_sector to 0.
+
+2011-10-19 Vladimir Serbinenko <phcoder@gmail.com>
+
+ Move grub_reboot out of the kernel.
+
+ * grub-core/Makefile.core.def (reboot): Add platform-specific files.
+ * grub-core/kern/efi/efi.c (grub_reboot): Moved to ...
+ * grub-core/lib/efi/reboot.c: ... here.
+ * grub-core/kern/i386/efi/startup.S: Remove including of realmode.S.
+ * grub-core/kern/i386/ieee1275/startup.S: Likewise.
+ * grub-core/kern/i386/pc/startup.S (grub_exit): Inline cold_reboot.
+ * grub-core/kern/i386/realmode.S (grub_reboot): Moved to...
+ * grub-core/lib/i386/reboot_trampoline.S: ... here.
+ * grub-core/kern/ieee1275/openfw.c (grub_reboot): Moved to...
+ * grub-core/lib/ieee1275/reboot.c: ... here.
+ * grub-core/kern/mips/arc/init.c (grub_reboot): Moved to...
+ * grub-core/lib/mips/arc/reboot.c: ... here.
+ * grub-core/kern/mips/loongson/init.c (grub_reboot): Moved to...
+ * grub-core/lib/mips/loongson/reboot.c: ...here.
+ * grub-core/kern/mips/qemu_mips/init.c (grub_reboot): Moved to...
+ * grub-core/lib/mips/qemu_mips/reboot.c: ... here.
+ * include/grub/emu/misc.h (grub_reboot): New function declaration.
+ * include/grub/i386/reboot.h: New file.
+ * include/grub/mips/loongson/ec.h: Fix includes.
+ * include/grub/mips/qemu_mips/kernel.h (grub_reboot): Removed.
+ * include/grub/misc.h (grub_reboot): Don't mark as kernel function.
+ * grub-core/lib/i386/reboot.c: New file.
+
+2011-10-18 Vladimir Serbinenko <phcoder@gmail.com>
+
+ Make grub_prefix into module to fix the arbitrary limit and save
+ some space.
+
+ * grub-core/kern/emu/main.c (grub_prefix): Removed.
+ * grub-core/kern/i386/coreboot/startup.S (grub_prefix): Likewise.
+ * grub-core/kern/i386/efi/startup.S (grub_prefix): Likewise.
+ * grub-core/kern/i386/ieee1275/startup.S (grub_prefix): Likewise.
+ * grub-core/kern/i386/pc/startup.S (grub_prefix): Likewise.
+ * grub-core/kern/i386/qemu/startup.S (grub_prefix): Likewise.
+ * grub-core/kern/ia64/efi/startup.S (grub_prefix): Likewise.
+ * grub-core/kern/mips/startup.S (grub_prefix): Likewise.
+ * grub-core/kern/powerpc/ieee1275/startup.S (grub_prefix): Likewise.
+ * grub-core/kern/sparc64/ieee1275/crt0.S (grub_prefix): Likewise.
+ * grub-core/kern/x86_64/efi/startup.S (grub_prefix): Likewise.
+ * include/grub/ia64/efi/kernel.h: Removed.
+ * include/grub/kernel.h: New module type OBJ_TYPE_PREFIX.
+ (grub_prefix): Removed.
+ * include/grub/offsets.h (GRUB_KERNEL_I386_PC_PREFIX): Removed.
+ (GRUB_KERNEL_I386_PC_PREFIX_END): Likewise.
+ (GRUB_KERNEL_I386_QEMU_PREFIX): Likewise.
+ (GRUB_KERNEL_I386_QEMU_PREFIX_END): Likewise.
+ (GRUB_KERNEL_SPARC64_IEEE1275_PREFIX): Likewise.
+ (GRUB_KERNEL_SPARC64_IEEE1275_PREFIX_END): Likewise.
+ (GRUB_KERNEL_POWERPC_IEEE1275_PREFIX): Likewise.
+ (GRUB_KERNEL_POWERPC_IEEE1275_PREFIX_END): Likewise.
+ (GRUB_KERNEL_MIPS_LOONGSON_PREFIX): Likewise.
+ (GRUB_KERNEL_MIPS_LOONGSON_PREFIX_END): Likewise.
+ (GRUB_KERNEL_MIPS_QEMU_MIPS_PREFIX): Likewise.
+ (GRUB_KERNEL_MIPS_QEMU_MIPS_PREFIX_END): Likewise.
+ (GRUB_KERNEL_MIPS_ARC_PREFIX): Likewise.
+ (GRUB_KERNEL_MIPS_ARC_PREFIX_END): Likewise.
+ (GRUB_KERNEL_I386_EFI_PREFIX): Likewise.
+ (GRUB_KERNEL_I386_EFI_PREFIX_END): Likewise.
+ (GRUB_KERNEL_IA64_EFI_PREFIX): Likewise.
+ (GRUB_KERNEL_IA64_EFI_PREFIX_END): Likewise.
+ (GRUB_KERNEL_X86_64_EFI_PREFIX): Likewise.
+ (GRUB_KERNEL_X86_64_EFI_PREFIX_END): Likewise.
+ (GRUB_KERNEL_I386_COREBOOT_PREFIX): Likewise.
+ (GRUB_KERNEL_I386_COREBOOT_PREFIX_END): Likewise.
+ (GRUB_KERNEL_I386_MULTIBOOT_PREFIX): Likewise.
+ (GRUB_KERNEL_I386_MULTIBOOT_PREFIX_END): Likewise.
+ (GRUB_KERNEL_I386_IEEE1275_PREFIX): Likewise.
+ (GRUB_KERNEL_I386_IEEE1275_PREFIX_END): Likewise.
+ (GRUB_KERNEL_MACHINE_PREFIX): Likewise.
+ (GRUB_KERNEL_MACHINE_PREFIX_END): Likewise.
+ * grub-core/kern/main.c (grub_set_prefix_and_root): Retrieve grub_prefix
+ from module.
+ * util/grub-mkimage.c (image_target_desc): Removed prefix and
+ prefix_end.
+ (image_targets): Likewise.
+ (generate_image): Put prefix as a module.
+
+2011-10-16 Vladimir Serbinenko <phcoder@gmail.com>
+
+ Replace grub_module_iterate with FOR_MODULES.
+
+ * grub-core/disk/memdisk.c (GRUB_MOD_INIT): Switched to new interface.
+ * grub-core/kern/efi/efi.c (grub_arch_modules_addr): Renamed to...
+ (grub_efi_modules_addr): ...this.
+ * grub-core/kern/efi/init.c (grub_modbase): New variable.
+ (grub_efi_init): Set grub_modbase.
+ * grub-core/kern/emu/main.c (grub_arch_modules_addr): Removed.
+ (grub_modbase): New variable.
+ * grub-core/kern/i386/coreboot/init.c (grub_arch_modules_addr): Removed.
+ (grub_modbase): New variable.
+ (grub_machine_init): Set grub_modbase.
+ * grub-core/kern/i386/pc/init.c (grub_arch_modules_addr): Removed.
+ (grub_modbase): New variable.
+ (grub_machine_init): Set grub_modbase.
+ * grub-core/kern/ieee1275/init.c (grub_arch_modules_addr): Removed.
+ (grub_modbase): New variable.
+ (grub_machine_init): Set grub_modbase.
+ * grub-core/kern/main.c (grub_module_iterate): Remove.
+ (grub_modules_get_end): Use grub_modbase.
+ (grub_load_modules): Use FOR_MODULES.
+ (grub_load_config): Likewise.
+ * grub-core/kern/mips/arc/init.c (grub_arch_modules_addr): Removed.
+ (grub_modbase): New variable.
+ (grub_machine_init): Set grub_modbase.
+ * grub-core/kern/mips/loongson/init.c (grub_arch_modules_addr): Removed.
+ (grub_modbase): New variable.
+ (grub_machine_init): Set grub_modbase.
+ * grub-core/kern/mips/qemu_mips/init.c (grub_arch_modules_addr):
+ Removed.
+ (grub_modbase): New variable.
+ (grub_machine_init): Set grub_modbase.
+ * include/grub/efi/efi.h (grub_efi_modules_addr): New declaration.
+ * include/grub/kernel.h (grub_arch_modules_addr): Removed.
+ (grub_module_iterate): Likewise.
+ (grub_modbase): New variable declaration.
+ (FOR_MODULES): New macro.
+
+2011-10-16 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * configure.ac: Check for __ctzdi2 and __ctzsi2.
+ * include/grub/libgcc.h: Include __ctzdi2 and __ctzsi2 if present.
+
+2011-10-16 Vladimir Serbinenko <phcoder@gmail.com>
+
+ Fix few obvious type discrepancies.
+
+ * grub-core/fs/affs.c (grub_affs_read_file): Use grub_off_t for offset.
+ * grub-core/fs/afs.c (grub_afs_read_file): Likewise.
+ * grub-core/fs/fshelp.c (grub_fshelp_find_file): Remove leftover
+ variable.
+ * grub-core/fs/hfs.c (grub_hfs_read_file): Use grub_off_t for offset
+ and connected types.
+ * grub-core/fs/nilfs2.c (grub_nilfs2_read_file): Use grub_off_t for
+ offset.
+ (grub_nilfs2_iterate_dir): Use grub_off_t for fpos.
+ * grub-core/fs/sfs.c (grub_sfs_read_file): Use grub_off_t for offset.
+ * grub-core/fs/ufs.c (grub_ufs_read_file): Use grub_off_t for offset
+ and connected types.
+
+2011-10-16 Vladimir Serbinenko <phcoder@gmail.com>
+
+ Fix python 3.x incompatibilities.
+
+ * gentpl.py: Put brackets around print strings.
+ * util/import_gcry.py: Open explicitly as utf-8.
+ Use in instead of has_key.
+
+2011-10-16 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * grub-core/fs/xfs.c (grub_xfs_inode): New field fork_offset.
+ (GRUB_XFS_INO_AGBITS): Make into inline function.
+ (GRUB_XFS_INO_INOINAG): Likewise.
+ (GRUB_XFS_INO_AG): Likewise.
+ (GRUB_XFS_FSB_TO_BLOCK): Likewise.
+ (GRUB_XFS_EXTENT_OFFSET): Likewise.
+ (GRUB_XFS_EXTENT_BLOCK): Likewise.
+ (GRUB_XFS_EXTENT_SIZE): Likewise.
+ (GRUB_XFS_ROUND_TO_DIRENT): Likewise.
+ (GRUB_XFS_NEXT_DIRENT): Likewise.
+ (grub_xfs_read_block): Rewrite the btree parsing. Fixes invalid BMAP.
+ (grub_xfs_read_file): Fix offset type.
+
+2011-10-15 Robert Millan <rmh@gnu.org>
+
+ * util/getroot.c (grub_util_get_grub_dev): Fix OS selection #ifdefs.
+
+2011-10-15 Robert Millan <rmh@gnu.org>
+
+ Fix build problem on FreeBSD and GNU/kFreeBSD.
+
+ * util/getroot.c [__FreeBSD_kernel__]: Include `<sys/mount.h>'.
+
+2011-10-14 Vladimir Serbinenko <phcoder@gmail.com>
+
+ Fix overflow with >2GiB file on HFS+. >4GiB wasn't tested.
+
+ * grub-core/fs/hfsplus.c (grub_hfsplus_btree): Use more appropriate
+ types.
+ (grub_hfsplus_btree_recoffset): Likewise.
+ (grub_hfsplus_btree_recptr): Likewise.
+ (grub_hfsplus_find_block): Likewise.
+ (grub_hfsplus_btree_search): Likewise.
+ (grub_hfsplus_read_block): Likewise.
+ (grub_hfsplus_read_file): Likewise.
+ (grub_hfsplus_mount): Likewise.
+ (grub_hfsplus_btree_iterate_node): Likewise.
+ (grub_hfsplus_btree_search): Likewise.
+ (grub_hfsplus_iterate_dir): Likewise.
+ (grub_hfsplus_read): A small code simplification.
+
+2011-10-14 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * grub-core/kern/emu/hostdisk.c
+ (convert_system_partition_to_system_disk): Don't assume that children
+ of mapper nodes are mapper nodes.
+
+2011-10-14 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * grub-core/lib/posix_wrap/ctype.h (isxdigit): Use grub_isxdigit.
+ * include/grub/misc.h (grub_isxdigit): New function.
+ * grub-core/video/colors.c (my_isxdigit): Removed. All users
+ switched to grub_isxdigit.
+ * grub-core/term/serial.c (grub_serial_find): Fix in case of port
+ number starting with a letter.
+
+2011-10-09 Robert Millan <rmh@gnu.org>
+
+ LVM support for FreeBSD and GNU/kFreeBSD.
+
+ * util/lvm.c (grub_util_lvm_isvolume): Enable on FreeBSD and
+ GNU/kFreeBSD.
+ (LVM_DEV_MAPPER_STRING): Move from here ...
+ * include/grub/util/lvm.h (LVM_DEV_MAPPER_STRING): ... to here.
+ * util/getroot.c: Include `<grub/util/lvm.h>'.
+ (grub_util_get_dev_abstraction): Enable
+ grub_util_biosdisk_is_present() on FreeBSD and GNU/kFreeBSD.
+ Check for LVM abstraction on FreeBSD and GNU/kFreeBSD.
+ (grub_util_get_grub_dev): Replace "/dev/mapper/" with
+ `LVM_DEV_MAPPER_STRING'. Enable LVM and mdRAID only on platforms that
+ support it.
+ * util/grub-setup.c (main): Check for LVM also on FreeBSD and
+ GNU/kFreeBSD.
+ * util/grub.d/10_kfreebsd.in: Load `geom_linux_lvm' kernel module
+ when LVM abstraction is required for ${GRUB_DEVICE}.
+
+2011-10-06 Szymon Janc <szymon@janc.net.pl>
+
+ Add support for LZO compression in GRUB:
+ - import of minilzo library,
+ - LZO decompression for btrfs,
+ - lzop files decompression.
+
+ * grub-core/io/lzopio.c: New file.
+ * grub-core/lib/adler32.c: Likewise.
+ * grub-core/lib/minilzo/lzoconf.h: Likewise.
+ * grub-core/lib/minilzo/lzodefs.h: Likewise.
+ * grub-core/lib/minilzo/minilzo.c: Likewise.
+ * grub-core/lib/minilzo/minilzo.h: Likewise.
+ * Makefile.util.def (libgrubmods.a): Add grub-core/io/lzopio.c,
+ grub-core/lib/adler32.c, grub-core/io/lzopio.c,
+ grub-core/lib/minilzo/minilzo.c to common.
+ * Makefile.util.def (libgrubmods.a): Add flags required by minilzo to
+ cflags in cppflags.
+ * grub-core/Makefile.core.def (btrfs): Likewise.
+ * grub-core/Makefile.core.def (lzopio): New module.
+ (adler32): Likewise.
+ * grub-core/fs/btrfs.c: Include minilzo.h.
+ (GRUB_BTRFS_COMPRESSION_LZO): New define.
+ (GRUB_BTRFS_LZO_BLOCK_SIZE): Likewise.
+ (GRUB_BTRFS_LZO_BLOCK_MAX_CSIZE): Likewise.
+ (grub_btrfs_lzo_decompress): New function.
+ (grub_btrfs_extent_read): Add support for LZO compression type.
+ * include/grub/types.h (GRUB_UCHAR_MAX): New define.
+ (GRUB_USHRT_MAX): Likewise.
+ (GRUB_UINT_MAX): Likewise.
+ * grub-core/lib/posix_wrap/limits.h (USHRT_MAX): Likewise.
+ (UINT_MAX): Likewise.
+ (CHAR_BIT): Likewise.
+ * grub-core/lib/posix_wrap/sys/types.h (ULONG_MAX): Moved to
+ grub-core/lib/posix_wrap/limits.h
+ (UCHAR_MAX): Likewise.
+ * include/grub/file.h (grub_file_filter_id): New compression filter
+ GRUB_FILE_FILTER_LZOPIO.
+ * include/grub/file.h (grub_file_filter_id): Set
+ GRUB_FILE_FILTER_LZOPIO as GRUB_FILE_FILTER_COMPRESSION_LAST.
+ * include/grub/types.h (grub_get_unaligned16): New function.
+ (grub_get_unaligned32): Likewise.
+ (grub_get_unaligned64): Likewise.
+ * util/import_gcry.py (cryptolist): Add adler32.
+
+2011-10-05 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * grub-core/Makefile.core.def: Eliminate rarely used emu_condition. This
+ in perspective decreases the complexity of build system and fixes
+ compilation right now.
+
+2011-10-01 Ales Nesrsta <starous@volny.cz>
+
+ * grub-core/bus/usb/uhci.c: Changes made by Rock Cui - thanks!
+ (fixed problem related to using UHCI with coreboot).
+
+2011-08-25 BVK Chaitanya <bvk.groups@gmail.com>
+
+ * gentpl.py: Use Autogen macros so that the output template file
+ (Makefile.tpl) size is reduced.
+
+2011-09-29 Mads Kiilerich <mads@kiilerich.com>
+
+ * grub-core/Makefile.core.def (kernel): Add kern/i386/int.S to
+ extra_dist.
+
+2011-09-29 Mario Limonciello <mario_limonciello@dell.com>
+
+ * util/misc.c (grub_util_get_disk_size) [__MINGW32__]: Strip trailing
+ slashes on PHYSICALDRIVE%d paths when making Windows CreateFile calls.
+
+2011-09-29 Mario Limonciello <mario_limonciello@dell.com>
+
+ * grub-core/kern/emu/misc.c (canonicalize_file_name) [__MINGW32__]: Use
+ _fullpath.
+
+2011-09-29 Mario Limonciello <mario_limonciello@dell.com>
+
+ Remove extra declaration of sleep for mingw32.
+
+ * util/misc.c (sleep) [__MINGW32__]: Removed.
+ * include/grub/util/misc.h (sleep) [__MINGW32__]: Likewise.
+
+2011-09-28 Grégoire Sutre <gregoire.sutre@gmail.com>
+
+ * include/grub/bsdlabel.h (grub_partition_bsd_disk_label): Add fields
+ type and packname.
+ * include/grub/i386/netbsd_bootinfo.h (NETBSD_BTINFO_BOOTDISK):
+ Resurrected.
+ (NETBSD_BTINFO_BOOTWEDGE): New definition.
+ (grub_netbsd_btinfo_bootwedge): New struct.
+ * grub-core/loader/i386/bsd.c (grub_netbsd_add_boot_disk_and_wedge):
+ New function.
+ (grub_cmd_netbsd): Call grub_netbsd_add_boot_disk_and_wedge.
+
+2011-09-28 Thomas Haller <thomas.haller@fen-net.de>
+
+ * grub-core/loader/multiboot_elfxx.c (Elf_Shdr): Set according to
+ loader.
+
+2011-09-28 Andreas Born <futur.andy@googlemail.com>
+
+ Fix incorrect identifiers in bash-completion.
+
+ * util/bash-completion.d/grub-completion.bash.in
+ (_grub_mkpasswd-pbkdf2): Rename to ...
+ (_grub_mkpasswd_pbkdf2): ... this. All users updated.
+ (_grub_script-check): Rename to ...
+ (_grub_script_check): ... this. All users updated.
+
+2011-09-28 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * grub-core/kern/emu/hostdisk.c (grub_util_biosdisk_is_floppy):
+ Return 0 if disk isn't biosdisk.
+
+2011-09-17 Grégoire Sutre <gregoire.sutre@gmail.com>
+
+ * Makefile.util.def (grub-mkrelpath): Add LIBUTIL for getrawpartition(3)
+ on NetBSD.
+ * Makefile.util.def (grub-fstest): Likewise.
+
+2011-09-17 Grégoire Sutre <gregoire.sutre@gmail.com>
+
+ * grub-core/kern/emu/hostdisk.c (grub_util_get_fd_sectors) [__NetBSD__]:
+ Get sector size from disk label.
+
+2011-09-05 Colin Watson <cjwatson@ubuntu.com>
+
+ * util/grub-mkconfig_lib.in (grub_file_is_not_garbage): Return 1 for
+ */README* as well as README*.
+ Reported by: Axel Beckert.
+
+2011-08-23 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * grub-core/kern/mips/loongson/init.c (grub_machine_init): Handle the
+ case of less than 256 MiB of RAM.
+
+2011-08-23 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * grub-core/commands/wildcard.c (make_regex): Handle @.
+
+2011-08-23 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * util/grub-install.in: Move cryptodisk logic to appropriate place.
+
+2011-08-21 Szymon Janc <szymon@janc.net.pl>
+
+ * acinclude.m4: Use AC_LANG_PROGRAM macro to generate source code for
+ AC_LANG_CONFTEST macros.
+
+2011-08-20 Szymon Janc <szymon@janc.net.pl>
+
+ Add grub-fstest option to uncompress data for commands.
+
+ * util/grub-fstest.c (uncompress): New var.
+ (options): New option -u.
+
+2011-08-20 Szymon Janc <szymon@janc.net.pl>
+
+ * grub-core/loader/i386/linux.c (grub_linux_setup_video): Add
+ GRUB_VIDEO_DRIVER_RADEON_FULOONG2E to switch case statement.
+
+2011-08-20 Szymon Janc <szymon@janc.net.pl>
+
+ * grub-core/io/gzio.c (grub_gzio_open): Always return original io if
+ file type was not recognized correctly (not gzip or corrupted).
+
+2011-08-19 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * grub-core/kern/mips/loongson/init.c (grub_reboot): Reboot Fuloong.
+ * include/grub/cs5536.h (GRUB_CS5536_MSR_DIVIL_RESET): New definition.
+
+2011-08-19 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * grub-core/Makefile.core.def (kernel): Add video/radeon_fuloong2e.c on
+ loongson.
+ * grub-core/kern/mips/loongson/init.c (grub_machine_init): Init
+ video_radeon_fuloong2e.
+ * grub-core/video/radeon_fuloong2e.c: New file.
+ * include/grub/video.h (grub_video_id_t): Add new ID
+ GRUB_VIDEO_DRIVER_RADEON_FULOONG2E.
+
+2011-08-19 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * include/grub/mips/loongson.h (GRUB_CPU_LOONGSON_COP0_PRID): New
+ define.
+ * grub-core/kern/mips/loongson/init.c (grub_machine_init): Check
+ that PRID matches the detected subplatform and reset the subplatform
+ if it doesn't.
+
+2011-08-19 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * grub-core/kern/misc.c (grub_vprintf): Fix a bug on malloc failure.
+
+2011-08-19 Vladimir Serbinenko <phcoder@gmail.com>
+
+ Fix PCI iterating on functions >= 4.
+
+ * grub-core/bus/pci.c (grub_pci_iterate): Remove useless ghost skipping.
+ * include/grub/mips/loongson/pci.h (GRUB_LOONGSON_OHCI_GHOST_FUNCTION):
+ Removed.
+ (GRUB_LOONGSON_EHCI_GHOST_FUNCTION): Likewise.
+ (grub_pci_read): Fix bitmask.
+ (grub_pci_read_word): Likewise.
+ (grub_pci_read_byte): Likewise.
+ (grub_pci_write): Likewise.
+ (grub_pci_write_word): Likewise.
+ (grub_pci_write_byte): Likewise.
+
+2011-08-19 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * configure.ac: Don't impose march=loongson2f on loongson platform. (It
+ can still be specified in TARGET_CFLAGS)
+
+2011-08-19 Vladimir Serbinenko <phcoder@gmail.com>
+
+ Rename Fuloong into Fuloong 2F. Add new ID for Fuloong2E.
+
+ * grub-core/Makefile.core.def (fwstart_fuloong): Rename fwstart_fuloong
+ into fwstart_fuloong2f. Use boot/mips/loongson/fuloong2f.S.
+ * grub-core/boot/mips/loongson/fuloong.S: Rename to ...
+ * grub-core/boot/mips/loongson/fuloong2f.S: ... this.
+ (FULOONG): Rename to ...
+ (FULOONG2F): ... this. All users updated.
+ * grub-core/boot/mips/startup_raw.S (machtype_fuloong_str): Rename to
+ (machtype_fuloong2f_str): ... this.
+ (machtype_fuloong2e_str): New string.
+ Check for machtype_fuloong2e_str.
+ * grub-core/loader/mips/linux.c (loongson_machtypes)
+ [GRUB_MACHINE_MIPS_LOONGSON]: Add GRUB_ARCH_MACHINE_FULOONG2E.
+ * grub-core/term/serial.c (loongson_defserial)
+ [GRUB_MACHINE_MIPS_LOONGSON]: New array.
+ (grub_serial_register) [GRUB_MACHINE_MIPS_LOONGSON]: Use
+ loongson_defserial.
+ * include/grub/mips/loongson/kernel.h (GRUB_ARCH_MACHINE_FULOONG):
+ Rename to ...
+ (GRUB_ARCH_MACHINE_FULOONG2F): ... this.
+ (GRUB_ARCH_MACHINE_FULOONG2E): New const.
+ * util/grub-mkimage.c (image_target_desc): Rename IMAGE_FULOONG_FLASH
+ to IMAGE_FULOONG2F_FLASH. All users updated.
+ (image_targets): Rename images.
+ * util/grub-mkstandalone.in: Accept fuloong2f and fuloong2e.
+
+2011-08-19 Szymon Janc <szymon@janc.net.pl>
+
+ Make enable of disk cache statistics code configurable.
+
+ * configure.ac: --enable-cache-stats added.
+ * config.h.in (DISK_CACHE_STATS): New define.
+ * grub-core/Makefile.core.def (cacheinfo): New command.
+ * include/grub/disk.h(grub_disk_cache_get_performance): New function.
+ * grub-core/commands/cacheinfo.c: New file.
+ * grub-core/commands/minicmd.c (grub_rescue_cmd_info): Updated and
+ moved to cacheinfo.c.
+ * grub-core/kern/disk.c: Use DISK_CACHE_STATS to disable disk cache
+ debug code.
+ * include/grub/disk.h: Likewise.
+
+2011-08-19 Szymon Janc <szymon@janc.net.pl>
+
+ * Makefile.am (AUTOMAKE_OPTIONS): = Added -Wno-portability flag.
+ * grub-core/Makefile.am: Likewise.
+
+2011-08-16 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * grub-core/kern/emu/hostdisk.c (grub_util_biosdisk_iterate): Skip with
+ non-zero pull.
+
+2011-08-16 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * grub-core/fs/jfs.c (grub_jfs_read_file): New parameter ino.
+ All users updated.
+ (grub_jfs_lookup_symlink): Use correct starting inode.
+
+2011-08-16 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * util/grub-setup.c (main): Add missing gcry initialisation.
+
+2011-08-16 Vladimir Serbinenko <phcoder@gmail.com>
+
+ Don't accept text modes on EFI when booting Linux.
+
+ * grub-core/loader/i386/linux.c (ACCEPTS_PURE_TEXT): New define.
+ (grub_linux_boot) [!ACCEPTS_PURE_TEXT]: Restrict to graphics modes.
+
+2011-08-15 Mario Limonciello <mario_limonciello@dell.com>
+2011-08-15 Colin Watson <cjwatson@ubuntu.com>
+
+ * util/grub-probe.c (probe): Canonicalise the path argument, fixing
+ use of "/path/.." as in grub-install for EFI as well as handling
+ symlinks correctly.
+ Fixes Debian bug #637768.
+
+2011-08-15 Colin Watson <cjwatson@ubuntu.com>
+
+ * util/grub-probe.c: Remove duplicate #include.
+
+2011-08-10 Robert Millan <rmh@gnu.org>
+
+ Detect LSI MegaRAID SAS (`mfi') devices on GNU/kFreeBSD.
+
+ * util/deviceiter.c [__FreeBSD_kernel__] (get_mfi_disk_name): New
+ function.
+ [__FreeBSD_kernel__] (grub_util_iterate_devices): Scan for mfi
+ (/dev/mfid[0-9]+) devices using get_mfi_disk_name().
+
+2011-08-03 Robert Millan <rmh@gnu.org>
+
+ * include/grub/zfs/zap_leaf.h (typedef union zap_leaf_chunk): Mark
+ la_array as packed.
+ Reported by: Zachary Bedell
+
+2011-07-26 Colin Watson <cjwatson@ubuntu.com>
+
+ * configure.ac: The Loongson port requires grub-mkfont due to its
+ use of -DUSE_ASCII_FAILBACK. Raise an error if it is not going to
+ be built.
+
+2011-07-26 Colin Watson <cjwatson@ubuntu.com>
+
+ * util/grub-install.in: Don't source grub-mkconfig_lib until after
+ processing arguments (otherwise help2man fails when GRUB has not yet
+ been installed).
+
+2011-07-25 Vladimir Serbinenko <phcoder@gmail.com>
+
+ New script grub-mkstandalone.
+
+ * Makefile.util.def (grub-mkstandalone): New script.
+ * docs/man/grub-mkstandalone.h2m: New file.
+ * util/grub-mkstandalone.in: Likewise.
+
+2011-07-25 Vladimir Serbinenko <phcoder@gmail.com>
+
+ Support ATA disks with 4K sectors.
+
+ * include/grub/ata.h (grub_ata): New member log_sector_size.
+ * grub-core/disk/ata.c (grub_ata_dumpinfo): Show sector size.
+ (grub_ata_identify): Read sector size.
+ (grub_ata_readwrite): Use log_sector_size rather than hardcoded value.
+
+2011-07-25 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * util/grub-install.in: Don't use uhci outside of x86.
+
+2011-07-25 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * util/grub-mkrescue.in: Add missing quotes.
+
+2011-07-25 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * grub-core/normal/menu.c (grub_menu_execute_entry): Fix NULL
+ dereference.
+
+2011-07-23 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * grub-core/disk/pata.c (grub_pata_readwrite): Add missing wait.
+
+2011-07-23 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * include/grub/video.h: add missing EXPORT_FUND on
+ grub_video_edid_checksum and grub_video_edid_preferred_mode.
+
+2011-07-23 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * include/grub/mips/kernel.h: Fix define conflict.
+
+2011-07-23 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * grub-core/kern/mips/cache_flush.S [GRUB_MACHINE_MIPS_LOONGSON]: Flush
+ all four ways.
+
+2011-07-21 Colin Watson <cjwatson@ubuntu.com>
+
+ Preferred resolution detection for VBE.
+
+ * grub-core/video/video.c (grub_video_edid_checksum): New function.
+ (grub_video_edid_preferred_mode): Likewise. Try EDID followed by
+ the Flat Panel extension, in line with the X.org VESA driver.
+ * grub-core/video/i386/pc/vbe.c (grub_vbe_bios_get_flat_panel_info):
+ New function.
+ (grub_vbe_bios_get_ddc_capabilities): Likewise.
+ (grub_vbe_bios_read_edid): Likewise.
+ (grub_vbe_get_preferred_mode): Likewise.
+ (grub_video_vbe_setup): When the mode is "auto", try to get the
+ preferred mode from VBE, and use the largest mode that is no larger
+ than the preferred mode (some BIOSes expose a preferred mode that is
+ not in their mode list!). If this fails, fall back to 640x480 as a
+ safe conservative choice.
+ (grub_video_vbe_get_edid): New function.
+ (grub_video_vbe_adapter): Add get_edid.
+ * include/grub/video.h (struct grub_vbe_edid_info): New structure.
+ (struct grub_video_adapter): Add get_edid.
+ (grub_video_edid_checksum): Add prototype.
+ (grub_video_edid_preferred_mode): Likewise.
+ * include/grub/i386/pc/vbe.h (struct grub_vbe_flat_panel_info): New
+ structure.
+
+ * grub-core/commands/videoinfo.c (print_edid): New function.
+ (grub_cmd_videoinfo): Print EDID if available.
+
+ * util/grub.d/00_header.in (GRUB_GFXMODE): Default to "auto". This
+ is more appropriate on a wider range of platforms than 640x480.
+ * docs/grub.texi (Simple configuration): Update GRUB_GFXMODE
+ documentation.
+
+2011-07-10 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * util/grub-install.in: Recognize ESP mounted at /boot/EFI.
+
+2011-07-10 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * po/POTFILES.in: Regenerate.
+
+2011-07-10 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * grub-core/disk/efi/efidisk.c (grub_efidisk_get_device_name): Fix
+ incorrect memory usage.
+
+2011-07-10 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * util/grub-install.in: Source grub-mkconfig_lib.
+
+2011-07-08 Vladimir Serbinenko <phcoder@gmail.com>
+
+ Remove getroot.c from core on emu platform.
+
+ * grub-core/Makefile.core.def (kernel): Remove kern/emu/getroot.c and
+ kern/emu/raid.c.
+ * grub-core/kern/emu/main.c (main): Don't try to guess root device. It's
+ useless.
+ * grub-core/kern/emu/misc.c (get_win32_path): Moved from here...
+ * util/getroot.c (get_win32_path): ... here.
+ * grub-core/kern/emu/misc.c (fini_libzfs): Moved from here...
+ * util/getroot.c (fini_libzfs): ... here.
+ * grub-core/kern/emu/misc.c (grub_get_libzfs_handle): Moved from here...
+ * util/getroot.c (grub_get_libzfs_handle): ... here.
+ * grub-core/kern/emu/misc.c (grub_find_zpool_from_dir):
+ Moved from here...
+ * util/getroot.c (grub_find_zpool_from_dir): ... here.
+ * grub-core/kern/emu/misc.c
+ (grub_make_system_path_relative_to_its_root): Moved from here...
+ * util/getroot.c (grub_make_system_path_relative_to_its_root): ... here.
+ * grub-core/kern/emu/getroot.c: Moved from here ...
+ * util/getroot.c: ... here. All users updated.
+ * grub-core/kern/emu/raid.c: Moved from here ...
+ * util/raid.c: ... here. All users updated.
+
+2011-07-08 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * po/POTFILES.in: Regenerate.
+
+2011-07-07 Vladimir Serbinenko <phcoder@gmail.com>
+
+ Fix compilation on GNU/Linux.
+
+ * grub-core/kern/emu/getroot.c (grub_util_pull_device) [!FreeBSD]:
+ Disable geli.
+ (grub_util_get_grub_dev) [!FreeBSD]: Likewise.
+ (grub_util_pull_device) [HAVE_DEVICE_MAPPER]: Fix const and func name.
+ * grub-core/disk/cryptodisk.c (grub_cryptodisk_open): Fix proto.
+
+2011-07-07 Vladimir Serbinenko <phcoder@gmail.com>
+2011-07-07 Michael Gorven <michael@gorven.za.net>
+2011-07-07 Clemens Fruhwirth <clemens@endorphin.org>
+
+ LUKS and GELI support.
+
+ * Makefile.util.def (libgrubkern.a): Add grub-core/lib/crypto.c,
+ grub-core/disk/luks.c, grub-core/disk/geli.c,
+ grub-core/disk/cryptodisk.c, grub-core/disk/AFSplitter.c,
+ grub-core/lib/pbkdf2.c, grub-core/commands/extcmd.c,
+ grub-core/lib/arg.c.
+ (libgrubmods.a): Remove gcrypts cflags and cppflags.
+ Remove grub-core/commands/extcmd.c, grub-core/lib/arg.c,
+ grub-core/lib/crypto.c, grub-core/lib/libgcrypt-grub/cipher/sha512.c,
+ grub-core/lib/libgcrypt-grub/cipher/crc.c and grub-core/lib/pbkdf2.c.
+ (grub-bin2h): Add libgcry.a.
+ (grub-mkimage): Likewise.
+ (grub-mkrelpath): Likewise.
+ (grub-script-check): Likewise.
+ (grub-editenv): Likewise.
+ (grub-mkpasswd-pbkdf2): Likewise.
+ (grub-pe2elf): Likewise.
+ (grub-fstest): Likewise.
+ (grub-mkfont): Likewise.
+ (grub-mkdevicemap): Likewise.
+ (grub-probe): Likewise.
+ (grub-ofpath): Likewise.
+ (grub-mklayout): Likewise.
+ (example_unit_test): Likewise.
+ (grub-menulst2cfg): Likewise.
+ * autogen.sh (UTIL_DEFS): Add Makefile.utilgcry.def.
+ * grub-core/Makefile.core.def (cryptodisk): New module.
+ (luks): Likewise.
+ (geli): Likewise.
+ * grub-core/disk/AFSplitter.c: New file.
+ * grub-core/disk/cryptodisk.c: Likewise.
+ * grub-core/disk/geli.c: Likewise.
+ * grub-core/disk/luks.c: Likewise.
+ * grub-core/kern/emu/getroot.c (get_dm_uuid): New function based on
+ grub_util_is_lvm.
+ (grub_util_get_dm_abstraction): New function.
+ (grub_util_follow_gpart_up): Likewise.
+ (grub_util_get_geom_abstraction): Likewise.
+ (grub_util_get_dev_abstraction): Use new functions.
+ (grub_util_pull_device): Pull GELI and LUKS.
+ (grub_util_get_grub_dev): Handle LUKS and GELI.
+ * grub-core/kern/emu/hostdisk.c (grub_util_get_fd_sectors): New function.
+ (grub_util_biosdisk_open): Use grub_util_get_fd_sectors.
+ (follow_geom_up): Removed.
+ (grub_util_fd_seek): New function.
+ (open_device): Use grub_util_fd_seek.
+ (nread): Rename to ..
+ (grub_util_fd_read): ... this. All users updated.
+ * grub-core/lib/crypto.c (grub_crypto_ecb_decrypt): A better prototype.
+ (grub_crypto_cbc_decrypt): Likewise.
+ (grub_crypto_hmac_write): Likewise.
+ (grub_crypto_hmac_buffer): Likewise.
+ (grub_password_get): Extend to util.
+ * include/grub/crypto.h (gcry_cipher_spec) [GRUB_UTIL]:
+ New member modname.
+ (gcry_md_spec) [GRUB_UTIL]: Likewise.
+ * include/grub/cryptodisk.h: New file.
+ * include/grub/disk.h (grub_disk_dev_id): Rename LUKS to CRYPTODISK.
+ * include/grub/emu/getroot.h (grub_dev_abstraction_types): Add
+ LUKS and GELI.
+ (grub_util_follow_gpart_up): New proto.
+ * include/grub/emu/hostdisk.h (grub_util_fd_seek): Likewise.
+ (grub_util_fd_read): Likewise.
+ (grub_cryptodisk_cheat_mount): Likewise.
+ (grub_util_cryptodisk_print_uuid): Likewise.
+ (grub_util_get_fd_sectors): Likewise.
+ * util/grub-fstest.c (mount_crypt): New var.
+ (fstest): Mount crypto if requested.
+ (options): New option -C.
+ (argp_parser): Parse -C.
+ (main): Init and fini gcry.
+ * util/grub-install.in: Support cryptodisk install.
+ * util/grub-mkconfig.in: Export GRUB_ENABLE_CRYPTODISK.
+ * util/grub-mkconfig_lib.in (is_path_readable_by_grub): Support
+ cryptodisk.
+ (prepare_grub_to_access_device): Likewise.
+ * util/grub-mkpasswd-pbkdf2.c (main): Use grub_password_get.
+ * util/grub-probe.c (probe_partmap): Support cryptodisk UUID probe.
+ (probe_cryptodisk_uuid): New function.
+ (probe_abstraction): Likewise.
+ (probe): Use new functions.
+ * util/import_gcry.py: Create Makefile.utilgcry.def.
+ Add modname member.
+
+2011-07-07 Vladimir Serbinenko <phcoder@gmail.com>
+
+ Lazy device scanning.
+
+ * Makefile.util.def (libgrubkern.a): Add grub-core/kern/emu/raid.c.
+ (grub-setup): Remove util/raid.c.
+ * grub-core/Makefile.core.def (kernel): Add kern/emu/raid.c on emu.
+ * grub-core/disk/lvm.c (scan_depth): New variable.
+ (grub_lvm_iterate): Rescan if necessary.
+ (find_lv): New function based on grub_lvm_open.
+ (grub_lvm_open): Use find_lv. Rescan on error.
+ (is_node_readable): New function.
+ (is_lv_readable): Likewise.
+ (grub_lvm_scan_device): Skip already found disks.
+ (do_lvm_scan): New function. Move grub_lvm_scan_device inside of it.
+ Stop if searched device is found and readable.
+ * grub-core/disk/raid.c (inscnt): New variable.
+ (scan_depth): Likewise.
+ (scan_devices): New function based on grub_raid_register. Abort if
+ looked for device is found.
+ (grub_raid_iterate): Rescan if needed.
+ (find_array): NEw function based on -grub_raid_open.
+ (grub_raid_open): Use find_array and rescan.
+ (insert_array): Set became_readable_at.
+ * grub-core/kern/disk.c (grub_disk_dev_iterate): Iterate though "pull.
+ * grub-core/kern/emu/getroot.c (grub_util_open_dm) [HAVE_DEVICE_MAPPER]:
+ New function.
+ (grub_util_is_lvm) [HAVE_DEVICE_MAPPER]: Use grub_util_open_dm.
+ (grub_util_pull_device): New function.
+ (grub_util_get_grub_dev): Call grub_util_pull_device.
+ * util/raid.c: Moved to ..
+ * grub-core/kern/emu/raid.c: ... here.
+ (grub_util_raid_getmembers): New parameter "bootable".
+ All users updated. Support 1.x.
+ * include/grub/ata.h (grub_ata_dev): Change iterate prototype.
+ All users updated.
+ * include/grub/disk.h (grub_disk_pull_t): New enum.
+ (grub_disk_dev): Change iterate prototype.
+ All users updated.
+ * include/grub/emu/getroot.h (grub_util_raid_getmembers) [__linux__]:
+ New proto.
+ * include/grub/emu/hostdisk.h (grub_util_pull_device): Likewise.
+ * include/grub/lvm.h (grub_lvm_lv): New members fullname and compatname.
+ * include/grub/raid.h (grub_raid_array): New member became_readable_at.
+ * include/grub/scsi.h (grub_scsi_dev): Change iterate prototype.
+ All users updated.
+ * include/grub/util/raid.h: Removed.
+
+2011-07-06 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * po/POTFILES.in: Regenerate.
+
+2011-07-06 Vladimir Serbinenko <phcoder@gmail.com>
+
+ Unify sparc init with other ieee1275.
+
+ * grub-core/Makefile.core.def (kernel): Use kern/ieee1275/init.c
+ instead of kern/sparc64/ieee1275/init.c.
+ * grub-core/kern/ieee1275/cmain.c (grub_ieee1275_find_options)
+ [__sparc__]: Set GRUB_IEEE1275_FLAG_NO_PARTITION_0.
+ * grub-core/kern/ieee1275/init.c [__sparc__]: Include
+ grub/machine/kernel.h.
+ (grub_ieee1275_original_stack) [__sparc__]: New variable.
+ (grub_claim_heap) [__sparc__]: Use sparc version.
+ (grub_machine_init): Moved args parsing to
+ (grub_parse_cmdline): ...this.
+ * grub-core/kern/sparc64/ieee1275/init.c: Removed.
+ * include/grub/offsets.h (GRUB_KERNEL_SPARC64_IEEE1275_MOD_GAP):
+ New definition.
+ (GRUB_KERNEL_SPARC64_IEEE1275_MOD_ALIGN): Likewise.
+
+ Move BOOTP to separate file.
+
+ * grub-core/Makefile.core.def (net): Add net/bootp.c.
+ * grub-core/net/net.c: Move all BOOTP functions to
+ * grub-core/net/bootp.c: ... here.
+
+ Use frame interface on PXE.
+
+ * grub-core/Makefile.core.def (pxecmd): Removed.
+ (pxe): Use net/drivers/i386/pc/pxe.c rather than net/i386/pc/pxe.c.
+ * grub-core/commands/i386/pc/pxecmd.c: Removed.
+ * grub-core/i386/pc/pxe.c: Moved from here ...
+ * grub-core/net/i386/pc/pxe.c: ... here. Rewritten.
+ * grub-core/net/net.c (grub_net_open_real): Handle old pxe syntax.
+ * include/grub/i386/pc/pxe.h (grub_pxe_unload): Removed.
+
+ EFI network support.
+
+ * grub-core/Makefile.core.def (efinet): New module.
+ * grub-core/disk/efi/efidisk.c (compare_device_paths): Moved from
+ here...
+ * grub-core/kern/efi/efi.c (grub_efi_compare_device_paths): ... here.
+ All users updated.
+ * grub-core/kern/efi/init.c (grub_efi_net_config): New variable.
+ (grub_machine_get_bootlocation): Call grub_efi_net_config if needed.
+ * grub-core/kern/x86_64/efi/callwrap.S (efi_wrap_7): New function.
+ * grub-core/net/drivers/efi/efinet.c: New file.
+ * include/grub/efi/efi.h (grub_efi_compare_device_paths): New proto.
+ (grub_efi_net_config): New extern var.
+
+ Various cleanups and bugfixes.
+
+ * grub-core/disk/efi/efidisk.c (grub_efidisk_open): Fix off-by-one
+ error.
+ (grub_efidisk_get_device_name): Unify similar codepaths. Accept whole
+ disk declared as partition.
+ * grub-core/disk/ieee1275/ofdisk.c (grub_ofdisk_open): Fix memory
+ leak on failure.
+ * grub-core/kern/dl.c (grub_dl_load_file): Fix memory leak.
+ * grub-core/kern/mm.c (grub_debug_malloc): Don't use unsupported %zx.
+ (grub_debug_zalloc): Likewise.
+ (grub_debug_realloc): Likewise.
+ (grub_debug_memalign): Likewise.
+ * grub-core/net/arp.c (grub_net_arp_receive): IPv4 is 4-byte wide.
+ Check that target is IPv4.
+ * grub-core/net/drivers/ieee1275/ofnet.c (grub_ofnet_findcards): Use
+ local-mac-address as fallback.
+ * grub-core/net/ethernet.c (grub_net_recv_ethernet_packet): Prevent
+ memory leak.
+ * grub-core/net/ip.c (ipchksum): Rename to ...
+ (grub_net_ip_chksum): ... this. All users updated.
+ (grub_net_recv_ip_packets): Special handling for DHCP.
+ * util/grub-mkimage.c (generate_image): Zero-out aout header.
+
+ Unify prefix handling
+
+ * grub-core/kern/efi/init.c (grub_efi_set_prefix): Revamped into ...
+ (grub_machine_get_bootlocation): ... this.
+ * grub-core/kern/emu/main.c (grub_machine_set_prefix): Revamped into ...
+ (grub_machine_get_bootlocation): ... this.
+ (grub_prefix): New variable.
+ (prefix): Removed.
+ (root_dev): New variable.
+ (dir): Likewise.
+ (main): Use new variables.
+ * grub-core/kern/i386/coreboot/init.c (grub_machine_set_prefix):
+ Revamped into ...
+ (grub_machine_get_bootlocation): ... this.
+ * grub-core/kern/i386/efi/init.c (grub_machine_set_prefix): Removed.
+ * grub-core/kern/i386/pc/init.c (make_install_device): Revamped into ...
+ (grub_machine_get_bootlocation): ... this.
+ (grub_machine_set_prefix): Removed.
+ * grub-core/kern/ia64/efi/init.c (grub_machine_set_prefix): Removed.
+ * grub-core/kern/ieee1275/init.c (grub_machine_set_prefix):
+ Revamped into ...
+ (grub_machine_get_bootlocation): ... this.
+ * grub-core/kern/main.c (grub_set_root_dev): Revamped into ...
+ (grub_set_prefix_and_root): ... this. All users updated.
+ * grub-core/kern/mips/init.c (grub_machine_set_prefix):
+ Revamped into ...
+ (grub_machine_get_bootlocation): ... this.
+ * include/grub/kernel.h (grub_machine_set_prefix): Removed.
+ (grub_machine_get_bootlocation): New proto.
+ * include/grub/i386/pc/kernel.h (grub_pc_net_config): New var.
+
+ Less intrusive and more reliable seek on network implementation.
+
+ * grub-core/kern/file.c (grub_file_net_seek): Removed.
+ (grub_file_seek): Don't call grub_file_net_seek.
+ * grub-core/net/net.c (grub_net_fs_read): Renamed to ...
+ (grub_net_fs_read_real): .. this.
+ (grub_net_seek_real): Use net->offset.
+ (grub_net_fs_read): Seek if necessary.
+
+ Unify IEEE1275 netwotk config with the other platforms.
+
+ * grub-core/kern/ieee1275/init.c (grub_ieee1275_net_config):
+ New variable.
+ (grub_machine_get_bootlocation): Support network.
+ * grub-core/kern/ieee1275/openfw.c (grub_ieee1275_parse_args):
+ Support type and device parsing.
+ (grub_ieee1275_get_device_type): New function.
+ * grub-core/net/drivers/ieee1275/ofnet.c (grub_getbootp_real): Revamped
+ into ...
+ (grub_ieee1275_net_config_real): ... this.
+ (grub_ofnet_probecards): Removed.
+ * grub-core/Makefile.am (KERNEL_HEADER_FILES): Remove ofnet.h.
+ * include/grub/ieee1275/ofnet.h: Removed.
+ * include/grub/ieee1275/ieee1275.h (grub_ieee1275_net_config): NEw
+ extern var.
+ (grub_ieee1275_get_device_type): New function.
+
+ Unify network device closing across platforms and make more robust.
+
+ * grub-core/kern/ieee1275/init.c (grub_machine_fini): Don't call
+ grub_grubnet_fini.
+ * grub-core/net/ethernet.c (send_ethernet_packet): Open card if it isn't
+ already.
+ * grub-core/net/net.c (grub_net_network_level_interface_register):
+ Update num_ifaces.
+ (grub_net_card_unregister): Close all interfaces.
+ (receive_packets): Don't poll if no iterfaces are registered.
+ Open if necessary.
+ (grub_net_fini_hw): New function.
+ (grub_net_restore_hw): Likewise.
+ (fini_hnd): New variable.
+ (GRUB_MOD_INIT): Register preboot hook.
+ (GRUB_MOD_FINI): Run and unregister preboot hook.
+
+ Poll network cards when idle.
+
+ * grub-core/kern/term.c (grub_net_poll_cards_idle): New variable.
+ (grub_checkkey): Call grub_net_poll_cards_idle if it's not NULL.
+ * grub-core/net/net.c (receive_packets): Save last poll time.
+ (grub_net_poll_cards_idle_real): New function.
+ (GRUB_MOD_INIT): Register grub_net_poll_cards_idle.
+ (GRUB_MOD_FINI): Unregister grub_net_poll_cards_idle.
+ * include/grub/kernel.h (grub_poll_cards_idle): New extern variable.
+
+ Rename ofnet interfaces.
+
+ * grub-core/net/drivers/ieee1275/ofnet.c (find_alias): New function.
+ (grub_ofnet_findcards): Use ofnet_%s names.
+
+ * util/grub-mknetdir.in: Support for EFI and IEEE1275.
+
+ Cleanup socket opening.
+
+ * grub-core/net/net.c (grub_net_fs_open): Rewritten.
+ (grub_net_fs_close): Likewise.
+ (grub_net_fs_read_real): Use eof member.
+ * include/grub/net/udp.h (+grub_net_udp_open): New proto.
+ (+grub_net_udp_close): New inline function.
+
+ * include/grub/net/tftp.h: Moved to the top of ...
+ * grub-core/net/tftp.c: ... here.
+ * include/grub/net/ip.h: Moved mostly to the top of ...
+ * grub-core/net/ip.c: ... here.
+ * include/grub/net/ethernet.h: Moved mostly to the top of ...
+ * grub-core/net/ethernet.c: ... here.
+
+ * grub-core/kern/device.c (grub_device_close): Free device->net->server.
+
+ * grub-core/commands/probe.c (grub_cmd_probe): Use protocol name for
+ FS name.
+
+ * include/grub/net/ip.h (ipv4_ini): Removed.
+ (ipv4_fini): Likewise.
+
+ * include/grub/net/ip.h (grub_net_recv_ip_packets): New proto.
+ (grub_net_send_ip_packets): Likewise.
+
+2011-07-05 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * grub-core/kern/i386/qemu/mmap.c (grub_machine_mmap_init): Use new
+ grub_read_cmos prototype.
+
+2011-07-05 Vladimir Serbinenko <phcoder@gmail.com>
+
+ VGA text support in qemu-mips
+
+ * grub-core/Makefile.core.def (kernel): Add term/i386/pc/vga_text.c,
+ term/i386/vga_common.c and kern/vga_init.c on qemu-mips.
+ * grub-core/kern/mips/qemu_mips/init.c (grub_machine_init): Init vga
+ text.
+ * grub-core/kern/i386/qemu/init.c: Renamed to ...
+ * grub-core/kern/vga_init.c: ... this.
+ * grub-core/kern/vga_init.c (VGA_ADDR) [__mips__]: Adjust.
+ (grub_qemu_init_cirrus) [__mips__]: Skip PCI and adjust the I/O base.
+ * grub-core/term/i386/pc/vga_text.c (VGA_TEXT_SCREEN) [__mips__]:
+ Adjust.
+ * include/grub/vga.h [GRUB_MACHINE_MIPS_QEMU_MIPS]: Declare
+ GRUB_MACHINE_PCI_IO_BASE.
+
+2011-07-05 Vladimir Serbinenko <phcoder@gmail.com>
+
+ MIPS qemu flash support.
+
+ * grub-core/boot/mips/startup_raw.S [GRUB_MACHINE_MIPS_QEMU_MIPS]: Check
+ magic.
+ * grub-core/kern/mips/qemu_mips/init.c (probe_mem): New function.
+ (grub_machine_init): Probe memory if its size isn't known.
+ * util/grub-mkimage.c (image_targets): Add flash targets.
+ (generate_image): Handle flash targets.
+
+2011-07-05 Vladimir Serbinenko <phcoder@gmail.com>
+
+ MIPS qemu at_keyboard support.
+
+ * gentpl.py (videoinkernel): Add qemu-mips.
+ * grub-core/Makefile.am (KERNEL_HEADER_FILES): Add necessary headers.
+ * grub-core/Makefile.core.def (kernel): Add at_keyboard and layout.
+ * grub-core/kern/mips/qemu_mips/init.c (grub_machine_init): Init new
+ modules.
+ * grub-core/term/at_keyboard.c (grub_keyboard_controller_init)
+ [GRUB_MACHINE_MIPS_QEMU_MIPS]: Don't consider original set.
+ * grub-core/term/serial.c (grub_serial_register)
+ [GRUB_MACHINE_MIPS_QEMU_MIPS]: Make com0 explicitly active.
+
+2011-07-05 Vladimir Serbinenko <phcoder@gmail.com>
+
+ CMOS support on sparc.
+
+ * gentpl.py (cmos): Add powerpc and sparc.
+ * grub-core/Makefile.core.def (datetime): Add lib/ieee1275/cmos.c on
+ powerpc and sparc.
+ * grub-core/lib/cmos_datetime.c (grub_get_datetime)
+ [__powerpc__ || __sparc__]: Rename to grub_get_datetime_cmos.
+ (grub_set_datetime) [__powerpc__ || __sparc__]: Likewise to
+ grub_set_datetime_cmos.
+ * grub-core/lib/ieee1275/cmos.c: New file.
+ * grub-core/lib/ieee1275/datetime.c (no_ieee1275_rtc): New vaiable.
+ (find_rtc): Set no_ieee1275_rtc on error.
+ (grub_get_datetime): Call grub_get_datetime_cmos on error.
+ (grub_set_datetime): Call grub_set_datetime_cmos on error.
+ * include/grub/cmos.h (grub_cmos_read): Return grub_err_t since it may
+ fail. Move value to argument. All users updated
+ (grub_cmos_write): Likewise.
+ (grub_cmos_read) [__powerpc__ || __sparc__]: Rewritten.
+ (grub_cmos_write) [__powerpc__ || __sparc__]: Likewise.
+ * include/grub/datetime.h [__powerpc__ || __sparc__]: Declare
+ grub_get_datetime_cmos and grub_set_datetime_cmos.
+
+2011-07-02 Grégoire Sutre <gregoire.sutre@gmail.com>
+
+ * util/grub-mkconfig.in: Use @PACKAGE@ instead of hardcoded name when
+ sourcing grub-mkconfig_lib.
+ * util/update-grub_lib.in: Likewise.
+ * util/grub.d/00_header.in: Likewise.
+ * util/grub.d/10_hurd.in: Likewise.
+ * util/grub.d/10_kfreebsd.in: Likewise.
+ * util/grub.d/10_linux.in: Likewise.
+ * util/grub.d/10_netbsd.in: Likewise.
+ * util/grub.d/10_windows.in: Likewise.
+ * util/grub.d/20_linux_xen.in: Likewise.
+ * util/grub.d/30_os-prober.in: Likewise.
+
+2011-06-28 Colin Watson <cjwatson@ubuntu.com>
+
+ * grub-core/term/gfxterm.c (grub_virtual_screen_setup): Use
+ default_bg_color rather than black.
+ (grub_gfxterm_fullscreen): Likewise.
+ (grub_gfxterm_background_color_cmd): Save new background color in
+ default_bg_color.
+
+2011-06-27 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * grub-core/Makefile.core.def (chain): Fix coreboot filename.
+
+2011-06-27 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * grub-core/disk/pata.c (grub_pata_initialize) [QEMU_MIPS]: Fix a
+ mismerge.
+
+2011-06-27 Vladimir Serbinenko <phcoder@gmail.com>
+
+ Chainloading on coreboot support.
+
+ * grub-core/Makefile.core.def (chain): Add coreboot.
+ * grub-core/loader/i386/coreboot/chainloader.c: New file.
+
+2011-06-27 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * grub-core/loader/i386/bsd.c (grub_bsd_load): Handle relocator failure
+ if it happens.
+
+2011-06-27 Vladimir Serbinenko <phcoder@gmail.com>
+
+ Implement time command.
+
+ * grub-core/Makefile.core.def (time): New module.
+ * grub-core/commands/time.c: New file.
+ * grub-core/script/parser.y: Remove "time" keyword.
+ * grub-core/script/yylex.l: Likewise.
+
+2011-06-27 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * include/grub/loader.h (grub_loader_unregister_preboot_hook): Export.
+
+2011-06-27 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * grub-core/lib/relocator.c (malloc_in_range): Fix a memory corruption
+ when handling leftovers.
+
+2011-06-27 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * util/ieee1275/grub-ofpathname.c (main): Handle --help and --version
+ so that help2man doesn't fail.
+
+2011-06-27 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * grub-core/net/drivers/ieee1275/ofnet.c (send_card_buffer) Use right
+ type in pointers on sparc64.
+ (get_card_packet): Likewise.
+
+2011-06-27 Colin Watson <cjwatson@ubuntu.com>
+
+ * grub-core/commands/videoinfo.c (hook): Indicate current video mode
+ with `*'.
+ (grub_cmd_videoinfo): Fetch current video mode.
+
+2011-06-27 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * grub-core/disk/scsi.c (grub_scsi_read): Limit SCSI reads to 32K
+ because of underlying system restrictions.
+
+2011-06-27 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * util/grub-mkrescue.in: Rename "ata" to "pata" and add ahci when
+ necessary.
+
+2011-06-27 Vladimir Serbinenko <phcoder@gmail.com>
+
+ Coreboot video support.
+
+ * grub-core/Makefile.core.def (vga): Extend to coreboot and multiboot.
+ (vbe): Likewise.
+ * grub-core/kern/i386/coreboot/startup.S: Include int.S.
+ * grub-core/kern/i386/pc/startup.S (grub_bios_interrupt): Moved from
+ here ...
+ * grub-core/kern/i386/int.S: ... here.
+ * grub-core/video/i386/pc/vbe.c: Updated includes.
+ * grub-core/video/i386/pc/vga.c: Likewise.
+ * include/grub/i386/coreboot/memory.h
+ (GRUB_MEMORY_MACHINE_SCRATCH_ADDR): New definition.
+ (GRUB_MEMORY_MACHINE_SCRATCH_SEG): Likewise.
+ (GRUB_MEMORY_MACHINE_SCRATCH_SIZE): Likewise.
+ * include/grub/i386/pc/int.h (GRUB_CPU_INT_FLAGS_DEFAULT) [!PCBIOS]:
+ Disable interrupts.
+ * include/grub/i386/pc/vga.h: Removed. All users updated.
+
+2011-06-27 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * grub-core/disk/ahci.c (grub_ahci_readwrite_real): Use proper
+ definitions for dprintf.
+ * grub-core/disk/pata.c (grub_pata_readwrite): Likewise.
+
+2011-06-27 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * grub-core/net/drivers/ieee1275/ofnet.c (send_card_buffer): Fix
+ prototype.
+ (get_card_packet): Likewise.
+
+2011-06-26 Yves Blusseau <blusseau@zetam.org>
+
+ Display the path of the file when file is not found
+
+ * grub-core/fs/fat.c: Display the filename when file is not found.
+ * grub-core/fs/fshelp.c: Likewise.
+ * grub-core/fs/hfs.c: Likewise.
+ * grub-core/fs/jfs.c: Likewise.
+ * grub-core/fs/minix.c: Likewise.
+ * grub-core/fs/ufs.c: Likewise.
+ * grub-core/fs/btrfs.c: Likewise.
+ * grub-core/commands/i386/pc/play.c: Likewise.
+
+2011-06-26 Szymon Janc <szymon@janc.net.pl>
+
+ * grub-core/commands/cmp.c (grub_cmd_cmp): Remove unnecessary NULL
+ pointer checks before calling grub_free().
+ * grub-core/commands/wildcard.c (match_devices): Likewise.
+ * grub-core/commands/wildcard.c (match_files): Likewise.
+ * grub-core/fs/cpio.c (grub_cpio_dir): Likewise.
+ * grub-core/fs/cpio.c (grub_cpio_open): Likewise.
+ * grub-core/fs/udf.c (grub_udf_read_block): Likewise.
+ * grub-core/fs/xfs.c (grub_xfs_read_block): Likewise.
+ * grub-core/loader/efi/chainloader.c (grub_cmd_chainloader): Likewise.
+ * grub-core/normal/cmdline.c (grub_cmdline_get): Likewise.
+ * grub-core/script/yylex.l (grub_lexer_unput): Likewise.
+ * grub-core/video/readers/jpeg.c (grub_video_reader_jpeg): Likewise.
+ * grub-core/video/readers/png.c (grub_png_output_byte): Likewise.
+
+2011-06-25 Patrick <p55@mailinator.com>
+
+ * grub-core/kern/main.c (grub_load_normal_mode): Correct the comment.
+
+2011-06-25 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * grub-core/net/i386/pc/pxe.c (grub_pxe_recv): Fix declaration.
+ (grub_pxe_send): Likewise.
+ (GRUB_MOD_INIT): Fix types.
+
+2011-06-24 Szymon Janc <szymon@janc.net.pl>
+
+ * grub-core/io/xzio.c: Fix code style issues
+
+2011-06-24 Vladimir Serbinenko <phcoder@gmail.com>
+2011-06-24 Manoel Rebelo Abranches <mrabran@gmail.com>
+
+ Network infrastructure.
+ The ARP protocol was made by Paulo Pinatti <ppinatti@br.ibm.com>
+
+ * include/grub/net/arp.h: New file.
+ * include/grub/net/device.h: Likewise.
+ * include/grub/net/ethernet.h: Likewise.
+ * include/grub/net/ip.h: Likewise.
+ * include/grub/net/netbuff.h: Likewise.
+ * include/grub/net/tftp.h: Likewise.
+ * include/grub/net/udp.h: Likewise.
+ * include/grub/ieee1275/ofnet.h: Likewise.
+ * include/grub/emu/export.h: Likewise.
+ * include/grub/net.h: Likewise.
+ * grub-core/net/arp.c: Likewise.
+ * grub-core/net/ethernet.c: Likewise.
+ * grub-core/net/ip.c: Likewise.
+ * grub-core/net/udp.c: Likewise.
+ * grub-core/net/tftp.c: Likewise.
+ * grub-core/net/netbuff.c: Likewise.
+ * grub-core/net/net.c: Likewise.
+ * grub-core/net/drivers/emu/emunet.c: Likewise.
+ * grub-core/net/drivers/ieee1275/ofnet.c: Likewise.
+ * grub-core/Makefile.am (KERNEL_HEADER_FILES): Add net.h, ofnet.h and
+ export.h.
+ * grub-core/Makefile.core.def (net): New module.
+ (tftp): Likewise.
+ (ofnet): Likewise.
+ (emunet): Likewise.
+ * grub-core/commands/ls.c (grub_ls_list_devices) [!GRUB_UTIL]: List
+ network protocols.
+ * grub-core/kern/device.c (grub_net_open) : New variable.
+ (grub_device_open): Handle network device.
+ (grub_device_close): Likewise.
+ * grub-core/kern/file.c (grub_file_net_seek) : New variable.
+ (grub_grubnet_fini): Likewise.
+ (grub_file_seek): Seek in network device.
+ * grub-core/kern/fs.c (grub_fs_probe): Handle network devices.
+ * grub-core/kern/ieee1275/init.c (grub_machine_set_prefix): Handle
+ network root.
+ (grub_machine_fini): Call grub_grubnet_fini.
+ * grub-core/kern/ieee1275/openfw.c (grub_ieee1275_parse_args): Handle
+ network.
+ (grub_ieee1275_get_aliasdevname): New function.
+ * grub-core/loader/i386/multiboot_mbi.c (grub_multiboot_get_mbi_size):
+ Add unofficial Solaris network info.
+ (grub_multiboot_make_mbi): Likewise.
+ * grub-core/fs/i386/pc/pxe.c: Moved from here ...
+ * grub-core/net/i386/pc/pxe.c: ...here. Adapted for new design.
+ * include/grub/device.h (grub_fs): Removed.
+ * include/grub/err.h (grub_err_t): Add network-related values.
+ * include/grub/i386/pc/pxe.h: Removed bootp parts.
+ * include/grub/ieee1275/ieee1275.h (grub_ofnetcard_data): New struct.
+ (grub_ieee1275_get_aliasdevname): New proto.
+ * include/grub/net.h: Rewritten.
+
+2011-06-24 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * grub-core/disk/raid.c (insert_array): Ensure uniqueness of readable
+ names.
+
+2011-06-24 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * grub-core/commands/wildcard.c (match_files): Add a useful dprintf.
+ (wildcard_expand): Don't stop on nonregexp parts after regexp ones since
+ it truncates the output.
+ Reported by: Ximin Luo.
+
+2011-06-24 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * grub-core/fs/iso9660.c (grub_iso9660_iterate_dir): Skip . and ..
+
+2011-06-24 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * util/grub-mkconfig_lib.in (prepare_grub_to_access_device): Load
+ partmap before abstraction.
+
+2011-06-24 Alexander Kurtz <kurtz.alex@googlemail.com>
+
+ * util/grub-mkconfig_lib.in: Add missing quotes.
+
+2011-06-24 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * grub-core/kern/emu/getroot.c (grub_guess_root_device): Revert to
+ old method if mountinfo would return /dev/root and /dev/root doesn't
+ exist.
+
+2011-06-24 Vladimir Serbinenko <phcoder@gmail.com>
+
+ ZFS zlib support
+
+ * grub-core/fs/zfs/zfs.c (zlib_decompress): New function.
+ (decomp_table): Add zlib entries.
+ (zio_read): USe 8 bits for compression function rather than 3.
+ * include/grub/zfs/zio.h (zio_compress): Add zlib values.
+
+2011-06-24 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * grub-core/disk/ahci.c: Add missing license statements.
+ * grub-core/fs/romfs.c: Likewise.
+ * grub-core/lib/ia64/setjmp.S: Likewise.
+ * grub-core/loader/i386/pc/freedos.c: Likewise.
+ * grub-core/loader/ia64/efi/linux.c: Likewise.
+ * grub-core/video/colors.c: Likewise.
+ * include/grub/dl.h (GRUB_MOD_DEP): New macro.
+
+2011-06-23 Vladimir Serbinenko <phcoder@gmail.com>
+
+ AHCI support.
+
+ * grub-core/Makefile.core.def (ata_pthru): Removed.
+ (ahci): New module.
+ (pata): Likewise.
+ * grub-core/bus/usb/ohci.c (GRUB_MOD_FINI): Unregister preboot hook
+ on unload.
+ * grub-core/commands/hdparm.c (grub_hdparm_do_ata_cmd): Use ATA
+ readwrite.
+ (grub_hdparm_do_check_powermode_cmd): Likewise.
+ (grub_hdparm_do_smart_cmd): Likewise.
+ (grub_hdparm_set_val_cmd): Likewise.
+ (grub_cmd_hdparm): Likewise. Check thta we have an ATA device.
+ * grub-core/disk/ahci.c: New file.
+ * grub-core/disk/ata.c: Factor out the low-level part into ...
+ * grub-core/disk/pata.c: ... here.
+ * grub-core/disk/ata_pthru.c: Contents moved to ...
+ * grub-core/disk/pata.c: ... here.
+ * grub-core/disk/scsi.c (grub_scsi_names): New array.
+ (grub_scsi_iterate): Use grub_scsi_names.
+ (grub_scsi_open): Likewise.
+ * grub-core/kern/disk.c (grub_disk_ata_pass_through): Removed.
+ * include/grub/ata.h (grub_ata_commands): Add DMA commands.
+ (grub_ata_regs_t): New struct.
+ (grub_disk_ata_pass_through_parms): Likewise.
+ (grub_ata_device): Renamed to ...
+ (grub_ata): ... this.
+ (grub_ata_dev): New struct.
+ Removed all low-level inline functions.
+ * include/grub/scsi.h: Add PATA and AHCI subsystems.
+ (grub_scsi_dev): Removed 'name' and 'id'. Added 'id' parameter to
+ iterate hooks and open. All users updated.
+ * util/grub-install.in: Handle AHCI disk module.
+
+2011-06-23 Szymon Janc <szymon@janc.net.pl>
+
+ Add support for DRI and RSTn markers in JPEG files.
+
+ * grub-core/video/readers/jpeg.c (JPEG_MARKER_DRI): New define.
+ (JPEG_MARKER_RST0): Likewise.
+ (JPEG_MARKER_RST1): Likewise.
+ (JPEG_MARKER_RST2): Likewise.
+ (JPEG_MARKER_RST3): Likewise.
+ (JPEG_MARKER_RST4): Likewise.
+ (JPEG_MARKER_RST5): Likewise.
+ (JPEG_MARKER_RST6): Likewise.
+ (JPEG_MARKER_RST7): Likewise.
+ (grub_jpeg_data): New fields dri, r1, bitmap_ptr.
+ (grub_jpeg_decode_dri): New function.
+ (grub_jpeg_decode_sos): Move image data related part into
+ grub_jpeg_decode_data function.
+ (grub_jpeg_decode_data): New function.
+ (grub_jpeg_reset): New function.
+ (grub_jpeg_decode_jpeg): Handle new markers.
+
+2011-06-23 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * util/ieee1275/ofpath.c (check_sas): Close fd.
+ (main): Free of_path.
+ Reported by: David Volgyes <dvolgyes>.
+
+2011-06-23 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * util/grub-mkpasswd-pbkdf2.c (main): Don't double-close.
+ Reported by: David Volgyes <dvolgyes>.
+
+2011-06-23 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * grub-core/kern/emu/hostdisk.c (grub_util_biosdisk_is_floppy): Close
+ file after stat.
+ Reported by: David Volgyes <dvolgyes>.
+
+2011-06-23 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * util/raid.c (grub_util_raid_getmembers): Close fd before returning.
+
+ Reported by: David Volgyes <dvolgyes>.
+
+2011-06-23 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * grub-core/lib/reed_solomon.c (rs_recover) [STANDALONE]:
+ Prevent memory leak.
+
+2011-06-23 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * grub-core/lib/reed_solomon.c (rs_recover): Prevent memory leak.
+ (main): Close file.
+ Reported by: David Volgyes <dvolgyes>.
+
+2011-06-23 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * grub-core/loader/i386/xnu.c (grub_cpu_xnu_fill_devprop): Don't attempt
+ to continue if allocation is failed.
+
+ Reported by: David Volgyes <dvolgyes>.
+
+2011-06-23 David Volgyes <dvolgyes>
+
+ * grub-core/bus/usb/ohci.c (grub_ohci_pci_iter): Avoid NULL-pointer
+ dereference.
+
+2011-06-23 Vladimir Serbinenko <phcoder@gmail.com>
+
+ Fix spurious warning.
+
+ * grub-core/partmap/acorn.c (grub_acorn_boot_block): Make a union.
+ (acorn_partition_map_find): Use .bin member.
+
+2011-06-23 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * grub-core/kern/emu/getroot.c (grub_guess_root_device): Don't accept
+ /dev/root as a valid device.
+
+2011-06-23 Jim Meyering <meyering@redhat.com>
+
+ Avoid NULL deref in grub_device_open.
+
+ * grub-core/kern/device.c (grub_device_open): Don't dereference
+ a NULL pointer upon failed grub_env_get.
+
+2011-06-23 Vladimir Serbinenko <phcoder@gmail.com>
+
+ Support non-512B sectors and agglomerate reads.
+
+ * Makefile.util.def (libgrubmods.a): Add grub-core/commands/testload.c.
+ * grub-core/disk/efi/efidisk.c (grub_efidisk_data): Remove disk_io.
+ (disk_io_guid): Removed.
+ (make_devices): Locate solely by BlockIO.
+ (grub_efidisk_open): Fill log_sector_size and total_sectors.
+ (grub_efidisk_read): Use read_blocks.
+ (grub_efidisk_write): Use write_blocks.
+ * grub-core/disk/i386/pc/biosdisk.c (grub_biosdisk_open): Fill
+ log_sector_size.
+ (get_safe_sectors): Handle non-512B sectors.
+ (grub_biosdisk_read): Remove special CDROM handling. Handle non-512B
+ sectors.
+ (grub_biosdisk_write): Handle non-512B sectors.
+ * grub-core/disk/scsi.c (grub_scsi_open): Fill log_sector_size.
+ (grub_scsi_read): Remove special non-512B block handling (now handled
+ one level up).
+ * grub-core/kern/disk.c (grub_disk_open): Fill default log_sector_size
+ and do sanity checks.
+ (grub_disk_adjust_range): Handle non-512B sectors.
+ (transform_sector): New function.
+ (grub_disk_read_small): Likewise.
+ (grub_disk_read): Rewritten.
+ (grub_disk_write): Handle non-512B sectors.
+ * grub-core/kern/emu/hostdisk.c (grub_util_biosdisk_open): Fill
+ log_sector_size.
+ (open_device): Use log_sector_size.
+ (grub_util_biosdisk_read): Likewise.
+ (grub_util_biosdisk_write): Likewise.
+ * grub-core/partmap/msdos.c (grub_partition_msdos_iterate): Handle
+ non-512B sectors.
+ (pc_partition_map_embed): Likewise.
+ * include/grub/disk.h (grub_disk): New field log_sector_size.
+ (GRUB_DISK_CACHE_SIZE): Redefined from GRUB_DISK_CACHE_BITS.
+ (GRUB_DISK_CACHE_BITS): Increased to 6.
+ * util/grub-fstest.c (fstest): New command testload.
+ (argp_parser): Likewise.
+
+2011-06-16 Robert Millan <rmh@gnu.org>
+
+ Detect `ataraid' devices on GNU/kFreeBSD. Fix for ATA devices using
+ `ata' driver on kernel of FreeBSD 9.
+
+ * util/deviceiter.c [__FreeBSD_kernel__] (get_ada_disk_name)
+ (get_ataraid_disk_name): New functions.
+ [__FreeBSD_kernel__] (grub_util_iterate_devices): Scan for ataraid
+ (/dev/ar[0-9]+) and ada (/dev/ada[0-9]+) devices using
+ get_ataraid_disk_name() and get_ada_disk_name().
+
+2011-06-13 Colin Watson <cjwatson@ubuntu.com>
+
+ * docs/man/grub-mklayout.h2m (DESCRIPTION): Add a reference to the
+ input format.
+
+2011-05-29 Colin Watson <cjwatson@ubuntu.com>
+
+ * docs/grub.texi (Obtaining and Building GRUB): Substitute
+ `ftp.gnu.org' for `alpha.gnu.org'.
+
+2011-05-27 Colin Watson <cjwatson@ubuntu.com>
+
+ * grub-core/kern/emu/hostdisk.c (linux_find_partition): Handle
+ partitions under /dev/disk/by-id/.
+
+2011-05-27 Colin Watson <cjwatson@ubuntu.com>
+
+ * grub-core/kern/emu/hostdisk.c (linux_find_partition): Give up
+ after ten consecutive open failures. Scanning all the way up to
+ 10000 is excessive and can cause serious performance problems in
+ some configurations.
+ Fixes Ubuntu bug #787461.
+
+2011-05-21 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * grub-core/disk/arc/arcdisk.c (reopen): Close old handle before
+ opening new one.
+
+2011-05-21 Colin Watson <cjwatson@ubuntu.com>
+2011-05-21 Vladimir Serbinenko <phcoder@gmail.com>
+
+ Don't stat devices unless we have to.
+
+ * grub-core/kern/emu/getroot.c (grub_find_device): Recognize
+ dir == /dev/mapper.
+ (grub_guess_root_device): Use already known os_dev if possible.
+ * grub-core/kern/emu/hostdisk.c
+ (convert_system_partition_to_system_disk): Scan only in /dev/mapper
+ if device is known to be a dm one.
+
+2011-05-20 Colin Watson <cjwatson@ubuntu.com>
+
+ * util/grub-mkconfig.in: Export GRUB_CMDLINE_LINUX_XEN_REPLACE and
+ GRUB_CMDLINE_LINUX_XEN_REPLACE_DEFAULT.
+ Reported by: Pawel Tecza.
+
+2011-05-19 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * grub-core/Makefile.core.def (lsacpi): Fix ia64 mismerge.
+ (lsefisystab): Likewise.
+ (lssal): Likewise.
+ (lsefimmap): Likewise.
+ (hdparm): Enable on qemu-mips.
+ (setjmp): Add ia64 nodist.
+ (serial): Simplify tags.
+
+2011-05-18 Colin Watson <cjwatson@ubuntu.com>
+
+ * Makefile.util.def (grub-ofpathname): Install manual page.
+
+2011-05-18 Colin Watson <cjwatson@ubuntu.com>
+
+ * grub-core/fs/squash4.c: Add missing GRUB_MOD_LICENSE.
+
+2011-05-18 Colin Watson <cjwatson@ubuntu.com>
+
+ * .bzrignore: Add grub-core/modinfo.sh and a number of test files.
+
+2011-05-18 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * grub-core/bus/usb/usbhub.c (poll_nonroot_hub): Downgrade a printf
+ into dprintf.
+
+2011-05-18 Vladimir Serbinenko <phcoder@gmail.com>
+
+ Use full 64-bit division.
+
+ * grub-core/kern/misc.c (grub_divmod64_full): Renamed to ...
+ (grub_divmod64): ... this.
+ * include/grub/misc.h (grub_divmod64): Removed. All users switch to full
+ version.
+
+2011-05-18 Colin Watson <cjwatson@ubuntu.com>
+
+ * util/grub-mkrescue.in: Use portable `.' rather than non-portable
+ `source'.
+
+2011-05-18 Colin Watson <cjwatson@ubuntu.com>
+
+ * grub-core/genmod.sh.in: Use 'set -e' rather than '#! /bin/sh -e',
+ to avoid accidents when debugging with 'sh -x'.
+ * grub-core/gensyminfo.sh.in: Likewise.
+ * tests/example_scripted_test.in: Likewise.
+ * tests/grub_cmd_regexp.in: Likewise.
+ * tests/grub_script_blanklines.in: Likewise.
+ * tests/grub_script_dollar.in: Likewise.
+ * tests/grub_script_expansion.in: Likewise.
+ * tests/grub_script_final_semicolon.in: Likewise.
+ * tests/partmap_test.in: Likewise.
+ * tests/util/grub-shell-tester.in: Likewise.
+ * tests/util/grub-shell.in: Likewise.
+
+2011-05-18 Colin Watson <cjwatson@ubuntu.com>
+
+ Move gfxmenu color handling to video, so that gfxterm can use it
+ too.
+
+ * grub-core/gfxmenu/named_colors.c: Move to ...
+ * grub-core/video/colors.c: ... here. Rename
+ grub_gui_get_named_color to grub_video_get_named_color.
+ * grub-core/gfxmenu/gui_string_util.c (my_isxdigit): Move to ...
+ * grub-core/video/colors.c (my_isxdigit): ... here.
+ * grub-core/gfxmenu/gui_string_util.c (parse_hex_color_component):
+ Move to ...
+ * grub-core/video/colors.c (parse_hex_color_component): ... here.
+ * grub-core/gfxmenu/gui_string_util.c (grub_gui_parse_color): Move
+ to ...
+ * grub-core/video/colors.c (grub_video_parse_color): ... here.
+
+ * include/grub/gui.h (grub_gui_color_t): Move to ...
+ * include/grub/video.h (grub_video_rgba_color_t): ... here.
+ * include/grub/gui.h (grub_gui_color_rgb): Move to ...
+ * include/grub/video.h (grub_video_rgba_color_rgb): ... here.
+ * include/grub/gui.h (grub_gui_map_color): Move to ...
+ * include/grub/video.h (grub_video_map_rgba_color): ... here.
+ * include/grub/gui_string_util.h (grub_gui_get_named_color): Move
+ to ...
+ * include/grub/video.h (grub_video_get_named_color): ... here.
+ * include/grub/gui_string_util.h (grub_gui_parse_color): Move to ...
+ * include/grub/video.h (grub_video_parse_color): ... here.
+
+ * grub-core/Makefile.core.def (kernel) [videoinkernel]: Add
+ video/colors.c.
+ (gfxmenu): Remove gfxmenu/named_colors.c.
+ (video) [videomodules]: Add video/colors.c.
+
+ Add a background_color command.
+
+ * grub-core/term/gfxterm.c (grub_gfxterm_background_color_cmd): New
+ function.
+ (GRUB_MOD_INIT): Register background_color command.
+ (GRUB_MOD_FINI): Unregister background_color command.
+ (redraw_screen_rect): Allow blend/replace of text layer to be
+ controlled independently from whether there is a background bitmap.
+ (grub_gfxterm_background_image_cmd): Change blend_text_bg when
+ changing bitmap.
+
+2011-05-18 Vladimir Serbinenko <phcoder@gmail.com>
+
+ Patch BPB in ntldr and chainloader --bpb.
+
+ * grub-core/fs/fat.c: Include grub/fat.h.
+ (grub_fat_bpb): Moved to ...
+ * include/grub/fat.h (grub_fat_bpb): ... here. New file.
+ * grub-core/loader/i386/pc/chainloader.c: Include grub/fat.h and
+ grub/ntfs.h.
+ * include/grub/i386/pc/chainloader.h (grub_chainloader_flags_t):
+ Moved from here...
+ * grub-core/loader/i386/pc/chainloader.c (grub_chainloader_flags_t): ...
+ here.
+ * grub-core/loader/i386/pc/chainloader.c (grub_chainloader_patch_bpb):
+ New function.
+ (grub_chainloader_cmd): Patch BPB if --bpb is given.
+ (GRUB_MOD_INIT): Show --bpb.
+ * grub-core/loader/i386/pc/ntldr.c (grub_cmd_ntldr): Patch BPB.
+ * grub-core/normal/main.c (features): New variable.
+ (GRUB_MOD_INIT): Set feature_* variables.
+ * include/grub/i386/pc/chainloader.h (grub_chainloader_patch_bpb): New
+ proto.
+ * include/grub/ntfs.h (grub_ntfs_bpb): New field bios_drive.
+
+2011-05-18 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * grub-core/Makefile.core.def (ieee1275_fb): Use enable=powerpc_ieee1275
+ for cleanness.
+
+2011-05-18 Vladimir Serbinenko <phcoder@gmail.com>
+
+ FreeDOS direct loading support.
+
+ * docs/grub.texi (Supported OS): Add FreeDOS.
+ * grub-core/Makefile.core.def (freedos): New module.
+ * grub-core/lib/i386/relocator.c (grub_relocator16_ebx): New extern
+ variable.
+ (grub_relocator16_boot): Handle %ebx.
+ * grub-core/lib/i386/relocator16.S: Likewise.
+ * grub-core/loader/i386/pc/freedos.c: New file.
+
+2011-05-18 Vladimir Serbinenko <phcoder@gmail.com>
+
+ Long Linux command line support.
+
+ * grub-core/loader/i386/linux.c (GRUB_LINUX_CL_END_OFFSET): Removed.
+ (maximal_cmdline_size): New variable.
+ (allocate_pages): Use maximal_cmdline_size.
+ (grub_cmd_linux): Set and use maximal_cmdline_size.
+ * grub-core/loader/i386/pc/linux.c (GRUB_LINUX_CL_END_OFFSET): Removed.
+ (allocate_pages): Use maximal_cmdline_size.
+ (grub_cmd_linux): Set and use maximal_cmdline_size.
+ * include/grub/i386/linux.h (GRUB_LINUX_SETUP_MOVE_SIZE): Removed.
+ (linux_kernel_header): Add fields kernel_alignment, relocatable, pad
+ and cmdline_size.
+
+2011-05-18 Vladimir Serbinenko <phcoder@gmail.com>
+2011-05-18 Colin Watson <cjwatson@ubuntu.com>
+
+ Improve devmapper support
+
+ * grub-core/kern/emu/getroot.c (grub_util_is_dmraid): Removed.
+ (grub_util_is_lvm): New function.
+ (grub_util_get_dev_abstraction): Assume dmraid if not lvm rather
+ than lvm if not dmraid.
+ Handle mapped md nodes.
+ * grub-core/kern/emu/hostdisk.c (device_is_mapped): Rename to ...
+ (grub_util_device_is_mapped): ... this. Make always available. All users
+ updated.
+ (grub_util_get_dm_node_linear_info) [HAVE_DEVICE_MAPPER]: New function.
+ (convert_system_partition_to_system_disk): Handle lvm, mpath and
+ dmraid nodes.
+ * include/grub/emu/misc.h (grub_util_device_is_mapped): New proto.
+
+2011-05-18 Vladimir Serbinenko <phcoder@gmail.com>
+
+ Unify grub-mkrescue (except powerpc) and grrub-mknetdir across platforms
+
+ * grub-core/Makefile.am (platform_DATA): Add modinfo.sh.
+ * grub-core/modinfo.sh.in: New file.
+ * grub-core/Makefile.core.def (modinfo.sh): New script.
+ * util/grub-mknetdir.in: Use modinfo.sh.
+ * util/grub-mkrescue.in: Likewise.
+
+2011-05-17 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * grub-core/kern/ia64/dl_helper.c (grub_ia64_dl_get_tramp_got_size):
+ Fix potential usage of Elf32 instead of Elf64 when compiling on
+ 32-bit architecture. Add endianness macros while on it.
+
+2011-05-17 Vladimir Serbinenko <phcoder@gmail.com>
+
+ Use mipsel- rather than mips- in directories involving mipsel ports to
+ allow both endiannesses coexist.
+
+ * configure.ac: proparate target_cpu=mipsel rather than resetting to
+ mips. All conditions adjusted.
+ * tests/util/grub-shell-tester.in: Remove gratuitious target_cpu
+ variable.
+ * util/grub-install.in: Adjust conditions to take renaming into account.
+ * util/grub-mkimage.c (image_targets): Likewise. New target
+ mips-qemu_mips-elf for bigendian mips.
+
+2011-05-17 Vladimir Serbinenko <phcoder@gmail.com>
+
+ Avoid unnecessary copying on MIPS.
+
+ * grub-core/boot/decompressor/none.c (grub_decompress_core): Exit
+ early if src == dest.
+ * util/grub-mkimage.c (generate_image): Arange for src == dest if
+ compression is none.
+
+2011-05-17 Vladimir Serbinenko <phcoder@gmail.com>
+
+ Reduce memory footprint on SGI by putting modules before the kernel
+ as opposed to after.
+
+ * grub-core/Makefile.core.def (kernel): Increase linking address.
+ (none_decompress): Likewise.
+ (xz_decompress): Likewise.
+ * grub-core/boot/mips/startup_raw.S: Use prewritten uncompression
+ address.
+ * grub-core/kern/mips/arc/init.c (grub_machine_init): Handle memory
+ layout change.
+ (grub_arch_modules_addr): New function.
+ * grub-core/kern/mips/init.c (grub_arch_modules_addr): Moved from here...
+ * grub-core/kern/mips/loongson/init.c (grub_arch_modules_addr): .. here
+ * grub-core/kern/mips/qemu_mips/init.c (grub_arch_modules_addr): ... and
+ here.
+ * grub-core/kern/mips/startup.S (total_size): Rename to ...
+ (grub_total_modules_size): ... this. Make global.
+ [GRUB_MACHINE_ARC]: Don't attempt to move modules out of the bss.
+ * include/grub/offsets.h (GRUB_KERNEL_MIPS_LOONGSON_UNCOMPRESSED_ADDR):
+ New definition.
+ (GRUB_KERNEL_MIPS_QEMU_MIPS_UNCOMPRESSED_ADDR): Likewise.
+ (GRUB_KERNEL_MIPS_ARC_UNCOMPRESSED_ADDR): Likewise.
+ (GRUB_KERNEL_MACHINE_UNCOMPRESSED_ADDR): Likewise.
+ (GRUB_KERNEL_MIPS_ARC_LINK_ADDR): Increased.
+ * util/grub-mkimage.c (image_target_desc): New flag
+ PLATFORM_FLAGS_MODULES_BEFORE_KERNEL.
+ (image_targets): Set PLATFORM_FLAGS_MODULES_BEFORE_KERNEL on mips-arc.
+ (generate_image): Handle images with modules before kernel.
+
+2011-05-17 Vladimir Serbinenko <phcoder@gmail.com>
+
+ Prevent potential loss of memory map by overwrite on qemu-mips.
+
+ * grub-core/boot/mips/startup_raw.S [GRUB_MACHINE_MIPS_QEMU_MIPS]:
+ Save ram size in $s4.
+ * grub-core/kern/mips/qemu_mips/init.c (RAMSIZE): Removed.
+ All users changed to grub_arch_memsize.
+ * grub-core/kern/mips/startup.S (grub_arch_machine): Restrict to
+ Loongson.
+ [GRUB_MACHINE_MIPS_QEMU_MIPS]: Save grub_arch_memsize.
+ * grub-core/loader/mips/linux.c (grub_linux_boot): Pass memory size.
+ * include/grub/mips/qemu_mips/memory.h (grub_arch_memsize): New
+ external variable.
+
+2011-05-17 Colin Watson <cjwatson@ubuntu.com>
+
+ * .bzrignore: Remove grub-dumpbios.
+
+2011-05-17 Colin Watson <cjwatson@ubuntu.com>
+
+ * util/grub.d/20_linux_xen.in: Honour GRUB_CMDLINE_LINUX_XEN_REPLACE
+ and GRUB_CMDLINE_LINUX_XEN_REPLACE_DEFAULT, which replace
+ GRUB_CMDLINE_LINUX and GRUB_CMDLINE_LINUX_DEFAULT (complementing the
+ existing options which append).
+ * docs/grub.texi (Simple configuration): Document new options.
+ Reported by: Ian Jackson. Fixes Debian bug #617538.
+
+2011-05-17 Colin Watson <cjwatson@ubuntu.com>
+
+ * util/grub-fstest.c (cmd_cat): New function.
+ (fstest): Handle CMD_CAT.
+ (options): Add cat.
+ (argp_parser): Handle cat.
+
+2011-05-17 Colin Watson <cjwatson@ubuntu.com>
+
+ * Makefile.util.def (grub-bin2h): Don't install.
+ * docs/man/grub-bin2h.h2m: Remove.
+
+2011-05-17 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * grub-core/kern/mips/startup.S (grub_arch_cpuclock): Move to the right
+ place.
+
+2011-05-17 Vladimir Serbinenko <phcoder@gmail.com>
+
+ Reenable qemu-mips port.
+
+ * configure.ac: Handle --target=qemu-mips and --target=qemu_mips.
+ Fix small arc bug while on it.
+ * gentpl.py: Handle qemu_mips.
+ * grub-core/Makefile.am: Likewise.
+ * grub-core/Makefile.core.def: Likewise.
+ * grub-core/disk/ata.c [GRUB_MACHINE_MIPS_QEMU_MIPS]: Remove
+ inappropriate includes.
+ (grub_ata_pciinit) [GRUB_MACHINE_MIPS_QEMU_MIPS]: Removed.
+ (grub_ata_initialize): [GRUB_MACHINE_MIPS_QEMU_MIPS]: Rewritten.
+ * grub-core/kern/main.c (grub_modules_get_end)
+ [GRUB_MACHINE_MIPS_QEMU_MIPS]: Enable.
+ * grub-core/kern/mips/qemu-mips: Moved to ..
+ * grub-core/kern/mips/qemu_mips: ... this.
+ * grub-core/kern/mips/qemu_mips/init.c (grub_get_rtc): Removed.
+ (grub_machine_init): Call terminfo_init and serial_init.
+ * grub-core/kern/mips/startup.S: Change MIPS_LOONGSON to MACHINE.
+ * grub-core/loader/mips/linux.c (params) [GRUB_MACHINE_MIPS_QEMU_MIPS]:
+ New variable.
+ (grub_linux_boot) [GRUB_MACHINE_MIPS_QEMU_MIPS]: Handle the qemu-mips
+ parameter passing.
+ (grub_linux_unload) [GRUB_MACHINE_MIPS_QEMU_MIPS]: Free params.
+ (grub_cmd_linux) [GRUB_MACHINE_MIPS_QEMU_MIPS]: Handle params.
+ (grub_cmd_initrd) [GRUB_MACHINE_MIPS_QEMU_MIPS]: Likewise.
+ * include/grub/mips/qemu_mips/cmos.h: New file.
+ * include/grub/mips/qemu-mips/kernel.h: Don't include cpu/kernel.h.
+ * include/grub/mips/qemu-mips/memory.h (grub_machine_mmap_iterate):
+ Removed.
+ * include/grub/mips/qemu-mips/serial.h (GRUB_MACHINE_SERIAL_PORTS):
+ Use correct mips-style address.
+ * include/grub/mips/qemu-mips/time.h: Include cpu/time.h.
+ (GRUB_TICKS_PER_SECOND): Removed.
+ (grub_get_rtc): Likewise.
+ (grub_cpu_idle): Likewise.
+ * include/grub/offsets.h (GRUB_KERNEL_MIPS_QEMU_MIPS_LINK_ADDR):
+ New definition.
+ (GRUB_KERNEL_MIPS_QEMU_MIPS_LINK_ALIGN): Likewise.
+ (GRUB_KERNEL_MIPS_QEMU_MIPS_COMPRESSED_SIZE): Likewise.
+ (GRUB_KERNEL_MIPS_QEMU_MIPS_UNCOMPRESSED_SIZE): Likewise.
+ (GRUB_KERNEL_MIPS_QEMU_MIPS_TOTAL_MODULE_SIZE): Likewise.
+ (GRUB_KERNEL_MIPS_QEMU_MIPS_PREFIX): Likewise.
+ (GRUB_KERNEL_MIPS_QEMU_MIPS_PREFIX_END): Likewise.
+ (GRUB_KERNEL_MIPS_QEMU_MIPS_MOD_ALIGN): Likewise.
+ * util/grub-mkimage.c (image_targets): Add mipsel-qemu_mips-elf.
+
+2011-05-17 Vladimir Serbinenko <phcoder@gmail.com>
+
+ SGI ARCS port.
+
+ * Makefile.util.def (libgrubmods.a): Add dvh.c.
+ * conf/Makefile.common (CCASFLAGS_PLATFORM): Add -mips3 on all mips
+ platforms.
+ * configure.ac: New target mips-arc.
+ * gentpl.py: Likewise.
+ * grub-core/Makefile.am: Likewise.
+ * grub-core/Makefile.core.def: Likewise.
+ (xz_decompress): Remove -D GRUB_MACHINE_LINK_ADDR.
+ (none_decompress): Likewise.
+ (lsdev): New module.
+ (datetime): Use lib/arc/datetime.c on ARC.
+ (part_dvh): New module.
+ * grub-core/commands/arc/lsdev.c: New file.
+ * grub-core/disk/arc/arcdisk.c: Likewise.
+ * grub-core/kern/mips/arc/init.c: Likewise.
+ * grub-core/kern/mips/cache_flush.S: Don't flush non 4-byte
+ aligned addresses.
+ * grub-core/kern/mips/dl.c (grub_arch_dl_check_header): Fix bigendian
+ support.
+ (grub_arch_dl_relocate_symbols): Likewise.
+ * grub-core/kern/mips/loongson/init.c (grub_get_rtc): Moved from here...
+ * grub-core/kern/mips/init.c (grub_get_rtc): ... here.
+ * grub-core/kern/mips/startup.S (grub_arch_cpuclock): Have on all
+ platforms.
+ * grub-core/lib/arc/datetime.c: New file.
+ * grub-core/loader/mips/linux.c: Always include time.h. Don't include
+ pci.h on non-loongson.
+ (envp_off) [!GRUB_MACHINE_MIPS_LOONGSON]: Remove.
+ (grub_linux_boot): Set unused registers to 0.
+ (grub_cmd_linux) [!GRUB_MACHINE_MIPS_LOONGSON]: Remove envp.
+ * grub-core/mmap/mips/loongson/uppermem.c: Moved from here ...
+ * grub-core/mmap/mips/uppermem.c: ...here.
+ * grub-core/partmap/dvh.c: New file.
+ * grub-core/term/arc/console.c: Likewise.
+ * grub-core/term/terminfo.c (ANSI_C0_STR): New const.
+ (grub_terminfo_set_current): Add terminal "arc".
+ (grub_terminfo_readkey): Support ARC sequences.
+ * include/grub/arc/arc.h: New file.
+ * include/grub/arc/console.h: Likewise.
+ * include/grub/disk.h (grub_disk_dev_id): Add
+ GRUB_DISK_DEVICE_ARCDISK_ID.
+ * include/grub/mips/arc/kernel.h: New file.
+ * include/grub/mips/arc/memory.h: Likewise.
+ * include/grub/mips/arc/time.h: Likewise.
+ * include/grub/mips/loongson/kernel.h (grub_halt): Moved from here ...
+ * include/grub/mips/kernel.h (grub_halt): ... here.
+ * include/grub/mips/loongson.h (GRUB_CPU_REGISTER_WRAP): Moved from
+ here...
+ * include/grub/mips/mips.h (GRUB_CPU_REGISTER_WRAP): ... here.
+ (GRUB_CPU_LOONGSON_COP0_TIMER_COUNT): Moved from here ...
+ * include/grub/mips/mips.h (GRUB_CPU_LOONGSON_COP0_TIMER_COUNT): .. here
+ * include/grub/mips/loongson/kernel.h (grub_reboot): Removed redundant
+ proto.
+ * include/grub/mips/loongson/memory.h (GRUB_ARCH_LOWMEMVSTART): Moved
+ from here ...
+ * include/grub/mips/memory.h (GRUB_ARCH_LOWMEMVSTART): ... here.
+ (GRUB_ARCH_LOWMEMPSTART): Moved from here ...
+ * include/grub/mips/memory.h (GRUB_ARCH_LOWMEMPSTART): ... here.
+ (GRUB_ARCH_LOWMEMMAXSIZE): Moved from here ...
+ * include/grub/mips/memory.h (GRUB_ARCH_LOWMEMMAXSIZE): ... here.
+ (GRUB_ARCH_HIGHMEMPSTART): Moved from here ...
+ * include/grub/mips/memory.h (GRUB_ARCH_HIGHMEMPSTART): ... here.
+ (grub_phys_addr_t): Moved from here ...
+ * include/grub/mips/memory.h (grub_phys_addr_t): ... here.
+ (grub_vtop): Moved from here ...
+ * include/grub/mips/memory.h (grub_vtop): ... here.
+ (grub_map_memory): Moved from here ...
+ * include/grub/mips/memory.h (grub_map_memory): ... here.
+ (grub_unmap_memory): Moved from here ...
+ * include/grub/mips/memory.h (grub_unmap_memory): ... here.
+ (grub_machine_mmap_iterate): Moved from here ...
+ * include/grub/mips/memory.h (grub_machine_mmap_iterate): ... here.
+ (grub_mmap_get_lower): Moved from here ...
+ * include/grub/mips/memory.h (grub_mmap_get_lower): ... here.
+ (grub_mmap_get_upper): Moved from here ...
+ * include/grub/mips/memory.h (grub_mmap_get_upper): ... here.
+ * include/grub/mips/loongson/time.h (grub_arch_cpuclock): Moved from
+ here ...
+ * include/grub/mips/time.h (grub_arch_cpuclock): ... here.
+ * include/grub/mips/loongson/time.h (grub_get_rtc): Moved from
+ here ...
+ * include/grub/mips/time.h (grub_get_rtc): ... here.
+ * include/grub/mips/loongson/time.h (grub_arch_cpuclock): Moved from
+ here ...
+ * include/grub/mips/time.h (grub_arch_cpuclock): ... here.
+ * include/grub/mips/loongson/time.h (grub_cpu_idle): Moved from
+ here ...
+ * include/grub/mips/time.h (grub_cpu_idle): ... here.
+ * include/grub/offsets.h (GRUB_KERNEL_MIPS_ARC_LINK_ADDR): New
+ definition.
+ (GRUB_KERNEL_MIPS_ARC_LINK_ALIGN): Likewise.
+ (GRUB_KERNEL_MIPS_ARC_COMPRESSED_SIZE): Likewise.
+ (GRUB_KERNEL_MIPS_ARC_UNCOMPRESSED_SIZE): Likewise.
+ (GRUB_KERNEL_MIPS_ARC_TOTAL_MODULE_SIZE): Likewise.
+ (GRUB_KERNEL_MIPS_ARC_PREFIX): Likewise.
+ (GRUB_KERNEL_MIPS_ARC_PREFIX_END): Likewise.
+ (GRUB_KERNEL_MIPS_ARC_MOD_ALIGN): Likewise.
+ (GRUB_MACHINE_LINK_ADDR): Likewise.
+ * include/grub/terminfo.h (GRUB_TERMINFO_READKEY_MAX_LEN): Increased
+ to 6.
+ * util/grub-install.in: Run dvhtool on ARC.
+ * util/grub-mkimage.c (image_targets): Add mips-arc.
+ (generate_image): Handle ECOFF output for mips-arc.
+
+2011-05-16 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * grub-core/bus/pci.c (grub_memalign_dma32): Always allocate in 64-byte
+ blocks.
+
+2011-05-16 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * grub-core/bus/usb/usbhub.c (attach_root_port): Wait 10ms
+ after enabling port.
+
+2011-05-16 Vladimir Serbinenko <phcoder@gmail.com>
+
+ Skip incorrect USB devices.
+
+ * grub-core/bus/usb/usb.c (grub_usb_device_initialize): Fail if
+ configcnt == 0.
+ * include/grub/usb.h (grub_usb_err_t): New enum value
+ GRUB_USB_ERR_BADDEVICE.
+
+2011-05-16 Vladimir Serbinenko <phcoder@gmail.com>
+
+ Fuloong video init support.
+
+ * include/grub/vga.h (grub_vga_write_arx): inb monochrome address as
+ well.
+ (grub_vga_read_arx): New function.
+ * grub-core/video/sis315pro.c (GRUB_SIS315PRO_MMIO_SPACE): New
+ definition.
+ (framebuffer): New members io, mmioptr and mmiobase.
+ (read_sis_cmd): New function.
+ (write_sis_cmd): Likewise.
+ (grub_video_sis315pro_setup): Do the initialisation. Use 640x480
+ rather than 640x400.
+ * grub-core/video/sis315_init.c: New file.
+
+2011-05-15 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * grub-core/bus/cs5536.c: Don't include grub/machine/kernel.h on
+ non-loongson.
+ * grub-core/kern/mips/dl.c (grub_arch_dl_init_linker): Fix argument
+ to grub_dl_register_symbol.
+
+2011-05-15 Vladimir Serbinenko <phcoder@gmail.com>
+
+ Fix compilation errors.
+
+ * grub-core/term/ns8250.c (serial_get_divisor): Declare 'port' as
+ potentially unused.
+ * grub-core/loader/i386/linux.c (grub_linux_setup_video):
+ Handle GRUB_VIDEO_DRIVER_SIS315PRO.
+ * grub-core/bus/cs5536.c (grub_cs5536_init_geode): Restrict DIVIL init
+ to loongson machines.
+
+2011-05-15 Vladimir Serbinenko <phcoder@gmail.com>
+
+ Several FS mtime support.
+
+ * grub-core/fs/affs.c (grub_affs_time): New struct.
+ (grub_affs_file): New field mtime.
+ (grub_fshelp_node): Changed 'block' and 'parent' to more appropriate
+ type. Removed 'size'. New field 'di'. All users updated.
+ (grub_affs_mount): Simplify checsum checking.
+ (grub_affs_iterate_dir): New helper grub_affs_create_node.
+ (grub_affs_dir): Handle mtime.
+ * grub-core/fs/cpio.c (grub_cpio_find_file): Handle mtime.
+ (grub_cpio_dir): Likewise.
+ * grub-core/fs/hfs.c (grub_hfs_dirrec): New fields 'ctime' and 'mtime'.
+ (grub_hfs_filerec): New field mtime.
+ (grub_hfs_dir): Handle mtime.
+ (grub_hfs_mtime): New function.
+ (grub_hfs_fs): Register grub_hfs_mtime.
+ * grub-core/fs/iso9660.c (grub_iso9660_date2): New struct.
+ (grub_iso9660_dir): New field mtime.
+ (grub_fshelp_node): New field dirent.
+ (iso9660_to_unixtime): New function.
+ (iso9660_to_unixtime2): Likewise.
+ (grub_iso9660_read_symlink): Use node->dirent.
+ (grub_iso9660_iterate_dir): Likewise.
+ (grub_iso9660_dir): Set mtime.
+ (grub_iso9660_mtime): New function.
+ (grub_iso9660_fs): Register grub_iso9660_mtime.
+ * grub-core/fs/jfs.c (grub_jfs_time): New struct.
+ (grub_jfs_inode): New fields atime, ctime and mtime.
+ (grub_jfs_dir): Set mtime.
+ * grub-core/fs/minix.c (grub_minix_dir): Likewise.
+ * grub-core/fs/ntfs.c (list_file): Set mtime.
+ (grub_ntfs_dir): Likewise.
+ * grub-core/fs/reiserfs.c (grub_fshelp_node): New field 'mtime'.
+ (grub_reiserfs_iterate_dir): Set mtime.
+ (grub_reiserfs_dir): Likewise.
+ * grub-core/fs/sfs.c (grub_sfs_obj): New field mtime.
+ (grub_fshelp_node): Likewise.
+ (grub_sfs_iterate_dir): Set mtime.
+ (grub_sfs_dir): Likewise.
+ * grub-core/fs/udf.c (grub_udf_dir): Set mtime.
+ * grub-core/fs/xfs.c (grub_xfs_time): New struct.
+ (grub_xfs_inode): New fields atime, mtime, ctime.
+ (grub_xfs_dir): Set mtime.
+ * include/grub/datetime.h (grub_datetime2unixtime): New function.
+ * include/grub/hfs.h (grub_hfs_sblock): New fields ctime and mtime.
+ * include/grub/ntfs.h (grub_fshelp_node): New field mtime.
+
+ Support UDF symlinks.
+
+ * grub-core/fs/udf.c (grub_udf_iterate_dir): Handle symlinks.
+ (grub_ufs_read_symlink): New function. All users updated.
+
+ Check amiga partmap checksum.
+
+ * grub-core/partmap/amiga.c (grub_amiga_rdsk): Pad to 128 bytes.
+ (grub_amiga_partition): Likewise.
+ (amiga_partition_map_checksum): New function.
+ (amiga_partition_map_iterate): Check checksum.
+
+2011-05-15 Vladimir Serbinenko <phcoder@gmail.com>
+
+ ROMFS support.
+
+ * Makefile.util.def (libgrubmods.a): Add romfs.
+ * grub-core/Makefile.core.def (romfs): New module.
+ * grub-core/fs/romfs.c: New file.
+
+2011-05-15 Vladimir Serbinenko <phcoder@gmail.com>
+
+ Squashfs v4 support.
+
+ * Makefile.util.def (libgrubmods.a): Add squash4.
+ * grub-core/Makefile.core.def (squash4): New module.
+ * grub-core/fs/squash4.c: New file.
+ * grub-core/io/gzio.c (grub_gzio): New members disk_input_off,
+ disk_input_start, disk_input.
+ (get_byte): Handle disk_input.
+ (grub_zlib_disk_read): New function.
+ * include/grub/deflate.h (grub_zlib_disk_read): New proto.
+
+2011-05-15 Vladimir Serbinenko <phcoder@gmail.com>
+2011-05-15 Feiran Zheng <famcool@gmail.com>
+
+ * Makefile.util.def (libgrubmods.a): Add minix3.
+ * grub-core/Makefile.core.def (minix3): New module.
+ * grub-core/fs/minix.c (GRUB_MINIX_MAGIC) [MODE_MINIX3]: New value.
+ (GRUB_MINIX_BSIZE): Removed.
+ (GRUB_MINIX_INODE_DIR_BLOCKS): New definition. All users updated.
+ (grub_minix_ino_t): New type.
+ (grub_minix_le_to_cpu_ino): New macro.
+ (GRUB_MINIX_ZONE2SECT): New definition. All users updated.
+ (grub_minix_sblock) [MODE_MINIX3]: Change for minix3.
+ (grub_minix_data): New field block_size.
+ (grub_minix_read_file): Handle 64-bit correctly.
+ * grub-core/fs/minix3.c: New file.
+
+2011-05-15 Tristan Gingold <gingold@free.fr>
+2011-05-15 Robert Millan <rmh.grub@aybabtu.com>
+2011-05-15 Vladimir Serbinenko <phcoder@gmail.com>
+
+ IA64 support.
+
+ * Makefile.util.def (libgrubmods.a): Add grub-core/kern/ia64/dl_helper.c
+ * configure.ac: Add ia64-efi target.
+ Probe for __ia64_trampoline, __udivsi3, __umoddi3, __udivdi3,
+ __divsi3, __modsi3, __umodsi3, __moddi3 and __divdi3 symbols.
+ * gentpl.py: Add ia64_efi platform.
+ Rename x86_efi to efi and Add ia64-efi. All users updated.
+ * grub-core/Makefile.am: Set KERNEL_HEADER_FILES for ia64-efi.
+ * grub-core/Makefile.core.def (kernel.img): Add compile flags for ia64.
+ Remove kern/generic/rtc_get_time_ms.c on EFI.
+ Add kern/ia64/efi/startup.S, kern/ia64/efi/init.c, kern/ia64/dl.c,
+ kern/ia64/dl_helper.c on ia64-efi.
+ Add kern/emu/cache.c on emu.
+ (linux): Use on loader/ia64/efi/linux.c on ia64.
+ * grub-core/gensymlist.sh (grub_register_exported_symbols): Check
+ whether symbol is a function.
+ * grub-core/kern/dl.c [GRUB_MACHINE_EMU]: Include sys/mman.h.
+ (grub_symbol): New field 'isfunc'.
+ (grub_dl_resolve_symbol): Return whole symbol rather than just address.
+ (grub_dl_register_symbol): New argument 'isfunc'. All users updated.
+ (grub_dl_load_segments): Place all sections into the same region.
+ [__ia64__]: Create trampolines and got.
+ [GRUB_MACHINE_EMU]: Call mprotect.
+ (grub_dl_resolve_symbols): Resolve symbol type as well.
+ [__ia64__]: Create function descriptors.
+ * grub-core/kern/efi/efi.c (grub_get_rtc): Renamed to ...
+ (grub_rtc_get_time_ms): ... this. Expressions simplified.
+ (grub_get_rtc): New function.
+ * grub-core/kern/emu/cache.c [__ia64__]: New file.
+ * grub-core/kern/emu/cache.S: Renamed to ...
+ * grub-core/kern/emu/cache_s.S: ... this.
+ [__ia64__]: Add a nop.
+ * grub-core/kern/emu/full.c (grub_arch_dl_get_tramp_got_size)
+ [__ia64__]: New function.
+ * grub-core/kern/emu/lite.c [__ia64__]: Include ../ia64/dl.c.
+ * grub-core/kern/ia64/dl.c: New file.
+ * grub-core/kern/ia64/dl_helper.c: Likewise.
+ * grub-core/kern/ia64/efi/init.c: New file.
+ * grub-core/kern/ia64/efi/startup.S: Likewise.
+ * grub-core/lib/efi/halt.c [__ia64__]: Don't try acpi.
+ * grub-core/lib/ia64/longjmp.S: New file (from glibc).
+ * grub-core/lib/ia64/setjmp.S: Likewise (from glibc).
+ * grub-core/lib/setjmp.S [__ia64__]: Include ./ia64/setjmp.S.
+ * grub-core/loader/ia64/efi/linux.c: New file.
+ * include/grub/dl.h (GRUB_MOD_NAME): Redefined using C rather than asm.
+ (GRUB_MOD_DEP): Likewise.
+ (grub_dl) [__ia64__]: New fields got and tramp.
+ (grub_dl): New field 'base'.
+ (grub_dl_register_symbol): New argument isfunc. All users updated.
+ (GRUB_IA64_DL_TRAMP_ALIGN): New definition.
+ (GRUB_IA64_DL_TRAMP_SIZE): Likewise.
+ (GRUB_IA64_DL_GOT_ALIGN): Likewise.
+ (grub_ia64_dl_get_tramp_got_size): New proto.
+ (GRUB_ARCH_DL_TRAMP_ALIGN) [__ia64__]: Likewise
+ (GRUB_ARCH_DL_GOT_ALIGN) [__ia64__]: Likewise
+ (grub_arch_dl_get_tramp_got_size) [__ia64__]: Likewise
+ * include/grub/efi/api.h: Skip call wrappers on ia64.
+ * include/grub/efi/pe32.h (GRUB_PE32_MACHINE_IA64): New definition.
+ * include/grub/efi/time.h (GRUB_TICKS_PER_SECOND): Change to 1000.
+ * include/grub/elf.h (ELF_ST_INFO): New definition.
+ * include/grub/ia64/efi/kernel.h: New file.
+ * include/grub/ia64/efi/memory.h: Likewise.
+ * include/grub/ia64/efi/time.h: Likewise.
+ * include/grub/ia64/kernel.h: Likewise.
+ * include/grub/ia64/setjmp.h: Likewise (from glibc).
+ * include/grub/ia64/time.h: New file.
+ * include/grub/ia64/types.h: Likewise.
+ * include/grub/libgcc.h (__udivsi3, __umodsi3, __umoddi3, __udivdi3,
+ __moddi3, __divdi3, __divsi3, __modsi3, __ia64_trampoline):
+ New protos.
+ * include/grub/offsets.h (GRUB_KERNEL_IA64_EFI_PREFIX): New definition.
+ (GRUB_KERNEL_IA64_EFI_PREFIX_END): Likewise.
+ * include/grub/types.h (PRIxGRUB_ADDR): Likewise.
+ * util/grub-mkimage.c (image_target_desc): New field pe_target.
+ All users updated.
+ (EFI64_HEADER_SIZE): New definition. All users updated.
+ (image_targets): Add ia64-efi.
+ * util/grub-mkimagexx.c (relocate_symbols): New arguments jumpers and
+ jumpers_addr. All users updated.
+ Create function descriptors.
+ (count_funcs): New function.
+ (unaligned_uint32): New struct.
+ (MASK20): New definition.
+ (MASK19): Likewise.
+ (MASKF21): Likewise.
+ (add_value_to_slot_20b): New function.
+ (add_value_to_slot_21_real): Likewise.
+ (add_value_to_slot_21): Likewise.
+ (ia64_kernel_trampoline): New struct.
+ (nopm): New variable.
+ (jump): Likewise.
+ (make_trampoline): New function.
+ (relocate_addresses): Handle ia64.
+ (make_reloc_section): Likewise.
+ (load_image): Likewise.
+
+2011-05-15 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * grub-core/fs/btrfs.c (grub_btrfs_read_logical): Silence spurious
+ warning. Move variables before code while on it.
+
+2011-05-15 Vladimir Serbinenko <phcoder@gmail.com>
+
+ Fuloong support.
+
+ * configure.ac: Rename yeeloong platform to loongson. All users updated.
+ * grub-core/Makefile.core.def (fwstart_fuloong): New image.
+ * grub-core/boot/mips/loongson/fuloong.S: New file.
+ * grub-core/boot/mips/loongson/fwstart.S: Wait for CS5536 to come up.
+ Explicitly init CS5536.
+ [FULOONG]: Don't use serial until CS5536 is available.
+ Set GPIO based on dumps.
+ (serial_hw_init) [FULOONG]: Handle CS5536 parts.
+ [FULOONG]: Handle GPIO and memory controller differences.
+ Parse machine type in $a2.
+ * grub-core/boot/mips/startup_raw.S: Determine and save the
+ architecture.
+ * grub-core/bus/cs5536.c (gpiodump): Move to fwstart.S.
+ (grub_cs5536_init_geode): Remove gpio part. Conditionalise DIVIL
+ init on architecture type.
+ * grub-core/kern/mips/loongson/init.c (grub_machine_init): Init
+ SIS315E. Don't init at_keyboard on fuloong.
+ (grub_halt): Support Fuloong.
+ * grub-core/kern/mips/startup.S [LOONGSON]: Save $s7.
+ * grub-core/loader/mips/linux.c (LOONGSON_MACHTYPE): Removed.
+ (loongson_machtypes): New array.
+ (grub_cmd_linux) [GRUB_MACHINE_MIPS_LOONGSON]: Pass the right machine
+ type.
+ * grub-core/term/ns8250.c (serial_get_divisor): New parameter port and
+ config. All users updated. Handle CS5536 serial.
+ * grub-core/term/serial.c (grub_serial_register): Conditionalise
+ default port on machine type. Register serial as inactive.
+ * grub-core/video/sis315pro.c: New file.
+ * include/grub/cs5536.h (GRUB_CS5536_MSR_MAILBOX_CONFIG_ENABLED): New
+ definition.
+ (GRUB_CS5536_MSR_MAILBOX_CONFIG): Likewise.
+ (GRUB_CS5536_MSR_DIVIL_LEG_IO_UART1_COM1): Likewise.
+ (GRUB_CS5536_MSR_DIVIL_LEG_IO_UART2_COM3): Likewise.
+ (GRUB_CS5536_MSR_DIVIL_UART1_CONF): Likewise.
+ (GRUB_CS5536_MSR_DIVIL_UART2_CONF): Likewise.
+ * include/grub/mips/loongson.h (GRUB_CPU_LOONGSON_SHUTDOWN_GPIO): Rename
+ to ...
+ (GRUB_CPU_YEELOONG_SHUTDOWN_GPIO): ... this.
+ * include/grub/mips/loongson/kernel.h (GRUB_ARCH_MACHINE_YEELOONG): New
+ definition.
+ (GRUB_ARCH_MACHINE_FULOONG): Likewise.
+ (grub_arch_machine): New extern var.
+ * include/grub/mips/loongson/serial.h
+ (GRUB_MACHINE_SERIAL_DIVISOR_115200): Renamed to ...
+ (GRUB_MACHINE_SERIAL_PORT0_DIVISOR_115200): ... this.
+ (GRUB_MACHINE_SERIAL_PORT): Renamed to ...
+ (GRUB_MACHINE_SERIAL_PORT0): ... this.
+ (GRUB_MACHINE_SERIAL_PORT2_DIVISOR_115200): New definition.
+ (GRUB_MACHINE_SERIAL_PORT1): Likewise.
+ (GRUB_MACHINE_SERIAL_PORT2): Likewise.
+ (GRUB_MACHINE_SERIAL_PORTS): Include ports 1 and 2.
+ * include/grub/term.h (grub_term_register_input_inactive): New inline
+ function.
+ (grub_term_register_output_inactive): Likewise.
+ * include/grub/video.h (grub_video_driver_id): New value
+ GRUB_VIDEO_DRIVER_SIS315PRO.
+ * util/grub-mkimage.c (image_target_desc): Rename name to dirname.
+ New field "names". All users updated.
+ New field value IMAGE_FULOONG_FLASH.
+ (generate_image): USe separate fwstart hashes for yeeloong and fuloong.
+
+2011-05-14 Jordan Uggla <jordan.uggla@gmail.com>
+
+ * docs/grub.texi (Invoking grub-install): Fix additional outdated claims
+ and add some clarification.
+
+2011-05-14 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * util/grub.d/10_linux.in: Autoload gzio since it's needed on some
+ platforms if kernel is compressed.
+
+2011-05-14 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * grub-core/kern/mm.c (grub_memalign): Disable auto-unloadding of
+ unused modules since currently referrence counter isn't reliable and
+ there isn't much memory to recover there anyway.
+
+2011-05-14 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * grub-core/kern/dl.c (grub_dl_load_file): Decrease ref counter
+ rather than resetting it to allow modules to reference themselves
+ in init.
+
+2011-05-14 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * grub-core/kern/dl.c (grub_dl_unload): Don't decrease reference
+ counter on dependencies since grub_dl_unref already handles this.
+
+2011-05-14 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * grub-core/font/font_cmd.c (loadfont_command): Set grub_errno
+ on error if not already done.
+
+2011-05-14 Vladimir Serbinenko <phcoder@gmail.com>
+
+ Fix few potential memory misusage.
+
+ * grub-core/font/font.c (load_font_index): Don't free char_index to
+ avoid double free.
+ (grub_font_load): Zero-fill font at alloc for safety.
+ Close file on error.
+ (free_font): Free bmp_idx.
+
+2011-05-14 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * docs/grub.texi (Installation): Fix several outdated claims.
+
+2011-05-14 Vladimir Serbinenko <phcoder@gmail.com>
+
+ Handle module_license on windows.
+
+ * util/grub-pe2elf.c (MODLICENSE_SECTION): New definition. All following
+ sections shifted.
+ (insert_string): Make argument const char * instead of char *.
+ (write_section_data): Handle long section names.
+ Handle module_license.
+
+2011-05-14 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * grub-core/commands/menuentry.c (grub_cmd_menuentry): Correctly
+ handle class-free menuentries.
+ (grub_normal_add_menu_entry): Add a check to be sure.
+
+2011-05-14 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * grub-core/term/at_keyboard.c (set1_e0_mapping): Fix swap between
+ PgUp and PgDown.
+
+2011-05-13 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * configure.ac: Bump version to 1.99.
+
+2011-05-13 Vladimir Serbinenko <phcoder@gmail.com>
+
+ Give ATA device a bit more time on first try in order to allow disks
+ to spin up.
+
+ * grub-core/disk/ata.c (grub_atapi_identify): Use GRUB_ATA_TOUT_DEV_INIT
+ if dev->present is 1. Reset dev->present on failure.
+ (grub_ata_device_initialize): Set dev->present to 1.
+ * include/grub/ata.h (GRUB_ATA_TOUT_DEV_INIT): New value.
+ (grub_ata_device): New member 'present'.
+
+2011-05-13 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * util/grub-mkimage.c (generate_image): Update hash.
+
+2011-05-13 Vladimir Serbinenko <phcoder@gmail.com>
+
+ Flush caches on DMA memory.
+
+ * grub-core/kern/mips/cache.S (grub_arch_sync_dma_caches): New function.
+ * grub-core/bus/pci.c (grub_memalign_dma32): Flush caches.
+ (grub_dma_free): Likewise.
+ * include/grub/cache.h (grub_arch_sync_dma_caches): New declaration.
+
+2011-05-13 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * grub-core/boot/mips/yeeloong/fwstart.S: Add explicit set mips3
+ to avoid asm treating ld and sd as macros.
+
+2011-05-13 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * grub-core/boot/mips/startup_raw.S: Flush cache after loading
+ decompressor.
+
+2011-05-13 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * grub-core/boot/mips/startup_raw.S: Use jalr rather than bal to call
+ grub_decompress_core since later would fail if grub_decompress_core
+ is too far.
+
+2011-05-13 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * grub-core/kern/mips/dl.c (grub_arch_dl_relocate_symbols): Handle
+ R_MIPS_JALR since it's used by newer compiler.
+
+2011-05-10 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * util/grub.d/10_linux.in: Correctly handle the Linux in root.
+
+2011-05-09 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * grub-core/loader/efi/chainloader.c (grub_chainloader_unload): Set
+ file_path to 0 for surety.
+ (grub_chainloader_boot): Set exit_data to NULL.
+ Unset the loader once done.
+ (grub_cmd_chainloader): Fix confusing error message if file is empty.
+
+2011-05-09 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * grub-core/term/at_keyboard.c (fetch_key): Make a printf on
+ unknown key into a dprintf.
+
+2011-05-09 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * grub-core/kern/emu/hostdisk.c (linux_find_partition): Don't abort
+ on first non-existant partition.
+
+2011-05-09 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * grub-core/kern/emu/hostdisk.c (open_device): Set data->fd to -1 if
+ openning fails.
+ Reported by: Mark Korenberg.
+
+2011-05-09 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * grub-core/kern/emu/hostdisk.c (linux_find_partition): Prevent possible
+ overflow.
+
+2011-05-09 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * util/grub-mkimage.c (main): Explicitely flush and sync the output
+ before closing to ensure that it will be readable by grub-setup.
+
+2011-05-05 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * grub-core/loader/efi/appleloader.c (MAKE_PIWG_PATH): New macro.
+ (devpath_1): Use MAKE_PIWG_PATH.
+ (devpath_2): Likewise.
+ (devpath_3): Likewise.
+ (devpath_4): Likewise.
+ (devpath_5): Likewise.
+ (devpath_6): Likewise.
+
+ The appleldr.mod was checked that to be binary identical to previous
+ version.
+
+2011-05-05 Zach <mikezackles>
+
+ Support 2010 Macbooks.
+
+ * grub-core/loader/efi/appleloader.c (devpath_6): New variable.
+ (devs): Add devpath_6.
+
+2011-05-05 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * util/grub-mkpasswd-pbkdf2.c (main): Use /dev/urandom and not
+ /dev/random. /dev/urandom is good enough for our purposes (salting).
+
+2011-05-05 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * util/grub-mkrescue.in (process_input_dir): Include efiemu??.o.
+
+2011-05-05 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * grub-core/lib/legacy_parse.c (grub_legacy_parse): Correctly handle
+ hexadecimal.
+
+2011-05-05 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * grub-core/efiemu/main.c (grub_efiemu_load_file): Return grub_errno
+ and not 0 on failure.
+
+2011-05-03 Colin Watson <cjwatson@ubuntu.com>
+
+ * grub-core/fs/i386/pc/pxe.c (grub_pxefs_dir): Return
+ GRUB_ERR_BAD_FS rather than GRUB_ERR_IO if the disk is not a pxe
+ disk; otherwise grub_fs_probe will not fall back to the next
+ filesystem.
+ (grub_pxefs_open): Likewise, for consistency.
+ Reported and tested by: Ezekiel Grave.
+
+2011-05-03 Colin Watson <cjwatson@ubuntu.com>
+
+ * tests/partmap_test.in: Don't hardcode path to parted.
+ Reported by: Peter Hjalmarsson. Fixes Savannah bug #33150.
+
+2011-05-01 Colin Watson <cjwatson@ubuntu.com>
+
+ * docs/grub.texi (GRUB only offers a rescue shell): Suggest the use
+ of `ls' to find out which devices are available.
+
+2011-04-25 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * grub-core/loader/i386/linux.c (grub_linux_boot): Supply target rather
+ than source address for efi mmap buffer.
+
+2011-04-25 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * grub-core/partmap/amiga.c (amiga_partition_map_iterate): Fix a
+ wrong action on non-detecting the magic.
+
+2011-04-25 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * grub-core/gnulib/regex.c: Remove GRUB_MOD_LICENSE since it's
+ already supplied by another part of the module (fixes compilation on
+ FreeBSD).
+
+2011-04-25 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * grub-core/disk/mdraid_linux.c (grub_mdraid_detect): Make mdraid UUID
+ match the one used by mdadm.
+
+2011-04-21 Colin Watson <cjwatson@ubuntu.com>
+
+ * po/README: Add instructions for creating po/LINGUAS.
+
+2011-04-21 Colin Watson <cjwatson@ubuntu.com>
+
+ Add "SEE ALSO" sections to most man pages. Fixes Debian bug
+ #551428.
+
+ * docs/man/grub-editenv.h2m (SEE ALSO): New section.
+ * docs/man/grub-emu.h2m (SEE ALSO): Likewise.
+ * docs/man/grub-fstest.h2m (SEE ALSO): Likewise.
+ * docs/man/grub-install.h2m (SEE ALSO): Likewise.
+ * docs/man/grub-macho2img.h2m (SEE ALSO): Likewise.
+ * docs/man/grub-menulst2cfg.h2m (SEE ALSO): Likewise.
+ * docs/man/grub-mkconfig.h2m (SEE ALSO): Likewise.
+ * docs/man/grub-mkdevicemap.h2m (SEE ALSO): Likewise.
+ * docs/man/grub-mkfont.h2m (SEE ALSO): Likewise.
+ * docs/man/grub-mkimage.h2m (SEE ALSO): Likewise.
+ * docs/man/grub-mklayout.h2m (SEE ALSO): Likewise.
+ * docs/man/grub-mknetdir.h2m (SEE ALSO): Likewise.
+ * docs/man/grub-mkpasswd-pbkdf2.h2m (SEE ALSO): Likewise.
+ * docs/man/grub-mkrelpath.h2m (SEE ALSO): Likewise.
+ * docs/man/grub-mkrescue.h2m (SEE ALSO): Likewise.
+ * docs/man/grub-ofpathname.h2m (SEE ALSO): Likewise.
+ * docs/man/grub-pe2elf.h2m (SEE ALSO): Likewise.
+ * docs/man/grub-probe.h2m (SEE ALSO): Likewise.
+ * docs/man/grub-reboot.h2m (SEE ALSO): Likewise.
+ * docs/man/grub-script-check.h2m (SEE ALSO): Likewise.
+ * docs/man/grub-set-default.h2m (SEE ALSO): Likewise.
+ * docs/man/grub-setup.h2m (SEE ALSO): Likewise.
+
+2011-04-21 Colin Watson <cjwatson@ubuntu.com>
+
+ * grub-core/kern/emu/getroot.c
+ (grub_find_root_device_from_mountinfo): Remove non-virtual-device
+ test that was incorrectly reintroduced in r3214.
+ Reported by: Ian Dall. Fixes Savannah bug #33133.
+
+2011-04-21 Colin Watson <cjwatson@ubuntu.com>
+
+ Fix stack pointer handling in 16-bit relocator.
+
+ * grub-core/lib/i386/relocator16.S (grub_relocator16_start): Move
+ grub_relocator16_sp to %esp rather than %ss, and zero-extend it.
+ Fixes Ubuntu bug #683904.
+
+2011-04-20 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * configure.ac: Bump version to 1.99~rc2.
+
+2011-04-20 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * include/grub/dl.h [ASM_FILE]: Adapt for assembly.
+ * grub-core/lib/i386/setjmp.S: Add missing GRUB_MOD_LICENSE.
+ * grub-core/lib/x86_64/setjmp.S: Likewise.
+ * grub-core/lib/mips/setjmp.S: Likewise.
+ * grub-core/lib/powerpc/setjmp.S: Likewise.
+ * grub-core/lib/sparc64/setjmp.S: Likewise.
+
+2011-04-20 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * grub-core/lib/efi/datetime.c: Add missing GRUB_MOD_LICENSE.
+ * grub-core/lib/efi/datetime.c: Likewise.
+
+2011-04-19 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * grub-core/kern/emu/hostdisk.c (grub_util_biosdisk_flush):
+ New function.
+ (grub_util_biosdisk_close): Use grub_util_biosdisk_flush.
+ * include/grub/emu/hostdisk.h (grub_util_biosdisk_flush): New proto.
+ * util/grub-setup.c (setup): Use grub_util_biosdisk_flush.
+
+2011-04-19 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * grub-core/term/gfxterm.c (grub_gfxterm_fullscreen): Preserve previous
+ bitmap.
+ (grub_gfxterm_term_init): Likewise.
+
+2011-04-19 Vladimir Serbinenko <phcoder@gmail.com>
+
+ Take into account the decorations the computing menu entry width.
+
+ * grub-core/gfxmenu/widget-box.c (get_border_width): New function.
+ (grub_gfxmenu_create_box): Register get_border_width.
+ * grub-core/gfxmenu/gui_list.c (draw_menu): Use get_border_width
+ if available.
+ * include/grub/gfxwidgets.h (grub_gfxmenu_box): New member
+ get_border_width.
+
+2011-04-18 Endres Puschner <code@e7p.de>
+
+ * grub-core/gfxmenu/icon_manager.c (grub_gfxmenu_icon_manager_get_icon):
+ Don't skip first class.
+
+2011-04-18 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * grub-core/fs/btrfs.c (grub_btrfs_read_logical): Support huge
+ chunks.
+ * include/grub/err.h (grub_err_t): New enum value GRUB_ERR_BUG.
+
+2011-04-18 Vladimir Serbinenko <phcoder@gmail.com>
+
+ Complete 64-bit division support.
+
+ * grub-core/kern/misc.c (grub_divmod64): Rename to ...
+ (grub_divmod64_full): ... this. Support 64-bit divisor and reminder.
+ * include/grub/misc.h (grub_divmod64): Rename to ...
+ (grub_divmod64_full): ... this.
+ (grub_divmod64): New inline function.
+
+2011-04-18 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * util/grub-mkimage.c (generate_image): Add forgotten comma.
+
+2011-04-18 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * util/grub-mkimage.c (generate_image): Update fwstart.img hash after
+ performing the necessary test.
+
+2011-04-17 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * Makefile.am (multiboot.elf): Add -Wl,--build-id=none.
+ (kfreebsd.elf): Likewise.
+ (pc-chainloader.elf): Likewise.
+ (ntldr.elf): Likewise.
+
+2011-04-17 Vladimir Serbinenko <phcoder@gmail.com>
+
+ Identify RAID by its UUID rather than (guessed) name.
+
+ * grub-core/disk/raid.c (ascii2hex): New function.
+ (grub_raid_open): Accept mduuid/%s specification.
+ * grub-core/kern/emu/getroot.c (get_mdadm_name): Revamped into ...
+ (get_mdadm_uuid): ... this.
+ (grub_util_get_grub_dev): Use mduuid/%s if UUID is available.
+
+2011-04-16 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * grub-core/gfxmenu/gui_image.c (rescale_image): Don't attempt to scale
+ to negative size.
+
+2011-04-13 Colin Watson <cjwatson@ubuntu.com>
+
+ * util/grub.d/10_linux.in: Add rootflags=subvol=<name> if / is on a
+ btrfs subvolume.
+ * util/grub.d/20_linux_xen.in: Likewise.
+
+2011-04-13 Colin Watson <cjwatson@ubuntu.com>
+
+ Rewrite /proc/self/mountinfo handling to cope with bind-mounts and
+ move-mounts appearing out of order. Fixes Ubuntu bug #738345.
+
+ * grub-core/kern/emu/getroot.c (find_root_device_from_mountinfo):
+ Build a list of relevant visible mounts using the mnt_id and
+ parent_mnt_id fields, and then scan that list at the end.
+
+2011-04-12 Colin Watson <cjwatson@ubuntu.com>
+
+ * docs/grub.texi (normal): New section.
+ (normal_exit): New section.
+ (Embedded configuration): Add reference to normal.
+ (GRUB only offers a rescue shell): Likewise.
+ * docs/grub-dev.texi (Error Handling): Fix typo.
+
+2011-04-12 Colin Watson <cjwatson@ubuntu.com>
+
+ * NEWS: Drop obsolete entry about probe-only btrfs support.
+
+2011-04-12 Colin Watson <cjwatson@ubuntu.com>
+
+ * util/import_gcry.py: Fix typo.
+
+2011-04-11 Vladimir Serbinenko <phcoder@gmail.com>
+
+ * NEWS: Add btrfs support.
+
+2011-04-11 Vladimir Serbinenko <phcoder@gmail.com>
+2011-04-11 Colin Watson <cjwatson@ubuntu.com>
+
+ BtrFS support. Written by me (Vladimir) with important bugfixes and
+ even more important testing by Colin.
+
+ * Makefile.util.def (libgrubmods.a): Add crc.c and gzio.c
+ * grub-core/Makefile.core.def (btrfs): Add crc.c.
+ * grub-core/fs/btrfs.c: Stub replaced with real implementation.
+ * grub-core/io/gzio.c (grub_gzio): New fields mem_input_size,
+ mem_input_off and mem_input. All users updated to accept in-RAM input.
+ (gzio_seek): New function.
+ (test_zlib_header): Likewise.
+ (grub_gzio_read): Likewise.
+ (grub_zlib_decompress): Likewise.
+ * grub-core/kern/emu/getroot.c (grub_find_root_device_from_mountinfo):
+ Accept partial and non-virtual mounts.
+ (grub_guess_root_device): Do rescanning after device_from_mountinfo to
+ avoid receiving /dev/dm-X as device.
+ * grub-core/kern/emu/misc.c (grub_make_system_path_relative_to_its_root):
+ Handle bind and partial mounts.
+ * grub-core/lib/crc.c: New file.
+ * include/grub/deflate.h: Likewise.
+ * include/grub/emu/misc.h (grub_find_root_device_from_mountinfo): New
+ proto.
+ * include/grub/lib/crc.h: New file.
+
+2011-04-11 Vladimir Serbinenko <phcoder@gmail.com>
+
+ Implement automatic module license checking according to new GNU
+ guidelines.
+
+ * grub-core/kern/dl.c (grub_dl_check_license): New function.
+ (grub_dl_load_core): Use grub_dl_check_license.
+ * include/grub/dl.h (GRUB_MOD_SECTION): New macro.
+ (GRUB_MOD_LICENSE): Likewise.
+ (GRUB_MOD_DUAL_LICENSE): Likewise.
+ All modules updated.
+
+2011-04-11 Colin Watson <cjwatson@ubuntu.com>
+
+ * grub-core/fs/btrfs.c (grub_btrfs_fs) [GRUB_UTIL]: Set
+ reserved_first_sector to 1. btrfs reserves plenty of space for boot
+ loaders.
+ Reported by: Gene Cumm. Fixes Ubuntu bug #757446.
+
2011-04-11 Vladimir Serbinenko <phcoder@gmail.com>
* util/grub-fstest.c (cmd_cmp): Check that sizes match.
(grub_util_biosdisk_open): Don't apply ioctl on non-disk devices.
(open_device) Likewise.
(grub_util_biosdisk_close): Likewise.
- Reported by: Mark Korenberger.
+ Reported by: Mark Korenberg.
2011-04-10 Alexander Kurtz <kurtz.alex@googlemail.com>
-AUTOMAKE_OPTIONS = subdir-objects
+AUTOMAKE_OPTIONS = subdir-objects -Wno-portability
DEPDIR = .deps-util
SUBDIRS = grub-core/gnulib . grub-core po docs util/bash-completion.d
$(TARGET_CC) -o $@ $< -m32 -nostdlib -nostdinc -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\"
multiboot.elf: $(srcdir)/grub-core/tests/boot/kernel-i386.S
- $(TARGET_CC) -o $@ $< -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" -ffreestanding -nostdlib -nostdinc -DTARGET_MULTIBOOT=1 -Wl,-N -Wl,-Ttext,0x100000 -m32 -I$(srcdir)/include
+ $(TARGET_CC) -o $@ $< -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" -ffreestanding -nostdlib -nostdinc -DTARGET_MULTIBOOT=1 -Wl,--build-id=none -Wl,-N -Wl,-Ttext,0x100000 -m32 -I$(srcdir)/include
kfreebsd.elf: $(srcdir)/grub-core/tests/boot/kernel-i386.S
- $(TARGET_CC) -o $@ $< -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" -ffreestanding -nostdlib -nostdinc -Wl,-N -Wl,-Ttext,0x100000 -m32 -I$(srcdir)/include
+ $(TARGET_CC) -o $@ $< -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" -ffreestanding -nostdlib -nostdinc -Wl,--build-id=none -Wl,-N -Wl,-Ttext,0x100000 -m32 -I$(srcdir)/include
kfreebsd.aout: kfreebsd.elf
$(OBJCOPY) -O a.out-i386-linux $< $@ -R .note.gnu.build-id
pc-chainloader.elf: $(srcdir)/grub-core/tests/boot/kernel-8086.S
- $(TARGET_CC) -o $@ $< -DTARGET_CHAINLOADER=1 -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" -ffreestanding -nostdlib -nostdinc -Wl,-N -Wl,-Ttext,0x7c00 -m32
+ $(TARGET_CC) -o $@ $< -DTARGET_CHAINLOADER=1 -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" -ffreestanding -nostdlib -nostdinc -Wl,--build-id=none -Wl,-N -Wl,-Ttext,0x7c00 -m32
pc-chainloader.bin: pc-chainloader.elf
$(OBJCOPY) -O binary --strip-unneeded -R .note -R .comment -R .note.gnu.build-id -R .reginfo -R .rel.dyn $< $@;
ntldr.elf: $(srcdir)/grub-core/tests/boot/kernel-8086.S
- $(TARGET_CC) -o $@ $< -DTARGET_NTLDR=1 -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" -ffreestanding -nostdlib -nostdinc -Wl,-N -Wl,-Ttext,0 -m32
+ $(TARGET_CC) -o $@ $< -DTARGET_NTLDR=1 -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" -ffreestanding -nostdlib -nostdinc -Wl,--build-id=none -Wl,-N -Wl,-Ttext,0 -m32
ntldr.bin: ntldr.elf
$(OBJCOPY) -O binary --strip-unneeded -R .note -R .comment -R .note.gnu.build-id -R .reginfo -R .rel.dyn $< $@;
multiboot2.elf: $(srcdir)/grub-core/tests/boot/kernel-i386.S
- $(TARGET_CC) -o $@ $< -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" -ffreestanding -nostdlib -nostdinc -Wl,-N -Wl,-Ttext,0x100000 -m32 -I$(srcdir)/include -DTARGET_MULTIBOOT2=1
+ $(TARGET_CC) -o $@ $< -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" -ffreestanding -nostdlib -nostdinc -Wl,--build-id=none -Wl,-N -Wl,-Ttext,0x100000 -m32 -I$(srcdir)/include -DTARGET_MULTIBOOT2=1
kfreebsd.init.x86_64: $(srcdir)/grub-core/tests/boot/kfreebsd.init-x86_64.S
$(TARGET_CC) -o $@ $< -m64 -nostdlib -nostdinc -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" && freebsd-brandelf -t FreeBSD $@
common = grub-core/kern/command.c;
common = grub-core/kern/device.c;
common = grub-core/kern/disk.c;
- common = grub-core/kern/emu/getroot.c;
+ common = util/getroot.c;
+ common = util/raid.c;
common = grub-core/kern/emu/hostdisk.c;
common = grub-core/kern/emu/misc.c;
common = grub-core/kern/emu/mm.c;
common = grub-core/kern/list.c;
common = grub-core/kern/misc.c;
common = grub-core/kern/partition.c;
+ common = grub-core/lib/crypto.c;
+ common = grub-core/disk/luks.c;
+ common = grub-core/disk/geli.c;
+ common = grub-core/disk/cryptodisk.c;
+ common = grub-core/disk/AFSplitter.c;
+ common = grub-core/lib/pbkdf2.c;
+ common = grub-core/commands/extcmd.c;
+ common = grub-core/lib/arg.c;
};
library = {
name = libgrubmods.a;
- cflags = '$(CFLAGS_GCRY)';
- cppflags = '$(CPPFLAGS_GCRY)';
+ cflags = '$(CFLAGS_POSIX) -Wno-undef';
+ cppflags = '-I$(srcdir)/lib/posix_wrap -I$(top_srcdir)/grub-core/lib/minilzo -DMINILZO_HAVE_CONFIG_H';
common_nodist = grub_script.tab.c;
common_nodist = grub_script.yy.c;
common_nodist = grub_script.tab.h;
common = grub-core/commands/blocklist.c;
- common = grub-core/commands/extcmd.c;
+ common = grub-core/commands/testload.c;
common = grub-core/commands/ls.c;
common = grub-core/disk/dmraid_nvidia.c;
common = grub-core/disk/loopback.c;
common = grub-core/fs/jfs.c;
common = grub-core/fs/minix.c;
common = grub-core/fs/minix2.c;
+ common = grub-core/fs/minix3.c;
common = grub-core/fs/nilfs2.c;
common = grub-core/fs/ntfs.c;
common = grub-core/fs/ntfscomp.c;
common = grub-core/fs/reiserfs.c;
+ common = grub-core/fs/romfs.c;
common = grub-core/fs/sfs.c;
+ common = grub-core/fs/squash4.c;
common = grub-core/fs/tar.c;
common = grub-core/fs/udf.c;
common = grub-core/fs/ufs2.c;
common = grub-core/fs/zfs/zfs_lzjb.c;
common = grub-core/fs/zfs/zfs_sha256.c;
common = grub-core/fs/zfs/zfs_fletcher.c;
- common = grub-core/lib/arg.c;
- common = grub-core/lib/crypto.c;
common = grub-core/lib/envblk.c;
common = grub-core/lib/hexdump.c;
- common = grub-core/lib/libgcrypt-grub/cipher/sha512.c;
- common = grub-core/lib/libgcrypt-grub/cipher/crc.c;
common = grub-core/lib/LzFind.c;
common = grub-core/lib/LzmaEnc.c;
- common = grub-core/lib/pbkdf2.c;
+ common = grub-core/lib/crc.c;
+ common = grub-core/lib/adler32.c;
common = grub-core/normal/datetime.c;
common = grub-core/normal/misc.c;
common = grub-core/partmap/acorn.c;
common = grub-core/partmap/gpt.c;
common = grub-core/partmap/msdos.c;
common = grub-core/partmap/sun.c;
+ common = grub-core/partmap/dvh.c;
common = grub-core/partmap/sunpc.c;
common = grub-core/partmap/bsdlabel.c;
common = grub-core/script/function.c;
common = grub-core/script/main.c;
common = grub-core/script/script.c;
common = grub-core/script/argv.c;
+ common = grub-core/io/gzio.c;
+ common = grub-core/io/lzopio.c;
+ common = grub-core/kern/ia64/dl_helper.c;
+ common = grub-core/lib/minilzo/minilzo.c;
};
program = {
name = grub-bin2h;
common = util/bin2h.c;
ldadd = libgrubmods.a;
+ ldadd = libgrubgcry.a;
ldadd = libgrubkern.a;
ldadd = grub-core/gnulib/libgnu.a;
ldadd = '$(LIBINTL) $(LIBDEVMAPPER)';
- mansection = 1;
+ installdir = noinst;
};
program = {
extra_dist = util/grub-mkimagexx.c;
ldadd = libgrubmods.a;
+ ldadd = libgrubgcry.a;
ldadd = libgrubkern.a;
ldadd = grub-core/gnulib/libgnu.a;
ldadd = '$(LIBLZMA)';
common = util/grub-mkrelpath.c;
ldadd = libgrubmods.a;
+ ldadd = libgrubgcry.a;
ldadd = libgrubkern.a;
ldadd = grub-core/gnulib/libgnu.a;
- ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)';
+ ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)';
};
program = {
common = util/grub-script-check.c;
ldadd = libgrubmods.a;
+ ldadd = libgrubgcry.a;
ldadd = libgrubkern.a;
ldadd = grub-core/gnulib/libgnu.a;
ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)';
common = util/grub-editenv.c;
ldadd = libgrubmods.a;
+ ldadd = libgrubgcry.a;
ldadd = libgrubkern.a;
ldadd = grub-core/gnulib/libgnu.a;
ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)';
common = util/grub-mkpasswd-pbkdf2.c;
ldadd = libgrubmods.a;
+ ldadd = libgrubgcry.a;
ldadd = libgrubkern.a;
ldadd = grub-core/gnulib/libgnu.a;
ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)';
common = util/grub-pe2elf.c;
ldadd = libgrubmods.a;
+ ldadd = libgrubgcry.a;
ldadd = libgrubkern.a;
ldadd = grub-core/gnulib/libgnu.a;
ldadd = '$(LIBINTL)';
cppflags = '$(CPPFLAGS_GCRY)';
ldadd = libgrubmods.a;
+ ldadd = libgrubgcry.a;
ldadd = libgrubkern.a;
ldadd = grub-core/gnulib/libgnu.a;
- ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)';
+ ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)';
};
program = {
cflags = '$(freetype_cflags)';
ldadd = libgrubmods.a;
+ ldadd = libgrubgcry.a;
ldadd = libgrubkern.a;
ldadd = grub-core/gnulib/libgnu.a;
ldadd = '$(freetype_libs)';
sparc64_ieee1275 = util/ieee1275/devicemap.c;
ldadd = libgrubmods.a;
+ ldadd = libgrubgcry.a;
ldadd = libgrubkern.a;
ldadd = grub-core/gnulib/libgnu.a;
ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)';
common = util/grub-probe.c;
ldadd = libgrubmods.a;
+ ldadd = libgrubgcry.a;
ldadd = libgrubkern.a;
ldadd = grub-core/gnulib/libgnu.a;
ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)';
installdir = sbin;
mansection = 8;
common = util/grub-setup.c;
- common = util/raid.c;
common = util/lvm.c;
common = grub-core/lib/reed_solomon.c;
ldadd = libgrubmods.a;
ldadd = libgrubkern.a;
+ ldadd = libgrubgcry.a;
ldadd = grub-core/gnulib/libgnu.a;
ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)';
program = {
name = grub-ofpathname;
installdir = sbin;
+ mansection = 8;
ieee1275 = util/ieee1275/grub-ofpathname.c;
ieee1275 = util/ieee1275/ofpath.c;
ldadd = libgrubmods.a;
+ ldadd = libgrubgcry.a;
ldadd = libgrubkern.a;
ldadd = grub-core/gnulib/libgnu.a;
ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBGEOM)';
common = util/grub-mklayout.c;
ldadd = libgrubmods.a;
+ ldadd = libgrubgcry.a;
ldadd = libgrubkern.a;
ldadd = grub-core/gnulib/libgnu.a;
ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)';
x86 = util/grub-mkrescue.in;
powerpc_ieee1275 = util/powerpc/ieee1275/grub-mkrescue.in;
enable = i386_pc;
- enable = x86_efi;
+ enable = i386_efi;
+ enable = x86_64_efi;
enable = i386_qemu;
enable = i386_multiboot;
enable = i386_coreboot;
enable = powerpc_ieee1275;
};
+script = {
+ mansection = 1;
+ name = grub-mkstandalone;
+ common = util/grub-mkstandalone.in;
+};
+
script = {
mansection = 8;
installdir = sbin;
common = grub-core/tests/lib/test.c;
cflags = -Wno-format;
ldadd = libgrubmods.a;
+ ldadd = libgrubgcry.a;
ldadd = libgrubkern.a;
ldadd = grub-core/gnulib/libgnu.a;
ldadd = '$(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)';
common = grub-core/lib/i386/pc/vesa_modes_table.c;
ldadd = libgrubmods.a;
+ ldadd = libgrubgcry.a;
ldadd = libgrubkern.a;
ldadd = grub-core/gnulib/libgnu.a;
ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)';
* New `lsacpi' command.
-* Basic btrfs support (detection and UUID).
+* Btrfs support.
* New `--boot-directory' option to `grub-install', `grub-reboot', and
`grub-set-default', with clearer semantics than the previous
* 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.
dnl Check if the C compiler generates calls to `__enable_execute_stack()'.
AC_DEFUN([grub_CHECK_ENABLE_EXECUTE_STACK],[
AC_MSG_CHECKING([whether `$CC' generates calls to `__enable_execute_stack()'])
-AC_LANG_CONFTEST([[
+AC_LANG_CONFTEST([AC_LANG_SOURCE([[
void f (int (*p) (void));
void g (int i)
{
int nestedfunc (void) { return i; }
f (nestedfunc);
}
-]])
+]])])
if AC_TRY_COMMAND([${CC-cc} ${CFLAGS} -S conftest.c]) && test -s conftest.s; then
true
else
ssp_possible=yes]
AC_MSG_CHECKING([whether `$CC' accepts `-fstack-protector'])
# Is this a reliable test case?
-AC_LANG_CONFTEST([[void foo (void) { volatile char a[8]; a[3]; }]])
+AC_LANG_CONFTEST([AC_LANG_SOURCE([[
+void foo (void) { volatile char a[8]; a[3]; }
+]])])
[# `$CC -c -o ...' might not be portable. But, oh, well... Is calling
# `ac_compile' like this correct, after all?
if eval "$ac_compile -S -fstack-protector -o conftest.s" 2> /dev/null; then]
[# Smashing stack arg probe.
sap_possible=yes]
AC_MSG_CHECKING([whether `$CC' accepts `-mstack-arg-probe'])
-AC_LANG_CONFTEST([[void foo (void) { volatile char a[8]; a[3]; }]])
+AC_LANG_CONFTEST([AC_LANG_SOURCE([[
+void foo (void) { volatile char a[8]; a[3]; }
+]])])
[if eval "$ac_compile -S -mstack-arg-probe -o conftest.s" 2> /dev/null; then]
AC_MSG_RESULT([yes])
[# Should we clear up other files as well, having called `AC_LANG_CONFTEST'?
pie_possible=yes]
AC_MSG_CHECKING([whether `$CC' has `-fPIE' as default])
# Is this a reliable test case?
-AC_LANG_CONFTEST([[
+AC_LANG_CONFTEST([AC_LANG_SOURCE([[
#ifdef __PIE__
int main() {
return 0;
#else
#error NO __PIE__ DEFINED
#endif
-]])
+]])])
[# `$CC -c -o ...' might not be portable. But, oh, well... Is calling
# `ac_compile' like this correct, after all?
[ "${GRUB_CONTRIB}" = grub-core/contrib ] || ln -s ../contrib grub-core/contrib
fi
-UTIL_DEFS=Makefile.util.def
+UTIL_DEFS='Makefile.util.def Makefile.utilgcry.def'
CORE_DEFS='grub-core/Makefile.core.def grub-core/Makefile.gcry.def'
for extra in contrib/*/Makefile.util.def; do
if COND_i386_ieee1275
CFLAGS_PLATFORM += -mrtd -mregparm=3
endif
-if COND_mips_yeeloong
+if COND_mips_loongson
CFLAGS_PLATFORM += -mexplicit-relocs
CPPFLAGS_PLATFORM = -DUSE_ASCII_FAILBACK
- CCASFLAGS_PLATFORM = -march=mips3
endif
if COND_mips
CFLAGS_PLATFORM += -mflush-func=grub_cpu_flush_cache
+ CCASFLAGS_PLATFORM = -march=mips3
endif
if COND_sparc64_ieee1275
CFLAGS_PLATFORM += -mno-app-regs
#define NEED_ENABLE_EXECUTE_STACK @NEED_ENABLE_EXECUTE_STACK@
/* Define to 1 if GCC generates calls to __register_frame_info(). */
#define NEED_REGISTER_FRAME_INFO @NEED_REGISTER_FRAME_INFO@
+/* Define to 1 to enable disk cache statistics. */
+#define DISK_CACHE_STATS @DISK_CACHE_STATS@
#if defined(__i386__)
#define NESTED_FUNC_ATTR __attribute__ ((__regparm__ (1)))
dnl (such as TARGET_CC, TARGET_CFLAGS, etc.) are used for the target
dnl type.
-AC_INIT([GRUB],[1.99~rc1],[bug-grub@gnu.org])
+AC_INIT([GRUB],[1.99],[bug-grub@gnu.org])
AC_CONFIG_AUX_DIR([build-aux])
amd64) target_cpu=x86_64 ;;
sparc) target_cpu=sparc64 ;;
mipsel|mips64el)
- target_cpu=mips;
+ target_cpu=mipsel;
machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_CPU_MIPSEL=1";
;;
mips|mips64)
powerpc-*) platform=ieee1275 ;;
powerpc64-*) platform=ieee1275 ;;
sparc64-*) platform=ieee1275 ;;
- mips-*) platform=yeeloong ;;
+ mipsel-*) platform=loongson ;;
+ mips-*) platform=arc ;;
+ ia64-*) platform=efi ;;
*) AC_MSG_ERROR([unsupported CPU: "$target_cpu"]) ;;
esac
else
i386-qemu) ;;
powerpc-ieee1275) ;;
sparc64-ieee1275) ;;
- mips-qemu-mips) ;;
- mips-yeeloong) ;;
+ ia64-efi) ;;
+ mips-qemu_mips) ;;
+ mips-qemu-mips) platform=qemu_mips;;
+ mips-arc) ;;
+ mipsel-qemu_mips) ;;
+ mipsel-qemu-mips) platform=qemu_mips;;
+ mipsel-yeeloong) platform=loongson ;;
+ mipsel-fuloong) platform=loongson ;;
+ mipsel-loongson) ;;
*-emu) ;;
*) AC_MSG_ERROR([platform "$platform" is not supported for target CPU "$target_cpu"]) ;;
esac
qemu) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_QEMU=1" ;;
pc) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_PCBIOS=1" ;;
emu) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_EMU=1" ;;
- yeeloong) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_MIPS_YEELOONG=1 -DGRUB_MACHINE_MIPS_BONITO=1" ;;
- qemu-mips) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_MIPS_QEMU_MIPS=1 -DGRUB_MACHINE_MIPS_BONITO=1" ;;
+ loongson) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_MIPS_LOONGSON=1 -DGRUB_MACHINE_MIPS_BONITO=1" ;;
+ qemu_mips) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_MIPS_QEMU_MIPS=1 -DGRUB_MACHINE_MIPS_BONITO=1" ;;
+ arc) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_ARC=1" ;;
esac
case "$target_cpu" in
- mips) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_MIPS=1" ;;
+ mips |mipsel) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_MIPS=1" ;;
sparc64) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_SPARC64=1" ;;
esac
-machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE=`echo ${target_cpu}_$platform | sed y,abcdefghijklmnopqrstuvwxyz,ABCDEFGHIJKLMNOPQRSTUVWXYZ,`"
+if test x${target_cpu} = xmipsel ; then
+ machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE=`echo mips_$platform | sed y,abcdefghijklmnopqrstuvwxyz,ABCDEFGHIJKLMNOPQRSTUVWXYZ,`"
+else
+ machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE=`echo ${target_cpu}_$platform | sed y,abcdefghijklmnopqrstuvwxyz,ABCDEFGHIJKLMNOPQRSTUVWXYZ,`"
+fi
HOST_CPPFLAGS="$HOST_CPPFLAGS $machine_CPPFLAGS"
TARGET_CPPFLAGS="$TARGET_CPPFLAGS $machine_CPPFLAGS"
done
done
-if test "x$FONT_SOURCE" = x && ( test "x$platform" = xqemu || test "x$platform" = xyeeloong ); then
- AC_MSG_ERROR([qemu and yeeloong ports need unifont])
+if test "x$FONT_SOURCE" = x && ( test "x$platform" = xqemu || test "x$platform" = xloongson ); then
+ AC_MSG_ERROR([qemu and loongson ports need unifont])
fi
AC_SUBST([FONT_SOURCE])
TARGET_CFLAGS="$TARGET_CFLAGS -fno-dwarf2-cfi-asm"
fi
-if test "${target_cpu}-${platform}" = mips-yeeloong; then
- AC_CACHE_CHECK([whether -march=loongson2f works], [grub_cv_cc_march_loongson2f], [
- SAVE_CFLAGS="$CFLAGS"
- CFLAGS="$CFLAGS -march=loongson2f"
- AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])],
- [grub_cv_cc_march_loongson2f=yes],
- [grub_cv_cc_march_loongson2f=no])
- CFLAGS="$SAVE_CFLAGS"
- ])
-
- if test "x$grub_cv_cc_march_loongson2f" = xyes; then
- TARGET_CFLAGS="$TARGET_CFLAGS -march=loongson2f"
- else
- TARGET_CFLAGS="$TARGET_CFLAGS -march=mips3"
- fi
-fi
-
grub_apple_target_cc
if test x$grub_cv_apple_target_cc = xyes ; then
TARGET_CPPFLAGS="$TARGET_CPPFLAGS -DAPPLE_CC=1"
fi
# Check for libgcc symbols
-AC_CHECK_FUNCS(__bswapsi2 __bswapdi2 __ashldi3 __ashrdi3 __lshrdi3 __trampoline_setup __ucmpdi2 _restgpr_14_x)
+AC_CHECK_FUNCS(__bswapsi2 __bswapdi2 __ashldi3 __ashrdi3 __lshrdi3 __trampoline_setup __ucmpdi2 _restgpr_14_x __ia64_trampoline __udivsi3 __umoddi3 __udivdi3 __divsi3 __modsi3 __umodsi3 __moddi3 __divdi3 __ctzdi2 __ctzsi2)
if test "x$TARGET_APPLE_CC" = x1 ; then
CFLAGS="$TARGET_CFLAGS -nostdlib"
[AC_DEFINE([MM_DEBUG], [1],
[Define to 1 if you enable memory manager debugging.])])
+AC_ARG_ENABLE([cache-stats],
+ AS_HELP_STRING([--enable-cache-stats],
+ [enable disk cache statistics collection]))
+
+if test x$enable_cache_stats = xyes; then
+ DISK_CACHE_STATS=1
+else
+ DISK_CACHE_STATS=0
+fi
+AC_SUBST([DISK_CACHE_STATS])
+
AC_ARG_ENABLE([grub-emu-usb],
[AS_HELP_STRING([--enable-grub-emu-usb],
[build and install the `grub-emu' debugging utility with USB support (default=guessed)])])
else
enable_grub_mkfont=no
fi
+if test x"$enable_grub_mkfont" = xno && test "x$platform" = xloongson; then
+ AC_MSG_ERROR([loongson port needs grub-mkfont])
+fi
AC_SUBST([enable_grub_mkfont])
AC_SUBST([freetype_cflags])
AC_SUBST([freetype_libs])
AM_CONDITIONAL([COND_emu], [test x$platform = xemu])
AM_CONDITIONAL([COND_i386_pc], [test x$target_cpu = xi386 -a x$platform = xpc])
AM_CONDITIONAL([COND_i386_efi], [test x$target_cpu = xi386 -a x$platform = xefi])
+AM_CONDITIONAL([COND_ia64_efi], [test x$target_cpu = xia64 -a x$platform = xefi])
AM_CONDITIONAL([COND_i386_qemu], [test x$target_cpu = xi386 -a x$platform = xqemu])
AM_CONDITIONAL([COND_i386_ieee1275], [test x$target_cpu = xi386 -a x$platform = xieee1275])
AM_CONDITIONAL([COND_i386_coreboot], [test x$target_cpu = xi386 -a x$platform = xcoreboot])
AM_CONDITIONAL([COND_i386_multiboot], [test x$target_cpu = xi386 -a x$platform = xmultiboot])
AM_CONDITIONAL([COND_x86_64_efi], [test x$target_cpu = xx86_64 -a x$platform = xefi])
-AM_CONDITIONAL([COND_mips_yeeloong], [test x$target_cpu = xmips -a x$platform = xyeeloong])
-AM_CONDITIONAL([COND_mips_qemu_mips], [test x$target_cpu = xmips -a x$platform = xqemu_mips])
+AM_CONDITIONAL([COND_mips_loongson], [test x$target_cpu = xmipsel -a x$platform = xloongson])
+AM_CONDITIONAL([COND_mips_qemu_mips], [test "(" x$target_cpu = xmips -o x$target_cpu = xmipsel ")" -a x$platform = xqemu_mips])
+AM_CONDITIONAL([COND_mips_arc], [test x$target_cpu = xmips -a x$platform = xarc])
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_mips], [test x$target_cpu = xmips -o x$target_cpu = xmipsel])
AM_CONDITIONAL([COND_HOST_HURD], [test x$host_kernel = xhurd])
AM_CONDITIONAL([COND_HOST_LINUX], [test x$host_kernel = xlinux])
AM_CONDITIONAL([COND_GRUB_PE2ELF], [test x$TARGET_OBJ2ELF != x])
AM_CONDITIONAL([COND_APPLE_CC], [test x$TARGET_APPLE_CC = x1])
AM_CONDITIONAL([COND_ENABLE_EFIEMU], [test x$enable_efiemu = xyes])
+AM_CONDITIONAL([COND_ENABLE_CACHE_STATS], [test x$DISK_CACHE_STATS = x1])
AM_CONDITIONAL([COND_HAVE_ASM_USCORE], [test x$HAVE_ASM_USCORE = x1])
AM_CONDITIONAL([COND_CYGWIN], [test x$host_os = xcygwin])
# Output files.
+cpudir="${target_cpu}"
+if test x${cpudir} = xmipsel; then
+ cpudir=mips;
+fi
grub_CHECK_LINK_DIR
if test x"$link_dir" = xyes ; then
- AC_CONFIG_LINKS([include/grub/cpu:include/grub/$target_cpu])
+ AC_CONFIG_LINKS([include/grub/cpu:include/grub/$cpudir])
if test "$platform" != emu ; then
- AC_CONFIG_LINKS([include/grub/machine:include/grub/$target_cpu/$platform])
+ AC_CONFIG_LINKS([include/grub/machine:include/grub/$cpudir/$platform])
fi
else
mkdir -p include/grub 2>/dev/null
rm -rf include/grub/cpu
- cp -rp $srcdir/include/grub/$target_cpu include/grub/cpu 2>/dev/null
+ cp -rp $srcdir/include/grub/$cpudir include/grub/cpu 2>/dev/null
if test "$platform" != emu ; then
rm -rf include/grub/machine
- cp -rp $srcdir/include/grub/$target_cpu/$platform include/grub/machine 2>/dev/null
+ cp -rp $srcdir/include/grub/$cpudir/$platform include/grub/machine 2>/dev/null
fi
fi
else
echo With memory debugging: No
fi
+if [ x"$enable_cache_stats" = xyes ]; then
+echo With disk cache statistics: Yes
+else
+echo With disk cache statistics: No
+fi
if [ x"$efiemu_excuse" = x ]; then
echo efiemu runtime: Yes
else
@chapter Error Handling
Error handling in GRUB 2 is based on exception handling model. As C language
-doesn't direcly support exceptions, exception handling behavior is emulated
+doesn't directly support exceptions, exception handling behavior is emulated
in software.
When exception is raised, function must return to calling function. If calling
from the source tarball, or as a package for your OS.
After you have done that, you need to install the boot loader on a
-drive (floppy or hard disk). There are two ways of doing that - either
-using the utility @command{grub-install} (@pxref{Invoking
-grub-install}) on a UNIX-like OS, or by running GRUB itself from a
-floppy. These are quite similar, however the utility might probe a
-wrong BIOS drive, so you should be careful.
-
-Also, if you install GRUB on a UNIX-like OS, please make sure that you
-have an emergency boot disk ready, so that you can rescue your computer
-if, by any chance, your hard drive becomes unusable (unbootable).
+drive (floppy or hard disk) by using the utility
+@command{grub-install} (@pxref{Invoking grub-install}) on a UNIX-like OS.
GRUB comes with boot images, which are normally put in the directory
-@file{/usr/lib/grub/i386-pc}. Hereafter, the directory where GRUB images are
-initially placed (normally @file{/usr/lib/grub/i386-pc}) will be
+@file{/usr/lib/grub/<cpu>-<platform>} (for BIOS-based machines
+@file{/usr/lib/grub/i386-pc}). Hereafter, the directory where GRUB images are
+initially placed (normally @file{/usr/lib/grub/<cpu>-<platform>}) will be
called the @dfn{image directory}, and the directory where the boot
-loader needs to find them (usually @file{/boot/grub}) will be called
+loader needs to find them (usually @file{/boot}) will be called
the @dfn{boot directory}.
@menu
@node Installing GRUB using grub-install
@section Installing GRUB using grub-install
-@strong{Caution:} This procedure is definitely less safe, because
-there are several ways in which your computer can become
-unbootable. For example, most operating systems don't tell GRUB how to
-map BIOS drives to OS devices correctly---GRUB merely @dfn{guesses}
-the mapping. This will succeed in most cases, but not
-always. Therefore, GRUB provides you with a map file called the
-@dfn{device map}, which you must fix if it is wrong. @xref{Device
-map}, for more details.
-
For information on where GRUB should be installed on PC BIOS platforms,
@pxref{BIOS installation}.
-If you still do want to install GRUB under a UNIX-like OS (such
+In order to install GRUB under a UNIX-like OS (such
as @sc{gnu}), invoke the program @command{grub-install} (@pxref{Invoking
grub-install}) as the superuser (@dfn{root}).
The usage is basically very simple. You only need to specify one
argument to the program, namely, where to install the boot loader. The
-argument can be either a device file (like @samp{/dev/hda}) or a
-partition specified in GRUB's notation. For example, under Linux the
-following will install GRUB into the MBR of the first IDE disk:
+argument has to be either a device file (like @samp{/dev/hda}).
+For example, under Linux the following will install GRUB into the MBR
+of the first IDE disk:
@example
# @kbd{grub-install /dev/hda}
# @kbd{grub-install /dev/hd0}
@end example
-But all the above examples assume that GRUB should use images under
-the root directory. If you want GRUB to use images under a directory
-other than the root directory, you need to specify the option
-@option{--root-directory}. The typical usage is that you create a GRUB
+But all the above examples assume that GRUB should put images under
+the @file{/boot} directory. If you want GRUB to put images under a directory
+other than @file{/boot}, you need to specify the option
+@option{--boot-directory}. The typical usage is that you create a GRUB
boot floppy with a filesystem. Here is an example:
@example
@group
# @kbd{mke2fs /dev/fd0}
# @kbd{mount -t ext2 /dev/fd0 /mnt}
-# @kbd{grub-install --root-directory=/mnt fd0}
+# @kbd{mkdir /mnt/boot}
+# @kbd{grub-install --boot-directory=/mnt/boot /dev/fd0}
# @kbd{umount /mnt}
@end group
@end example
-Another example is when you have a separate boot partition
-which is mounted at @file{/boot}. Since GRUB is a boot loader, it
-doesn't know anything about mountpoints at all. Thus, you need to run
-@command{grub-install} like this:
-
-@example
-# @kbd{grub-install --root-directory=/boot /dev/hda}
-@end example
-
-By the way, as noted above, it is quite difficult to guess BIOS drives
-correctly under a UNIX-like OS. Thus, @command{grub-install} will prompt
-you to check if it could really guess the correct mappings, after the
-installation. The format is defined in @ref{Device map}. Please be
-quite careful. If the output is wrong, it is unlikely that your
-computer will be able to boot with no problem.
-
Some BIOSes have a bug of exposing the first partition of a USB drive as a
floppy instead of exposing the USB drive as a hard disk (they call it
``USB-FDD'' boot). In such cases, you need to install like this:
@item GRUB_CMDLINE_XEN
@itemx GRUB_CMDLINE_XEN_DEFAULT
-As @samp{GRUB_CMDLINE_LINUX} and @samp{GRUB_CMDLINE_LINUX_DEFAULT}, but for
-Linux and Xen.
+The values of these options are appended to the values of
+@samp{GRUB_CMDLINE_LINUX} and @samp{GRUB_CMDLINE_LINUX_DEFAULT} for Linux
+and Xen menu entries.
+
+@item GRUB_CMDLINE_LINUX_XEN_REPLACE
+@item GRUB_CMDLINE_LINUX_XEN_REPLACE_DEFAULT
+The values of these options replace the values of @samp{GRUB_CMDLINE_LINUX}
+and @samp{GRUB_CMDLINE_LINUX_DEFAULT} for Linux and Xen menu entries.
@item GRUB_DISABLE_LINUX_UUID
Normally, @command{grub-mkconfig} will generate menu entries that use
Set the resolution used on the @samp{gfxterm} graphical terminal. Note that
you can only use modes which your graphics card supports via VESA BIOS
Extensions (VBE), so for example native LCD panel resolutions may not be
-available. The default is @samp{640x480}. @xref{gfxmode}.
+available. The default is @samp{auto}, which tries to select a preferred
+resolution. @xref{gfxmode}.
@item GRUB_BACKGROUND
Set a background image for use with the @samp{gfxterm} graphical terminal.
@command{grub-mkimage}.
After the embedded configuration file (if any) is executed, GRUB will load
-the @samp{normal} module, which will then read the real configuration file
-from @file{$prefix/grub.cfg}. By this point, the @code{root} variable will
-also have been set to the root device name. For example, @code{prefix}
-might be set to @samp{(hd0,1)/boot/grub}, and @code{root} might be set to
-@samp{hd0,1}. Thus, in most cases, the embedded configuration file only
-needs to set the @code{prefix} and @code{root} variables, and then drop
-through to GRUB's normal processing. A typical example of this might look
-like this:
+the @samp{normal} module (@pxref{normal}), which will then read the real
+configuration file from @file{$prefix/grub.cfg}. By this point, the
+@code{root} variable will also have been set to the root device name. For
+example, @code{prefix} might be set to @samp{(hd0,1)/boot/grub}, and
+@code{root} might be set to @samp{hd0,1}. Thus, in most cases, the embedded
+configuration file only needs to set the @code{prefix} and @code{root}
+variables, and then drop through to GRUB's normal processing. A typical
+example of this might look like this:
@example
@group
* load_env:: Load variables from environment block
* loopback:: Make a device from a filesystem image
* ls:: List devices or files
+* normal:: Enter normal mode
+* normal_exit:: Exit from normal mode
* parttool:: Modify partition table entries
* password:: Set a clear-text password
* password_pbkdf2:: Set a hashed password
@end deffn
+@node normal
+@subsection normal
+
+@deffn Command normal [file]
+Enter normal mode and display the GRUB menu.
+
+In normal mode, commands, filesystem modules, and cryptography modules are
+automatically loaded, and the full GRUB script parser is available. Other
+modules may be explicitly loaded using @command{insmod} (@pxref{insmod}).
+
+If a @var{file} is given, then commands will be read from that file.
+Otherwise, they will be read from @file{$prefix/grub.cfg} if it exists.
+
+@command{normal} may be called from within normal mode, creating a nested
+environment. It is more usual to use @command{configfile}
+(@pxref{configfile}) for this.
+@end deffn
+
+
+@node normal_exit
+@subsection normal_exit
+
+@deffn Command normal_exit
+Exit normal mode (@pxref{normal}). If this instance of normal mode was not
+nested within another one, then return to rescue mode.
+@end deffn
+
+
@node parttool
@subsection parttool
@item @tab BIOS @tab Coreboot
@item BIOS chainloading @tab yes @tab no (1)
@item NTLDR @tab yes @tab no (1)
+@item Freedos @tab yes @tab no (1)
@item FreeBSD bootloader @tab yes @tab crashes (1)
@item 32-bit kFreeBSD @tab yes @tab crashes (2,6)
@item 64-bit kFreeBSD @tab yes @tab crashes (2,6)
@item @tab Multiboot @tab Qemu
@item BIOS chainloading @tab no (1) @tab no (1)
@item NTLDR @tab no (1) @tab no (1)
+@item FreeDOS @tab no (1) @tab no (1)
@item FreeBSD bootloader @tab crashes (1) @tab crashes (1)
@item 32-bit kFreeBSD @tab crashes (6) @tab crashes (6)
@item 64-bit kFreeBSD @tab crashes (6) @tab crashes (6)
@item @tab 32-bit EFI @tab 64-bit EFI
@item BIOS chainloading @tab no (1) @tab no (1)
@item NTLDR @tab no (1) @tab no (1)
+@item FreeDOS @tab no (1) @tab no (1)
@item FreeBSD bootloader @tab crashes (1) @tab crashes (1)
@item 32-bit kFreeBSD @tab headless @tab headless
@item 64-bit kFreeBSD @tab headless @tab headless
@item @tab IEEE1275
@item BIOS chainloading @tab no (1)
@item NTLDR @tab no (1)
+@item FreeDOS @tab no (1)
@item FreeBSD bootloader @tab crashes (1)
@item 32-bit kFreeBSD @tab crashes (6)
@item 64-bit kFreeBSD @tab crashes (6)
environment variable to a value set in the core image by
@command{grub-install}, setting the @samp{root} variable to match, loading
the @samp{normal} module from the prefix, and running the @samp{normal}
-command. This command is responsible for reading
+command (@pxref{normal}). This command is responsible for reading
@file{/boot/grub/grub.cfg}, running the menu, and doing all the useful
things GRUB is supposed to do.
@group
# Inspect the current prefix (and other preset variables):
set
+# Find out which devices are available:
+ls
# Set to the correct value, which might be something like this:
set prefix=(hd0,1)/grub
set root=(hd0,1)
@item --version
Print the version number of GRUB and exit.
-@item --root-directory=@var{dir}
-Install GRUB images under the directory @var{dir} instead of the root
-directory. This option is useful when you want to install GRUB into a
-separate partition or a removable disk. Here is an example in which
-you have a separate @dfn{boot} partition which is mounted on
-@file{/boot}:
+@item --boot-directory=@var{dir}
+Install GRUB images under the directory @file{@var{dir}/grub/}
+This option is useful when you want to install GRUB into a
+separate partition or a removable disk.
+If this option is not specified then it defaults to @file{/boot}, so
+
+@example
+@kbd{grub-install /dev/sda}
+@end example
+
+is equivalent to
+
+@example
+@kbd{grub-install --boot-directory=/boot/ /dev/sda}
+@end example
+
+Here is an example in which you have a separate @dfn{boot} partition which is
+mounted on
+@file{/mnt/boot}:
@example
-@kbd{grub-install --root-directory=/boot hd0}
+@kbd{grub-install --boot-directory=/mnt/boot /dev/sdb}
@end example
@item --recheck
@end quotation
GRUB is available from the GNU alpha archive site
-@uref{ftp://alpha.gnu.org/gnu/grub} or any of its mirrors. The file
+@uref{ftp://ftp.gnu.org/gnu/grub} or any of its mirrors. The file
will be named grub-version.tar.gz. The current version is
@value{VERSION}, so the file you should grab is:
-@uref{ftp://alpha.gnu.org/gnu/grub/grub-@value{VERSION}.tar.gz}
+@uref{ftp://ftp.gnu.org/gnu/grub/grub-@value{VERSION}.tar.gz}
To unbundle GRUB use the instruction:
+++ /dev/null
-[NAME]
-grub-bin2h \- convert a binary file to a C header
[NAME]
grub-editenv \- edit GRUB environment block
+[SEE ALSO]
+.BR grub-reboot (8),
+.BR grub-set-default (8)
[NAME]
grub-emu \- GRUB emulator
+[SEE ALSO]
+If you are trying to install GRUB, then you should use
+.BR grub-install (8)
+rather than this program.
[NAME]
grub-fstest \- debug tool for GRUB filesystem drivers
+[SEE ALSO]
+.BR grub-probe (8)
[NAME]
grub-install \- install GRUB to a device
+[SEE ALSO]
+.BR grub-mkconfig (8),
+.BR grub-mkimage (1),
+.BR grub-setup (8),
+.BR grub-mkrescue (1)
[NAME]
grub-macho2img \- convert Mach-O to raw image
+[SEE ALSO]
+.BR grub-mkimage (1)
[NAME]
grub-menulst2cfg \- transform legacy menu.lst into grub.cfg
-
+[SEE ALSO]
+.BR grub-mkconfig (8)
[NAME]
grub-mkconfig \- generate a GRUB configuration file
+[SEE ALSO]
+.BR grub-install (8)
[NAME]
grub-mkdevicemap \- generate a GRUB device map file automatically
+[SEE ALSO]
+.BR grub-install (8)
[NAME]
grub-mkfont \- make GRUB font files
+[SEE ALSO]
+.BR grub-mkconfig (8)
[NAME]
grub-mkimage \- make a bootable image of GRUB
+[SEE ALSO]
+.BR grub-install (8),
+.BR grub-setup (8),
+.BR grub-mkrescue (1),
+.BR grub-mknetdir (8)
[NAME]
grub-mklayout \- generate a GRUB keyboard layout file
+[DESCRIPTION]
+grub-mklayout processes a keyboard layout description in
+.BR keymaps (5)
+format into a format that can be used by GRUB's
+.B keymap
+command.
+[SEE ALSO]
+.BR grub-mkconfig (8)
[NAME]
grub-mknetdir \- prepare a GRUB netboot directory.
+[SEE ALSO]
+.BR grub-mkimage (1)
[NAME]
grub-mkpasswd-pbkdf2 \- generate hashed password for GRUB
+[SEE ALSO]
+.BR grub-mkconfig (8)
[NAME]
grub-mkrelpath \- make a system path relative to its root
+[SEE ALSO]
+.BR grub-probe (8)
[NAME]
grub-mkrescue \- make a GRUB rescue image
+[SEE ALSO]
+.BR grub-mkimage (1)
--- /dev/null
+[NAME]
+grub-mkstandalone \- make a memdisk-based GRUB image
+[SEE ALSO]
+.BR grub-mkimage (1)
[NAME]
grub-ofpathname \- find OpenBOOT path for a device
+[SEE ALSO]
+.BR grub-probe (8)
[NAME]
grub-pe2elf \- convert PE image to ELF
+[SEE ALSO]
+.BR grub-mkimage (1)
[NAME]
grub-probe \- probe device information for GRUB
+[SEE ALSO]
+.BR grub-fstest (1)
[NAME]
grub-reboot \- set the default boot entry for GRUB, for the next boot only
+[SEE ALSO]
+.BR grub-set-default (8),
+.BR grub-editenv (1)
[NAME]
grub-script-check \- check grub.cfg for syntax errors
+[SEE ALSO]
+.BR grub-mkconfig (8)
[NAME]
grub-set-default \- set the saved default boot entry for GRUB
+[SEE ALSO]
+.BR grub-reboot (8),
+.BR grub-editenv (1)
[NAME]
grub-setup \- set up a device to boot using GRUB
+[SEE ALSO]
+.BR grub-install (8),
+.BR grub-mkimage (1),
+.BR grub-mkrescue (1)
GRUB_PLATFORMS = [ "emu", "i386_pc", "i386_efi", "i386_qemu", "i386_coreboot",
"i386_multiboot", "i386_ieee1275", "x86_64_efi",
- "mips_yeeloong", "sparc64_ieee1275",
- "powerpc_ieee1275" ]
+ "mips_loongson", "sparc64_ieee1275",
+ "powerpc_ieee1275", "mips_arc", "ia64_efi",
+ "mips_qemu_mips" ]
GROUPS = {}
GROUPS["i386"] = [ "i386_pc", "i386_efi", "i386_qemu", "i386_coreboot", "i386_multiboot", "i386_ieee1275" ]
GROUPS["x86_64"] = [ "x86_64_efi" ]
GROUPS["x86"] = GROUPS["i386"] + GROUPS["x86_64"]
-GROUPS["mips"] = [ "mips_yeeloong" ]
+GROUPS["mips"] = [ "mips_loongson", "mips_qemu_mips", "mips_arc" ]
GROUPS["sparc64"] = [ "sparc64_ieee1275" ]
GROUPS["powerpc"] = [ "powerpc_ieee1275" ]
# Groups based on firmware
-GROUPS["x86_efi"] = [ "i386_efi", "x86_64_efi" ]
+GROUPS["efi"] = [ "i386_efi", "x86_64_efi", "ia64_efi" ]
GROUPS["ieee1275"] = [ "i386_ieee1275", "sparc64_ieee1275", "powerpc_ieee1275" ]
# emu is a special case so many core functionality isn't needed on this platform
GROUPS["noemu"] = GRUB_PLATFORMS[:]; GROUPS["noemu"].remove("emu")
# Groups based on hardware features
-GROUPS["cmos"] = GROUPS["x86"][:] + ["mips_yeeloong"]; GROUPS["cmos"].remove("i386_efi"); GROUPS["cmos"].remove("x86_64_efi")
-GROUPS["pci"] = GROUPS["x86"] + GROUPS["mips"]
+GROUPS["cmos"] = GROUPS["x86"][:] + ["mips_loongson", "mips_qemu_mips",
+ "sparc64_ieee1275", "powerpc_ieee1275"]
+GROUPS["cmos"].remove("i386_efi"); GROUPS["cmos"].remove("x86_64_efi")
+GROUPS["pci"] = GROUPS["x86"] + ["mips_loongson"]
GROUPS["usb"] = GROUPS["pci"]
# If gfxterm is main output console integrate it into kernel
-GROUPS["videoinkernel"] = ["mips_yeeloong"]
+GROUPS["videoinkernel"] = ["mips_loongson", "mips_qemu_mips"]
GROUPS["videomodules"] = GRUB_PLATFORMS[:];
for i in GROUPS["videoinkernel"]: GROUPS["videomodules"].remove(i)
# Similar for terminfo
-GROUPS["terminfoinkernel"] = ["mips_yeeloong"] + GROUPS["ieee1275"];
+GROUPS["terminfoinkernel"] = ["mips_loongson", "mips_arc", "mips_qemu_mips" ] + GROUPS["ieee1275"];
GROUPS["terminfomodule"] = GRUB_PLATFORMS[:];
for i in GROUPS["terminfoinkernel"]: GROUPS["terminfomodule"].remove(i)
r += "[+ ELSE +][+ FOR " + nonetag + " +]" + closure("[+ ." + nonetag + " +]") + "[+ ENDFOR +][+ ENDIF +]"
return r
+#
+# Returns autogen code that defines an autogen macro using the
+# definition given in the 'snippet'.
+#
+def define_autogen_macro(name, snippet):
+ r = ""
+ r += "[+ DEFINE " + name + " +]"
+ r += snippet
+ r += "[+ ENDDEF +]\n"
+ return r
+
#
# Template for handling values from sum of all groups for a platform,
# for example:
# noemu = bus/usb/usbhub.c;
# enable = emu;
# enable = i386;
-# enable = mips_yeeloong;
+# enable = mips_loongson;
# emu_condition = COND_GRUB_EMU_USB;
# };
#
+def define_macro_for_platform_conditionals_if_statement(p):
+ return define_autogen_macro(
+ "if_" + p + "_conditionals",
+ foreach_platform_specific_value(platform, "_condition", "condition", lambda cond: "if " + cond + "\n"))
+def define_macro_for_platform_conditionals_endif_statement(p):
+ return define_autogen_macro(
+ "endif_" + p + "_conditionals",
+ foreach_platform_specific_value(platform, "_condition", "condition", lambda cond: "endif " + cond + "\n"))
def under_platform_specific_conditionals(platform, snippet):
- r = foreach_platform_specific_value(platform, "_condition", "condition", lambda cond: "if " + cond + "\n")
+ r = "[+ if_" + platform + "_conditionals +]"
r += snippet
- r += foreach_platform_specific_value(platform, "_condition", "condition", lambda cond: "endif " + cond + "\n")
+ r += "[+ endif_" + platform + "_conditionals +]"
return r
def platform_specific_values(platform, suffix, nonetag):
def extra_dist():
return foreach_value("extra_dist", lambda value: value + " ")
-def platform_sources(p): return platform_values(p, "")
-def platform_nodist_sources(p): return platform_values(p, "_nodist")
-def platform_dependencies(p): return platform_values(p, "dependencies", "_dependencies")
+def define_macro_for_platform_sources(p):
+ return define_autogen_macro(
+ "get_" + p + "_sources",
+ platform_values(p, ""))
+def define_macro_for_platform_nodist_sources(p):
+ return define_autogen_macro(
+ "get_" + p + "_nodist_sources",
+ platform_values(p, "_nodist"))
+def define_macro_for_platform_dependencies(p):
+ return define_autogen_macro(
+ "get_" + p + "_dependencies",
+ platform_values(p, "dependencies", "_dependencies"))
+def platform_sources(p): return "[+ get_" + p + "_sources +]"
+def platform_nodist_sources(p): return "[+ get_" + p + "_nodist_sources +]"
+def platform_dependencies(p): return "[+ get_" + p + "_dependencies +]"
-def platform_startup(p): return platform_specific_values(p, "_startup", "startup")
-def platform_ldadd(p): return platform_specific_values(p, "_ldadd", "ldadd")
-def platform_cflags(p): return platform_specific_values(p, "_cflags", "cflags")
-def platform_ldflags(p): return platform_specific_values(p, "_ldflags", "ldflags")
-def platform_cppflags(p): return platform_specific_values(p, "_cppflags", "cppflags")
-def platform_ccasflags(p): return platform_specific_values(p, "_ccasflags", "ccasflags")
-def platform_stripflags(p): return platform_specific_values(p, "_stripflags", "stripflags")
-def platform_objcopyflags(p): return platform_specific_values(p, "_objcopyflags", "objcopyflags")
+#
+# Returns Autogen code which defines the autogen macros that collect
+# platform specific values for cflags, ldflags, etc. tags.
+#
+def define_macro_for_platform_startup(p):
+ return define_autogen_macro(
+ "get_" + p + "_startup",
+ platform_specific_values(p, "_startup", "startup"))
+def define_macro_for_platform_cflags(p):
+ return define_autogen_macro(
+ "get_" + p + "_cflags",
+ platform_specific_values(p, "_cflags", "cflags"))
+def define_macro_for_platform_ldadd(p):
+ return define_autogen_macro(
+ "get_" + p + "_ldadd",
+ platform_specific_values(p, "_ldadd", "ldadd"))
+def define_macro_for_platform_ldflags(p):
+ return define_autogen_macro(
+ "get_" + p + "_ldflags",
+ platform_specific_values(p, "_ldflags", "ldflags"))
+def define_macro_for_platform_cppflags(p):
+ return define_autogen_macro(
+ "get_" + p + "_cppflags",
+ platform_specific_values(p, "_cppflags", "cppflags"))
+def define_macro_for_platform_ccasflags(p):
+ return define_autogen_macro(
+ "get_" + p + "_ccasflags",
+ platform_specific_values(p, "_ccasflags", "ccasflags"))
+def define_macro_for_platform_stripflags(p):
+ return define_autogen_macro(
+ "get_" + p + "_stripflags",
+ platform_specific_values(p, "_stripflags", "stripflags"))
+def define_macro_for_platform_objcopyflags(p):
+ return define_autogen_macro(
+ "get_" + p + "_objcopyflags",
+ platform_specific_values(p, "_objcopyflags", "objcopyflags"))
+#
+# Autogen calls to invoke the above macros.
+#
+def platform_startup(p): return "[+ get_" + p + "_startup +]"
+def platform_ldadd(p): return "[+ get_" + p + "_ldadd +]"
+def platform_cflags(p): return "[+ get_" + p + "_cflags +]"
+def platform_ldflags(p): return "[+ get_" + p + "_ldflags +]"
+def platform_cppflags(p): return "[+ get_" + p + "_cppflags +]"
+def platform_ccasflags(p): return "[+ get_" + p + "_ccasflags +]"
+def platform_stripflags(p): return "[+ get_" + p + "_stripflags +]"
+def platform_objcopyflags(p): return "[+ get_" + p + "_objcopyflags +]"
#
# Emit snippet only the first time through for the current name.
def data_rules():
return rules("data", data)
-print "[+ AutoGen5 template +]\n"
a = module_rules()
b = kernel_rules()
c = image_rules()
g = data_rules()
z = global_variable_initializers()
+print ("[+ AutoGen5 template +]\n")
+for p in GRUB_PLATFORMS:
+ print (define_macro_for_platform_sources(p))
+ print (define_macro_for_platform_nodist_sources(p))
+ # print define_macro_for_platform_dependencies(p)
+
+ print (define_macro_for_platform_startup(p))
+ print (define_macro_for_platform_cflags(p))
+ print (define_macro_for_platform_ldadd(p))
+ print (define_macro_for_platform_ldflags(p))
+ print (define_macro_for_platform_cppflags(p))
+ print (define_macro_for_platform_ccasflags(p))
+ print (define_macro_for_platform_stripflags(p))
+ print (define_macro_for_platform_objcopyflags(p))
+
+ print (define_macro_for_platform_conditionals_if_statement(p))
+ print (define_macro_for_platform_conditionals_endif_statement(p))
# print z # initializer for all vars
-print a
-print b
-print c
-print d
-print e
-print f
-print g
+print (a)
+print (b)
+print (c)
+print (d)
+print (e)
+print (f)
+print (g)
-AUTOMAKE_OPTIONS = subdir-objects
+AUTOMAKE_OPTIONS = subdir-objects -Wno-portability
DEPDIR=.deps-core
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/net.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/libgcc.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/memory.h
if COND_i386_coreboot
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/pit.h
+KERNEL_HEADER_FILES += $(top_builddir)/include/grub/i386/pc/int.h
endif
if COND_i386_multiboot
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/pit.h
+KERNEL_HEADER_FILES += $(top_builddir)/include/grub/i386/pc/int.h
endif
if COND_i386_qemu
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/pit.h
endif
-if COND_mips_yeeloong
+if COND_ia64_efi
+KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/efi.h
+KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/time.h
+KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/disk.h
+endif
+
+if COND_mips
+KERNEL_HEADER_FILES += $(top_builddir)/include/grub/cpu/kernel.h
+endif
+
+if COND_mips_arc
+KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h
+KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/arc/arc.h
+endif
+
+if COND_mips_qemu_mips
+KERNEL_HEADER_FILES += $(top_builddir)/include/grub/keyboard_layouts.h
+KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/kernel.h
+KERNEL_HEADER_FILES += $(top_builddir)/include/grub/cpu/cache.h
+KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/bitmap.h
+KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/video.h
+KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/gfxterm.h
+KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/font.h
+KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/bitmap_scale.h
+KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/bufio.h
+KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/serial.h
+KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/loader.h
+KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/terminfo.h
+KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h
+KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/lib/arg.h
+endif
+
+if COND_mips_loongson
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/keyboard_layouts.h
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/kernel.h
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/cpu/cache.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/lib/arg.h
endif
+if COND_mips_qemu_mips
+KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/memory.h
+KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/kernel.h
+endif
+
if COND_powerpc_ieee1275
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ieee1275/ieee1275.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/terminfo.h
if COND_emu
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/datetime.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/emu/misc.h
+KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/emu/export.h
if COND_GRUB_EMU_SDL
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/sdl.h
endif
$(MOD_FILES): %.mod : genmod.sh moddep.lst %.module$(EXEEXT)
TARGET_OBJ2ELF=@TARGET_OBJ2ELF@ sh $^ $@
platform_DATA += $(MOD_FILES)
+platform_DATA += modinfo.sh
CLEANFILES += $(MOD_FILES)
if COND_ENABLE_EFIEMU
common = genmod.sh.in;
};
+script = {
+ installdir = noinst;
+ name = modinfo.sh;
+ common = modinfo.sh.in;
+};
+
kernel = {
name = kernel;
nostrip = emu;
emu_ldflags = '-Wl,-r,-d';
- x86_efi_ldflags = '-Wl,-r,-d';
- x86_efi_stripflags = '--strip-unneeded -K start -R .note -R .comment';
+ i386_efi_ldflags = '-Wl,-r,-d';
+ i386_efi_stripflags = '--strip-unneeded -K start -R .note -R .comment';
+ x86_64_efi_ldflags = '-Wl,-r,-d';
+ x86_64_efi_stripflags = '--strip-unneeded -K start -R .note -R .comment';
+
+ ia64_efi_cflags = '-fno-builtin -fpic -minline-int-divide-max-throughput';
+ ia64_efi_ldflags = '-Wl,-r,-d';
+ ia64_efi_stripflags = '--strip-unneeded -K start -R .note -R .comment';
i386_pc_ldflags = '$(TARGET_IMG_LDFLAGS)';
i386_pc_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x8200';
i386_coreboot_ldflags = '-Wl,-Ttext=0x8200';
i386_multiboot_ldflags = '-Wl,-Ttext=0x8200';
i386_ieee1275_ldflags = '-Wl,-Ttext=0x10000';
- mips_yeeloong_ldflags = '-Wl,-Ttext,0x80200000';
+ mips_loongson_ldflags = '-Wl,-Ttext,0x80200000';
powerpc_ieee1275_ldflags = '-Wl,-Ttext,0x200000';
sparc64_ieee1275_ldflags = '-Wl,-Ttext,0x4400';
+ mips_arc_ldflags = '-Wl,-Ttext,0x8bd00000';
+ mips_qemu_mips_ldflags = '-Wl,-Ttext,0x80200000';
- mips_yeeloong_cppflags = '-DUSE_ASCII_FAILBACK';
+ mips_loongson_cppflags = '-DUSE_ASCII_FAILBACK';
i386_qemu_cppflags = '-DGRUB_BOOT_MACHINE_LINK_ADDR=$(GRUB_BOOT_MACHINE_LINK_ADDR)';
emu_cflags = '$(CFLAGS_GNULIB)';
emu_cppflags = '$(CPPFLAGS_GNULIB)';
i386_ieee1275_startup = kern/i386/ieee1275/startup.S;
i386_coreboot_startup = kern/i386/coreboot/startup.S;
i386_multiboot_startup = kern/i386/coreboot/startup.S;
- mips_yeeloong_startup = kern/mips/startup.S;
+ mips_startup = kern/mips/startup.S;
sparc64_ieee1275_startup = kern/sparc64/ieee1275/crt0.S;
powerpc_ieee1275_startup = kern/powerpc/ieee1275/startup.S;
noemu_nodist = symlist.c;
i386_pc = kern/generic/rtc_get_time_ms.c;
- x86_efi = kern/generic/rtc_get_time_ms.c;
i386_qemu = kern/generic/rtc_get_time_ms.c;
i386_coreboot = kern/generic/rtc_get_time_ms.c;
i386_multiboot = kern/generic/rtc_get_time_ms.c;
- mips_yeeloong = kern/generic/rtc_get_time_ms.c;
+ mips = kern/generic/rtc_get_time_ms.c;
ieee1275 = disk/ieee1275/ofdisk.c;
ieee1275 = kern/ieee1275/cmain.c;
ieee1275 = kern/ieee1275/mmap.c;
ieee1275 = kern/ieee1275/openfw.c;
ieee1275 = term/ieee1275/ofconsole.c;
+ ieee1275 = kern/ieee1275/init.c;
terminfoinkernel = term/terminfo.c;
terminfoinkernel = term/tparm.c;
x86 = kern/i386/pit.c;
- x86_efi = disk/efi/efidisk.c;
- x86_efi = kern/efi/efi.c;
- x86_efi = kern/efi/init.c;
- x86_efi = kern/efi/mm.c;
- x86_efi = kern/i386/efi/init.c;
- x86_efi = term/efi/console.c;
+ efi = disk/efi/efidisk.c;
+ efi = kern/efi/efi.c;
+ efi = kern/efi/init.c;
+ efi = kern/efi/mm.c;
+ efi = term/efi/console.c;
i386_efi = kern/i386/tsc.c;
+ i386_efi = kern/i386/efi/init.c;
x86_64_efi = kern/i386/tsc.c;
x86_64_efi = kern/x86_64/dl.c;
x86_64_efi = kern/x86_64/efi/callwrap.S;
+ x86_64_efi = kern/i386/efi/init.c;
+
+ ia64_efi = kern/ia64/efi/startup.S;
+ ia64_efi = kern/ia64/efi/init.c;
+ ia64_efi = kern/ia64/dl.c;
+ ia64_efi = kern/ia64/dl_helper.c;
i386_pc = kern/i386/pc/init.c;
i386_pc = kern/i386/pc/mmap.c;
i386_pc = term/i386/pc/console.c;
i386_qemu = bus/pci.c;
- i386_qemu = kern/i386/qemu/init.c;
+ i386_qemu = kern/vga_init.c;
i386_qemu = kern/i386/qemu/mmap.c;
i386_qemu = kern/i386/tsc.c;
i386_multiboot = kern/i386/multiboot_mmap.c;
i386_multiboot = kern/i386/tsc.c;
- i386_ieee1275 = kern/ieee1275/init.c;
-
- mips_yeeloong = term/ns8250.c;
- mips_yeeloong = bus/bonito.c;
- mips_yeeloong = bus/cs5536.c;
- mips_yeeloong = bus/pci.c;
- mips_yeeloong = kern/mips/cache.S;
- mips_yeeloong = kern/mips/dl.c;
- mips_yeeloong = kern/mips/init.c;
- mips_yeeloong = kern/mips/yeeloong/init.c;
- mips_yeeloong = term/at_keyboard.c;
- mips_yeeloong = term/serial.c;
- mips_yeeloong = video/sm712.c;
+ mips = kern/mips/cache.S;
+ mips = kern/mips/dl.c;
+ mips = kern/mips/init.c;
+
+ mips_qemu_mips = kern/mips/qemu_mips/init.c;
+ mips_qemu_mips = term/ns8250.c;
+ mips_qemu_mips = term/serial.c;
+ mips_qemu_mips = term/at_keyboard.c;
+ mips_qemu_mips = commands/keylayouts.c;
+ mips_qemu_mips = term/i386/pc/vga_text.c;
+ mips_qemu_mips = term/i386/vga_common.c;
+ mips_qemu_mips = kern/vga_init.c;
+
+ mips_arc = kern/mips/arc/init.c;
+ mips_arc = term/arc/console.c;
+ mips_arc = disk/arc/arcdisk.c;
+
+ mips_loongson = term/ns8250.c;
+ mips_loongson = bus/bonito.c;
+ mips_loongson = bus/cs5536.c;
+ mips_loongson = bus/pci.c;
+ mips_loongson = kern/mips/loongson/init.c;
+ mips_loongson = term/at_keyboard.c;
+ mips_loongson = term/serial.c;
+ mips_loongson = video/sm712.c;
+ mips_loongson = video/sis315pro.c;
+ mips_loongson = video/radeon_fuloong2e.c;
extra_dist = video/sm712_init.c;
- mips_yeeloong = commands/keylayouts.c;
+ mips_loongson = commands/keylayouts.c;
- powerpc_ieee1275 = kern/ieee1275/init.c;
powerpc_ieee1275 = kern/powerpc/cache.S;
powerpc_ieee1275 = kern/powerpc/dl.c;
sparc64_ieee1275 = kern/sparc64/cache.S;
sparc64_ieee1275 = kern/sparc64/dl.c;
sparc64_ieee1275 = kern/sparc64/ieee1275/ieee1275.c;
- sparc64_ieee1275 = kern/sparc64/ieee1275/init.c;
emu = disk/host.c;
emu = gnulib/progname.c;
emu = gnulib/error.c;
- emu = kern/emu/cache.S;
+ emu = kern/emu/cache_s.S;
emu = kern/emu/console.c;
- emu = kern/emu/getroot.c;
emu = kern/emu/hostdisk.c;
emu = kern/emu/hostfs.c;
emu = kern/emu/main.c;
emu = kern/emu/misc.c;
emu = kern/emu/mm.c;
emu = kern/emu/time.c;
+ emu = kern/emu/cache.c;
videoinkernel = term/gfxterm.c;
videoinkernel = font/font.c;
videoinkernel = io/bufio.c;
videoinkernel = video/bitmap.c;
videoinkernel = video/bitmap_scale.c;
+ videoinkernel = video/colors.c;
videoinkernel = video/fb/fbblit.c;
videoinkernel = video/fb/fbfill.c;
videoinkernel = video/fb/fbutil.c;
videoinkernel = commands/boot.c;
+ extra_dist = kern/i386/int.S;
extra_dist = kern/i386/realmode.S;
extra_dist = kern/i386/pc/lzma_decode.S;
extra_dist = kern/mips/cache_flush.S;
common = lib/xzembed/xz_dec_lzma2.c;
common = lib/xzembed/xz_dec_stream.c;
- cppflags = '-I$(srcdir)/lib/posix_wrap -I$(srcdir)/lib/xzembed';
-
- mips_cppflags = '-I$(srcdir)/lib/posix_wrap -I$(srcdir)/lib/xzembed -DGRUB_EMBED_DECOMPRESSOR=1 -DGRUB_MACHINE_LINK_ADDR=0x80200000';
+ cppflags = '-I$(srcdir)/lib/posix_wrap -I$(srcdir)/lib/xzembed -DGRUB_EMBED_DECOMPRESSOR=1';
objcopyflags = '-O binary';
- ldflags = '-static-libgcc -Wl,-Ttext,0x80100000';
+ mips_loongson_ldflags = '-static-libgcc -Wl,-Ttext,0x80100000';
+ mips_qemu_mips_ldflags = '-static-libgcc -Wl,-Ttext,0x80100000';
+ mips_arc_ldflags = '-static-libgcc -Wl,-Ttext,0x8bc00000';
ldadd = '-lgcc';
cflags = '-static-libgcc';
enable = mips;
mips = boot/mips/startup_raw.S;
common = boot/decompressor/none.c;
- mips_cppflags = '-DGRUB_EMBED_DECOMPRESSOR=1 -DGRUB_MACHINE_LINK_ADDR=0x80200000';
+ cppflags = '-DGRUB_EMBED_DECOMPRESSOR=1';
objcopyflags = '-O binary';
- ldflags = '-static-libgcc -Wl,-Ttext,0x80100000';
+ mips_loongson_ldflags = '-static-libgcc -Wl,-Ttext,0x80100000';
+ mips_qemu_mips_ldflags = '-static-libgcc -Wl,-Ttext,0x80100000';
+ mips_arc_ldflags = '-static-libgcc -Wl,-Ttext,0x8bc00000';
ldadd = '-lgcc';
cflags = '-static-libgcc';
enable = mips;
image = {
name = fwstart;
- mips_yeeloong = boot/mips/yeeloong/fwstart.S;
+ mips_loongson = boot/mips/loongson/fwstart.S;
objcopyflags = '-O binary';
ldflags = '-static-libgcc -lgcc -Wl,-N,-S,-Ttext,0xbfc00000,-Bstatic';
- enable = mips_yeeloong;
+ enable = mips_loongson;
+};
+
+image = {
+ name = fwstart_fuloong2f;
+ mips_loongson = boot/mips/loongson/fuloong2f.S;
+ objcopyflags = '-O binary';
+ ldflags = '-static-libgcc -lgcc -Wl,-N,-S,-Ttext,0xbfc00000,-Bstatic';
+ enable = mips_loongson;
};
module = {
module = {
name = lsspd;
- mips_yeeloong = commands/mips/yeeloong/lsspd.c;
- enable = mips_yeeloong;
+ mips_loongson = commands/mips/loongson/lsspd.c;
+ enable = mips_loongson;
};
module = {
name = usb;
common = bus/usb/usb.c;
- noemu = bus/usb/usbtrans.c;
- noemu = bus/usb/usbhub.c;
- enable = emu;
+ common = bus/usb/usbtrans.c;
+ common = bus/usb/usbhub.c;
enable = usb;
- emu_condition = COND_GRUB_EMU_USB;
+};
+
+module = {
+ name = emuusb;
+ common = bus/usb/usb.c;
+ condition = COND_GRUB_EMU_USB;
};
module = {
module = {
name = pci;
- noemu = bus/pci.c;
- emu = bus/emu/pci.c;
- emu = commands/lspci.c;
+ common = bus/pci.c;
- enable = emu;
enable = i386_pc;
- enable = x86_efi;
+ enable = i386_efi;
+ enable = x86_64_efi;
enable = i386_ieee1275;
enable = i386_coreboot;
enable = i386_multiboot;
- emu_condition = COND_GRUB_EMU_PCI;
+};
+
+module = {
+ name = emupci;
+ common = bus/emu/pci.c;
+ common = commands/lspci.c;
+
+ condition = COND_GRUB_EMU_PCI;
+};
+
+module = {
+ name = lsdev;
+ common = commands/arc/lsdev.c;
+
+ enable = mips_arc;
};
library = {
name = acpi;
common = commands/acpi.c;
- x86_efi = commands/efi/acpi.c;
+ efi = commands/efi/acpi.c;
i386_pc = commands/i386/pc/acpi.c;
i386_coreboot = commands/i386/pc/acpi.c;
i386_multiboot = commands/i386/pc/acpi.c;
- enable = x86_efi;
+ enable = efi;
enable = i386_pc;
enable = i386_coreboot;
enable = i386_multiboot;
common = commands/lsacpi.c;
- enable = x86_efi;
+ enable = efi;
enable = i386_pc;
enable = i386_coreboot;
enable = i386_multiboot;
common = commands/efi/lsefisystab.c;
- enable = x86_efi;
+ enable = efi;
};
module = {
common = commands/efi/lssal.c;
- enable = x86_efi;
+ enable = efi;
};
module = {
common = commands/efi/lsefimmap.c;
- enable = x86_efi;
+ enable = efi;
};
module = {
module = {
name = fixvideo;
- x86_efi = commands/efi/fixvideo.c;
- enable = x86_efi;
+ common = commands/efi/fixvideo.c;
+ enable = i386_efi;
+ enable = x86_64_efi;
};
module = {
i386_pc = commands/acpihalt.c;
i386_coreboot = commands/acpihalt.c;
i386_multiboot = commands/acpihalt.c;
- x86_efi = commands/acpihalt.c;
+ i386_efi = commands/acpihalt.c;
+ x86_64_efi = commands/acpihalt.c;
i386_multiboot = lib/i386/halt.c;
i386_coreboot = lib/i386/halt.c;
i386_qemu = lib/i386/halt.c;
- x86_efi = lib/efi/halt.c;
+ efi = lib/efi/halt.c;
ieee1275 = lib/ieee1275/halt.c;
emu = lib/emu/halt.c;
};
+module = {
+ name = reboot;
+ i386 = lib/i386/reboot.c;
+ i386 = lib/i386/reboot_trampoline.S;
+ ia64_efi = lib/efi/reboot.c;
+ x86_64_efi = lib/efi/reboot.c;
+ powerpc_ieee1275 = lib/ieee1275/reboot.c;
+ sparc64_ieee1275 = lib/ieee1275/reboot.c;
+ mips_arc = lib/mips/arc/reboot.c;
+ mips_loongson = lib/mips/loongson/reboot.c;
+ mips_qemu_mips = lib/mips/qemu_mips/reboot.c;
+ common = commands/reboot.c;
+};
+
module = {
name = hashsum;
common = commands/hashsum.c;
common = commands/hdparm.c;
common = lib/hexdump.c;
enable = pci;
+ enable = mips_qemu_mips;
};
module = {
module = {
name = loadbios;
- x86_efi = commands/efi/loadbios.c;
- enable = x86_efi;
+ common = commands/efi/loadbios.c;
+ enable = i386_efi;
+ enable = x86_64_efi;
};
module = {
common = commands/probe.c;
};
-module = {
- name = pxecmd;
- i386_pc = commands/i386/pc/pxecmd.c;
- enable = i386_pc;
-};
-
module = {
name = read;
common = commands/read.c;
};
-module = {
- name = reboot;
- common = commands/reboot.c;
-};
-
module = {
name = search;
common = commands/search_wrap.c;
name = usbtest;
common = commands/usbtest.c;
enable = usb;
- enable = emu;
- emu_condition = COND_GRUB_EMU_USB;
};
module = {
common = disk/loopback.c;
};
+module = {
+ name = cryptodisk;
+ common = disk/cryptodisk.c;
+};
+
+module = {
+ name = luks;
+ common = disk/luks.c;
+ common = disk/AFSplitter.c;
+};
+
+module = {
+ name = geli;
+ common = disk/geli.c;
+};
+
module = {
name = lvm;
common = disk/lvm.c;
name = ata;
common = disk/ata.c;
enable = pci;
+ enable = mips_qemu_mips;
+};
+
+module = {
+ name = ahci;
+ common = disk/ahci.c;
+ enable = pci;
};
module = {
- name = ata_pthru;
- common = disk/ata_pthru.c;
+ name = pata;
+ common = disk/pata.c;
enable = pci;
+ enable = mips_qemu_mips;
};
module = {
name = usbms;
common = disk/usbms.c;
enable = usb;
- enable = emu;
- emu_condition = COND_GRUB_EMU_USB;
};
module = {
module = {
name = btrfs;
common = fs/btrfs.c;
+ common = lib/crc.c;
+ cflags = '$(CFLAGS_POSIX) -Wno-undef';
+ cppflags = '-I$(srcdir)/lib/posix_wrap -I$(srcdir)/lib/minilzo -DMINILZO_HAVE_CONFIG_H';
};
module = {
common = fs/minix2.c;
};
+module = {
+ name = minix3;
+ common = fs/minix3.c;
+};
+
module = {
name = nilfs2;
common = fs/nilfs2.c;
common = fs/reiserfs.c;
};
+module = {
+ name = romfs;
+ common = fs/romfs.c;
+};
+
module = {
name = sfs;
common = fs/sfs.c;
};
+module = {
+ name = squash4;
+ common = fs/squash4.c;
+};
+
module = {
name = tar;
common = fs/tar.c;
module = {
name = pxe;
- i386_pc = fs/i386/pc/pxe.c;
+ i386_pc = net/drivers/i386/pc/pxe.c;
enable = i386_pc;
};
common = gfxmenu/gui_progress_bar.c;
common = gfxmenu/gui_util.c;
common = gfxmenu/gui_string_util.c;
- common = gfxmenu/named_colors.c;
};
module = {
x86_64 = lib/x86_64/relocator_asm.S;
x86 = lib/i386/relocator.c;
ieee1275 = lib/ieee1275/relocator.c;
- x86_efi = lib/efi/relocator.c;
+ efi = lib/efi/relocator.c;
mips = lib/mips/relocator_asm.S;
mips = lib/mips/relocator.c;
powerpc = lib/powerpc/relocator_asm.S;
module = {
name = datetime;
cmos = lib/cmos_datetime.c;
- x86_efi = lib/efi/datetime.c;
+ efi = lib/efi/datetime.c;
sparc64_ieee1275 = lib/ieee1275/datetime.c;
powerpc_ieee1275 = lib/ieee1275/datetime.c;
+ sparc64_ieee1275 = lib/ieee1275/cmos.c;
+ powerpc_ieee1275 = lib/ieee1275/cmos.c;
+
+ mips_arc = lib/arc/datetime.c;
enable = noemu;
};
extra_dist = lib/x86_64/setjmp.S;
extra_dist = lib/sparc64/setjmp.S;
extra_dist = lib/powerpc/setjmp.S;
+ extra_dist = lib/ia64/setjmp.S;
};
module = {
enable = i386_pc;
};
+module = {
+ name = freedos;
+ i386_pc = loader/i386/pc/freedos.c;
+ enable = i386_pc;
+};
+
module = {
name = multiboot2;
cppflags = "-DGRUB_USE_MULTIBOOT2";
mips = loader/mips/linux.c;
powerpc_ieee1275 = loader/powerpc/ieee1275/linux.c;
sparc64_ieee1275 = loader/sparc64/ieee1275/linux.c;
+ ia64_efi = loader/ia64/efi/linux.c;
common = lib/cmdline.c;
enable = noemu;
};
module = {
name = appleldr;
- x86_efi = loader/efi/appleloader.c;
- enable = x86_efi;
+ common = loader/efi/appleloader.c;
+ enable = i386_efi;
+ enable = x86_64_efi;
};
module = {
name = chain;
- x86_efi = loader/efi/chainloader.c;
+ efi = loader/efi/chainloader.c;
i386_pc = loader/i386/pc/chainloader.c;
+ i386_coreboot = loader/i386/coreboot/chainloader.c;
enable = i386_pc;
- enable = x86_efi;
+ enable = i386_coreboot;
+ enable = efi;
};
module = {
i386_pc = mmap/i386/pc/mmap.c;
i386_pc = mmap/i386/pc/mmap_helper.S;
- x86_efi = mmap/efi/mmap.c;
+ efi = mmap/efi/mmap.c;
- mips_yeeloong = mmap/mips/yeeloong/uppermem.c;
+ mips = mmap/mips/uppermem.c;
enable = x86;
- enable = mips_yeeloong;
+ enable = ia64_efi;
+ enable = mips;
};
module = {
common = partmap/sun.c;
};
+module = {
+ name = part_dvh;
+ common = partmap/dvh.c;
+};
+
module = {
name = part_bsd;
common = partmap/bsdlabel.c;
common = term/serial.c;
x86 = term/ns8250.c;
- enable = emu;
- enable = i386;
- enable = x86_64_efi;
- emu_condition = COND_GRUB_EMU_USB;
+ enable = x86;
};
module = {
module = {
name = vga;
- i386_pc = video/i386/pc/vga.c;
+ common = video/i386/pc/vga.c;
enable = i386_pc;
+ enable = i386_coreboot;
+ enable = i386_multiboot;
};
module = {
module = {
name = efi_gop;
- x86_efi = video/efi_gop.c;
- enable = x86_efi;
+ efi = video/efi_gop.c;
+ enable = efi;
};
module = {
name = efi_uga;
- x86_efi = video/efi_uga.c;
- enable = x86_efi;
+ efi = video/efi_uga.c;
+ enable = i386_efi;
+ enable = x86_64_efi;
};
module = {
module = {
name = vbe;
- i386_pc = video/i386/pc/vbe.c;
+ common = video/i386/pc/vbe.c;
enable = i386_pc;
+ enable = i386_coreboot;
+ enable = i386_multiboot;
};
module = {
module = {
name = video;
common = video/video.c;
+ common = video/colors.c;
enable = videomodules;
};
module = {
name = ieee1275_fb;
ieee1275 = video/ieee1275.c;
- enable = powerpc;
+ enable = powerpc_ieee1275;
};
module = {
common = hook/datehook.c;
};
+module = {
+ name = net;
+ common = net/net.c;
+ common = net/bootp.c;
+ common = net/ip.c;
+ common = net/udp.c;
+ common = net/ethernet.c;
+ common = net/arp.c;
+ common = net/netbuff.c;
+};
+
+module = {
+ name = tftp;
+ common = net/tftp.c;
+};
+
+module = {
+ name = ofnet;
+ common = net/drivers/ieee1275/ofnet.c;
+ enable = ieee1275;
+};
+
+module = {
+ name = efinet;
+ common = net/drivers/efi/efinet.c;
+ enable = efi;
+};
+
+module = {
+ name = emunet;
+ emu = net/drivers/emu/emunet.c;
+ enable = emu;
+};
+
module = {
name = legacycfg;
common = commands/legacycfg.c;
cppflags = '-I$(srcdir)/lib/posix_wrap -I$(srcdir)/lib/xzembed';
};
+module = {
+ name = lzopio;
+ common = io/lzopio.c;
+ common = lib/minilzo/minilzo.c;
+ cflags = '$(CFLAGS_POSIX) -Wno-undef';
+ cppflags = '-I$(srcdir)/lib/posix_wrap -I$(srcdir)/lib/minilzo -DMINILZO_HAVE_CONFIG_H';
+};
+
module = {
name = testload;
common = commands/testload.c;
common = commands/keylayouts.c;
enable = videomodules;
};
+
+module = {
+ name = time;
+ common = commands/time.c;
+};
+
+module = {
+ name = cacheinfo;
+ common = commands/cacheinfo.c;
+ condition = COND_ENABLE_CACHE_STATS;
+};
+
+module = {
+ name = adler32;
+ common = lib/adler32.c;
+};
char *d = (char *) dest;
const char *s = (const char *) src;
+ if (d == s)
+ return;
+
if (d < s)
while (n--)
*d++ = *s++;
--- /dev/null
+#define FULOONG2F 1
+#include "fwstart.S"
--- /dev/null
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2000,2001,2002,2003,2004,2005,2007,2008,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/mips/loongson/serial.h>
+#include <grub/mips/loongson/pci.h>
+#include <grub/mips/loongson.h>
+#include <grub/pci.h>
+#include <grub/machine/serial.h>
+#include <grub/machine/kernel.h>
+#include <grub/ns8250.h>
+#include <grub/cs5536.h>
+#include <grub/smbus.h>
+
+#ifdef FULOONG2F
+#define GRUB_MACHINE_SERIAL_PORT GRUB_MACHINE_SERIAL_PORT2
+#define GRUB_MACHINE_SERIAL_DIVISOR_115200 GRUB_MACHINE_SERIAL_PORT2_DIVISOR_115200
+#else
+#define GRUB_MACHINE_SERIAL_PORT GRUB_MACHINE_SERIAL_PORT0
+#define GRUB_MACHINE_SERIAL_DIVISOR_115200 GRUB_MACHINE_SERIAL_PORT0_DIVISOR_115200
+#endif
+
+ .set noreorder
+ .set noat
+ .set nomacro
+ .set mips3
+
+ .global start,_start,__start
+start:
+_start:
+__start:
+ /* Put serial init as soon as possible. But on Fuloong2f serial is past
+ Geode, so on Fuloong2f we need Geode first.
+ */
+#ifndef FULOONG2F
+ bal serial_hw_init
+ nop
+#endif
+
+ /* Find CS5536 controller. */
+ /* $t4 chooses device in priority encoding. */
+ /* Resulting value is kept in GRUB_MACHINE_PCI_CONF_CTRL_REG.
+ This way we don't need to sacrifice a register for it. */
+retry_cs5536:
+ /* We have only one bus (0). Function is 0. */
+ lui $t0, %hi(GRUB_MACHINE_PCI_CONF_CTRL_REG_ADDR)
+ lui $t1, %hi(GRUB_MACHINE_PCI_CONFSPACE)
+ lui $t3, %hi(GRUB_CS5536_PCIID)
+ addiu $t3, $t3, %lo(GRUB_CS5536_PCIID)
+ ori $t4, $zero, 1
+1:
+ andi $t4, $t4, ((1 << GRUB_PCI_NUM_DEVICES) - 1)
+ /* In case of failure try again. CS5536 may be slow to come up. */
+ beql $t4, $zero, retry_cs5536
+ nop
+ sw $t4, %lo(GRUB_MACHINE_PCI_CONF_CTRL_REG_ADDR) ($t0)
+ lw $t2, (%lo(GRUB_MACHINE_PCI_CONFSPACE) + GRUB_PCI_REG_PCI_ID) ($t1)
+ bnel $t2, $t3, 1b
+ sll $t4, $t4, 1
+
+#ifndef FULOONG2F
+ bal message
+ addiu $a0, $a0, %lo(cs5536_found)
+ bal printhex
+ move $a0, $t4
+#endif
+
+ lui $t0, %hi(GRUB_MACHINE_PCI_CONFSPACE)
+ li $t1, GRUB_CS5536_MSR_MAILBOX_CONFIG_ENABLED
+ sw $t1, (%lo(GRUB_MACHINE_PCI_CONFSPACE) + GRUB_CS5536_MSR_MAILBOX_CONFIG) ($t0)
+
+ /* Set GPIO LBAR. */
+ lui $a0, %hi(GRUB_CS5536_MSR_GPIO_BAR)
+ addiu $a0, $a0, %lo(GRUB_CS5536_MSR_GPIO_BAR)
+ ori $a1, $zero, GRUB_CS5536_LBAR_GPIO
+ /* Set mask to 0xf and enabled bit to 1. */
+ bal wrmsr
+ ori $a2, $zero, ((GRUB_CS5536_LBAR_MASK_MASK \
+ | GRUB_CS5536_LBAR_ENABLE) >> 32)
+
+ bal gpio_init
+ nop
+
+#ifdef FULOONG2F
+ bal serial_hw_init
+ nop
+#endif
+
+ /* Initialise SMBus controller. */
+ /* Set SMBUS LBAR. */
+ lui $a0, %hi(GRUB_CS5536_MSR_SMB_BAR)
+ addiu $a0, $a0, %lo(GRUB_CS5536_MSR_SMB_BAR)
+ ori $a1, $zero, GRUB_CS5536_LBAR_SMBUS
+ /* Set mask to 0xf and enabled bit to 1. */
+ bal wrmsr
+ ori $a2, $zero, ((GRUB_CS5536_LBAR_MASK_MASK \
+ | GRUB_CS5536_LBAR_ENABLE) >> 32)
+
+ lui $a0, %hi(smbus_enabled)
+ bal message
+ addiu $a0, $a0, %lo(smbus_enabled)
+
+ lui $t0, %hi(GRUB_MACHINE_PCI_IO_BASE + GRUB_CS5536_LBAR_SMBUS)
+
+ /* Disable SMB. */
+ sb $zero, %lo(GRUB_MACHINE_PCI_IO_BASE + GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL2) ($t0)
+
+ /* Disable interrupts. */
+ sb $zero, %lo(GRUB_MACHINE_PCI_IO_BASE + GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1) ($t0)
+
+ /* Set as master. */
+ sb $zero, %lo(GRUB_MACHINE_PCI_IO_BASE + GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_ADDR) ($t0)
+
+ /* Launch SMBus controller at slowest speed possible. */
+ ori $t1, $zero, 0xff
+ sb $t1, %lo(GRUB_MACHINE_PCI_IO_BASE + GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL3) ($t0)
+ sb $t1, %lo(GRUB_MACHINE_PCI_IO_BASE + GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL2) ($t0)
+
+ /* Yeeloong and Fuloong2f have only one memory slot. */
+ /* Output first byte on serial for debugging. */
+ ori $a1, $zero, GRUB_SMB_RAM_START_ADDR
+ bal read_spd
+ move $a0, $zero
+ bal printhex
+ move $a0, $v0
+
+ bal read_spd
+ ori $a0, $zero, GRUB_SMBUS_SPD_MEMORY_TYPE_ADDR
+ ori $t0, $zero, GRUB_SMBUS_SPD_MEMORY_TYPE_DDR2
+ lui $a0, %hi(unimplemented_memory_type)
+ bne $t0, $v0, fatal
+ addiu $a0, $a0, %lo(unimplemented_memory_type)
+
+ /* And here is our goal: DDR2 controller initialisation. */
+ lui $t0, %hi(GRUB_CPU_LOONGSON_CORECFG)
+ ld $t1, %lo(GRUB_CPU_LOONGSON_CORECFG) ($t0)
+ /* Use addiu for sign-extension. */
+ addiu $t2, $zero, ~(GRUB_CPU_LOONGSON_CORECFG_DISABLE_DDR2_SPACE|GRUB_CPU_LOONGSON_CORECFG_BUFFER_CPU)
+ and $t1, $t1, $t2
+ sd $t1, %lo (GRUB_CPU_LOONGSON_CORECFG) ($t0)
+
+ b continue
+
+ . = start + GRUB_CPU_LOONGSON_FLASH_TLB_REFILL - GRUB_CPU_LOONGSON_FLASH_START
+tlb_refill:
+ mfc0 $s1, GRUB_CPU_LOONGSON_COP0_EPC
+ mfc0 $s2, GRUB_CPU_LOONGSON_COP0_BADVADDR
+ move $s3, $ra
+ lui $a0, %hi(epc)
+ bal message
+ addiu $a0, $a0, %lo(epc)
+
+ bal printhex
+ move $a0, $s1
+
+ lui $a0, %hi(badvaddr)
+ bal message
+ addiu $a0, $a0, %lo(badvaddr)
+
+ bal printhex
+ move $a0, $s2
+
+ lui $a0, %hi(return_msg)
+ bal message
+ addiu $a0, $a0, %lo(return_msg)
+
+ bal printhex
+ move $a0, $s3
+
+ lui $a0, %hi(newline)
+ bal message
+ addiu $a0, $a0, %lo(newline)
+
+ lui $a0, %hi(unhandled_tlb_refill)
+ b fatal
+ addiu $a0, $a0, %lo(unhandled_tlb_refill)
+
+ . = start + GRUB_CPU_LOONGSON_FLASH_CACHE_ERROR - GRUB_CPU_LOONGSON_FLASH_START
+cache_error:
+ lui $a0, %hi(unhandled_cache_error)
+ b fatal
+ addiu $a0, $a0, %lo(unhandled_cache_error)
+
+ . = start + GRUB_CPU_LOONGSON_FLASH_OTHER_EXCEPTION - GRUB_CPU_LOONGSON_FLASH_START
+other_exception:
+ mfc0 $s0, GRUB_CPU_LOONGSON_COP0_CAUSE
+ mfc0 $s1, GRUB_CPU_LOONGSON_COP0_EPC
+ mfc0 $s2, GRUB_CPU_LOONGSON_COP0_BADVADDR
+ lui $a0, %hi(cause)
+ bal message
+ addiu $a0, $a0, %lo(cause)
+
+ bal printhex
+ move $a0, $s0
+
+ lui $a0, %hi(epc)
+ bal message
+ addiu $a0, $a0, %lo(epc)
+
+ bal printhex
+ move $a0, $s1
+
+ lui $a0, %hi(badvaddr)
+ bal message
+ addiu $a0, $a0, %lo(badvaddr)
+
+ bal printhex
+ move $a0, $s2
+
+ lui $a0, %hi(newline)
+ bal message
+ addiu $a0, $a0, %lo(newline)
+
+ lui $a0, %hi(unhandled_exception)
+ b fatal
+ addiu $a0, $a0, %lo(unhandled_exception)
+
+gpio_init:
+ lui $t0, %hi(GRUB_MACHINE_PCI_IO_BASE + GRUB_CS5536_LBAR_GPIO)
+ addiu $t0, $t0, %lo(GRUB_MACHINE_PCI_IO_BASE + GRUB_CS5536_LBAR_GPIO)
+ lui $t1, %hi (gpio_dump)
+ addiu $t1, $t1, %lo (gpio_dump)
+
+1:
+ lw $t2, 0($t1)
+ sw $t2, 0($t0)
+ addiu $t0, $t0, 4
+ addiu $t1, $t1, 4
+ lui $t2, %hi (gpio_dump_end)
+ addiu $t2, $t2, %lo (gpio_dump_end)
+ bne $t1, $t2, 1b
+ nop
+ jr $ra
+ nop
+
+ /* Same as similarly named C function but in asm since
+ we need it early. */
+ /* In: none. Out: none. Clobbered: $t0, $t1, $t2, $a0, $a1, $a2. */
+serial_hw_init:
+ move $t2, $ra
+#ifdef FULOONG2F
+ lui $a0, %hi(GRUB_CS5536_MSR_DIVIL_LEG_IO)
+ addiu $a0, $a0, %lo(GRUB_CS5536_MSR_DIVIL_LEG_IO)
+ lui $a1, %hi (GRUB_CS5536_MSR_DIVIL_LEG_IO_UART2_COM3 \
+ | GRUB_CS5536_MSR_DIVIL_LEG_IO_F_REMAP \
+ | GRUB_CS5536_MSR_DIVIL_LEG_IO_MODE_X86 \
+ | GRUB_CS5536_MSR_DIVIL_LEG_IO_UART1_COM1)
+ ori $a1, $a1, (GRUB_CS5536_MSR_DIVIL_LEG_IO_RTC_ENABLE0 \
+ | GRUB_CS5536_MSR_DIVIL_LEG_IO_RTC_ENABLE1)
+ bal wrmsr
+ move $a2, $zero
+
+ lui $a0, %hi(GRUB_CS5536_MSR_DIVIL_UART1_CONF)
+ addiu $a0, $a0, %lo(GRUB_CS5536_MSR_DIVIL_UART1_CONF)
+ li $a1, 2
+ bal wrmsr
+ move $a2, $zero
+
+ lui $a0, %hi(GRUB_CS5536_MSR_DIVIL_UART2_CONF)
+ addiu $a0, $a0, %lo(GRUB_CS5536_MSR_DIVIL_UART2_CONF)
+ li $a1, 2
+ bal wrmsr
+ move $a2, $zero
+#endif
+
+ lui $t0, %hi (GRUB_MACHINE_SERIAL_PORT)
+
+ /* Turn off the interrupt. */
+ sb $zero, (%lo (GRUB_MACHINE_SERIAL_PORT) + UART_IER)($t0)
+
+ /* Set DLAB. */
+ ori $t1, $zero, UART_DLAB
+ sb $t1, (%lo (GRUB_MACHINE_SERIAL_PORT) + UART_LCR)($t0)
+
+ /* Set the baud rate 115200. */
+ ori $t1, $zero, GRUB_MACHINE_SERIAL_DIVISOR_115200
+ sb $t1, (%lo (GRUB_MACHINE_SERIAL_PORT) + UART_DLL)($t0)
+ sb $zero, (%lo (GRUB_MACHINE_SERIAL_PORT) + UART_DLH)($t0)
+
+ /* Set the line status. */
+ ori $t1, $zero, (UART_NO_PARITY | UART_8BITS_WORD | UART_1_STOP_BIT)
+ sb $t1, (%lo (GRUB_MACHINE_SERIAL_PORT) + UART_LCR)($t0)
+
+ /* Enable the FIFO. */
+ ori $t1, $zero, UART_ENABLE_FIFO_TRIGGER1
+ sb $t1, (%lo (GRUB_MACHINE_SERIAL_PORT) + UART_FCR)($t0)
+
+ /* Turn on DTR and RTS. */
+ ori $t1, $zero, UART_ENABLE_DTRRTS
+ sb $t1, (%lo (GRUB_MACHINE_SERIAL_PORT) + UART_MCR)($t0)
+
+ /* Let message return to original caller. */
+ lui $a0, %hi(notification_string)
+ addiu $a0, $a0, %lo(notification_string)
+ move $ra, $t2
+
+ /* Print message on serial console. */
+ /* In: $a0 = asciiz message. Out: none. Clobbered: $t0, $t1, $a0. */
+message:
+ lui $t0, %hi (GRUB_MACHINE_SERIAL_PORT)
+1:
+ lb $t1, (%lo (GRUB_MACHINE_SERIAL_PORT) + UART_LSR)($t0)
+ andi $t1, $t1, UART_EMPTY_TRANSMITTER
+ beq $t1, $zero, 1b
+ nop
+ lb $t1, 0($a0)
+ sb $t1, (%lo (GRUB_MACHINE_SERIAL_PORT) + UART_TX)($t0)
+ bne $t1, $zero, 1b
+ addiu $a0, $a0, 1
+ jr $ra
+ nop
+
+ /* Print 32-bit hexadecimal on serial.
+ In: $a0. Out: None. Clobbered: $a0, $t0, $t1, $t2
+ */
+printhex:
+ lui $t0, %hi (GRUB_MACHINE_SERIAL_PORT)
+ ori $t2, $zero, 8
+1:
+ lb $t1, (%lo (GRUB_MACHINE_SERIAL_PORT) + UART_LSR)($t0)
+ andi $t1, $t1, UART_EMPTY_TRANSMITTER
+ beq $t1, $zero, 1b
+ nop
+ srl $t1, $a0, 28
+ addiu $t1, $t1, -10
+ blt $t1, $zero, 2f
+ sll $a0, $a0, 4
+ addiu $t1, $t1, 'A'-10-'0'
+2: addiu $t1, $t1, '0'+10
+ sb $t1, (%lo (GRUB_MACHINE_SERIAL_PORT) + UART_TX)($t0)
+ addiu $t2, $t2, -1
+ bne $t2, $zero, 1b
+ nop
+ jr $ra
+ nop
+
+fatal:
+ bal message
+ nop
+self:
+ b self
+ nop
+
+ /* Write CS5536 MSR.
+ In: $a0 address, $a1 lower word, $a2 upper word.
+ Out: None
+ Clobbered: $t0
+ */
+wrmsr:
+ lui $t0, %hi(GRUB_MACHINE_PCI_CONFSPACE)
+ sw $a0, (%lo(GRUB_MACHINE_PCI_CONFSPACE) + GRUB_CS5536_MSR_MAILBOX_ADDR) ($t0)
+ sw $a1, (%lo(GRUB_MACHINE_PCI_CONFSPACE) + GRUB_CS5536_MSR_MAILBOX_DATA0) ($t0)
+ jr $ra
+ sw $a2, (%lo(GRUB_MACHINE_PCI_CONFSPACE) + GRUB_CS5536_MSR_MAILBOX_DATA1) ($t0)
+
+ /* Wait for SMBus data or empty transmitter. */
+ /* In: $a0 = exception handler. Out: none. Clobbered: $t0, $t1 */
+smbus_wait:
+1:
+ lui $t0, %hi(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_STATUS + GRUB_MACHINE_PCI_IO_BASE)
+ lb $t0, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_STATUS + GRUB_MACHINE_PCI_IO_BASE) ($t0)
+ andi $t1, $t0, GRUB_CS5536_SMB_REG_STATUS_SDAST
+ bne $t1, $zero, return
+ nop
+ andi $t1, $t0, (GRUB_CS5536_SMB_REG_STATUS_BER | GRUB_CS5536_SMB_REG_STATUS_NACK)
+ beq $t1, $zero, 1b
+ nop
+ jr $a0
+ nop
+return:
+ jr $ra
+ nop
+
+ /* Read SPD byte. In: $a0 byte, $a1 device. Out: $v0 read byte (0x100 on failure).
+ Clobbered: $t0, $t1, $t2, $t3, $a0. */
+read_spd:
+ move $t2, $a0
+ move $t3, $ra
+ lui $a0, %hi(read_spd_fail)
+ addiu $a0, $a0, %hi(read_spd_fail)
+
+ /* Send START. */
+ lui $t0, %hi(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1 + GRUB_MACHINE_PCI_IO_BASE)
+ lb $t1, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1 + GRUB_MACHINE_PCI_IO_BASE) ($t0)
+ ori $t1, $t1, GRUB_CS5536_SMB_REG_CTRL1_START
+ bal smbus_wait
+ sb $t1, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1 + GRUB_MACHINE_PCI_IO_BASE) ($t0)
+
+ /* Send device address. */
+ lui $t0, %hi(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_DATA + GRUB_MACHINE_PCI_IO_BASE)
+ sll $t1, $a1, 1
+ bal smbus_wait
+ sb $t1, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_DATA + GRUB_MACHINE_PCI_IO_BASE) ($t0)
+
+ /* Send ACK. */
+ lui $t0, %hi(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1 + GRUB_MACHINE_PCI_IO_BASE)
+ lb $t1, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1 + GRUB_MACHINE_PCI_IO_BASE) ($t0)
+ ori $t1, $t1, GRUB_CS5536_SMB_REG_CTRL1_ACK
+ sb $t1, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1 + GRUB_MACHINE_PCI_IO_BASE) ($t0)
+
+ /* Send byte address. */
+ lui $t0, %hi(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_DATA + GRUB_MACHINE_PCI_IO_BASE)
+ bal smbus_wait
+ sb $t2, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_DATA + GRUB_MACHINE_PCI_IO_BASE) ($t0)
+
+ /* Send START. */
+ lui $t0, %hi(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1 + GRUB_MACHINE_PCI_IO_BASE)
+ lb $t1, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1 + GRUB_MACHINE_PCI_IO_BASE) ($t0)
+ ori $t1, $t1, GRUB_CS5536_SMB_REG_CTRL1_START
+ bal smbus_wait
+ sb $t1, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1 + GRUB_MACHINE_PCI_IO_BASE) ($t0)
+
+ /* Send device address. */
+ lui $t0, %hi(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_DATA + GRUB_MACHINE_PCI_IO_BASE)
+ sll $t1, $a1, 1
+ ori $t1, $t1, 1
+ bal smbus_wait
+ sb $t1, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_DATA + GRUB_MACHINE_PCI_IO_BASE) ($t0)
+
+ /* Send STOP. */
+ lui $t0, %hi(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1 + GRUB_MACHINE_PCI_IO_BASE)
+ lb $t1, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1 + GRUB_MACHINE_PCI_IO_BASE) ($t0)
+ ori $t1, $t1, GRUB_CS5536_SMB_REG_CTRL1_STOP
+ bal smbus_wait
+ sb $t1, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1 + GRUB_MACHINE_PCI_IO_BASE) ($t0)
+
+ lui $t0, %hi(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_DATA + GRUB_MACHINE_PCI_IO_BASE)
+ lb $v0, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_DATA + GRUB_MACHINE_PCI_IO_BASE) ($t0)
+ jr $t3
+ andi $v0, $v0, 0xff
+read_spd_fail:
+ jr $t3
+ ori $v0, $v0, 0x100
+
+notification_string: .asciz "GRUB "
+cs5536_found: .asciz "CS5536 at "
+sm_failed: .asciz "SM transaction failed.\n\r"
+unhandled_tlb_refill: .asciz "Unhandled TLB refill.\n\r"
+unhandled_cache_error: .asciz "Unhandled cache error.\n\r"
+unhandled_exception: .asciz "Unhandled exception.\n\r"
+smbus_enabled: .asciz "SMBus controller enabled.\n\r"
+unimplemented_memory_type: .asciz "non-DDR2 memory isn't supported.\n\r"
+no_cas_latency: .asciz "Couldn't determine CAS latency.\n\r"
+cause: .asciz "Cause: "
+epc: .asciz "\n\rEPC: "
+badvaddr: .asciz "\n\rBadVaddr: "
+newline: .asciz "\n\r"
+return_msg: .asciz "\n\rReturn address: "
+caches_enabled: .asciz "Caches enabled\n\r"
+
+ .p2align 3
+
+regdump:
+ .quad 0x0100010000000101 /* 0 */
+ .quad 0x0100010100000000 /* 2 */
+ .quad 0x0101000001000000 /* 3 */
+ .quad 0x0100020200010101 /* 4 */
+ .quad 0x0a04030603050203 /* 6 */
+ .quad 0x0f0e040000010a0b /* 7 */
+#ifdef FULOONG2F
+ .quad 0x0000000100000001 /* 8 */
+#else
+ .quad 0x0000010200000102 /* 8 */
+#endif
+ .quad 0x0000060c00000000 /* 9 */
+ .quad 0x2323233f3f1f0200 /* a */
+ .quad 0x5f7f232323232323 /* b */
+ .quad 0x002a3c0615000000 /* c */
+ .quad 0x002a002a002a002a /* d */
+ .quad 0x002a002a002a002a /* e */
+#ifdef FULOONG2F
+ .quad 0x00b40020005b0004 /* f */
+#else
+ .quad 0x00b40020006d0004 /* f */
+#endif
+ .quad 0x070007ff00000087 /* 10 */
+ .quad 0x000000000016101f /* 11 */
+ .quad 0x001c000000000000 /* 12 */
+ .quad 0x28e1000200c8006b /* 13 */
+ .quad 0x0000204200c8002f /* 14 */
+ .quad 0x0000000000030d40 /* 15 */
+ .quad 0 /* 16 */
+ .quad 0 /* 17 */
+ .quad 0 /* 18 */
+ .quad 0 /* 19 */
+ .quad 0 /* 1a */
+ .quad 0 /* 1b */
+ .quad 0 /* 1c */
+
+/* Dump of GPIO connections. FIXME: Remove useless and macroify. */
+gpio_dump:
+#ifdef FULOONG2F
+ .long 0xffff0000, 0x2eefd110, 0xffff0000, 0xffff0000
+ .long 0x2eefd110, 0xffff0000, 0x1000efff, 0xefff1000
+ .long 0x3df3c20c, 0xffff0000, 0xffff0000, 0xffff0000
+ .long 0x7df3820c, 0x3df3c20c, 0xffff0000, 0x00000000
+ .long 0xffff0000, 0xffff0000, 0x3de3c21c, 0x3d83c27c
+ .long 0x00000000, 0x00000000, 0x00000000, 0x00000000
+ .long 0x00000000, 0x00000000, 0x00000000, 0x00000000
+ .long 0x00000000, 0x00000000, 0x00000000, 0x00000000
+ .long 0xffff0000, 0xffff0000, 0xffff0000, 0xffff0000
+ .long 0xffff0000, 0xffff0000, 0x0000ffff, 0xffff0000
+ .long 0xefff1000, 0xffff0000, 0xffff0000, 0xffff0000
+ .long 0xefff1000, 0xefff1000, 0xffff0000, 0x00000000
+ .long 0xffff0000, 0xffff0000, 0xefff1000, 0xefff1000
+ .long 0x00000000, 0x00000000, 0x00000000, 0x00000000
+ .long 0x00000000, 0x00000000, 0x00000000, 0x00000000
+ .long 0x00000000, 0x00000000, 0x00000000, 0x00000000
+#else
+ .long 0xffff0000, 0x2ffdd002, 0xffff0000, 0xffff0000
+ .long 0x2fffd000, 0xffff0000, 0x1000efff, 0xefff1000
+ .long 0x3ffbc004, 0xffff0000, 0xffff0000, 0xffff0000
+ .long 0x3ffbc004, 0x3ffbc004, 0xffff0000, 0x00000000
+ .long 0xffff0000, 0xffff0000, 0x3ffbc004, 0x3f9bc064
+ .long 0x00000000, 0x00000000, 0x00000000, 0x00000000
+ .long 0x00000000, 0x00000000, 0x00000000, 0x00000000
+ .long 0x00000000, 0x00000000, 0x00000000, 0x00000000
+ .long 0xffff0000, 0xffff0000, 0xffff0000, 0xffff0000
+ .long 0xffff0000, 0xffff0000, 0x0000ffff, 0xffff0000
+ .long 0xefff1000, 0xffff0000, 0xffff0000, 0xffff0000
+ .long 0xefff1000, 0xefff1000, 0xffff0000, 0x00000000
+ .long 0xffff0000, 0xffff0000, 0xefff1000, 0xffff0000
+ .long 0x00000000, 0x00000000, 0x00000000, 0x00000000
+ .long 0x00000000, 0x00000000, 0x00000000, 0x00000000
+ .long 0x00000000, 0x50000000, 0x00000000, 0x00000000
+#endif
+gpio_dump_end:
+
+ .p2align
+
+write_dumpreg:
+ ld $t2, 0($t6)
+ sd $t2, 0($t4)
+ addiu $t4, $t4, GRUB_CPU_LOONGSON_DDR2_REG_STEP
+ jr $ra
+ addiu $t6, $t6, GRUB_CPU_LOONGSON_DDR2_REG_SIZE
+
+continue:
+ lui $t4, %hi(GRUB_CPU_LOONGSON_DDR2_BASE)
+ addiu $t4, $t4, %lo(GRUB_CPU_LOONGSON_DDR2_BASE)
+ lui $t6, %hi(regdump)
+
+ /* 0 */
+ bal write_dumpreg
+ addiu $t6, $t6, %lo(regdump)
+
+ /* 1 */
+ ori $a1, $a1, GRUB_SMB_RAM_START_ADDR
+ move $t8, $zero
+ lui $t5, 0x0001
+ bal read_spd
+ ori $a0, $zero, GRUB_SMBUS_SPD_MEMORY_NUM_BANKS_ADDR
+ ori $t7, $zero, 8
+ bne $v0, $t7, 1f
+ ori $t5, $t5, 0x0001
+ ori $t8, $t8, GRUB_CPU_LOONGSON_DDR2_REG1_HI_8BANKS
+1:
+ dsll $t8, $t8, 32
+ or $t5, $t5, $t8
+ sd $t5, 0 ($t4)
+ addiu $t4, $t4, GRUB_CPU_LOONGSON_DDR2_REG_STEP
+
+ /* 2 */
+ bal write_dumpreg
+ nop
+
+ /* 3 */
+ bal write_dumpreg
+ nop
+
+ /* 4 */
+ bal write_dumpreg
+ nop
+
+ /* 5 */
+ /* FIXME: figure termination resistance. */
+ ori $t5, $zero, 0x2
+ bal read_spd
+ ori $a0, $zero, GRUB_SMBUS_SPD_MEMORY_NUM_ROWS_ADDR
+ /* $v0 = 15 - $v0. */
+ xori $v0, $v0, 0xf
+ andi $v0, $v0, 0x7
+ sll $v0, $v0, 8
+ or $t5, $t5, $v0
+
+ /* Find the fastest supported CAS latency. */
+ bal read_spd
+ ori $a0, $zero, GRUB_SMBUS_SPD_MEMORY_CAS_LATENCY_ADDR
+ ori $t0, $zero, GRUB_SMBUS_SPD_MEMORY_CAS_LATENCY_MIN_VALUE
+ ori $t1, $zero, (1 << GRUB_SMBUS_SPD_MEMORY_CAS_LATENCY_MIN_VALUE)
+2:
+ and $t2, $t1, $v0
+ bne $t2, $zero, 1f
+ ori $t3, $zero, 8
+ lui $a0, %hi(no_cas_latency)
+ beq $t0, $t3, fatal
+ addiu $a0, $a0, %lo(no_cas_latency)
+ addiu $t0, $t0, 1
+ b 2b
+ sll $t1, $t1, 1
+1:
+ sll $t0, $t0, 16
+ or $t5, $t5, $t0
+
+ bal read_spd
+ ori $a0, $zero, GRUB_SMBUS_SPD_MEMORY_NUM_COLUMNS_ADDR
+ /* $v0 = 15 - ($v0 + 1) = 14 - $v0. */
+ addiu $v0, $v0, 1
+ xori $v0, $v0, 0xf
+ andi $v0, $v0, 0x7
+ sll $v0, 24
+ or $t5, $t5, $v0
+ sd $t5, 0 ($t4)
+
+ addiu $t4, $t4, GRUB_CPU_LOONGSON_DDR2_REG_STEP
+
+ ori $t7, $zero, 0x16
+
+1:
+ ld $t2, 0($t6)
+ sd $t2, 0($t4)
+ addiu $t4, $t4, GRUB_CPU_LOONGSON_DDR2_REG_STEP
+ addiu $t7, $t7, -1
+ bne $t7, $zero, 1b
+ addiu $t6, $t6, GRUB_CPU_LOONGSON_DDR2_REG_SIZE
+
+ lui $t4, %hi(GRUB_CPU_LOONGSON_DDR2_BASE)
+ ld $t5, (%lo(GRUB_CPU_LOONGSON_DDR2_BASE) + 0x30) ($t4)
+ ori $t0, $zero, 1
+ dsll $t0, $t0, 40
+ or $t5, $t5, $t0
+ sd $t5, (%lo(GRUB_CPU_LOONGSON_DDR2_BASE) + 0x30) ($t4)
+
+ /* Desactivate DDR2 registers. */
+ lui $t0, %hi (GRUB_CPU_LOONGSON_CORECFG)
+ ld $t1, %lo (GRUB_CPU_LOONGSON_CORECFG) ($t0)
+ ori $t1, $t1, GRUB_CPU_LOONGSON_CORECFG_DISABLE_DDR2_SPACE
+ sd $t1, %lo (GRUB_CPU_LOONGSON_CORECFG) ($t0)
+
+ /* Enable cache. */
+ mfc0 $t0, GRUB_CPU_LOONGSON_COP0_CACHE_CONFIG
+ addiu $t1, $zero, ~GRUB_CPU_LOONGSON_CACHE_TYPE_MASK
+ and $t0, $t1, $t1
+ /* Set line size to 32 bytes and disabled cache. */
+ ori $t0, $t0, (GRUB_CPU_LOONGSON_COP0_CACHE_CONFIG_ILINESIZE \
+ | GRUB_CPU_LOONGSON_COP0_CACHE_CONFIG_DLINESIZE \
+ | GRUB_CPU_LOONGSON_CACHE_ACCELERATED)
+ mtc0 $t0, GRUB_CPU_LOONGSON_COP0_CACHE_CONFIG
+
+ /* Invalidate all I-cache entries. */
+ srl $t1, $t0, GRUB_CPU_LOONGSON_COP0_CACHE_ISIZE_SHIFT
+ andi $t1, $t1, GRUB_CPU_LOONGSON_COP0_CACHE_SIZE_MASK
+ ori $t2, $zero, (1 << (GRUB_CPU_LOONGSON_COP0_CACHE_SIZE_OFFSET \
+ - GRUB_CPU_LOONGSON_CACHE_LINE_SIZE_LOG_BIG \
+ - GRUB_CPU_LOONGSON_I_CACHE_LOG_WAYS))
+ sll $t1, $t2, $t1
+ lui $t2, 0x8000
+
+1:
+ cache GRUB_CPU_LOONGSON_COP0_I_INDEX_INVALIDATE, 0($t2)
+ addiu $t1, $t1, -1
+ bne $t1, $zero, 1b
+ addiu $t2, $t2, (1 << GRUB_CPU_LOONGSON_COP0_I_INDEX_BIT_OFFSET)
+
+ /* Invalidate all D-cache entries. */
+ srl $t1, $t0, GRUB_CPU_LOONGSON_COP0_CACHE_DSIZE_SHIFT
+ andi $t1, $t1, GRUB_CPU_LOONGSON_COP0_CACHE_SIZE_MASK
+ ori $t2, $zero, (1 << (GRUB_CPU_LOONGSON_COP0_CACHE_SIZE_OFFSET \
+ - GRUB_CPU_LOONGSON_CACHE_LINE_SIZE_LOG_BIG \
+ - GRUB_CPU_LOONGSON_D_CACHE_LOG_WAYS))
+ sll $t1, $t2, $t1
+ lui $t2, 0x8000
+ mtc0 $zero, GRUB_CPU_LOONGSON_COP0_CACHE_TAGLO
+ mtc0 $zero, GRUB_CPU_LOONGSON_COP0_CACHE_TAGHI
+1:
+ /* All four ways. */
+ cache GRUB_CPU_LOONGSON_COP0_D_INDEX_TAG_STORE, 0($t2)
+ cache GRUB_CPU_LOONGSON_COP0_D_INDEX_TAG_STORE, 1($t2)
+ cache GRUB_CPU_LOONGSON_COP0_D_INDEX_TAG_STORE, 2($t2)
+ cache GRUB_CPU_LOONGSON_COP0_D_INDEX_TAG_STORE, 3($t2)
+ addiu $t1, $t1, -1
+ bne $t1, $zero, 1b
+ addiu $t2, $t2, (1 << GRUB_CPU_LOONGSON_COP0_D_INDEX_BIT_OFFSET)
+
+ /* Invalidate all S-cache entries. */
+ ori $t1, $zero, (1 << (GRUB_CPU_LOONGSON_SECONDARY_CACHE_LOG_SIZE \
+ - GRUB_CPU_LOONGSON_CACHE_LINE_SIZE_LOG_BIG \
+ - GRUB_CPU_LOONGSON_S_CACHE_LOG_WAYS))
+ lui $t2, 0x8000
+ mtc0 $zero, GRUB_CPU_LOONGSON_COP0_CACHE_TAGLO
+ mtc0 $zero, GRUB_CPU_LOONGSON_COP0_CACHE_TAGHI
+1:
+ /* All four ways. */
+ cache GRUB_CPU_LOONGSON_COP0_S_INDEX_TAG_STORE, 0($t2)
+ cache GRUB_CPU_LOONGSON_COP0_S_INDEX_TAG_STORE, 1($t2)
+ cache GRUB_CPU_LOONGSON_COP0_S_INDEX_TAG_STORE, 2($t2)
+ cache GRUB_CPU_LOONGSON_COP0_S_INDEX_TAG_STORE, 3($t2)
+ addiu $t1, $t1, -1
+ bne $t1, $zero, 1b
+ addiu $t2, $t2, (1 << GRUB_CPU_LOONGSON_COP0_D_INDEX_BIT_OFFSET)
+
+ /* Finally enable cache. */
+ mfc0 $t0, GRUB_CPU_LOONGSON_COP0_CACHE_CONFIG
+ addiu $t1, $zero, ~GRUB_CPU_LOONGSON_CACHE_TYPE_MASK
+ and $t0, $t1, $t1
+ ori $t0, $t0, GRUB_CPU_LOONGSON_CACHE_CACHED
+ mtc0 $t0, GRUB_CPU_LOONGSON_COP0_CACHE_CONFIG
+
+ lui $a0, %hi(caches_enabled)
+ bal message
+ addiu $a0, $a0, %lo(caches_enabled)
+
+ /* Set ROM delay cycles to 1. */
+ lui $t0, %hi(GRUB_CPU_LOONGSON_LIOCFG)
+ lw $t1, %lo(GRUB_CPU_LOONGSON_LIOCFG) ($t0)
+ addiu $t2, $zero, ~(GRUB_CPU_LOONGSON_ROM_DELAY_MASK \
+ << GRUB_CPU_LOONGSON_ROM_DELAY_OFFSET)
+ and $t1, $t1, $t2
+ ori $t1, $t1, (1 << GRUB_CPU_LOONGSON_ROM_DELAY_OFFSET)
+ sw $t1, %lo(GRUB_CPU_LOONGSON_LIOCFG) ($t0)
+
+ addiu $a0, $zero, -1
+ addiu $a1, $zero, -1
+
+ /* Take advantage of cache. */
+ lui $t0, %hi(cached_continue - 0x20000000)
+ addiu $t0, $t0, %lo(cached_continue - 0x20000000)
+ jr $t0
+#ifdef FULOONG2F
+ addiu $a2, $zero, -(1 + GRUB_ARCH_MACHINE_FULOONG2F)
+#else
+ addiu $a2, $zero, -(1 + GRUB_ARCH_MACHINE_YEELOONG)
+#endif
+
+cached_continue:
#include <grub/symbol.h>
#include <grub/offsets.h>
#include <grub/machine/memory.h>
+#include <grub/machine/kernel.h>
#include <grub/offsets.h>
#define BASE_ADDR 8
. = _start + GRUB_KERNEL_MACHINE_UNCOMPRESSED_SIZE
uncompressed_size:
.long 0
+ . = _start + GRUB_KERNEL_MACHINE_UNCOMPRESSED_ADDR
+uncompressed_addr:
+ .long 0
codestart:
/* Save our base. */
move $s0, $ra
/* Parse arguments. Has to be done before relocation.
So need to do it in asm. */
-#ifdef GRUB_MACHINE_MIPS_YEELOONG
+#ifdef GRUB_MACHINE_MIPS_QEMU_MIPS
+ lui $t0, %hi (((16 << 20) - 264 + 4) | 0x80000000)
+ lw $t1, %lo (((16 << 20) - 264 + 4) | 0x80000000) ($t0)
+
+ lui $t2, 0x1234
+ ori $t2, 0x5678
+
+ bne $t1, $t2, 1f
+ nop
+
+ lui $t0, %hi (((16 << 20) - 264) | 0x80000000)
+ b 2f
+ lw $s4, %lo (((16 << 20) - 264) | 0x80000000) ($t0)
+
+1:
+ li $s4, 0
+2:
+#endif
+
+#ifdef GRUB_MACHINE_MIPS_LOONGSON
move $s2, $zero
move $s3, $zero
move $s4, $zero
move $s5, $zero
+ move $s7, $zero
/* $a2 has the environment. */
- addiu $t0, $a2, 1
- beq $t0, $zero, argdone
+ addiu $t0, $zero, -0x10
+ and $t1, $a2, $t0
+ beq $t0, $t1, argfw
nop
move $t0, $a2
argcont:
nop ;\
b 2f;\
move reg, $v0; \
-1:
+1:
+#define DO_CHECKT1(str, val) \
+ move $t6, $t1 ;\
+ addiu $t7, $s0, (str - base);\
+ bal do_check ;\
+ li $t2, val
+
DO_PARSE (busclockstr, $s2)
DO_PARSE (cpuclockstr, $s3)
DO_PARSE (memsizestr, $s4)
DO_PARSE (highmemsizestr, $s5)
+ DO_CHECKT1 (pmon_yeeloong_verstr, GRUB_ARCH_MACHINE_YEELOONG)
+ DO_CHECKT1 (pmon_fuloong2f_verstr, GRUB_ARCH_MACHINE_FULOONG2F)
2:
b argcont
addiu $t0, $t0, 4
cpuclockstr: .asciiz "cpuclock="
memsizestr: .asciiz "memsize="
highmemsizestr: .asciiz "highmemsize="
+machtype_yeeloong_str1: .asciiz "machtype=8.9"
+machtype_yeeloong_str2: .asciiz "machtype=lemote-yeeloong-"
+machtype_fuloong2f_str: .asciiz "machtype=lemote-fuloong-2f"
+machtype_fuloong2e_str: .asciiz "machtype=lemote-fuloong-2e"
+pmon_yeeloong_str: .asciiz "PMON_VER=LM8"
+pmon_fuloong2f_str: .asciiz "PMON_VER=LM6"
+pmon_yeeloong_verstr: .asciiz "Version=LM8"
+pmon_fuloong2f_verstr: .asciiz "Version=LM6"
.p2align 2
+
argdone:
+ beq $a0, $zero, cmdlinedone
+ nop
+#define DO_CHECKA1(str, val) \
+ lw $t6, 0($a1) ;\
+ addiu $t7, $s0, (str - base);\
+ bal do_check ;\
+ li $t2, val
+ DO_CHECKA1 (machtype_yeeloong_str1, GRUB_ARCH_MACHINE_YEELOONG)
+ DO_CHECKA1 (machtype_yeeloong_str2, GRUB_ARCH_MACHINE_YEELOONG)
+ DO_CHECKA1 (pmon_yeeloong_str, GRUB_ARCH_MACHINE_YEELOONG)
+ DO_CHECKA1 (machtype_fuloong2f_str, GRUB_ARCH_MACHINE_FULOONG2F)
+ DO_CHECKA1 (machtype_fuloong2e_str, GRUB_ARCH_MACHINE_FULOONG2E)
+ DO_CHECKA1 (pmon_fuloong2f_str, GRUB_ARCH_MACHINE_FULOONG2F)
+ addiu $a0, $a0, -1
+ b argdone
+ addiu $a1, $a1, 4
+do_check:
+ lb $t4, 0($t7)
+ beq $t4, $zero, 1f
+ lb $t3, 0($t6)
+ bne $t3, $t4, 2f
+ addiu $t6, $t6, 1
+ b do_check
+ addiu $t7, $t7, 1
+1:
+ move $s7, $t2
+2:
+ jr $ra
+ nop
+argfw:
+ not $s7, $a2
+cmdlinedone:
#endif
/* Copy the decompressor. */
lui $t1, %hi(base)
b 1b
addiu $t1, $t1, 1
2:
+ lui $a0, %hi(base)
+ addiu $a0, $a0, %lo(base)
+ lui $a1, %hi(_end)
+ addiu $a1, %lo(_end)
+ subu $a1,$a1,$a0
+
+#include "../../kern/mips/cache_flush.S"
/* Decompress the payload. */
lui $a0, %hi(__bss_start)
subu $a0, $a0, $t0
addu $a0, $a0, $s0
- lui $a1, %hi(GRUB_MACHINE_LINK_ADDR)
- addiu $a1, %lo(GRUB_MACHINE_LINK_ADDR)
+ lw $a1, (GRUB_KERNEL_MACHINE_UNCOMPRESSED_ADDR - BASE_ADDR)($s0)
lw $a2, (GRUB_KERNEL_MACHINE_COMPRESSED_SIZE - BASE_ADDR)($s0)
lw $a3, (GRUB_KERNEL_MACHINE_UNCOMPRESSED_SIZE - BASE_ADDR)($s0)
move $s1, $a1
*/
move $s6, $a3
- lui $sp, %hi(_start - 256)
+ lui $t0, %hi(EXT_C(grub_decompress_core))
+ addiu $t0, $t0, %lo(EXT_C(grub_decompress_core))
- bal EXT_C(grub_decompress_core)
+ lui $sp, %hi(_start - 256)
+ jalr $t0
addiu $sp, $sp, %lo(_start - 256)
move $a0, $s1
+++ /dev/null
-/*
- * GRUB -- GRand Unified Bootloader
- * Copyright (C) 2000,2001,2002,2003,2004,2005,2007,2008,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/mips/yeeloong/serial.h>
-#include <grub/mips/yeeloong/pci.h>
-#include <grub/mips/loongson.h>
-#include <grub/pci.h>
-#include <grub/machine/serial.h>
-#include <grub/ns8250.h>
-#include <grub/cs5536.h>
-#include <grub/smbus.h>
-
- .set noreorder
- .set noat
- .set nomacro
-
- .global start,_start,__start
-start:
-_start:
-__start:
- bal serial_hw_init
- nop
- /* Find CS5536 controller. */
- /* $t4 chooses device in priority encoding. */
- /* Resulting value is kept in GRUB_MACHINE_PCI_CONF_CTRL_REG.
- This way we don't need to sacrifice a register for it. */
- /* We have only one bus (0). Function is 0. */
- lui $t0, %hi(GRUB_MACHINE_PCI_CONF_CTRL_REG_ADDR)
- lui $t1, %hi(GRUB_MACHINE_PCI_CONFSPACE)
- lui $t3, %hi(GRUB_CS5536_PCIID)
- addiu $t3, $t3, %lo(GRUB_CS5536_PCIID)
- ori $t4, $zero, 1
- lui $a0, %hi(no_cs5536)
-1:
- andi $t4, $t4, ((1 << GRUB_PCI_NUM_DEVICES) - 1)
- beql $t4, $zero, fatal
- addiu $a0, $a0, %lo(no_cs5536)
- sw $t4, %lo(GRUB_MACHINE_PCI_CONF_CTRL_REG_ADDR) ($t0)
- lw $t2, (%lo(GRUB_MACHINE_PCI_CONFSPACE) + GRUB_PCI_REG_PCI_ID) ($t1)
- bnel $t2, $t3, 1b
- sll $t4, $t4, 1
-
- bal message
- addiu $a0, $a0, %lo(cs5536_found)
- bal printhex
- move $a0, $t4
-
- /* Initialise SMBus controller. */
- /* Set GPIO LBAR. */
- lui $a0, %hi(GRUB_CS5536_MSR_GPIO_BAR)
- addiu $a0, $a0, %lo(GRUB_CS5536_MSR_GPIO_BAR)
- ori $a1, $zero, GRUB_CS5536_LBAR_GPIO
- /* Set mask to 0xf and enabled bit to 1. */
- bal wrmsr
- ori $a2, $zero, ((GRUB_CS5536_LBAR_MASK_MASK \
- | GRUB_CS5536_LBAR_ENABLE) >> 32)
-
- /* Set SMBUS LBAR. */
- lui $a0, %hi(GRUB_CS5536_MSR_SMB_BAR)
- addiu $a0, $a0, %lo(GRUB_CS5536_MSR_SMB_BAR)
- ori $a1, $zero, GRUB_CS5536_LBAR_SMBUS
- /* Set mask to 0xf and enabled bit to 1. */
- bal wrmsr
- ori $a2, $zero, ((GRUB_CS5536_LBAR_MASK_MASK \
- | GRUB_CS5536_LBAR_ENABLE) >> 32)
-
- lui $a0, %hi(smbus_enabled)
- bal message
- addiu $a0, $a0, %lo(smbus_enabled)
-
- /* Enable SMBus controller pins. */
- lui $t0, %hi(GRUB_MACHINE_PCI_IO_BASE + GRUB_CS5536_LBAR_GPIO)
- ori $t1, $zero, GRUB_GPIO_SMBUS_PINS
- sw $t1, %lo(GRUB_MACHINE_PCI_IO_BASE + GRUB_CS5536_LBAR_GPIO + GRUB_GPIO_REG_OUT_EN) ($t0)
- sw $t1, %lo(GRUB_MACHINE_PCI_IO_BASE + GRUB_CS5536_LBAR_GPIO + GRUB_GPIO_REG_OUT_AUX1) ($t0)
- sw $t1, %lo(GRUB_MACHINE_PCI_IO_BASE + GRUB_CS5536_LBAR_GPIO + GRUB_GPIO_REG_IN_EN) ($t0)
- sw $t1, %lo(GRUB_MACHINE_PCI_IO_BASE + GRUB_CS5536_LBAR_GPIO + GRUB_GPIO_REG_IN_AUX1) ($t0)
-
- lui $t0, %hi(GRUB_MACHINE_PCI_IO_BASE + GRUB_CS5536_LBAR_SMBUS)
-
- /* Disable SMB. */
- sb $zero, %lo(GRUB_MACHINE_PCI_IO_BASE + GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL2) ($t0)
-
- /* Disable interrupts. */
- sb $zero, %lo(GRUB_MACHINE_PCI_IO_BASE + GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1) ($t0)
-
- /* Set as master. */
- sb $zero, %lo(GRUB_MACHINE_PCI_IO_BASE + GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_ADDR) ($t0)
-
- /* Launch SMBus controller at slowest speed possible. */
- ori $t1, $zero, 0xff
- sb $t1, %lo(GRUB_MACHINE_PCI_IO_BASE + GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL3) ($t0)
- sb $t1, %lo(GRUB_MACHINE_PCI_IO_BASE + GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL2) ($t0)
-
- /* Yeeloong has only one memory slot. */
- /* Output first byte on serial for debugging. */
- ori $a1, $zero, GRUB_SMB_RAM_START_ADDR
- bal read_spd
- move $a0, $zero
- bal printhex
- move $a0, $v0
-
- bal read_spd
- ori $a0, $zero, GRUB_SMBUS_SPD_MEMORY_TYPE_ADDR
- ori $t0, $zero, GRUB_SMBUS_SPD_MEMORY_TYPE_DDR2
- lui $a0, %hi(unimplemented_memory_type)
- bne $t0, $v0, fatal
- addiu $a0, $a0, %lo(unimplemented_memory_type)
-
- /* And here is our goal: DDR2 controller initialisation. */
- lui $t0, %hi(GRUB_CPU_LOONGSON_CORECFG)
- ld $t1, %lo(GRUB_CPU_LOONGSON_CORECFG) ($t0)
- /* Use addiu for sign-extension. */
- addiu $t2, $zero, ~(GRUB_CPU_LOONGSON_CORECFG_DISABLE_DDR2_SPACE|GRUB_CPU_LOONGSON_CORECFG_BUFFER_CPU)
- and $t1, $t1, $t2
- sd $t1, %lo (GRUB_CPU_LOONGSON_CORECFG) ($t0)
-
- b continue
-
- . = start + GRUB_CPU_LOONGSON_FLASH_TLB_REFILL - GRUB_CPU_LOONGSON_FLASH_START
-tlb_refill:
- mfc0 $s1, GRUB_CPU_LOONGSON_COP0_EPC
- mfc0 $s2, GRUB_CPU_LOONGSON_COP0_BADVADDR
- move $s3, $ra
- lui $a0, %hi(epc)
- bal message
- addiu $a0, $a0, %lo(epc)
-
- bal printhex
- move $a0, $s1
-
- lui $a0, %hi(badvaddr)
- bal message
- addiu $a0, $a0, %lo(badvaddr)
-
- bal printhex
- move $a0, $s2
-
- lui $a0, %hi(return_msg)
- bal message
- addiu $a0, $a0, %lo(return_msg)
-
- bal printhex
- move $a0, $s3
-
- lui $a0, %hi(newline)
- bal message
- addiu $a0, $a0, %lo(newline)
-
- lui $a0, %hi(unhandled_tlb_refill)
- b fatal
- addiu $a0, $a0, %lo(unhandled_tlb_refill)
-
- . = start + GRUB_CPU_LOONGSON_FLASH_CACHE_ERROR - GRUB_CPU_LOONGSON_FLASH_START
-cache_error:
- lui $a0, %hi(unhandled_cache_error)
- b fatal
- addiu $a0, $a0, %lo(unhandled_cache_error)
-
- . = start + GRUB_CPU_LOONGSON_FLASH_OTHER_EXCEPTION - GRUB_CPU_LOONGSON_FLASH_START
-other_exception:
- mfc0 $s0, GRUB_CPU_LOONGSON_COP0_CAUSE
- mfc0 $s1, GRUB_CPU_LOONGSON_COP0_EPC
- mfc0 $s2, GRUB_CPU_LOONGSON_COP0_BADVADDR
- lui $a0, %hi(cause)
- bal message
- addiu $a0, $a0, %lo(cause)
-
- bal printhex
- move $a0, $s0
-
- lui $a0, %hi(epc)
- bal message
- addiu $a0, $a0, %lo(epc)
-
- bal printhex
- move $a0, $s1
-
- lui $a0, %hi(badvaddr)
- bal message
- addiu $a0, $a0, %lo(badvaddr)
-
- bal printhex
- move $a0, $s2
-
- lui $a0, %hi(newline)
- bal message
- addiu $a0, $a0, %lo(newline)
-
- lui $a0, %hi(unhandled_exception)
- b fatal
- addiu $a0, $a0, %lo(unhandled_exception)
-
- /* Same as similarly named C function but in asm since
- we need it early. */
- /* In: none. Out: none. Clobbered: $t0, $t1, $a0. */
-serial_hw_init:
- lui $t0, %hi (GRUB_MACHINE_SERIAL_PORT)
-
- /* Turn off the interrupt. */
- sb $zero, (%lo (GRUB_MACHINE_SERIAL_PORT) + UART_IER)($t0)
-
- /* Set DLAB. */
- ori $t1, $zero, UART_DLAB
- sb $t1, (%lo (GRUB_MACHINE_SERIAL_PORT) + UART_LCR)($t0)
-
- /* Set the baud rate 115200. */
- ori $t1, $zero, GRUB_MACHINE_SERIAL_DIVISOR_115200
- sb $t1, (%lo (GRUB_MACHINE_SERIAL_PORT) + UART_DLL)($t0)
- sb $zero, (%lo (GRUB_MACHINE_SERIAL_PORT) + UART_DLH)($t0)
-
- /* Set the line status. */
- ori $t1, $zero, (UART_NO_PARITY | UART_8BITS_WORD | UART_1_STOP_BIT)
- sb $t1, (%lo (GRUB_MACHINE_SERIAL_PORT) + UART_LCR)($t0)
-
- /* Enable the FIFO. */
- ori $t1, $zero, UART_ENABLE_FIFO_TRIGGER1
- sb $t1, (%lo (GRUB_MACHINE_SERIAL_PORT) + UART_FCR)($t0)
-
- /* Turn on DTR and RTS. */
- ori $t1, $zero, UART_ENABLE_DTRRTS
- sb $t1, (%lo (GRUB_MACHINE_SERIAL_PORT) + UART_MCR)($t0)
-
- /* Let message return to original caller. */
- lui $a0, %hi(notification_string)
- addiu $a0, $a0, %lo(notification_string)
-
- /* Print message on serial console. */
- /* In: $a0 = asciiz message. Out: none. Clobbered: $t0, $t1, $a0. */
-message:
- lui $t0, %hi (GRUB_MACHINE_SERIAL_PORT)
-1:
- lb $t1, (%lo (GRUB_MACHINE_SERIAL_PORT) + UART_LSR)($t0)
- andi $t1, $t1, UART_EMPTY_TRANSMITTER
- beq $t1, $zero, 1b
- nop
- lb $t1, 0($a0)
- sb $t1, (%lo (GRUB_MACHINE_SERIAL_PORT) + UART_TX)($t0)
- bne $t1, $zero, 1b
- addiu $a0, $a0, 1
- jr $ra
- nop
-
- /* Print 32-bit hexadecimal on serial.
- In: $a0. Out: None. Clobbered: $a0, $t0, $t1, $t2
- */
-printhex:
- lui $t0, %hi (GRUB_MACHINE_SERIAL_PORT)
- ori $t2, $zero, 8
-1:
- lb $t1, (%lo (GRUB_MACHINE_SERIAL_PORT) + UART_LSR)($t0)
- andi $t1, $t1, UART_EMPTY_TRANSMITTER
- beq $t1, $zero, 1b
- nop
- srl $t1, $a0, 28
- addiu $t1, $t1, -10
- blt $t1, $zero, 2f
- sll $a0, $a0, 4
- addiu $t1, $t1, 'A'-10-'0'
-2: addiu $t1, $t1, '0'+10
- sb $t1, (%lo (GRUB_MACHINE_SERIAL_PORT) + UART_TX)($t0)
- addiu $t2, $t2, -1
- bne $t2, $zero, 1b
- nop
- jr $ra
- nop
-
-fatal:
- bal message
- nop
-self:
- b self
- nop
-
- /* Write CS5536 MSR.
- In: $a0 address, $a1 lower word, $a2 upper word.
- Out: None
- Clobbered: $t0
- */
-wrmsr:
- lui $t0, %hi(GRUB_MACHINE_PCI_CONFSPACE)
- sw $a0, (%lo(GRUB_MACHINE_PCI_CONFSPACE) + GRUB_CS5536_MSR_MAILBOX_ADDR) ($t0)
- sw $a1, (%lo(GRUB_MACHINE_PCI_CONFSPACE) + GRUB_CS5536_MSR_MAILBOX_DATA0) ($t0)
- jr $ra
- sw $a2, (%lo(GRUB_MACHINE_PCI_CONFSPACE) + GRUB_CS5536_MSR_MAILBOX_DATA1) ($t0)
-
- /* Wait for SMBus data or empty transmitter. */
- /* In: $a0 = exception handler. Out: none. Clobbered: $t0, $t1 */
-smbus_wait:
-1:
- lui $t0, %hi(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_STATUS + GRUB_MACHINE_PCI_IO_BASE)
- lb $t0, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_STATUS + GRUB_MACHINE_PCI_IO_BASE) ($t0)
- andi $t1, $t0, GRUB_CS5536_SMB_REG_STATUS_SDAST
- bne $t1, $zero, return
- nop
- andi $t1, $t0, (GRUB_CS5536_SMB_REG_STATUS_BER | GRUB_CS5536_SMB_REG_STATUS_NACK)
- beq $t1, $zero, 1b
- nop
- jr $a0
- nop
-return:
- jr $ra
- nop
-
- /* Read SPD byte. In: $a0 byte, $a1 device. Out: $v0 read byte (0x100 on failure).
- Clobbered: $t0, $t1, $t2, $t3, $a0. */
-read_spd:
- move $t2, $a0
- move $t3, $ra
- lui $a0, %hi(read_spd_fail)
- addiu $a0, $a0, %hi(read_spd_fail)
-
- /* Send START. */
- lui $t0, %hi(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1 + GRUB_MACHINE_PCI_IO_BASE)
- lb $t1, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1 + GRUB_MACHINE_PCI_IO_BASE) ($t0)
- ori $t1, $t1, GRUB_CS5536_SMB_REG_CTRL1_START
- bal smbus_wait
- sb $t1, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1 + GRUB_MACHINE_PCI_IO_BASE) ($t0)
-
- /* Send device address. */
- lui $t0, %hi(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_DATA + GRUB_MACHINE_PCI_IO_BASE)
- sll $t1, $a1, 1
- bal smbus_wait
- sb $t1, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_DATA + GRUB_MACHINE_PCI_IO_BASE) ($t0)
-
- /* Send ACK. */
- lui $t0, %hi(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1 + GRUB_MACHINE_PCI_IO_BASE)
- lb $t1, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1 + GRUB_MACHINE_PCI_IO_BASE) ($t0)
- ori $t1, $t1, GRUB_CS5536_SMB_REG_CTRL1_ACK
- sb $t1, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1 + GRUB_MACHINE_PCI_IO_BASE) ($t0)
-
- /* Send byte address. */
- lui $t0, %hi(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_DATA + GRUB_MACHINE_PCI_IO_BASE)
- bal smbus_wait
- sb $t2, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_DATA + GRUB_MACHINE_PCI_IO_BASE) ($t0)
-
- /* Send START. */
- lui $t0, %hi(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1 + GRUB_MACHINE_PCI_IO_BASE)
- lb $t1, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1 + GRUB_MACHINE_PCI_IO_BASE) ($t0)
- ori $t1, $t1, GRUB_CS5536_SMB_REG_CTRL1_START
- bal smbus_wait
- sb $t1, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1 + GRUB_MACHINE_PCI_IO_BASE) ($t0)
-
- /* Send device address. */
- lui $t0, %hi(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_DATA + GRUB_MACHINE_PCI_IO_BASE)
- sll $t1, $a1, 1
- ori $t1, $t1, 1
- bal smbus_wait
- sb $t1, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_DATA + GRUB_MACHINE_PCI_IO_BASE) ($t0)
-
- /* Send STOP. */
- lui $t0, %hi(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1 + GRUB_MACHINE_PCI_IO_BASE)
- lb $t1, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1 + GRUB_MACHINE_PCI_IO_BASE) ($t0)
- ori $t1, $t1, GRUB_CS5536_SMB_REG_CTRL1_STOP
- bal smbus_wait
- sb $t1, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1 + GRUB_MACHINE_PCI_IO_BASE) ($t0)
-
- lui $t0, %hi(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_DATA + GRUB_MACHINE_PCI_IO_BASE)
- lb $v0, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_DATA + GRUB_MACHINE_PCI_IO_BASE) ($t0)
- jr $t3
- andi $v0, $v0, 0xff
-read_spd_fail:
- jr $t3
- ori $v0, $v0, 0x100
-
-notification_string: .asciz "GRUB "
-no_cs5536: .asciz "No CS5536 found.\n\r"
-cs5536_found: .asciz "CS5536 at "
-sm_failed: .asciz "SM transaction failed.\n\r"
-unhandled_tlb_refill: .asciz "Unhandled TLB refill.\n\r"
-unhandled_cache_error: .asciz "Unhandled cache error.\n\r"
-unhandled_exception: .asciz "Unhandled exception.\n\r"
-smbus_enabled: .asciz "SMBus controller enabled.\n\r"
-unimplemented_memory_type: .asciz "non-DDR2 memory isn't supported.\n\r"
-no_cas_latency: .asciz "Couldn't determine CAS latency.\n\r"
-cause: .asciz "Cause: "
-epc: .asciz "\n\rEPC: "
-badvaddr: .asciz "\n\rBadVaddr: "
-newline: .asciz "\n\r"
-return_msg: .asciz "\n\rReturn address: "
-caches_enabled: .asciz "Caches enabled\n\r"
-
- .p2align 3
-
-regdump:
- .quad 0x0100010000000101 /* 0 */
- .quad 0x0100010100000000 /* 2 */
- .quad 0x0101000001000000 /* 3 */
- .quad 0x0100020200010101 /* 4 */
- .quad 0x0a04030603050203 /* 6 */
- .quad 0x0f0e040000010a0b /* 7 */
- .quad 0x0000010200000102 /* 8 */
- .quad 0x0000060c00000000 /* 9 */
- .quad 0x2323233f3f1f0200 /* a */
- .quad 0x5f7f232323232323 /* b */
- .quad 0x002a3c0615000000 /* c */
- .quad 0x002a002a002a002a /* d */
- .quad 0x002a002a002a002a /* e */
- .quad 0x00b40020006d0004 /* f */
- .quad 0x070007ff00000087 /* 10 */
- .quad 0x000000000016101f /* 11 */
- .quad 0x001c000000000000 /* 12 */
- .quad 0x28e1000200c8006b /* 13 */
- .quad 0x0000204200c8002f /* 14 */
- .quad 0x0000000000030d40 /* 15 */
- .quad 0 /* 16 */
- .quad 0 /* 17 */
- .quad 0 /* 18 */
- .quad 0 /* 19 */
- .quad 0 /* 1a */
- .quad 0 /* 1b */
- .quad 0 /* 1c */
-
- .p2align
-
-write_dumpreg:
- ld $t2, 0($t6)
- sd $t2, 0($t4)
- addiu $t4, $t4, GRUB_CPU_LOONGSON_DDR2_REG_STEP
- jr $ra
- addiu $t6, $t6, GRUB_CPU_LOONGSON_DDR2_REG_SIZE
-
-continue:
- lui $t4, %hi(GRUB_CPU_LOONGSON_DDR2_BASE)
- addiu $t4, $t4, %lo(GRUB_CPU_LOONGSON_DDR2_BASE)
- lui $t6, %hi(regdump)
-
- /* 0 */
- bal write_dumpreg
- addiu $t6, $t6, %lo(regdump)
-
- /* 1 */
- ori $a1, $a1, GRUB_SMB_RAM_START_ADDR
- move $t8, $zero
- lui $t5, 0x0001
- bal read_spd
- ori $a0, $zero, GRUB_SMBUS_SPD_MEMORY_NUM_BANKS_ADDR
- ori $t7, $zero, 8
- bne $v0, $t7, 1f
- ori $t5, $t5, 0x0001
- ori $t8, $t8, GRUB_CPU_LOONGSON_DDR2_REG1_HI_8BANKS
-1:
- dsll $t8, $t8, 32
- or $t5, $t5, $t8
- sd $t5, 0 ($t4)
- addiu $t4, $t4, GRUB_CPU_LOONGSON_DDR2_REG_STEP
-
- /* 2 */
- bal write_dumpreg
- nop
-
- /* 3 */
- bal write_dumpreg
- nop
-
- /* 4 */
- bal write_dumpreg
- nop
-
- /* 5 */
- /* FIXME: figure termination resistance. */
- ori $t5, $zero, 0x2
- bal read_spd
- ori $a0, $zero, GRUB_SMBUS_SPD_MEMORY_NUM_ROWS_ADDR
- /* $v0 = 15 - $v0. */
- xori $v0, $v0, 0xf
- andi $v0, $v0, 0x7
- sll $v0, $v0, 8
- or $t5, $t5, $v0
-
- /* Find the fastest supported CAS latency. */
- bal read_spd
- ori $a0, $zero, GRUB_SMBUS_SPD_MEMORY_CAS_LATENCY_ADDR
- ori $t0, $zero, GRUB_SMBUS_SPD_MEMORY_CAS_LATENCY_MIN_VALUE
- ori $t1, $zero, (1 << GRUB_SMBUS_SPD_MEMORY_CAS_LATENCY_MIN_VALUE)
-2:
- and $t2, $t1, $v0
- bne $t2, $zero, 1f
- ori $t3, $zero, 8
- lui $a0, %hi(no_cas_latency)
- beq $t0, $t3, fatal
- addiu $a0, $a0, %lo(no_cas_latency)
- addiu $t0, $t0, 1
- b 2b
- sll $t1, $t1, 1
-1:
- sll $t0, $t0, 16
- or $t5, $t5, $t0
-
- bal read_spd
- ori $a0, $zero, GRUB_SMBUS_SPD_MEMORY_NUM_COLUMNS_ADDR
- /* $v0 = 15 - ($v0 + 1) = 14 - $v0. */
- addiu $v0, $v0, 1
- xori $v0, $v0, 0xf
- andi $v0, $v0, 0x7
- sll $v0, 24
- or $t5, $t5, $v0
- sd $t5, 0 ($t4)
-
- addiu $t4, $t4, GRUB_CPU_LOONGSON_DDR2_REG_STEP
-
- ori $t7, $zero, 0x16
-
-1:
- ld $t2, 0($t6)
- sd $t2, 0($t4)
- addiu $t4, $t4, GRUB_CPU_LOONGSON_DDR2_REG_STEP
- addiu $t7, $t7, -1
- bne $t7, $zero, 1b
- addiu $t6, $t6, GRUB_CPU_LOONGSON_DDR2_REG_SIZE
-
- lui $t4, %hi(GRUB_CPU_LOONGSON_DDR2_BASE)
- ld $t5, (%lo(GRUB_CPU_LOONGSON_DDR2_BASE) + 0x30) ($t4)
- ori $t0, $zero, 1
- dsll $t0, $t0, 40
- or $t5, $t5, $t0
- sd $t5, (%lo(GRUB_CPU_LOONGSON_DDR2_BASE) + 0x30) ($t4)
-
- /* Desactivate DDR2 registers. */
- lui $t0, %hi (GRUB_CPU_LOONGSON_CORECFG)
- ld $t1, %lo (GRUB_CPU_LOONGSON_CORECFG) ($t0)
- ori $t1, $t1, GRUB_CPU_LOONGSON_CORECFG_DISABLE_DDR2_SPACE
- sd $t1, %lo (GRUB_CPU_LOONGSON_CORECFG) ($t0)
-
- /* Enable cache. */
- mfc0 $t0, GRUB_CPU_LOONGSON_COP0_CACHE_CONFIG
- addiu $t1, $zero, ~GRUB_CPU_LOONGSON_CACHE_TYPE_MASK
- and $t0, $t1, $t1
- /* Set line size to 32 bytes and disabled cache. */
- ori $t0, $t0, (GRUB_CPU_LOONGSON_COP0_CACHE_CONFIG_ILINESIZE \
- | GRUB_CPU_LOONGSON_COP0_CACHE_CONFIG_DLINESIZE \
- | GRUB_CPU_LOONGSON_CACHE_ACCELERATED)
- mtc0 $t0, GRUB_CPU_LOONGSON_COP0_CACHE_CONFIG
-
- /* Invalidate all I-cache entries. */
- srl $t1, $t0, GRUB_CPU_LOONGSON_COP0_CACHE_ISIZE_SHIFT
- andi $t1, $t1, GRUB_CPU_LOONGSON_COP0_CACHE_SIZE_MASK
- ori $t2, $zero, (1 << (GRUB_CPU_LOONGSON_COP0_CACHE_SIZE_OFFSET \
- - GRUB_CPU_LOONGSON_CACHE_LINE_SIZE_LOG_BIG \
- - GRUB_CPU_LOONGSON_I_CACHE_LOG_WAYS))
- sll $t1, $t2, $t1
- lui $t2, 0x8000
-
-1:
- cache GRUB_CPU_LOONGSON_COP0_I_INDEX_INVALIDATE, 0($t2)
- addiu $t1, $t1, -1
- bne $t1, $zero, 1b
- addiu $t2, $t2, (1 << GRUB_CPU_LOONGSON_COP0_I_INDEX_BIT_OFFSET)
-
- /* Invalidate all D-cache entries. */
- srl $t1, $t0, GRUB_CPU_LOONGSON_COP0_CACHE_DSIZE_SHIFT
- andi $t1, $t1, GRUB_CPU_LOONGSON_COP0_CACHE_SIZE_MASK
- ori $t2, $zero, (1 << (GRUB_CPU_LOONGSON_COP0_CACHE_SIZE_OFFSET \
- - GRUB_CPU_LOONGSON_CACHE_LINE_SIZE_LOG_BIG \
- - GRUB_CPU_LOONGSON_D_CACHE_LOG_WAYS))
- sll $t1, $t2, $t1
- lui $t2, 0x8000
- mtc0 $zero, GRUB_CPU_LOONGSON_COP0_CACHE_TAGLO
- mtc0 $zero, GRUB_CPU_LOONGSON_COP0_CACHE_TAGHI
-1:
- /* All four ways. */
- cache GRUB_CPU_LOONGSON_COP0_D_INDEX_TAG_STORE, 0($t2)
- cache GRUB_CPU_LOONGSON_COP0_D_INDEX_TAG_STORE, 1($t2)
- cache GRUB_CPU_LOONGSON_COP0_D_INDEX_TAG_STORE, 2($t2)
- cache GRUB_CPU_LOONGSON_COP0_D_INDEX_TAG_STORE, 3($t2)
- addiu $t1, $t1, -1
- bne $t1, $zero, 1b
- addiu $t2, $t2, (1 << GRUB_CPU_LOONGSON_COP0_D_INDEX_BIT_OFFSET)
-
- /* Invalidate all S-cache entries. */
- ori $t1, $zero, (1 << (GRUB_CPU_LOONGSON_SECONDARY_CACHE_LOG_SIZE \
- - GRUB_CPU_LOONGSON_CACHE_LINE_SIZE_LOG_BIG \
- - GRUB_CPU_LOONGSON_S_CACHE_LOG_WAYS))
- lui $t2, 0x8000
- mtc0 $zero, GRUB_CPU_LOONGSON_COP0_CACHE_TAGLO
- mtc0 $zero, GRUB_CPU_LOONGSON_COP0_CACHE_TAGHI
-1:
- /* All four ways. */
- cache GRUB_CPU_LOONGSON_COP0_S_INDEX_TAG_STORE, 0($t2)
- cache GRUB_CPU_LOONGSON_COP0_S_INDEX_TAG_STORE, 1($t2)
- cache GRUB_CPU_LOONGSON_COP0_S_INDEX_TAG_STORE, 2($t2)
- cache GRUB_CPU_LOONGSON_COP0_S_INDEX_TAG_STORE, 3($t2)
- addiu $t1, $t1, -1
- bne $t1, $zero, 1b
- addiu $t2, $t2, (1 << GRUB_CPU_LOONGSON_COP0_D_INDEX_BIT_OFFSET)
-
- /* Finally enable cache. */
- mfc0 $t0, GRUB_CPU_LOONGSON_COP0_CACHE_CONFIG
- addiu $t1, $zero, ~GRUB_CPU_LOONGSON_CACHE_TYPE_MASK
- and $t0, $t1, $t1
- ori $t0, $t0, GRUB_CPU_LOONGSON_CACHE_CACHED
- mtc0 $t0, GRUB_CPU_LOONGSON_COP0_CACHE_CONFIG
-
- lui $a0, %hi(caches_enabled)
- bal message
- addiu $a0, $a0, %lo(caches_enabled)
-
- /* Set ROM delay cycles to 1. */
- lui $t0, %hi(GRUB_CPU_LOONGSON_LIOCFG)
- lw $t1, %lo(GRUB_CPU_LOONGSON_LIOCFG) ($t0)
- addiu $t2, $zero, ~(GRUB_CPU_LOONGSON_ROM_DELAY_MASK \
- << GRUB_CPU_LOONGSON_ROM_DELAY_OFFSET)
- and $t1, $t1, $t2
- ori $t1, $t1, (1 << GRUB_CPU_LOONGSON_ROM_DELAY_OFFSET)
- sw $t1, %lo(GRUB_CPU_LOONGSON_LIOCFG) ($t0)
-
- addiu $a0, $zero, -1
- addiu $a1, $zero, -1
-
- /* Take advantage of cache. */
- lui $t0, %hi(cached_continue - 0x20000000)
- addiu $t0, $t0, %lo(cached_continue - 0x20000000)
- jr $t0
- addiu $a2, $zero, -1
-
-cached_continue:
\ No newline at end of file
#include <grub/pci.h>
#include <grub/time.h>
#include <grub/ata.h>
+#ifdef GRUB_MACHINE_MIPS_LOONGSON
+#include <grub/machine/kernel.h>
+#endif
+
+#include <grub/dl.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
int
grub_cs5536_find (grub_pci_device_t *devp)
return GRUB_ERR_NONE;
}
-/* Dump of GPIO connections. FIXME: Remove useless and macroify. */
-static grub_uint32_t gpiodump[] = {
- 0xffff0000, 0x2ffdd002, 0xffff0000, 0xffff0000,
- 0x2fffd000, 0xffff0000, 0x1000efff, 0xefff1000,
- 0x3ffbc004, 0xffff0000, 0xffff0000, 0xffff0000,
- 0x3ffbc004, 0x3ffbc004, 0xffff0000, 0x00000000,
- 0xffff0000, 0xffff0000, 0x3ffbc004, 0x3f9bc064,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0xffff0000, 0xffff0000, 0xffff0000, 0xffff0000,
- 0xffff0000, 0xffff0000, 0x0000ffff, 0xffff0000,
- 0xefff1000, 0xffff0000, 0xffff0000, 0xffff0000,
- 0xefff1000, 0xefff1000, 0xffff0000, 0x00000000,
- 0xffff0000, 0xffff0000, 0xefff1000, 0xffff0000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x50000000, 0x00000000, 0x00000000,
-};
-
static inline void
set_io_space (grub_pci_device_t dev, int num, grub_uint16_t start,
grub_uint16_t len)
void
grub_cs5536_init_geode (grub_pci_device_t dev)
{
- int i;
-
- /* Make sure GPIO is where we expect it to be. */
- grub_cs5536_write_msr (dev, GRUB_CS5536_MSR_GPIO_BAR,
- GRUB_CS5536_LBAR_TURN_ON | GRUB_CS5536_LBAR_GPIO);
-
- /* Setup GPIO. */
- for (i = 0; i < (int) ARRAY_SIZE (gpiodump); i++)
- ((volatile grub_uint32_t *) (GRUB_MACHINE_PCI_IO_BASE
- + GRUB_CS5536_LBAR_GPIO)) [i] = gpiodump[i];
-
/* Enable more BARs. */
grub_cs5536_write_msr (dev, GRUB_CS5536_MSR_IRQ_MAP_BAR,
GRUB_CS5536_LBAR_TURN_ON | GRUB_CS5536_LBAR_IRQ_MAP);
GRUB_CS5536_LBAR_TURN_ON | GRUB_CS5536_LBAR_PM);
/* Setup DIVIL. */
- grub_cs5536_write_msr (dev, GRUB_CS5536_MSR_DIVIL_LEG_IO,
- GRUB_CS5536_MSR_DIVIL_LEG_IO_MODE_X86
- | GRUB_CS5536_MSR_DIVIL_LEG_IO_F_REMAP
- | GRUB_CS5536_MSR_DIVIL_LEG_IO_RTC_ENABLE0
- | GRUB_CS5536_MSR_DIVIL_LEG_IO_RTC_ENABLE1);
+#ifdef GRUB_MACHINE_MIPS_LOONGSON
+ switch (grub_arch_machine)
+ {
+ case GRUB_ARCH_MACHINE_YEELOONG:
+ grub_cs5536_write_msr (dev, GRUB_CS5536_MSR_DIVIL_LEG_IO,
+ GRUB_CS5536_MSR_DIVIL_LEG_IO_MODE_X86
+ | GRUB_CS5536_MSR_DIVIL_LEG_IO_F_REMAP
+ | GRUB_CS5536_MSR_DIVIL_LEG_IO_RTC_ENABLE0
+ | GRUB_CS5536_MSR_DIVIL_LEG_IO_RTC_ENABLE1);
+ break;
+ case GRUB_ARCH_MACHINE_FULOONG2F:
+ grub_cs5536_write_msr (dev, GRUB_CS5536_MSR_DIVIL_LEG_IO,
+ GRUB_CS5536_MSR_DIVIL_LEG_IO_UART2_COM3
+ | GRUB_CS5536_MSR_DIVIL_LEG_IO_UART1_COM1
+ | GRUB_CS5536_MSR_DIVIL_LEG_IO_MODE_X86
+ | GRUB_CS5536_MSR_DIVIL_LEG_IO_F_REMAP
+ | GRUB_CS5536_MSR_DIVIL_LEG_IO_RTC_ENABLE0
+ | GRUB_CS5536_MSR_DIVIL_LEG_IO_RTC_ENABLE1);
+ break;
+ }
+#endif
grub_cs5536_write_msr (dev, GRUB_CS5536_MSR_DIVIL_IRQ_MAPPER_PRIMARY_MASK,
(~GRUB_CS5536_DIVIL_LPC_INTERRUPTS) & 0xffff);
grub_cs5536_write_msr (dev, GRUB_CS5536_MSR_DIVIL_IRQ_MAPPER_LPC_MASK,
#include <grub/dl.h>
#include <grub/pci.h>
#include <grub/mm.h>
+#include <grub/misc.h>
+#include <grub/mm_private.h>
+#include <grub/cache.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
/* FIXME: correctly support 64-bit architectures. */
/* #if GRUB_TARGET_SIZEOF_VOID_P == 4 */
struct grub_pci_dma_chunk *
grub_memalign_dma32 (grub_size_t align, grub_size_t size)
{
- return grub_memalign (align, size);
+ void *ret;
+ if (align < 64)
+ align = 64;
+ size = ALIGN_UP (size, align);
+ ret = grub_memalign (align, size);
+ if (!ret)
+ return 0;
+ grub_arch_sync_dma_caches (ret, size);
+ return ret;
}
+/* FIXME: evil. */
void
grub_dma_free (struct grub_pci_dma_chunk *ch)
{
+ grub_size_t size = (((struct grub_mm_header *) ch) - 1)->size * GRUB_MM_ALIGN;
+ grub_arch_sync_dma_caches (ch, size);
grub_free (ch);
}
/* #endif */
-#ifdef GRUB_MACHINE_MIPS_YEELOONG
+#ifdef GRUB_MACHINE_MIPS_LOONGSON
volatile void *
grub_dma_get_virt (struct grub_pci_dma_chunk *ch)
{
continue;
}
-#ifdef GRUB_MACHINE_MIPS_YEELOONG
- /* Skip ghosts. */
- if (id == GRUB_YEELOONG_OHCI_PCIID
- && dev.function == GRUB_YEELOONG_OHCI_GHOST_FUNCTION)
- continue;
- if (id == GRUB_YEELOONG_EHCI_PCIID
- && dev.function == GRUB_YEELOONG_EHCI_GHOST_FUNCTION)
- continue;
-#endif
-
if (hook (dev, id))
return;
#include <grub/usb.h>
#include <grub/dl.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
\f
static struct grub_usb_controller_dev usb_controller =
{
#include <grub/cs5536.h>
#include <grub/loader.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
struct grub_ohci_hcca
{
/* Pointers to Interrupt Endpoint Descriptors. Not used by
fail:
if (o)
- grub_dma_free (o->td_chunk);
- grub_dma_free (o->ed_bulk_chunk);
- grub_dma_free (o->ed_ctrl_chunk);
- grub_dma_free (o->hcca_chunk);
+ {
+ grub_dma_free (o->td_chunk);
+ grub_dma_free (o->ed_bulk_chunk);
+ grub_dma_free (o->ed_ctrl_chunk);
+ grub_dma_free (o->hcca_chunk);
+ }
grub_free (o);
return 0;
.detect_dev = grub_ohci_detect_dev
};
+static void *fini_hnd;
+
GRUB_MOD_INIT(ohci)
{
COMPILE_TIME_ASSERT (sizeof (struct grub_ohci_td) == 32);
COMPILE_TIME_ASSERT (sizeof (struct grub_ohci_ed) == 16);
grub_ohci_inithw ();
grub_usb_controller_dev_register (&usb_controller);
- grub_loader_register_preboot_hook (grub_ohci_fini_hw, grub_ohci_restore_hw,
- GRUB_LOADER_PREBOOT_HOOK_PRIO_DISK);
+ fini_hnd = grub_loader_register_preboot_hook (grub_ohci_fini_hw,
+ grub_ohci_restore_hw,
+ GRUB_LOADER_PREBOOT_HOOK_PRIO_DISK);
}
GRUB_MOD_FINI(ohci)
{
grub_ohci_fini_hw (0);
+ grub_loader_unregister_preboot_hook (fini_hnd);
grub_usb_controller_dev_unregister (&usb_controller);
}
#include <grub/serial.h>
#include <grub/usbserial.h>
+#include <grub/dl.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
void
grub_usbserial_fini (struct grub_serial_port *port)
#include <grub/usb.h>
#include <grub/usbserial.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
enum
{
GRUB_FTDI_MODEM_CTRL = 0x01,
#include <grub/usb.h>
#include <grub/usbserial.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
/* Convert speed to divisor. */
static grub_uint32_t
is_speed_supported (unsigned int speed)
#include <grub/i386/io.h>
#include <grub/time.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
#define GRUB_UHCI_IOMASK (0x7FF << 5)
#define N_QH 256
typedef enum
{
GRUB_UHCI_REG_USBCMD = 0x00,
+ GRUB_UHCI_REG_USBINTR = 0x04,
GRUB_UHCI_REG_FLBASEADD = 0x08,
GRUB_UHCI_REG_PORTSC1 = 0x10,
- GRUB_UHCI_REG_PORTSC2 = 0x12
+ GRUB_UHCI_REG_PORTSC2 = 0x12,
+ GRUB_UHCI_REG_USBLEGSUP = 0xc0
} grub_uhci_reg_t;
+/* R/WC legacy support bits */
+#define GRUB_UHCI_LEGSUP_END_A20GATE (1 << 15)
+#define GRUB_UHCI_TRAP_BY_64H_WSTAT (1 << 11)
+#define GRUB_UHCI_TRAP_BY_64H_RSTAT (1 << 10)
+#define GRUB_UHCI_TRAP_BY_60H_WSTAT (1 << 9)
+#define GRUB_UHCI_TRAP_BY_60H_RSTAT (1 << 8)
+
+/* Reset all legacy support - clear all R/WC bits and all R/W bits */
+#define GRUB_UHCI_RESET_LEGSUP_SMI ( GRUB_UHCI_LEGSUP_END_A20GATE \
+ | GRUB_UHCI_TRAP_BY_64H_WSTAT \
+ | GRUB_UHCI_TRAP_BY_64H_RSTAT \
+ | GRUB_UHCI_TRAP_BY_60H_WSTAT \
+ | GRUB_UHCI_TRAP_BY_60H_RSTAT )
+
+/* Some UHCI commands */
+#define GRUB_UHCI_CMD_RUN_STOP (1 << 0)
+#define GRUB_UHCI_CMD_HCRESET (1 << 1)
+#define GRUB_UHCI_CMD_MAXP (1 << 7)
+
+/* Important bits in structures */
#define GRUB_UHCI_LINK_TERMINATE 1
#define GRUB_UHCI_LINK_QUEUE_HEAD 2
if (class != 0x0c || subclass != 0x03 || interf != 0x00)
return 0;
+ /* Set bus master - needed for coreboot or broken BIOSes */
+ addr = grub_pci_make_address (dev, GRUB_PCI_REG_COMMAND);
+ grub_pci_write_word(addr,
+ GRUB_PCI_COMMAND_BUS_MASTER | grub_pci_read_word(addr));
+
/* Determine IO base address. */
addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG4);
base = grub_pci_read (addr);
u->iobase = base & GRUB_UHCI_IOMASK;
+ /* Reset PIRQ and SMI */
+ addr = grub_pci_make_address (dev, GRUB_UHCI_REG_USBLEGSUP);
+ grub_pci_write_word(addr, GRUB_UHCI_RESET_LEGSUP_SMI);
+ /* Reset the HC */
+ grub_uhci_writereg16(u, GRUB_UHCI_REG_USBCMD, GRUB_UHCI_CMD_HCRESET);
+ grub_millisleep(5);
+ /* Disable interrupts and commands (just to be safe) */
+ grub_uhci_writereg16(u, GRUB_UHCI_REG_USBINTR, 0);
+ /* Finish HC reset, HC remains disabled */
+ grub_uhci_writereg16(u, GRUB_UHCI_REG_USBCMD, 0);
+ /* Read back to be sure PCI write is done */
+ grub_uhci_readreg16(u, GRUB_UHCI_REG_USBCMD);
+
/* Reserve a page for the frame list. */
u->framelist = grub_memalign (4096, 4096);
if (! u->framelist)
u->td[N_TD - 2].linkptr = 0;
u->tdfree = u->td;
- /* Make sure UHCI is disabled! */
- grub_uhci_writereg16 (u, GRUB_UHCI_REG_USBCMD, 0);
-
/* Setup the frame list pointers. Since no isochronous transfers
are and will be supported, they all point to the (same!) queue
head. */
u->qh[N_QH - 1].linkptr = 1;
/* Enable UHCI again. */
- grub_uhci_writereg16 (u, GRUB_UHCI_REG_USBCMD, 1 | (1 << 7));
+ grub_uhci_writereg16 (u, GRUB_UHCI_REG_USBCMD,
+ GRUB_UHCI_CMD_RUN_STOP | GRUB_UHCI_CMD_MAXP);
/* UHCI is initialized and ready for transfers. */
grub_dprintf ("uhci", "UHCI initialized\n");
#include <grub/list.h>
#include <grub/term.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
static grub_usb_controller_dev_t grub_usb_list;
static struct grub_usb_attach_desc *attach_hooks;
for (i = 0; i < 8; i++)
dev->config[i].descconf = NULL;
+ if (descdev->configcnt == 0)
+ {
+ err = GRUB_USB_ERR_BADDEVICE;
+ goto fail;
+ }
+
for (i = 0; i < descdev->configcnt; i++)
{
int pos;
return;
hub->controller->dev->pending_reset = grub_get_time_ms () + 5000;
+ grub_millisleep (10);
+
/* Enable the port and create a device. */
dev = grub_usb_hub_add_dev (hub->controller, speed);
hub->controller->dev->pending_reset = 0;
GRUB_USB_REQ_GET_STATUS,
0, i, sizeof (status), (char *) &status);
- grub_printf ("dev = %p, i = %d, status = %08x\n",
- dev, i, status);
+ grub_dprintf ("usb", "dev = %p, i = %d, status = %08x\n",
+ dev, i, status);
if (err)
continue;
#include <grub/efi/api.h>
#endif
+GRUB_MOD_LICENSE ("GPLv3+");
+
static const struct grub_arg_option options[] = {
{"exclude", 'x', 0,
N_("Don't load host tables specified by comma-separated list."),
--- /dev/null
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2011 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/dl.h>
+#include <grub/misc.h>
+#include <grub/command.h>
+#include <grub/i18n.h>
+#include <grub/arc/arc.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
+
+static grub_err_t
+grub_cmd_lsdev (grub_command_t cmd __attribute__ ((unused)),
+ int argc __attribute__ ((unused)),
+ char **args __attribute__ ((unused)))
+{
+ auto int hook (const char *name, const struct grub_arc_component *comp);
+ int hook (const char *name, const struct grub_arc_component *comp __attribute__ ((unused)))
+ {
+ grub_printf ("%s\n", name);
+ return 0;
+ }
+ grub_arc_iterate_devs (hook, 0);
+ return 0;
+}
+
+static grub_command_t cmd;
+
+GRUB_MOD_INIT(lsdev)
+{
+ cmd = grub_register_command ("lsdev", grub_cmd_lsdev, "",
+ N_("List devices."));
+}
+
+GRUB_MOD_FINI(lsdev)
+{
+ grub_unregister_command (cmd);
+}
#include <grub/command.h>
#include <grub/i18n.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
static grub_err_t
grub_cmd_blocklist (grub_command_t cmd __attribute__ ((unused)),
int argc, char **args)
#include <grub/mm.h>
#include <grub/i18n.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
static grub_err_t (*grub_loader_boot_func) (void);
static grub_err_t (*grub_loader_unload_func) (void);
static int grub_loader_noreturn;
--- /dev/null
+/* cacheinfo.c - disk cache statistics */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2008,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/misc.h>
+#include <grub/command.h>
+#include <grub/i18n.h>
+#include <grub/disk.h>
+
+static grub_err_t
+grub_rescue_cmd_info (struct grub_command *cmd __attribute__ ((unused)),
+ int argc __attribute__ ((unused)),
+ char *argv[] __attribute__ ((unused)))
+{
+ unsigned long hits, misses;
+
+ grub_disk_cache_get_performance (&hits, &misses);
+ grub_printf ("Disk cache: hits = %lu, misses = %lu ", hits, misses);
+ if (hits + misses)
+ {
+ unsigned long ratio = hits * 10000 / (hits + misses);
+ grub_printf ("(%lu.%lu%%)\n", ratio / 100, ratio % 100);
+ }
+ else
+ grub_printf ("(N/A)\n");
+
+ return 0;
+}
+
+static grub_command_t cmd_cacheinfo;
+
+GRUB_MOD_INIT(cacheinfo)
+{
+ cmd_cacheinfo =
+ grub_register_command ("cacheinfo", grub_rescue_cmd_info,
+ 0, N_("Get disk cache info."));
+}
+
+GRUB_MOD_FINI(cacheinfo)
+{
+ grub_unregister_command (cmd_cacheinfo);
+}
#include <grub/extcmd.h>
#include <grub/i18n.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
static const struct grub_arg_option options[] =
{
{"dos", -1, 0, N_("Accept DOS-style CR/NL line endings."), 0, 0},
#include <grub/command.h>
#include <grub/i18n.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
#define BUFFER_SIZE 512
static grub_err_t
cleanup:
- if (buf1)
- grub_free (buf1);
- if (buf2)
- grub_free (buf2);
+ grub_free (buf1);
+ grub_free (buf2);
if (file1)
grub_file_close (file1);
if (file2)
#include <grub/command.h>
#include <grub/i18n.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
static grub_err_t
grub_cmd_source (grub_command_t cmd, int argc, char **args)
{
#include <grub/command.h>
#include <grub/i18n.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
#define GRUB_DATETIME_SET_YEAR 1
#define GRUB_DATETIME_SET_MONTH 2
#define GRUB_DATETIME_SET_DAY 4
#include <grub/i18n.h>
#include <grub/term.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
static const struct grub_arg_option options[] =
{
{0, 'n', 0, N_("Do not output the trailing newline."), 0, 0},
#include <grub/command.h>
#include <grub/i18n.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
static struct grub_video_patch
{
const char *name;
#include <grub/command.h>
#include <grub/i18n.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
static grub_efi_guid_t acpi_guid = GRUB_EFI_ACPI_TABLE_GUID;
static grub_efi_guid_t acpi2_guid = GRUB_EFI_ACPI_20_TABLE_GUID;
static grub_efi_guid_t smbios_guid = GRUB_EFI_SMBIOS_TABLE_GUID;
#include <grub/efi/efi.h>
#include <grub/command.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
#define ADD_MEMORY_DESCRIPTOR(desc, size) \
((grub_efi_memory_descriptor_t *) ((char *) (desc) + (size)))
*/
#include <grub/types.h>
#include <grub/mm.h>
+#include <grub/dl.h>
#include <grub/misc.h>
#include <grub/normal.h>
#include <grub/charset.h>
#include <grub/efi/api.h>
#include <grub/efi/efi.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
struct guid_mapping
{
grub_efi_guid_t guid;
#include <grub/charset.h>
#include <grub/efi/api.h>
#include <grub/efi/efi.h>
+#include <grub/dl.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
static void
disp_sal (void *table)
#include <grub/misc.h>
#include <grub/extcmd.h>
#include <grub/script_sh.h>
+#include <grub/dl.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
grub_err_t
grub_extcmd_dispatcher (struct grub_command *cmd, int argc, char **args,
#include <grub/fs.h>
#include <grub/i18n.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
/* Convert a LBA address to a CHS address in the INT 13 format. */
/* Taken from grub1. */
/* XXX: use hardcoded geometry of C = 1024, H = 255, S = 63.
#include <grub/misc.h>
#include <grub/i18n.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
static grub_err_t
grub_cmd_halt (grub_command_t cmd __attribute__ ((unused)),
int argc __attribute__ ((unused)),
#include <grub/normal.h>
#include <grub/i18n.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
static const struct grub_arg_option options[] = {
{"hash", 'h', 0, N_("Specify hash to use."), N_("HASH"), ARG_TYPE_STRING},
{"check", 'c', 0, N_("Check hash list file."), N_("FILE"), ARG_TYPE_STRING},
*/
#include <grub/ata.h>
+#include <grub/scsi.h>
#include <grub/disk.h>
#include <grub/dl.h>
#include <grub/misc.h>
#include <grub/extcmd.h>
#include <grub/i18n.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
static const struct grub_arg_option options[] = {
{"apm", 'B', 0, N_("Set Advanced Power Management\n"
"(1=low, ..., 254=high, 255=off)."),
static int quiet = 0;
static grub_err_t
-grub_hdparm_do_ata_cmd (grub_disk_t disk, grub_uint8_t cmd,
+grub_hdparm_do_ata_cmd (grub_ata_t ata, grub_uint8_t cmd,
grub_uint8_t features, grub_uint8_t sectors,
void * buffer, int size)
{
struct grub_disk_ata_pass_through_parms apt;
grub_memset (&apt, 0, sizeof (apt));
- apt.taskfile[GRUB_ATA_REG_CMD] = cmd;
- apt.taskfile[GRUB_ATA_REG_FEATURES] = features;
- apt.taskfile[GRUB_ATA_REG_SECTORS] = sectors;
+ apt.taskfile.cmd = cmd;
+ apt.taskfile.features = features;
+ apt.taskfile.sectors = sectors;
+ apt.taskfile.disk = 0xE0;
+
apt.buffer = buffer;
apt.size = size;
- if (grub_disk_ata_pass_through (disk, &apt))
+ if (ata->dev->readwrite (ata, &apt, 0))
return grub_errno;
return GRUB_ERR_NONE;
}
static int
-grub_hdparm_do_check_powermode_cmd (grub_disk_t disk)
+grub_hdparm_do_check_powermode_cmd (grub_ata_t ata)
{
struct grub_disk_ata_pass_through_parms apt;
grub_memset (&apt, 0, sizeof (apt));
- apt.taskfile[GRUB_ATA_REG_CMD] = GRUB_ATA_CMD_CHECK_POWER_MODE;
+ apt.taskfile.cmd = GRUB_ATA_CMD_CHECK_POWER_MODE;
+ apt.taskfile.disk = 0xE0;
- if (grub_disk_ata_pass_through (disk, &apt))
+ if (ata->dev->readwrite (ata, &apt, 0))
return -1;
- return apt.taskfile[GRUB_ATA_REG_SECTORS];
+ return apt.taskfile.sectors;
}
static int
-grub_hdparm_do_smart_cmd (grub_disk_t disk, grub_uint8_t features)
+grub_hdparm_do_smart_cmd (grub_ata_t ata, grub_uint8_t features)
{
struct grub_disk_ata_pass_through_parms apt;
grub_memset (&apt, 0, sizeof (apt));
- apt.taskfile[GRUB_ATA_REG_CMD] = GRUB_ATA_CMD_SMART;
- apt.taskfile[GRUB_ATA_REG_FEATURES] = features;
- apt.taskfile[GRUB_ATA_REG_LBAMID] = 0x4f;
- apt.taskfile[GRUB_ATA_REG_LBAHIGH] = 0xc2;
+ apt.taskfile.cmd = GRUB_ATA_CMD_SMART;
+ apt.taskfile.features = features;
+ apt.taskfile.lba_mid = 0x4f;
+ apt.taskfile.lba_high = 0xc2;
+ apt.taskfile.disk = 0xE0;
- if (grub_disk_ata_pass_through (disk, &apt))
+ if (ata->dev->readwrite (ata, &apt, 0))
return -1;
if (features == GRUB_ATA_FEAT_SMART_STATUS)
{
- if ( apt.taskfile[GRUB_ATA_REG_LBAMID] == 0x4f
- && apt.taskfile[GRUB_ATA_REG_LBAHIGH] == 0xc2)
+ if ( apt.taskfile.lba_mid == 0x4f
+ && apt.taskfile.lba_high == 0xc2)
return 0; /* Good SMART status. */
- else if ( apt.taskfile[GRUB_ATA_REG_LBAMID] == 0xf4
- && apt.taskfile[GRUB_ATA_REG_LBAHIGH] == 0x2c)
+ else if ( apt.taskfile.lba_mid == 0xf4
+ && apt.taskfile.lba_high == 0x2c)
return 1; /* Bad SMART status. */
else
return -1;
static grub_err_t
grub_hdparm_simple_cmd (const char * msg,
- grub_disk_t disk, grub_uint8_t cmd)
+ grub_ata_t ata, grub_uint8_t cmd)
{
if (! quiet && msg)
grub_printf ("%s", msg);
- grub_err_t err = grub_hdparm_do_ata_cmd (disk, cmd, 0, 0, NULL, 0);
+ grub_err_t err = grub_hdparm_do_ata_cmd (ata, cmd, 0, 0, NULL, 0);
if (! quiet && msg)
grub_printf ("%s\n", ! err ? "" : ": not supported");
static grub_err_t
grub_hdparm_set_val_cmd (const char * msg, int val,
- grub_disk_t disk, grub_uint8_t cmd,
+ grub_ata_t ata, grub_uint8_t cmd,
grub_uint8_t features, grub_uint8_t sectors)
{
if (! quiet && msg && *msg)
grub_printf ("Disable %s", msg);
}
- grub_err_t err = grub_hdparm_do_ata_cmd (disk, cmd, features, sectors,
+ grub_err_t err = grub_hdparm_do_ata_cmd (ata, cmd, features, sectors,
NULL, 0);
if (! quiet && msg)
grub_cmd_hdparm (grub_extcmd_context_t ctxt, int argc, char **args) // state????
{
struct grub_arg_list *state = ctxt->state;
+ struct grub_ata *ata;
/* Check command line. */
if (argc != 1)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "argument is not a device name");
args[0][len - 1] = 0;
- if (! grub_disk_ata_pass_through)
- return grub_error (GRUB_ERR_BAD_ARGUMENT, "ATA pass through not available");
-
int i = 0;
int apm = get_int_arg (&state[i++]);
int power = state[i++].set;
return grub_error (GRUB_ERR_BAD_ARGUMENT, "partition not allowed");
}
+ switch (disk->dev->id)
+ {
+ case GRUB_DISK_DEVICE_ATA_ID:
+ ata = disk->data;
+ break;
+ case GRUB_DISK_DEVICE_SCSI_ID:
+ if (((disk->id >> GRUB_SCSI_ID_SUBSYSTEM_SHIFT) & 0xFF)
+ == GRUB_SCSI_SUBSYSTEM_PATA
+ || (((disk->id >> GRUB_SCSI_ID_SUBSYSTEM_SHIFT) & 0xFF)
+ == GRUB_SCSI_SUBSYSTEM_AHCI))
+ {
+ ata = ((struct grub_scsi *) disk->data)->data;
+ break;
+ }
+ default:
+ return grub_error (GRUB_ERR_IO, "not an ATA device");
+ }
+
+
/* Change settings. */
if (aam >= 0)
grub_hdparm_set_val_cmd ("Automatic Acoustic Management", (aam ? aam : -1),
- disk, GRUB_ATA_CMD_SET_FEATURES, (aam ? 0x42 : 0xc2), aam);
+ ata, GRUB_ATA_CMD_SET_FEATURES,
+ (aam ? 0x42 : 0xc2), aam);
if (apm >= 0)
grub_hdparm_set_val_cmd ("Advanced Power Management",
- (apm != 255 ? apm : -1), disk, GRUB_ATA_CMD_SET_FEATURES,
- (apm != 255 ? 0x05 : 0x85), (apm != 255 ? apm : 0));
+ (apm != 255 ? apm : -1), ata,
+ GRUB_ATA_CMD_SET_FEATURES,
+ (apm != 255 ? 0x05 : 0x85),
+ (apm != 255 ? apm : 0));
if (standby_tout >= 0)
{
grub_printf (")");
}
/* The IDLE cmd sets disk to idle mode and configures standby timer. */
- grub_hdparm_set_val_cmd ("", -1, disk, GRUB_ATA_CMD_IDLE, 0, standby_tout);
+ grub_hdparm_set_val_cmd ("", -1, ata, GRUB_ATA_CMD_IDLE, 0, standby_tout);
}
if (enable_smart >= 0)
{
if (! quiet)
grub_printf ("%sable SMART operations", (enable_smart ? "En" : "Dis"));
- int err = grub_hdparm_do_smart_cmd (disk, (enable_smart ?
+ int err = grub_hdparm_do_smart_cmd (ata, (enable_smart ?
GRUB_ATA_FEAT_SMART_ENABLE : GRUB_ATA_FEAT_SMART_DISABLE));
if (! quiet)
grub_printf ("%s\n", err ? ": not supported" : "");
}
if (sec_freeze)
- grub_hdparm_simple_cmd ("Freeze security settings", disk,
+ grub_hdparm_simple_cmd ("Freeze security settings", ata,
GRUB_ATA_CMD_SECURITY_FREEZE_LOCK);
/* Print/dump IDENTIFY. */
if (ident || dumpid)
{
char buf[GRUB_DISK_SECTOR_SIZE];
- if (grub_hdparm_do_ata_cmd (disk, GRUB_ATA_CMD_IDENTIFY_DEVICE,
+ if (grub_hdparm_do_ata_cmd (ata, GRUB_ATA_CMD_IDENTIFY_DEVICE,
0, 0, buf, sizeof (buf)))
grub_printf ("Cannot read ATA IDENTIFY data\n");
else
if (power)
{
grub_printf ("Disk power mode is: ");
- int mode = grub_hdparm_do_check_powermode_cmd (disk);
+ int mode = grub_hdparm_do_check_powermode_cmd (ata);
if (mode < 0)
grub_printf ("unknown\n");
else
{
if (! quiet)
grub_printf ("SMART status is: ");
- int err = grub_hdparm_do_smart_cmd (disk, GRUB_ATA_FEAT_SMART_STATUS);
+ int err = grub_hdparm_do_smart_cmd (ata, GRUB_ATA_FEAT_SMART_STATUS);
if (! quiet)
grub_printf ("%s\n", (err < 0 ? "unknown" :
err == 0 ? "OK" : "*BAD*"));
/* Change power mode. */
if (standby_now)
- grub_hdparm_simple_cmd ("Set disk to standby mode", disk,
+ grub_hdparm_simple_cmd ("Set disk to standby mode", ata,
GRUB_ATA_CMD_STANDBY_IMMEDIATE);
if (sleep_now)
- grub_hdparm_simple_cmd ("Set disk to sleep mode", disk,
+ grub_hdparm_simple_cmd ("Set disk to sleep mode", ata,
GRUB_ATA_CMD_SLEEP);
grub_disk_close (disk);
#include <grub/normal.h>
#include <grub/charset.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
static grub_err_t
grub_cmd_help (grub_extcmd_context_t ctxt __attribute__ ((unused)), int argc,
char **args)
#include <grub/extcmd.h>
#include <grub/i18n.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
static const struct grub_arg_option options[] = {
{"skip", 's', 0, N_("Skip offset bytes from the beginning of file."), 0,
ARG_TYPE_INT},
#include <grub/misc.h>
#include <grub/cmos.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
static grub_err_t
parse_args (int argc, char *argv[], int *byte, int *bit)
{
{
int byte, bit;
grub_err_t err;
+ grub_uint8_t value;
err = parse_args (argc, argv, &byte, &bit);
if (err)
return err;
- if (grub_cmos_read (byte) & (1 << bit))
+ err = grub_cmos_read (byte, &value);
+ if (err)
+ return err;
+
+ if (value & (1 << bit))
return GRUB_ERR_NONE;
return grub_error (GRUB_ERR_TEST_FAILURE, "false");
{
int byte, bit;
grub_err_t err;
+ grub_uint8_t value;
err = parse_args (argc, argv, &byte, &bit);
+ if (err)
+ return err;
+ err = grub_cmos_read (byte, &value);
if (err)
return err;
- grub_cmos_write (byte, grub_cmos_read (byte) & (~(1 << bit)));
- return GRUB_ERR_NONE;
+ return grub_cmos_write (byte, value & (~(1 << bit)));
}
static grub_command_t cmd, cmd_clean;
#include <grub/i386/cpuid.h>
#include <grub/i18n.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
#define cpuid(num,a,b,c,d) \
asm volatile ("xchgl %%ebx, %1; cpuid; xchgl %%ebx, %1" \
: "=a" (a), "=r" (b), "=c" (c), "=d" (d) \
#include <grub/memory.h>
#include <grub/machine/memory.h>
+GRUB_MOD_LICENSE ("GPLv3+");
/* Real mode IVT slot (seg:off far pointer) for interrupt 0x13. */
static grub_uint32_t *const int13slot = UINT_TO_PTR (4 * 0x13);
#include <grub/machine/int.h>
#include <grub/acpi.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
static const struct grub_arg_option options[] =
{
{"no-apm", 'n', 0, N_("Do not use APM to halt the computer."), 0, 0},
#include <grub/command.h>
#include <grub/i18n.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
int
grub_apm_get_info (struct grub_apm_info *info)
{
#include <grub/command.h>
#include <grub/i18n.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
#define BASE_TEMPO (60 * GRUB_TICKS_PER_SECOND)
/* The speaker port. */
file = grub_file_open (args[0]);
if (! file)
- return grub_error (GRUB_ERR_FILE_NOT_FOUND, "file not found");
+ return grub_error (GRUB_ERR_FILE_NOT_FOUND, "file `%s' not found", args[0]);
if (grub_file_read (file, &tempo, sizeof (tempo)) != sizeof (tempo))
{
if (*end)
/* Was not a number either, assume it was supposed to be a file name. */
- return grub_error (GRUB_ERR_FILE_NOT_FOUND, "file not found");
+ return grub_error (GRUB_ERR_FILE_NOT_FOUND, "file `%s' not found", args[0]);
grub_dprintf ("play","tempo = %d\n", tempo);
+++ /dev/null
-/* pxe.c - command to control the pxe driver */
-/*
- * GRUB -- GRand Unified Bootloader
- * Copyright (C) 2008,2009 Free Software Foundation, Inc.
- *
- * GRUB is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * GRUB is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <grub/dl.h>
-#include <grub/err.h>
-#include <grub/misc.h>
-#include <grub/machine/pxe.h>
-#include <grub/command.h>
-#include <grub/i18n.h>
-
-static grub_err_t
-grub_cmd_pxe_unload (grub_command_t cmd __attribute__ ((unused)),
- int argc __attribute__ ((unused)),
- char **args __attribute__ ((unused)))
-{
- if (! grub_pxe_pxenv)
- return grub_error (GRUB_ERR_FILE_NOT_FOUND, "no pxe environment");
-
- grub_pxe_unload ();
-
- return 0;
-}
-
-static grub_command_t cmd;
-
-GRUB_MOD_INIT(pxecmd)
-{
- cmd = grub_register_command ("pxe_unload", grub_cmd_pxe_unload,
- 0,
- N_("Unload PXE environment."));
-}
-
-GRUB_MOD_FINI(pxecmd)
-{
- grub_unregister_command (cmd);
-}
#include <grub/cpu/io.h>
#include <grub/loader.h>
+GRUB_MOD_LICENSE ("GPLv2+");
+
static char sendkey[0x20];
/* Length of sendkey. */
static int keylen = 0;
#include <grub/command.h>
#include <grub/i18n.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
static grub_err_t
grub_cmd_suspend (grub_command_t cmd __attribute__ ((unused)),
int argc __attribute__ ((unused)),
#include <grub/cpu/io.h>
#include <grub/i18n.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
static grub_extcmd_t cmd_read_byte, cmd_read_word, cmd_read_dword;
static grub_command_t cmd_write_byte, cmd_write_word, cmd_write_dword;
#include <grub/i18n.h>
#include <grub/file.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
static struct grub_keyboard_layout layout_us = {
.keyboard_map = {
/* Keyboard errors. Handled by driver. */
#include <grub/term.h>
#include <grub/i18n.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
static const struct grub_arg_option options[] =
{
{"shift", 's', 0, N_("Check Shift key."), 0, 0},
#include <grub/disk.h>
#include <grub/partition.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
static grub_err_t
legacy_file (const char *filename)
{
#include <grub/extcmd.h>
#include <grub/i18n.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
static const struct grub_arg_option options[] =
{
{"file", 'f', 0, N_("Specify filename."), 0, ARG_TYPE_PATHNAME},
#include <grub/extcmd.h>
#include <grub/datetime.h>
#include <grub/i18n.h>
+#include <grub/net.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
static const struct grub_arg_option options[] =
{
grub_device_iterate (grub_ls_print_devices);
grub_xputs ("\n");
+
+#ifndef GRUB_UTIL
+ {
+ grub_net_app_level_t proto;
+ int first = 1;
+ FOR_NET_APP_LEVEL (proto)
+ {
+ if (first)
+ grub_puts_ (N_ ("Network protocols:"));
+ first = 0;
+ grub_printf ("%s ", proto->name);
+ }
+ grub_xputs ("\n");
+ }
+#endif
+
grub_refresh ();
return 0;
if (units)
{
- grub_uint32_t whole, fraction;
+ grub_uint64_t whole, fraction;
whole = grub_divmod64 (fsize, 100, &fraction);
grub_snprintf (buf, sizeof (buf),
- "%u.%02u%c", whole, fraction,
+ "%" PRIuGRUB_UINT64_T
+ ".%02" PRIuGRUB_UINT64_T "%c", whole, fraction,
grub_human_sizes[units]);
grub_printf ("%-12s", buf);
}
#include <grub/i18n.h>
#include <grub/dl.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
static void
print_strn (grub_uint8_t *str, grub_size_t len)
{
#include <grub/i18n.h>
#include <grub/memory.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
static const char *names[] =
{
[GRUB_MEMORY_AVAILABLE] = "available",
#include <grub/extcmd.h>
#include <grub/i18n.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
struct grub_pci_classname
{
int class;
#include <grub/env.h>
#include <grub/i18n.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
static grub_extcmd_t cmd_read_byte, cmd_read_word, cmd_read_dword;
static grub_command_t cmd_write_byte, cmd_write_word, cmd_write_dword;
if (! menu_sourcecode)
return grub_errno;
- if (classes)
+ if (classes && classes[0])
{
int i;
for (i = 0; classes[i]; i++); /* count # of menuentry classes */
if (! ctxt->script)
return grub_normal_add_menu_entry (argc, (const char **) args,
- ctxt->state[0].args, ctxt->state[1].arg,
+ (ctxt->state[0].set ? ctxt->state[0].args
+ : NULL), ctxt->state[1].arg,
ctxt->state[2].arg, 0,
ctxt->state[3].arg,
ctxt->extcmd->cmd->name[0] == 's');
#include <grub/command.h>
#include <grub/i18n.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
/* cat FILE */
static grub_err_t
grub_mini_cmd_cat (struct grub_command *cmd __attribute__ ((unused)),
return 0;
}
-#if 0
-static void
-grub_rescue_cmd_info (void)
-{
- extern void grub_disk_cache_get_performance (unsigned long *,
- unsigned long *);
- unsigned long hits, misses;
-
- grub_disk_cache_get_performance (&hits, &misses);
- grub_printf ("Disk cache: hits = %u, misses = %u ", hits, misses);
- if (hits + misses)
- {
- unsigned long ratio = hits * 10000 / (hits + misses);
- grub_printf ("(%u.%u%%)\n", ratio / 100, ratio % 100);
- }
- else
- grub_printf ("(N/A)\n");
-}
-#endif
-
/* dump ADDRESS [SIZE] */
static grub_err_t
grub_mini_cmd_dump (struct grub_command *cmd __attribute__ ((unused)),
--- /dev/null
+/*
+ * 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/mm.h>
+#include <grub/err.h>
+#include <grub/dl.h>
+#include <grub/command.h>
+#include <grub/cs5536.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
+
+static grub_err_t
+grub_cmd_lsspd (grub_command_t cmd __attribute__ ((unused)),
+ int argc __attribute__ ((unused)),
+ char **args __attribute__ ((unused)))
+{
+ grub_pci_device_t dev;
+ grub_port_t smbbase;
+ int i;
+ grub_err_t err;
+
+ if (!grub_cs5536_find (&dev))
+ {
+ grub_printf ("No CS5536 found\n");
+ return GRUB_ERR_NONE;
+ }
+ grub_printf ("CS5536 at %d:%d.%d\n", grub_pci_get_bus (dev),
+ grub_pci_get_device (dev), grub_pci_get_function (dev));
+
+ err = grub_cs5536_init_smbus (dev, 0x7fff, &smbbase);
+ if (err)
+ return err;
+
+ grub_printf ("SMB base = 0x%x\n", smbbase);
+
+ for (i = GRUB_SMB_RAM_START_ADDR;
+ i < GRUB_SMB_RAM_START_ADDR + GRUB_SMB_RAM_NUM_MAX; i++)
+ {
+ struct grub_smbus_spd spd;
+ grub_memset (&spd, 0, sizeof (spd));
+ grub_printf ("Device %d\n", i);
+ err = grub_cs5536_read_spd (smbbase, i, &spd);
+ if (err)
+ {
+ grub_print_error ();
+ continue;
+ }
+ grub_printf ("Written SPD bytes: %d B.\n", spd.written_size);
+ grub_printf ("Total flash size: %d B.\n", 1 << spd.log_total_flash_size);
+ if (spd.memory_type == GRUB_SMBUS_SPD_MEMORY_TYPE_DDR2)
+ {
+ char str[sizeof (spd.ddr2.part_number) + 1];
+ grub_printf ("Memory type: DDR2.\n");
+ grub_memcpy (str, spd.ddr2.part_number,
+ sizeof (spd.ddr2.part_number));
+ str[sizeof (spd.ddr2.part_number)] = 0;
+ grub_printf ("Part no: %s.\n", str);
+ }
+ else
+ grub_printf ("Memory type: Unknown.\n");
+ }
+
+ return GRUB_ERR_NONE;
+}
+
+static grub_command_t cmd;
+
+GRUB_MOD_INIT(lsspd)
+{
+ cmd = grub_register_command ("lsspd", grub_cmd_lsspd, 0,
+ "Print Memory information.");
+}
+
+GRUB_MOD_FINI(lsspd)
+{
+ grub_unregister_command (cmd);
+}
+++ /dev/null
-/*
- * 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/mm.h>
-#include <grub/err.h>
-#include <grub/dl.h>
-#include <grub/command.h>
-#include <grub/cs5536.h>
-
-static grub_err_t
-grub_cmd_lsspd (grub_command_t cmd __attribute__ ((unused)),
- int argc __attribute__ ((unused)),
- char **args __attribute__ ((unused)))
-{
- grub_pci_device_t dev;
- grub_port_t smbbase;
- int i;
- grub_err_t err;
-
- if (!grub_cs5536_find (&dev))
- {
- grub_printf ("No CS5536 found\n");
- return GRUB_ERR_NONE;
- }
- grub_printf ("CS5536 at %d:%d.%d\n", grub_pci_get_bus (dev),
- grub_pci_get_device (dev), grub_pci_get_function (dev));
-
- err = grub_cs5536_init_smbus (dev, 0x7fff, &smbbase);
- if (err)
- return err;
-
- grub_printf ("SMB base = 0x%x\n", smbbase);
-
- for (i = GRUB_SMB_RAM_START_ADDR;
- i < GRUB_SMB_RAM_START_ADDR + GRUB_SMB_RAM_NUM_MAX; i++)
- {
- struct grub_smbus_spd spd;
- grub_memset (&spd, 0, sizeof (spd));
- grub_printf ("Device %d\n", i);
- err = grub_cs5536_read_spd (smbbase, i, &spd);
- if (err)
- {
- grub_print_error ();
- continue;
- }
- grub_printf ("Written SPD bytes: %d B.\n", spd.written_size);
- grub_printf ("Total flash size: %d B.\n", 1 << spd.log_total_flash_size);
- if (spd.memory_type == GRUB_SMBUS_SPD_MEMORY_TYPE_DDR2)
- {
- char str[sizeof (spd.ddr2.part_number) + 1];
- grub_printf ("Memory type: DDR2.\n");
- grub_memcpy (str, spd.ddr2.part_number,
- sizeof (spd.ddr2.part_number));
- str[sizeof (spd.ddr2.part_number)] = 0;
- grub_printf ("Part no: %s.\n", str);
- }
- else
- grub_printf ("Memory type: Unknown.\n");
- }
-
- return GRUB_ERR_NONE;
-}
-
-static grub_command_t cmd;
-
-GRUB_MOD_INIT(lsspd)
-{
- cmd = grub_register_command ("lsspd", grub_cmd_lsspd, 0,
- "Print Memory information.");
-}
-
-GRUB_MOD_FINI(lsspd)
-{
- grub_unregister_command (cmd);
-}
#include <grub/command.h>
#include <grub/i18n.h>
+GRUB_MOD_LICENSE ("GPLv2+");
+
static struct grub_parttool *parts = 0;
static int curhandle = 0;
static grub_dl_t mymod;
#include <grub/dl.h>
#include <grub/i18n.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
static grub_dl_t my_mod;
static grub_err_t
#include <grub/dl.h>
#include <grub/i18n.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
static grub_dl_t my_mod;
struct pbkdf2_password
#include <grub/extcmd.h>
#include <grub/i18n.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
static const struct grub_arg_option options[] =
{
{"set", 's', 0,
{
const char *val = "none";
if (dev->net)
- val = dev->net->dev->name;
+ val = dev->net->protocol->name;
if (dev->disk)
val = dev->disk->dev->name;
if (state[0].set)
#include <grub/command.h>
#include <grub/i18n.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
static char *
grub_getline (void)
{
#include <grub/misc.h>
#include <grub/i18n.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
static grub_err_t
grub_cmd_reboot (grub_command_t cmd __attribute__ ((unused)),
int argc __attribute__ ((unused)),
#include <grub/script_sh.h>
#include <regex.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
static const struct grub_arg_option options[] =
{
{ "set", 's', GRUB_ARG_OPTION_REPEATABLE,
#include <grub/disk.h>
#include <grub/partition.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
void
FUNC_NAME (const char *key, const char *var, int no_floppy,
char **hints, unsigned nhints)
#include <grub/search.h>
#include <grub/i18n.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
static const struct grub_arg_option options[] =
{
{"file", 'f', 0, N_("Search devices by a file."), 0, 0},
#include <grub/mm.h>
#include <grub/i18n.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
struct pci_register
{
const char *name;
#include <grub/extcmd.h>
#include <grub/i18n.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
static const struct grub_arg_option options[] =
{
{"verbose", 'v', 0, N_("Verbose countdown."), 0, 0},
#include <grub/i18n.h>
#include <grub/misc.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
struct grub_term_autoload *grub_term_input_autoload = NULL;
struct grub_term_autoload *grub_term_output_autoload = NULL;
#include <grub/command.h>
#include <grub/i18n.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
/* A simple implementation for signed numbers. */
static int
grub_strtosl (char *arg, char **end, int base)
#include <grub/command.h>
#include <grub/i18n.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
static grub_err_t
grub_cmd_testload (struct grub_command *cmd __attribute__ ((unused)),
int argc, char *argv[])
--- /dev/null
+/* echo.c - Command to display a line of text */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2011 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/time.h>
+#include <grub/misc.h>
+#include <grub/dl.h>
+#include <grub/command.h>
+#include <grub/i18n.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
+
+
+static grub_err_t
+grub_cmd_time (grub_command_t ctxt __attribute__ ((unused)),
+ int argc, char **args)
+{
+ grub_command_t cmd;
+ grub_uint32_t start;
+ grub_uint32_t end;
+
+ if (argc == 0)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "command expected");
+
+ cmd = grub_command_find (args[0]);
+
+ if (!cmd)
+ return grub_error (GRUB_ERR_UNKNOWN_COMMAND, "Unknown command `%s'\n",
+ args[0]);
+
+ start = grub_get_time_ms ();
+ (cmd->func) (cmd, argc - 1, &args[1]);
+ end = grub_get_time_ms ();
+
+ grub_printf ("Elapsed time: %d.%03d seconds \n", (end - start) / 1000,
+ (end - start) % 1000);
+
+ return grub_errno;
+}
+
+static grub_command_t cmd;
+\f
+GRUB_MOD_INIT(time)
+{
+ cmd = grub_register_command ("time", grub_cmd_time,
+ N_("COMMAND [ARGS]"),
+ N_("Measure time used by COMMAND"));
+}
+
+GRUB_MOD_FINI(time)
+{
+ grub_unregister_command (cmd);
+}
#include <grub/command.h>
#include <grub/i18n.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
static grub_err_t
grub_cmd_true (struct grub_command *cmd __attribute__ ((unused)),
int argc __attribute__ ((unused)),
#include <grub/command.h>
#include <grub/i18n.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
static const char *usb_classes[] =
{
"Unknown",
#include <grub/command.h>
#include <grub/i18n.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
static unsigned height, width, depth;
+static struct grub_video_mode_info *current_mode;
static int
hook (const struct grub_video_mode_info *info)
if (info->mode_number == GRUB_VIDEO_MODE_NUMBER_INVALID)
grub_printf (" ");
else
- grub_printf (" 0x%03x ", info->mode_number);
+ {
+ if (current_mode && info->mode_number == current_mode->mode_number)
+ grub_printf ("*");
+ else
+ grub_printf (" ");
+ grub_printf (" 0x%03x ", info->mode_number);
+ }
grub_printf ("%4d x %4d x %2d ", info->width, info->height, info->bpp);
if (info->mode_type & GRUB_VIDEO_MODE_TYPE_PURE_TEXT)
return 0;
}
+static void
+print_edid (struct grub_video_edid_info *edid_info)
+{
+ unsigned int edid_width, edid_height;
+
+ if (grub_video_edid_checksum (edid_info))
+ {
+ grub_printf (" EDID checksum invalid\n");
+ grub_errno = GRUB_ERR_NONE;
+ return;
+ }
+
+ grub_printf (" EDID version: %u.%u\n",
+ edid_info->version, edid_info->revision);
+ if (grub_video_edid_preferred_mode (edid_info, &edid_width, &edid_height)
+ == GRUB_ERR_NONE)
+ grub_printf (" Preferred mode: %ux%u\n", edid_width, edid_height);
+ else
+ {
+ grub_printf (" No preferred mode available\n");
+ grub_errno = GRUB_ERR_NONE;
+ }
+}
+
static grub_err_t
grub_cmd_videoinfo (grub_command_t cmd __attribute__ ((unused)),
int argc, char **args)
FOR_VIDEO_ADAPTERS (adapter)
{
+ struct grub_video_mode_info info;
+ struct grub_video_edid_info edid_info;
+
grub_printf ("Adapter '%s':\n", adapter->name);
if (!adapter->iterate)
continue;
}
- if (adapter->id != id)
+ current_mode = NULL;
+
+ if (adapter->id == id)
+ {
+ if (grub_video_get_info (&info) == GRUB_ERR_NONE)
+ current_mode = &info;
+ else
+ /* Don't worry about errors. */
+ grub_errno = GRUB_ERR_NONE;
+ }
+ else
{
if (adapter->init ())
{
adapter->iterate (hook);
+ if (adapter->get_edid && adapter->get_edid (&edid_info) == GRUB_ERR_NONE)
+ print_edid (&edid_info);
+ else
+ grub_errno = GRUB_ERR_NONE;
+
+ current_mode = NULL;
+
if (adapter->id != id)
{
if (adapter->fini ())
#include <grub/gfxmenu_view.h>
#include <grub/env.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
static grub_err_t
grub_cmd_videotest (grub_command_t cmd __attribute__ ((unused)),
int argc, char **args)
case '.':
case '(':
case ')':
+ case '@':
buffer[i++] = '\\';
buffer[i++] = ch;
break;
for (i = 0; devs && devs[i]; i++)
grub_free (devs[i]);
- if (devs)
- grub_free (devs);
+ grub_free (devs);
return 0;
}
if (regexec (regexp, name, 0, 0, 0))
return 0;
+ grub_dprintf ("expand", "matched\n");
+
buffer = grub_xasprintf ("%s%s", dir, name);
if (! buffer)
return 1;
fail:
- if (dir)
- grub_free (dir);
+ grub_free (dir);
for (i = 0; files && files[i]; i++)
grub_free (files[i]);
- if (files)
- grub_free (files);
+ grub_free (files);
if (dev)
grub_device_close (dev);
- if (device_name)
- grub_free (device_name);
+ grub_free (device_name);
grub_error_pop ();
return 0;
while (*start)
{
split_path (start, &noregexop, ®exop);
- if (noregexop >= regexop) /* no more wildcards */
- break;
if (make_regex (noregexop, regexop, ®exp))
goto fail;
#include <grub/i18n.h>
#include <grub/crypto.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
/* This prefix is used by xnu and boot-132 to hash
together with volume serial. */
static grub_uint8_t hash_prefix[16]
--- /dev/null
+/*
+ * AFsplitter - Anti forensic information splitter
+ * Copyright 2004, Clemens Fruhwirth <clemens@endorphin.org>
+ *
+ * AFsplitter diffuses information over a large stripe of data,
+ * therefor supporting secure data destruction.
+ *
+ * This program is grub_free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the grub_free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the grub_free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <grub/crypto.h>
+#include <grub/mm.h>
+#include <grub/misc.h>
+
+gcry_err_code_t AF_merge (const gcry_md_spec_t * hash, grub_uint8_t * src,
+ grub_uint8_t * dst, grub_size_t blocksize,
+ grub_size_t blocknumbers);
+
+static void
+diffuse (const gcry_md_spec_t * hash, grub_uint8_t * src,
+ grub_uint8_t * dst, grub_size_t size)
+{
+ grub_size_t i;
+ grub_uint32_t IV; /* host byte order independend hash IV */
+
+ grub_size_t fullblocks = size / hash->mdlen;
+ int padding = size % hash->mdlen;
+ grub_uint8_t final[hash->mdlen];
+ grub_uint8_t temp[sizeof (IV) + hash->mdlen];
+
+ /* hash block the whole data set with different IVs to produce
+ * more than just a single data block
+ */
+ for (i = 0; i < fullblocks; i++)
+ {
+ IV = grub_cpu_to_be32 (i);
+ grub_memcpy (temp, &IV, sizeof (IV));
+ grub_memcpy (temp + sizeof (IV), src + hash->mdlen * i, hash->mdlen);
+ grub_crypto_hash (hash, dst + hash->mdlen * i, temp,
+ sizeof (IV) + hash->mdlen);
+ }
+
+ if (padding)
+ {
+ IV = grub_cpu_to_be32 (i);
+ grub_memcpy (temp, &IV, sizeof (IV));
+ grub_memcpy (temp + sizeof (IV), src + hash->mdlen * i, padding);
+ grub_crypto_hash (hash, final, temp, sizeof (IV) + padding);
+ grub_memcpy (dst + hash->mdlen * i, final, padding);
+ }
+}
+
+/**
+ * Merges the splitted master key stored on disk into the original key
+ */
+gcry_err_code_t
+AF_merge (const gcry_md_spec_t * hash, grub_uint8_t * src, grub_uint8_t * dst,
+ grub_size_t blocksize, grub_size_t blocknumbers)
+{
+ grub_size_t i;
+ grub_uint8_t *bufblock;
+
+ bufblock = grub_zalloc (blocksize);
+ if (bufblock == NULL)
+ return GPG_ERR_OUT_OF_MEMORY;
+
+ grub_memset (bufblock, 0, blocksize);
+ for (i = 0; i < blocknumbers - 1; i++)
+ {
+ grub_crypto_xor (bufblock, src + (blocksize * i), bufblock, blocksize);
+ diffuse (hash, bufblock, bufblock, blocksize);
+ }
+ grub_crypto_xor (dst, src + (i * blocksize), bufblock, blocksize);
+
+ grub_free (bufblock);
+ return GPG_ERR_NO_ERROR;
+}
--- /dev/null
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2007, 2008, 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/disk.h>
+#include <grub/mm.h>
+#include <grub/time.h>
+#include <grub/pci.h>
+#include <grub/ata.h>
+#include <grub/scsi.h>
+#include <grub/misc.h>
+#include <grub/list.h>
+#include <grub/loader.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
+
+struct grub_ahci_cmd_head
+{
+ grub_uint32_t config;
+ grub_uint32_t transfered;
+ grub_uint64_t command_table_base;
+ grub_uint32_t unused[4];
+};
+
+struct grub_ahci_prdt_entry
+{
+ grub_uint64_t data_base;
+ grub_uint32_t unused;
+ grub_uint32_t size;
+};
+
+struct grub_ahci_cmd_table
+{
+ grub_uint8_t cfis[0x40];
+ grub_uint8_t command[0x10];
+ grub_uint8_t reserved[0x30];
+ struct grub_ahci_prdt_entry prdt[1];
+};
+
+struct grub_ahci_hba_port
+{
+ grub_uint64_t command_list_base;
+ grub_uint64_t fis_base;
+ grub_uint32_t intstatus;
+ grub_uint32_t inten;
+ grub_uint32_t command;
+ grub_uint32_t unused1;
+ grub_uint32_t task_file_data;
+ grub_uint32_t sig;
+ grub_uint32_t status;
+ grub_uint32_t unused2;
+ grub_uint32_t sata_error;
+ grub_uint32_t sata_active;
+ grub_uint32_t command_issue;
+ grub_uint32_t unused3;
+ grub_uint32_t fbs;
+ grub_uint32_t unused4[15];
+};
+
+enum grub_ahci_hba_port_command
+ {
+ GRUB_AHCI_HBA_PORT_CMD_ST = 0x01,
+ GRUB_AHCI_HBA_PORT_CMD_FRE = 0x10,
+ GRUB_AHCI_HBA_PORT_CMD_CR = 0x8000,
+ GRUB_AHCI_HBA_PORT_CMD_FR = 0x4000,
+ };
+
+struct grub_ahci_hba
+{
+ grub_uint32_t cap;
+ grub_uint32_t global_control;
+ grub_uint32_t intr_status;
+ grub_uint32_t ports_implemented;
+ grub_uint32_t unused1[6];
+ grub_uint32_t bios_handoff;
+ grub_uint32_t unused2[53];
+ struct grub_ahci_hba_port ports[32];
+};
+
+struct grub_ahci_received_fis
+{
+ char raw[4096];
+};
+
+enum
+ {
+ GRUB_AHCI_HBA_CAP_NPORTS_MASK = 0x1f
+ };
+
+enum
+ {
+ GRUB_AHCI_HBA_GLOBAL_CONTROL_RESET = 0x00000001,
+ GRUB_AHCI_HBA_GLOBAL_CONTROL_INTR_EN = 0x00000002,
+ GRUB_AHCI_HBA_GLOBAL_CONTROL_AHCI_EN = 0x80000000,
+ };
+
+enum
+ {
+ GRUB_AHCI_BIOS_HANDOFF_BIOS_OWNED = 1,
+ GRUB_AHCI_BIOS_HANDOFF_OS_OWNED = 2,
+ GRUB_AHCI_BIOS_HANDOFF_OS_OWNERSHIP_CHANGED = 8,
+ GRUB_AHCI_BIOS_HANDOFF_RWC = 8
+ };
+
+
+struct grub_ahci_device
+{
+ struct grub_ahci_device *next;
+ volatile struct grub_ahci_hba *hba;
+ int port;
+ int num;
+ struct grub_pci_dma_chunk *command_list_chunk;
+ volatile struct grub_ahci_cmd_head *command_list;
+ struct grub_pci_dma_chunk *command_table_chunk;
+ volatile struct grub_ahci_cmd_table *command_table;
+ struct grub_pci_dma_chunk *rfis;
+ int present;
+};
+
+static grub_err_t
+grub_ahci_readwrite_real (struct grub_ahci_device *dev,
+ struct grub_disk_ata_pass_through_parms *parms,
+ int spinup);
+
+
+enum
+ {
+ GRUB_AHCI_CONFIG_READ = 0,
+ GRUB_AHCI_CONFIG_CFIS_LENGTH_MASK = 0x1f,
+ GRUB_AHCI_CONFIG_ATAPI = 0x20,
+ GRUB_AHCI_CONFIG_WRITE = 0x40,
+ GRUB_AHCI_CONFIG_PREFETCH = 0x80,
+ GRUB_AHCI_CONFIG_RESET = 0x100,
+ GRUB_AHCI_CONFIG_BIST = 0x200,
+ GRUB_AHCI_CONFIG_CLEAR_R_OK = 0x400,
+ GRUB_AHCI_CONFIG_PMP_MASK = 0xf000,
+ GRUB_AHCI_CONFIG_PRDT_LENGTH_MASK = 0xffff0000,
+ };
+#define GRUB_AHCI_CONFIG_CFIS_LENGTH_SHIFT 0
+#define GRUB_AHCI_CONFIG_PMP_SHIFT 12
+#define GRUB_AHCI_CONFIG_PRDT_LENGTH_SHIFT 16
+#define GRUB_AHCI_INTERRUPT_ON_COMPLETE 0x80000000
+
+#define GRUB_AHCI_PRDT_MAX_CHUNK_LENGTH 0x200000
+
+static struct grub_ahci_device *grub_ahci_devices;
+static int numdevs;
+
+static int
+init_port (struct grub_ahci_device *dev)
+{
+ struct grub_pci_dma_chunk *command_list;
+ struct grub_pci_dma_chunk *command_table;
+ grub_uint64_t endtime;
+
+ command_list = grub_memalign_dma32 (1024, sizeof (struct grub_ahci_cmd_head));
+ if (!command_list)
+ return 1;
+
+ command_table = grub_memalign_dma32 (1024,
+ sizeof (struct grub_ahci_cmd_table));
+ if (!command_table)
+ {
+ grub_dma_free (command_list);
+ return 1;
+ }
+
+ grub_dprintf ("ahci", "found device ahci%d (port %d)\n", dev->num, dev->port);
+
+ dev->hba->ports[dev->port].command &= ~GRUB_AHCI_HBA_PORT_CMD_FRE;
+ endtime = grub_get_time_ms () + 1000;
+ while ((dev->hba->ports[dev->port].command & GRUB_AHCI_HBA_PORT_CMD_FR))
+ if (grub_get_time_ms () > endtime)
+ {
+ grub_dprintf ("ahci", "couldn't stop FR\n");
+ goto out;
+ }
+
+ dev->hba->ports[dev->port].command &= ~GRUB_AHCI_HBA_PORT_CMD_ST;
+ endtime = grub_get_time_ms () + 1000;
+ while ((dev->hba->ports[dev->port].command & GRUB_AHCI_HBA_PORT_CMD_CR))
+ if (grub_get_time_ms () > endtime)
+ {
+ grub_dprintf ("ahci", "couldn't stop CR\n");
+ goto out;
+ }
+
+ dev->hba->ports[dev->port].fbs = 2;
+
+ dev->rfis = grub_memalign_dma32 (4096,
+ sizeof (struct grub_ahci_received_fis));
+ grub_memset ((char *) grub_dma_get_virt (dev->rfis), 0,
+ sizeof (struct grub_ahci_received_fis));
+ dev->hba->ports[dev->port].fis_base = grub_dma_get_phys (dev->rfis);
+ dev->hba->ports[dev->port].command_list_base
+ = grub_dma_get_phys (command_list);
+ dev->hba->ports[dev->port].command |= GRUB_AHCI_HBA_PORT_CMD_FRE;
+ while (!(dev->hba->ports[dev->port].command & GRUB_AHCI_HBA_PORT_CMD_FR))
+ if (grub_get_time_ms () > endtime)
+ {
+ grub_dprintf ("ahci", "couldn't start FR\n");
+ dev->hba->ports[dev->port].command &= ~GRUB_AHCI_HBA_PORT_CMD_FRE;
+ goto out;
+ }
+ dev->hba->ports[dev->port].command |= GRUB_AHCI_HBA_PORT_CMD_ST;
+ while (!(dev->hba->ports[dev->port].command & GRUB_AHCI_HBA_PORT_CMD_CR))
+ if (grub_get_time_ms () > endtime)
+ {
+ grub_dprintf ("ahci", "couldn't start CR\n");
+ dev->hba->ports[dev->port].command &= ~GRUB_AHCI_HBA_PORT_CMD_CR;
+ goto out_stop_fr;
+ }
+
+ dev->hba->ports[dev->port].command
+ = (dev->hba->ports[dev->port].command & 0x0fffffff) | (1 << 28) | 2 | 4;
+
+ dev->command_list_chunk = command_list;
+ dev->command_list = grub_dma_get_virt (command_list);
+ dev->command_table_chunk = command_table;
+ dev->command_table = grub_dma_get_virt (command_table);
+ dev->command_list->command_table_base
+ = grub_dma_get_phys (command_table);
+
+ return 0;
+ out_stop_fr:
+ dev->hba->ports[dev->port].command &= ~GRUB_AHCI_HBA_PORT_CMD_FRE;
+ endtime = grub_get_time_ms () + 1000;
+ while ((dev->hba->ports[dev->port].command & GRUB_AHCI_HBA_PORT_CMD_FR))
+ if (grub_get_time_ms () > endtime)
+ {
+ grub_dprintf ("ahci", "couldn't stop FR\n");
+ break;
+ }
+ out:
+ grub_dma_free (command_list);
+ grub_dma_free (command_table);
+ grub_dma_free (dev->rfis);
+ return 1;
+}
+
+static int NESTED_FUNC_ATTR
+grub_ahci_pciinit (grub_pci_device_t dev,
+ grub_pci_id_t pciid __attribute__ ((unused)))
+{
+ grub_pci_address_t addr;
+ grub_uint32_t class;
+ grub_uint32_t bar;
+ unsigned i, nports;
+ volatile struct grub_ahci_hba *hba;
+
+ /* Read class. */
+ addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS);
+ class = grub_pci_read (addr);
+
+ /* Check if this class ID matches that of a PCI IDE Controller. */
+ if (class >> 8 != 0x010601)
+ return 0;
+
+ addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG5);
+ bar = grub_pci_read (addr);
+
+ if ((bar & (GRUB_PCI_ADDR_SPACE_MASK | GRUB_PCI_ADDR_MEM_TYPE_MASK
+ | GRUB_PCI_ADDR_MEM_PREFETCH))
+ != (GRUB_PCI_ADDR_SPACE_MEMORY | GRUB_PCI_ADDR_MEM_TYPE_32))
+ return 0;
+
+ hba = grub_pci_device_map_range (dev, bar & GRUB_PCI_ADDR_MEM_MASK,
+ sizeof (hba));
+
+ if (! (hba->bios_handoff & GRUB_AHCI_BIOS_HANDOFF_OS_OWNED))
+ {
+ grub_uint64_t endtime;
+
+ grub_dprintf ("ahci", "Requesting AHCI ownership\n");
+ hba->bios_handoff = (hba->bios_handoff & ~GRUB_AHCI_BIOS_HANDOFF_RWC)
+ | GRUB_AHCI_BIOS_HANDOFF_OS_OWNED;
+ grub_dprintf ("ahci", "Waiting for BIOS to give up ownership\n");
+ endtime = grub_get_time_ms () + 1000;
+ while ((hba->bios_handoff & GRUB_AHCI_BIOS_HANDOFF_BIOS_OWNED)
+ && grub_get_time_ms () < endtime);
+ if (hba->bios_handoff & GRUB_AHCI_BIOS_HANDOFF_BIOS_OWNED)
+ {
+ grub_dprintf ("ahci", "Forcibly taking ownership\n");
+ hba->bios_handoff = GRUB_AHCI_BIOS_HANDOFF_OS_OWNED;
+ hba->bios_handoff |= GRUB_AHCI_BIOS_HANDOFF_OS_OWNERSHIP_CHANGED;
+ }
+ else
+ grub_dprintf ("ahci", "AHCI ownership obtained\n");
+ }
+ else
+ grub_dprintf ("ahci", "AHCI is already in OS mode\n");
+
+ if (~(hba->global_control & GRUB_AHCI_HBA_GLOBAL_CONTROL_AHCI_EN))
+ grub_dprintf ("ahci", "AHCI is in compat mode. Switching\n");
+ else
+ grub_dprintf ("ahci", "AHCI is in AHCI mode.\n");
+
+ for (i = 0; i < 5; i++)
+ {
+ hba->global_control |= GRUB_AHCI_HBA_GLOBAL_CONTROL_AHCI_EN;
+ grub_millisleep (1);
+ if (hba->global_control & GRUB_AHCI_HBA_GLOBAL_CONTROL_AHCI_EN)
+ break;
+ }
+ if (i == 5)
+ {
+ grub_dprintf ("ahci", "Couldn't put AHCI in AHCI mode\n");
+ return 0;
+ }
+
+ /*
+ {
+ grub_uint64_t endtime;
+ hba->global_control |= 1;
+ endtime = grub_get_time_ms () + 1000;
+ while (hba->global_control & 1)
+ if (grub_get_time_ms () > endtime)
+ {
+ grub_dprintf ("ahci", "couldn't reset AHCI\n");
+ return 0;
+ }
+ }
+
+ for (i = 0; i < 5; i++)
+ {
+ hba->global_control |= GRUB_AHCI_HBA_GLOBAL_CONTROL_AHCI_EN;
+ grub_millisleep (1);
+ if (hba->global_control & GRUB_AHCI_HBA_GLOBAL_CONTROL_AHCI_EN)
+ break;
+ }
+ if (i == 5)
+ {
+ grub_dprintf ("ahci", "Couldn't put AHCI in AHCI mode\n");
+ return 0;
+ }
+ */
+
+ nports = (hba->cap & GRUB_AHCI_HBA_CAP_NPORTS_MASK) + 1;
+
+ grub_dprintf ("ahci", "%d AHCI ports\n", nports);
+
+ for (i = 0; i < nports; i++)
+ {
+ struct grub_ahci_device *adev;
+ grub_uint32_t st;
+
+ if (!(hba->ports_implemented & (1 << i)))
+ continue;
+
+ grub_dprintf ("ahci", "status %d:%x\n", i, hba->ports[i].status);
+ /* FIXME: support hotplugging. */
+ st = hba->ports[i].status;
+ if ((st & 0xf) != 0x3 && (st & 0xf) != 0x1)
+ continue;
+
+ adev = grub_malloc (sizeof (*adev));
+ if (!adev)
+ return 1;
+
+ adev->hba = hba;
+ adev->port = i;
+ adev->present = 1;
+ adev->num = numdevs++;
+
+ if (init_port (adev))
+ {
+ grub_free (adev);
+ return 1;
+ }
+
+ grub_list_push (GRUB_AS_LIST_P (&grub_ahci_devices),
+ GRUB_AS_LIST (adev));
+ }
+
+ return 0;
+}
+
+static grub_err_t
+grub_ahci_initialize (void)
+{
+ grub_pci_iterate (grub_ahci_pciinit);
+ return grub_errno;
+}
+
+static grub_err_t
+grub_ahci_fini_hw (int noreturn __attribute__ ((unused)))
+{
+ struct grub_ahci_device *dev;
+
+ for (dev = grub_ahci_devices; dev; dev = dev->next)
+ {
+ grub_uint64_t endtime;
+
+ dev->hba->ports[dev->port].command &= ~GRUB_AHCI_HBA_PORT_CMD_FRE;
+ endtime = grub_get_time_ms () + 1000;
+ while ((dev->hba->ports[dev->port].command & GRUB_AHCI_HBA_PORT_CMD_FR))
+ if (grub_get_time_ms () > endtime)
+ {
+ grub_dprintf ("ahci", "couldn't stop FR\n");
+ break;
+ }
+
+ dev->hba->ports[dev->port].command &= ~GRUB_AHCI_HBA_PORT_CMD_ST;
+ endtime = grub_get_time_ms () + 1000;
+ while ((dev->hba->ports[dev->port].command & GRUB_AHCI_HBA_PORT_CMD_CR))
+ if (grub_get_time_ms () > endtime)
+ {
+ grub_dprintf ("ahci", "couldn't stop CR\n");
+ break;
+ }
+ grub_dma_free (dev->command_list_chunk);
+ grub_dma_free (dev->command_table_chunk);
+ grub_dma_free (dev->rfis);
+ dev->command_list_chunk = NULL;
+ dev->command_table_chunk = NULL;
+ dev->rfis = NULL;
+ }
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_ahci_restore_hw (void)
+{
+ struct grub_ahci_device **pdev;
+
+ for (pdev = &grub_ahci_devices; *pdev; pdev = &((*pdev)->next))
+ if (init_port (*pdev))
+ {
+ struct grub_ahci_device *odev;
+ odev = *pdev;
+ *pdev = (*pdev)->next;
+ grub_free (odev);
+ }
+ return GRUB_ERR_NONE;
+}
+
+
+\f
+
+static int
+grub_ahci_iterate (int (*hook) (int id, int bus),
+ grub_disk_pull_t pull)
+{
+ struct grub_ahci_device *dev;
+
+ if (pull != GRUB_DISK_PULL_NONE)
+ return 0;
+
+ FOR_LIST_ELEMENTS(dev, grub_ahci_devices)
+ if (hook (GRUB_SCSI_SUBSYSTEM_AHCI, dev->num))
+ return 1;
+
+ return 0;
+}
+
+#if 0
+static int
+find_free_cmd_slot (struct grub_ahci_device *dev)
+{
+ int i;
+ for (i = 0; i < 32; i++)
+ {
+ if (dev->hda->ports[dev->port].command_issue & (1 << i))
+ continue;
+ if (dev->hda->ports[dev->port].sata_active & (1 << i))
+ continue;
+ return i;
+ }
+ return -1;
+}
+#endif
+
+enum
+ {
+ GRUB_AHCI_FIS_REG_H2D = 0x27
+ };
+
+static const int register_map[11] = { 3 /* Features */,
+ 12 /* Sectors */,
+ 4 /* LBA low */,
+ 5 /* LBA mid */,
+ 6 /* LBA high */,
+ 7 /* Device */,
+ 2 /* CMD register */,
+ 13 /* Sectors 48 */,
+ 8 /* LBA48 low */,
+ 9 /* LBA48 mid */,
+ 10 /* LBA48 high */ };
+
+static grub_err_t
+grub_ahci_readwrite_real (struct grub_ahci_device *dev,
+ struct grub_disk_ata_pass_through_parms *parms,
+ int spinup)
+{
+ struct grub_pci_dma_chunk *bufc;
+ grub_uint64_t endtime;
+ unsigned i;
+ grub_err_t err = GRUB_ERR_NONE;
+
+ grub_dprintf ("ahci", "AHCI tfd = %x\n",
+ dev->hba->ports[dev->port].task_file_data);
+
+ if ((dev->hba->ports[dev->port].task_file_data & 0x80))
+ {
+ dev->hba->ports[dev->port].command &= ~GRUB_AHCI_HBA_PORT_CMD_ST;
+ endtime = grub_get_time_ms () + 1000;
+ while ((dev->hba->ports[dev->port].command & GRUB_AHCI_HBA_PORT_CMD_CR))
+ if (grub_get_time_ms () > endtime)
+ {
+ grub_dprintf ("ahci", "couldn't stop CR\n");
+ break;
+ }
+ dev->hba->ports[dev->port].command |= GRUB_AHCI_HBA_PORT_CMD_ST;
+ endtime = grub_get_time_ms () + (spinup ? 10000 : 1000);
+ while (!(dev->hba->ports[dev->port].command & GRUB_AHCI_HBA_PORT_CMD_CR))
+ if (grub_get_time_ms () > endtime)
+ {
+ grub_dprintf ("ahci", "couldn't start CR\n");
+ break;
+ }
+ }
+
+ dev->hba->ports[dev->port].sata_error = dev->hba->ports[dev->port].sata_error;
+
+ grub_dprintf("ahci", "grub_ahci_read (size=%llu, cmdsize = %llu)\n",
+ (unsigned long long) parms->size,
+ (unsigned long long) parms->cmdsize);
+
+ if (parms->cmdsize != 0 && parms->cmdsize != 12 && parms->cmdsize != 16)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "incorrect ATAPI command size");
+
+ if (parms->size > GRUB_AHCI_PRDT_MAX_CHUNK_LENGTH)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "too big data buffer");
+
+ bufc = grub_memalign_dma32 (1024, parms->size + (parms->size & 1));
+
+ dev->hba->ports[dev->port].command |= 8;
+
+ grub_dprintf ("ahci", "AHCI tfd = %x\n",
+ dev->hba->ports[dev->port].task_file_data);
+ /* FIXME: support port multipliers. */
+ dev->command_list[0].config
+ = (5 << GRUB_AHCI_CONFIG_CFIS_LENGTH_SHIFT)
+ // | GRUB_AHCI_CONFIG_CLEAR_R_OK
+ | (0 << GRUB_AHCI_CONFIG_PMP_SHIFT)
+ | (1 << GRUB_AHCI_CONFIG_PRDT_LENGTH_SHIFT)
+ | (parms->cmdsize ? GRUB_AHCI_CONFIG_ATAPI : 0)
+ | (parms->write ? GRUB_AHCI_CONFIG_WRITE : GRUB_AHCI_CONFIG_READ)
+ | (parms->taskfile.cmd == 8 ? (1 << 8) : 0);
+ dev->command_list[0].transfered = 0;
+ dev->command_list[0].command_table_base
+ = grub_dma_get_phys (dev->command_table_chunk);
+ grub_memset ((char *) dev->command_list[0].unused, 0,
+ sizeof (dev->command_list[0].unused));
+ grub_memset ((char *) &dev->command_table[0], 0,
+ sizeof (dev->command_table[0]));
+ if (parms->cmdsize)
+ grub_memcpy ((char *) dev->command_table[0].command, parms->cmd,
+ parms->cmdsize);
+
+ dev->command_table[0].cfis[0] = GRUB_AHCI_FIS_REG_H2D;
+ dev->command_table[0].cfis[1] = 0x80;
+ for (i = 0; i < sizeof (parms->taskfile.raw); i++)
+ dev->command_table[0].cfis[register_map[i]] = parms->taskfile.raw[i];
+
+ grub_dprintf ("ahci", "cfis: %02x %02x %02x %02x %02x %02x %02x %02x\n",
+ dev->command_table[0].cfis[0], dev->command_table[0].cfis[1],
+ dev->command_table[0].cfis[2], dev->command_table[0].cfis[3],
+ dev->command_table[0].cfis[4], dev->command_table[0].cfis[5],
+ dev->command_table[0].cfis[6], dev->command_table[0].cfis[7]);
+ grub_dprintf ("ahci", "cfis: %02x %02x %02x %02x %02x %02x %02x %02x\n",
+ dev->command_table[0].cfis[8], dev->command_table[0].cfis[9],
+ dev->command_table[0].cfis[10], dev->command_table[0].cfis[11],
+ dev->command_table[0].cfis[12], dev->command_table[0].cfis[13],
+ dev->command_table[0].cfis[14], dev->command_table[0].cfis[15]);
+
+ dev->command_table[0].prdt[0].data_base = grub_dma_get_phys (bufc);
+ dev->command_table[0].prdt[0].unused = 0;
+ dev->command_table[0].prdt[0].size = (parms->size + (parms->size & 1) - 1)
+ | GRUB_AHCI_INTERRUPT_ON_COMPLETE;
+
+ grub_dprintf ("ahci", "PRDT = %" PRIxGRUB_UINT64_T ", %x, %x (%"
+ PRIuGRUB_SIZE ")\n",
+ dev->command_table[0].prdt[0].data_base,
+ dev->command_table[0].prdt[0].unused,
+ dev->command_table[0].prdt[0].size,
+ (char *) &dev->command_table[0].prdt[0]
+ - (char *) &dev->command_table[0]);
+
+ if (parms->write)
+ grub_memcpy ((char *) grub_dma_get_virt (bufc), parms->buffer, parms->size);
+
+ grub_dprintf ("ahci", "AHCI command schedulded\n");
+ grub_dprintf ("ahci", "AHCI tfd = %x\n",
+ dev->hba->ports[dev->port].task_file_data);
+ dev->hba->ports[dev->port].inten = 0xffffffff;//(1 << 2) | (1 << 5);
+ dev->hba->ports[dev->port].intstatus = 0xffffffff;//(1 << 2) | (1 << 5);
+ grub_dprintf ("ahci", "AHCI tfd = %x\n",
+ dev->hba->ports[dev->port].task_file_data);
+ dev->hba->ports[dev->port].command_issue |= 1;
+ grub_dprintf ("ahci", "AHCI sig = %x\n", dev->hba->ports[dev->port].sig);
+ grub_dprintf ("ahci", "AHCI tfd = %x\n",
+ dev->hba->ports[dev->port].task_file_data);
+
+ endtime = grub_get_time_ms () + (spinup ? 10000 : 1000);
+ while ((dev->hba->ports[dev->port].command_issue & 1))
+ if (grub_get_time_ms () > endtime)
+ {
+ grub_dprintf ("ahci", "AHCI status <%x %x %x>\n",
+ dev->hba->ports[dev->port].command_issue,
+ dev->hba->ports[dev->port].intstatus,
+ dev->hba->ports[dev->port].task_file_data);
+ err = grub_error (GRUB_ERR_IO, "AHCI transfer timeouted");
+ break;
+ }
+
+ grub_dprintf ("ahci", "AHCI command completed <%x %x %x %x %x, %x %x>\n",
+ dev->hba->ports[dev->port].command_issue,
+ dev->hba->ports[dev->port].intstatus,
+ dev->hba->ports[dev->port].task_file_data,
+ dev->command_list[0].transfered,
+ dev->hba->ports[dev->port].sata_error,
+ ((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x00],
+ ((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x18]);
+ grub_dprintf ("ahci",
+ "last PIO FIS %08x %08x %08x %08x %08x %08x %08x %08x\n",
+ ((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x08],
+ ((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x09],
+ ((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x0a],
+ ((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x0b],
+ ((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x0c],
+ ((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x0d],
+ ((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x0e],
+ ((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x0f]);
+ grub_dprintf ("ahci",
+ "last REG FIS %08x %08x %08x %08x %08x %08x %08x %08x\n",
+ ((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x10],
+ ((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x11],
+ ((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x12],
+ ((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x13],
+ ((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x14],
+ ((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x15],
+ ((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x16],
+ ((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x17]);
+
+ if (!parms->write)
+ grub_memcpy (parms->buffer, (char *) grub_dma_get_virt (bufc), parms->size);
+ grub_dma_free (bufc);
+
+ return err;
+}
+
+static grub_err_t
+grub_ahci_readwrite (grub_ata_t disk,
+ struct grub_disk_ata_pass_through_parms *parms,
+ int spinup)
+{
+ return grub_ahci_readwrite_real (disk->data, parms, spinup);
+}
+
+static grub_err_t
+grub_ahci_open (int id, int devnum, struct grub_ata *ata)
+{
+ struct grub_ahci_device *dev;
+
+ if (id != GRUB_SCSI_SUBSYSTEM_AHCI)
+ return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not an AHCI device");
+
+ FOR_LIST_ELEMENTS(dev, grub_ahci_devices)
+ if (dev->num == devnum)
+ break;
+
+ if (! dev)
+ return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no such AHCI device");
+
+ grub_dprintf ("ahci", "opening AHCI dev `ahci%d'\n", dev->num);
+
+ ata->data = dev;
+ ata->dma = 1;
+ ata->present = &dev->present;
+
+ return GRUB_ERR_NONE;
+}
+
+static struct grub_ata_dev grub_ahci_dev =
+ {
+ .iterate = grub_ahci_iterate,
+ .open = grub_ahci_open,
+ .readwrite = grub_ahci_readwrite,
+ };
+
+\f
+
+static void *fini_hnd;
+
+GRUB_MOD_INIT(ahci)
+{
+ /* To prevent two drivers operating on the same disks. */
+ grub_disk_firmware_is_tainted = 1;
+ if (grub_disk_firmware_fini)
+ {
+ grub_disk_firmware_fini ();
+ grub_disk_firmware_fini = NULL;
+ }
+
+ /* AHCI initialization. */
+ grub_ahci_initialize ();
+
+ /* AHCI devices are handled by scsi.mod. */
+ grub_ata_dev_register (&grub_ahci_dev);
+
+ fini_hnd = grub_loader_register_preboot_hook (grub_ahci_fini_hw,
+ grub_ahci_restore_hw,
+ GRUB_LOADER_PREBOOT_HOOK_PRIO_DISK);
+}
+
+GRUB_MOD_FINI(ahci)
+{
+ grub_ahci_fini_hw (0);
+ grub_loader_unregister_preboot_hook (fini_hnd);
+
+ grub_ata_dev_unregister (&grub_ahci_dev);
+}
--- /dev/null
+/* ofdisk.c - Open Firmware disk access. */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2004,2006,2007,2008,2009,2011 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/misc.h>
+#include <grub/disk.h>
+#include <grub/mm.h>
+#include <grub/arc/arc.h>
+
+static grub_arc_fileno_t last_handle = 0;
+static char *last_path = NULL;
+
+static int lnum = 0;
+
+struct arcdisk_hash_ent
+{
+ char *devpath;
+ int num;
+ struct arcdisk_hash_ent *next;
+};
+
+#define ARCDISK_HASH_SZ 8
+static struct arcdisk_hash_ent *arcdisk_hash[ARCDISK_HASH_SZ];
+
+static int
+arcdisk_hash_fn (const char *devpath)
+{
+ int hash = 0;
+ while (*devpath)
+ hash ^= *devpath++;
+ return (hash & (ARCDISK_HASH_SZ - 1));
+}
+
+static struct arcdisk_hash_ent *
+arcdisk_hash_find (const char *devpath)
+{
+ struct arcdisk_hash_ent *p = arcdisk_hash[arcdisk_hash_fn (devpath)];
+
+ while (p)
+ {
+ if (!grub_strcmp (p->devpath, devpath))
+ break;
+ p = p->next;
+ }
+ return p;
+}
+
+static struct arcdisk_hash_ent *
+arcdisk_hash_add (char *devpath)
+{
+ struct arcdisk_hash_ent *p;
+ struct arcdisk_hash_ent **head = &arcdisk_hash[arcdisk_hash_fn(devpath)];
+
+ p = grub_malloc (sizeof (*p));
+ if (!p)
+ return NULL;
+
+ p->devpath = devpath;
+ p->next = *head;
+ p->num = lnum++;
+ *head = p;
+ return p;
+}
+
+
+static int
+grub_arcdisk_iterate (int (*hook_in) (const char *name),
+ grub_disk_pull_t pull)
+{
+ auto int hook (const char *name, const struct grub_arc_component *comp);
+ int hook (const char *name, const struct grub_arc_component *comp)
+ {
+ if (!(comp->type == GRUB_ARC_COMPONENT_TYPE_DISK
+ || comp->type == GRUB_ARC_COMPONENT_TYPE_DISK
+ || comp->type == GRUB_ARC_COMPONENT_TYPE_TAPE))
+ return 0;
+ return hook_in (name);
+ }
+ if (pull != GRUB_DISK_PULL_NONE)
+ return 0;
+
+ return grub_arc_iterate_devs (hook, 1);
+}
+
+#define RAW_SUFFIX "partition(10)"
+
+static grub_err_t
+reopen (const char *name)
+{
+ grub_arc_fileno_t handle;
+
+ if (last_path && grub_strcmp (last_path, name) == 0)
+ {
+ grub_dprintf ("arcdisk", "using already opened %s\n", name);
+ return GRUB_ERR_NONE;
+ }
+ if (last_path)
+ {
+ GRUB_ARC_FIRMWARE_VECTOR->close (last_handle);
+ grub_free (last_path);
+ last_path = NULL;
+ last_handle = 0;
+ }
+ if (GRUB_ARC_FIRMWARE_VECTOR->open (name, 0, &handle))
+ {
+ grub_dprintf ("arcdisk", "couldn't open %s\n", name);
+ return grub_error (GRUB_ERR_IO, "couldn't open %s", name);
+ }
+ last_path = grub_strdup (name);
+ if (!last_path)
+ return grub_errno;
+ last_handle = handle;
+ grub_dprintf ("arcdisk", "opened %s\n", name);
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_arcdisk_open (const char *name, grub_disk_t disk)
+{
+ char *fullname, *optr;
+ const char *iptr;
+ int state = 0;
+ grub_err_t err;
+ grub_arc_err_t r;
+ struct grub_arc_fileinfo info;
+ struct arcdisk_hash_ent *hash;
+
+ if (grub_memcmp (name, "arc/", 4) != 0)
+ return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not arc device");
+ fullname = grub_malloc (2 * grub_strlen (name) + sizeof (RAW_SUFFIX));
+ if (!fullname)
+ return grub_errno;
+ optr = fullname;
+ for (iptr = name + 4; *iptr; iptr++)
+ if (state == 0)
+ {
+ if (!grub_isdigit (*iptr))
+ *optr++ = *iptr;
+ else
+ {
+ *optr++ = '(';
+ *optr++ = *iptr;
+ state = 1;
+ }
+ }
+ else
+ {
+ if (grub_isdigit (*iptr))
+ *optr++ = *iptr;
+ else
+ {
+ *optr++ = ')';
+ state = 0;
+ }
+ }
+ if (state)
+ *optr++ = ')';
+ grub_memcpy (optr, RAW_SUFFIX, sizeof (RAW_SUFFIX));
+ disk->data = fullname;
+ grub_dprintf ("arcdisk", "opening %s\n", fullname);
+
+ hash = arcdisk_hash_find (fullname);
+ if (!hash)
+ hash = arcdisk_hash_add (fullname);
+ if (!hash)
+ return grub_errno;
+
+ err = reopen (fullname);
+ if (err)
+ return err;
+
+ r = GRUB_ARC_FIRMWARE_VECTOR->getfileinformation (last_handle, &info);
+ if (r)
+ {
+ grub_uint64_t res = 0;
+ int i;
+
+ grub_dprintf ("arcdisk", "couldn't retrieve size: %ld\n", r);
+ for (i = 40; i >= 9; i--)
+ {
+ grub_uint64_t pos = res | (1ULL << i);
+ char buf[512];
+ long unsigned count = 0;
+ grub_dprintf ("arcdisk",
+ "seek to 0x%" PRIxGRUB_UINT64_T "\n", pos);
+ if (GRUB_ARC_FIRMWARE_VECTOR->seek (last_handle, &pos, 0))
+ continue;
+ if (GRUB_ARC_FIRMWARE_VECTOR->read (last_handle, buf,
+ 0x200, &count))
+ continue;
+ if (count == 0)
+ continue;
+ res |= (1ULL << i);
+ }
+ grub_dprintf ("arcdisk",
+ "determined disk size 0x%" PRIxGRUB_UINT64_T "\n", res);
+ disk->total_sectors = (res + 0x200) >> 9;
+ }
+ else
+ disk->total_sectors = (info.end >> 9);
+
+ disk->id = hash->num;
+ return GRUB_ERR_NONE;
+}
+
+static void
+grub_arcdisk_close (grub_disk_t disk)
+{
+ grub_free (disk->data);
+}
+
+static grub_err_t
+grub_arcdisk_read (grub_disk_t disk, grub_disk_addr_t sector,
+ grub_size_t size, char *buf)
+{
+ grub_err_t err;
+ grub_uint64_t pos = sector << 9;
+ unsigned long count;
+ grub_uint64_t totl = size << 9;
+ grub_arc_err_t r;
+
+ err = reopen (disk->data);
+ if (err)
+ return err;
+ r = GRUB_ARC_FIRMWARE_VECTOR->seek (last_handle, &pos, 0);
+ if (r)
+ {
+ grub_dprintf ("arcdisk", "seek to 0x%" PRIxGRUB_UINT64_T " failed: %ld\n",
+ pos, r);
+ return grub_error (GRUB_ERR_IO, "couldn't seek");
+ }
+
+ while (totl)
+ {
+ if (GRUB_ARC_FIRMWARE_VECTOR->read (last_handle, buf,
+ totl, &count))
+ return grub_error (GRUB_ERR_READ_ERROR, "read failed");
+ totl -= count;
+ buf += count;
+ }
+
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_arcdisk_write (grub_disk_t disk __attribute ((unused)),
+ grub_disk_addr_t sector __attribute ((unused)),
+ grub_size_t size __attribute ((unused)),
+ const char *buf __attribute ((unused)))
+{
+ return GRUB_ERR_NOT_IMPLEMENTED_YET;
+}
+
+static struct grub_disk_dev grub_arcdisk_dev =
+ {
+ .name = "arcdisk",
+ .id = GRUB_DISK_DEVICE_ARCDISK_ID,
+ .iterate = grub_arcdisk_iterate,
+ .open = grub_arcdisk_open,
+ .close = grub_arcdisk_close,
+ .read = grub_arcdisk_read,
+ .write = grub_arcdisk_write,
+ .next = 0
+ };
+
+void
+grub_arcdisk_init (void)
+{
+ grub_disk_dev_register (&grub_arcdisk_dev);
+}
+
+void
+grub_arcdisk_fini (void)
+{
+ if (last_path)
+ {
+ GRUB_ARC_FIRMWARE_VECTOR->close (last_handle);
+ grub_free (last_path);
+ last_path = NULL;
+ last_handle = 0;
+ }
+
+ grub_disk_dev_unregister (&grub_arcdisk_dev);
+}
#include <grub/dl.h>
#include <grub/disk.h>
#include <grub/mm.h>
-#include <grub/time.h>
-#include <grub/pci.h>
#include <grub/scsi.h>
-#include <grub/cs5536.h>
-/* At the moment, only two IDE ports are supported. */
-static const grub_port_t grub_ata_ioaddress[] = { GRUB_ATA_CH0_PORT1,
- GRUB_ATA_CH1_PORT1 };
-static const grub_port_t grub_ata_ioaddress2[] = { GRUB_ATA_CH0_PORT2,
- GRUB_ATA_CH1_PORT2 };
+GRUB_MOD_LICENSE ("GPLv3+");
-static struct grub_ata_device *grub_ata_devices;
-
-/* Wait for !BSY. */
-grub_err_t
-grub_ata_wait_not_busy (struct grub_ata_device *dev, int milliseconds)
-{
- /* ATA requires 400ns (after a write to CMD register) or
- 1 PIO cycle (after a DRQ block transfer) before
- first check of BSY. */
- grub_millisleep (1);
-
- int i = 1;
- grub_uint8_t sts;
- while ((sts = grub_ata_regget (dev, GRUB_ATA_REG_STATUS))
- & GRUB_ATA_STATUS_BUSY)
- {
- if (i >= milliseconds)
- {
- grub_dprintf ("ata", "timeout: %dms, status=0x%x\n",
- milliseconds, sts);
- return grub_error (GRUB_ERR_TIMEOUT, "ATA timeout");
- }
-
- grub_millisleep (1);
- i++;
- }
-
- return GRUB_ERR_NONE;
-}
-
-static inline void
-grub_ata_wait (void)
-{
- grub_millisleep (50);
-}
-
-/* Wait for !BSY, DRQ. */
-grub_err_t
-grub_ata_wait_drq (struct grub_ata_device *dev, int rw,
- int milliseconds)
-{
- if (grub_ata_wait_not_busy (dev, milliseconds))
- return grub_errno;
-
- /* !DRQ implies error condition. */
- grub_uint8_t sts = grub_ata_regget (dev, GRUB_ATA_REG_STATUS);
- if ((sts & (GRUB_ATA_STATUS_DRQ | GRUB_ATA_STATUS_ERR))
- != GRUB_ATA_STATUS_DRQ)
- {
- grub_dprintf ("ata", "ata error: status=0x%x, error=0x%x\n",
- sts, grub_ata_regget (dev, GRUB_ATA_REG_ERROR));
- if (! rw)
- return grub_error (GRUB_ERR_READ_ERROR, "ATA read error");
- else
- return grub_error (GRUB_ERR_WRITE_ERROR, "ATA write error");
- }
-
- return GRUB_ERR_NONE;
-}
+static grub_ata_dev_t grub_ata_dev_list;
/* Byteorder has to be changed before strings can be read. */
static void
dst[len] = '\0';
}
-void
-grub_ata_pio_read (struct grub_ata_device *dev, char *buf, grub_size_t size)
-{
- grub_uint16_t *buf16 = (grub_uint16_t *) buf;
- unsigned int i;
-
- /* Read in the data, word by word. */
- for (i = 0; i < size / 2; i++)
- buf16[i] = grub_le_to_cpu16 (grub_inw(dev->ioaddress + GRUB_ATA_REG_DATA));
-}
-
-static void
-grub_ata_pio_write (struct grub_ata_device *dev, char *buf, grub_size_t size)
-{
- grub_uint16_t *buf16 = (grub_uint16_t *) buf;
- unsigned int i;
-
- /* Write the data, word by word. */
- for (i = 0; i < size / 2; i++)
- grub_outw(grub_cpu_to_le16 (buf16[i]), dev->ioaddress + GRUB_ATA_REG_DATA);
-}
-
static void
-grub_ata_dumpinfo (struct grub_ata_device *dev, char *info)
+grub_ata_dumpinfo (struct grub_ata *dev, char *info)
{
char text[41];
{
grub_dprintf ("ata", "Addressing: %d\n", dev->addr);
grub_dprintf ("ata", "Sectors: %lld\n", (unsigned long long) dev->size);
+ grub_dprintf ("ata", "Sector size: %u\n", 1U << dev->log_sector_size);
}
}
static grub_err_t
-grub_atapi_identify (struct grub_ata_device *dev)
+grub_atapi_identify (struct grub_ata *dev)
{
+ struct grub_disk_ata_pass_through_parms parms;
char *info;
+ grub_err_t err;
info = grub_malloc (GRUB_DISK_SECTOR_SIZE);
if (! info)
return grub_errno;
- grub_ata_regset (dev, GRUB_ATA_REG_DISK, 0xE0 | dev->device << 4);
- grub_ata_wait ();
- if (grub_ata_check_ready (dev))
+ grub_memset (&parms, 0, sizeof (parms));
+ parms.taskfile.disk = 0xE0;
+ parms.taskfile.cmd = GRUB_ATA_CMD_IDENTIFY_PACKET_DEVICE;
+ parms.size = GRUB_DISK_SECTOR_SIZE;
+ parms.buffer = info;
+
+ err = dev->dev->readwrite (dev, &parms, *dev->present);
+ if (err)
{
- grub_free (info);
- return grub_errno;
+ *dev->present = 0;
+ return err;
}
- grub_ata_regset (dev, GRUB_ATA_REG_CMD, GRUB_ATA_CMD_IDENTIFY_PACKET_DEVICE);
- grub_ata_wait ();
-
- if (grub_ata_wait_drq (dev, 0, GRUB_ATA_TOUT_STD))
+ if (parms.size != GRUB_DISK_SECTOR_SIZE)
{
- grub_free (info);
- return grub_errno;
+ *dev->present = 0;
+ return grub_error (GRUB_ERR_UNKNOWN_DEVICE,
+ "device cannot be identified");
}
- grub_ata_pio_read (dev, info, GRUB_DISK_SECTOR_SIZE);
dev->atapi = 1;
}
static grub_err_t
-grub_atapi_wait_drq (struct grub_ata_device *dev,
- grub_uint8_t ireason,
- int milliseconds)
-{
- /* Wait for !BSY, DRQ, ireason */
- if (grub_ata_wait_not_busy (dev, milliseconds))
- return grub_errno;
-
- grub_uint8_t sts = grub_ata_regget (dev, GRUB_ATA_REG_STATUS);
- grub_uint8_t irs = grub_ata_regget (dev, GRUB_ATAPI_REG_IREASON);
-
- /* OK if DRQ is asserted and interrupt reason is as expected. */
- if ((sts & GRUB_ATA_STATUS_DRQ)
- && (irs & GRUB_ATAPI_IREASON_MASK) == ireason)
- return GRUB_ERR_NONE;
-
- /* !DRQ implies error condition. */
- grub_dprintf ("ata", "atapi error: status=0x%x, ireason=0x%x, error=0x%x\n",
- sts, irs, grub_ata_regget (dev, GRUB_ATA_REG_ERROR));
-
- if (! (sts & GRUB_ATA_STATUS_DRQ)
- && (irs & GRUB_ATAPI_IREASON_MASK) == GRUB_ATAPI_IREASON_ERROR)
- {
- if (ireason == GRUB_ATAPI_IREASON_CMD_OUT)
- return grub_error (GRUB_ERR_READ_ERROR, "ATA PACKET command error");
- else
- return grub_error (GRUB_ERR_READ_ERROR, "ATAPI read error");
- }
-
- return grub_error (GRUB_ERR_READ_ERROR, "ATAPI protocol error");
-}
-
-static grub_err_t
-grub_atapi_packet (struct grub_ata_device *dev, char *packet,
- grub_size_t size)
-{
- grub_ata_regset (dev, GRUB_ATA_REG_DISK, dev->device << 4);
- if (grub_ata_check_ready (dev))
- return grub_errno;
-
- /* Send ATA PACKET command. */
- grub_ata_regset (dev, GRUB_ATA_REG_FEATURES, 0);
- grub_ata_regset (dev, GRUB_ATAPI_REG_IREASON, 0);
- grub_ata_regset (dev, GRUB_ATAPI_REG_CNTHIGH, size >> 8);
- grub_ata_regset (dev, GRUB_ATAPI_REG_CNTLOW, size & 0xFF);
-
- grub_ata_regset (dev, GRUB_ATA_REG_CMD, GRUB_ATA_CMD_PACKET);
-
- /* Wait for !BSY, DRQ, !I/O, C/D. */
- if (grub_atapi_wait_drq (dev, GRUB_ATAPI_IREASON_CMD_OUT, GRUB_ATA_TOUT_STD))
- return grub_errno;
-
- /* Write the packet. */
- grub_ata_pio_write (dev, packet, 12);
-
- return GRUB_ERR_NONE;
-}
-
-static grub_err_t
-grub_ata_identify (struct grub_ata_device *dev)
+grub_ata_identify (struct grub_ata *dev)
{
+ struct grub_disk_ata_pass_through_parms parms;
char *info;
grub_uint16_t *info16;
+ grub_err_t err;
info = grub_malloc (GRUB_DISK_SECTOR_SIZE);
if (! info)
return grub_errno;
info16 = (grub_uint16_t *) info;
+ grub_memset (&parms, 0, sizeof (parms));
+ parms.buffer = info;
+ parms.size = GRUB_DISK_SECTOR_SIZE;
+ parms.taskfile.disk = 0xE0;
- grub_ata_regset (dev, GRUB_ATA_REG_DISK, 0xE0 | dev->device << 4);
- grub_ata_wait ();
- if (grub_ata_check_ready (dev))
- {
- grub_free (info);
- return grub_errno;
- }
+ parms.taskfile.cmd = GRUB_ATA_CMD_IDENTIFY_DEVICE;
- grub_ata_regset (dev, GRUB_ATA_REG_CMD, GRUB_ATA_CMD_IDENTIFY_DEVICE);
- grub_ata_wait ();
+ err = dev->dev->readwrite (dev, &parms, *dev->present);
- if (grub_ata_wait_drq (dev, 0, GRUB_ATA_TOUT_STD))
+ if (err || parms.size != GRUB_DISK_SECTOR_SIZE)
{
+ grub_uint8_t sts = parms.taskfile.status;
grub_free (info);
grub_errno = GRUB_ERR_NONE;
- grub_uint8_t sts = grub_ata_regget (dev, GRUB_ATA_REG_STATUS);
-
if ((sts & (GRUB_ATA_STATUS_BUSY | GRUB_ATA_STATUS_DRQ
| GRUB_ATA_STATUS_ERR)) == GRUB_ATA_STATUS_ERR
- && (grub_ata_regget (dev, GRUB_ATA_REG_ERROR) & 0x04 /* ABRT */))
+ && (parms.taskfile.error & 0x04 /* ABRT */))
/* Device without ATA IDENTIFY, try ATAPI. */
return grub_atapi_identify (dev);
else if (sts == 0x00)
- /* No device, return error but don't print message. */
- return GRUB_ERR_UNKNOWN_DEVICE;
-
+ {
+ *dev->present = 0;
+ /* No device, return error but don't print message. */
+ return GRUB_ERR_UNKNOWN_DEVICE;
+ }
else
- /* Other Error. */
- return grub_error (GRUB_ERR_UNKNOWN_DEVICE,
- "device cannot be identified");
- }
-
- grub_ata_pio_read (dev, info, GRUB_DISK_SECTOR_SIZE);
-
- /* Re-check status to avoid bogus identify data due to stuck DRQ. */
- grub_uint8_t sts = grub_ata_regget (dev, GRUB_ATA_REG_STATUS);
- if (sts & (GRUB_ATA_STATUS_BUSY | GRUB_ATA_STATUS_DRQ | GRUB_ATA_STATUS_ERR))
- {
- grub_dprintf ("ata", "bad status=0x%x\n", sts);
- grub_free (info);
- /* No device, return error but don't print message. */
- grub_errno = GRUB_ERR_NONE;
- return GRUB_ERR_UNKNOWN_DEVICE;
+ {
+ *dev->present = 0;
+ /* Other Error. */
+ return grub_error (GRUB_ERR_UNKNOWN_DEVICE,
+ "device cannot be identified");
+ }
}
/* Now it is certain that this is not an ATAPI device. */
else
dev->size = grub_le_to_cpu64(*((grub_uint64_t *) &info16[100]));
+ if (info16[106] & (1 << 12))
+ {
+ grub_uint32_t secsize;
+ secsize = grub_le_to_cpu32 (*((grub_uint32_t *) &info16[117]));
+ if (secsize & (secsize - 1) || !secsize
+ || secsize > 1048576)
+ secsize = 256;
+ for (dev->log_sector_size = 0;
+ (1U << dev->log_sector_size) < secsize;
+ dev->log_sector_size++);
+ dev->log_sector_size++;
+ }
+ else
+ dev->log_sector_size = 9;
+
/* Read CHS information. */
dev->cylinders = info16[1];
dev->heads = info16[3];
}
static grub_err_t
-check_device (struct grub_ata_device *dev)
-{
- grub_ata_regset (dev, GRUB_ATA_REG_DISK, dev->device << 4);
- grub_ata_wait ();
-
- /* Try to detect if the port is in use by writing to it,
- waiting for a while and reading it again. If the value
- was preserved, there is a device connected. */
- grub_ata_regset (dev, GRUB_ATA_REG_SECTORS, 0x5A);
- grub_ata_wait ();
- grub_uint8_t sec = grub_ata_regget (dev, GRUB_ATA_REG_SECTORS);
- grub_dprintf ("ata", "sectors=0x%x\n", sec);
- if (sec != 0x5A)
- return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no device connected");
-
- /* The above test may detect a second (slave) device
- connected to a SATA controller which supports only one
- (master) device. It is not safe to use the status register
- READY bit to check for controller channel existence. Some
- ATAPI commands (RESET, DIAGNOSTIC) may clear this bit. */
-
- /* Use the IDENTIFY DEVICE command to query the device. */
- return grub_ata_identify (dev);
-}
-
-static grub_err_t
-grub_ata_device_initialize (int port, int device, int addr, int addr2)
-{
- struct grub_ata_device *dev;
- struct grub_ata_device **devp;
- grub_err_t err;
-
- grub_dprintf ("ata", "detecting device %d,%d (0x%x, 0x%x)\n",
- port, device, addr, addr2);
-
- dev = grub_malloc (sizeof(*dev));
- if (! dev)
- return grub_errno;
-
- /* Setup the device information. */
- dev->port = port;
- dev->device = device;
- dev->ioaddress = addr + GRUB_MACHINE_PCI_IO_BASE;
- dev->ioaddress2 = addr2 + GRUB_MACHINE_PCI_IO_BASE;
- dev->next = NULL;
-
- /* Register the device. */
- for (devp = &grub_ata_devices; *devp; devp = &(*devp)->next);
- *devp = dev;
-
- err = check_device (dev);
- if (err)
- grub_print_error ();
-
- return 0;
-}
-
-static int NESTED_FUNC_ATTR
-grub_ata_pciinit (grub_pci_device_t dev,
- grub_pci_id_t pciid)
-{
- static int compat_use[2] = { 0 };
- grub_pci_address_t addr;
- grub_uint32_t class;
- grub_uint32_t bar1;
- grub_uint32_t bar2;
- int rega;
- int regb;
- int i;
- static int controller = 0;
- int cs5536 = 0;
- int nports = 2;
-
- /* Read class. */
- addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS);
- class = grub_pci_read (addr);
-
- /* AMD CS5536 Southbridge. */
- if (pciid == GRUB_CS5536_PCIID)
- {
- cs5536 = 1;
- nports = 1;
- }
-
- /* Check if this class ID matches that of a PCI IDE Controller. */
- if (!cs5536 && (class >> 16 != 0x0101))
- return 0;
-
- for (i = 0; i < nports; i++)
- {
- /* Set to 0 when the channel operated in compatibility mode. */
- int compat;
-
- /* We don't support non-compatibility mode for CS5536. */
- if (cs5536)
- compat = 0;
- else
- compat = (class >> (8 + 2 * i)) & 1;
-
- rega = 0;
- regb = 0;
-
- /* If the channel is in compatibility mode, just assign the
- default registers. */
- if (compat == 0 && !compat_use[i])
- {
- rega = grub_ata_ioaddress[i];
- regb = grub_ata_ioaddress2[i];
- compat_use[i] = 1;
- }
- else if (compat)
- {
- /* Read the BARs, which either contain a mmapped IO address
- or the IO port address. */
- addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESSES
- + sizeof (grub_uint64_t) * i);
- bar1 = grub_pci_read (addr);
- addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESSES
- + sizeof (grub_uint64_t) * i
- + sizeof (grub_uint32_t));
- bar2 = grub_pci_read (addr);
-
- /* Check if the BARs describe an IO region. */
- if ((bar1 & 1) && (bar2 & 1))
- {
- rega = bar1 & ~3;
- regb = bar2 & ~3;
- }
- }
-
- grub_dprintf ("ata",
- "PCI dev (%d,%d,%d) compat=%d rega=0x%x regb=0x%x\n",
- grub_pci_get_bus (dev), grub_pci_get_device (dev),
- grub_pci_get_function (dev), compat, rega, regb);
-
- if (rega && regb)
- {
- grub_errno = GRUB_ERR_NONE;
- grub_ata_device_initialize (controller * 2 + i, 0, rega, regb);
-
- /* Most errors raised by grub_ata_device_initialize() are harmless.
- They just indicate this particular drive is not responding, most
- likely because it doesn't exist. We might want to ignore specific
- error types here, instead of printing them. */
- if (grub_errno)
- {
- grub_print_error ();
- grub_errno = GRUB_ERR_NONE;
- }
-
- grub_ata_device_initialize (controller * 2 + i, 1, rega, regb);
-
- /* Likewise. */
- if (grub_errno)
- {
- grub_print_error ();
- grub_errno = GRUB_ERR_NONE;
- }
- }
- }
-
- controller++;
-
- return 0;
-}
-
-static grub_err_t
-grub_ata_initialize (void)
-{
- grub_pci_iterate (grub_ata_pciinit);
- return 0;
-}
-
-static void
-grub_ata_setlba (struct grub_ata_device *dev, grub_disk_addr_t sector,
- grub_size_t size)
-{
- grub_ata_regset (dev, GRUB_ATA_REG_SECTORS, size);
- grub_ata_regset (dev, GRUB_ATA_REG_LBALOW, sector & 0xFF);
- grub_ata_regset (dev, GRUB_ATA_REG_LBAMID, (sector >> 8) & 0xFF);
- grub_ata_regset (dev, GRUB_ATA_REG_LBAHIGH, (sector >> 16) & 0xFF);
-}
-
-static grub_err_t
-grub_ata_setaddress (struct grub_ata_device *dev,
- grub_ata_addressing_t addressing,
+grub_ata_setaddress (struct grub_ata *dev,
+ struct grub_disk_ata_pass_through_parms *parms,
grub_disk_addr_t sector,
- grub_size_t size)
+ grub_size_t size,
+ grub_ata_addressing_t addressing)
{
switch (addressing)
{
return grub_error (GRUB_ERR_OUT_OF_RANGE,
"sector %d cannot be addressed "
"using CHS addressing", sector);
-
- grub_ata_regset (dev, GRUB_ATA_REG_DISK, (dev->device << 4) | head);
- if (grub_ata_check_ready (dev))
- return grub_errno;
-
- grub_ata_regset (dev, GRUB_ATA_REG_SECTNUM, sect);
- grub_ata_regset (dev, GRUB_ATA_REG_CYLLSB, cylinder & 0xFF);
- grub_ata_regset (dev, GRUB_ATA_REG_CYLMSB, cylinder >> 8);
+
+ parms->taskfile.disk = 0xE0 | head;
+ parms->taskfile.sectnum = sect;
+ parms->taskfile.cyllsb = cylinder & 0xFF;
+ parms->taskfile.cylmsb = cylinder >> 8;
break;
}
case GRUB_ATA_LBA:
if (size == 256)
size = 0;
- grub_ata_regset (dev, GRUB_ATA_REG_DISK,
- 0xE0 | (dev->device << 4) | ((sector >> 24) & 0x0F));
- if (grub_ata_check_ready (dev))
- return grub_errno;
+ parms->taskfile.disk = 0xE0 | ((sector >> 24) & 0x0F);
- grub_ata_setlba (dev, sector, size);
+ parms->taskfile.sectors = size;
+ parms->taskfile.lba_low = sector & 0xFF;
+ parms->taskfile.lba_mid = (sector >> 8) & 0xFF;
+ parms->taskfile.lba_high = (sector >> 16) & 0xFF;
break;
case GRUB_ATA_LBA48:
if (size == 65536)
size = 0;
- grub_ata_regset (dev, GRUB_ATA_REG_DISK, 0xE0 | (dev->device << 4));
- if (grub_ata_check_ready (dev))
- return grub_errno;
+ parms->taskfile.disk = 0xE0;
/* Set "Previous". */
- grub_ata_setlba (dev, sector >> 24, size >> 8);
+ parms->taskfile.sectors = size & 0xFF;
+ parms->taskfile.lba_low = sector & 0xFF;
+ parms->taskfile.lba_mid = (sector >> 8) & 0xFF;
+ parms->taskfile.lba_high = (sector >> 16) & 0xFF;
+
/* Set "Current". */
- grub_ata_setlba (dev, sector, size);
+ parms->taskfile.sectors48 = (size >> 8) & 0xFF;
+ parms->taskfile.lba48_low = (sector >> 24) & 0xFF;
+ parms->taskfile.lba48_mid = (sector >> 32) & 0xFF;
+ parms->taskfile.lba48_high = (sector >> 40) & 0xFF;
break;
}
grub_ata_readwrite (grub_disk_t disk, grub_disk_addr_t sector,
grub_size_t size, char *buf, int rw)
{
- struct grub_ata_device *dev = (struct grub_ata_device *) disk->data;
-
- grub_dprintf("ata", "grub_ata_readwrite (size=%llu, rw=%d)\n", (unsigned long long) size, rw);
+ struct grub_ata *ata = disk->data;
- grub_ata_addressing_t addressing = dev->addr;
+ grub_ata_addressing_t addressing = ata->addr;
grub_size_t batch;
int cmd, cmd_write;
+ grub_dprintf("ata", "grub_ata_readwrite (size=%llu, rw=%d)\n",
+ (unsigned long long) size, rw);
+
if (addressing == GRUB_ATA_LBA48 && ((sector + size) >> 28) != 0)
{
batch = 65536;
- cmd = GRUB_ATA_CMD_READ_SECTORS_EXT;
- cmd_write = GRUB_ATA_CMD_WRITE_SECTORS_EXT;
+ if (ata->dma)
+ {
+ cmd = GRUB_ATA_CMD_READ_SECTORS_DMA_EXT;
+ cmd_write = GRUB_ATA_CMD_WRITE_SECTORS_DMA_EXT;
+ }
+ else
+ {
+ cmd = GRUB_ATA_CMD_READ_SECTORS_EXT;
+ cmd_write = GRUB_ATA_CMD_WRITE_SECTORS_EXT;
+ }
}
else
{
if (addressing == GRUB_ATA_LBA48)
addressing = GRUB_ATA_LBA;
- batch = 256;
- cmd = GRUB_ATA_CMD_READ_SECTORS;
- cmd_write = GRUB_ATA_CMD_WRITE_SECTORS;
- }
+ if (addressing != GRUB_ATA_CHS)
+ batch = 256;
+ else
+ batch = 1;
+ if (ata->dma)
+ {
+ cmd = GRUB_ATA_CMD_READ_SECTORS_DMA;
+ cmd_write = GRUB_ATA_CMD_WRITE_SECTORS_DMA;
+ }
+ else
+ {
+ cmd = GRUB_ATA_CMD_READ_SECTORS;
+ cmd_write = GRUB_ATA_CMD_WRITE_SECTORS;
+ }
+ }
grub_size_t nsectors = 0;
while (nsectors < size)
{
+ struct grub_disk_ata_pass_through_parms parms;
+ grub_err_t err;
+
if (size - nsectors < batch)
batch = size - nsectors;
grub_dprintf("ata", "rw=%d, sector=%llu, batch=%llu\n", rw, (unsigned long long) sector, (unsigned long long) batch);
-
- /* Send read/write command. */
- if (grub_ata_setaddress (dev, addressing, sector, batch))
- return grub_errno;
-
- grub_ata_regset (dev, GRUB_ATA_REG_CMD, (! rw ? cmd : cmd_write));
-
- unsigned sect;
- for (sect = 0; sect < batch; sect++)
- {
- /* Wait for !BSY, DRQ. */
- if (grub_ata_wait_drq (dev, rw, GRUB_ATA_TOUT_DATA))
- return grub_errno;
-
- /* Transfer data. */
- if (! rw)
- grub_ata_pio_read (dev, buf, GRUB_DISK_SECTOR_SIZE);
- else
- grub_ata_pio_write (dev, buf, GRUB_DISK_SECTOR_SIZE);
-
- buf += GRUB_DISK_SECTOR_SIZE;
- }
-
- if (rw)
- {
- /* Check for write error. */
- if (grub_ata_wait_not_busy (dev, GRUB_ATA_TOUT_DATA))
- return grub_errno;
-
- if (grub_ata_regget (dev, GRUB_ATA_REG_STATUS)
- & (GRUB_ATA_STATUS_DRQ | GRUB_ATA_STATUS_ERR))
- return grub_error (GRUB_ERR_WRITE_ERROR, "ATA write error");
- }
-
+ grub_memset (&parms, 0, sizeof (parms));
+ grub_ata_setaddress (ata, &parms, sector, batch, addressing);
+ parms.taskfile.cmd = (! rw ? cmd : cmd_write);
+ parms.buffer = buf;
+ parms.size = batch << ata->log_sector_size;
+ parms.write = rw;
+ if (ata->dma)
+ parms.dma = 1;
+
+ err = ata->dev->readwrite (ata, &parms, 0);
+ if (err)
+ return err;
+ if (parms.size != batch << ata->log_sector_size)
+ return grub_error (GRUB_ERR_READ_ERROR, "incomplete read");
+ buf += batch << ata->log_sector_size;
sector += batch;
nsectors += batch;
}
\f
-static int
-grub_ata_iterate (int (*hook) (const char *name))
+static inline void
+grub_ata_real_close (struct grub_ata *ata)
+{
+ if (ata->dev->close)
+ ata->dev->close (ata);
+}
+
+static struct grub_ata *
+grub_ata_real_open (int id, int bus)
{
- struct grub_ata_device *dev;
+ struct grub_ata *ata;
+ grub_ata_dev_t p;
- for (dev = grub_ata_devices; dev; dev = dev->next)
+ ata = grub_malloc (sizeof (*ata));
+ if (!ata)
+ return NULL;
+ for (p = grub_ata_dev_list; p; p = p->next)
{
- char devname[10];
grub_err_t err;
-
- err = check_device (dev);
- if (err)
+ if (p->open (id, bus, ata))
{
grub_errno = GRUB_ERR_NONE;
continue;
}
+ ata->dev = p;
+ /* Use the IDENTIFY DEVICE command to query the device. */
+ err = grub_ata_identify (ata);
+ if (err)
+ {
+ grub_free (ata);
+ return NULL;
+ }
+ return ata;
+ }
+ grub_free (ata);
+ grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no such ATA device");
+ return NULL;
+}
- if (dev->atapi)
- continue;
-
- grub_snprintf (devname, sizeof (devname),
- "ata%d", dev->port * 2 + dev->device);
+static int
+grub_ata_iterate (int (*hook_in) (const char *name),
+ grub_disk_pull_t pull)
+{
+ auto int hook (int id, int bus);
+ int hook (int id, int bus)
+ {
+ struct grub_ata *ata;
+ int ret;
+ char devname[40];
- if (hook (devname))
- return 1;
- }
+ ata = grub_ata_real_open (id, bus);
+ if (!ata)
+ {
+ grub_errno = GRUB_ERR_NONE;
+ return 0;
+ }
+ if (ata->atapi)
+ {
+ grub_ata_real_close (ata);
+ return 0;
+ }
+ grub_snprintf (devname, sizeof (devname),
+ "%s%d", grub_scsi_names[id], bus);
+ ret = hook_in (devname);
+ grub_ata_real_close (ata);
+ return ret;
+ }
+
+ grub_ata_dev_t p;
+
+ for (p = grub_ata_dev_list; p; p = p->next)
+ if (p->iterate && p->iterate (hook, pull))
+ return 1;
return 0;
}
static grub_err_t
grub_ata_open (const char *name, grub_disk_t disk)
{
- struct grub_ata_device *dev;
- grub_err_t err;
+ unsigned id, bus;
+ struct grub_ata *ata;
- for (dev = grub_ata_devices; dev; dev = dev->next)
- {
- char devname[10];
- grub_snprintf (devname, sizeof (devname),
- "ata%d", dev->port * 2 + dev->device);
- if (grub_strcmp (name, devname) == 0)
- break;
- }
-
- if (! dev)
- return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't open device");
-
- if (dev->atapi)
+ for (id = 0; id < GRUB_SCSI_NUM_SUBSYSTEMS; id++)
+ if (grub_strncmp (grub_scsi_names[id], name,
+ grub_strlen (grub_scsi_names[id])) == 0
+ && grub_isdigit (name[grub_strlen (grub_scsi_names[id])]))
+ break;
+ if (id == GRUB_SCSI_NUM_SUBSYSTEMS)
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not an ATA harddisk");
+ bus = grub_strtoul (name + grub_strlen (grub_scsi_names[id]), 0, 0);
+ ata = grub_ata_real_open (id, bus);
+ if (!ata)
+ return grub_errno;
- err = check_device (dev);
-
- if (err)
- return err;
+ if (ata->atapi)
+ return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not an ATA harddisk");
- disk->total_sectors = dev->size;
+ disk->total_sectors = ata->size;
+ disk->log_sector_size = ata->log_sector_size;
- disk->id = (unsigned long) dev;
+ disk->id = grub_make_scsi_id (id, bus, 0);
- disk->data = dev;
+ disk->data = ata;
return 0;
}
static void
-grub_ata_close (grub_disk_t disk __attribute__((unused)))
+grub_ata_close (grub_disk_t disk)
{
-
+ struct grub_ata *ata = disk->data;
+ grub_ata_real_close (ata);
}
static grub_err_t
\f
/* ATAPI code. */
-static int
-grub_atapi_iterate (int (*hook) (int bus, int luns))
-{
- struct grub_ata_device *dev;
-
- for (dev = grub_ata_devices; dev; dev = dev->next)
- {
- grub_err_t err;
-
- err = check_device (dev);
- if (err)
- {
- grub_errno = GRUB_ERR_NONE;
- continue;
- }
-
- if (! dev->atapi)
- continue;
-
- if (hook (dev->port * 2 + dev->device, 1))
- return 1;
- }
-
- return 0;
-
-}
-
static grub_err_t
-grub_atapi_read (struct grub_scsi *scsi,
- grub_size_t cmdsize __attribute__((unused)),
- char *cmd, grub_size_t size, char *buf)
+grub_atapi_read (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd,
+ grub_size_t size, char *buf)
{
- struct grub_ata_device *dev = (struct grub_ata_device *) scsi->data;
+ struct grub_ata *dev = scsi->data;
+ struct grub_disk_ata_pass_through_parms parms;
+ grub_err_t err;
grub_dprintf("ata", "grub_atapi_read (size=%llu)\n", (unsigned long long) size);
+ grub_memset (&parms, 0, sizeof (parms));
+
+ parms.taskfile.disk = 0;
+ parms.taskfile.features = 0;
+ parms.taskfile.atapi_ireason = 0;
+ parms.taskfile.atapi_cnthigh = size >> 8;
+ parms.taskfile.atapi_cntlow = size & 0xff;
+ parms.taskfile.cmd = GRUB_ATA_CMD_PACKET;
+ parms.cmd = cmd;
+ parms.cmdsize = cmdsize;
+
+ parms.size = size;
+ parms.buffer = buf;
+
+ err = dev->dev->readwrite (dev, &parms, 0);
+ if (err)
+ return err;
- if (grub_atapi_packet (dev, cmd, size))
- return grub_errno;
-
- grub_size_t nread = 0;
- while (nread < size)
- {
- /* Wait for !BSY, DRQ, I/O, !C/D. */
- if (grub_atapi_wait_drq (dev, GRUB_ATAPI_IREASON_DATA_IN, GRUB_ATA_TOUT_DATA))
- return grub_errno;
-
- /* Get byte count for this DRQ assertion. */
- unsigned cnt = grub_ata_regget (dev, GRUB_ATAPI_REG_CNTHIGH) << 8
- | grub_ata_regget (dev, GRUB_ATAPI_REG_CNTLOW);
- grub_dprintf("ata", "DRQ count=%u\n", cnt);
-
- /* Count of last transfer may be uneven. */
- if (! (0 < cnt && cnt <= size - nread && (! (cnt & 1) || cnt == size - nread)))
- return grub_error (GRUB_ERR_READ_ERROR, "invalid ATAPI transfer count");
-
- /* Read the data. */
- grub_ata_pio_read (dev, buf + nread, cnt);
-
- if (cnt & 1)
- buf[nread + cnt - 1] = (char) grub_le_to_cpu16 (grub_inw (dev->ioaddress + GRUB_ATA_REG_DATA));
-
- nread += cnt;
- }
-
+ if (parms.size != size)
+ return grub_error (GRUB_ERR_READ_ERROR, "incomplete ATAPI read");
return GRUB_ERR_NONE;
}
}
static grub_err_t
-grub_atapi_open (int devnum, struct grub_scsi *scsi)
+grub_atapi_open (int id, int bus, struct grub_scsi *scsi)
{
- struct grub_ata_device *dev;
- struct grub_ata_device *devfnd = 0;
- grub_err_t err;
+ struct grub_ata *ata;
- for (dev = grub_ata_devices; dev; dev = dev->next)
- {
- if (dev->port * 2 + dev->device == devnum)
- {
- devfnd = dev;
- break;
- }
- }
+ ata = grub_ata_real_open (id, bus);
+ if (!ata)
+ return grub_errno;
+
+ if (! ata->atapi)
+ return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no such ATAPI device");
- grub_dprintf ("ata", "opening ATAPI dev `ata%d'\n", devnum);
+ scsi->data = ata;
+ scsi->luns = 1;
- if (! devfnd)
- return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no such ATAPI device");
+ return GRUB_ERR_NONE;
+}
- err = check_device (devfnd);
- if (err)
- return err;
+static int
+grub_atapi_iterate (int NESTED_FUNC_ATTR (*hook_in) (int id, int bus, int luns),
+ grub_disk_pull_t pull)
+{
+ auto int hook (int id, int bus);
+ int hook (int id, int bus)
+ {
+ struct grub_ata *ata;
+ int ret;
- if (! devfnd->atapi)
- return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no such ATAPI device");
+ ata = grub_ata_real_open (id, bus);
- scsi->data = devfnd;
+ if (!ata)
+ {
+ grub_errno = GRUB_ERR_NONE;
+ return 0;
+ }
+ if (!ata->atapi)
+ {
+ grub_ata_real_close (ata);
+ return 0;
+ }
+ ret = hook_in (id, bus, 1);
+ grub_ata_real_close (ata);
+ return ret;
+ }
+
+ grub_ata_dev_t p;
+
+ for (p = grub_ata_dev_list; p; p = p->next)
+ if (p->iterate && p->iterate (hook, pull))
+ return 1;
+ return 0;
+}
- return GRUB_ERR_NONE;
+static void
+grub_atapi_close (grub_scsi_t disk)
+{
+ struct grub_ata *ata = disk->data;
+ grub_ata_real_close (ata);
}
+void
+grub_ata_dev_register (grub_ata_dev_t dev)
+{
+ dev->next = grub_ata_dev_list;
+ grub_ata_dev_list = dev;
+}
+
+void
+grub_ata_dev_unregister (grub_ata_dev_t dev)
+{
+ grub_ata_dev_t *p, q;
+
+ for (p = &grub_ata_dev_list, q = *p; q; p = &(q->next), q = q->next)
+ if (q == dev)
+ {
+ *p = q->next;
+ break;
+ }
+}
+
static struct grub_scsi_dev grub_atapi_dev =
{
- .name = "ata",
- .id = GRUB_SCSI_SUBSYSTEM_ATAPI,
.iterate = grub_atapi_iterate,
.open = grub_atapi_open,
+ .close = grub_atapi_close,
.read = grub_atapi_read,
- .write = grub_atapi_write
+ .write = grub_atapi_write,
+ .next = 0
};
\f
GRUB_MOD_INIT(ata)
{
- /* To prevent two drivers operating on the same disks. */
- grub_disk_firmware_is_tainted = 1;
- if (grub_disk_firmware_fini)
- {
- grub_disk_firmware_fini ();
- grub_disk_firmware_fini = NULL;
- }
-
- /* ATA initialization. */
- grub_ata_initialize ();
-
grub_disk_dev_register (&grub_atadisk_dev);
/* ATAPI devices are handled by scsi.mod. */
+++ /dev/null
-/* ata_pthru.c - ATA pass through for ata.mod. */
-/*
- * GRUB -- GRand Unified Bootloader
- * Copyright (C) 2009 Free Software Foundation, Inc.
- *
- * GRUB is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * GRUB is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <grub/ata.h>
-#include <grub/disk.h>
-#include <grub/dl.h>
-#include <grub/mm.h>
-
-
-/* ATA pass through support, used by hdparm.mod. */
-static grub_err_t
-grub_ata_pass_through (grub_disk_t disk,
- struct grub_disk_ata_pass_through_parms *parms)
-{
- if (disk->dev->id != GRUB_DISK_DEVICE_ATA_ID)
- return grub_error (GRUB_ERR_BAD_DEVICE,
- "device not accessed via ata.mod");
-
- struct grub_ata_device *dev = (struct grub_ata_device *) disk->data;
-
- if (! (parms->size == 0 || parms->size == GRUB_DISK_SECTOR_SIZE))
- return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
- "ATA multi-sector read and DATA OUT not implemented");
-
- grub_dprintf ("ata", "ata_pass_through: cmd=0x%x, features=0x%x, sectors=0x%x\n",
- parms->taskfile[GRUB_ATA_REG_CMD],
- parms->taskfile[GRUB_ATA_REG_FEATURES],
- parms->taskfile[GRUB_ATA_REG_SECTORS]);
- grub_dprintf ("ata", "lba_high=0x%x, lba_mid=0x%x, lba_low=0x%x, size=%d\n",
- parms->taskfile[GRUB_ATA_REG_LBAHIGH],
- parms->taskfile[GRUB_ATA_REG_LBAMID],
- parms->taskfile[GRUB_ATA_REG_LBALOW], parms->size);
-
- /* Set registers. */
- grub_ata_regset (dev, GRUB_ATA_REG_DISK, 0xE0 | dev->device << 4
- | (parms->taskfile[GRUB_ATA_REG_DISK] & 0xf));
- if (grub_ata_check_ready (dev))
- return grub_errno;
-
- int i;
- for (i = GRUB_ATA_REG_FEATURES; i <= GRUB_ATA_REG_LBAHIGH; i++)
- grub_ata_regset (dev, i, parms->taskfile[i]);
-
- /* Start command. */
- grub_ata_regset (dev, GRUB_ATA_REG_CMD, parms->taskfile[GRUB_ATA_REG_CMD]);
-
- /* Wait for !BSY. */
- if (grub_ata_wait_not_busy (dev, GRUB_ATA_TOUT_DATA))
- return grub_errno;
-
- /* Check status. */
- grub_int8_t sts = grub_ata_regget (dev, GRUB_ATA_REG_STATUS);
- grub_dprintf ("ata", "status=0x%x\n", sts);
-
- /* Transfer data. */
- if ((sts & (GRUB_ATA_STATUS_DRQ | GRUB_ATA_STATUS_ERR)) == GRUB_ATA_STATUS_DRQ)
- {
- if (parms->size != GRUB_DISK_SECTOR_SIZE)
- return grub_error (GRUB_ERR_READ_ERROR, "DRQ unexpected");
- grub_ata_pio_read (dev, parms->buffer, GRUB_DISK_SECTOR_SIZE);
- }
-
- /* Return registers. */
- for (i = GRUB_ATA_REG_ERROR; i <= GRUB_ATA_REG_STATUS; i++)
- parms->taskfile[i] = grub_ata_regget (dev, i);
-
- grub_dprintf ("ata", "status=0x%x, error=0x%x, sectors=0x%x\n",
- parms->taskfile[GRUB_ATA_REG_STATUS],
- parms->taskfile[GRUB_ATA_REG_ERROR],
- parms->taskfile[GRUB_ATA_REG_SECTORS]);
-
- if (parms->taskfile[GRUB_ATA_REG_STATUS]
- & (GRUB_ATA_STATUS_DRQ | GRUB_ATA_STATUS_ERR))
- return grub_error (GRUB_ERR_READ_ERROR, "ATA passthrough failed");
-
- return GRUB_ERR_NONE;
-}
-
-\f
-
-GRUB_MOD_INIT(ata_pthru)
-{
- /* Register ATA pass through function. */
- grub_disk_ata_pass_through = grub_ata_pass_through;
-}
-
-GRUB_MOD_FINI(ata_pthru)
-{
- if (grub_disk_ata_pass_through == grub_ata_pass_through)
- grub_disk_ata_pass_through = NULL;
-}
--- /dev/null
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2003,2007,2010,2011 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/cryptodisk.h>
+#include <grub/mm.h>
+#include <grub/misc.h>
+#include <grub/dl.h>
+#include <grub/extcmd.h>
+#include <grub/i18n.h>
+
+#ifdef GRUB_UTIL
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <grub/emu/hostdisk.h>
+#include <unistd.h>
+#include <string.h>
+#endif
+
+GRUB_MOD_LICENSE ("GPLv3+");
+
+grub_cryptodisk_dev_t grub_cryptodisk_list;
+
+static const struct grub_arg_option options[] =
+ {
+ {"uuid", 'u', 0, N_("Mount by UUID."), 0, 0},
+ {"all", 'a', 0, N_("Mount all."), 0, 0},
+ {"boot", 'b', 0, N_("Mount all volumes marked as boot."), 0, 0},
+ {0, 0, 0, 0, 0, 0}
+ };
+
+/* Our irreducible polynom is x^128+x^7+x^2+x+1. Lowest byte of it is: */
+#define GF_POLYNOM 0x87
+static inline int GF_PER_SECTOR (const struct grub_cryptodisk *dev)
+{
+ return 1U << (dev->log_sector_size - GRUB_CRYPTODISK_GF_LOG_BYTES);
+}
+
+static grub_cryptodisk_t cryptodisk_list = NULL;
+static grub_uint8_t n = 0;
+
+static void
+gf_mul_x (grub_uint8_t *g)
+{
+ int over = 0, over2 = 0;
+ unsigned j;
+
+ for (j = 0; j < GRUB_CRYPTODISK_GF_BYTES; j++)
+ {
+ over2 = !!(g[j] & 0x80);
+ g[j] <<= 1;
+ g[j] |= over;
+ over = over2;
+ }
+ if (over)
+ g[0] ^= GF_POLYNOM;
+}
+
+
+static void
+gf_mul_x_be (grub_uint8_t *g)
+{
+ int over = 0, over2 = 0;
+ int j;
+
+ for (j = (int) GRUB_CRYPTODISK_GF_BYTES - 1; j >= 0; j--)
+ {
+ over2 = !!(g[j] & 0x80);
+ g[j] <<= 1;
+ g[j] |= over;
+ over = over2;
+ }
+ if (over)
+ g[GRUB_CRYPTODISK_GF_BYTES - 1] ^= GF_POLYNOM;
+}
+
+static void
+gf_mul_be (grub_uint8_t *o, const grub_uint8_t *a, const grub_uint8_t *b)
+{
+ unsigned i;
+ grub_uint8_t t[GRUB_CRYPTODISK_GF_BYTES];
+ grub_memset (o, 0, GRUB_CRYPTODISK_GF_BYTES);
+ grub_memcpy (t, b, GRUB_CRYPTODISK_GF_BYTES);
+ for (i = 0; i < GRUB_CRYPTODISK_GF_SIZE; i++)
+ {
+ if (((a[GRUB_CRYPTODISK_GF_BYTES - i / 8 - 1] >> (i % 8))) & 1)
+ grub_crypto_xor (o, o, t, GRUB_CRYPTODISK_GF_BYTES);
+ gf_mul_x_be (t);
+ }
+}
+
+static gcry_err_code_t
+grub_crypto_pcbc_decrypt (grub_crypto_cipher_handle_t cipher,
+ void *out, void *in, grub_size_t size,
+ void *iv)
+{
+ grub_uint8_t *inptr, *outptr, *end;
+ grub_uint8_t ivt[cipher->cipher->blocksize];
+ if (!cipher->cipher->decrypt)
+ return GPG_ERR_NOT_SUPPORTED;
+ if (size % cipher->cipher->blocksize != 0)
+ return GPG_ERR_INV_ARG;
+ end = (grub_uint8_t *) in + size;
+ for (inptr = in, outptr = out; inptr < end;
+ inptr += cipher->cipher->blocksize, outptr += cipher->cipher->blocksize)
+ {
+ grub_memcpy (ivt, inptr, cipher->cipher->blocksize);
+ cipher->cipher->decrypt (cipher->ctx, outptr, inptr);
+ grub_crypto_xor (outptr, outptr, iv, cipher->cipher->blocksize);
+ grub_crypto_xor (iv, ivt, outptr, cipher->cipher->blocksize);
+ }
+ return GPG_ERR_NO_ERROR;
+}
+
+struct lrw_sector
+{
+ grub_uint8_t low[GRUB_CRYPTODISK_GF_BYTES];
+ grub_uint8_t high[GRUB_CRYPTODISK_GF_BYTES];
+ grub_uint8_t low_byte, low_byte_c;
+};
+
+static void
+generate_lrw_sector (struct lrw_sector *sec,
+ const struct grub_cryptodisk *dev,
+ const grub_uint8_t *iv)
+{
+ grub_uint8_t idx[GRUB_CRYPTODISK_GF_BYTES];
+ grub_uint16_t c;
+ int j;
+ grub_memcpy (idx, iv, GRUB_CRYPTODISK_GF_BYTES);
+ sec->low_byte = (idx[GRUB_CRYPTODISK_GF_BYTES - 1]
+ & (GF_PER_SECTOR (dev) - 1));
+ sec->low_byte_c = (((GF_PER_SECTOR (dev) - 1) & ~sec->low_byte) + 1);
+ idx[GRUB_CRYPTODISK_GF_BYTES - 1] &= ~(GF_PER_SECTOR (dev) - 1);
+ gf_mul_be (sec->low, dev->lrw_key, idx);
+ if (!sec->low_byte)
+ return;
+
+ c = idx[GRUB_CRYPTODISK_GF_BYTES - 1] + GF_PER_SECTOR (dev);
+ if (c & 0x100)
+ {
+ for (j = GRUB_CRYPTODISK_GF_BYTES - 2; j >= 0; j--)
+ {
+ idx[j]++;
+ if (idx[j] != 0)
+ break;
+ }
+ }
+ idx[GRUB_CRYPTODISK_GF_BYTES - 1] = c;
+ gf_mul_be (sec->high, dev->lrw_key, idx);
+}
+
+static void __attribute__ ((unused))
+lrw_xor (const struct lrw_sector *sec,
+ const struct grub_cryptodisk *dev,
+ grub_uint8_t *b)
+{
+ unsigned i;
+
+ for (i = 0; i < sec->low_byte_c * GRUB_CRYPTODISK_GF_BYTES;
+ i += GRUB_CRYPTODISK_GF_BYTES)
+ grub_crypto_xor (b + i, b + i, sec->low, GRUB_CRYPTODISK_GF_BYTES);
+ grub_crypto_xor (b, b, dev->lrw_precalc + GRUB_CRYPTODISK_GF_BYTES * sec->low_byte,
+ sec->low_byte_c * GRUB_CRYPTODISK_GF_BYTES);
+ if (!sec->low_byte)
+ return;
+
+ for (i = sec->low_byte_c * GRUB_CRYPTODISK_GF_BYTES;
+ i < (1U << dev->log_sector_size); i += GRUB_CRYPTODISK_GF_BYTES)
+ grub_crypto_xor (b + i, b + i, sec->high, GRUB_CRYPTODISK_GF_BYTES);
+ grub_crypto_xor (b + sec->low_byte_c * GRUB_CRYPTODISK_GF_BYTES,
+ b + sec->low_byte_c * GRUB_CRYPTODISK_GF_BYTES,
+ dev->lrw_precalc, sec->low_byte * GRUB_CRYPTODISK_GF_BYTES);
+}
+
+gcry_err_code_t
+grub_cryptodisk_decrypt (struct grub_cryptodisk *dev,
+ grub_uint8_t * data, grub_size_t len,
+ grub_disk_addr_t sector)
+{
+ grub_size_t i;
+ gcry_err_code_t err;
+
+ /* The only mode without IV. */
+ if (dev->mode == GRUB_CRYPTODISK_MODE_ECB && !dev->rekey)
+ return grub_crypto_ecb_decrypt (dev->cipher, data, data, len);
+
+ for (i = 0; i < len; i += (1U << dev->log_sector_size))
+ {
+ grub_size_t sz = ((dev->cipher->cipher->blocksize
+ + sizeof (grub_uint32_t) - 1)
+ / sizeof (grub_uint32_t));
+ grub_uint32_t iv[sz];
+
+ if (dev->rekey)
+ {
+ grub_uint64_t zone = sector >> dev->rekey_shift;
+ if (zone != dev->last_rekey)
+ {
+ err = dev->rekey (dev, zone);
+ if (err)
+ return err;
+ dev->last_rekey = zone;
+ }
+ }
+
+ grub_memset (iv, 0, sz * sizeof (iv[0]));
+ switch (dev->mode_iv)
+ {
+ case GRUB_CRYPTODISK_MODE_IV_NULL:
+ break;
+ case GRUB_CRYPTODISK_MODE_IV_BYTECOUNT64_HASH:
+ {
+ grub_uint64_t tmp;
+ grub_uint64_t ctx[(dev->iv_hash->contextsize + 7) / 8];
+
+ grub_memset (ctx, 0, sizeof (ctx));
+
+ tmp = grub_cpu_to_le64 (sector << dev->log_sector_size);
+ dev->iv_hash->init (ctx);
+ dev->iv_hash->write (ctx, dev->iv_prefix, dev->iv_prefix_len);
+ dev->iv_hash->write (ctx, &tmp, sizeof (tmp));
+ dev->iv_hash->final (ctx);
+
+ grub_memcpy (iv, dev->iv_hash->read (ctx), sizeof (iv));
+ }
+ break;
+ case GRUB_CRYPTODISK_MODE_IV_PLAIN64:
+ iv[1] = grub_cpu_to_le32 (sector >> 32);
+ case GRUB_CRYPTODISK_MODE_IV_PLAIN:
+ iv[0] = grub_cpu_to_le32 (sector & 0xFFFFFFFF);
+ break;
+ case GRUB_CRYPTODISK_MODE_IV_BYTECOUNT64:
+ iv[1] = grub_cpu_to_le32 (sector >> (32 - dev->log_sector_size));
+ iv[0] = grub_cpu_to_le32 ((sector << dev->log_sector_size)
+ & 0xFFFFFFFF);
+ break;
+ case GRUB_CRYPTODISK_MODE_IV_BENBI:
+ {
+ grub_uint64_t num = (sector << dev->benbi_log) + 1;
+ iv[sz - 2] = grub_cpu_to_be32 (num >> 32);
+ iv[sz - 1] = grub_cpu_to_be32 (num & 0xFFFFFFFF);
+ }
+ break;
+ case GRUB_CRYPTODISK_MODE_IV_ESSIV:
+ iv[0] = grub_cpu_to_le32 (sector & 0xFFFFFFFF);
+ err = grub_crypto_ecb_encrypt (dev->essiv_cipher, iv, iv,
+ dev->cipher->cipher->blocksize);
+ if (err)
+ return err;
+ }
+
+ switch (dev->mode)
+ {
+ case GRUB_CRYPTODISK_MODE_CBC:
+ err = grub_crypto_cbc_decrypt (dev->cipher, data + i, data + i,
+ (1U << dev->log_sector_size), iv);
+ if (err)
+ return err;
+ break;
+
+ case GRUB_CRYPTODISK_MODE_PCBC:
+ err = grub_crypto_pcbc_decrypt (dev->cipher, data + i, data + i,
+ (1U << dev->log_sector_size), iv);
+ if (err)
+ return err;
+ break;
+ case GRUB_CRYPTODISK_MODE_XTS:
+ {
+ unsigned j;
+ err = grub_crypto_ecb_encrypt (dev->secondary_cipher, iv, iv,
+ dev->cipher->cipher->blocksize);
+ if (err)
+ return err;
+
+ for (j = 0; j < (1U << dev->log_sector_size);
+ j += dev->cipher->cipher->blocksize)
+ {
+ grub_crypto_xor (data + i + j, data + i + j, iv,
+ dev->cipher->cipher->blocksize);
+ err = grub_crypto_ecb_decrypt (dev->cipher, data + i + j,
+ data + i + j,
+ dev->cipher->cipher->blocksize);
+ if (err)
+ return err;
+ grub_crypto_xor (data + i + j, data + i + j, iv,
+ dev->cipher->cipher->blocksize);
+ gf_mul_x ((grub_uint8_t *) iv);
+ }
+ }
+ break;
+ case GRUB_CRYPTODISK_MODE_LRW:
+ {
+ struct lrw_sector sec;
+
+ generate_lrw_sector (&sec, dev, (grub_uint8_t *) iv);
+ lrw_xor (&sec, dev, data + i);
+
+ err = grub_crypto_ecb_decrypt (dev->cipher, data + i,
+ data + i,
+ (1U << dev->log_sector_size));
+ if (err)
+ return err;
+ lrw_xor (&sec, dev, data + i);
+ }
+ break;
+ case GRUB_CRYPTODISK_MODE_ECB:
+ grub_crypto_ecb_decrypt (dev->cipher, data + i, data + i,
+ (1U << dev->log_sector_size));
+ break;
+ default:
+ return GPG_ERR_NOT_IMPLEMENTED;
+ }
+ sector++;
+ }
+ return GPG_ERR_NO_ERROR;
+}
+
+gcry_err_code_t
+grub_cryptodisk_setkey (grub_cryptodisk_t dev, grub_uint8_t *key, grub_size_t keysize)
+{
+ gcry_err_code_t err;
+ int real_keysize;
+
+ real_keysize = keysize;
+ if (dev->mode == GRUB_CRYPTODISK_MODE_XTS)
+ real_keysize /= 2;
+ if (dev->mode == GRUB_CRYPTODISK_MODE_LRW)
+ real_keysize -= dev->cipher->cipher->blocksize;
+
+ /* Set the PBKDF2 output as the cipher key. */
+ err = grub_crypto_cipher_set_key (dev->cipher, key, real_keysize);
+ if (err)
+ return err;
+
+ /* Configure ESSIV if necessary. */
+ if (dev->mode_iv == GRUB_CRYPTODISK_MODE_IV_ESSIV)
+ {
+ grub_size_t essiv_keysize = dev->essiv_hash->mdlen;
+ grub_uint8_t hashed_key[essiv_keysize];
+
+ grub_crypto_hash (dev->essiv_hash, hashed_key, key, keysize);
+ err = grub_crypto_cipher_set_key (dev->essiv_cipher,
+ hashed_key, essiv_keysize);
+ if (err)
+ return err;
+ }
+ if (dev->mode == GRUB_CRYPTODISK_MODE_XTS)
+ {
+ err = grub_crypto_cipher_set_key (dev->secondary_cipher,
+ key + real_keysize,
+ keysize / 2);
+ if (err)
+ return err;
+ }
+
+ if (dev->mode == GRUB_CRYPTODISK_MODE_LRW)
+ {
+ unsigned i;
+ grub_uint8_t idx[GRUB_CRYPTODISK_GF_BYTES];
+
+ grub_free (dev->lrw_precalc);
+ grub_memcpy (dev->lrw_key, key + real_keysize,
+ dev->cipher->cipher->blocksize);
+ dev->lrw_precalc = grub_malloc ((1U << dev->log_sector_size));
+ if (!dev->lrw_precalc)
+ return GPG_ERR_OUT_OF_MEMORY;
+ grub_memset (idx, 0, GRUB_CRYPTODISK_GF_BYTES);
+ for (i = 0; i < (1U << dev->log_sector_size);
+ i += GRUB_CRYPTODISK_GF_BYTES)
+ {
+ idx[GRUB_CRYPTODISK_GF_BYTES - 1] = i / GRUB_CRYPTODISK_GF_BYTES;
+ gf_mul_be (dev->lrw_precalc + i, idx, dev->lrw_key);
+ }
+ }
+ return GPG_ERR_NO_ERROR;
+}
+
+static int
+grub_cryptodisk_iterate (int (*hook) (const char *name),
+ grub_disk_pull_t pull)
+{
+ grub_cryptodisk_t i;
+
+ if (pull != GRUB_DISK_PULL_NONE)
+ return 0;
+
+ for (i = cryptodisk_list; i != NULL; i = i->next)
+ {
+ char buf[30];
+ grub_snprintf (buf, sizeof (buf), "crypto%lu", i->id);
+ if (hook (buf))
+ return 1;
+ }
+
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_cryptodisk_open (const char *name, grub_disk_t disk)
+{
+ grub_cryptodisk_t dev;
+
+ if (grub_memcmp (name, "crypto", sizeof ("crypto") - 1) != 0)
+ return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "No such device");
+
+ if (grub_memcmp (name, "cryptouuid/", sizeof ("cryptouuid/") - 1) == 0)
+ {
+ for (dev = cryptodisk_list; dev != NULL; dev = dev->next)
+ if (grub_strcasecmp (name + sizeof ("cryptouuid/") - 1, dev->uuid) == 0)
+ break;
+ }
+ else
+ {
+ unsigned long id = grub_strtoul (name + sizeof ("crypto") - 1, 0, 0);
+ if (grub_errno)
+ return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "No such device");
+ /* Search for requested device in the list of CRYPTODISK devices. */
+ for (dev = cryptodisk_list; dev != NULL; dev = dev->next)
+ if (dev->id == id)
+ break;
+ }
+ if (!dev)
+ return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "No such device");
+
+ disk->log_sector_size = dev->log_sector_size;
+
+#ifdef GRUB_UTIL
+ if (dev->cheat)
+ {
+ if (dev->cheat_fd == -1)
+ dev->cheat_fd = open (dev->cheat, O_RDONLY);
+ if (dev->cheat_fd == -1)
+ return grub_error (GRUB_ERR_IO, "couldn't open %s: %s",
+ dev->cheat, strerror (errno));
+ }
+#endif
+
+ if (!dev->source_disk)
+ {
+ grub_dprintf ("cryptodisk", "Opening device %s\n", name);
+ /* Try to open the source disk and populate the requested disk. */
+ dev->source_disk = grub_disk_open (dev->source);
+ if (!dev->source_disk)
+ return grub_errno;
+ }
+
+ disk->data = dev;
+ disk->total_sectors = dev->total_length;
+ disk->id = dev->id;
+ dev->ref++;
+ return GRUB_ERR_NONE;
+}
+
+static void
+grub_cryptodisk_close (grub_disk_t disk)
+{
+ grub_cryptodisk_t dev = (grub_cryptodisk_t) disk->data;
+ grub_dprintf ("cryptodisk", "Closing disk\n");
+
+ dev->ref--;
+
+ if (dev->ref != 0)
+ return;
+#ifdef GRUB_UTIL
+ if (dev->cheat)
+ {
+ close (dev->cheat_fd);
+ dev->cheat_fd = -1;
+ }
+#endif
+ grub_disk_close (dev->source_disk);
+ dev->source_disk = NULL;
+}
+
+static grub_err_t
+grub_cryptodisk_read (grub_disk_t disk, grub_disk_addr_t sector,
+ grub_size_t size, char *buf)
+{
+ grub_cryptodisk_t dev = (grub_cryptodisk_t) disk->data;
+ grub_err_t err;
+ gcry_err_code_t gcry_err;
+
+#ifdef GRUB_UTIL
+ if (dev->cheat)
+ {
+ err = grub_util_fd_seek (dev->cheat_fd, dev->cheat,
+ sector << disk->log_sector_size);
+ if (err)
+ return err;
+ if (grub_util_fd_read (dev->cheat_fd, buf, size << disk->log_sector_size)
+ != (ssize_t) (size << disk->log_sector_size))
+ return grub_error (GRUB_ERR_READ_ERROR, "cannot read from `%s'",
+ dev->cheat);
+ return GRUB_ERR_NONE;
+ }
+#endif
+
+ grub_dprintf ("cryptodisk",
+ "Reading %" PRIuGRUB_SIZE " sectors from sector 0x%"
+ PRIxGRUB_UINT64_T " with offset of %" PRIuGRUB_UINT64_T "\n",
+ size, sector, dev->offset);
+
+ err = grub_disk_read (dev->source_disk,
+ (sector << (disk->log_sector_size
+ - GRUB_DISK_SECTOR_BITS)) + dev->offset, 0,
+ size << disk->log_sector_size, buf);
+ if (err)
+ {
+ grub_dprintf ("cryptodisk", "grub_disk_read failed with error %d\n", err);
+ return err;
+ }
+ gcry_err = grub_cryptodisk_decrypt (dev, (grub_uint8_t *) buf,
+ size << disk->log_sector_size,
+ sector);
+ return grub_crypto_gcry_error (gcry_err);
+}
+
+static grub_err_t
+grub_cryptodisk_write (grub_disk_t disk __attribute ((unused)),
+ grub_disk_addr_t sector __attribute ((unused)),
+ grub_size_t size __attribute ((unused)),
+ const char *buf __attribute ((unused)))
+{
+ return GRUB_ERR_NOT_IMPLEMENTED_YET;
+}
+
+#ifdef GRUB_UTIL
+static grub_disk_memberlist_t
+grub_cryptodisk_memberlist (grub_disk_t disk)
+{
+ grub_cryptodisk_t dev = (grub_cryptodisk_t) disk->data;
+ grub_disk_memberlist_t list = NULL;
+
+ list = grub_malloc (sizeof (*list));
+ if (list)
+ {
+ list->disk = dev->source_disk;
+ list->next = NULL;
+ }
+
+ return list;
+}
+#endif
+
+static void
+cryptodisk_cleanup (void)
+{
+ grub_cryptodisk_t dev = cryptodisk_list;
+ grub_cryptodisk_t tmp;
+
+ while (dev != NULL)
+ {
+ grub_free (dev->source);
+ grub_free (dev->cipher);
+ grub_free (dev->secondary_cipher);
+ grub_free (dev->essiv_cipher);
+ tmp = dev->next;
+ grub_free (dev);
+ dev = tmp;
+ }
+}
+
+grub_err_t
+grub_cryptodisk_insert (grub_cryptodisk_t newdev, const char *name,
+ grub_disk_t source)
+{
+ newdev->source = grub_strdup (name);
+ if (!newdev->source)
+ {
+ grub_free (newdev);
+ return grub_errno;
+ }
+
+ newdev->id = n++;
+ newdev->source_id = source->id;
+ newdev->source_dev_id = source->dev->id;
+ newdev->next = cryptodisk_list;
+ cryptodisk_list = newdev;
+
+ return GRUB_ERR_NONE;
+}
+
+grub_cryptodisk_t
+grub_cryptodisk_get_by_uuid (const char *uuid)
+{
+ grub_cryptodisk_t dev;
+ for (dev = cryptodisk_list; dev != NULL; dev = dev->next)
+ if (grub_strcasecmp (dev->uuid, uuid) == 0)
+ return dev;
+ return NULL;
+}
+
+grub_cryptodisk_t
+grub_cryptodisk_get_by_source_disk (grub_disk_t disk)
+{
+ grub_cryptodisk_t dev;
+ for (dev = cryptodisk_list; dev != NULL; dev = dev->next)
+ if (dev->source_id == disk->id && dev->source_dev_id == disk->dev->id)
+ return dev;
+ return NULL;
+}
+
+#ifdef GRUB_UTIL
+grub_err_t
+grub_cryptodisk_cheat_insert (grub_cryptodisk_t newdev, const char *name,
+ grub_disk_t source, const char *cheat)
+{
+ newdev->cheat = grub_strdup (cheat);
+ newdev->source = grub_strdup (name);
+ if (!newdev->source || !newdev->cheat)
+ {
+ grub_free (newdev->source);
+ grub_free (newdev->cheat);
+ return grub_errno;
+ }
+
+ newdev->cheat_fd = -1;
+ newdev->source_id = source->id;
+ newdev->source_dev_id = source->dev->id;
+ newdev->id = n++;
+ newdev->next = cryptodisk_list;
+ cryptodisk_list = newdev;
+
+ return GRUB_ERR_NONE;
+}
+
+void
+grub_util_cryptodisk_print_abstraction (grub_disk_t disk)
+{
+ grub_cryptodisk_t dev = (grub_cryptodisk_t) disk->data;
+
+ grub_printf ("cryptodisk %s ", dev->modname);
+
+ if (dev->cipher)
+ grub_printf ("%s ", dev->cipher->cipher->modname);
+ if (dev->secondary_cipher)
+ grub_printf ("%s ", dev->secondary_cipher->cipher->modname);
+ if (dev->essiv_cipher)
+ grub_printf ("%s ", dev->essiv_cipher->cipher->modname);
+ if (dev->hash)
+ grub_printf ("%s ", dev->hash->modname);
+ if (dev->essiv_hash)
+ grub_printf ("%s ", dev->essiv_hash->modname);
+ if (dev->iv_hash)
+ grub_printf ("%s ", dev->iv_hash->modname);
+}
+
+void
+grub_util_cryptodisk_print_uuid (grub_disk_t disk)
+{
+ grub_cryptodisk_t dev = (grub_cryptodisk_t) disk->data;
+ grub_printf ("%s ", dev->uuid);
+}
+
+#endif
+
+static int check_boot, have_it;
+static char *search_uuid;
+
+static void
+cryptodisk_close (grub_cryptodisk_t dev)
+{
+ grub_crypto_cipher_close (dev->cipher);
+ grub_crypto_cipher_close (dev->secondary_cipher);
+ grub_crypto_cipher_close (dev->essiv_cipher);
+ grub_free (dev);
+}
+
+static grub_err_t
+grub_cryptodisk_scan_device_real (const char *name, grub_disk_t source)
+{
+ grub_err_t err;
+ grub_cryptodisk_t dev;
+ grub_cryptodisk_dev_t cr;
+
+ dev = grub_cryptodisk_get_by_source_disk (source);
+
+ if (dev)
+ return GRUB_ERR_NONE;
+
+ FOR_CRYPTODISK_DEVS (cr)
+ {
+ dev = cr->scan (source, search_uuid, check_boot);
+ if (grub_errno)
+ return grub_errno;
+ if (!dev)
+ continue;
+
+ err = cr->recover_key (source, dev);
+ if (err)
+ {
+ cryptodisk_close (dev);
+ return err;
+ }
+
+ grub_cryptodisk_insert (dev, name, source);
+
+ have_it = 1;
+
+ return GRUB_ERR_NONE;
+ }
+ return GRUB_ERR_NONE;
+}
+
+#ifdef GRUB_UTIL
+#include <grub/util/misc.h>
+grub_err_t
+grub_cryptodisk_cheat_mount (const char *sourcedev, const char *cheat)
+{
+ grub_err_t err;
+ grub_cryptodisk_t dev;
+ grub_cryptodisk_dev_t cr;
+ grub_disk_t source;
+
+ /* Try to open disk. */
+ source = grub_disk_open (sourcedev);
+ if (!source)
+ return grub_errno;
+
+ dev = grub_cryptodisk_get_by_source_disk (source);
+
+ if (dev)
+ {
+ grub_disk_close (source);
+ return GRUB_ERR_NONE;
+ }
+
+ FOR_CRYPTODISK_DEVS (cr)
+ {
+ dev = cr->scan (source, search_uuid, check_boot);
+ if (grub_errno)
+ return grub_errno;
+ if (!dev)
+ continue;
+
+ grub_util_info ("cheatmounted %s (%s) at %s", sourcedev, dev->modname,
+ cheat);
+ err = grub_cryptodisk_cheat_insert (dev, sourcedev, source, cheat);
+ grub_disk_close (source);
+ if (err)
+ grub_free (dev);
+
+ return GRUB_ERR_NONE;
+ }
+
+ grub_disk_close (source);
+
+ return GRUB_ERR_NONE;
+}
+#endif
+
+static int
+grub_cryptodisk_scan_device (const char *name)
+{
+ grub_err_t err;
+ grub_disk_t source;
+
+ /* Try to open disk. */
+ source = grub_disk_open (name);
+ if (!source)
+ return grub_errno;
+
+ err = grub_cryptodisk_scan_device_real (name, source);
+
+ grub_disk_close (source);
+
+ if (err)
+ grub_print_error ();
+ return have_it && search_uuid ? 1 : 0;
+}
+
+static grub_err_t
+grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
+{
+ struct grub_arg_list *state = ctxt->state;
+
+ if (argc < 1 && !state[1].set && !state[2].set)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "device name required");
+
+ have_it = 0;
+ if (state[0].set)
+ {
+ grub_cryptodisk_t dev;
+
+ dev = grub_cryptodisk_get_by_uuid (args[0]);
+ if (dev)
+ {
+ grub_dprintf ("cryptodisk",
+ "already mounted as crypto%lu\n", dev->id);
+ return GRUB_ERR_NONE;
+ }
+
+ check_boot = state[2].set;
+ search_uuid = args[0];
+ grub_device_iterate (&grub_cryptodisk_scan_device);
+ search_uuid = NULL;
+
+ if (!have_it)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "no such cryptodisk found");
+ return GRUB_ERR_NONE;
+ }
+ else if (state[1].set || (argc == 0 && state[2].set))
+ {
+ search_uuid = NULL;
+ check_boot = state[2].set;
+ grub_device_iterate (&grub_cryptodisk_scan_device);
+ search_uuid = NULL;
+ return GRUB_ERR_NONE;
+ }
+ else
+ {
+ grub_err_t err;
+ grub_disk_t disk;
+ grub_cryptodisk_t dev;
+
+ search_uuid = NULL;
+ check_boot = state[2].set;
+ disk = grub_disk_open (args[0]);
+ if (!disk)
+ return grub_errno;
+
+ dev = grub_cryptodisk_get_by_source_disk (disk);
+ if (dev)
+ {
+ grub_dprintf ("cryptodisk", "already mounted as crypto%lu\n", dev->id);
+ grub_disk_close (disk);
+ return GRUB_ERR_NONE;
+ }
+
+ err = grub_cryptodisk_scan_device_real (args[0], disk);
+
+ grub_disk_close (disk);
+
+ return err;
+ }
+}
+
+static struct grub_disk_dev grub_cryptodisk_dev = {
+ .name = "cryptodisk",
+ .id = GRUB_DISK_DEVICE_CRYPTODISK_ID,
+ .iterate = grub_cryptodisk_iterate,
+ .open = grub_cryptodisk_open,
+ .close = grub_cryptodisk_close,
+ .read = grub_cryptodisk_read,
+ .write = grub_cryptodisk_write,
+#ifdef GRUB_UTIL
+ .memberlist = grub_cryptodisk_memberlist,
+#endif
+ .next = 0
+};
+
+static grub_extcmd_t cmd;
+
+GRUB_MOD_INIT (cryptodisk)
+{
+ grub_disk_dev_register (&grub_cryptodisk_dev);
+ cmd = grub_register_extcmd ("cryptomount", grub_cmd_cryptomount, 0,
+ N_("SOURCE|-u UUID|-a|-b"),
+ N_("Mount a crypto device."), options);
+}
+
+GRUB_MOD_FINI (cryptodisk)
+{
+ grub_disk_dev_unregister (&grub_cryptodisk_dev);
+ cryptodisk_cleanup ();
+}
#include <grub/misc.h>
#include <grub/raid.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
#define NV_SIGNATURES 4
#define NV_IDLE 0
grub_efi_device_path_t *device_path;
grub_efi_device_path_t *last_device_path;
grub_efi_block_io_t *block_io;
- grub_efi_disk_io_t *disk_io;
struct grub_efidisk_data *next;
};
-/* GUIDs. */
-static grub_efi_guid_t disk_io_guid = GRUB_EFI_DISK_IO_GUID;
+/* GUID. */
static grub_efi_guid_t block_io_guid = GRUB_EFI_BLOCK_IO_GUID;
static struct grub_efidisk_data *fd_devices;
return p;
}
-/* Compare device paths. */
-static int
-compare_device_paths (const grub_efi_device_path_t *dp1,
- const grub_efi_device_path_t *dp2)
-{
- if (! dp1 || ! dp2)
- /* Return non-zero. */
- return 1;
-
- while (1)
- {
- grub_efi_uint8_t type1, type2;
- grub_efi_uint8_t subtype1, subtype2;
- grub_efi_uint16_t len1, len2;
- int ret;
-
- type1 = GRUB_EFI_DEVICE_PATH_TYPE (dp1);
- type2 = GRUB_EFI_DEVICE_PATH_TYPE (dp2);
-
- if (type1 != type2)
- return (int) type2 - (int) type1;
-
- subtype1 = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp1);
- subtype2 = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp2);
-
- if (subtype1 != subtype2)
- return (int) subtype1 - (int) subtype2;
-
- len1 = GRUB_EFI_DEVICE_PATH_LENGTH (dp1);
- len2 = GRUB_EFI_DEVICE_PATH_LENGTH (dp2);
-
- if (len1 != len2)
- return (int) len1 - (int) len2;
-
- ret = grub_memcmp (dp1, dp2, len1);
- if (ret != 0)
- return ret;
-
- if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp1))
- break;
-
- dp1 = (grub_efi_device_path_t *) ((char *) dp1 + len1);
- dp2 = (grub_efi_device_path_t *) ((char *) dp2 + len2);
- }
-
- return 0;
-}
-
static struct grub_efidisk_data *
make_devices (void)
{
struct grub_efidisk_data *devices = 0;
/* Find handles which support the disk io interface. */
- handles = grub_efi_locate_handle (GRUB_EFI_BY_PROTOCOL, &disk_io_guid,
+ handles = grub_efi_locate_handle (GRUB_EFI_BY_PROTOCOL, &block_io_guid,
0, &num_handles);
if (! handles)
return 0;
grub_efi_device_path_t *ldp;
struct grub_efidisk_data *d;
grub_efi_block_io_t *bio;
- grub_efi_disk_io_t *dio;
dp = grub_efi_get_device_path (*handle);
if (! dp)
bio = grub_efi_open_protocol (*handle, &block_io_guid,
GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
- dio = grub_efi_open_protocol (*handle, &disk_io_guid,
- GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
- if (! bio || ! dio)
+ if (! bio)
/* This should not happen... Why? */
continue;
d->device_path = dp;
d->last_device_path = ldp;
d->block_io = bio;
- d->disk_io = dio;
d->next = devices;
devices = d;
}
if (parent == d)
continue;
- if (compare_device_paths (parent->device_path, dp) == 0)
+ if (grub_efi_compare_device_paths (parent->device_path, dp) == 0)
{
/* Found. */
if (! parent->last_device_path)
ldp->length[0] = sizeof (*ldp);
ldp->length[1] = 0;
- if (compare_device_paths (dp, d->device_path) == 0)
+ if (grub_efi_compare_device_paths (dp, d->device_path) == 0)
if (hook (p))
{
grub_free (dp);
{
int ret;
- ret = compare_device_paths (find_last_device_path ((*p)->device_path),
- find_last_device_path (d->device_path));
+ ret = grub_efi_compare_device_paths (find_last_device_path ((*p)->device_path),
+ find_last_device_path (d->device_path));
if (ret == 0)
- ret = compare_device_paths ((*p)->device_path,
- d->device_path);
+ ret = grub_efi_compare_device_paths ((*p)->device_path,
+ d->device_path);
if (ret == 0)
return;
else if (ret > 0)
}
static int
-grub_efidisk_iterate (int (*hook) (const char *name))
+grub_efidisk_iterate (int (*hook) (const char *name),
+ grub_disk_pull_t pull)
{
struct grub_efidisk_data *d;
char buf[16];
int count;
- for (d = fd_devices, count = 0; d; d = d->next, count++)
+ switch (pull)
{
- grub_snprintf (buf, sizeof (buf), "fd%d", count);
- grub_dprintf ("efidisk", "iterating %s\n", buf);
- if (hook (buf))
- return 1;
- }
-
- for (d = hd_devices, count = 0; d; d = d->next, count++)
- {
- grub_snprintf (buf, sizeof (buf), "hd%d", count);
- grub_dprintf ("efidisk", "iterating %s\n", buf);
- if (hook (buf))
- return 1;
- }
+ case GRUB_DISK_PULL_NONE:
+ for (d = hd_devices, count = 0; d; d = d->next, count++)
+ {
+ grub_snprintf (buf, sizeof (buf), "hd%d", count);
+ grub_dprintf ("efidisk", "iterating %s\n", buf);
+ if (hook (buf))
+ return 1;
+ }
+ break;
+ case GRUB_DISK_PULL_REMOVABLE:
+ for (d = fd_devices, count = 0; d; d = d->next, count++)
+ {
+ grub_snprintf (buf, sizeof (buf), "fd%d", count);
+ grub_dprintf ("efidisk", "iterating %s\n", buf);
+ if (hook (buf))
+ return 1;
+ }
- for (d = cd_devices, count = 0; d; d = d->next, count++)
- {
- grub_snprintf (buf, sizeof (buf), "cd%d", count);
- grub_dprintf ("efidisk", "iterating %s\n", buf);
- if (hook (buf))
- return 1;
+ for (d = cd_devices, count = 0; d; d = d->next, count++)
+ {
+ grub_snprintf (buf, sizeof (buf), "cd%d", count);
+ grub_dprintf ("efidisk", "iterating %s\n", buf);
+ if (hook (buf))
+ return 1;
+ }
+ break;
+ default:
+ return 0;
}
return 0;
and total sectors should be replaced with total blocks. */
grub_dprintf ("efidisk", "m = %p, last block = %llx, block size = %x\n",
m, (unsigned long long) m->last_block, m->block_size);
- disk->total_sectors = (m->last_block
- * (m->block_size >> GRUB_DISK_SECTOR_BITS));
+ disk->total_sectors = m->last_block + 1;
+ if (m->block_size & (m->block_size - 1) || !m->block_size)
+ return grub_error (GRUB_ERR_IO, "invalid sector size %d",
+ m->block_size);
+ for (disk->log_sector_size = 0;
+ (1U << disk->log_sector_size) < m->block_size;
+ disk->log_sector_size++);
disk->data = d;
grub_dprintf ("efidisk", "opening %s succeeded\n", name);
{
/* For now, use the disk io interface rather than the block io's. */
struct grub_efidisk_data *d;
- grub_efi_disk_io_t *dio;
grub_efi_block_io_t *bio;
grub_efi_status_t status;
d = disk->data;
- dio = d->disk_io;
bio = d->block_io;
grub_dprintf ("efidisk",
"reading 0x%lx sectors at the sector 0x%llx from %s\n",
(unsigned long) size, (unsigned long long) sector, disk->name);
- status = efi_call_5 (dio->read, dio, bio->media->media_id,
- (grub_efi_uint64_t) sector << GRUB_DISK_SECTOR_BITS,
- (grub_efi_uintn_t) size << GRUB_DISK_SECTOR_BITS,
- buf);
+ status = efi_call_5 (bio->read_blocks, bio, bio->media->media_id,
+ (grub_efi_uint64_t) sector,
+ (grub_efi_uintn_t) size << disk->log_sector_size,
+ buf);
if (status != GRUB_EFI_SUCCESS)
return grub_error (GRUB_ERR_READ_ERROR, "efidisk read error");
{
/* For now, use the disk io interface rather than the block io's. */
struct grub_efidisk_data *d;
- grub_efi_disk_io_t *dio;
grub_efi_block_io_t *bio;
grub_efi_status_t status;
d = disk->data;
- dio = d->disk_io;
bio = d->block_io;
grub_dprintf ("efidisk",
"writing 0x%lx sectors at the sector 0x%llx to %s\n",
(unsigned long) size, (unsigned long long) sector, disk->name);
- status = efi_call_5 (dio->write, dio, bio->media->media_id,
- (grub_efi_uint64_t) sector << GRUB_DISK_SECTOR_BITS,
- (grub_efi_uintn_t) size << GRUB_DISK_SECTOR_BITS,
+ status = efi_call_5 (bio->write_blocks, bio, bio->media->media_id,
+ (grub_efi_uint64_t) sector,
+ (grub_efi_uintn_t) size << disk->log_sector_size,
(void *) buf);
if (status != GRUB_EFI_SUCCESS)
return grub_error (GRUB_ERR_WRITE_ERROR, "efidisk write error");
char *
grub_efidisk_get_device_name (grub_efi_handle_t *handle)
{
- grub_efi_device_path_t *dp, *ldp;
+ grub_efi_device_path_t *dp, *ldp, *sdp;
+ /* This is a hard disk partition. */
+ grub_disk_t parent = 0;
+ auto int find_parent_disk (const char *name);
+
+ /* Find the disk which is the parent of a given hard disk partition. */
+ int find_parent_disk (const char *name)
+ {
+ grub_disk_t disk;
+
+ disk = grub_disk_open (name);
+ if (! disk)
+ return 1;
+
+ if (disk->dev->id == GRUB_DISK_DEVICE_EFIDISK_ID)
+ {
+ struct grub_efidisk_data *d;
+
+ d = disk->data;
+ if (grub_efi_compare_device_paths (d->device_path, sdp) == 0)
+ {
+ parent = disk;
+ return 1;
+ }
+ }
+
+ grub_disk_close (disk);
+ return 0;
+ }
dp = grub_efi_get_device_path (handle);
if (! dp)
&& (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp)
== GRUB_EFI_HARD_DRIVE_DEVICE_PATH_SUBTYPE))
{
- /* This is a hard disk partition. */
- grub_disk_t parent = 0;
- grub_partition_t tpart = NULL;
+ char *partition_name = NULL;
char *device_name;
grub_efi_device_path_t *dup_dp, *dup_ldp;
grub_efi_hard_drive_device_path_t hd;
- auto int find_parent_disk (const char *name);
auto int find_partition (grub_disk_t disk, const grub_partition_t part);
- /* Find the disk which is the parent of a given hard disk partition. */
- int find_parent_disk (const char *name)
- {
- grub_disk_t disk;
-
- disk = grub_disk_open (name);
- if (! disk)
- return 1;
-
- if (disk->dev->id == GRUB_DISK_DEVICE_EFIDISK_ID)
- {
- struct grub_efidisk_data *d;
-
- d = disk->data;
- if (compare_device_paths (d->device_path, dup_dp) == 0)
- {
- parent = disk;
- return 1;
- }
- }
-
- grub_disk_close (disk);
- return 0;
- }
-
/* Find the identical partition. */
int find_partition (grub_disk_t disk __attribute__ ((unused)),
const grub_partition_t part)
if (grub_partition_get_start (part) == hd.partition_start
&& grub_partition_get_len (part) == hd.partition_size)
{
- tpart = part;
+ partition_name = grub_partition_get_name (part);
return 1;
}
dup_ldp->length[0] = sizeof (*dup_ldp);
dup_ldp->length[1] = 0;
- grub_efidisk_iterate (find_parent_disk);
+ sdp = dup_dp;
+
+ grub_efidisk_iterate (find_parent_disk, GRUB_DISK_PULL_NONE);
+ if (!parent)
+ grub_efidisk_iterate (find_parent_disk, GRUB_DISK_PULL_REMOVABLE);
grub_free (dup_dp);
if (! parent)
/* Find a partition which matches the hard drive device path. */
grub_memcpy (&hd, ldp, sizeof (hd));
- grub_partition_iterate (parent, find_partition);
-
- if (! tpart)
+ if (hd.partition_start == 0
+ && hd.partition_size == grub_disk_get_size (parent))
{
- grub_disk_close (parent);
- return 0;
+ device_name = grub_strdup (parent->name);
}
+ else
+ {
+ grub_partition_iterate (parent, find_partition);
- {
- char *partition_name = grub_partition_get_name (tpart);
- device_name = grub_xasprintf ("%s,%s", parent->name, partition_name);
- grub_free (partition_name);
- }
+ if (! partition_name)
+ {
+ grub_disk_close (parent);
+ return 0;
+ }
+
+ device_name = grub_xasprintf ("%s,%s", parent->name, partition_name);
+ grub_free (partition_name);
+ }
grub_disk_close (parent);
return device_name;
else
{
/* This should be an entire disk. */
- auto int find_disk (const char *name);
char *device_name = 0;
- int find_disk (const char *name)
- {
- grub_disk_t disk;
-
- disk = grub_disk_open (name);
- if (! disk)
- return 1;
-
- if (disk->dev->id == GRUB_DISK_DEVICE_EFIDISK_ID)
- {
- struct grub_efidisk_data *d;
-
- d = disk->data;
- if (compare_device_paths (d->device_path, dp) == 0)
- {
- device_name = grub_strdup (disk->name);
- grub_disk_close (disk);
- return 1;
- }
- }
-
- grub_disk_close (disk);
- return 0;
+ sdp = dp;
- }
-
- grub_efidisk_iterate (find_disk);
+ grub_efidisk_iterate (find_parent_disk, GRUB_DISK_PULL_NONE);
+ if (!parent)
+ grub_efidisk_iterate (find_parent_disk, GRUB_DISK_PULL_REMOVABLE);
+ if (!parent)
+ return NULL;
+ device_name = grub_strdup (parent->name);
+ grub_disk_close (parent);
return device_name;
}
--- /dev/null
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2003,2007,2010,2011 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* This file is loosely based on FreeBSD geli implementation
+ (but no code was directly copied). FreeBSD geli is distributed under
+ following terms: */
+/*-
+ * Copyright (c) 2005-2006 Pawel Jakub Dawidek <pjd@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <grub/cryptodisk.h>
+#include <grub/types.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/dl.h>
+#include <grub/err.h>
+#include <grub/disk.h>
+#include <grub/crypto.h>
+#include <grub/partition.h>
+#include <grub/i18n.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
+
+struct grub_geli_key
+{
+ grub_uint8_t iv_key[64];
+ grub_uint8_t cipher_key[64];
+ grub_uint8_t hmac[64];
+} __attribute__ ((packed));
+
+struct grub_geli_phdr
+{
+ grub_uint8_t magic[16];
+#define GELI_MAGIC "GEOM::ELI"
+ grub_uint32_t version;
+ grub_uint32_t flags;
+ grub_uint16_t alg;
+ grub_uint16_t keylen;
+ grub_uint16_t unused3[5];
+ grub_uint32_t sector_size;
+ grub_uint8_t keys_used;
+ grub_uint32_t niter;
+ grub_uint8_t salt[64];
+ struct grub_geli_key keys[2];
+} __attribute__ ((packed));
+
+enum
+ {
+ GRUB_GELI_FLAGS_ONETIME = 1,
+ GRUB_GELI_FLAGS_BOOT = 2,
+ };
+
+/* FIXME: support version 0. */
+/* FIXME: support big-endian pre-version-4 volumes. */
+/* FIXME: support for keyfiles. */
+/* FIXME: support for HMAC. */
+const char *algorithms[] = {
+ [0x01] = "des",
+ [0x02] = "3des",
+ [0x03] = "blowfish",
+ [0x04] = "cast5",
+ /* FIXME: 0x05 is skipjack, but we don't have it. */
+ [0x0b] = "aes",
+ /* FIXME: 0x10 is null. */
+ [0x15] = "camellia128",
+ [0x16] = "aes"
+};
+
+#define MAX_PASSPHRASE 256
+
+static gcry_err_code_t
+geli_rekey (struct grub_cryptodisk *dev, grub_uint64_t zoneno)
+{
+ gcry_err_code_t gcry_err;
+ const struct {
+ char magic[4];
+ grub_uint64_t zone;
+ } __attribute__ ((packed)) tohash
+ = { {'e', 'k', 'e', 'y'}, grub_cpu_to_le64 (zoneno) };
+ grub_uint64_t key[(dev->hash->mdlen + 7) / 8];
+
+ grub_dprintf ("geli", "rekeying %" PRIuGRUB_UINT64_T " keysize=%d\n",
+ zoneno, dev->rekey_derived_size);
+ gcry_err = grub_crypto_hmac_buffer (dev->hash, dev->rekey_key, 64,
+ &tohash, sizeof (tohash), key);
+ if (gcry_err)
+ return grub_crypto_gcry_error (gcry_err);
+
+ return grub_cryptodisk_setkey (dev, (grub_uint8_t *) key,
+ dev->rekey_derived_size);
+}
+
+static inline int
+ascii2hex (char c)
+{
+ if (c >= '0' && c <= '9')
+ return c - '0';
+ if (c >= 'a' && c <= 'f')
+ return c - 'a' + 10;
+ if (c >= 'A' && c <= 'F')
+ return c - 'A' + 10;
+ return 0;
+}
+
+static inline gcry_err_code_t
+make_uuid (const struct grub_geli_phdr *header,
+ char *uuid)
+{
+ grub_uint8_t uuidbin[GRUB_MD_SHA256->mdlen];
+ gcry_err_code_t err;
+ grub_uint8_t *iptr;
+ char *optr;
+
+ err = grub_crypto_hmac_buffer (GRUB_MD_SHA256,
+ header->salt, sizeof (header->salt),
+ "uuid", sizeof ("uuid") - 1, uuidbin);
+ if (err)
+ return err;
+
+ optr = uuid;
+ for (iptr = uuidbin; iptr < &uuidbin[ARRAY_SIZE (uuidbin)]; iptr++)
+ {
+ grub_snprintf (optr, 3, "%02x", *iptr);
+ optr += 2;
+ }
+ *optr = 0;
+ return GPG_ERR_NO_ERROR;
+}
+
+#ifdef GRUB_UTIL
+
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <grub/emu/hostdisk.h>
+#include <unistd.h>
+#include <string.h>
+#include <grub/emu/misc.h>
+
+char *
+grub_util_get_geli_uuid (const char *dev)
+{
+ int fd = open (dev, O_RDONLY);
+ grub_uint64_t s;
+ unsigned log_secsize;
+ grub_uint8_t hdr[512];
+ struct grub_geli_phdr *header;
+ char *uuid;
+ gcry_err_code_t err;
+
+ if (fd < 0)
+ return NULL;
+
+ s = grub_util_get_fd_sectors (fd, &log_secsize);
+ grub_util_fd_seek (fd, dev, (s << log_secsize) - 512);
+
+ uuid = xmalloc (GRUB_MD_SHA256->mdlen * 2 + 1);
+ if (grub_util_fd_read (fd, (void *) &hdr, 512) < 0)
+ grub_util_error ("couldn't read ELI metadata");
+
+ COMPILE_TIME_ASSERT (sizeof (header) <= 512);
+ header = (void *) &hdr;
+
+ /* Look for GELI magic sequence. */
+ if (grub_memcmp (header->magic, GELI_MAGIC, sizeof (GELI_MAGIC))
+ || grub_le_to_cpu32 (header->version) > 5
+ || grub_le_to_cpu32 (header->version) < 1)
+ grub_util_error ("wrong ELI magic or version");
+
+ err = make_uuid ((void *) &hdr, uuid);
+ if (err)
+ return NULL;
+
+ return uuid;
+}
+#endif
+
+static grub_cryptodisk_t
+configure_ciphers (grub_disk_t disk, const char *check_uuid,
+ int boot_only)
+{
+ grub_cryptodisk_t newdev;
+ struct grub_geli_phdr header;
+ grub_crypto_cipher_handle_t cipher = NULL, secondary_cipher = NULL;
+ const struct gcry_cipher_spec *ciph;
+ const char *ciphername = NULL;
+ gcry_err_code_t gcry_err;
+ char uuid[GRUB_MD_SHA256->mdlen * 2 + 1];
+ grub_disk_addr_t sector;
+ grub_err_t err;
+
+ sector = grub_disk_get_size (disk);
+ if (sector == GRUB_DISK_SIZE_UNKNOWN || sector == 0)
+ return NULL;
+
+ /* Read the GELI header. */
+ err = grub_disk_read (disk, sector - 1, 0, sizeof (header), &header);
+ if (err)
+ return NULL;
+
+ /* Look for GELI magic sequence. */
+ if (grub_memcmp (header.magic, GELI_MAGIC, sizeof (GELI_MAGIC))
+ || grub_le_to_cpu32 (header.version) > 5
+ || grub_le_to_cpu32 (header.version) < 1)
+ {
+ grub_dprintf ("geli", "wrong magic %02x\n", header.magic[0]);
+ return NULL;
+ }
+
+ if ((grub_le_to_cpu32 (header.sector_size)
+ & (grub_le_to_cpu32 (header.sector_size) - 1))
+ || grub_le_to_cpu32 (header.sector_size) == 0)
+ {
+ grub_dprintf ("geli", "incorrect sector size %d\n",
+ grub_le_to_cpu32 (header.sector_size));
+ return NULL;
+ }
+
+ if (grub_le_to_cpu32 (header.flags) & GRUB_GELI_FLAGS_ONETIME)
+ {
+ grub_dprintf ("geli", "skipping one-time volume\n");
+ return NULL;
+ }
+
+ if (boot_only && !(grub_le_to_cpu32 (header.flags) & GRUB_GELI_FLAGS_BOOT))
+ {
+ grub_dprintf ("geli", "not a boot volume\n");
+ return NULL;
+ }
+
+ gcry_err = make_uuid (&header, uuid);
+ if (gcry_err)
+ {
+ grub_crypto_gcry_error (gcry_err);
+ return NULL;
+ }
+
+ if (check_uuid && grub_strcasecmp (check_uuid, uuid) != 0)
+ {
+ grub_dprintf ("geli", "%s != %s\n", uuid, check_uuid);
+ return NULL;
+ }
+
+ if (grub_le_to_cpu16 (header.alg) >= ARRAY_SIZE (algorithms)
+ || algorithms[grub_le_to_cpu16 (header.alg)] == NULL)
+ {
+ grub_error (GRUB_ERR_FILE_NOT_FOUND, "Cipher 0x%x unknown",
+ grub_le_to_cpu16 (header.alg));
+ return NULL;
+ }
+
+ ciphername = algorithms[grub_le_to_cpu16 (header.alg)];
+ ciph = grub_crypto_lookup_cipher_by_name (ciphername);
+ if (!ciph)
+ {
+ grub_error (GRUB_ERR_FILE_NOT_FOUND, "Cipher %s isn't available",
+ ciphername);
+ return NULL;
+ }
+
+ /* Configure the cipher used for the bulk data. */
+ cipher = grub_crypto_cipher_open (ciph);
+ if (!cipher)
+ return NULL;
+
+ if (grub_le_to_cpu16 (header.alg) == 0x16)
+ {
+ secondary_cipher = grub_crypto_cipher_open (ciph);
+ if (!secondary_cipher)
+ return NULL;
+ }
+
+ if (grub_le_to_cpu16 (header.keylen) > 1024)
+ {
+ grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid keysize %d",
+ grub_le_to_cpu16 (header.keylen));
+ return NULL;
+ }
+
+ newdev = grub_zalloc (sizeof (struct grub_cryptodisk));
+ if (!newdev)
+ return NULL;
+ newdev->cipher = cipher;
+ newdev->secondary_cipher = secondary_cipher;
+ newdev->offset = 0;
+ newdev->source_disk = NULL;
+ newdev->benbi_log = 0;
+ if (grub_le_to_cpu16 (header.alg) == 0x16)
+ {
+ newdev->mode = GRUB_CRYPTODISK_MODE_XTS;
+ newdev->mode_iv = GRUB_CRYPTODISK_MODE_IV_BYTECOUNT64;
+ }
+ else
+ {
+ newdev->mode = GRUB_CRYPTODISK_MODE_CBC;
+ newdev->mode_iv = GRUB_CRYPTODISK_MODE_IV_BYTECOUNT64_HASH;
+ }
+ newdev->essiv_cipher = NULL;
+ newdev->essiv_hash = NULL;
+ newdev->hash = GRUB_MD_SHA512;
+ newdev->iv_hash = GRUB_MD_SHA256;
+
+ for (newdev->log_sector_size = 0;
+ (1U << newdev->log_sector_size) < grub_le_to_cpu32 (header.sector_size);
+ newdev->log_sector_size++);
+
+ if (grub_le_to_cpu32 (header.version) >= 5)
+ {
+ newdev->rekey = geli_rekey;
+ newdev->rekey_shift = 20;
+ }
+
+#ifdef GRUB_UTIL
+ newdev->modname = "geli";
+#endif
+
+ newdev->total_length = grub_disk_get_size (disk) - 1;
+ grub_memcpy (newdev->uuid, uuid, sizeof (newdev->uuid));
+ COMPILE_TIME_ASSERT (sizeof (newdev->uuid) >= 32 * 2 + 1);
+ return newdev;
+}
+
+static grub_err_t
+recover_key (grub_disk_t source, grub_cryptodisk_t dev)
+{
+ grub_size_t keysize;
+ grub_uint8_t digest[dev->hash->mdlen];
+ grub_uint8_t geomkey[dev->hash->mdlen];
+ grub_uint8_t verify_key[dev->hash->mdlen];
+ grub_uint8_t zero[dev->cipher->cipher->blocksize];
+ char passphrase[MAX_PASSPHRASE] = "";
+ unsigned i;
+ gcry_err_code_t gcry_err;
+ struct grub_geli_phdr header;
+ char *tmp;
+ grub_disk_addr_t sector;
+ grub_err_t err;
+
+ sector = grub_disk_get_size (source);
+ if (sector == GRUB_DISK_SIZE_UNKNOWN || sector == 0)
+ return grub_error (GRUB_ERR_OUT_OF_RANGE, "not a geli");
+
+ /* Read the GELI header. */
+ err = grub_disk_read (source, sector - 1, 0, sizeof (header), &header);
+ if (err)
+ return err;
+
+ keysize = grub_le_to_cpu16 (header.keylen) / 8;
+ grub_memset (zero, 0, sizeof (zero));
+
+ grub_printf ("Attempting to decrypt master key...\n");
+
+ /* Get the passphrase from the user. */
+ tmp = NULL;
+ if (source->partition)
+ tmp = grub_partition_get_name (source->partition);
+ grub_printf ("Enter passphrase for %s%s%s (%s): ", source->name,
+ source->partition ? "," : "", tmp ? : "",
+ dev->uuid);
+ grub_free (tmp);
+ if (!grub_password_get (passphrase, MAX_PASSPHRASE))
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "Passphrase not supplied");
+
+ /* Calculate the PBKDF2 of the user supplied passphrase. */
+ if (grub_le_to_cpu32 (header.niter) != 0)
+ {
+ grub_uint8_t pbkdf_key[64];
+ gcry_err = grub_crypto_pbkdf2 (dev->hash, (grub_uint8_t *) passphrase,
+ grub_strlen (passphrase),
+ header.salt,
+ sizeof (header.salt),
+ grub_le_to_cpu32 (header.niter),
+ pbkdf_key, sizeof (pbkdf_key));
+
+ if (gcry_err)
+ return grub_crypto_gcry_error (gcry_err);
+
+ gcry_err = grub_crypto_hmac_buffer (dev->hash, NULL, 0, pbkdf_key,
+ sizeof (pbkdf_key), geomkey);
+ if (gcry_err)
+ return grub_crypto_gcry_error (gcry_err);
+ }
+ else
+ {
+ struct grub_crypto_hmac_handle *hnd;
+
+ hnd = grub_crypto_hmac_init (dev->hash, NULL, 0);
+ if (!hnd)
+ return grub_crypto_gcry_error (GPG_ERR_OUT_OF_MEMORY);
+
+ grub_crypto_hmac_write (hnd, header.salt, sizeof (header.salt));
+ grub_crypto_hmac_write (hnd, passphrase, grub_strlen (passphrase));
+
+ gcry_err = grub_crypto_hmac_fini (hnd, geomkey);
+ if (gcry_err)
+ return grub_crypto_gcry_error (gcry_err);
+ }
+
+ gcry_err = grub_crypto_hmac_buffer (dev->hash, geomkey,
+ sizeof (geomkey), "\1", 1, digest);
+ if (gcry_err)
+ return grub_crypto_gcry_error (gcry_err);
+
+ gcry_err = grub_crypto_hmac_buffer (dev->hash, geomkey,
+ sizeof (geomkey), "\0", 1, verify_key);
+ if (gcry_err)
+ return grub_crypto_gcry_error (gcry_err);
+
+ grub_dprintf ("geli", "keylen = %" PRIuGRUB_SIZE "\n", keysize);
+
+ /* Try to recover master key from each active keyslot. */
+ for (i = 0; i < ARRAY_SIZE (header.keys); i++)
+ {
+ struct grub_geli_key candidate_key;
+ grub_uint8_t key_hmac[dev->hash->mdlen];
+
+ /* Check if keyslot is enabled. */
+ if (! (header.keys_used & (1 << i)))
+ continue;
+
+ grub_dprintf ("geli", "Trying keyslot %d\n", i);
+
+ gcry_err = grub_crypto_cipher_set_key (dev->cipher,
+ digest, keysize);
+ if (gcry_err)
+ return grub_crypto_gcry_error (gcry_err);
+
+ gcry_err = grub_crypto_cbc_decrypt (dev->cipher, &candidate_key,
+ &header.keys[i],
+ sizeof (candidate_key),
+ zero);
+ if (gcry_err)
+ return grub_crypto_gcry_error (gcry_err);
+
+ gcry_err = grub_crypto_hmac_buffer (dev->hash, verify_key,
+ sizeof (verify_key),
+ &candidate_key,
+ (sizeof (candidate_key)
+ - sizeof (candidate_key.hmac)),
+ key_hmac);
+ if (gcry_err)
+ return grub_crypto_gcry_error (gcry_err);
+
+ if (grub_memcmp (candidate_key.hmac, key_hmac, dev->hash->mdlen) != 0)
+ continue;
+ grub_printf ("Slot %d opened\n", i);
+
+ /* Set the master key. */
+ if (!dev->rekey)
+ {
+ grub_size_t real_keysize = keysize;
+ if (grub_le_to_cpu16 (header.alg) == 0x16)
+ real_keysize *= 2;
+ gcry_err = grub_cryptodisk_setkey (dev, candidate_key.cipher_key,
+ real_keysize);
+ if (gcry_err)
+ return grub_crypto_gcry_error (gcry_err);
+ }
+ else
+ {
+ grub_size_t real_keysize = keysize;
+ if (grub_le_to_cpu16 (header.alg) == 0x16)
+ real_keysize *= 2;
+ /* For a reason I don't know, the IV key is used in rekeying. */
+ grub_memcpy (dev->rekey_key, candidate_key.iv_key,
+ sizeof (candidate_key.iv_key));
+ dev->rekey_derived_size = real_keysize;
+ dev->last_rekey = -1;
+ COMPILE_TIME_ASSERT (sizeof (dev->rekey_key)
+ >= sizeof (candidate_key.iv_key));
+ }
+
+ dev->iv_prefix_len = sizeof (candidate_key.iv_key);
+ grub_memcpy (dev->iv_prefix, candidate_key.iv_key,
+ sizeof (candidate_key.iv_key));
+
+ COMPILE_TIME_ASSERT (sizeof (dev->iv_prefix) >= sizeof (candidate_key.iv_key));
+
+ return GRUB_ERR_NONE;
+ }
+
+ return GRUB_ACCESS_DENIED;
+}
+
+struct grub_cryptodisk_dev geli_crypto = {
+ .scan = configure_ciphers,
+ .recover_key = recover_key
+};
+
+GRUB_MOD_INIT (geli)
+{
+ grub_cryptodisk_dev_register (&geli_crypto);
+}
+
+GRUB_MOD_FINI (geli)
+{
+ grub_cryptodisk_dev_unregister (&geli_crypto);
+}
int grub_disk_host_i_want_a_reference;
static int
-grub_host_iterate (int (*hook) (const char *name))
+grub_host_iterate (int (*hook) (const char *name),
+ grub_disk_pull_t pull)
{
+ if (pull != GRUB_DISK_PULL_NONE)
+ return 0;
+
if (hook ("host"))
return 1;
return 0;
#include <grub/err.h>
#include <grub/term.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
static int cd_drive = 0;
static int grub_biosdisk_rw_int13_extensions (int ah, int drive, void *dap);
}
static int
-grub_biosdisk_iterate (int (*hook) (const char *name))
+grub_biosdisk_iterate (int (*hook) (const char *name),
+ grub_disk_pull_t pull __attribute__ ((unused)))
{
- int drive;
int num_floppies;
+ int drive;
/* For hard disks, attempt to read the MBR. */
- for (drive = 0x80; drive < 0x90; drive++)
+ switch (pull)
{
- if (grub_biosdisk_rw_standard (0x02, drive, 0, 0, 1, 1,
- GRUB_MEMORY_MACHINE_SCRATCH_SEG) != 0)
+ case GRUB_DISK_PULL_NONE:
+ for (drive = 0x80; drive < 0x90; drive++)
{
- grub_dprintf ("disk", "Read error when probing drive 0x%2x\n", drive);
- break;
+ if (grub_biosdisk_rw_standard (0x02, drive, 0, 0, 1, 1,
+ GRUB_MEMORY_MACHINE_SCRATCH_SEG) != 0)
+ {
+ grub_dprintf ("disk", "Read error when probing drive 0x%2x\n", drive);
+ break;
+ }
+
+ if (grub_biosdisk_call_hook (hook, drive))
+ return 1;
}
+ return 0;
- if (grub_biosdisk_call_hook (hook, drive))
- return 1;
- }
+ case GRUB_DISK_PULL_REMOVABLE:
+ if (cd_drive)
+ {
+ if (grub_biosdisk_call_hook (hook, cd_drive))
+ return 1;
+ }
- if (cd_drive)
- {
- if (grub_biosdisk_call_hook (hook, cd_drive))
- return 1;
+ /* For floppy disks, we can get the number safely. */
+ num_floppies = grub_biosdisk_get_num_floppies ();
+ for (drive = 0; drive < num_floppies; drive++)
+ if (grub_biosdisk_call_hook (hook, drive))
+ return 1;
+ return 0;
+ default:
+ return 0;
}
-
- /* For floppy disks, we can get the number safely. */
- num_floppies = grub_biosdisk_get_num_floppies ();
- for (drive = 0; drive < num_floppies; drive++)
- if (grub_biosdisk_call_hook (hook, drive))
- return 1;
-
return 0;
}
if ((cd_drive) && (drive == cd_drive))
{
data->flags = GRUB_BIOSDISK_FLAG_LBA | GRUB_BIOSDISK_FLAG_CDROM;
- data->sectors = 32;
+ data->sectors = 8;
+ disk->log_sector_size = 11;
/* TODO: get the correct size. */
total_sectors = GRUB_DISK_SIZE_UNKNOWN;
}
/* HDD */
int version;
+ disk->log_sector_size = 9;
+
version = grub_biosdisk_check_int13_extensions (drive);
if (version)
{
correctly but returns zero. So if it is zero, compute
it by C/H/S returned by the LBA BIOS call. */
total_sectors = drp->cylinders * drp->heads * drp->sectors;
+ if (drp->bytes_per_sector
+ && !(drp->bytes_per_sector & (drp->bytes_per_sector - 1))
+ && drp->bytes_per_sector >= 512
+ && drp->bytes_per_sector <= 16384)
+ {
+ for (disk->log_sector_size = 0;
+ (1 << disk->log_sector_size) < drp->bytes_per_sector;
+ disk->log_sector_size++);
+ }
}
}
}
dap = (struct grub_biosdisk_dap *) (GRUB_MEMORY_MACHINE_SCRATCH_ADDR
+ (data->sectors
- << GRUB_DISK_SECTOR_BITS));
+ << disk->log_sector_size));
dap->length = sizeof (*dap);
dap->reserved = 0;
dap->blocks = size;
if (cmd)
return grub_error (GRUB_ERR_WRITE_ERROR, "can\'t write to cdrom");
- dap->blocks = ALIGN_UP (dap->blocks, 4) >> 2;
- dap->block >>= 2;
-
for (i = 0; i < GRUB_BIOSDISK_CDROM_RETRY_COUNT; i++)
if (! grub_biosdisk_rw_int13_extensions (0x42, data->drive, dap))
break;
/* Return the number of sectors which can be read safely at a time. */
static grub_size_t
-get_safe_sectors (grub_disk_addr_t sector, grub_uint32_t sectors)
+get_safe_sectors (grub_disk_t disk, grub_disk_addr_t sector)
{
grub_size_t size;
- grub_uint32_t offset;
+ grub_uint64_t offset;
+ struct grub_biosdisk_data *data = disk->data;
+ grub_uint32_t sectors = data->sectors;
/* OFFSET = SECTOR % SECTORS */
grub_divmod64 (sector, sectors, &offset);
size = sectors - offset;
/* Limit the max to 0x7f because of Phoenix EDD. */
- if (size > 0x7f)
- size = 0x7f;
+ if (size > ((0x7fU << GRUB_DISK_SECTOR_BITS) >> disk->log_sector_size))
+ size = ((0x7fU << GRUB_DISK_SECTOR_BITS) >> disk->log_sector_size);
return size;
}
grub_biosdisk_read (grub_disk_t disk, grub_disk_addr_t sector,
grub_size_t size, char *buf)
{
- struct grub_biosdisk_data *data = disk->data;
-
while (size)
{
grub_size_t len;
- grub_size_t cdoff = 0;
- len = get_safe_sectors (sector, data->sectors);
-
- if (data->flags & GRUB_BIOSDISK_FLAG_CDROM)
- {
- cdoff = (sector & 3) << GRUB_DISK_SECTOR_BITS;
- len = ALIGN_UP (sector + len, 4) - (sector & ~3);
- sector &= ~3;
- }
+ len = get_safe_sectors (disk, sector);
if (len > size)
len = size;
GRUB_MEMORY_MACHINE_SCRATCH_SEG))
return grub_errno;
- grub_memcpy (buf, (void *) (GRUB_MEMORY_MACHINE_SCRATCH_ADDR + cdoff),
- len << GRUB_DISK_SECTOR_BITS);
- buf += len << GRUB_DISK_SECTOR_BITS;
+ grub_memcpy (buf, (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR,
+ len << disk->log_sector_size);
+
+ buf += len << disk->log_sector_size;
sector += len;
size -= len;
}
{
grub_size_t len;
- len = get_safe_sectors (sector, data->sectors);
+ len = get_safe_sectors (disk, sector);
if (len > size)
len = size;
grub_memcpy ((void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR, buf,
- len << GRUB_DISK_SECTOR_BITS);
+ len << disk->log_sector_size);
if (grub_biosdisk_rw (GRUB_BIOSDISK_WRITE, disk, sector, len,
GRUB_MEMORY_MACHINE_SCRATCH_SEG))
return grub_errno;
- buf += len << GRUB_DISK_SECTOR_BITS;
+ buf += len << disk->log_sector_size;
sector += len;
size -= len;
}
#include <grub/dl.h>
#include <grub/ieee1275/ieee1275.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
struct grub_nand_data
{
grub_ieee1275_ihandle_t handle;
};
static int
-grub_nand_iterate (int (*hook) (const char *name))
+grub_nand_iterate (int (*hook) (const char *name),
+ grub_disk_pull_t pull)
{
auto int dev_iterate (struct grub_ieee1275_devalias *alias);
int dev_iterate (struct grub_ieee1275_devalias *alias)
return 0;
}
+ if (pull != GRUB_DISK_PULL_NONE)
+ return 0;
+
return grub_devalias_iterate (dev_iterate);
}
}
static int
-grub_ofdisk_iterate (int (*hook) (const char *name))
+grub_ofdisk_iterate (int (*hook) (const char *name),
+ grub_disk_pull_t pull)
{
unsigned i;
+
+ if (pull != GRUB_DISK_PULL_NONE)
+ return 0;
+
scan ();
for (i = 0; i < ARRAY_SIZE (ofdisk_hash); i++)
grub_dprintf ("disk", "Opening `%s'.\n", devpath);
if (grub_ieee1275_finddevice (devpath, &dev))
- return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't read device properties");
+ {
+ grub_free (devpath);
+ return grub_error (GRUB_ERR_UNKNOWN_DEVICE,
+ "can't read device properties");
+ }
if (grub_ieee1275_get_property (dev, "device_type", prop, sizeof (prop),
&actual))
- return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't read the device type");
+ {
+ grub_free (devpath);
+ return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't read the device type");
+ }
if (grub_strcmp (prop, "block"))
- return grub_error (GRUB_ERR_BAD_DEVICE, "not a block device");
+ {
+ grub_free (devpath);
+ return grub_error (GRUB_ERR_BAD_DEVICE, "not a block device");
+ }
/* XXX: There is no property to read the number of blocks. There
should be a property `#blocks', but it is not there. Perhaps it
#include <grub/extcmd.h>
#include <grub/i18n.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
struct grub_loopback
{
char *devname;
\f
static int
-grub_loopback_iterate (int (*hook) (const char *name))
+grub_loopback_iterate (int (*hook) (const char *name),
+ grub_disk_pull_t pull)
{
struct grub_loopback *d;
+ if (pull != GRUB_DISK_PULL_NONE)
+ return 0;
for (d = loopback_list; d; d = d->next)
{
if (hook (d->devname))
--- /dev/null
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2003,2007,2010,2011 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/cryptodisk.h>
+#include <grub/types.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/dl.h>
+#include <grub/err.h>
+#include <grub/disk.h>
+#include <grub/crypto.h>
+#include <grub/partition.h>
+#include <grub/i18n.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
+
+#define MAX_PASSPHRASE 256
+
+#define LUKS_KEY_ENABLED 0x00AC71F3
+
+/* On disk LUKS header */
+struct grub_luks_phdr
+{
+ grub_uint8_t magic[6];
+#define LUKS_MAGIC "LUKS\xBA\xBE"
+ grub_uint16_t version;
+ char cipherName[32];
+ char cipherMode[32];
+ char hashSpec[32];
+ grub_uint32_t payloadOffset;
+ grub_uint32_t keyBytes;
+ grub_uint8_t mkDigest[20];
+ grub_uint8_t mkDigestSalt[32];
+ grub_uint32_t mkDigestIterations;
+ char uuid[40];
+ struct
+ {
+ grub_uint32_t active;
+ grub_uint32_t passwordIterations;
+ grub_uint8_t passwordSalt[32];
+ grub_uint32_t keyMaterialOffset;
+ grub_uint32_t stripes;
+ } keyblock[8];
+} __attribute__ ((packed));
+
+typedef struct grub_luks_phdr *grub_luks_phdr_t;
+
+gcry_err_code_t AF_merge (const gcry_md_spec_t * hash, grub_uint8_t * src,
+ grub_uint8_t * dst, grub_size_t blocksize,
+ grub_size_t blocknumbers);
+
+static grub_cryptodisk_t
+configure_ciphers (grub_disk_t disk, const char *check_uuid,
+ int check_boot)
+{
+ grub_cryptodisk_t newdev;
+ const char *iptr;
+ struct grub_luks_phdr header;
+ char *optr;
+ char uuid[sizeof (header.uuid) + 1];
+ char ciphername[sizeof (header.cipherName) + 1];
+ char ciphermode[sizeof (header.cipherMode) + 1];
+ char *cipheriv = NULL;
+ char hashspec[sizeof (header.hashSpec) + 1];
+ grub_crypto_cipher_handle_t cipher = NULL, secondary_cipher = NULL;
+ grub_crypto_cipher_handle_t essiv_cipher = NULL;
+ const gcry_md_spec_t *hash = NULL, *essiv_hash = NULL;
+ const struct gcry_cipher_spec *ciph;
+ grub_cryptodisk_mode_t mode;
+ grub_cryptodisk_mode_iv_t mode_iv;
+ int benbi_log = 0;
+ grub_err_t err;
+
+ if (check_boot)
+ return NULL;
+
+ /* Read the LUKS header. */
+ err = grub_disk_read (disk, 0, 0, sizeof (header), &header);
+ if (err)
+ {
+ if (err == GRUB_ERR_OUT_OF_RANGE)
+ grub_errno = GRUB_ERR_NONE;
+ return NULL;
+ }
+
+ /* Look for LUKS magic sequence. */
+ if (grub_memcmp (header.magic, LUKS_MAGIC, sizeof (header.magic))
+ || grub_be_to_cpu16 (header.version) != 1)
+ return NULL;
+
+ optr = uuid;
+ for (iptr = header.uuid; iptr < &header.uuid[ARRAY_SIZE (header.uuid)];
+ iptr++)
+ {
+ if (*iptr != '-')
+ *optr++ = *iptr;
+ }
+ *optr = 0;
+
+ if (check_uuid && grub_strcasecmp (check_uuid, uuid) != 0)
+ {
+ grub_dprintf ("luks", "%s != %s\n", uuid, check_uuid);
+ return NULL;
+ }
+
+ /* Make sure that strings are null terminated. */
+ grub_memcpy (ciphername, header.cipherName, sizeof (header.cipherName));
+ ciphername[sizeof (header.cipherName)] = 0;
+ grub_memcpy (ciphermode, header.cipherMode, sizeof (header.cipherMode));
+ ciphermode[sizeof (header.cipherMode)] = 0;
+ grub_memcpy (hashspec, header.hashSpec, sizeof (header.hashSpec));
+ hashspec[sizeof (header.hashSpec)] = 0;
+
+ ciph = grub_crypto_lookup_cipher_by_name (ciphername);
+ if (!ciph)
+ {
+ grub_error (GRUB_ERR_FILE_NOT_FOUND, "Cipher %s isn't available",
+ ciphername);
+ return NULL;
+ }
+
+ /* Configure the cipher used for the bulk data. */
+ cipher = grub_crypto_cipher_open (ciph);
+ if (!cipher)
+ return NULL;
+
+ if (grub_be_to_cpu32 (header.keyBytes) > 1024)
+ {
+ grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid keysize %d",
+ grub_be_to_cpu32 (header.keyBytes));
+ return NULL;
+ }
+
+ /* Configure the cipher mode. */
+ if (grub_strcmp (ciphermode, "ecb") == 0)
+ {
+ mode = GRUB_CRYPTODISK_MODE_ECB;
+ mode_iv = GRUB_CRYPTODISK_MODE_IV_PLAIN;
+ cipheriv = NULL;
+ }
+ else if (grub_strcmp (ciphermode, "plain") == 0)
+ {
+ mode = GRUB_CRYPTODISK_MODE_CBC;
+ mode_iv = GRUB_CRYPTODISK_MODE_IV_PLAIN;
+ cipheriv = NULL;
+ }
+ else if (grub_memcmp (ciphermode, "cbc-", sizeof ("cbc-") - 1) == 0)
+ {
+ mode = GRUB_CRYPTODISK_MODE_CBC;
+ cipheriv = ciphermode + sizeof ("cbc-") - 1;
+ }
+ else if (grub_memcmp (ciphermode, "pcbc-", sizeof ("pcbc-") - 1) == 0)
+ {
+ mode = GRUB_CRYPTODISK_MODE_PCBC;
+ cipheriv = ciphermode + sizeof ("pcbc-") - 1;
+ }
+ else if (grub_memcmp (ciphermode, "xts-", sizeof ("xts-") - 1) == 0)
+ {
+ mode = GRUB_CRYPTODISK_MODE_XTS;
+ cipheriv = ciphermode + sizeof ("xts-") - 1;
+ secondary_cipher = grub_crypto_cipher_open (ciph);
+ if (!secondary_cipher)
+ {
+ grub_crypto_cipher_close (cipher);
+ return NULL;
+ }
+ if (cipher->cipher->blocksize != GRUB_CRYPTODISK_GF_BYTES)
+ {
+ grub_crypto_cipher_close (cipher);
+ grub_error (GRUB_ERR_BAD_ARGUMENT, "Unsupported XTS block size: %d",
+ cipher->cipher->blocksize);
+ return NULL;
+ }
+ if (secondary_cipher->cipher->blocksize != GRUB_CRYPTODISK_GF_BYTES)
+ {
+ grub_crypto_cipher_close (cipher);
+ grub_error (GRUB_ERR_BAD_ARGUMENT, "Unsupported XTS block size: %d",
+ secondary_cipher->cipher->blocksize);
+ return NULL;
+ }
+ }
+ else if (grub_memcmp (ciphermode, "lrw-", sizeof ("lrw-") - 1) == 0)
+ {
+ mode = GRUB_CRYPTODISK_MODE_LRW;
+ cipheriv = ciphermode + sizeof ("lrw-") - 1;
+ if (cipher->cipher->blocksize != GRUB_CRYPTODISK_GF_BYTES)
+ {
+ grub_crypto_cipher_close (cipher);
+ grub_error (GRUB_ERR_BAD_ARGUMENT, "Unsupported LRW block size: %d",
+ cipher->cipher->blocksize);
+ return NULL;
+ }
+ }
+ else
+ {
+ grub_crypto_cipher_close (cipher);
+ grub_error (GRUB_ERR_BAD_ARGUMENT, "Unknown cipher mode: %s",
+ ciphermode);
+ return NULL;
+ }
+
+ if (cipheriv == NULL);
+ else if (grub_memcmp (cipheriv, "plain", sizeof ("plain") - 1) == 0)
+ mode_iv = GRUB_CRYPTODISK_MODE_IV_PLAIN;
+ else if (grub_memcmp (cipheriv, "plain64", sizeof ("plain64") - 1) == 0)
+ mode_iv = GRUB_CRYPTODISK_MODE_IV_PLAIN64;
+ else if (grub_memcmp (cipheriv, "benbi", sizeof ("benbi") - 1) == 0)
+ {
+ if (cipher->cipher->blocksize & (cipher->cipher->blocksize - 1)
+ || cipher->cipher->blocksize == 0)
+ grub_error (GRUB_ERR_BAD_ARGUMENT, "Unsupported benbi blocksize: %d",
+ cipher->cipher->blocksize);
+ for (benbi_log = 0;
+ (cipher->cipher->blocksize << benbi_log) < GRUB_DISK_SECTOR_SIZE;
+ benbi_log++);
+ mode_iv = GRUB_CRYPTODISK_MODE_IV_BENBI;
+ }
+ else if (grub_memcmp (cipheriv, "null", sizeof ("null") - 1) == 0)
+ mode_iv = GRUB_CRYPTODISK_MODE_IV_NULL;
+ else if (grub_memcmp (cipheriv, "essiv:", sizeof ("essiv:") - 1) == 0)
+ {
+ char *hash_str = cipheriv + 6;
+
+ mode_iv = GRUB_CRYPTODISK_MODE_IV_ESSIV;
+
+ /* Configure the hash and cipher used for ESSIV. */
+ essiv_hash = grub_crypto_lookup_md_by_name (hash_str);
+ if (!essiv_hash)
+ {
+ grub_crypto_cipher_close (cipher);
+ grub_error (GRUB_ERR_FILE_NOT_FOUND,
+ "Couldn't load %s hash", hash_str);
+ return NULL;
+ }
+ essiv_cipher = grub_crypto_cipher_open (ciph);
+ if (!essiv_cipher)
+ {
+ grub_crypto_cipher_close (cipher);
+ return NULL;
+ }
+ }
+ else
+ {
+ grub_crypto_cipher_close (cipher);
+ grub_error (GRUB_ERR_BAD_ARGUMENT, "Unknown IV mode: %s",
+ cipheriv);
+ return NULL;
+ }
+
+ /* Configure the hash used for the AF splitter and HMAC. */
+ hash = grub_crypto_lookup_md_by_name (hashspec);
+ if (!hash)
+ {
+ grub_crypto_cipher_close (cipher);
+ grub_crypto_cipher_close (essiv_cipher);
+ grub_crypto_cipher_close (secondary_cipher);
+ grub_error (GRUB_ERR_FILE_NOT_FOUND, "Couldn't load %s hash",
+ hashspec);
+ return NULL;
+ }
+
+ newdev = grub_zalloc (sizeof (struct grub_cryptodisk));
+ if (!newdev)
+ return NULL;
+ newdev->cipher = cipher;
+ newdev->offset = grub_be_to_cpu32 (header.payloadOffset);
+ newdev->source_disk = NULL;
+ newdev->benbi_log = benbi_log;
+ newdev->mode = mode;
+ newdev->mode_iv = mode_iv;
+ newdev->secondary_cipher = secondary_cipher;
+ newdev->essiv_cipher = essiv_cipher;
+ newdev->essiv_hash = essiv_hash;
+ newdev->hash = hash;
+ newdev->log_sector_size = 9;
+ newdev->total_length = grub_disk_get_size (disk) - newdev->offset;
+ grub_memcpy (newdev->uuid, uuid, sizeof (newdev->uuid));
+#ifdef GRUB_UTIL
+ newdev->modname = "luks";
+#endif
+ COMPILE_TIME_ASSERT (sizeof (newdev->uuid) >= sizeof (uuid));
+ return newdev;
+}
+
+static grub_err_t
+luks_recover_key (grub_disk_t source,
+ grub_cryptodisk_t dev)
+{
+ struct grub_luks_phdr header;
+ grub_size_t keysize;
+ grub_uint8_t *split_key = NULL;
+ char passphrase[MAX_PASSPHRASE] = "";
+ grub_uint8_t candidate_digest[sizeof (header.mkDigest)];
+ unsigned i;
+ grub_size_t length;
+ grub_err_t err;
+ grub_size_t max_stripes = 1;
+ char *tmp;
+
+ err = grub_disk_read (source, 0, 0, sizeof (header), &header);
+ if (err)
+ return err;
+
+ grub_printf ("Attempting to decrypt master key...\n");
+ keysize = grub_be_to_cpu32 (header.keyBytes);
+
+ for (i = 0; i < ARRAY_SIZE (header.keyblock); i++)
+ if (grub_be_to_cpu32 (header.keyblock[i].active) == LUKS_KEY_ENABLED
+ && grub_be_to_cpu32 (header.keyblock[i].stripes) > max_stripes)
+ max_stripes = grub_be_to_cpu32 (header.keyblock[i].stripes);
+
+ split_key = grub_malloc (keysize * max_stripes);
+ if (!split_key)
+ return grub_errno;
+
+ /* Get the passphrase from the user. */
+ tmp = NULL;
+ if (source->partition)
+ tmp = grub_partition_get_name (source->partition);
+ grub_printf ("Enter passphrase for %s%s%s (%s): ", source->name,
+ source->partition ? "," : "", tmp ? : "",
+ dev->uuid);
+ grub_free (tmp);
+ if (!grub_password_get (passphrase, MAX_PASSPHRASE))
+ {
+ grub_free (split_key);
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "Passphrase not supplied");
+ }
+
+ /* Try to recover master key from each active keyslot. */
+ for (i = 0; i < ARRAY_SIZE (header.keyblock); i++)
+ {
+ gcry_err_code_t gcry_err;
+ grub_uint8_t candidate_key[keysize];
+ grub_uint8_t digest[keysize];
+
+ /* Check if keyslot is enabled. */
+ if (grub_be_to_cpu32 (header.keyblock[i].active) != LUKS_KEY_ENABLED)
+ continue;
+
+ grub_dprintf ("luks", "Trying keyslot %d\n", i);
+
+ /* Calculate the PBKDF2 of the user supplied passphrase. */
+ gcry_err = grub_crypto_pbkdf2 (dev->hash, (grub_uint8_t *) passphrase,
+ grub_strlen (passphrase),
+ header.keyblock[i].passwordSalt,
+ sizeof (header.keyblock[i].passwordSalt),
+ grub_be_to_cpu32 (header.keyblock[i].
+ passwordIterations),
+ digest, keysize);
+
+ if (gcry_err)
+ {
+ grub_free (split_key);
+ return grub_crypto_gcry_error (gcry_err);
+ }
+
+ grub_dprintf ("luks", "PBKDF2 done\n");
+
+ gcry_err = grub_cryptodisk_setkey (dev, digest, keysize);
+ if (gcry_err)
+ {
+ grub_free (split_key);
+ return grub_crypto_gcry_error (gcry_err);
+ }
+
+ length = (keysize * grub_be_to_cpu32 (header.keyblock[i].stripes));
+
+ /* Read and decrypt the key material from the disk. */
+ err = grub_disk_read (source,
+ grub_be_to_cpu32 (header.keyblock
+ [i].keyMaterialOffset), 0,
+ length, split_key);
+ if (err)
+ {
+ grub_free (split_key);
+ return err;
+ }
+
+ gcry_err = grub_cryptodisk_decrypt (dev, split_key, length, 0);
+ if (gcry_err)
+ {
+ grub_free (split_key);
+ return grub_crypto_gcry_error (gcry_err);
+ }
+
+ /* Merge the decrypted key material to get the candidate master key. */
+ gcry_err = AF_merge (dev->hash, split_key, candidate_key, keysize,
+ grub_be_to_cpu32 (header.keyblock[i].stripes));
+ if (gcry_err)
+ {
+ grub_free (split_key);
+ return grub_crypto_gcry_error (gcry_err);
+ }
+
+ grub_dprintf ("luks", "candidate key recovered\n");
+
+ /* Calculate the PBKDF2 of the candidate master key. */
+ gcry_err = grub_crypto_pbkdf2 (dev->hash, candidate_key,
+ grub_be_to_cpu32 (header.keyBytes),
+ header.mkDigestSalt,
+ sizeof (header.mkDigestSalt),
+ grub_be_to_cpu32
+ (header.mkDigestIterations),
+ candidate_digest,
+ sizeof (candidate_digest));
+ if (gcry_err)
+ {
+ grub_free (split_key);
+ return grub_crypto_gcry_error (gcry_err);
+ }
+
+ /* Compare the calculated PBKDF2 to the digest stored
+ in the header to see if it's correct. */
+ if (grub_memcmp (candidate_digest, header.mkDigest,
+ sizeof (header.mkDigest)) != 0)
+ {
+ grub_dprintf ("luks", "bad digest\n");
+ continue;
+ }
+
+ grub_printf ("Slot %d opened\n", i);
+
+ /* Set the master key. */
+ gcry_err = grub_cryptodisk_setkey (dev, candidate_key, keysize);
+ if (gcry_err)
+ {
+ grub_free (split_key);
+ return grub_crypto_gcry_error (gcry_err);
+ }
+
+ grub_free (split_key);
+
+ return GRUB_ERR_NONE;
+ }
+
+ return GRUB_ACCESS_DENIED;
+}
+
+struct grub_cryptodisk_dev luks_crypto = {
+ .scan = configure_ciphers,
+ .recover_key = luks_recover_key
+};
+
+GRUB_MOD_INIT (luks)
+{
+ COMPILE_TIME_ASSERT (sizeof (((struct grub_luks_phdr *) 0)->uuid)
+ < GRUB_CRYPTODISK_MAX_UUID_LENGTH);
+ grub_cryptodisk_dev_register (&luks_crypto);
+}
+
+GRUB_MOD_FINI (luks)
+{
+ grub_cryptodisk_dev_unregister (&luks_crypto);
+}
#ifdef GRUB_UTIL
#include <grub/emu/misc.h>
+#include <grub/emu/hostdisk.h>
#endif
+GRUB_MOD_LICENSE ("GPLv3+");
+
static struct grub_lvm_vg *vg_list;
static int lv_count;
+static int scan_depth = 0;
+
+static int is_lv_readable (struct grub_lvm_lv *lv);
\f
/* Go the string STR and return the number after STR. *P will point
}
}
+static struct grub_lvm_lv *
+find_lv (const char *name)
+{
+ struct grub_lvm_vg *vg;
+ struct grub_lvm_lv *lv = NULL;
+ for (vg = vg_list; vg; vg = vg->next)
+ {
+ if (vg->lvs)
+ for (lv = vg->lvs; lv; lv = lv->next)
+ if ((grub_strcmp (lv->fullname, name) == 0
+ || grub_strcmp (lv->compatname, name) == 0)
+ && is_lv_readable (lv))
+ return lv;
+ }
+ return NULL;
+}
+
+static void
+do_lvm_scan (const char *scan_for)
+{
+ auto int grub_lvm_scan_device (const char *name);
+ int grub_lvm_scan_device (const char *name)
+ {
+ grub_err_t err;
+ grub_disk_t disk;
+ grub_uint64_t mda_offset, mda_size;
+ char buf[GRUB_LVM_LABEL_SIZE];
+ char vg_id[GRUB_LVM_ID_STRLEN+1];
+ char pv_id[GRUB_LVM_ID_STRLEN+1];
+ char *metadatabuf, *p, *q, *vgname;
+ struct grub_lvm_label_header *lh = (struct grub_lvm_label_header *) buf;
+ struct grub_lvm_pv_header *pvh;
+ struct grub_lvm_disk_locn *dlocn;
+ struct grub_lvm_mda_header *mdah;
+ struct grub_lvm_raw_locn *rlocn;
+ unsigned int i, j, vgname_len;
+ 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)
+ {
+ if (grub_errno == GRUB_ERR_OUT_OF_RANGE)
+ grub_errno = GRUB_ERR_NONE;
+ return 0;
+ }
+
+ for (vg = vg_list; vg; vg = vg->next)
+ for (pv = vg->pvs; pv; pv = pv->next)
+ if (pv->disk && pv->disk->id == disk->id
+ && pv->disk->dev->id == disk->dev->id)
+ {
+ grub_disk_close (disk);
+ return 0;
+ }
+
+ /* Search for label. */
+ for (i = 0; i < GRUB_LVM_LABEL_SCAN_SECTORS; i++)
+ {
+ err = grub_disk_read (disk, i, 0, sizeof(buf), buf);
+ if (err)
+ goto fail;
+
+ if ((! grub_strncmp ((char *)lh->id, GRUB_LVM_LABEL_ID,
+ sizeof (lh->id)))
+ && (! grub_strncmp ((char *)lh->type, GRUB_LVM_LVM2_LABEL,
+ sizeof (lh->type))))
+ break;
+ }
+
+ /* Return if we didn't find a label. */
+ if (i == GRUB_LVM_LABEL_SCAN_SECTORS)
+ {
+#ifdef GRUB_UTIL
+ grub_util_info ("no LVM signature found");
+#endif
+ goto fail;
+ }
+
+ pvh = (struct grub_lvm_pv_header *) (buf + grub_le_to_cpu32(lh->offset_xl));
+
+ for (i = 0, j = 0; i < GRUB_LVM_ID_LEN; i++)
+ {
+ pv_id[j++] = pvh->pv_uuid[i];
+ if ((i != 1) && (i != 29) && (i % 4 == 1))
+ pv_id[j++] = '-';
+ }
+ pv_id[j] = '\0';
+
+ dlocn = pvh->disk_areas_xl;
+
+ dlocn++;
+ /* Is it possible to have multiple data/metadata areas? I haven't
+ seen devices that have it. */
+ if (dlocn->offset)
+ {
+ 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;
+ }
+
+ dlocn++;
+ mda_offset = grub_le_to_cpu64 (dlocn->offset);
+ mda_size = grub_le_to_cpu64 (dlocn->size);
+
+ /* It's possible to have multiple copies of metadata areas, we just use the
+ first one. */
+
+ /* Allocate buffer space for the circular worst-case scenario. */
+ metadatabuf = grub_malloc (2 * mda_size);
+ if (! metadatabuf)
+ goto fail;
+
+ err = grub_disk_read (disk, 0, mda_offset, mda_size, metadatabuf);
+ if (err)
+ goto fail2;
+
+ mdah = (struct grub_lvm_mda_header *) metadatabuf;
+ if ((grub_strncmp ((char *)mdah->magic, GRUB_LVM_FMTT_MAGIC,
+ sizeof (mdah->magic)))
+ || (grub_le_to_cpu32 (mdah->version) != GRUB_LVM_FMTT_VERSION))
+ {
+ 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;
+ }
+
+ rlocn = mdah->raw_locns;
+ if (grub_le_to_cpu64 (rlocn->offset) + grub_le_to_cpu64 (rlocn->size) >
+ grub_le_to_cpu64 (mdah->size))
+ {
+ /* Metadata is circular. Copy the wrap in place. */
+ grub_memcpy (metadatabuf + mda_size,
+ metadatabuf + GRUB_LVM_MDA_HEADER_SIZE,
+ grub_le_to_cpu64 (rlocn->offset) +
+ grub_le_to_cpu64 (rlocn->size) -
+ grub_le_to_cpu64 (mdah->size));
+ }
+ p = q = metadatabuf + grub_le_to_cpu64 (rlocn->offset);
+
+ while (*q != ' ' && q < metadatabuf + mda_size)
+ q++;
+
+ if (q == metadatabuf + mda_size)
+ {
+#ifdef GRUB_UTIL
+ grub_util_info ("error parsing metadata\n");
+#endif
+ goto fail2;
+ }
+
+ vgname_len = q - p;
+ vgname = grub_malloc (vgname_len + 1);
+ if (!vgname)
+ goto fail2;
+
+ grub_memcpy (vgname, p, vgname_len);
+ vgname[vgname_len] = '\0';
+
+ p = grub_strstr (q, "id = \"");
+ if (p == NULL)
+ {
+#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';
+
+ for (vg = vg_list; vg; vg = vg->next)
+ {
+ if (! grub_memcmp(vg_id, vg->id, GRUB_LVM_ID_STRLEN))
+ break;
+ }
+
+ if (! vg)
+ {
+ /* First time we see this volume group. We've to create the
+ whole volume group structure. */
+ vg = grub_malloc (sizeof (*vg));
+ if (! vg)
+ goto fail3;
+ vg->name = vgname;
+ grub_memcpy (vg->id, vg_id, GRUB_LVM_ID_STRLEN+1);
+
+ vg->extent_size = grub_lvm_getvalue (&p, "extent_size = ");
+ if (p == NULL)
+ {
+#ifdef GRUB_UTIL
+ grub_util_info ("unknown extent size\n");
+#endif
+ goto fail4;
+ }
+
+ vg->lvs = NULL;
+ vg->pvs = NULL;
+
+ p = grub_strstr (p, "physical_volumes {");
+ if (p)
+ {
+ p += sizeof ("physical_volumes {") - 1;
+
+ /* Add all the pvs to the volume group. */
+ while (1)
+ {
+ int s;
+ while (grub_isspace (*p))
+ p++;
+
+ if (*p == '}')
+ break;
+
+ pv = grub_malloc (sizeof (*pv));
+ q = p;
+ while (*q != ' ')
+ q++;
+
+ s = q - p;
+ pv->name = grub_malloc (s + 1);
+ grub_memcpy (pv->name, p, s);
+ pv->name[s] = '\0';
+
+ p = grub_strstr (p, "id = \"");
+ if (p == NULL)
+ goto pvs_fail;
+ p += sizeof("id = \"") - 1;
+
+ grub_memcpy (pv->id, p, GRUB_LVM_ID_STRLEN);
+ pv->id[GRUB_LVM_ID_STRLEN] = '\0';
+
+ pv->start = grub_lvm_getvalue (&p, "pe_start = ");
+ if (p == NULL)
+ {
+#ifdef GRUB_UTIL
+ grub_util_info ("unknown pe_start\n");
+#endif
+ goto pvs_fail;
+ }
+
+ p = grub_strchr (p, '}');
+ if (p == NULL)
+ {
+#ifdef GRUB_UTIL
+ grub_util_info ("error parsing pe_start\n");
+#endif
+ goto pvs_fail;
+ }
+ p++;
+
+ pv->disk = NULL;
+ pv->next = vg->pvs;
+ vg->pvs = pv;
+
+ continue;
+ pvs_fail:
+ grub_free (pv->name);
+ grub_free (pv);
+ goto fail4;
+ }
+ }
+
+ p = grub_strstr (p, "logical_volumes");
+ if (p)
+ {
+ p += 18;
+
+ /* And add all the lvs to the volume group. */
+ while (1)
+ {
+ int s;
+ int skip_lv = 0;
+ struct grub_lvm_lv *lv;
+ struct grub_lvm_segment *seg;
+ int is_pvmove;
+
+ while (grub_isspace (*p))
+ p++;
+
+ if (*p == '}')
+ break;
+
+ lv = grub_malloc (sizeof (*lv));
+
+ q = p;
+ while (*q != ' ')
+ q++;
+
+ s = q - p;
+ lv->name = grub_strndup (p, s);
+ if (!lv->name)
+ goto lvs_fail;
+ lv->compatname = grub_malloc (vgname_len + 1 + s + 1);
+ if (!lv->compatname)
+ goto lvs_fail;
+ grub_memcpy (lv->compatname, vgname, vgname_len);
+ lv->compatname[vgname_len] = '-';
+ grub_memcpy (lv->compatname + vgname_len + 1, p, s);
+ lv->compatname[vgname_len + 1 + s] = '\0';
+
+ {
+ const char *iptr;
+ char *optr;
+ lv->fullname = grub_malloc (sizeof("lvm/") + 2 * vgname_len
+ + 1 + 2 * s + 1);
+ if (!lv->fullname)
+ goto lvs_fail;
+
+ optr = lv->fullname;
+ grub_memcpy (optr, "lvm/", sizeof ("lvm/") - 1);
+ optr += sizeof ("lvm/") - 1;
+ for (iptr = vgname; iptr < vgname + vgname_len; iptr++)
+ {
+ *optr++ = *iptr;
+ if (*iptr == '-')
+ *optr++ = '-';
+ }
+ *optr++ = '-';
+ for (iptr = p; iptr < p + s; iptr++)
+ {
+ *optr++ = *iptr;
+ if (*iptr == '-')
+ *optr++ = '-';
+ }
+ *optr++ = 0;
+ }
+
+ lv->size = 0;
+
+ lv->visible = grub_lvm_check_flag (p, "status", "VISIBLE");
+ is_pvmove = grub_lvm_check_flag (p, "status", "PVMOVE");
+
+ lv->segment_count = grub_lvm_getvalue (&p, "segment_count = ");
+ if (p == NULL)
+ {
+#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;
+
+ for (i = 0; i < lv->segment_count; i++)
+ {
+
+ p = grub_strstr (p, "segment");
+ if (p == NULL)
+ {
+#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)
+ {
+#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)
+ {
+#ifdef GRUB_UTIL
+ grub_util_info ("unknown extent_count\n");
+#endif
+ goto lvs_segment_fail;
+ }
+
+ p = grub_strstr (p, "type = \"");
+ if (p == NULL)
+ goto lvs_segment_fail;
+ p += sizeof("type = \"") - 1;
+
+ lv->size += seg->extent_count * vg->extent_size;
+
+ if (grub_memcmp (p, "striped\"",
+ sizeof ("striped\"") - 1) == 0)
+ {
+ struct grub_lvm_node *stripe;
+
+ seg->type = GRUB_LVM_STRIPED;
+ seg->node_count = grub_lvm_getvalue (&p, "stripe_count = ");
+ if (p == NULL)
+ {
+#ifdef GRUB_UTIL
+ grub_util_info ("unknown stripe_count\n");
+#endif
+ goto lvs_segment_fail;
+ }
+
+ if (seg->node_count != 1)
+ seg->stripe_size = grub_lvm_getvalue (&p, "stripe_size = ");
+
+ seg->nodes = grub_zalloc (sizeof (*stripe)
+ * seg->node_count);
+ stripe = seg->nodes;
+
+ p = grub_strstr (p, "stripes = [");
+ if (p == NULL)
+ {
+#ifdef GRUB_UTIL
+ grub_util_info ("unknown stripes\n");
+#endif
+ goto lvs_segment_fail2;
+ }
+ p += sizeof("stripes = [") - 1;
+
+ for (j = 0; j < seg->node_count; j++)
+ {
+ p = grub_strchr (p, '"');
+ if (p == NULL)
+ continue;
+ q = ++p;
+ while (*q != '"')
+ q++;
+
+ s = q - p;
+
+ stripe->name = grub_malloc (s + 1);
+ if (stripe->name == NULL)
+ goto lvs_segment_fail2;
+
+ grub_memcpy (stripe->name, p, s);
+ stripe->name[s] = '\0';
+
+ stripe->start = grub_lvm_getvalue (&p, ",");
+ if (p == NULL)
+ continue;
+
+ stripe++;
+ }
+ }
+ else if (grub_memcmp (p, "mirror\"", sizeof ("mirror\"") - 1)
+ == 0)
+ {
+ seg->type = GRUB_LVM_MIRROR;
+ seg->node_count = grub_lvm_getvalue (&p, "mirror_count = ");
+ if (p == NULL)
+ {
+#ifdef GRUB_UTIL
+ grub_util_info ("unknown mirror_count\n");
+#endif
+ goto lvs_segment_fail;
+ }
+
+ seg->nodes = grub_zalloc (sizeof (seg->nodes[0])
+ * seg->node_count);
+
+ p = grub_strstr (p, "mirrors = [");
+ if (p == NULL)
+ {
+#ifdef GRUB_UTIL
+ grub_util_info ("unknown mirrors\n");
+#endif
+ goto lvs_segment_fail2;
+ }
+ p += sizeof("mirrors = [") - 1;
+
+ for (j = 0; j < seg->node_count; j++)
+ {
+ char *lvname;
+
+ p = grub_strchr (p, '"');
+ if (p == NULL)
+ continue;
+ q = ++p;
+ while (*q != '"')
+ q++;
+
+ s = q - p;
+
+ lvname = grub_malloc (s + 1);
+ if (lvname == NULL)
+ goto lvs_segment_fail2;
+
+ grub_memcpy (lvname, p, s);
+ lvname[s] = '\0';
+ seg->nodes[j].name = lvname;
+ p = q + 1;
+ }
+ /* Only first (original) is ok with in progress pvmove. */
+ if (is_pvmove)
+ seg->node_count = 1;
+ }
+ else
+ {
+#ifdef GRUB_UTIL
+ char *p2;
+ p2 = grub_strchr (p, '"');
+ if (p2)
+ *p2 = 0;
+ grub_util_info ("unknown LVM type %s\n", p);
+ if (p2)
+ *p2 ='"';
+#endif
+ /* Found a non-supported type, give up and move on. */
+ skip_lv = 1;
+ break;
+ }
+
+ seg++;
+
+ continue;
+ lvs_segment_fail2:
+ grub_free (seg->nodes);
+ lvs_segment_fail:
+ goto fail4;
+ }
+
+ if (p != NULL)
+ p = grub_strchr (p, '}');
+ if (p == NULL)
+ goto lvs_fail;
+ p += 3;
+
+ if (skip_lv)
+ {
+ grub_free (lv->name);
+ grub_free (lv);
+ continue;
+ }
+
+ lv->number = lv_count++;
+ lv->vg = vg;
+ lv->next = vg->lvs;
+ vg->lvs = lv;
+
+ continue;
+ lvs_fail:
+ grub_free (lv->name);
+ grub_free (lv);
+ goto fail4;
+ }
+ }
+
+ /* Match lvs. */
+ {
+ struct grub_lvm_lv *lv1;
+ struct grub_lvm_lv *lv2;
+ for (lv1 = vg->lvs; lv1; lv1 = lv1->next)
+ for (i = 0; i < lv1->segment_count; i++)
+ for (j = 0; j < lv1->segments[i].node_count; j++)
+ {
+ if (vg->pvs)
+ for (pv = vg->pvs; pv; pv = pv->next)
+ {
+ if (! grub_strcmp (pv->name,
+ lv1->segments[i].nodes[j].name))
+ {
+ lv1->segments[i].nodes[j].pv = pv;
+ break;
+ }
+ }
+ if (lv1->segments[i].nodes[j].pv == NULL)
+ for (lv2 = vg->lvs; lv2; lv2 = lv2->next)
+ if (grub_strcmp (lv2->name + grub_strlen (vg->name) + 1,
+ lv1->segments[i].nodes[j].name) == 0)
+ lv1->segments[i].nodes[j].lv = lv2;
+ }
+
+ }
+
+ vg->next = vg_list;
+ vg_list = vg;
+ }
+ else
+ {
+ grub_free (vgname);
+ }
+
+ /* Match the device we are currently reading from with the right
+ PV. */
+ if (vg->pvs)
+ for (pv = vg->pvs; pv; pv = pv->next)
+ {
+ if (! grub_memcmp (pv->id, pv_id, GRUB_LVM_ID_STRLEN))
+ {
+ /* This could happen to LVM on RAID, pv->disk points to the
+ raid device, we shouldn't change it. */
+ if (! pv->disk)
+ pv->disk = grub_disk_open (name);
+ break;
+ }
+ }
+
+ goto fail2;
+
+ /* Failure path. */
+ fail4:
+ grub_free (vg);
+ fail3:
+ grub_free (vgname);
+
+ /* Normal exit path. */
+ fail2:
+ grub_free (metadatabuf);
+ fail:
+ grub_disk_close (disk);
+ if (grub_errno == GRUB_ERR_OUT_OF_RANGE)
+ grub_errno = GRUB_ERR_NONE;
+ grub_print_error ();
+ if (scan_for && find_lv (scan_for))
+ return 1;
+ return 0;
+ }
+
+ scan_depth++;
+ grub_device_iterate (&grub_lvm_scan_device);
+ scan_depth--;
+}
+
static int
-grub_lvm_iterate (int (*hook) (const char *name))
+grub_lvm_iterate (int (*hook) (const char *name),
+ grub_disk_pull_t pull)
{
struct grub_lvm_vg *vg;
+ unsigned old_count = 0;
+ if (pull == GRUB_DISK_PULL_RESCAN && scan_depth)
+ return 0;
+
+ if (pull == GRUB_DISK_PULL_RESCAN)
+ {
+ old_count = lv_count;
+ if (!scan_depth)
+ do_lvm_scan (NULL);
+ }
+ if (pull != GRUB_DISK_PULL_RESCAN && pull != GRUB_DISK_PULL_NONE)
+ return GRUB_ERR_NONE;
for (vg = vg_list; vg; vg = vg->next)
{
struct grub_lvm_lv *lv;
if (vg->lvs)
for (lv = vg->lvs; lv; lv = lv->next)
- if (lv->visible && hook (lv->name))
- return 1;
+ if (lv->visible && lv->number >= old_count)
+ {
+ if (hook (lv->fullname))
+ return 1;
+ }
}
return 0;
static grub_err_t
grub_lvm_open (const char *name, grub_disk_t disk)
{
- struct grub_lvm_vg *vg;
struct grub_lvm_lv *lv = NULL;
- for (vg = vg_list; vg; vg = vg->next)
- {
- if (vg->lvs)
- for (lv = vg->lvs; lv; lv = lv->next)
- if (! grub_strcmp (lv->name, name))
- break;
+ int explicit = 0;
- if (lv)
- break;
+ if (grub_memcmp (name, "lvm/", sizeof ("lvm/") - 1) == 0)
+ explicit = 1;
+
+ lv = find_lv (name);
+
+ if (! lv && !scan_depth && explicit)
+ {
+ do_lvm_scan (name);
+ if (grub_errno)
+ {
+ grub_print_error ();
+ grub_errno = GRUB_ERR_NONE;
+ }
+ lv = find_lv (name);
}
if (! lv)
/* This is a striped segment. We have to find the right PV
similar to RAID0. */
struct grub_lvm_node *stripe = seg->nodes;
- grub_uint32_t a, b;
+ grub_uint64_t a, b;
grub_uint64_t seg_offset; /* Offset of the segment in PV device. */
- unsigned int stripenr;
+ grub_uint64_t stripenr;
offset = sector - ((grub_uint64_t) seg->start_extent
* (grub_uint64_t) vg->extent_size);
return grub_error (GRUB_ERR_IO, "unknown LVM segment");
}
+static grub_err_t
+is_node_readable (const struct grub_lvm_node *node)
+{
+ /* Check whether we actually know the physical volume we want to
+ read from. */
+ if (node->pv)
+ return !!(node->pv->disk);
+ if (node->lv)
+ return is_lv_readable (node->lv);
+ return 0;
+}
+
+static int
+is_lv_readable (struct grub_lvm_lv *lv)
+{
+ unsigned int i, j;
+
+ if (!lv)
+ return 0;
+
+ /* Find the right segment. */
+ for (i = 0; i < lv->segment_count; i++)
+ switch (lv->segments[i].type)
+ {
+ case GRUB_LVM_STRIPED:
+ for (j = 0; j < lv->segments[i].node_count; j++)
+ if (!is_node_readable (lv->segments[i].nodes + j))
+ return 0;
+ break;
+ case GRUB_LVM_MIRROR:
+ for (j = 0; j < lv->segments[i].node_count; j++)
+ if (is_node_readable (lv->segments[i].nodes + j))
+ break;
+ if (j == lv->segments[i].node_count)
+ return 0;
+ default:
+ return 0;
+ }
+
+ return 1;
+}
+
+
static grub_err_t
grub_lvm_read (grub_disk_t disk, grub_disk_addr_t sector,
grub_size_t size, char *buf)
return GRUB_ERR_NOT_IMPLEMENTED_YET;
}
-static int
-grub_lvm_scan_device (const char *name)
-{
- grub_err_t err;
- grub_disk_t disk;
- grub_uint64_t mda_offset, mda_size;
- char buf[GRUB_LVM_LABEL_SIZE];
- char vg_id[GRUB_LVM_ID_STRLEN+1];
- char pv_id[GRUB_LVM_ID_STRLEN+1];
- char *metadatabuf, *p, *q, *vgname;
- struct grub_lvm_label_header *lh = (struct grub_lvm_label_header *) buf;
- struct grub_lvm_pv_header *pvh;
- struct grub_lvm_disk_locn *dlocn;
- struct grub_lvm_mda_header *mdah;
- struct grub_lvm_raw_locn *rlocn;
- unsigned int i, j, vgname_len;
- 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)
- {
- if (grub_errno == GRUB_ERR_OUT_OF_RANGE)
- grub_errno = GRUB_ERR_NONE;
- return 0;
- }
-
- /* Search for label. */
- for (i = 0; i < GRUB_LVM_LABEL_SCAN_SECTORS; i++)
- {
- err = grub_disk_read (disk, i, 0, sizeof(buf), buf);
- if (err)
- goto fail;
-
- if ((! grub_strncmp ((char *)lh->id, GRUB_LVM_LABEL_ID,
- sizeof (lh->id)))
- && (! grub_strncmp ((char *)lh->type, GRUB_LVM_LVM2_LABEL,
- sizeof (lh->type))))
- break;
- }
-
- /* Return if we didn't find a label. */
- if (i == GRUB_LVM_LABEL_SCAN_SECTORS)
- {
-#ifdef GRUB_UTIL
- grub_util_info ("no LVM signature found");
-#endif
- goto fail;
- }
-
- pvh = (struct grub_lvm_pv_header *) (buf + grub_le_to_cpu32(lh->offset_xl));
-
- for (i = 0, j = 0; i < GRUB_LVM_ID_LEN; i++)
- {
- pv_id[j++] = pvh->pv_uuid[i];
- if ((i != 1) && (i != 29) && (i % 4 == 1))
- pv_id[j++] = '-';
- }
- pv_id[j] = '\0';
-
- dlocn = pvh->disk_areas_xl;
-
- dlocn++;
- /* Is it possible to have multiple data/metadata areas? I haven't
- seen devices that have it. */
- if (dlocn->offset)
- {
- 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;
- }
-
- dlocn++;
- mda_offset = grub_le_to_cpu64 (dlocn->offset);
- mda_size = grub_le_to_cpu64 (dlocn->size);
-
- /* It's possible to have multiple copies of metadata areas, we just use the
- first one. */
-
- /* Allocate buffer space for the circular worst-case scenario. */
- metadatabuf = grub_malloc (2 * mda_size);
- if (! metadatabuf)
- goto fail;
-
- err = grub_disk_read (disk, 0, mda_offset, mda_size, metadatabuf);
- if (err)
- goto fail2;
-
- mdah = (struct grub_lvm_mda_header *) metadatabuf;
- if ((grub_strncmp ((char *)mdah->magic, GRUB_LVM_FMTT_MAGIC,
- sizeof (mdah->magic)))
- || (grub_le_to_cpu32 (mdah->version) != GRUB_LVM_FMTT_VERSION))
- {
- 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;
- }
-
- rlocn = mdah->raw_locns;
- if (grub_le_to_cpu64 (rlocn->offset) + grub_le_to_cpu64 (rlocn->size) >
- grub_le_to_cpu64 (mdah->size))
- {
- /* Metadata is circular. Copy the wrap in place. */
- grub_memcpy (metadatabuf + mda_size,
- metadatabuf + GRUB_LVM_MDA_HEADER_SIZE,
- grub_le_to_cpu64 (rlocn->offset) +
- grub_le_to_cpu64 (rlocn->size) -
- grub_le_to_cpu64 (mdah->size));
- }
- p = q = metadatabuf + grub_le_to_cpu64 (rlocn->offset);
-
- while (*q != ' ' && q < metadatabuf + mda_size)
- q++;
-
- if (q == metadatabuf + mda_size)
- {
-#ifdef GRUB_UTIL
- grub_util_info ("error parsing metadata\n");
-#endif
- goto fail2;
- }
-
- vgname_len = q - p;
- vgname = grub_malloc (vgname_len + 1);
- if (!vgname)
- goto fail2;
-
- grub_memcpy (vgname, p, vgname_len);
- vgname[vgname_len] = '\0';
-
- p = grub_strstr (q, "id = \"");
- if (p == NULL)
- {
-#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';
-
- for (vg = vg_list; vg; vg = vg->next)
- {
- if (! grub_memcmp(vg_id, vg->id, GRUB_LVM_ID_STRLEN))
- break;
- }
-
- if (! vg)
- {
- /* First time we see this volume group. We've to create the
- whole volume group structure. */
- vg = grub_malloc (sizeof (*vg));
- if (! vg)
- goto fail3;
- vg->name = vgname;
- grub_memcpy (vg->id, vg_id, GRUB_LVM_ID_STRLEN+1);
-
- vg->extent_size = grub_lvm_getvalue (&p, "extent_size = ");
- if (p == NULL)
- {
-#ifdef GRUB_UTIL
- grub_util_info ("unknown extent size\n");
-#endif
- goto fail4;
- }
-
- vg->lvs = NULL;
- vg->pvs = NULL;
-
- p = grub_strstr (p, "physical_volumes {");
- if (p)
- {
- p += sizeof ("physical_volumes {") - 1;
-
- /* Add all the pvs to the volume group. */
- while (1)
- {
- int s;
- while (grub_isspace (*p))
- p++;
-
- if (*p == '}')
- break;
-
- pv = grub_malloc (sizeof (*pv));
- q = p;
- while (*q != ' ')
- q++;
-
- s = q - p;
- pv->name = grub_malloc (s + 1);
- grub_memcpy (pv->name, p, s);
- pv->name[s] = '\0';
-
- p = grub_strstr (p, "id = \"");
- if (p == NULL)
- goto pvs_fail;
- p += sizeof("id = \"") - 1;
-
- grub_memcpy (pv->id, p, GRUB_LVM_ID_STRLEN);
- pv->id[GRUB_LVM_ID_STRLEN] = '\0';
-
- pv->start = grub_lvm_getvalue (&p, "pe_start = ");
- if (p == NULL)
- {
-#ifdef GRUB_UTIL
- grub_util_info ("unknown pe_start\n");
-#endif
- goto pvs_fail;
- }
-
- p = grub_strchr (p, '}');
- if (p == NULL)
- {
-#ifdef GRUB_UTIL
- grub_util_info ("error parsing pe_start\n");
-#endif
- goto pvs_fail;
- }
- p++;
-
- pv->disk = NULL;
- pv->next = vg->pvs;
- vg->pvs = pv;
-
- continue;
- pvs_fail:
- grub_free (pv->name);
- grub_free (pv);
- goto fail4;
- }
- }
-
- p = grub_strstr (p, "logical_volumes");
- if (p)
- {
- p += 18;
-
- /* And add all the lvs to the volume group. */
- while (1)
- {
- int s;
- int skip_lv = 0;
- struct grub_lvm_lv *lv;
- struct grub_lvm_segment *seg;
- int is_pvmove;
-
- while (grub_isspace (*p))
- p++;
-
- if (*p == '}')
- break;
-
- lv = grub_malloc (sizeof (*lv));
-
- q = p;
- while (*q != ' ')
- q++;
-
- s = q - p;
- lv->name = grub_malloc (vgname_len + 1 + s + 1);
- grub_memcpy (lv->name, vgname, vgname_len);
- lv->name[vgname_len] = '-';
- grub_memcpy (lv->name + vgname_len + 1, p, s);
- lv->name[vgname_len + 1 + s] = '\0';
-
- lv->size = 0;
-
- lv->visible = grub_lvm_check_flag (p, "status", "VISIBLE");
- is_pvmove = grub_lvm_check_flag (p, "status", "PVMOVE");
-
- lv->segment_count = grub_lvm_getvalue (&p, "segment_count = ");
- if (p == NULL)
- {
-#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;
-
- for (i = 0; i < lv->segment_count; i++)
- {
-
- p = grub_strstr (p, "segment");
- if (p == NULL)
- {
-#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)
- {
-#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)
- {
-#ifdef GRUB_UTIL
- grub_util_info ("unknown extent_count\n");
-#endif
- goto lvs_segment_fail;
- }
-
- p = grub_strstr (p, "type = \"");
- if (p == NULL)
- goto lvs_segment_fail;
- p += sizeof("type = \"") - 1;
-
- lv->size += seg->extent_count * vg->extent_size;
-
- if (grub_memcmp (p, "striped\"",
- sizeof ("striped\"") - 1) == 0)
- {
- struct grub_lvm_node *stripe;
-
- seg->type = GRUB_LVM_STRIPED;
- seg->node_count = grub_lvm_getvalue (&p, "stripe_count = ");
- if (p == NULL)
- {
-#ifdef GRUB_UTIL
- grub_util_info ("unknown stripe_count\n");
-#endif
- goto lvs_segment_fail;
- }
-
- if (seg->node_count != 1)
- seg->stripe_size = grub_lvm_getvalue (&p, "stripe_size = ");
-
- seg->nodes = grub_zalloc (sizeof (*stripe)
- * seg->node_count);
- stripe = seg->nodes;
-
- p = grub_strstr (p, "stripes = [");
- if (p == NULL)
- {
-#ifdef GRUB_UTIL
- grub_util_info ("unknown stripes\n");
-#endif
- goto lvs_segment_fail2;
- }
- p += sizeof("stripes = [") - 1;
-
- for (j = 0; j < seg->node_count; j++)
- {
- p = grub_strchr (p, '"');
- if (p == NULL)
- continue;
- q = ++p;
- while (*q != '"')
- q++;
-
- s = q - p;
-
- stripe->name = grub_malloc (s + 1);
- if (stripe->name == NULL)
- goto lvs_segment_fail2;
-
- grub_memcpy (stripe->name, p, s);
- stripe->name[s] = '\0';
-
- stripe->start = grub_lvm_getvalue (&p, ",");
- if (p == NULL)
- continue;
-
- stripe++;
- }
- }
- else if (grub_memcmp (p, "mirror\"", sizeof ("mirror\"") - 1)
- == 0)
- {
- seg->type = GRUB_LVM_MIRROR;
- seg->node_count = grub_lvm_getvalue (&p, "mirror_count = ");
- if (p == NULL)
- {
-#ifdef GRUB_UTIL
- grub_util_info ("unknown mirror_count\n");
-#endif
- goto lvs_segment_fail;
- }
-
- seg->nodes = grub_zalloc (sizeof (seg->nodes[0])
- * seg->node_count);
-
- p = grub_strstr (p, "mirrors = [");
- if (p == NULL)
- {
-#ifdef GRUB_UTIL
- grub_util_info ("unknown mirrors\n");
-#endif
- goto lvs_segment_fail2;
- }
- p += sizeof("mirrors = [") - 1;
-
- for (j = 0; j < seg->node_count; j++)
- {
- char *lvname;
-
- p = grub_strchr (p, '"');
- if (p == NULL)
- continue;
- q = ++p;
- while (*q != '"')
- q++;
-
- s = q - p;
-
- lvname = grub_malloc (s + 1);
- if (lvname == NULL)
- goto lvs_segment_fail2;
-
- grub_memcpy (lvname, p, s);
- lvname[s] = '\0';
- seg->nodes[j].name = lvname;
- p = q + 1;
- }
- /* Only first (original) is ok with in progress pvmove. */
- if (is_pvmove)
- seg->node_count = 1;
- }
- else
- {
-#ifdef GRUB_UTIL
- char *p2;
- p2 = grub_strchr (p, '"');
- if (p2)
- *p2 = 0;
- grub_util_info ("unknown LVM type %s\n", p);
- if (p2)
- *p2 ='"';
-#endif
- /* Found a non-supported type, give up and move on. */
- skip_lv = 1;
- break;
- }
-
- seg++;
-
- continue;
- lvs_segment_fail2:
- grub_free (seg->nodes);
- lvs_segment_fail:
- goto fail4;
- }
-
- if (p != NULL)
- p = grub_strchr (p, '}');
- if (p == NULL)
- goto lvs_fail;
- p += 3;
-
- if (skip_lv)
- {
- grub_free (lv->name);
- grub_free (lv);
- continue;
- }
-
- lv->number = lv_count++;
- lv->vg = vg;
- lv->next = vg->lvs;
- vg->lvs = lv;
-
- continue;
- lvs_fail:
- grub_free (lv->name);
- grub_free (lv);
- goto fail4;
- }
- }
-
- /* Match lvs. */
- {
- struct grub_lvm_lv *lv1;
- struct grub_lvm_lv *lv2;
- for (lv1 = vg->lvs; lv1; lv1 = lv1->next)
- for (i = 0; i < lv1->segment_count; i++)
- for (j = 0; j < lv1->segments[i].node_count; j++)
- {
- if (vg->pvs)
- for (pv = vg->pvs; pv; pv = pv->next)
- {
- if (! grub_strcmp (pv->name,
- lv1->segments[i].nodes[j].name))
- {
- lv1->segments[i].nodes[j].pv = pv;
- break;
- }
- }
- if (lv1->segments[i].nodes[j].pv == NULL)
- for (lv2 = vg->lvs; lv2; lv2 = lv2->next)
- if (grub_strcmp (lv2->name + grub_strlen (vg->name) + 1,
- lv1->segments[i].nodes[j].name) == 0)
- lv1->segments[i].nodes[j].lv = lv2;
- }
-
- }
-
- vg->next = vg_list;
- vg_list = vg;
- }
- else
- {
- grub_free (vgname);
- }
-
- /* Match the device we are currently reading from with the right
- PV. */
- if (vg->pvs)
- for (pv = vg->pvs; pv; pv = pv->next)
- {
- if (! grub_memcmp (pv->id, pv_id, GRUB_LVM_ID_STRLEN))
- {
- /* This could happen to LVM on RAID, pv->disk points to the
- raid device, we shouldn't change it. */
- if (! pv->disk)
- pv->disk = grub_disk_open (name);
- break;
- }
- }
-
- goto fail2;
-
- /* Failure path. */
- fail4:
- grub_free (vg);
- fail3:
- grub_free (vgname);
-
- /* Normal exit path. */
- fail2:
- grub_free (metadatabuf);
- fail:
- grub_disk_close (disk);
- if (grub_errno == GRUB_ERR_OUT_OF_RANGE)
- grub_errno = GRUB_ERR_NONE;
- grub_print_error ();
- return 0;
-}
-
static struct grub_disk_dev grub_lvm_dev =
{
.name = "lvm",
\f
GRUB_MOD_INIT(lvm)
{
- grub_device_iterate (&grub_lvm_scan_device);
- if (grub_errno)
- {
- grub_print_error ();
- grub_errno = GRUB_ERR_NONE;
- }
-
grub_disk_dev_register (&grub_lvm_dev);
}
#include <grub/misc.h>
#include <grub/raid.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
/* Linux RAID on disk structures and constants,
copied from include/linux/raid/md_p.h. */
/* Linux RAID on disk structures and constants,
copied from include/linux/raid/md_p.h. */
+GRUB_MOD_LICENSE ("GPLv3+");
+
#define RESERVED_BYTES (64 * 1024)
#define RESERVED_SECTORS (RESERVED_BYTES / 512)
return grub_errno;
uuid = (grub_uint32_t *) array->uuid;
- uuid[0] = sb.set_uuid0;
- uuid[1] = sb.set_uuid1;
- uuid[2] = sb.set_uuid2;
- uuid[3] = sb.set_uuid3;
+ uuid[0] = grub_swap_bytes32 (sb.set_uuid0);
+ uuid[1] = grub_swap_bytes32 (sb.set_uuid1);
+ uuid[2] = grub_swap_bytes32 (sb.set_uuid2);
+ uuid[3] = grub_swap_bytes32 (sb.set_uuid3);
*start_sector = 0;
#include <grub/mm.h>
#include <grub/types.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
static char *memdisk_addr;
static grub_off_t memdisk_size = 0;
static int
-grub_memdisk_iterate (int (*hook) (const char *name))
+grub_memdisk_iterate (int (*hook) (const char *name),
+ grub_disk_pull_t pull)
{
+ if (pull != GRUB_DISK_PULL_NONE)
+ return 0;
+
return hook ("memdisk");
}
GRUB_MOD_INIT(memdisk)
{
- auto int hook (struct grub_module_header *);
- int hook (struct grub_module_header *header)
- {
- if (header->type == OBJ_TYPE_MEMDISK)
- {
- char *memdisk_orig_addr;
- memdisk_orig_addr = (char *) header + sizeof (struct grub_module_header);
-
- grub_dprintf ("memdisk", "Found memdisk image at %p\n", memdisk_orig_addr);
-
- memdisk_size = header->size - sizeof (struct grub_module_header);
- memdisk_addr = grub_malloc (memdisk_size);
+ struct grub_module_header *header;
+ FOR_MODULES (header)
+ if (header->type == OBJ_TYPE_MEMDISK)
+ {
+ char *memdisk_orig_addr;
+ memdisk_orig_addr = (char *) header + sizeof (struct grub_module_header);
- grub_dprintf ("memdisk", "Copying memdisk image to dynamic memory\n");
- grub_memmove (memdisk_addr, memdisk_orig_addr, memdisk_size);
+ grub_dprintf ("memdisk", "Found memdisk image at %p\n", memdisk_orig_addr);
- grub_disk_dev_register (&grub_memdisk_dev);
- return 1;
- }
+ memdisk_size = header->size - sizeof (struct grub_module_header);
+ memdisk_addr = grub_malloc (memdisk_size);
- return 0;
- }
+ grub_dprintf ("memdisk", "Copying memdisk image to dynamic memory\n");
+ grub_memmove (memdisk_addr, memdisk_orig_addr, memdisk_size);
- grub_module_iterate (hook);
+ grub_disk_dev_register (&grub_memdisk_dev);
+ break;
+ }
}
GRUB_MOD_FINI(memdisk)
--- /dev/null
+/* ata_pthru.c - ATA pass through for ata.mod. */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2009 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/ata.h>
+#include <grub/scsi.h>
+#include <grub/disk.h>
+#include <grub/dl.h>
+#include <grub/mm.h>
+#ifndef GRUB_MACHINE_MIPS_QEMU_MIPS
+#include <grub/pci.h>
+#include <grub/cs5536.h>
+#else
+#define GRUB_MACHINE_PCI_IO_BASE 0xb4000000
+#endif
+#include <grub/time.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
+
+/* At the moment, only two IDE ports are supported. */
+static const grub_port_t grub_pata_ioaddress[] = { GRUB_ATA_CH0_PORT1,
+ GRUB_ATA_CH1_PORT1 };
+
+struct grub_pata_device
+{
+ /* IDE port to use. */
+ int port;
+
+ /* IO addresses on which the registers for this device can be
+ found. */
+ grub_port_t ioaddress;
+
+ /* Two devices can be connected to a single cable. Use this field
+ to select device 0 (commonly known as "master") or device 1
+ (commonly known as "slave"). */
+ int device;
+
+ int present;
+
+ struct grub_pata_device *next;
+};
+
+static struct grub_pata_device *grub_pata_devices;
+
+static inline void
+grub_pata_regset (struct grub_pata_device *dev, int reg, int val)
+{
+ grub_outb (val, dev->ioaddress + reg);
+}
+
+static inline grub_uint8_t
+grub_pata_regget (struct grub_pata_device *dev, int reg)
+{
+ return grub_inb (dev->ioaddress + reg);
+}
+
+/* Wait for !BSY. */
+static grub_err_t
+grub_pata_wait_not_busy (struct grub_pata_device *dev, int milliseconds)
+{
+ /* ATA requires 400ns (after a write to CMD register) or
+ 1 PIO cycle (after a DRQ block transfer) before
+ first check of BSY. */
+ grub_millisleep (1);
+
+ int i = 1;
+ grub_uint8_t sts;
+ while ((sts = grub_pata_regget (dev, GRUB_ATA_REG_STATUS))
+ & GRUB_ATA_STATUS_BUSY)
+ {
+ if (i >= milliseconds)
+ {
+ grub_dprintf ("pata", "timeout: %dms, status=0x%x\n",
+ milliseconds, sts);
+ return grub_error (GRUB_ERR_TIMEOUT, "PATA timeout");
+ }
+
+ grub_millisleep (1);
+ i++;
+ }
+
+ return GRUB_ERR_NONE;
+}
+
+static inline grub_err_t
+grub_pata_check_ready (struct grub_pata_device *dev, int spinup)
+{
+ if (grub_pata_regget (dev, GRUB_ATA_REG_STATUS) & GRUB_ATA_STATUS_BUSY)
+ return grub_pata_wait_not_busy (dev, spinup ? GRUB_ATA_TOUT_SPINUP
+ : GRUB_ATA_TOUT_STD);
+
+ return GRUB_ERR_NONE;
+}
+
+static inline void
+grub_pata_wait (void)
+{
+ grub_millisleep (50);
+}
+
+static void
+grub_pata_pio_read (struct grub_pata_device *dev, char *buf, grub_size_t size)
+{
+ grub_uint16_t *buf16 = (grub_uint16_t *) buf;
+ unsigned int i;
+
+ /* Read in the data, word by word. */
+ for (i = 0; i < size / 2; i++)
+ buf16[i] = grub_le_to_cpu16 (grub_inw(dev->ioaddress + GRUB_ATA_REG_DATA));
+ if (size & 1)
+ buf[size - 1] = (char) grub_le_to_cpu16 (grub_inw (dev->ioaddress
+ + GRUB_ATA_REG_DATA));
+}
+
+static void
+grub_pata_pio_write (struct grub_pata_device *dev, char *buf, grub_size_t size)
+{
+ grub_uint16_t *buf16 = (grub_uint16_t *) buf;
+ unsigned int i;
+
+ /* Write the data, word by word. */
+ for (i = 0; i < size / 2; i++)
+ grub_outw(grub_cpu_to_le16 (buf16[i]), dev->ioaddress + GRUB_ATA_REG_DATA);
+}
+
+/* ATA pass through support, used by hdparm.mod. */
+static grub_err_t
+grub_pata_readwrite (struct grub_ata *disk,
+ struct grub_disk_ata_pass_through_parms *parms,
+ int spinup)
+{
+ struct grub_pata_device *dev = (struct grub_pata_device *) disk->data;
+ grub_size_t nread = 0;
+ int i;
+
+ if (! (parms->cmdsize == 0 || parms->cmdsize == 12))
+ return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
+ "ATAPI non-12 byte commands not supported");
+
+ grub_dprintf ("pata", "pata_pass_through: cmd=0x%x, features=0x%x, sectors=0x%x\n",
+ parms->taskfile.cmd,
+ parms->taskfile.features,
+ parms->taskfile.sectors);
+ grub_dprintf ("pata", "lba_high=0x%x, lba_mid=0x%x, lba_low=0x%x, size=%"
+ PRIuGRUB_SIZE "\n",
+ parms->taskfile.lba_high,
+ parms->taskfile.lba_mid,
+ parms->taskfile.lba_low, parms->size);
+
+ /* Set registers. */
+ grub_pata_regset (dev, GRUB_ATA_REG_DISK, (dev->device << 4)
+ | (parms->taskfile.disk & 0xef));
+ if (grub_pata_check_ready (dev, spinup))
+ return grub_errno;
+
+ for (i = GRUB_ATA_REG_SECTORS; i <= GRUB_ATA_REG_LBAHIGH; i++)
+ grub_pata_regset (dev, i,
+ parms->taskfile.raw[7 + (i - GRUB_ATA_REG_SECTORS)]);
+ for (i = GRUB_ATA_REG_FEATURES; i <= GRUB_ATA_REG_LBAHIGH; i++)
+ grub_pata_regset (dev, i, parms->taskfile.raw[i - GRUB_ATA_REG_FEATURES]);
+
+ /* Start command. */
+ grub_pata_regset (dev, GRUB_ATA_REG_CMD, parms->taskfile.cmd);
+
+ /* Wait for !BSY. */
+ if (grub_pata_wait_not_busy (dev, GRUB_ATA_TOUT_DATA))
+ return grub_errno;
+
+ /* Check status. */
+ grub_int8_t sts = grub_pata_regget (dev, GRUB_ATA_REG_STATUS);
+ grub_dprintf ("pata", "status=0x%x\n", sts);
+
+ if (parms->cmdsize)
+ {
+ grub_uint8_t irs;
+ /* Wait for !BSY. */
+ if (grub_pata_wait_not_busy (dev, GRUB_ATA_TOUT_DATA))
+ return grub_errno;
+
+ irs = grub_pata_regget (dev, GRUB_ATAPI_REG_IREASON);
+ /* OK if DRQ is asserted and interrupt reason is as expected. */
+ if (!((sts & GRUB_ATA_STATUS_DRQ)
+ && (irs & GRUB_ATAPI_IREASON_MASK) == GRUB_ATAPI_IREASON_CMD_OUT))
+ return grub_error (GRUB_ERR_READ_ERROR, "ATAPI protocol error");
+ /* Write the packet. */
+ grub_pata_pio_write (dev, parms->cmd, parms->cmdsize);
+ }
+
+ /* Transfer data. */
+ while (nread < parms->size
+ && ((sts & (GRUB_ATA_STATUS_DRQ | GRUB_ATA_STATUS_ERR))
+ == GRUB_ATA_STATUS_DRQ)
+ && (!parms->cmdsize
+ || ((grub_pata_regget (dev, GRUB_ATAPI_REG_IREASON)
+ & GRUB_ATAPI_IREASON_MASK) == GRUB_ATAPI_IREASON_DATA_IN)))
+ {
+ unsigned cnt;
+
+ /* Wait for !BSY. */
+ if (grub_pata_wait_not_busy (dev, GRUB_ATA_TOUT_DATA))
+ return grub_errno;
+
+ if (parms->cmdsize)
+ {
+ cnt = grub_pata_regget (dev, GRUB_ATAPI_REG_CNTHIGH) << 8
+ | grub_pata_regget (dev, GRUB_ATAPI_REG_CNTLOW);
+ grub_dprintf("pata", "DRQ count=%u\n", cnt);
+
+ /* Count of last transfer may be uneven. */
+ if (! (0 < cnt && cnt <= parms->size - nread
+ && (! (cnt & 1) || cnt == parms->size - nread)))
+ return grub_error (GRUB_ERR_READ_ERROR,
+ "invalid ATAPI transfer count");
+ }
+ else
+ cnt = GRUB_DISK_SECTOR_SIZE;
+ if (cnt > parms->size - nread)
+ cnt = parms->size - nread;
+
+ if (parms->write)
+ grub_pata_pio_write (dev, (char *) parms->buffer + nread, cnt);
+ else
+ grub_pata_pio_read (dev, (char *) parms->buffer + nread, cnt);
+
+ nread += cnt;
+ }
+ if (parms->write)
+ {
+ /* Check for write error. */
+ if (grub_pata_wait_not_busy (dev, GRUB_ATA_TOUT_DATA))
+ return grub_errno;
+
+ if (grub_pata_regget (dev, GRUB_ATA_REG_STATUS)
+ & (GRUB_ATA_STATUS_DRQ | GRUB_ATA_STATUS_ERR))
+ return grub_error (GRUB_ERR_WRITE_ERROR, "ATA write error");
+ }
+ parms->size = nread;
+
+ /* Wait for !BSY. */
+ if (grub_pata_wait_not_busy (dev, GRUB_ATA_TOUT_DATA))
+ return grub_errno;
+
+ /* Return registers. */
+ for (i = GRUB_ATA_REG_ERROR; i <= GRUB_ATA_REG_STATUS; i++)
+ parms->taskfile.raw[i - GRUB_ATA_REG_FEATURES] = grub_pata_regget (dev, i);
+
+ grub_dprintf ("pata", "status=0x%x, error=0x%x, sectors=0x%x\n",
+ parms->taskfile.status,
+ parms->taskfile.error,
+ parms->taskfile.sectors);
+
+ if (parms->taskfile.status
+ & (GRUB_ATA_STATUS_DRQ | GRUB_ATA_STATUS_ERR))
+ return grub_error (GRUB_ERR_READ_ERROR, "PATA passthrough failed");
+
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+check_device (struct grub_pata_device *dev)
+{
+ grub_pata_regset (dev, GRUB_ATA_REG_DISK, dev->device << 4);
+ grub_pata_wait ();
+
+ /* Try to detect if the port is in use by writing to it,
+ waiting for a while and reading it again. If the value
+ was preserved, there is a device connected. */
+ grub_pata_regset (dev, GRUB_ATA_REG_SECTORS, 0x5A);
+ grub_pata_wait ();
+ grub_uint8_t sec = grub_pata_regget (dev, GRUB_ATA_REG_SECTORS);
+ grub_dprintf ("ata", "sectors=0x%x\n", sec);
+ if (sec != 0x5A)
+ return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no device connected");
+
+ /* The above test may detect a second (slave) device
+ connected to a SATA controller which supports only one
+ (master) device. It is not safe to use the status register
+ READY bit to check for controller channel existence. Some
+ ATAPI commands (RESET, DIAGNOSTIC) may clear this bit. */
+
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_pata_device_initialize (int port, int device, int addr)
+{
+ struct grub_pata_device *dev;
+ struct grub_pata_device **devp;
+ grub_err_t err;
+
+ grub_dprintf ("pata", "detecting device %d,%d (0x%x)\n",
+ port, device, addr);
+
+ dev = grub_malloc (sizeof(*dev));
+ if (! dev)
+ return grub_errno;
+
+ /* Setup the device information. */
+ dev->port = port;
+ dev->device = device;
+ dev->ioaddress = addr + GRUB_MACHINE_PCI_IO_BASE;
+ dev->present = 1;
+ dev->next = NULL;
+
+ /* Register the device. */
+ for (devp = &grub_pata_devices; *devp; devp = &(*devp)->next);
+ *devp = dev;
+
+ err = check_device (dev);
+ if (err)
+ grub_print_error ();
+
+ return 0;
+}
+
+#ifndef GRUB_MACHINE_MIPS_QEMU_MIPS
+static int NESTED_FUNC_ATTR
+grub_pata_pciinit (grub_pci_device_t dev,
+ grub_pci_id_t pciid)
+{
+ static int compat_use[2] = { 0 };
+ grub_pci_address_t addr;
+ grub_uint32_t class;
+ grub_uint32_t bar1;
+ grub_uint32_t bar2;
+ int rega;
+ int i;
+ static int controller = 0;
+ int cs5536 = 0;
+ int nports = 2;
+
+ /* Read class. */
+ addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS);
+ class = grub_pci_read (addr);
+
+ /* AMD CS5536 Southbridge. */
+ if (pciid == GRUB_CS5536_PCIID)
+ {
+ cs5536 = 1;
+ nports = 1;
+ }
+
+ /* Check if this class ID matches that of a PCI IDE Controller. */
+ if (!cs5536 && (class >> 16 != 0x0101))
+ return 0;
+
+ for (i = 0; i < nports; i++)
+ {
+ /* Set to 0 when the channel operated in compatibility mode. */
+ int compat;
+
+ /* We don't support non-compatibility mode for CS5536. */
+ if (cs5536)
+ compat = 0;
+ else
+ compat = (class >> (8 + 2 * i)) & 1;
+
+ rega = 0;
+
+ /* If the channel is in compatibility mode, just assign the
+ default registers. */
+ if (compat == 0 && !compat_use[i])
+ {
+ rega = grub_pata_ioaddress[i];
+ compat_use[i] = 1;
+ }
+ else if (compat)
+ {
+ /* Read the BARs, which either contain a mmapped IO address
+ or the IO port address. */
+ addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESSES
+ + sizeof (grub_uint64_t) * i);
+ bar1 = grub_pci_read (addr);
+ addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESSES
+ + sizeof (grub_uint64_t) * i
+ + sizeof (grub_uint32_t));
+ bar2 = grub_pci_read (addr);
+
+ /* Check if the BARs describe an IO region. */
+ if ((bar1 & 1) && (bar2 & 1))
+ {
+ rega = bar1 & ~3;
+ }
+ }
+
+ grub_dprintf ("pata",
+ "PCI dev (%d,%d,%d) compat=%d rega=0x%x\n",
+ grub_pci_get_bus (dev), grub_pci_get_device (dev),
+ grub_pci_get_function (dev), compat, rega);
+
+ if (rega)
+ {
+ grub_errno = GRUB_ERR_NONE;
+ grub_pata_device_initialize (controller * 2 + i, 0, rega);
+
+ /* Most errors raised by grub_ata_device_initialize() are harmless.
+ They just indicate this particular drive is not responding, most
+ likely because it doesn't exist. We might want to ignore specific
+ error types here, instead of printing them. */
+ if (grub_errno)
+ {
+ grub_print_error ();
+ grub_errno = GRUB_ERR_NONE;
+ }
+
+ grub_pata_device_initialize (controller * 2 + i, 1, rega);
+
+ /* Likewise. */
+ if (grub_errno)
+ {
+ grub_print_error ();
+ grub_errno = GRUB_ERR_NONE;
+ }
+ }
+ }
+
+ controller++;
+
+ return 0;
+}
+
+static grub_err_t
+grub_pata_initialize (void)
+{
+ grub_pci_iterate (grub_pata_pciinit);
+ return 0;
+}
+#else
+static grub_err_t
+grub_pata_initialize (void)
+{
+ int i;
+ for (i = 0; i < 2; i++)
+ {
+ grub_pata_device_initialize (i, 0, grub_pata_ioaddress[i]);
+ grub_pata_device_initialize (i, 1, grub_pata_ioaddress[i]);
+ }
+ return 0;
+}
+#endif
+
+static grub_err_t
+grub_pata_open (int id, int devnum, struct grub_ata *ata)
+{
+ struct grub_pata_device *dev;
+ struct grub_pata_device *devfnd = 0;
+ grub_err_t err;
+
+ if (id != GRUB_SCSI_SUBSYSTEM_PATA)
+ return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a PATA device");
+
+ for (dev = grub_pata_devices; dev; dev = dev->next)
+ {
+ if (dev->port * 2 + dev->device == devnum)
+ {
+ devfnd = dev;
+ break;
+ }
+ }
+
+ grub_dprintf ("pata", "opening PATA dev `ata%d'\n", devnum);
+
+ if (! devfnd)
+ return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no such PATA device");
+
+ err = check_device (devfnd);
+ if (err)
+ return err;
+
+ ata->data = devfnd;
+ ata->dma = 0;
+ ata->present = &devfnd->present;
+
+ return GRUB_ERR_NONE;
+}
+
+static int
+grub_pata_iterate (int (*hook) (int id, int bus),
+ grub_disk_pull_t pull)
+{
+ struct grub_pata_device *dev;
+
+ if (pull != GRUB_DISK_PULL_NONE)
+ return 0;
+
+ for (dev = grub_pata_devices; dev; dev = dev->next)
+ if (hook (GRUB_SCSI_SUBSYSTEM_PATA, dev->port * 2 + dev->device))
+ return 1;
+
+ return 0;
+}
+
+
+static struct grub_ata_dev grub_pata_dev =
+ {
+ .iterate = grub_pata_iterate,
+ .open = grub_pata_open,
+ .readwrite = grub_pata_readwrite,
+ };
+
+
+\f
+
+GRUB_MOD_INIT(ata_pthru)
+{
+ /* To prevent two drivers operating on the same disks. */
+ grub_disk_firmware_is_tainted = 1;
+ if (grub_disk_firmware_fini)
+ {
+ grub_disk_firmware_fini ();
+ grub_disk_firmware_fini = NULL;
+ }
+
+ /* ATA initialization. */
+ grub_pata_initialize ();
+
+ grub_ata_dev_register (&grub_pata_dev);
+}
+
+GRUB_MOD_FINI(ata_pthru)
+{
+ grub_ata_dev_unregister (&grub_pata_dev);
+}
#include <grub/util/misc.h>
#endif
+GRUB_MOD_LICENSE ("GPLv3+");
+
/* Linked list of RAID arrays. */
static struct grub_raid_array *array_list;
grub_raid5_recover_func_t grub_raid5_recover_func;
grub_raid6_recover_func_t grub_raid6_recover_func;
+static grub_raid_t grub_raid_list;
+static int inscnt = 0;
+
+static struct grub_raid_array *
+find_array (const char *name);
\f
static char
return 0;
}
+static grub_err_t
+insert_array (grub_disk_t disk, struct grub_raid_array *new_array,
+ grub_disk_addr_t start_sector, const char *scanner_name,
+ grub_raid_t raid __attribute__ ((unused)));
+
+static int scan_depth = 0;
+
+static void
+scan_devices (const char *arname)
+{
+ grub_raid_t raid;
+
+ auto int hook (const char *name);
+ int hook (const char *name)
+ {
+ grub_disk_t disk;
+ struct grub_raid_array array;
+ struct grub_raid_array *arr;
+ grub_disk_addr_t start_sector;
+
+ grub_dprintf ("raid", "Scanning for %s RAID devices on disk %s\n",
+ raid->name, name);
+#ifdef GRUB_UTIL
+ grub_util_info ("Scanning for %s RAID devices on disk %s",
+ raid->name, name);
+#endif
+
+ disk = grub_disk_open (name);
+ if (!disk)
+ return 0;
+
+ for (arr = array_list; arr != NULL; arr = arr->next)
+ {
+ struct grub_raid_member *m;
+ for (m = arr->members; m < arr->members + arr->nr_devs; m++)
+ if (m->device && m->device->id == disk->id
+ && m->device->dev->id == m->device->dev->id)
+ {
+ grub_disk_close (disk);
+ return 0;
+ }
+ }
+
+ if ((disk->total_sectors != GRUB_ULONG_MAX) &&
+ (! raid->detect (disk, &array, &start_sector)) &&
+ (! insert_array (disk, &array, start_sector, raid->name,
+ raid)))
+ return 0;
+
+ /* This error usually means it's not raid, no need to display
+ it. */
+ if (grub_errno != GRUB_ERR_OUT_OF_RANGE)
+ grub_print_error ();
+
+ grub_errno = GRUB_ERR_NONE;
+
+ grub_disk_close (disk);
+
+ if (arname && find_array (arname))
+ return 1;
+
+ return 0;
+ }
+
+ if (scan_depth)
+ return;
+
+ scan_depth++;
+ for (raid = grub_raid_list; raid; raid = raid->next)
+ grub_device_iterate (&hook);
+ scan_depth--;
+}
+
static int
-grub_raid_iterate (int (*hook) (const char *name))
+grub_raid_iterate (int (*hook) (const char *name),
+ grub_disk_pull_t pull)
{
struct grub_raid_array *array;
+ int islcnt = 0;
+
+ if (pull == GRUB_DISK_PULL_RESCAN)
+ {
+ islcnt = inscnt;
+ scan_devices (NULL);
+ }
+
+ if (pull != GRUB_DISK_PULL_NONE && pull != GRUB_DISK_PULL_RESCAN)
+ return 0;
for (array = array_list; array != NULL; array = array->next)
{
- if (grub_is_array_readable (array))
+ if (grub_is_array_readable (array) && array->became_readable_at >= islcnt)
if (hook (array->name))
return 1;
}
}
#endif
+static inline int
+ascii2hex (char c)
+{
+ if (c >= '0' && c <= '9')
+ return c - '0';
+ if (c >= 'a' && c <= 'f')
+ return c - 'a' + 10;
+ if (c >= 'A' && c <= 'F')
+ return c - 'A' + 10;
+ return 0;
+}
+
+static struct grub_raid_array *
+find_array (const char *name)
+{
+ struct grub_raid_array *array;
+
+ if (grub_memcmp (name, "mduuid/", sizeof ("mduuid/") - 1) == 0)
+ {
+ const char *uuidstr = name + sizeof ("mduuid/") - 1;
+ grub_size_t uuid_len = grub_strlen (uuidstr) / 2;
+ grub_uint8_t uuidbin[uuid_len];
+ unsigned i;
+ for (i = 0; i < uuid_len; i++)
+ uuidbin[i] = ascii2hex (uuidstr[2 * i + 1])
+ | (ascii2hex (uuidstr[2 * i]) << 4);
+
+ for (array = array_list; array != NULL; array = array->next)
+ {
+ if (uuid_len == (unsigned) array->uuid_len
+ && grub_memcmp (uuidbin, array->uuid, uuid_len) == 0)
+ if (grub_is_array_readable (array))
+ return array;
+ }
+ }
+ else
+ for (array = array_list; array != NULL; array = array->next)
+ {
+ if (!grub_strcmp (array->name, name))
+ if (grub_is_array_readable (array))
+ return array;
+ }
+ return NULL;
+}
+
static grub_err_t
grub_raid_open (const char *name, grub_disk_t disk)
{
struct grub_raid_array *array;
unsigned n;
- for (array = array_list; array != NULL; array = array->next)
+ if (grub_memcmp (name, "md", sizeof ("md") - 1) != 0)
+ return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "unknown RAID device %s",
+ name);
+
+ array = find_array (name);
+
+ if (! array)
{
- if (!grub_strcmp (array->name, name))
- if (grub_is_array_readable (array))
- break;
+ scan_devices (name);
+ if (grub_errno)
+ {
+ grub_print_error ();
+ grub_errno = GRUB_ERR_NONE;
+ }
+ array = find_array (name);
}
if (!array)
case 10:
{
grub_disk_addr_t read_sector, far_ofs;
- grub_uint32_t disknr, b, near, far, ofs;
+ grub_uint64_t disknr, b, near, far, ofs;
read_sector = grub_divmod64 (sector, array->chunk_size, &b);
far = ofs = near = 1;
case 6:
{
grub_disk_addr_t read_sector;
- grub_uint32_t b, p, n, disknr, e;
+ grub_uint64_t b, p, n, disknr, e;
/* n = 1 for level 4 and 5, 2 for level 6. */
n = array->level / 3;
grub_raid_t raid __attribute__ ((unused)))
{
struct grub_raid_array *array = 0, *p;
+ int was_readable = 0;
/* See whether the device is part of an array we have already seen a
device from. */
grub_free (new_array->uuid);
array = p;
+ was_readable = grub_is_array_readable (array);
+
/* Do some checks before adding the device to the array. */
if (new_array->index >= array->allocated_devs)
scanner_name);
#endif
+ {
+ int max_used_number = 0, len, need_new_name = 0;
+ int add_us = 0;
+ len = grub_strlen (array->name);
+ if (len && grub_isdigit (array->name[len-1]))
+ add_us = 1;
+ for (p = array_list; p != NULL; p = p->next)
+ {
+ int cur_num;
+ char *num, *end;
+ if (grub_strncmp (p->name, array->name, len) != 0)
+ continue;
+ if (p->name[len] == 0)
+ {
+ need_new_name = 1;
+ continue;
+ }
+ if (add_us && p->name[len] != '_')
+ continue;
+ if (add_us)
+ num = p->name + len + 1;
+ else
+ num = p->name + len;
+ if (!grub_isdigit (num[0]))
+ continue;
+ cur_num = grub_strtoull (num, &end, 10);
+ if (end[0])
+ continue;
+ if (cur_num > max_used_number)
+ max_used_number = cur_num;
+ }
+ if (need_new_name)
+ {
+ char *tmp;
+ tmp = grub_xasprintf ("%s%s%d", array->name, add_us ? "_" : "",
+ max_used_number + 1);
+ if (!tmp)
+ return grub_errno;
+ grub_free (array->name);
+ array->name = tmp;
+ }
+ }
+
/* Add our new array to the list. */
array->next = array_list;
array_list = array;
array->members[new_array->index].device = disk;
array->members[new_array->index].start_sector = start_sector;
array->nr_devs++;
+ if (!was_readable && grub_is_array_readable (array))
+ array->became_readable_at = inscnt++;
return 0;
}
-static grub_raid_t grub_raid_list;
-
static void
free_array (void)
{
void
grub_raid_register (grub_raid_t raid)
{
- auto int hook (const char *name);
- int hook (const char *name)
- {
- grub_disk_t disk;
- struct grub_raid_array array;
- grub_disk_addr_t start_sector;
-
- grub_dprintf ("raid", "Scanning for %s RAID devices on disk %s\n",
- grub_raid_list->name, name);
-#ifdef GRUB_UTIL
- grub_util_info ("Scanning for %s RAID devices on disk %s",
- grub_raid_list->name, name);
-#endif
-
- disk = grub_disk_open (name);
- if (!disk)
- return 0;
-
- if ((disk->total_sectors != GRUB_ULONG_MAX) &&
- (! grub_raid_list->detect (disk, &array, &start_sector)) &&
- (! insert_array (disk, &array, start_sector, grub_raid_list->name,
- grub_raid_list)))
- return 0;
-
- /* This error usually means it's not raid, no need to display
- it. */
- if (grub_errno != GRUB_ERR_OUT_OF_RANGE)
- grub_print_error ();
-
- grub_errno = GRUB_ERR_NONE;
-
- grub_disk_close (disk);
-
- return 0;
- }
-
raid->next = grub_raid_list;
grub_raid_list = raid;
- grub_device_iterate (&hook);
}
void
#include <grub/misc.h>
#include <grub/raid.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
static grub_err_t
grub_raid5_recover (struct grub_raid_array *array, int disknr,
char *buf, grub_disk_addr_t sector, int size)
#include <grub/misc.h>
#include <grub/raid.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
static grub_uint8_t raid6_table1[256][256];
static grub_uint8_t raid6_table2[256][256];
#include <grub/scsicmd.h>
#include <grub/time.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
\f
static grub_scsi_dev_t grub_scsi_dev_list;
+const char grub_scsi_names[GRUB_SCSI_NUM_SUBSYSTEMS][5] = {
+ [GRUB_SCSI_SUBSYSTEM_USBMS] = "usb",
+ [GRUB_SCSI_SUBSYSTEM_PATA] = "ata",
+ [GRUB_SCSI_SUBSYSTEM_AHCI] = "ahci"
+};
+
void
grub_scsi_dev_register (grub_scsi_dev_t dev)
{
\f
static int
-grub_scsi_iterate (int (*hook) (const char *name))
+grub_scsi_iterate (int (*hook) (const char *name),
+ grub_disk_pull_t pull)
{
grub_scsi_dev_t p;
- auto int scsi_iterate (int bus, int luns);
+ auto int NESTED_FUNC_ATTR scsi_iterate (int id, int bus, int luns);
- int scsi_iterate (int bus, int luns)
+ int NESTED_FUNC_ATTR scsi_iterate (int id, int bus, int luns)
{
int i;
{
char *sname;
int ret;
- sname = grub_xasprintf ("%s%d", p->name, bus);
+ sname = grub_xasprintf ("%s%d", grub_scsi_names[id], bus);
if (!sname)
return 1;
ret = hook (sname);
{
char *sname;
int ret;
- sname = grub_xasprintf ("%s%d%c", p->name, bus, 'a' + i);
+ sname = grub_xasprintf ("%s%d%c", grub_scsi_names[id], bus, 'a' + i);
if (!sname)
return 1;
ret = hook (sname);
}
for (p = grub_scsi_dev_list; p; p = p->next)
- if (p->iterate && (p->iterate) (scsi_iterate))
+ if (p->iterate && (p->iterate) (scsi_iterate, pull))
return 1;
return 0;
int lun, bus;
grub_uint64_t maxtime;
const char *nameend;
+ unsigned id;
nameend = name + grub_strlen (name) - 1;
/* Try to detect a LUN ('a'-'z'), otherwise just use the first
if (! scsi)
return grub_errno;
- for (p = grub_scsi_dev_list; p; p = p->next)
+ for (id = 0; id < ARRAY_SIZE (grub_scsi_names); id++)
+ if (grub_strncmp (grub_scsi_names[id], name, nameend - name) == 0)
+ break;
+
+ if (id == ARRAY_SIZE (grub_scsi_names))
{
- if (grub_strncmp (p->name, name, nameend - name) != 0)
- continue;
+ grub_free (scsi);
+ return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a SCSI disk");
+ }
- if (p->open (bus, scsi))
- continue;
+ for (p = grub_scsi_dev_list; p; p = p->next)
+ {
+ if (p->open (id, bus, scsi))
+ {
+ grub_errno = GRUB_ERR_NONE;
+ continue;
+ }
- disk->id = grub_make_scsi_id (p->id, bus, lun);
+ disk->id = grub_make_scsi_id (id, bus, lun);
disk->data = scsi;
scsi->dev = p;
scsi->lun = lun;
return err;
}
- /* SCSI blocks can be something else than 512, although GRUB
- wants 512 byte blocks. */
- disk->total_sectors = ((grub_uint64_t)scsi->size
- * (grub_uint64_t)scsi->blocksize)
- >> GRUB_DISK_SECTOR_BITS;
+ disk->total_sectors = scsi->size;
+ if (scsi->blocksize & (scsi->blocksize - 1) || !scsi->blocksize)
+ {
+ grub_free (scsi);
+ return grub_error (GRUB_ERR_IO, "invalid sector size %d",
+ scsi->blocksize);
+ }
+ for (disk->log_sector_size = 0;
+ (1 << disk->log_sector_size) < scsi->blocksize;
+ disk->log_sector_size++);
grub_dprintf ("scsi", "blocks=%u, blocksize=%u\n",
scsi->size, scsi->blocksize);
- grub_dprintf ("scsi", "Disk total 512 sectors = %llu\n",
+ grub_dprintf ("scsi", "Disk total sectors = %llu\n",
(unsigned long long) disk->total_sectors);
return GRUB_ERR_NONE;
}
grub_free (scsi);
-
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a SCSI disk");
}
scsi = disk->data;
- /* SCSI sectors are variable in size. GRUB uses 512 byte
- sectors. */
- if (scsi->blocksize != GRUB_DISK_SECTOR_SIZE)
- {
- unsigned spb = scsi->blocksize >> GRUB_DISK_SECTOR_BITS;
- if (spb == 0 || (scsi->blocksize & (GRUB_DISK_SECTOR_SIZE - 1)) != 0)
- return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
- "unsupported SCSI block size");
-
- grub_uint32_t sector_mod = 0;
- sector = grub_divmod64 (sector, spb, §or_mod);
-
- if (! (sector_mod == 0 && size % spb == 0))
- return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
- "unaligned SCSI read not supported");
-
- size /= spb;
- }
-
- /* Depending on the type, select a read function. */
- switch (scsi->devtype)
+ while (size)
{
- case grub_scsi_devtype_direct:
- return grub_scsi_read10 (disk, sector, size, buf);
-
- case grub_scsi_devtype_cdrom:
- return grub_scsi_read12 (disk, sector, size, buf);
+ /* PATA doesn't support more than 32K reads.
+ Not sure about AHCI and USB. If it's confirmed that either of
+ them can do bigger reads reliably this value can be moved to 'scsi'
+ structure. */
+ grub_size_t len = 32768 >> disk->log_sector_size;
+ grub_err_t err;
+ if (len > size)
+ len = size;
+ /* Depending on the type, select a read function. */
+ switch (scsi->devtype)
+ {
+ case grub_scsi_devtype_direct:
+ err = grub_scsi_read10 (disk, sector, len, buf);
+ if (err)
+ return err;
+ break;
+
+ case grub_scsi_devtype_cdrom:
+ err = grub_scsi_read12 (disk, sector, len, buf);
+ if (err)
+ return err;
+ break;
+ }
+ size -= len;
+ sector += len;
+ buf += len << disk->log_sector_size;
}
- /* XXX: Never reached. */
return GRUB_ERR_NONE;
#if 0 /* Workaround - it works - but very slowly, from some reason
#include <grub/scsicmd.h>
#include <grub/misc.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
#define GRUB_USBMS_DIRECTION_BIT 7
/* The USB Mass Storage Command Block Wrapper. */
\f
static int
-grub_usbms_iterate (int (*hook) (int bus, int luns))
+grub_usbms_iterate (int NESTED_FUNC_ATTR (*hook) (int id, int bus, int luns),
+ grub_disk_pull_t pull)
{
unsigned i;
+ if (pull != GRUB_DISK_PULL_NONE)
+ return 0;
+
grub_usb_poll_devices ();
for (i = 0; i < ARRAY_SIZE (grub_usbms_devices); i++)
if (grub_usbms_devices[i])
{
- if (hook (i, grub_usbms_devices[i]->luns))
+ if (hook (GRUB_SCSI_SUBSYSTEM_USBMS, i, grub_usbms_devices[i]->luns))
return 1;
}
}
static grub_err_t
-grub_usbms_open (int devnum, struct grub_scsi *scsi)
+grub_usbms_open (int id, int devnum, struct grub_scsi *scsi)
{
+ if (id != GRUB_SCSI_SUBSYSTEM_USBMS)
+ return grub_error (GRUB_ERR_UNKNOWN_DEVICE,
+ "not USB Mass Storage device");
+
grub_usb_poll_devices ();
if (!grub_usbms_devices[devnum])
static struct grub_scsi_dev grub_usbms_dev =
{
- .name = "usb",
- .id = GRUB_SCSI_SUBSYSTEM_USBMS,
.iterate = grub_usbms_iterate,
.open = grub_usbms_open,
.read = grub_usbms_read,
#include <grub/command.h>
#include <grub/i18n.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
/* System table. Two version depending on mode */
grub_efi_system_table32_t *grub_efiemu_system_table32 = 0;
grub_efi_system_table64_t *grub_efiemu_system_table64 = 0;
file = grub_file_open (filename);
if (! file)
- return 0;
+ return grub_errno;
err = grub_efiemu_mm_init ();
if (err)
#include <grub/unicode.h>
#include <grub/fontformat.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
#ifdef USE_ASCII_FAILBACK
#include "ascii.h"
#endif
return 1;
font->bmp_idx = grub_malloc (0x10000 * sizeof (grub_uint16_t));
if (!font->bmp_idx)
- {
- grub_free (font->char_index);
- return 1;
- }
+ return 1;
grub_memset (font->bmp_idx, 0xff, 0x10000 * sizeof (grub_uint16_t));
#endif
/* Allocate the font object. */
- font = (grub_font_t) grub_malloc (sizeof (struct grub_font));
+ font = (grub_font_t) grub_zalloc (sizeof (struct grub_font));
if (!font)
goto fail;
return 0;
fail:
+ if (file)
+ grub_file_close (file);
+ if (font)
+ font->file = 0;
+
free_font (font);
return 1;
}
grub_free (font->name);
grub_free (font->family);
grub_free (font->char_index);
+ grub_free (font->bmp_idx);
grub_free (font);
}
}
while (argc--)
if (grub_font_load (*args++) != 0)
- return GRUB_ERR_BAD_FONT;
+ {
+ if (!grub_errno)
+ return grub_error (GRUB_ERR_BAD_FONT, "invalid font");
+ return grub_errno;
+ }
return GRUB_ERR_NONE;
}
#include <grub/types.h>
#include <grub/fshelp.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
/* The affs bootblock. */
struct grub_affs_bblock
{
grub_uint32_t hashtable[1];
} __attribute__ ((packed));
+struct grub_affs_time
+{
+ grub_int32_t day;
+ grub_uint32_t min;
+ grub_uint32_t hz;
+} __attribute__ ((packed));
+
/* The second part of a file header block. */
struct grub_affs_file
{
grub_uint8_t unused1[12];
grub_uint32_t size;
- grub_uint8_t unused2[104];
+ grub_uint8_t unused2[92];
+ struct grub_affs_time mtime;
grub_uint8_t namelen;
grub_uint8_t name[30];
grub_uint8_t unused3[33];
struct grub_fshelp_node
{
struct grub_affs_data *data;
- int block;
- int size;
- int parent;
+ grub_disk_addr_t block;
+ struct grub_fshelp_node *parent;
+ struct grub_affs_file di;
};
/* Information about a "mounted" affs filesystem. */
int block = node->block;
struct grub_affs_file file;
struct grub_affs_data *data = node->data;
- grub_uint32_t mod;
+ grub_uint64_t mod;
/* Find the block that points to the fileblock we are looking up by
following the chain until the right table is reached. */
grub_affs_read_file (grub_fshelp_node_t node,
void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
unsigned offset, unsigned length),
- int pos, grub_size_t len, char *buf)
+ grub_off_t pos, grub_size_t len, char *buf)
{
return grub_fshelp_read_file (node->data->disk, node, read_hook,
pos, len, buf, grub_affs_read_block,
- node->size, 0);
+ grub_be_to_cpu32 (node->di.size), 0);
}
struct grub_affs_rblock *rblock;
int checksum = 0;
- int checksumr = 0;
int blocksize = 0;
data = grub_malloc (sizeof (struct grub_affs_data));
/* The filesystem blocksize is not stored anywhere in the filesystem
itself. One way to determine it is reading blocks for the
rootblock until the checksum is correct. */
- checksumr = grub_be_to_cpu32 (rblock->checksum);
- rblock->checksum = 0;
for (blocksize = 0; blocksize < 8; blocksize++)
{
grub_uint32_t *currblock = rootblock + GRUB_DISK_SECTOR_SIZE * blocksize;
for (i = 0; i < GRUB_DISK_SECTOR_SIZE / sizeof (*currblock); i++)
checksum += grub_be_to_cpu32 (currblock[i]);
- if (checksumr == -checksum)
+ if (checksum == 0)
break;
}
- if (-checksum != checksumr)
+ if (checksum != 0)
{
grub_error (GRUB_ERR_BAD_FS, "AFFS blocksize couldn't be determined");
goto fail;
data->htsize = grub_be_to_cpu32 (rblock->htsize);
data->diropen.data = data;
data->diropen.block = grub_be_to_cpu32 (data->bblock.rootblock);
+ data->diropen.parent = NULL;
+ grub_memcpy (&data->diropen.di, rootblock, sizeof (data->diropen.di));
grub_free (rootblock);
struct grub_affs_data *data = dir->data;
grub_uint32_t *hashtable;
- auto int NESTED_FUNC_ATTR grub_affs_create_node (const char *name, int block,
- int size, int type);
+ auto int NESTED_FUNC_ATTR grub_affs_create_node (const char *name,
+ grub_disk_addr_t block,
+ const struct grub_affs_file *fil);
- int NESTED_FUNC_ATTR grub_affs_create_node (const char *name, int block,
- int size, int type)
+ int NESTED_FUNC_ATTR grub_affs_create_node (const char *name,
+ grub_disk_addr_t block,
+ const struct grub_affs_file *fil)
{
+ int type;
node = grub_malloc (sizeof (*node));
if (!node)
{
return 1;
}
+ if ((int) grub_be_to_cpu32 (fil->type) == GRUB_AFFS_FILETYPE_DIR)
+ type = GRUB_FSHELP_REG;
+ else if (grub_be_to_cpu32 (fil->type) == GRUB_AFFS_FILETYPE_REG)
+ type = GRUB_FSHELP_DIR;
+ else if (grub_be_to_cpu32 (fil->type) == GRUB_AFFS_FILETYPE_SYMLINK)
+ type = GRUB_FSHELP_SYMLINK;
+ else
+ type = GRUB_FSHELP_UNKNOWN;
+
node->data = data;
- node->size = size;
node->block = block;
- node->parent = grub_be_to_cpu32 (file.parent);
+ node->di = *fil;
+ node->parent = dir;
if (hook (name, type, node))
{
return 0;
}
+ /* Create the directory entries for `.' and `..'. */
+ node = grub_malloc (sizeof (*node));
+ if (!node)
+ return 1;
+
+ *node = *dir;
+ if (hook (".", GRUB_FSHELP_DIR, node))
+ return 1;
+ if (dir->parent)
+ {
+ node = grub_malloc (sizeof (*node));
+ if (!node)
+ return 1;
+ *node = *dir->parent;
+ if (hook ("..", GRUB_FSHELP_DIR, node))
+ return 1;
+ }
+
hashtable = grub_malloc (data->htsize * sizeof (*hashtable));
if (!hashtable)
return 1;
if (grub_errno)
goto fail;
- /* Create the directory entries for `.' and `..'. */
- if (grub_affs_create_node (".", dir->block, dir->size, GRUB_FSHELP_DIR))
- return 1;
- if (grub_affs_create_node ("..", dir->parent ? dir->parent : dir->block,
- dir->size, GRUB_FSHELP_DIR))
- return 1;
-
for (i = 0; i < data->htsize; i++)
{
- enum grub_fshelp_filetype type;
grub_uint64_t next;
if (!hashtable[i])
file.name[file.namelen] = '\0';
- if ((int) grub_be_to_cpu32 (file.type) == GRUB_AFFS_FILETYPE_DIR)
- type = GRUB_FSHELP_REG;
- else if (grub_be_to_cpu32 (file.type) == GRUB_AFFS_FILETYPE_REG)
- type = GRUB_FSHELP_DIR;
- else if (grub_be_to_cpu32 (file.type) == GRUB_AFFS_FILETYPE_SYMLINK)
- type = GRUB_FSHELP_SYMLINK;
- else
- type = GRUB_FSHELP_UNKNOWN;
-
- if (grub_affs_create_node ((char *) (file.name), next,
- grub_be_to_cpu32 (file.size), type))
+ if (grub_affs_create_node ((char *) (file.name), next, &file))
return 1;
next = grub_be_to_cpu32 (file.next);
if (grub_errno)
goto fail;
- file->size = fdiro->size;
+ file->size = grub_be_to_cpu32 (fdiro->di.size);
data->diropen = *fdiro;
grub_free (fdiro);
struct grub_dirhook_info info;
grub_memset (&info, 0, sizeof (info));
info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
+ info.mtimeset = 1;
+ info.mtime = grub_be_to_cpu32 (node->di.mtime.day) * 86400
+ + grub_be_to_cpu32 (node->di.mtime.min) * 60
+ + grub_be_to_cpu32 (node->di.mtime.hz) / 50
+ + 8 * 365 * 86400 + 86400 * 2;
grub_free (node);
return hook (filename, &info);
}
#include <grub/types.h>
#include <grub/fshelp.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
#ifdef MODE_BIGENDIAN
#define GRUB_AFS_FSNAME_SUFFIX "_be"
#else
grub_afs_read_file (grub_fshelp_node_t node,
void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
unsigned offset, unsigned length),
- int pos, grub_size_t len, char *buf)
+ grub_off_t pos, grub_size_t len, char *buf)
{
return grub_fshelp_read_file (node->data->disk, node, read_hook,
pos, len, buf, grub_afs_read_block,
#include <grub/disk.h>
#include <grub/dl.h>
#include <grub/types.h>
+#include <grub/lib/crc.h>
+#include <grub/deflate.h>
+#include <minilzo.h>
-#define BTRFS_SIGNATURE "_BHRfS_M"
+GRUB_MOD_LICENSE ("GPLv3+");
-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];
+#define GRUB_BTRFS_SIGNATURE "_BHRfS_M"
+
+/* From http://www.oberhumer.com/opensource/lzo/lzofaq.php
+ * LZO will expand incompressible data by a little amount. I still haven't
+ * computed the exact values, but I suggest using these formulas for
+ * a worst-case expansion calculation:
+ *
+ * output_block_size = input_block_size + (input_block_size / 16) + 64 + 3
+ * */
+#define GRUB_BTRFS_LZO_BLOCK_SIZE 4096
+#define GRUB_BTRFS_LZO_BLOCK_MAX_CSIZE (GRUB_BTRFS_LZO_BLOCK_SIZE + \
+ (GRUB_BTRFS_LZO_BLOCK_SIZE / 16) + 64 + 3)
+
+typedef grub_uint8_t grub_btrfs_checksum_t[0x20];
+typedef grub_uint16_t grub_btrfs_uuid_t[8];
+
+struct grub_btrfs_device
+{
+ grub_uint64_t device_id;
+ grub_uint8_t dummy[0x62 - 8];
+} __attribute__ ((packed));
+
+struct grub_btrfs_superblock
+{
+ grub_btrfs_checksum_t checksum;
+ grub_btrfs_uuid_t uuid;
+ grub_uint8_t dummy[0x10];
+ grub_uint8_t signature[sizeof (GRUB_BTRFS_SIGNATURE) - 1];
+ grub_uint64_t generation;
+ grub_uint64_t root_tree;
+ grub_uint64_t chunk_tree;
+ grub_uint8_t dummy2[0x20];
+ grub_uint64_t root_dir_objectid;
+ grub_uint8_t dummy3[0x41];
+ struct grub_btrfs_device this_device;
+ char label[0x100];
+ grub_uint8_t dummy4[0x100];
+ grub_uint8_t bootstrap_mapping[0x800];
+} __attribute__ ((packed));
+
+struct btrfs_header
+{
+ grub_btrfs_checksum_t checksum;
+ grub_btrfs_uuid_t uuid;
+ grub_uint8_t dummy[0x30];
+ grub_uint32_t nitems;
+ grub_uint8_t level;
} __attribute__ ((packed));
+struct grub_btrfs_device_desc
+{
+ grub_device_t dev;
+ grub_uint64_t id;
+};
+
struct grub_btrfs_data
{
- struct btrfs_superblock sblock;
+ struct grub_btrfs_superblock sblock;
+ grub_uint64_t tree;
+ grub_uint64_t inode;
+
+ struct grub_btrfs_device_desc *devices_attached;
+ unsigned n_devices_attached;
+ unsigned n_devices_allocated;
+
+ /* Cached extent data. */
+ grub_uint64_t extstart;
+ grub_uint64_t extend;
+ grub_uint64_t extino;
+ grub_uint64_t exttree;
+ grub_size_t extsize;
+ struct grub_btrfs_extent_data *extent;
};
+struct grub_btrfs_key
+{
+ grub_uint64_t object_id;
+#define GRUB_BTRFS_ITEM_TYPE_INODE_ITEM 0x01
+#define GRUB_BTRFS_ITEM_TYPE_DIR_ITEM 0x54
+#define GRUB_BTRFS_ITEM_TYPE_EXTENT_ITEM 0x6c
+#define GRUB_BTRFS_ITEM_TYPE_ROOT_ITEM 0x84
+#define GRUB_BTRFS_ITEM_TYPE_DEVICE 0xd8
+#define GRUB_BTRFS_ITEM_TYPE_CHUNK 0xe4
+ grub_uint8_t type;
+ grub_uint64_t offset;
+} __attribute__ ((packed));
+
+struct grub_btrfs_chunk_item
+{
+ grub_uint64_t size;
+ grub_uint64_t dummy;
+ grub_uint64_t stripe_length;
+ grub_uint64_t type;
+#define GRUB_BTRFS_CHUNK_TYPE_BITS_DONTCARE 0x07
+#define GRUB_BTRFS_CHUNK_TYPE_SINGLE 0x00
+#define GRUB_BTRFS_CHUNK_TYPE_RAID0 0x08
+#define GRUB_BTRFS_CHUNK_TYPE_RAID1 0x10
+#define GRUB_BTRFS_CHUNK_TYPE_DUPLICATED 0x20
+#define GRUB_BTRFS_CHUNK_TYPE_RAID10 0x40
+ grub_uint8_t dummy2[0xc];
+ grub_uint16_t nstripes;
+ grub_uint16_t nsubstripes;
+} __attribute__ ((packed));
+
+struct grub_btrfs_chunk_stripe
+{
+ grub_uint64_t device_id;
+ grub_uint64_t offset;
+ grub_btrfs_uuid_t device_uuid;
+} __attribute__ ((packed));
+
+struct grub_btrfs_leaf_node
+{
+ struct grub_btrfs_key key;
+ grub_uint32_t offset;
+ grub_uint32_t size;
+} __attribute__ ((packed));
+
+struct grub_btrfs_internal_node
+{
+ struct grub_btrfs_key key;
+ grub_uint64_t addr;
+ grub_uint64_t dummy;
+} __attribute__ ((packed));
+
+struct grub_btrfs_dir_item
+{
+ struct grub_btrfs_key key;
+ grub_uint8_t dummy[8];
+ grub_uint16_t m;
+ grub_uint16_t n;
+#define GRUB_BTRFS_DIR_ITEM_TYPE_REGULAR 1
+#define GRUB_BTRFS_DIR_ITEM_TYPE_DIRECTORY 2
+#define GRUB_BTRFS_DIR_ITEM_TYPE_SYMLINK 7
+ grub_uint8_t type;
+ char name[0];
+} __attribute__ ((packed));
+
+struct grub_btrfs_leaf_descriptor
+{
+ unsigned depth;
+ unsigned allocated;
+ struct
+ {
+ grub_disk_addr_t addr;
+ unsigned iter;
+ unsigned maxiter;
+ int leaf;
+ } *data;
+};
+
+struct grub_btrfs_root_item
+{
+ grub_uint8_t dummy[0xb0];
+ grub_uint64_t tree;
+ grub_uint64_t inode;
+};
+
+struct grub_btrfs_time
+{
+ grub_int64_t sec;
+ grub_uint32_t nanosec;
+} __attribute__ ((aligned (4)));
+
+struct grub_btrfs_inode
+{
+ grub_uint8_t dummy1[0x10];
+ grub_uint64_t size;
+ grub_uint8_t dummy2[0x70];
+ struct grub_btrfs_time mtime;
+} __attribute__ ((packed));
+
+struct grub_btrfs_extent_data
+{
+ grub_uint64_t dummy;
+ grub_uint64_t size;
+ grub_uint8_t compression;
+ grub_uint8_t encryption;
+ grub_uint16_t encoding;
+ grub_uint8_t type;
+ union
+ {
+ char inl[0];
+ struct
+ {
+ grub_uint64_t laddr;
+ grub_uint64_t compressed_size;
+ grub_uint64_t offset;
+ grub_uint64_t filled;
+ };
+ };
+} __attribute__ ((packed));
+
+#define GRUB_BTRFS_EXTENT_INLINE 0
+#define GRUB_BTRFS_EXTENT_REGULAR 1
+
+#define GRUB_BTRFS_COMPRESSION_NONE 0
+#define GRUB_BTRFS_COMPRESSION_ZLIB 1
+#define GRUB_BTRFS_COMPRESSION_LZO 2
+
+#define GRUB_BTRFS_OBJECT_ID_CHUNK 0x100
+
+static grub_disk_addr_t superblock_sectors[] = { 64 * 2, 64 * 1024 * 2,
+ 256 * 1048576 * 2, 1048576ULL * 1048576ULL * 2
+};
+
+static grub_err_t
+grub_btrfs_read_logical (struct grub_btrfs_data *data,
+ grub_disk_addr_t addr, void *buf, grub_size_t size);
+
+static grub_err_t
+read_sblock (grub_disk_t disk, struct grub_btrfs_superblock *sb)
+{
+ unsigned i;
+ grub_err_t err = GRUB_ERR_NONE;
+ for (i = 0; i < ARRAY_SIZE (superblock_sectors); i++)
+ {
+ struct grub_btrfs_superblock sblock;
+ err = grub_disk_read (disk, superblock_sectors[i], 0,
+ sizeof (sblock), &sblock);
+ if (err == GRUB_ERR_OUT_OF_RANGE)
+ break;
+
+ if (grub_memcmp ((char *) sblock.signature, GRUB_BTRFS_SIGNATURE,
+ sizeof (GRUB_BTRFS_SIGNATURE) - 1) != 0)
+ break;
+ if (i == 0 || grub_le_to_cpu64 (sblock.generation)
+ > grub_le_to_cpu64 (sb->generation))
+ grub_memcpy (sb, &sblock, sizeof (sblock));
+ }
+
+ if ((err == GRUB_ERR_OUT_OF_RANGE || !err) && i == 0)
+ return grub_error (GRUB_ERR_BAD_FS, "not a Btrfs filesystem");
+
+ if (err == GRUB_ERR_OUT_OF_RANGE)
+ grub_errno = err = GRUB_ERR_NONE;
+
+ return err;
+}
+
+static int
+key_cmp (const struct grub_btrfs_key *a, const struct grub_btrfs_key *b)
+{
+ if (grub_cpu_to_le64 (a->object_id) < grub_cpu_to_le64 (b->object_id))
+ return -1;
+ if (grub_cpu_to_le64 (a->object_id) > grub_cpu_to_le64 (b->object_id))
+ return +1;
+
+ if (a->type < b->type)
+ return -1;
+ if (a->type > b->type)
+ return +1;
+
+ if (grub_cpu_to_le64 (a->offset) < grub_cpu_to_le64 (b->offset))
+ return -1;
+ if (grub_cpu_to_le64 (a->offset) > grub_cpu_to_le64 (b->offset))
+ return +1;
+ return 0;
+}
+
+static void
+free_iterator (struct grub_btrfs_leaf_descriptor *desc)
+{
+ grub_free (desc->data);
+}
+
+static grub_err_t
+save_ref (struct grub_btrfs_leaf_descriptor *desc,
+ grub_disk_addr_t addr, unsigned i, unsigned m, int l)
+{
+ desc->depth++;
+ if (desc->allocated < desc->depth)
+ {
+ void *newdata;
+ desc->allocated *= 2;
+ newdata = grub_realloc (desc->data, sizeof (desc->data[0])
+ * desc->allocated);
+ if (!newdata)
+ return grub_errno;
+ desc->data = newdata;
+ }
+ desc->data[desc->depth - 1].addr = addr;
+ desc->data[desc->depth - 1].iter = i;
+ desc->data[desc->depth - 1].maxiter = m;
+ desc->data[desc->depth - 1].leaf = l;
+ return GRUB_ERR_NONE;
+}
+
+static int
+next (struct grub_btrfs_data *data,
+ struct grub_btrfs_leaf_descriptor *desc,
+ grub_disk_addr_t * outaddr, grub_size_t * outsize,
+ struct grub_btrfs_key *key_out)
+{
+ grub_err_t err;
+ struct grub_btrfs_leaf_node leaf;
+
+ for (; desc->depth > 0; desc->depth--)
+ {
+ desc->data[desc->depth - 1].iter++;
+ if (desc->data[desc->depth - 1].iter
+ < desc->data[desc->depth - 1].maxiter)
+ break;
+ }
+ if (desc->depth == 0)
+ return 0;
+ while (!desc->data[desc->depth - 1].leaf)
+ {
+ struct grub_btrfs_internal_node node;
+ struct btrfs_header head;
+
+ err = grub_btrfs_read_logical (data, desc->data[desc->depth - 1].iter
+ * sizeof (node)
+ + sizeof (struct btrfs_header)
+ + desc->data[desc->depth - 1].addr,
+ &node, sizeof (node));
+ if (err)
+ return -err;
+
+ err = grub_btrfs_read_logical (data, grub_le_to_cpu64 (node.addr),
+ &head, sizeof (head));
+ if (err)
+ return -err;
+
+ save_ref (desc, grub_le_to_cpu64 (node.addr), 0,
+ grub_le_to_cpu32 (head.nitems), !head.level);
+ }
+ err = grub_btrfs_read_logical (data, desc->data[desc->depth - 1].iter
+ * sizeof (leaf)
+ + sizeof (struct btrfs_header)
+ + desc->data[desc->depth - 1].addr, &leaf,
+ sizeof (leaf));
+ if (err)
+ return -err;
+ *outsize = grub_le_to_cpu32 (leaf.size);
+ *outaddr = desc->data[desc->depth - 1].addr + sizeof (struct btrfs_header)
+ + grub_le_to_cpu32 (leaf.offset);
+ *key_out = leaf.key;
+ return 1;
+}
+
+static grub_err_t
+lower_bound (struct grub_btrfs_data *data,
+ const struct grub_btrfs_key *key_in,
+ struct grub_btrfs_key *key_out,
+ grub_disk_addr_t root,
+ grub_disk_addr_t *outaddr, grub_size_t *outsize,
+ struct grub_btrfs_leaf_descriptor *desc)
+{
+ grub_disk_addr_t addr = root;
+ int depth = -1;
+
+ if (desc)
+ {
+ desc->allocated = 16;
+ desc->depth = 0;
+ desc->data = grub_malloc (sizeof (desc->data[0]) * desc->allocated);
+ if (!desc->data)
+ return grub_errno;
+ }
+
+ grub_dprintf ("btrfs",
+ "retrieving %" PRIxGRUB_UINT64_T
+ " %x %" PRIxGRUB_UINT64_T "\n",
+ key_in->object_id, key_in->type, key_in->offset);
+
+ while (1)
+ {
+ grub_err_t err;
+ struct btrfs_header head;
+
+ reiter:
+ depth++;
+ /* FIXME: preread few nodes into buffer. */
+ err = grub_btrfs_read_logical (data, addr, &head, sizeof (head));
+ if (err)
+ return err;
+ addr += sizeof (head);
+ if (head.level)
+ {
+ unsigned i;
+ struct grub_btrfs_internal_node node, node_last;
+ int have_last = 0;
+ grub_memset (&node_last, 0, sizeof (node_last));
+ for (i = 0; i < grub_le_to_cpu32 (head.nitems); i++)
+ {
+ err = grub_btrfs_read_logical (data, addr + i * sizeof (node),
+ &node, sizeof (node));
+ if (err)
+ return err;
+
+ grub_dprintf ("btrfs",
+ "internal node (depth %d) %" PRIxGRUB_UINT64_T
+ " %x %" PRIxGRUB_UINT64_T "\n", depth,
+ node.key.object_id, node.key.type,
+ node.key.offset);
+
+ if (key_cmp (&node.key, key_in) == 0)
+ {
+ err = GRUB_ERR_NONE;
+ if (desc)
+ err = save_ref (desc, addr - sizeof (head), i,
+ grub_le_to_cpu32 (head.nitems), 0);
+ if (err)
+ return err;
+ addr = grub_le_to_cpu64 (node.addr);
+ goto reiter;
+ }
+ if (key_cmp (&node.key, key_in) > 0)
+ break;
+ node_last = node;
+ have_last = 1;
+ }
+ if (have_last)
+ {
+ err = GRUB_ERR_NONE;
+ if (desc)
+ err = save_ref (desc, addr - sizeof (head), i - 1,
+ grub_le_to_cpu32 (head.nitems), 0);
+ if (err)
+ return err;
+ addr = grub_le_to_cpu64 (node_last.addr);
+ goto reiter;
+ }
+ *outsize = 0;
+ *outaddr = 0;
+ grub_memset (key_out, 0, sizeof (*key_out));
+ if (desc)
+ return save_ref (desc, addr - sizeof (head), -1,
+ grub_le_to_cpu32 (head.nitems), 0);
+ return GRUB_ERR_NONE;
+ }
+ {
+ unsigned i;
+ struct grub_btrfs_leaf_node leaf, leaf_last;
+ int have_last = 0;
+ for (i = 0; i < grub_le_to_cpu32 (head.nitems); i++)
+ {
+ err = grub_btrfs_read_logical (data, addr + i * sizeof (leaf),
+ &leaf, sizeof (leaf));
+ if (err)
+ return err;
+
+ grub_dprintf ("btrfs",
+ "leaf (depth %d) %" PRIxGRUB_UINT64_T
+ " %x %" PRIxGRUB_UINT64_T "\n", depth,
+ leaf.key.object_id, leaf.key.type, leaf.key.offset);
+
+ if (key_cmp (&leaf.key, key_in) == 0)
+ {
+ grub_memcpy (key_out, &leaf.key, sizeof (*key_out));
+ *outsize = grub_le_to_cpu32 (leaf.size);
+ *outaddr = addr + grub_le_to_cpu32 (leaf.offset);
+ if (desc)
+ return save_ref (desc, addr - sizeof (head), i,
+ grub_le_to_cpu32 (head.nitems), 1);
+ return GRUB_ERR_NONE;
+ }
+
+ if (key_cmp (&leaf.key, key_in) > 0)
+ break;
+
+ have_last = 1;
+ leaf_last = leaf;
+ }
+
+ if (have_last)
+ {
+ grub_memcpy (key_out, &leaf_last.key, sizeof (*key_out));
+ *outsize = grub_le_to_cpu32 (leaf_last.size);
+ *outaddr = addr + grub_le_to_cpu32 (leaf_last.offset);
+ if (desc)
+ return save_ref (desc, addr - sizeof (head), i - 1,
+ grub_le_to_cpu32 (head.nitems), 1);
+ return GRUB_ERR_NONE;
+ }
+ *outsize = 0;
+ *outaddr = 0;
+ grub_memset (key_out, 0, sizeof (*key_out));
+ if (desc)
+ return save_ref (desc, addr - sizeof (head), -1,
+ grub_le_to_cpu32 (head.nitems), 1);
+ return GRUB_ERR_NONE;
+ }
+ }
+}
+
+static grub_device_t
+find_device (struct grub_btrfs_data *data, grub_uint64_t id, int do_rescan)
+{
+ grub_device_t dev_found = NULL;
+ auto int hook (const char *name);
+ int hook (const char *name)
+ {
+ grub_device_t dev;
+ grub_err_t err;
+ struct grub_btrfs_superblock sb;
+ dev = grub_device_open (name);
+ if (!dev)
+ return 0;
+ if (!dev->disk)
+ {
+ grub_device_close (dev);
+ return 0;
+ }
+ err = read_sblock (dev->disk, &sb);
+ if (err == GRUB_ERR_BAD_FS)
+ {
+ grub_device_close (dev);
+ grub_errno = GRUB_ERR_NONE;
+ return 0;
+ }
+ if (err)
+ {
+ grub_device_close (dev);
+ grub_print_error ();
+ return 0;
+ }
+ if (grub_memcmp (data->sblock.uuid, sb.uuid, sizeof (sb.uuid)) != 0
+ || sb.this_device.device_id != id)
+ {
+ grub_device_close (dev);
+ return 0;
+ }
+
+ dev_found = dev;
+ return 1;
+ }
+
+ unsigned i;
+
+ for (i = 0; i < data->n_devices_attached; i++)
+ if (id == data->devices_attached[i].id)
+ return data->devices_attached[i].dev;
+ if (do_rescan)
+ grub_device_iterate (hook);
+ if (!dev_found)
+ {
+ grub_error (GRUB_ERR_BAD_FS, "couldn't find a member device");
+ return NULL;
+ }
+ data->n_devices_attached++;
+ if (data->n_devices_attached > data->n_devices_allocated)
+ {
+ void *tmp;
+ data->n_devices_allocated = 2 * data->n_devices_attached + 1;
+ data->devices_attached
+ = grub_realloc (tmp = data->devices_attached,
+ data->n_devices_allocated
+ * sizeof (data->devices_attached[0]));
+ if (!data->devices_attached)
+ {
+ grub_device_close (dev_found);
+ data->devices_attached = tmp;
+ return NULL;
+ }
+ }
+ data->devices_attached[data->n_devices_attached - 1].id = id;
+ data->devices_attached[data->n_devices_attached - 1].dev = dev_found;
+ return dev_found;
+}
+
+static grub_err_t
+grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr,
+ void *buf, grub_size_t size)
+{
+ while (size > 0)
+ {
+ grub_uint8_t *ptr;
+ struct grub_btrfs_key *key;
+ struct grub_btrfs_chunk_item *chunk;
+ grub_uint64_t csize;
+ grub_err_t err = 0;
+ struct grub_btrfs_key key_out;
+ int challoc = 0;
+ grub_device_t dev;
+ struct grub_btrfs_key key_in;
+ grub_size_t chsize;
+ grub_disk_addr_t chaddr;
+
+ grub_dprintf ("btrfs", "searching for laddr %" PRIxGRUB_UINT64_T "\n",
+ addr);
+ for (ptr = data->sblock.bootstrap_mapping;
+ ptr < data->sblock.bootstrap_mapping
+ + sizeof (data->sblock.bootstrap_mapping)
+ - sizeof (struct grub_btrfs_key);)
+ {
+ key = (struct grub_btrfs_key *) ptr;
+ if (key->type != GRUB_BTRFS_ITEM_TYPE_CHUNK)
+ break;
+ chunk = (struct grub_btrfs_chunk_item *) (key + 1);
+ grub_dprintf ("btrfs",
+ "%" PRIxGRUB_UINT64_T " %" PRIxGRUB_UINT64_T " \n",
+ grub_le_to_cpu64 (key->offset),
+ grub_le_to_cpu64 (chunk->size));
+ if (grub_le_to_cpu64 (key->offset) <= addr
+ && addr < grub_le_to_cpu64 (key->offset)
+ + grub_le_to_cpu64 (chunk->size))
+ goto chunk_found;
+ ptr += sizeof (*key) + sizeof (*chunk)
+ + sizeof (struct grub_btrfs_chunk_stripe)
+ * grub_le_to_cpu16 (chunk->nstripes);
+ }
+
+ key_in.object_id = GRUB_BTRFS_OBJECT_ID_CHUNK;
+ key_in.type = GRUB_BTRFS_ITEM_TYPE_CHUNK;
+ key_in.offset = addr;
+ err = lower_bound (data, &key_in, &key_out,
+ grub_le_to_cpu64 (data->sblock.chunk_tree),
+ &chaddr, &chsize, NULL);
+ if (err)
+ return err;
+ key = &key_out;
+ if (key->type != GRUB_BTRFS_ITEM_TYPE_CHUNK
+ || !(grub_le_to_cpu64 (key->offset) <= addr))
+ return grub_error (GRUB_ERR_BAD_FS,
+ "couldn't find the chunk descriptor");
+
+ chunk = grub_malloc (chsize);
+ if (!chunk)
+ return grub_errno;
+
+ challoc = 1;
+ err = grub_btrfs_read_logical (data, chaddr, chunk, chsize);
+ if (err)
+ {
+ grub_free (chunk);
+ return err;
+ }
+
+ chunk_found:
+ {
+ grub_uint64_t stripen;
+ grub_uint64_t stripe_offset;
+ grub_uint64_t off = addr - grub_le_to_cpu64 (key->offset);
+ unsigned redundancy = 1;
+ unsigned i, j;
+
+ if (grub_le_to_cpu64 (chunk->size) <= off)
+ {
+ grub_dprintf ("btrfs", "no chunk\n");
+ return grub_error (GRUB_ERR_BAD_FS,
+ "couldn't find the chunk descriptor");
+ }
+
+ grub_dprintf ("btrfs", "chunk 0x%" PRIxGRUB_UINT64_T
+ "+0x%" PRIxGRUB_UINT64_T
+ " (%d stripes (%d substripes) of %"
+ PRIxGRUB_UINT64_T ")\n",
+ grub_le_to_cpu64 (key->offset),
+ grub_le_to_cpu64 (chunk->size),
+ grub_le_to_cpu16 (chunk->nstripes),
+ grub_le_to_cpu16 (chunk->nsubstripes),
+ grub_le_to_cpu64 (chunk->stripe_length));
+
+ switch (grub_le_to_cpu64 (chunk->type)
+ & ~GRUB_BTRFS_CHUNK_TYPE_BITS_DONTCARE)
+ {
+ case GRUB_BTRFS_CHUNK_TYPE_SINGLE:
+ {
+ grub_uint64_t stripe_length;
+ grub_dprintf ("btrfs", "single\n");
+ stripe_length = grub_divmod64 (grub_le_to_cpu64 (chunk->size),
+ grub_le_to_cpu16 (chunk->nstripes),
+ NULL);
+ stripen = grub_divmod64 (off, stripe_length, &stripe_offset);
+ csize = (stripen + 1) * stripe_length - off;
+ break;
+ }
+ case GRUB_BTRFS_CHUNK_TYPE_DUPLICATED:
+ case GRUB_BTRFS_CHUNK_TYPE_RAID1:
+ {
+ grub_dprintf ("btrfs", "RAID1\n");
+ stripen = 0;
+ stripe_offset = off;
+ csize = grub_le_to_cpu64 (chunk->size) - off;
+ redundancy = 2;
+ break;
+ }
+ case GRUB_BTRFS_CHUNK_TYPE_RAID0:
+ {
+ grub_uint64_t middle, high;
+ grub_uint64_t low;
+ grub_dprintf ("btrfs", "RAID0\n");
+ middle = grub_divmod64 (off,
+ grub_le_to_cpu64 (chunk->stripe_length),
+ &low);
+
+ high = grub_divmod64 (middle, grub_le_to_cpu16 (chunk->nstripes),
+ &stripen);
+ stripe_offset =
+ low + grub_le_to_cpu64 (chunk->stripe_length) * high;
+ csize = grub_le_to_cpu64 (chunk->stripe_length) - low;
+ break;
+ }
+ case GRUB_BTRFS_CHUNK_TYPE_RAID10:
+ {
+ grub_uint64_t middle, high;
+ grub_uint64_t low;
+ middle = grub_divmod64 (off,
+ grub_le_to_cpu64 (chunk->stripe_length),
+ &low);
+
+ high = grub_divmod64 (middle,
+ grub_le_to_cpu16 (chunk->nsubstripes),
+ &stripen);
+ stripen *= grub_le_to_cpu16 (chunk->nstripes)
+ / grub_le_to_cpu16 (chunk->nsubstripes);
+ redundancy = grub_le_to_cpu16 (chunk->nstripes)
+ / grub_le_to_cpu16 (chunk->nsubstripes);
+ stripe_offset = low + grub_le_to_cpu64 (chunk->stripe_length)
+ * high;
+ csize = grub_le_to_cpu64 (chunk->stripe_length) - low;
+ break;
+ }
+ default:
+ grub_dprintf ("btrfs", "unsupported RAID\n");
+ return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
+ "unsupported RAID flags %" PRIxGRUB_UINT64_T,
+ grub_le_to_cpu64 (chunk->type));
+ }
+ if (csize == 0)
+ return grub_error (GRUB_ERR_BUG,
+ "couldn't find the chunk descriptor");
+ if ((grub_size_t) csize > size)
+ csize = size;
+
+ for (j = 0; j < 2; j++)
+ {
+ for (i = 0; i < redundancy; i++)
+ {
+ struct grub_btrfs_chunk_stripe *stripe;
+ grub_disk_addr_t paddr;
+
+ stripe = (struct grub_btrfs_chunk_stripe *) (chunk + 1);
+ /* Right now the redundancy handling is easy.
+ With RAID5-like it will be more difficult. */
+ stripe += stripen + i;
+
+ paddr = stripe->offset + stripe_offset;
+
+ grub_dprintf ("btrfs", "chunk 0x%" PRIxGRUB_UINT64_T
+ "+0x%" PRIxGRUB_UINT64_T
+ " (%d stripes (%d substripes) of %"
+ PRIxGRUB_UINT64_T ") stripe %" PRIxGRUB_UINT64_T
+ " maps to 0x%" PRIxGRUB_UINT64_T "\n",
+ grub_le_to_cpu64 (key->offset),
+ grub_le_to_cpu64 (chunk->size),
+ grub_le_to_cpu16 (chunk->nstripes),
+ grub_le_to_cpu16 (chunk->nsubstripes),
+ grub_le_to_cpu64 (chunk->stripe_length),
+ stripen, stripe->offset);
+ grub_dprintf ("btrfs", "reading paddr 0x%" PRIxGRUB_UINT64_T
+ " for laddr 0x%" PRIxGRUB_UINT64_T "\n", paddr,
+ addr);
+
+ dev = find_device (data, stripe->device_id, j);
+ if (!dev)
+ {
+ err = grub_errno;
+ grub_errno = GRUB_ERR_NONE;
+ continue;
+ }
+
+ err = grub_disk_read (dev->disk, paddr >> GRUB_DISK_SECTOR_BITS,
+ paddr & (GRUB_DISK_SECTOR_SIZE - 1),
+ csize, buf);
+ if (!err)
+ break;
+ grub_errno = GRUB_ERR_NONE;
+ }
+ if (i != redundancy)
+ break;
+ }
+ if (err)
+ return grub_errno = err;
+ }
+ size -= csize;
+ buf = (grub_uint8_t *) buf + csize;
+ addr += csize;
+ if (challoc)
+ grub_free (chunk);
+ }
+ return GRUB_ERR_NONE;
+}
+
static struct grub_btrfs_data *
-grub_btrfs_mount (grub_disk_t disk)
+grub_btrfs_mount (grub_device_t dev)
{
- struct grub_btrfs_data *data = grub_malloc (sizeof (*data));
- if (! data)
+ struct grub_btrfs_data *data;
+ grub_err_t err;
+
+ if (!dev->disk)
+ {
+ grub_error (GRUB_ERR_BAD_FS, "not BtrFS");
+ return NULL;
+ }
+
+ data = grub_zalloc (sizeof (*data));
+ if (!data)
return NULL;
- if (grub_disk_read (disk, 128, 0, sizeof (data->sblock),
- &data->sblock) != GRUB_ERR_NONE)
- goto fail;
+ err = read_sblock (dev->disk, &data->sblock);
+ if (err)
+ {
+ grub_free (data);
+ return NULL;
+ }
- if (grub_memcmp ((char *) data->sblock.signature, BTRFS_SIGNATURE, sizeof (BTRFS_SIGNATURE) - 1))
+ data->n_devices_allocated = 16;
+ data->devices_attached = grub_malloc (sizeof (data->devices_attached[0])
+ * data->n_devices_allocated);
+ if (!data->devices_attached)
{
- grub_error (GRUB_ERR_BAD_FS, "not a Btrfs filesystem");
- goto fail;
+ grub_free (data);
+ return NULL;
}
+ data->n_devices_attached = 1;
+ data->devices_attached[0].dev = dev;
+ data->devices_attached[0].id = data->sblock.this_device.device_id;
return data;
+}
- fail:
- if (grub_errno == GRUB_ERR_OUT_OF_RANGE)
- grub_error (GRUB_ERR_BAD_FS, "not a Btrfs filesystem");
-
+static void
+grub_btrfs_unmount (struct grub_btrfs_data *data)
+{
+ unsigned i;
+ /* The device 0 is closed one layer upper. */
+ for (i = 1; i < data->n_devices_attached; i++)
+ grub_device_close (data->devices_attached[i].dev);
+ grub_free (data->devices_attached);
+ grub_free (data->extent);
grub_free (data);
- return NULL;
}
static grub_err_t
-grub_btrfs_open (struct grub_file *file __attribute__ ((unused)),
- const char *name __attribute__ ((unused)))
+grub_btrfs_read_inode (struct grub_btrfs_data *data,
+ struct grub_btrfs_inode *inode, grub_uint64_t num,
+ grub_uint64_t tree)
{
- return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "only detection is supported for Btrfs");
+ struct grub_btrfs_key key_in, key_out;
+ grub_disk_addr_t elemaddr;
+ grub_size_t elemsize;
+ grub_err_t err;
+
+ key_in.object_id = num;
+ key_in.type = GRUB_BTRFS_ITEM_TYPE_INODE_ITEM;
+ key_in.offset = 0;
+
+ err = lower_bound (data, &key_in, &key_out, tree, &elemaddr, &elemsize, NULL);
+ if (err)
+ return err;
+ if (num != key_out.object_id
+ || key_out.type != GRUB_BTRFS_ITEM_TYPE_INODE_ITEM)
+ return grub_error (GRUB_ERR_BAD_FS, "inode not found");
+
+ return grub_btrfs_read_logical (data, elemaddr, inode, sizeof (*inode));
+}
+
+static grub_ssize_t
+grub_btrfs_lzo_decompress(char *ibuf, grub_size_t isize, grub_off_t off,
+ char *obuf, grub_size_t osize)
+{
+ grub_uint32_t total_size, cblock_size, ret = 0;
+ unsigned char buf[GRUB_BTRFS_LZO_BLOCK_SIZE];
+
+ total_size = grub_le_to_cpu32 (grub_get_unaligned32 (ibuf));
+ ibuf += sizeof (total_size);
+
+ if (isize < total_size)
+ return -1;
+
+ /* Jump forward to first block with requested data. */
+ while (off >= GRUB_BTRFS_LZO_BLOCK_SIZE)
+ {
+ cblock_size = grub_le_to_cpu32 (grub_get_unaligned32 (ibuf));
+ ibuf += sizeof (cblock_size);
+
+ if (cblock_size > GRUB_BTRFS_LZO_BLOCK_MAX_CSIZE)
+ return -1;
+
+ off -= GRUB_BTRFS_LZO_BLOCK_SIZE;
+ ibuf += cblock_size;
+ }
+
+ while (osize > 0)
+ {
+ lzo_uint usize = GRUB_BTRFS_LZO_BLOCK_SIZE;
+
+ cblock_size = grub_le_to_cpu32 (grub_get_unaligned32 (ibuf));
+ ibuf += sizeof (cblock_size);
+
+ if (cblock_size > GRUB_BTRFS_LZO_BLOCK_MAX_CSIZE)
+ return -1;
+
+ /* Block partially filled with requested data. */
+ if (off > 0 || osize < GRUB_BTRFS_LZO_BLOCK_SIZE)
+ {
+ grub_size_t to_copy = grub_min(osize, GRUB_BTRFS_LZO_BLOCK_SIZE - off);
+
+ if (lzo1x_decompress_safe ((lzo_bytep)ibuf, cblock_size, buf, &usize,
+ NULL) != LZO_E_OK)
+ return -1;
+
+ to_copy = grub_min(to_copy, usize);
+ grub_memcpy(obuf, buf + off, to_copy);
+
+ osize -= to_copy;
+ ret += to_copy;
+ obuf += to_copy;
+ ibuf += cblock_size;
+ off = 0;
+ continue;
+ }
+
+ /* Decompress whole block directly to output buffer. */
+ if (lzo1x_decompress_safe ((lzo_bytep)ibuf, cblock_size, (lzo_bytep)obuf,
+ &usize, NULL) != LZO_E_OK)
+ return -1;
+
+ osize -= usize;
+ ret += usize;
+ obuf += usize;
+ ibuf += cblock_size;
+ }
+
+ return ret;
+}
+
+static grub_ssize_t
+grub_btrfs_extent_read (struct grub_btrfs_data *data,
+ grub_uint64_t ino, grub_uint64_t tree,
+ grub_off_t pos0, char *buf, grub_size_t len)
+{
+ grub_off_t pos = pos0;
+ while (len)
+ {
+ grub_size_t csize;
+ grub_err_t err;
+ grub_off_t extoff;
+ if (!data->extent || data->extstart > pos || data->extino != ino
+ || data->exttree != tree || data->extend <= pos)
+ {
+ struct grub_btrfs_key key_in, key_out;
+ grub_disk_addr_t elemaddr;
+ grub_size_t elemsize;
+
+ grub_free (data->extent);
+ key_in.object_id = ino;
+ key_in.type = GRUB_BTRFS_ITEM_TYPE_EXTENT_ITEM;
+ key_in.offset = grub_cpu_to_le64 (pos);
+ err = lower_bound (data, &key_in, &key_out, tree,
+ &elemaddr, &elemsize, NULL);
+ if (err)
+ return -1;
+ if (key_out.object_id != ino
+ || key_out.type != GRUB_BTRFS_ITEM_TYPE_EXTENT_ITEM)
+ {
+ grub_error (GRUB_ERR_BAD_FS, "extent not found");
+ return -1;
+ }
+ data->extstart = grub_le_to_cpu64 (key_out.offset);
+ data->extsize = elemsize;
+ data->extent = grub_malloc (elemsize);
+ data->extino = ino;
+ data->exttree = tree;
+ if (!data->extent)
+ return grub_errno;
+
+ err = grub_btrfs_read_logical (data, elemaddr, data->extent,
+ elemsize);
+ if (err)
+ return err;
+
+ data->extend = data->extstart + grub_le_to_cpu64 (data->extent->size);
+ if (data->extent->type == GRUB_BTRFS_EXTENT_REGULAR
+ && (char *) &data->extent + elemsize
+ >= (char *) &data->extent->filled + sizeof (data->extent->filled))
+ data->extend =
+ data->extstart + grub_le_to_cpu64 (data->extent->filled);
+
+ grub_dprintf ("btrfs", "extent 0x%" PRIxGRUB_UINT64_T "+0x%"
+ PRIxGRUB_UINT64_T " (0x%"
+ PRIxGRUB_UINT64_T ")\n",
+ grub_le_to_cpu64 (key_out.offset),
+ grub_le_to_cpu64 (data->extent->size),
+ grub_le_to_cpu64 (data->extent->filled));
+ if (data->extend <= pos)
+ {
+ grub_error (GRUB_ERR_BAD_FS, "extent not found");
+ return -1;
+ }
+ }
+ csize = data->extend - pos;
+ extoff = pos - data->extstart;
+ if (csize > len)
+ csize = len;
+
+ if (data->extent->encryption)
+ {
+ grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
+ "encryption not supported");
+ return -1;
+ }
+
+ if (data->extent->compression != GRUB_BTRFS_COMPRESSION_NONE
+ && data->extent->compression != GRUB_BTRFS_COMPRESSION_ZLIB
+ && data->extent->compression != GRUB_BTRFS_COMPRESSION_LZO)
+ {
+ grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
+ "compression type 0x%x not supported",
+ data->extent->compression);
+ return -1;
+ }
+
+ if (data->extent->encoding)
+ {
+ grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "encoding not supported");
+ return -1;
+ }
+
+ switch (data->extent->type)
+ {
+ case GRUB_BTRFS_EXTENT_INLINE:
+ if (data->extent->compression == GRUB_BTRFS_COMPRESSION_ZLIB)
+ {
+ if (grub_zlib_decompress (data->extent->inl, data->extsize -
+ ((grub_uint8_t *) data->extent->inl
+ - (grub_uint8_t *) data->extent),
+ extoff, buf, csize)
+ != (grub_ssize_t) csize)
+ return -1;
+ }
+ else if (data->extent->compression == GRUB_BTRFS_COMPRESSION_LZO)
+ {
+ if (grub_btrfs_lzo_decompress(data->extent->inl, data->extsize -
+ ((grub_uint8_t *) data->extent->inl
+ - (grub_uint8_t *) data->extent),
+ extoff, buf, csize)
+ != (grub_ssize_t) csize)
+ return -1;
+ }
+ else
+ grub_memcpy (buf, data->extent->inl + extoff, csize);
+ break;
+ case GRUB_BTRFS_EXTENT_REGULAR:
+ if (!data->extent->laddr)
+ {
+ grub_memset (buf, 0, csize);
+ break;
+ }
+
+ if (data->extent->compression != GRUB_BTRFS_COMPRESSION_NONE)
+ {
+ char *tmp;
+ grub_uint64_t zsize;
+ grub_ssize_t ret;
+
+ zsize = grub_le_to_cpu64 (data->extent->compressed_size);
+ tmp = grub_malloc (zsize);
+ if (!tmp)
+ return -1;
+ err = grub_btrfs_read_logical (data,
+ grub_le_to_cpu64 (data->extent->laddr),
+ tmp, zsize);
+ if (err)
+ {
+ grub_free (tmp);
+ return -1;
+ }
+
+ if (data->extent->compression == GRUB_BTRFS_COMPRESSION_ZLIB)
+ ret = grub_zlib_decompress (tmp, zsize, extoff
+ + grub_le_to_cpu64 (data->extent->offset),
+ buf, csize);
+ else if (data->extent->compression == GRUB_BTRFS_COMPRESSION_LZO)
+ ret = grub_btrfs_lzo_decompress (tmp, zsize, extoff
+ + grub_le_to_cpu64 (data->extent->offset),
+ buf, csize);
+ else
+ ret = -1;
+
+ grub_free (tmp);
+
+ if (ret != (grub_ssize_t) csize)
+ return -1;
+
+ break;
+ }
+ err = grub_btrfs_read_logical (data,
+ grub_le_to_cpu64 (data->extent->laddr)
+ + grub_le_to_cpu64 (data->extent->offset)
+ + extoff, buf, csize);
+ if (err)
+ return -1;
+ break;
+ default:
+ grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
+ "unsupported extent type 0x%x", data->extent->type);
+ return -1;
+ }
+ buf += csize;
+ pos += csize;
+ len -= csize;
+ }
+ return pos - pos0;
}
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)
+find_path (struct grub_btrfs_data *data,
+ const char *path, struct grub_btrfs_key *key,
+ grub_uint64_t *tree, grub_uint8_t *type)
+{
+ const char *slash = path;
+ grub_err_t err;
+ grub_disk_addr_t elemaddr;
+ grub_size_t elemsize;
+ grub_size_t allocated = 0;
+ struct grub_btrfs_dir_item *direl = NULL;
+ struct grub_btrfs_key key_out;
+ int skip_default;
+ const char *ctoken;
+ grub_size_t ctokenlen;
+ char *path_alloc = NULL;
+ char *origpath = NULL;
+ unsigned symlinks_max = 32;
+
+ *type = GRUB_BTRFS_DIR_ITEM_TYPE_DIRECTORY;
+ *tree = data->sblock.root_tree;
+ key->object_id = data->sblock.root_dir_objectid;
+ key->type = GRUB_BTRFS_ITEM_TYPE_DIR_ITEM;
+ key->offset = 0;
+ skip_default = 1;
+ origpath = grub_strdup (path);
+ if (!origpath)
return grub_errno;
- grub_free (data);
+ while (1)
+ {
+ if (!skip_default)
+ {
+ while (path[0] == '/')
+ path++;
+ if (!path[0])
+ break;
+ slash = grub_strchr (path, '/');
+ if (!slash)
+ slash = path + grub_strlen (path);
+ ctoken = path;
+ ctokenlen = slash - path;
+ }
+ else
+ {
+ ctoken = "default";
+ ctokenlen = sizeof ("default") - 1;
+ }
+
+ if (*type != GRUB_BTRFS_DIR_ITEM_TYPE_DIRECTORY)
+ {
+ grub_free (path_alloc);
+ grub_free (origpath);
+ return grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory");
+ }
+ key->type = GRUB_BTRFS_ITEM_TYPE_DIR_ITEM;
+ key->offset = grub_cpu_to_le64 (~grub_getcrc32c (1, ctoken, ctokenlen));
+
+ err = lower_bound (data, key, &key_out, *tree, &elemaddr, &elemsize,
+ NULL);
+ if (err)
+ {
+ grub_free (direl);
+ grub_free (path_alloc);
+ grub_free (origpath);
+ return err;
+ }
+ if (key_cmp (key, &key_out) != 0)
+ {
+ grub_free (direl);
+ grub_free (path_alloc);
+ err = grub_error (GRUB_ERR_FILE_NOT_FOUND, "file `%s' not found", origpath);
+ grub_free (origpath);
+ return err;
+ }
+
+ struct grub_btrfs_dir_item *cdirel;
+ if (elemsize > allocated)
+ {
+ allocated = 2 * elemsize;
+ grub_free (direl);
+ direl = grub_malloc (allocated + 1);
+ if (!direl)
+ {
+ grub_free (path_alloc);
+ grub_free (origpath);
+ return grub_errno;
+ }
+ }
+
+ err = grub_btrfs_read_logical (data, elemaddr, direl, elemsize);
+ if (err)
+ {
+ grub_free (direl);
+ grub_free (path_alloc);
+ grub_free (origpath);
+ return err;
+ }
+
+ for (cdirel = direl;
+ (grub_uint8_t *) cdirel - (grub_uint8_t *) direl
+ < (grub_ssize_t) elemsize;
+ cdirel = (void *) ((grub_uint8_t *) (direl + 1)
+ + grub_le_to_cpu16 (cdirel->n)
+ + grub_le_to_cpu16 (cdirel->m)))
+ {
+ if (ctokenlen == grub_le_to_cpu16 (cdirel->n)
+ && grub_memcmp (cdirel->name, ctoken, ctokenlen) == 0)
+ break;
+ }
+ if ((grub_uint8_t *) cdirel - (grub_uint8_t *) direl
+ >= (grub_ssize_t) elemsize)
+ {
+ grub_free (direl);
+ grub_free (path_alloc);
+ err = grub_error (GRUB_ERR_FILE_NOT_FOUND, "file `%s' not found", origpath);
+ grub_free (origpath);
+ return err;
+ }
+
+ if (!skip_default)
+ path = slash;
+ skip_default = 0;
+ if (cdirel->type == GRUB_BTRFS_DIR_ITEM_TYPE_SYMLINK)
+ {
+ struct grub_btrfs_inode inode;
+ char *tmp;
+ if (--symlinks_max == 0)
+ {
+ grub_free (direl);
+ grub_free (path_alloc);
+ grub_free (origpath);
+ return grub_error (GRUB_ERR_SYMLINK_LOOP,
+ "too deep nesting of symlinks");
+ }
+
+ err = grub_btrfs_read_inode (data, &inode,
+ cdirel->key.object_id, *tree);
+ if (err)
+ {
+ grub_free (direl);
+ grub_free (path_alloc);
+ grub_free (origpath);
+ return err;
+ }
+ tmp = grub_malloc (grub_le_to_cpu64 (inode.size)
+ + grub_strlen (path) + 1);
+ if (!tmp)
+ {
+ grub_free (direl);
+ grub_free (path_alloc);
+ grub_free (origpath);
+ return grub_errno;
+ }
+
+ if (grub_btrfs_extent_read (data, cdirel->key.object_id,
+ *tree, 0, tmp,
+ grub_le_to_cpu64 (inode.size))
+ != (grub_ssize_t) grub_le_to_cpu64 (inode.size))
+ {
+ grub_free (direl);
+ grub_free (path_alloc);
+ grub_free (origpath);
+ grub_free (tmp);
+ return grub_errno;
+ }
+ grub_memcpy (tmp + grub_le_to_cpu64 (inode.size), path,
+ grub_strlen (path) + 1);
+ grub_free (path_alloc);
+ grub_free (origpath);
+ path = path_alloc = tmp;
+ if (path[0] == '/')
+ {
+ *type = GRUB_BTRFS_DIR_ITEM_TYPE_DIRECTORY;
+ *tree = data->sblock.root_tree;
+ key->object_id = data->sblock.root_dir_objectid;
+ key->type = GRUB_BTRFS_ITEM_TYPE_DIR_ITEM;
+ key->offset = 0;
+ skip_default = 1;
+ }
+ continue;
+ }
+ *type = cdirel->type;
+
+ switch (cdirel->key.type)
+ {
+ case GRUB_BTRFS_ITEM_TYPE_ROOT_ITEM:
+ {
+ struct grub_btrfs_root_item ri;
+ err = lower_bound (data, &cdirel->key, &key_out,
+ data->sblock.root_tree,
+ &elemaddr, &elemsize, NULL);
+ if (err)
+ {
+ grub_free (direl);
+ grub_free (path_alloc);
+ grub_free (origpath);
+ return err;
+ }
+ if (cdirel->key.object_id != key_out.object_id
+ || cdirel->key.type != key_out.type)
+ {
+ grub_free (direl);
+ grub_free (path_alloc);
+ err = grub_error (GRUB_ERR_FILE_NOT_FOUND, "file `%s' not found", origpath);
+ grub_free (origpath);
+ return err;
+ }
+ err = grub_btrfs_read_logical (data, elemaddr, &ri, sizeof (ri));
+ if (err)
+ {
+ grub_free (direl);
+ grub_free (path_alloc);
+ grub_free (origpath);
+ return err;
+ }
+ key->type = GRUB_BTRFS_ITEM_TYPE_DIR_ITEM;
+ key->offset = 0;
+ key->object_id = GRUB_BTRFS_OBJECT_ID_CHUNK;
+ *tree = grub_le_to_cpu64 (ri.tree);
+ break;
+ }
+ case GRUB_BTRFS_ITEM_TYPE_INODE_ITEM:
+ if (*slash && *type == GRUB_BTRFS_DIR_ITEM_TYPE_REGULAR)
+ {
+ grub_free (direl);
+ grub_free (path_alloc);
+ err = grub_error (GRUB_ERR_FILE_NOT_FOUND, "file `%s' not found", origpath);
+ grub_free (origpath);
+ return err;
+ }
+ *key = cdirel->key;
+ if (*type == GRUB_BTRFS_DIR_ITEM_TYPE_DIRECTORY)
+ key->type = GRUB_BTRFS_ITEM_TYPE_DIR_ITEM;
+ break;
+ default:
+ grub_free (path_alloc);
+ grub_free (origpath);
+ grub_free (direl);
+ return grub_error (GRUB_ERR_BAD_FS, "unrecognised object type 0x%x",
+ cdirel->key.type);
+ }
+ }
+
+ grub_free (direl);
return GRUB_ERR_NONE;
}
+static grub_err_t
+grub_btrfs_dir (grub_device_t device, const char *path,
+ int (*hook) (const char *filename,
+ const struct grub_dirhook_info *info))
+{
+ struct grub_btrfs_data *data = grub_btrfs_mount (device);
+ struct grub_btrfs_key key_in, key_out;
+ grub_err_t err;
+ grub_disk_addr_t elemaddr;
+ grub_size_t elemsize;
+ grub_size_t allocated = 0;
+ struct grub_btrfs_dir_item *direl = NULL;
+ struct grub_btrfs_leaf_descriptor desc;
+ int r = 0;
+ grub_uint64_t tree;
+ grub_uint8_t type;
+
+ if (!data)
+ return grub_errno;
+
+ err = find_path (data, path, &key_in, &tree, &type);
+ if (err)
+ return err;
+ if (type != GRUB_BTRFS_DIR_ITEM_TYPE_DIRECTORY)
+ return grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory");
+
+ err = lower_bound (data, &key_in, &key_out, tree, &elemaddr, &elemsize, &desc);
+ if (err)
+ return err;
+ if (key_out.type != GRUB_BTRFS_ITEM_TYPE_DIR_ITEM
+ || key_out.object_id != key_in.object_id)
+ {
+ r = next (data, &desc, &elemaddr, &elemsize, &key_out);
+ if (r <= 0)
+ {
+ free_iterator (&desc);
+ return -r;
+ }
+ }
+ do
+ {
+ struct grub_btrfs_dir_item *cdirel;
+ if (key_out.type != GRUB_BTRFS_ITEM_TYPE_DIR_ITEM
+ || key_out.object_id != key_in.object_id)
+ {
+ r = 0;
+ break;
+ }
+ if (elemsize > allocated)
+ {
+ allocated = 2 * elemsize;
+ grub_free (direl);
+ direl = grub_malloc (allocated + 1);
+ if (!direl)
+ {
+ free_iterator (&desc);
+ return grub_errno;
+ }
+ }
+
+ err = grub_btrfs_read_logical (data, elemaddr, direl, elemsize);
+ if (err)
+ return err;
+
+ for (cdirel = direl;
+ (grub_uint8_t *) cdirel - (grub_uint8_t *) direl
+ < (grub_ssize_t) elemsize;
+ cdirel = (void *) ((grub_uint8_t *) (direl + 1)
+ + grub_le_to_cpu16 (cdirel->n)
+ + grub_le_to_cpu16 (cdirel->m)))
+ {
+ char c;
+ struct grub_btrfs_inode inode;
+ struct grub_dirhook_info info;
+ err = grub_btrfs_read_inode (data, &inode, cdirel->key.object_id,
+ tree);
+ grub_memset (&info, 0, sizeof (info));
+ if (err)
+ grub_errno = GRUB_ERR_NONE;
+ else
+ {
+ info.mtime = inode.mtime.sec;
+ info.mtimeset = 1;
+ }
+ c = cdirel->name[grub_le_to_cpu16 (cdirel->n)];
+ cdirel->name[grub_le_to_cpu16 (cdirel->n)] = 0;
+ info.dir = (cdirel->type == GRUB_BTRFS_DIR_ITEM_TYPE_DIRECTORY);
+ if (hook (cdirel->name, &info))
+ goto out;
+ cdirel->name[grub_le_to_cpu16 (cdirel->n)] = c;
+ }
+ r = next (data, &desc, &elemaddr, &elemsize, &key_out);
+ }
+ while (r > 0);
+
+out:
+ grub_free (direl);
+
+ free_iterator (&desc);
+ grub_btrfs_unmount (data);
+
+ return -r;
+}
+
+static grub_err_t
+grub_btrfs_open (struct grub_file *file, const char *name)
+{
+ struct grub_btrfs_data *data = grub_btrfs_mount (file->device);
+ grub_err_t err;
+ struct grub_btrfs_inode inode;
+ grub_uint8_t type;
+ struct grub_btrfs_key key_in;
+
+ if (!data)
+ return grub_errno;
+
+ err = find_path (data, name, &key_in, &data->tree, &type);
+ if (err)
+ {
+ grub_btrfs_unmount (data);
+ return err;
+ }
+ if (type != GRUB_BTRFS_DIR_ITEM_TYPE_REGULAR)
+ {
+ grub_btrfs_unmount (data);
+ return grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a regular file");
+ }
+
+ data->inode = key_in.object_id;
+ err = grub_btrfs_read_inode (data, &inode, data->inode, data->tree);
+ if (err)
+ {
+ grub_btrfs_unmount (data);
+ return err;
+ }
+
+ file->data = data;
+ file->size = grub_le_to_cpu64 (inode.size);
+
+ return err;
+}
+
+static grub_err_t
+grub_btrfs_close (grub_file_t file)
+{
+ grub_btrfs_unmount (file->data);
+
+ return GRUB_ERR_NONE;
+}
+
+static grub_ssize_t
+grub_btrfs_read (grub_file_t file, char *buf, grub_size_t len)
+{
+ struct grub_btrfs_data *data = file->data;
+
+ return grub_btrfs_extent_read (data, data->inode,
+ data->tree, file->offset, buf, len);
+}
+
static grub_err_t
grub_btrfs_uuid (grub_device_t device, char **uuid)
{
*uuid = NULL;
- data = grub_btrfs_mount (device->disk);
- if (! data)
+ data = grub_btrfs_mount (device);
+ if (!data)
return grub_errno;
*uuid = grub_xasprintf ("%04x%04x-%04x-%04x-%04x-%04x%04x%04x",
grub_be_to_cpu16 (data->sblock.uuid[6]),
grub_be_to_cpu16 (data->sblock.uuid[7]));
- grub_free (data);
+ grub_btrfs_unmount (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,
- };
+static grub_err_t
+grub_btrfs_label (grub_device_t device, char **label)
+{
+ struct grub_btrfs_data *data;
+
+ *label = NULL;
+
+ data = grub_btrfs_mount (device);
+ if (!data)
+ return grub_errno;
+
+ *label = grub_strndup (data->sblock.label, sizeof (data->sblock.label));
+
+ grub_btrfs_unmount (data);
+
+ return grub_errno;
+}
+
+static struct grub_fs grub_btrfs_fs = {
+ .name = "btrfs",
+ .dir = grub_btrfs_dir,
+ .open = grub_btrfs_open,
+ .read = grub_btrfs_read,
+ .close = grub_btrfs_close,
+ .uuid = grub_btrfs_uuid,
+ .label = grub_btrfs_label,
+#ifdef GRUB_UTIL
+ .reserved_first_sector = 1,
+#endif
+};
-GRUB_MOD_INIT(btrfs)
+GRUB_MOD_INIT (btrfs)
{
grub_fs_register (&grub_btrfs_fs);
}
-GRUB_MOD_FINI(btrfs)
+GRUB_MOD_FINI (btrfs)
{
grub_fs_unregister (&grub_btrfs_fs);
}
#include <grub/disk.h>
#include <grub/dl.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
#ifndef MODE_USTAR
/* cpio support */
#define MAGIC_BCPIO 070707
static grub_err_t
grub_cpio_find_file (struct grub_cpio_data *data, char **name,
- grub_uint32_t * ofs)
+ grub_int32_t *mtime, grub_uint32_t * ofs)
{
#ifndef MODE_USTAR
struct head hd;
return grub_error (GRUB_ERR_BAD_FS, "invalid cpio archive");
data->size = (((grub_uint32_t) hd.filesize_1) << 16) + hd.filesize_2;
+ if (mtime)
+ *mtime = (((grub_uint32_t) hd.mtime_1) << 16) + hd.mtime_2;
if (hd.namesize & 1)
hd.namesize++;
data->dofs = data->hofs + GRUB_DISK_SECTOR_SIZE;
*ofs = data->dofs + ((data->size + GRUB_DISK_SECTOR_SIZE - 1) &
~(GRUB_DISK_SECTOR_SIZE - 1));
+ if (mtime)
+ *mtime = grub_strtoul (hd.mtime, NULL, 8);
#endif
return GRUB_ERR_NONE;
}
data->hofs = 0;
while (1)
{
- if (grub_cpio_find_file (data, &name, &ofs))
+ grub_int32_t mtime;
+
+ if (grub_cpio_find_file (data, &name, &mtime, &ofs))
goto fail;
if (!ofs)
struct grub_dirhook_info info;
grub_memset (&info, 0, sizeof (info));
info.dir = (p != NULL);
+ info.mtime = mtime;
+ info.mtimeset = 1;
hook (name + len, &info);
- if (prev)
- grub_free (prev);
+ grub_free (prev);
prev = name;
}
else
fail:
- if (prev)
- grub_free (prev);
-
- if (data)
- grub_free (data);
+ grub_free (prev);
+ grub_free (data);
grub_dl_unref (my_mod);
data->hofs = 0;
while (1)
{
- if (grub_cpio_find_file (data, &fn, &ofs))
+ if (grub_cpio_find_file (data, &fn, NULL, &ofs))
goto fail;
if (!ofs)
fail:
- if (data)
- grub_free (data);
+ grub_free (data);
grub_dl_unref (my_mod);
#include <grub/types.h>
#include <grub/fshelp.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
/* Log2 size of ext2 block in 512 blocks. */
#define LOG2_EXT2_BLOCK_SIZE(data) \
(grub_le_to_cpu32 (data->sblock.log2_block_size) + 1)
#include <grub/err.h>
#include <grub/dl.h>
#include <grub/charset.h>
+#include <grub/fat.h>
-#define GRUB_FAT_DIR_ENTRY_SIZE 32
+GRUB_MOD_LICENSE ("GPLv3+");
-#define GRUB_FAT_ATTR_READ_ONLY 0x01
-#define GRUB_FAT_ATTR_HIDDEN 0x02
-#define GRUB_FAT_ATTR_SYSTEM 0x04
+enum
+ {
+ GRUB_FAT_ATTR_READ_ONLY = 0x01,
+ GRUB_FAT_ATTR_HIDDEN = 0x02,
+ GRUB_FAT_ATTR_SYSTEM = 0x04,
#ifndef MODE_EXFAT
-#define GRUB_FAT_ATTR_VOLUME_ID 0x08
+ GRUB_FAT_ATTR_VOLUME_ID = 0x08,
#endif
-#define GRUB_FAT_ATTR_DIRECTORY 0x10
-#define GRUB_FAT_ATTR_ARCHIVE 0x20
-
-#define GRUB_FAT_MAXFILE 256
+ GRUB_FAT_ATTR_DIRECTORY = 0x10,
+ GRUB_FAT_ATTR_ARCHIVE = 0x20,
#ifndef MODE_EXFAT
-#define GRUB_FAT_ATTR_LONG_NAME (GRUB_FAT_ATTR_READ_ONLY \
- | GRUB_FAT_ATTR_HIDDEN \
- | GRUB_FAT_ATTR_SYSTEM \
- | GRUB_FAT_ATTR_VOLUME_ID)
+ GRUB_FAT_ATTR_LONG_NAME = (GRUB_FAT_ATTR_READ_ONLY
+ | GRUB_FAT_ATTR_HIDDEN
+ | GRUB_FAT_ATTR_SYSTEM
+ | GRUB_FAT_ATTR_VOLUME_ID),
#endif
-static const grub_uint8_t GRUB_FAT_ATTR_VALID = (GRUB_FAT_ATTR_READ_ONLY
- | GRUB_FAT_ATTR_HIDDEN
- | GRUB_FAT_ATTR_SYSTEM
- | GRUB_FAT_ATTR_DIRECTORY
- | GRUB_FAT_ATTR_ARCHIVE
+ GRUB_FAT_ATTR_VALID = (GRUB_FAT_ATTR_READ_ONLY
+ | GRUB_FAT_ATTR_HIDDEN
+ | GRUB_FAT_ATTR_SYSTEM
+ | GRUB_FAT_ATTR_DIRECTORY
+ | GRUB_FAT_ATTR_ARCHIVE
#ifndef MODE_EXFAT
- | GRUB_FAT_ATTR_VOLUME_ID
+ | GRUB_FAT_ATTR_VOLUME_ID
#endif
- );
+ )
+ };
#ifdef MODE_EXFAT
-struct grub_fat_bpb
+struct grub_exfat_bpb
{
grub_uint8_t jmp_boot[3];
grub_uint8_t oem_name[8];
grub_uint8_t num_ph_drive;
grub_uint8_t reserved[8];
} __attribute__ ((packed));
-
+typedef struct grub_exfat_bpb grub_current_fat_bpb_t;
#else
-struct grub_fat_bpb
-{
- grub_uint8_t jmp_boot[3];
- grub_uint8_t oem_name[8];
- grub_uint16_t bytes_per_sector;
- grub_uint8_t sectors_per_cluster;
- grub_uint16_t num_reserved_sectors;
- grub_uint8_t num_fats;
- grub_uint16_t num_root_entries;
- grub_uint16_t num_total_sectors_16;
- grub_uint8_t media;
- grub_uint16_t sectors_per_fat_16;
- grub_uint16_t sectors_per_track;
- grub_uint16_t num_heads;
- grub_uint32_t num_hidden_sectors;
- grub_uint32_t num_total_sectors_32;
- union
- {
- struct
- {
- grub_uint8_t num_ph_drive;
- grub_uint8_t reserved;
- grub_uint8_t boot_sig;
- grub_uint32_t num_serial;
- grub_uint8_t label[11];
- grub_uint8_t fstype[8];
- } __attribute__ ((packed)) fat12_or_fat16;
- struct
- {
- grub_uint32_t sectors_per_fat_32;
- grub_uint16_t extended_flags;
- grub_uint16_t fs_version;
- grub_uint32_t root_cluster;
- grub_uint16_t fs_info;
- grub_uint16_t backup_boot_sector;
- grub_uint8_t reserved[12];
- grub_uint8_t num_ph_drive;
- grub_uint8_t reserved1;
- grub_uint8_t boot_sig;
- grub_uint32_t num_serial;
- grub_uint8_t label[11];
- grub_uint8_t fstype[8];
- } __attribute__ ((packed)) fat32;
- } __attribute__ ((packed)) version_specific;
-} __attribute__ ((packed));
+typedef struct grub_fat_bpb grub_current_fat_bpb_t;
#endif
#ifdef MODE_EXFAT
static struct grub_fat_data *
grub_fat_mount (grub_disk_t disk)
{
- struct grub_fat_bpb bpb;
+ grub_current_fat_bpb_t bpb;
struct grub_fat_data *data = 0;
grub_uint32_t first_fat, magic;
goto fail;
#endif
- grub_dprintf ("exfat", "alive\n");
-
/* Get the sizes of logical sectors and clusters. */
#ifdef MODE_EXFAT
data->logical_sector_bits = bpb.bytes_per_sector_shift;
if (bpb.num_fats == 0)
goto fail;
- grub_dprintf ("exfat", "alive\n");
-
#ifndef MODE_EXFAT
data->root_sector = data->fat_sector + bpb.num_fats * data->sectors_per_fat;
data->num_root_sectors
= ((((grub_uint32_t) grub_le_to_cpu16 (bpb.num_root_entries)
- * GRUB_FAT_DIR_ENTRY_SIZE
+ * sizeof (struct grub_fat_dir_entry)
+ grub_le_to_cpu16 (bpb.bytes_per_sector) - 1)
>> (data->logical_sector_bits + GRUB_DISK_SECTOR_BITS))
<< (data->logical_sector_bits));
they overwrite the media descriptor. */
if ((first_fat | 0x8) != (magic | bpb.media | 0x8))
goto fail;
+#else
+ (void) magic;
#endif
/* Start from the root directory. */
const struct grub_dirhook_info *info))
{
char *dirname, *dirp;
+ char *origpath = NULL;
int call_hook;
int found = 0;
return 0;
}
+ origpath = grub_strdup (path);
+ if (!origpath)
+ return 0;
+
/* Extract a directory name. */
while (*path == '/')
path++;
dirname = grub_malloc (len + 1);
if (! dirname)
- return 0;
+ goto fail;
grub_memcpy (dirname, path, len);
dirname[len] = '\0';
grub_fat_iterate_dir (disk, data, iter_hook);
if (grub_errno == GRUB_ERR_NONE && ! found && !call_hook)
- grub_error (GRUB_ERR_FILE_NOT_FOUND, "file not found");
+ grub_error (GRUB_ERR_FILE_NOT_FOUND, "file `%s' not found", origpath);
+ fail:
grub_free (dirname);
+ grub_free (origpath);
return found ? dirp : 0;
}
GRUB_MOD_INIT(fat)
#endif
{
+ COMPILE_TIME_ASSERT (sizeof (struct grub_fat_dir_entry) == 32);
grub_fs_register (&grub_fat_fs);
my_mod = mod;
}
#include <grub/misc.h>
#include <grub/disk.h>
#include <grub/fshelp.h>
+#include <grub/dl.h>
+GRUB_MOD_LICENSE ("GPLv3+");
/* Lookup the node PATH. The node ROOTNODE describes the root of the
directory tree. The node found is returned in FOUNDNODE, which is
char fpath[grub_strlen (currpath) + 1];
char *name = fpath;
char *next;
- // unsigned int pos = 0;
enum grub_fshelp_filetype type = GRUB_FSHELP_DIR;
grub_fshelp_node_t currnode = currroot;
grub_fshelp_node_t oldnode = currroot;
name = next;
}
- return grub_error (GRUB_ERR_FILE_NOT_FOUND, "file not found");
+ return grub_error (GRUB_ERR_FILE_NOT_FOUND, "file `%s' not found", path);
}
if (!path || path[0] != '/')
#include <grub/types.h>
#include <grub/hfs.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
#define GRUB_HFS_SBLOCK 2
#define GRUB_HFS_EMBED_HFSPLUS_SIG 0x482B
grub_uint8_t type;
grub_uint8_t unused[5];
grub_uint32_t dirid;
+ grub_uint32_t ctime;
+ grub_uint32_t mtime;
} __attribute__ ((packed));
/* Information about a file. */
grub_uint32_t fileid;
grub_uint8_t unused2[2];
grub_uint32_t size;
- grub_uint8_t unused3[44];
+ grub_uint8_t unused3[18];
+ grub_uint32_t mtime;
+ grub_uint8_t unused4[22];
/* The first 3 extents of the file. The other extents can be found
in the extent overflow file. */
grub_hfs_read_file (struct grub_hfs_data *data,
void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
unsigned offset, unsigned length),
- int pos, grub_size_t len, char *buf)
+ grub_off_t pos, grub_size_t len, char *buf)
{
- int i;
- int blockcnt;
+ grub_off_t i;
+ grub_off_t blockcnt;
- blockcnt = ((len + pos)
- + data->blksz - 1) / data->blksz;
+ blockcnt = grub_divmod64 (((len + pos)
+ + data->blksz - 1), data->blksz, 0);
- for (i = pos / data->blksz; i < blockcnt; i++)
+ for (i = grub_divmod64 (pos, data->blksz, 0); i < blockcnt; i++)
{
- int blknr;
- int blockoff = pos % data->blksz;
- int blockend = data->blksz;
+ grub_disk_addr_t blknr;
+ grub_off_t blockoff;
+ grub_off_t blockend = data->blksz;
int skipfirst = 0;
+ grub_divmod64 (pos, data->blksz, &blockoff);
+
blknr = grub_hfs_block (data, data->extents, data->fileid, i, 1);
if (grub_errno)
return -1;
/* Last block. */
if (i == blockcnt - 1)
{
- blockend = (len + pos) % data->blksz;
+ grub_divmod64 ((len + pos), data->blksz, &blockend);
/* The last portion is exactly EXT2_BLOCK_SIZE (data). */
if (! blockend)
}
/* First block. */
- if (i == pos / data->blksz)
+ if (i == grub_divmod64 (pos, data->blksz, 0))
{
skipfirst = blockoff;
blockend -= skipfirst;
if (! grub_hfs_find_node (data, (char *) &key, data->cat_root,
0, (char *) &fdrec.frec, sizeof (fdrec.frec)))
{
- grub_error (GRUB_ERR_FILE_NOT_FOUND, "file not found");
+ grub_error (GRUB_ERR_FILE_NOT_FOUND, "file `%s' not found", origpath);
goto fail;
}
int dir_hook (struct grub_hfs_record *rec)
{
char fname[32] = { 0 };
- char *filetype = rec->data;
+ struct grub_hfs_dirrec *drec = rec->data;
+ struct grub_hfs_filerec *frec = rec->data;
struct grub_hfs_catalog_key *ckey = rec->key;
struct grub_dirhook_info info;
grub_memset (&info, 0, sizeof (info));
grub_strncpy (fname, (char *) (ckey->str), ckey->strlen);
- if (*filetype == GRUB_HFS_FILETYPE_DIR
- || *filetype == GRUB_HFS_FILETYPE_FILE)
+ if (drec->type == GRUB_HFS_FILETYPE_DIR)
+ {
+ info.dir = 1;
+ info.mtimeset = 1;
+ info.mtime = grub_be_to_cpu32 (drec->mtime) - 2082844800;
+ return hook (fname, &info);
+ }
+ if (frec->type == GRUB_HFS_FILETYPE_FILE)
{
- info.dir = (*filetype == GRUB_HFS_FILETYPE_DIR);
+ info.dir = 0;
+ info.mtimeset = 1;
+ info.mtime = grub_be_to_cpu32 (frec->mtime) - 2082844800;
return hook (fname, &info);
}
+
return 0;
}
return grub_errno;
}
+static grub_err_t
+grub_hfs_mtime (grub_device_t device, grub_int32_t *tm)
+{
+ struct grub_hfs_data *data;
+
+ data = grub_hfs_mount (device->disk);
+
+ if (data)
+ *tm = grub_be_to_cpu32 (data->sblock.mtime) - 2082844800;
+ else
+ *tm = 0;
+
+ grub_free (data);
+ return grub_errno;
+}
+
static grub_err_t
grub_hfs_uuid (grub_device_t device, char **uuid)
{
.close = grub_hfs_close,
.label = grub_hfs_label,
.uuid = grub_hfs_uuid,
+ .mtime = grub_hfs_mtime,
.next = 0
};
#include <grub/hfs.h>
#include <grub/charset.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
#define GRUB_HFSPLUS_MAGIC 0x482B
#define GRUB_HFSPLUSX_MAGIC 0x4858
#define GRUB_HFSPLUS_SBLOCK 2
struct grub_hfsplus_btree
{
grub_uint32_t root;
- int nodesize;
+ grub_size_t nodesize;
/* Catalog file node. */
struct grub_fshelp_node file;
/* This is the offset into the physical disk for an embedded HFS+
filesystem (one inside a plain HFS wrapper). */
- int embedded_offset;
+ grub_disk_addr_t embedded_offset;
int case_sensitive;
};
\f
/* Return the offset of the record with the index INDEX, in the node
NODE which is part of the B+ tree BTREE. */
-static inline unsigned int
+static inline grub_off_t
grub_hfsplus_btree_recoffset (struct grub_hfsplus_btree *btree,
struct grub_hfsplus_btnode *node, int index)
{
struct grub_hfsplus_btnode *node, int index)
{
char *cnode = (char *) node;
- unsigned int offset;
+ grub_off_t offset;
offset = grub_hfsplus_btree_recoffset (btree, node, index);
return (struct grub_hfsplus_key *) &cnode[offset];
}
/* Find the extent that points to FILEBLOCK. If it is not in one of
the 8 extents described by EXTENT, return -1. In that case set
FILEBLOCK to the next block. */
-static int
+static grub_disk_addr_t
grub_hfsplus_find_block (struct grub_hfsplus_extent *extent,
- int *fileblock)
+ grub_disk_addr_t *fileblock)
{
int i;
- grub_size_t blksleft = *fileblock;
+ grub_disk_addr_t blksleft = *fileblock;
/* First lookup the file in the given extents. */
for (i = 0; i < 8; i++)
}
*fileblock = blksleft;
- return -1;
+ return 0xffffffffffffffffULL;
}
static grub_err_t
struct grub_hfsplus_key_internal *key,
int (*compare_keys) (struct grub_hfsplus_key *keya,
struct grub_hfsplus_key_internal *keyb),
- struct grub_hfsplus_btnode **matchnode, int *keyoffset);
+ struct grub_hfsplus_btnode **matchnode,
+ grub_off_t *keyoffset);
static int grub_hfsplus_cmp_extkey (struct grub_hfsplus_key *keya,
struct grub_hfsplus_key_internal *keyb);
grub_hfsplus_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
{
struct grub_hfsplus_btnode *nnode = 0;
- int blksleft = fileblock;
+ grub_disk_addr_t blksleft = fileblock;
struct grub_hfsplus_extent *extents = &node->extents[0];
while (1)
{
struct grub_hfsplus_extkey *key;
struct grub_hfsplus_extkey_internal extoverflow;
- int blk;
- int ptr;
+ grub_disk_addr_t blk;
+ grub_off_t ptr;
/* Try to find this block in the current set of extents. */
blk = grub_hfsplus_find_block (extents, &blksleft);
grub_free (nnode);
nnode = 0;
- if (blk != -1)
+ if (blk != 0xffffffffffffffffULL)
return (blk
+ (node->data->embedded_offset >> (node->data->log2blksize
- GRUB_DISK_SECTOR_BITS)));
grub_hfsplus_read_file (grub_fshelp_node_t node,
void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
unsigned offset, unsigned length),
- int pos, grub_size_t len, char *buf)
+ grub_off_t pos, grub_size_t len, char *buf)
{
return grub_fshelp_read_file (node->data->disk, node, read_hook,
pos, len, buf, grub_hfsplus_read_block,
data->embedded_offset = 0;
if (grub_be_to_cpu16 (volheader.hfs.magic) == GRUB_HFS_MAGIC)
{
- int extent_start;
- int ablk_size;
- int ablk_start;
+ grub_disk_addr_t extent_start;
+ grub_disk_addr_t ablk_size;
+ grub_disk_addr_t ablk_start;
/* See if there's an embedded HFS+ filesystem. */
if (grub_be_to_cpu16 (volheader.hfs.embed_sig) != GRUB_HFSPLUS_MAGIC)
static int
grub_hfsplus_btree_iterate_node (struct grub_hfsplus_btree *btree,
struct grub_hfsplus_btnode *first_node,
- int first_rec,
+ grub_disk_addr_t first_rec,
int (*hook) (void *record))
{
- int rec;
+ grub_disk_addr_t rec;
for (;;)
{
struct grub_hfsplus_key_internal *key,
int (*compare_keys) (struct grub_hfsplus_key *keya,
struct grub_hfsplus_key_internal *keyb),
- struct grub_hfsplus_btnode **matchnode, int *keyoffset)
+ struct grub_hfsplus_btnode **matchnode,
+ grub_off_t *keyoffset)
{
grub_uint64_t currnode;
char *node;
struct grub_hfsplus_btnode *nodedesc;
- int rec;
+ grub_disk_addr_t rec;
node = grub_malloc (btree->nodesize);
if (! node)
struct grub_hfsplus_key_internal intern;
struct grub_hfsplus_btnode *node;
- int ptr;
+ grub_disk_addr_t ptr;
/* Create a key that points to the first entry in the directory. */
intern.catkey.parent = dir->fileid;
return GRUB_ERR_NONE;
}
-
/* Read LEN bytes data from FILE into BUF. */
static grub_ssize_t
grub_hfsplus_read (grub_file_t file, char *buf, grub_size_t len)
struct grub_hfsplus_data *data =
(struct grub_hfsplus_data *) file->data;
- int size = grub_hfsplus_read_file (&data->opened_file, file->read_hook,
+ return grub_hfsplus_read_file (&data->opened_file, file->read_hook,
file->offset, len, buf);
-
- return size;
}
-
static grub_err_t
grub_hfsplus_dir (grub_device_t device, const char *path,
int (*hook) (const char *filename,
+++ /dev/null
-/* pxe.c - Driver to provide access to the pxe filesystem */
-/*
- * GRUB -- GRand Unified Bootloader
- * Copyright (C) 2008,2009 Free Software Foundation, Inc.
- *
- * GRUB is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * GRUB is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <grub/dl.h>
-#include <grub/fs.h>
-#include <grub/mm.h>
-#include <grub/disk.h>
-#include <grub/file.h>
-#include <grub/misc.h>
-#include <grub/bufio.h>
-#include <grub/env.h>
-
-#include <grub/machine/pxe.h>
-#include <grub/machine/int.h>
-#include <grub/machine/memory.h>
-
-#define SEGMENT(x) ((x) >> 4)
-#define OFFSET(x) ((x) & 0xF)
-#define SEGOFS(x) ((SEGMENT(x) << 16) + OFFSET(x))
-#define LINEAR(x) (void *) (((x >> 16) <<4) + (x & 0xFFFF))
-
-struct grub_pxe_disk_data
-{
- grub_uint32_t server_ip;
- grub_uint32_t gateway_ip;
-};
-
-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;
-static unsigned grub_pxe_blksize = GRUB_PXE_MIN_BLKSIZE;
-
-static grub_file_t curr_file = 0;
-
-struct grub_pxe_data
-{
- grub_uint32_t packet_number;
- grub_uint32_t block_size;
- char filename[0];
-};
-
-static grub_uint32_t pxe_rm_entry = 0;
-
-static struct grub_pxe_bangpxe *
-grub_pxe_scan (void)
-{
- struct grub_bios_int_registers regs;
- 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;
-
- 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 (pxenv->version < 0x201)
- return NULL;
-
- bangpxe = (void *) ((((pxenv->pxe_ptr & 0xffff0000) >> 16) << 4)
- + (pxenv->pxe_ptr & 0xffff));
-
- if (!bangpxe)
- return NULL;
-
- if (grub_memcmp (bangpxe->signature, GRUB_PXE_BANGPXE_SIGNATURE,
- sizeof (bangpxe->signature)) != 0)
- return NULL;
-
- pxe_rm_entry = bangpxe->rm_entry;
-
- return bangpxe;
-}
-
-static int
-grub_pxe_iterate (int (*hook) (const char *name))
-{
- if (hook ("pxe"))
- return 1;
- return 0;
-}
-
-static grub_err_t
-parse_ip (const char *val, grub_uint32_t *ip, const char **rest)
-{
- grub_uint32_t newip = 0;
- unsigned long t;
- int i;
- const char *ptr = val;
-
- for (i = 0; i < 4; i++)
- {
- t = grub_strtoul (ptr, (char **) &ptr, 0);
- if (grub_errno)
- return grub_errno;
- if (t & ~0xff)
- return grub_error (GRUB_ERR_OUT_OF_RANGE, "Invalid IP.");
- newip >>= 8;
- newip |= (t << 24);
- if (i != 3 && *ptr != '.')
- return grub_error (GRUB_ERR_OUT_OF_RANGE, "Invalid IP.");
- ptr++;
- }
- *ip = newip;
- if (rest)
- *rest = ptr - 1;
- return 0;
-}
-
-static grub_err_t
-grub_pxe_open (const char *name, grub_disk_t disk)
-{
- struct grub_pxe_disk_data *data;
-
- if (grub_strcmp (name, "pxe") != 0
- && grub_strncmp (name, "pxe:", sizeof ("pxe:") - 1) != 0)
- return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a pxe disk");
-
- data = grub_malloc (sizeof (*data));
- if (!data)
- return grub_errno;
-
- if (grub_strncmp (name, "pxe:", sizeof ("pxe:") - 1) == 0)
- {
- const char *ptr;
- grub_err_t err;
-
- ptr = name + sizeof ("pxe:") - 1;
- err = parse_ip (ptr, &(data->server_ip), &ptr);
- if (err)
- return err;
- if (*ptr == ':')
- {
- err = parse_ip (ptr + 1, &(data->gateway_ip), 0);
- if (err)
- return err;
- }
- else
- data->gateway_ip = grub_pxe_default_gateway_ip;
- }
- else
- {
- data->server_ip = grub_pxe_default_server_ip;
- data->gateway_ip = grub_pxe_default_gateway_ip;
- }
-
- disk->total_sectors = 0;
- disk->id = (unsigned long) data;
-
- disk->data = data;
-
- return GRUB_ERR_NONE;
-}
-
-static void
-grub_pxe_close (grub_disk_t disk)
-{
- grub_free (disk->data);
-}
-
-static grub_err_t
-grub_pxe_read (grub_disk_t disk __attribute((unused)),
- grub_disk_addr_t sector __attribute((unused)),
- grub_size_t size __attribute((unused)),
- char *buf __attribute((unused)))
-{
- return GRUB_ERR_OUT_OF_RANGE;
-}
-
-static grub_err_t
-grub_pxe_write (grub_disk_t disk __attribute((unused)),
- grub_disk_addr_t sector __attribute((unused)),
- grub_size_t size __attribute((unused)),
- const char *buf __attribute((unused)))
-{
- return GRUB_ERR_OUT_OF_RANGE;
-}
-
-static struct grub_disk_dev grub_pxe_dev =
- {
- .name = "pxe",
- .id = GRUB_DISK_DEVICE_PXE_ID,
- .iterate = grub_pxe_iterate,
- .open = grub_pxe_open,
- .close = grub_pxe_close,
- .read = grub_pxe_read,
- .write = grub_pxe_write,
- .next = 0
- };
-
-static grub_err_t
-grub_pxefs_dir (grub_device_t device,
- const char *path __attribute__ ((unused)),
- int (*hook) (const char *filename,
- const struct grub_dirhook_info *info)
- __attribute__ ((unused)))
-{
- if (device->disk->dev->id != GRUB_DISK_DEVICE_PXE_ID)
- return grub_error (GRUB_ERR_IO, "not a pxe disk");
-
- return GRUB_ERR_NONE;
-}
-
-static grub_err_t
-grub_pxefs_open (struct grub_file *file, const char *name)
-{
- union
- {
- struct grub_pxenv_tftp_get_fsize c1;
- struct grub_pxenv_tftp_open c2;
- } c;
- struct grub_pxe_data *data;
- struct grub_pxe_disk_data *disk_data = file->device->disk->data;
- grub_file_t file_int, bufio;
-
- if (file->device->disk->dev->id != GRUB_DISK_DEVICE_PXE_ID)
- return grub_error (GRUB_ERR_IO, "not a pxe disk");
-
- if (curr_file != 0)
- {
- grub_pxe_call (GRUB_PXENV_TFTP_CLOSE, &c.c2, pxe_rm_entry);
- curr_file = 0;
- }
-
- c.c1.server_ip = disk_data->server_ip;
- c.c1.gateway_ip = disk_data->gateway_ip;
- grub_strcpy ((char *)&c.c1.filename[0], name);
- grub_pxe_call (GRUB_PXENV_TFTP_GET_FSIZE, &c.c1, pxe_rm_entry);
- if (c.c1.status)
- return grub_error (GRUB_ERR_FILE_NOT_FOUND, "file not found");
-
- file->size = c.c1.file_size;
-
- c.c2.tftp_port = grub_cpu_to_be16 (GRUB_PXE_TFTP_PORT);
- c.c2.packet_size = grub_pxe_blksize;
- grub_pxe_call (GRUB_PXENV_TFTP_OPEN, &c.c2, pxe_rm_entry);
- if (c.c2.status)
- return grub_error (GRUB_ERR_BAD_FS, "open fails");
-
- data = grub_zalloc (sizeof (struct grub_pxe_data) + grub_strlen (name) + 1);
- if (! data)
- return grub_errno;
-
- data->block_size = c.c2.packet_size;
- grub_strcpy (data->filename, name);
-
- file_int = grub_malloc (sizeof (*file_int));
- if (! file_int)
- {
- grub_free (data);
- return grub_errno;
- }
-
- file->data = data;
- file->not_easily_seekable = 1;
- grub_memcpy (file_int, file, sizeof (struct grub_file));
- curr_file = file_int;
-
- bufio = grub_bufio_open (file_int, data->block_size);
- if (! bufio)
- {
- grub_free (file_int);
- grub_free (data);
- return grub_errno;
- }
-
- grub_memcpy (file, bufio, sizeof (struct grub_file));
-
- return GRUB_ERR_NONE;
-}
-
-static grub_ssize_t
-grub_pxefs_read (grub_file_t file, char *buf, grub_size_t len)
-{
- struct grub_pxenv_tftp_read c;
- struct grub_pxe_data *data;
- struct grub_pxe_disk_data *disk_data = file->device->disk->data;
- grub_uint32_t pn, r;
-
- data = file->data;
-
- pn = grub_divmod64 (file->offset, data->block_size, &r);
- if (r)
- {
- grub_error (GRUB_ERR_BAD_FS,
- "read access must be aligned to packet size");
- return -1;
- }
-
- if ((curr_file != file) || (data->packet_number > pn))
- {
- struct grub_pxenv_tftp_open o;
-
- if (curr_file != 0)
- grub_pxe_call (GRUB_PXENV_TFTP_CLOSE, &o, pxe_rm_entry);
-
- o.server_ip = disk_data->server_ip;
- 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 = data->block_size;
- grub_pxe_call (GRUB_PXENV_TFTP_OPEN, &o, pxe_rm_entry);
- if (o.status)
- {
- grub_error (GRUB_ERR_BAD_FS, "open fails");
- return -1;
- }
- data->block_size = o.packet_size;
- data->packet_number = 0;
- curr_file = file;
- }
-
- c.buffer = SEGOFS (GRUB_MEMORY_MACHINE_SCRATCH_ADDR);
- while (pn >= data->packet_number)
- {
- c.buffer_size = data->block_size;
- grub_pxe_call (GRUB_PXENV_TFTP_READ, &c, pxe_rm_entry);
- if (c.status)
- {
- grub_error (GRUB_ERR_BAD_FS, "read fails");
- return -1;
- }
- data->packet_number++;
- }
-
- grub_memcpy (buf, (char *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR, len);
-
- return len;
-}
-
-static grub_err_t
-grub_pxefs_close (grub_file_t file)
-{
- struct grub_pxenv_tftp_close c;
-
- if (curr_file == file)
- {
- grub_pxe_call (GRUB_PXENV_TFTP_CLOSE, &c, pxe_rm_entry);
- curr_file = 0;
- }
-
- grub_free (file->data);
-
- return GRUB_ERR_NONE;
-}
-
-static grub_err_t
-grub_pxefs_label (grub_device_t device __attribute ((unused)),
- char **label __attribute ((unused)))
-{
- *label = 0;
- return GRUB_ERR_NONE;
-}
-
-static struct grub_fs grub_pxefs_fs =
- {
- .name = "pxefs",
- .dir = grub_pxefs_dir,
- .open = grub_pxefs_open,
- .read = grub_pxefs_read,
- .close = grub_pxefs_close,
- .label = grub_pxefs_label,
- .next = 0
- };
-
-static char *
-grub_env_write_readonly (struct grub_env_var *var __attribute__ ((unused)),
- const char *val __attribute__ ((unused)))
-{
- return NULL;
-}
-
-static void
-set_mac_env (grub_uint8_t *mac_addr, grub_size_t mac_len)
-{
- char buf[(sizeof ("XX:") - 1) * mac_len + 1];
- char *ptr = buf;
- unsigned i;
-
- for (i = 0; i < mac_len; i++)
- {
- grub_snprintf (ptr, sizeof (buf) - (ptr - buf),
- "%02x:", mac_addr[i] & 0xff);
- ptr += (sizeof ("XX:") - 1);
- }
- if (mac_len)
- *(ptr - 1) = 0;
- else
- buf[0] = 0;
-
- grub_env_set ("net_pxe_mac", buf);
- /* XXX: Is it possible to change MAC in PXE? */
- grub_register_variable_hook ("net_pxe_mac", 0, grub_env_write_readonly);
- grub_env_export ("net_pxe_mac");
-}
-
-static void
-set_env_limn_ro (const char *varname, char *value, grub_size_t len)
-{
- char c;
- c = value[len];
- value[len] = 0;
- grub_env_set (varname, value);
- value[len] = c;
- grub_register_variable_hook (varname, 0, grub_env_write_readonly);
- grub_env_export (varname);
-}
-
-static void
-parse_dhcp_vendor (void *vend, int limit)
-{
- grub_uint8_t *ptr, *ptr0;
-
- ptr = ptr0 = vend;
-
- if (grub_be_to_cpu32 (*(grub_uint32_t *) ptr) != 0x63825363)
- return;
- ptr = ptr + sizeof (grub_uint32_t);
- while (ptr - ptr0 < limit)
- {
- grub_uint8_t tagtype;
- grub_uint8_t taglength;
-
- tagtype = *ptr++;
-
- /* Pad tag. */
- if (tagtype == 0)
- continue;
-
- /* End tag. */
- if (tagtype == 0xff)
- return;
-
- taglength = *ptr++;
-
- switch (tagtype)
- {
- case 12:
- set_env_limn_ro ("net_pxe_hostname", (char *) ptr, taglength);
- break;
-
- case 15:
- set_env_limn_ro ("net_pxe_domain", (char *) ptr, taglength);
- break;
-
- case 17:
- set_env_limn_ro ("net_pxe_rootpath", (char *) ptr, taglength);
- break;
-
- case 18:
- set_env_limn_ro ("net_pxe_extensionspath", (char *) ptr, taglength);
- break;
-
- /* If you need any other options please contact GRUB
- development team. */
- }
-
- ptr += taglength;
- }
-}
-
-static void
-grub_pxe_detect (void)
-{
- struct grub_pxe_bangpxe *pxenv;
- struct grub_pxenv_get_cached_info ci;
- struct grub_pxenv_boot_player *bp;
-
- pxenv = grub_pxe_scan ();
- if (! pxenv)
- return;
-
- ci.packet_type = GRUB_PXENV_PACKET_TYPE_DHCP_ACK;
- ci.buffer = 0;
- ci.buffer_size = 0;
- grub_pxe_call (GRUB_PXENV_GET_CACHED_INFO, &ci, pxe_rm_entry);
- if (ci.status)
- return;
-
- bp = LINEAR (ci.buffer);
-
- grub_pxe_your_ip = bp->your_ip;
- grub_pxe_default_server_ip = bp->server_ip;
- grub_pxe_default_gateway_ip = bp->gateway_ip;
- set_mac_env (bp->mac_addr, bp->hw_len < sizeof (bp->mac_addr) ? bp->hw_len
- : sizeof (bp->mac_addr));
- set_env_limn_ro ("net_pxe_boot_file", (char *) bp->boot_file,
- sizeof (bp->boot_file));
- set_env_limn_ro ("net_pxe_dhcp_server_name", (char *) bp->server_name,
- sizeof (bp->server_name));
- parse_dhcp_vendor (&bp->vendor, sizeof (bp->vendor));
- grub_pxe_pxenv = pxenv;
-}
-
-void
-grub_pxe_unload (void)
-{
- if (grub_pxe_pxenv)
- {
- grub_fs_unregister (&grub_pxefs_fs);
- grub_disk_dev_unregister (&grub_pxe_dev);
-
- grub_pxe_pxenv = 0;
- }
-}
-
-static void
-set_ip_env (char *varname, grub_uint32_t ip)
-{
- char buf[sizeof ("XXX.XXX.XXX.XXX")];
-
- grub_snprintf (buf, sizeof (buf), "%d.%d.%d.%d", (ip & 0xff),
- (ip >> 8) & 0xff, (ip >> 16) & 0xff, (ip >> 24) & 0xff);
- grub_env_set (varname, buf);
-}
-
-static char *
-write_ip_env (grub_uint32_t *ip, const char *val)
-{
- char *buf;
- grub_err_t err;
- grub_uint32_t newip;
-
- err = parse_ip (val, &newip, 0);
- if (err)
- return 0;
-
- /* Normalize the IP. */
- buf = grub_xasprintf ("%d.%d.%d.%d", (newip & 0xff), (newip >> 8) & 0xff,
- (newip >> 16) & 0xff, (newip >> 24) & 0xff);
- if (!buf)
- return 0;
-
- *ip = newip;
-
- return buf;
-}
-
-static char *
-grub_env_write_pxe_default_server (struct grub_env_var *var
- __attribute__ ((unused)),
- const char *val)
-{
- return write_ip_env (&grub_pxe_default_server_ip, val);
-}
-
-static char *
-grub_env_write_pxe_default_gateway (struct grub_env_var *var
- __attribute__ ((unused)),
- const char *val)
-{
- return write_ip_env (&grub_pxe_default_gateway_ip, val);
-}
-
-static char *
-grub_env_write_pxe_blocksize (struct grub_env_var *var __attribute__ ((unused)),
- const char *val)
-{
- unsigned size;
- char *buf;
-
- size = grub_strtoul (val, 0, 0);
- if (grub_errno)
- return 0;
-
- if (size < GRUB_PXE_MIN_BLKSIZE)
- size = GRUB_PXE_MIN_BLKSIZE;
- else if (size > GRUB_PXE_MAX_BLKSIZE)
- size = GRUB_PXE_MAX_BLKSIZE;
-
- buf = grub_xasprintf ("%d", size);
- if (!buf)
- return 0;
-
- grub_pxe_blksize = size;
-
- return buf;
-}
-
-
-GRUB_MOD_INIT(pxe)
-{
- grub_pxe_detect ();
- if (grub_pxe_pxenv)
- {
- char *buf;
-
- buf = grub_xasprintf ("%d", grub_pxe_blksize);
- if (buf)
- grub_env_set ("pxe_blksize", buf);
- grub_free (buf);
-
- set_ip_env ("pxe_default_server", grub_pxe_default_server_ip);
- set_ip_env ("pxe_default_gateway", grub_pxe_default_gateway_ip);
- set_ip_env ("net_pxe_ip", grub_pxe_your_ip);
- grub_register_variable_hook ("pxe_default_server", 0,
- grub_env_write_pxe_default_server);
- grub_register_variable_hook ("pxe_default_gateway", 0,
- grub_env_write_pxe_default_gateway);
-
-
- /* XXX: Is it possible to change IP in PXE? */
- grub_register_variable_hook ("net_pxe_ip", 0,
- grub_env_write_readonly);
- grub_register_variable_hook ("pxe_blksize", 0,
- grub_env_write_pxe_blocksize);
-
- grub_env_export ("pxe_default_server");
- grub_env_export ("pxe_default_gateway");
- grub_env_export ("net_pxe_ip");
- grub_env_export ("pxe_blksize");
-
- grub_disk_dev_register (&grub_pxe_dev);
- grub_fs_register (&grub_pxefs_fs);
- }
-}
-
-GRUB_MOD_FINI(pxe)
-{
- grub_pxe_unload ();
-}
#include <grub/types.h>
#include <grub/fshelp.h>
#include <grub/charset.h>
+#include <grub/datetime.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
#define GRUB_ISO9660_FSTYPE_DIR 0040000
#define GRUB_ISO9660_FSTYPE_REG 0100000
grub_uint8_t version;
} __attribute__ ((packed));
+struct grub_iso9660_date2
+{
+ grub_uint8_t year;
+ grub_uint8_t month;
+ grub_uint8_t day;
+ grub_uint8_t hour;
+ grub_uint8_t minute;
+ grub_uint8_t second;
+ grub_uint8_t offset;
+} __attribute__ ((packed));
+
/* A directory entry. */
struct grub_iso9660_dir
{
grub_uint32_t first_sector_be;
grub_uint32_t size;
grub_uint32_t size_be;
- grub_uint8_t unused1[7];
+ struct grub_iso9660_date2 mtime;
grub_uint8_t flags;
grub_uint8_t unused2[6];
grub_uint8_t namelen;
struct grub_fshelp_node
{
struct grub_iso9660_data *data;
+ struct grub_iso9660_dir dirent;
unsigned int size;
unsigned int blk;
unsigned int dir_blk;
static grub_dl_t my_mod;
\f
+static grub_err_t
+iso9660_to_unixtime (const struct grub_iso9660_date *i, grub_int32_t *nix)
+{
+ struct grub_datetime datetime;
+
+ if (! i->year[0] && ! i->year[1]
+ && ! i->year[2] && ! i->year[3]
+ && ! i->month[0] && ! i->month[1]
+ && ! i->day[0] && ! i->day[1]
+ && ! i->hour[0] && ! i->hour[1]
+ && ! i->minute[0] && ! i->minute[1]
+ && ! i->second[0] && ! i->second[1]
+ && ! i->hundredth[0] && ! i->hundredth[1])
+ return grub_error (GRUB_ERR_BAD_NUMBER, "empty date");
+ datetime.year = (i->year[0] - '0') * 1000 + (i->year[1] - '0') * 100
+ + (i->year[2] - '0') * 10 + (i->year[3] - '0');
+ datetime.month = (i->month[0] - '0') * 10 + (i->month[1] - '0');
+ datetime.day = (i->day[0] - '0') * 10 + (i->day[1] - '0');
+ datetime.hour = (i->hour[0] - '0') * 10 + (i->hour[1] - '0');
+ datetime.minute = (i->minute[0] - '0') * 10 + (i->minute[1] - '0');
+ datetime.second = (i->second[0] - '0') * 10 + (i->second[1] - '0');
+
+ if (!grub_datetime2unixtime (&datetime, nix))
+ return grub_error (GRUB_ERR_BAD_NUMBER, "incorrect date");
+ *nix -= i->offset * 60 * 15;
+ return GRUB_ERR_NONE;
+}
+
+static int
+iso9660_to_unixtime2 (const struct grub_iso9660_date2 *i, grub_int32_t *nix)
+{
+ struct grub_datetime datetime;
+
+ datetime.year = i->year + 1900;
+ datetime.month = i->month;
+ datetime.day = i->day;
+ datetime.hour = i->hour;
+ datetime.minute = i->minute;
+ datetime.second = i->second;
+
+ if (!grub_datetime2unixtime (&datetime, nix))
+ return 0;
+ *nix -= i->offset * 60 * 15;
+ return 1;
+}
+
/* Iterate over the susp entries, starting with block SUA_BLOCK on the
offset SUA_POS with a size of SUA_SIZE bytes. Hook is called for
every entry. */
static char *
grub_iso9660_read_symlink (grub_fshelp_node_t node)
{
- struct grub_iso9660_dir dirent;
int sua_off;
int sua_size;
char *symlink = 0;
return 0;
}
- if (grub_disk_read (node->data->disk, node->dir_blk, node->dir_off,
- sizeof (dirent), (char *) &dirent))
- return 0;
-
- sua_off = (sizeof (dirent) + dirent.namelen + 1 - (dirent.namelen % 2)
+ sua_off = (sizeof (node->dirent) + node->dirent.namelen + 1
+ - (node->dirent.namelen % 2)
+ node->data->susp_skip);
- sua_size = dirent.len - sua_off;
+ sua_size = node->dirent.len - sua_off;
symlink = grub_malloc (1);
if (!symlink)
return 0;
}
- while (offset < dir->size)
+ for (; offset < dir->size; offset += dirent.len)
{
if (grub_disk_read (dir->data->disk,
(dir->blk << GRUB_ISO9660_LOG2_BLKSZ)
if (filename)
*filename = '\0';
- if (dirent.namelen == 1 && name[0] == 0)
- filename = ".";
- else if (dirent.namelen == 1 && name[0] == 1)
- filename = "..";
+ /* . and .. */
+ if (dirent.namelen == 1 && (name[0] == 0 || name[0] == 1))
+ continue;
else
filename = name;
}
filename_alloc = 1;
}
+ node->dirent = dirent;
if (hook (filename, type, node))
{
if (filename_alloc)
if (filename_alloc)
grub_free (filename);
}
-
- offset += dirent.len;
}
return 0;
struct grub_dirhook_info info;
grub_memset (&info, 0, sizeof (info));
info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
+ info.mtimeset = !!iso9660_to_unixtime2 (&node->dirent.mtime, &info.mtime);
+
grub_free (node);
return hook (filename, &info);
}
return grub_errno;
}
+/* Get writing time of filesystem. */
+static grub_err_t
+grub_iso9660_mtime (grub_device_t device, grub_int32_t *timebuf)
+{
+ struct grub_iso9660_data *data;
+ grub_disk_t disk = device->disk;
+ grub_err_t err;
+
+ grub_dl_ref (my_mod);
+
+ data = grub_iso9660_mount (disk);
+ if (!data)
+ {
+ grub_dl_unref (my_mod);
+ return grub_errno;
+ }
+ err = iso9660_to_unixtime (&data->voldesc.modified, timebuf);
+
+ grub_dl_unref (my_mod);
+
+ grub_free (data);
+
+ return err;
+}
+
+
\f
static struct grub_fs grub_iso9660_fs =
.close = grub_iso9660_close,
.label = grub_iso9660_label,
.uuid = grub_iso9660_uuid,
+ .mtime = grub_iso9660_mtime,
.next = 0
};
#include <grub/types.h>
#include <grub/charset.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
#define GRUB_JFS_MAX_SYMLNK_CNT 8
#define GRUB_JFS_FILETYPE_MASK 0170000
#define GRUB_JFS_FILETYPE_REG 0100000
grub_uint16_t namepart[15];
} __attribute__ ((packed));
+struct grub_jfs_time
+{
+ grub_int32_t sec;
+ grub_int32_t nanosec;
+} __attribute__ ((packed));
+
struct grub_jfs_inode
{
grub_uint32_t stamp;
grub_uint64_t size;
grub_uint8_t unused2[20];
grub_uint32_t mode;
- grub_uint8_t unused3[72];
+ struct grub_jfs_time atime;
+ struct grub_jfs_time ctime;
+ struct grub_jfs_time mtime;
+ grub_uint8_t unused3[48];
grub_uint8_t unused4[96];
union
/* Find the file with the pathname PATH on the filesystem described by
DATA. */
static grub_err_t
-grub_jfs_find_file (struct grub_jfs_data *data, const char *path)
+grub_jfs_find_file (struct grub_jfs_data *data, const char *path,
+ grub_uint32_t start_ino)
{
char fpath[grub_strlen (path)];
char *name = fpath;
grub_strncpy (fpath, path, grub_strlen (path) + 1);
- if (grub_jfs_read_inode (data, GRUB_JFS_AGGR_INODE, &data->currinode))
+ if (grub_jfs_read_inode (data, start_ino, &data->currinode))
return grub_errno;
/* Skip the first slashes. */
}
grub_jfs_closedir (diro);
- grub_error (GRUB_ERR_FILE_NOT_FOUND, "file not found");
+ grub_error (GRUB_ERR_FILE_NOT_FOUND, "file `%s' not found", path);
return grub_errno;
}
if (symlink[0] == '/')
ino = 2;
- /* Now load in the old inode. */
- if (grub_jfs_read_inode (data, ino, &data->currinode))
- return grub_errno;
-
- grub_jfs_find_file (data, symlink);
+ grub_jfs_find_file (data, symlink, ino);
if (grub_errno)
grub_error (grub_errno, "cannot follow symlink `%s'", symlink);
if (!data)
goto fail;
- if (grub_jfs_find_file (data, path))
+ if (grub_jfs_find_file (data, path, GRUB_JFS_AGGR_INODE))
goto fail;
diro = grub_jfs_opendir (data, &data->currinode);
info.dir = (grub_le_to_cpu32 (inode.mode)
& GRUB_JFS_FILETYPE_MASK) == GRUB_JFS_FILETYPE_DIR;
+ info.mtimeset = 1;
+ info.mtime = grub_le_to_cpu32 (inode.mtime.sec);
if (hook (diro->name, &info))
goto fail;
}
if (!data)
goto fail;
- grub_jfs_find_file (data, name);
+ grub_jfs_find_file (data, name, GRUB_JFS_AGGR_INODE);
if (grub_errno)
goto fail;
#include <grub/dl.h>
#include <grub/types.h>
-#ifdef MODE_MINIX2
+GRUB_MOD_LICENSE ("GPLv3+");
+
+#ifdef MODE_MINIX3
+#define GRUB_MINIX_MAGIC 0x4D5A
+#elif defined(MODE_MINIX2)
#define GRUB_MINIX_MAGIC 0x2468
#define GRUB_MINIX_MAGIC_30 0x2478
#else
#define GRUB_MINIX_MAGIC 0x137F
#define GRUB_MINIX_MAGIC_30 0x138F
#endif
-#define GRUB_MINIX_BSIZE 1024U
+
+#define GRUB_MINIX_INODE_DIR_BLOCKS 7
#define GRUB_MINIX_LOG2_BSIZE 1
#define GRUB_MINIX_ROOT_INODE 1
#define GRUB_MINIX_MAX_SYMLNK_CNT 8
#define GRUB_MINIX_IFDIR 0040000U
#define GRUB_MINIX_IFLNK 0120000U
-#ifdef MODE_MINIX2
+#if defined(MODE_MINIX2) || defined(MODE_MINIX3)
typedef grub_uint32_t grub_minix_uintn_t;
#define grub_minix_le_to_cpu_n grub_le_to_cpu32
#else
#endif
#define GRUB_MINIX_INODE_BLKSZ(data) sizeof (grub_minix_uintn_t)
+#ifdef MODE_MINIX3
+typedef grub_uint32_t grub_minix_ino_t;
+#define grub_minix_le_to_cpu_ino grub_le_to_cpu32
+#else
+typedef grub_uint16_t grub_minix_ino_t;
+#define grub_minix_le_to_cpu_ino grub_le_to_cpu16
+#endif
#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_DINDIR_ZONE(data) (grub_minix_le_to_cpu_n \
(data->inode.double_indir_zone))
+#ifndef MODE_MINIX3
#define GRUB_MINIX_LOG2_ZONESZ (GRUB_MINIX_LOG2_BSIZE \
- + grub_le_to_cpu16 (sblock->log2_zone_size))
-#define GRUB_MINIX_ZONESZ (GRUB_MINIX_BSIZE \
- << grub_le_to_cpu16 (sblock->log2_zone_size))
+ + grub_le_to_cpu16 (data->sblock.log2_zone_size))
+#endif
+#define GRUB_MINIX_ZONESZ (data->block_size \
+ << grub_le_to_cpu16 (data->sblock.log2_zone_size))
+
+#ifdef MODE_MINIX3
+#define GRUB_MINIX_ZONE2SECT(zone) ((zone) * (data->block_size / GRUB_DISK_SECTOR_SIZE))
+#else
+#define GRUB_MINIX_ZONE2SECT(zone) ((zone) << GRUB_MINIX_LOG2_ZONESZ)
+#endif
+
+#ifdef MODE_MINIX3
struct grub_minix_sblock
{
- grub_uint16_t inode_cnt;
+ grub_uint32_t inode_cnt;
grub_uint16_t zone_cnt;
grub_uint16_t inode_bmap_size;
grub_uint16_t zone_bmap_size;
grub_uint16_t first_data_zone;
grub_uint16_t log2_zone_size;
+ grub_uint16_t pad;
grub_uint32_t max_file_size;
+ grub_uint32_t zones;
grub_uint16_t magic;
+
+ grub_uint16_t pad2;
+ grub_uint16_t block_size;
+ grub_uint8_t disk_version;
};
-
-#ifndef MODE_MINIX2
-struct grub_minix_inode
+#else
+struct grub_minix_sblock
{
- grub_uint16_t mode;
- grub_uint16_t uid;
- grub_uint16_t size;
- grub_uint32_t ctime;
- grub_uint8_t gid;
- grub_uint8_t nlinks;
- grub_uint16_t dir_zones[7];
- grub_uint16_t indir_zone;
- grub_uint16_t double_indir_zone;
+ grub_uint16_t inode_cnt;
+ grub_uint16_t zone_cnt;
+ grub_uint16_t inode_bmap_size;
+ grub_uint16_t zone_bmap_size;
+ grub_uint16_t first_data_zone;
+ grub_uint16_t log2_zone_size;
+ grub_uint32_t max_file_size;
+ grub_uint16_t magic;
};
+#endif
-#else
-
+#if defined(MODE_MINIX3) || defined(MODE_MINIX2)
struct grub_minix_inode
{
grub_uint16_t mode;
grub_uint32_t unused;
};
+#else
+struct grub_minix_inode
+{
+ grub_uint16_t mode;
+ grub_uint16_t uid;
+ grub_uint16_t size;
+ grub_uint32_t ctime;
+ grub_uint8_t gid;
+ grub_uint8_t nlinks;
+ grub_uint16_t dir_zones[7];
+ grub_uint16_t indir_zone;
+ grub_uint16_t double_indir_zone;
+};
#endif
int linknest;
grub_disk_t disk;
int filename_size;
+ grub_size_t block_size;
};
static grub_dl_t my_mod;
static int
grub_minix_get_file_block (struct grub_minix_data *data, unsigned int blk)
{
- struct grub_minix_sblock *sblock = &data->sblock;
int indir;
auto int grub_get_indir (int, int);
{
grub_minix_uintn_t indirn;
grub_disk_read (data->disk,
- zone << GRUB_MINIX_LOG2_ZONESZ,
+ GRUB_MINIX_ZONE2SECT(zone),
sizeof (grub_minix_uintn_t) * num,
sizeof (grub_minix_uintn_t), (char *) &indirn);
return grub_minix_le_to_cpu_n (indirn);
}
/* Direct block. */
- if (blk < 7)
+ if (blk < GRUB_MINIX_INODE_DIR_BLOCKS)
return GRUB_MINIX_INODE_DIR_ZONES (data, blk);
/* Indirect block. */
- blk -= 7;
+ blk -= GRUB_MINIX_INODE_DIR_BLOCKS;
if (blk < GRUB_MINIX_ZONESZ / GRUB_MINIX_INODE_BLKSZ (data))
{
indir = grub_get_indir (GRUB_MINIX_INODE_INDIR_ZONE (data), blk);
grub_minix_read_file (struct grub_minix_data *data,
void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
unsigned offset, unsigned length),
- int pos, grub_disk_addr_t len, char *buf)
+ grub_off_t pos, grub_disk_addr_t len, char *buf)
{
- struct grub_minix_sblock *sblock = &data->sblock;
- int i;
- int blockcnt;
+ grub_disk_addr_t i;
+ grub_disk_addr_t blockcnt;
+ grub_uint64_t posblock;
+ grub_uint64_t blockoff;
/* Adjust len so it we can't read past the end of the file. */
if (len + pos > GRUB_MINIX_INODE_SIZE (data))
len = GRUB_MINIX_INODE_SIZE (data) - pos;
- blockcnt = (len + pos + GRUB_MINIX_BSIZE - 1) / GRUB_MINIX_BSIZE;
+ blockcnt = grub_divmod64 ((len + pos + data->block_size - 1),
+ data->block_size, 0);
+ posblock = grub_divmod64 (pos, data->block_size, &blockoff);
- for (i = pos / GRUB_MINIX_BSIZE; i < blockcnt; i++)
+ for (i = posblock; i < blockcnt; i++)
{
- int blknr;
- int blockoff = pos % GRUB_MINIX_BSIZE;
- int blockend = GRUB_MINIX_BSIZE;
-
- int skipfirst = 0;
+ grub_disk_addr_t blknr;
+ grub_uint64_t blockend = data->block_size;
+ grub_off_t skipfirst = 0;
blknr = grub_minix_get_file_block (data, i);
if (grub_errno)
/* Last block. */
if (i == blockcnt - 1)
{
- blockend = (len + pos) % GRUB_MINIX_BSIZE;
+ grub_divmod64 (len + pos, data->block_size, &blockend);
if (!blockend)
- blockend = GRUB_MINIX_BSIZE;
+ blockend = data->block_size;
}
/* First block. */
- if (i == (pos / (int) GRUB_MINIX_BSIZE))
+ if (i == posblock)
{
skipfirst = blockoff;
blockend -= skipfirst;
}
data->disk->read_hook = read_hook;
- grub_disk_read (data->disk, blknr << GRUB_MINIX_LOG2_ZONESZ,
+ grub_disk_read (data->disk,
+ GRUB_MINIX_ZONE2SECT(blknr),
skipfirst, blockend, buf);
-
data->disk->read_hook = 0;
if (grub_errno)
return -1;
- buf += GRUB_MINIX_BSIZE - skipfirst;
+ buf += data->block_size - skipfirst;
}
return len;
struct grub_minix_sblock *sblock = &data->sblock;
/* Block in which the inode is stored. */
- int block;
+ grub_disk_addr_t block;
data->ino = ino;
/* The first inode in minix is inode 1. */
ino--;
-
- block = ((2 + grub_le_to_cpu16 (sblock->inode_bmap_size)
- + grub_le_to_cpu16 (sblock->zone_bmap_size))
- << GRUB_MINIX_LOG2_BSIZE);
-
+ block = GRUB_MINIX_ZONE2SECT (2 + grub_le_to_cpu16 (sblock->inode_bmap_size)
+ + grub_le_to_cpu16 (sblock->zone_bmap_size));
block += ino / (GRUB_DISK_SECTOR_SIZE / sizeof (struct grub_minix_inode));
int offs = (ino % (GRUB_DISK_SECTOR_SIZE
/ sizeof (struct grub_minix_inode))
do
{
- grub_uint16_t ino;
+ grub_minix_ino_t ino;
char filename[data->filename_size + 1];
if (grub_strlen (name) == 0)
if (!grub_strcmp (name, filename))
{
dirino = data->ino;
- grub_minix_read_inode (data, grub_le_to_cpu16 (ino));
+ grub_minix_read_inode (data, grub_minix_le_to_cpu_ino (ino));
/* Follow the symlink. */
if ((GRUB_MINIX_INODE_MODE (data)
pos += sizeof (ino) + data->filename_size;
} while (pos < GRUB_MINIX_INODE_SIZE (data));
- grub_error (GRUB_ERR_FILE_NOT_FOUND, "file not found");
+ grub_error (GRUB_ERR_FILE_NOT_FOUND, "file `%s' not found", path);
return grub_errno;
}
goto fail;
if (grub_le_to_cpu16 (data->sblock.magic) == GRUB_MINIX_MAGIC)
+ {
+#if !defined(MODE_MINIX3)
data->filename_size = 14;
+#else
+ data->filename_size = 60;
+#endif
+ }
+#if !defined(MODE_MINIX3)
else if (grub_le_to_cpu16 (data->sblock.magic) == GRUB_MINIX_MAGIC_30)
data->filename_size = 30;
+#endif
else
goto fail;
data->disk = disk;
data->linknest = 0;
+#ifdef MODE_MINIX3
+ data->block_size = grub_le_to_cpu16 (data->sblock.block_size);
+#else
+ data->block_size = 1024U;
+#endif
return data;
fail:
grub_free (data);
-#ifdef MODE_MINIX2
+#if defined(MODE_MINIX3)
+ grub_error (GRUB_ERR_BAD_FS, "not a minix3 filesystem");
+#elif defined(MODE_MINIX2)
grub_error (GRUB_ERR_BAD_FS, "not a minix2 filesystem");
#else
grub_error (GRUB_ERR_BAD_FS, "not a minix filesystem");
while (pos < GRUB_MINIX_INODE_SIZE (data))
{
- grub_uint16_t ino;
+ grub_minix_ino_t ino;
char filename[data->filename_size + 1];
int dirino = data->ino;
struct grub_dirhook_info info;
(char *) filename) < 0)
return grub_errno;
filename[data->filename_size] = '\0';
+ if (!ino)
+ {
+ pos += sizeof (ino) + data->filename_size;
+ continue;
+ }
- /* The filetype is not stored in the dirent. Read the inode to
- find out the filetype. This *REALLY* sucks. */
- grub_minix_read_inode (data, grub_le_to_cpu16 (ino));
+ grub_minix_read_inode (data, grub_minix_le_to_cpu_ino (ino));
info.dir = ((GRUB_MINIX_INODE_MODE (data)
& GRUB_MINIX_IFDIR) == GRUB_MINIX_IFDIR);
+ info.mtimeset = 1;
+#ifndef MODE_MINIX2
+ info.mtime = grub_le_to_cpu32 (data->inode.ctime);
+#else
+ info.mtime = grub_le_to_cpu32 (data->inode.mtime);
+#endif
+
if (hook (filename, &info) ? 1 : 0)
break;
\f
static struct grub_fs grub_minix_fs =
{
-#ifdef MODE_MINIX2
+#if defined(MODE_MINIX3)
+ .name = "minix3",
+#elif defined(MODE_MINIX2)
.name = "minix2",
#else
.name = "minix",
.next = 0
};
-#ifdef MODE_MINIX2
+#if defined(MODE_MINIX3)
+GRUB_MOD_INIT(minix3)
+#elif defined(MODE_MINIX2)
GRUB_MOD_INIT(minix2)
#else
GRUB_MOD_INIT(minix)
my_mod = mod;
}
-#ifdef MODE_MINIX2
+#if defined(MODE_MINIX3)
+GRUB_MOD_FINI(minix3)
+#elif defined(MODE_MINIX2)
GRUB_MOD_FINI(minix2)
#else
GRUB_MOD_FINI(minix)
--- /dev/null
+#define MODE_MINIX3 1
+#include "minix.c"
#include <grub/types.h>
#include <grub/fshelp.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
#define NILFS_INODE_BMAP_SIZE 7
#define NILFS_SUPORT_REV 2
static inline grub_uint64_t
grub_nilfs2_palloc_group (struct grub_nilfs2_data *data,
- grub_uint64_t nr, grub_uint32_t * offset)
+ grub_uint64_t nr, grub_uint64_t * offset)
{
return grub_divmod64 (nr, grub_nilfs2_palloc_entries_per_group (data),
offset);
grub_uint64_t nr, unsigned long entry_size)
{
unsigned long group;
- grub_uint32_t group_offset;
+ grub_uint64_t group_offset;
group = grub_nilfs2_palloc_group (data, nr, &group_offset);
return grub_nilfs2_palloc_bitmap_block_offset (data, group,
entry_size) + 1 +
- group_offset / grub_nilfs2_entries_per_block (data, entry_size);
+ grub_divmod64 (group_offset, grub_nilfs2_entries_per_block (data,
+ entry_size),
+ NULL);
}
struct grub_nilfs2_dat_entry entry;
grub_disk_t disk = data->disk;
grub_uint64_t pptr;
- grub_uint32_t blockno, offset;
+ grub_uint64_t blockno, offset;
unsigned int nilfs2_block_count = (1 << LOG2_NILFS2_BLOCK_SIZE (data));
blockno = grub_nilfs2_palloc_entry_offset (data, key,
sector,
unsigned offset,
unsigned length),
- int pos, grub_size_t len, char *buf)
+ grub_off_t pos, grub_size_t len, char *buf)
{
return grub_fshelp_read_file (node->data->disk, node, read_hook,
pos, len, buf, grub_nilfs2_read_block,
struct grub_nilfs2_checkpoint *cpp)
{
grub_uint64_t blockno;
- grub_uint32_t offset;
+ grub_uint64_t offset;
grub_uint64_t pptr;
grub_disk_t disk = data->disk;
unsigned int nilfs2_block_count = (1 << LOG2_NILFS2_BLOCK_SIZE (data));
grub_uint64_t ino, struct grub_nilfs2_inode *inodep)
{
grub_uint64_t blockno;
- unsigned int offset;
+ grub_uint64_t offset;
grub_uint64_t pptr;
grub_disk_t disk = data->disk;
unsigned int nilfs2_block_count = (1 << LOG2_NILFS2_BLOCK_SIZE (data));
enum grub_fshelp_filetype filetype,
grub_fshelp_node_t node))
{
- unsigned int fpos = 0;
+ grub_off_t fpos = 0;
struct grub_fshelp_node *diro = (struct grub_fshelp_node *) dir;
if (!diro->inode_read)
#include <grub/ntfs.h>
#include <grub/charset.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
static grub_dl_t my_mod;
ntfscomp_func_t grub_ntfscomp_func;
if (at->flags & AF_GPOS)
{
grub_disk_addr_t st0, st1;
- grub_uint32_t m;
+ grub_uint64_t m;
grub_divmod64 (ofs >> BLK_SHR, ctx->comp.spc, &m);
fdiro->data = diro->data;
fdiro->ino = u32at (pos, 0);
+ if (u64at (pos, 0x20) > u64at (pos, 0x28))
+ fdiro->mtime = u64at (pos, 0x20);
+ else
+ fdiro->mtime = u64at (pos, 0x28);
ustr = grub_malloc (ns * 4 + 1);
if (ustr == NULL)
struct grub_dirhook_info info;
grub_memset (&info, 0, sizeof (info));
info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
+ info.mtimeset = 1;
+ info.mtime = grub_divmod64 (node->mtime, 10000000, 0)
+ - 86400ULL * 365 * (1970 - 1601)
+ - 86400ULL * ((1970 - 1601) / 4) + 86400ULL * ((1970 - 1601) / 100);
grub_free (node);
return hook (filename, &info);
}
#include <grub/fshelp.h>
#include <grub/ntfs.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
static grub_err_t
decomp_nextvcn (struct grub_ntfs_comp *cc)
{
#include <grub/types.h>
#include <grub/fshelp.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
#define MIN(a, b) \
({ typeof (a) _a = (a); \
typeof (b) _b = (b); \
grub_uint32_t block_number; /* 0 if node is not found. */
grub_uint16_t block_position;
grub_uint64_t next_offset;
+ grub_int32_t mtime;
enum grub_reiserfs_item_type type; /* To know how to read the header. */
struct grub_reiserfs_item_header header;
};
entry_v1_stat.rdev,
entry_v1_stat.first_direct_byte);
#endif
+ entry_item->mtime = grub_le_to_cpu32 (entry_v1_stat.mtime);
if ((grub_le_to_cpu16 (entry_v1_stat.mode) & S_IFLNK)
== S_IFLNK)
entry_type = GRUB_FSHELP_SYMLINK;
entry_v2_stat.blocks,
entry_v2_stat.first_direct_byte);
#endif
+ entry_item->mtime = grub_le_to_cpu32 (entry_v2_stat.mtime);
if ((grub_le_to_cpu16 (entry_v2_stat.mode) & S_IFLNK)
== S_IFLNK)
entry_type = GRUB_FSHELP_SYMLINK;
struct grub_dirhook_info info;
grub_memset (&info, 0, sizeof (info));
info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
+ info.mtimeset = 1;
+ info.mtime = node->mtime;
grub_free (node);
return hook (filename, &info);
}
--- /dev/null
+/*
+ * 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/file.h>
+#include <grub/types.h>
+#include <grub/dl.h>
+#include <grub/mm.h>
+#include <grub/disk.h>
+#include <grub/fs.h>
+#include <grub/fshelp.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
+
+struct grub_romfs_superblock
+{
+ char magic[8];
+#define GRUB_ROMFS_MAGIC "-rom1fs-"
+ grub_uint32_t total_size;
+ grub_uint32_t chksum;
+ char label[0];
+};
+
+struct grub_romfs_file_header
+{
+ grub_uint32_t next_file;
+ grub_uint32_t spec;
+ grub_uint32_t size;
+ grub_uint32_t chksum;
+ char name[0];
+};
+
+struct grub_romfs_data
+{
+ grub_disk_addr_t first_file;
+ grub_disk_t disk;
+};
+
+struct grub_fshelp_node
+{
+ grub_disk_addr_t addr;
+ struct grub_romfs_data *data;
+ grub_disk_addr_t data_addr;
+ /* Not filled for root. */
+ struct grub_romfs_file_header file;
+};
+
+#define GRUB_ROMFS_ALIGN 16
+#define GRUB_ROMFS_TYPE_MASK 7
+#define GRUB_ROMFS_TYPE_HARDLINK 0
+#define GRUB_ROMFS_TYPE_DIRECTORY 1
+#define GRUB_ROMFS_TYPE_REGULAR 2
+#define GRUB_ROMFS_TYPE_SYMLINK 3
+
+static grub_err_t
+do_checksum (void *in, grub_size_t insize)
+{
+ grub_uint32_t *a = in;
+ grub_size_t sz = insize / 4;
+ grub_uint32_t *b = a + sz;
+ grub_uint32_t csum = 0;
+
+ while (a < b)
+ csum += grub_be_to_cpu32 (*a++);
+ if (csum)
+ return grub_error (GRUB_ERR_BAD_FS, "invalid checksum");
+ return GRUB_ERR_NONE;
+}
+
+static struct grub_romfs_data *
+grub_romfs_mount (grub_device_t dev)
+{
+ union {
+ struct grub_romfs_superblock sb;
+ char d[512];
+ } sb;
+ grub_err_t err;
+ char *ptr;
+ grub_disk_addr_t sec = 0;
+ struct grub_romfs_data *data;
+ if (!dev->disk)
+ {
+ grub_error (GRUB_ERR_BAD_FS, "not a disk");
+ return NULL;
+ }
+ err = grub_disk_read (dev->disk, 0, 0, sizeof (sb), &sb);
+ if (err == GRUB_ERR_OUT_OF_RANGE)
+ err = grub_errno = GRUB_ERR_BAD_FS;
+ if (err)
+ return NULL;
+ if (grub_be_to_cpu32 (sb.sb.total_size) < sizeof (sb))
+ {
+ grub_error (GRUB_ERR_BAD_FS, "too short filesystem");
+ return NULL;
+ }
+ err = do_checksum (&sb, sizeof (sb) < grub_be_to_cpu32 (sb.sb.total_size) ?
+ sizeof (sb) : grub_be_to_cpu32 (sb.sb.total_size));
+ if (err)
+ return NULL;
+ for (ptr = sb.sb.label; (void *) ptr < (void *) (&sb + 1)
+ && ptr < sb.d + grub_be_to_cpu32 (sb.sb.total_size); ptr++)
+ if (!*ptr)
+ break;
+ if ((void *) ptr == &sb + 1)
+ for (sec++; ; sec++)
+ {
+ err = grub_disk_read (dev->disk, sec, 0, sizeof (sb), &sb);
+ if (err == GRUB_ERR_OUT_OF_RANGE)
+ err = grub_errno = GRUB_ERR_BAD_FS;
+ if (err)
+ return NULL;
+ for (ptr = sb.d; (void *) ptr < (void *) (&sb + 1)
+ && ptr < sb.d + grub_be_to_cpu32 (sb.sb.total_size); ptr++)
+ if (!*ptr)
+ break;
+ }
+ data = grub_malloc (sizeof (*data));
+ if (!data)
+ return NULL;
+ data->first_file = ALIGN_UP (ptr - sb.d, GRUB_ROMFS_ALIGN) + sec * 512;
+ data->disk = dev->disk;
+ return data;
+}
+
+static char *
+grub_romfs_read_symlink (grub_fshelp_node_t node)
+{
+ char *ret;
+ grub_err_t err;
+ ret = grub_malloc (grub_be_to_cpu32 (node->file.size) + 1);
+ if (!ret)
+ return NULL;
+ err = grub_disk_read (node->data->disk,
+ (node->data_addr) >> GRUB_DISK_SECTOR_BITS,
+ (node->data_addr) & (GRUB_DISK_SECTOR_SIZE - 1),
+ grub_be_to_cpu32 (node->file.size), ret);
+ if (err)
+ {
+ grub_free (ret);
+ return NULL;
+ }
+ ret[grub_be_to_cpu32 (node->file.size)] = 0;
+ return ret;
+}
+
+static int
+grub_romfs_iterate_dir (grub_fshelp_node_t dir,
+ int NESTED_FUNC_ATTR
+ (*hook) (const char *filename,
+ enum grub_fshelp_filetype filetype,
+ grub_fshelp_node_t node))
+{
+ grub_disk_addr_t caddr;
+ struct grub_romfs_file_header hdr;
+ grub_size_t a = 0;
+ char *name = NULL;
+ unsigned nptr;
+ unsigned i, j;
+ for (caddr = dir->data_addr; caddr;
+ caddr = grub_be_to_cpu32 (hdr.next_file) & ~(GRUB_ROMFS_ALIGN - 1))
+ {
+ grub_disk_addr_t naddr = caddr + sizeof (hdr);
+ grub_uint32_t csum = 0;
+ enum grub_fshelp_filetype filetype = GRUB_FSHELP_UNKNOWN;
+ struct grub_fshelp_node *node;
+ grub_err_t err;
+
+ err = grub_disk_read (dir->data->disk, caddr >> GRUB_DISK_SECTOR_BITS,
+ caddr & (GRUB_DISK_SECTOR_SIZE - 1),
+ sizeof (hdr), &hdr);
+ if (err)
+ {
+ grub_free (name);
+ return 1;
+ }
+ for (nptr = 0; ; nptr++, naddr += 16)
+ {
+ if (a >= nptr)
+ {
+ char *on;
+ a = 2 * (nptr + 1);
+ on = name;
+ name = grub_realloc (name, a * 16);
+ if (!name)
+ {
+ grub_free (on);
+ return 1;
+ }
+ }
+ err = grub_disk_read (dir->data->disk, naddr >> GRUB_DISK_SECTOR_BITS,
+ naddr & (GRUB_DISK_SECTOR_SIZE - 1),
+ 16, name + 16 * nptr);
+ if (err)
+ return 1;
+ for (j = 0; j < 16; j++)
+ if (!name[16 * nptr + j])
+ break;
+ if (j != 16)
+ break;
+ }
+ for (i = 0; i < sizeof (hdr) / sizeof (grub_uint32_t); i++)
+ csum += grub_be_to_cpu32 (((grub_uint32_t *) &hdr)[i]);
+ for (i = 0; i < (nptr + 1) * 4; i++)
+ csum += grub_be_to_cpu32 (((grub_uint32_t *) name)[i]);
+ if (csum != 0)
+ {
+ grub_error (GRUB_ERR_BAD_FS, "invalid checksum");
+ grub_free (name);
+ return 1;
+ }
+ node = grub_malloc (sizeof (*node));
+ if (!node)
+ return 1;
+ node->addr = caddr;
+ node->data_addr = caddr + (nptr + 1) * 16 + sizeof (hdr);
+ node->data = dir->data;
+ node->file = hdr;
+ switch (grub_be_to_cpu32 (hdr.next_file) & GRUB_ROMFS_TYPE_MASK)
+ {
+ case GRUB_ROMFS_TYPE_REGULAR:
+ filetype = GRUB_FSHELP_REG;
+ break;
+ case GRUB_ROMFS_TYPE_SYMLINK:
+ filetype = GRUB_FSHELP_SYMLINK;
+ break;
+ case GRUB_ROMFS_TYPE_DIRECTORY:
+ node->data_addr = grub_be_to_cpu32 (hdr.spec);
+ filetype = GRUB_FSHELP_DIR;
+ break;
+ case GRUB_ROMFS_TYPE_HARDLINK:
+ {
+ grub_disk_addr_t laddr;
+ node->addr = laddr = grub_be_to_cpu32 (hdr.spec);
+ err = grub_disk_read (dir->data->disk,
+ laddr >> GRUB_DISK_SECTOR_BITS,
+ laddr & (GRUB_DISK_SECTOR_SIZE - 1),
+ sizeof (node->file), &node->file);
+ if (err)
+ return 1;
+ if ((grub_be_to_cpu32 (node->file.next_file) & GRUB_ROMFS_TYPE_MASK)
+ == GRUB_ROMFS_TYPE_REGULAR
+ || (grub_be_to_cpu32 (node->file.next_file)
+ & GRUB_ROMFS_TYPE_MASK) == GRUB_ROMFS_TYPE_SYMLINK)
+ {
+ laddr += sizeof (hdr);
+ while (1)
+ {
+ char buf[16];
+ err = grub_disk_read (dir->data->disk,
+ laddr >> GRUB_DISK_SECTOR_BITS,
+ laddr & (GRUB_DISK_SECTOR_SIZE - 1),
+ 16, buf);
+ if (err)
+ return 1;
+ for (i = 0; i < 16; i++)
+ if (!buf[i])
+ break;
+ if (i != 16)
+ break;
+ laddr += 16;
+ }
+ node->data_addr = laddr + 16;
+ }
+ if ((grub_be_to_cpu32 (node->file.next_file)
+ & GRUB_ROMFS_TYPE_MASK) == GRUB_ROMFS_TYPE_REGULAR)
+ filetype = GRUB_FSHELP_REG;
+ if ((grub_be_to_cpu32 (node->file.next_file)
+ & GRUB_ROMFS_TYPE_MASK) == GRUB_ROMFS_TYPE_SYMLINK)
+ filetype = GRUB_FSHELP_SYMLINK;
+ if ((grub_be_to_cpu32 (node->file.next_file) & GRUB_ROMFS_TYPE_MASK)
+ == GRUB_ROMFS_TYPE_DIRECTORY)
+ {
+ node->data_addr = grub_be_to_cpu32 (node->file.spec);
+ filetype = GRUB_FSHELP_DIR;
+ }
+
+ break;
+ }
+ }
+
+ if (hook (name, filetype, node))
+ {
+ grub_free (name);
+ return 1;
+ }
+ }
+ grub_free (name);
+ return 0;
+}
+
+static grub_err_t
+grub_romfs_dir (grub_device_t device, const char *path,
+ int (*hook) (const char *filename,
+ const struct grub_dirhook_info *info))
+{
+ struct grub_romfs_data *data = 0;
+ struct grub_fshelp_node *fdiro = 0, start;
+
+ auto int NESTED_FUNC_ATTR iterate (const char *filename,
+ enum grub_fshelp_filetype filetype,
+ grub_fshelp_node_t node);
+
+ int NESTED_FUNC_ATTR iterate (const char *filename,
+ enum grub_fshelp_filetype filetype,
+ grub_fshelp_node_t node)
+ {
+ struct grub_dirhook_info info;
+ grub_memset (&info, 0, sizeof (info));
+
+ info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
+ grub_free (node);
+ return hook (filename, &info);
+ }
+
+ data = grub_romfs_mount (device);
+ if (! data)
+ goto fail;
+
+ start.addr = data->first_file;
+ start.data_addr = data->first_file;
+ start.data = data;
+ grub_fshelp_find_file (path, &start, &fdiro, grub_romfs_iterate_dir,
+ grub_romfs_read_symlink, GRUB_FSHELP_DIR);
+ if (grub_errno)
+ goto fail;
+
+ grub_romfs_iterate_dir (fdiro, iterate);
+
+ fail:
+ grub_free (data);
+
+ return grub_errno;
+}
+
+static grub_err_t
+grub_romfs_open (struct grub_file *file, const char *name)
+{
+ struct grub_romfs_data *data = 0;
+ struct grub_fshelp_node *fdiro = 0, start;
+
+ data = grub_romfs_mount (file->device);
+ if (! data)
+ goto fail;
+
+ start.addr = data->first_file;
+ start.data_addr = data->first_file;
+ start.data = data;
+
+ grub_fshelp_find_file (name, &start, &fdiro, grub_romfs_iterate_dir,
+ grub_romfs_read_symlink, GRUB_FSHELP_REG);
+ if (grub_errno)
+ goto fail;
+
+ file->size = grub_be_to_cpu32 (fdiro->file.size);
+ file->data = fdiro;
+
+ fail:
+ grub_free (data);
+
+ return grub_errno;
+}
+
+static grub_ssize_t
+grub_romfs_read (grub_file_t file, char *buf, grub_size_t len)
+{
+ struct grub_fshelp_node *data = file->data;
+
+ /* XXX: The file is stored in as a single extent. */
+ data->data->disk->read_hook = file->read_hook;
+ grub_disk_read (data->data->disk,
+ (data->data_addr + file->offset) >> GRUB_DISK_SECTOR_BITS,
+ (data->data_addr + file->offset) & (GRUB_DISK_SECTOR_SIZE - 1),
+ len, buf);
+ data->data->disk->read_hook = NULL;
+
+ if (grub_errno)
+ return -1;
+
+ return len;
+}
+
+static grub_err_t
+grub_romfs_close (grub_file_t file)
+{
+ grub_free (file->data);
+
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_romfs_label (grub_device_t device, char **label)
+{
+ struct grub_romfs_data *data;
+ grub_err_t err;
+
+ *label = NULL;
+
+ data = grub_romfs_mount (device);
+ if (!data)
+ return grub_errno;
+ *label = grub_malloc (data->first_file + 1
+ - sizeof (struct grub_romfs_superblock));
+ if (!*label)
+ {
+ grub_free (data);
+ return grub_errno;
+ }
+ err = grub_disk_read (device->disk, 0, sizeof (struct grub_romfs_superblock),
+ data->first_file
+ - sizeof (struct grub_romfs_superblock),
+ *label);
+ if (err)
+ {
+ grub_free (data);
+ grub_free (*label);
+ *label = NULL;
+ return err;
+ }
+ (*label)[data->first_file - sizeof (struct grub_romfs_superblock)] = 0;
+ return GRUB_ERR_NONE;
+}
+
+
+static struct grub_fs grub_romfs_fs =
+ {
+ .name = "romfs",
+ .dir = grub_romfs_dir,
+ .open = grub_romfs_open,
+ .read = grub_romfs_read,
+ .close = grub_romfs_close,
+ .label = grub_romfs_label,
+#ifdef GRUB_UTIL
+ .reserved_first_sector = 0,
+#endif
+ .next = 0
+ };
+
+GRUB_MOD_INIT(romfs)
+{
+ grub_fs_register (&grub_romfs_fs);
+}
+
+GRUB_MOD_FINI(romfs)
+{
+ grub_fs_unregister (&grub_romfs_fs);
+}
#include <grub/types.h>
#include <grub/fshelp.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
/* The common header for a block. */
struct grub_sfs_bheader
{
grub_uint32_t dir_objc;
} dir __attribute__ ((packed));
} file_dir;
- grub_uint8_t unused3[4];
+ grub_uint32_t mtime;
grub_uint8_t type;
grub_uint8_t filename[1];
grub_uint8_t comment[1];
struct grub_sfs_data *data;
int block;
int size;
+ grub_uint32_t mtime;
};
/* Information about a "mounted" sfs filesystem. */
grub_sfs_read_file (grub_fshelp_node_t node,
void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
unsigned offset, unsigned length),
- int pos, grub_size_t len, char *buf)
+ grub_off_t pos, grub_size_t len, char *buf)
{
return grub_fshelp_read_file (node->data->disk, node, read_hook,
pos, len, buf, grub_sfs_read_block,
int pos;
auto int NESTED_FUNC_ATTR grub_sfs_create_node (const char *name, int block,
- int size, int type);
+ int size, int type,
+ grub_uint32_t mtime);
int NESTED_FUNC_ATTR grub_sfs_create_node (const char *name, int block,
- int size, int type)
+ int size, int type,
+ grub_uint32_t mtime)
{
node = grub_malloc (sizeof (*node));
if (!node)
node->data = data;
node->size = size;
node->block = block;
+ node->mtime = mtime;
return hook (name, type, node);
}
if (grub_sfs_create_node (filename, block,
grub_be_to_cpu32 (obj->file_dir.file.size),
- type))
+ type, grub_be_to_cpu32 (obj->mtime)))
{
grub_free (objc_data);
return 1;
struct grub_dirhook_info info;
grub_memset (&info, 0, sizeof (info));
info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
+ info.mtime = node->mtime + 8 * 365 * 86400 + 86400 * 2;
+ info.mtimeset = 1;
grub_free (node);
return hook (filename, &info);
}
--- /dev/null
+/* squash4.c - SquashFS */
+/*
+ * 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>
+#include <grub/fshelp.h>
+#include <grub/deflate.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
+
+/*
+ object format Pointed by
+ superblock RAW Fixed offset (0)
+ data RAW ? Fixed offset (60)
+ inode table Chunk superblock
+ dir table Chunk superblock
+ fragment table Chunk unk1
+ unk1 RAW, Chunk superblock
+ unk2 RAW superblock
+ UID/GID Chunk exttblptr
+ exttblptr RAW superblock
+
+ UID/GID table is the array ot uint32_t
+ unk1 contains pointer to unk3 followed by some chunk.
+ unk2 containts one uint64_t
+*/
+
+struct grub_squash_super
+{
+ grub_uint32_t magic;
+#define SQUASH_MAGIC 0x73717368
+ grub_uint32_t dummy1;
+ grub_uint32_t creation_time;
+ grub_uint32_t dummy2;
+ grub_uint64_t dummy3;
+ grub_uint8_t flags;
+#define SQUASH_FLAG_UNCOMPRESSED_INODES 1
+#define SQUASH_FLAG_UNCOMPRESSED_DATA 2
+#define SQUASH_FLAG_UNCOMPRESSED_FRAGMENTS 8
+ grub_uint8_t dummy4[7];
+ grub_uint16_t root_ino_offset;
+ grub_uint32_t root_ino_chunk;
+ grub_uint16_t dummy5;
+ grub_uint64_t total_size;
+ grub_uint64_t exttbloffset;
+ grub_uint64_t dummy6;
+ grub_uint64_t inodeoffset;
+ grub_uint64_t diroffset;
+ grub_uint64_t unk1offset;
+ grub_uint64_t unk2offset;
+} __attribute__ ((packed));
+
+
+/* Chunk-based */
+struct grub_squash_inode
+{
+ /* Same values as direlem types. */
+ grub_uint16_t type;
+ grub_uint16_t dummy[3];
+ grub_uint32_t mtime;
+ union
+ {
+ struct {
+ grub_uint32_t dummy;
+ grub_uint32_t chunk;
+ grub_uint32_t fragment;
+ grub_uint32_t offset;
+ grub_uint32_t size;
+ } __attribute__ ((packed)) file;
+ struct {
+ grub_uint32_t dummy1;
+ grub_uint32_t chunk;
+ grub_uint32_t dummy2;
+ grub_uint16_t size;
+ grub_uint32_t offset;
+ grub_uint16_t dummy3;
+ } __attribute__ ((packed)) dir;
+ struct {
+ grub_uint64_t dummy;
+ grub_uint32_t namelen;
+ char name[0];
+ } __attribute__ ((packed)) symlink;
+ } __attribute__ ((packed));
+} __attribute__ ((packed));
+
+/* Chunk-based. */
+struct grub_squash_dirent_header
+{
+ /* Actually the value is the number of elements - 1. */
+ grub_uint32_t nelems;
+ grub_uint64_t ino_chunk;
+} __attribute__ ((packed));
+
+struct grub_squash_dirent
+{
+ grub_uint16_t ino_offset;
+ grub_uint16_t dummy;
+ grub_uint16_t type;
+#define SQUASH_TYPE_DIR 1
+#define SQUASH_TYPE_REGULAR 2
+#define SQUASH_TYPE_SYMLINK 3
+ /* Actually the value is the length of name - 1. */
+ grub_uint16_t namelen;
+ char name[0];
+} __attribute__ ((packed));
+
+struct grub_squash_frag_desc
+{
+ grub_uint64_t offset;
+ grub_uint64_t dummy;
+} __attribute__ ((packed));
+
+#define SQUASH_CHUNK_SIZE 0x2000
+#define SQUASH_CHUNK_FLAGS 0x8000
+#define SQUASH_CHUNK_UNCOMPRESSED 0x8000
+
+struct grub_squash_data
+{
+ grub_disk_t disk;
+ struct grub_squash_super sb;
+ struct grub_squash_inode ino;
+ grub_uint64_t fragments;
+};
+
+struct grub_fshelp_node
+{
+ struct grub_squash_data *data;
+ struct grub_squash_inode ino;
+ grub_uint32_t ino_chunk;
+ grub_uint16_t ino_offset;
+};
+
+static grub_err_t
+read_chunk (grub_disk_t disk, void *buf, grub_size_t len,
+ grub_uint64_t chunk, grub_off_t offset)
+{
+ grub_uint64_t chunk_start;
+ chunk_start = grub_le_to_cpu64 (chunk);
+ while (len > 0)
+ {
+ grub_uint64_t csize;
+ grub_uint16_t d;
+ grub_err_t err;
+ while (1)
+ {
+ err = grub_disk_read (disk, chunk_start >> GRUB_DISK_SECTOR_BITS,
+ chunk_start & (GRUB_DISK_SECTOR_SIZE - 1),
+ sizeof (d), &d);
+ if (err)
+ return err;
+ if (offset < SQUASH_CHUNK_SIZE)
+ break;
+ offset -= SQUASH_CHUNK_SIZE;
+ chunk_start += 2 + (grub_le_to_cpu16 (d) & ~SQUASH_CHUNK_FLAGS);
+ }
+
+ csize = SQUASH_CHUNK_SIZE - offset;
+ if (csize > len)
+ csize = len;
+
+ if (grub_le_to_cpu16 (d) & SQUASH_CHUNK_UNCOMPRESSED)
+ {
+ grub_disk_addr_t a = chunk_start + 2 + offset;
+ err = grub_disk_read (disk, (a >> GRUB_DISK_SECTOR_BITS),
+ a & (GRUB_DISK_SECTOR_SIZE - 1),
+ csize, buf);
+ if (err)
+ return err;
+ }
+ else
+ {
+ char *tmp;
+ grub_size_t bsize = grub_le_to_cpu16 (d) & ~SQUASH_CHUNK_FLAGS;
+ grub_disk_addr_t a = chunk_start + 2;
+ tmp = grub_malloc (bsize);
+ if (!tmp)
+ return grub_errno;
+ /* FIXME: buffer uncompressed data. */
+ err = grub_disk_read (disk, (a >> GRUB_DISK_SECTOR_BITS),
+ a & (GRUB_DISK_SECTOR_SIZE - 1),
+ bsize, tmp);
+ if (err)
+ {
+ grub_free (tmp);
+ return err;
+ }
+
+ if (grub_zlib_decompress (tmp, bsize, offset,
+ buf, csize) < 0)
+ {
+ grub_free (tmp);
+ return grub_errno;
+ }
+ grub_free (tmp);
+ }
+ len -= csize;
+ offset += csize;
+ buf = (char *) buf + csize;
+ }
+ return GRUB_ERR_NONE;
+}
+
+static struct grub_squash_data *
+squash_mount (grub_disk_t disk)
+{
+ struct grub_squash_super sb;
+ grub_err_t err;
+ struct grub_squash_data *data;
+ grub_uint64_t frag;
+
+ err = grub_disk_read (disk, 0, 0, sizeof (sb), &sb);
+ if (grub_errno == GRUB_ERR_OUT_OF_RANGE)
+ grub_error (GRUB_ERR_BAD_FS, "not a squash4");
+ if (err)
+ return NULL;
+ if (grub_le_to_cpu32 (sb.magic) != SQUASH_MAGIC)
+ {
+ grub_error (GRUB_ERR_BAD_FS, "not squash4");
+ return NULL;
+ }
+
+ err = grub_disk_read (disk, grub_le_to_cpu32 (sb.unk1offset)
+ >> GRUB_DISK_SECTOR_BITS,
+ grub_le_to_cpu32 (sb.unk1offset)
+ & (GRUB_DISK_SECTOR_SIZE - 1), sizeof (frag), &frag);
+ if (grub_errno == GRUB_ERR_OUT_OF_RANGE)
+ grub_error (GRUB_ERR_BAD_FS, "not a squash4");
+ if (err)
+ return NULL;
+
+ data = grub_malloc (sizeof (*data));
+ if (!data)
+ return NULL;
+ data->sb = sb;
+ data->disk = disk;
+ data->fragments = frag;
+
+ return data;
+}
+
+static char *
+grub_squash_read_symlink (grub_fshelp_node_t node)
+{
+ char *ret;
+ grub_err_t err;
+ ret = grub_malloc (grub_le_to_cpu32 (node->ino.symlink.namelen) + 1);
+
+ err = read_chunk (node->data->disk, ret,
+ grub_le_to_cpu32 (node->ino.symlink.namelen),
+ grub_le_to_cpu64 (node->data->sb.inodeoffset)
+ + node->ino_chunk,
+ node->ino_offset + (node->ino.symlink.name
+ - (char *) &node->ino));
+ if (err)
+ {
+ grub_free (ret);
+ return NULL;
+ }
+ ret[grub_le_to_cpu32 (node->ino.symlink.namelen)] = 0;
+ return ret;
+}
+
+static int
+grub_squash_iterate_dir (grub_fshelp_node_t dir,
+ int NESTED_FUNC_ATTR
+ (*hook) (const char *filename,
+ enum grub_fshelp_filetype filetype,
+ grub_fshelp_node_t node))
+{
+ grub_uint32_t off = grub_le_to_cpu16 (dir->ino.dir.offset);
+ grub_uint32_t endoff;
+ unsigned i;
+
+ /* FIXME: why - 3 ? */
+ endoff = grub_le_to_cpu32 (dir->ino.dir.size) + off - 3;
+
+ while (off < endoff)
+ {
+ struct grub_squash_dirent_header dh;
+ grub_err_t err;
+
+ err = read_chunk (dir->data->disk, &dh, sizeof (dh),
+ grub_le_to_cpu64 (dir->data->sb.diroffset)
+ + grub_le_to_cpu32 (dir->ino.dir.chunk), off);
+ if (err)
+ return 0;
+ off += sizeof (dh);
+ for (i = 0; i < (unsigned) grub_le_to_cpu16 (dh.nelems) + 1; i++)
+ {
+ char *buf;
+ int r;
+ struct grub_fshelp_node *node;
+ enum grub_fshelp_filetype filetype = GRUB_FSHELP_REG;
+ struct grub_squash_dirent di;
+ struct grub_squash_inode ino;
+
+ err = read_chunk (dir->data->disk, &di, sizeof (di),
+ grub_le_to_cpu64 (dir->data->sb.diroffset)
+ + grub_le_to_cpu32 (dir->ino.dir.chunk), off);
+ if (err)
+ return 0;
+ off += sizeof (di);
+
+ err = read_chunk (dir->data->disk, &ino, sizeof (ino),
+ grub_le_to_cpu64 (dir->data->sb.inodeoffset)
+ + grub_le_to_cpu32 (dh.ino_chunk),
+ grub_cpu_to_le16 (di.ino_offset));
+ if (err)
+ return 0;
+
+ buf = grub_malloc (grub_le_to_cpu16 (di.namelen) + 2);
+ if (!buf)
+ return 0;
+ err = read_chunk (dir->data->disk, buf,
+ grub_le_to_cpu16 (di.namelen) + 1,
+ grub_le_to_cpu64 (dir->data->sb.diroffset)
+ + grub_le_to_cpu32 (dir->ino.dir.chunk), off);
+ if (err)
+ return 0;
+
+ off += grub_le_to_cpu16 (di.namelen) + 1;
+ buf[grub_le_to_cpu16 (di.namelen) + 1] = 0;
+ if (grub_le_to_cpu16 (di.type) == SQUASH_TYPE_DIR)
+ filetype = GRUB_FSHELP_DIR;
+ if (grub_le_to_cpu16 (di.type) == SQUASH_TYPE_SYMLINK)
+ filetype = GRUB_FSHELP_SYMLINK;
+
+ node = grub_malloc (sizeof (*node));
+ if (! node)
+ return 0;
+ *node = *dir;
+ node->ino = ino;
+ node->ino_chunk = grub_le_to_cpu32 (dh.ino_chunk);
+ node->ino_offset = grub_le_to_cpu16 (di.ino_offset);
+
+ r = hook (buf, filetype, node);
+
+ grub_free (buf);
+ if (r)
+ return r;
+ }
+ }
+ return 0;
+}
+
+static grub_err_t
+make_root_node (struct grub_squash_data *data, struct grub_fshelp_node *root)
+{
+ grub_memset (root, 0, sizeof (*root));
+ root->data = data;
+
+ return read_chunk (data->disk, &root->ino, sizeof (root->ino),
+ grub_le_to_cpu64 (data->sb.inodeoffset)
+ + grub_le_to_cpu16 (data->sb.root_ino_chunk),
+ grub_cpu_to_le16 (data->sb.root_ino_offset));
+}
+
+static grub_err_t
+grub_squash_dir (grub_device_t device, const char *path,
+ int (*hook) (const char *filename,
+ const struct grub_dirhook_info *info))
+{
+ auto int NESTED_FUNC_ATTR iterate (const char *filename,
+ enum grub_fshelp_filetype filetype,
+ grub_fshelp_node_t node);
+
+ int NESTED_FUNC_ATTR iterate (const char *filename,
+ enum grub_fshelp_filetype filetype,
+ grub_fshelp_node_t node)
+ {
+ struct grub_dirhook_info info;
+ grub_memset (&info, 0, sizeof (info));
+ info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
+ info.mtimeset = 1;
+ info.mtime = grub_le_to_cpu32 (node->ino.mtime);
+ return hook (filename, &info);
+ }
+
+ struct grub_squash_data *data = 0;
+ struct grub_fshelp_node *fdiro = 0;
+ struct grub_fshelp_node root;
+ grub_err_t err;
+
+ data = squash_mount (device->disk);
+ if (! data)
+ return grub_errno;
+
+ err = make_root_node (data, &root);
+ if (err)
+ return err;
+
+ grub_fshelp_find_file (path, &root, &fdiro, grub_squash_iterate_dir,
+ grub_squash_read_symlink, GRUB_FSHELP_DIR);
+ if (!grub_errno)
+ grub_squash_iterate_dir (fdiro, iterate);
+
+ grub_free (data);
+
+ return grub_errno;
+}
+
+static grub_err_t
+grub_squash_open (struct grub_file *file, const char *name)
+{
+ struct grub_squash_data *data = 0;
+ struct grub_fshelp_node *fdiro = 0;
+ struct grub_fshelp_node root;
+ grub_err_t err;
+
+ data = squash_mount (file->device->disk);
+ if (! data)
+ return grub_errno;
+
+ err = make_root_node (data, &root);
+ if (err)
+ return err;
+
+ grub_fshelp_find_file (name, &root, &fdiro, grub_squash_iterate_dir,
+ grub_squash_read_symlink, GRUB_FSHELP_REG);
+ if (grub_errno)
+ {
+ grub_free (data);
+ return grub_errno;
+ }
+
+ file->data = data;
+ data->ino = fdiro->ino;
+ file->size = grub_le_to_cpu32 (fdiro->ino.file.size);
+
+ return GRUB_ERR_NONE;
+}
+
+static grub_ssize_t
+grub_squash_read_data (struct grub_squash_data *data,
+ grub_disk_t disk, const struct grub_squash_inode *ino,
+ grub_off_t off, char *buf, grub_size_t len)
+{
+ grub_err_t err;
+ grub_uint64_t a, b;
+ int compressed = 0;
+
+ if (grub_le_to_cpu16 (ino->file.fragment) == 0xffff)
+ {
+ if (grub_le_to_cpu32 (ino->file.chunk))
+ a = grub_le_to_cpu32 (ino->file.chunk);
+ else
+ a = sizeof (struct grub_squash_super);
+ compressed = !(data->sb.flags & SQUASH_FLAG_UNCOMPRESSED_DATA);
+ }
+ else
+ {
+ struct grub_squash_frag_desc frag;
+ err = read_chunk (disk, &frag, sizeof (frag),
+ data->fragments, sizeof (frag)
+ * grub_le_to_cpu16 (ino->file.fragment));
+ if (err)
+ return -1;
+ a = grub_le_to_cpu64 (frag.offset) + grub_le_to_cpu32 (ino->file.chunk);
+ compressed = !(data->sb.flags & SQUASH_FLAG_UNCOMPRESSED_FRAGMENTS);
+ }
+
+ b = grub_le_to_cpu32 (data->ino.file.offset) + off;
+
+ /* FIXME: cache uncompressed chunks. */
+ if (compressed)
+ err = grub_zlib_disk_read (disk, a, b, buf, len);
+ else
+ err = grub_disk_read (disk, (a + b) >> GRUB_DISK_SECTOR_BITS,
+ (a + b) & (GRUB_DISK_SECTOR_SIZE - 1), len, buf);
+ if (err)
+ return -1;
+ return len;
+}
+
+static grub_ssize_t
+grub_squash_read (grub_file_t file, char *buf, grub_size_t len)
+{
+ struct grub_squash_data *data = file->data;
+
+ return grub_squash_read_data (data, file->device->disk, &data->ino,
+ file->offset, buf, len);
+}
+
+static grub_err_t
+grub_squash_close (grub_file_t file)
+{
+ grub_free (file->data);
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_squash_mtime (grub_device_t dev, grub_int32_t *tm)
+{
+ struct grub_squash_data *data = 0;
+
+ data = squash_mount (dev->disk);
+ if (! data)
+ return grub_errno;
+ *tm = grub_le_to_cpu32 (data->sb.creation_time);
+ grub_free (data);
+ return GRUB_ERR_NONE;
+}
+
+static struct grub_fs grub_squash_fs =
+ {
+ .name = "squash4",
+ .dir = grub_squash_dir,
+ .open = grub_squash_open,
+ .read = grub_squash_read,
+ .close = grub_squash_close,
+ .mtime = grub_squash_mtime,
+#ifdef GRUB_UTIL
+ .reserved_first_sector = 0,
+#endif
+ .next = 0
+ };
+
+GRUB_MOD_INIT(squash4)
+{
+ grub_fs_register (&grub_squash_fs);
+}
+
+GRUB_MOD_FINI(squash4)
+{
+ grub_fs_unregister (&grub_squash_fs);
+}
+
#include <grub/types.h>
#include <grub/fshelp.h>
#include <grub/charset.h>
+#include <grub/datetime.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
#define GRUB_UDF_MAX_PDS 2
#define GRUB_UDF_MAX_PMS 6
}
fail:
- if (buf)
- grub_free (buf);
+ grub_free (buf);
return 0;
}
type = ((dirent.characteristics & GRUB_UDF_FID_CHAR_DIRECTORY) ?
(GRUB_FSHELP_DIR) : (GRUB_FSHELP_REG));
+ if (child->fe.icbtag.file_type == GRUB_UDF_ICBTAG_TYPE_SYMLINK)
+ type = GRUB_FSHELP_SYMLINK;
if ((grub_udf_read_file (dir, 0, offset,
dirent.file_ident_length,
return 0;
}
+static char *
+grub_ufs_read_symlink (grub_fshelp_node_t node)
+{
+ grub_size_t sz = U64 (node->fe.file_size);
+ grub_uint8_t *raw;
+ char *ret;
+
+ if (sz < 4)
+ return NULL;
+ raw = grub_malloc (sz - 4);
+ if (!raw)
+ return NULL;
+ if (grub_udf_read_file (node, NULL, 4, sz - 4, (char *) raw) < 0)
+ return NULL;
+ ret = read_string (raw, sz - 4);
+ grub_free (raw);
+ return ret;
+}
+
static grub_err_t
grub_udf_dir (grub_device_t device, const char *path,
int (*hook) (const char *filename,
grub_fshelp_node_t node)
{
struct grub_dirhook_info info;
+ const struct grub_udf_timestamp *tstamp = NULL;
grub_memset (&info, 0, sizeof (info));
info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
+ if (U16 (node->fe.tag.tag_ident) == GRUB_UDF_TAG_IDENT_FE)
+ tstamp = &node->fe.modification_time;
+ else if (U16 (node->fe.tag.tag_ident) == GRUB_UDF_TAG_IDENT_EFE)
+ tstamp = &node->efe.modification_time;
+
+ if (tstamp && (U16 (tstamp->type_and_timezone) & 0xf000) == 0x1000)
+ {
+ grub_int16_t tz;
+ struct grub_datetime datetime;
+
+ datetime.year = U16 (tstamp->year);
+ datetime.month = tstamp->month;
+ datetime.day = tstamp->day;
+ datetime.hour = tstamp->hour;
+ datetime.minute = tstamp->minute;
+ datetime.second = tstamp->second;
+
+ tz = U16 (tstamp->type_and_timezone) & 0xfff;
+ if (tz & 0x800)
+ tz |= 0xf000;
+ if (tz == -2047)
+ tz = 0;
+
+ info.mtimeset = !!grub_datetime2unixtime (&datetime, &info.mtime);
+
+ info.mtime -= 60 * tz;
+ }
grub_free (node);
return hook (filename, &info);
}
if (grub_fshelp_find_file (path, &rootnode,
&foundnode,
- grub_udf_iterate_dir, 0, GRUB_FSHELP_DIR))
+ grub_udf_iterate_dir, grub_ufs_read_symlink,
+ GRUB_FSHELP_DIR))
goto fail;
grub_udf_iterate_dir (foundnode, iterate);
if (grub_fshelp_find_file (name, &rootnode,
&foundnode,
- grub_udf_iterate_dir, 0, GRUB_FSHELP_REG))
+ grub_udf_iterate_dir, grub_ufs_read_symlink,
+ GRUB_FSHELP_REG))
goto fail;
file->data = foundnode;
#include <grub/dl.h>
#include <grub/types.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
#ifdef MODE_UFS2
#define GRUB_UFS_MAGIC 0x19540119
#else
grub_ufs_read_file (struct grub_ufs_data *data,
void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
unsigned offset, unsigned length),
- int pos, grub_size_t len, char *buf)
+ grub_off_t pos, grub_size_t len, char *buf)
{
struct grub_ufs_sblock *sblock = &data->sblock;
- int i;
- int blockcnt;
+ grub_off_t i;
+ grub_off_t blockcnt;
/* Adjust len so it we can't read past the end of the file. */
if (len + pos > INODE_SIZE (data))
len = INODE_SIZE (data) - pos;
- blockcnt = (len + pos + UFS_BLKSZ (sblock) - 1) / UFS_BLKSZ (sblock);
+ blockcnt = grub_divmod64 ((len + pos + UFS_BLKSZ (sblock) - 1),
+ UFS_BLKSZ (sblock), 0);
- for (i = pos / UFS_BLKSZ (sblock); i < blockcnt; i++)
+ for (i = grub_divmod64 (pos, UFS_BLKSZ (sblock), 0); i < blockcnt; i++)
{
- int blknr;
- int blockoff = pos % UFS_BLKSZ (sblock);
- int blockend = UFS_BLKSZ (sblock);
+ grub_disk_addr_t blknr;
+ grub_off_t blockoff;
+ grub_off_t blockend = UFS_BLKSZ (sblock);
int skipfirst = 0;
+ grub_divmod64 (pos, UFS_BLKSZ (sblock), &blockoff);
+
blknr = grub_ufs_get_file_block (data, i);
if (grub_errno)
return -1;
/* Last block. */
if (i == blockcnt - 1)
{
- blockend = (len + pos) % UFS_BLKSZ (sblock);
+ grub_divmod64 (len + pos, UFS_BLKSZ (sblock), &blockend);
if (!blockend)
blockend = UFS_BLKSZ (sblock);
}
/* First block. */
- if (i == (pos / (int) UFS_BLKSZ (sblock)))
+ if (i == grub_divmod64 (pos, UFS_BLKSZ (sblock), 0))
{
skipfirst = blockoff;
blockend -= skipfirst;
pos += grub_le_to_cpu16 (dirent.direntlen);
} while (pos < INODE_SIZE (data));
- grub_error (GRUB_ERR_FILE_NOT_FOUND, "file not found");
+ grub_error (GRUB_ERR_FILE_NOT_FOUND, "file `%s' not found", path);
return grub_errno;
}
#include <grub/types.h>
#include <grub/fshelp.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
#define XFS_INODE_EXTENTS 9
#define XFS_INODE_FORMAT_INO 1
grub_uint64_t keys[1];
} __attribute__ ((packed));
+struct grub_xfs_time
+{
+ grub_uint32_t sec;
+ grub_uint32_t nanosec;
+} __attribute__ ((packed));
+
struct grub_xfs_inode
{
grub_uint8_t magic[2];
grub_uint16_t mode;
grub_uint8_t version;
grub_uint8_t format;
- grub_uint8_t unused2[50];
+ grub_uint8_t unused2[26];
+ struct grub_xfs_time atime;
+ struct grub_xfs_time mtime;
+ struct grub_xfs_time ctime;
grub_uint64_t size;
grub_uint64_t nblocks;
grub_uint32_t extsize;
grub_uint32_t nextents;
- grub_uint8_t unused3[20];
+ grub_uint16_t unused3;
+ grub_uint8_t fork_offset;
+ grub_uint8_t unused4[17];
union
{
char raw[156];
grub_disk_t disk;
int pos;
int bsize;
- int agsize;
+ grub_uint32_t agsize;
struct grub_fshelp_node diropen;
};
#define FILETYPE_INO_DIRECTORY 0040000
#define FILETYPE_INO_SYMLINK 0120000
-#define GRUB_XFS_INO_AGBITS(data) \
- ((data)->sblock.log2_agblk + (data)->sblock.log2_inop)
-#define GRUB_XFS_INO_INOINAG(data, ino) \
- (grub_be_to_cpu64 (ino) & ((1LL << GRUB_XFS_INO_AGBITS (data)) - 1))
-#define GRUB_XFS_INO_AG(data,ino) \
- (grub_be_to_cpu64 (ino) >> GRUB_XFS_INO_AGBITS (data))
-
-#define GRUB_XFS_FSB_TO_BLOCK(data, fsb) \
- (((fsb) >> (data)->sblock.log2_agblk) * (data)->agsize \
- + ((fsb) & ((1LL << (data)->sblock.log2_agblk) - 1)))
-
-#define GRUB_XFS_EXTENT_OFFSET(exts,ex) \
- ((grub_be_to_cpu32 (exts[ex][0]) & ~(1 << 31)) << 23 \
- | grub_be_to_cpu32 (exts[ex][1]) >> 9)
-
-#define GRUB_XFS_EXTENT_BLOCK(exts,ex) \
- ((grub_uint64_t) (grub_be_to_cpu32 (exts[ex][1]) \
- & (0x1ff)) << 43 \
- | (grub_uint64_t) grub_be_to_cpu32 (exts[ex][2]) << 11 \
- | grub_be_to_cpu32 (exts[ex][3]) >> 21)
-
-#define GRUB_XFS_EXTENT_SIZE(exts,ex) \
- (grub_be_to_cpu32 (exts[ex][3]) & ((1 << 20) - 1))
-
-#define GRUB_XFS_ROUND_TO_DIRENT(pos) ((((pos) + 8 - 1) / 8) * 8)
-#define GRUB_XFS_NEXT_DIRENT(pos,len) \
- (pos) + GRUB_XFS_ROUND_TO_DIRENT (8 + 1 + len + 2)
+static inline int
+GRUB_XFS_INO_AGBITS(struct grub_xfs_data *data)
+{
+ return ((data)->sblock.log2_agblk + (data)->sblock.log2_inop);
+}
+
+static inline grub_uint64_t
+GRUB_XFS_INO_INOINAG (struct grub_xfs_data *data,
+ grub_uint64_t ino)
+{
+ return (grub_be_to_cpu64 (ino) & ((1LL << GRUB_XFS_INO_AGBITS (data)) - 1));
+}
+
+static inline grub_uint64_t
+GRUB_XFS_INO_AG (struct grub_xfs_data *data,
+ grub_uint64_t ino)
+{
+ return (grub_be_to_cpu64 (ino) >> GRUB_XFS_INO_AGBITS (data));
+}
+
+static inline grub_disk_addr_t
+GRUB_XFS_FSB_TO_BLOCK (struct grub_xfs_data *data, grub_disk_addr_t fsb)
+{
+ return ((fsb >> data->sblock.log2_agblk) * data->agsize
+ + (fsb & ((1LL << data->sblock.log2_agblk) - 1)));
+}
+
+static inline grub_uint64_t
+GRUB_XFS_EXTENT_OFFSET (grub_xfs_extent *exts, int ex)
+{
+ return ((grub_be_to_cpu32 (exts[ex][0]) & ~(1 << 31)) << 23
+ | grub_be_to_cpu32 (exts[ex][1]) >> 9);
+}
+
+static inline grub_uint64_t
+GRUB_XFS_EXTENT_BLOCK (grub_xfs_extent *exts, int ex)
+{
+ return ((grub_uint64_t) (grub_be_to_cpu32 (exts[ex][1])
+ & (0x1ff)) << 43
+ | (grub_uint64_t) grub_be_to_cpu32 (exts[ex][2]) << 11
+ | grub_be_to_cpu32 (exts[ex][3]) >> 21);
+}
+
+static inline grub_uint64_t
+GRUB_XFS_EXTENT_SIZE (grub_xfs_extent *exts, int ex)
+{
+ return (grub_be_to_cpu32 (exts[ex][3]) & ((1 << 20) - 1));
+}
+
+static inline int
+GRUB_XFS_ROUND_TO_DIRENT (int pos)
+{
+ return ((((pos) + 8 - 1) / 8) * 8);
+}
+
+static inline int
+GRUB_XFS_NEXT_DIRENT (int pos, int len)
+{
+ return (pos) + GRUB_XFS_ROUND_TO_DIRENT (8 + 1 + len + 2);
+}
+
\f
static inline grub_uint64_t
grub_xfs_inode_block (struct grub_xfs_data *data,
if (node->inode.format == XFS_INODE_FORMAT_BTREE)
{
grub_uint64_t *keys;
+ int recoffset;
- leaf = grub_malloc (node->data->sblock.bsize);
+ leaf = grub_malloc (node->data->bsize);
if (leaf == 0)
return 0;
nrec = grub_be_to_cpu16 (node->inode.data.btree.numrecs);
keys = &node->inode.data.btree.keys[0];
+ if (node->inode.fork_offset)
+ recoffset = (node->inode.fork_offset
+ - ((char *) &node->inode.data.btree.keys - (char *) &node->inode))
+ / (2 * sizeof (grub_uint64_t));
+ else
+ recoffset = ((1 << node->data->sblock.log2_inode)
+ - ((char *) &node->inode.data.btree.keys
+ - (char *) &node->inode))
+ / (2 * sizeof (grub_uint64_t));
do
{
int i;
grub_free (leaf);
return 0;
}
-
if (grub_disk_read (node->data->disk,
- grub_be_to_cpu64 (keys[i - 1 + nrec])
- << (node->data->sblock.log2_bsize
- - GRUB_DISK_SECTOR_BITS),
- 0, node->data->sblock.bsize, leaf))
+ GRUB_XFS_FSB_TO_BLOCK (node->data, grub_be_to_cpu64 (keys[i - 1 + recoffset])) << (node->data->sblock.log2_bsize - GRUB_DISK_SECTOR_BITS),
+ 0, node->data->bsize, leaf))
return 0;
if (grub_strncmp ((char *) leaf->magic, "BMAP", 4))
nrec = grub_be_to_cpu16 (leaf->numrecs);
keys = &leaf->keys[0];
- } while (leaf->level);
+ recoffset = ((node->data->bsize - ((char *) &leaf->keys
+ - (char *) leaf))
+ / (2 * sizeof (grub_uint64_t)));
+ }
+ while (leaf->level);
exts = (grub_xfs_extent *) keys;
}
else if (node->inode.format == XFS_INODE_FORMAT_EXT)
}
}
- if (leaf)
- grub_free (leaf);
+ grub_free (leaf);
return GRUB_XFS_FSB_TO_BLOCK(node->data, ret);
}
grub_xfs_read_file (grub_fshelp_node_t node,
void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
unsigned offset, unsigned length),
- int pos, grub_size_t len, char *buf)
+ grub_off_t pos, grub_size_t len, char *buf)
{
return grub_fshelp_read_file (node->data->disk, node, read_hook,
pos, len, buf, grub_xfs_read_block,
{
struct grub_dirhook_info info;
grub_memset (&info, 0, sizeof (info));
+ if (node->inode_read)
+ {
+ info.mtimeset = 1;
+ info.mtime = grub_be_to_cpu32 (node->inode.mtime.sec);
+ }
info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
grub_free (node);
return hook (filename, &info);
#include <grub/zfs/sa_impl.h>
#include <grub/zfs/dsl_dir.h>
#include <grub/zfs/dsl_dataset.h>
+#include <grub/deflate.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
#define ZPOOL_PROP_BOOTFS "bootfs"
grub_disk_addr_t vdev_phys_sector;
};
+static grub_err_t
+zlib_decompress (void *s, void *d,
+ grub_size_t slen, grub_size_t dlen)
+{
+ if (grub_zlib_decompress (s, slen, 0, d, dlen) < 0)
+ return grub_errno;
+ return GRUB_ERR_NONE;
+}
+
static decomp_entry_t decomp_table[ZIO_COMPRESS_FUNCTIONS] = {
{"inherit", NULL}, /* ZIO_COMPRESS_INHERIT */
{"on", lzjb_decompress}, /* ZIO_COMPRESS_ON */
{"off", NULL}, /* ZIO_COMPRESS_OFF */
{"lzjb", lzjb_decompress}, /* ZIO_COMPRESS_LZJB */
{"empty", NULL}, /* ZIO_COMPRESS_EMPTY */
- {"gzip", NULL}, /* ZIO_COMPRESS_GZIP */
+ {"gzip-1", zlib_decompress}, /* ZIO_COMPRESS_GZIP1 */
+ {"gzip-2", zlib_decompress}, /* ZIO_COMPRESS_GZIP2 */
+ {"gzip-3", zlib_decompress}, /* ZIO_COMPRESS_GZIP3 */
+ {"gzip-4", zlib_decompress}, /* ZIO_COMPRESS_GZIP4 */
+ {"gzip-5", zlib_decompress}, /* ZIO_COMPRESS_GZIP5 */
+ {"gzip-6", zlib_decompress}, /* ZIO_COMPRESS_GZIP6 */
+ {"gzip-7", zlib_decompress}, /* ZIO_COMPRESS_GZIP7 */
+ {"gzip-8", zlib_decompress}, /* ZIO_COMPRESS_GZIP8 */
+ {"gzip-9", zlib_decompress}, /* ZIO_COMPRESS_GZIP9 */
};
static grub_err_t zio_read_data (blkptr_t * bp, grub_zfs_endian_t endian,
*buf = NULL;
checksum = (grub_zfs_to_cpu64((bp)->blk_prop, endian) >> 40) & 0xff;
- comp = (grub_zfs_to_cpu64((bp)->blk_prop, endian)>>32) & 0x7;
+ comp = (grub_zfs_to_cpu64((bp)->blk_prop, endian)>>32) & 0xff;
lsize = (BP_IS_HOLE(bp) ? 0 :
(((grub_zfs_to_cpu64 ((bp)->blk_prop, endian) & 0xffff) + 1)
<< SPA_MINBLOCKSHIFT));
#include <grub/dl.h>
#include <grub/env.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
static inline void
print_tabs (int n)
{
-#! /bin/sh -e
-#
+#! /bin/sh
+set -e
+
# Copyright (C) 2010 Free Software Foundation, Inc.
#
# This gensymlist.sh is free software; the author
-#! /bin/sh -e
-#
+#! /bin/sh
+set -e
+
# Copyright (C) 2010 Free Software Foundation, Inc.
#
# This gensymlist.sh is free software; the author
EOF
cat <<EOF
- struct symtab { const char *name; void *addr; };
+ struct symtab { const char *name; void *addr; int isfunc; };
struct symtab *p;
static struct symtab tab[] =
{
(while read LINE; do echo $LINE; done) \
| grep -v '^#' \
| sed -n \
- -e '/EXPORT_FUNC *([a-zA-Z0-9_]*)/{s/.*EXPORT_FUNC *(\([a-zA-Z0-9_]*\)).*/ {"\1", \1},/;p;}' \
- -e '/EXPORT_VAR *([a-zA-Z0-9_]*)/{s/.*EXPORT_VAR *(\([a-zA-Z0-9_]*\)).*/ {"\1", \&\1},/;p;}' \
+ -e '/EXPORT_FUNC *([a-zA-Z0-9_]*)/{s/.*EXPORT_FUNC *(\([a-zA-Z0-9_]*\)).*/ {"\1", \1, 1},/;p;}' \
+ -e '/EXPORT_VAR *([a-zA-Z0-9_]*)/{s/.*EXPORT_VAR *(\([a-zA-Z0-9_]*\)).*/ {"\1", \&\1, 0},/;p;}' \
| sort -u
cat <<EOF
- {0, 0}
+ {0, 0, 0}
};
COMPILE_TIME_ASSERT (sizeof (tab) > sizeof (tab[0]));
for (p = tab; p->name; p++)
- grub_dl_register_symbol (p->name, p->addr, 0);
+ grub_dl_register_symbol (p->name, p->addr, p->isfunc, 0);
}
EOF
int i;
printf ("#include <grub/types.h>\n");
+ printf ("#include <grub/dl.h>\n");
+ printf ("\n");
+
+ printf ("/* Under copyright legislature such automated output isn't\n");
+ printf ("covered by any copyright. Hence it's public domain. Public\n");
+ printf ("domain works can be dual-licenced with any license. */\n");
+ printf ("GRUB_MOD_LICENSE (\"GPLv3+\");");
+ printf ("GRUB_MOD_DUAL_LICENSE (\"Public Domain\");");
#define TAB(op) \
printf ("grub_int16_t grub_trig_" #op "tab[] =\n{"); \
#include <grub/kernel.h>
#include <grub/i18n.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
/*
.mo file information from:
http://www.gnu.org/software/autoconf/manual/gettext/MO-Files.html .
#include <grub/gfxmenu_view.h>
#include <grub/time.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
static grub_gfxmenu_view_t cached_view;
static void
static grub_err_t
rescale_image (grub_gui_image_t self)
{
+ signed width;
+ signed height;
+
if (! self->raw_bitmap)
{
if (self->bitmap)
return grub_errno;
}
- unsigned width = self->bounds.width;
- unsigned height = self->bounds.height;
+ width = self->bounds.width;
+ height = self->bounds.height;
if (self->bitmap
- && (grub_video_bitmap_get_width (self->bitmap) == width)
- && (grub_video_bitmap_get_height (self->bitmap) == height))
+ && ((signed) grub_video_bitmap_get_width (self->bitmap) == width)
+ && ((signed) grub_video_bitmap_get_height (self->bitmap) == height))
{
/* Nothing to do; already the right size. */
return grub_errno;
/* Create a scaled bitmap, unless the requested size is the same
as the raw size -- in that case a reference is made. */
- if (grub_video_bitmap_get_width (self->raw_bitmap) == width
- && grub_video_bitmap_get_height (self->raw_bitmap) == height)
+ if ((signed) grub_video_bitmap_get_width (self->raw_bitmap) == width
+ && (signed) grub_video_bitmap_get_height (self->raw_bitmap) == height)
{
self->bitmap = self->raw_bitmap;
return grub_errno;
}
/* Don't scale to an invalid size. */
- if (width == 0 || height == 0)
+ if (width <= 0 || height <= 0)
return grub_errno;
/* Create the scaled bitmap. */
char *text;
char *template;
grub_font_t font;
- grub_gui_color_t color;
+ grub_video_rgba_color_t color;
int value;
enum align_mode align;
};
grub_gui_set_viewport (&self->bounds, &vpsave);
grub_font_draw_string (self->text,
self->font,
- grub_gui_map_color (self->color),
+ grub_video_map_rgba_color (self->color),
left_x,
grub_font_get_ascent (self->font));
grub_gui_restore_viewport (&vpsave);
}
else if (grub_strcmp (name, "color") == 0)
{
- grub_gui_parse_color (value, &self->color);
+ grub_video_parse_color (value, &self->color);
}
else if (grub_strcmp (name, "align") == 0)
{
int item_spacing;
grub_font_t item_font;
grub_font_t selected_item_font;
- grub_gui_color_t item_color;
+ grub_video_rgba_color_t item_color;
int selected_item_color_set;
- grub_gui_color_t selected_item_color;
+ grub_video_rgba_color_t selected_item_color;
int draw_scrollbar;
int need_to_recreate_scrollbar;
if (is_selected)
{
- selbox->set_content_size (selbox, oviewport.width - 2 * boxpad - 2,
- item_height - 1);
+ int cwidth = oviewport.width - 2 * boxpad - 2;
+ if (selbox->get_border_width)
+ cwidth -= selbox->get_border_width (selbox);
+ selbox->set_content_size (selbox, cwidth, item_height - 1);
selbox->draw (selbox, 0,
item_top - sel_toppad);
}
(is_selected && self->selected_item_font
? self->selected_item_font
: self->item_font);
- grub_gui_color_t text_color =
+ grub_video_rgba_color_t text_color =
((is_selected && self->selected_item_color_set)
? self->selected_item_color
: self->item_color);
grub_font_draw_string (item_title,
font,
- grub_gui_map_color (text_color),
+ grub_video_map_rgba_color (text_color),
sel_leftpad + self->icon_width + icon_text_space,
(item_top + (item_height - (ascent + descent))
/ 2 + ascent));
}
else if (grub_strcmp (name, "item_color") == 0)
{
- grub_gui_parse_color (value, &self->item_color);
+ grub_video_parse_color (value, &self->item_color);
}
else if (grub_strcmp (name, "selected_item_color") == 0)
{
}
else
{
- if (grub_gui_parse_color (value, &self->selected_item_color)
+ if (grub_video_parse_color (value, &self->selected_item_color)
== GRUB_ERR_NONE)
self->selected_item_color_set = 1;
}
{
list_impl_t self;
grub_font_t default_font;
- grub_gui_color_t default_fg_color;
+ grub_video_rgba_color_t default_fg_color;
self = grub_zalloc (sizeof (*self));
if (! self)
self->visible = 1;
default_font = grub_font_get ("Unknown Regular 16");
- default_fg_color = grub_gui_color_rgb (0, 0, 0);
+ default_fg_color = grub_video_rgba_color_rgb (0, 0, 0);
self->icon_width = 32;
self->icon_height = 32;
int show_text;
char *template;
grub_font_t font;
- grub_gui_color_t text_color;
- grub_gui_color_t border_color;
- grub_gui_color_t bg_color;
- grub_gui_color_t fg_color;
+ grub_video_rgba_color_t text_color;
+ grub_video_rgba_color_t border_color;
+ grub_video_rgba_color_t bg_color;
+ grub_video_rgba_color_t fg_color;
char *theme_dir;
int need_to_recreate_pixmaps;
f.height = self->bounds.height - 2;
/* Border. */
- grub_video_fill_rect (grub_gui_map_color (self->border_color),
+ grub_video_fill_rect (grub_video_map_rgba_color (self->border_color),
f.x - 1, f.y - 1,
f.width + 2, f.height + 2);
int barwidth = (f.width
* (self->value - self->start)
/ (self->end - self->start));
- grub_video_fill_rect (grub_gui_map_color (self->bg_color),
+ grub_video_fill_rect (grub_video_map_rgba_color (self->bg_color),
f.x + barwidth, f.y,
f.width - barwidth, f.height);
/* Bar foreground. */
- grub_video_fill_rect (grub_gui_map_color (self->fg_color),
+ grub_video_fill_rect (grub_video_map_rgba_color (self->fg_color),
f.x, f.y,
barwidth, f.height);
}
if (self->template)
{
grub_font_t font = self->font;
- grub_video_color_t text_color = grub_gui_map_color (self->text_color);
+ grub_video_color_t text_color =
+ grub_video_map_rgba_color (self->text_color);
int width = self->bounds.width;
int height = self->bounds.height;
char *text;
}
else if (grub_strcmp (name, "text_color") == 0)
{
- grub_gui_parse_color (value, &self->text_color);
+ grub_video_parse_color (value, &self->text_color);
}
else if (grub_strcmp (name, "border_color") == 0)
{
- grub_gui_parse_color (value, &self->border_color);
+ grub_video_parse_color (value, &self->border_color);
}
else if (grub_strcmp (name, "bg_color") == 0)
{
- grub_gui_parse_color (value, &self->bg_color);
+ grub_video_parse_color (value, &self->bg_color);
}
else if (grub_strcmp (name, "fg_color") == 0)
{
- grub_gui_parse_color (value, &self->fg_color);
+ grub_video_parse_color (value, &self->fg_color);
}
else if (grub_strcmp (name, "bar_style") == 0)
{
self->progress.component.ops = &progress_bar_ops;
self->visible = 1;
self->font = grub_font_get ("Unknown Regular 16");
- grub_gui_color_t black = { .red = 0, .green = 0, .blue = 0, .alpha = 255 };
- grub_gui_color_t gray = { .red = 128, .green = 128, .blue = 128, .alpha = 255 };
- grub_gui_color_t lightgray = { .red = 200, .green = 200, .blue = 200, .alpha = 255 };
+ grub_video_rgba_color_t black = { .red = 0, .green = 0, .blue = 0, .alpha = 255 };
+ grub_video_rgba_color_t gray = { .red = 128, .green = 128, .blue = 128, .alpha = 255 };
+ grub_video_rgba_color_t lightgray = { .red = 200, .green = 200, .blue = 200, .alpha = 255 };
self->text_color = black;
self->border_color = black;
self->bg_color = gray;
return grub_new_substring (file_path, 0, last_slash + 1);
}
-
-static __inline int
-my_isxdigit (char c)
-{
- return ((c >= '0' && c <= '9')
- || (c >= 'a' && c <= 'f')
- || (c >= 'A' && c <= 'F'));
-}
-
-static int
-parse_hex_color_component (const char *s, unsigned start, unsigned end)
-{
- unsigned len;
- char buf[3];
-
- len = end - start;
- /* Check the limits so we don't overrun the buffer. */
- if (len < 1 || len > 2)
- return 0;
-
- if (len == 1)
- {
- buf[0] = s[start]; /* Get the first and only hex digit. */
- buf[1] = buf[0]; /* Duplicate the hex digit. */
- }
- else if (len == 2)
- {
- buf[0] = s[start];
- buf[1] = s[start + 1];
- }
-
- buf[2] = '\0';
-
- return grub_strtoul (buf, 0, 16);
-}
-
-/* Parse a color string of the form "r, g, b", "#RGB", "#RGBA",
- "#RRGGBB", or "#RRGGBBAA". */
-grub_err_t
-grub_gui_parse_color (const char *s, grub_gui_color_t *color)
-{
- grub_gui_color_t c;
-
- /* Skip whitespace. */
- while (*s && grub_isspace (*s))
- s++;
-
- if (*s == '#')
- {
- /* HTML-style. Number if hex digits:
- [6] #RRGGBB [3] #RGB
- [8] #RRGGBBAA [4] #RGBA */
-
- s++; /* Skip the '#'. */
- /* Count the hexits to determine the format. */
- int hexits = 0;
- const char *end = s;
- while (my_isxdigit (*end))
- {
- end++;
- hexits++;
- }
-
- /* Parse the color components based on the format. */
- if (hexits == 3 || hexits == 4)
- {
- c.red = parse_hex_color_component (s, 0, 1);
- c.green = parse_hex_color_component (s, 1, 2);
- c.blue = parse_hex_color_component (s, 2, 3);
- if (hexits == 4)
- c.alpha = parse_hex_color_component (s, 3, 4);
- else
- c.alpha = 255;
- }
- else if (hexits == 6 || hexits == 8)
- {
- c.red = parse_hex_color_component (s, 0, 2);
- c.green = parse_hex_color_component (s, 2, 4);
- c.blue = parse_hex_color_component (s, 4, 6);
- if (hexits == 8)
- c.alpha = parse_hex_color_component (s, 6, 8);
- else
- c.alpha = 255;
- }
- else
- return grub_error (GRUB_ERR_BAD_ARGUMENT,
- "invalid HTML-type color string `%s'", s);
- }
- else if (grub_isdigit (*s))
- {
- /* Comma separated decimal values. */
- c.red = grub_strtoul (s, 0, 0);
- if ((s = grub_strchr (s, ',')) == 0)
- return grub_error (GRUB_ERR_BAD_ARGUMENT,
- "missing 1st comma separator in color `%s'", s);
- s++;
- c.green = grub_strtoul (s, 0, 0);
- if ((s = grub_strchr (s, ',')) == 0)
- return grub_error (GRUB_ERR_BAD_ARGUMENT,
- "missing 2nd comma separator in color `%s'", s);
- s++;
- c.blue = grub_strtoul (s, 0, 0);
- if ((s = grub_strchr (s, ',')) == 0)
- c.alpha = 255;
- else
- {
- s++;
- c.alpha = grub_strtoul (s, 0, 0);
- }
- }
- else
- {
- if (! grub_gui_get_named_color (s, &c))
- return grub_error (GRUB_ERR_BAD_ARGUMENT,
- "invalid named color `%s'", s);
- }
-
- if (grub_errno == GRUB_ERR_NONE)
- *color = c;
- return grub_errno;
-}
/* Try each class in succession. */
icon = 0;
- for (c = entry->classes->next; c && ! icon; c = c->next)
+ for (c = entry->classes; c && ! icon; c = c->next)
icon = get_icon_by_class (mgr, c->name);
return icon;
}
+++ /dev/null
-/* named_colors.c - Named color values. */
-/*
- * GRUB -- GRand Unified Bootloader
- * Copyright (C) 2008 Free Software Foundation, Inc.
- *
- * GRUB is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * GRUB is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <grub/types.h>
-#include <grub/gui.h>
-#include <grub/gui_string_util.h>
-#include <grub/misc.h>
-
-struct named_color
-{
- const char *name;
- grub_gui_color_t color;
-};
-
-/*
- Named color list generated from the list of SVG color keywords from
- <http://www.w3.org/TR/css3-color/#svg-color>,
- processed through the following Perl command:
- perl -ne 'chomp;split;print "{ \"$_[0]\", RGB_COLOR($_[2]) },\n"'
- */
-
-#define RGB_COLOR(r,g,b) {.red = r, .green = g, .blue = b, .alpha = 255}
-
-static struct named_color named_colors[] =
-{
- { "aliceblue", RGB_COLOR(240,248,255) },
- { "antiquewhite", RGB_COLOR(250,235,215) },
- { "aqua", RGB_COLOR(0,255,255) },
- { "aquamarine", RGB_COLOR(127,255,212) },
- { "azure", RGB_COLOR(240,255,255) },
- { "beige", RGB_COLOR(245,245,220) },
- { "bisque", RGB_COLOR(255,228,196) },
- { "black", RGB_COLOR(0,0,0) },
- { "blanchedalmond", RGB_COLOR(255,235,205) },
- { "blue", RGB_COLOR(0,0,255) },
- { "blueviolet", RGB_COLOR(138,43,226) },
- { "brown", RGB_COLOR(165,42,42) },
- { "burlywood", RGB_COLOR(222,184,135) },
- { "cadetblue", RGB_COLOR(95,158,160) },
- { "chartreuse", RGB_COLOR(127,255,0) },
- { "chocolate", RGB_COLOR(210,105,30) },
- { "coral", RGB_COLOR(255,127,80) },
- { "cornflowerblue", RGB_COLOR(100,149,237) },
- { "cornsilk", RGB_COLOR(255,248,220) },
- { "crimson", RGB_COLOR(220,20,60) },
- { "cyan", RGB_COLOR(0,255,255) },
- { "darkblue", RGB_COLOR(0,0,139) },
- { "darkcyan", RGB_COLOR(0,139,139) },
- { "darkgoldenrod", RGB_COLOR(184,134,11) },
- { "darkgray", RGB_COLOR(169,169,169) },
- { "darkgreen", RGB_COLOR(0,100,0) },
- { "darkgrey", RGB_COLOR(169,169,169) },
- { "darkkhaki", RGB_COLOR(189,183,107) },
- { "darkmagenta", RGB_COLOR(139,0,139) },
- { "darkolivegreen", RGB_COLOR(85,107,47) },
- { "darkorange", RGB_COLOR(255,140,0) },
- { "darkorchid", RGB_COLOR(153,50,204) },
- { "darkred", RGB_COLOR(139,0,0) },
- { "darksalmon", RGB_COLOR(233,150,122) },
- { "darkseagreen", RGB_COLOR(143,188,143) },
- { "darkslateblue", RGB_COLOR(72,61,139) },
- { "darkslategray", RGB_COLOR(47,79,79) },
- { "darkslategrey", RGB_COLOR(47,79,79) },
- { "darkturquoise", RGB_COLOR(0,206,209) },
- { "darkviolet", RGB_COLOR(148,0,211) },
- { "deeppink", RGB_COLOR(255,20,147) },
- { "deepskyblue", RGB_COLOR(0,191,255) },
- { "dimgray", RGB_COLOR(105,105,105) },
- { "dimgrey", RGB_COLOR(105,105,105) },
- { "dodgerblue", RGB_COLOR(30,144,255) },
- { "firebrick", RGB_COLOR(178,34,34) },
- { "floralwhite", RGB_COLOR(255,250,240) },
- { "forestgreen", RGB_COLOR(34,139,34) },
- { "fuchsia", RGB_COLOR(255,0,255) },
- { "gainsboro", RGB_COLOR(220,220,220) },
- { "ghostwhite", RGB_COLOR(248,248,255) },
- { "gold", RGB_COLOR(255,215,0) },
- { "goldenrod", RGB_COLOR(218,165,32) },
- { "gray", RGB_COLOR(128,128,128) },
- { "green", RGB_COLOR(0,128,0) },
- { "greenyellow", RGB_COLOR(173,255,47) },
- { "grey", RGB_COLOR(128,128,128) },
- { "honeydew", RGB_COLOR(240,255,240) },
- { "hotpink", RGB_COLOR(255,105,180) },
- { "indianred", RGB_COLOR(205,92,92) },
- { "indigo", RGB_COLOR(75,0,130) },
- { "ivory", RGB_COLOR(255,255,240) },
- { "khaki", RGB_COLOR(240,230,140) },
- { "lavender", RGB_COLOR(230,230,250) },
- { "lavenderblush", RGB_COLOR(255,240,245) },
- { "lawngreen", RGB_COLOR(124,252,0) },
- { "lemonchiffon", RGB_COLOR(255,250,205) },
- { "lightblue", RGB_COLOR(173,216,230) },
- { "lightcoral", RGB_COLOR(240,128,128) },
- { "lightcyan", RGB_COLOR(224,255,255) },
- { "lightgoldenrodyellow", RGB_COLOR(250,250,210) },
- { "lightgray", RGB_COLOR(211,211,211) },
- { "lightgreen", RGB_COLOR(144,238,144) },
- { "lightgrey", RGB_COLOR(211,211,211) },
- { "lightpink", RGB_COLOR(255,182,193) },
- { "lightsalmon", RGB_COLOR(255,160,122) },
- { "lightseagreen", RGB_COLOR(32,178,170) },
- { "lightskyblue", RGB_COLOR(135,206,250) },
- { "lightslategray", RGB_COLOR(119,136,153) },
- { "lightslategrey", RGB_COLOR(119,136,153) },
- { "lightsteelblue", RGB_COLOR(176,196,222) },
- { "lightyellow", RGB_COLOR(255,255,224) },
- { "lime", RGB_COLOR(0,255,0) },
- { "limegreen", RGB_COLOR(50,205,50) },
- { "linen", RGB_COLOR(250,240,230) },
- { "magenta", RGB_COLOR(255,0,255) },
- { "maroon", RGB_COLOR(128,0,0) },
- { "mediumaquamarine", RGB_COLOR(102,205,170) },
- { "mediumblue", RGB_COLOR(0,0,205) },
- { "mediumorchid", RGB_COLOR(186,85,211) },
- { "mediumpurple", RGB_COLOR(147,112,219) },
- { "mediumseagreen", RGB_COLOR(60,179,113) },
- { "mediumslateblue", RGB_COLOR(123,104,238) },
- { "mediumspringgreen", RGB_COLOR(0,250,154) },
- { "mediumturquoise", RGB_COLOR(72,209,204) },
- { "mediumvioletred", RGB_COLOR(199,21,133) },
- { "midnightblue", RGB_COLOR(25,25,112) },
- { "mintcream", RGB_COLOR(245,255,250) },
- { "mistyrose", RGB_COLOR(255,228,225) },
- { "moccasin", RGB_COLOR(255,228,181) },
- { "navajowhite", RGB_COLOR(255,222,173) },
- { "navy", RGB_COLOR(0,0,128) },
- { "oldlace", RGB_COLOR(253,245,230) },
- { "olive", RGB_COLOR(128,128,0) },
- { "olivedrab", RGB_COLOR(107,142,35) },
- { "orange", RGB_COLOR(255,165,0) },
- { "orangered", RGB_COLOR(255,69,0) },
- { "orchid", RGB_COLOR(218,112,214) },
- { "palegoldenrod", RGB_COLOR(238,232,170) },
- { "palegreen", RGB_COLOR(152,251,152) },
- { "paleturquoise", RGB_COLOR(175,238,238) },
- { "palevioletred", RGB_COLOR(219,112,147) },
- { "papayawhip", RGB_COLOR(255,239,213) },
- { "peachpuff", RGB_COLOR(255,218,185) },
- { "peru", RGB_COLOR(205,133,63) },
- { "pink", RGB_COLOR(255,192,203) },
- { "plum", RGB_COLOR(221,160,221) },
- { "powderblue", RGB_COLOR(176,224,230) },
- { "purple", RGB_COLOR(128,0,128) },
- { "red", RGB_COLOR(255,0,0) },
- { "rosybrown", RGB_COLOR(188,143,143) },
- { "royalblue", RGB_COLOR(65,105,225) },
- { "saddlebrown", RGB_COLOR(139,69,19) },
- { "salmon", RGB_COLOR(250,128,114) },
- { "sandybrown", RGB_COLOR(244,164,96) },
- { "seagreen", RGB_COLOR(46,139,87) },
- { "seashell", RGB_COLOR(255,245,238) },
- { "sienna", RGB_COLOR(160,82,45) },
- { "silver", RGB_COLOR(192,192,192) },
- { "skyblue", RGB_COLOR(135,206,235) },
- { "slateblue", RGB_COLOR(106,90,205) },
- { "slategray", RGB_COLOR(112,128,144) },
- { "slategrey", RGB_COLOR(112,128,144) },
- { "snow", RGB_COLOR(255,250,250) },
- { "springgreen", RGB_COLOR(0,255,127) },
- { "steelblue", RGB_COLOR(70,130,180) },
- { "tan", RGB_COLOR(210,180,140) },
- { "teal", RGB_COLOR(0,128,128) },
- { "thistle", RGB_COLOR(216,191,216) },
- { "tomato", RGB_COLOR(255,99,71) },
- { "turquoise", RGB_COLOR(64,224,208) },
- { "violet", RGB_COLOR(238,130,238) },
- { "wheat", RGB_COLOR(245,222,179) },
- { "white", RGB_COLOR(255,255,255) },
- { "whitesmoke", RGB_COLOR(245,245,245) },
- { "yellow", RGB_COLOR(255,255,0) },
- { "yellowgreen", RGB_COLOR(154,205,50) },
- { 0, { 0, 0, 0, 0 } } /* Terminator. */
-};
-
-/* Get the color named NAME. If the color was found, returns 1 and
- stores the color into *COLOR. If the color was not found, returns 0 and
- does not modify *COLOR. */
-int
-grub_gui_get_named_color (const char *name,
- grub_gui_color_t *color)
-{
- int i;
- for (i = 0; named_colors[i].name; i++)
- {
- if (grub_strcmp (named_colors[i].name, name) == 0)
- {
- *color = named_colors[i].color;
- return 1;
- }
- }
- return 0;
-}
return grub_errno;
}
else if (! grub_strcmp ("title-color", name))
- grub_gui_parse_color (value, &view->title_color);
+ grub_video_parse_color (value, &view->title_color);
else if (! grub_strcmp ("message-color", name))
- grub_gui_parse_color (value, &view->message_color);
+ grub_video_parse_color (value, &view->message_color);
else if (! grub_strcmp ("message-bg-color", name))
- grub_gui_parse_color (value, &view->message_bg_color);
+ grub_video_parse_color (value, &view->message_bg_color);
else if (! grub_strcmp ("desktop-image", name))
{
struct grub_video_bitmap *raw_bitmap;
view->desktop_image = scaled_bitmap;
}
else if (! grub_strcmp ("desktop-color", name))
- grub_gui_parse_color (value, &view->desktop_color);
+ grub_video_parse_color (value, &view->desktop_color);
else if (! grub_strcmp ("terminal-box", name))
{
grub_err_t err;
{
grub_gfxmenu_view_t view;
grub_font_t default_font;
- grub_gui_color_t default_fg_color;
- grub_gui_color_t default_bg_color;
+ grub_video_rgba_color_t default_fg_color;
+ grub_video_rgba_color_t default_bg_color;
view = grub_malloc (sizeof (*view));
if (! view)
view->screen.height = height;
default_font = grub_font_get ("Unknown Regular 16");
- default_fg_color = grub_gui_color_rgb (0, 0, 0);
- default_bg_color = grub_gui_color_rgb (255, 255, 255);
+ default_fg_color = grub_video_rgba_color_rgb (0, 0, 0);
+ default_bg_color = grub_video_rgba_color_rgb (255, 255, 255);
view->canvas = 0;
}
else
{
- grub_video_fill_rect (grub_gui_map_color (view->desktop_color),
+ grub_video_fill_rect (grub_video_map_rgba_color (view->desktop_color),
bounds->x, bounds->y,
bounds->width, bounds->height);
}
int y = 40 + grub_font_get_ascent (view->title_font);
grub_font_draw_string (view->title_text,
view->title_font,
- grub_gui_map_color (view->title_color),
+ grub_video_map_rgba_color (view->title_color),
x, y);
}
return;
grub_font_t font = view->message_font;
- grub_video_color_t color = grub_gui_map_color (view->message_color);
+ grub_video_color_t color = grub_video_map_rgba_color (view->message_color);
/* Border. */
grub_video_fill_rect (color,
f.x-1, f.y-1, f.width+2, f.height+2);
/* Fill. */
- grub_video_fill_rect (grub_gui_map_color (view->message_bg_color),
+ grub_video_fill_rect (grub_video_map_rgba_color (view->message_bg_color),
f.x, f.y, f.width, f.height);
/* Center the text. */
return;
}
+static int
+get_border_width (grub_gfxmenu_box_t self)
+{
+ return (get_width (self->raw_pixmaps[BOX_PIXMAP_E])
+ + get_width (self->raw_pixmaps[BOX_PIXMAP_W]));
+}
+
static int
get_left_pad (grub_gfxmenu_box_t self)
{
box->draw = draw;
box->set_content_size = set_content_size;
+ box->get_border_width = get_border_width;
+
box->get_left_pad = get_left_pad;
box->get_top_pad = get_top_pad;
box->get_right_pad = get_right_pad;
#include <grub/extcmd.h>
#include <grub/i18n.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
static grub_err_t
grub_cmd_hello (grub_extcmd_context_t ctxt __attribute__ ((unused)),
int argc __attribute__ ((unused)),
#include <grub/normal.h>
#include <grub/datetime.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
static char *grub_datetime_names[] =
{
"YEAR",
#include <grub/misc.h>
#include <grub/fs.h>
#include <grub/bufio.h>
+#include <grub/dl.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
#define GRUB_BUFIO_DEF_SIZE 8192
#define GRUB_BUFIO_MAX_SIZE 1048576
{
grub_size_t res = len;
grub_bufio_t bufio = file->data;
- grub_uint32_t pos;
+ grub_uint64_t pos;
if ((file->offset >= bufio->file->offset) &&
(file->offset < bufio->file->offset + bufio->buffer_len))
#include <grub/fs.h>
#include <grub/file.h>
#include <grub/dl.h>
+#include <grub/disk.h>
+#include <grub/deflate.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
/*
* Window Size
{
/* The underlying file object. */
grub_file_t file;
+ /* If input is in memory following fields are used instead of file. */
+ grub_size_t mem_input_size, mem_input_off;
+ grub_uint8_t *mem_input;
+ grub_disk_addr_t disk_input_off;
+ grub_disk_addr_t disk_input_start;
+ grub_disk_t disk_input;
/* The offset at which the data starts in the underlying file. */
grub_off_t data_offset;
/* The type of current block. */
static struct grub_fs grub_gzio_fs;
/* Function prototypes */
-static void initialize_tables (grub_file_t file);
+static void initialize_tables (grub_gzio_t);
/* Eat variable-length header fields. */
static int
typedef unsigned long ulg;
static int
-test_header (grub_file_t file)
+test_gzip_header (grub_file_t file)
{
struct {
grub_uint16_t magic;
file->size = grub_le_to_cpu32 (orig_len);
}
- initialize_tables (file);
+ initialize_tables (gzio);
return 1;
}
0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
};
-#define NEEDBITS(n) do {while(k<(n)){b|=((ulg)get_byte(file))<<k;k+=8;}} while (0)
+#define NEEDBITS(n) do {while(k<(n)){b|=((ulg)get_byte(gzio))<<k;k+=8;}} while (0)
#define DUMPBITS(n) do {b>>=(n);k-=(n);} while (0)
static int
-get_byte (grub_file_t file)
+get_byte (grub_gzio_t gzio)
{
- grub_gzio_t gzio = file->data;
+ if (gzio->mem_input)
+ {
+ if (gzio->mem_input_off < gzio->mem_input_size)
+ return gzio->mem_input[gzio->mem_input_off++];
+ return 0;
+ }
- if (grub_file_tell (gzio->file) == (grub_off_t) gzio->data_offset
- || gzio->inbuf_d == INBUFSIZ)
+ if (gzio->disk_input && (gzio->disk_input_off == gzio->data_offset
+ || gzio->inbuf_d == INBUFSIZ))
+ {
+ grub_disk_addr_t d = gzio->disk_input_start + gzio->disk_input_off;
+ gzio->inbuf_d = 0;
+ grub_disk_read (gzio->disk_input,
+ d >> GRUB_DISK_SECTOR_BITS,
+ d & (GRUB_DISK_SECTOR_SIZE - 1),
+ INBUFSIZ, gzio->inbuf);
+ gzio->disk_input_off += INBUFSIZ;
+ }
+
+ if (gzio->file && (grub_file_tell (gzio->file)
+ == (grub_off_t) gzio->data_offset
+ || gzio->inbuf_d == INBUFSIZ))
{
gzio->inbuf_d = 0;
grub_file_read (gzio->file, gzio->inbuf, INBUFSIZ);
return gzio->inbuf[gzio->inbuf_d++];
}
+static void
+gzio_seek (grub_gzio_t gzio, grub_off_t off)
+{
+ if (gzio->mem_input)
+ {
+ if (off > gzio->mem_input_size)
+ grub_error (GRUB_ERR_OUT_OF_RANGE,
+ "attempt to seek outside of the file");
+ else
+ gzio->mem_input_off = off;
+ }
+ else if (gzio->disk_input)
+ gzio->disk_input_off = off;
+ else
+ grub_file_seek (gzio->file, off);
+}
+
/* more function prototypes */
static int huft_build (unsigned *, unsigned, unsigned, ush *, ush *,
struct huft **, int *);
static int huft_free (struct huft *);
-static int inflate_codes_in_window (grub_file_t);
+static int inflate_codes_in_window (grub_gzio_t);
/* Given a list of code lengths and a maximum table size, make a set of
*/
static int
-inflate_codes_in_window (grub_file_t file)
+inflate_codes_in_window (grub_gzio_t gzio)
{
register unsigned e; /* table entry flag/number of extra bits */
unsigned n, d; /* length and index for copy */
unsigned ml, md; /* masks for bl and bd bits */
register ulg b; /* bit buffer */
register unsigned k; /* number of bits in bit buffer */
- grub_gzio_t gzio = file->data;
/* make local copies of globals */
d = gzio->inflate_d;
/* get header for an inflated type 0 (stored) block. */
static void
-init_stored_block (grub_file_t file)
+init_stored_block (grub_gzio_t gzio)
{
register ulg b; /* bit buffer */
register unsigned k; /* number of bits in bit buffer */
- grub_gzio_t gzio = file->data;
/* make local copies of globals */
b = gzio->bb; /* initialize bit buffer */
Huffman tables. */
static void
-init_fixed_block (grub_file_t file)
+init_fixed_block (grub_gzio_t gzio)
{
int i; /* temporary variable */
unsigned l[288]; /* length list for huft_build */
- grub_gzio_t gzio = file->data;
/* set up literal table */
for (i = 0; i < 144; i++)
/* get header for an inflated type 2 (dynamic Huffman codes) block. */
static void
-init_dynamic_block (grub_file_t file)
+init_dynamic_block (grub_gzio_t gzio)
{
int i; /* temporary variables */
unsigned j;
unsigned ll[286 + 30]; /* literal/length and distance code lengths */
register ulg b; /* bit buffer */
register unsigned k; /* number of bits in bit buffer */
- grub_gzio_t gzio = file->data;
/* make local bit buffer */
b = gzio->bb;
static void
-get_new_block (grub_file_t file)
+get_new_block (grub_gzio_t gzio)
{
register ulg b; /* bit buffer */
register unsigned k; /* number of bits in bit buffer */
- grub_gzio_t gzio = file->data;
/* make local bit buffer */
b = gzio->bb;
switch (gzio->block_type)
{
case INFLATE_STORED:
- init_stored_block (file);
+ init_stored_block (gzio);
break;
case INFLATE_FIXED:
- init_fixed_block (file);
+ init_fixed_block (gzio);
break;
case INFLATE_DYNAMIC:
- init_dynamic_block (file);
+ init_dynamic_block (gzio);
break;
default:
break;
static void
-inflate_window (grub_file_t file)
+inflate_window (grub_gzio_t gzio)
{
- grub_gzio_t gzio = file->data;
-
/* initialize window */
gzio->wp = 0;
if (gzio->last_block)
break;
- get_new_block (file);
+ get_new_block (gzio);
}
if (gzio->block_type > INFLATE_DYNAMIC)
while (gzio->block_len && w < WSIZE && grub_errno == GRUB_ERR_NONE)
{
- gzio->slide[w++] = get_byte (file);
+ gzio->slide[w++] = get_byte (gzio);
gzio->block_len--;
}
* Expand other kind of block.
*/
- if (inflate_codes_in_window (file))
+ if (inflate_codes_in_window (gzio))
{
huft_free (gzio->tl);
huft_free (gzio->td);
static void
-initialize_tables (grub_file_t file)
+initialize_tables (grub_gzio_t gzio)
{
- grub_gzio_t gzio = file->data;
-
gzio->saved_offset = 0;
- grub_file_seek (gzio->file, gzio->data_offset);
+ gzio_seek (gzio, gzio->data_offset);
/* Initialize the bit buffer. */
gzio->bk = 0;
file->fs = &grub_gzio_fs;
file->not_easily_seekable = 1;
- if (! test_header (file))
+ if (! test_gzip_header (file))
{
grub_free (gzio);
grub_free (file);
grub_file_seek (io, 0);
+ grub_errno = GRUB_ERR_NONE;
- if (grub_errno == GRUB_ERR_BAD_FILE_TYPE)
- {
- grub_errno = GRUB_ERR_NONE;
- return io;
- }
+ return io;
}
return file;
}
+static int
+test_zlib_header (grub_gzio_t gzio)
+{
+ grub_uint8_t cmf, flg;
+
+ cmf = get_byte (gzio);
+ flg = get_byte (gzio);
+
+ /* Check that compression method is DEFLATE. */
+ if ((cmf & 0xf) != DEFLATED)
+ {
+ grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, "unsupported gzip format");
+ return 0;
+ }
+
+ if ((cmf * 256 + flg) % 31)
+ {
+ grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, "unsupported gzip format");
+ return 0;
+ }
+
+ /* Dictionary isn't supported. */
+ if (flg & 0x20)
+ {
+ grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, "unsupported gzip format");
+ return 0;
+ }
+
+ gzio->data_offset = 2;
+ initialize_tables (gzio);
+
+ return 1;
+}
+
static grub_ssize_t
-grub_gzio_read (grub_file_t file, char *buf, grub_size_t len)
+grub_gzio_read_real (grub_gzio_t gzio, grub_off_t offset,
+ char *buf, grub_size_t len)
{
grub_ssize_t ret = 0;
- grub_gzio_t gzio = file->data;
- grub_off_t offset;
/* Do we reset decompression to the beginning of the file? */
- if (gzio->saved_offset > file->offset + WSIZE)
- initialize_tables (file);
+ if (gzio->saved_offset > offset + WSIZE)
+ initialize_tables (gzio);
/*
* This loop operates upon uncompressed data only. The only
* window is within the range of data it needs.
*/
- offset = file->offset;
-
while (len > 0 && grub_errno == GRUB_ERR_NONE)
{
register grub_size_t size;
register char *srcaddr;
while (offset >= gzio->saved_offset)
- inflate_window (file);
+ inflate_window (gzio);
srcaddr = (char *) ((offset & (WSIZE - 1)) + gzio->slide);
size = gzio->saved_offset - offset;
return ret;
}
+static grub_ssize_t
+grub_gzio_read (grub_file_t file, char *buf, grub_size_t len)
+{
+ return grub_gzio_read_real (file->data, file->offset, buf, len);
+}
+
/* Release everything, including the underlying file object. */
static grub_err_t
grub_gzio_close (grub_file_t file)
return grub_errno;
}
+grub_ssize_t
+grub_zlib_decompress (char *inbuf, grub_size_t insize, grub_off_t off,
+ char *outbuf, grub_size_t outsize)
+{
+ grub_gzio_t gzio = 0;
+ grub_ssize_t ret;
+
+ gzio = grub_zalloc (sizeof (*gzio));
+ if (! gzio)
+ return -1;
+ gzio->mem_input = (grub_uint8_t *) inbuf;
+ gzio->mem_input_size = insize;
+ gzio->mem_input_off = 0;
+
+ if (!test_zlib_header (gzio))
+ {
+ grub_free (gzio);
+ return -1;
+ }
+
+ ret = grub_gzio_read_real (gzio, off, outbuf, outsize);
+ grub_free (gzio);
+
+ /* FIXME: Check Adler. */
+ return ret;
+}
+
+grub_err_t
+grub_zlib_disk_read (grub_disk_t disk, grub_disk_addr_t zlibstart,
+ grub_off_t off, char *outbuf, grub_size_t outsize)
+{
+ grub_gzio_t gzio = 0;
+ grub_ssize_t ret;
+
+ gzio = grub_zalloc (sizeof (*gzio));
+ if (! gzio)
+ return -1;
+
+ gzio->disk_input_off = 0;
+ gzio->disk_input_start = zlibstart;
+ gzio->disk_input = disk;
+
+ if (!test_zlib_header (gzio))
+ {
+ grub_free (gzio);
+ return -1;
+ }
+
+ ret = grub_gzio_read_real (gzio, off, outbuf, outsize);
+ grub_free (gzio);
+
+ /* FIXME: Check Adler. */
+ return ret < 0 ? grub_errno : GRUB_ERR_NONE;
+}
+
\f
static struct grub_fs grub_gzio_fs =
--- /dev/null
+/* lzopio.c - decompression support for lzop */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2011 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/err.h>
+#include <grub/mm.h>
+#include <grub/file.h>
+#include <grub/fs.h>
+#include <grub/dl.h>
+#include <grub/crypto.h>
+#include <minilzo.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
+
+#define LZOP_MAGIC "\x89\x4c\x5a\x4f\x00\x0d\x0a\x1a\x0a"
+#define LZOP_MAGIC_SIZE 9
+#define LZOP_CHECK_SIZE 4
+#define LZOP_NEW_LIB 0x0940
+
+/* Header flags - copied from conf.h of LZOP source code. */
+#define F_ADLER32_D 0x00000001L
+#define F_ADLER32_C 0x00000002L
+#define F_STDIN 0x00000004L
+#define F_STDOUT 0x00000008L
+#define F_NAME_DEFAULT 0x00000010L
+#define F_DOSISH 0x00000020L
+#define F_H_EXTRA_FIELD 0x00000040L
+#define F_H_GMTDIFF 0x00000080L
+#define F_CRC32_D 0x00000100L
+#define F_CRC32_C 0x00000200L
+#define F_MULTIPART 0x00000400L
+#define F_H_FILTER 0x00000800L
+#define F_H_CRC32 0x00001000L
+#define F_H_PATH 0x00002000L
+#define F_MASK 0x00003FFFL
+
+struct block_header
+{
+ grub_uint32_t usize;
+ grub_uint32_t csize;
+ grub_uint32_t ucheck;
+ grub_uint32_t ccheck;
+ unsigned char *cdata;
+ unsigned char *udata;
+};
+
+struct grub_lzopio
+{
+ grub_file_t file;
+ int has_ccheck;
+ int has_ucheck;
+ const gcry_md_spec_t *ucheck_fun;
+ const gcry_md_spec_t *ccheck_fun;
+ grub_off_t saved_off; /* Rounded down to block boundary. */
+ grub_off_t start_block_off;
+ struct block_header block;
+};
+
+typedef struct grub_lzopio *grub_lzopio_t;
+static struct grub_fs grub_lzopio_fs;
+
+/* Some helper functions. On errors memory allocated by those function is free
+ * either on close() so no risk of leaks. This makes functions simpler. */
+
+/* Read block header from file, after successful exit file points to
+ * beginning of block data. */
+static int
+read_block_header (struct grub_lzopio *lzopio)
+{
+ lzopio->saved_off += lzopio->block.usize;
+
+ /* Free cached block data if any. */
+ grub_free (lzopio->block.udata);
+ grub_free (lzopio->block.cdata);
+ lzopio->block.udata = NULL;
+ lzopio->block.cdata = NULL;
+
+ if (grub_file_read (lzopio->file, &lzopio->block.usize,
+ sizeof (lzopio->block.usize)) !=
+ sizeof (lzopio->block.usize))
+ return -1;
+
+ lzopio->block.usize = grub_be_to_cpu32 (lzopio->block.usize);
+
+ /* Last block has uncompressed data size == 0 and no other fields. */
+ if (lzopio->block.usize == 0)
+ {
+ if (grub_file_tell (lzopio->file) == grub_file_size (lzopio->file))
+ return 0;
+ else
+ return -1;
+ }
+
+ /* Read compressed data block size. */
+ if (grub_file_read (lzopio->file, &lzopio->block.csize,
+ sizeof (lzopio->block.csize)) !=
+ sizeof (lzopio->block.csize))
+ return -1;
+
+ lzopio->block.csize = grub_be_to_cpu32 (lzopio->block.csize);
+
+ /* Corrupted. */
+ if (lzopio->block.csize > lzopio->block.usize)
+ return -1;
+
+ /* Read checksum of uncompressed data. */
+ if (lzopio->has_ucheck)
+ {
+ if (grub_file_read (lzopio->file, &lzopio->block.ucheck,
+ sizeof (lzopio->block.ucheck)) !=
+ sizeof (lzopio->block.ucheck))
+ return -1;
+
+ lzopio->block.ucheck = grub_be_to_cpu32 (lzopio->block.ucheck);
+ }
+
+ /* Read checksum of compressed data. */
+ if (lzopio->has_ccheck)
+ {
+ /* Incompressible data block. */
+ if (lzopio->block.csize == lzopio->block.usize)
+ {
+ lzopio->block.ccheck = lzopio->block.ucheck;
+ }
+ else
+ {
+ if (grub_file_read (lzopio->file, &lzopio->block.ccheck,
+ sizeof (lzopio->block.ccheck)) !=
+ sizeof (lzopio->block.ccheck))
+ return -1;
+
+ lzopio->block.ccheck = grub_be_to_cpu32 (lzopio->block.ccheck);
+ }
+ }
+
+ return 0;
+}
+
+/* Read block data into memory. File must be set to beginning of block data.
+ * Can't be called on last block. */
+static int
+read_block_data (struct grub_lzopio *lzopio)
+{
+ lzopio->block.cdata = grub_malloc (lzopio->block.csize);
+ if (!lzopio->block.cdata)
+ return -1;
+
+ if (grub_file_read (lzopio->file, lzopio->block.cdata, lzopio->block.csize)
+ != (grub_ssize_t) lzopio->block.csize)
+ return -1;
+
+ if (lzopio->ccheck_fun)
+ {
+ grub_uint64_t context[(lzopio->ccheck_fun->contextsize + 7) / 8];
+
+ lzopio->ccheck_fun->init (context);
+ lzopio->ccheck_fun->write (context, lzopio->block.cdata,
+ lzopio->block.csize);
+ lzopio->ccheck_fun->final (context);
+
+ if (grub_memcmp
+ (lzopio->ccheck_fun->read (context), &lzopio->block.ccheck,
+ sizeof (lzopio->block.ccheck)) != 0)
+ return -1;
+ }
+
+ return 0;
+}
+
+/* Read block data, uncompressed and also store it in memory. */
+/* XXX Investigate possibility of in-place decompression to reduce memory
+ * footprint. Or try to uncompress directly to buf if possible. */
+static int
+uncompress_block (struct grub_lzopio *lzopio)
+{
+ lzo_uint usize = lzopio->block.usize;
+
+ if (read_block_data (lzopio) < 0)
+ return -1;
+
+ /* Incompressible data. */
+ if (lzopio->block.csize == lzopio->block.usize)
+ {
+ lzopio->block.udata = lzopio->block.cdata;
+ lzopio->block.cdata = NULL;
+ }
+ else
+ {
+ lzopio->block.udata = grub_malloc (lzopio->block.usize);
+ if (!lzopio->block.udata)
+ return -1;
+
+ if (lzo1x_decompress_safe (lzopio->block.cdata, lzopio->block.csize,
+ lzopio->block.udata, &usize, NULL)
+ != LZO_E_OK)
+ return -1;
+
+ if (lzopio->ucheck_fun)
+ {
+ grub_uint64_t context[(lzopio->ccheck_fun->contextsize + 7) / 8];
+
+ lzopio->ucheck_fun->init (context);
+ lzopio->ucheck_fun->write (context, lzopio->block.udata,
+ lzopio->block.usize);
+ lzopio->ucheck_fun->final (context);
+
+ if (grub_memcmp
+ (lzopio->ucheck_fun->read (context), &lzopio->block.ucheck,
+ sizeof (lzopio->block.ucheck)) != 0)
+ return -1;
+ }
+
+ /* Compressed data can be free now. */
+ grub_free (lzopio->block.cdata);
+ lzopio->block.cdata = NULL;
+ }
+
+ return 0;
+}
+
+/* Jump to next block and read its header. */
+static int
+jump_block (struct grub_lzopio *lzopio)
+{
+ /* only jump if block was not decompressed (and read from disk) */
+ if (!lzopio->block.udata)
+ {
+ grub_off_t off = grub_file_tell (lzopio->file) + lzopio->block.csize;
+
+ if (grub_file_seek (lzopio->file, off) == ((grub_off_t) - 1))
+ return -1;
+ }
+
+ return read_block_header (lzopio);
+}
+
+static int
+calculate_uncompressed_size (grub_file_t file)
+{
+ grub_lzopio_t lzopio = file->data;
+ grub_off_t usize_total = 0;
+
+ if (read_block_header (lzopio) < 0)
+ return -1;
+
+ /* FIXME: Don't do this for not easily seekable files. */
+ while (lzopio->block.usize != 0)
+ {
+ usize_total += lzopio->block.usize;
+
+ if (jump_block (lzopio) < 0)
+ return -1;
+ }
+
+ file->size = usize_total;
+
+ return 0;
+}
+
+struct lzop_header
+{
+ grub_uint8_t magic[LZOP_MAGIC_SIZE];
+ grub_uint16_t lzop_version;
+ grub_uint16_t lib_version;
+ grub_uint16_t lib_version_ext;
+ grub_uint8_t method;
+ grub_uint8_t level;
+ grub_uint32_t flags;
+ /* grub_uint32_t filter; */ /* No filters support. Rarely used anyway. */
+ grub_uint32_t mode;
+ grub_uint32_t mtime_lo;
+ grub_uint32_t mtime_hi;
+ grub_uint8_t name_len;
+} __attribute__ ((packed));
+
+static int
+test_header (grub_file_t file)
+{
+ grub_lzopio_t lzopio = file->data;
+ struct lzop_header header;
+ grub_uint32_t flags, checksum;
+ const gcry_md_spec_t *hcheck;
+ grub_uint8_t *context = NULL;
+ grub_uint8_t *name = NULL;
+
+ if (grub_file_read (lzopio->file, &header, sizeof (header)) != sizeof (header))
+ {
+ grub_error (GRUB_ERR_BAD_FILE_TYPE, "no lzop magic found");
+ return 0;
+ }
+
+ if (grub_memcmp (header.magic, LZOP_MAGIC, LZOP_MAGIC_SIZE) != 0)
+ {
+ grub_error (GRUB_ERR_BAD_FILE_TYPE, "no lzop magic found");
+ return 0;
+ }
+
+ if (grub_be_to_cpu16(header.lib_version) < LZOP_NEW_LIB)
+ {
+ grub_error (GRUB_ERR_BAD_COMPRESSED_DATA,
+ "unsupported (too old) LZOP version");
+ return 0;
+ }
+
+ /* Too new version, should upgrade minilzo? */
+ if (grub_be_to_cpu16 (header.lib_version_ext) > MINILZO_VERSION)
+ {
+ grub_error (GRUB_ERR_BAD_COMPRESSED_DATA,
+ "unsupported (too new) LZO version");
+ return 0;
+ }
+
+ flags = grub_be_to_cpu32 (header.flags);
+
+ if (flags & F_CRC32_D)
+ {
+ lzopio->has_ucheck = 1;
+ lzopio->ucheck_fun = grub_crypto_lookup_md_by_name ("crc32");
+ }
+ else if (flags & F_ADLER32_D)
+ {
+ lzopio->has_ucheck = 1;
+ lzopio->ucheck_fun = grub_crypto_lookup_md_by_name ("adler32");
+ }
+
+ if (flags & F_CRC32_C)
+ {
+ lzopio->has_ccheck = 1;
+ lzopio->ccheck_fun = grub_crypto_lookup_md_by_name ("crc32");
+ }
+ else if (flags & F_ADLER32_C)
+ {
+ lzopio->has_ccheck = 1;
+ lzopio->ccheck_fun = grub_crypto_lookup_md_by_name ("adler32");
+ }
+
+ if (flags & F_H_CRC32)
+ hcheck = grub_crypto_lookup_md_by_name ("crc32");
+ else
+ hcheck = grub_crypto_lookup_md_by_name ("adler32");
+
+ if (hcheck) {
+ context = grub_malloc(hcheck->contextsize);
+ if (! context)
+ return 0;
+
+ hcheck->init(context);
+
+ /* MAGIC is not included in check calculation. */
+ hcheck->write(context, &header.lzop_version, sizeof(header)- LZOP_MAGIC_SIZE);
+ }
+
+ if (header.name_len != 0)
+ {
+ name = grub_malloc (header.name_len);
+ if (! name)
+ {
+ grub_free (context);
+ return 0;
+ }
+
+ if (grub_file_read (lzopio->file, name, header.name_len) !=
+ header.name_len)
+ {
+ grub_free(name);
+ goto CORRUPTED;
+ }
+
+ if (hcheck)
+ hcheck->write(context, name, header.name_len);
+
+ grub_free(name);
+ }
+
+ if (hcheck)
+ hcheck->final(context);
+
+ if (grub_file_read (lzopio->file, &checksum, sizeof (checksum)) !=
+ sizeof (checksum))
+ goto CORRUPTED;
+
+ if (hcheck)
+ {
+ checksum = grub_cpu_to_be32(checksum);
+ if (memcmp(&checksum, hcheck->read(context), sizeof(checksum)) != 0)
+ goto CORRUPTED;
+ }
+
+ lzopio->start_block_off = grub_file_tell (lzopio->file);
+
+ if (calculate_uncompressed_size (file) < 0)
+ goto CORRUPTED;
+
+ /* Get back to start block. */
+ grub_file_seek (lzopio->file, lzopio->start_block_off);
+
+ /* Read first block - grub_lzopio_read() expects valid block. */
+ if (read_block_header (lzopio) < 0)
+ goto CORRUPTED;
+
+ lzopio->saved_off = 0;
+ return 1;
+
+CORRUPTED:
+ grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, "lzop file corrupted");
+
+ grub_free(name);
+
+ return 0;
+}
+
+static grub_file_t
+grub_lzopio_open (grub_file_t io)
+{
+ grub_file_t file;
+ grub_lzopio_t lzopio;
+
+ file = (grub_file_t) grub_zalloc (sizeof (*file));
+ if (!file)
+ return 0;
+
+ lzopio = grub_zalloc (sizeof (*lzopio));
+ if (!lzopio)
+ {
+ grub_free (file);
+ return 0;
+ }
+
+ lzopio->file = io;
+
+ file->device = io->device;
+ file->offset = 0;
+ file->data = lzopio;
+ file->read_hook = 0;
+ file->fs = &grub_lzopio_fs;
+ file->size = GRUB_FILE_SIZE_UNKNOWN;
+ file->not_easily_seekable = 1;
+
+ if (grub_file_tell (lzopio->file) != 0)
+ grub_file_seek (lzopio->file, 0);
+
+ if (!test_header (file))
+ {
+ grub_errno = GRUB_ERR_NONE;
+ grub_file_seek (io, 0);
+ grub_free (lzopio);
+ grub_free (file);
+
+ return io;
+ }
+
+ return file;
+}
+
+static grub_ssize_t
+grub_lzopio_read (grub_file_t file, char *buf, grub_size_t len)
+{
+ grub_lzopio_t lzopio = file->data;
+ grub_ssize_t ret = 0;
+ grub_off_t off;
+
+ /* Backward seek before last read block. */
+ if (lzopio->saved_off > grub_file_tell (file))
+ {
+ grub_file_seek (lzopio->file, lzopio->start_block_off);
+
+ if (read_block_header (lzopio) < 0)
+ goto CORRUPTED;
+
+ lzopio->saved_off = 0;
+ }
+
+ /* Forward to first block with requested data. */
+ while (lzopio->saved_off + lzopio->block.usize <= grub_file_tell (file))
+ {
+ /* EOF, could be possible files with unknown size. */
+ if (lzopio->block.usize == 0)
+ return 0;
+
+ if (jump_block (lzopio) < 0)
+ goto CORRUPTED;
+ }
+
+ off = grub_file_tell (file) - lzopio->saved_off;
+
+ while (len != 0 && lzopio->block.usize != 0)
+ {
+ long to_copy;
+
+ /* Block not decompressed yet. */
+ if (!lzopio->block.udata && uncompress_block (lzopio) < 0)
+ goto CORRUPTED;
+
+ /* Copy requested data into buffer. */
+ to_copy = grub_min (lzopio->block.usize - off, len);
+ grub_memcpy (buf, lzopio->block.udata + off, to_copy);
+
+ len -= to_copy;
+ buf += to_copy;
+ ret += to_copy;
+ off = 0;
+
+ /* Read next block if needed. */
+ if (len > 0 && read_block_header (lzopio) < 0)
+ goto CORRUPTED;
+ }
+
+ return ret;
+
+CORRUPTED:
+ grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, "lzop file corrupted");
+ return -1;
+}
+
+/* Release everything, including the underlying file object. */
+static grub_err_t
+grub_lzopio_close (grub_file_t file)
+{
+ grub_lzopio_t lzopio = file->data;
+
+ grub_file_close (lzopio->file);
+ grub_free (lzopio->block.cdata);
+ grub_free (lzopio->block.udata);
+ grub_free (lzopio);
+
+ /* Device must not be closed twice. */
+ file->device = 0;
+ return grub_errno;
+}
+
+static struct grub_fs grub_lzopio_fs = {
+ .name = "lzopio",
+ .dir = 0,
+ .open = 0,
+ .read = grub_lzopio_read,
+ .close = grub_lzopio_close,
+ .label = 0,
+ .next = 0
+};
+
+GRUB_MOD_INIT (lzopio)
+{
+ grub_file_filter_register (GRUB_FILE_FILTER_LZOPIO, grub_lzopio_open);
+}
+
+GRUB_MOD_FINI (lzopio)
+{
+ grub_file_filter_unregister (GRUB_FILE_FILTER_LZOPIO);
+}
#include <grub/fs.h>
#include <grub/dl.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
#include "xz.h"
#include "xz_stream.h"
static grub_size_t
decode_vli (const grub_uint8_t buf[], grub_size_t size_max,
- grub_uint64_t * num)
+ grub_uint64_t *num)
{
if (size_max == 0)
return 0;
}
static grub_ssize_t
-read_vli (grub_file_t file, grub_uint64_t * num)
+read_vli (grub_file_t file, grub_uint64_t *num)
{
grub_uint8_t buf[VLI_MAX_DIGITS];
grub_ssize_t read;
test_header (grub_file_t file)
{
grub_xzio_t xzio = file->data;
+ enum xz_ret ret;
+
xzio->buf.in_size = grub_file_read (xzio->file, xzio->inbuf,
STREAM_HEADER_SIZE);
return 0;
}
- enum xz_ret ret = xz_dec_run (xzio->dec, &xzio->buf);
+ ret = xz_dec_run (xzio->dec, &xzio->buf);
if (ret == XZ_FORMAT_ERROR)
{
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
+ if (grub_file_read (xzio->file, footer, FOOTER_MAGIC_SIZE)
+ != FOOTER_MAGIC_SIZE
|| grub_memcmp (footer, FOOTER_MAGIC, FOOTER_MAGIC_SIZE) != 0)
goto ERROR;
xzio->file->size - XZ_STREAM_FOOTER_SIZE - backsize);
/* Test index marker. */
- if (grub_file_read (xzio->file, &imarker, sizeof (imarker)) !=
- sizeof (imarker) && imarker != 0x00)
+ if (grub_file_read (xzio->file, &imarker, sizeof (imarker))
+ != sizeof (imarker) && imarker != 0x00)
goto ERROR;
if (read_vli (xzio->file, &records) <= 0)
#include <grub/env.h>
#include <grub/partition.h>
+grub_net_t (*grub_net_open) (const char *name) = NULL;
+
grub_device_t
grub_device_open (const char *name)
{
if (! name)
{
name = grub_env_get ("root");
- if (*name == '\0')
+ if (name == NULL || *name == '\0')
{
grub_error (GRUB_ERR_BAD_DEVICE, "no device is set");
goto fail;
if (! dev)
goto fail;
+ dev->net = NULL;
/* Try to open a disk. */
- disk = grub_disk_open (name);
- if (! disk)
- goto fail;
-
- dev->disk = disk;
- dev->net = 0; /* FIXME */
+ dev->disk = grub_disk_open (name);
+ if (dev->disk)
+ return dev;
+ if (grub_net_open && grub_errno == GRUB_ERR_UNKNOWN_DEVICE)
+ {
+ grub_errno = GRUB_ERR_NONE;
+ dev->net = grub_net_open (name);
+ }
- return dev;
+ if (dev->net)
+ return dev;
fail:
if (disk)
if (device->disk)
grub_disk_close (device->disk);
+ if (device->net)
+ {
+ grub_free (device->net->server);
+ grub_free (device->net);
+ }
+
grub_free (device);
return grub_errno;
void (*grub_disk_firmware_fini) (void);
int grub_disk_firmware_is_tainted;
-grub_err_t (* grub_disk_ata_pass_through) (grub_disk_t,
- struct grub_disk_ata_pass_through_parms *);
-
-
-#if 0
+#if DISK_CACHE_STATS
static unsigned long grub_disk_cache_hits;
static unsigned long grub_disk_cache_misses;
&& cache->sector == sector)
{
cache->lock = 1;
-#if 0
+#if DISK_CACHE_STATS
grub_disk_cache_hits++;
#endif
return cache->data;
}
-#if 0
+#if DISK_CACHE_STATS
grub_disk_cache_misses++;
#endif
grub_disk_dev_iterate (int (*hook) (const char *name))
{
grub_disk_dev_t p;
+ grub_disk_pull_t pull;
- for (p = grub_disk_dev_list; p; p = p->next)
- if (p->iterate && (p->iterate) (hook))
- return 1;
+ for (pull = 0; pull < GRUB_DISK_PULL_MAX; pull++)
+ for (p = grub_disk_dev_list; p; p = p->next)
+ if (p->iterate && (p->iterate) (hook, pull))
+ return 1;
return 0;
}
disk = (grub_disk_t) grub_zalloc (sizeof (*disk));
if (! disk)
return 0;
+ disk->log_sector_size = GRUB_DISK_SECTOR_BITS;
p = find_part_sep (name);
if (p)
if (! disk->name)
goto fail;
-
for (dev = grub_disk_dev_list; dev; dev = dev->next)
{
if ((dev->open) (raw, disk) == GRUB_ERR_NONE)
grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no such disk");
goto fail;
}
+ if (disk->log_sector_size > GRUB_DISK_CACHE_BITS + GRUB_DISK_SECTOR_BITS
+ || disk->log_sector_size < GRUB_DISK_SECTOR_BITS)
+ {
+ grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
+ "sector sizes of %d bytes aren't supported yet",
+ (1 << disk->log_sector_size));
+ goto fail;
+ }
disk->dev = dev;
*sector += start;
}
- if (disk->total_sectors <= *sector
- || ((*offset + size + GRUB_DISK_SECTOR_SIZE - 1)
- >> GRUB_DISK_SECTOR_BITS) > disk->total_sectors - *sector)
+ if (disk->total_sectors != GRUB_DISK_SIZE_UNKNOWN
+ && ((disk->total_sectors << (disk->log_sector_size - GRUB_DISK_SECTOR_BITS)) <= *sector
+ || ((*offset + size + GRUB_DISK_SECTOR_SIZE - 1)
+ >> GRUB_DISK_SECTOR_BITS) > (disk->total_sectors
+ << (disk->log_sector_size
+ - GRUB_DISK_SECTOR_BITS)) - *sector))
return grub_error (GRUB_ERR_OUT_OF_RANGE, "out of disk");
return GRUB_ERR_NONE;
}
+static inline grub_disk_addr_t
+transform_sector (grub_disk_t disk, grub_disk_addr_t sector)
+{
+ return sector >> (disk->log_sector_size - GRUB_DISK_SECTOR_BITS);
+}
+
+/* Small read (less than cache size and not pass across cache unit boundaries).
+ sector is already adjusted and is divisible by cache unit size.
+ */
+static grub_err_t
+grub_disk_read_small (grub_disk_t disk, grub_disk_addr_t sector,
+ grub_off_t offset, grub_size_t size, void *buf)
+{
+ char *data;
+ char *tmp_buf;
+
+ /* Fetch the cache. */
+ data = grub_disk_cache_fetch (disk->dev->id, disk->id, sector);
+ if (data)
+ {
+ /* Just copy it! */
+ grub_memcpy (buf, data + offset, size);
+ grub_disk_cache_unlock (disk->dev->id, disk->id, sector);
+ return GRUB_ERR_NONE;
+ }
+
+ /* Allocate a temporary buffer. */
+ tmp_buf = grub_malloc (GRUB_DISK_SECTOR_SIZE << GRUB_DISK_CACHE_BITS);
+ if (! tmp_buf)
+ return grub_errno;
+
+ /* Otherwise read data from the disk actually. */
+ if (disk->total_sectors == GRUB_DISK_SIZE_UNKNOWN
+ || sector + GRUB_DISK_CACHE_SIZE
+ < (disk->total_sectors << (disk->log_sector_size - GRUB_DISK_SECTOR_BITS)))
+ {
+ grub_err_t err;
+ err = (disk->dev->read) (disk, transform_sector (disk, sector),
+ 1 << (GRUB_DISK_CACHE_BITS
+ + GRUB_DISK_SECTOR_BITS
+ - disk->log_sector_size), tmp_buf);
+ if (!err)
+ {
+ /* Copy it and store it in the disk cache. */
+ grub_memcpy (buf, tmp_buf + offset, size);
+ grub_disk_cache_store (disk->dev->id, disk->id,
+ sector, tmp_buf);
+ grub_free (tmp_buf);
+ return GRUB_ERR_NONE;
+ }
+ }
+
+ grub_errno = GRUB_ERR_NONE;
+
+ {
+ /* Uggh... Failed. Instead, just read necessary data. */
+ unsigned num;
+ grub_disk_addr_t aligned_sector;
+
+ sector += (offset >> GRUB_DISK_SECTOR_BITS);
+ offset &= ((1 << GRUB_DISK_SECTOR_BITS) - 1);
+ aligned_sector = (sector & ~((1 << (disk->log_sector_size
+ - GRUB_DISK_SECTOR_BITS))
+ - 1));
+ offset += ((sector - aligned_sector) << GRUB_DISK_SECTOR_BITS);
+ num = ((size + offset + (1 << (disk->log_sector_size))
+ - 1) >> (disk->log_sector_size));
+
+ tmp_buf = grub_malloc (num << disk->log_sector_size);
+ if (!tmp_buf)
+ return grub_errno;
+
+ if ((disk->dev->read) (disk, transform_sector (disk, aligned_sector),
+ num, tmp_buf))
+ {
+ grub_error_push ();
+ grub_dprintf ("disk", "%s read failed\n", disk->name);
+ grub_error_pop ();
+ return grub_errno;
+ }
+ grub_memcpy (buf, tmp_buf + offset, size);
+ return GRUB_ERR_NONE;
+ }
+}
+
/* Read data from the disk. */
grub_err_t
grub_disk_read (grub_disk_t disk, grub_disk_addr_t sector,
grub_off_t offset, grub_size_t size, void *buf)
{
- char *tmp_buf;
- unsigned real_offset;
+ grub_off_t real_offset;
+ grub_disk_addr_t real_sector;
+ grub_size_t real_size;
/* First of all, check if the region is within the disk. */
if (grub_disk_adjust_range (disk, §or, &offset, size) != GRUB_ERR_NONE)
return grub_errno;
}
+ real_sector = sector;
real_offset = offset;
+ real_size = size;
- /* Allocate a temporary buffer. */
- tmp_buf = grub_malloc (GRUB_DISK_SECTOR_SIZE << GRUB_DISK_CACHE_BITS);
- if (! tmp_buf)
- return grub_errno;
-
- /* Until SIZE is zero... */
- while (size)
+ /* First read until first cache boundary. */
+ if (offset || (sector & (GRUB_DISK_CACHE_SIZE - 1)))
{
- char *data;
grub_disk_addr_t start_sector;
- grub_size_t len;
grub_size_t pos;
+ grub_err_t err;
+ grub_size_t len;
- /* For reading bulk data. */
start_sector = sector & ~(GRUB_DISK_CACHE_SIZE - 1);
pos = (sector - start_sector) << GRUB_DISK_SECTOR_BITS;
len = ((GRUB_DISK_SECTOR_SIZE << GRUB_DISK_CACHE_BITS)
- - pos - real_offset);
+ - pos - offset);
if (len > size)
len = size;
+ err = grub_disk_read_small (disk, start_sector,
+ offset + pos, len, buf);
+ if (err)
+ return err;
+ buf = (char *) buf + len;
+ size -= len;
+ offset += len;
+ sector += (offset >> GRUB_DISK_SECTOR_BITS);
+ offset &= ((1 << GRUB_DISK_SECTOR_BITS) - 1);
+ }
- /* Fetch the cache. */
- data = grub_disk_cache_fetch (disk->dev->id, disk->id, start_sector);
- if (data)
+ /* Until SIZE is zero... */
+ while (size >= (GRUB_DISK_CACHE_SIZE << GRUB_DISK_SECTOR_BITS))
+ {
+ char *data = NULL;
+ grub_disk_addr_t agglomerate;
+ grub_err_t err;
+
+ /* agglomerate read until we find a first cached entry. */
+ for (agglomerate = 0; agglomerate
+ < (size >> (GRUB_DISK_SECTOR_BITS + GRUB_DISK_CACHE_BITS));
+ agglomerate++)
{
- /* Just copy it! */
- grub_memcpy (buf, data + pos + real_offset, len);
- grub_disk_cache_unlock (disk->dev->id, disk->id, start_sector);
+ data = grub_disk_cache_fetch (disk->dev->id, disk->id,
+ sector + (agglomerate
+ << GRUB_DISK_CACHE_BITS));
+ if (data)
+ break;
}
- else
- {
- /* Otherwise read data from the disk actually. */
- if (start_sector + GRUB_DISK_CACHE_SIZE > disk->total_sectors
- || (disk->dev->read) (disk, start_sector,
- GRUB_DISK_CACHE_SIZE, tmp_buf)
- != GRUB_ERR_NONE)
- {
- /* Uggh... Failed. Instead, just read necessary data. */
- unsigned num;
- char *p;
-
- grub_errno = GRUB_ERR_NONE;
-
- num = ((size + real_offset + GRUB_DISK_SECTOR_SIZE - 1)
- >> GRUB_DISK_SECTOR_BITS);
-
- p = grub_realloc (tmp_buf, num << GRUB_DISK_SECTOR_BITS);
- if (!p)
- goto finish;
-
- tmp_buf = p;
-
- if ((disk->dev->read) (disk, sector, num, tmp_buf))
- {
- grub_error_push ();
- grub_dprintf ("disk", "%s read failed\n", disk->name);
- grub_error_pop ();
- goto finish;
- }
-
- grub_memcpy (buf, tmp_buf + real_offset, size);
-
- /* Call the read hook, if any. */
- if (disk->read_hook)
- while (size)
- {
- grub_size_t to_read = (size > GRUB_DISK_SECTOR_SIZE) ? GRUB_DISK_SECTOR_SIZE : size;
- (disk->read_hook) (sector, real_offset,
- to_read);
- if (grub_errno != GRUB_ERR_NONE)
- goto finish;
-
- sector++;
- size -= to_read - real_offset;
- real_offset = 0;
- }
-
- /* This must be the end. */
- goto finish;
- }
- /* Copy it and store it in the disk cache. */
- grub_memcpy (buf, tmp_buf + pos + real_offset, len);
- grub_disk_cache_store (disk->dev->id, disk->id,
- start_sector, tmp_buf);
+ if (data)
+ {
+ grub_memcpy ((char *) buf
+ + (agglomerate << (GRUB_DISK_CACHE_BITS
+ + GRUB_DISK_SECTOR_BITS)),
+ data, GRUB_DISK_CACHE_SIZE << GRUB_DISK_SECTOR_BITS);
+ grub_disk_cache_unlock (disk->dev->id, disk->id,
+ sector + (agglomerate
+ << GRUB_DISK_CACHE_BITS));
}
- /* Call the read hook, if any. */
- if (disk->read_hook)
+ if (agglomerate)
{
- grub_disk_addr_t s = sector;
- grub_size_t l = len;
-
- while (l)
- {
- (disk->read_hook) (s, real_offset,
- ((l > GRUB_DISK_SECTOR_SIZE)
- ? GRUB_DISK_SECTOR_SIZE
- : l));
-
- if (l < GRUB_DISK_SECTOR_SIZE - real_offset)
- break;
+ grub_disk_addr_t i;
+
+ err = (disk->dev->read) (disk, transform_sector (disk, sector),
+ agglomerate << (GRUB_DISK_CACHE_BITS
+ + GRUB_DISK_SECTOR_BITS
+ - disk->log_sector_size),
+ buf);
+ if (err)
+ return err;
+
+ for (i = 0; i < agglomerate; i ++)
+ grub_disk_cache_store (disk->dev->id, disk->id,
+ sector + (i << GRUB_DISK_CACHE_BITS),
+ (char *) buf
+ + (i << (GRUB_DISK_CACHE_BITS
+ + GRUB_DISK_SECTOR_BITS)));
+
+ sector += agglomerate << GRUB_DISK_CACHE_BITS;
+ size -= agglomerate << (GRUB_DISK_CACHE_BITS + GRUB_DISK_SECTOR_BITS);
+ buf = (char *) buf
+ + (agglomerate << (GRUB_DISK_CACHE_BITS + GRUB_DISK_SECTOR_BITS));
+ }
- s++;
- l -= GRUB_DISK_SECTOR_SIZE - real_offset;
- real_offset = 0;
- }
+ if (data)
+ {
+ sector += GRUB_DISK_CACHE_SIZE;
+ buf = (char *) buf + (GRUB_DISK_CACHE_SIZE << GRUB_DISK_SECTOR_BITS);
+ size -= (GRUB_DISK_CACHE_SIZE << GRUB_DISK_SECTOR_BITS);
}
+ }
- sector = start_sector + GRUB_DISK_CACHE_SIZE;
- buf = (char *) buf + len;
- size -= len;
- real_offset = 0;
+ /* And now read the last part. */
+ if (size)
+ {
+ grub_err_t err;
+ err = grub_disk_read_small (disk, sector, 0, size, buf);
+ if (err)
+ return err;
}
- finish:
+ /* Call the read hook, if any. */
+ if (disk->read_hook)
+ {
+ grub_disk_addr_t s = real_sector;
+ grub_size_t l = real_size;
+ grub_off_t o = real_offset;
- grub_free (tmp_buf);
+ while (l)
+ {
+ (disk->read_hook) (s, o,
+ ((l > GRUB_DISK_SECTOR_SIZE)
+ ? GRUB_DISK_SECTOR_SIZE
+ : l));
+ s++;
+ l -= GRUB_DISK_SECTOR_SIZE - o;
+ o = 0;
+ }
+ }
return grub_errno;
}
grub_off_t offset, grub_size_t size, const void *buf)
{
unsigned real_offset;
+ grub_disk_addr_t aligned_sector;
grub_dprintf ("disk", "Writing `%s'...\n", disk->name);
if (grub_disk_adjust_range (disk, §or, &offset, size) != GRUB_ERR_NONE)
return -1;
- real_offset = offset;
+ aligned_sector = (sector & ~((1 << (disk->log_sector_size
+ - GRUB_DISK_SECTOR_BITS)) - 1));
+ real_offset = offset + ((sector - aligned_sector) << GRUB_DISK_SECTOR_BITS);
+ sector = aligned_sector;
while (size)
{
- if (real_offset != 0 || (size < GRUB_DISK_SECTOR_SIZE && size != 0))
+ if (real_offset != 0 || (size < (1U << disk->log_sector_size)
+ && size != 0))
{
- char tmp_buf[GRUB_DISK_SECTOR_SIZE];
+ char tmp_buf[1 << disk->log_sector_size];
grub_size_t len;
grub_partition_t part;
part = disk->partition;
disk->partition = 0;
- if (grub_disk_read (disk, sector, 0, GRUB_DISK_SECTOR_SIZE, tmp_buf)
+ if (grub_disk_read (disk, sector,
+ 0, (1 << disk->log_sector_size), tmp_buf)
!= GRUB_ERR_NONE)
{
disk->partition = part;
}
disk->partition = part;
- len = GRUB_DISK_SECTOR_SIZE - real_offset;
+ len = (1 << disk->log_sector_size) - real_offset;
if (len > size)
len = size;
if ((disk->dev->write) (disk, sector, 1, tmp_buf) != GRUB_ERR_NONE)
goto finish;
- sector++;
+ sector += (1 << (disk->log_sector_size - GRUB_DISK_SECTOR_BITS));
buf = (char *) buf + len;
size -= len;
real_offset = 0;
grub_size_t len;
grub_size_t n;
- len = size & ~(GRUB_DISK_SECTOR_SIZE - 1);
- n = size >> GRUB_DISK_SECTOR_BITS;
+ len = size & ~((1 << disk->log_sector_size) - 1);
+ n = size >> disk->log_sector_size;
if ((disk->dev->write) (disk, sector, n, buf) != GRUB_ERR_NONE)
goto finish;
{
if (disk->partition)
return grub_partition_get_len (disk->partition);
+ else if (disk->total_sectors != GRUB_DISK_SIZE_UNKNOWN)
+ return disk->total_sectors << (disk->log_sector_size - GRUB_DISK_SECTOR_BITS);
else
- return disk->total_sectors;
+ return GRUB_DISK_SIZE_UNKNOWN;
}
#define GRUB_MODULES_MACHINE_READONLY
#endif
+#ifdef GRUB_MACHINE_EMU
+#include <sys/mman.h>
+#endif
+
\f
grub_dl_t grub_dl_head = 0;
struct grub_symbol *next;
const char *name;
void *addr;
+ int isfunc;
grub_dl_t mod; /* The module to which this symbol belongs. */
};
typedef struct grub_symbol *grub_symbol_t;
/* Resolve the symbol name NAME and return the address.
Return NULL, if not found. */
-static void *
+static grub_symbol_t
grub_dl_resolve_symbol (const char *name)
{
grub_symbol_t sym;
for (sym = grub_symtab[grub_symbol_hash (name)]; sym; sym = sym->next)
if (grub_strcmp (sym->name, name) == 0)
- return sym->addr;
+ return sym;
return 0;
}
/* Register a symbol with the name NAME and the address ADDR. */
grub_err_t
-grub_dl_register_symbol (const char *name, void *addr, grub_dl_t mod)
+grub_dl_register_symbol (const char *name, void *addr, int isfunc,
+ grub_dl_t mod)
{
grub_symbol_t sym;
unsigned k;
sym->addr = addr;
sym->mod = mod;
+ sym->isfunc = isfunc;
k = grub_symbol_hash (name);
sym->next = grub_symtab[k];
{
unsigned i;
Elf_Shdr *s;
+ grub_size_t tsize = 0, talign = 1;
+#ifdef __ia64__
+ grub_size_t tramp;
+ grub_size_t got;
+#endif
+ char *ptr;
+
+ for (i = 0, s = (Elf_Shdr *)((char *) e + e->e_shoff);
+ i < e->e_shnum;
+ i++, s = (Elf_Shdr *)((char *) s + e->e_shentsize))
+ {
+ tsize += ALIGN_UP (s->sh_size, s->sh_addralign);
+ if (talign < s->sh_addralign)
+ talign = s->sh_addralign;
+ }
+
+#ifdef __ia64__
+ grub_arch_dl_get_tramp_got_size (e, &tramp, &got);
+ tramp *= GRUB_IA64_DL_TRAMP_SIZE;
+ got *= sizeof (grub_uint64_t);
+ tsize += ALIGN_UP (tramp, GRUB_ARCH_DL_TRAMP_ALIGN);
+ if (talign < GRUB_ARCH_DL_TRAMP_ALIGN)
+ talign = GRUB_ARCH_DL_TRAMP_ALIGN;
+ tsize += ALIGN_UP (got, GRUB_ARCH_DL_GOT_ALIGN);
+ if (talign < GRUB_ARCH_DL_GOT_ALIGN)
+ talign = GRUB_ARCH_DL_GOT_ALIGN;
+#endif
+
+#ifdef GRUB_MACHINE_EMU
+ if (talign < 8192 * 16)
+ talign = 8192 * 16;
+ tsize = ALIGN_UP (tsize, 8192 * 16);
+#endif
+
+ mod->base = grub_memalign (talign, tsize);
+ if (!mod->base)
+ return grub_errno;
+ ptr = mod->base;
+
+#ifdef GRUB_MACHINE_EMU
+ mprotect (mod->base, tsize, PROT_READ | PROT_WRITE | PROT_EXEC);
+#endif
for (i = 0, s = (Elf_Shdr *)((char *) e + e->e_shoff);
i < e->e_shnum;
{
void *addr;
- addr = grub_memalign (s->sh_addralign, s->sh_size);
- if (! addr)
- {
- grub_free (seg);
- return grub_errno;
- }
+ ptr = (char *) ALIGN_UP ((grub_addr_t) ptr, s->sh_addralign);
+ addr = ptr;
+ ptr += s->sh_size;
switch (s->sh_type)
{
mod->segment = seg;
}
}
+#ifdef __ia64__
+ ptr = (char *) ALIGN_UP ((grub_addr_t) ptr, GRUB_ARCH_DL_TRAMP_ALIGN);
+ mod->tramp = ptr;
+ ptr += tramp;
+ ptr = (char *) ALIGN_UP ((grub_addr_t) ptr, GRUB_ARCH_DL_GOT_ALIGN);
+ mod->got = ptr;
+ ptr += got;
+#endif
return GRUB_ERR_NONE;
}
/* Resolve a global symbol. */
if (sym->st_name != 0 && sym->st_shndx == 0)
{
- sym->st_value = (Elf_Addr) grub_dl_resolve_symbol (name);
- if (! sym->st_value)
+ grub_symbol_t nsym = grub_dl_resolve_symbol (name);
+ if (! nsym)
return grub_error (GRUB_ERR_BAD_MODULE,
"symbol not found: `%s'", name);
+ sym->st_value = (Elf_Addr) nsym->addr;
+ if (nsym->isfunc)
+ sym->st_info = ELF_ST_INFO (bind, STT_FUNC);
}
else
{
sym->st_value += (Elf_Addr) grub_dl_get_section_addr (mod,
sym->st_shndx);
if (bind != STB_LOCAL)
- if (grub_dl_register_symbol (name, (void *) sym->st_value, mod))
+ if (grub_dl_register_symbol (name, (void *) sym->st_value, 0, mod))
return grub_errno;
}
break;
case STT_FUNC:
sym->st_value += (Elf_Addr) grub_dl_get_section_addr (mod,
sym->st_shndx);
+#ifdef __ia64__
+ {
+ /* FIXME: free descriptor once it's not used anymore. */
+ char **desc;
+ desc = grub_malloc (2 * sizeof (char *));
+ if (!desc)
+ return grub_errno;
+ desc[0] = (void *) sym->st_value;
+ desc[1] = mod->base;
+ sym->st_value = (grub_addr_t) desc;
+ }
+#endif
if (bind != STB_LOCAL)
- if (grub_dl_register_symbol (name, (void *) sym->st_value, mod))
+ if (grub_dl_register_symbol (name, (void *) sym->st_value, 1, mod))
return grub_errno;
-
if (grub_strcmp (name, "grub_mod_init") == 0)
mod->init = (void (*) (grub_dl_t)) sym->st_value;
else if (grub_strcmp (name, "grub_mod_fini") == 0)
(mod->init) (mod);
}
+/* Me, Vladimir Serbinenko, hereby I add this module check as per new
+ GNU module policy. Note that this license check is informative only.
+ Modules have to be licensed under GPLv3 or GPLv3+ (optionally
+ multi-licensed under other licences as well) independently of the
+ presence of this check and solely by linking (module loading in GRUB
+ constitutes linking) and GRUB core being licensed under GPLv3+.
+ Be sure to understand your license obligations.
+*/
+static grub_err_t
+grub_dl_check_license (Elf_Ehdr *e)
+{
+ Elf_Shdr *s;
+ const char *str;
+ unsigned i;
+
+ s = (Elf_Shdr *) ((char *) e + e->e_shoff + e->e_shstrndx * e->e_shentsize);
+ str = (char *) e + s->sh_offset;
+
+ for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff);
+ i < e->e_shnum;
+ i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize))
+ if (grub_strcmp (str + s->sh_name, ".module_license") == 0)
+ {
+ if (grub_strcmp ((char *) e + s->sh_offset, "LICENSE=GPLv3") == 0
+ || grub_strcmp ((char *) e + s->sh_offset, "LICENSE=GPLv3+") == 0
+ || grub_strcmp ((char *) e + s->sh_offset, "LICENSE=GPLv2+") == 0)
+ return GRUB_ERR_NONE;
+ }
+
+ return grub_error (GRUB_ERR_BAD_MODULE, "incompatible license");
+}
+
static grub_err_t
grub_dl_resolve_name (grub_dl_t mod, Elf_Ehdr *e)
{
mod->ref_count = 1;
grub_dprintf ("modules", "relocating to %p\n", mod);
- if (grub_dl_resolve_name (mod, e)
+ /* Me, Vladimir Serbinenko, hereby I add this module check as per new
+ GNU module policy. Note that this license check is informative only.
+ Modules have to be licensed under GPLv3 or GPLv3+ (optionally
+ multi-licensed under other licences as well) independently of the
+ presence of this check and solely by linking (module loading in GRUB
+ constitutes linking) and GRUB core being licensed under GPLv3+.
+ Be sure to understand your license obligations.
+ */
+ if (grub_dl_check_license (e)
+ || grub_dl_resolve_name (mod, e)
|| grub_dl_resolve_dependencies (mod, e)
|| grub_dl_load_segments (mod, e)
|| grub_dl_resolve_symbols (mod, e)
grub_file_close (file);
mod = grub_dl_load_core (core, size);
+ grub_free (core);
if (! mod)
- {
- grub_free (core);
- return 0;
- }
+ return 0;
- mod->ref_count = 0;
+ mod->ref_count--;
return mod;
}
{
depn = dep->next;
- if (! grub_dl_unref (dep->mod))
- grub_dl_unload (dep->mod);
+ grub_dl_unload (dep->mod);
grub_free (dep);
}
#include <grub/efi/console_control.h>
#include <grub/efi/pe32.h>
#include <grub/machine/time.h>
+#include <grub/time.h>
#include <grub/term.h>
#include <grub/kernel.h>
#include <grub/mm.h>
for (;;) ;
}
-/* On i386, a firmware-independant grub_reboot() is provided by realmode.S. */
-#ifndef __i386__
-void
-grub_reboot (void)
-{
- grub_efi_fini ();
- efi_call_4 (grub_efi_system_table->runtime_services->reset_system,
- GRUB_EFI_RESET_COLD, GRUB_EFI_SUCCESS, 0, NULL);
- for (;;) ;
-}
-#endif
-
grub_err_t
grub_efi_set_virtual_address_map (grub_efi_uintn_t memory_map_size,
grub_efi_uintn_t descriptor_size,
return grub_error (GRUB_ERR_IO, "set_virtual_address_map failed");
}
-grub_uint32_t
-grub_get_rtc (void)
+grub_uint64_t
+grub_rtc_get_time_ms (void)
{
grub_efi_time_t time;
grub_efi_runtime_services_t *r;
/* What is possible in this case? */
return 0;
- return (((time.minute * 60 + time.second) * 1000
- + time.nanosecond / 1000000)
- * GRUB_TICKS_PER_SECOND / 1000);
+ return ((time.minute * 60 + time.second) * 1000
+ + time.nanosecond / 1000000);
+}
+
+grub_uint32_t
+grub_get_rtc (void)
+{
+ return grub_rtc_get_time_ms ();
}
/* Search the mods section from the PE32/PE32+ image. This code uses
a PE32 header, but should work with PE32+ as well. */
grub_addr_t
-grub_arch_modules_addr (void)
+grub_efi_modules_addr (void)
{
grub_efi_loaded_image_t *image;
struct grub_pe32_header *header;
dp = (grub_efi_device_path_t *) ((char *) dp + len);
}
}
+
+/* Compare device paths. */
+int
+grub_efi_compare_device_paths (const grub_efi_device_path_t *dp1,
+ const grub_efi_device_path_t *dp2)
+{
+ if (! dp1 || ! dp2)
+ /* Return non-zero. */
+ return 1;
+
+ while (1)
+ {
+ grub_efi_uint8_t type1, type2;
+ grub_efi_uint8_t subtype1, subtype2;
+ grub_efi_uint16_t len1, len2;
+ int ret;
+
+ type1 = GRUB_EFI_DEVICE_PATH_TYPE (dp1);
+ type2 = GRUB_EFI_DEVICE_PATH_TYPE (dp2);
+
+ if (type1 != type2)
+ return (int) type2 - (int) type1;
+
+ subtype1 = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp1);
+ subtype2 = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp2);
+
+ if (subtype1 != subtype2)
+ return (int) subtype1 - (int) subtype2;
+
+ len1 = GRUB_EFI_DEVICE_PATH_LENGTH (dp1);
+ len2 = GRUB_EFI_DEVICE_PATH_LENGTH (dp2);
+
+ if (len1 != len2)
+ return (int) len1 - (int) len2;
+
+ ret = grub_memcmp (dp1, dp2, len1);
+ if (ret != 0)
+ return ret;
+
+ if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp1))
+ break;
+
+ dp1 = (grub_efi_device_path_t *) ((char *) dp1 + len1);
+ dp2 = (grub_efi_device_path_t *) ((char *) dp2 + len2);
+ }
+
+ return 0;
+}
#include <grub/mm.h>
#include <grub/kernel.h>
+grub_addr_t grub_modbase;
+
void
grub_efi_init (void)
{
+ grub_modbase = grub_efi_modules_addr ();
/* First of all, initialize the console so that GRUB can display
messages. */
grub_console_init ();
grub_efidisk_init ();
}
+void (*grub_efi_net_config) (grub_efi_handle_t hnd,
+ char **device,
+ char **path);
+
void
-grub_efi_set_prefix (void)
+grub_machine_get_bootlocation (char **device, char **path)
{
grub_efi_loaded_image_t *image = NULL;
- char *device = NULL;
- char *path = NULL;
-
- {
- char *pptr = NULL;
- if (grub_prefix[0] == '(')
- {
- pptr = grub_strrchr (grub_prefix, ')');
- if (pptr)
- {
- device = grub_strndup (grub_prefix + 1, pptr - grub_prefix - 1);
- pptr++;
- }
- }
- if (!pptr)
- pptr = grub_prefix;
- if (pptr[0])
- path = grub_strdup (pptr);
- }
-
- if ((!device || device[0] == ',' || !device[0]) || !path)
- image = grub_efi_get_loaded_image (grub_efi_image_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)
- {
- char *p;
-
- path = grub_efi_get_filename (image->file_path);
-
- /* Get the directory. */
- p = grub_strrchr (path, '/');
- if (p)
- *p = '\0';
- }
-
- if (device && path)
- {
- char *prefix;
-
- prefix = grub_xasprintf ("(%s)%s", device, path);
- if (prefix)
- {
- grub_env_set ("prefix", prefix);
- grub_free (prefix);
- }
- }
-
- grub_free (device);
- grub_free (path);
+ char *p;
+
+ image = grub_efi_get_loaded_image (grub_efi_image_handle);
+ if (!image)
+ return;
+ *device = grub_efidisk_get_device_name (image->device_handle);
+ *path = grub_efi_get_filename (image->file_path);
+ if (!*device && grub_efi_net_config)
+ grub_efi_net_config (image->device_handle, device, path);
+
+ /* Get the directory. */
+ p = grub_strrchr (*path, '/');
+ if (p)
+ *p = '\0';
}
void
#include <grub/file.h>
#include <grub/misc.h>
#include <grub/mm.h>
+#include <grub/dl.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
/* Check if EHDR is a valid ELF header. */
static grub_err_t
+++ /dev/null
-#ifndef GRUB_MACHINE_EMU
-#error "This source is only meant for grub-emu platform"
-#endif
-
-#if defined(__i386__) || defined(__x86_64__)
-/* Nothing is necessary. */
-#elif defined(__sparc__)
-#include "../sparc64/cache.S"
-#elif defined(__mips__)
-/* 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
-#error "No target cpu type is defined"
-#endif
--- /dev/null
+
+#if defined(__ia64__)
+#include <grub/cache.h>
+
+void __clear_cache (char *beg, char *end);
+
+void
+grub_arch_sync_caches (void *address, grub_size_t len)
+{
+ __clear_cache (address, (char *) address + len);
+}
+#endif
+
--- /dev/null
+#ifndef GRUB_MACHINE_EMU
+#error "This source is only meant for grub-emu platform"
+#endif
+
+#if defined(__i386__) || defined(__x86_64__)
+/* Nothing is necessary. */
+#elif defined(__sparc__)
+#include "../sparc64/cache.S"
+#elif defined(__mips__)
+/* 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"
+#elif defined(__ia64__)
+#else
+#error "No target cpu type is defined"
+#endif
grub_no_autoload = 1;
}
+#ifdef __ia64__
+void grub_arch_dl_get_tramp_got_size (const void *ehdr __attribute__ ((unused)),
+ grub_size_t *tramp, grub_size_t *got)
+{
+ *tramp = 0;
+ *got = 0;
+}
+#endif
+
#ifdef GRUB_LINKER_HAVE_INIT
void
grub_arch_dl_init_linker (void)
+++ /dev/null
-/* getroot.c - Get root device */
-/*
- * GRUB -- GRand Unified Bootloader
- * Copyright (C) 1999,2000,2001,2002,2003,2006,2007,2008,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 <config-util.h>
-#include <config.h>
-
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <assert.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <string.h>
-#include <dirent.h>
-#include <errno.h>
-#include <error.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <grub/util/misc.h>
-
-#ifdef __GNU__
-#include <hurd.h>
-#include <hurd/lookup.h>
-#include <hurd/fs.h>
-#include <sys/mman.h>
-#endif
-
-#ifdef __linux__
-# include <sys/types.h>
-# include <sys/wait.h>
-#endif
-
-#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR)
-# include <grub/util/libzfs.h>
-# include <grub/util/libnvpair.h>
-#endif
-
-#include <grub/mm.h>
-#include <grub/misc.h>
-#include <grub/emu/misc.h>
-#include <grub/emu/hostdisk.h>
-#include <grub/emu/getroot.h>
-
-static void
-strip_extra_slashes (char *dir)
-{
- char *p = dir;
-
- while ((p = strchr (p, '/')) != 0)
- {
- if (p[1] == '/')
- {
- memmove (p, p + 1, strlen (p));
- continue;
- }
- else if (p[1] == '\0')
- {
- if (p > dir)
- p[0] = '\0';
- break;
- }
-
- p++;
- }
-}
-
-static char *
-xgetcwd (void)
-{
- size_t size = 10;
- char *path;
-
- path = xmalloc (size);
- while (! getcwd (path, size))
- {
- size <<= 1;
- path = xrealloc (path, size);
- }
-
- return path;
-}
-
-#ifdef __linux__
-
-/* Statting something on a btrfs filesystem always returns a virtual device
- major/minor pair rather than the real underlying device, because btrfs
- can span multiple underlying devices (and even if it's currently only
- using a single device it can be dynamically extended onto another). We
- can't deal with the multiple-device case yet, but in the meantime, we can
- at least cope with the single-device case by scanning
- /proc/self/mountinfo. */
-static char *
-find_root_device_from_mountinfo (const char *dir)
-{
- FILE *fp;
- char *buf = NULL;
- size_t len = 0;
- char *ret = NULL;
-
- fp = fopen ("/proc/self/mountinfo", "r");
- if (! fp)
- return NULL; /* fall through to other methods */
-
- while (getline (&buf, &len, fp) > 0)
- {
- int mnt_id, parent_mnt_id;
- unsigned int major, minor;
- char enc_root[PATH_MAX], enc_path[PATH_MAX];
- int count;
- size_t enc_path_len;
- const char *sep;
- char fstype[PATH_MAX], device[PATH_MAX];
- struct stat st;
-
- if (sscanf (buf, "%d %d %u:%u %s %s%n",
- &mnt_id, &parent_mnt_id, &major, &minor, enc_root, enc_path,
- &count) < 6)
- continue;
-
- if (strcmp (enc_root, "/") != 0)
- continue; /* only a subtree is mounted */
-
- enc_path_len = strlen (enc_path);
- /* Check that enc_path is a prefix of dir. The prefix must either be
- the entire string, or end with a slash, or be immediately followed
- by a slash. */
- if (strncmp (dir, enc_path, enc_path_len) != 0 ||
- (enc_path_len && dir[enc_path_len - 1] != '/' &&
- dir[enc_path_len] && dir[enc_path_len] != '/'))
- continue;
-
- /* This is a parent of the requested directory. /proc/self/mountinfo
- is in mount order, so it must be the closest parent we've
- encountered so far. If it's virtual, return its device node;
- otherwise, carry on to try to find something closer. */
-
- free (ret);
- ret = NULL;
-
- if (major != 0)
- continue; /* not a virtual device */
-
- sep = strstr (buf + count, " - ");
- if (!sep)
- continue;
-
- sep += sizeof (" - ") - 1;
- if (sscanf (sep, "%s %s", fstype, device) != 2)
- continue;
-
- if (stat (device, &st) < 0)
- continue;
-
- if (!S_ISBLK (st.st_mode))
- continue; /* not a block device */
-
- ret = strdup (device);
- }
-
- free (buf);
- fclose (fp);
- return ret;
-}
-
-#endif /* __linux__ */
-
-#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR)
-static char *
-find_root_device_from_libzfs (const char *dir)
-{
- char *device = NULL;
- char *poolname;
- char *poolfs;
-
- grub_find_zpool_from_dir (dir, &poolname, &poolfs);
- if (! poolname)
- return NULL;
-
- {
- zpool_handle_t *zpool;
- libzfs_handle_t *libzfs;
- nvlist_t *config, *vdev_tree;
- nvlist_t **children, **path;
- unsigned int nvlist_count;
- unsigned int i;
-
- libzfs = grub_get_libzfs_handle ();
- if (! libzfs)
- return NULL;
-
- zpool = zpool_open (libzfs, poolname);
- config = zpool_get_config (zpool, NULL);
-
- if (nvlist_lookup_nvlist (config, "vdev_tree", &vdev_tree) != 0)
- error (1, errno, "nvlist_lookup_nvlist (\"vdev_tree\")");
-
- if (nvlist_lookup_nvlist_array (vdev_tree, "children", &children, &nvlist_count) != 0)
- error (1, errno, "nvlist_lookup_nvlist_array (\"children\")");
- assert (nvlist_count > 0);
-
- while (nvlist_lookup_nvlist_array (children[0], "children",
- &children, &nvlist_count) == 0)
- assert (nvlist_count > 0);
-
- for (i = 0; i < nvlist_count; i++)
- {
- if (nvlist_lookup_string (children[i], "path", &device) != 0)
- error (1, errno, "nvlist_lookup_string (\"path\")");
-
- struct stat st;
- if (stat (device, &st) == 0)
- {
- device = xstrdup (device);
- break;
- }
-
- device = NULL;
- }
-
- zpool_close (zpool);
- }
-
- free (poolname);
- if (poolfs)
- free (poolfs);
-
- return device;
-}
-#endif
-
-#ifdef __MINGW32__
-
-char *
-grub_find_device (const char *dir __attribute__ ((unused)),
- dev_t dev __attribute__ ((unused)))
-{
- return 0;
-}
-
-#elif ! defined(__CYGWIN__)
-
-char *
-grub_find_device (const char *dir, dev_t dev)
-{
- DIR *dp;
- char *saved_cwd;
- struct dirent *ent;
-
- if (! dir)
- {
-#ifdef __CYGWIN__
- return NULL;
-#else
- dir = "/dev";
-#endif
- }
-
- dp = opendir (dir);
- if (! dp)
- return 0;
-
- saved_cwd = xgetcwd ();
-
- grub_util_info ("changing current directory to %s", dir);
- if (chdir (dir) < 0)
- {
- free (saved_cwd);
- closedir (dp);
- return 0;
- }
-
- while ((ent = readdir (dp)) != 0)
- {
- struct stat st;
-
- /* Avoid:
- - dotfiles (like "/dev/.tmp.md0") since they could be duplicates.
- - dotdirs (like "/dev/.static") since they could contain duplicates. */
- if (ent->d_name[0] == '.')
- continue;
-
- if (lstat (ent->d_name, &st) < 0)
- /* Ignore any error. */
- continue;
-
- if (S_ISLNK (st.st_mode)) {
-#ifdef __linux__
- if (strcmp (dir, "mapper") == 0) {
- /* Follow symbolic links under /dev/mapper/; the canonical name
- may be something like /dev/dm-0, but the names under
- /dev/mapper/ are more human-readable and so we prefer them if
- we can get them. */
- if (stat (ent->d_name, &st) < 0)
- continue;
- } else
-#endif /* __linux__ */
- /* Don't follow other symbolic links. */
- continue;
- }
-
- if (S_ISDIR (st.st_mode))
- {
- /* Find it recursively. */
- char *res;
-
- res = grub_find_device (ent->d_name, dev);
-
- if (res)
- {
- if (chdir (saved_cwd) < 0)
- grub_util_error ("cannot restore the original directory");
-
- free (saved_cwd);
- closedir (dp);
- return res;
- }
- }
-
-#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__APPLE__)
- if (S_ISCHR (st.st_mode) && st.st_rdev == dev)
-#else
- if (S_ISBLK (st.st_mode) && st.st_rdev == dev)
-#endif
- {
-#ifdef __linux__
- /* Skip device names like /dev/dm-0, which are short-hand aliases
- to more descriptive device names, e.g. those under /dev/mapper */
- if (ent->d_name[0] == 'd' &&
- ent->d_name[1] == 'm' &&
- ent->d_name[2] == '-' &&
- ent->d_name[3] >= '0' &&
- ent->d_name[3] <= '9')
- continue;
-#endif
-
- /* Found! */
- char *res;
- char *cwd;
-#if defined(__NetBSD__)
- /* Convert this block device to its character (raw) device. */
- const char *template = "%s/r%s";
-#else
- /* Keep the device name as it is. */
- const char *template = "%s/%s";
-#endif
-
- cwd = xgetcwd ();
- res = xmalloc (strlen (cwd) + strlen (ent->d_name) + 3);
- sprintf (res, template, cwd, ent->d_name);
- strip_extra_slashes (res);
- free (cwd);
-
- /* /dev/root is not a real block device keep looking, takes care
- of situation where root filesystem is on the same partition as
- grub files */
-
- if (strcmp(res, "/dev/root") == 0)
- continue;
-
- if (chdir (saved_cwd) < 0)
- grub_util_error ("cannot restore the original directory");
-
- free (saved_cwd);
- closedir (dp);
- return res;
- }
- }
-
- if (chdir (saved_cwd) < 0)
- grub_util_error ("cannot restore the original directory");
-
- free (saved_cwd);
- closedir (dp);
- return 0;
-}
-
-#else /* __CYGWIN__ */
-
-/* Read drive/partition serial number from mbr/boot sector,
- return 0 on read error, ~0 on unknown serial. */
-static unsigned
-get_bootsec_serial (const char *os_dev, int mbr)
-{
- /* Read boot sector. */
- int fd = open (os_dev, O_RDONLY);
- if (fd < 0)
- return 0;
- unsigned char buf[0x200];
- int n = read (fd, buf, sizeof (buf));
- close (fd);
- if (n != sizeof(buf))
- return 0;
-
- /* Check signature. */
- if (!(buf[0x1fe] == 0x55 && buf[0x1ff] == 0xaa))
- return ~0;
-
- /* Serial number offset depends on boot sector type. */
- if (mbr)
- n = 0x1b8;
- else if (memcmp (buf + 0x03, "NTFS", 4) == 0)
- n = 0x048;
- else if (memcmp (buf + 0x52, "FAT32", 5) == 0)
- n = 0x043;
- else if (memcmp (buf + 0x36, "FAT", 3) == 0)
- n = 0x027;
- else
- return ~0;
-
- unsigned serial = *(unsigned *)(buf + n);
- if (serial == 0)
- return ~0;
- return serial;
-}
-
-char *
-grub_find_device (const char *path, dev_t dev)
-{
- /* No root device for /cygdrive. */
- if (dev == (DEV_CYGDRIVE_MAJOR << 16))
- return 0;
-
- /* Convert to full POSIX and Win32 path. */
- char fullpath[PATH_MAX], winpath[PATH_MAX];
- cygwin_conv_to_full_posix_path (path, fullpath);
- cygwin_conv_to_full_win32_path (fullpath, winpath);
-
- /* If identical, this is no real filesystem path. */
- if (strcmp (fullpath, winpath) == 0)
- return 0;
-
- /* Check for floppy drive letter. */
- if (winpath[0] && winpath[1] == ':' && strchr ("AaBb", winpath[0]))
- return xstrdup (strchr ("Aa", winpath[0]) ? "/dev/fd0" : "/dev/fd1");
-
- /* Cygwin returns the partition serial number in stat.st_dev.
- This is never identical to the device number of the emulated
- /dev/sdXN device, so above grub_find_device () does not work.
- Search the partition with the same serial in boot sector instead. */
- char devpath[sizeof ("/dev/sda15") + 13]; /* Size + Paranoia. */
- int d;
- for (d = 'a'; d <= 'z'; d++)
- {
- sprintf (devpath, "/dev/sd%c", d);
- if (get_bootsec_serial (devpath, 1) == 0)
- continue;
- int p;
- for (p = 1; p <= 15; p++)
- {
- sprintf (devpath, "/dev/sd%c%d", d, p);
- unsigned ser = get_bootsec_serial (devpath, 0);
- if (ser == 0)
- break;
- if (ser != (unsigned)~0 && dev == (dev_t)ser)
- return xstrdup (devpath);
- }
- }
- return 0;
-}
-
-#endif /* __CYGWIN__ */
-
-char *
-grub_guess_root_device (const char *dir)
-{
- char *os_dev;
-#ifdef __GNU__
- file_t file;
- mach_port_t *ports;
- int *ints;
- loff_t *offsets;
- char *data;
- error_t err;
- mach_msg_type_number_t num_ports = 0, num_ints = 0, num_offsets = 0, data_len = 0;
- size_t name_len;
-
- file = file_name_lookup (dir, 0, 0);
- if (file == MACH_PORT_NULL)
- return 0;
-
- err = file_get_storage_info (file,
- &ports, &num_ports,
- &ints, &num_ints,
- &offsets, &num_offsets,
- &data, &data_len);
-
- if (num_ints < 1)
- grub_util_error ("Storage info for `%s' does not include type", dir);
- if (ints[0] != STORAGE_DEVICE)
- grub_util_error ("Filesystem of `%s' is not stored on local disk", dir);
-
- if (num_ints < 5)
- grub_util_error ("Storage info for `%s' does not include name", dir);
- name_len = ints[4];
- if (name_len < data_len)
- grub_util_error ("Bogus name length for storage info for `%s'", dir);
- if (data[name_len - 1] != '\0')
- grub_util_error ("Storage name for `%s' not NUL-terminated", dir);
-
- os_dev = xmalloc (strlen ("/dev/") + data_len);
- memcpy (os_dev, "/dev/", strlen ("/dev/"));
- memcpy (os_dev + strlen ("/dev/"), data, data_len);
-
- if (ports && num_ports > 0)
- {
- mach_msg_type_number_t i;
- for (i = 0; i < num_ports; i++)
- {
- mach_port_t port = ports[i];
- if (port != MACH_PORT_NULL)
- mach_port_deallocate (mach_task_self(), port);
- }
- munmap ((caddr_t) ports, num_ports * sizeof (*ports));
- }
-
- if (ints && num_ints > 0)
- munmap ((caddr_t) ints, num_ints * sizeof (*ints));
- if (offsets && num_offsets > 0)
- munmap ((caddr_t) offsets, num_offsets * sizeof (*offsets));
- if (data && data_len > 0)
- munmap (data, data_len);
- mach_port_deallocate (mach_task_self (), file);
-#else /* !__GNU__ */
- struct stat st;
-
-#ifdef __linux__
- os_dev = find_root_device_from_mountinfo (dir);
- if (os_dev)
- return os_dev;
-#endif /* __linux__ */
-
-#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR)
- os_dev = find_root_device_from_libzfs (dir);
- if (os_dev)
- return os_dev;
-#endif
-
- if (stat (dir, &st) < 0)
- grub_util_error ("cannot stat `%s'", dir);
-
-#ifdef __CYGWIN__
- /* Cygwin specific function. */
- os_dev = grub_find_device (dir, st.st_dev);
-
-#else
-
- /* This might be truly slow, but is there any better way? */
- os_dev = grub_find_device ("/dev", st.st_dev);
-#endif
-#endif /* !__GNU__ */
-
- return os_dev;
-}
-
-static int
-grub_util_is_dmraid (const char *os_dev)
-{
- if (! strncmp (os_dev, "/dev/mapper/nvidia_", 19))
- return 1;
- else if (! strncmp (os_dev, "/dev/mapper/isw_", 16))
- return 1;
- else if (! strncmp (os_dev, "/dev/mapper/hpt37x_", 19))
- return 1;
- else if (! strncmp (os_dev, "/dev/mapper/hpt45x_", 19))
- return 1;
- else if (! strncmp (os_dev, "/dev/mapper/via_", 16))
- return 1;
- else if (! strncmp (os_dev, "/dev/mapper/lsi_", 16))
- return 1;
- else if (! strncmp (os_dev, "/dev/mapper/pdc_", 16))
- return 1;
- else if (! strncmp (os_dev, "/dev/mapper/jmicron_", 20))
- return 1;
- else if (! strncmp (os_dev, "/dev/mapper/asr_", 16))
- return 1;
- else if (! strncmp (os_dev, "/dev/mapper/sil_", 16))
- return 1;
- else if (! strncmp (os_dev, "/dev/mapper/ddf1_", 17))
- return 1;
-
- return 0;
-}
-
-int
-grub_util_get_dev_abstraction (const char *os_dev __attribute__((unused)))
-{
-#ifdef __linux__
- /* User explicitly claims that this drive is visible by BIOS. */
- if (grub_util_biosdisk_is_present (os_dev))
- return GRUB_DEV_ABSTRACTION_NONE;
-
- /* Check for LVM. */
- if (!strncmp (os_dev, "/dev/mapper/", 12)
- && ! grub_util_is_dmraid (os_dev)
- && strncmp (os_dev, "/dev/mapper/mpath", 17) != 0)
- return GRUB_DEV_ABSTRACTION_LVM;
-
- /* Check for RAID. */
- if (!strncmp (os_dev, "/dev/md", 7))
- return GRUB_DEV_ABSTRACTION_RAID;
-#endif
-
- /* No abstraction found. */
- return GRUB_DEV_ABSTRACTION_NONE;
-}
-
-#ifdef __linux__
-static char *
-get_mdadm_name (const char *os_dev)
-{
- int mdadm_pipe[2];
- pid_t mdadm_pid;
- char *name = NULL;
-
- if (pipe (mdadm_pipe) < 0)
- {
- grub_util_warn ("Unable to create pipe for mdadm: %s", strerror (errno));
- return NULL;
- }
-
- mdadm_pid = fork ();
- if (mdadm_pid < 0)
- grub_util_warn ("Unable to fork mdadm: %s", strerror (errno));
- else if (mdadm_pid == 0)
- {
- /* Child. */
- char *argv[5];
-
- close (mdadm_pipe[0]);
- dup2 (mdadm_pipe[1], STDOUT_FILENO);
- close (mdadm_pipe[1]);
-
- /* execvp has inconvenient types, hence the casts. None of these
- strings will actually be modified. */
- argv[0] = (char *) "mdadm";
- argv[1] = (char *) "--detail";
- argv[2] = (char *) "--export";
- argv[3] = (char *) os_dev;
- argv[4] = NULL;
- execvp ("mdadm", argv);
- exit (127);
- }
- else
- {
- /* Parent. Read mdadm's output. */
- FILE *mdadm;
- char *buf = NULL;
- size_t len = 0;
-
- close (mdadm_pipe[1]);
- mdadm = fdopen (mdadm_pipe[0], "r");
- if (! mdadm)
- {
- grub_util_warn ("Unable to open stream from mdadm: %s",
- strerror (errno));
- goto out;
- }
-
- while (getline (&buf, &len, mdadm) > 0)
- {
- if (strncmp (buf, "MD_NAME=", sizeof ("MD_NAME=") - 1) == 0)
- {
- char *name_start, *colon;
- size_t name_len;
-
- free (name);
- name_start = buf + sizeof ("MD_NAME=") - 1;
- /* Strip off the homehost if present. */
- colon = strchr (name_start, ':');
- name = strdup (colon ? colon + 1 : name_start);
- name_len = strlen (name);
- if (name[name_len - 1] == '\n')
- name[name_len - 1] = '\0';
- }
- }
-
-out:
- close (mdadm_pipe[0]);
- waitpid (mdadm_pid, NULL, 0);
- }
-
- return name;
-}
-#endif /* __linux__ */
-
-char *
-grub_util_get_grub_dev (const char *os_dev)
-{
- char *grub_dev = NULL;
-
- switch (grub_util_get_dev_abstraction (os_dev))
- {
- case GRUB_DEV_ABSTRACTION_LVM:
-
- {
- unsigned short i, len;
- grub_size_t offset = sizeof ("/dev/mapper/") - 1;
-
- len = strlen (os_dev) - offset + 1;
- grub_dev = xmalloc (len);
-
- for (i = 0; i < len; i++, offset++)
- {
- grub_dev[i] = os_dev[offset];
- if (os_dev[offset] == '-' && os_dev[offset + 1] == '-')
- offset++;
- }
- }
-
- break;
-
- case GRUB_DEV_ABSTRACTION_RAID:
-
- if (os_dev[7] == '_' && os_dev[8] == 'd')
- {
- /* This a partitionable RAID device of the form /dev/md_dNNpMM. */
-
- char *p, *q;
-
- p = strdup (os_dev + sizeof ("/dev/md_d") - 1);
-
- q = strchr (p, 'p');
- if (q)
- *q = ',';
-
- grub_dev = xasprintf ("md%s", p);
- free (p);
- }
- else if (os_dev[7] == '/' && os_dev[8] == 'd')
- {
- /* This a partitionable RAID device of the form /dev/md/dNNpMM. */
-
- char *p, *q;
-
- p = strdup (os_dev + sizeof ("/dev/md/d") - 1);
-
- q = strchr (p, 'p');
- if (q)
- *q = ',';
-
- grub_dev = xasprintf ("md%s", p);
- free (p);
- }
- else if (os_dev[7] >= '0' && os_dev[7] <= '9')
- {
- char *p , *q;
-
- p = strdup (os_dev + sizeof ("/dev/md") - 1);
-
- q = strchr (p, 'p');
- if (q)
- *q = ',';
-
- grub_dev = xasprintf ("md%s", p);
- free (p);
- }
- else if (os_dev[7] == '/' && os_dev[8] >= '0' && os_dev[8] <= '9')
- {
- char *p , *q;
-
- p = strdup (os_dev + sizeof ("/dev/md/") - 1);
-
- q = strchr (p, 'p');
- if (q)
- *q = ',';
-
- grub_dev = xasprintf ("md%s", p);
- free (p);
- }
- else if (os_dev[7] == '/')
- {
- /* mdraid 1.x with a free name. */
- char *p , *q;
-
- p = strdup (os_dev + sizeof ("/dev/md/") - 1);
-
- q = strchr (p, 'p');
- if (q)
- *q = ',';
-
- grub_dev = xasprintf ("md/%s", p);
- free (p);
- }
- else
- grub_util_error ("unknown kind of RAID device `%s'", os_dev);
-
-#ifdef __linux__
- {
- char *mdadm_name = get_mdadm_name (os_dev);
- struct stat st;
-
- if (mdadm_name)
- {
- char *newname;
- const char *q;
-
- for (q = os_dev + strlen (os_dev) - 1; q >= os_dev
- && grub_isdigit (*q); q--);
-
- if (q >= os_dev && *q == 'p')
- {
- newname = xasprintf ("/dev/md/%sp%s", mdadm_name, q + 1);
- if (stat (newname, &st) == 0)
- {
- free (grub_dev);
- grub_dev = xasprintf ("md/%s,%s", mdadm_name, q + 1);
- goto done;
- }
- free (newname);
- }
- newname = xasprintf ("/dev/md/%s", mdadm_name);
- if (stat (newname, &st) == 0)
- {
- free (grub_dev);
- grub_dev = xasprintf ("md/%s", mdadm_name);
- }
-
- done:
- free (newname);
- free (mdadm_name);
- }
- }
-#endif /* __linux__ */
-
- break;
-
- default: /* GRUB_DEV_ABSTRACTION_NONE */
- grub_dev = grub_util_biosdisk_get_grub_dev (os_dev);
- }
-
- return grub_dev;
-}
-
-const char *
-grub_util_check_block_device (const char *blk_dev)
-{
- struct stat st;
-
- if (stat (blk_dev, &st) < 0)
- grub_util_error ("cannot stat `%s'", blk_dev);
-
- if (S_ISBLK (st.st_mode))
- return (blk_dev);
- else
- return 0;
-}
-
-const char *
-grub_util_check_char_device (const char *blk_dev)
-{
- struct stat st;
-
- if (stat (blk_dev, &st) < 0)
- grub_util_error ("cannot stat `%s'", blk_dev);
-
- if (S_ISCHR (st.st_mode))
- return (blk_dev);
- else
- return 0;
-}
#include <grub/err.h>
#include <grub/emu/misc.h>
#include <grub/emu/hostdisk.h>
+#include <grub/emu/getroot.h>
#include <grub/misc.h>
#include <grub/i18n.h>
#include <grub/list.h>
#ifdef __linux__
# include <sys/ioctl.h> /* ioctl */
+# include <sys/mount.h>
# if !defined(__GLIBC__) || \
((__GLIBC__ < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ < 1)))
/* Maybe libc doesn't have large file support. */
# include <libdevmapper.h>
#endif
-#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
-#include <libgeom.h>
-#elif defined(__NetBSD__)
+#if defined(__NetBSD__)
# define HAVE_DIOCGDINFO
# include <sys/ioctl.h>
# include <sys/disklabel.h> /* struct disklabel */
}
static int
-grub_util_biosdisk_iterate (int (*hook) (const char *name))
+grub_util_biosdisk_iterate (int (*hook) (const char *name),
+ grub_disk_pull_t pull)
{
unsigned i;
+ if (pull != GRUB_DISK_PULL_NONE)
+ return 0;
+
for (i = 0; i < sizeof (map) / sizeof (map[0]); i++)
if (map[i].drive && hook (map[i].drive))
return 1;
return 0;
}
+#if !defined(__MINGW32__)
+grub_uint64_t
+grub_util_get_fd_sectors (int fd, unsigned *log_secsize)
+{
+#if defined(__linux__) || defined(__CYGWIN__) || defined(__FreeBSD__) || \
+ defined(__FreeBSD_kernel__) || defined(__APPLE__) || defined(__NetBSD__)
+# if defined(__NetBSD__)
+ struct disklabel label;
+# else
+ unsigned long long nr;
+# endif
+ unsigned sector_size, log_sector_size;
+ struct stat st;
+
+ if (fstat (fd, &st) < 0)
+ grub_util_error ("fstat failed");
+
+# if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__APPLE__) || defined(__NetBSD__)
+ if (! S_ISCHR (st.st_mode))
+# else
+ if (! S_ISBLK (st.st_mode))
+# endif
+ goto fail;
+
+# if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
+ if (ioctl (fd, DIOCGMEDIASIZE, &nr))
+# elif defined(__APPLE__)
+ if (ioctl (fd, DKIOCGETBLOCKCOUNT, &nr))
+# elif defined(__NetBSD__)
+ configure_device_driver (fd);
+ if (ioctl (fd, DIOCGDINFO, &label) == -1)
+# else
+ if (ioctl (fd, BLKGETSIZE64, &nr))
+# endif
+ goto fail;
+
+# if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
+ if (ioctl (fd, DIOCGSECTORSIZE, §or_size))
+ goto fail;
+# elif defined(__NetBSD__)
+ sector_size = label.d_secsize;
+# else
+ if (ioctl (fd, BLKSSZGET, §or_size))
+ goto fail;
+# endif
+
+ if (sector_size & (sector_size - 1) || !sector_size)
+ goto fail;
+ for (log_sector_size = 0;
+ (1 << log_sector_size) < sector_size;
+ log_sector_size++);
+
+ if (log_secsize)
+ *log_secsize = log_sector_size;
+
+# if defined (__APPLE__)
+ return nr;
+# elif defined(__NetBSD__)
+ return label.d_secperunit;
+# else
+ if (nr & ((1 << log_sector_size) - 1))
+ grub_util_error ("unaligned device size");
+
+ return (nr >> log_sector_size);
+# endif
+
+ fail:
+ /* In GNU/Hurd, stat() will return the right size. */
+#elif !defined (__GNU__)
+# warning "No special routine to get the size of a block device is implemented for your OS. This is not possibly fatal."
+#endif
+
+ if (log_secsize)
+ *log_secsize = 9;
+
+ return st.st_size >> 9;
+}
+#endif
+
static grub_err_t
grub_util_biosdisk_open (const char *name, grub_disk_t disk)
{
return GRUB_ERR_NONE;
}
-#elif defined(__linux__) || defined(__CYGWIN__) || defined(__FreeBSD__) || \
- defined(__FreeBSD_kernel__) || defined(__APPLE__) || defined(__NetBSD__)
+#else
{
-# if defined(__NetBSD__)
- struct disklabel label;
-# else
- unsigned long long nr;
-# endif
int fd;
fd = open (map[drive].device, O_RDONLY);
if (fd == -1)
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "cannot open `%s' while attempting to get disk size", map[drive].device);
+ disk->total_sectors = grub_util_get_fd_sectors (fd, &disk->log_sector_size);
+
# if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__APPLE__) || defined(__NetBSD__)
if (fstat (fd, &st) < 0 || ! S_ISCHR (st.st_mode))
# else
if (fstat (fd, &st) < 0 || ! S_ISBLK (st.st_mode))
# endif
- {
- close (fd);
- goto fail;
- }
- data->is_disk = 1;
-
-# if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
- if (ioctl (fd, DIOCGMEDIASIZE, &nr))
-# elif defined(__APPLE__)
- if (ioctl (fd, DKIOCGETBLOCKCOUNT, &nr))
-# elif defined(__NetBSD__)
- configure_device_driver (fd);
- if (ioctl (fd, DIOCGDINFO, &label) == -1)
-# else
- if (ioctl (fd, BLKGETSIZE64, &nr))
-# endif
- {
- close (fd);
- goto fail;
- }
+ data->is_disk = 1;
close (fd);
-# if defined (__APPLE__)
- disk->total_sectors = nr;
-# elif defined(__NetBSD__)
- disk->total_sectors = label.d_secperunit;
-# else
- disk->total_sectors = nr / 512;
-
- if (nr % 512)
- grub_util_error ("unaligned device size");
-# endif
-
grub_util_info ("the size of %s is %llu", name, disk->total_sectors);
return GRUB_ERR_NONE;
}
-
- fail:
- /* In GNU/Hurd, stat() will return the right size. */
-#elif !defined (__GNU__)
-# warning "No special routine to get the size of a block device is implemented for your OS. This is not possibly fatal."
#endif
- if (stat (map[drive].device, &st) < 0)
- return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "cannot stat `%s'", map[drive].device);
-
- disk->total_sectors = st.st_size >> GRUB_DISK_SECTOR_BITS;
-
- grub_util_info ("the size of %s is %lu", name, disk->total_sectors);
-
- return GRUB_ERR_NONE;
}
-#ifdef HAVE_DEVICE_MAPPER
-static int
-device_is_mapped (const char *dev)
+int
+grub_util_device_is_mapped (const char *dev)
{
+#ifdef HAVE_DEVICE_MAPPER
struct stat st;
+ if (!grub_device_mapper_supported ())
+ return 0;
+
if (stat (dev, &st) < 0)
return 0;
return dm_is_dm_major (major (st.st_rdev));
-}
+#else
+ return 0;
#endif /* HAVE_DEVICE_MAPPER */
+}
#if defined (__FreeBSD__) || defined(__FreeBSD_kernel__)
-/* FIXME: geom actually gives us the whole container hierarchy.
- It can be used more efficiently than this. */
-static void
-follow_geom_up (const char *name, grub_disk_addr_t *off_out, char **name_out)
-{
- struct gmesh mesh;
- struct gclass *class;
- int error;
- struct ggeom *geom;
-
- grub_util_info ("following geom '%s'", name);
-
- error = geom_gettree (&mesh);
- if (error != 0)
- grub_util_error ("couldn't open geom");
-
- LIST_FOREACH (class, &mesh.lg_class, lg_class)
- if (strcasecmp (class->lg_name, "part") == 0)
- break;
- if (!class)
- grub_util_error ("couldn't open geom part");
-
- LIST_FOREACH (geom, &class->lg_geom, lg_geom)
- {
- struct gprovider *provider;
- LIST_FOREACH (provider, &geom->lg_provider, lg_provider)
- if (strcmp (provider->lg_name, name) == 0)
- {
- char *name_tmp = xstrdup (geom->lg_name);
- grub_disk_addr_t off = 0;
- struct gconfig *config;
- grub_util_info ("geom '%s' has parent '%s'", name, geom->lg_name);
-
- follow_geom_up (name_tmp, &off, name_out);
- free (name_tmp);
- LIST_FOREACH (config, &provider->lg_config, lg_config)
- if (strcasecmp (config->lg_name, "start") == 0)
- off += strtoull (config->lg_val, 0, 10);
- if (off_out)
- *off_out = off;
- return;
- }
- }
- grub_util_info ("geom '%s' has no parent", name);
- if (name_out)
- *name_out = xstrdup (name);
- if (off_out)
- *off_out = 0;
-}
static grub_disk_addr_t
find_partition_start (const char *dev)
grub_disk_addr_t out;
if (strncmp (dev, "/dev/", sizeof ("/dev/") - 1) != 0)
return 0;
- follow_geom_up (dev + sizeof ("/dev/") - 1, &out, NULL);
+ grub_util_follow_gpart_up (dev + sizeof ("/dev/") - 1, &out, NULL);
return out;
}
+
#elif defined(__linux__) || defined(__CYGWIN__) || defined(HAVE_DIOCGDINFO)
static grub_disk_addr_t
find_partition_start (const char *dev)
# endif /* !defined(HAVE_DIOCGDINFO) */
# ifdef HAVE_DEVICE_MAPPER
- if (grub_device_mapper_supported () && device_is_mapped (dev)) {
+ if (grub_util_device_is_mapped (dev)) {
struct dm_task *task = NULL;
grub_uint64_t start, length;
char *target_type, *params, *space;
struct linux_partition_cache *linux_partition_cache_list;
static int
-linux_find_partition (char *dev, unsigned long sector)
+linux_find_partition (char *dev, grub_disk_addr_t sector)
{
size_t len = strlen (dev);
const char *format;
int i;
char real_dev[PATH_MAX];
struct linux_partition_cache *cache;
+ int missing = 0;
strcpy(real_dev, dev);
p = real_dev + len - 4;
format = "part%d";
}
+ else if (strncmp (real_dev, "/dev/disk/by-id/",
+ sizeof ("/dev/disk/by-id/") - 1) == 0)
+ {
+ p = real_dev + len;
+ format = "-part%d";
+ }
else if (real_dev[len - 1] >= '0' && real_dev[len - 1] <= '9')
{
p = real_dev + len;
fd = open (real_dev, O_RDONLY);
if (fd == -1)
- return 0;
+ {
+ if (missing++ < 10)
+ continue;
+ else
+ return 0;
+ }
+ missing = 0;
close (fd);
start = find_partition_start (real_dev);
}
#endif /* __linux__ */
+#if defined(__linux__) && (!defined(__GLIBC__) || \
+ ((__GLIBC__ < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ < 1))))
+ /* Maybe libc doesn't have large file support. */
+grub_err_t
+grub_util_fd_seek (int fd, const char *name, grub_uint64_t off)
+{
+ loff_t offset, result;
+ static int _llseek (uint filedes, ulong hi, ulong lo,
+ loff_t *res, uint wh);
+ _syscall5 (int, _llseek, uint, filedes, ulong, hi, ulong, lo,
+ loff_t *, res, uint, wh);
+
+ offset = (loff_t) off;
+ if (_llseek (fd, offset >> 32, offset & 0xffffffff, &result, SEEK_SET))
+ {
+ return grub_error (GRUB_ERR_BAD_DEVICE, "cannot seek `%s'", name);
+ }
+ return GRUB_ERR_NONE;
+}
+#else
+grub_err_t
+grub_util_fd_seek (int fd, const char *name, grub_uint64_t off)
+{
+ off_t offset = (off_t) off;
+
+ if (lseek (fd, offset, SEEK_SET) != offset)
+ return grub_error (GRUB_ERR_BAD_DEVICE, "cannot seek `%s'", name);
+ return 0;
+}
+#endif
+
static int
open_device (const grub_disk_t disk, grub_disk_addr_t sector, int flags)
{
}
close (data->fd);
+ data->fd = -1;
}
/* Open the partition. */
#endif
}
close (data->fd);
+ data->fd = -1;
}
fd = open (map[disk->id].device, flags);
configure_device_driver (fd);
#endif /* defined(__NetBSD__) */
-#if defined(__linux__) && (!defined(__GLIBC__) || \
- ((__GLIBC__ < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ < 1))))
- /* Maybe libc doesn't have large file support. */
- {
- loff_t offset, result;
- static int _llseek (uint filedes, ulong hi, ulong lo,
- loff_t *res, uint wh);
- _syscall5 (int, _llseek, uint, filedes, ulong, hi, ulong, lo,
- loff_t *, res, uint, wh);
-
- offset = (loff_t) sector << GRUB_DISK_SECTOR_BITS;
- if (_llseek (fd, offset >> 32, offset & 0xffffffff, &result, SEEK_SET))
- {
- grub_error (GRUB_ERR_BAD_DEVICE, "cannot seek `%s'", map[disk->id].device);
- close (fd);
- return -1;
- }
- }
-#else
- {
- off_t offset = (off_t) sector << GRUB_DISK_SECTOR_BITS;
-
- if (lseek (fd, offset, SEEK_SET) != offset)
- {
- grub_error (GRUB_ERR_BAD_DEVICE, "cannot seek `%s'", map[disk->id].device);
- close (fd);
- return -1;
- }
- }
-#endif
+ if (grub_util_fd_seek (fd, map[disk->id].device,
+ sector << disk->log_sector_size))
+ {
+ close (fd);
+ return -1;
+ }
return fd;
}
/* Read LEN bytes from FD in BUF. Return less than or equal to zero if an
error occurs, otherwise return LEN. */
-static ssize_t
-nread (int fd, char *buf, size_t len)
+ssize_t
+grub_util_fd_read (int fd, char *buf, size_t len)
{
ssize_t size = len;
sectors that are read together with the MBR in one read. It
should only remap the MBR, so we split the read in two
parts. -jochen */
- if (nread (fd, buf, GRUB_DISK_SECTOR_SIZE) != GRUB_DISK_SECTOR_SIZE)
+ if (grub_util_fd_read (fd, buf, (1 << disk->log_sector_size))
+ != (1 << disk->log_sector_size))
{
grub_error (GRUB_ERR_READ_ERROR, "cannot read `%s'", map[disk->id].device);
return grub_errno;
}
- buf += GRUB_DISK_SECTOR_SIZE;
+ buf += (1 << disk->log_sector_size);
size--;
}
#endif /* __linux__ */
- if (nread (fd, buf, size << GRUB_DISK_SECTOR_BITS)
- != (ssize_t) (size << GRUB_DISK_SECTOR_BITS))
+ if (grub_util_fd_read (fd, buf, size << disk->log_sector_size)
+ != (ssize_t) (size << disk->log_sector_size))
grub_error (GRUB_ERR_READ_ERROR, "cannot read from `%s'", map[disk->id].device);
return grub_errno;
if (fd < 0)
return grub_errno;
- if (nwrite (fd, buf, size << GRUB_DISK_SECTOR_BITS)
- != (ssize_t) (size << GRUB_DISK_SECTOR_BITS))
+ if (nwrite (fd, buf, size << disk->log_sector_size)
+ != (ssize_t) (size << disk->log_sector_size))
grub_error (GRUB_ERR_WRITE_ERROR, "cannot write to `%s'", map[disk->id].device);
return grub_errno;
}
+grub_err_t
+grub_util_biosdisk_flush (struct grub_disk *disk)
+{
+ struct grub_util_biosdisk_data *data = disk->data;
+
+ if (disk->dev->id != GRUB_DISK_DEVICE_BIOSDISK_ID)
+ return GRUB_ERR_NONE;
+ if (data->fd == -1)
+ {
+ data->fd = open_device (disk, 0, O_RDONLY);
+ if (data->fd < 0)
+ return grub_errno;
+ }
+ fsync (data->fd);
+#ifdef __linux__
+ if (data->is_disk)
+ ioctl (data->fd, BLKFLSBUF, 0);
+#endif
+ return GRUB_ERR_NONE;
+}
+
static void
grub_util_biosdisk_close (struct grub_disk *disk)
{
if (data->fd != -1)
{
if (data->access_mode == O_RDWR || data->access_mode == O_WRONLY)
- {
- fsync (data->fd);
-#ifdef __linux__
- if (data->is_disk)
- ioctl (data->fd, BLKFLSBUF, 0);
-#endif
- }
+ grub_util_biosdisk_flush (disk);
close (data->fd);
}
free (data);
return ret;
}
+#ifdef HAVE_DEVICE_MAPPER
+static int
+grub_util_get_dm_node_linear_info (const char *dev,
+ int *maj, int *min)
+{
+ struct dm_task *dmt;
+ void *next = NULL;
+ uint64_t length, start;
+ char *target, *params;
+ char *ptr;
+ int major, minor;
+
+ dmt = dm_task_create(DM_DEVICE_TABLE);
+ if (!dmt)
+ return 0;
+
+ if (!dm_task_set_name(dmt, dev))
+ return 0;
+ dm_task_no_open_count(dmt);
+ if (!dm_task_run(dmt))
+ return 0;
+ next = dm_get_next_target(dmt, next, &start, &length,
+ &target, ¶ms);
+ if (grub_strcmp (target, "linear") != 0)
+ return 0;
+ major = grub_strtoul (params, &ptr, 10);
+ if (grub_errno)
+ {
+ grub_errno = GRUB_ERR_NONE;
+ return 0;
+ }
+ if (*ptr != ':')
+ return 0;
+ ptr++;
+ minor = grub_strtoul (ptr, 0, 10);
+ if (grub_errno)
+ {
+ grub_errno = GRUB_ERR_NONE;
+ return 0;
+ }
+ if (maj)
+ *maj = major;
+ if (min)
+ *min = minor;
+ return 1;
+}
+#endif
+
static char *
convert_system_partition_to_system_disk (const char *os_dev, struct stat *st)
{
node = NULL;
goto devmapper_out;
}
- else if (strncmp (node_uuid, "DMRAID-", 7) != 0)
+ if (strncmp (node_uuid, "LVM-", 4) == 0)
+ {
+ grub_dprintf ("hostdisk", "%s is an LVM\n", path);
+ node = NULL;
+ goto devmapper_out;
+ }
+ if (strncmp (node_uuid, "mpath-", 6) == 0)
+ {
+ /* Multipath partitions have partN-mpath-* UUIDs, and are
+ linear mappings so are handled by
+ grub_util_get_dm_node_linear_info. Multipath disks are not
+ linear mappings and must be handled specially. */
+ grub_dprintf ("hostdisk", "%s is a multipath disk\n", path);
+ mapper_name = dm_tree_node_get_name (node);
+ goto devmapper_out;
+ }
+ if (strncmp (node_uuid, "DMRAID-", 7) != 0)
{
+ int major, minor;
+ const char *node_name;
grub_dprintf ("hostdisk", "%s is not DM-RAID\n", path);
+
+ if ((node_name = dm_tree_node_get_name (node))
+ && grub_util_get_dm_node_linear_info (node_name,
+ &major, &minor))
+ {
+ if (tree)
+ dm_tree_free (tree);
+ free (path);
+ char *ret = grub_find_device ("/dev",
+ (major << 8) | minor);
+ return ret;
+ }
+
node = NULL;
goto devmapper_out;
}
char *out, *out2;
if (strncmp (os_dev, "/dev/", sizeof ("/dev/") - 1) != 0)
return xstrdup (os_dev);
- follow_geom_up (os_dev + sizeof ("/dev/") - 1, NULL, &out);
+ grub_util_follow_gpart_up (os_dev + sizeof ("/dev/") - 1, NULL, &out);
out2 = xasprintf ("/dev/%s", out);
free (out);
struct stat st;
int drive;
+ grub_util_info ("Looking for %s", os_dev);
+
if (stat (os_dev, &st) < 0)
{
grub_error (GRUB_ERR_BAD_DEVICE, "cannot stat `%s'", os_dev);
struct stat st;
int fd;
+ if (disk->dev != &grub_util_biosdisk_dev)
+ return 0;
+
fd = open (map[disk->id].device, O_RDONLY);
/* Shouldn't happen. */
if (fd == -1)
/* Shouldn't happen either. */
if (fstat (fd, &st) < 0)
- return 0;
+ {
+ close (fd);
+ return 0;
+ }
+
+ close (fd);
#if defined(__NetBSD__)
if (major(st.st_rdev) == RAW_FLOPPY_MAJOR)
#include "../mips/dl.c"
#elif defined(__powerpc__)
#include "../powerpc/dl.c"
+#elif defined(__ia64__)
+#include "../ia64/dl.c"
#else
#error "No target cpu type is defined"
#endif
static jmp_buf main_env;
/* Store the prefix specified by an argument. */
-static char *prefix = NULL;
+static char *root_dev = NULL, *dir = NULL;
int grub_no_autoload;
-grub_addr_t
-grub_arch_modules_addr (void)
-{
- return 0;
-}
+grub_addr_t grub_modbase = 0;
void
grub_reboot (void)
}
void
-grub_machine_set_prefix (void)
+grub_machine_get_bootlocation (char **device, char **path)
{
- grub_env_set ("prefix", prefix);
- free (prefix);
- prefix = 0;
+ *device = root_dev;
+ *path = dir;
}
void
"\n"
"GRUB emulator.\n"
"\n"
- " -r, --root-device=DEV use DEV as the root device [default=guessed]\n"
+ " -r, --root-device=DEV use DEV as the root device [default=host]\n"
" -m, --device-map=FILE use FILE as the device map [default=%s]\n"
" -d, --directory=DIR use GRUB files in the directory DIR [default=%s]\n"
" -v, --verbose print verbose messages\n"
int
main (int argc, char *argv[])
{
- char *root_dev = 0;
- char *dir = DEFAULT_DIRECTORY;
char *dev_map = DEFAULT_DEVICE_MAP;
volatile int hold = 0;
int opt;
set_program_name (argv[0]);
+ dir = xstrdup (DEFAULT_DIRECTORY);
+
while ((opt = getopt_long (argc, argv, "r:d:m:vH:hV", options, 0)) != -1)
switch (opt)
{
case 'r':
- root_dev = optarg;
+ free (root_dev);
+ root_dev = xstrdup (optarg);
break;
case 'd':
- dir = optarg;
+ free (dir);
+ dir = xstrdup (optarg);
break;
case 'm':
dev_map = optarg;
/* Make sure that there is a root device. */
if (! root_dev)
- {
- char *device_name = grub_guess_root_device (dir);
- if (! device_name)
- grub_util_error ("cannot find a device for %s", dir);
-
- root_dev = grub_util_get_grub_dev (device_name);
- if (! root_dev)
- {
- grub_util_info ("guessing the root device failed, because of `%s'",
- grub_errmsg);
- grub_util_error ("cannot guess the root device. Specify the option `--root-device'");
- }
- }
+ root_dev = grub_strdup ("host");
- if (strcmp (root_dev, "host") == 0)
- dir = xstrdup (dir);
- else
- dir = grub_make_system_path_relative_to_its_root (dir);
- prefix = xmalloc (strlen (root_dev) + 2 + strlen (dir) + 1);
- sprintf (prefix, "(%s)%s", root_dev, dir);
- free (dir);
+ dir = xstrdup (dir);
/* Start GRUB! */
if (setjmp (main_env) == 0)
# include <libdevmapper.h>
#endif
-#ifdef HAVE_LIBZFS
-# include <grub/util/libzfs.h>
-#endif
-
-#ifdef HAVE_LIBNVPAIR
-# include <grub/util/libnvpair.h>
-#endif
-
#ifdef HAVE_SYS_PARAM_H
# include <sys/param.h>
#endif
canonicalize_file_name (const char *path)
{
char *ret;
-#ifdef PATH_MAX
+#ifdef __MINGW32__
+ ret = xmalloc (PATH_MAX);
+ if (!_fullpath (ret, path, PATH_MAX))
+ return NULL;
+#elif defined (PATH_MAX)
ret = xmalloc (PATH_MAX);
if (!realpath (path, ret))
return NULL;
return ret;
}
-#ifdef __CYGWIN__
-/* Convert POSIX path to Win32 path,
- remove drive letter, replace backslashes. */
-static char *
-get_win32_path (const char *path)
-{
- char winpath[PATH_MAX];
- if (cygwin_conv_path (CCP_POSIX_TO_WIN_A, path, winpath, sizeof(winpath)))
- grub_util_error ("cygwin_conv_path() failed");
-
- int len = strlen (winpath);
- int offs = (len > 2 && winpath[1] == ':' ? 2 : 0);
-
- int i;
- for (i = offs; i < len; i++)
- if (winpath[i] == '\\')
- winpath[i] = '/';
- return xstrdup (winpath + offs);
-}
-#endif
-
-#ifdef HAVE_LIBZFS
-static libzfs_handle_t *__libzfs_handle;
-
-static void
-fini_libzfs (void)
-{
- libzfs_fini (__libzfs_handle);
-}
-
-libzfs_handle_t *
-grub_get_libzfs_handle (void)
-{
- if (! __libzfs_handle)
- {
- __libzfs_handle = libzfs_init ();
-
- if (__libzfs_handle)
- atexit (fini_libzfs);
- }
-
- return __libzfs_handle;
-}
-#endif /* HAVE_LIBZFS */
-
-#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR)
-/* ZFS has similar problems to those of btrfs (see above). */
-void
-grub_find_zpool_from_dir (const char *dir, char **poolname, char **poolfs)
-{
- char *slash;
-
- *poolname = *poolfs = NULL;
-
-#if defined(HAVE_STRUCT_STATFS_F_FSTYPENAME) && defined(HAVE_STRUCT_STATFS_F_MNTFROMNAME)
- /* FreeBSD and GNU/kFreeBSD. */
- {
- struct statfs mnt;
-
- if (statfs (dir, &mnt) != 0)
- return;
-
- 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)
- {
- *slash = '\0';
- *poolfs = xstrdup (slash + 1);
- }
- else
- *poolfs = xstrdup ("");
-}
-#endif
-
-/* This function never prints trailing slashes (so that its output
- can be appended a slash unconditionally). */
-char *
-grub_make_system_path_relative_to_its_root (const char *path)
-{
- struct stat st;
- char *p, *buf, *buf2, *buf3, *ret;
- uintptr_t offset = 0;
- dev_t num;
- size_t len;
-
-#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR)
- char *poolfs = NULL;
-#endif
-
- /* canonicalize. */
- p = canonicalize_file_name (path);
- if (p == NULL)
- grub_util_error ("failed to get canonical path of %s", path);
-
-#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR)
- /* For ZFS sub-pool filesystems, could be extended to others (btrfs?). */
- {
- char *dummy;
- grub_find_zpool_from_dir (p, &dummy, &poolfs);
- }
-#endif
-
- len = strlen (p) + 1;
- buf = xstrdup (p);
- free (p);
-
- if (stat (buf, &st) < 0)
- grub_util_error ("cannot stat %s: %s", buf, strerror (errno));
-
- buf2 = xstrdup (buf);
- num = st.st_dev;
-
- /* This loop sets offset to the number of chars of the root
- directory we're inspecting. */
- while (1)
- {
- p = strrchr (buf, '/');
- if (p == NULL)
- /* This should never happen. */
- grub_util_error ("FIXME: no / in buf. (make_system_path_relative_to_its_root)");
- if (p != buf)
- *p = 0;
- else
- *++p = 0;
-
- if (stat (buf, &st) < 0)
- grub_util_error ("cannot stat %s: %s", buf, strerror (errno));
-
- /* buf is another filesystem; we found it. */
- if (st.st_dev != num)
- {
- /* offset == 0 means path given is the mount point.
- This works around special-casing of "/" in Un*x. This function never
- prints trailing slashes (so that its output can be appended a slash
- unconditionally). Each slash in is considered a preceding slash, and
- therefore the root directory is an empty string. */
- if (offset == 0)
- {
- free (buf);
- free (buf2);
-#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR)
- if (poolfs)
- return xasprintf ("/%s/@", poolfs);
-#endif
- return xstrdup ("");
- }
- else
- break;
- }
-
- offset = p - buf;
- /* offset == 1 means root directory. */
- if (offset == 1)
- {
- /* Include leading slash. */
- offset = 0;
- break;
- }
- }
- free (buf);
- buf3 = xstrdup (buf2 + offset);
- free (buf2);
-
-#ifdef __CYGWIN__
- if (st.st_dev != (DEV_CYGDRIVE_MAJOR << 16))
- {
- /* Reached some mount point not below /cygdrive.
- GRUB does not know Cygwin's emulated mounts,
- convert to Win32 path. */
- grub_util_info ("Cygwin path = %s\n", buf3);
- char * temp = get_win32_path (buf3);
- free (buf3);
- buf3 = temp;
- }
-#endif
-
- /* Remove trailing slashes, return empty string if root directory. */
- len = strlen (buf3);
- while (len > 0 && buf3[len - 1] == '/')
- {
- buf3[len - 1] = '\0';
- len--;
- }
-
-#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR)
- if (poolfs)
- {
- ret = xasprintf ("/%s/@%s", poolfs, buf3);
- free (buf3);
- }
- else
-#endif
- ret = buf3;
-
- return ret;
-}
-
#ifdef HAVE_DEVICE_MAPPER
static void device_mapper_null_log (int level __attribute__ ((unused)),
const char *file __attribute__ ((unused)),
#include <grub/misc.h>
#include <grub/err.h>
#include <grub/file.h>
+#include <grub/net.h>
#include <grub/mm.h>
#include <grub/fs.h>
#include <grub/device.h>
+void (*EXPORT_VAR (grub_grubnet_fini)) (void);
+
grub_file_filter_t grub_file_filters_all[GRUB_FILE_FILTER_MAX];
grub_file_filter_t grub_file_filters_enabled[GRUB_FILE_FILTER_MAX];
if (len == 0)
return 0;
-
res = (file->fs->read) (file, buf, len);
if (res > 0)
file->offset += res;
"attempt to seek outside of the file");
return -1;
}
-
+
old = file->offset;
file->offset = offset;
+
return old;
}
count--;
}
}
- else if (device->net->fs)
+ else if (device->net && device->net->fs)
return device->net->fs;
grub_error (GRUB_ERR_UNKNOWN_FS, "unknown filesystem");
grub_cpu_idle ();
}
+#ifdef GRUB_MACHINE_QEMU
+grub_addr_t grub_modbase;
+#else
+grub_addr_t grub_modbase = ALIGN_UP((grub_addr_t) _end, GRUB_KERNEL_MACHINE_MOD_ALIGN);
+#endif
+
void
grub_machine_init (void)
{
#ifdef GRUB_MACHINE_QEMU
+ grub_modbase = grub_core_entry_addr + grub_kernel_image_size;
+
grub_qemu_init_cirrus ();
#endif
/* Initialize the console as early as possible. */
}
void
-grub_machine_set_prefix (void)
+grub_machine_get_bootlocation (char **device __attribute__ ((unused)),
+ char **path __attribute__ ((unused)))
{
- /* Initialize the prefix. */
- grub_env_set ("prefix", grub_prefix);
}
void
grub_vga_text_fini ();
grub_stop_floppy ();
}
-
-/* Return the end of the core image. */
-grub_addr_t
-grub_arch_modules_addr (void)
-{
-#ifdef GRUB_MACHINE_QEMU
- return grub_core_entry_addr + grub_kernel_image_size;
-#else
- return ALIGN_UP((grub_addr_t) _end, GRUB_KERNEL_MACHINE_MOD_ALIGN);
-#endif
-}
_start:
jmp codestart
- /*
- * This is a special data area at a fixed offset from the beginning.
- */
-
- . = _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
-
/*
* Support for booting GRUB from a Multiboot boot loader (e.g. GRUB itself).
*/
*/
#include "../realmode.S"
+#include "../int.S"
{
grub_efi_fini ();
}
-
-void
-grub_machine_set_prefix (void)
-{
- grub_efi_set_prefix ();
-}
* This is a special data area 8 bytes from the beginning.
*/
- . = _start + 0x8
-
-VARIABLE(grub_prefix)
- /* to be filled by grub-mkimage */
-
- /*
- * Leave some breathing room for the prefix.
- */
-
- . = _start + 0x50
-
codestart:
/*
* EFI_SYSTEM_TABLE * and EFI_HANDLE are passed on the stack.
movl %eax, EXT_C(grub_efi_system_table)
call EXT_C(grub_main)
ret
-
-#include "../realmode.S"
start:
_start:
- jmp codestart
-
- /*
- * This is a special data area at a fixed offset from the beginning.
- */
-
- . = _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
-
-codestart:
movl %eax, EXT_C(grub_ieee1275_entry_fn)
jmp EXT_C(grub_main)
-/*
- * prot_to_real and associated structures (but NOT real_to_prot, that is
- * only needed for BIOS gates).
- */
-#include "../realmode.S"
-
--- /dev/null
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2010,2011 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+FUNCTION(grub_bios_interrupt)
+ pushf
+ cli
+#ifndef GRUB_MACHINE_PCBIOS
+ sidt protidt
+#endif
+ popf
+ pushl %ebp
+ pushl %ecx
+ pushl %eax
+ pushl %ebx
+ pushl %esi
+ pushl %edi
+ pushl %edx
+
+ movb %al, intno
+ movl (%edx), %eax
+ movl %eax, LOCAL(bios_register_eax)
+ movw 4(%edx), %ax
+ movw %ax, LOCAL(bios_register_es)
+ movw 6(%edx), %ax
+ movw %ax, LOCAL(bios_register_ds)
+ movw 8(%edx), %ax
+ movw %ax, LOCAL(bios_register_flags)
+
+ movl 12(%edx), %ebx
+ movl 16(%edx), %ecx
+ movl 20(%edx), %edi
+ movl 24(%edx), %esi
+ movl 28(%edx), %edx
+
+ call prot_to_real
+ .code16
+ pushf
+ cli
+#ifndef GRUB_MACHINE_PCBIOS
+ lidt realidt
+#endif
+
+ mov %ds, %ax
+ push %ax
+
+ /* movw imm16, %ax*/
+ .byte 0xb8
+LOCAL(bios_register_es):
+ .short 0
+ movw %ax, %es
+ /* movw imm16, %ax*/
+ .byte 0xb8
+LOCAL(bios_register_ds):
+ .short 0
+ movw %ax, %ds
+
+ /* movw imm16, %ax*/
+ .byte 0xb8
+LOCAL(bios_register_flags):
+ .short 0
+ push %ax
+ popf
+
+ /* movl imm32, %eax*/
+ .byte 0x66, 0xb8
+LOCAL(bios_register_eax):
+ .long 0
+
+ /* int imm8. */
+ .byte 0xcd
+intno:
+ .byte 0
+
+ movl %eax, %cs:LOCAL(bios_register_eax)
+ movw %ds, %ax
+ movw %ax, %cs:LOCAL(bios_register_ds)
+ pop %ax
+ mov %ax, %ds
+ pushf
+ pop %ax
+ movw %ax, LOCAL(bios_register_flags)
+ mov %es, %ax
+ movw %ax, LOCAL(bios_register_es)
+
+ popf
+ DATA32 call real_to_prot
+ .code32
+
+ popl %eax
+
+ movl %ebx, 12(%eax)
+ movl %ecx, 16(%eax)
+ movl %edi, 20(%eax)
+ movl %esi, 24(%eax)
+ movl %edx, 28(%eax)
+
+ movl %eax, %edx
+
+ movl LOCAL(bios_register_eax), %eax
+ movl %eax, (%edx)
+ movw LOCAL(bios_register_es), %ax
+ movw %ax, 4(%edx)
+ movw LOCAL(bios_register_ds), %ax
+ movw %ax, 6(%edx)
+ movw LOCAL(bios_register_flags), %ax
+ movw %ax, 8(%edx)
+
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %eax
+ popl %ecx
+ popl %ebp
+#ifndef GRUB_MACHINE_PCBIOS
+ lidt protidt
+#endif
+ ret
+#ifndef GRUB_MACHINE_PCBIOS
+realidt:
+ .word 0x100
+ .long 0
+protidt:
+ .word 0
+ .long 0
+#endif
static struct mem_region mem_regions[MAX_REGIONS];
static int num_regions;
-static char *
-make_install_device (void)
-{
- /* XXX: This should be enough. */
- char dev[100], *ptr = dev;
+void (*grub_pc_net_config) (char **device, char **path);
- if (grub_prefix[0] != '(')
- {
- /* No hardcoded root partition - make it from the boot drive and the
- partition number encoded at the install time. */
- if (grub_boot_drive == GRUB_BOOT_MACHINE_PXE_DL)
- {
- grub_strcpy (dev, "(pxe");
- ptr += sizeof ("(pxe") - 1;
- }
- else
- {
- grub_snprintf (dev, sizeof (dev),
- "(%cd%u", (grub_boot_drive & 0x80) ? 'h' : 'f',
- grub_boot_drive & 0x7f);
- ptr += grub_strlen (ptr);
-
- if (grub_install_dos_part >= 0)
- grub_snprintf (ptr, sizeof (dev) - (ptr - dev),
- ",%u", grub_install_dos_part + 1);
- ptr += grub_strlen (ptr);
-
- if (grub_install_bsd_part >= 0)
- grub_snprintf (ptr, sizeof (dev) - (ptr - dev), ",%u",
- grub_install_bsd_part + 1);
- ptr += grub_strlen (ptr);
- }
+void
+grub_machine_get_bootlocation (char **device, char **path)
+{
+ char *ptr;
- grub_snprintf (ptr, sizeof (dev) - (ptr - dev), ")%s", grub_prefix);
- grub_strcpy (grub_prefix, dev);
- }
- else if (grub_prefix[1] == ',' || grub_prefix[1] == ')')
+ /* No hardcoded root partition - make it from the boot drive and the
+ partition number encoded at the install time. */
+ if (grub_boot_drive == GRUB_BOOT_MACHINE_PXE_DL)
{
- /* We have a prefix, but still need to fill in the boot drive. */
- grub_snprintf (dev, sizeof (dev),
- "(%cd%u%s", (grub_boot_drive & 0x80) ? 'h' : 'f',
- grub_boot_drive & 0x7f, grub_prefix + 1);
- grub_strcpy (grub_prefix, dev);
+ if (grub_pc_net_config)
+ grub_pc_net_config (device, path);
+ return;
}
- return grub_prefix;
+ /* XXX: This should be enough. */
+#define DEV_SIZE 100
+ *device = grub_malloc (DEV_SIZE);
+ ptr = *device;
+ grub_snprintf (*device, DEV_SIZE,
+ "%cd%u", (grub_boot_drive & 0x80) ? 'h' : 'f',
+ grub_boot_drive & 0x7f);
+ ptr += grub_strlen (ptr);
+
+ if (grub_install_dos_part >= 0)
+ grub_snprintf (ptr, DEV_SIZE - (ptr - *device),
+ ",%u", grub_install_dos_part + 1);
+ ptr += grub_strlen (ptr);
+
+ if (grub_install_bsd_part >= 0)
+ grub_snprintf (ptr, DEV_SIZE - (ptr - *device), ",%u",
+ grub_install_bsd_part + 1);
+ ptr += grub_strlen (ptr);
+ *ptr = 0;
}
/* Add a memory region. */
}
}
+grub_addr_t grub_modbase;
+
void
grub_machine_init (void)
{
int grub_lower_mem;
#endif
+ grub_modbase = GRUB_MEMORY_MACHINE_DECOMPRESSION_ADDR
+ + (grub_kernel_image_size - GRUB_KERNEL_MACHINE_RAW_SIZE);
+
/* Initialize the console as early as possible. */
grub_console_init ();
grub_tsc_init ();
}
-void
-grub_machine_set_prefix (void)
-{
- /* Initialize the prefix. */
- grub_env_set ("prefix", make_install_device ());
-}
-
void
grub_machine_fini (void)
{
grub_console_fini ();
grub_stop_floppy ();
}
-
-/* Return the end of the core image. */
-grub_addr_t
-grub_arch_modules_addr (void)
-{
- return GRUB_MEMORY_MACHINE_DECOMPRESSION_ADDR
- + (grub_kernel_image_size - GRUB_KERNEL_MACHINE_RAW_SIZE);
-}
*/
. = _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()
*
.code16
/* Tell the BIOS a boot failure. If this does not work, reboot. */
int $0x18
- jmp cold_reboot
+ /* set 0x472 to 0x0000 for cold boot (0x1234 for warm boot) */
+ movw $0x0472, %di
+ movw %ax, (%di)
+ ljmp $0xf000, $0xfff0
.code32
/*
popl %ebp
ret
-FUNCTION(grub_bios_interrupt)
- pushl %ebp
- pushl %ecx
- pushl %eax
- pushl %ebx
- pushl %esi
- pushl %edi
- pushl %edx
-
- movb %al, intno
- movl (%edx), %eax
- movl %eax, LOCAL(bios_register_eax)
- movw 4(%edx), %ax
- movw %ax, LOCAL(bios_register_es)
- movw 6(%edx), %ax
- movw %ax, LOCAL(bios_register_ds)
- movw 8(%edx), %ax
- movw %ax, LOCAL(bios_register_flags)
-
- movl 12(%edx), %ebx
- movl 16(%edx), %ecx
- movl 20(%edx), %edi
- movl 24(%edx), %esi
- movl 28(%edx), %edx
-
- call prot_to_real
- .code16
-
- mov %ds, %ax
- push %ax
-
- /* movw imm16, %ax*/
- .byte 0xb8
-LOCAL(bios_register_es):
- .short 0
- movw %ax, %es
- /* movw imm16, %ax*/
- .byte 0xb8
-LOCAL(bios_register_ds):
- .short 0
- movw %ax, %ds
-
- /* movw imm16, %ax*/
- .byte 0xb8
-LOCAL(bios_register_flags):
- .short 0
- push %ax
- popf
-
- /* movl imm32, %eax*/
- .byte 0x66, 0xb8
-LOCAL(bios_register_eax):
- .long 0
-
- /* int imm8. */
- .byte 0xcd
-intno:
- .byte 0
-
- movl %eax, %cs:LOCAL(bios_register_eax)
- movw %ds, %ax
- movw %ax, %cs:LOCAL(bios_register_ds)
- pop %ax
- mov %ax, %ds
- pushf
- pop %ax
- movw %ax, LOCAL(bios_register_flags)
- mov %es, %ax
- movw %ax, LOCAL(bios_register_es)
-
- DATA32 call real_to_prot
- .code32
-
- popl %eax
-
- movl %ebx, 12(%eax)
- movl %ecx, 16(%eax)
- movl %edi, 20(%eax)
- movl %esi, 24(%eax)
- movl %edx, 28(%eax)
-
- movl %eax, %edx
-
- movl LOCAL(bios_register_eax), %eax
- movl %eax, (%edx)
- movw LOCAL(bios_register_es), %ax
- movw %ax, 4(%edx)
- movw LOCAL(bios_register_ds), %ax
- movw %ax, 6(%edx)
- movw LOCAL(bios_register_flags), %ax
- movw %ax, 8(%edx)
-
- popl %edi
- popl %esi
- popl %ebx
- popl %eax
- popl %ecx
- popl %ebp
- ret
+#include "../int.S"
+++ /dev/null
-/*
- * 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/pci.h>
-#include <grub/machine/kernel.h>
-#include <grub/misc.h>
-#include <grub/vga.h>
-
-static struct {grub_uint8_t r, g, b, a; } colors[] =
- {
- // {R, G, B, A}
- {0x00, 0x00, 0x00, 0xFF}, // 0 = black
- {0x00, 0x00, 0xA8, 0xFF}, // 1 = blue
- {0x00, 0xA8, 0x00, 0xFF}, // 2 = green
- {0x00, 0xA8, 0xA8, 0xFF}, // 3 = cyan
- {0xA8, 0x00, 0x00, 0xFF}, // 4 = red
- {0xA8, 0x00, 0xA8, 0xFF}, // 5 = magenta
- {0xA8, 0x54, 0x00, 0xFF}, // 6 = brown
- {0xA8, 0xA8, 0xA8, 0xFF}, // 7 = light gray
-
- {0x54, 0x54, 0x54, 0xFF}, // 8 = dark gray
- {0x54, 0x54, 0xFE, 0xFF}, // 9 = bright blue
- {0x54, 0xFE, 0x54, 0xFF}, // 10 = bright green
- {0x54, 0xFE, 0xFE, 0xFF}, // 11 = bright cyan
- {0xFE, 0x54, 0x54, 0xFF}, // 12 = bright red
- {0xFE, 0x54, 0xFE, 0xFF}, // 13 = bright magenta
- {0xFE, 0xFE, 0x54, 0xFF}, // 14 = yellow
- {0xFE, 0xFE, 0xFE, 0xFF} // 15 = white
- };
-
-#include <ascii.h>
-
-static void
-load_font (void)
-{
- unsigned i;
-
- grub_vga_gr_write (0 << 2, GRUB_VGA_GR_GR6);
-
- grub_vga_sr_write (GRUB_VGA_SR_MEMORY_MODE_NORMAL, GRUB_VGA_SR_MEMORY_MODE);
- grub_vga_sr_write (1 << GRUB_VGA_TEXT_FONT_PLANE,
- GRUB_VGA_SR_MAP_MASK_REGISTER);
-
- grub_vga_gr_write (0, GRUB_VGA_GR_DATA_ROTATE);
- grub_vga_gr_write (0, GRUB_VGA_GR_MODE);
- grub_vga_gr_write (0xff, GRUB_VGA_GR_BITMASK);
-
- for (i = 0; i < 128; i++)
- grub_memcpy ((void *) (0xa0000 + 32 * i), ascii_bitmaps + 16 * i, 16);
-}
-
-static void
-load_palette (void)
-{
- unsigned i;
- for (i = 0; i < 16; i++)
- grub_vga_write_arx (i, i);
-
- for (i = 0; i < ARRAY_SIZE (colors); i++)
- grub_vga_palette_write (i, colors[i].r, colors[i].g, colors[i].b);
-}
-
-void
-grub_qemu_init_cirrus (void)
-{
- auto int NESTED_FUNC_ATTR find_card (grub_pci_device_t dev, grub_pci_id_t pciid);
- int NESTED_FUNC_ATTR find_card (grub_pci_device_t dev, grub_pci_id_t pciid __attribute__ ((unused)))
- {
- grub_pci_address_t addr;
- grub_uint32_t class;
-
- addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS);
- class = grub_pci_read (addr);
-
- if (((class >> 16) & 0xffff) != GRUB_PCI_CLASS_SUBCLASS_VGA)
- return 0;
-
- /* FIXME: chooose addresses dynamically. */
- addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0);
- grub_pci_write (addr, 0xf0000000 | GRUB_PCI_ADDR_MEM_PREFETCH
- | GRUB_PCI_ADDR_SPACE_MEMORY | GRUB_PCI_ADDR_MEM_TYPE_32);
- addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG1);
- grub_pci_write (addr, 0xf2000000
- | GRUB_PCI_ADDR_SPACE_MEMORY | GRUB_PCI_ADDR_MEM_TYPE_32);
-
- addr = grub_pci_make_address (dev, GRUB_PCI_REG_COMMAND);
- grub_pci_write (addr, GRUB_PCI_COMMAND_MEM_ENABLED
- | GRUB_PCI_COMMAND_IO_ENABLED);
-
- return 1;
- }
-
- grub_pci_iterate (find_card);
-
- grub_outb (GRUB_VGA_IO_MISC_COLOR, GRUB_VGA_IO_MISC_WRITE);
-
- load_font ();
-
- grub_vga_gr_write (GRUB_VGA_GR_GR6_MMAP_CGA, GRUB_VGA_GR_GR6);
- grub_vga_gr_write (GRUB_VGA_GR_MODE_ODD_EVEN, GRUB_VGA_GR_MODE);
-
- grub_vga_sr_write (GRUB_VGA_SR_MEMORY_MODE_NORMAL, GRUB_VGA_SR_MEMORY_MODE);
-
- grub_vga_sr_write ((1 << GRUB_VGA_TEXT_TEXT_PLANE)
- | (1 << GRUB_VGA_TEXT_ATTR_PLANE),
- GRUB_VGA_SR_MAP_MASK_REGISTER);
-
- grub_vga_cr_write (15, GRUB_VGA_CR_CELL_HEIGHT);
- grub_vga_cr_write (79, GRUB_VGA_CR_HORIZ_END);
- grub_vga_cr_write (40, GRUB_VGA_CR_PITCH);
-
- int vert = 25 * 16;
- grub_vga_cr_write (vert & 0xff, GRUB_VGA_CR_VDISPLAY_END);
- grub_vga_cr_write (((vert >> GRUB_VGA_CR_OVERFLOW_HEIGHT1_SHIFT)
- & GRUB_VGA_CR_OVERFLOW_HEIGHT1_MASK)
- | ((vert >> GRUB_VGA_CR_OVERFLOW_HEIGHT2_SHIFT)
- & GRUB_VGA_CR_OVERFLOW_HEIGHT2_MASK),
- GRUB_VGA_CR_OVERFLOW);
-
- load_palette ();
-
- grub_vga_write_arx (GRUB_VGA_ARX_MODE_TEXT, GRUB_VGA_ARX_MODE);
- grub_vga_write_arx (0, GRUB_VGA_ARX_COLOR_SELECT);
-
- grub_vga_sr_write (GRUB_VGA_SR_CLOCKING_MODE_8_DOT_CLOCK,
- GRUB_VGA_SR_CLOCKING_MODE);
-
- grub_vga_cr_write (14, GRUB_VGA_CR_CURSOR_START);
- grub_vga_cr_write (15, GRUB_VGA_CR_CURSOR_END);
-
- grub_outb (0x20, 0x3c0);
-}
void
grub_machine_mmap_init ()
{
- mem_size = ((grub_uint64_t) grub_cmos_read (QEMU_CMOS_MEMSIZE_HIGH)) << 24
- | ((grub_uint64_t) grub_cmos_read (QEMU_CMOS_MEMSIZE_LOW)) << 16;
+ grub_uint8_t high, low, b, c, d;
+ grub_cmos_read (QEMU_CMOS_MEMSIZE_HIGH, &high);
+ grub_cmos_read (QEMU_CMOS_MEMSIZE_LOW, &low);
+ mem_size = ((grub_uint64_t) high) << 24
+ | ((grub_uint64_t) low) << 16;
if (mem_size > 0)
{
/* Don't ask... */
}
else
{
+ grub_cmos_read (QEMU_CMOS_MEMSIZE2_HIGH, &high);
+ grub_cmos_read (QEMU_CMOS_MEMSIZE2_LOW, &low);
mem_size
- = ((((grub_uint64_t) grub_cmos_read (QEMU_CMOS_MEMSIZE2_HIGH)) << 18)
- | ((grub_uint64_t) (grub_cmos_read (QEMU_CMOS_MEMSIZE2_LOW)) << 10))
+ = ((((grub_uint64_t) high) << 18) | (((grub_uint64_t) low) << 10))
+ 1024 * 1024;
}
- above_4g = (((grub_uint64_t) grub_cmos_read (0x5b)) << 16)
- | (((grub_uint64_t) grub_cmos_read (0x5c)) << 24)
- | (((grub_uint64_t) grub_cmos_read (0x5d)) << 32);
+ grub_cmos_read (0x5b, &b);
+ grub_cmos_read (0x5c, &c);
+ grub_cmos_read (0x5d, &d);
+ above_4g = (((grub_uint64_t) b) << 16)
+ | (((grub_uint64_t) c) << 24)
+ | (((grub_uint64_t) d) << 32);
}
grub_err_t
.long 0
VARIABLE(grub_kernel_image_size)
.long 0
-VARIABLE(grub_prefix)
- /* to be filled by grub-mkimage */
-
- /*
- * Leave some breathing room for the prefix.
- */
-
- . = _start + GRUB_KERNEL_MACHINE_PREFIX_END
codestart:
/* Relocate to low memory. First we figure out our location.
DATA32 ret
.code32
-
-/*
- * grub_reboot()
- *
- * Reboot the system. At the moment, rely on BIOS.
- */
-FUNCTION(grub_reboot)
- call prot_to_real
- .code16
-cold_reboot:
- /* set 0x472 to 0x0000 for cold boot (0x1234 for warm boot) */
- movw $0x0472, %di
- movw %ax, (%di)
- ljmp $0xf000, $0xfff0
- .code32
--- /dev/null
+/* dl.c - arch-dependent part of loadable module support */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2002,2004,2005,2007,2009 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/dl.h>
+#include <grub/elf.h>
+#include <grub/misc.h>
+#include <grub/err.h>
+#include <grub/mm.h>
+
+/* Check if EHDR is a valid ELF header. */
+grub_err_t
+grub_arch_dl_check_header (void *ehdr)
+{
+ Elf_Ehdr *e = ehdr;
+
+ /* Check the magic numbers. */
+ if (e->e_ident[EI_CLASS] != ELFCLASS64
+ || e->e_ident[EI_DATA] != ELFDATA2LSB
+ || e->e_machine != EM_IA_64)
+ return grub_error (GRUB_ERR_BAD_OS, "invalid arch specific ELF magic");
+
+ return GRUB_ERR_NONE;
+}
+
+#define MASK20 ((1 << 20) - 1)
+#define MASK19 ((1 << 19) - 1)
+
+struct unaligned_uint32
+{
+ grub_uint32_t val;
+} __attribute__ ((packed));
+
+static void
+add_value_to_slot_20b (grub_addr_t addr, grub_uint32_t value)
+{
+ struct unaligned_uint32 *p;
+ switch (addr & 3)
+ {
+ case 0:
+ p = (struct unaligned_uint32 *) ((addr & ~3ULL) + 2);
+ p->val = ((((((p->val >> 2) & MASK20) + value) & MASK20) << 2)
+ | (p->val & ~(MASK20 << 2)));
+ break;
+ case 1:
+ p = (struct unaligned_uint32 *) ((grub_uint8_t *) (addr & ~3ULL) + 7);
+ p->val = ((((((p->val >> 3) & MASK20) + value) & MASK20) << 3)
+ | (p->val & ~(MASK20 << 3)));
+ break;
+ case 2:
+ p = (struct unaligned_uint32 *) ((grub_uint8_t *) (addr & ~3ULL) + 12);
+ p->val = ((((((p->val >> 4) & MASK20) + value) & MASK20) << 4)
+ | (p->val & ~(MASK20 << 4)));
+ break;
+ }
+}
+
+#define MASKF21 ( ((1 << 23) - 1) & ~((1 << 7) | (1 << 8)) )
+
+static grub_uint32_t
+add_value_to_slot_21_real (grub_uint32_t a, grub_uint32_t value)
+{
+ grub_uint32_t high, mid, low, c;
+ low = (a & 0x00007f);
+ mid = (a & 0x7fc000) >> 7;
+ high = (a & 0x003e00) << 7;
+ c = (low | mid | high) + value;
+ return (c & 0x7f) | ((c << 7) & 0x7fc000) | ((c >> 7) & 0x0003e00); //0x003e00
+}
+
+static void
+add_value_to_slot_21 (grub_addr_t addr, grub_uint32_t value)
+{
+ struct unaligned_uint32 *p;
+ switch (addr & 3)
+ {
+ case 0:
+ p = (struct unaligned_uint32 *) ((addr & ~3ULL) + 2);
+ p->val = ((add_value_to_slot_21_real (((p->val >> 2) & MASKF21), value) & MASKF21) << 2) | (p->val & ~(MASKF21 << 2));
+ break;
+ case 1:
+ p = (struct unaligned_uint32 *) ((grub_uint8_t *) (addr & ~3ULL) + 7);
+ p->val = ((add_value_to_slot_21_real (((p->val >> 3) & MASKF21), value) & MASKF21) << 3) | (p->val & ~(MASKF21 << 3));
+ break;
+ case 2:
+ p = (struct unaligned_uint32 *) ((grub_uint8_t *) (addr & ~3ULL) + 12);
+ p->val = ((add_value_to_slot_21_real (((p->val >> 4) & MASKF21), value) & MASKF21) << 4) | (p->val & ~(MASKF21 << 4));
+ break;
+ }
+}
+
+static grub_uint8_t nopm[5] =
+ {
+ /* [MLX] nop.m 0x0 */
+ 0x05, 0x00, 0x00, 0x00, 0x01
+ };
+
+static grub_uint8_t jump[0x20] =
+ {
+ /* ld8 r16=[r15],8 */
+ 0x02, 0x80, 0x20, 0x1e, 0x18, 0x14,
+ /* mov r14=r1;; */
+ 0xe0, 0x00, 0x04, 0x00, 0x42, 0x00,
+ /* nop.i 0x0 */
+ 0x00, 0x00, 0x04, 0x00,
+ /* ld8 r1=[r15] */
+ 0x11, 0x08, 0x00, 0x1e, 0x18, 0x10,
+ /* mov b6=r16 */
+ 0x60, 0x80, 0x04, 0x80, 0x03, 0x00,
+ /* br.few b6;; */
+ 0x60, 0x00, 0x80, 0x00
+ };
+
+struct ia64_trampoline
+{
+ /* nop.m */
+ grub_uint8_t nop[5];
+ /* movl r15 = addr*/
+ grub_uint8_t addr_hi[6];
+ grub_uint8_t e0;
+ grub_uint8_t addr_lo[4];
+ grub_uint8_t jump[0x20];
+};
+
+static void
+make_trampoline (struct ia64_trampoline *tr, grub_uint64_t addr)
+{
+ COMPILE_TIME_ASSERT (sizeof (struct ia64_trampoline)
+ == GRUB_IA64_DL_TRAMP_SIZE);
+ grub_memcpy (tr->nop, nopm, sizeof (tr->nop));
+ tr->addr_hi[0] = ((addr & 0xc00000) >> 16);
+ tr->addr_hi[1] = (addr >> 24) & 0xff;
+ tr->addr_hi[2] = (addr >> 32) & 0xff;
+ tr->addr_hi[3] = (addr >> 40) & 0xff;
+ tr->addr_hi[4] = (addr >> 48) & 0xff;
+ tr->addr_hi[5] = (addr >> 56) & 0xff;
+ tr->e0 = 0xe0;
+ tr->addr_lo[0] = ((addr & 0x000f) << 4) | 0x01;
+ tr->addr_lo[1] = (((addr & 0x0070) >> 4) | ((addr & 0x070000) >> 11)
+ | ((addr & 0x200000) >> 17));
+ tr->addr_lo[2] = ((addr & 0x1f80) >> 5) | ((addr & 0x180000) >> 19);
+ tr->addr_lo[3] = ((addr & 0xe000) >> 13) | 0x60;
+ grub_memcpy (tr->jump, jump, sizeof (tr->jump));
+}
+
+/* Relocate symbols. */
+grub_err_t
+grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr)
+{
+ Elf_Ehdr *e = ehdr;
+ Elf_Shdr *s;
+ Elf_Word entsize;
+ unsigned i;
+ grub_uint64_t *gp, *gpptr;
+ struct ia64_trampoline *tr;
+
+ gp = (grub_uint64_t *) mod->base;
+ gpptr = (grub_uint64_t *) mod->got;
+ tr = mod->tramp;
+
+ /* Find a symbol table. */
+ for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff);
+ i < e->e_shnum;
+ i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize))
+ if (s->sh_type == SHT_SYMTAB)
+ break;
+
+ if (i == e->e_shnum)
+ return grub_error (GRUB_ERR_BAD_MODULE, "no symtab found");
+
+ entsize = s->sh_entsize;
+
+ for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff);
+ i < e->e_shnum;
+ i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize))
+ if (s->sh_type == SHT_RELA)
+ {
+ grub_dl_segment_t seg;
+
+ /* Find the target segment. */
+ for (seg = mod->segment; seg; seg = seg->next)
+ if (seg->section == s->sh_info)
+ break;
+
+ if (seg)
+ {
+ Elf_Rela *rel, *max;
+
+ for (rel = (Elf_Rela *) ((char *) e + s->sh_offset),
+ max = rel + s->sh_size / s->sh_entsize;
+ rel < max;
+ rel++)
+ {
+ grub_addr_t addr;
+ Elf_Sym *sym;
+ grub_uint64_t value;
+
+ if (seg->size < (rel->r_offset & ~3))
+ return grub_error (GRUB_ERR_BAD_MODULE,
+ "reloc offset is out of the segment");
+
+ addr = (grub_addr_t) seg->addr + rel->r_offset;
+ sym = (Elf_Sym *) ((char *) mod->symtab
+ + entsize * ELF_R_SYM (rel->r_info));
+
+ /* On the PPC the value does not have an explicit
+ addend, add it. */
+ value = sym->st_value + rel->r_addend;
+
+ switch (ELF_R_TYPE (rel->r_info))
+ {
+ case R_IA64_PCREL21B:
+ {
+ grub_uint64_t noff;
+ make_trampoline (tr, value);
+ noff = ((char *) tr - (char *) (addr & ~3)) >> 4;
+ tr++;
+ if (noff & ~MASK19)
+ return grub_error (GRUB_ERR_BAD_OS,
+ "trampoline offset too big (%lx)", noff);
+ add_value_to_slot_20b (addr, noff);
+ }
+ break;
+ case R_IA64_SEGREL64LSB:
+ *(grub_uint64_t *) addr += value - (grub_addr_t) seg->addr;
+ break;
+ case R_IA64_FPTR64LSB:
+ case R_IA64_DIR64LSB:
+ *(grub_uint64_t *) addr += value;
+ break;
+ case R_IA64_PCREL64LSB:
+ *(grub_uint64_t *) addr += value - addr;
+ break;
+ case R_IA64_GPREL22:
+ add_value_to_slot_21 (addr, value - (grub_addr_t) gp);
+ break;
+
+ case R_IA64_LTOFF22X:
+ case R_IA64_LTOFF22:
+ if (ELF_ST_TYPE (sym->st_info) == STT_FUNC)
+ value = *(grub_uint64_t *) sym->st_value + rel->r_addend;
+ case R_IA64_LTOFF_FPTR22:
+ *gpptr = value;
+ add_value_to_slot_21 (addr, (grub_addr_t) gpptr - (grub_addr_t) gp);
+ gpptr++;
+ break;
+
+ /* We treat LTOFF22X as LTOFF22, so we can ignore LDXMOV. */
+ case R_IA64_LDXMOV:
+ break;
+ default:
+ return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
+ "this relocation (0x%x) is not implemented yet",
+ ELF_R_TYPE (rel->r_info));
+ }
+ }
+ }
+ }
+
+ return GRUB_ERR_NONE;
+}
--- /dev/null
+/* dl.c - arch-dependent part of loadable module support */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2002,2004,2005,2007,2009 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/dl.h>
+#include <grub/elf.h>
+#include <grub/misc.h>
+#include <grub/err.h>
+#include <grub/mm.h>
+
+void
+grub_ia64_dl_get_tramp_got_size (const void *ehdr, grub_size_t *tramp,
+ grub_size_t *got)
+{
+ const Elf64_Ehdr *e = ehdr;
+ grub_size_t cntt = 0, cntg = 0;;
+ const Elf64_Shdr *s;
+ Elf64_Word entsize;
+ unsigned i;
+
+ /* Find a symbol table. */
+ for (i = 0, s = (Elf64_Shdr *) ((char *) e + grub_le_to_cpu32 (e->e_shoff));
+ i < grub_le_to_cpu16 (e->e_shnum);
+ i++, s = (Elf64_Shdr *) ((char *) s + grub_le_to_cpu16 (e->e_shentsize)))
+ if (grub_le_to_cpu32 (s->sh_type) == SHT_SYMTAB)
+ break;
+
+ if (i == grub_le_to_cpu16 (e->e_shnum))
+ return;
+
+ entsize = s->sh_entsize;
+
+ for (i = 0, s = (Elf64_Shdr *) ((char *) e + grub_le_to_cpu32 (e->e_shoff));
+ i < grub_le_to_cpu16 (e->e_shnum);
+ i++, s = (Elf64_Shdr *) ((char *) s + grub_le_to_cpu16 (e->e_shentsize)))
+ if (grub_le_to_cpu32 (s->sh_type) == SHT_RELA)
+ {
+ Elf64_Rela *rel, *max;
+
+ for (rel = (Elf64_Rela *) ((char *) e + grub_le_to_cpu32 (s->sh_offset)),
+ max = rel + grub_le_to_cpu32 (s->sh_size) / grub_le_to_cpu16 (s->sh_entsize);
+ rel < max; rel++)
+ switch (ELF64_R_TYPE (grub_le_to_cpu32 (rel->r_info)))
+ {
+ case R_IA64_PCREL21B:
+ cntt++;
+ break;
+ case R_IA64_LTOFF_FPTR22:
+ case R_IA64_LTOFF22X:
+ case R_IA64_LTOFF22:
+ cntg++;
+ break;
+ }
+ }
+ *tramp = cntt;
+ *got = cntg;
+}
+
--- /dev/null
+/* init.c - initialize an ia64-based EFI system */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2008 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/types.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/time.h>
+#include <grub/err.h>
+#include <grub/dl.h>
+#include <grub/cache.h>
+#include <grub/kernel.h>
+#include <grub/efi/efi.h>
+
+void
+grub_machine_init (void)
+{
+ grub_efi_init ();
+ grub_install_get_time_ms (grub_rtc_get_time_ms);
+}
+
+void
+grub_machine_fini (void)
+{
+ grub_efi_fini ();
+}
+
+void
+grub_arch_sync_caches (void *address, grub_size_t len)
+{
+ /* Cache line length is at least 32. */
+ grub_uint64_t a = (grub_uint64_t)address & ~0x1f;
+
+ /* Flush data. */
+ for (len = (len + 31) & ~0x1f; len > 0; len -= 0x20, a += 0x20)
+ asm volatile ("fc.i %0" : : "r" (a));
+ /* Sync and serialize. Maybe extra. */
+ asm volatile (";; sync.i;; srlz.i;;");
+}
--- /dev/null
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2008 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <config.h>
+#include <grub/symbol.h>
+#include <grub/offsets.h>
+
+ .text
+ .psr abi64
+ .psr lsb
+ .lsb
+
+ .global _start
+ .proc _start
+_start:
+ alloc loc0=ar.pfs,2,4,0,0
+ mov loc1=rp
+ addl loc2=@gprel(grub_efi_image_handle),gp
+ addl loc3=@gprel(grub_efi_system_table),gp
+ ;;
+ st8 [loc2]=in0
+ st8 [loc3]=in1
+ br.call.sptk.few rp=grub_main
+ ;;
+ mov ar.pfs=loc0
+ mov rp=loc1
+ ;;
+ br.ret.sptk.few rp
+
+ .endp _start
int is_olpc = 0;
int is_qemu = 0;
+#ifdef __sparc__
+ grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_NO_PARTITION_0);
+#endif
+
grub_ieee1275_finddevice ("/", &root);
grub_ieee1275_finddevice ("/options", &options);
grub_ieee1275_finddevice ("/openprom", &openprom);
#include <grub/ieee1275/console.h>
#include <grub/ieee1275/ofdisk.h>
#include <grub/ieee1275/ieee1275.h>
+#include <grub/net.h>
#include <grub/offsets.h>
#include <grub/memory.h>
+#ifdef __sparc__
+#include <grub/machine/kernel.h>
+#endif
/* The minimal heap size we can live with. */
#define HEAP_MIN_SIZE (unsigned long) (2 * 1024 * 1024)
extern char _start[];
extern char _end[];
+#ifdef __sparc__
+grub_addr_t grub_ieee1275_original_stack;
+#endif
+
void
grub_exit (void)
{
}
}
+void (*grub_ieee1275_net_config) (const char *dev,
+ char **device,
+ char **path);
void
-grub_machine_set_prefix (void)
+grub_machine_get_bootlocation (char **device, char **path)
{
char bootpath[64]; /* XXX check length */
char *filename;
- char *prefix;
-
- if (grub_prefix[0])
- {
- grub_env_set ("prefix", grub_prefix);
- /* Prefix is hardcoded in the core image. */
- return;
- }
-
+ char *type;
+
if (grub_ieee1275_get_property (grub_ieee1275_chosen, "bootpath", &bootpath,
sizeof (bootpath), 0))
{
/* Should never happen. */
grub_printf ("/chosen/bootpath property missing!\n");
- grub_env_set ("prefix", "");
return;
}
/* Transform an OF device path to a GRUB path. */
- prefix = grub_ieee1275_encode_devname (bootpath);
+ type = grub_ieee1275_get_device_type (bootpath);
+ if (type && grub_strcmp (type, "network") == 0)
+ {
+ char *dev, *canon;
+ char *ptr;
+ dev = grub_ieee1275_get_aliasdevname (bootpath);
+ canon = grub_ieee1275_canonicalise_devname (dev);
+ ptr = canon + grub_strlen (canon) - 1;
+ while (ptr > canon && (*ptr == ',' || *ptr == ':'))
+ ptr--;
+ ptr++;
+ *ptr = 0;
+
+ if (grub_ieee1275_net_config)
+ grub_ieee1275_net_config (canon, device, path);
+ grub_free (dev);
+ grub_free (canon);
+ }
+ else
+ *device = grub_ieee1275_encode_devname (bootpath);
+ grub_free (type);
filename = grub_ieee1275_get_filename (bootpath);
if (filename)
{
- char *newprefix;
char *lastslash = grub_strrchr (filename, '\\');
/* Truncate at last directory. */
*lastslash = '\0';
grub_translate_ieee1275_path (filename);
- newprefix = grub_xasprintf ("%s%s", prefix, filename);
- if (newprefix)
- {
- grub_free (prefix);
- prefix = newprefix;
- }
+ *path = filename;
}
}
-
- grub_env_set ("prefix", prefix);
-
- grub_free (filename);
- grub_free (prefix);
}
/* Claim some available memory in the first /memory node. */
-static void grub_claim_heap (void)
+#ifdef __sparc__
+static void
+grub_claim_heap (void)
+{
+ grub_mm_init_region ((void *) (grub_modules_get_end ()
+ + GRUB_KERNEL_MACHINE_STACK_SIZE), 0x200000);
+}
+#else
+static void
+grub_claim_heap (void)
{
unsigned long total = 0;
else
grub_machine_mmap_iterate (heap_init);
}
+#endif
-static grub_uint64_t ieee1275_get_time_ms (void);
-
-void
-grub_machine_init (void)
+static void
+grub_parse_cmdline (void)
{
- char args[256];
grub_ssize_t actual;
+ char args[256];
- grub_ieee1275_init ();
-
- grub_console_init_early ();
- grub_claim_heap ();
- grub_console_init_lately ();
- grub_ofdisk_init ();
-
- /* Process commandline. */
if (grub_ieee1275_get_property (grub_ieee1275_chosen, "bootargs", &args,
sizeof args, &actual) == 0
&& actual > 1)
}
}
}
+}
+
+static grub_uint64_t ieee1275_get_time_ms (void);
+
+grub_addr_t grub_modbase;
+
+void
+grub_machine_init (void)
+{
+ grub_modbase = ALIGN_UP((grub_addr_t) _end
+ + GRUB_KERNEL_MACHINE_MOD_GAP,
+ GRUB_KERNEL_MACHINE_MOD_ALIGN);
+ grub_ieee1275_init ();
+
+ grub_console_init_early ();
+ grub_claim_heap ();
+ grub_console_init_lately ();
+ grub_ofdisk_init ();
+
+ grub_parse_cmdline ();
grub_install_get_time_ms (ieee1275_get_time_ms);
}
{
return ieee1275_get_time_ms ();
}
-
-grub_addr_t
-grub_arch_modules_addr (void)
-{
- return ALIGN_UP((grub_addr_t) _end + GRUB_KERNEL_MACHINE_MOD_GAP, GRUB_KERNEL_MACHINE_MOD_ALIGN);
-}
#include <grub/misc.h>
#include <grub/mm.h>
#include <grub/ieee1275/ieee1275.h>
+#include <grub/net.h>
enum grub_ieee1275_parse_type
{
GRUB_PARSE_FILENAME,
GRUB_PARSE_PARTITION,
+ GRUB_PARSE_DEVICE,
+ GRUB_PARSE_DEVICE_TYPE
};
/* Walk children of 'devpath', calling hook for each. */
{
char type[64]; /* XXX check size. */
char *device = grub_ieee1275_get_devname (path);
- char *args = grub_ieee1275_get_devargs (path);
char *ret = 0;
grub_ieee1275_phandle_t dev;
- if (!args)
- /* Shouldn't happen. */
- return 0;
-
/* We need to know what type of device it is in order to parse the full
file path properly. */
if (grub_ieee1275_finddevice (device, &dev))
goto fail;
}
- if (!grub_strcmp ("block", type))
+ switch (ptype)
{
- /* The syntax of the device arguments is defined in the CHRP and PReP
- IEEE1275 bindings: "[partition][,[filename]]". */
- char *comma = grub_strchr (args, ',');
+ case GRUB_PARSE_DEVICE:
+ ret = grub_strdup (device);
+ break;
+ case GRUB_PARSE_DEVICE_TYPE:
+ ret = grub_strdup (type);
+ break;
+ case GRUB_PARSE_FILENAME:
+ {
+ char *comma;
+ char *args;
+
+ if (grub_strcmp ("block", type) != 0)
+ goto unknown;
+
+ args = grub_ieee1275_get_devargs (path);
+ if (!args)
+ /* Shouldn't happen. */
+ return 0;
- if (ptype == GRUB_PARSE_FILENAME)
- {
- if (comma)
- {
- char *filepath = comma + 1;
-
- /* Make sure filepath has leading backslash. */
- if (filepath[0] != '\\')
- ret = grub_xasprintf ("\\%s", filepath);
- else
- ret = grub_strdup (filepath);
+ /* The syntax of the device arguments is defined in the CHRP and PReP
+ IEEE1275 bindings: "[partition][,[filename]]". */
+ comma = grub_strchr (args, ',');
+
+ if (comma)
+ {
+ char *filepath = comma + 1;
+
+ /* Make sure filepath has leading backslash. */
+ if (filepath[0] != '\\')
+ ret = grub_xasprintf ("\\%s", filepath);
+ else
+ ret = grub_strdup (filepath);
}
+ grub_free (args);
}
- else if (ptype == GRUB_PARSE_PARTITION)
- {
- if (!comma)
- ret = grub_strdup (args);
- else
- ret = grub_strndup (args, (grub_size_t)(comma - args));
- }
- }
- else
- {
- /* XXX Handle net devices by configuring & registering a grub_net_dev
- here, then return its name?
- Example path: "net:<server ip>,<file name>,<client ip>,<gateway
- ip>,<bootp retries>,<tftp retries>". */
+ break;
+ case GRUB_PARSE_PARTITION:
+ {
+ char *comma;
+ char *args;
+
+ if (grub_strcmp ("block", type) != 0)
+ goto unknown;
+
+ args = grub_ieee1275_get_devargs (path);
+ if (!args)
+ /* Shouldn't happen. */
+ return 0;
+
+ comma = grub_strchr (args, ',');
+ if (!comma)
+ ret = grub_strdup (args);
+ else
+ ret = grub_strndup (args, (grub_size_t)(comma - args));
+ /* Consistently provide numbered partitions to GRUB.
+ OpenBOOT traditionally uses alphabetical partition
+ specifiers. */
+ if (ret[0] >= 'a' && ret[0] <= 'z')
+ ret[0] = '1' + (ret[0] - 'a');
+ grub_free (args);
+ }
+ break;
+ default:
+ unknown:
grub_printf ("Unsupported type %s for device %s\n", type, device);
}
fail:
grub_free (device);
- grub_free (args);
return ret;
}
+char *
+grub_ieee1275_get_device_type (const char *path)
+{
+ return grub_ieee1275_parse_args (path, GRUB_PARSE_DEVICE_TYPE);
+}
+
+char *
+grub_ieee1275_get_aliasdevname (const char *path)
+{
+ return grub_ieee1275_parse_args (path, GRUB_PARSE_DEVICE);
+}
+
char *
grub_ieee1275_get_filename (const char *path)
{
return encoding;
}
-/* On i386, a firmware-independant grub_reboot() is provided by realmode.S. */
-#ifndef __i386__
-void
-grub_reboot (void)
-{
- grub_ieee1275_interpret ("reset-all", 0);
- for (;;) ;
-}
-#endif
-
/* Resolve aliases. */
char *
grub_ieee1275_canonicalise_devname (const char *path)
grub_free (buf);
return NULL;
}
+
#include <grub/reader.h>
#include <grub/parser.h>
-void
-grub_module_iterate (int (*hook) (struct grub_module_header *header))
-{
- struct grub_module_info *modinfo;
- struct grub_module_header *header;
- grub_addr_t modbase;
-
- modbase = grub_arch_modules_addr ();
- modinfo = (struct grub_module_info *) modbase;
-
- /* Check if there are any modules. */
- if ((modinfo == 0) || modinfo->magic != GRUB_MODULE_MAGIC)
- return;
-
- for (header = (struct grub_module_header *) (modbase + modinfo->offset);
- header < (struct grub_module_header *) (modbase + modinfo->size);
- header = (struct grub_module_header *) ((char *) header + header->size))
- {
- if (hook (header))
- break;
- }
-}
-
-/* This is actualy platform-independant but used only on yeeloong and sparc. */
-#if defined (GRUB_MACHINE_MIPS_YEELOONG) || defined (GRUB_MACHINE_SPARC64)
+/* This is actualy platform-independant but used only on loongson and sparc. */
+#if defined (GRUB_MACHINE_MIPS_LOONGSON) || defined (GRUB_MACHINE_MIPS_QEMU_MIPS) || defined (GRUB_MACHINE_SPARC64)
grub_addr_t
grub_modules_get_end (void)
{
struct grub_module_info *modinfo;
- grub_addr_t modbase;
- modbase = grub_arch_modules_addr ();
- modinfo = (struct grub_module_info *) modbase;
+ modinfo = (struct grub_module_info *) grub_modbase;
/* Check if there are any modules. */
if ((modinfo == 0) || modinfo->magic != GRUB_MODULE_MAGIC)
- return modbase;
+ return grub_modbase;
- return modbase + modinfo->size;
+ return grub_modbase + modinfo->size;
}
#endif
static void
grub_load_modules (void)
{
- auto int hook (struct grub_module_header *);
- int hook (struct grub_module_header *header)
- {
- /* Not an ELF module, skip. */
- if (header->type != OBJ_TYPE_ELF)
- return 0;
-
- if (! grub_dl_load_core ((char *) header + sizeof (struct grub_module_header),
- (header->size - sizeof (struct grub_module_header))))
- grub_fatal ("%s", grub_errmsg);
-
- if (grub_errno)
- grub_print_error ();
-
- return 0;
- }
-
- grub_module_iterate (hook);
+ struct grub_module_header *header;
+ FOR_MODULES (header)
+ {
+ /* Not an ELF module, skip. */
+ if (header->type != OBJ_TYPE_ELF)
+ continue;
+
+ if (! grub_dl_load_core ((char *) header + sizeof (struct grub_module_header),
+ (header->size - sizeof (struct grub_module_header))))
+ grub_fatal ("%s", grub_errmsg);
+
+ if (grub_errno)
+ grub_print_error ();
+ }
}
static void
grub_load_config (void)
{
- auto int hook (struct grub_module_header *);
- int hook (struct grub_module_header *header)
- {
- /* Not an embedded config, skip. */
- if (header->type != OBJ_TYPE_CONFIG)
- return 0;
-
- grub_parser_execute ((char *) header +
- sizeof (struct grub_module_header));
- return 1;
- }
-
- grub_module_iterate (hook);
+ struct grub_module_header *header;
+ FOR_MODULES (header)
+ {
+ /* Not an embedded config, skip. */
+ if (header->type != OBJ_TYPE_CONFIG)
+ continue;
+
+ grub_parser_execute ((char *) header +
+ sizeof (struct grub_module_header));
+ break;
+ }
}
/* Write hook for the environment variables of root. Remove surrounding
return grub_strdup (val);
}
-/* Set the root device according to the dl prefix. */
static void
-grub_set_root_dev (void)
+grub_set_prefix_and_root (void)
{
- const char *prefix;
+ char *device = NULL;
+ char *path = NULL;
+ char *fwdevice = NULL;
+ char *fwpath = NULL;
+ char *prefix;
+ struct grub_module_header *header;
- grub_register_variable_hook ("root", 0, grub_env_write_root);
+ FOR_MODULES (header)
+ if (header->type == OBJ_TYPE_PREFIX)
+ prefix = (char *) header + sizeof (struct grub_module_header);
- prefix = grub_env_get ("prefix");
+ grub_register_variable_hook ("root", 0, grub_env_write_root);
if (prefix)
{
- char *dev;
+ char *pptr = NULL;
+ if (prefix[0] == '(')
+ {
+ pptr = grub_strrchr (prefix, ')');
+ if (pptr)
+ {
+ device = grub_strndup (prefix + 1, pptr - prefix - 1);
+ pptr++;
+ }
+ }
+ if (!pptr)
+ pptr = prefix;
+ if (pptr[0])
+ path = grub_strdup (pptr);
+ }
+ if ((!device || device[0] == ',' || !device[0]) || !path)
+ grub_machine_get_bootlocation (&fwdevice, &fwpath);
+
+ if (!device && fwdevice)
+ device = fwdevice;
+ else if (fwdevice && (device[0] == ',' || !device[0]))
+ {
+ /* We have a partition, but still need to fill in the drive. */
+ char *comma, *new_device;
+
+ comma = grub_strchr (fwdevice, ',');
+ if (comma)
+ {
+ char *drive = grub_strndup (fwdevice, comma - fwdevice);
+ new_device = grub_xasprintf ("%s%s", drive, device);
+ grub_free (drive);
+ }
+ else
+ new_device = grub_xasprintf ("%s%s", fwdevice, device);
- dev = grub_file_get_device_name (prefix);
- if (dev)
+ grub_free (fwdevice);
+ grub_free (device);
+ device = new_device;
+ }
+ if (fwpath && !path)
+ path = fwpath;
+ if (device)
+ {
+ char *prefix_set;
+
+ prefix_set = grub_xasprintf ("(%s)%s", device, path ? : "");
+ if (prefix_set)
{
- grub_env_set ("root", dev);
- grub_free (dev);
+ grub_env_set ("prefix", prefix_set);
+ grub_free (prefix_set);
}
+ grub_env_set ("root", device);
}
+
+ grub_free (device);
+ grub_free (path);
+ grub_print_error ();
}
/* Load the normal mode module and execute the normal mode if possible. */
/* Load the module. */
grub_dl_load ("normal");
- /* Something went wrong. Print errors here to let user know why we're entering rescue mode. */
+ /* Print errors if any. */
grub_print_error ();
grub_errno = 0;
/* It is better to set the root device as soon as possible,
for convenience. */
- grub_machine_set_prefix ();
- grub_set_root_dev ();
+ grub_set_prefix_and_root ();
grub_env_export ("root");
grub_env_export ("prefix");
--- /dev/null
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 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/kernel.h>
+#include <grub/misc.h>
+#include <grub/env.h>
+#include <grub/time.h>
+#include <grub/types.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/time.h>
+#include <grub/machine/kernel.h>
+#include <grub/machine/memory.h>
+#include <grub/arc/console.h>
+#include <grub/cpu/memory.h>
+#include <grub/cpu/time.h>
+#include <grub/memory.h>
+#include <grub/term.h>
+#include <grub/arc/arc.h>
+#include <grub/offsets.h>
+
+const char *type_names[] = {
+#ifdef GRUB_CPU_WORDS_BIGENDIAN
+ NULL,
+#endif
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ "eisa", "tc", "scsi", "dti", "multi", "disk", "tape", "cdrom", "worm",
+ "serial", "net", "video", "par", "point", "key", "audio", "other",
+ "rdisk", "fdisk", "tape", "modem", "monitor", "print", "pointer",
+ "keyboard", "term", "other", "line", "network", NULL
+};
+
+static int
+iterate_rec (const char *prefix, const struct grub_arc_component *parent,
+ int (*hook) (const char *name,
+ const struct grub_arc_component *comp),
+ int alt_names)
+{
+ const struct grub_arc_component *comp;
+ FOR_ARC_CHILDREN(comp, parent)
+ {
+ char *name;
+ const char *cname = NULL;
+ if (comp->type < ARRAY_SIZE (type_names))
+ cname = type_names[comp->type];
+ if (!cname)
+ cname = "unknown";
+ if (alt_names)
+ name = grub_xasprintf ("%s/%s%lu", prefix, cname, comp->key);
+ else
+ name = grub_xasprintf ("%s%s(%lu)", prefix, cname, comp->key);
+ if (!name)
+ return 1;
+ if (hook (name, comp))
+ {
+ grub_free (name);
+ return 1;
+ }
+ if (iterate_rec ((parent ? name : prefix), comp, hook, alt_names))
+ {
+ grub_free (name);
+ return 1;
+ }
+ grub_free (name);
+ }
+ return 0;
+}
+
+int
+grub_arc_iterate_devs (int (*hook) (const char *name,
+ const struct grub_arc_component *comp),
+ int alt_names)
+{
+ return iterate_rec ((alt_names ? "arc" : ""), NULL, hook, alt_names);
+}
+
+grub_err_t
+grub_machine_mmap_iterate (grub_memory_hook_t hook)
+{
+ struct grub_arc_memory_descriptor *cur = NULL;
+ while (1)
+ {
+ grub_memory_type_t type;
+ cur = GRUB_ARC_FIRMWARE_VECTOR->getmemorydescriptor (cur);
+ if (!cur)
+ return GRUB_ERR_NONE;
+ switch (cur->type)
+ {
+ case GRUB_ARC_MEMORY_EXCEPTION_BLOCK:
+ case GRUB_ARC_MEMORY_SYSTEM_PARAMETER_BLOCK:
+ case GRUB_ARC_MEMORY_FW_PERMANENT:
+ default:
+ type = GRUB_MEMORY_RESERVED;
+ break;
+
+ case GRUB_ARC_MEMORY_FW_TEMPORARY:
+ case GRUB_ARC_MEMORY_FREE:
+ case GRUB_ARC_MEMORY_LOADED:
+ case GRUB_ARC_MEMORY_FREE_CONTIGUOUS:
+ type = GRUB_MEMORY_AVAILABLE;
+ break;
+ case GRUB_ARC_MEMORY_BADRAM:
+ type = GRUB_MEMORY_BADRAM;
+ break;
+ }
+ if (hook (((grub_uint64_t) cur->start_page) << 12,
+ ((grub_uint64_t) cur->num_pages) << 12, type))
+ return GRUB_ERR_NONE;
+ }
+}
+
+extern grub_uint32_t grub_total_modules_size;
+grub_addr_t grub_modbase;
+
+void
+grub_machine_init (void)
+{
+ struct grub_arc_memory_descriptor *cur = NULL;
+
+ grub_modbase = GRUB_KERNEL_MIPS_ARC_LINK_ADDR - grub_total_modules_size;
+ grub_console_init_early ();
+
+ /* FIXME: measure this. */
+ grub_arch_cpuclock = 64000000;
+ grub_install_get_time_ms (grub_rtc_get_time_ms);
+
+ while (1)
+ {
+ grub_uint64_t start, end;
+ cur = GRUB_ARC_FIRMWARE_VECTOR->getmemorydescriptor (cur);
+ if (!cur)
+ break;
+ if (cur->type != GRUB_ARC_MEMORY_FREE
+ && cur->type != GRUB_ARC_MEMORY_LOADED
+ && cur->type != GRUB_ARC_MEMORY_FREE_CONTIGUOUS)
+ continue;
+ start = ((grub_uint64_t) cur->start_page) << 12;
+ end = ((grub_uint64_t) cur->num_pages) << 12;
+ end += start;
+ if ((grub_uint64_t) end > ((GRUB_KERNEL_MIPS_ARC_LINK_ADDR
+ - grub_total_modules_size) & 0x1fffffff))
+ end = ((GRUB_KERNEL_MIPS_ARC_LINK_ADDR - grub_total_modules_size)
+ & 0x1fffffff);
+ if (end > start)
+ grub_mm_init_region ((void *) (grub_addr_t) (start | 0x80000000),
+ end - start);
+ }
+
+ grub_console_init_lately ();
+
+ grub_arcdisk_init ();
+}
+
+void
+grub_machine_fini (void)
+{
+}
+
+void
+grub_halt (void)
+{
+ GRUB_ARC_FIRMWARE_VECTOR->powerdown ();
+
+ grub_millisleep (1500);
+
+ grub_printf ("Shutdown failed\n");
+ grub_refresh ();
+ while (1);
+}
+
+void
+grub_exit (void)
+{
+ GRUB_ARC_FIRMWARE_VECTOR->exit ();
+
+ grub_millisleep (1500);
+
+ grub_printf ("Exit failed\n");
+ grub_refresh ();
+ while (1);
+}
+
FUNCTION (grub_arch_sync_caches)
#include "cache_flush.S"
j $ra
+
+FUNCTION (grub_arch_sync_dma_caches)
+ move $t2, $a0
+ addu $t3, $a0, $a1
+ srl $t2, $t2, 5
+ sll $t2, $t2, 5
+ addu $t3, $t3, 0x1f
+ srl $t3, $t3, 5
+ sll $t3, $t3, 5
+ move $t0, $t2
+ subu $t1, $t3, $t2
+1:
+ cache 1, 0($t0)
+ addiu $t1, $t1, 0xffff
+ bne $t1, $zero, 1b
+ addiu $t0, $t0, 0x1
+ sync
+ move $t0, $t2
+ subu $t1, $t3, $t2
+2:
+ cache 0, 0($t0)
+ addiu $t1, $t1, 0xffff
+ bne $t1, $zero, 2b
+ addiu $t0, $t0, 0x1
+ sync
+ move $t0, $t2
+ subu $t1, $t3, $t2
+2:
+ cache 23, 0($t0)
+ addiu $t1, $t1, 0xffff
+ bne $t1, $zero, 2b
+ addiu $t0, $t0, 0x1
+ sync
+
+ jr $ra
\ No newline at end of file
subu $t1, $t3, $t2
1:
cache 1, 0($t0)
- addiu $t1, $t1, 0xffff
+ /* All four ways. */
+#ifdef GRUB_MACHINE_MIPS_LOONGSON
+ cache 1, 1($t0)
+ cache 1, 2($t0)
+ cache 1, 3($t0)
+#endif
+
+ addiu $t1, $t1, -0x4
bne $t1, $zero, 1b
- addiu $t0, $t0, 0x1
+ addiu $t0, $t0, 0x4
sync
move $t0, $t2
subu $t1, $t3, $t2
2:
cache 0, 0($t0)
- addiu $t1, $t1, 0xffff
+ addiu $t1, $t1, -0x4
bne $t1, $zero, 2b
- addiu $t0, $t0, 0x1
+ addiu $t0, $t0, 0x4
sync
Elf_Ehdr *e = ehdr;
/* Check the magic numbers. */
-#ifdef WORDS_BIGENDIAN
+#ifdef GRUB_CPU_WORDS_BIGENDIAN
if (e->e_ident[EI_CLASS] != ELFCLASS32
|| e->e_ident[EI_DATA] != ELFDATA2MSB
|| e->e_machine != EM_MIPS)
rel < max;
rel++)
{
- Elf_Word *addr;
+ grub_uint8_t *addr;
Elf_Sym *sym;
if (seg->size < rel->r_offset)
return grub_error (GRUB_ERR_BAD_MODULE,
"reloc offset is out of the segment");
- addr = (Elf_Word *) ((char *) seg->addr + rel->r_offset);
+ addr = (grub_uint8_t *) ((char *) seg->addr + rel->r_offset);
sym = (Elf_Sym *) ((char *) mod->symtab
+ entsize * ELF_R_SYM (rel->r_info));
if (sym->st_value == (grub_addr_t) &__gnu_local_gp_dummy)
{
grub_uint32_t value;
Elf_Rel *rel2;
-
+
+#ifdef GRUB_CPU_WORDS_BIGENDIAN
+ addr += 2;
+#endif
+
/* Handle partner lo16 relocation. Lower part is
treated as signed. Hence add 0x8000 to compensate.
*/
&& ELF_R_TYPE (rel2->r_info) == R_MIPS_LO16)
{
value += *(grub_int16_t *)
- ((char *) seg->addr + rel2->r_offset);
+ ((char *) seg->addr + rel2->r_offset
+#ifdef GRUB_CPU_WORDS_BIGENDIAN
+ + 2
+#endif
+ );
break;
}
*(grub_uint16_t *) addr = (value >> 16) & 0xffff;
}
break;
case R_MIPS_LO16:
+#ifdef GRUB_CPU_WORDS_BIGENDIAN
+ addr += 2;
+#endif
*(grub_uint16_t *) addr += (sym->st_value) & 0xffff;
break;
case R_MIPS_32:
case R_MIPS_GOT16:
case R_MIPS_CALL16:
/* FIXME: reuse*/
+#ifdef GRUB_CPU_WORDS_BIGENDIAN
+ addr += 2;
+#endif
*gpptr = sym->st_value + *(grub_uint16_t *) addr;
*(grub_uint16_t *) addr
= sizeof (grub_uint32_t) * (gpptr - gp);
gpptr++;
break;
+ case R_MIPS_JALR:
+ break;
default:
{
grub_free (gp);
void
grub_arch_dl_init_linker (void)
{
- grub_dl_register_symbol ("__gnu_local_gp", &__gnu_local_gp_dummy, 0);
+ grub_dl_register_symbol ("__gnu_local_gp", &__gnu_local_gp_dummy, 0, 0);
}
#include <grub/kernel.h>
#include <grub/env.h>
+#include <grub/cpu/time.h>
+#include <grub/cpu/mips.h>
-void
-grub_machine_set_prefix (void)
+/* FIXME: use interrupt to count high. */
+grub_uint64_t
+grub_get_rtc (void)
{
- grub_env_set ("prefix", grub_prefix);
-}
+ static grub_uint32_t high = 0;
+ static grub_uint32_t last = 0;
+ grub_uint32_t low;
-extern char _end[];
+ asm volatile ("mfc0 %0, " GRUB_CPU_MIPS_COP0_TIMER_COUNT : "=r" (low));
+ if (low < last)
+ high++;
+ last = low;
-grub_addr_t
-grub_arch_modules_addr (void)
+ return (((grub_uint64_t) high) << 32) | low;
+}
+
+void
+grub_machine_get_bootlocation (char **device __attribute__ ((unused)),
+ char **path __attribute__ ((unused)))
{
- return (grub_addr_t) _end;
}
--- /dev/null
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 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/kernel.h>
+#include <grub/misc.h>
+#include <grub/env.h>
+#include <grub/time.h>
+#include <grub/types.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/time.h>
+#include <grub/machine/kernel.h>
+#include <grub/machine/memory.h>
+#include <grub/memory.h>
+#include <grub/mips/loongson.h>
+#include <grub/cs5536.h>
+#include <grub/term.h>
+#include <grub/cpu/memory.h>
+
+extern void grub_video_sm712_init (void);
+extern void grub_video_sis315pro_init (void);
+extern void grub_video_radeon_fuloong2e_init (void);
+extern void grub_video_init (void);
+extern void grub_bitmap_init (void);
+extern void grub_font_init (void);
+extern void grub_gfxterm_init (void);
+extern void grub_at_keyboard_init (void);
+extern void grub_serial_init (void);
+extern void grub_terminfo_init (void);
+extern void grub_keylayouts_init (void);
+extern void grub_boot_init (void);
+
+grub_err_t
+grub_machine_mmap_iterate (grub_memory_hook_t hook)
+{
+ hook (GRUB_ARCH_LOWMEMPSTART, grub_arch_memsize << 20,
+ GRUB_MEMORY_AVAILABLE);
+ hook (GRUB_ARCH_HIGHMEMPSTART, grub_arch_highmemsize << 20,
+ GRUB_MEMORY_AVAILABLE);
+ return GRUB_ERR_NONE;
+}
+
+static void
+init_pci (void)
+{
+ auto int NESTED_FUNC_ATTR set_card (grub_pci_device_t dev, grub_pci_id_t pciid);
+ int NESTED_FUNC_ATTR set_card (grub_pci_device_t dev, grub_pci_id_t pciid)
+ {
+ grub_pci_address_t addr;
+ /* FIXME: autoscan for BARs and devices. */
+ switch (pciid)
+ {
+ case GRUB_LOONGSON_OHCI_PCIID:
+ addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0);
+ grub_pci_write (addr, 0x5025000);
+ addr = grub_pci_make_address (dev, GRUB_PCI_REG_COMMAND);
+ grub_pci_write_word (addr, GRUB_PCI_COMMAND_SERR_ENABLE
+ | GRUB_PCI_COMMAND_PARITY_ERROR
+ | GRUB_PCI_COMMAND_BUS_MASTER
+ | GRUB_PCI_COMMAND_MEM_ENABLED);
+
+ addr = grub_pci_make_address (dev, GRUB_PCI_REG_STATUS);
+ grub_pci_write_word (addr, 0x0200 | GRUB_PCI_STATUS_CAPABILITIES);
+ break;
+ case GRUB_LOONGSON_EHCI_PCIID:
+ addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0);
+ grub_pci_write (addr, 0x5026000);
+ addr = grub_pci_make_address (dev, GRUB_PCI_REG_COMMAND);
+ grub_pci_write_word (addr, GRUB_PCI_COMMAND_SERR_ENABLE
+ | GRUB_PCI_COMMAND_PARITY_ERROR
+ | GRUB_PCI_COMMAND_BUS_MASTER
+ | GRUB_PCI_COMMAND_MEM_ENABLED);
+
+ addr = grub_pci_make_address (dev, GRUB_PCI_REG_STATUS);
+ grub_pci_write_word (addr, (1 << GRUB_PCI_STATUS_DEVSEL_TIMING_SHIFT)
+ | GRUB_PCI_STATUS_CAPABILITIES);
+ break;
+ }
+ return 0;
+ }
+
+ *((volatile grub_uint32_t *) GRUB_CPU_LOONGSON_PCI_HIT1_SEL_LO) = 0x8000000c;
+ *((volatile grub_uint32_t *) GRUB_CPU_LOONGSON_PCI_HIT1_SEL_HI) = 0xffffffff;
+
+ /* Setup PCI controller. */
+ *((volatile grub_uint16_t *) (GRUB_MACHINE_PCI_CONTROLLER_HEADER
+ + GRUB_PCI_REG_COMMAND))
+ = GRUB_PCI_COMMAND_PARITY_ERROR | GRUB_PCI_COMMAND_BUS_MASTER
+ | GRUB_PCI_COMMAND_MEM_ENABLED;
+ *((volatile grub_uint16_t *) (GRUB_MACHINE_PCI_CONTROLLER_HEADER
+ + GRUB_PCI_REG_STATUS))
+ = (1 << GRUB_PCI_STATUS_DEVSEL_TIMING_SHIFT)
+ | GRUB_PCI_STATUS_FAST_B2B_CAPABLE | GRUB_PCI_STATUS_66MHZ_CAPABLE
+ | GRUB_PCI_STATUS_CAPABILITIES;
+
+ *((volatile grub_uint32_t *) (GRUB_MACHINE_PCI_CONTROLLER_HEADER
+ + GRUB_PCI_REG_CACHELINE)) = 0xff;
+ *((volatile grub_uint32_t *) (GRUB_MACHINE_PCI_CONTROLLER_HEADER
+ + GRUB_PCI_REG_ADDRESS_REG0))
+ = 0x80000000 | GRUB_PCI_ADDR_MEM_TYPE_64 | GRUB_PCI_ADDR_MEM_PREFETCH;
+ *((volatile grub_uint32_t *) (GRUB_MACHINE_PCI_CONTROLLER_HEADER
+ + GRUB_PCI_REG_ADDRESS_REG1)) = 0;
+
+ grub_pci_iterate (set_card);
+}
+
+void
+grub_machine_init (void)
+{
+ grub_addr_t modend;
+ grub_uint32_t prid;
+
+ asm volatile ("mfc0 %0, " GRUB_CPU_LOONGSON_COP0_PRID : "=r" (prid));
+
+ switch (prid)
+ {
+ /* Loongson 2E. */
+ case 0x6302:
+ grub_arch_machine = GRUB_ARCH_MACHINE_FULOONG2E;
+ break;
+ /* Loongson 2F. */
+ case 0x6303:
+ if (grub_arch_machine != GRUB_ARCH_MACHINE_FULOONG2F
+ && grub_arch_machine != GRUB_ARCH_MACHINE_YEELOONG)
+ grub_arch_machine = GRUB_ARCH_MACHINE_YEELOONG;
+ break;
+ }
+
+ /* FIXME: measure this. */
+ if (grub_arch_busclock == 0)
+ {
+ grub_arch_busclock = 66000000;
+ grub_arch_cpuclock = 797000000;
+ }
+
+ grub_install_get_time_ms (grub_rtc_get_time_ms);
+
+ if (grub_arch_memsize == 0)
+ {
+ grub_port_t smbbase;
+ grub_err_t err;
+ grub_pci_device_t dev;
+ struct grub_smbus_spd spd;
+ unsigned totalmem;
+ int i;
+
+ if (!grub_cs5536_find (&dev))
+ grub_fatal ("No CS5536 found\n");
+
+ err = grub_cs5536_init_smbus (dev, 0x7ff, &smbbase);
+ if (err)
+ grub_fatal ("Couldn't init SMBus: %s\n", grub_errmsg);
+
+ /* Yeeloong and Fuloong have only one memory slot. */
+ err = grub_cs5536_read_spd (smbbase, GRUB_SMB_RAM_START_ADDR, &spd);
+ if (err)
+ grub_fatal ("Couldn't read SPD: %s\n", grub_errmsg);
+ for (i = 5; i < 13; i++)
+ if (spd.ddr2.rank_capacity & (1 << (i & 7)))
+ break;
+ /* Something is wrong. */
+ if (i == 13)
+ totalmem = 256;
+ else
+ totalmem = ((spd.ddr2.num_of_ranks
+ & GRUB_SMBUS_SPD_MEMORY_NUM_OF_RANKS_MASK) + 1) << (i + 2);
+
+ if (totalmem >= 256)
+ {
+ grub_arch_memsize = 256;
+ grub_arch_highmemsize = totalmem - 256;
+ }
+ else
+ {
+ grub_arch_memsize = totalmem;
+ grub_arch_highmemsize = 0;
+ }
+
+ grub_cs5536_init_geode (dev);
+
+ init_pci ();
+ }
+
+ modend = grub_modules_get_end ();
+ grub_mm_init_region ((void *) modend, (grub_arch_memsize << 20)
+ - (modend - GRUB_ARCH_LOWMEMVSTART));
+ /* FIXME: use upper memory as well. */
+
+ /* Initialize output terminal (can't be done earlier, as gfxterm
+ relies on a working heap. */
+ grub_video_init ();
+ grub_video_sm712_init ();
+ grub_video_sis315pro_init ();
+ grub_video_radeon_fuloong2e_init ();
+ grub_bitmap_init ();
+ grub_font_init ();
+ grub_gfxterm_init ();
+
+ grub_keylayouts_init ();
+ if (grub_arch_machine == GRUB_ARCH_MACHINE_YEELOONG)
+ grub_at_keyboard_init ();
+
+ grub_terminfo_init ();
+ grub_serial_init ();
+
+ grub_boot_init ();
+}
+
+void
+grub_machine_fini (void)
+{
+}
+
+void
+grub_halt (void)
+{
+ switch (grub_arch_machine)
+ {
+ case GRUB_ARCH_MACHINE_FULOONG2E:
+ break;
+ case GRUB_ARCH_MACHINE_FULOONG2F:
+ {
+ grub_pci_device_t dev;
+ grub_port_t p;
+ if (grub_cs5536_find (&dev))
+ {
+ p = (grub_cs5536_read_msr (dev, GRUB_CS5536_MSR_GPIO_BAR)
+ & GRUB_CS5536_LBAR_ADDR_MASK) + GRUB_MACHINE_PCI_IO_BASE;
+ grub_outl ((1 << 13), p + 4);
+ grub_outl ((1 << 29), p);
+ grub_millisleep (5000);
+ }
+ }
+ break;
+ case GRUB_ARCH_MACHINE_YEELOONG:
+ grub_outb (grub_inb (GRUB_CPU_LOONGSON_GPIOCFG)
+ & ~GRUB_CPU_YEELOONG_SHUTDOWN_GPIO, GRUB_CPU_LOONGSON_GPIOCFG);
+ grub_millisleep (1500);
+ break;
+ }
+
+ grub_printf ("Shutdown failed\n");
+ grub_refresh ();
+ while (1);
+}
+
+void
+grub_exit (void)
+{
+ grub_halt ();
+}
+
+extern char _end[];
+grub_addr_t grub_modbase = (grub_addr_t) _end;
+
+++ /dev/null
-#include <grub/kernel.h>
-#include <grub/misc.h>
-#include <grub/env.h>
-#include <grub/time.h>
-#include <grub/types.h>
-#include <grub/misc.h>
-#include <grub/mm.h>
-#include <grub/time.h>
-#include <grub/machine/kernel.h>
-#include <grub/machine/memory.h>
-#include <grub/cpu/kernel.h>
-
-#define RAMSIZE (*(grub_uint32_t *) ((16 << 20) - 264))
-
-grub_uint32_t
-grub_get_rtc (void)
-{
- static int calln = 0;
- return calln++;
-}
-
-void
-grub_machine_init (void)
-{
- grub_mm_init_region ((void *) GRUB_MACHINE_MEMORY_USABLE,
- RAMSIZE - (GRUB_MACHINE_MEMORY_USABLE & 0x7fffffff));
- grub_install_get_time_ms (grub_rtc_get_time_ms);
-}
-
-void
-grub_machine_fini (void)
-{
-}
-
-void
-grub_exit (void)
-{
- while (1);
-}
-
-void
-grub_halt (void)
-{
- while (1);
-}
-
-void
-grub_reboot (void)
-{
- while (1);
-}
-
-grub_err_t
-grub_machine_mmap_iterate (grub_memory_hook_t hook)
-{
- hook (0, RAMSIZE, GRUB_MEMORY_AVAILABLE);
- return GRUB_ERR_NONE;
-}
--- /dev/null
+#include <grub/kernel.h>
+#include <grub/misc.h>
+#include <grub/env.h>
+#include <grub/time.h>
+#include <grub/types.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/time.h>
+#include <grub/machine/memory.h>
+#include <grub/machine/kernel.h>
+#include <grub/cpu/memory.h>
+#include <grub/memory.h>
+
+extern void grub_serial_init (void);
+extern void grub_terminfo_init (void);
+extern void grub_at_keyboard_init (void);
+extern void grub_video_init (void);
+extern void grub_bitmap_init (void);
+extern void grub_font_init (void);
+extern void grub_gfxterm_init (void);
+extern void grub_at_keyboard_init (void);
+extern void grub_serial_init (void);
+extern void grub_terminfo_init (void);
+extern void grub_keylayouts_init (void);
+extern void grub_boot_init (void);
+extern void grub_vga_text_init (void);
+
+static inline int
+probe_mem (grub_addr_t addr)
+{
+ volatile grub_uint8_t *ptr = (grub_uint8_t *) (0xa0000000 | addr);
+ grub_uint8_t c = *ptr;
+ *ptr = 0xAA;
+ if (*ptr != 0xAA)
+ return 0;
+ *ptr = 0x55;
+ if (*ptr != 0x55)
+ return 0;
+ *ptr = c;
+ return 1;
+}
+
+void
+grub_machine_init (void)
+{
+ grub_addr_t modend;
+
+ if (grub_arch_memsize == 0)
+ {
+ int i;
+
+ for (i = 27; i >= 0; i--)
+ if (probe_mem (grub_arch_memsize | (1 << i)))
+ grub_arch_memsize |= (1 << i);
+ grub_arch_memsize++;
+ }
+
+ /* FIXME: measure this. */
+ grub_arch_cpuclock = 64000000;
+
+ modend = grub_modules_get_end ();
+ grub_mm_init_region ((void *) modend, grub_arch_memsize
+ - (modend - GRUB_ARCH_LOWMEMVSTART));
+
+ grub_install_get_time_ms (grub_rtc_get_time_ms);
+
+ grub_video_init ();
+ grub_bitmap_init ();
+ grub_font_init ();
+
+ grub_keylayouts_init ();
+ grub_at_keyboard_init ();
+
+ grub_qemu_init_cirrus ();
+ grub_vga_text_init ();
+
+ grub_terminfo_init ();
+ grub_serial_init ();
+
+ grub_boot_init ();
+
+ grub_gfxterm_init ();
+}
+
+void
+grub_machine_fini (void)
+{
+}
+
+void
+grub_exit (void)
+{
+ while (1);
+}
+
+void
+grub_halt (void)
+{
+ while (1);
+}
+
+grub_err_t
+grub_machine_mmap_iterate (grub_memory_hook_t hook)
+{
+ hook (0, grub_arch_memsize, GRUB_MEMORY_AVAILABLE);
+ return GRUB_ERR_NONE;
+}
+
+extern char _end[];
+grub_addr_t grub_modbase = (grub_addr_t) _end;
+
#include <grub/symbol.h>
#include <grub/offsets.h>
#include <grub/machine/memory.h>
+#include <grub/machine/kernel.h>
#include <grub/offsets.h>
#define BASE_ADDR 8
bal cont
nop
- . = _start + GRUB_KERNEL_MIPS_YEELOONG_TOTAL_MODULE_SIZE
-total_module_size:
+ . = _start + GRUB_KERNEL_MACHINE_TOTAL_MODULE_SIZE
+VARIABLE(grub_total_modules_size)
.long 0
- . = _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
-#ifdef GRUB_MACHINE_MIPS_YEELOONG
VARIABLE (grub_arch_busclock)
.long 0
VARIABLE (grub_arch_cpuclock)
.long 0
VARIABLE (grub_arch_highmemsize)
.long 0
+#ifdef GRUB_MACHINE_MIPS_LOONGSON
+VARIABLE (grub_arch_machine)
+ .long GRUB_ARCH_MACHINE_FULOONG2F
#endif
cont:
/* Save our base. */
move $s0, $ra
-#ifdef GRUB_MACHINE_MIPS_YEELOONG
+#ifdef GRUB_MACHINE_MIPS_QEMU_MIPS
+ lui $t1, %hi(grub_arch_busclock)
+ addiu $t1, %lo(grub_arch_busclock)
+ sw $s4, 8($t1)
+#endif
+
+#ifdef GRUB_MACHINE_MIPS_LOONGSON
lui $t1, %hi(grub_arch_busclock)
addiu $t1, %lo(grub_arch_busclock)
sw $s2, 0($t1)
sw $s3, 4($t1)
sw $s4, 8($t1)
sw $s5, 12($t1)
+ sw $s7, 16($t1)
#endif
/* Move the modules out of BSS. */
+#ifndef GRUB_MACHINE_ARC
lui $t2, %hi(__bss_start)
addiu $t2, %lo(__bss_start)
b modulesmovcont
addiu $t3, $t3, -1
modulesmovdone:
+#endif
/* Clean BSS. */
+++ /dev/null
-/*
- * GRUB -- GRand Unified Bootloader
- * Copyright (C) 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/kernel.h>
-#include <grub/misc.h>
-#include <grub/env.h>
-#include <grub/time.h>
-#include <grub/types.h>
-#include <grub/misc.h>
-#include <grub/mm.h>
-#include <grub/time.h>
-#include <grub/machine/kernel.h>
-#include <grub/machine/memory.h>
-#include <grub/memory.h>
-#include <grub/mips/loongson.h>
-#include <grub/cs5536.h>
-#include <grub/term.h>
-#include <grub/machine/ec.h>
-
-extern void grub_video_sm712_init (void);
-extern void grub_video_init (void);
-extern void grub_bitmap_init (void);
-extern void grub_font_init (void);
-extern void grub_gfxterm_init (void);
-extern void grub_at_keyboard_init (void);
-extern void grub_serial_init (void);
-extern void grub_terminfo_init (void);
-extern void grub_keylayouts_init (void);
-extern void grub_boot_init (void);
-
-/* FIXME: use interrupt to count high. */
-grub_uint64_t
-grub_get_rtc (void)
-{
- static grub_uint32_t high = 0;
- static grub_uint32_t last = 0;
- grub_uint32_t low;
-
- asm volatile ("mfc0 %0, " GRUB_CPU_LOONGSON_COP0_TIMER_COUNT : "=r" (low));
- if (low < last)
- high++;
- last = low;
-
- return (((grub_uint64_t) high) << 32) | low;
-}
-
-grub_err_t
-grub_machine_mmap_iterate (grub_memory_hook_t hook)
-{
- hook (GRUB_ARCH_LOWMEMPSTART, grub_arch_memsize << 20,
- GRUB_MEMORY_AVAILABLE);
- hook (GRUB_ARCH_HIGHMEMPSTART, grub_arch_highmemsize << 20,
- GRUB_MEMORY_AVAILABLE);
- return GRUB_ERR_NONE;
-}
-
-static void
-init_pci (void)
-{
- auto int NESTED_FUNC_ATTR set_card (grub_pci_device_t dev, grub_pci_id_t pciid);
- int NESTED_FUNC_ATTR set_card (grub_pci_device_t dev, grub_pci_id_t pciid)
- {
- grub_pci_address_t addr;
- /* FIXME: autoscan for BARs and devices. */
- switch (pciid)
- {
- case GRUB_YEELOONG_OHCI_PCIID:
- addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0);
- grub_pci_write (addr, 0x5025000);
- addr = grub_pci_make_address (dev, GRUB_PCI_REG_COMMAND);
- grub_pci_write_word (addr, GRUB_PCI_COMMAND_SERR_ENABLE
- | GRUB_PCI_COMMAND_PARITY_ERROR
- | GRUB_PCI_COMMAND_BUS_MASTER
- | GRUB_PCI_COMMAND_MEM_ENABLED);
-
- addr = grub_pci_make_address (dev, GRUB_PCI_REG_STATUS);
- grub_pci_write_word (addr, 0x0200 | GRUB_PCI_STATUS_CAPABILITIES);
- break;
- case GRUB_YEELOONG_EHCI_PCIID:
- addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0);
- grub_pci_write (addr, 0x5026000);
- addr = grub_pci_make_address (dev, GRUB_PCI_REG_COMMAND);
- grub_pci_write_word (addr, GRUB_PCI_COMMAND_SERR_ENABLE
- | GRUB_PCI_COMMAND_PARITY_ERROR
- | GRUB_PCI_COMMAND_BUS_MASTER
- | GRUB_PCI_COMMAND_MEM_ENABLED);
-
- addr = grub_pci_make_address (dev, GRUB_PCI_REG_STATUS);
- grub_pci_write_word (addr, (1 << GRUB_PCI_STATUS_DEVSEL_TIMING_SHIFT)
- | GRUB_PCI_STATUS_CAPABILITIES);
- break;
- }
- return 0;
- }
-
- *((volatile grub_uint32_t *) GRUB_CPU_LOONGSON_PCI_HIT1_SEL_LO) = 0x8000000c;
- *((volatile grub_uint32_t *) GRUB_CPU_LOONGSON_PCI_HIT1_SEL_HI) = 0xffffffff;
-
- /* Setup PCI controller. */
- *((volatile grub_uint16_t *) (GRUB_MACHINE_PCI_CONTROLLER_HEADER
- + GRUB_PCI_REG_COMMAND))
- = GRUB_PCI_COMMAND_PARITY_ERROR | GRUB_PCI_COMMAND_BUS_MASTER
- | GRUB_PCI_COMMAND_MEM_ENABLED;
- *((volatile grub_uint16_t *) (GRUB_MACHINE_PCI_CONTROLLER_HEADER
- + GRUB_PCI_REG_STATUS))
- = (1 << GRUB_PCI_STATUS_DEVSEL_TIMING_SHIFT)
- | GRUB_PCI_STATUS_FAST_B2B_CAPABLE | GRUB_PCI_STATUS_66MHZ_CAPABLE
- | GRUB_PCI_STATUS_CAPABILITIES;
-
- *((volatile grub_uint32_t *) (GRUB_MACHINE_PCI_CONTROLLER_HEADER
- + GRUB_PCI_REG_CACHELINE)) = 0xff;
- *((volatile grub_uint32_t *) (GRUB_MACHINE_PCI_CONTROLLER_HEADER
- + GRUB_PCI_REG_ADDRESS_REG0))
- = 0x80000000 | GRUB_PCI_ADDR_MEM_TYPE_64 | GRUB_PCI_ADDR_MEM_PREFETCH;
- *((volatile grub_uint32_t *) (GRUB_MACHINE_PCI_CONTROLLER_HEADER
- + GRUB_PCI_REG_ADDRESS_REG1)) = 0;
-
- grub_pci_iterate (set_card);
-}
-
-void
-grub_machine_init (void)
-{
- grub_addr_t modend;
-
- /* FIXME: measure this. */
- if (grub_arch_busclock == 0)
- {
- grub_arch_busclock = 66000000;
- grub_arch_cpuclock = 797000000;
- }
-
- grub_install_get_time_ms (grub_rtc_get_time_ms);
-
- if (grub_arch_memsize == 0)
- {
- grub_port_t smbbase;
- grub_err_t err;
- grub_pci_device_t dev;
- struct grub_smbus_spd spd;
- unsigned totalmem;
- int i;
-
- if (!grub_cs5536_find (&dev))
- grub_fatal ("No CS5536 found\n");
-
- err = grub_cs5536_init_smbus (dev, 0x7ff, &smbbase);
- if (err)
- grub_fatal ("Couldn't init SMBus: %s\n", grub_errmsg);
-
- /* Yeeloong has only one memory slot. */
- err = grub_cs5536_read_spd (smbbase, GRUB_SMB_RAM_START_ADDR, &spd);
- if (err)
- grub_fatal ("Couldn't read SPD: %s\n", grub_errmsg);
- for (i = 5; i < 13; i++)
- if (spd.ddr2.rank_capacity & (1 << (i & 7)))
- break;
- /* Something is wrong. */
- if (i == 13)
- totalmem = 256;
- else
- totalmem = ((spd.ddr2.num_of_ranks
- & GRUB_SMBUS_SPD_MEMORY_NUM_OF_RANKS_MASK) + 1) << (i + 2);
-
- if (totalmem >= 256)
- {
- grub_arch_memsize = 256;
- grub_arch_highmemsize = totalmem - 256;
- }
- else
- {
- grub_arch_memsize = (totalmem >> 20);
- grub_arch_highmemsize = 0;
- }
-
- grub_cs5536_init_geode (dev);
-
- init_pci ();
- }
-
- modend = grub_modules_get_end ();
- grub_mm_init_region ((void *) modend, (grub_arch_memsize << 20)
- - (modend - GRUB_ARCH_LOWMEMVSTART));
- /* FIXME: use upper memory as well. */
-
- /* Initialize output terminal (can't be done earlier, as gfxterm
- relies on a working heap. */
- grub_video_init ();
- grub_video_sm712_init ();
- grub_bitmap_init ();
- grub_font_init ();
- grub_gfxterm_init ();
-
- grub_keylayouts_init ();
- grub_at_keyboard_init ();
-
- grub_terminfo_init ();
- grub_serial_init ();
-
- grub_boot_init ();
-}
-
-void
-grub_machine_fini (void)
-{
-}
-
-void
-grub_halt (void)
-{
- grub_outb (grub_inb (GRUB_CPU_LOONGSON_GPIOCFG)
- & ~GRUB_CPU_LOONGSON_SHUTDOWN_GPIO, GRUB_CPU_LOONGSON_GPIOCFG);
-
- grub_millisleep (1500);
-
- grub_printf ("Shutdown failed\n");
- grub_refresh ();
- while (1);
-}
-
-void
-grub_exit (void)
-{
- grub_halt ();
-}
-
-void
-grub_reboot (void)
-{
- grub_write_ec (GRUB_MACHINE_EC_COMMAND_REBOOT);
-
- grub_millisleep (1500);
-
- grub_printf ("Reboot failed\n");
- grub_refresh ();
- while (1);
-}
-
buf[PREALLOC_SIZE - 2] = '.';
buf[PREALLOC_SIZE - 1] = '.';
buf[PREALLOC_SIZE] = 0;
+ curbuf = buf;
}
else
s = grub_vsnprintf_real (curbuf, s, fmt, ap2);
/* Divide N by D, return the quotient, and store the remainder in *R. */
grub_uint64_t
-grub_divmod64 (grub_uint64_t n, grub_uint32_t d, grub_uint32_t *r)
+grub_divmod64 (grub_uint64_t n, grub_uint64_t d, grub_uint64_t *r)
{
/* This algorithm is typically implemented by hardware. The idea
is to get the highest bit in N, 64 times, by keeping
- upper(N * 2^i) = upper((Q * 10 + M) * 2^i), where upper
+ upper(N * 2^i) = (Q * D + M), where upper
represents the high 64 bits in 128-bits space. */
unsigned bits = 64;
- unsigned long long q = 0;
- unsigned m = 0;
+ grub_uint64_t q = 0;
+ grub_uint64_t m = 0;
/* Skip the slow computation if 32-bit arithmetic is possible. */
- if (n < 0xffffffff)
+ if (n < 0xffffffff && d < 0xffffffff)
{
if (r)
- *r = ((grub_uint32_t) n) % d;
+ *r = ((grub_uint32_t) n) % (grub_uint32_t) d;
- return ((grub_uint32_t) n) / d;
+ return ((grub_uint32_t) n) / (grub_uint32_t) d;
}
while (bits--)
/* BASE == 10 */
do
{
- unsigned m;
+ grub_uint64_t m;
n = grub_divmod64 (n, 10, &m);
*p++ = m + '0';
count++;
goto again;
+#if 0
case 1:
/* Unload unneeded modules. */
grub_dl_unload_unneeded ();
count++;
goto again;
+#endif
default:
break;
void *ptr;
if (grub_mm_debug)
- grub_printf ("%s:%d: malloc (0x%zx) = ", file, line, size);
+ grub_printf ("%s:%d: malloc (0x%" PRIxGRUB_SIZE ") = ", file, line, size);
ptr = grub_malloc (size);
if (grub_mm_debug)
grub_printf ("%p\n", ptr);
void *ptr;
if (grub_mm_debug)
- grub_printf ("%s:%d: zalloc (0x%zx) = ", file, line, size);
+ grub_printf ("%s:%d: zalloc (0x%" PRIxGRUB_SIZE ") = ", file, line, size);
ptr = grub_zalloc (size);
if (grub_mm_debug)
grub_printf ("%p\n", ptr);
grub_debug_realloc (const char *file, int line, void *ptr, grub_size_t size)
{
if (grub_mm_debug)
- grub_printf ("%s:%d: realloc (%p, 0x%zx) = ", file, line, ptr, size);
+ grub_printf ("%s:%d: realloc (%p, 0x%" PRIxGRUB_SIZE ") = ", file, line, ptr, size);
ptr = grub_realloc (ptr, size);
if (grub_mm_debug)
grub_printf ("%p\n", ptr);
void *ptr;
if (grub_mm_debug)
- grub_printf ("%s:%d: memalign (0x%zx, 0x%zx) = ",
- file, line, align, size);
+ grub_printf ("%s:%d: memalign (0x%" PRIxGRUB_SIZE ", 0x%" PRIxGRUB_SIZE
+ ") = ", file, line, align, size);
ptr = grub_memalign (align, size);
if (grub_mm_debug)
grub_printf ("%p\n", ptr);
.globl start, _start
start:
_start:
- b codestart
-
- . = _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
-
-codestart:
li 2, 0
li 13, 0
.word 0
VARIABLE(grub_compressed_size)
.word 0
-VARIABLE(grub_prefix)
- /* to be filled by grub-mkimage */
-
- /*
- * Leave some breathing room for the prefix.
- */
-
- . = EXT_C(_start) + GRUB_KERNEL_MACHINE_PREFIX_END
codestart:
/* Copy the modules past the end of the kernel image.
+++ /dev/null
-/* init.c -- Initialize GRUB on SPARC64. */
-/*
- * GRUB -- GRand Unified Bootloader
- * Copyright (C) 2009 Free Software Foundation, Inc.
- *
- * GRUB is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * GRUB is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <grub/kernel.h>
-#include <grub/mm.h>
-#include <grub/env.h>
-#include <grub/err.h>
-#include <grub/misc.h>
-#include <grub/time.h>
-#include <grub/machine/boot.h>
-#include <grub/ieee1275/console.h>
-#include <grub/machine/kernel.h>
-#include <grub/machine/time.h>
-#include <grub/ieee1275/ofdisk.h>
-#include <grub/ieee1275/ieee1275.h>
-
-grub_addr_t grub_ieee1275_original_stack;
-
-void
-grub_exit (void)
-{
- grub_ieee1275_exit ();
-}
-
-static grub_uint64_t
-ieee1275_get_time_ms (void)
-{
- grub_uint32_t msecs = 0;
-
- grub_ieee1275_milliseconds (&msecs);
-
- return msecs;
-}
-
-grub_uint32_t
-grub_get_rtc (void)
-{
- return ieee1275_get_time_ms ();
-}
-
-grub_addr_t
-grub_arch_modules_addr (void)
-{
- extern char _end[];
- return (grub_addr_t) _end;
-}
-
-void
-grub_machine_set_prefix (void)
-{
- if (grub_prefix[0] != '(')
- {
- char bootpath[IEEE1275_MAX_PATH_LEN];
- char *prefix, *path, *colon;
- grub_ssize_t actual;
-
- if (grub_ieee1275_get_property (grub_ieee1275_chosen, "bootpath",
- &bootpath, sizeof (bootpath), &actual))
- {
- /* Should never happen. */
- grub_printf ("/chosen/bootpath property missing!\n");
- grub_env_set ("prefix", "");
- return;
- }
-
- /* Transform an OF device path to a GRUB path. */
- colon = grub_strchr (bootpath, ':');
- if (colon)
- {
- char *part = colon + 1;
-
- /* Consistently provide numbered partitions to GRUB.
- OpenBOOT traditionally uses alphabetical partition
- specifiers. */
- if (part[0] >= 'a' && part[0] <= 'z')
- part[0] = '1' + (part[0] - 'a');
- }
- prefix = grub_ieee1275_encode_devname (bootpath);
-
- path = grub_xasprintf("%s%s", prefix, grub_prefix);
-
- grub_strcpy (grub_prefix, path);
-
- grub_free (path);
- grub_free (prefix);
- }
-
- grub_env_set ("prefix", grub_prefix);
-}
-
-static void
-grub_heap_init (void)
-{
- grub_mm_init_region ((void *) (grub_modules_get_end ()
- + GRUB_KERNEL_MACHINE_STACK_SIZE), 0x200000);
-}
-
-static void
-grub_parse_cmdline (void)
-{
- grub_ssize_t actual;
- char args[256];
-
- if (grub_ieee1275_get_property (grub_ieee1275_chosen, "bootargs", &args,
- sizeof args, &actual) == 0
- && actual > 1)
- {
- int i = 0;
-
- while (i < actual)
- {
- char *command = &args[i];
- char *end;
- char *val;
-
- end = grub_strchr (command, ';');
- if (end == 0)
- i = actual; /* No more commands after this one. */
- else
- {
- *end = '\0';
- i += end - command + 1;
- while (grub_isspace(args[i]))
- i++;
- }
-
- /* Process command. */
- val = grub_strchr (command, '=');
- if (val)
- {
- *val = '\0';
- grub_env_set (command, val + 1);
- }
- }
- }
-}
-
-void
-grub_machine_init (void)
-{
- grub_ieee1275_init ();
- grub_console_init_early ();
- grub_heap_init ();
- grub_console_init_lately ();
-
- grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_NO_PARTITION_0);
- grub_ofdisk_init ();
-
- grub_parse_cmdline ();
- grub_install_get_time_ms (ieee1275_get_time_ms);
-}
-
-void
-grub_machine_fini (void)
-{
- grub_ofdisk_fini ();
- grub_console_fini ();
-}
struct grub_term_input *grub_term_inputs;
void (*grub_term_poll_usb) (void) = NULL;
+void (*grub_net_poll_cards_idle) (void) = NULL;
/* Put a Unicode character. */
static void
if (grub_term_poll_usb)
grub_term_poll_usb ();
+ if (grub_net_poll_cards_idle)
+ grub_net_poll_cards_idle ();
+
FOR_ACTIVE_TERM_INPUTS(term)
{
pending_key = term->getkey (term);
--- /dev/null
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2010,2011 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __mips__
+#include <grub/pci.h>
+#endif
+#include <grub/machine/kernel.h>
+#include <grub/misc.h>
+#include <grub/vga.h>
+
+static struct {grub_uint8_t r, g, b, a; } colors[] =
+ {
+ // {R, G, B, A}
+ {0x00, 0x00, 0x00, 0xFF}, // 0 = black
+ {0x00, 0x00, 0xA8, 0xFF}, // 1 = blue
+ {0x00, 0xA8, 0x00, 0xFF}, // 2 = green
+ {0x00, 0xA8, 0xA8, 0xFF}, // 3 = cyan
+ {0xA8, 0x00, 0x00, 0xFF}, // 4 = red
+ {0xA8, 0x00, 0xA8, 0xFF}, // 5 = magenta
+ {0xA8, 0x54, 0x00, 0xFF}, // 6 = brown
+ {0xA8, 0xA8, 0xA8, 0xFF}, // 7 = light gray
+
+ {0x54, 0x54, 0x54, 0xFF}, // 8 = dark gray
+ {0x54, 0x54, 0xFE, 0xFF}, // 9 = bright blue
+ {0x54, 0xFE, 0x54, 0xFF}, // 10 = bright green
+ {0x54, 0xFE, 0xFE, 0xFF}, // 11 = bright cyan
+ {0xFE, 0x54, 0x54, 0xFF}, // 12 = bright red
+ {0xFE, 0x54, 0xFE, 0xFF}, // 13 = bright magenta
+ {0xFE, 0xFE, 0x54, 0xFF}, // 14 = yellow
+ {0xFE, 0xFE, 0xFE, 0xFF} // 15 = white
+ };
+
+#ifdef __mips__
+extern unsigned char ascii_bitmaps[];
+#else
+#include <ascii.h>
+#endif
+
+#ifdef __mips__
+#define VGA_ADDR 0xb00a0000
+#else
+#define VGA_ADDR 0xa0000
+#endif
+
+static void
+load_font (void)
+{
+ unsigned i;
+
+ grub_vga_gr_write (0 << 2, GRUB_VGA_GR_GR6);
+
+ grub_vga_sr_write (GRUB_VGA_SR_MEMORY_MODE_NORMAL, GRUB_VGA_SR_MEMORY_MODE);
+ grub_vga_sr_write (1 << GRUB_VGA_TEXT_FONT_PLANE,
+ GRUB_VGA_SR_MAP_MASK_REGISTER);
+
+ grub_vga_gr_write (0, GRUB_VGA_GR_DATA_ROTATE);
+ grub_vga_gr_write (0, GRUB_VGA_GR_MODE);
+ grub_vga_gr_write (0xff, GRUB_VGA_GR_BITMASK);
+
+ for (i = 0; i < 128; i++)
+ grub_memcpy ((void *) (VGA_ADDR + 32 * i), ascii_bitmaps + 16 * i, 16);
+}
+
+static void
+load_palette (void)
+{
+ unsigned i;
+ for (i = 0; i < 16; i++)
+ grub_vga_write_arx (i, i);
+
+ for (i = 0; i < ARRAY_SIZE (colors); i++)
+ grub_vga_palette_write (i, colors[i].r, colors[i].g, colors[i].b);
+}
+
+void
+grub_qemu_init_cirrus (void)
+{
+#ifndef __mips__
+ auto int NESTED_FUNC_ATTR find_card (grub_pci_device_t dev, grub_pci_id_t pciid);
+ int NESTED_FUNC_ATTR find_card (grub_pci_device_t dev, grub_pci_id_t pciid __attribute__ ((unused)))
+ {
+ grub_pci_address_t addr;
+ grub_uint32_t class;
+
+ addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS);
+ class = grub_pci_read (addr);
+
+ if (((class >> 16) & 0xffff) != GRUB_PCI_CLASS_SUBCLASS_VGA)
+ return 0;
+
+ /* FIXME: chooose addresses dynamically. */
+ addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0);
+ grub_pci_write (addr, 0xf0000000 | GRUB_PCI_ADDR_MEM_PREFETCH
+ | GRUB_PCI_ADDR_SPACE_MEMORY | GRUB_PCI_ADDR_MEM_TYPE_32);
+ addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG1);
+ grub_pci_write (addr, 0xf2000000
+ | GRUB_PCI_ADDR_SPACE_MEMORY | GRUB_PCI_ADDR_MEM_TYPE_32);
+
+ addr = grub_pci_make_address (dev, GRUB_PCI_REG_COMMAND);
+ grub_pci_write (addr, GRUB_PCI_COMMAND_MEM_ENABLED
+ | GRUB_PCI_COMMAND_IO_ENABLED);
+
+ return 1;
+ }
+
+ grub_pci_iterate (find_card);
+#endif
+
+ grub_outb (GRUB_VGA_IO_MISC_COLOR,
+ GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_MISC_WRITE);
+
+ load_font ();
+
+ grub_vga_gr_write (GRUB_VGA_GR_GR6_MMAP_CGA, GRUB_VGA_GR_GR6);
+ grub_vga_gr_write (GRUB_VGA_GR_MODE_ODD_EVEN, GRUB_VGA_GR_MODE);
+
+ grub_vga_sr_write (GRUB_VGA_SR_MEMORY_MODE_NORMAL, GRUB_VGA_SR_MEMORY_MODE);
+
+ grub_vga_sr_write ((1 << GRUB_VGA_TEXT_TEXT_PLANE)
+ | (1 << GRUB_VGA_TEXT_ATTR_PLANE),
+ GRUB_VGA_SR_MAP_MASK_REGISTER);
+
+ grub_vga_cr_write (15, GRUB_VGA_CR_CELL_HEIGHT);
+ grub_vga_cr_write (79, GRUB_VGA_CR_HORIZ_END);
+ grub_vga_cr_write (40, GRUB_VGA_CR_PITCH);
+
+ int vert = 25 * 16;
+ grub_vga_cr_write (vert & 0xff, GRUB_VGA_CR_VDISPLAY_END);
+ grub_vga_cr_write (((vert >> GRUB_VGA_CR_OVERFLOW_HEIGHT1_SHIFT)
+ & GRUB_VGA_CR_OVERFLOW_HEIGHT1_MASK)
+ | ((vert >> GRUB_VGA_CR_OVERFLOW_HEIGHT2_SHIFT)
+ & GRUB_VGA_CR_OVERFLOW_HEIGHT2_MASK),
+ GRUB_VGA_CR_OVERFLOW);
+
+ load_palette ();
+
+ grub_vga_write_arx (GRUB_VGA_ARX_MODE_TEXT, GRUB_VGA_ARX_MODE);
+ grub_vga_write_arx (0, GRUB_VGA_ARX_COLOR_SELECT);
+
+ grub_vga_sr_write (GRUB_VGA_SR_CLOCKING_MODE_8_DOT_CLOCK,
+ GRUB_VGA_SR_CLOCKING_MODE);
+
+ grub_vga_cr_write (14, GRUB_VGA_CR_CURSOR_START);
+ grub_vga_cr_write (15, GRUB_VGA_CR_CURSOR_END);
+
+ grub_outb (0x20, GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_ARX);
+}
addq $64, %rsp
ret
+FUNCTION(efi_wrap_7)
+ subq $96, %rsp
+ mov 96+16(%rsp), %rax
+ mov %rax, 48(%rsp)
+ mov 96+8(%rsp), %rax
+ mov %rax, 40(%rsp)
+ mov %r9, 32(%rsp)
+ mov %r8, %r9
+ mov %rcx, %r8
+ mov %rsi, %rcx
+ call *%rdi
+ addq $96, %rsp
+ ret
+
FUNCTION(efi_wrap_10)
subq $96, %rsp
mov 96+40(%rsp), %rax
. = _start + 0x6
.byte GRUB_BOOT_VERSION_MAJOR, GRUB_BOOT_VERSION_MINOR
- /*
- * This is a special data area 8 bytes from the beginning.
- */
-
- . = _start + 0x8
-
-VARIABLE(grub_prefix)
- /* to be filled by grub-mkimage */
-
- /*
- * Leave some breathing room for the prefix.
- */
-
- . = _start + 0x50
-
codestart:
movq %rcx, EXT_C(grub_efi_image_handle)(%rip)
movq %rdx, EXT_C(grub_efi_system_table)(%rip)
--- /dev/null
+/* adler32.c - adler32 check. */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2011 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/types.h>
+#include <grub/dl.h>
+#include <grub/crypto.h>
+
+/* Based on adler32() from adler32.c of zlib-1.2.5 library. */
+
+#define BASE 65521UL
+#define NMAX 5552
+
+#define DO1(buf,i) {adler += (buf)[i]; sum2 += adler;}
+#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1);
+#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2);
+#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4);
+#define DO16(buf) DO8(buf,0); DO8(buf,8);
+
+static grub_uint32_t
+update_adler32 (grub_uint32_t adler, const grub_uint8_t *buf, grub_size_t len)
+{
+ unsigned long sum2;
+ unsigned int n;
+
+ sum2 = (adler >> 16) & 0xffff;
+ adler &= 0xffff;
+
+ if (len == 1)
+ {
+ adler += buf[0];
+ if (adler >= BASE)
+ adler -= BASE;
+ sum2 += adler;
+ if (sum2 >= BASE)
+ sum2 -= BASE;
+ return adler | (sum2 << 16);
+ }
+
+ if (len < 16)
+ {
+ while (len--)
+ {
+ adler += *buf++;
+ sum2 += adler;
+ }
+ if (adler >= BASE)
+ adler -= BASE;
+ sum2 %= BASE;
+ return adler | (sum2 << 16);
+ }
+
+ while (len >= NMAX)
+ {
+ len -= NMAX;
+ n = NMAX / 16;
+ do
+ {
+ DO16 (buf);
+ buf += 16;
+ }
+ while (--n);
+ adler %= BASE;
+ sum2 %= BASE;
+ }
+
+ if (len)
+ {
+ while (len >= 16)
+ {
+ len -= 16;
+ DO16 (buf);
+ buf += 16;
+ }
+ while (len--)
+ {
+ adler += *buf++;
+ sum2 += adler;
+ }
+ adler %= BASE;
+ sum2 %= BASE;
+ }
+
+ return adler | (sum2 << 16);
+}
+
+typedef struct
+{
+ grub_uint32_t adler;
+}
+adler32_context;
+
+static void
+adler32_init (void *context)
+{
+ adler32_context *ctx = (adler32_context *) context;
+ ctx->adler = 1;
+}
+
+static void
+adler32_write (void *context, const void *inbuf, grub_size_t inlen)
+{
+ adler32_context *ctx = (adler32_context *) context;
+ if (!inbuf)
+ return;
+ ctx->adler = update_adler32 (ctx->adler, inbuf, inlen);
+}
+
+static grub_uint8_t *
+adler32_read (void *context)
+{
+ adler32_context *ctx = (adler32_context *) context;
+ return (grub_uint8_t *) &ctx->adler;
+}
+
+static void
+adler32_final (void *context __attribute__ ((unused)))
+{
+}
+
+gcry_md_spec_t _gcry_digest_spec_adler32 = {
+ "ADLER32",0 , 0, 0 , 4,
+ adler32_init, adler32_write, adler32_final, adler32_read,
+ sizeof (adler32_context),
+ .blocksize = 64
+};
+
+GRUB_MOD_INIT(adler32)
+{
+ grub_md_register (&_gcry_digest_spec_adler32);
+}
+
+GRUB_MOD_FINI(adler32)
+{
+ grub_md_unregister (&_gcry_digest_spec_adler32);
+}
--- /dev/null
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2011 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/datetime.h>
+#include <grub/dl.h>
+#include <grub/misc.h>
+#include <grub/arc/arc.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
+
+grub_err_t
+grub_get_datetime (struct grub_datetime *datetime)
+{
+ struct grub_arc_timeinfo *dt;
+ grub_memset (datetime, 0, sizeof (*datetime));
+
+ dt = GRUB_ARC_FIRMWARE_VECTOR->gettime ();
+
+ datetime->year = dt->y;
+ datetime->month = dt->m;
+ datetime->day = dt->d;
+ datetime->hour = dt->h;
+ datetime->minute = dt->min;
+ datetime->second = dt->s;
+
+ return 0;
+}
+
+grub_err_t
+grub_set_datetime (struct grub_datetime *datetime __attribute__ ((unused)))
+{
+ return grub_error (GRUB_ERR_IO, "setting time isn't supported");
+}
#include <grub/datetime.h>
#include <grub/cmos.h>
+#include <grub/dl.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
+
+#if !defined (__powerpc__) && !defined (__sparc__)
+#define grub_get_datetime_cmos grub_get_datetime
+#define grub_set_datetime_cmos grub_set_datetime
+#endif
grub_err_t
-grub_get_datetime (struct grub_datetime *datetime)
+grub_get_datetime_cmos (struct grub_datetime *datetime)
{
int is_bcd, is_12hour;
grub_uint8_t value, flag;
+ grub_err_t err;
- flag = grub_cmos_read (GRUB_CMOS_INDEX_STATUS_B);
+ err = grub_cmos_read (GRUB_CMOS_INDEX_STATUS_B, &flag);
+ if (err)
+ return err;
is_bcd = ! (flag & GRUB_CMOS_STATUS_B_BINARY);
- value = grub_cmos_read (GRUB_CMOS_INDEX_YEAR);
+ err = grub_cmos_read (GRUB_CMOS_INDEX_YEAR, &value);
+ if (err)
+ return err;
if (is_bcd)
value = grub_bcd_to_num (value);
datetime->year = value;
datetime->year += (value < 80) ? 2000 : 1900;
- value = grub_cmos_read (GRUB_CMOS_INDEX_MONTH);
+ err = grub_cmos_read (GRUB_CMOS_INDEX_MONTH, &value);
+ if (err)
+ return err;
if (is_bcd)
value = grub_bcd_to_num (value);
datetime->month = value;
- value = grub_cmos_read (GRUB_CMOS_INDEX_DAY_OF_MONTH);
+ err = grub_cmos_read (GRUB_CMOS_INDEX_DAY_OF_MONTH, &value);
+ if (err)
+ return err;
if (is_bcd)
value = grub_bcd_to_num (value);
is_12hour = ! (flag & GRUB_CMOS_STATUS_B_24HOUR);
- value = grub_cmos_read (GRUB_CMOS_INDEX_HOUR);
+ err = grub_cmos_read (GRUB_CMOS_INDEX_HOUR, &value);
+ if (err)
+ return err;
if (is_12hour)
{
is_12hour = (value & 0x80);
datetime->hour = value;
- value = grub_cmos_read (GRUB_CMOS_INDEX_MINUTE);
+ err = grub_cmos_read (GRUB_CMOS_INDEX_MINUTE, &value);
+ if (err)
+ return err;
+
if (is_bcd)
value = grub_bcd_to_num (value);
datetime->minute = value;
- value = grub_cmos_read (GRUB_CMOS_INDEX_SECOND);
+ err = grub_cmos_read (GRUB_CMOS_INDEX_SECOND, &value);
+ if (err)
+ return err;
if (is_bcd)
value = grub_bcd_to_num (value);
}
grub_err_t
-grub_set_datetime (struct grub_datetime *datetime)
+grub_set_datetime_cmos (struct grub_datetime *datetime)
{
int is_bcd, is_12hour;
grub_uint8_t value, flag;
+ grub_err_t err;
- flag = grub_cmos_read (GRUB_CMOS_INDEX_STATUS_B);
+ err = grub_cmos_read (GRUB_CMOS_INDEX_STATUS_B, &flag);
+ if (err)
+ return err;
is_bcd = ! (flag & GRUB_CMOS_STATUS_B_BINARY);
if (is_bcd)
value = grub_num_to_bcd (value);
- grub_cmos_write (GRUB_CMOS_INDEX_YEAR, value);
+ err = grub_cmos_write (GRUB_CMOS_INDEX_YEAR, value);
+ if (err)
+ return err;
value = datetime->month;
if (is_bcd)
value = grub_num_to_bcd (value);
- grub_cmos_write (GRUB_CMOS_INDEX_MONTH, value);
+ err = grub_cmos_write (GRUB_CMOS_INDEX_MONTH, value);
+ if (err)
+ return err;
value = datetime->day;
if (is_bcd)
value = grub_num_to_bcd (value);
- grub_cmos_write (GRUB_CMOS_INDEX_DAY_OF_MONTH, value);
+ err = grub_cmos_write (GRUB_CMOS_INDEX_DAY_OF_MONTH, value);
+ if (err)
+ return err;
value = datetime->hour;
if (is_12hour)
value |= 0x80;
- grub_cmos_write (GRUB_CMOS_INDEX_HOUR, value);
+ err = grub_cmos_write (GRUB_CMOS_INDEX_HOUR, value);
+ if (err)
+ return err;
value = datetime->minute;
if (is_bcd)
value = grub_num_to_bcd (value);
- grub_cmos_write (GRUB_CMOS_INDEX_MINUTE, value);
+ err = grub_cmos_write (GRUB_CMOS_INDEX_MINUTE, value);
+ if (err)
+ return err;
value = datetime->second;
if (is_bcd)
value = grub_num_to_bcd (value);
- grub_cmos_write (GRUB_CMOS_INDEX_SECOND, value);
+ err = grub_cmos_write (GRUB_CMOS_INDEX_SECOND, value);
+ if (err)
+ return err;
return 0;
}
--- /dev/null
+/* crc.c - crc function */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2008 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/types.h>
+#include <grub/lib/crc.h>
+
+static grub_uint32_t crc32c_table [256];
+
+static void
+init_crc32c_table (void)
+{
+ auto grub_uint32_t reflect (grub_uint32_t ref, int len);
+ grub_uint32_t reflect (grub_uint32_t ref, int len)
+ {
+ grub_uint32_t result = 0;
+ int i;
+
+ for (i = 1; i <= len; i++)
+ {
+ if (ref & 1)
+ result |= 1 << (len - i);
+ ref >>= 1;
+ }
+
+ return result;
+ }
+
+ grub_uint32_t polynomial = 0x1edc6f41;
+ int i, j;
+
+ for(i = 0; i < 256; i++)
+ {
+ crc32c_table[i] = reflect(i, 8) << 24;
+ for (j = 0; j < 8; j++)
+ crc32c_table[i] = (crc32c_table[i] << 1) ^
+ (crc32c_table[i] & (1 << 31) ? polynomial : 0);
+ crc32c_table[i] = reflect(crc32c_table[i], 32);
+ }
+}
+
+grub_uint32_t
+grub_getcrc32c (grub_uint32_t crc, const void *buf, int size)
+{
+ int i;
+ const grub_uint8_t *data = buf;
+
+ if (! crc32c_table[1])
+ init_crc32c_table ();
+
+ crc^= 0xffffffff;
+
+ for (i = 0; i < size; i++)
+ {
+ crc = (crc >> 8) ^ crc32c_table[(crc & 0xFF) ^ *data];
+ data++;
+ }
+
+ return crc ^ 0xffffffff;
+}
#include <grub/misc.h>
#include <grub/mm.h>
#include <grub/term.h>
+#include <grub/dl.h>
+
+#ifdef GRUB_UTIL
+#include <termios.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#endif
+
+GRUB_MOD_LICENSE ("GPLv3+");
struct grub_crypto_hmac_handle
{
gcry_err_code_t
grub_crypto_ecb_decrypt (grub_crypto_cipher_handle_t cipher,
- void *out, void *in, grub_size_t size)
+ void *out, const void *in, grub_size_t size)
{
- grub_uint8_t *inptr, *outptr, *end;
+ const grub_uint8_t *inptr;
+ grub_uint8_t *outptr, *end;
if (!cipher->cipher->decrypt)
return GPG_ERR_NOT_SUPPORTED;
if (size % cipher->cipher->blocksize != 0)
gcry_err_code_t
grub_crypto_cbc_decrypt (grub_crypto_cipher_handle_t cipher,
- void *out, void *in, grub_size_t size,
+ void *out, const void *in, grub_size_t size,
void *iv)
{
- grub_uint8_t *inptr, *outptr, *end;
+ const grub_uint8_t *inptr;
+ grub_uint8_t *outptr, *end;
grub_uint8_t ivt[cipher->cipher->blocksize];
if (!cipher->cipher->decrypt)
return GPG_ERR_NOT_SUPPORTED;
}
void
-grub_crypto_hmac_write (struct grub_crypto_hmac_handle *hnd, void *data,
+grub_crypto_hmac_write (struct grub_crypto_hmac_handle *hnd,
+ const void *data,
grub_size_t datalen)
{
hnd->md->write (hnd->ctx, data, datalen);
gcry_err_code_t
grub_crypto_hmac_buffer (const struct gcry_md_spec *md,
const void *key, grub_size_t keylen,
- void *data, grub_size_t datalen, void *out)
+ const void *data, grub_size_t datalen, void *out)
{
struct grub_crypto_hmac_handle *hnd;
return !!counter;
}
-#ifndef GRUB_MKPASSWD
int
grub_password_get (char buf[], unsigned buf_size)
{
+#ifdef GRUB_UTIL
+ FILE *in;
+ struct termios s, t;
+ int tty_changed = 0;
+ char *ptr;
+
+ /* Disable echoing. Based on glibc. */
+ in = fopen ("/dev/tty", "w+c");
+ if (in == NULL)
+ in = stdin;
+
+ if (tcgetattr (fileno (in), &t) == 0)
+ {
+ /* Save the old one. */
+ s = t;
+ /* Tricky, tricky. */
+ t.c_lflag &= ~(ECHO|ISIG);
+ tty_changed = (tcsetattr (fileno (in), TCSAFLUSH, &t) == 0);
+ }
+ else
+ tty_changed = 0;
+ fgets (buf, buf_size, stdin);
+ ptr = buf + strlen (buf) - 1;
+ while (buf <= ptr && (*ptr == '\n' || *ptr == '\r'))
+ *ptr-- = 0;
+ /* Restore the original setting. */
+ if (tty_changed)
+ (void) tcsetattr (fileno (in), TCSAFLUSH, &s);
+
+ grub_xputs ("\n");
+ grub_refresh ();
+
+ return 1;
+#else
unsigned cur_len = 0;
int key;
grub_refresh ();
return (key != '\e');
-}
#endif
+}
#include <grub/efi/api.h>
#include <grub/efi/efi.h>
#include <grub/datetime.h>
+#include <grub/dl.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
grub_err_t
grub_get_datetime (struct grub_datetime *datetime)
grub_halt (void)
{
grub_machine_fini ();
+#ifndef __ia64__
grub_acpi_halt ();
+#endif
efi_call_4 (grub_efi_system_table->runtime_services->reset_system,
GRUB_EFI_RESET_SHUTDOWN, GRUB_EFI_SUCCESS, 0, NULL);
--- /dev/null
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2011 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/efi/api.h>
+#include <grub/efi/efi.h>
+#include <grub/mm.h>
+#include <grub/misc.h>
+#include <grub/kernel.h>
+
+void
+grub_reboot (void)
+{
+ grub_machine_fini ();
+ efi_call_4 (grub_efi_system_table->runtime_services->reset_system,
+ GRUB_EFI_RESET_COLD, GRUB_EFI_SUCCESS, 0, NULL);
+ for (;;) ;
+}
--- /dev/null
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2011 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/relocator.h>
+#include <grub/cpu/relocator.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/cpu/reboot.h>
+#include <grub/i386/floppy.h>
+
+void
+grub_reboot (void)
+{
+ struct grub_relocator *relocator = NULL;
+ grub_relocator_chunk_t ch;
+ grub_err_t err;
+ void *buf;
+ struct grub_relocator16_state state;
+ grub_uint16_t segment;
+
+ relocator = grub_relocator_new ();
+ if (!relocator)
+ while (1);
+ err = grub_relocator_alloc_chunk_align (relocator, &ch, 0x1000, 0x1000,
+ grub_reboot_end - grub_reboot_start,
+ 16, GRUB_RELOCATOR_PREFERENCE_NONE);
+ if (err)
+ while (1);
+ buf = get_virtual_current_address (ch);
+ grub_memcpy (buf, grub_reboot_start, grub_reboot_end - grub_reboot_start);
+
+ segment = ((grub_addr_t) get_physical_target_address (ch)) >> 4;
+ state.gs = state.fs = state.es = state.ds = state.ss = segment;
+ state.sp = 0;
+ state.cs = segment;
+ state.ip = 0;
+
+ grub_stop_floppy ();
+
+ err = grub_relocator16_boot (relocator, state);
+
+ while (1);
+}
+
--- /dev/null
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2011 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/symbol.h>
+#include <grub/i386/reboot.h>
+
+ .p2align 4
+
+VARIABLE(grub_reboot_start)
+ .code16
+
+ /* set 0x472 to 0x0000 for cold boot (0x1234 for warm boot) */
+ movw $0x0472, %di
+ movw %ax, (%di)
+ ljmp $0xf000, $0xfff0
+
+ .code32
+VARIABLE(grub_reboot_end)
extern grub_uint16_t grub_relocator16_ss;
extern grub_uint16_t grub_relocator16_sp;
extern grub_uint32_t grub_relocator16_edx;
+extern grub_uint32_t grub_relocator16_ebx;
extern grub_uint8_t grub_relocator32_start;
extern grub_uint8_t grub_relocator32_end;
grub_relocator16_ss = state.ss;
grub_relocator16_sp = state.sp;
+ grub_relocator16_ebx = state.ebx;
grub_relocator16_edx = state.edx;
grub_memmove (get_virtual_current_address (ch), &grub_relocator16_start,
.byte 0xb8
VARIABLE(grub_relocator16_sp)
.word 0
- movw %ax, %ss
+ movzwl %ax, %esp
/* movw imm32, %edx. */
.byte 0x66, 0xba
VARIABLE(grub_relocator16_edx)
.long 0
-
+
+ /* movw imm32, %ebx. */
+ .byte 0x66, 0xbb
+VARIABLE(grub_relocator16_ebx)
+ .long 0
+
/* Cleared direction flag is of no problem with any current
payload and makes this implementation easier. */
cld
*/
#include <grub/symbol.h>
+#include <grub/dl.h>
.file "setjmp.S"
+GRUB_MOD_LICENSE ("GPLv3+")
+
.text
/*
--- /dev/null
+/* Copyright (C) 1999, 2000, 2001, 2002, 2008 Free Software Foundation, Inc.
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA.
+
+ Note that __sigsetjmp() did NOT flush the register stack. Instead,
+ we do it here since __longjmp() is usually much less frequently
+ invoked than __sigsetjmp(). The only difficulty is that __sigsetjmp()
+ didn't (and wouldn't be able to) save ar.rnat either. This is a problem
+ because if we're not careful, we could end up loading random NaT bits.
+ There are two cases:
+
+ (i) ar.bsp < ia64_rse_rnat_addr(jmpbuf.ar_bsp)
+ ar.rnat contains the desired bits---preserve ar.rnat
+ across loadrs and write to ar.bspstore
+
+ (ii) ar.bsp >= ia64_rse_rnat_addr(jmpbuf.ar_bsp)
+ The desired ar.rnat is stored in
+ ia64_rse_rnat_addr(jmpbuf.ar_bsp). Load those
+ bits into ar.rnat after setting ar.bspstore. */
+
+
+
+# define pPos p6 /* is rotate count positive? */
+# define pNeg p7 /* is rotate count negative? */
+
+
+ /* __longjmp(__jmp_buf buf, int val) */
+
+ .text
+ .global longjmp
+ .proc longjmp
+longjmp:
+ alloc r8=ar.pfs,2,1,0,0
+ mov r27=ar.rsc
+ add r2=0x98,in0 // r2 <- &jmpbuf.orig_jmp_buf_addr
+ ;;
+ ld8 r8=[r2],-16 // r8 <- orig_jmp_buf_addr
+ mov r10=ar.bsp
+ and r11=~0x3,r27 // clear ar.rsc.mode
+ ;;
+ flushrs // flush dirty regs to backing store (must be first in insn grp)
+ ld8 r23=[r2],8 // r23 <- jmpbuf.ar_bsp
+ sub r8=r8,in0 // r8 <- &orig_jmpbuf - &jmpbuf
+ ;;
+ ld8 r25=[r2] // r25 <- jmpbuf.ar_unat
+ extr.u r8=r8,3,6 // r8 <- (&orig_jmpbuf - &jmpbuf)/8 & 0x3f
+ ;;
+ cmp.lt pNeg,pPos=r8,r0
+ mov r2=in0
+ ;;
+(pPos) mov r16=r8
+(pNeg) add r16=64,r8
+(pPos) sub r17=64,r8
+(pNeg) sub r17=r0,r8
+ ;;
+ mov ar.rsc=r11 // put RSE in enforced lazy mode
+ shr.u r8=r25,r16
+ add r3=8,in0 // r3 <- &jmpbuf.r1
+ shl r9=r25,r17
+ ;;
+ or r25=r8,r9
+ ;;
+ mov r26=ar.rnat
+ mov ar.unat=r25 // setup ar.unat (NaT bits for r1, r4-r7, and r12)
+ ;;
+ ld8.fill.nta sp=[r2],16 // r12 (sp)
+ ld8.fill.nta gp=[r3],16 // r1 (gp)
+ dep r11=-1,r23,3,6 // r11 <- ia64_rse_rnat_addr(jmpbuf.ar_bsp)
+ ;;
+ ld8.nta r16=[r2],16 // caller's unat
+ ld8.nta r17=[r3],16 // fpsr
+ ;;
+ ld8.fill.nta r4=[r2],16 // r4
+ ld8.fill.nta r5=[r3],16 // r5 (gp)
+ cmp.geu p8,p0=r10,r11 // p8 <- (ar.bsp >= jmpbuf.ar_bsp)
+ ;;
+ ld8.fill.nta r6=[r2],16 // r6
+ ld8.fill.nta r7=[r3],16 // r7
+ ;;
+ mov ar.unat=r16 // restore caller's unat
+ mov ar.fpsr=r17 // restore fpsr
+ ;;
+ ld8.nta r16=[r2],16 // b0
+ ld8.nta r17=[r3],16 // b1
+ ;;
+(p8) ld8 r26=[r11] // r26 <- *ia64_rse_rnat_addr(jmpbuf.ar_bsp)
+ mov ar.bspstore=r23 // restore ar.bspstore
+ ;;
+ ld8.nta r18=[r2],16 // b2
+ ld8.nta r19=[r3],16 // b3
+ ;;
+ ld8.nta r20=[r2],16 // b4
+ ld8.nta r21=[r3],16 // b5
+ ;;
+ ld8.nta r11=[r2],16 // ar.pfs
+ ld8.nta r22=[r3],56 // ar.lc
+ ;;
+ ld8.nta r24=[r2],32 // pr
+ mov b0=r16
+ ;;
+ ldf.fill.nta f2=[r2],32
+ ldf.fill.nta f3=[r3],32
+ mov b1=r17
+ ;;
+ ldf.fill.nta f4=[r2],32
+ ldf.fill.nta f5=[r3],32
+ mov b2=r18
+ ;;
+ ldf.fill.nta f16=[r2],32
+ ldf.fill.nta f17=[r3],32
+ mov b3=r19
+ ;;
+ ldf.fill.nta f18=[r2],32
+ ldf.fill.nta f19=[r3],32
+ mov b4=r20
+ ;;
+ ldf.fill.nta f20=[r2],32
+ ldf.fill.nta f21=[r3],32
+ mov b5=r21
+ ;;
+ ldf.fill.nta f22=[r2],32
+ ldf.fill.nta f23=[r3],32
+ mov ar.lc=r22
+ ;;
+ ldf.fill.nta f24=[r2],32
+ ldf.fill.nta f25=[r3],32
+ cmp.eq p8,p9=0,in1
+ ;;
+ ldf.fill.nta f26=[r2],32
+ ldf.fill.nta f27=[r3],32
+ mov ar.pfs=r11
+ ;;
+ ldf.fill.nta f28=[r2],32
+ ldf.fill.nta f29=[r3],32
+ ;;
+ ldf.fill.nta f30=[r2]
+ ldf.fill.nta f31=[r3]
+(p8) mov r8=1
+
+ mov ar.rnat=r26 // restore ar.rnat
+ ;;
+ mov ar.rsc=r27 // restore ar.rsc
+(p9) mov r8=in1
+
+ invala // virt. -> phys. regnum mapping may change
+ mov pr=r24,-1
+ br.ret.dptk.few rp
+ .endp longjmp
--- /dev/null
+/* Copyright (C) 1999, 2000, 2001, 2002, 2008 Free Software Foundation, Inc.
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA.
+
+ The layout of the jmp_buf is as follows. This is subject to change
+ and user-code should never depend on the particular layout of
+ jmp_buf!
+
+
+ offset: description:
+ ------- ------------
+ 0x000 stack pointer (r12) ; unchangeable (see _JMPBUF_UNWINDS)
+ 0x008 r1 (gp)
+ 0x010 caller's unat
+ 0x018 fpsr
+ 0x020 r4
+ 0x028 r5
+ 0x030 r6
+ 0x038 r7
+ 0x040 rp (b0)
+ 0x048 b1
+ 0x050 b2
+ 0x058 b3
+ 0x060 b4
+ 0x068 b5
+ 0x070 ar.pfs
+ 0x078 ar.lc
+ 0x080 pr
+ 0x088 ar.bsp ; unchangeable (see __longjmp.S)
+ 0x090 ar.unat
+ 0x098 &__jmp_buf ; address of the jmpbuf (needed to locate NaT bits in unat)
+ 0x0a0 f2
+ 0x0b0 f3
+ 0x0c0 f4
+ 0x0d0 f5
+ 0x0e0 f16
+ 0x0f0 f17
+ 0x100 f18
+ 0x110 f19
+ 0x120 f20
+ 0x130 f21
+ 0x130 f22
+ 0x140 f23
+ 0x150 f24
+ 0x160 f25
+ 0x170 f26
+ 0x180 f27
+ 0x190 f28
+ 0x1a0 f29
+ 0x1b0 f30
+ 0x1c0 f31 */
+
+#include <grub/symbol.h>
+#include <grub/dl.h>
+
+ .file "setjmp.S"
+
+GRUB_MOD_LICENSE ("GPLv2+")
+
+ /* The following two entry points are the traditional entry points: */
+
+ .text
+ .global setjmp
+ .proc setjmp
+setjmp:
+ alloc r8=ar.pfs,2,0,0,0
+ mov in1=1
+ br.cond.sptk.many __sigsetjmp
+ .endp setjmp
+
+ /* __sigsetjmp(__jmp_buf buf, int savemask) */
+
+ .proc __sigsetjmp
+__sigsetjmp:
+ //.prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(2)
+ alloc loc1=ar.pfs,2,2,2,0
+ mov r16=ar.unat
+ ;;
+ mov r17=ar.fpsr
+ mov r2=in0
+ add r3=8,in0
+ ;;
+ st8.spill.nta [r2]=sp,16 // r12 (sp)
+ st8.spill.nta [r3]=gp,16 // r1 (gp)
+ ;;
+ st8.nta [r2]=r16,16 // save caller's unat
+ st8.nta [r3]=r17,16 // save fpsr
+ add r8=0xa0,in0
+ ;;
+ st8.spill.nta [r2]=r4,16 // r4
+ st8.spill.nta [r3]=r5,16 // r5
+ add r9=0xb0,in0
+ ;;
+ stf.spill.nta [r8]=f2,32
+ stf.spill.nta [r9]=f3,32
+ mov loc0=rp
+ .body
+ ;;
+ stf.spill.nta [r8]=f4,32
+ stf.spill.nta [r9]=f5,32
+ mov r17=b1
+ ;;
+ stf.spill.nta [r8]=f16,32
+ stf.spill.nta [r9]=f17,32
+ mov r18=b2
+ ;;
+ stf.spill.nta [r8]=f18,32
+ stf.spill.nta [r9]=f19,32
+ mov r19=b3
+ ;;
+ stf.spill.nta [r8]=f20,32
+ stf.spill.nta [r9]=f21,32
+ mov r20=b4
+ ;;
+ stf.spill.nta [r8]=f22,32
+ stf.spill.nta [r9]=f23,32
+ mov r21=b5
+ ;;
+ stf.spill.nta [r8]=f24,32
+ stf.spill.nta [r9]=f25,32
+ mov r22=ar.lc
+ ;;
+ stf.spill.nta [r8]=f26,32
+ stf.spill.nta [r9]=f27,32
+ mov r24=pr
+ ;;
+ stf.spill.nta [r8]=f28,32
+ stf.spill.nta [r9]=f29,32
+ ;;
+ stf.spill.nta [r8]=f30
+ stf.spill.nta [r9]=f31
+
+ st8.spill.nta [r2]=r6,16 // r6
+ st8.spill.nta [r3]=r7,16 // r7
+ ;;
+ mov r23=ar.bsp
+ mov r25=ar.unat
+ mov out0=in0
+
+ st8.nta [r2]=loc0,16 // b0
+ st8.nta [r3]=r17,16 // b1
+ mov out1=in1
+ ;;
+ st8.nta [r2]=r18,16 // b2
+ st8.nta [r3]=r19,16 // b3
+ ;;
+ st8.nta [r2]=r20,16 // b4
+ st8.nta [r3]=r21,16 // b5
+ ;;
+ st8.nta [r2]=loc1,16 // ar.pfs
+ st8.nta [r3]=r22,16 // ar.lc
+ ;;
+ st8.nta [r2]=r24,16 // pr
+ st8.nta [r3]=r23,16 // ar.bsp
+ ;;
+ st8.nta [r2]=r25 // ar.unat
+ st8.nta [r3]=in0 // &__jmp_buf
+ mov r8=0
+ mov rp=loc0
+ mov ar.pfs=loc1
+ br.ret.sptk.many rp
+
+ .endp __sigsetjmp
--- /dev/null
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2011 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/datetime.h>
+#include <grub/cmos.h>
+#include <grub/dl.h>
+#include <grub/ieee1275/ieee1275.h>
+#include <grub/misc.h>
+
+volatile grub_uint8_t *grub_cmos_port = 0;
+grub_err_t
+grub_cmos_find_port (void)
+{
+ auto int hook (struct grub_ieee1275_devalias *alias);
+ int hook (struct grub_ieee1275_devalias *alias)
+ {
+ grub_ieee1275_phandle_t dev;
+ grub_uint32_t addr[2];
+ grub_ssize_t actual;
+ /* Enough to check if it's "m5819" */
+ char compat[100];
+ if (grub_ieee1275_finddevice (alias->path, &dev))
+ return 0;
+ if (grub_ieee1275_get_property (dev, "compatible", compat, sizeof (compat),
+ 0))
+ return 0;
+ if (grub_strcmp (compat, "m5819") != 0)
+ return 0;
+ if (grub_ieee1275_get_integer_property (dev, "address",
+ addr, sizeof (addr), &actual))
+ return 0;
+ if (actual == 4)
+ {
+ grub_cmos_port = (volatile grub_uint8_t *) (grub_addr_t) addr[0];
+ return 1;
+ }
+
+#if GRUB_CPU_SIZEOF_VOID_P == 8
+ if (actual == 8)
+ {
+ grub_cmos_port = (volatile grub_uint8_t *)
+ ((((grub_addr_t) addr[0]) << 32) | addr[1]);
+ return 1;
+ }
+#else
+ if (actual == 8 && addr[0] == 0)
+ {
+ grub_cmos_port = (volatile grub_uint8_t *) addr[1];
+ return 1;
+ }
+#endif
+ return 0;
+ }
+
+ grub_ieee1275_devices_iterate (hook);
+ if (!grub_cmos_port)
+ return grub_error (GRUB_ERR_IO, "no cmos found");
+
+ return GRUB_ERR_NONE;
+}
#include <grub/datetime.h>
#include <grub/ieee1275/ieee1275.h>
#include <grub/misc.h>
+#include <grub/dl.h>
+#if defined (__powerpc__) || defined (__sparc__)
+#include <grub/cmos.h>
+#endif
+
+GRUB_MOD_LICENSE ("GPLv3+");
static char *rtc = 0;
+static int no_ieee1275_rtc = 0;
static void
find_rtc (void)
}
grub_ieee1275_devices_iterate (hook);
+ if (!rtc)
+ no_ieee1275_rtc = 1;
}
grub_err_t
int status;
grub_ieee1275_ihandle_t ihandle;
+ if (no_ieee1275_rtc)
+ return grub_get_datetime_cmos (datetime);
if (!rtc)
find_rtc ();
if (!rtc)
- return grub_error (GRUB_ERR_IO, "no RTC found");
+ return grub_get_datetime_cmos (datetime);
status = grub_ieee1275_open (rtc, &ihandle);
if (status == -1)
int status;
grub_ieee1275_ihandle_t ihandle;
+ if (no_ieee1275_rtc)
+ return grub_set_datetime_cmos (datetime);
if (!rtc)
find_rtc ();
if (!rtc)
- return grub_error (GRUB_ERR_IO, "no RTC found");
+ return grub_set_datetime_cmos (datetime);
status = grub_ieee1275_open (rtc, &ihandle);
if (status == -1)
--- /dev/null
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2011 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/ieee1275/ieee1275.h>
+#include <grub/misc.h>
+
+void
+grub_reboot (void)
+{
+ grub_ieee1275_interpret ("reset-all", 0);
+ for (;;) ;
+}
int base = 10;
brk = curarg;
if (brk[0] == '0' && brk[1] == 'x')
- base = 16;
+ {
+ base = 16;
+ brk += 2;
+ }
else if (brk[0] == '0')
base = 8;
for (; *brk && brk < curarg + curarglen; brk++)
--- /dev/null
+/* lzoconf.h -- configuration of the LZO data compression library
+
+ This file is part of the LZO real-time data compression library.
+
+ Copyright (C) 2011 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2010 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2009 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
+ All Rights Reserved.
+
+ The LZO library 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 2 of
+ the License, or (at your option) any later version.
+
+ The LZO library 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 the LZO library; see the file COPYING.
+ If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ Markus F.X.J. Oberhumer
+ <markus@oberhumer.com>
+ http://www.oberhumer.com/opensource/lzo/
+ */
+
+
+#ifndef __LZOCONF_H_INCLUDED
+#define __LZOCONF_H_INCLUDED 1
+
+#define LZO_VERSION 0x2050
+#define LZO_VERSION_STRING "2.05"
+#define LZO_VERSION_DATE "Apr 23 2011"
+
+/* internal Autoconf configuration file - only used when building LZO */
+#if defined(LZO_HAVE_CONFIG_H)
+# include <config.h>
+#endif
+#include <limits.h>
+#include <stddef.h>
+
+
+/***********************************************************************
+// LZO requires a conforming <limits.h>
+************************************************************************/
+
+#if !defined(CHAR_BIT) || (CHAR_BIT != 8)
+# error "invalid CHAR_BIT"
+#endif
+#if !defined(UCHAR_MAX) || !defined(UINT_MAX) || !defined(ULONG_MAX)
+# error "check your compiler installation"
+#endif
+#if (USHRT_MAX < 1) || (UINT_MAX < 1) || (ULONG_MAX < 1)
+# error "your limits.h macros are broken"
+#endif
+
+/* get OS and architecture defines */
+#ifndef __LZODEFS_H_INCLUDED
+#include "lzodefs.h"
+#endif
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/***********************************************************************
+// some core defines
+************************************************************************/
+
+#if !defined(LZO_UINT32_C)
+# if (UINT_MAX < LZO_0xffffffffL)
+# define LZO_UINT32_C(c) c ## UL
+# else
+# define LZO_UINT32_C(c) ((c) + 0U)
+# endif
+#endif
+
+/* memory checkers */
+#if !defined(__LZO_CHECKER)
+# if defined(__BOUNDS_CHECKING_ON)
+# define __LZO_CHECKER 1
+# elif defined(__CHECKER__)
+# define __LZO_CHECKER 1
+# elif defined(__INSURE__)
+# define __LZO_CHECKER 1
+# elif defined(__PURIFY__)
+# define __LZO_CHECKER 1
+# endif
+#endif
+
+
+/***********************************************************************
+// integral and pointer types
+************************************************************************/
+
+/* lzo_uint should match size_t */
+#if !defined(LZO_UINT_MAX)
+# if defined(LZO_ABI_LLP64) /* WIN64 */
+# if defined(LZO_OS_WIN64)
+ typedef unsigned __int64 lzo_uint;
+ typedef __int64 lzo_int;
+# else
+ typedef unsigned long long lzo_uint;
+ typedef long long lzo_int;
+# endif
+# define LZO_UINT_MAX 0xffffffffffffffffull
+# define LZO_INT_MAX 9223372036854775807LL
+# define LZO_INT_MIN (-1LL - LZO_INT_MAX)
+# elif defined(LZO_ABI_IP32L64) /* MIPS R5900 */
+ typedef unsigned int lzo_uint;
+ typedef int lzo_int;
+# define LZO_UINT_MAX UINT_MAX
+# define LZO_INT_MAX INT_MAX
+# define LZO_INT_MIN INT_MIN
+# elif (ULONG_MAX >= LZO_0xffffffffL)
+ typedef unsigned long lzo_uint;
+ typedef long lzo_int;
+# define LZO_UINT_MAX ULONG_MAX
+# define LZO_INT_MAX LONG_MAX
+# define LZO_INT_MIN LONG_MIN
+# else
+# error "lzo_uint"
+# endif
+#endif
+
+/* Integral types with 32 bits or more. */
+#if !defined(LZO_UINT32_MAX)
+# if (UINT_MAX >= LZO_0xffffffffL)
+ typedef unsigned int lzo_uint32;
+ typedef int lzo_int32;
+# define LZO_UINT32_MAX UINT_MAX
+# define LZO_INT32_MAX INT_MAX
+# define LZO_INT32_MIN INT_MIN
+# elif (ULONG_MAX >= LZO_0xffffffffL)
+ typedef unsigned long lzo_uint32;
+ typedef long lzo_int32;
+# define LZO_UINT32_MAX ULONG_MAX
+# define LZO_INT32_MAX LONG_MAX
+# define LZO_INT32_MIN LONG_MIN
+# else
+# error "lzo_uint32"
+# endif
+#endif
+
+/* Integral types with exactly 64 bits. */
+#if !defined(LZO_UINT64_MAX)
+# if (LZO_UINT_MAX >= LZO_0xffffffffL)
+# if ((((LZO_UINT_MAX) >> 31) >> 31) == 3)
+# define lzo_uint64 lzo_uint
+# define lzo_int64 lzo_int
+# define LZO_UINT64_MAX LZO_UINT_MAX
+# define LZO_INT64_MAX LZO_INT_MAX
+# define LZO_INT64_MIN LZO_INT_MIN
+# endif
+# elif (ULONG_MAX >= LZO_0xffffffffL)
+# if ((((ULONG_MAX) >> 31) >> 31) == 3)
+ typedef unsigned long lzo_uint64;
+ typedef long lzo_int64;
+# define LZO_UINT64_MAX ULONG_MAX
+# define LZO_INT64_MAX LONG_MAX
+# define LZO_INT64_MIN LONG_MIN
+# endif
+# endif
+#endif
+
+/* The larger type of lzo_uint and lzo_uint32. */
+#if (LZO_UINT_MAX >= LZO_UINT32_MAX)
+# define lzo_xint lzo_uint
+#else
+# define lzo_xint lzo_uint32
+#endif
+
+/* Memory model that allows to access memory at offsets of lzo_uint. */
+#if !defined(__LZO_MMODEL)
+# if (LZO_UINT_MAX <= UINT_MAX)
+# define __LZO_MMODEL /*empty*/
+# elif defined(LZO_HAVE_MM_HUGE_PTR)
+# define __LZO_MMODEL_HUGE 1
+# define __LZO_MMODEL __huge
+# else
+# define __LZO_MMODEL /*empty*/
+# endif
+#endif
+
+/* no typedef here because of const-pointer issues */
+#define lzo_bytep unsigned char __LZO_MMODEL *
+#define lzo_charp char __LZO_MMODEL *
+#define lzo_voidp void __LZO_MMODEL *
+#define lzo_shortp short __LZO_MMODEL *
+#define lzo_ushortp unsigned short __LZO_MMODEL *
+#define lzo_uint32p lzo_uint32 __LZO_MMODEL *
+#define lzo_int32p lzo_int32 __LZO_MMODEL *
+#if defined(LZO_UINT64_MAX)
+#define lzo_uint64p lzo_uint64 __LZO_MMODEL *
+#define lzo_int64p lzo_int64 __LZO_MMODEL *
+#endif
+#define lzo_uintp lzo_uint __LZO_MMODEL *
+#define lzo_intp lzo_int __LZO_MMODEL *
+#define lzo_xintp lzo_xint __LZO_MMODEL *
+#define lzo_voidpp lzo_voidp __LZO_MMODEL *
+#define lzo_bytepp lzo_bytep __LZO_MMODEL *
+/* deprecated - use 'lzo_bytep' instead of 'lzo_byte *' */
+#define lzo_byte unsigned char __LZO_MMODEL
+
+typedef int lzo_bool;
+
+
+/***********************************************************************
+// function types
+************************************************************************/
+
+/* name mangling */
+#if !defined(__LZO_EXTERN_C)
+# ifdef __cplusplus
+# define __LZO_EXTERN_C extern "C"
+# else
+# define __LZO_EXTERN_C extern
+# endif
+#endif
+
+/* calling convention */
+#if !defined(__LZO_CDECL)
+# define __LZO_CDECL __lzo_cdecl
+#endif
+
+/* DLL export information */
+#if !defined(__LZO_EXPORT1)
+# define __LZO_EXPORT1 /*empty*/
+#endif
+#if !defined(__LZO_EXPORT2)
+# define __LZO_EXPORT2 /*empty*/
+#endif
+
+/* __cdecl calling convention for public C and assembly functions */
+#if !defined(LZO_PUBLIC)
+# define LZO_PUBLIC(_rettype) __LZO_EXPORT1 _rettype __LZO_EXPORT2 __LZO_CDECL
+#endif
+#if !defined(LZO_EXTERN)
+# define LZO_EXTERN(_rettype) __LZO_EXTERN_C LZO_PUBLIC(_rettype)
+#endif
+#if !defined(LZO_PRIVATE)
+# define LZO_PRIVATE(_rettype) static _rettype __LZO_CDECL
+#endif
+
+/* function types */
+typedef int
+(__LZO_CDECL *lzo_compress_t) ( const lzo_bytep src, lzo_uint src_len,
+ lzo_bytep dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem );
+
+typedef int
+(__LZO_CDECL *lzo_decompress_t) ( const lzo_bytep src, lzo_uint src_len,
+ lzo_bytep dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem );
+
+typedef int
+(__LZO_CDECL *lzo_optimize_t) ( lzo_bytep src, lzo_uint src_len,
+ lzo_bytep dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem );
+
+typedef int
+(__LZO_CDECL *lzo_compress_dict_t)(const lzo_bytep src, lzo_uint src_len,
+ lzo_bytep dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem,
+ const lzo_bytep dict, lzo_uint dict_len );
+
+typedef int
+(__LZO_CDECL *lzo_decompress_dict_t)(const lzo_bytep src, lzo_uint src_len,
+ lzo_bytep dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem,
+ const lzo_bytep dict, lzo_uint dict_len );
+
+
+/* Callback interface. Currently only the progress indicator ("nprogress")
+ * is used, but this may change in a future release. */
+
+struct lzo_callback_t;
+typedef struct lzo_callback_t lzo_callback_t;
+#define lzo_callback_p lzo_callback_t __LZO_MMODEL *
+
+/* malloc & free function types */
+typedef lzo_voidp (__LZO_CDECL *lzo_alloc_func_t)
+ (lzo_callback_p self, lzo_uint items, lzo_uint size);
+typedef void (__LZO_CDECL *lzo_free_func_t)
+ (lzo_callback_p self, lzo_voidp ptr);
+
+/* a progress indicator callback function */
+typedef void (__LZO_CDECL *lzo_progress_func_t)
+ (lzo_callback_p, lzo_uint, lzo_uint, int);
+
+struct lzo_callback_t
+{
+ /* custom allocators (set to 0 to disable) */
+ lzo_alloc_func_t nalloc; /* [not used right now] */
+ lzo_free_func_t nfree; /* [not used right now] */
+
+ /* a progress indicator callback function (set to 0 to disable) */
+ lzo_progress_func_t nprogress;
+
+ /* NOTE: the first parameter "self" of the nalloc/nfree/nprogress
+ * callbacks points back to this struct, so you are free to store
+ * some extra info in the following variables. */
+ lzo_voidp user1;
+ lzo_xint user2;
+ lzo_xint user3;
+};
+
+
+/***********************************************************************
+// error codes and prototypes
+************************************************************************/
+
+/* Error codes for the compression/decompression functions. Negative
+ * values are errors, positive values will be used for special but
+ * normal events.
+ */
+#define LZO_E_OK 0
+#define LZO_E_ERROR (-1)
+#define LZO_E_OUT_OF_MEMORY (-2) /* [lzo_alloc_func_t failure] */
+#define LZO_E_NOT_COMPRESSIBLE (-3) /* [not used right now] */
+#define LZO_E_INPUT_OVERRUN (-4)
+#define LZO_E_OUTPUT_OVERRUN (-5)
+#define LZO_E_LOOKBEHIND_OVERRUN (-6)
+#define LZO_E_EOF_NOT_FOUND (-7)
+#define LZO_E_INPUT_NOT_CONSUMED (-8)
+#define LZO_E_NOT_YET_IMPLEMENTED (-9) /* [not used right now] */
+#define LZO_E_INVALID_ARGUMENT (-10)
+
+
+#ifndef lzo_sizeof_dict_t
+# define lzo_sizeof_dict_t ((unsigned)sizeof(lzo_bytep))
+#endif
+
+/* lzo_init() should be the first function you call.
+ * Check the return code !
+ *
+ * lzo_init() is a macro to allow checking that the library and the
+ * compiler's view of various types are consistent.
+ */
+#define lzo_init() __lzo_init_v2(LZO_VERSION,(int)sizeof(short),(int)sizeof(int),\
+ (int)sizeof(long),(int)sizeof(lzo_uint32),(int)sizeof(lzo_uint),\
+ (int)lzo_sizeof_dict_t,(int)sizeof(char *),(int)sizeof(lzo_voidp),\
+ (int)sizeof(lzo_callback_t))
+LZO_EXTERN(int) __lzo_init_v2(unsigned,int,int,int,int,int,int,int,int,int);
+
+/* version functions (useful for shared libraries) */
+LZO_EXTERN(unsigned) lzo_version(void);
+LZO_EXTERN(const char *) lzo_version_string(void);
+LZO_EXTERN(const char *) lzo_version_date(void);
+LZO_EXTERN(const lzo_charp) _lzo_version_string(void);
+LZO_EXTERN(const lzo_charp) _lzo_version_date(void);
+
+/* string functions */
+LZO_EXTERN(int)
+ lzo_memcmp(const lzo_voidp a, const lzo_voidp b, lzo_uint len);
+LZO_EXTERN(lzo_voidp)
+ lzo_memcpy(lzo_voidp dst, const lzo_voidp src, lzo_uint len);
+LZO_EXTERN(lzo_voidp)
+ lzo_memmove(lzo_voidp dst, const lzo_voidp src, lzo_uint len);
+LZO_EXTERN(lzo_voidp)
+ lzo_memset(lzo_voidp buf, int c, lzo_uint len);
+
+/* checksum functions */
+LZO_EXTERN(lzo_uint32)
+ lzo_adler32(lzo_uint32 c, const lzo_bytep buf, lzo_uint len);
+LZO_EXTERN(lzo_uint32)
+ lzo_crc32(lzo_uint32 c, const lzo_bytep buf, lzo_uint len);
+LZO_EXTERN(const lzo_uint32p)
+ lzo_get_crc32_table(void);
+
+/* misc. */
+LZO_EXTERN(int) _lzo_config_check(void);
+typedef union { lzo_bytep p; lzo_uint u; } __lzo_pu_u;
+typedef union { lzo_bytep p; lzo_uint32 u32; } __lzo_pu32_u;
+typedef union { void *vp; lzo_bytep bp; lzo_uint u; lzo_uint32 u32; unsigned long l; } lzo_align_t;
+
+/* align a char pointer on a boundary that is a multiple of 'size' */
+LZO_EXTERN(unsigned) __lzo_align_gap(const lzo_voidp p, lzo_uint size);
+#define LZO_PTR_ALIGN_UP(p,size) \
+ ((p) + (lzo_uint) __lzo_align_gap((const lzo_voidp)(p),(lzo_uint)(size)))
+
+
+/***********************************************************************
+// deprecated macros - only for backward compatibility with LZO v1.xx
+************************************************************************/
+
+#if defined(LZO_CFG_COMPAT)
+
+#define __LZOCONF_H 1
+
+#if defined(LZO_ARCH_I086)
+# define __LZO_i386 1
+#elif defined(LZO_ARCH_I386)
+# define __LZO_i386 1
+#endif
+
+#if defined(LZO_OS_DOS16)
+# define __LZO_DOS 1
+# define __LZO_DOS16 1
+#elif defined(LZO_OS_DOS32)
+# define __LZO_DOS 1
+#elif defined(LZO_OS_WIN16)
+# define __LZO_WIN 1
+# define __LZO_WIN16 1
+#elif defined(LZO_OS_WIN32)
+# define __LZO_WIN 1
+#endif
+
+#define __LZO_CMODEL /*empty*/
+#define __LZO_DMODEL /*empty*/
+#define __LZO_ENTRY __LZO_CDECL
+#define LZO_EXTERN_CDECL LZO_EXTERN
+#define LZO_ALIGN LZO_PTR_ALIGN_UP
+
+#define lzo_compress_asm_t lzo_compress_t
+#define lzo_decompress_asm_t lzo_decompress_t
+
+#endif /* LZO_CFG_COMPAT */
+
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* already included */
+
+
+/* vim:set ts=4 et: */
--- /dev/null
+/* lzodefs.h -- architecture, OS and compiler specific defines
+
+ This file is part of the LZO real-time data compression library.
+
+ Copyright (C) 2011 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2010 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2009 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
+ All Rights Reserved.
+
+ The LZO library 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 2 of
+ the License, or (at your option) any later version.
+
+ The LZO library 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 the LZO library; see the file COPYING.
+ If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ Markus F.X.J. Oberhumer
+ <markus@oberhumer.com>
+ http://www.oberhumer.com/opensource/lzo/
+ */
+
+
+#ifndef __LZODEFS_H_INCLUDED
+#define __LZODEFS_H_INCLUDED 1
+
+#if defined(__CYGWIN32__) && !defined(__CYGWIN__)
+# define __CYGWIN__ __CYGWIN32__
+#endif
+#if defined(__IBMCPP__) && !defined(__IBMC__)
+# define __IBMC__ __IBMCPP__
+#endif
+#if defined(__ICL) && defined(_WIN32) && !defined(__INTEL_COMPILER)
+# define __INTEL_COMPILER __ICL
+#endif
+#if 1 && defined(__INTERIX) && defined(__GNUC__) && !defined(_ALL_SOURCE)
+# define _ALL_SOURCE 1
+#endif
+#if defined(__mips__) && defined(__R5900__)
+# if !defined(__LONG_MAX__)
+# define __LONG_MAX__ 9223372036854775807L
+# endif
+#endif
+#if defined(__INTEL_COMPILER) && defined(__linux__)
+# pragma warning(disable: 193)
+#endif
+#if defined(__KEIL__) && defined(__C166__)
+# pragma warning disable = 322
+#elif 0 && defined(__C251__)
+# pragma warning disable = 322
+#endif
+#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) && !defined(__MWERKS__)
+# if (_MSC_VER >= 1300)
+# pragma warning(disable: 4668)
+# endif
+#endif
+#if 0 && defined(__WATCOMC__)
+# if (__WATCOMC__ >= 1050) && (__WATCOMC__ < 1060)
+# pragma warning 203 9
+# endif
+#endif
+#if defined(__BORLANDC__) && defined(__MSDOS__) && !defined(__FLAT__)
+# pragma option -h
+#endif
+#if 0
+#define LZO_0xffffL 0xfffful
+#define LZO_0xffffffffL 0xfffffffful
+#else
+#define LZO_0xffffL 65535ul
+#define LZO_0xffffffffL 4294967295ul
+#endif
+#if (LZO_0xffffL == LZO_0xffffffffL)
+# error "your preprocessor is broken 1"
+#endif
+#if (16ul * 16384ul != 262144ul)
+# error "your preprocessor is broken 2"
+#endif
+#if 0
+#if (32767 >= 4294967295ul)
+# error "your preprocessor is broken 3"
+#endif
+#if (65535u >= 4294967295ul)
+# error "your preprocessor is broken 4"
+#endif
+#endif
+#if (UINT_MAX == LZO_0xffffL)
+#if defined(__ZTC__) && defined(__I86__) && !defined(__OS2__)
+# if !defined(MSDOS)
+# define MSDOS 1
+# endif
+# if !defined(_MSDOS)
+# define _MSDOS 1
+# endif
+#elif 0 && defined(__VERSION) && defined(MB_LEN_MAX)
+# if (__VERSION == 520) && (MB_LEN_MAX == 1)
+# if !defined(__AZTEC_C__)
+# define __AZTEC_C__ __VERSION
+# endif
+# if !defined(__DOS__)
+# define __DOS__ 1
+# endif
+# endif
+#endif
+#endif
+#if defined(_MSC_VER) && defined(M_I86HM) && (UINT_MAX == LZO_0xffffL)
+# define ptrdiff_t long
+# define _PTRDIFF_T_DEFINED 1
+#endif
+#if (UINT_MAX == LZO_0xffffL)
+# undef __LZO_RENAME_A
+# undef __LZO_RENAME_B
+# if defined(__AZTEC_C__) && defined(__DOS__)
+# define __LZO_RENAME_A 1
+# elif defined(_MSC_VER) && defined(MSDOS)
+# if (_MSC_VER < 600)
+# define __LZO_RENAME_A 1
+# elif (_MSC_VER < 700)
+# define __LZO_RENAME_B 1
+# endif
+# elif defined(__TSC__) && defined(__OS2__)
+# define __LZO_RENAME_A 1
+# elif defined(__MSDOS__) && defined(__TURBOC__) && (__TURBOC__ < 0x0410)
+# define __LZO_RENAME_A 1
+# elif defined(__PACIFIC__) && defined(DOS)
+# if !defined(__far)
+# define __far far
+# endif
+# if !defined(__near)
+# define __near near
+# endif
+# endif
+# if defined(__LZO_RENAME_A)
+# if !defined(__cdecl)
+# define __cdecl cdecl
+# endif
+# if !defined(__far)
+# define __far far
+# endif
+# if !defined(__huge)
+# define __huge huge
+# endif
+# if !defined(__near)
+# define __near near
+# endif
+# if !defined(__pascal)
+# define __pascal pascal
+# endif
+# if !defined(__huge)
+# define __huge huge
+# endif
+# elif defined(__LZO_RENAME_B)
+# if !defined(__cdecl)
+# define __cdecl _cdecl
+# endif
+# if !defined(__far)
+# define __far _far
+# endif
+# if !defined(__huge)
+# define __huge _huge
+# endif
+# if !defined(__near)
+# define __near _near
+# endif
+# if !defined(__pascal)
+# define __pascal _pascal
+# endif
+# elif (defined(__PUREC__) || defined(__TURBOC__)) && defined(__TOS__)
+# if !defined(__cdecl)
+# define __cdecl cdecl
+# endif
+# if !defined(__pascal)
+# define __pascal pascal
+# endif
+# endif
+# undef __LZO_RENAME_A
+# undef __LZO_RENAME_B
+#endif
+#if (UINT_MAX == LZO_0xffffL)
+#if defined(__AZTEC_C__) && defined(__DOS__)
+# define LZO_BROKEN_CDECL_ALT_SYNTAX 1
+#elif defined(_MSC_VER) && defined(MSDOS)
+# if (_MSC_VER < 600)
+# define LZO_BROKEN_INTEGRAL_CONSTANTS 1
+# endif
+# if (_MSC_VER < 700)
+# define LZO_BROKEN_INTEGRAL_PROMOTION 1
+# define LZO_BROKEN_SIZEOF 1
+# endif
+#elif defined(__PACIFIC__) && defined(DOS)
+# define LZO_BROKEN_INTEGRAL_CONSTANTS 1
+#elif defined(__TURBOC__) && defined(__MSDOS__)
+# if (__TURBOC__ < 0x0150)
+# define LZO_BROKEN_CDECL_ALT_SYNTAX 1
+# define LZO_BROKEN_INTEGRAL_CONSTANTS 1
+# define LZO_BROKEN_INTEGRAL_PROMOTION 1
+# endif
+# if (__TURBOC__ < 0x0200)
+# define LZO_BROKEN_SIZEOF 1
+# endif
+# if (__TURBOC__ < 0x0400) && defined(__cplusplus)
+# define LZO_BROKEN_CDECL_ALT_SYNTAX 1
+# endif
+#elif (defined(__PUREC__) || defined(__TURBOC__)) && defined(__TOS__)
+# define LZO_BROKEN_CDECL_ALT_SYNTAX 1
+# define LZO_BROKEN_SIZEOF 1
+#endif
+#endif
+#if defined(__WATCOMC__) && (__WATCOMC__ < 900)
+# define LZO_BROKEN_INTEGRAL_CONSTANTS 1
+#endif
+#if defined(_CRAY) && defined(_CRAY1)
+# define LZO_BROKEN_SIGNED_RIGHT_SHIFT 1
+#endif
+#define LZO_PP_STRINGIZE(x) #x
+#define LZO_PP_MACRO_EXPAND(x) LZO_PP_STRINGIZE(x)
+#define LZO_PP_CONCAT2(a,b) a ## b
+#define LZO_PP_CONCAT3(a,b,c) a ## b ## c
+#define LZO_PP_CONCAT4(a,b,c,d) a ## b ## c ## d
+#define LZO_PP_CONCAT5(a,b,c,d,e) a ## b ## c ## d ## e
+#define LZO_PP_ECONCAT2(a,b) LZO_PP_CONCAT2(a,b)
+#define LZO_PP_ECONCAT3(a,b,c) LZO_PP_CONCAT3(a,b,c)
+#define LZO_PP_ECONCAT4(a,b,c,d) LZO_PP_CONCAT4(a,b,c,d)
+#define LZO_PP_ECONCAT5(a,b,c,d,e) LZO_PP_CONCAT5(a,b,c,d,e)
+#if 1
+#define LZO_CPP_STRINGIZE(x) #x
+#define LZO_CPP_MACRO_EXPAND(x) LZO_CPP_STRINGIZE(x)
+#define LZO_CPP_CONCAT2(a,b) a ## b
+#define LZO_CPP_CONCAT3(a,b,c) a ## b ## c
+#define LZO_CPP_CONCAT4(a,b,c,d) a ## b ## c ## d
+#define LZO_CPP_CONCAT5(a,b,c,d,e) a ## b ## c ## d ## e
+#define LZO_CPP_ECONCAT2(a,b) LZO_CPP_CONCAT2(a,b)
+#define LZO_CPP_ECONCAT3(a,b,c) LZO_CPP_CONCAT3(a,b,c)
+#define LZO_CPP_ECONCAT4(a,b,c,d) LZO_CPP_CONCAT4(a,b,c,d)
+#define LZO_CPP_ECONCAT5(a,b,c,d,e) LZO_CPP_CONCAT5(a,b,c,d,e)
+#endif
+#define __LZO_MASK_GEN(o,b) (((((o) << ((b)-1)) - (o)) << 1) + (o))
+#if 1 && defined(__cplusplus)
+# if !defined(__STDC_CONSTANT_MACROS)
+# define __STDC_CONSTANT_MACROS 1
+# endif
+# if !defined(__STDC_LIMIT_MACROS)
+# define __STDC_LIMIT_MACROS 1
+# endif
+#endif
+#if defined(__cplusplus)
+# define LZO_EXTERN_C extern "C"
+#else
+# define LZO_EXTERN_C extern
+#endif
+#if !defined(__LZO_OS_OVERRIDE)
+#if (LZO_OS_FREESTANDING)
+# define LZO_INFO_OS "freestanding"
+#elif (LZO_OS_EMBEDDED)
+# define LZO_INFO_OS "embedded"
+#elif 1 && defined(__IAR_SYSTEMS_ICC__)
+# define LZO_OS_EMBEDDED 1
+# define LZO_INFO_OS "embedded"
+#elif defined(__CYGWIN__) && defined(__GNUC__)
+# define LZO_OS_CYGWIN 1
+# define LZO_INFO_OS "cygwin"
+#elif defined(__EMX__) && defined(__GNUC__)
+# define LZO_OS_EMX 1
+# define LZO_INFO_OS "emx"
+#elif defined(__BEOS__)
+# define LZO_OS_BEOS 1
+# define LZO_INFO_OS "beos"
+#elif defined(__Lynx__)
+# define LZO_OS_LYNXOS 1
+# define LZO_INFO_OS "lynxos"
+#elif defined(__OS400__)
+# define LZO_OS_OS400 1
+# define LZO_INFO_OS "os400"
+#elif defined(__QNX__)
+# define LZO_OS_QNX 1
+# define LZO_INFO_OS "qnx"
+#elif defined(__BORLANDC__) && defined(__DPMI32__) && (__BORLANDC__ >= 0x0460)
+# define LZO_OS_DOS32 1
+# define LZO_INFO_OS "dos32"
+#elif defined(__BORLANDC__) && defined(__DPMI16__)
+# define LZO_OS_DOS16 1
+# define LZO_INFO_OS "dos16"
+#elif defined(__ZTC__) && defined(DOS386)
+# define LZO_OS_DOS32 1
+# define LZO_INFO_OS "dos32"
+#elif defined(__OS2__) || defined(__OS2V2__)
+# if (UINT_MAX == LZO_0xffffL)
+# define LZO_OS_OS216 1
+# define LZO_INFO_OS "os216"
+# elif (UINT_MAX == LZO_0xffffffffL)
+# define LZO_OS_OS2 1
+# define LZO_INFO_OS "os2"
+# else
+# error "check your limits.h header"
+# endif
+#elif defined(__WIN64__) || defined(_WIN64) || defined(WIN64)
+# define LZO_OS_WIN64 1
+# define LZO_INFO_OS "win64"
+#elif defined(__WIN32__) || defined(_WIN32) || defined(WIN32) || defined(__WINDOWS_386__)
+# define LZO_OS_WIN32 1
+# define LZO_INFO_OS "win32"
+#elif defined(__MWERKS__) && defined(__INTEL__)
+# define LZO_OS_WIN32 1
+# define LZO_INFO_OS "win32"
+#elif defined(__WINDOWS__) || defined(_WINDOWS) || defined(_Windows)
+# if (UINT_MAX == LZO_0xffffL)
+# define LZO_OS_WIN16 1
+# define LZO_INFO_OS "win16"
+# elif (UINT_MAX == LZO_0xffffffffL)
+# define LZO_OS_WIN32 1
+# define LZO_INFO_OS "win32"
+# else
+# error "check your limits.h header"
+# endif
+#elif defined(__DOS__) || defined(__MSDOS__) || defined(_MSDOS) || defined(MSDOS) || (defined(__PACIFIC__) && defined(DOS))
+# if (UINT_MAX == LZO_0xffffL)
+# define LZO_OS_DOS16 1
+# define LZO_INFO_OS "dos16"
+# elif (UINT_MAX == LZO_0xffffffffL)
+# define LZO_OS_DOS32 1
+# define LZO_INFO_OS "dos32"
+# else
+# error "check your limits.h header"
+# endif
+#elif defined(__WATCOMC__)
+# if defined(__NT__) && (UINT_MAX == LZO_0xffffL)
+# define LZO_OS_DOS16 1
+# define LZO_INFO_OS "dos16"
+# elif defined(__NT__) && (__WATCOMC__ < 1100)
+# define LZO_OS_WIN32 1
+# define LZO_INFO_OS "win32"
+# elif defined(__linux__) || defined(__LINUX__)
+# define LZO_OS_POSIX 1
+# define LZO_INFO_OS "posix"
+# else
+# error "please specify a target using the -bt compiler option"
+# endif
+#elif defined(__palmos__)
+# define LZO_OS_PALMOS 1
+# define LZO_INFO_OS "palmos"
+#elif defined(__TOS__) || defined(__atarist__)
+# define LZO_OS_TOS 1
+# define LZO_INFO_OS "tos"
+#elif defined(macintosh) && !defined(__ppc__)
+# define LZO_OS_MACCLASSIC 1
+# define LZO_INFO_OS "macclassic"
+#elif defined(__VMS)
+# define LZO_OS_VMS 1
+# define LZO_INFO_OS "vms"
+#elif ((defined(__mips__) && defined(__R5900__)) || defined(__MIPS_PSX2__))
+# define LZO_OS_CONSOLE 1
+# define LZO_OS_CONSOLE_PS2 1
+# define LZO_INFO_OS "console"
+# define LZO_INFO_OS_CONSOLE "ps2"
+#elif (defined(__mips__) && defined(__psp__))
+# define LZO_OS_CONSOLE 1
+# define LZO_OS_CONSOLE_PSP 1
+# define LZO_INFO_OS "console"
+# define LZO_INFO_OS_CONSOLE "psp"
+#else
+# define LZO_OS_POSIX 1
+# define LZO_INFO_OS "posix"
+#endif
+#if (LZO_OS_POSIX)
+# if defined(_AIX) || defined(__AIX__) || defined(__aix__)
+# define LZO_OS_POSIX_AIX 1
+# define LZO_INFO_OS_POSIX "aix"
+# elif defined(__FreeBSD__)
+# define LZO_OS_POSIX_FREEBSD 1
+# define LZO_INFO_OS_POSIX "freebsd"
+# elif defined(__hpux__) || defined(__hpux)
+# define LZO_OS_POSIX_HPUX 1
+# define LZO_INFO_OS_POSIX "hpux"
+# elif defined(__INTERIX)
+# define LZO_OS_POSIX_INTERIX 1
+# define LZO_INFO_OS_POSIX "interix"
+# elif defined(__IRIX__) || defined(__irix__)
+# define LZO_OS_POSIX_IRIX 1
+# define LZO_INFO_OS_POSIX "irix"
+# elif defined(__linux__) || defined(__linux) || defined(__LINUX__)
+# define LZO_OS_POSIX_LINUX 1
+# define LZO_INFO_OS_POSIX "linux"
+# elif defined(__APPLE__) || defined(__MACOS__)
+# define LZO_OS_POSIX_MACOSX 1
+# define LZO_INFO_OS_POSIX "macosx"
+# elif defined(__minix__) || defined(__minix)
+# define LZO_OS_POSIX_MINIX 1
+# define LZO_INFO_OS_POSIX "minix"
+# elif defined(__NetBSD__)
+# define LZO_OS_POSIX_NETBSD 1
+# define LZO_INFO_OS_POSIX "netbsd"
+# elif defined(__OpenBSD__)
+# define LZO_OS_POSIX_OPENBSD 1
+# define LZO_INFO_OS_POSIX "openbsd"
+# elif defined(__osf__)
+# define LZO_OS_POSIX_OSF 1
+# define LZO_INFO_OS_POSIX "osf"
+# elif defined(__solaris__) || defined(__sun)
+# if defined(__SVR4) || defined(__svr4__)
+# define LZO_OS_POSIX_SOLARIS 1
+# define LZO_INFO_OS_POSIX "solaris"
+# else
+# define LZO_OS_POSIX_SUNOS 1
+# define LZO_INFO_OS_POSIX "sunos"
+# endif
+# elif defined(__ultrix__) || defined(__ultrix)
+# define LZO_OS_POSIX_ULTRIX 1
+# define LZO_INFO_OS_POSIX "ultrix"
+# elif defined(_UNICOS)
+# define LZO_OS_POSIX_UNICOS 1
+# define LZO_INFO_OS_POSIX "unicos"
+# else
+# define LZO_OS_POSIX_UNKNOWN 1
+# define LZO_INFO_OS_POSIX "unknown"
+# endif
+#endif
+#endif
+#if (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16)
+# if (UINT_MAX != LZO_0xffffL)
+# error "this should not happen"
+# endif
+# if (ULONG_MAX != LZO_0xffffffffL)
+# error "this should not happen"
+# endif
+#endif
+#if (LZO_OS_DOS32 || LZO_OS_OS2 || LZO_OS_WIN32 || LZO_OS_WIN64)
+# if (UINT_MAX != LZO_0xffffffffL)
+# error "this should not happen"
+# endif
+# if (ULONG_MAX != LZO_0xffffffffL)
+# error "this should not happen"
+# endif
+#endif
+#if defined(CIL) && defined(_GNUCC) && defined(__GNUC__)
+# define LZO_CC_CILLY 1
+# define LZO_INFO_CC "Cilly"
+# if defined(__CILLY__)
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__CILLY__)
+# else
+# define LZO_INFO_CCVER "unknown"
+# endif
+#elif 0 && defined(SDCC) && defined(__VERSION__) && !defined(__GNUC__)
+# define LZO_CC_SDCC 1
+# define LZO_INFO_CC "sdcc"
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(SDCC)
+#elif defined(__PATHSCALE__) && defined(__PATHCC_PATCHLEVEL__)
+# define LZO_CC_PATHSCALE (__PATHCC__ * 0x10000L + __PATHCC_MINOR__ * 0x100 + __PATHCC_PATCHLEVEL__)
+# define LZO_INFO_CC "Pathscale C"
+# define LZO_INFO_CCVER __PATHSCALE__
+#elif defined(__INTEL_COMPILER)
+# define LZO_CC_INTELC 1
+# define LZO_INFO_CC "Intel C"
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__INTEL_COMPILER)
+# if defined(_WIN32) || defined(_WIN64)
+# define LZO_CC_SYNTAX_MSC 1
+# else
+# define LZO_CC_SYNTAX_GNUC 1
+# endif
+#elif defined(__POCC__) && defined(_WIN32)
+# define LZO_CC_PELLESC 1
+# define LZO_INFO_CC "Pelles C"
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__POCC__)
+#elif defined(__clang__) && defined(__llvm__) && defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__)
+# if defined(__GNUC_PATCHLEVEL__)
+# define LZO_CC_CLANG_GNUC (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100 + __GNUC_PATCHLEVEL__)
+# else
+# define LZO_CC_CLANG_GNUC (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100)
+# endif
+# if defined(__clang_major__) && defined(__clang_minor__) && defined(__clang_patchlevel__)
+# define LZO_CC_CLANG_CLANG (__clang_major__ * 0x10000L + __clang_minor__ * 0x100 + __clang_patchlevel__)
+# else
+# define LZO_CC_CLANG_CLANG 0x010000L
+# endif
+# define LZO_CC_CLANG LZO_CC_CLANG_GNUC
+# define LZO_INFO_CC "clang"
+# define LZO_INFO_CCVER __VERSION__
+#elif defined(__llvm__) && defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__)
+# if defined(__GNUC_PATCHLEVEL__)
+# define LZO_CC_LLVM_GNUC (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100 + __GNUC_PATCHLEVEL__)
+# else
+# define LZO_CC_LLVM_GNUC (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100)
+# endif
+# define LZO_CC_LLVM LZO_CC_LLVM_GNUC
+# define LZO_INFO_CC "llvm-gcc"
+# define LZO_INFO_CCVER __VERSION__
+#elif defined(__GNUC__) && defined(__VERSION__)
+# if defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__)
+# define LZO_CC_GNUC (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100 + __GNUC_PATCHLEVEL__)
+# elif defined(__GNUC_MINOR__)
+# define LZO_CC_GNUC (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100)
+# else
+# define LZO_CC_GNUC (__GNUC__ * 0x10000L)
+# endif
+# define LZO_INFO_CC "gcc"
+# define LZO_INFO_CCVER __VERSION__
+#elif defined(__ACK__) && defined(_ACK)
+# define LZO_CC_ACK 1
+# define LZO_INFO_CC "Amsterdam Compiler Kit C"
+# define LZO_INFO_CCVER "unknown"
+#elif defined(__AZTEC_C__)
+# define LZO_CC_AZTECC 1
+# define LZO_INFO_CC "Aztec C"
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__AZTEC_C__)
+#elif defined(__CODEGEARC__)
+# define LZO_CC_CODEGEARC 1
+# define LZO_INFO_CC "CodeGear C"
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__CODEGEARC__)
+#elif defined(__BORLANDC__)
+# define LZO_CC_BORLANDC 1
+# define LZO_INFO_CC "Borland C"
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__BORLANDC__)
+#elif defined(_CRAYC) && defined(_RELEASE)
+# define LZO_CC_CRAYC 1
+# define LZO_INFO_CC "Cray C"
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(_RELEASE)
+#elif defined(__DMC__) && defined(__SC__)
+# define LZO_CC_DMC 1
+# define LZO_INFO_CC "Digital Mars C"
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__DMC__)
+#elif defined(__DECC)
+# define LZO_CC_DECC 1
+# define LZO_INFO_CC "DEC C"
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__DECC)
+#elif defined(__HIGHC__)
+# define LZO_CC_HIGHC 1
+# define LZO_INFO_CC "MetaWare High C"
+# define LZO_INFO_CCVER "unknown"
+#elif defined(__IAR_SYSTEMS_ICC__)
+# define LZO_CC_IARC 1
+# define LZO_INFO_CC "IAR C"
+# if defined(__VER__)
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__VER__)
+# else
+# define LZO_INFO_CCVER "unknown"
+# endif
+#elif defined(__IBMC__)
+# define LZO_CC_IBMC 1
+# define LZO_INFO_CC "IBM C"
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__IBMC__)
+#elif defined(__KEIL__) && defined(__C166__)
+# define LZO_CC_KEILC 1
+# define LZO_INFO_CC "Keil C"
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__C166__)
+#elif defined(__LCC__) && defined(_WIN32) && defined(__LCCOPTIMLEVEL)
+# define LZO_CC_LCCWIN32 1
+# define LZO_INFO_CC "lcc-win32"
+# define LZO_INFO_CCVER "unknown"
+#elif defined(__LCC__)
+# define LZO_CC_LCC 1
+# define LZO_INFO_CC "lcc"
+# if defined(__LCC_VERSION__)
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__LCC_VERSION__)
+# else
+# define LZO_INFO_CCVER "unknown"
+# endif
+#elif defined(_MSC_VER)
+# define LZO_CC_MSC 1
+# define LZO_INFO_CC "Microsoft C"
+# if defined(_MSC_FULL_VER)
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(_MSC_VER) "." LZO_PP_MACRO_EXPAND(_MSC_FULL_VER)
+# else
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(_MSC_VER)
+# endif
+#elif defined(__MWERKS__)
+# define LZO_CC_MWERKS 1
+# define LZO_INFO_CC "Metrowerks C"
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__MWERKS__)
+#elif (defined(__NDPC__) || defined(__NDPX__)) && defined(__i386)
+# define LZO_CC_NDPC 1
+# define LZO_INFO_CC "Microway NDP C"
+# define LZO_INFO_CCVER "unknown"
+#elif defined(__PACIFIC__)
+# define LZO_CC_PACIFICC 1
+# define LZO_INFO_CC "Pacific C"
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__PACIFIC__)
+#elif defined(__PGI) && (defined(__linux__) || defined(__WIN32__))
+# define LZO_CC_PGI 1
+# define LZO_INFO_CC "Portland Group PGI C"
+# define LZO_INFO_CCVER "unknown"
+#elif defined(__PUREC__) && defined(__TOS__)
+# define LZO_CC_PUREC 1
+# define LZO_INFO_CC "Pure C"
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__PUREC__)
+#elif defined(__SC__) && defined(__ZTC__)
+# define LZO_CC_SYMANTECC 1
+# define LZO_INFO_CC "Symantec C"
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__SC__)
+#elif defined(__SUNPRO_C)
+# define LZO_INFO_CC "SunPro C"
+# if ((__SUNPRO_C)+0 > 0)
+# define LZO_CC_SUNPROC __SUNPRO_C
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__SUNPRO_C)
+# else
+# define LZO_CC_SUNPROC 1
+# define LZO_INFO_CCVER "unknown"
+# endif
+#elif defined(__SUNPRO_CC)
+# define LZO_INFO_CC "SunPro C"
+# if ((__SUNPRO_CC)+0 > 0)
+# define LZO_CC_SUNPROC __SUNPRO_CC
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__SUNPRO_CC)
+# else
+# define LZO_CC_SUNPROC 1
+# define LZO_INFO_CCVER "unknown"
+# endif
+#elif defined(__TINYC__)
+# define LZO_CC_TINYC 1
+# define LZO_INFO_CC "Tiny C"
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__TINYC__)
+#elif defined(__TSC__)
+# define LZO_CC_TOPSPEEDC 1
+# define LZO_INFO_CC "TopSpeed C"
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__TSC__)
+#elif defined(__WATCOMC__)
+# define LZO_CC_WATCOMC 1
+# define LZO_INFO_CC "Watcom C"
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__WATCOMC__)
+#elif defined(__TURBOC__)
+# define LZO_CC_TURBOC 1
+# define LZO_INFO_CC "Turbo C"
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__TURBOC__)
+#elif defined(__ZTC__)
+# define LZO_CC_ZORTECHC 1
+# define LZO_INFO_CC "Zortech C"
+# if (__ZTC__ == 0x310)
+# define LZO_INFO_CCVER "0x310"
+# else
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__ZTC__)
+# endif
+#else
+# define LZO_CC_UNKNOWN 1
+# define LZO_INFO_CC "unknown"
+# define LZO_INFO_CCVER "unknown"
+#endif
+#if 0 && (LZO_CC_MSC && (_MSC_VER >= 1200)) && !defined(_MSC_FULL_VER)
+# error "LZO_CC_MSC: _MSC_FULL_VER is not defined"
+#endif
+#if !defined(__LZO_ARCH_OVERRIDE) && !(LZO_ARCH_GENERIC) && defined(_CRAY)
+# if (UINT_MAX > LZO_0xffffffffL) && defined(_CRAY)
+# if defined(_CRAYMPP) || defined(_CRAYT3D) || defined(_CRAYT3E)
+# define LZO_ARCH_CRAY_MPP 1
+# elif defined(_CRAY1)
+# define LZO_ARCH_CRAY_PVP 1
+# endif
+# endif
+#endif
+#if !defined(__LZO_ARCH_OVERRIDE)
+#if (LZO_ARCH_GENERIC)
+# define LZO_INFO_ARCH "generic"
+#elif (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16)
+# define LZO_ARCH_I086 1
+# define LZO_ARCH_IA16 1
+# define LZO_INFO_ARCH "i086"
+#elif defined(__alpha__) || defined(__alpha) || defined(_M_ALPHA)
+# define LZO_ARCH_ALPHA 1
+# define LZO_INFO_ARCH "alpha"
+#elif (LZO_ARCH_CRAY_MPP) && (defined(_CRAYT3D) || defined(_CRAYT3E))
+# define LZO_ARCH_ALPHA 1
+# define LZO_INFO_ARCH "alpha"
+#elif defined(__amd64__) || defined(__x86_64__) || defined(_M_AMD64)
+# define LZO_ARCH_AMD64 1
+# define LZO_INFO_ARCH "amd64"
+#elif defined(__thumb__) || (defined(_M_ARM) && defined(_M_THUMB))
+# define LZO_ARCH_ARM 1
+# define LZO_ARCH_ARM_THUMB 1
+# define LZO_INFO_ARCH "arm_thumb"
+#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICCARM__)
+# define LZO_ARCH_ARM 1
+# if defined(__CPU_MODE__) && ((__CPU_MODE__)+0 == 1)
+# define LZO_ARCH_ARM_THUMB 1
+# define LZO_INFO_ARCH "arm_thumb"
+# elif defined(__CPU_MODE__) && ((__CPU_MODE__)+0 == 2)
+# define LZO_INFO_ARCH "arm"
+# else
+# define LZO_INFO_ARCH "arm"
+# endif
+#elif defined(__arm__) || defined(_M_ARM)
+# define LZO_ARCH_ARM 1
+# define LZO_INFO_ARCH "arm"
+#elif (UINT_MAX <= LZO_0xffffL) && defined(__AVR__)
+# define LZO_ARCH_AVR 1
+# define LZO_INFO_ARCH "avr"
+#elif defined(__avr32__) || defined(__AVR32__)
+# define LZO_ARCH_AVR32 1
+# define LZO_INFO_ARCH "avr32"
+#elif defined(__bfin__)
+# define LZO_ARCH_BLACKFIN 1
+# define LZO_INFO_ARCH "blackfin"
+#elif (UINT_MAX == LZO_0xffffL) && defined(__C166__)
+# define LZO_ARCH_C166 1
+# define LZO_INFO_ARCH "c166"
+#elif defined(__cris__)
+# define LZO_ARCH_CRIS 1
+# define LZO_INFO_ARCH "cris"
+#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICCEZ80__)
+# define LZO_ARCH_EZ80 1
+# define LZO_INFO_ARCH "ez80"
+#elif defined(__H8300__) || defined(__H8300H__) || defined(__H8300S__) || defined(__H8300SX__)
+# define LZO_ARCH_H8300 1
+# define LZO_INFO_ARCH "h8300"
+#elif defined(__hppa__) || defined(__hppa)
+# define LZO_ARCH_HPPA 1
+# define LZO_INFO_ARCH "hppa"
+#elif defined(__386__) || defined(__i386__) || defined(__i386) || defined(_M_IX86) || defined(_M_I386)
+# define LZO_ARCH_I386 1
+# define LZO_ARCH_IA32 1
+# define LZO_INFO_ARCH "i386"
+#elif (LZO_CC_ZORTECHC && defined(__I86__))
+# define LZO_ARCH_I386 1
+# define LZO_ARCH_IA32 1
+# define LZO_INFO_ARCH "i386"
+#elif (LZO_OS_DOS32 && LZO_CC_HIGHC) && defined(_I386)
+# define LZO_ARCH_I386 1
+# define LZO_ARCH_IA32 1
+# define LZO_INFO_ARCH "i386"
+#elif defined(__ia64__) || defined(__ia64) || defined(_M_IA64)
+# define LZO_ARCH_IA64 1
+# define LZO_INFO_ARCH "ia64"
+#elif (UINT_MAX == LZO_0xffffL) && defined(__m32c__)
+# define LZO_ARCH_M16C 1
+# define LZO_INFO_ARCH "m16c"
+#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICCM16C__)
+# define LZO_ARCH_M16C 1
+# define LZO_INFO_ARCH "m16c"
+#elif defined(__m32r__)
+# define LZO_ARCH_M32R 1
+# define LZO_INFO_ARCH "m32r"
+#elif (LZO_OS_TOS) || defined(__m68k__) || defined(__m68000__) || defined(__mc68000__) || defined(__mc68020__) || defined(_M_M68K)
+# define LZO_ARCH_M68K 1
+# define LZO_INFO_ARCH "m68k"
+#elif (UINT_MAX == LZO_0xffffL) && defined(__C251__)
+# define LZO_ARCH_MCS251 1
+# define LZO_INFO_ARCH "mcs251"
+#elif (UINT_MAX == LZO_0xffffL) && defined(__C51__)
+# define LZO_ARCH_MCS51 1
+# define LZO_INFO_ARCH "mcs51"
+#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICC8051__)
+# define LZO_ARCH_MCS51 1
+# define LZO_INFO_ARCH "mcs51"
+#elif defined(__mips__) || defined(__mips) || defined(_MIPS_ARCH) || defined(_M_MRX000)
+# define LZO_ARCH_MIPS 1
+# define LZO_INFO_ARCH "mips"
+#elif (UINT_MAX == LZO_0xffffL) && defined(__MSP430__)
+# define LZO_ARCH_MSP430 1
+# define LZO_INFO_ARCH "msp430"
+#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICC430__)
+# define LZO_ARCH_MSP430 1
+# define LZO_INFO_ARCH "msp430"
+#elif defined(__powerpc__) || defined(__powerpc) || defined(__ppc__) || defined(__PPC__) || defined(_M_PPC) || defined(_ARCH_PPC) || defined(_ARCH_PWR)
+# define LZO_ARCH_POWERPC 1
+# define LZO_INFO_ARCH "powerpc"
+#elif defined(__s390__) || defined(__s390) || defined(__s390x__) || defined(__s390x)
+# define LZO_ARCH_S390 1
+# define LZO_INFO_ARCH "s390"
+#elif defined(__sh__) || defined(_M_SH)
+# define LZO_ARCH_SH 1
+# define LZO_INFO_ARCH "sh"
+#elif defined(__sparc__) || defined(__sparc) || defined(__sparcv8)
+# define LZO_ARCH_SPARC 1
+# define LZO_INFO_ARCH "sparc"
+#elif defined(__SPU__)
+# define LZO_ARCH_SPU 1
+# define LZO_INFO_ARCH "spu"
+#elif (UINT_MAX == LZO_0xffffL) && defined(__z80)
+# define LZO_ARCH_Z80 1
+# define LZO_INFO_ARCH "z80"
+#elif (LZO_ARCH_CRAY_PVP)
+# if defined(_CRAYSV1)
+# define LZO_ARCH_CRAY_SV1 1
+# define LZO_INFO_ARCH "cray_sv1"
+# elif (_ADDR64)
+# define LZO_ARCH_CRAY_T90 1
+# define LZO_INFO_ARCH "cray_t90"
+# elif (_ADDR32)
+# define LZO_ARCH_CRAY_YMP 1
+# define LZO_INFO_ARCH "cray_ymp"
+# else
+# define LZO_ARCH_CRAY_XMP 1
+# define LZO_INFO_ARCH "cray_xmp"
+# endif
+#else
+# define LZO_ARCH_UNKNOWN 1
+# define LZO_INFO_ARCH "unknown"
+#endif
+#endif
+#if 1 && (LZO_ARCH_UNKNOWN) && (LZO_OS_DOS32 || LZO_OS_OS2)
+# error "FIXME - missing define for CPU architecture"
+#endif
+#if 1 && (LZO_ARCH_UNKNOWN) && (LZO_OS_WIN32)
+# error "FIXME - missing WIN32 define for CPU architecture"
+#endif
+#if 1 && (LZO_ARCH_UNKNOWN) && (LZO_OS_WIN64)
+# error "FIXME - missing WIN64 define for CPU architecture"
+#endif
+#if (LZO_OS_OS216 || LZO_OS_WIN16)
+# define LZO_ARCH_I086PM 1
+# define LZO_ARCH_IA16PM 1
+#elif 1 && (LZO_OS_DOS16 && defined(BLX286))
+# define LZO_ARCH_I086PM 1
+# define LZO_ARCH_IA16PM 1
+#elif 1 && (LZO_OS_DOS16 && defined(DOSX286))
+# define LZO_ARCH_I086PM 1
+# define LZO_ARCH_IA16PM 1
+#elif 1 && (LZO_OS_DOS16 && LZO_CC_BORLANDC && defined(__DPMI16__))
+# define LZO_ARCH_I086PM 1
+# define LZO_ARCH_IA16PM 1
+#endif
+#if (LZO_ARCH_ARM_THUMB) && !(LZO_ARCH_ARM)
+# error "this should not happen"
+#endif
+#if (LZO_ARCH_I086PM) && !(LZO_ARCH_I086)
+# error "this should not happen"
+#endif
+#if (LZO_ARCH_I086)
+# if (UINT_MAX != LZO_0xffffL)
+# error "this should not happen"
+# endif
+# if (ULONG_MAX != LZO_0xffffffffL)
+# error "this should not happen"
+# endif
+#endif
+#if (LZO_ARCH_I386)
+# if (UINT_MAX != LZO_0xffffL) && defined(__i386_int16__)
+# error "this should not happen"
+# endif
+# if (UINT_MAX != LZO_0xffffffffL) && !defined(__i386_int16__)
+# error "this should not happen"
+# endif
+# if (ULONG_MAX != LZO_0xffffffffL)
+# error "this should not happen"
+# endif
+#endif
+#if !defined(__LZO_MM_OVERRIDE)
+#if (LZO_ARCH_I086)
+#if (UINT_MAX != LZO_0xffffL)
+# error "this should not happen"
+#endif
+#if defined(__TINY__) || defined(M_I86TM) || defined(_M_I86TM)
+# define LZO_MM_TINY 1
+#elif defined(__HUGE__) || defined(_HUGE_) || defined(M_I86HM) || defined(_M_I86HM)
+# define LZO_MM_HUGE 1
+#elif defined(__SMALL__) || defined(M_I86SM) || defined(_M_I86SM) || defined(SMALL_MODEL)
+# define LZO_MM_SMALL 1
+#elif defined(__MEDIUM__) || defined(M_I86MM) || defined(_M_I86MM)
+# define LZO_MM_MEDIUM 1
+#elif defined(__COMPACT__) || defined(M_I86CM) || defined(_M_I86CM)
+# define LZO_MM_COMPACT 1
+#elif defined(__LARGE__) || defined(M_I86LM) || defined(_M_I86LM) || defined(LARGE_MODEL)
+# define LZO_MM_LARGE 1
+#elif (LZO_CC_AZTECC)
+# if defined(_LARGE_CODE) && defined(_LARGE_DATA)
+# define LZO_MM_LARGE 1
+# elif defined(_LARGE_CODE)
+# define LZO_MM_MEDIUM 1
+# elif defined(_LARGE_DATA)
+# define LZO_MM_COMPACT 1
+# else
+# define LZO_MM_SMALL 1
+# endif
+#elif (LZO_CC_ZORTECHC && defined(__VCM__))
+# define LZO_MM_LARGE 1
+#else
+# error "unknown memory model"
+#endif
+#if (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16)
+#define LZO_HAVE_MM_HUGE_PTR 1
+#define LZO_HAVE_MM_HUGE_ARRAY 1
+#if (LZO_MM_TINY)
+# undef LZO_HAVE_MM_HUGE_ARRAY
+#endif
+#if (LZO_CC_AZTECC || LZO_CC_PACIFICC || LZO_CC_ZORTECHC)
+# undef LZO_HAVE_MM_HUGE_PTR
+# undef LZO_HAVE_MM_HUGE_ARRAY
+#elif (LZO_CC_DMC || LZO_CC_SYMANTECC)
+# undef LZO_HAVE_MM_HUGE_ARRAY
+#elif (LZO_CC_MSC && defined(_QC))
+# undef LZO_HAVE_MM_HUGE_ARRAY
+# if (_MSC_VER < 600)
+# undef LZO_HAVE_MM_HUGE_PTR
+# endif
+#elif (LZO_CC_TURBOC && (__TURBOC__ < 0x0295))
+# undef LZO_HAVE_MM_HUGE_ARRAY
+#endif
+#if (LZO_ARCH_I086PM) && !(LZO_HAVE_MM_HUGE_PTR)
+# if (LZO_OS_DOS16)
+# error "this should not happen"
+# elif (LZO_CC_ZORTECHC)
+# else
+# error "this should not happen"
+# endif
+#endif
+#ifdef __cplusplus
+extern "C" {
+#endif
+#if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0200))
+ extern void __near __cdecl _AHSHIFT(void);
+# define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT)
+#elif (LZO_CC_DMC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC)
+ extern void __near __cdecl _AHSHIFT(void);
+# define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT)
+#elif (LZO_CC_MSC || LZO_CC_TOPSPEEDC)
+ extern void __near __cdecl _AHSHIFT(void);
+# define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT)
+#elif (LZO_CC_TURBOC && (__TURBOC__ >= 0x0295))
+ extern void __near __cdecl _AHSHIFT(void);
+# define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT)
+#elif ((LZO_CC_AZTECC || LZO_CC_PACIFICC || LZO_CC_TURBOC) && LZO_OS_DOS16)
+# define LZO_MM_AHSHIFT 12
+#elif (LZO_CC_WATCOMC)
+ extern unsigned char _HShift;
+# define LZO_MM_AHSHIFT ((unsigned) _HShift)
+#else
+# error "FIXME - implement LZO_MM_AHSHIFT"
+#endif
+#ifdef __cplusplus
+}
+#endif
+#endif
+#elif (LZO_ARCH_C166)
+#if !defined(__MODEL__)
+# error "FIXME - C166 __MODEL__"
+#elif ((__MODEL__) == 0)
+# define LZO_MM_SMALL 1
+#elif ((__MODEL__) == 1)
+# define LZO_MM_SMALL 1
+#elif ((__MODEL__) == 2)
+# define LZO_MM_LARGE 1
+#elif ((__MODEL__) == 3)
+# define LZO_MM_TINY 1
+#elif ((__MODEL__) == 4)
+# define LZO_MM_XTINY 1
+#elif ((__MODEL__) == 5)
+# define LZO_MM_XSMALL 1
+#else
+# error "FIXME - C166 __MODEL__"
+#endif
+#elif (LZO_ARCH_MCS251)
+#if !defined(__MODEL__)
+# error "FIXME - MCS251 __MODEL__"
+#elif ((__MODEL__) == 0)
+# define LZO_MM_SMALL 1
+#elif ((__MODEL__) == 2)
+# define LZO_MM_LARGE 1
+#elif ((__MODEL__) == 3)
+# define LZO_MM_TINY 1
+#elif ((__MODEL__) == 4)
+# define LZO_MM_XTINY 1
+#elif ((__MODEL__) == 5)
+# define LZO_MM_XSMALL 1
+#else
+# error "FIXME - MCS251 __MODEL__"
+#endif
+#elif (LZO_ARCH_MCS51)
+#if !defined(__MODEL__)
+# error "FIXME - MCS51 __MODEL__"
+#elif ((__MODEL__) == 1)
+# define LZO_MM_SMALL 1
+#elif ((__MODEL__) == 2)
+# define LZO_MM_LARGE 1
+#elif ((__MODEL__) == 3)
+# define LZO_MM_TINY 1
+#elif ((__MODEL__) == 4)
+# define LZO_MM_XTINY 1
+#elif ((__MODEL__) == 5)
+# define LZO_MM_XSMALL 1
+#else
+# error "FIXME - MCS51 __MODEL__"
+#endif
+#elif (LZO_ARCH_CRAY_PVP)
+# define LZO_MM_PVP 1
+#else
+# define LZO_MM_FLAT 1
+#endif
+#if (LZO_MM_COMPACT)
+# define LZO_INFO_MM "compact"
+#elif (LZO_MM_FLAT)
+# define LZO_INFO_MM "flat"
+#elif (LZO_MM_HUGE)
+# define LZO_INFO_MM "huge"
+#elif (LZO_MM_LARGE)
+# define LZO_INFO_MM "large"
+#elif (LZO_MM_MEDIUM)
+# define LZO_INFO_MM "medium"
+#elif (LZO_MM_PVP)
+# define LZO_INFO_MM "pvp"
+#elif (LZO_MM_SMALL)
+# define LZO_INFO_MM "small"
+#elif (LZO_MM_TINY)
+# define LZO_INFO_MM "tiny"
+#else
+# error "unknown memory model"
+#endif
+#endif
+#if defined(SIZEOF_SHORT)
+# define LZO_SIZEOF_SHORT (SIZEOF_SHORT)
+#endif
+#if defined(SIZEOF_INT)
+# define LZO_SIZEOF_INT (SIZEOF_INT)
+#endif
+#if defined(SIZEOF_LONG)
+# define LZO_SIZEOF_LONG (SIZEOF_LONG)
+#endif
+#if defined(SIZEOF_LONG_LONG)
+# define LZO_SIZEOF_LONG_LONG (SIZEOF_LONG_LONG)
+#endif
+#if defined(SIZEOF___INT16)
+# define LZO_SIZEOF___INT16 (SIZEOF___INT16)
+#endif
+#if defined(SIZEOF___INT32)
+# define LZO_SIZEOF___INT32 (SIZEOF___INT32)
+#endif
+#if defined(SIZEOF___INT64)
+# define LZO_SIZEOF___INT64 (SIZEOF___INT64)
+#endif
+#if defined(SIZEOF_VOID_P)
+# define LZO_SIZEOF_VOID_P (SIZEOF_VOID_P)
+#endif
+#if defined(SIZEOF_SIZE_T)
+# define LZO_SIZEOF_SIZE_T (SIZEOF_SIZE_T)
+#endif
+#if defined(SIZEOF_PTRDIFF_T)
+# define LZO_SIZEOF_PTRDIFF_T (SIZEOF_PTRDIFF_T)
+#endif
+#define __LZO_LSR(x,b) (((x)+0ul) >> (b))
+#if !defined(LZO_SIZEOF_SHORT)
+# if (LZO_ARCH_CRAY_PVP)
+# define LZO_SIZEOF_SHORT 8
+# elif (USHRT_MAX == LZO_0xffffL)
+# define LZO_SIZEOF_SHORT 2
+# elif (__LZO_LSR(USHRT_MAX,7) == 1)
+# define LZO_SIZEOF_SHORT 1
+# elif (__LZO_LSR(USHRT_MAX,15) == 1)
+# define LZO_SIZEOF_SHORT 2
+# elif (__LZO_LSR(USHRT_MAX,31) == 1)
+# define LZO_SIZEOF_SHORT 4
+# elif (__LZO_LSR(USHRT_MAX,63) == 1)
+# define LZO_SIZEOF_SHORT 8
+# elif (__LZO_LSR(USHRT_MAX,127) == 1)
+# define LZO_SIZEOF_SHORT 16
+# else
+# error "LZO_SIZEOF_SHORT"
+# endif
+#endif
+#if !defined(LZO_SIZEOF_INT)
+# if (LZO_ARCH_CRAY_PVP)
+# define LZO_SIZEOF_INT 8
+# elif (UINT_MAX == LZO_0xffffL)
+# define LZO_SIZEOF_INT 2
+# elif (UINT_MAX == LZO_0xffffffffL)
+# define LZO_SIZEOF_INT 4
+# elif (__LZO_LSR(UINT_MAX,7) == 1)
+# define LZO_SIZEOF_INT 1
+# elif (__LZO_LSR(UINT_MAX,15) == 1)
+# define LZO_SIZEOF_INT 2
+# elif (__LZO_LSR(UINT_MAX,31) == 1)
+# define LZO_SIZEOF_INT 4
+# elif (__LZO_LSR(UINT_MAX,63) == 1)
+# define LZO_SIZEOF_INT 8
+# elif (__LZO_LSR(UINT_MAX,127) == 1)
+# define LZO_SIZEOF_INT 16
+# else
+# error "LZO_SIZEOF_INT"
+# endif
+#endif
+#if !defined(LZO_SIZEOF_LONG)
+# if (ULONG_MAX == LZO_0xffffffffL)
+# define LZO_SIZEOF_LONG 4
+# elif (__LZO_LSR(ULONG_MAX,7) == 1)
+# define LZO_SIZEOF_LONG 1
+# elif (__LZO_LSR(ULONG_MAX,15) == 1)
+# define LZO_SIZEOF_LONG 2
+# elif (__LZO_LSR(ULONG_MAX,31) == 1)
+# define LZO_SIZEOF_LONG 4
+# elif (__LZO_LSR(ULONG_MAX,63) == 1)
+# define LZO_SIZEOF_LONG 8
+# elif (__LZO_LSR(ULONG_MAX,127) == 1)
+# define LZO_SIZEOF_LONG 16
+# else
+# error "LZO_SIZEOF_LONG"
+# endif
+#endif
+#if !defined(LZO_SIZEOF_LONG_LONG) && !defined(LZO_SIZEOF___INT64)
+#if (LZO_SIZEOF_LONG > 0 && LZO_SIZEOF_LONG < 8)
+# if defined(__LONG_MAX__) && defined(__LONG_LONG_MAX__)
+# if (LZO_CC_GNUC >= 0x030300ul)
+# if ((__LONG_MAX__)+0 == (__LONG_LONG_MAX__)+0)
+# define LZO_SIZEOF_LONG_LONG LZO_SIZEOF_LONG
+# elif (__LZO_LSR(__LONG_LONG_MAX__,30) == 1)
+# define LZO_SIZEOF_LONG_LONG 4
+# endif
+# endif
+# endif
+#endif
+#endif
+#if !defined(LZO_SIZEOF_LONG_LONG) && !defined(LZO_SIZEOF___INT64)
+#if (LZO_SIZEOF_LONG > 0 && LZO_SIZEOF_LONG < 8)
+#if (LZO_ARCH_I086 && LZO_CC_DMC)
+#elif (LZO_CC_CILLY) && defined(__GNUC__)
+# define LZO_SIZEOF_LONG_LONG 8
+#elif (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE)
+# define LZO_SIZEOF_LONG_LONG 8
+#elif ((LZO_OS_WIN32 || LZO_OS_WIN64 || defined(_WIN32)) && LZO_CC_MSC && (_MSC_VER >= 1400))
+# define LZO_SIZEOF_LONG_LONG 8
+#elif (LZO_OS_WIN64 || defined(_WIN64))
+# define LZO_SIZEOF___INT64 8
+#elif (LZO_ARCH_I386 && (LZO_CC_DMC))
+# define LZO_SIZEOF_LONG_LONG 8
+#elif (LZO_ARCH_I386 && (LZO_CC_SYMANTECC && (__SC__ >= 0x700)))
+# define LZO_SIZEOF_LONG_LONG 8
+#elif (LZO_ARCH_I386 && (LZO_CC_INTELC && defined(__linux__)))
+# define LZO_SIZEOF_LONG_LONG 8
+#elif (LZO_ARCH_I386 && (LZO_CC_MWERKS || LZO_CC_PELLESC || LZO_CC_PGI || LZO_CC_SUNPROC))
+# define LZO_SIZEOF_LONG_LONG 8
+#elif (LZO_ARCH_I386 && (LZO_CC_INTELC || LZO_CC_MSC))
+# define LZO_SIZEOF___INT64 8
+#elif ((LZO_OS_WIN32 || defined(_WIN32)) && (LZO_CC_MSC))
+# define LZO_SIZEOF___INT64 8
+#elif (LZO_ARCH_I386 && (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0520)))
+# define LZO_SIZEOF___INT64 8
+#elif (LZO_ARCH_I386 && (LZO_CC_WATCOMC && (__WATCOMC__ >= 1100)))
+# define LZO_SIZEOF___INT64 8
+#elif (LZO_CC_WATCOMC && defined(_INTEGRAL_MAX_BITS) && (_INTEGRAL_MAX_BITS == 64))
+# define LZO_SIZEOF___INT64 8
+#elif (LZO_OS_OS400 || defined(__OS400__)) && defined(__LLP64_IFC__)
+# define LZO_SIZEOF_LONG_LONG 8
+#elif (defined(__vms) || defined(__VMS)) && (__INITIAL_POINTER_SIZE+0 == 64)
+# define LZO_SIZEOF_LONG_LONG 8
+#elif (LZO_CC_SDCC) && (LZO_SIZEOF_INT == 2)
+#elif 1 && defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
+# define LZO_SIZEOF_LONG_LONG 8
+#endif
+#endif
+#endif
+#if defined(__cplusplus) && (LZO_CC_GNUC)
+# if (LZO_CC_GNUC < 0x020800ul)
+# undef LZO_SIZEOF_LONG_LONG
+# endif
+#endif
+#if (LZO_CFG_NO_LONG_LONG) || defined(__NO_LONG_LONG)
+# undef LZO_SIZEOF_LONG_LONG
+#endif
+#if !defined(LZO_SIZEOF_VOID_P)
+#if (LZO_ARCH_I086)
+# define __LZO_WORDSIZE 2
+# if (LZO_MM_TINY || LZO_MM_SMALL || LZO_MM_MEDIUM)
+# define LZO_SIZEOF_VOID_P 2
+# elif (LZO_MM_COMPACT || LZO_MM_LARGE || LZO_MM_HUGE)
+# define LZO_SIZEOF_VOID_P 4
+# else
+# error "LZO_MM"
+# endif
+#elif (LZO_ARCH_AVR || LZO_ARCH_Z80)
+# define __LZO_WORDSIZE 1
+# define LZO_SIZEOF_VOID_P 2
+#elif (LZO_ARCH_C166 || LZO_ARCH_MCS51 || LZO_ARCH_MCS251 || LZO_ARCH_MSP430)
+# define LZO_SIZEOF_VOID_P 2
+#elif (LZO_ARCH_H8300)
+# if defined(__NORMAL_MODE__)
+# define __LZO_WORDSIZE 4
+# define LZO_SIZEOF_VOID_P 2
+# elif defined(__H8300H__) || defined(__H8300S__) || defined(__H8300SX__)
+# define __LZO_WORDSIZE 4
+# define LZO_SIZEOF_VOID_P 4
+# else
+# define __LZO_WORDSIZE 2
+# define LZO_SIZEOF_VOID_P 2
+# endif
+# if (LZO_CC_GNUC && (LZO_CC_GNUC < 0x040000ul)) && (LZO_SIZEOF_INT == 4)
+# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_INT
+# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_INT
+# endif
+#elif (LZO_ARCH_M16C)
+# define __LZO_WORDSIZE 2
+# if defined(__m32c_cpu__) || defined(__m32cm_cpu__)
+# define LZO_SIZEOF_VOID_P 4
+# else
+# define LZO_SIZEOF_VOID_P 2
+# endif
+#elif (LZO_SIZEOF_LONG == 8) && ((defined(__mips__) && defined(__R5900__)) || defined(__MIPS_PSX2__))
+# define __LZO_WORDSIZE 8
+# define LZO_SIZEOF_VOID_P 4
+#elif defined(__LLP64__) || defined(__LLP64) || defined(_LLP64) || defined(_WIN64)
+# define __LZO_WORDSIZE 8
+# define LZO_SIZEOF_VOID_P 8
+#elif (LZO_OS_OS400 || defined(__OS400__)) && defined(__LLP64_IFC__)
+# define LZO_SIZEOF_VOID_P LZO_SIZEOF_LONG
+# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG
+# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG
+#elif (LZO_OS_OS400 || defined(__OS400__))
+# define __LZO_WORDSIZE LZO_SIZEOF_LONG
+# define LZO_SIZEOF_VOID_P 16
+# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG
+# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG
+#elif (defined(__vms) || defined(__VMS)) && (__INITIAL_POINTER_SIZE+0 == 64)
+# define LZO_SIZEOF_VOID_P 8
+# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG
+# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG
+#elif (LZO_ARCH_SPU)
+# if 0
+# define __LZO_WORDSIZE 16
+# endif
+# define LZO_SIZEOF_VOID_P 4
+#else
+# define LZO_SIZEOF_VOID_P LZO_SIZEOF_LONG
+#endif
+#endif
+#if !defined(LZO_WORDSIZE)
+# if defined(__LZO_WORDSIZE)
+# define LZO_WORDSIZE __LZO_WORDSIZE
+# else
+# define LZO_WORDSIZE LZO_SIZEOF_VOID_P
+# endif
+#endif
+#if !defined(LZO_SIZEOF_SIZE_T)
+#if (LZO_ARCH_I086 || LZO_ARCH_M16C)
+# define LZO_SIZEOF_SIZE_T 2
+#else
+# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_VOID_P
+#endif
+#endif
+#if !defined(LZO_SIZEOF_PTRDIFF_T)
+#if (LZO_ARCH_I086)
+# if (LZO_MM_TINY || LZO_MM_SMALL || LZO_MM_MEDIUM || LZO_MM_HUGE)
+# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_VOID_P
+# elif (LZO_MM_COMPACT || LZO_MM_LARGE)
+# if (LZO_CC_BORLANDC || LZO_CC_TURBOC)
+# define LZO_SIZEOF_PTRDIFF_T 4
+# else
+# define LZO_SIZEOF_PTRDIFF_T 2
+# endif
+# else
+# error "LZO_MM"
+# endif
+#else
+# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_SIZE_T
+#endif
+#endif
+#if (LZO_ABI_NEUTRAL_ENDIAN)
+# undef LZO_ABI_BIG_ENDIAN
+# undef LZO_ABI_LITTLE_ENDIAN
+#elif !(LZO_ABI_BIG_ENDIAN) && !(LZO_ABI_LITTLE_ENDIAN)
+#if (LZO_ARCH_ALPHA) && (LZO_ARCH_CRAY_MPP)
+# define LZO_ABI_BIG_ENDIAN 1
+#elif (LZO_ARCH_IA64) && (LZO_OS_POSIX_LINUX || LZO_OS_WIN64)
+# define LZO_ABI_LITTLE_ENDIAN 1
+#elif (LZO_ARCH_ALPHA || LZO_ARCH_AMD64 || LZO_ARCH_BLACKFIN || LZO_ARCH_CRIS || LZO_ARCH_I086 || LZO_ARCH_I386 || LZO_ARCH_MSP430)
+# define LZO_ABI_LITTLE_ENDIAN 1
+#elif (LZO_ARCH_AVR32 || LZO_ARCH_M68K || LZO_ARCH_S390)
+# define LZO_ABI_BIG_ENDIAN 1
+#elif 1 && defined(__IAR_SYSTEMS_ICC__) && defined(__LITTLE_ENDIAN__)
+# if (__LITTLE_ENDIAN__ == 1)
+# define LZO_ABI_LITTLE_ENDIAN 1
+# else
+# define LZO_ABI_BIG_ENDIAN 1
+# endif
+#elif 1 && defined(__BIG_ENDIAN__) && !defined(__LITTLE_ENDIAN__)
+# define LZO_ABI_BIG_ENDIAN 1
+#elif 1 && defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__)
+# define LZO_ABI_LITTLE_ENDIAN 1
+#elif 1 && (LZO_ARCH_ARM) && defined(__ARMEB__) && !defined(__ARMEL__)
+# define LZO_ABI_BIG_ENDIAN 1
+#elif 1 && (LZO_ARCH_ARM) && defined(__ARMEL__) && !defined(__ARMEB__)
+# define LZO_ABI_LITTLE_ENDIAN 1
+#elif 1 && (LZO_ARCH_MIPS) && defined(__MIPSEB__) && !defined(__MIPSEL__)
+# define LZO_ABI_BIG_ENDIAN 1
+#elif 1 && (LZO_ARCH_MIPS) && defined(__MIPSEL__) && !defined(__MIPSEB__)
+# define LZO_ABI_LITTLE_ENDIAN 1
+#endif
+#endif
+#if (LZO_ABI_BIG_ENDIAN) && (LZO_ABI_LITTLE_ENDIAN)
+# error "this should not happen"
+#endif
+#if (LZO_ABI_BIG_ENDIAN)
+# define LZO_INFO_ABI_ENDIAN "be"
+#elif (LZO_ABI_LITTLE_ENDIAN)
+# define LZO_INFO_ABI_ENDIAN "le"
+#elif (LZO_ABI_NEUTRAL_ENDIAN)
+# define LZO_INFO_ABI_ENDIAN "neutral"
+#endif
+#if (LZO_SIZEOF_INT == 1 && LZO_SIZEOF_LONG == 2 && LZO_SIZEOF_VOID_P == 2)
+# define LZO_ABI_I8LP16 1
+# define LZO_INFO_ABI_PM "i8lp16"
+#elif (LZO_SIZEOF_INT == 2 && LZO_SIZEOF_LONG == 2 && LZO_SIZEOF_VOID_P == 2)
+# define LZO_ABI_ILP16 1
+# define LZO_INFO_ABI_PM "ilp16"
+#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 4 && LZO_SIZEOF_VOID_P == 4)
+# define LZO_ABI_ILP32 1
+# define LZO_INFO_ABI_PM "ilp32"
+#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 4 && LZO_SIZEOF_VOID_P == 8 && LZO_SIZEOF_SIZE_T == 8)
+# define LZO_ABI_LLP64 1
+# define LZO_INFO_ABI_PM "llp64"
+#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 8 && LZO_SIZEOF_VOID_P == 8)
+# define LZO_ABI_LP64 1
+# define LZO_INFO_ABI_PM "lp64"
+#elif (LZO_SIZEOF_INT == 8 && LZO_SIZEOF_LONG == 8 && LZO_SIZEOF_VOID_P == 8)
+# define LZO_ABI_ILP64 1
+# define LZO_INFO_ABI_PM "ilp64"
+#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 8 && LZO_SIZEOF_VOID_P == 4)
+# define LZO_ABI_IP32L64 1
+# define LZO_INFO_ABI_PM "ip32l64"
+#endif
+#if !defined(__LZO_LIBC_OVERRIDE)
+#if (LZO_LIBC_NAKED)
+# define LZO_INFO_LIBC "naked"
+#elif (LZO_LIBC_FREESTANDING)
+# define LZO_INFO_LIBC "freestanding"
+#elif (LZO_LIBC_MOSTLY_FREESTANDING)
+# define LZO_INFO_LIBC "mfreestanding"
+#elif (LZO_LIBC_ISOC90)
+# define LZO_INFO_LIBC "isoc90"
+#elif (LZO_LIBC_ISOC99)
+# define LZO_INFO_LIBC "isoc99"
+#elif defined(__dietlibc__)
+# define LZO_LIBC_DIETLIBC 1
+# define LZO_INFO_LIBC "dietlibc"
+#elif defined(_NEWLIB_VERSION)
+# define LZO_LIBC_NEWLIB 1
+# define LZO_INFO_LIBC "newlib"
+#elif defined(__UCLIBC__) && defined(__UCLIBC_MAJOR__) && defined(__UCLIBC_MINOR__)
+# if defined(__UCLIBC_SUBLEVEL__)
+# define LZO_LIBC_UCLIBC (__UCLIBC_MAJOR__ * 0x10000L + __UCLIBC_MINOR__ * 0x100 + __UCLIBC_SUBLEVEL__)
+# else
+# define LZO_LIBC_UCLIBC 0x00090bL
+# endif
+# define LZO_INFO_LIBC "uclibc"
+#elif defined(__GLIBC__) && defined(__GLIBC_MINOR__)
+# define LZO_LIBC_GLIBC (__GLIBC__ * 0x10000L + __GLIBC_MINOR__ * 0x100)
+# define LZO_INFO_LIBC "glibc"
+#elif (LZO_CC_MWERKS) && defined(__MSL__)
+# define LZO_LIBC_MSL __MSL__
+# define LZO_INFO_LIBC "msl"
+#elif 1 && defined(__IAR_SYSTEMS_ICC__)
+# define LZO_LIBC_ISOC90 1
+# define LZO_INFO_LIBC "isoc90"
+#else
+# define LZO_LIBC_DEFAULT 1
+# define LZO_INFO_LIBC "default"
+#endif
+#endif
+#if !defined(__lzo_gnuc_extension__)
+#if (LZO_CC_GNUC >= 0x020800ul)
+# define __lzo_gnuc_extension__ __extension__
+#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE)
+# define __lzo_gnuc_extension__ __extension__
+#else
+# define __lzo_gnuc_extension__ /*empty*/
+#endif
+#endif
+#if !defined(__lzo_ua_volatile)
+# define __lzo_ua_volatile volatile
+#endif
+#if !defined(__lzo_alignof)
+#if (LZO_CC_CILLY || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI)
+# define __lzo_alignof(e) __alignof__(e)
+#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 700))
+# define __lzo_alignof(e) __alignof__(e)
+#elif (LZO_CC_MSC && (_MSC_VER >= 1300))
+# define __lzo_alignof(e) __alignof(e)
+#elif (LZO_CC_SUNPROC && (LZO_CC_SUNPROC >= 0x5100))
+# define __lzo_alignof(e) __alignof__(e)
+#endif
+#endif
+#if defined(__lzo_alignof)
+# define __lzo_HAVE_alignof 1
+#endif
+#if !defined(__lzo_constructor)
+#if (LZO_CC_GNUC >= 0x030400ul)
+# define __lzo_constructor __attribute__((__constructor__,__used__))
+#elif (LZO_CC_GNUC >= 0x020700ul)
+# define __lzo_constructor __attribute__((__constructor__))
+#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE)
+# define __lzo_constructor __attribute__((__constructor__))
+#endif
+#endif
+#if defined(__lzo_constructor)
+# define __lzo_HAVE_constructor 1
+#endif
+#if !defined(__lzo_destructor)
+#if (LZO_CC_GNUC >= 0x030400ul)
+# define __lzo_destructor __attribute__((__destructor__,__used__))
+#elif (LZO_CC_GNUC >= 0x020700ul)
+# define __lzo_destructor __attribute__((__destructor__))
+#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE)
+# define __lzo_destructor __attribute__((__destructor__))
+#endif
+#endif
+#if defined(__lzo_destructor)
+# define __lzo_HAVE_destructor 1
+#endif
+#if (__lzo_HAVE_destructor) && !(__lzo_HAVE_constructor)
+# error "this should not happen"
+#endif
+#if !defined(__lzo_inline)
+#if (LZO_CC_TURBOC && (__TURBOC__ <= 0x0295))
+#elif defined(__cplusplus)
+# define __lzo_inline inline
+#elif (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0550))
+# define __lzo_inline __inline
+#elif (LZO_CC_CILLY || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI)
+# define __lzo_inline __inline__
+#elif (LZO_CC_DMC)
+# define __lzo_inline __inline
+#elif (LZO_CC_INTELC)
+# define __lzo_inline __inline
+#elif (LZO_CC_MWERKS && (__MWERKS__ >= 0x2405))
+# define __lzo_inline __inline
+#elif (LZO_CC_MSC && (_MSC_VER >= 900))
+# define __lzo_inline __inline
+#elif (LZO_CC_SUNPROC && (LZO_CC_SUNPROC >= 0x5100))
+# define __lzo_inline __inline__
+#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
+# define __lzo_inline inline
+#endif
+#endif
+#if defined(__lzo_inline)
+# define __lzo_HAVE_inline 1
+#else
+# define __lzo_inline /*empty*/
+#endif
+#if !defined(__lzo_forceinline)
+#if (LZO_CC_GNUC >= 0x030200ul)
+# define __lzo_forceinline __inline__ __attribute__((__always_inline__))
+#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 450) && LZO_CC_SYNTAX_MSC)
+# define __lzo_forceinline __forceinline
+#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 800) && LZO_CC_SYNTAX_GNUC)
+# define __lzo_forceinline __inline__ __attribute__((__always_inline__))
+#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE)
+# define __lzo_forceinline __inline__ __attribute__((__always_inline__))
+#elif (LZO_CC_MSC && (_MSC_VER >= 1200))
+# define __lzo_forceinline __forceinline
+#elif (LZO_CC_SUNPROC && (LZO_CC_SUNPROC >= 0x5100))
+# define __lzo_forceinline __inline__ __attribute__((__always_inline__))
+#endif
+#endif
+#if defined(__lzo_forceinline)
+# define __lzo_HAVE_forceinline 1
+#else
+# define __lzo_forceinline /*empty*/
+#endif
+#if !defined(__lzo_noinline)
+#if 1 && (LZO_ARCH_I386) && (LZO_CC_GNUC >= 0x040000ul) && (LZO_CC_GNUC < 0x040003ul)
+# define __lzo_noinline __attribute__((__noinline__,__used__))
+#elif (LZO_CC_GNUC >= 0x030200ul)
+# define __lzo_noinline __attribute__((__noinline__))
+#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 600) && LZO_CC_SYNTAX_MSC)
+# define __lzo_noinline __declspec(noinline)
+#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 800) && LZO_CC_SYNTAX_GNUC)
+# define __lzo_noinline __attribute__((__noinline__))
+#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE)
+# define __lzo_noinline __attribute__((__noinline__))
+#elif (LZO_CC_MSC && (_MSC_VER >= 1300))
+# define __lzo_noinline __declspec(noinline)
+#elif (LZO_CC_MWERKS && (__MWERKS__ >= 0x3200) && (LZO_OS_WIN32 || LZO_OS_WIN64))
+# if defined(__cplusplus)
+# else
+# define __lzo_noinline __declspec(noinline)
+# endif
+#elif (LZO_CC_SUNPROC && (LZO_CC_SUNPROC >= 0x5100))
+# define __lzo_noinline __attribute__((__noinline__))
+#endif
+#endif
+#if defined(__lzo_noinline)
+# define __lzo_HAVE_noinline 1
+#else
+# define __lzo_noinline /*empty*/
+#endif
+#if (__lzo_HAVE_forceinline || __lzo_HAVE_noinline) && !(__lzo_HAVE_inline)
+# error "this should not happen"
+#endif
+#if !defined(__lzo_noreturn)
+#if (LZO_CC_GNUC >= 0x020700ul)
+# define __lzo_noreturn __attribute__((__noreturn__))
+#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 450) && LZO_CC_SYNTAX_MSC)
+# define __lzo_noreturn __declspec(noreturn)
+#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 600) && LZO_CC_SYNTAX_GNUC)
+# define __lzo_noreturn __attribute__((__noreturn__))
+#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE)
+# define __lzo_noreturn __attribute__((__noreturn__))
+#elif (LZO_CC_MSC && (_MSC_VER >= 1200))
+# define __lzo_noreturn __declspec(noreturn)
+#endif
+#endif
+#if defined(__lzo_noreturn)
+# define __lzo_HAVE_noreturn 1
+#else
+# define __lzo_noreturn /*empty*/
+#endif
+#if !defined(__lzo_nothrow)
+#if (LZO_CC_GNUC >= 0x030300ul)
+# define __lzo_nothrow __attribute__((__nothrow__))
+#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 450) && LZO_CC_SYNTAX_MSC) && defined(__cplusplus)
+# define __lzo_nothrow __declspec(nothrow)
+#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 900) && LZO_CC_SYNTAX_GNUC)
+# define __lzo_nothrow __attribute__((__nothrow__))
+#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE)
+# define __lzo_nothrow __attribute__((__nothrow__))
+#elif (LZO_CC_MSC && (_MSC_VER >= 1200)) && defined(__cplusplus)
+# define __lzo_nothrow __declspec(nothrow)
+#endif
+#endif
+#if defined(__lzo_nothrow)
+# define __lzo_HAVE_nothrow 1
+#else
+# define __lzo_nothrow /*empty*/
+#endif
+#if !defined(__lzo_restrict)
+#if (LZO_CC_GNUC >= 0x030400ul)
+# define __lzo_restrict __restrict__
+#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 600) && LZO_CC_SYNTAX_GNUC)
+# define __lzo_restrict __restrict__
+#elif (LZO_CC_CLANG || LZO_CC_LLVM)
+# define __lzo_restrict __restrict__
+#elif (LZO_CC_MSC && (_MSC_VER >= 1400))
+# define __lzo_restrict __restrict
+#endif
+#endif
+#if defined(__lzo_restrict)
+# define __lzo_HAVE_restrict 1
+#else
+# define __lzo_restrict /*empty*/
+#endif
+#if !defined(__lzo_likely) && !defined(__lzo_unlikely)
+#if (LZO_CC_GNUC >= 0x030200ul)
+# define __lzo_likely(e) (__builtin_expect(!!(e),1))
+# define __lzo_unlikely(e) (__builtin_expect(!!(e),0))
+#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 800))
+# define __lzo_likely(e) (__builtin_expect(!!(e),1))
+# define __lzo_unlikely(e) (__builtin_expect(!!(e),0))
+#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE)
+# define __lzo_likely(e) (__builtin_expect(!!(e),1))
+# define __lzo_unlikely(e) (__builtin_expect(!!(e),0))
+#endif
+#endif
+#if defined(__lzo_likely)
+# define __lzo_HAVE_likely 1
+#else
+# define __lzo_likely(e) (e)
+#endif
+#if defined(__lzo_unlikely)
+# define __lzo_HAVE_unlikely 1
+#else
+# define __lzo_unlikely(e) (e)
+#endif
+#if !defined(LZO_UNUSED)
+# if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0600))
+# define LZO_UNUSED(var) ((void) &var)
+# elif (LZO_CC_BORLANDC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PELLESC || LZO_CC_TURBOC)
+# define LZO_UNUSED(var) if (&var) ; else
+# elif (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE)
+# define LZO_UNUSED(var) ((void) var)
+# elif (LZO_CC_MSC && (_MSC_VER < 900))
+# define LZO_UNUSED(var) if (&var) ; else
+# elif (LZO_CC_KEILC)
+# define LZO_UNUSED(var) {extern int __lzo_unused[1-2*!(sizeof(var)>0)];}
+# elif (LZO_CC_PACIFICC)
+# define LZO_UNUSED(var) ((void) sizeof(var))
+# elif (LZO_CC_WATCOMC) && defined(__cplusplus)
+# define LZO_UNUSED(var) ((void) var)
+# else
+# define LZO_UNUSED(var) ((void) &var)
+# endif
+#endif
+#if !defined(LZO_UNUSED_FUNC)
+# if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0600))
+# define LZO_UNUSED_FUNC(func) ((void) func)
+# elif (LZO_CC_BORLANDC || LZO_CC_NDPC || LZO_CC_TURBOC)
+# define LZO_UNUSED_FUNC(func) if (func) ; else
+# elif (LZO_CC_CLANG || LZO_CC_LLVM)
+# define LZO_UNUSED_FUNC(func) ((void) &func)
+# elif (LZO_CC_MSC && (_MSC_VER < 900))
+# define LZO_UNUSED_FUNC(func) if (func) ; else
+# elif (LZO_CC_MSC)
+# define LZO_UNUSED_FUNC(func) ((void) &func)
+# elif (LZO_CC_KEILC || LZO_CC_PELLESC)
+# define LZO_UNUSED_FUNC(func) {extern int __lzo_unused[1-2*!(sizeof((int)func)>0)];}
+# else
+# define LZO_UNUSED_FUNC(func) ((void) func)
+# endif
+#endif
+#if !defined(LZO_UNUSED_LABEL)
+# if (LZO_CC_WATCOMC) && defined(__cplusplus)
+# define LZO_UNUSED_LABEL(l) switch(0) case 1:goto l
+# elif (LZO_CC_CLANG || LZO_CC_INTELC || LZO_CC_WATCOMC)
+# define LZO_UNUSED_LABEL(l) if (0) goto l
+# else
+# define LZO_UNUSED_LABEL(l) switch(0) case 1:goto l
+# endif
+#endif
+#if !defined(LZO_DEFINE_UNINITIALIZED_VAR)
+# if 0
+# define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init) type var
+# elif 0 && (LZO_CC_GNUC)
+# define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init) type var = var
+# else
+# define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init) type var = init
+# endif
+#endif
+#if !defined(LZO_UNCONST_CAST)
+# if 0 && defined(__cplusplus)
+# define LZO_UNCONST_CAST(t,e) (const_cast<t> (e))
+# elif (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE)
+# define LZO_UNCONST_CAST(t,e) ((t) ((void *) ((char *) ((lzo_uintptr_t) ((const void *) (e))))))
+# else
+# define LZO_UNCONST_CAST(t,e) ((t) ((void *) ((char *) ((const void *) (e)))))
+# endif
+#endif
+#if !defined(LZO_COMPILE_TIME_ASSERT_HEADER)
+# if (LZO_CC_AZTECC || LZO_CC_ZORTECHC)
+# define LZO_COMPILE_TIME_ASSERT_HEADER(e) extern int __lzo_cta[1-!(e)];
+# elif (LZO_CC_DMC || LZO_CC_SYMANTECC)
+# define LZO_COMPILE_TIME_ASSERT_HEADER(e) extern int __lzo_cta[1u-2*!(e)];
+# elif (LZO_CC_TURBOC && (__TURBOC__ == 0x0295))
+# define LZO_COMPILE_TIME_ASSERT_HEADER(e) extern int __lzo_cta[1-!(e)];
+# else
+# define LZO_COMPILE_TIME_ASSERT_HEADER(e) extern int __lzo_cta[1-2*!(e)];
+# endif
+#endif
+#if !defined(LZO_COMPILE_TIME_ASSERT)
+# if (LZO_CC_AZTECC)
+# define LZO_COMPILE_TIME_ASSERT(e) {typedef int __lzo_cta_t[1-!(e)];}
+# elif (LZO_CC_DMC || LZO_CC_PACIFICC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC)
+# define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break;
+# elif (LZO_CC_MSC && (_MSC_VER < 900))
+# define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break;
+# elif (LZO_CC_TURBOC && (__TURBOC__ == 0x0295))
+# define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break;
+# else
+# define LZO_COMPILE_TIME_ASSERT(e) {typedef int __lzo_cta_t[1-2*!(e)];}
+# endif
+#endif
+#if (LZO_ARCH_I086 || LZO_ARCH_I386) && (LZO_OS_DOS16 || LZO_OS_DOS32 || LZO_OS_OS2 || LZO_OS_OS216 || LZO_OS_WIN16 || LZO_OS_WIN32 || LZO_OS_WIN64)
+# if (LZO_CC_GNUC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PACIFICC)
+# elif (LZO_CC_DMC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC)
+# define __lzo_cdecl __cdecl
+# define __lzo_cdecl_atexit /*empty*/
+# define __lzo_cdecl_main __cdecl
+# if (LZO_OS_OS2 && (LZO_CC_DMC || LZO_CC_SYMANTECC))
+# define __lzo_cdecl_qsort __pascal
+# elif (LZO_OS_OS2 && (LZO_CC_ZORTECHC))
+# define __lzo_cdecl_qsort _stdcall
+# else
+# define __lzo_cdecl_qsort __cdecl
+# endif
+# elif (LZO_CC_WATCOMC)
+# define __lzo_cdecl __cdecl
+# else
+# define __lzo_cdecl __cdecl
+# define __lzo_cdecl_atexit __cdecl
+# define __lzo_cdecl_main __cdecl
+# define __lzo_cdecl_qsort __cdecl
+# endif
+# if (LZO_CC_GNUC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PACIFICC || LZO_CC_WATCOMC)
+# elif (LZO_OS_OS2 && (LZO_CC_DMC || LZO_CC_SYMANTECC))
+# define __lzo_cdecl_sighandler __pascal
+# elif (LZO_OS_OS2 && (LZO_CC_ZORTECHC))
+# define __lzo_cdecl_sighandler _stdcall
+# elif (LZO_CC_MSC && (_MSC_VER >= 1400)) && defined(_M_CEE_PURE)
+# define __lzo_cdecl_sighandler __clrcall
+# elif (LZO_CC_MSC && (_MSC_VER >= 600 && _MSC_VER < 700))
+# if defined(_DLL)
+# define __lzo_cdecl_sighandler _far _cdecl _loadds
+# elif defined(_MT)
+# define __lzo_cdecl_sighandler _far _cdecl
+# else
+# define __lzo_cdecl_sighandler _cdecl
+# endif
+# else
+# define __lzo_cdecl_sighandler __cdecl
+# endif
+#elif (LZO_ARCH_I386) && (LZO_CC_WATCOMC)
+# define __lzo_cdecl __cdecl
+#elif (LZO_ARCH_M68K && LZO_OS_TOS && (LZO_CC_PUREC || LZO_CC_TURBOC))
+# define __lzo_cdecl cdecl
+#endif
+#if !defined(__lzo_cdecl)
+# define __lzo_cdecl /*empty*/
+#endif
+#if !defined(__lzo_cdecl_atexit)
+# define __lzo_cdecl_atexit /*empty*/
+#endif
+#if !defined(__lzo_cdecl_main)
+# define __lzo_cdecl_main /*empty*/
+#endif
+#if !defined(__lzo_cdecl_qsort)
+# define __lzo_cdecl_qsort /*empty*/
+#endif
+#if !defined(__lzo_cdecl_sighandler)
+# define __lzo_cdecl_sighandler /*empty*/
+#endif
+#if !defined(__lzo_cdecl_va)
+# define __lzo_cdecl_va __lzo_cdecl
+#endif
+#if !(LZO_CFG_NO_WINDOWS_H)
+#if (LZO_OS_CYGWIN || (LZO_OS_EMX && defined(__RSXNT__)) || LZO_OS_WIN32 || LZO_OS_WIN64)
+# if (LZO_CC_WATCOMC && (__WATCOMC__ < 1000))
+# elif (LZO_OS_WIN32 && LZO_CC_GNUC) && defined(__PW32__)
+# elif ((LZO_OS_CYGWIN || defined(__MINGW32__)) && (LZO_CC_GNUC && (LZO_CC_GNUC < 0x025f00ul)))
+# else
+# define LZO_HAVE_WINDOWS_H 1
+# endif
+#endif
+#endif
+#if (LZO_ARCH_ALPHA)
+# define LZO_OPT_AVOID_UINT_INDEX 1
+# define LZO_OPT_AVOID_SHORT 1
+# define LZO_OPT_AVOID_USHORT 1
+#elif (LZO_ARCH_AMD64)
+# define LZO_OPT_AVOID_INT_INDEX 1
+# define LZO_OPT_AVOID_UINT_INDEX 1
+# define LZO_OPT_UNALIGNED16 1
+# define LZO_OPT_UNALIGNED32 1
+# define LZO_OPT_UNALIGNED64 1
+#elif (LZO_ARCH_ARM && LZO_ARCH_ARM_THUMB)
+#elif (LZO_ARCH_ARM)
+# define LZO_OPT_AVOID_SHORT 1
+# define LZO_OPT_AVOID_USHORT 1
+#elif (LZO_ARCH_CRIS)
+# define LZO_OPT_UNALIGNED16 1
+# define LZO_OPT_UNALIGNED32 1
+#elif (LZO_ARCH_I386)
+# define LZO_OPT_UNALIGNED16 1
+# define LZO_OPT_UNALIGNED32 1
+#elif (LZO_ARCH_IA64)
+# define LZO_OPT_AVOID_INT_INDEX 1
+# define LZO_OPT_AVOID_UINT_INDEX 1
+# define LZO_OPT_PREFER_POSTINC 1
+#elif (LZO_ARCH_M68K)
+# define LZO_OPT_PREFER_POSTINC 1
+# define LZO_OPT_PREFER_PREDEC 1
+# if defined(__mc68020__) && !defined(__mcoldfire__)
+# define LZO_OPT_UNALIGNED16 1
+# define LZO_OPT_UNALIGNED32 1
+# endif
+#elif (LZO_ARCH_MIPS)
+# define LZO_OPT_AVOID_UINT_INDEX 1
+#elif (LZO_ARCH_POWERPC)
+# define LZO_OPT_PREFER_PREINC 1
+# define LZO_OPT_PREFER_PREDEC 1
+# if (LZO_ABI_BIG_ENDIAN)
+# define LZO_OPT_UNALIGNED16 1
+# define LZO_OPT_UNALIGNED32 1
+# endif
+#elif (LZO_ARCH_S390)
+# define LZO_OPT_UNALIGNED16 1
+# define LZO_OPT_UNALIGNED32 1
+# if (LZO_SIZEOF_SIZE_T == 8)
+# define LZO_OPT_UNALIGNED64 1
+# endif
+#elif (LZO_ARCH_SH)
+# define LZO_OPT_PREFER_POSTINC 1
+# define LZO_OPT_PREFER_PREDEC 1
+#endif
+#ifndef LZO_CFG_NO_INLINE_ASM
+#if (LZO_CC_LLVM)
+# define LZO_CFG_NO_INLINE_ASM 1
+#endif
+#endif
+#ifndef LZO_CFG_NO_UNALIGNED
+#if (LZO_ABI_NEUTRAL_ENDIAN) || (LZO_ARCH_GENERIC)
+# define LZO_CFG_NO_UNALIGNED 1
+#endif
+#endif
+#if (LZO_CFG_NO_UNALIGNED)
+# undef LZO_OPT_UNALIGNED16
+# undef LZO_OPT_UNALIGNED32
+# undef LZO_OPT_UNALIGNED64
+#endif
+#if (LZO_CFG_NO_INLINE_ASM)
+#elif (LZO_ARCH_I386 && (LZO_OS_DOS32 || LZO_OS_WIN32) && (LZO_CC_DMC || LZO_CC_INTELC || LZO_CC_MSC || LZO_CC_PELLESC))
+# define LZO_ASM_SYNTAX_MSC 1
+#elif (LZO_OS_WIN64 && (LZO_CC_DMC || LZO_CC_INTELC || LZO_CC_MSC || LZO_CC_PELLESC))
+#elif (LZO_ARCH_I386 && LZO_CC_GNUC && (LZO_CC_GNUC == 0x011f00ul))
+#elif (LZO_ARCH_I386 && (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_INTELC || LZO_CC_PATHSCALE))
+# define LZO_ASM_SYNTAX_GNUC 1
+#elif (LZO_ARCH_AMD64 && (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_INTELC || LZO_CC_PATHSCALE))
+# define LZO_ASM_SYNTAX_GNUC 1
+#endif
+#if (LZO_ASM_SYNTAX_GNUC)
+#if (LZO_ARCH_I386 && LZO_CC_GNUC && (LZO_CC_GNUC < 0x020000ul))
+# define __LZO_ASM_CLOBBER "ax"
+#elif (LZO_CC_INTELC)
+# define __LZO_ASM_CLOBBER "memory"
+#else
+# define __LZO_ASM_CLOBBER "cc", "memory"
+#endif
+#endif
+#if defined(__LZO_INFOSTR_MM)
+#elif (LZO_MM_FLAT) && (defined(__LZO_INFOSTR_PM) || defined(LZO_INFO_ABI_PM))
+# define __LZO_INFOSTR_MM ""
+#elif defined(LZO_INFO_MM)
+# define __LZO_INFOSTR_MM "." LZO_INFO_MM
+#else
+# define __LZO_INFOSTR_MM ""
+#endif
+#if defined(__LZO_INFOSTR_PM)
+#elif defined(LZO_INFO_ABI_PM)
+# define __LZO_INFOSTR_PM "." LZO_INFO_ABI_PM
+#else
+# define __LZO_INFOSTR_PM ""
+#endif
+#if defined(__LZO_INFOSTR_ENDIAN)
+#elif defined(LZO_INFO_ABI_ENDIAN)
+# define __LZO_INFOSTR_ENDIAN "." LZO_INFO_ABI_ENDIAN
+#else
+# define __LZO_INFOSTR_ENDIAN ""
+#endif
+#if defined(__LZO_INFOSTR_OSNAME)
+#elif defined(LZO_INFO_OS_CONSOLE)
+# define __LZO_INFOSTR_OSNAME LZO_INFO_OS "." LZO_INFO_OS_CONSOLE
+#elif defined(LZO_INFO_OS_POSIX)
+# define __LZO_INFOSTR_OSNAME LZO_INFO_OS "." LZO_INFO_OS_POSIX
+#else
+# define __LZO_INFOSTR_OSNAME LZO_INFO_OS
+#endif
+#if defined(__LZO_INFOSTR_LIBC)
+#elif defined(LZO_INFO_LIBC)
+# define __LZO_INFOSTR_LIBC "." LZO_INFO_LIBC
+#else
+# define __LZO_INFOSTR_LIBC ""
+#endif
+#if defined(__LZO_INFOSTR_CCVER)
+#elif defined(LZO_INFO_CCVER)
+# define __LZO_INFOSTR_CCVER " " LZO_INFO_CCVER
+#else
+# define __LZO_INFOSTR_CCVER ""
+#endif
+#define LZO_INFO_STRING \
+ LZO_INFO_ARCH __LZO_INFOSTR_MM __LZO_INFOSTR_PM __LZO_INFOSTR_ENDIAN \
+ " " __LZO_INFOSTR_OSNAME __LZO_INFOSTR_LIBC " " LZO_INFO_CC __LZO_INFOSTR_CCVER
+
+#endif /* already included */
+
+/* vim:set ts=4 et: */
--- /dev/null
+/* minilzo.c -- mini subset of the LZO real-time data compression library
+
+ This file is part of the LZO real-time data compression library.
+
+ Copyright (C) 2011 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2010 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2009 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
+ All Rights Reserved.
+
+ The LZO library 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 2 of
+ the License, or (at your option) any later version.
+
+ The LZO library 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 the LZO library; see the file COPYING.
+ If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ Markus F.X.J. Oberhumer
+ <markus@oberhumer.com>
+ http://www.oberhumer.com/opensource/lzo/
+ */
+
+/*
+ * NOTE:
+ * the full LZO package can be found at
+ * http://www.oberhumer.com/opensource/lzo/
+ */
+
+#define __LZO_IN_MINILZO 1
+
+#if defined(LZO_CFG_FREESTANDING)
+# undef MINILZO_HAVE_CONFIG_H
+# define LZO_LIBC_FREESTANDING 1
+# define LZO_OS_FREESTANDING 1
+#endif
+
+#ifdef MINILZO_HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <limits.h>
+#include <stddef.h>
+#if defined(MINILZO_CFG_USE_INTERNAL_LZODEFS)
+
+#ifndef __LZODEFS_H_INCLUDED
+#define __LZODEFS_H_INCLUDED 1
+
+#if defined(__CYGWIN32__) && !defined(__CYGWIN__)
+# define __CYGWIN__ __CYGWIN32__
+#endif
+#if defined(__IBMCPP__) && !defined(__IBMC__)
+# define __IBMC__ __IBMCPP__
+#endif
+#if defined(__ICL) && defined(_WIN32) && !defined(__INTEL_COMPILER)
+# define __INTEL_COMPILER __ICL
+#endif
+#if 1 && defined(__INTERIX) && defined(__GNUC__) && !defined(_ALL_SOURCE)
+# define _ALL_SOURCE 1
+#endif
+#if defined(__mips__) && defined(__R5900__)
+# if !defined(__LONG_MAX__)
+# define __LONG_MAX__ 9223372036854775807L
+# endif
+#endif
+#if defined(__INTEL_COMPILER) && defined(__linux__)
+# pragma warning(disable: 193)
+#endif
+#if defined(__KEIL__) && defined(__C166__)
+# pragma warning disable = 322
+#elif 0 && defined(__C251__)
+# pragma warning disable = 322
+#endif
+#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) && !defined(__MWERKS__)
+# if (_MSC_VER >= 1300)
+# pragma warning(disable: 4668)
+# endif
+#endif
+#if 0 && defined(__WATCOMC__)
+# if (__WATCOMC__ >= 1050) && (__WATCOMC__ < 1060)
+# pragma warning 203 9
+# endif
+#endif
+#if defined(__BORLANDC__) && defined(__MSDOS__) && !defined(__FLAT__)
+# pragma option -h
+#endif
+#if 0
+#define LZO_0xffffL 0xfffful
+#define LZO_0xffffffffL 0xfffffffful
+#else
+#define LZO_0xffffL 65535ul
+#define LZO_0xffffffffL 4294967295ul
+#endif
+#if (LZO_0xffffL == LZO_0xffffffffL)
+# error "your preprocessor is broken 1"
+#endif
+#if (16ul * 16384ul != 262144ul)
+# error "your preprocessor is broken 2"
+#endif
+#if 0
+#if (32767 >= 4294967295ul)
+# error "your preprocessor is broken 3"
+#endif
+#if (65535u >= 4294967295ul)
+# error "your preprocessor is broken 4"
+#endif
+#endif
+#if (UINT_MAX == LZO_0xffffL)
+#if defined(__ZTC__) && defined(__I86__) && !defined(__OS2__)
+# if !defined(MSDOS)
+# define MSDOS 1
+# endif
+# if !defined(_MSDOS)
+# define _MSDOS 1
+# endif
+#elif 0 && defined(__VERSION) && defined(MB_LEN_MAX)
+# if (__VERSION == 520) && (MB_LEN_MAX == 1)
+# if !defined(__AZTEC_C__)
+# define __AZTEC_C__ __VERSION
+# endif
+# if !defined(__DOS__)
+# define __DOS__ 1
+# endif
+# endif
+#endif
+#endif
+#if defined(_MSC_VER) && defined(M_I86HM) && (UINT_MAX == LZO_0xffffL)
+# define ptrdiff_t long
+# define _PTRDIFF_T_DEFINED 1
+#endif
+#if (UINT_MAX == LZO_0xffffL)
+# undef __LZO_RENAME_A
+# undef __LZO_RENAME_B
+# if defined(__AZTEC_C__) && defined(__DOS__)
+# define __LZO_RENAME_A 1
+# elif defined(_MSC_VER) && defined(MSDOS)
+# if (_MSC_VER < 600)
+# define __LZO_RENAME_A 1
+# elif (_MSC_VER < 700)
+# define __LZO_RENAME_B 1
+# endif
+# elif defined(__TSC__) && defined(__OS2__)
+# define __LZO_RENAME_A 1
+# elif defined(__MSDOS__) && defined(__TURBOC__) && (__TURBOC__ < 0x0410)
+# define __LZO_RENAME_A 1
+# elif defined(__PACIFIC__) && defined(DOS)
+# if !defined(__far)
+# define __far far
+# endif
+# if !defined(__near)
+# define __near near
+# endif
+# endif
+# if defined(__LZO_RENAME_A)
+# if !defined(__cdecl)
+# define __cdecl cdecl
+# endif
+# if !defined(__far)
+# define __far far
+# endif
+# if !defined(__huge)
+# define __huge huge
+# endif
+# if !defined(__near)
+# define __near near
+# endif
+# if !defined(__pascal)
+# define __pascal pascal
+# endif
+# if !defined(__huge)
+# define __huge huge
+# endif
+# elif defined(__LZO_RENAME_B)
+# if !defined(__cdecl)
+# define __cdecl _cdecl
+# endif
+# if !defined(__far)
+# define __far _far
+# endif
+# if !defined(__huge)
+# define __huge _huge
+# endif
+# if !defined(__near)
+# define __near _near
+# endif
+# if !defined(__pascal)
+# define __pascal _pascal
+# endif
+# elif (defined(__PUREC__) || defined(__TURBOC__)) && defined(__TOS__)
+# if !defined(__cdecl)
+# define __cdecl cdecl
+# endif
+# if !defined(__pascal)
+# define __pascal pascal
+# endif
+# endif
+# undef __LZO_RENAME_A
+# undef __LZO_RENAME_B
+#endif
+#if (UINT_MAX == LZO_0xffffL)
+#if defined(__AZTEC_C__) && defined(__DOS__)
+# define LZO_BROKEN_CDECL_ALT_SYNTAX 1
+#elif defined(_MSC_VER) && defined(MSDOS)
+# if (_MSC_VER < 600)
+# define LZO_BROKEN_INTEGRAL_CONSTANTS 1
+# endif
+# if (_MSC_VER < 700)
+# define LZO_BROKEN_INTEGRAL_PROMOTION 1
+# define LZO_BROKEN_SIZEOF 1
+# endif
+#elif defined(__PACIFIC__) && defined(DOS)
+# define LZO_BROKEN_INTEGRAL_CONSTANTS 1
+#elif defined(__TURBOC__) && defined(__MSDOS__)
+# if (__TURBOC__ < 0x0150)
+# define LZO_BROKEN_CDECL_ALT_SYNTAX 1
+# define LZO_BROKEN_INTEGRAL_CONSTANTS 1
+# define LZO_BROKEN_INTEGRAL_PROMOTION 1
+# endif
+# if (__TURBOC__ < 0x0200)
+# define LZO_BROKEN_SIZEOF 1
+# endif
+# if (__TURBOC__ < 0x0400) && defined(__cplusplus)
+# define LZO_BROKEN_CDECL_ALT_SYNTAX 1
+# endif
+#elif (defined(__PUREC__) || defined(__TURBOC__)) && defined(__TOS__)
+# define LZO_BROKEN_CDECL_ALT_SYNTAX 1
+# define LZO_BROKEN_SIZEOF 1
+#endif
+#endif
+#if defined(__WATCOMC__) && (__WATCOMC__ < 900)
+# define LZO_BROKEN_INTEGRAL_CONSTANTS 1
+#endif
+#if defined(_CRAY) && defined(_CRAY1)
+# define LZO_BROKEN_SIGNED_RIGHT_SHIFT 1
+#endif
+#define LZO_PP_STRINGIZE(x) #x
+#define LZO_PP_MACRO_EXPAND(x) LZO_PP_STRINGIZE(x)
+#define LZO_PP_CONCAT2(a,b) a ## b
+#define LZO_PP_CONCAT3(a,b,c) a ## b ## c
+#define LZO_PP_CONCAT4(a,b,c,d) a ## b ## c ## d
+#define LZO_PP_CONCAT5(a,b,c,d,e) a ## b ## c ## d ## e
+#define LZO_PP_ECONCAT2(a,b) LZO_PP_CONCAT2(a,b)
+#define LZO_PP_ECONCAT3(a,b,c) LZO_PP_CONCAT3(a,b,c)
+#define LZO_PP_ECONCAT4(a,b,c,d) LZO_PP_CONCAT4(a,b,c,d)
+#define LZO_PP_ECONCAT5(a,b,c,d,e) LZO_PP_CONCAT5(a,b,c,d,e)
+#if 1
+#define LZO_CPP_STRINGIZE(x) #x
+#define LZO_CPP_MACRO_EXPAND(x) LZO_CPP_STRINGIZE(x)
+#define LZO_CPP_CONCAT2(a,b) a ## b
+#define LZO_CPP_CONCAT3(a,b,c) a ## b ## c
+#define LZO_CPP_CONCAT4(a,b,c,d) a ## b ## c ## d
+#define LZO_CPP_CONCAT5(a,b,c,d,e) a ## b ## c ## d ## e
+#define LZO_CPP_ECONCAT2(a,b) LZO_CPP_CONCAT2(a,b)
+#define LZO_CPP_ECONCAT3(a,b,c) LZO_CPP_CONCAT3(a,b,c)
+#define LZO_CPP_ECONCAT4(a,b,c,d) LZO_CPP_CONCAT4(a,b,c,d)
+#define LZO_CPP_ECONCAT5(a,b,c,d,e) LZO_CPP_CONCAT5(a,b,c,d,e)
+#endif
+#define __LZO_MASK_GEN(o,b) (((((o) << ((b)-1)) - (o)) << 1) + (o))
+#if 1 && defined(__cplusplus)
+# if !defined(__STDC_CONSTANT_MACROS)
+# define __STDC_CONSTANT_MACROS 1
+# endif
+# if !defined(__STDC_LIMIT_MACROS)
+# define __STDC_LIMIT_MACROS 1
+# endif
+#endif
+#if defined(__cplusplus)
+# define LZO_EXTERN_C extern "C"
+#else
+# define LZO_EXTERN_C extern
+#endif
+#if !defined(__LZO_OS_OVERRIDE)
+#if (LZO_OS_FREESTANDING)
+# define LZO_INFO_OS "freestanding"
+#elif (LZO_OS_EMBEDDED)
+# define LZO_INFO_OS "embedded"
+#elif 1 && defined(__IAR_SYSTEMS_ICC__)
+# define LZO_OS_EMBEDDED 1
+# define LZO_INFO_OS "embedded"
+#elif defined(__CYGWIN__) && defined(__GNUC__)
+# define LZO_OS_CYGWIN 1
+# define LZO_INFO_OS "cygwin"
+#elif defined(__EMX__) && defined(__GNUC__)
+# define LZO_OS_EMX 1
+# define LZO_INFO_OS "emx"
+#elif defined(__BEOS__)
+# define LZO_OS_BEOS 1
+# define LZO_INFO_OS "beos"
+#elif defined(__Lynx__)
+# define LZO_OS_LYNXOS 1
+# define LZO_INFO_OS "lynxos"
+#elif defined(__OS400__)
+# define LZO_OS_OS400 1
+# define LZO_INFO_OS "os400"
+#elif defined(__QNX__)
+# define LZO_OS_QNX 1
+# define LZO_INFO_OS "qnx"
+#elif defined(__BORLANDC__) && defined(__DPMI32__) && (__BORLANDC__ >= 0x0460)
+# define LZO_OS_DOS32 1
+# define LZO_INFO_OS "dos32"
+#elif defined(__BORLANDC__) && defined(__DPMI16__)
+# define LZO_OS_DOS16 1
+# define LZO_INFO_OS "dos16"
+#elif defined(__ZTC__) && defined(DOS386)
+# define LZO_OS_DOS32 1
+# define LZO_INFO_OS "dos32"
+#elif defined(__OS2__) || defined(__OS2V2__)
+# if (UINT_MAX == LZO_0xffffL)
+# define LZO_OS_OS216 1
+# define LZO_INFO_OS "os216"
+# elif (UINT_MAX == LZO_0xffffffffL)
+# define LZO_OS_OS2 1
+# define LZO_INFO_OS "os2"
+# else
+# error "check your limits.h header"
+# endif
+#elif defined(__WIN64__) || defined(_WIN64) || defined(WIN64)
+# define LZO_OS_WIN64 1
+# define LZO_INFO_OS "win64"
+#elif defined(__WIN32__) || defined(_WIN32) || defined(WIN32) || defined(__WINDOWS_386__)
+# define LZO_OS_WIN32 1
+# define LZO_INFO_OS "win32"
+#elif defined(__MWERKS__) && defined(__INTEL__)
+# define LZO_OS_WIN32 1
+# define LZO_INFO_OS "win32"
+#elif defined(__WINDOWS__) || defined(_WINDOWS) || defined(_Windows)
+# if (UINT_MAX == LZO_0xffffL)
+# define LZO_OS_WIN16 1
+# define LZO_INFO_OS "win16"
+# elif (UINT_MAX == LZO_0xffffffffL)
+# define LZO_OS_WIN32 1
+# define LZO_INFO_OS "win32"
+# else
+# error "check your limits.h header"
+# endif
+#elif defined(__DOS__) || defined(__MSDOS__) || defined(_MSDOS) || defined(MSDOS) || (defined(__PACIFIC__) && defined(DOS))
+# if (UINT_MAX == LZO_0xffffL)
+# define LZO_OS_DOS16 1
+# define LZO_INFO_OS "dos16"
+# elif (UINT_MAX == LZO_0xffffffffL)
+# define LZO_OS_DOS32 1
+# define LZO_INFO_OS "dos32"
+# else
+# error "check your limits.h header"
+# endif
+#elif defined(__WATCOMC__)
+# if defined(__NT__) && (UINT_MAX == LZO_0xffffL)
+# define LZO_OS_DOS16 1
+# define LZO_INFO_OS "dos16"
+# elif defined(__NT__) && (__WATCOMC__ < 1100)
+# define LZO_OS_WIN32 1
+# define LZO_INFO_OS "win32"
+# elif defined(__linux__) || defined(__LINUX__)
+# define LZO_OS_POSIX 1
+# define LZO_INFO_OS "posix"
+# else
+# error "please specify a target using the -bt compiler option"
+# endif
+#elif defined(__palmos__)
+# define LZO_OS_PALMOS 1
+# define LZO_INFO_OS "palmos"
+#elif defined(__TOS__) || defined(__atarist__)
+# define LZO_OS_TOS 1
+# define LZO_INFO_OS "tos"
+#elif defined(macintosh) && !defined(__ppc__)
+# define LZO_OS_MACCLASSIC 1
+# define LZO_INFO_OS "macclassic"
+#elif defined(__VMS)
+# define LZO_OS_VMS 1
+# define LZO_INFO_OS "vms"
+#elif ((defined(__mips__) && defined(__R5900__)) || defined(__MIPS_PSX2__))
+# define LZO_OS_CONSOLE 1
+# define LZO_OS_CONSOLE_PS2 1
+# define LZO_INFO_OS "console"
+# define LZO_INFO_OS_CONSOLE "ps2"
+#elif (defined(__mips__) && defined(__psp__))
+# define LZO_OS_CONSOLE 1
+# define LZO_OS_CONSOLE_PSP 1
+# define LZO_INFO_OS "console"
+# define LZO_INFO_OS_CONSOLE "psp"
+#else
+# define LZO_OS_POSIX 1
+# define LZO_INFO_OS "posix"
+#endif
+#if (LZO_OS_POSIX)
+# if defined(_AIX) || defined(__AIX__) || defined(__aix__)
+# define LZO_OS_POSIX_AIX 1
+# define LZO_INFO_OS_POSIX "aix"
+# elif defined(__FreeBSD__)
+# define LZO_OS_POSIX_FREEBSD 1
+# define LZO_INFO_OS_POSIX "freebsd"
+# elif defined(__hpux__) || defined(__hpux)
+# define LZO_OS_POSIX_HPUX 1
+# define LZO_INFO_OS_POSIX "hpux"
+# elif defined(__INTERIX)
+# define LZO_OS_POSIX_INTERIX 1
+# define LZO_INFO_OS_POSIX "interix"
+# elif defined(__IRIX__) || defined(__irix__)
+# define LZO_OS_POSIX_IRIX 1
+# define LZO_INFO_OS_POSIX "irix"
+# elif defined(__linux__) || defined(__linux) || defined(__LINUX__)
+# define LZO_OS_POSIX_LINUX 1
+# define LZO_INFO_OS_POSIX "linux"
+# elif defined(__APPLE__) || defined(__MACOS__)
+# define LZO_OS_POSIX_MACOSX 1
+# define LZO_INFO_OS_POSIX "macosx"
+# elif defined(__minix__) || defined(__minix)
+# define LZO_OS_POSIX_MINIX 1
+# define LZO_INFO_OS_POSIX "minix"
+# elif defined(__NetBSD__)
+# define LZO_OS_POSIX_NETBSD 1
+# define LZO_INFO_OS_POSIX "netbsd"
+# elif defined(__OpenBSD__)
+# define LZO_OS_POSIX_OPENBSD 1
+# define LZO_INFO_OS_POSIX "openbsd"
+# elif defined(__osf__)
+# define LZO_OS_POSIX_OSF 1
+# define LZO_INFO_OS_POSIX "osf"
+# elif defined(__solaris__) || defined(__sun)
+# if defined(__SVR4) || defined(__svr4__)
+# define LZO_OS_POSIX_SOLARIS 1
+# define LZO_INFO_OS_POSIX "solaris"
+# else
+# define LZO_OS_POSIX_SUNOS 1
+# define LZO_INFO_OS_POSIX "sunos"
+# endif
+# elif defined(__ultrix__) || defined(__ultrix)
+# define LZO_OS_POSIX_ULTRIX 1
+# define LZO_INFO_OS_POSIX "ultrix"
+# elif defined(_UNICOS)
+# define LZO_OS_POSIX_UNICOS 1
+# define LZO_INFO_OS_POSIX "unicos"
+# else
+# define LZO_OS_POSIX_UNKNOWN 1
+# define LZO_INFO_OS_POSIX "unknown"
+# endif
+#endif
+#endif
+#if (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16)
+# if (UINT_MAX != LZO_0xffffL)
+# error "this should not happen"
+# endif
+# if (ULONG_MAX != LZO_0xffffffffL)
+# error "this should not happen"
+# endif
+#endif
+#if (LZO_OS_DOS32 || LZO_OS_OS2 || LZO_OS_WIN32 || LZO_OS_WIN64)
+# if (UINT_MAX != LZO_0xffffffffL)
+# error "this should not happen"
+# endif
+# if (ULONG_MAX != LZO_0xffffffffL)
+# error "this should not happen"
+# endif
+#endif
+#if defined(CIL) && defined(_GNUCC) && defined(__GNUC__)
+# define LZO_CC_CILLY 1
+# define LZO_INFO_CC "Cilly"
+# if defined(__CILLY__)
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__CILLY__)
+# else
+# define LZO_INFO_CCVER "unknown"
+# endif
+#elif 0 && defined(SDCC) && defined(__VERSION__) && !defined(__GNUC__)
+# define LZO_CC_SDCC 1
+# define LZO_INFO_CC "sdcc"
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(SDCC)
+#elif defined(__PATHSCALE__) && defined(__PATHCC_PATCHLEVEL__)
+# define LZO_CC_PATHSCALE (__PATHCC__ * 0x10000L + __PATHCC_MINOR__ * 0x100 + __PATHCC_PATCHLEVEL__)
+# define LZO_INFO_CC "Pathscale C"
+# define LZO_INFO_CCVER __PATHSCALE__
+#elif defined(__INTEL_COMPILER)
+# define LZO_CC_INTELC 1
+# define LZO_INFO_CC "Intel C"
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__INTEL_COMPILER)
+# if defined(_WIN32) || defined(_WIN64)
+# define LZO_CC_SYNTAX_MSC 1
+# else
+# define LZO_CC_SYNTAX_GNUC 1
+# endif
+#elif defined(__POCC__) && defined(_WIN32)
+# define LZO_CC_PELLESC 1
+# define LZO_INFO_CC "Pelles C"
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__POCC__)
+#elif defined(__clang__) && defined(__llvm__) && defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__)
+# if defined(__GNUC_PATCHLEVEL__)
+# define LZO_CC_CLANG_GNUC (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100 + __GNUC_PATCHLEVEL__)
+# else
+# define LZO_CC_CLANG_GNUC (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100)
+# endif
+# if defined(__clang_major__) && defined(__clang_minor__) && defined(__clang_patchlevel__)
+# define LZO_CC_CLANG_CLANG (__clang_major__ * 0x10000L + __clang_minor__ * 0x100 + __clang_patchlevel__)
+# else
+# define LZO_CC_CLANG_CLANG 0x010000L
+# endif
+# define LZO_CC_CLANG LZO_CC_CLANG_GNUC
+# define LZO_INFO_CC "clang"
+# define LZO_INFO_CCVER __VERSION__
+#elif defined(__llvm__) && defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__)
+# if defined(__GNUC_PATCHLEVEL__)
+# define LZO_CC_LLVM_GNUC (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100 + __GNUC_PATCHLEVEL__)
+# else
+# define LZO_CC_LLVM_GNUC (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100)
+# endif
+# define LZO_CC_LLVM LZO_CC_LLVM_GNUC
+# define LZO_INFO_CC "llvm-gcc"
+# define LZO_INFO_CCVER __VERSION__
+#elif defined(__GNUC__) && defined(__VERSION__)
+# if defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__)
+# define LZO_CC_GNUC (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100 + __GNUC_PATCHLEVEL__)
+# elif defined(__GNUC_MINOR__)
+# define LZO_CC_GNUC (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100)
+# else
+# define LZO_CC_GNUC (__GNUC__ * 0x10000L)
+# endif
+# define LZO_INFO_CC "gcc"
+# define LZO_INFO_CCVER __VERSION__
+#elif defined(__ACK__) && defined(_ACK)
+# define LZO_CC_ACK 1
+# define LZO_INFO_CC "Amsterdam Compiler Kit C"
+# define LZO_INFO_CCVER "unknown"
+#elif defined(__AZTEC_C__)
+# define LZO_CC_AZTECC 1
+# define LZO_INFO_CC "Aztec C"
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__AZTEC_C__)
+#elif defined(__CODEGEARC__)
+# define LZO_CC_CODEGEARC 1
+# define LZO_INFO_CC "CodeGear C"
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__CODEGEARC__)
+#elif defined(__BORLANDC__)
+# define LZO_CC_BORLANDC 1
+# define LZO_INFO_CC "Borland C"
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__BORLANDC__)
+#elif defined(_CRAYC) && defined(_RELEASE)
+# define LZO_CC_CRAYC 1
+# define LZO_INFO_CC "Cray C"
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(_RELEASE)
+#elif defined(__DMC__) && defined(__SC__)
+# define LZO_CC_DMC 1
+# define LZO_INFO_CC "Digital Mars C"
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__DMC__)
+#elif defined(__DECC)
+# define LZO_CC_DECC 1
+# define LZO_INFO_CC "DEC C"
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__DECC)
+#elif defined(__HIGHC__)
+# define LZO_CC_HIGHC 1
+# define LZO_INFO_CC "MetaWare High C"
+# define LZO_INFO_CCVER "unknown"
+#elif defined(__IAR_SYSTEMS_ICC__)
+# define LZO_CC_IARC 1
+# define LZO_INFO_CC "IAR C"
+# if defined(__VER__)
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__VER__)
+# else
+# define LZO_INFO_CCVER "unknown"
+# endif
+#elif defined(__IBMC__)
+# define LZO_CC_IBMC 1
+# define LZO_INFO_CC "IBM C"
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__IBMC__)
+#elif defined(__KEIL__) && defined(__C166__)
+# define LZO_CC_KEILC 1
+# define LZO_INFO_CC "Keil C"
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__C166__)
+#elif defined(__LCC__) && defined(_WIN32) && defined(__LCCOPTIMLEVEL)
+# define LZO_CC_LCCWIN32 1
+# define LZO_INFO_CC "lcc-win32"
+# define LZO_INFO_CCVER "unknown"
+#elif defined(__LCC__)
+# define LZO_CC_LCC 1
+# define LZO_INFO_CC "lcc"
+# if defined(__LCC_VERSION__)
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__LCC_VERSION__)
+# else
+# define LZO_INFO_CCVER "unknown"
+# endif
+#elif defined(_MSC_VER)
+# define LZO_CC_MSC 1
+# define LZO_INFO_CC "Microsoft C"
+# if defined(_MSC_FULL_VER)
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(_MSC_VER) "." LZO_PP_MACRO_EXPAND(_MSC_FULL_VER)
+# else
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(_MSC_VER)
+# endif
+#elif defined(__MWERKS__)
+# define LZO_CC_MWERKS 1
+# define LZO_INFO_CC "Metrowerks C"
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__MWERKS__)
+#elif (defined(__NDPC__) || defined(__NDPX__)) && defined(__i386)
+# define LZO_CC_NDPC 1
+# define LZO_INFO_CC "Microway NDP C"
+# define LZO_INFO_CCVER "unknown"
+#elif defined(__PACIFIC__)
+# define LZO_CC_PACIFICC 1
+# define LZO_INFO_CC "Pacific C"
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__PACIFIC__)
+#elif defined(__PGI) && (defined(__linux__) || defined(__WIN32__))
+# define LZO_CC_PGI 1
+# define LZO_INFO_CC "Portland Group PGI C"
+# define LZO_INFO_CCVER "unknown"
+#elif defined(__PUREC__) && defined(__TOS__)
+# define LZO_CC_PUREC 1
+# define LZO_INFO_CC "Pure C"
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__PUREC__)
+#elif defined(__SC__) && defined(__ZTC__)
+# define LZO_CC_SYMANTECC 1
+# define LZO_INFO_CC "Symantec C"
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__SC__)
+#elif defined(__SUNPRO_C)
+# define LZO_INFO_CC "SunPro C"
+# if ((__SUNPRO_C)+0 > 0)
+# define LZO_CC_SUNPROC __SUNPRO_C
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__SUNPRO_C)
+# else
+# define LZO_CC_SUNPROC 1
+# define LZO_INFO_CCVER "unknown"
+# endif
+#elif defined(__SUNPRO_CC)
+# define LZO_INFO_CC "SunPro C"
+# if ((__SUNPRO_CC)+0 > 0)
+# define LZO_CC_SUNPROC __SUNPRO_CC
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__SUNPRO_CC)
+# else
+# define LZO_CC_SUNPROC 1
+# define LZO_INFO_CCVER "unknown"
+# endif
+#elif defined(__TINYC__)
+# define LZO_CC_TINYC 1
+# define LZO_INFO_CC "Tiny C"
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__TINYC__)
+#elif defined(__TSC__)
+# define LZO_CC_TOPSPEEDC 1
+# define LZO_INFO_CC "TopSpeed C"
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__TSC__)
+#elif defined(__WATCOMC__)
+# define LZO_CC_WATCOMC 1
+# define LZO_INFO_CC "Watcom C"
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__WATCOMC__)
+#elif defined(__TURBOC__)
+# define LZO_CC_TURBOC 1
+# define LZO_INFO_CC "Turbo C"
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__TURBOC__)
+#elif defined(__ZTC__)
+# define LZO_CC_ZORTECHC 1
+# define LZO_INFO_CC "Zortech C"
+# if (__ZTC__ == 0x310)
+# define LZO_INFO_CCVER "0x310"
+# else
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__ZTC__)
+# endif
+#else
+# define LZO_CC_UNKNOWN 1
+# define LZO_INFO_CC "unknown"
+# define LZO_INFO_CCVER "unknown"
+#endif
+#if 0 && (LZO_CC_MSC && (_MSC_VER >= 1200)) && !defined(_MSC_FULL_VER)
+# error "LZO_CC_MSC: _MSC_FULL_VER is not defined"
+#endif
+#if !defined(__LZO_ARCH_OVERRIDE) && !(LZO_ARCH_GENERIC) && defined(_CRAY)
+# if (UINT_MAX > LZO_0xffffffffL) && defined(_CRAY)
+# if defined(_CRAYMPP) || defined(_CRAYT3D) || defined(_CRAYT3E)
+# define LZO_ARCH_CRAY_MPP 1
+# elif defined(_CRAY1)
+# define LZO_ARCH_CRAY_PVP 1
+# endif
+# endif
+#endif
+#if !defined(__LZO_ARCH_OVERRIDE)
+#if (LZO_ARCH_GENERIC)
+# define LZO_INFO_ARCH "generic"
+#elif (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16)
+# define LZO_ARCH_I086 1
+# define LZO_ARCH_IA16 1
+# define LZO_INFO_ARCH "i086"
+#elif defined(__alpha__) || defined(__alpha) || defined(_M_ALPHA)
+# define LZO_ARCH_ALPHA 1
+# define LZO_INFO_ARCH "alpha"
+#elif (LZO_ARCH_CRAY_MPP) && (defined(_CRAYT3D) || defined(_CRAYT3E))
+# define LZO_ARCH_ALPHA 1
+# define LZO_INFO_ARCH "alpha"
+#elif defined(__amd64__) || defined(__x86_64__) || defined(_M_AMD64)
+# define LZO_ARCH_AMD64 1
+# define LZO_INFO_ARCH "amd64"
+#elif defined(__thumb__) || (defined(_M_ARM) && defined(_M_THUMB))
+# define LZO_ARCH_ARM 1
+# define LZO_ARCH_ARM_THUMB 1
+# define LZO_INFO_ARCH "arm_thumb"
+#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICCARM__)
+# define LZO_ARCH_ARM 1
+# if defined(__CPU_MODE__) && ((__CPU_MODE__)+0 == 1)
+# define LZO_ARCH_ARM_THUMB 1
+# define LZO_INFO_ARCH "arm_thumb"
+# elif defined(__CPU_MODE__) && ((__CPU_MODE__)+0 == 2)
+# define LZO_INFO_ARCH "arm"
+# else
+# define LZO_INFO_ARCH "arm"
+# endif
+#elif defined(__arm__) || defined(_M_ARM)
+# define LZO_ARCH_ARM 1
+# define LZO_INFO_ARCH "arm"
+#elif (UINT_MAX <= LZO_0xffffL) && defined(__AVR__)
+# define LZO_ARCH_AVR 1
+# define LZO_INFO_ARCH "avr"
+#elif defined(__avr32__) || defined(__AVR32__)
+# define LZO_ARCH_AVR32 1
+# define LZO_INFO_ARCH "avr32"
+#elif defined(__bfin__)
+# define LZO_ARCH_BLACKFIN 1
+# define LZO_INFO_ARCH "blackfin"
+#elif (UINT_MAX == LZO_0xffffL) && defined(__C166__)
+# define LZO_ARCH_C166 1
+# define LZO_INFO_ARCH "c166"
+#elif defined(__cris__)
+# define LZO_ARCH_CRIS 1
+# define LZO_INFO_ARCH "cris"
+#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICCEZ80__)
+# define LZO_ARCH_EZ80 1
+# define LZO_INFO_ARCH "ez80"
+#elif defined(__H8300__) || defined(__H8300H__) || defined(__H8300S__) || defined(__H8300SX__)
+# define LZO_ARCH_H8300 1
+# define LZO_INFO_ARCH "h8300"
+#elif defined(__hppa__) || defined(__hppa)
+# define LZO_ARCH_HPPA 1
+# define LZO_INFO_ARCH "hppa"
+#elif defined(__386__) || defined(__i386__) || defined(__i386) || defined(_M_IX86) || defined(_M_I386)
+# define LZO_ARCH_I386 1
+# define LZO_ARCH_IA32 1
+# define LZO_INFO_ARCH "i386"
+#elif (LZO_CC_ZORTECHC && defined(__I86__))
+# define LZO_ARCH_I386 1
+# define LZO_ARCH_IA32 1
+# define LZO_INFO_ARCH "i386"
+#elif (LZO_OS_DOS32 && LZO_CC_HIGHC) && defined(_I386)
+# define LZO_ARCH_I386 1
+# define LZO_ARCH_IA32 1
+# define LZO_INFO_ARCH "i386"
+#elif defined(__ia64__) || defined(__ia64) || defined(_M_IA64)
+# define LZO_ARCH_IA64 1
+# define LZO_INFO_ARCH "ia64"
+#elif (UINT_MAX == LZO_0xffffL) && defined(__m32c__)
+# define LZO_ARCH_M16C 1
+# define LZO_INFO_ARCH "m16c"
+#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICCM16C__)
+# define LZO_ARCH_M16C 1
+# define LZO_INFO_ARCH "m16c"
+#elif defined(__m32r__)
+# define LZO_ARCH_M32R 1
+# define LZO_INFO_ARCH "m32r"
+#elif (LZO_OS_TOS) || defined(__m68k__) || defined(__m68000__) || defined(__mc68000__) || defined(__mc68020__) || defined(_M_M68K)
+# define LZO_ARCH_M68K 1
+# define LZO_INFO_ARCH "m68k"
+#elif (UINT_MAX == LZO_0xffffL) && defined(__C251__)
+# define LZO_ARCH_MCS251 1
+# define LZO_INFO_ARCH "mcs251"
+#elif (UINT_MAX == LZO_0xffffL) && defined(__C51__)
+# define LZO_ARCH_MCS51 1
+# define LZO_INFO_ARCH "mcs51"
+#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICC8051__)
+# define LZO_ARCH_MCS51 1
+# define LZO_INFO_ARCH "mcs51"
+#elif defined(__mips__) || defined(__mips) || defined(_MIPS_ARCH) || defined(_M_MRX000)
+# define LZO_ARCH_MIPS 1
+# define LZO_INFO_ARCH "mips"
+#elif (UINT_MAX == LZO_0xffffL) && defined(__MSP430__)
+# define LZO_ARCH_MSP430 1
+# define LZO_INFO_ARCH "msp430"
+#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICC430__)
+# define LZO_ARCH_MSP430 1
+# define LZO_INFO_ARCH "msp430"
+#elif defined(__powerpc__) || defined(__powerpc) || defined(__ppc__) || defined(__PPC__) || defined(_M_PPC) || defined(_ARCH_PPC) || defined(_ARCH_PWR)
+# define LZO_ARCH_POWERPC 1
+# define LZO_INFO_ARCH "powerpc"
+#elif defined(__s390__) || defined(__s390) || defined(__s390x__) || defined(__s390x)
+# define LZO_ARCH_S390 1
+# define LZO_INFO_ARCH "s390"
+#elif defined(__sh__) || defined(_M_SH)
+# define LZO_ARCH_SH 1
+# define LZO_INFO_ARCH "sh"
+#elif defined(__sparc__) || defined(__sparc) || defined(__sparcv8)
+# define LZO_ARCH_SPARC 1
+# define LZO_INFO_ARCH "sparc"
+#elif defined(__SPU__)
+# define LZO_ARCH_SPU 1
+# define LZO_INFO_ARCH "spu"
+#elif (UINT_MAX == LZO_0xffffL) && defined(__z80)
+# define LZO_ARCH_Z80 1
+# define LZO_INFO_ARCH "z80"
+#elif (LZO_ARCH_CRAY_PVP)
+# if defined(_CRAYSV1)
+# define LZO_ARCH_CRAY_SV1 1
+# define LZO_INFO_ARCH "cray_sv1"
+# elif (_ADDR64)
+# define LZO_ARCH_CRAY_T90 1
+# define LZO_INFO_ARCH "cray_t90"
+# elif (_ADDR32)
+# define LZO_ARCH_CRAY_YMP 1
+# define LZO_INFO_ARCH "cray_ymp"
+# else
+# define LZO_ARCH_CRAY_XMP 1
+# define LZO_INFO_ARCH "cray_xmp"
+# endif
+#else
+# define LZO_ARCH_UNKNOWN 1
+# define LZO_INFO_ARCH "unknown"
+#endif
+#endif
+#if 1 && (LZO_ARCH_UNKNOWN) && (LZO_OS_DOS32 || LZO_OS_OS2)
+# error "FIXME - missing define for CPU architecture"
+#endif
+#if 1 && (LZO_ARCH_UNKNOWN) && (LZO_OS_WIN32)
+# error "FIXME - missing WIN32 define for CPU architecture"
+#endif
+#if 1 && (LZO_ARCH_UNKNOWN) && (LZO_OS_WIN64)
+# error "FIXME - missing WIN64 define for CPU architecture"
+#endif
+#if (LZO_OS_OS216 || LZO_OS_WIN16)
+# define LZO_ARCH_I086PM 1
+# define LZO_ARCH_IA16PM 1
+#elif 1 && (LZO_OS_DOS16 && defined(BLX286))
+# define LZO_ARCH_I086PM 1
+# define LZO_ARCH_IA16PM 1
+#elif 1 && (LZO_OS_DOS16 && defined(DOSX286))
+# define LZO_ARCH_I086PM 1
+# define LZO_ARCH_IA16PM 1
+#elif 1 && (LZO_OS_DOS16 && LZO_CC_BORLANDC && defined(__DPMI16__))
+# define LZO_ARCH_I086PM 1
+# define LZO_ARCH_IA16PM 1
+#endif
+#if (LZO_ARCH_ARM_THUMB) && !(LZO_ARCH_ARM)
+# error "this should not happen"
+#endif
+#if (LZO_ARCH_I086PM) && !(LZO_ARCH_I086)
+# error "this should not happen"
+#endif
+#if (LZO_ARCH_I086)
+# if (UINT_MAX != LZO_0xffffL)
+# error "this should not happen"
+# endif
+# if (ULONG_MAX != LZO_0xffffffffL)
+# error "this should not happen"
+# endif
+#endif
+#if (LZO_ARCH_I386)
+# if (UINT_MAX != LZO_0xffffL) && defined(__i386_int16__)
+# error "this should not happen"
+# endif
+# if (UINT_MAX != LZO_0xffffffffL) && !defined(__i386_int16__)
+# error "this should not happen"
+# endif
+# if (ULONG_MAX != LZO_0xffffffffL)
+# error "this should not happen"
+# endif
+#endif
+#if !defined(__LZO_MM_OVERRIDE)
+#if (LZO_ARCH_I086)
+#if (UINT_MAX != LZO_0xffffL)
+# error "this should not happen"
+#endif
+#if defined(__TINY__) || defined(M_I86TM) || defined(_M_I86TM)
+# define LZO_MM_TINY 1
+#elif defined(__HUGE__) || defined(_HUGE_) || defined(M_I86HM) || defined(_M_I86HM)
+# define LZO_MM_HUGE 1
+#elif defined(__SMALL__) || defined(M_I86SM) || defined(_M_I86SM) || defined(SMALL_MODEL)
+# define LZO_MM_SMALL 1
+#elif defined(__MEDIUM__) || defined(M_I86MM) || defined(_M_I86MM)
+# define LZO_MM_MEDIUM 1
+#elif defined(__COMPACT__) || defined(M_I86CM) || defined(_M_I86CM)
+# define LZO_MM_COMPACT 1
+#elif defined(__LARGE__) || defined(M_I86LM) || defined(_M_I86LM) || defined(LARGE_MODEL)
+# define LZO_MM_LARGE 1
+#elif (LZO_CC_AZTECC)
+# if defined(_LARGE_CODE) && defined(_LARGE_DATA)
+# define LZO_MM_LARGE 1
+# elif defined(_LARGE_CODE)
+# define LZO_MM_MEDIUM 1
+# elif defined(_LARGE_DATA)
+# define LZO_MM_COMPACT 1
+# else
+# define LZO_MM_SMALL 1
+# endif
+#elif (LZO_CC_ZORTECHC && defined(__VCM__))
+# define LZO_MM_LARGE 1
+#else
+# error "unknown memory model"
+#endif
+#if (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16)
+#define LZO_HAVE_MM_HUGE_PTR 1
+#define LZO_HAVE_MM_HUGE_ARRAY 1
+#if (LZO_MM_TINY)
+# undef LZO_HAVE_MM_HUGE_ARRAY
+#endif
+#if (LZO_CC_AZTECC || LZO_CC_PACIFICC || LZO_CC_ZORTECHC)
+# undef LZO_HAVE_MM_HUGE_PTR
+# undef LZO_HAVE_MM_HUGE_ARRAY
+#elif (LZO_CC_DMC || LZO_CC_SYMANTECC)
+# undef LZO_HAVE_MM_HUGE_ARRAY
+#elif (LZO_CC_MSC && defined(_QC))
+# undef LZO_HAVE_MM_HUGE_ARRAY
+# if (_MSC_VER < 600)
+# undef LZO_HAVE_MM_HUGE_PTR
+# endif
+#elif (LZO_CC_TURBOC && (__TURBOC__ < 0x0295))
+# undef LZO_HAVE_MM_HUGE_ARRAY
+#endif
+#if (LZO_ARCH_I086PM) && !(LZO_HAVE_MM_HUGE_PTR)
+# if (LZO_OS_DOS16)
+# error "this should not happen"
+# elif (LZO_CC_ZORTECHC)
+# else
+# error "this should not happen"
+# endif
+#endif
+#ifdef __cplusplus
+extern "C" {
+#endif
+#if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0200))
+ extern void __near __cdecl _AHSHIFT(void);
+# define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT)
+#elif (LZO_CC_DMC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC)
+ extern void __near __cdecl _AHSHIFT(void);
+# define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT)
+#elif (LZO_CC_MSC || LZO_CC_TOPSPEEDC)
+ extern void __near __cdecl _AHSHIFT(void);
+# define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT)
+#elif (LZO_CC_TURBOC && (__TURBOC__ >= 0x0295))
+ extern void __near __cdecl _AHSHIFT(void);
+# define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT)
+#elif ((LZO_CC_AZTECC || LZO_CC_PACIFICC || LZO_CC_TURBOC) && LZO_OS_DOS16)
+# define LZO_MM_AHSHIFT 12
+#elif (LZO_CC_WATCOMC)
+ extern unsigned char _HShift;
+# define LZO_MM_AHSHIFT ((unsigned) _HShift)
+#else
+# error "FIXME - implement LZO_MM_AHSHIFT"
+#endif
+#ifdef __cplusplus
+}
+#endif
+#endif
+#elif (LZO_ARCH_C166)
+#if !defined(__MODEL__)
+# error "FIXME - C166 __MODEL__"
+#elif ((__MODEL__) == 0)
+# define LZO_MM_SMALL 1
+#elif ((__MODEL__) == 1)
+# define LZO_MM_SMALL 1
+#elif ((__MODEL__) == 2)
+# define LZO_MM_LARGE 1
+#elif ((__MODEL__) == 3)
+# define LZO_MM_TINY 1
+#elif ((__MODEL__) == 4)
+# define LZO_MM_XTINY 1
+#elif ((__MODEL__) == 5)
+# define LZO_MM_XSMALL 1
+#else
+# error "FIXME - C166 __MODEL__"
+#endif
+#elif (LZO_ARCH_MCS251)
+#if !defined(__MODEL__)
+# error "FIXME - MCS251 __MODEL__"
+#elif ((__MODEL__) == 0)
+# define LZO_MM_SMALL 1
+#elif ((__MODEL__) == 2)
+# define LZO_MM_LARGE 1
+#elif ((__MODEL__) == 3)
+# define LZO_MM_TINY 1
+#elif ((__MODEL__) == 4)
+# define LZO_MM_XTINY 1
+#elif ((__MODEL__) == 5)
+# define LZO_MM_XSMALL 1
+#else
+# error "FIXME - MCS251 __MODEL__"
+#endif
+#elif (LZO_ARCH_MCS51)
+#if !defined(__MODEL__)
+# error "FIXME - MCS51 __MODEL__"
+#elif ((__MODEL__) == 1)
+# define LZO_MM_SMALL 1
+#elif ((__MODEL__) == 2)
+# define LZO_MM_LARGE 1
+#elif ((__MODEL__) == 3)
+# define LZO_MM_TINY 1
+#elif ((__MODEL__) == 4)
+# define LZO_MM_XTINY 1
+#elif ((__MODEL__) == 5)
+# define LZO_MM_XSMALL 1
+#else
+# error "FIXME - MCS51 __MODEL__"
+#endif
+#elif (LZO_ARCH_CRAY_PVP)
+# define LZO_MM_PVP 1
+#else
+# define LZO_MM_FLAT 1
+#endif
+#if (LZO_MM_COMPACT)
+# define LZO_INFO_MM "compact"
+#elif (LZO_MM_FLAT)
+# define LZO_INFO_MM "flat"
+#elif (LZO_MM_HUGE)
+# define LZO_INFO_MM "huge"
+#elif (LZO_MM_LARGE)
+# define LZO_INFO_MM "large"
+#elif (LZO_MM_MEDIUM)
+# define LZO_INFO_MM "medium"
+#elif (LZO_MM_PVP)
+# define LZO_INFO_MM "pvp"
+#elif (LZO_MM_SMALL)
+# define LZO_INFO_MM "small"
+#elif (LZO_MM_TINY)
+# define LZO_INFO_MM "tiny"
+#else
+# error "unknown memory model"
+#endif
+#endif
+#if defined(SIZEOF_SHORT)
+# define LZO_SIZEOF_SHORT (SIZEOF_SHORT)
+#endif
+#if defined(SIZEOF_INT)
+# define LZO_SIZEOF_INT (SIZEOF_INT)
+#endif
+#if defined(SIZEOF_LONG)
+# define LZO_SIZEOF_LONG (SIZEOF_LONG)
+#endif
+#if defined(SIZEOF_LONG_LONG)
+# define LZO_SIZEOF_LONG_LONG (SIZEOF_LONG_LONG)
+#endif
+#if defined(SIZEOF___INT16)
+# define LZO_SIZEOF___INT16 (SIZEOF___INT16)
+#endif
+#if defined(SIZEOF___INT32)
+# define LZO_SIZEOF___INT32 (SIZEOF___INT32)
+#endif
+#if defined(SIZEOF___INT64)
+# define LZO_SIZEOF___INT64 (SIZEOF___INT64)
+#endif
+#if defined(SIZEOF_VOID_P)
+# define LZO_SIZEOF_VOID_P (SIZEOF_VOID_P)
+#endif
+#if defined(SIZEOF_SIZE_T)
+# define LZO_SIZEOF_SIZE_T (SIZEOF_SIZE_T)
+#endif
+#if defined(SIZEOF_PTRDIFF_T)
+# define LZO_SIZEOF_PTRDIFF_T (SIZEOF_PTRDIFF_T)
+#endif
+#define __LZO_LSR(x,b) (((x)+0ul) >> (b))
+#if !defined(LZO_SIZEOF_SHORT)
+# if (LZO_ARCH_CRAY_PVP)
+# define LZO_SIZEOF_SHORT 8
+# elif (USHRT_MAX == LZO_0xffffL)
+# define LZO_SIZEOF_SHORT 2
+# elif (__LZO_LSR(USHRT_MAX,7) == 1)
+# define LZO_SIZEOF_SHORT 1
+# elif (__LZO_LSR(USHRT_MAX,15) == 1)
+# define LZO_SIZEOF_SHORT 2
+# elif (__LZO_LSR(USHRT_MAX,31) == 1)
+# define LZO_SIZEOF_SHORT 4
+# elif (__LZO_LSR(USHRT_MAX,63) == 1)
+# define LZO_SIZEOF_SHORT 8
+# elif (__LZO_LSR(USHRT_MAX,127) == 1)
+# define LZO_SIZEOF_SHORT 16
+# else
+# error "LZO_SIZEOF_SHORT"
+# endif
+#endif
+#if !defined(LZO_SIZEOF_INT)
+# if (LZO_ARCH_CRAY_PVP)
+# define LZO_SIZEOF_INT 8
+# elif (UINT_MAX == LZO_0xffffL)
+# define LZO_SIZEOF_INT 2
+# elif (UINT_MAX == LZO_0xffffffffL)
+# define LZO_SIZEOF_INT 4
+# elif (__LZO_LSR(UINT_MAX,7) == 1)
+# define LZO_SIZEOF_INT 1
+# elif (__LZO_LSR(UINT_MAX,15) == 1)
+# define LZO_SIZEOF_INT 2
+# elif (__LZO_LSR(UINT_MAX,31) == 1)
+# define LZO_SIZEOF_INT 4
+# elif (__LZO_LSR(UINT_MAX,63) == 1)
+# define LZO_SIZEOF_INT 8
+# elif (__LZO_LSR(UINT_MAX,127) == 1)
+# define LZO_SIZEOF_INT 16
+# else
+# error "LZO_SIZEOF_INT"
+# endif
+#endif
+#if !defined(LZO_SIZEOF_LONG)
+# if (ULONG_MAX == LZO_0xffffffffL)
+# define LZO_SIZEOF_LONG 4
+# elif (__LZO_LSR(ULONG_MAX,7) == 1)
+# define LZO_SIZEOF_LONG 1
+# elif (__LZO_LSR(ULONG_MAX,15) == 1)
+# define LZO_SIZEOF_LONG 2
+# elif (__LZO_LSR(ULONG_MAX,31) == 1)
+# define LZO_SIZEOF_LONG 4
+# elif (__LZO_LSR(ULONG_MAX,63) == 1)
+# define LZO_SIZEOF_LONG 8
+# elif (__LZO_LSR(ULONG_MAX,127) == 1)
+# define LZO_SIZEOF_LONG 16
+# else
+# error "LZO_SIZEOF_LONG"
+# endif
+#endif
+#if !defined(LZO_SIZEOF_LONG_LONG) && !defined(LZO_SIZEOF___INT64)
+#if (LZO_SIZEOF_LONG > 0 && LZO_SIZEOF_LONG < 8)
+# if defined(__LONG_MAX__) && defined(__LONG_LONG_MAX__)
+# if (LZO_CC_GNUC >= 0x030300ul)
+# if ((__LONG_MAX__)+0 == (__LONG_LONG_MAX__)+0)
+# define LZO_SIZEOF_LONG_LONG LZO_SIZEOF_LONG
+# elif (__LZO_LSR(__LONG_LONG_MAX__,30) == 1)
+# define LZO_SIZEOF_LONG_LONG 4
+# endif
+# endif
+# endif
+#endif
+#endif
+#if !defined(LZO_SIZEOF_LONG_LONG) && !defined(LZO_SIZEOF___INT64)
+#if (LZO_SIZEOF_LONG > 0 && LZO_SIZEOF_LONG < 8)
+#if (LZO_ARCH_I086 && LZO_CC_DMC)
+#elif (LZO_CC_CILLY) && defined(__GNUC__)
+# define LZO_SIZEOF_LONG_LONG 8
+#elif (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE)
+# define LZO_SIZEOF_LONG_LONG 8
+#elif ((LZO_OS_WIN32 || LZO_OS_WIN64 || defined(_WIN32)) && LZO_CC_MSC && (_MSC_VER >= 1400))
+# define LZO_SIZEOF_LONG_LONG 8
+#elif (LZO_OS_WIN64 || defined(_WIN64))
+# define LZO_SIZEOF___INT64 8
+#elif (LZO_ARCH_I386 && (LZO_CC_DMC))
+# define LZO_SIZEOF_LONG_LONG 8
+#elif (LZO_ARCH_I386 && (LZO_CC_SYMANTECC && (__SC__ >= 0x700)))
+# define LZO_SIZEOF_LONG_LONG 8
+#elif (LZO_ARCH_I386 && (LZO_CC_INTELC && defined(__linux__)))
+# define LZO_SIZEOF_LONG_LONG 8
+#elif (LZO_ARCH_I386 && (LZO_CC_MWERKS || LZO_CC_PELLESC || LZO_CC_PGI || LZO_CC_SUNPROC))
+# define LZO_SIZEOF_LONG_LONG 8
+#elif (LZO_ARCH_I386 && (LZO_CC_INTELC || LZO_CC_MSC))
+# define LZO_SIZEOF___INT64 8
+#elif ((LZO_OS_WIN32 || defined(_WIN32)) && (LZO_CC_MSC))
+# define LZO_SIZEOF___INT64 8
+#elif (LZO_ARCH_I386 && (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0520)))
+# define LZO_SIZEOF___INT64 8
+#elif (LZO_ARCH_I386 && (LZO_CC_WATCOMC && (__WATCOMC__ >= 1100)))
+# define LZO_SIZEOF___INT64 8
+#elif (LZO_CC_WATCOMC && defined(_INTEGRAL_MAX_BITS) && (_INTEGRAL_MAX_BITS == 64))
+# define LZO_SIZEOF___INT64 8
+#elif (LZO_OS_OS400 || defined(__OS400__)) && defined(__LLP64_IFC__)
+# define LZO_SIZEOF_LONG_LONG 8
+#elif (defined(__vms) || defined(__VMS)) && (__INITIAL_POINTER_SIZE+0 == 64)
+# define LZO_SIZEOF_LONG_LONG 8
+#elif (LZO_CC_SDCC) && (LZO_SIZEOF_INT == 2)
+#elif 1 && defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
+# define LZO_SIZEOF_LONG_LONG 8
+#endif
+#endif
+#endif
+#if defined(__cplusplus) && (LZO_CC_GNUC)
+# if (LZO_CC_GNUC < 0x020800ul)
+# undef LZO_SIZEOF_LONG_LONG
+# endif
+#endif
+#if (LZO_CFG_NO_LONG_LONG) || defined(__NO_LONG_LONG)
+# undef LZO_SIZEOF_LONG_LONG
+#endif
+#if !defined(LZO_SIZEOF_VOID_P)
+#if (LZO_ARCH_I086)
+# define __LZO_WORDSIZE 2
+# if (LZO_MM_TINY || LZO_MM_SMALL || LZO_MM_MEDIUM)
+# define LZO_SIZEOF_VOID_P 2
+# elif (LZO_MM_COMPACT || LZO_MM_LARGE || LZO_MM_HUGE)
+# define LZO_SIZEOF_VOID_P 4
+# else
+# error "LZO_MM"
+# endif
+#elif (LZO_ARCH_AVR || LZO_ARCH_Z80)
+# define __LZO_WORDSIZE 1
+# define LZO_SIZEOF_VOID_P 2
+#elif (LZO_ARCH_C166 || LZO_ARCH_MCS51 || LZO_ARCH_MCS251 || LZO_ARCH_MSP430)
+# define LZO_SIZEOF_VOID_P 2
+#elif (LZO_ARCH_H8300)
+# if defined(__NORMAL_MODE__)
+# define __LZO_WORDSIZE 4
+# define LZO_SIZEOF_VOID_P 2
+# elif defined(__H8300H__) || defined(__H8300S__) || defined(__H8300SX__)
+# define __LZO_WORDSIZE 4
+# define LZO_SIZEOF_VOID_P 4
+# else
+# define __LZO_WORDSIZE 2
+# define LZO_SIZEOF_VOID_P 2
+# endif
+# if (LZO_CC_GNUC && (LZO_CC_GNUC < 0x040000ul)) && (LZO_SIZEOF_INT == 4)
+# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_INT
+# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_INT
+# endif
+#elif (LZO_ARCH_M16C)
+# define __LZO_WORDSIZE 2
+# if defined(__m32c_cpu__) || defined(__m32cm_cpu__)
+# define LZO_SIZEOF_VOID_P 4
+# else
+# define LZO_SIZEOF_VOID_P 2
+# endif
+#elif (LZO_SIZEOF_LONG == 8) && ((defined(__mips__) && defined(__R5900__)) || defined(__MIPS_PSX2__))
+# define __LZO_WORDSIZE 8
+# define LZO_SIZEOF_VOID_P 4
+#elif defined(__LLP64__) || defined(__LLP64) || defined(_LLP64) || defined(_WIN64)
+# define __LZO_WORDSIZE 8
+# define LZO_SIZEOF_VOID_P 8
+#elif (LZO_OS_OS400 || defined(__OS400__)) && defined(__LLP64_IFC__)
+# define LZO_SIZEOF_VOID_P LZO_SIZEOF_LONG
+# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG
+# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG
+#elif (LZO_OS_OS400 || defined(__OS400__))
+# define __LZO_WORDSIZE LZO_SIZEOF_LONG
+# define LZO_SIZEOF_VOID_P 16
+# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG
+# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG
+#elif (defined(__vms) || defined(__VMS)) && (__INITIAL_POINTER_SIZE+0 == 64)
+# define LZO_SIZEOF_VOID_P 8
+# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG
+# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG
+#elif (LZO_ARCH_SPU)
+# if 0
+# define __LZO_WORDSIZE 16
+# endif
+# define LZO_SIZEOF_VOID_P 4
+#else
+# define LZO_SIZEOF_VOID_P LZO_SIZEOF_LONG
+#endif
+#endif
+#if !defined(LZO_WORDSIZE)
+# if defined(__LZO_WORDSIZE)
+# define LZO_WORDSIZE __LZO_WORDSIZE
+# else
+# define LZO_WORDSIZE LZO_SIZEOF_VOID_P
+# endif
+#endif
+#if !defined(LZO_SIZEOF_SIZE_T)
+#if (LZO_ARCH_I086 || LZO_ARCH_M16C)
+# define LZO_SIZEOF_SIZE_T 2
+#else
+# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_VOID_P
+#endif
+#endif
+#if !defined(LZO_SIZEOF_PTRDIFF_T)
+#if (LZO_ARCH_I086)
+# if (LZO_MM_TINY || LZO_MM_SMALL || LZO_MM_MEDIUM || LZO_MM_HUGE)
+# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_VOID_P
+# elif (LZO_MM_COMPACT || LZO_MM_LARGE)
+# if (LZO_CC_BORLANDC || LZO_CC_TURBOC)
+# define LZO_SIZEOF_PTRDIFF_T 4
+# else
+# define LZO_SIZEOF_PTRDIFF_T 2
+# endif
+# else
+# error "LZO_MM"
+# endif
+#else
+# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_SIZE_T
+#endif
+#endif
+#if (LZO_ABI_NEUTRAL_ENDIAN)
+# undef LZO_ABI_BIG_ENDIAN
+# undef LZO_ABI_LITTLE_ENDIAN
+#elif !(LZO_ABI_BIG_ENDIAN) && !(LZO_ABI_LITTLE_ENDIAN)
+#if (LZO_ARCH_ALPHA) && (LZO_ARCH_CRAY_MPP)
+# define LZO_ABI_BIG_ENDIAN 1
+#elif (LZO_ARCH_IA64) && (LZO_OS_POSIX_LINUX || LZO_OS_WIN64)
+# define LZO_ABI_LITTLE_ENDIAN 1
+#elif (LZO_ARCH_ALPHA || LZO_ARCH_AMD64 || LZO_ARCH_BLACKFIN || LZO_ARCH_CRIS || LZO_ARCH_I086 || LZO_ARCH_I386 || LZO_ARCH_MSP430)
+# define LZO_ABI_LITTLE_ENDIAN 1
+#elif (LZO_ARCH_AVR32 || LZO_ARCH_M68K || LZO_ARCH_S390)
+# define LZO_ABI_BIG_ENDIAN 1
+#elif 1 && defined(__IAR_SYSTEMS_ICC__) && defined(__LITTLE_ENDIAN__)
+# if (__LITTLE_ENDIAN__ == 1)
+# define LZO_ABI_LITTLE_ENDIAN 1
+# else
+# define LZO_ABI_BIG_ENDIAN 1
+# endif
+#elif 1 && defined(__BIG_ENDIAN__) && !defined(__LITTLE_ENDIAN__)
+# define LZO_ABI_BIG_ENDIAN 1
+#elif 1 && defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__)
+# define LZO_ABI_LITTLE_ENDIAN 1
+#elif 1 && (LZO_ARCH_ARM) && defined(__ARMEB__) && !defined(__ARMEL__)
+# define LZO_ABI_BIG_ENDIAN 1
+#elif 1 && (LZO_ARCH_ARM) && defined(__ARMEL__) && !defined(__ARMEB__)
+# define LZO_ABI_LITTLE_ENDIAN 1
+#elif 1 && (LZO_ARCH_MIPS) && defined(__MIPSEB__) && !defined(__MIPSEL__)
+# define LZO_ABI_BIG_ENDIAN 1
+#elif 1 && (LZO_ARCH_MIPS) && defined(__MIPSEL__) && !defined(__MIPSEB__)
+# define LZO_ABI_LITTLE_ENDIAN 1
+#endif
+#endif
+#if (LZO_ABI_BIG_ENDIAN) && (LZO_ABI_LITTLE_ENDIAN)
+# error "this should not happen"
+#endif
+#if (LZO_ABI_BIG_ENDIAN)
+# define LZO_INFO_ABI_ENDIAN "be"
+#elif (LZO_ABI_LITTLE_ENDIAN)
+# define LZO_INFO_ABI_ENDIAN "le"
+#elif (LZO_ABI_NEUTRAL_ENDIAN)
+# define LZO_INFO_ABI_ENDIAN "neutral"
+#endif
+#if (LZO_SIZEOF_INT == 1 && LZO_SIZEOF_LONG == 2 && LZO_SIZEOF_VOID_P == 2)
+# define LZO_ABI_I8LP16 1
+# define LZO_INFO_ABI_PM "i8lp16"
+#elif (LZO_SIZEOF_INT == 2 && LZO_SIZEOF_LONG == 2 && LZO_SIZEOF_VOID_P == 2)
+# define LZO_ABI_ILP16 1
+# define LZO_INFO_ABI_PM "ilp16"
+#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 4 && LZO_SIZEOF_VOID_P == 4)
+# define LZO_ABI_ILP32 1
+# define LZO_INFO_ABI_PM "ilp32"
+#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 4 && LZO_SIZEOF_VOID_P == 8 && LZO_SIZEOF_SIZE_T == 8)
+# define LZO_ABI_LLP64 1
+# define LZO_INFO_ABI_PM "llp64"
+#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 8 && LZO_SIZEOF_VOID_P == 8)
+# define LZO_ABI_LP64 1
+# define LZO_INFO_ABI_PM "lp64"
+#elif (LZO_SIZEOF_INT == 8 && LZO_SIZEOF_LONG == 8 && LZO_SIZEOF_VOID_P == 8)
+# define LZO_ABI_ILP64 1
+# define LZO_INFO_ABI_PM "ilp64"
+#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 8 && LZO_SIZEOF_VOID_P == 4)
+# define LZO_ABI_IP32L64 1
+# define LZO_INFO_ABI_PM "ip32l64"
+#endif
+#if !defined(__LZO_LIBC_OVERRIDE)
+#if (LZO_LIBC_NAKED)
+# define LZO_INFO_LIBC "naked"
+#elif (LZO_LIBC_FREESTANDING)
+# define LZO_INFO_LIBC "freestanding"
+#elif (LZO_LIBC_MOSTLY_FREESTANDING)
+# define LZO_INFO_LIBC "mfreestanding"
+#elif (LZO_LIBC_ISOC90)
+# define LZO_INFO_LIBC "isoc90"
+#elif (LZO_LIBC_ISOC99)
+# define LZO_INFO_LIBC "isoc99"
+#elif defined(__dietlibc__)
+# define LZO_LIBC_DIETLIBC 1
+# define LZO_INFO_LIBC "dietlibc"
+#elif defined(_NEWLIB_VERSION)
+# define LZO_LIBC_NEWLIB 1
+# define LZO_INFO_LIBC "newlib"
+#elif defined(__UCLIBC__) && defined(__UCLIBC_MAJOR__) && defined(__UCLIBC_MINOR__)
+# if defined(__UCLIBC_SUBLEVEL__)
+# define LZO_LIBC_UCLIBC (__UCLIBC_MAJOR__ * 0x10000L + __UCLIBC_MINOR__ * 0x100 + __UCLIBC_SUBLEVEL__)
+# else
+# define LZO_LIBC_UCLIBC 0x00090bL
+# endif
+# define LZO_INFO_LIBC "uclibc"
+#elif defined(__GLIBC__) && defined(__GLIBC_MINOR__)
+# define LZO_LIBC_GLIBC (__GLIBC__ * 0x10000L + __GLIBC_MINOR__ * 0x100)
+# define LZO_INFO_LIBC "glibc"
+#elif (LZO_CC_MWERKS) && defined(__MSL__)
+# define LZO_LIBC_MSL __MSL__
+# define LZO_INFO_LIBC "msl"
+#elif 1 && defined(__IAR_SYSTEMS_ICC__)
+# define LZO_LIBC_ISOC90 1
+# define LZO_INFO_LIBC "isoc90"
+#else
+# define LZO_LIBC_DEFAULT 1
+# define LZO_INFO_LIBC "default"
+#endif
+#endif
+#if !defined(__lzo_gnuc_extension__)
+#if (LZO_CC_GNUC >= 0x020800ul)
+# define __lzo_gnuc_extension__ __extension__
+#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE)
+# define __lzo_gnuc_extension__ __extension__
+#else
+# define __lzo_gnuc_extension__ /*empty*/
+#endif
+#endif
+#if !defined(__lzo_ua_volatile)
+# define __lzo_ua_volatile volatile
+#endif
+#if !defined(__lzo_alignof)
+#if (LZO_CC_CILLY || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI)
+# define __lzo_alignof(e) __alignof__(e)
+#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 700))
+# define __lzo_alignof(e) __alignof__(e)
+#elif (LZO_CC_MSC && (_MSC_VER >= 1300))
+# define __lzo_alignof(e) __alignof(e)
+#elif (LZO_CC_SUNPROC && (LZO_CC_SUNPROC >= 0x5100))
+# define __lzo_alignof(e) __alignof__(e)
+#endif
+#endif
+#if defined(__lzo_alignof)
+# define __lzo_HAVE_alignof 1
+#endif
+#if !defined(__lzo_constructor)
+#if (LZO_CC_GNUC >= 0x030400ul)
+# define __lzo_constructor __attribute__((__constructor__,__used__))
+#elif (LZO_CC_GNUC >= 0x020700ul)
+# define __lzo_constructor __attribute__((__constructor__))
+#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE)
+# define __lzo_constructor __attribute__((__constructor__))
+#endif
+#endif
+#if defined(__lzo_constructor)
+# define __lzo_HAVE_constructor 1
+#endif
+#if !defined(__lzo_destructor)
+#if (LZO_CC_GNUC >= 0x030400ul)
+# define __lzo_destructor __attribute__((__destructor__,__used__))
+#elif (LZO_CC_GNUC >= 0x020700ul)
+# define __lzo_destructor __attribute__((__destructor__))
+#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE)
+# define __lzo_destructor __attribute__((__destructor__))
+#endif
+#endif
+#if defined(__lzo_destructor)
+# define __lzo_HAVE_destructor 1
+#endif
+#if (__lzo_HAVE_destructor) && !(__lzo_HAVE_constructor)
+# error "this should not happen"
+#endif
+#if !defined(__lzo_inline)
+#if (LZO_CC_TURBOC && (__TURBOC__ <= 0x0295))
+#elif defined(__cplusplus)
+# define __lzo_inline inline
+#elif (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0550))
+# define __lzo_inline __inline
+#elif (LZO_CC_CILLY || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI)
+# define __lzo_inline __inline__
+#elif (LZO_CC_DMC)
+# define __lzo_inline __inline
+#elif (LZO_CC_INTELC)
+# define __lzo_inline __inline
+#elif (LZO_CC_MWERKS && (__MWERKS__ >= 0x2405))
+# define __lzo_inline __inline
+#elif (LZO_CC_MSC && (_MSC_VER >= 900))
+# define __lzo_inline __inline
+#elif (LZO_CC_SUNPROC && (LZO_CC_SUNPROC >= 0x5100))
+# define __lzo_inline __inline__
+#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
+# define __lzo_inline inline
+#endif
+#endif
+#if defined(__lzo_inline)
+# define __lzo_HAVE_inline 1
+#else
+# define __lzo_inline /*empty*/
+#endif
+#if !defined(__lzo_forceinline)
+#if (LZO_CC_GNUC >= 0x030200ul)
+# define __lzo_forceinline __inline__ __attribute__((__always_inline__))
+#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 450) && LZO_CC_SYNTAX_MSC)
+# define __lzo_forceinline __forceinline
+#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 800) && LZO_CC_SYNTAX_GNUC)
+# define __lzo_forceinline __inline__ __attribute__((__always_inline__))
+#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE)
+# define __lzo_forceinline __inline__ __attribute__((__always_inline__))
+#elif (LZO_CC_MSC && (_MSC_VER >= 1200))
+# define __lzo_forceinline __forceinline
+#elif (LZO_CC_SUNPROC && (LZO_CC_SUNPROC >= 0x5100))
+# define __lzo_forceinline __inline__ __attribute__((__always_inline__))
+#endif
+#endif
+#if defined(__lzo_forceinline)
+# define __lzo_HAVE_forceinline 1
+#else
+# define __lzo_forceinline /*empty*/
+#endif
+#if !defined(__lzo_noinline)
+#if 1 && (LZO_ARCH_I386) && (LZO_CC_GNUC >= 0x040000ul) && (LZO_CC_GNUC < 0x040003ul)
+# define __lzo_noinline __attribute__((__noinline__,__used__))
+#elif (LZO_CC_GNUC >= 0x030200ul)
+# define __lzo_noinline __attribute__((__noinline__))
+#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 600) && LZO_CC_SYNTAX_MSC)
+# define __lzo_noinline __declspec(noinline)
+#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 800) && LZO_CC_SYNTAX_GNUC)
+# define __lzo_noinline __attribute__((__noinline__))
+#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE)
+# define __lzo_noinline __attribute__((__noinline__))
+#elif (LZO_CC_MSC && (_MSC_VER >= 1300))
+# define __lzo_noinline __declspec(noinline)
+#elif (LZO_CC_MWERKS && (__MWERKS__ >= 0x3200) && (LZO_OS_WIN32 || LZO_OS_WIN64))
+# if defined(__cplusplus)
+# else
+# define __lzo_noinline __declspec(noinline)
+# endif
+#elif (LZO_CC_SUNPROC && (LZO_CC_SUNPROC >= 0x5100))
+# define __lzo_noinline __attribute__((__noinline__))
+#endif
+#endif
+#if defined(__lzo_noinline)
+# define __lzo_HAVE_noinline 1
+#else
+# define __lzo_noinline /*empty*/
+#endif
+#if (__lzo_HAVE_forceinline || __lzo_HAVE_noinline) && !(__lzo_HAVE_inline)
+# error "this should not happen"
+#endif
+#if !defined(__lzo_noreturn)
+#if (LZO_CC_GNUC >= 0x020700ul)
+# define __lzo_noreturn __attribute__((__noreturn__))
+#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 450) && LZO_CC_SYNTAX_MSC)
+# define __lzo_noreturn __declspec(noreturn)
+#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 600) && LZO_CC_SYNTAX_GNUC)
+# define __lzo_noreturn __attribute__((__noreturn__))
+#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE)
+# define __lzo_noreturn __attribute__((__noreturn__))
+#elif (LZO_CC_MSC && (_MSC_VER >= 1200))
+# define __lzo_noreturn __declspec(noreturn)
+#endif
+#endif
+#if defined(__lzo_noreturn)
+# define __lzo_HAVE_noreturn 1
+#else
+# define __lzo_noreturn /*empty*/
+#endif
+#if !defined(__lzo_nothrow)
+#if (LZO_CC_GNUC >= 0x030300ul)
+# define __lzo_nothrow __attribute__((__nothrow__))
+#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 450) && LZO_CC_SYNTAX_MSC) && defined(__cplusplus)
+# define __lzo_nothrow __declspec(nothrow)
+#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 900) && LZO_CC_SYNTAX_GNUC)
+# define __lzo_nothrow __attribute__((__nothrow__))
+#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE)
+# define __lzo_nothrow __attribute__((__nothrow__))
+#elif (LZO_CC_MSC && (_MSC_VER >= 1200)) && defined(__cplusplus)
+# define __lzo_nothrow __declspec(nothrow)
+#endif
+#endif
+#if defined(__lzo_nothrow)
+# define __lzo_HAVE_nothrow 1
+#else
+# define __lzo_nothrow /*empty*/
+#endif
+#if !defined(__lzo_restrict)
+#if (LZO_CC_GNUC >= 0x030400ul)
+# define __lzo_restrict __restrict__
+#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 600) && LZO_CC_SYNTAX_GNUC)
+# define __lzo_restrict __restrict__
+#elif (LZO_CC_CLANG || LZO_CC_LLVM)
+# define __lzo_restrict __restrict__
+#elif (LZO_CC_MSC && (_MSC_VER >= 1400))
+# define __lzo_restrict __restrict
+#endif
+#endif
+#if defined(__lzo_restrict)
+# define __lzo_HAVE_restrict 1
+#else
+# define __lzo_restrict /*empty*/
+#endif
+#if !defined(__lzo_likely) && !defined(__lzo_unlikely)
+#if (LZO_CC_GNUC >= 0x030200ul)
+# define __lzo_likely(e) (__builtin_expect(!!(e),1))
+# define __lzo_unlikely(e) (__builtin_expect(!!(e),0))
+#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 800))
+# define __lzo_likely(e) (__builtin_expect(!!(e),1))
+# define __lzo_unlikely(e) (__builtin_expect(!!(e),0))
+#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE)
+# define __lzo_likely(e) (__builtin_expect(!!(e),1))
+# define __lzo_unlikely(e) (__builtin_expect(!!(e),0))
+#endif
+#endif
+#if defined(__lzo_likely)
+# define __lzo_HAVE_likely 1
+#else
+# define __lzo_likely(e) (e)
+#endif
+#if defined(__lzo_unlikely)
+# define __lzo_HAVE_unlikely 1
+#else
+# define __lzo_unlikely(e) (e)
+#endif
+#if !defined(LZO_UNUSED)
+# if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0600))
+# define LZO_UNUSED(var) ((void) &var)
+# elif (LZO_CC_BORLANDC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PELLESC || LZO_CC_TURBOC)
+# define LZO_UNUSED(var) if (&var) ; else
+# elif (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE)
+# define LZO_UNUSED(var) ((void) var)
+# elif (LZO_CC_MSC && (_MSC_VER < 900))
+# define LZO_UNUSED(var) if (&var) ; else
+# elif (LZO_CC_KEILC)
+# define LZO_UNUSED(var) {extern int __lzo_unused[1-2*!(sizeof(var)>0)];}
+# elif (LZO_CC_PACIFICC)
+# define LZO_UNUSED(var) ((void) sizeof(var))
+# elif (LZO_CC_WATCOMC) && defined(__cplusplus)
+# define LZO_UNUSED(var) ((void) var)
+# else
+# define LZO_UNUSED(var) ((void) &var)
+# endif
+#endif
+#if !defined(LZO_UNUSED_FUNC)
+# if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0600))
+# define LZO_UNUSED_FUNC(func) ((void) func)
+# elif (LZO_CC_BORLANDC || LZO_CC_NDPC || LZO_CC_TURBOC)
+# define LZO_UNUSED_FUNC(func) if (func) ; else
+# elif (LZO_CC_CLANG || LZO_CC_LLVM)
+# define LZO_UNUSED_FUNC(func) ((void) &func)
+# elif (LZO_CC_MSC && (_MSC_VER < 900))
+# define LZO_UNUSED_FUNC(func) if (func) ; else
+# elif (LZO_CC_MSC)
+# define LZO_UNUSED_FUNC(func) ((void) &func)
+# elif (LZO_CC_KEILC || LZO_CC_PELLESC)
+# define LZO_UNUSED_FUNC(func) {extern int __lzo_unused[1-2*!(sizeof((int)func)>0)];}
+# else
+# define LZO_UNUSED_FUNC(func) ((void) func)
+# endif
+#endif
+#if !defined(LZO_UNUSED_LABEL)
+# if (LZO_CC_WATCOMC) && defined(__cplusplus)
+# define LZO_UNUSED_LABEL(l) switch(0) case 1:goto l
+# elif (LZO_CC_CLANG || LZO_CC_INTELC || LZO_CC_WATCOMC)
+# define LZO_UNUSED_LABEL(l) if (0) goto l
+# else
+# define LZO_UNUSED_LABEL(l) switch(0) case 1:goto l
+# endif
+#endif
+#if !defined(LZO_DEFINE_UNINITIALIZED_VAR)
+# if 0
+# define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init) type var
+# elif 0 && (LZO_CC_GNUC)
+# define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init) type var = var
+# else
+# define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init) type var = init
+# endif
+#endif
+#if !defined(LZO_UNCONST_CAST)
+# if 0 && defined(__cplusplus)
+# define LZO_UNCONST_CAST(t,e) (const_cast<t> (e))
+# elif (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE)
+# define LZO_UNCONST_CAST(t,e) ((t) ((void *) ((char *) ((lzo_uintptr_t) ((const void *) (e))))))
+# else
+# define LZO_UNCONST_CAST(t,e) ((t) ((void *) ((char *) ((const void *) (e)))))
+# endif
+#endif
+#if !defined(LZO_COMPILE_TIME_ASSERT_HEADER)
+# if (LZO_CC_AZTECC || LZO_CC_ZORTECHC)
+# define LZO_COMPILE_TIME_ASSERT_HEADER(e) extern int __lzo_cta[1-!(e)];
+# elif (LZO_CC_DMC || LZO_CC_SYMANTECC)
+# define LZO_COMPILE_TIME_ASSERT_HEADER(e) extern int __lzo_cta[1u-2*!(e)];
+# elif (LZO_CC_TURBOC && (__TURBOC__ == 0x0295))
+# define LZO_COMPILE_TIME_ASSERT_HEADER(e) extern int __lzo_cta[1-!(e)];
+# else
+# define LZO_COMPILE_TIME_ASSERT_HEADER(e) extern int __lzo_cta[1-2*!(e)];
+# endif
+#endif
+#if !defined(LZO_COMPILE_TIME_ASSERT)
+# if (LZO_CC_AZTECC)
+# define LZO_COMPILE_TIME_ASSERT(e) {typedef int __lzo_cta_t[1-!(e)];}
+# elif (LZO_CC_DMC || LZO_CC_PACIFICC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC)
+# define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break;
+# elif (LZO_CC_MSC && (_MSC_VER < 900))
+# define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break;
+# elif (LZO_CC_TURBOC && (__TURBOC__ == 0x0295))
+# define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break;
+# else
+# define LZO_COMPILE_TIME_ASSERT(e) {typedef int __lzo_cta_t[1-2*!(e)];}
+# endif
+#endif
+#if (LZO_ARCH_I086 || LZO_ARCH_I386) && (LZO_OS_DOS16 || LZO_OS_DOS32 || LZO_OS_OS2 || LZO_OS_OS216 || LZO_OS_WIN16 || LZO_OS_WIN32 || LZO_OS_WIN64)
+# if (LZO_CC_GNUC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PACIFICC)
+# elif (LZO_CC_DMC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC)
+# define __lzo_cdecl __cdecl
+# define __lzo_cdecl_atexit /*empty*/
+# define __lzo_cdecl_main __cdecl
+# if (LZO_OS_OS2 && (LZO_CC_DMC || LZO_CC_SYMANTECC))
+# define __lzo_cdecl_qsort __pascal
+# elif (LZO_OS_OS2 && (LZO_CC_ZORTECHC))
+# define __lzo_cdecl_qsort _stdcall
+# else
+# define __lzo_cdecl_qsort __cdecl
+# endif
+# elif (LZO_CC_WATCOMC)
+# define __lzo_cdecl __cdecl
+# else
+# define __lzo_cdecl __cdecl
+# define __lzo_cdecl_atexit __cdecl
+# define __lzo_cdecl_main __cdecl
+# define __lzo_cdecl_qsort __cdecl
+# endif
+# if (LZO_CC_GNUC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PACIFICC || LZO_CC_WATCOMC)
+# elif (LZO_OS_OS2 && (LZO_CC_DMC || LZO_CC_SYMANTECC))
+# define __lzo_cdecl_sighandler __pascal
+# elif (LZO_OS_OS2 && (LZO_CC_ZORTECHC))
+# define __lzo_cdecl_sighandler _stdcall
+# elif (LZO_CC_MSC && (_MSC_VER >= 1400)) && defined(_M_CEE_PURE)
+# define __lzo_cdecl_sighandler __clrcall
+# elif (LZO_CC_MSC && (_MSC_VER >= 600 && _MSC_VER < 700))
+# if defined(_DLL)
+# define __lzo_cdecl_sighandler _far _cdecl _loadds
+# elif defined(_MT)
+# define __lzo_cdecl_sighandler _far _cdecl
+# else
+# define __lzo_cdecl_sighandler _cdecl
+# endif
+# else
+# define __lzo_cdecl_sighandler __cdecl
+# endif
+#elif (LZO_ARCH_I386) && (LZO_CC_WATCOMC)
+# define __lzo_cdecl __cdecl
+#elif (LZO_ARCH_M68K && LZO_OS_TOS && (LZO_CC_PUREC || LZO_CC_TURBOC))
+# define __lzo_cdecl cdecl
+#endif
+#if !defined(__lzo_cdecl)
+# define __lzo_cdecl /*empty*/
+#endif
+#if !defined(__lzo_cdecl_atexit)
+# define __lzo_cdecl_atexit /*empty*/
+#endif
+#if !defined(__lzo_cdecl_main)
+# define __lzo_cdecl_main /*empty*/
+#endif
+#if !defined(__lzo_cdecl_qsort)
+# define __lzo_cdecl_qsort /*empty*/
+#endif
+#if !defined(__lzo_cdecl_sighandler)
+# define __lzo_cdecl_sighandler /*empty*/
+#endif
+#if !defined(__lzo_cdecl_va)
+# define __lzo_cdecl_va __lzo_cdecl
+#endif
+#if !(LZO_CFG_NO_WINDOWS_H)
+#if (LZO_OS_CYGWIN || (LZO_OS_EMX && defined(__RSXNT__)) || LZO_OS_WIN32 || LZO_OS_WIN64)
+# if (LZO_CC_WATCOMC && (__WATCOMC__ < 1000))
+# elif (LZO_OS_WIN32 && LZO_CC_GNUC) && defined(__PW32__)
+# elif ((LZO_OS_CYGWIN || defined(__MINGW32__)) && (LZO_CC_GNUC && (LZO_CC_GNUC < 0x025f00ul)))
+# else
+# define LZO_HAVE_WINDOWS_H 1
+# endif
+#endif
+#endif
+#if (LZO_ARCH_ALPHA)
+# define LZO_OPT_AVOID_UINT_INDEX 1
+# define LZO_OPT_AVOID_SHORT 1
+# define LZO_OPT_AVOID_USHORT 1
+#elif (LZO_ARCH_AMD64)
+# define LZO_OPT_AVOID_INT_INDEX 1
+# define LZO_OPT_AVOID_UINT_INDEX 1
+# define LZO_OPT_UNALIGNED16 1
+# define LZO_OPT_UNALIGNED32 1
+# define LZO_OPT_UNALIGNED64 1
+#elif (LZO_ARCH_ARM && LZO_ARCH_ARM_THUMB)
+#elif (LZO_ARCH_ARM)
+# define LZO_OPT_AVOID_SHORT 1
+# define LZO_OPT_AVOID_USHORT 1
+#elif (LZO_ARCH_CRIS)
+# define LZO_OPT_UNALIGNED16 1
+# define LZO_OPT_UNALIGNED32 1
+#elif (LZO_ARCH_I386)
+# define LZO_OPT_UNALIGNED16 1
+# define LZO_OPT_UNALIGNED32 1
+#elif (LZO_ARCH_IA64)
+# define LZO_OPT_AVOID_INT_INDEX 1
+# define LZO_OPT_AVOID_UINT_INDEX 1
+# define LZO_OPT_PREFER_POSTINC 1
+#elif (LZO_ARCH_M68K)
+# define LZO_OPT_PREFER_POSTINC 1
+# define LZO_OPT_PREFER_PREDEC 1
+# if defined(__mc68020__) && !defined(__mcoldfire__)
+# define LZO_OPT_UNALIGNED16 1
+# define LZO_OPT_UNALIGNED32 1
+# endif
+#elif (LZO_ARCH_MIPS)
+# define LZO_OPT_AVOID_UINT_INDEX 1
+#elif (LZO_ARCH_POWERPC)
+# define LZO_OPT_PREFER_PREINC 1
+# define LZO_OPT_PREFER_PREDEC 1
+# if (LZO_ABI_BIG_ENDIAN)
+# define LZO_OPT_UNALIGNED16 1
+# define LZO_OPT_UNALIGNED32 1
+# endif
+#elif (LZO_ARCH_S390)
+# define LZO_OPT_UNALIGNED16 1
+# define LZO_OPT_UNALIGNED32 1
+# if (LZO_SIZEOF_SIZE_T == 8)
+# define LZO_OPT_UNALIGNED64 1
+# endif
+#elif (LZO_ARCH_SH)
+# define LZO_OPT_PREFER_POSTINC 1
+# define LZO_OPT_PREFER_PREDEC 1
+#endif
+#ifndef LZO_CFG_NO_INLINE_ASM
+#if (LZO_CC_LLVM)
+# define LZO_CFG_NO_INLINE_ASM 1
+#endif
+#endif
+#ifndef LZO_CFG_NO_UNALIGNED
+#if (LZO_ABI_NEUTRAL_ENDIAN) || (LZO_ARCH_GENERIC)
+# define LZO_CFG_NO_UNALIGNED 1
+#endif
+#endif
+#if (LZO_CFG_NO_UNALIGNED)
+# undef LZO_OPT_UNALIGNED16
+# undef LZO_OPT_UNALIGNED32
+# undef LZO_OPT_UNALIGNED64
+#endif
+#if (LZO_CFG_NO_INLINE_ASM)
+#elif (LZO_ARCH_I386 && (LZO_OS_DOS32 || LZO_OS_WIN32) && (LZO_CC_DMC || LZO_CC_INTELC || LZO_CC_MSC || LZO_CC_PELLESC))
+# define LZO_ASM_SYNTAX_MSC 1
+#elif (LZO_OS_WIN64 && (LZO_CC_DMC || LZO_CC_INTELC || LZO_CC_MSC || LZO_CC_PELLESC))
+#elif (LZO_ARCH_I386 && LZO_CC_GNUC && (LZO_CC_GNUC == 0x011f00ul))
+#elif (LZO_ARCH_I386 && (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_INTELC || LZO_CC_PATHSCALE))
+# define LZO_ASM_SYNTAX_GNUC 1
+#elif (LZO_ARCH_AMD64 && (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_INTELC || LZO_CC_PATHSCALE))
+# define LZO_ASM_SYNTAX_GNUC 1
+#endif
+#if (LZO_ASM_SYNTAX_GNUC)
+#if (LZO_ARCH_I386 && LZO_CC_GNUC && (LZO_CC_GNUC < 0x020000ul))
+# define __LZO_ASM_CLOBBER "ax"
+#elif (LZO_CC_INTELC)
+# define __LZO_ASM_CLOBBER "memory"
+#else
+# define __LZO_ASM_CLOBBER "cc", "memory"
+#endif
+#endif
+#if defined(__LZO_INFOSTR_MM)
+#elif (LZO_MM_FLAT) && (defined(__LZO_INFOSTR_PM) || defined(LZO_INFO_ABI_PM))
+# define __LZO_INFOSTR_MM ""
+#elif defined(LZO_INFO_MM)
+# define __LZO_INFOSTR_MM "." LZO_INFO_MM
+#else
+# define __LZO_INFOSTR_MM ""
+#endif
+#if defined(__LZO_INFOSTR_PM)
+#elif defined(LZO_INFO_ABI_PM)
+# define __LZO_INFOSTR_PM "." LZO_INFO_ABI_PM
+#else
+# define __LZO_INFOSTR_PM ""
+#endif
+#if defined(__LZO_INFOSTR_ENDIAN)
+#elif defined(LZO_INFO_ABI_ENDIAN)
+# define __LZO_INFOSTR_ENDIAN "." LZO_INFO_ABI_ENDIAN
+#else
+# define __LZO_INFOSTR_ENDIAN ""
+#endif
+#if defined(__LZO_INFOSTR_OSNAME)
+#elif defined(LZO_INFO_OS_CONSOLE)
+# define __LZO_INFOSTR_OSNAME LZO_INFO_OS "." LZO_INFO_OS_CONSOLE
+#elif defined(LZO_INFO_OS_POSIX)
+# define __LZO_INFOSTR_OSNAME LZO_INFO_OS "." LZO_INFO_OS_POSIX
+#else
+# define __LZO_INFOSTR_OSNAME LZO_INFO_OS
+#endif
+#if defined(__LZO_INFOSTR_LIBC)
+#elif defined(LZO_INFO_LIBC)
+# define __LZO_INFOSTR_LIBC "." LZO_INFO_LIBC
+#else
+# define __LZO_INFOSTR_LIBC ""
+#endif
+#if defined(__LZO_INFOSTR_CCVER)
+#elif defined(LZO_INFO_CCVER)
+# define __LZO_INFOSTR_CCVER " " LZO_INFO_CCVER
+#else
+# define __LZO_INFOSTR_CCVER ""
+#endif
+#define LZO_INFO_STRING \
+ LZO_INFO_ARCH __LZO_INFOSTR_MM __LZO_INFOSTR_PM __LZO_INFOSTR_ENDIAN \
+ " " __LZO_INFOSTR_OSNAME __LZO_INFOSTR_LIBC " " LZO_INFO_CC __LZO_INFOSTR_CCVER
+
+#endif
+
+#endif
+
+#undef LZO_HAVE_CONFIG_H
+#include "minilzo.h"
+
+#if !defined(MINILZO_VERSION) || (MINILZO_VERSION != 0x2050)
+# error "version mismatch in miniLZO source files"
+#endif
+
+#ifdef MINILZO_HAVE_CONFIG_H
+# define LZO_HAVE_CONFIG_H 1
+#endif
+
+#ifndef __LZO_CONF_H
+#define __LZO_CONF_H 1
+
+#if !defined(__LZO_IN_MINILZO)
+#if (LZO_CFG_FREESTANDING)
+# define LZO_LIBC_FREESTANDING 1
+# define LZO_OS_FREESTANDING 1
+# define ACC_LIBC_FREESTANDING 1
+# define ACC_OS_FREESTANDING 1
+#endif
+#if (LZO_CFG_NO_UNALIGNED)
+# define ACC_CFG_NO_UNALIGNED 1
+#endif
+#if (LZO_ARCH_GENERIC)
+# define ACC_ARCH_GENERIC 1
+#endif
+#if (LZO_ABI_NEUTRAL_ENDIAN)
+# define ACC_ABI_NEUTRAL_ENDIAN 1
+#endif
+#if (LZO_HAVE_CONFIG_H)
+# define ACC_CONFIG_NO_HEADER 1
+#endif
+#if defined(LZO_CFG_EXTRA_CONFIG_HEADER)
+# include LZO_CFG_EXTRA_CONFIG_HEADER
+#endif
+#if defined(__LZOCONF_H) || defined(__LZOCONF_H_INCLUDED)
+# error "include this file first"
+#endif
+#include "lzo/lzoconf.h"
+#endif
+
+#if (LZO_VERSION < 0x02000) || !defined(__LZOCONF_H_INCLUDED)
+# error "version mismatch"
+#endif
+
+#if (LZO_CC_BORLANDC && LZO_ARCH_I086)
+# pragma option -h
+#endif
+
+#if (LZO_CC_MSC && (_MSC_VER >= 1000))
+# pragma warning(disable: 4127 4701)
+#endif
+#if (LZO_CC_MSC && (_MSC_VER >= 1300))
+# pragma warning(disable: 4820)
+# pragma warning(disable: 4514 4710 4711)
+#endif
+
+#if (LZO_CC_SUNPROC)
+#if !defined(__cplusplus)
+# pragma error_messages(off,E_END_OF_LOOP_CODE_NOT_REACHED)
+# pragma error_messages(off,E_LOOP_NOT_ENTERED_AT_TOP)
+# pragma error_messages(off,E_STATEMENT_NOT_REACHED)
+#endif
+#endif
+
+#if (__LZO_MMODEL_HUGE) && !(LZO_HAVE_MM_HUGE_PTR)
+# error "this should not happen - check defines for __huge"
+#endif
+
+#if defined(__LZO_IN_MINILZO) || defined(LZO_CFG_FREESTANDING)
+#elif (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16)
+# define ACC_WANT_ACC_INCD_H 1
+# define ACC_WANT_ACC_INCE_H 1
+# define ACC_WANT_ACC_INCI_H 1
+#elif 1
+# include <string.h>
+#else
+# define ACC_WANT_ACC_INCD_H 1
+#endif
+
+#if (LZO_ARCH_I086)
+# define ACC_MM_AHSHIFT LZO_MM_AHSHIFT
+# define ACC_PTR_FP_OFF(x) (((const unsigned __far*)&(x))[0])
+# define ACC_PTR_FP_SEG(x) (((const unsigned __far*)&(x))[1])
+# define ACC_PTR_MK_FP(s,o) ((void __far*)(((unsigned long)(s)<<16)+(unsigned)(o)))
+#endif
+
+#if !defined(lzo_uintptr_t)
+# if defined(__LZO_MMODEL_HUGE)
+# define lzo_uintptr_t unsigned long
+# elif 1 && defined(LZO_OS_OS400) && (LZO_SIZEOF_VOID_P == 16)
+# define __LZO_UINTPTR_T_IS_POINTER 1
+ typedef char* lzo_uintptr_t;
+# define lzo_uintptr_t lzo_uintptr_t
+# elif (LZO_SIZEOF_SIZE_T == LZO_SIZEOF_VOID_P)
+# define lzo_uintptr_t size_t
+# elif (LZO_SIZEOF_LONG == LZO_SIZEOF_VOID_P)
+# define lzo_uintptr_t unsigned long
+# elif (LZO_SIZEOF_INT == LZO_SIZEOF_VOID_P)
+# define lzo_uintptr_t unsigned int
+# elif (LZO_SIZEOF_LONG_LONG == LZO_SIZEOF_VOID_P)
+# define lzo_uintptr_t unsigned long long
+# else
+# define lzo_uintptr_t size_t
+# endif
+#endif
+LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uintptr_t) >= sizeof(lzo_voidp))
+
+#if 1 && !defined(LZO_CFG_FREESTANDING)
+#if 1 && !defined(HAVE_STRING_H)
+#define HAVE_STRING_H 1
+#endif
+#if 1 && !defined(HAVE_MEMCMP)
+#define HAVE_MEMCMP 1
+#endif
+#if 1 && !defined(HAVE_MEMCPY)
+#define HAVE_MEMCPY 1
+#endif
+#if 1 && !defined(HAVE_MEMMOVE)
+#define HAVE_MEMMOVE 1
+#endif
+#if 1 && !defined(HAVE_MEMSET)
+#define HAVE_MEMSET 1
+#endif
+#endif
+
+#if 1 && defined(HAVE_STRING_H)
+#include <string.h>
+#endif
+
+#if (LZO_CFG_FREESTANDING)
+# undef HAVE_MEMCMP
+# undef HAVE_MEMCPY
+# undef HAVE_MEMMOVE
+# undef HAVE_MEMSET
+#endif
+
+#if !(HAVE_MEMCMP)
+# undef memcmp
+# define memcmp(a,b,c) lzo_memcmp(a,b,c)
+#elif !(__LZO_MMODEL_HUGE)
+# undef lzo_memcmp
+# define lzo_memcmp(a,b,c) memcmp(a,b,c)
+#endif
+#if !(HAVE_MEMCPY)
+# undef memcpy
+# define memcpy(a,b,c) lzo_memcpy(a,b,c)
+#elif !(__LZO_MMODEL_HUGE)
+# undef lzo_memcpy
+# define lzo_memcpy(a,b,c) memcpy(a,b,c)
+#endif
+#if !(HAVE_MEMMOVE)
+# undef memmove
+# define memmove(a,b,c) lzo_memmove(a,b,c)
+#elif !(__LZO_MMODEL_HUGE)
+# undef lzo_memmove
+# define lzo_memmove(a,b,c) memmove(a,b,c)
+#endif
+#if !(HAVE_MEMSET)
+# undef memset
+# define memset(a,b,c) lzo_memset(a,b,c)
+#elif !(__LZO_MMODEL_HUGE)
+# undef lzo_memset
+# define lzo_memset(a,b,c) memset(a,b,c)
+#endif
+
+#undef NDEBUG
+#if (LZO_CFG_FREESTANDING)
+# undef LZO_DEBUG
+# define NDEBUG 1
+# undef assert
+# define assert(e) ((void)0)
+#else
+# if !defined(LZO_DEBUG)
+# define NDEBUG 1
+# endif
+# include <assert.h>
+#endif
+
+#if 0 && defined(__BOUNDS_CHECKING_ON)
+# include <unchecked.h>
+#else
+# define BOUNDS_CHECKING_OFF_DURING(stmt) stmt
+# define BOUNDS_CHECKING_OFF_IN_EXPR(expr) (expr)
+#endif
+
+#if !defined(__lzo_inline)
+# define __lzo_inline /*empty*/
+#endif
+#if !defined(__lzo_forceinline)
+# define __lzo_forceinline /*empty*/
+#endif
+#if !defined(__lzo_noinline)
+# define __lzo_noinline /*empty*/
+#endif
+
+#if (LZO_CFG_PGO)
+# undef __acc_likely
+# undef __acc_unlikely
+# undef __lzo_likely
+# undef __lzo_unlikely
+# define __acc_likely(e) (e)
+# define __acc_unlikely(e) (e)
+# define __lzo_likely(e) (e)
+# define __lzo_unlikely(e) (e)
+#endif
+
+#if 1
+# define LZO_BYTE(x) ((unsigned char) (x))
+#else
+# define LZO_BYTE(x) ((unsigned char) ((x) & 0xff))
+#endif
+
+#define LZO_MAX(a,b) ((a) >= (b) ? (a) : (b))
+#define LZO_MIN(a,b) ((a) <= (b) ? (a) : (b))
+#define LZO_MAX3(a,b,c) ((a) >= (b) ? LZO_MAX(a,c) : LZO_MAX(b,c))
+#define LZO_MIN3(a,b,c) ((a) <= (b) ? LZO_MIN(a,c) : LZO_MIN(b,c))
+
+#define lzo_sizeof(type) ((lzo_uint) (sizeof(type)))
+
+#define LZO_HIGH(array) ((lzo_uint) (sizeof(array)/sizeof(*(array))))
+
+#define LZO_SIZE(bits) (1u << (bits))
+#define LZO_MASK(bits) (LZO_SIZE(bits) - 1)
+
+#define LZO_LSIZE(bits) (1ul << (bits))
+#define LZO_LMASK(bits) (LZO_LSIZE(bits) - 1)
+
+#define LZO_USIZE(bits) ((lzo_uint) 1 << (bits))
+#define LZO_UMASK(bits) (LZO_USIZE(bits) - 1)
+
+#if !defined(DMUL)
+#if 0
+
+# define DMUL(a,b) ((lzo_xint) ((lzo_uint32)(a) * (lzo_uint32)(b)))
+#else
+# define DMUL(a,b) ((lzo_xint) ((a) * (b)))
+#endif
+#endif
+
+#if 1 && (LZO_ARCH_AMD64 || LZO_ARCH_I386 || LZO_ARCH_POWERPC)
+# if (LZO_SIZEOF_SHORT == 2)
+# define LZO_UNALIGNED_OK_2 1
+# endif
+# if (LZO_SIZEOF_INT == 4)
+# define LZO_UNALIGNED_OK_4 1
+# endif
+#endif
+#if 1 && (LZO_ARCH_AMD64)
+# if defined(LZO_UINT64_MAX)
+# define LZO_UNALIGNED_OK_8 1
+# endif
+#endif
+#if (LZO_CFG_NO_UNALIGNED)
+# undef LZO_UNALIGNED_OK_2
+# undef LZO_UNALIGNED_OK_4
+# undef LZO_UNALIGNED_OK_8
+#endif
+
+#undef UA_GET16
+#undef UA_SET16
+#undef UA_COPY16
+#undef UA_GET32
+#undef UA_SET32
+#undef UA_COPY32
+#undef UA_GET64
+#undef UA_SET64
+#undef UA_COPY64
+#if defined(LZO_UNALIGNED_OK_2)
+ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(unsigned short) == 2)
+# if 1 && defined(ACC_UA_COPY16)
+# define UA_GET16 ACC_UA_GET16
+# define UA_SET16 ACC_UA_SET16
+# define UA_COPY16 ACC_UA_COPY16
+# else
+# define UA_GET16(p) (* (__lzo_ua_volatile const lzo_ushortp) (__lzo_ua_volatile const lzo_voidp) (p))
+# define UA_SET16(p,v) ((* (__lzo_ua_volatile lzo_ushortp) (__lzo_ua_volatile lzo_voidp) (p)) = (unsigned short) (v))
+# define UA_COPY16(d,s) UA_SET16(d, UA_GET16(s))
+# endif
+#endif
+#if defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4)
+ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint32) == 4)
+# if 1 && defined(ACC_UA_COPY32)
+# define UA_GET32 ACC_UA_GET32
+# define UA_SET32 ACC_UA_SET32
+# define UA_COPY32 ACC_UA_COPY32
+# else
+# define UA_GET32(p) (* (__lzo_ua_volatile const lzo_uint32p) (__lzo_ua_volatile const lzo_voidp) (p))
+# define UA_SET32(p,v) ((* (__lzo_ua_volatile lzo_uint32p) (__lzo_ua_volatile lzo_voidp) (p)) = (lzo_uint32) (v))
+# define UA_COPY32(d,s) UA_SET32(d, UA_GET32(s))
+# endif
+#endif
+#if defined(LZO_UNALIGNED_OK_8)
+ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint64) == 8)
+# if 1 && defined(ACC_UA_COPY64)
+# define UA_GET64 ACC_UA_GET64
+# define UA_SET64 ACC_UA_SET64
+# define UA_COPY64 ACC_UA_COPY64
+# else
+# define UA_GET64(p) (* (__lzo_ua_volatile const lzo_uint64p) (__lzo_ua_volatile const lzo_voidp) (p))
+# define UA_SET64(p,v) ((* (__lzo_ua_volatile lzo_uint64p) (__lzo_ua_volatile lzo_voidp) (p)) = (lzo_uint64) (v))
+# define UA_COPY64(d,s) UA_SET64(d, UA_GET64(s))
+# endif
+#endif
+
+#define MEMCPY8_DS(dest,src,len) \
+ lzo_memcpy(dest,src,len); dest += len; src += len
+
+#define BZERO8_PTR(s,l,n) \
+ lzo_memset((lzo_voidp)(s),0,(lzo_uint)(l)*(n))
+
+#define MEMCPY_DS(dest,src,len) \
+ do *dest++ = *src++; while (--len > 0)
+
+LZO_EXTERN(const lzo_bytep) lzo_copyright(void);
+
+#ifndef __LZO_PTR_H
+#define __LZO_PTR_H 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if !defined(lzo_uintptr_t)
+# if (__LZO_MMODEL_HUGE)
+# define lzo_uintptr_t unsigned long
+# else
+# define lzo_uintptr_t acc_uintptr_t
+# ifdef __ACC_INTPTR_T_IS_POINTER
+# define __LZO_UINTPTR_T_IS_POINTER 1
+# endif
+# endif
+#endif
+
+#if (LZO_ARCH_I086)
+#define PTR(a) ((lzo_bytep) (a))
+#define PTR_ALIGNED_4(a) ((ACC_PTR_FP_OFF(a) & 3) == 0)
+#define PTR_ALIGNED2_4(a,b) (((ACC_PTR_FP_OFF(a) | ACC_PTR_FP_OFF(b)) & 3) == 0)
+#elif (LZO_MM_PVP)
+#define PTR(a) ((lzo_bytep) (a))
+#define PTR_ALIGNED_8(a) ((((lzo_uintptr_t)(a)) >> 61) == 0)
+#define PTR_ALIGNED2_8(a,b) ((((lzo_uintptr_t)(a)|(lzo_uintptr_t)(b)) >> 61) == 0)
+#else
+#define PTR(a) ((lzo_uintptr_t) (a))
+#define PTR_LINEAR(a) PTR(a)
+#define PTR_ALIGNED_4(a) ((PTR_LINEAR(a) & 3) == 0)
+#define PTR_ALIGNED_8(a) ((PTR_LINEAR(a) & 7) == 0)
+#define PTR_ALIGNED2_4(a,b) (((PTR_LINEAR(a) | PTR_LINEAR(b)) & 3) == 0)
+#define PTR_ALIGNED2_8(a,b) (((PTR_LINEAR(a) | PTR_LINEAR(b)) & 7) == 0)
+#endif
+
+#define PTR_LT(a,b) (PTR(a) < PTR(b))
+#define PTR_GE(a,b) (PTR(a) >= PTR(b))
+#define PTR_DIFF(a,b) (PTR(a) - PTR(b))
+#define pd(a,b) ((lzo_uint) ((a)-(b)))
+
+LZO_EXTERN(lzo_uintptr_t)
+__lzo_ptr_linear(const lzo_voidp ptr);
+
+typedef union
+{
+ char a_char;
+ unsigned char a_uchar;
+ short a_short;
+ unsigned short a_ushort;
+ int a_int;
+ unsigned int a_uint;
+ long a_long;
+ unsigned long a_ulong;
+ lzo_int a_lzo_int;
+ lzo_uint a_lzo_uint;
+ lzo_int32 a_lzo_int32;
+ lzo_uint32 a_lzo_uint32;
+#if defined(LZO_UINT64_MAX)
+ lzo_int64 a_lzo_int64;
+ lzo_uint64 a_lzo_uint64;
+#endif
+ ptrdiff_t a_ptrdiff_t;
+ lzo_uintptr_t a_lzo_uintptr_t;
+ lzo_voidp a_lzo_voidp;
+ void * a_void_p;
+ lzo_bytep a_lzo_bytep;
+ lzo_bytepp a_lzo_bytepp;
+ lzo_uintp a_lzo_uintp;
+ lzo_uint * a_lzo_uint_p;
+ lzo_uint32p a_lzo_uint32p;
+ lzo_uint32 * a_lzo_uint32_p;
+ unsigned char * a_uchar_p;
+ char * a_char_p;
+}
+lzo_full_align_t;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+#ifndef LZO_DETERMINISTIC
+#define LZO_DETERMINISTIC 1
+#endif
+
+#ifndef LZO_DICT_USE_PTR
+#define LZO_DICT_USE_PTR 1
+#if 0 && (LZO_ARCH_I086)
+# undef LZO_DICT_USE_PTR
+# define LZO_DICT_USE_PTR 0
+#endif
+#endif
+
+#if (LZO_DICT_USE_PTR)
+# define lzo_dict_t const lzo_bytep
+# define lzo_dict_p lzo_dict_t __LZO_MMODEL *
+#else
+# define lzo_dict_t lzo_uint
+# define lzo_dict_p lzo_dict_t __LZO_MMODEL *
+#endif
+
+#endif
+
+#if !defined(MINILZO_CFG_SKIP_LZO_PTR)
+
+LZO_PUBLIC(lzo_uintptr_t)
+__lzo_ptr_linear(const lzo_voidp ptr)
+{
+ lzo_uintptr_t p;
+
+#if (LZO_ARCH_I086)
+ p = (((lzo_uintptr_t)(ACC_PTR_FP_SEG(ptr))) << (16 - ACC_MM_AHSHIFT)) + (ACC_PTR_FP_OFF(ptr));
+#elif (LZO_MM_PVP)
+ p = (lzo_uintptr_t) (ptr);
+ p = (p << 3) | (p >> 61);
+#else
+ p = (lzo_uintptr_t) PTR_LINEAR(ptr);
+#endif
+
+ return p;
+}
+
+LZO_PUBLIC(unsigned)
+__lzo_align_gap(const lzo_voidp ptr, lzo_uint size)
+{
+#if defined(__LZO_UINTPTR_T_IS_POINTER)
+ size_t n = (size_t) ptr;
+ n = (((n + size - 1) / size) * size) - n;
+#else
+ lzo_uintptr_t p, n;
+ p = __lzo_ptr_linear(ptr);
+ n = (((p + size - 1) / size) * size) - p;
+#endif
+
+ assert(size > 0);
+ assert((long)n >= 0);
+ assert(n <= size);
+ return (unsigned)n;
+}
+
+#endif
+#if !defined(MINILZO_CFG_SKIP_LZO_UTIL)
+
+/* If you use the LZO library in a product, I would appreciate that you
+ * keep this copyright string in the executable of your product.
+ */
+
+static const char __lzo_copyright[] =
+#if !defined(__LZO_IN_MINLZO)
+ LZO_VERSION_STRING;
+#else
+ "\r\n\n"
+ "LZO data compression library.\n"
+ "$Copyright: LZO Copyright (C) 1996-2011 Markus Franz Xaver Johannes Oberhumer\n"
+ "<markus@oberhumer.com>\n"
+ "http://www.oberhumer.com $\n\n"
+ "$Id: LZO version: v" LZO_VERSION_STRING ", " LZO_VERSION_DATE " $\n"
+ "$Info: " LZO_INFO_STRING " $\n";
+#endif
+
+LZO_PUBLIC(const lzo_bytep)
+lzo_copyright(void)
+{
+#if (LZO_OS_DOS16 && LZO_CC_TURBOC)
+ return (lzo_voidp) __lzo_copyright;
+#else
+ return (const lzo_bytep) __lzo_copyright;
+#endif
+}
+
+LZO_PUBLIC(unsigned)
+lzo_version(void)
+{
+ return LZO_VERSION;
+}
+
+LZO_PUBLIC(const char *)
+lzo_version_string(void)
+{
+ return LZO_VERSION_STRING;
+}
+
+LZO_PUBLIC(const char *)
+lzo_version_date(void)
+{
+ return LZO_VERSION_DATE;
+}
+
+LZO_PUBLIC(const lzo_charp)
+_lzo_version_string(void)
+{
+ return LZO_VERSION_STRING;
+}
+
+LZO_PUBLIC(const lzo_charp)
+_lzo_version_date(void)
+{
+ return LZO_VERSION_DATE;
+}
+
+#define LZO_BASE 65521u
+#define LZO_NMAX 5552
+
+#define LZO_DO1(buf,i) s1 += buf[i]; s2 += s1
+#define LZO_DO2(buf,i) LZO_DO1(buf,i); LZO_DO1(buf,i+1);
+#define LZO_DO4(buf,i) LZO_DO2(buf,i); LZO_DO2(buf,i+2);
+#define LZO_DO8(buf,i) LZO_DO4(buf,i); LZO_DO4(buf,i+4);
+#define LZO_DO16(buf,i) LZO_DO8(buf,i); LZO_DO8(buf,i+8);
+
+LZO_PUBLIC(lzo_uint32)
+lzo_adler32(lzo_uint32 adler, const lzo_bytep buf, lzo_uint len)
+{
+ lzo_uint32 s1 = adler & 0xffff;
+ lzo_uint32 s2 = (adler >> 16) & 0xffff;
+ unsigned k;
+
+ if (buf == NULL)
+ return 1;
+
+ while (len > 0)
+ {
+ k = len < LZO_NMAX ? (unsigned) len : LZO_NMAX;
+ len -= k;
+ if (k >= 16) do
+ {
+ LZO_DO16(buf,0);
+ buf += 16;
+ k -= 16;
+ } while (k >= 16);
+ if (k != 0) do
+ {
+ s1 += *buf++;
+ s2 += s1;
+ } while (--k > 0);
+ s1 %= LZO_BASE;
+ s2 %= LZO_BASE;
+ }
+ return (s2 << 16) | s1;
+}
+
+#undef LZO_DO1
+#undef LZO_DO2
+#undef LZO_DO4
+#undef LZO_DO8
+#undef LZO_DO16
+
+#endif
+#if !defined(MINILZO_CFG_SKIP_LZO_STRING)
+#undef lzo_memcmp
+#undef lzo_memcpy
+#undef lzo_memmove
+#undef lzo_memset
+#if !defined(__LZO_MMODEL_HUGE)
+# undef LZO_HAVE_MM_HUGE_PTR
+#endif
+#define lzo_hsize_t lzo_uint
+#define lzo_hvoid_p lzo_voidp
+#define lzo_hbyte_p lzo_bytep
+#define LZOLIB_PUBLIC(r,f) LZO_PUBLIC(r) f
+#define lzo_hmemcmp lzo_memcmp
+#define lzo_hmemcpy lzo_memcpy
+#define lzo_hmemmove lzo_memmove
+#define lzo_hmemset lzo_memset
+#define __LZOLIB_HMEMCPY_CH_INCLUDED 1
+#if !defined(LZOLIB_PUBLIC)
+# define LZOLIB_PUBLIC(r,f) r __LZOLIB_FUNCNAME(f)
+#endif
+LZOLIB_PUBLIC(int, lzo_hmemcmp) (const lzo_hvoid_p s1, const lzo_hvoid_p s2, lzo_hsize_t len)
+{
+#if (LZO_HAVE_MM_HUGE_PTR) || !(HAVE_MEMCMP)
+ const lzo_hbyte_p p1 = (const lzo_hbyte_p) s1;
+ const lzo_hbyte_p p2 = (const lzo_hbyte_p) s2;
+ if __lzo_likely(len > 0) do
+ {
+ int d = *p1 - *p2;
+ if (d != 0)
+ return d;
+ p1++; p2++;
+ } while __lzo_likely(--len > 0);
+ return 0;
+#else
+ return memcmp(s1, s2, len);
+#endif
+}
+LZOLIB_PUBLIC(lzo_hvoid_p, lzo_hmemcpy) (lzo_hvoid_p dest, const lzo_hvoid_p src, lzo_hsize_t len)
+{
+#if (LZO_HAVE_MM_HUGE_PTR) || !(HAVE_MEMCPY)
+ lzo_hbyte_p p1 = (lzo_hbyte_p) dest;
+ const lzo_hbyte_p p2 = (const lzo_hbyte_p) src;
+ if (!(len > 0) || p1 == p2)
+ return dest;
+ do
+ *p1++ = *p2++;
+ while __lzo_likely(--len > 0);
+ return dest;
+#else
+ return memcpy(dest, src, len);
+#endif
+}
+LZOLIB_PUBLIC(lzo_hvoid_p, lzo_hmemmove) (lzo_hvoid_p dest, const lzo_hvoid_p src, lzo_hsize_t len)
+{
+#if (LZO_HAVE_MM_HUGE_PTR) || !(HAVE_MEMMOVE)
+ lzo_hbyte_p p1 = (lzo_hbyte_p) dest;
+ const lzo_hbyte_p p2 = (const lzo_hbyte_p) src;
+ if (!(len > 0) || p1 == p2)
+ return dest;
+ if (p1 < p2)
+ {
+ do
+ *p1++ = *p2++;
+ while __lzo_likely(--len > 0);
+ }
+ else
+ {
+ p1 += len;
+ p2 += len;
+ do
+ *--p1 = *--p2;
+ while __lzo_likely(--len > 0);
+ }
+ return dest;
+#else
+ return memmove(dest, src, len);
+#endif
+}
+LZOLIB_PUBLIC(lzo_hvoid_p, lzo_hmemset) (lzo_hvoid_p s, int c, lzo_hsize_t len)
+{
+#if (LZO_HAVE_MM_HUGE_PTR) || !(HAVE_MEMSET)
+ lzo_hbyte_p p = (lzo_hbyte_p) s;
+ if __lzo_likely(len > 0) do
+ *p++ = (unsigned char) c;
+ while __lzo_likely(--len > 0);
+ return s;
+#else
+ return memset(s, c, len);
+#endif
+}
+#undef LZOLIB_PUBLIC
+#endif
+#if !defined(MINILZO_CFG_SKIP_LZO_INIT)
+
+#if !defined(__LZO_IN_MINILZO)
+
+#define ACC_WANT_ACC_CHK_CH 1
+#undef ACCCHK_ASSERT
+
+ ACCCHK_ASSERT_IS_SIGNED_T(lzo_int)
+ ACCCHK_ASSERT_IS_UNSIGNED_T(lzo_uint)
+
+ ACCCHK_ASSERT_IS_SIGNED_T(lzo_int32)
+ ACCCHK_ASSERT_IS_UNSIGNED_T(lzo_uint32)
+ ACCCHK_ASSERT((LZO_UINT32_C(1) << (int)(8*sizeof(LZO_UINT32_C(1))-1)) > 0)
+ ACCCHK_ASSERT(sizeof(lzo_uint32) >= 4)
+#if defined(LZO_UINT64_MAX)
+ ACCCHK_ASSERT(sizeof(lzo_uint64) == 8)
+ ACCCHK_ASSERT_IS_SIGNED_T(lzo_int64)
+ ACCCHK_ASSERT_IS_UNSIGNED_T(lzo_uint64)
+#endif
+
+#if !defined(__LZO_UINTPTR_T_IS_POINTER)
+ ACCCHK_ASSERT_IS_UNSIGNED_T(lzo_uintptr_t)
+#endif
+ ACCCHK_ASSERT(sizeof(lzo_uintptr_t) >= sizeof(lzo_voidp))
+
+ ACCCHK_ASSERT_IS_UNSIGNED_T(lzo_xint)
+ ACCCHK_ASSERT(sizeof(lzo_xint) >= sizeof(lzo_uint32))
+ ACCCHK_ASSERT(sizeof(lzo_xint) >= sizeof(lzo_uint))
+ ACCCHK_ASSERT(sizeof(lzo_xint) == sizeof(lzo_uint32) || sizeof(lzo_xint) == sizeof(lzo_uint))
+
+#endif
+#undef ACCCHK_ASSERT
+
+#if 0
+#define WANT_lzo_bitops_clz32 1
+#define WANT_lzo_bitops_clz64 1
+#endif
+#define WANT_lzo_bitops_ctz32 1
+#define WANT_lzo_bitops_ctz64 1
+
+#if (defined(_WIN32) || defined(_WIN64)) && ((LZO_CC_INTELC && (__INTEL_COMPILER >= 1000)) || (LZO_CC_MSC && (_MSC_VER >= 1400)))
+#include <intrin.h>
+#if !defined(lzo_bitops_clz32) && defined(WANT_lzo_bitops_clz32) && 0
+#pragma intrinsic(_BitScanReverse)
+static __lzo_inline unsigned lzo_bitops_clz32(lzo_uint32 v)
+{
+ unsigned long r;
+ (void) _BitScanReverse(&r, v);
+ return (unsigned) r;
+}
+#define lzo_bitops_clz32 lzo_bitops_clz32
+#endif
+#if !defined(lzo_bitops_clz64) && defined(WANT_lzo_bitops_clz64) && defined(LZO_UINT64_MAX) && 0
+#pragma intrinsic(_BitScanReverse64)
+static __lzo_inline unsigned lzo_bitops_clz64(lzo_uint64 v)
+{
+ unsigned long r;
+ (void) _BitScanReverse64(&r, v);
+ return (unsigned) r;
+}
+#define lzo_bitops_clz64 lzo_bitops_clz64
+#endif
+#if !defined(lzo_bitops_ctz32) && defined(WANT_lzo_bitops_ctz32)
+#pragma intrinsic(_BitScanForward)
+static __lzo_inline unsigned lzo_bitops_ctz32(lzo_uint32 v)
+{
+ unsigned long r;
+ (void) _BitScanForward(&r, v);
+ return (unsigned) r;
+}
+#define lzo_bitops_ctz32 lzo_bitops_ctz32
+#endif
+#if !defined(lzo_bitops_ctz64) && defined(WANT_lzo_bitops_ctz64) && defined(LZO_UINT64_MAX)
+#pragma intrinsic(_BitScanForward64)
+static __lzo_inline unsigned lzo_bitops_ctz64(lzo_uint64 v)
+{
+ unsigned long r;
+ (void) _BitScanForward64(&r, v);
+ return (unsigned) r;
+}
+#define lzo_bitops_ctz64 lzo_bitops_ctz64
+#endif
+
+#elif (LZO_CC_CLANG || (LZO_CC_GNUC >= 0x030400ul) || (LZO_CC_INTELC && (__INTEL_COMPILER >= 1000)) || LZO_CC_LLVM)
+#if !defined(lzo_bitops_clz32) && defined(WANT_lzo_bitops_clz32)
+#define lzo_bitops_clz32(v) ((unsigned) __builtin_clz(v))
+#endif
+#if !defined(lzo_bitops_clz64) && defined(WANT_lzo_bitops_clz64) && defined(LZO_UINT64_MAX)
+#define lzo_bitops_clz64(v) ((unsigned) __builtin_clzll(v))
+#endif
+#if !defined(lzo_bitops_ctz32) && defined(WANT_lzo_bitops_ctz32)
+#define lzo_bitops_ctz32(v) ((unsigned) __builtin_ctz(v))
+#endif
+#if !defined(lzo_bitops_ctz64) && defined(WANT_lzo_bitops_ctz64) && defined(LZO_UINT64_MAX)
+#define lzo_bitops_ctz64(v) ((unsigned) __builtin_ctzll(v))
+#endif
+#if !defined(lzo_bitops_popcount32) && defined(WANT_lzo_bitops_popcount32)
+#define lzo_bitops_popcount32(v) ((unsigned) __builtin_popcount(v))
+#endif
+#if !defined(lzo_bitops_popcount32) && defined(WANT_lzo_bitops_popcount64) && defined(LZO_UINT64_MAX)
+#define lzo_bitops_popcount64(v) ((unsigned) __builtin_popcountll(v))
+#endif
+#endif
+
+#if 0
+#define u2p(ptr,off) ((lzo_voidp) (((lzo_bytep)(lzo_voidp)(ptr)) + (off)))
+#else
+static __lzo_noinline lzo_voidp u2p(lzo_voidp ptr, lzo_uint off)
+{
+ return (lzo_voidp) ((lzo_bytep) ptr + off);
+}
+#endif
+
+LZO_PUBLIC(int)
+_lzo_config_check(void)
+{
+ lzo_bool r = 1;
+ union {
+ lzo_xint a[2]; unsigned char b[2*LZO_MAX(8,sizeof(lzo_xint))];
+#if defined(LZO_UNALIGNED_OK_8)
+ lzo_uint64 c[2];
+#endif
+ unsigned short x[2]; lzo_uint32 y[2]; lzo_uint z[2];
+ } u;
+ lzo_voidp p;
+
+ u.a[0] = u.a[1] = 0;
+ p = u2p(&u, 0);
+ r &= ((* (lzo_bytep) p) == 0);
+#if !defined(LZO_CFG_NO_CONFIG_CHECK)
+#if defined(LZO_ABI_BIG_ENDIAN)
+ u.a[0] = u.a[1] = 0; u.b[sizeof(lzo_uint) - 1] = 128;
+ p = u2p(&u, 0);
+ r &= ((* (lzo_uintp) p) == 128);
+#endif
+#if defined(LZO_ABI_LITTLE_ENDIAN)
+ u.a[0] = u.a[1] = 0; u.b[0] = 128;
+ p = u2p(&u, 0);
+ r &= ((* (lzo_uintp) p) == 128);
+#endif
+#if defined(LZO_UNALIGNED_OK_2)
+ u.a[0] = u.a[1] = 0;
+ u.b[0] = 1; u.b[sizeof(unsigned short) + 1] = 2;
+ p = u2p(&u, 1);
+ r &= ((* (lzo_ushortp) p) == 0);
+#endif
+#if defined(LZO_UNALIGNED_OK_4)
+ u.a[0] = u.a[1] = 0;
+ u.b[0] = 3; u.b[sizeof(lzo_uint32) + 1] = 4;
+ p = u2p(&u, 1);
+ r &= ((* (lzo_uint32p) p) == 0);
+#endif
+#if defined(LZO_UNALIGNED_OK_8)
+ u.c[0] = u.c[1] = 0;
+ u.b[0] = 5; u.b[sizeof(lzo_uint64) + 1] = 6;
+ p = u2p(&u, 1);
+ r &= ((* (lzo_uint64p) p) == 0);
+#endif
+#if defined(lzo_bitops_clz32)
+ { unsigned i; lzo_uint32 v = 1;
+ for (i = 0; i < 31; i++, v <<= 1)
+ r &= lzo_bitops_clz32(v) == 31 - i;
+ }
+#endif
+#if defined(lzo_bitops_clz64)
+ { unsigned i; lzo_uint64 v = 1;
+ for (i = 0; i < 63; i++, v <<= 1)
+ r &= lzo_bitops_clz64(v) == 63 - i;
+ }
+#endif
+#if defined(lzo_bitops_ctz32)
+ { unsigned i; lzo_uint32 v = 1;
+ for (i = 0; i < 31; i++, v <<= 1)
+ r &= lzo_bitops_ctz32(v) == i;
+ }
+#endif
+#if defined(lzo_bitops_ctz64)
+ { unsigned i; lzo_uint64 v = 1;
+ for (i = 0; i < 63; i++, v <<= 1)
+ r &= lzo_bitops_ctz64(v) == i;
+ }
+#endif
+#endif
+
+ return r == 1 ? LZO_E_OK : LZO_E_ERROR;
+}
+
+LZO_PUBLIC(int)
+__lzo_init_v2(unsigned v, int s1, int s2, int s3, int s4, int s5,
+ int s6, int s7, int s8, int s9)
+{
+ int r;
+
+#if defined(__LZO_IN_MINILZO)
+#elif (LZO_CC_MSC && ((_MSC_VER) < 700))
+#else
+#define ACC_WANT_ACC_CHK_CH 1
+#undef ACCCHK_ASSERT
+#define ACCCHK_ASSERT(expr) LZO_COMPILE_TIME_ASSERT(expr)
+#endif
+#undef ACCCHK_ASSERT
+
+ if (v == 0)
+ return LZO_E_ERROR;
+
+ r = (s1 == -1 || s1 == (int) sizeof(short)) &&
+ (s2 == -1 || s2 == (int) sizeof(int)) &&
+ (s3 == -1 || s3 == (int) sizeof(long)) &&
+ (s4 == -1 || s4 == (int) sizeof(lzo_uint32)) &&
+ (s5 == -1 || s5 == (int) sizeof(lzo_uint)) &&
+ (s6 == -1 || s6 == (int) lzo_sizeof_dict_t) &&
+ (s7 == -1 || s7 == (int) sizeof(char *)) &&
+ (s8 == -1 || s8 == (int) sizeof(lzo_voidp)) &&
+ (s9 == -1 || s9 == (int) sizeof(lzo_callback_t));
+ if (!r)
+ return LZO_E_ERROR;
+
+ r = _lzo_config_check();
+ if (r != LZO_E_OK)
+ return r;
+
+ return r;
+}
+
+#if !defined(__LZO_IN_MINILZO)
+
+#if (LZO_OS_WIN16 && LZO_CC_WATCOMC) && defined(__SW_BD)
+
+#if 0
+BOOL FAR PASCAL LibMain ( HANDLE hInstance, WORD wDataSegment,
+ WORD wHeapSize, LPSTR lpszCmdLine )
+#else
+int __far __pascal LibMain ( int a, short b, short c, long d )
+#endif
+{
+ LZO_UNUSED(a); LZO_UNUSED(b); LZO_UNUSED(c); LZO_UNUSED(d);
+ return 1;
+}
+
+#endif
+
+#endif
+
+#endif
+
+#define LZO1X 1
+#define LZO_EOF_CODE 1
+#define M2_MAX_OFFSET 0x0800
+
+#if !defined(MINILZO_CFG_SKIP_LZO1X_1_COMPRESS)
+
+#if 1 && defined(UA_GET32)
+#undef LZO_DICT_USE_PTR
+#define LZO_DICT_USE_PTR 0
+#undef lzo_dict_t
+#define lzo_dict_t unsigned short
+#endif
+
+#define LZO_NEED_DICT_H 1
+#ifndef D_BITS
+#define D_BITS 14
+#endif
+#define D_INDEX1(d,p) d = DM(DMUL(0x21,DX3(p,5,5,6)) >> 5)
+#define D_INDEX2(d,p) d = (d & (D_MASK & 0x7ff)) ^ (D_HIGH | 0x1f)
+#if 1
+#define DINDEX(dv,p) DM(((DMUL(0x1824429d,dv)) >> (32-D_BITS)))
+#else
+#define DINDEX(dv,p) DM((dv) + ((dv) >> (32-D_BITS)))
+#endif
+
+#ifndef __LZO_CONFIG1X_H
+#define __LZO_CONFIG1X_H 1
+
+#if !defined(LZO1X) && !defined(LZO1Y) && !defined(LZO1Z)
+# define LZO1X 1
+#endif
+
+#if !defined(__LZO_IN_MINILZO)
+#include "lzo/lzo1x.h"
+#endif
+
+#ifndef LZO_EOF_CODE
+#define LZO_EOF_CODE 1
+#endif
+#undef LZO_DETERMINISTIC
+
+#define M1_MAX_OFFSET 0x0400
+#ifndef M2_MAX_OFFSET
+#define M2_MAX_OFFSET 0x0800
+#endif
+#define M3_MAX_OFFSET 0x4000
+#define M4_MAX_OFFSET 0xbfff
+
+#define MX_MAX_OFFSET (M1_MAX_OFFSET + M2_MAX_OFFSET)
+
+#define M1_MIN_LEN 2
+#define M1_MAX_LEN 2
+#define M2_MIN_LEN 3
+#ifndef M2_MAX_LEN
+#define M2_MAX_LEN 8
+#endif
+#define M3_MIN_LEN 3
+#define M3_MAX_LEN 33
+#define M4_MIN_LEN 3
+#define M4_MAX_LEN 9
+
+#define M1_MARKER 0
+#define M2_MARKER 64
+#define M3_MARKER 32
+#define M4_MARKER 16
+
+#ifndef MIN_LOOKAHEAD
+#define MIN_LOOKAHEAD (M2_MAX_LEN + 1)
+#endif
+
+#if defined(LZO_NEED_DICT_H)
+
+#ifndef LZO_HASH
+#define LZO_HASH LZO_HASH_LZO_INCREMENTAL_B
+#endif
+#define DL_MIN_LEN M2_MIN_LEN
+
+#ifndef __LZO_DICT_H
+#define __LZO_DICT_H 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if !defined(D_BITS) && defined(DBITS)
+# define D_BITS DBITS
+#endif
+#if !defined(D_BITS)
+# error "D_BITS is not defined"
+#endif
+#if (D_BITS < 16)
+# define D_SIZE LZO_SIZE(D_BITS)
+# define D_MASK LZO_MASK(D_BITS)
+#else
+# define D_SIZE LZO_USIZE(D_BITS)
+# define D_MASK LZO_UMASK(D_BITS)
+#endif
+#define D_HIGH ((D_MASK >> 1) + 1)
+
+#if !defined(DD_BITS)
+# define DD_BITS 0
+#endif
+#define DD_SIZE LZO_SIZE(DD_BITS)
+#define DD_MASK LZO_MASK(DD_BITS)
+
+#if !defined(DL_BITS)
+# define DL_BITS (D_BITS - DD_BITS)
+#endif
+#if (DL_BITS < 16)
+# define DL_SIZE LZO_SIZE(DL_BITS)
+# define DL_MASK LZO_MASK(DL_BITS)
+#else
+# define DL_SIZE LZO_USIZE(DL_BITS)
+# define DL_MASK LZO_UMASK(DL_BITS)
+#endif
+
+#if (D_BITS != DL_BITS + DD_BITS)
+# error "D_BITS does not match"
+#endif
+#if (D_BITS < 6 || D_BITS > 18)
+# error "invalid D_BITS"
+#endif
+#if (DL_BITS < 6 || DL_BITS > 20)
+# error "invalid DL_BITS"
+#endif
+#if (DD_BITS < 0 || DD_BITS > 6)
+# error "invalid DD_BITS"
+#endif
+
+#if !defined(DL_MIN_LEN)
+# define DL_MIN_LEN 3
+#endif
+#if !defined(DL_SHIFT)
+# define DL_SHIFT ((DL_BITS + (DL_MIN_LEN - 1)) / DL_MIN_LEN)
+#endif
+
+#define LZO_HASH_GZIP 1
+#define LZO_HASH_GZIP_INCREMENTAL 2
+#define LZO_HASH_LZO_INCREMENTAL_A 3
+#define LZO_HASH_LZO_INCREMENTAL_B 4
+
+#if !defined(LZO_HASH)
+# error "choose a hashing strategy"
+#endif
+
+#undef DM
+#undef DX
+
+#if (DL_MIN_LEN == 3)
+# define _DV2_A(p,shift1,shift2) \
+ (((( (lzo_xint)((p)[0]) << shift1) ^ (p)[1]) << shift2) ^ (p)[2])
+# define _DV2_B(p,shift1,shift2) \
+ (((( (lzo_xint)((p)[2]) << shift1) ^ (p)[1]) << shift2) ^ (p)[0])
+# define _DV3_B(p,shift1,shift2,shift3) \
+ ((_DV2_B((p)+1,shift1,shift2) << (shift3)) ^ (p)[0])
+#elif (DL_MIN_LEN == 2)
+# define _DV2_A(p,shift1,shift2) \
+ (( (lzo_xint)(p[0]) << shift1) ^ p[1])
+# define _DV2_B(p,shift1,shift2) \
+ (( (lzo_xint)(p[1]) << shift1) ^ p[2])
+#else
+# error "invalid DL_MIN_LEN"
+#endif
+#define _DV_A(p,shift) _DV2_A(p,shift,shift)
+#define _DV_B(p,shift) _DV2_B(p,shift,shift)
+#define DA2(p,s1,s2) \
+ (((((lzo_xint)((p)[2]) << (s2)) + (p)[1]) << (s1)) + (p)[0])
+#define DS2(p,s1,s2) \
+ (((((lzo_xint)((p)[2]) << (s2)) - (p)[1]) << (s1)) - (p)[0])
+#define DX2(p,s1,s2) \
+ (((((lzo_xint)((p)[2]) << (s2)) ^ (p)[1]) << (s1)) ^ (p)[0])
+#define DA3(p,s1,s2,s3) ((DA2((p)+1,s2,s3) << (s1)) + (p)[0])
+#define DS3(p,s1,s2,s3) ((DS2((p)+1,s2,s3) << (s1)) - (p)[0])
+#define DX3(p,s1,s2,s3) ((DX2((p)+1,s2,s3) << (s1)) ^ (p)[0])
+#define DMS(v,s) ((lzo_uint) (((v) & (D_MASK >> (s))) << (s)))
+#define DM(v) DMS(v,0)
+
+#if (LZO_HASH == LZO_HASH_GZIP)
+# define _DINDEX(dv,p) (_DV_A((p),DL_SHIFT))
+
+#elif (LZO_HASH == LZO_HASH_GZIP_INCREMENTAL)
+# define __LZO_HASH_INCREMENTAL 1
+# define DVAL_FIRST(dv,p) dv = _DV_A((p),DL_SHIFT)
+# define DVAL_NEXT(dv,p) dv = (((dv) << DL_SHIFT) ^ p[2])
+# define _DINDEX(dv,p) (dv)
+# define DVAL_LOOKAHEAD DL_MIN_LEN
+
+#elif (LZO_HASH == LZO_HASH_LZO_INCREMENTAL_A)
+# define __LZO_HASH_INCREMENTAL 1
+# define DVAL_FIRST(dv,p) dv = _DV_A((p),5)
+# define DVAL_NEXT(dv,p) \
+ dv ^= (lzo_xint)(p[-1]) << (2*5); dv = (((dv) << 5) ^ p[2])
+# define _DINDEX(dv,p) ((DMUL(0x9f5f,dv)) >> 5)
+# define DVAL_LOOKAHEAD DL_MIN_LEN
+
+#elif (LZO_HASH == LZO_HASH_LZO_INCREMENTAL_B)
+# define __LZO_HASH_INCREMENTAL 1
+# define DVAL_FIRST(dv,p) dv = _DV_B((p),5)
+# define DVAL_NEXT(dv,p) \
+ dv ^= p[-1]; dv = (((dv) >> 5) ^ ((lzo_xint)(p[2]) << (2*5)))
+# define _DINDEX(dv,p) ((DMUL(0x9f5f,dv)) >> 5)
+# define DVAL_LOOKAHEAD DL_MIN_LEN
+
+#else
+# error "choose a hashing strategy"
+#endif
+
+#ifndef DINDEX
+#define DINDEX(dv,p) ((lzo_uint)((_DINDEX(dv,p)) & DL_MASK) << DD_BITS)
+#endif
+#if !defined(DINDEX1) && defined(D_INDEX1)
+#define DINDEX1 D_INDEX1
+#endif
+#if !defined(DINDEX2) && defined(D_INDEX2)
+#define DINDEX2 D_INDEX2
+#endif
+
+#if !defined(__LZO_HASH_INCREMENTAL)
+# define DVAL_FIRST(dv,p) ((void) 0)
+# define DVAL_NEXT(dv,p) ((void) 0)
+# define DVAL_LOOKAHEAD 0
+#endif
+
+#if !defined(DVAL_ASSERT)
+#if defined(__LZO_HASH_INCREMENTAL) && !defined(NDEBUG)
+#if (LZO_CC_CLANG || (LZO_CC_GNUC >= 0x020700ul) || LZO_CC_LLVM)
+static void __attribute__((__unused__))
+#else
+static void
+#endif
+DVAL_ASSERT(lzo_xint dv, const lzo_bytep p)
+{
+ lzo_xint df;
+ DVAL_FIRST(df,(p));
+ assert(DINDEX(dv,p) == DINDEX(df,p));
+}
+#else
+# define DVAL_ASSERT(dv,p) ((void) 0)
+#endif
+#endif
+
+#if (LZO_DICT_USE_PTR)
+# define DENTRY(p,in) (p)
+# define GINDEX(m_pos,m_off,dict,dindex,in) m_pos = dict[dindex]
+#else
+# define DENTRY(p,in) ((lzo_dict_t) pd(p, in))
+# define GINDEX(m_pos,m_off,dict,dindex,in) m_off = dict[dindex]
+#endif
+
+#if (DD_BITS == 0)
+
+# define UPDATE_D(dict,drun,dv,p,in) dict[ DINDEX(dv,p) ] = DENTRY(p,in)
+# define UPDATE_I(dict,drun,index,p,in) dict[index] = DENTRY(p,in)
+# define UPDATE_P(ptr,drun,p,in) (ptr)[0] = DENTRY(p,in)
+
+#else
+
+# define UPDATE_D(dict,drun,dv,p,in) \
+ dict[ DINDEX(dv,p) + drun++ ] = DENTRY(p,in); drun &= DD_MASK
+# define UPDATE_I(dict,drun,index,p,in) \
+ dict[ (index) + drun++ ] = DENTRY(p,in); drun &= DD_MASK
+# define UPDATE_P(ptr,drun,p,in) \
+ (ptr) [ drun++ ] = DENTRY(p,in); drun &= DD_MASK
+
+#endif
+
+#if (LZO_DICT_USE_PTR)
+
+#define LZO_CHECK_MPOS_DET(m_pos,m_off,in,ip,max_offset) \
+ (m_pos == NULL || (m_off = pd(ip, m_pos)) > max_offset)
+
+#define LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,max_offset) \
+ (BOUNDS_CHECKING_OFF_IN_EXPR(( \
+ m_pos = ip - (lzo_uint) PTR_DIFF(ip,m_pos), \
+ PTR_LT(m_pos,in) || \
+ (m_off = (lzo_uint) PTR_DIFF(ip,m_pos)) == 0 || \
+ m_off > max_offset )))
+
+#else
+
+#define LZO_CHECK_MPOS_DET(m_pos,m_off,in,ip,max_offset) \
+ (m_off == 0 || \
+ ((m_off = pd(ip, in) - m_off) > max_offset) || \
+ (m_pos = (ip) - (m_off), 0) )
+
+#define LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,max_offset) \
+ (pd(ip, in) <= m_off || \
+ ((m_off = pd(ip, in) - m_off) > max_offset) || \
+ (m_pos = (ip) - (m_off), 0) )
+
+#endif
+
+#if (LZO_DETERMINISTIC)
+# define LZO_CHECK_MPOS LZO_CHECK_MPOS_DET
+#else
+# define LZO_CHECK_MPOS LZO_CHECK_MPOS_NON_DET
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+#endif
+
+#endif
+
+#define LZO_DETERMINISTIC !(LZO_DICT_USE_PTR)
+
+#ifndef DO_COMPRESS
+#define DO_COMPRESS lzo1x_1_compress
+#endif
+
+#if 1 && defined(DO_COMPRESS) && !defined(do_compress)
+# define do_compress LZO_CPP_ECONCAT2(DO_COMPRESS,_core)
+#endif
+
+#if defined(UA_GET64)
+# define WANT_lzo_bitops_ctz64 1
+#elif defined(UA_GET32)
+# define WANT_lzo_bitops_ctz32 1
+#endif
+
+#if (defined(_WIN32) || defined(_WIN64)) && ((LZO_CC_INTELC && (__INTEL_COMPILER >= 1000)) || (LZO_CC_MSC && (_MSC_VER >= 1400)))
+#include <intrin.h>
+#if !defined(lzo_bitops_clz32) && defined(WANT_lzo_bitops_clz32) && 0
+#pragma intrinsic(_BitScanReverse)
+static __lzo_inline unsigned lzo_bitops_clz32(lzo_uint32 v)
+{
+ unsigned long r;
+ (void) _BitScanReverse(&r, v);
+ return (unsigned) r;
+}
+#define lzo_bitops_clz32 lzo_bitops_clz32
+#endif
+#if !defined(lzo_bitops_clz64) && defined(WANT_lzo_bitops_clz64) && defined(LZO_UINT64_MAX) && 0
+#pragma intrinsic(_BitScanReverse64)
+static __lzo_inline unsigned lzo_bitops_clz64(lzo_uint64 v)
+{
+ unsigned long r;
+ (void) _BitScanReverse64(&r, v);
+ return (unsigned) r;
+}
+#define lzo_bitops_clz64 lzo_bitops_clz64
+#endif
+#if !defined(lzo_bitops_ctz32) && defined(WANT_lzo_bitops_ctz32)
+#pragma intrinsic(_BitScanForward)
+static __lzo_inline unsigned lzo_bitops_ctz32(lzo_uint32 v)
+{
+ unsigned long r;
+ (void) _BitScanForward(&r, v);
+ return (unsigned) r;
+}
+#define lzo_bitops_ctz32 lzo_bitops_ctz32
+#endif
+#if !defined(lzo_bitops_ctz64) && defined(WANT_lzo_bitops_ctz64) && defined(LZO_UINT64_MAX)
+#pragma intrinsic(_BitScanForward64)
+static __lzo_inline unsigned lzo_bitops_ctz64(lzo_uint64 v)
+{
+ unsigned long r;
+ (void) _BitScanForward64(&r, v);
+ return (unsigned) r;
+}
+#define lzo_bitops_ctz64 lzo_bitops_ctz64
+#endif
+
+#elif (LZO_CC_CLANG || (LZO_CC_GNUC >= 0x030400ul) || (LZO_CC_INTELC && (__INTEL_COMPILER >= 1000)) || LZO_CC_LLVM)
+#if !defined(lzo_bitops_clz32) && defined(WANT_lzo_bitops_clz32)
+#define lzo_bitops_clz32(v) ((unsigned) __builtin_clz(v))
+#endif
+#if !defined(lzo_bitops_clz64) && defined(WANT_lzo_bitops_clz64) && defined(LZO_UINT64_MAX)
+#define lzo_bitops_clz64(v) ((unsigned) __builtin_clzll(v))
+#endif
+#if !defined(lzo_bitops_ctz32) && defined(WANT_lzo_bitops_ctz32)
+#define lzo_bitops_ctz32(v) ((unsigned) __builtin_ctz(v))
+#endif
+#if !defined(lzo_bitops_ctz64) && defined(WANT_lzo_bitops_ctz64) && defined(LZO_UINT64_MAX)
+#define lzo_bitops_ctz64(v) ((unsigned) __builtin_ctzll(v))
+#endif
+#if !defined(lzo_bitops_popcount32) && defined(WANT_lzo_bitops_popcount32)
+#define lzo_bitops_popcount32(v) ((unsigned) __builtin_popcount(v))
+#endif
+#if !defined(lzo_bitops_popcount32) && defined(WANT_lzo_bitops_popcount64) && defined(LZO_UINT64_MAX)
+#define lzo_bitops_popcount64(v) ((unsigned) __builtin_popcountll(v))
+#endif
+#endif
+
+static __lzo_noinline lzo_uint
+do_compress ( const lzo_bytep in , lzo_uint in_len,
+ lzo_bytep out, lzo_uintp out_len,
+ lzo_uint ti, lzo_voidp wrkmem)
+{
+ register const lzo_bytep ip;
+ lzo_bytep op;
+ const lzo_bytep const in_end = in + in_len;
+ const lzo_bytep const ip_end = in + in_len - 20;
+ const lzo_bytep ii;
+ lzo_dict_p const dict = (lzo_dict_p) wrkmem;
+
+ op = out;
+ ip = in;
+ ii = ip - ti;
+
+ ip += ti < 4 ? 4 - ti : 0;
+ for (;;)
+ {
+ const lzo_bytep m_pos;
+#if !(LZO_DETERMINISTIC)
+ LZO_DEFINE_UNINITIALIZED_VAR(lzo_uint, m_off, 0);
+ lzo_uint m_len;
+ lzo_uint dindex;
+next:
+ if __lzo_unlikely(ip >= ip_end)
+ break;
+ DINDEX1(dindex,ip);
+ GINDEX(m_pos,m_off,dict,dindex,in);
+ if (LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,M4_MAX_OFFSET))
+ goto literal;
+#if 1
+ if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3])
+ goto try_match;
+ DINDEX2(dindex,ip);
+#endif
+ GINDEX(m_pos,m_off,dict,dindex,in);
+ if (LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,M4_MAX_OFFSET))
+ goto literal;
+ if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3])
+ goto try_match;
+ goto literal;
+
+try_match:
+#if defined(UA_GET32)
+ if (UA_GET32(m_pos) != UA_GET32(ip))
+#else
+ if (m_pos[0] != ip[0] || m_pos[1] != ip[1] || m_pos[2] != ip[2] || m_pos[3] != ip[3])
+#endif
+ {
+literal:
+ UPDATE_I(dict,0,dindex,ip,in);
+ ip += 1 + ((ip - ii) >> 5);
+ continue;
+ }
+ UPDATE_I(dict,0,dindex,ip,in);
+#else
+ lzo_uint m_off;
+ lzo_uint m_len;
+ {
+ lzo_uint32 dv;
+ lzo_uint dindex;
+literal:
+ ip += 1 + ((ip - ii) >> 5);
+next:
+ if __lzo_unlikely(ip >= ip_end)
+ break;
+ dv = UA_GET32(ip);
+ dindex = DINDEX(dv,ip);
+ GINDEX(m_off,m_pos,in+dict,dindex,in);
+ UPDATE_I(dict,0,dindex,ip,in);
+ if __lzo_unlikely(dv != UA_GET32(m_pos))
+ goto literal;
+ }
+#endif
+
+ {
+ register lzo_uint t = pd(ip,ii);
+ if (t != 0)
+ {
+ if (t <= 3)
+ {
+ op[-2] |= LZO_BYTE(t);
+#if defined(UA_COPY32)
+ UA_COPY32(op, ii);
+ op += t;
+#else
+ { do *op++ = *ii++; while (--t > 0); }
+#endif
+ }
+#if defined(UA_COPY32) || defined(UA_COPY64)
+ else if (t <= 16)
+ {
+ *op++ = LZO_BYTE(t - 3);
+#if defined(UA_COPY64)
+ UA_COPY64(op, ii);
+ UA_COPY64(op+8, ii+8);
+#else
+ UA_COPY32(op, ii);
+ UA_COPY32(op+4, ii+4);
+ UA_COPY32(op+8, ii+8);
+ UA_COPY32(op+12, ii+12);
+#endif
+ op += t;
+ }
+#endif
+ else
+ {
+ if (t <= 18)
+ *op++ = LZO_BYTE(t - 3);
+ else
+ {
+ register lzo_uint tt = t - 18;
+ *op++ = 0;
+ while __lzo_unlikely(tt > 255)
+ {
+ tt -= 255;
+#if 1 && (LZO_CC_MSC && (_MSC_VER >= 1400))
+ * (volatile unsigned char *) op++ = 0;
+#else
+ *op++ = 0;
+#endif
+ }
+ assert(tt > 0);
+ *op++ = LZO_BYTE(tt);
+ }
+#if defined(UA_COPY32) || defined(UA_COPY64)
+ do {
+#if defined(UA_COPY64)
+ UA_COPY64(op, ii);
+ UA_COPY64(op+8, ii+8);
+#else
+ UA_COPY32(op, ii);
+ UA_COPY32(op+4, ii+4);
+ UA_COPY32(op+8, ii+8);
+ UA_COPY32(op+12, ii+12);
+#endif
+ op += 16; ii += 16; t -= 16;
+ } while (t >= 16); if (t > 0)
+#endif
+ { do *op++ = *ii++; while (--t > 0); }
+ }
+ }
+ }
+ m_len = 4;
+ {
+#if defined(UA_GET64)
+ lzo_uint64 v;
+ v = UA_GET64(ip + m_len) ^ UA_GET64(m_pos + m_len);
+ if __lzo_unlikely(v == 0) {
+ do {
+ m_len += 8;
+ v = UA_GET64(ip + m_len) ^ UA_GET64(m_pos + m_len);
+ if __lzo_unlikely(ip + m_len >= ip_end)
+ goto m_len_done;
+ } while (v == 0);
+ }
+#if (LZO_ABI_LITTLE_ENDIAN) && defined(lzo_bitops_ctz64)
+ m_len += lzo_bitops_ctz64(v) / CHAR_BIT;
+#elif (LZO_ABI_LITTLE_ENDIAN)
+ if ((v & UCHAR_MAX) == 0) do {
+ v >>= CHAR_BIT;
+ m_len += 1;
+ } while ((v & UCHAR_MAX) == 0);
+#else
+ if (ip[m_len] == m_pos[m_len]) do {
+ m_len += 1;
+ } while (ip[m_len] == m_pos[m_len]);
+#endif
+#elif defined(UA_GET32)
+ lzo_uint32 v;
+ v = UA_GET32(ip + m_len) ^ UA_GET32(m_pos + m_len);
+ if __lzo_unlikely(v == 0) {
+ do {
+ m_len += 4;
+ v = UA_GET32(ip + m_len) ^ UA_GET32(m_pos + m_len);
+ if __lzo_unlikely(ip + m_len >= ip_end)
+ goto m_len_done;
+ } while (v == 0);
+ }
+#if (LZO_ABI_LITTLE_ENDIAN) && defined(lzo_bitops_ctz32)
+ m_len += lzo_bitops_ctz32(v) / CHAR_BIT;
+#elif (LZO_ABI_LITTLE_ENDIAN)
+ if ((v & UCHAR_MAX) == 0) do {
+ v >>= CHAR_BIT;
+ m_len += 1;
+ } while ((v & UCHAR_MAX) == 0);
+#else
+ if (ip[m_len] == m_pos[m_len]) do {
+ m_len += 1;
+ } while (ip[m_len] == m_pos[m_len]);
+#endif
+#else
+ if __lzo_unlikely(ip[m_len] == m_pos[m_len]) {
+ do {
+ m_len += 1;
+ if __lzo_unlikely(ip + m_len >= ip_end)
+ goto m_len_done;
+ } while (ip[m_len] == m_pos[m_len]);
+ }
+#endif
+ }
+m_len_done:
+ m_off = pd(ip,m_pos);
+ ip += m_len;
+ ii = ip;
+ if (m_len <= M2_MAX_LEN && m_off <= M2_MAX_OFFSET)
+ {
+ m_off -= 1;
+#if defined(LZO1X)
+ *op++ = LZO_BYTE(((m_len - 1) << 5) | ((m_off & 7) << 2));
+ *op++ = LZO_BYTE(m_off >> 3);
+#elif defined(LZO1Y)
+ *op++ = LZO_BYTE(((m_len + 1) << 4) | ((m_off & 3) << 2));
+ *op++ = LZO_BYTE(m_off >> 2);
+#endif
+ }
+ else if (m_off <= M3_MAX_OFFSET)
+ {
+ m_off -= 1;
+ if (m_len <= M3_MAX_LEN)
+ *op++ = LZO_BYTE(M3_MARKER | (m_len - 2));
+ else
+ {
+ m_len -= M3_MAX_LEN;
+ *op++ = M3_MARKER | 0;
+ while __lzo_unlikely(m_len > 255)
+ {
+ m_len -= 255;
+#if 1 && (LZO_CC_MSC && (_MSC_VER >= 1400))
+ * (volatile unsigned char *) op++ = 0;
+#else
+ *op++ = 0;
+#endif
+ }
+ *op++ = LZO_BYTE(m_len);
+ }
+ *op++ = LZO_BYTE(m_off << 2);
+ *op++ = LZO_BYTE(m_off >> 6);
+ }
+ else
+ {
+ m_off -= 0x4000;
+ if (m_len <= M4_MAX_LEN)
+ *op++ = LZO_BYTE(M4_MARKER | ((m_off >> 11) & 8) | (m_len - 2));
+ else
+ {
+ m_len -= M4_MAX_LEN;
+ *op++ = LZO_BYTE(M4_MARKER | ((m_off >> 11) & 8));
+ while __lzo_unlikely(m_len > 255)
+ {
+ m_len -= 255;
+#if 1 && (LZO_CC_MSC && (_MSC_VER >= 1400))
+ * (volatile unsigned char *) op++ = 0;
+#else
+ *op++ = 0;
+#endif
+ }
+ *op++ = LZO_BYTE(m_len);
+ }
+ *op++ = LZO_BYTE(m_off << 2);
+ *op++ = LZO_BYTE(m_off >> 6);
+ }
+ goto next;
+ }
+
+ *out_len = pd(op, out);
+ return pd(in_end,ii);
+}
+
+LZO_PUBLIC(int)
+DO_COMPRESS ( const lzo_bytep in , lzo_uint in_len,
+ lzo_bytep out, lzo_uintp out_len,
+ lzo_voidp wrkmem )
+{
+ const lzo_bytep ip = in;
+ lzo_bytep op = out;
+ lzo_uint l = in_len;
+ lzo_uint t = 0;
+
+ while (l > 20)
+ {
+ lzo_uint ll = l;
+ lzo_uintptr_t ll_end;
+#if 0 || (LZO_DETERMINISTIC)
+ ll = LZO_MIN(ll, 49152);
+#endif
+ ll_end = (lzo_uintptr_t)ip + ll;
+ if ((ll_end + ((t + ll) >> 5)) <= ll_end || (const lzo_bytep)(ll_end + ((t + ll) >> 5)) <= ip + ll)
+ break;
+#if (LZO_DETERMINISTIC)
+ lzo_memset(wrkmem, 0, ((lzo_uint)1 << D_BITS) * sizeof(lzo_dict_t));
+#endif
+ t = do_compress(ip,ll,op,out_len,t,wrkmem);
+ ip += ll;
+ op += *out_len;
+ l -= ll;
+ }
+ t += l;
+
+ if (t > 0)
+ {
+ const lzo_bytep ii = in + in_len - t;
+
+ if (op == out && t <= 238)
+ *op++ = LZO_BYTE(17 + t);
+ else if (t <= 3)
+ op[-2] |= LZO_BYTE(t);
+ else if (t <= 18)
+ *op++ = LZO_BYTE(t - 3);
+ else
+ {
+ lzo_uint tt = t - 18;
+
+ *op++ = 0;
+ while (tt > 255)
+ {
+ tt -= 255;
+#if 1 && (LZO_CC_MSC && (_MSC_VER >= 1400))
+
+ * (volatile unsigned char *) op++ = 0;
+#else
+ *op++ = 0;
+#endif
+ }
+ assert(tt > 0);
+ *op++ = LZO_BYTE(tt);
+ }
+ do *op++ = *ii++; while (--t > 0);
+ }
+
+ *op++ = M4_MARKER | 1;
+ *op++ = 0;
+ *op++ = 0;
+
+ *out_len = pd(op, out);
+ return LZO_E_OK;
+}
+
+#endif
+
+#undef do_compress
+#undef DO_COMPRESS
+#undef LZO_HASH
+
+#undef LZO_TEST_OVERRUN
+#undef DO_DECOMPRESS
+#define DO_DECOMPRESS lzo1x_decompress
+
+#if !defined(MINILZO_CFG_SKIP_LZO1X_DECOMPRESS)
+
+#if defined(LZO_TEST_OVERRUN)
+# if !defined(LZO_TEST_OVERRUN_INPUT)
+# define LZO_TEST_OVERRUN_INPUT 2
+# endif
+# if !defined(LZO_TEST_OVERRUN_OUTPUT)
+# define LZO_TEST_OVERRUN_OUTPUT 2
+# endif
+# if !defined(LZO_TEST_OVERRUN_LOOKBEHIND)
+# define LZO_TEST_OVERRUN_LOOKBEHIND 1
+# endif
+#endif
+
+#undef TEST_IP
+#undef TEST_OP
+#undef TEST_LB
+#undef TEST_LBO
+#undef NEED_IP
+#undef NEED_OP
+#undef HAVE_TEST_IP
+#undef HAVE_TEST_OP
+#undef HAVE_NEED_IP
+#undef HAVE_NEED_OP
+#undef HAVE_ANY_IP
+#undef HAVE_ANY_OP
+
+#if defined(LZO_TEST_OVERRUN_INPUT)
+# if (LZO_TEST_OVERRUN_INPUT >= 1)
+# define TEST_IP (ip < ip_end)
+# endif
+# if (LZO_TEST_OVERRUN_INPUT >= 2)
+# define NEED_IP(x) \
+ if ((lzo_uint)(ip_end - ip) < (lzo_uint)(x)) goto input_overrun
+# endif
+#endif
+
+#if defined(LZO_TEST_OVERRUN_OUTPUT)
+# if (LZO_TEST_OVERRUN_OUTPUT >= 1)
+# define TEST_OP (op <= op_end)
+# endif
+# if (LZO_TEST_OVERRUN_OUTPUT >= 2)
+# undef TEST_OP
+# define NEED_OP(x) \
+ if ((lzo_uint)(op_end - op) < (lzo_uint)(x)) goto output_overrun
+# endif
+#endif
+
+#if defined(LZO_TEST_OVERRUN_LOOKBEHIND)
+# define TEST_LB(m_pos) if (m_pos < out || m_pos >= op) goto lookbehind_overrun
+# define TEST_LBO(m_pos,o) if (m_pos < out || m_pos >= op - (o)) goto lookbehind_overrun
+#else
+# define TEST_LB(m_pos) ((void) 0)
+# define TEST_LBO(m_pos,o) ((void) 0)
+#endif
+
+#if !defined(LZO_EOF_CODE) && !defined(TEST_IP)
+# define TEST_IP (ip < ip_end)
+#endif
+
+#if defined(TEST_IP)
+# define HAVE_TEST_IP 1
+#else
+# define TEST_IP 1
+#endif
+#if defined(TEST_OP)
+# define HAVE_TEST_OP 1
+#else
+# define TEST_OP 1
+#endif
+
+#if defined(NEED_IP)
+# define HAVE_NEED_IP 1
+#else
+# define NEED_IP(x) ((void) 0)
+#endif
+#if defined(NEED_OP)
+# define HAVE_NEED_OP 1
+#else
+# define NEED_OP(x) ((void) 0)
+#endif
+
+#if defined(HAVE_TEST_IP) || defined(HAVE_NEED_IP)
+# define HAVE_ANY_IP 1
+#endif
+#if defined(HAVE_TEST_OP) || defined(HAVE_NEED_OP)
+# define HAVE_ANY_OP 1
+#endif
+
+#if defined(DO_DECOMPRESS)
+LZO_PUBLIC(int)
+DO_DECOMPRESS ( const lzo_bytep in , lzo_uint in_len,
+ lzo_bytep out, lzo_uintp out_len,
+ lzo_voidp wrkmem )
+#endif
+{
+ register lzo_bytep op;
+ register const lzo_bytep ip;
+ register lzo_uint t;
+#if defined(COPY_DICT)
+ lzo_uint m_off;
+ const lzo_bytep dict_end;
+#else
+ register const lzo_bytep m_pos;
+#endif
+
+ const lzo_bytep const ip_end = in + in_len;
+#if defined(HAVE_ANY_OP)
+ lzo_bytep const op_end = out + *out_len;
+#endif
+#if defined(LZO1Z)
+ lzo_uint last_m_off = 0;
+#endif
+
+ LZO_UNUSED(wrkmem);
+
+#if defined(COPY_DICT)
+ if (dict)
+ {
+ if (dict_len > M4_MAX_OFFSET)
+ {
+ dict += dict_len - M4_MAX_OFFSET;
+ dict_len = M4_MAX_OFFSET;
+ }
+ dict_end = dict + dict_len;
+ }
+ else
+ {
+ dict_len = 0;
+ dict_end = NULL;
+ }
+#endif
+
+ *out_len = 0;
+
+ op = out;
+ ip = in;
+
+ if (*ip > 17)
+ {
+ t = *ip++ - 17;
+ if (t < 4)
+ goto match_next;
+ assert(t > 0); NEED_OP(t); NEED_IP(t+1);
+ do *op++ = *ip++; while (--t > 0);
+ goto first_literal_run;
+ }
+
+ while (TEST_IP && TEST_OP)
+ {
+ t = *ip++;
+ if (t >= 16)
+ goto match;
+ if (t == 0)
+ {
+ NEED_IP(1);
+ while (*ip == 0)
+ {
+ t += 255;
+ ip++;
+ NEED_IP(1);
+ }
+ t += 15 + *ip++;
+ }
+ assert(t > 0); NEED_OP(t+3); NEED_IP(t+4);
+#if defined(LZO_UNALIGNED_OK_8) && defined(LZO_UNALIGNED_OK_4)
+ t += 3;
+ if (t >= 8) do
+ {
+ UA_COPY64(op,ip);
+ op += 8; ip += 8; t -= 8;
+ } while (t >= 8);
+ if (t >= 4)
+ {
+ UA_COPY32(op,ip);
+ op += 4; ip += 4; t -= 4;
+ }
+ if (t > 0)
+ {
+ *op++ = *ip++;
+ if (t > 1) { *op++ = *ip++; if (t > 2) { *op++ = *ip++; } }
+ }
+#elif defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4)
+#if !defined(LZO_UNALIGNED_OK_4)
+ if (PTR_ALIGNED2_4(op,ip))
+ {
+#endif
+ UA_COPY32(op,ip);
+ op += 4; ip += 4;
+ if (--t > 0)
+ {
+ if (t >= 4)
+ {
+ do {
+ UA_COPY32(op,ip);
+ op += 4; ip += 4; t -= 4;
+ } while (t >= 4);
+ if (t > 0) do *op++ = *ip++; while (--t > 0);
+ }
+ else
+ do *op++ = *ip++; while (--t > 0);
+ }
+#if !defined(LZO_UNALIGNED_OK_4)
+ }
+ else
+#endif
+#endif
+#if !defined(LZO_UNALIGNED_OK_4) && !defined(LZO_UNALIGNED_OK_8)
+ {
+ *op++ = *ip++; *op++ = *ip++; *op++ = *ip++;
+ do *op++ = *ip++; while (--t > 0);
+ }
+#endif
+
+first_literal_run:
+
+ t = *ip++;
+ if (t >= 16)
+ goto match;
+#if defined(COPY_DICT)
+#if defined(LZO1Z)
+ m_off = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2);
+ last_m_off = m_off;
+#else
+ m_off = (1 + M2_MAX_OFFSET) + (t >> 2) + (*ip++ << 2);
+#endif
+ NEED_OP(3);
+ t = 3; COPY_DICT(t,m_off)
+#else
+#if defined(LZO1Z)
+ t = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2);
+ m_pos = op - t;
+ last_m_off = t;
+#else
+ m_pos = op - (1 + M2_MAX_OFFSET);
+ m_pos -= t >> 2;
+ m_pos -= *ip++ << 2;
+#endif
+ TEST_LB(m_pos); NEED_OP(3);
+ *op++ = *m_pos++; *op++ = *m_pos++; *op++ = *m_pos;
+#endif
+ goto match_done;
+
+ do {
+match:
+ if (t >= 64)
+ {
+#if defined(COPY_DICT)
+#if defined(LZO1X)
+ m_off = 1 + ((t >> 2) & 7) + (*ip++ << 3);
+ t = (t >> 5) - 1;
+#elif defined(LZO1Y)
+ m_off = 1 + ((t >> 2) & 3) + (*ip++ << 2);
+ t = (t >> 4) - 3;
+#elif defined(LZO1Z)
+ m_off = t & 0x1f;
+ if (m_off >= 0x1c)
+ m_off = last_m_off;
+ else
+ {
+ m_off = 1 + (m_off << 6) + (*ip++ >> 2);
+ last_m_off = m_off;
+ }
+ t = (t >> 5) - 1;
+#endif
+#else
+#if defined(LZO1X)
+ m_pos = op - 1;
+ m_pos -= (t >> 2) & 7;
+ m_pos -= *ip++ << 3;
+ t = (t >> 5) - 1;
+#elif defined(LZO1Y)
+ m_pos = op - 1;
+ m_pos -= (t >> 2) & 3;
+ m_pos -= *ip++ << 2;
+ t = (t >> 4) - 3;
+#elif defined(LZO1Z)
+ {
+ lzo_uint off = t & 0x1f;
+ m_pos = op;
+ if (off >= 0x1c)
+ {
+ assert(last_m_off > 0);
+ m_pos -= last_m_off;
+ }
+ else
+ {
+ off = 1 + (off << 6) + (*ip++ >> 2);
+ m_pos -= off;
+ last_m_off = off;
+ }
+ }
+ t = (t >> 5) - 1;
+#endif
+ TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1);
+ goto copy_match;
+#endif
+ }
+ else if (t >= 32)
+ {
+ t &= 31;
+ if (t == 0)
+ {
+ NEED_IP(1);
+ while (*ip == 0)
+ {
+ t += 255;
+ ip++;
+ NEED_IP(1);
+ }
+ t += 31 + *ip++;
+ }
+#if defined(COPY_DICT)
+#if defined(LZO1Z)
+ m_off = 1 + (ip[0] << 6) + (ip[1] >> 2);
+ last_m_off = m_off;
+#else
+ m_off = 1 + (ip[0] >> 2) + (ip[1] << 6);
+#endif
+#else
+#if defined(LZO1Z)
+ {
+ lzo_uint off = 1 + (ip[0] << 6) + (ip[1] >> 2);
+ m_pos = op - off;
+ last_m_off = off;
+ }
+#elif defined(LZO_UNALIGNED_OK_2) && defined(LZO_ABI_LITTLE_ENDIAN)
+ m_pos = op - 1;
+ m_pos -= UA_GET16(ip) >> 2;
+#else
+ m_pos = op - 1;
+ m_pos -= (ip[0] >> 2) + (ip[1] << 6);
+#endif
+#endif
+ ip += 2;
+ }
+ else if (t >= 16)
+ {
+#if defined(COPY_DICT)
+ m_off = (t & 8) << 11;
+#else
+ m_pos = op;
+ m_pos -= (t & 8) << 11;
+#endif
+ t &= 7;
+ if (t == 0)
+ {
+ NEED_IP(1);
+ while (*ip == 0)
+ {
+ t += 255;
+ ip++;
+ NEED_IP(1);
+ }
+ t += 7 + *ip++;
+ }
+#if defined(COPY_DICT)
+#if defined(LZO1Z)
+ m_off += (ip[0] << 6) + (ip[1] >> 2);
+#else
+ m_off += (ip[0] >> 2) + (ip[1] << 6);
+#endif
+ ip += 2;
+ if (m_off == 0)
+ goto eof_found;
+ m_off += 0x4000;
+#if defined(LZO1Z)
+ last_m_off = m_off;
+#endif
+#else
+#if defined(LZO1Z)
+ m_pos -= (ip[0] << 6) + (ip[1] >> 2);
+#elif defined(LZO_UNALIGNED_OK_2) && defined(LZO_ABI_LITTLE_ENDIAN)
+ m_pos -= UA_GET16(ip) >> 2;
+#else
+ m_pos -= (ip[0] >> 2) + (ip[1] << 6);
+#endif
+ ip += 2;
+ if (m_pos == op)
+ goto eof_found;
+ m_pos -= 0x4000;
+#if defined(LZO1Z)
+ last_m_off = pd((const lzo_bytep)op, m_pos);
+#endif
+#endif
+ }
+ else
+ {
+#if defined(COPY_DICT)
+#if defined(LZO1Z)
+ m_off = 1 + (t << 6) + (*ip++ >> 2);
+ last_m_off = m_off;
+#else
+ m_off = 1 + (t >> 2) + (*ip++ << 2);
+#endif
+ NEED_OP(2);
+ t = 2; COPY_DICT(t,m_off)
+#else
+#if defined(LZO1Z)
+ t = 1 + (t << 6) + (*ip++ >> 2);
+ m_pos = op - t;
+ last_m_off = t;
+#else
+ m_pos = op - 1;
+ m_pos -= t >> 2;
+ m_pos -= *ip++ << 2;
+#endif
+ TEST_LB(m_pos); NEED_OP(2);
+ *op++ = *m_pos++; *op++ = *m_pos;
+#endif
+ goto match_done;
+ }
+
+#if defined(COPY_DICT)
+
+ NEED_OP(t+3-1);
+ t += 3-1; COPY_DICT(t,m_off)
+
+#else
+
+ TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1);
+#if defined(LZO_UNALIGNED_OK_8) && defined(LZO_UNALIGNED_OK_4)
+ if (op - m_pos >= 8)
+ {
+ t += (3 - 1);
+ if (t >= 8) do
+ {
+ UA_COPY64(op,m_pos);
+ op += 8; m_pos += 8; t -= 8;
+ } while (t >= 8);
+ if (t >= 4)
+ {
+ UA_COPY32(op,m_pos);
+ op += 4; m_pos += 4; t -= 4;
+ }
+ if (t > 0)
+ {
+ *op++ = m_pos[0];
+ if (t > 1) { *op++ = m_pos[1]; if (t > 2) { *op++ = m_pos[2]; } }
+ }
+ }
+ else
+#elif defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4)
+#if !defined(LZO_UNALIGNED_OK_4)
+ if (t >= 2 * 4 - (3 - 1) && PTR_ALIGNED2_4(op,m_pos))
+ {
+ assert((op - m_pos) >= 4);
+#else
+ if (t >= 2 * 4 - (3 - 1) && (op - m_pos) >= 4)
+ {
+#endif
+ UA_COPY32(op,m_pos);
+ op += 4; m_pos += 4; t -= 4 - (3 - 1);
+ do {
+ UA_COPY32(op,m_pos);
+ op += 4; m_pos += 4; t -= 4;
+ } while (t >= 4);
+ if (t > 0) do *op++ = *m_pos++; while (--t > 0);
+ }
+ else
+#endif
+ {
+copy_match:
+ *op++ = *m_pos++; *op++ = *m_pos++;
+ do *op++ = *m_pos++; while (--t > 0);
+ }
+
+#endif
+
+match_done:
+#if defined(LZO1Z)
+ t = ip[-1] & 3;
+#else
+ t = ip[-2] & 3;
+#endif
+ if (t == 0)
+ break;
+
+match_next:
+ assert(t > 0); assert(t < 4); NEED_OP(t); NEED_IP(t+1);
+#if 0
+ do *op++ = *ip++; while (--t > 0);
+#else
+ *op++ = *ip++;
+ if (t > 1) { *op++ = *ip++; if (t > 2) { *op++ = *ip++; } }
+#endif
+ t = *ip++;
+ } while (TEST_IP && TEST_OP);
+ }
+
+#if defined(HAVE_TEST_IP) || defined(HAVE_TEST_OP)
+ *out_len = pd(op, out);
+ return LZO_E_EOF_NOT_FOUND;
+#endif
+
+eof_found:
+ assert(t == 1);
+ *out_len = pd(op, out);
+ return (ip == ip_end ? LZO_E_OK :
+ (ip < ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN));
+
+#if defined(HAVE_NEED_IP)
+input_overrun:
+ *out_len = pd(op, out);
+ return LZO_E_INPUT_OVERRUN;
+#endif
+
+#if defined(HAVE_NEED_OP)
+output_overrun:
+ *out_len = pd(op, out);
+ return LZO_E_OUTPUT_OVERRUN;
+#endif
+
+#if defined(LZO_TEST_OVERRUN_LOOKBEHIND)
+lookbehind_overrun:
+ *out_len = pd(op, out);
+ return LZO_E_LOOKBEHIND_OVERRUN;
+#endif
+}
+
+#endif
+
+#define LZO_TEST_OVERRUN 1
+#undef DO_DECOMPRESS
+#define DO_DECOMPRESS lzo1x_decompress_safe
+
+#if !defined(MINILZO_CFG_SKIP_LZO1X_DECOMPRESS_SAFE)
+
+#if defined(LZO_TEST_OVERRUN)
+# if !defined(LZO_TEST_OVERRUN_INPUT)
+# define LZO_TEST_OVERRUN_INPUT 2
+# endif
+# if !defined(LZO_TEST_OVERRUN_OUTPUT)
+# define LZO_TEST_OVERRUN_OUTPUT 2
+# endif
+# if !defined(LZO_TEST_OVERRUN_LOOKBEHIND)
+# define LZO_TEST_OVERRUN_LOOKBEHIND 1
+# endif
+#endif
+
+#undef TEST_IP
+#undef TEST_OP
+#undef TEST_LB
+#undef TEST_LBO
+#undef NEED_IP
+#undef NEED_OP
+#undef HAVE_TEST_IP
+#undef HAVE_TEST_OP
+#undef HAVE_NEED_IP
+#undef HAVE_NEED_OP
+#undef HAVE_ANY_IP
+#undef HAVE_ANY_OP
+
+#if defined(LZO_TEST_OVERRUN_INPUT)
+# if (LZO_TEST_OVERRUN_INPUT >= 1)
+# define TEST_IP (ip < ip_end)
+# endif
+# if (LZO_TEST_OVERRUN_INPUT >= 2)
+# define NEED_IP(x) \
+ if ((lzo_uint)(ip_end - ip) < (lzo_uint)(x)) goto input_overrun
+# endif
+#endif
+
+#if defined(LZO_TEST_OVERRUN_OUTPUT)
+# if (LZO_TEST_OVERRUN_OUTPUT >= 1)
+# define TEST_OP (op <= op_end)
+# endif
+# if (LZO_TEST_OVERRUN_OUTPUT >= 2)
+# undef TEST_OP
+# define NEED_OP(x) \
+ if ((lzo_uint)(op_end - op) < (lzo_uint)(x)) goto output_overrun
+# endif
+#endif
+
+#if defined(LZO_TEST_OVERRUN_LOOKBEHIND)
+# define TEST_LB(m_pos) if (m_pos < out || m_pos >= op) goto lookbehind_overrun
+# define TEST_LBO(m_pos,o) if (m_pos < out || m_pos >= op - (o)) goto lookbehind_overrun
+#else
+# define TEST_LB(m_pos) ((void) 0)
+# define TEST_LBO(m_pos,o) ((void) 0)
+#endif
+
+#if !defined(LZO_EOF_CODE) && !defined(TEST_IP)
+# define TEST_IP (ip < ip_end)
+#endif
+
+#if defined(TEST_IP)
+# define HAVE_TEST_IP 1
+#else
+# define TEST_IP 1
+#endif
+#if defined(TEST_OP)
+# define HAVE_TEST_OP 1
+#else
+# define TEST_OP 1
+#endif
+
+#if defined(NEED_IP)
+# define HAVE_NEED_IP 1
+#else
+# define NEED_IP(x) ((void) 0)
+#endif
+#if defined(NEED_OP)
+# define HAVE_NEED_OP 1
+#else
+# define NEED_OP(x) ((void) 0)
+#endif
+
+#if defined(HAVE_TEST_IP) || defined(HAVE_NEED_IP)
+# define HAVE_ANY_IP 1
+#endif
+#if defined(HAVE_TEST_OP) || defined(HAVE_NEED_OP)
+# define HAVE_ANY_OP 1
+#endif
+
+#if defined(DO_DECOMPRESS)
+LZO_PUBLIC(int)
+DO_DECOMPRESS ( const lzo_bytep in , lzo_uint in_len,
+ lzo_bytep out, lzo_uintp out_len,
+ lzo_voidp wrkmem )
+#endif
+{
+ register lzo_bytep op;
+ register const lzo_bytep ip;
+ register lzo_uint t;
+#if defined(COPY_DICT)
+ lzo_uint m_off;
+ const lzo_bytep dict_end;
+#else
+ register const lzo_bytep m_pos;
+#endif
+
+ const lzo_bytep const ip_end = in + in_len;
+#if defined(HAVE_ANY_OP)
+ lzo_bytep const op_end = out + *out_len;
+#endif
+#if defined(LZO1Z)
+ lzo_uint last_m_off = 0;
+#endif
+
+ LZO_UNUSED(wrkmem);
+
+#if defined(COPY_DICT)
+ if (dict)
+ {
+ if (dict_len > M4_MAX_OFFSET)
+ {
+ dict += dict_len - M4_MAX_OFFSET;
+ dict_len = M4_MAX_OFFSET;
+ }
+ dict_end = dict + dict_len;
+ }
+ else
+ {
+ dict_len = 0;
+ dict_end = NULL;
+ }
+#endif
+
+ *out_len = 0;
+
+ op = out;
+ ip = in;
+
+ if (*ip > 17)
+ {
+ t = *ip++ - 17;
+ if (t < 4)
+ goto match_next;
+ assert(t > 0); NEED_OP(t); NEED_IP(t+1);
+ do *op++ = *ip++; while (--t > 0);
+ goto first_literal_run;
+ }
+
+ while (TEST_IP && TEST_OP)
+ {
+ t = *ip++;
+ if (t >= 16)
+ goto match;
+ if (t == 0)
+ {
+ NEED_IP(1);
+ while (*ip == 0)
+ {
+ t += 255;
+ ip++;
+ NEED_IP(1);
+ }
+ t += 15 + *ip++;
+ }
+ assert(t > 0); NEED_OP(t+3); NEED_IP(t+4);
+#if defined(LZO_UNALIGNED_OK_8) && defined(LZO_UNALIGNED_OK_4)
+ t += 3;
+ if (t >= 8) do
+ {
+ UA_COPY64(op,ip);
+ op += 8; ip += 8; t -= 8;
+ } while (t >= 8);
+ if (t >= 4)
+ {
+ UA_COPY32(op,ip);
+ op += 4; ip += 4; t -= 4;
+ }
+ if (t > 0)
+ {
+ *op++ = *ip++;
+ if (t > 1) { *op++ = *ip++; if (t > 2) { *op++ = *ip++; } }
+ }
+#elif defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4)
+#if !defined(LZO_UNALIGNED_OK_4)
+ if (PTR_ALIGNED2_4(op,ip))
+ {
+#endif
+ UA_COPY32(op,ip);
+ op += 4; ip += 4;
+ if (--t > 0)
+ {
+ if (t >= 4)
+ {
+ do {
+ UA_COPY32(op,ip);
+ op += 4; ip += 4; t -= 4;
+ } while (t >= 4);
+ if (t > 0) do *op++ = *ip++; while (--t > 0);
+ }
+ else
+ do *op++ = *ip++; while (--t > 0);
+ }
+#if !defined(LZO_UNALIGNED_OK_4)
+ }
+ else
+#endif
+#endif
+#if !defined(LZO_UNALIGNED_OK_4) && !defined(LZO_UNALIGNED_OK_8)
+ {
+ *op++ = *ip++; *op++ = *ip++; *op++ = *ip++;
+ do *op++ = *ip++; while (--t > 0);
+ }
+#endif
+
+first_literal_run:
+
+ t = *ip++;
+ if (t >= 16)
+ goto match;
+#if defined(COPY_DICT)
+#if defined(LZO1Z)
+ m_off = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2);
+ last_m_off = m_off;
+#else
+ m_off = (1 + M2_MAX_OFFSET) + (t >> 2) + (*ip++ << 2);
+#endif
+ NEED_OP(3);
+ t = 3; COPY_DICT(t,m_off)
+#else
+#if defined(LZO1Z)
+ t = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2);
+ m_pos = op - t;
+ last_m_off = t;
+#else
+ m_pos = op - (1 + M2_MAX_OFFSET);
+ m_pos -= t >> 2;
+ m_pos -= *ip++ << 2;
+#endif
+ TEST_LB(m_pos); NEED_OP(3);
+ *op++ = *m_pos++; *op++ = *m_pos++; *op++ = *m_pos;
+#endif
+ goto match_done;
+
+ do {
+match:
+ if (t >= 64)
+ {
+#if defined(COPY_DICT)
+#if defined(LZO1X)
+ m_off = 1 + ((t >> 2) & 7) + (*ip++ << 3);
+ t = (t >> 5) - 1;
+#elif defined(LZO1Y)
+ m_off = 1 + ((t >> 2) & 3) + (*ip++ << 2);
+ t = (t >> 4) - 3;
+#elif defined(LZO1Z)
+ m_off = t & 0x1f;
+ if (m_off >= 0x1c)
+ m_off = last_m_off;
+ else
+ {
+ m_off = 1 + (m_off << 6) + (*ip++ >> 2);
+ last_m_off = m_off;
+ }
+ t = (t >> 5) - 1;
+#endif
+#else
+#if defined(LZO1X)
+ m_pos = op - 1;
+ m_pos -= (t >> 2) & 7;
+ m_pos -= *ip++ << 3;
+ t = (t >> 5) - 1;
+#elif defined(LZO1Y)
+ m_pos = op - 1;
+ m_pos -= (t >> 2) & 3;
+ m_pos -= *ip++ << 2;
+ t = (t >> 4) - 3;
+#elif defined(LZO1Z)
+ {
+ lzo_uint off = t & 0x1f;
+ m_pos = op;
+ if (off >= 0x1c)
+ {
+ assert(last_m_off > 0);
+ m_pos -= last_m_off;
+ }
+ else
+ {
+ off = 1 + (off << 6) + (*ip++ >> 2);
+ m_pos -= off;
+ last_m_off = off;
+ }
+ }
+ t = (t >> 5) - 1;
+#endif
+ TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1);
+ goto copy_match;
+#endif
+ }
+ else if (t >= 32)
+ {
+ t &= 31;
+ if (t == 0)
+ {
+ NEED_IP(1);
+ while (*ip == 0)
+ {
+ t += 255;
+ ip++;
+ NEED_IP(1);
+ }
+ t += 31 + *ip++;
+ }
+#if defined(COPY_DICT)
+#if defined(LZO1Z)
+ m_off = 1 + (ip[0] << 6) + (ip[1] >> 2);
+ last_m_off = m_off;
+#else
+ m_off = 1 + (ip[0] >> 2) + (ip[1] << 6);
+#endif
+#else
+#if defined(LZO1Z)
+ {
+ lzo_uint off = 1 + (ip[0] << 6) + (ip[1] >> 2);
+ m_pos = op - off;
+ last_m_off = off;
+ }
+#elif defined(LZO_UNALIGNED_OK_2) && defined(LZO_ABI_LITTLE_ENDIAN)
+ m_pos = op - 1;
+ m_pos -= UA_GET16(ip) >> 2;
+#else
+ m_pos = op - 1;
+ m_pos -= (ip[0] >> 2) + (ip[1] << 6);
+#endif
+#endif
+ ip += 2;
+ }
+ else if (t >= 16)
+ {
+#if defined(COPY_DICT)
+ m_off = (t & 8) << 11;
+#else
+ m_pos = op;
+ m_pos -= (t & 8) << 11;
+#endif
+ t &= 7;
+ if (t == 0)
+ {
+ NEED_IP(1);
+ while (*ip == 0)
+ {
+ t += 255;
+ ip++;
+ NEED_IP(1);
+ }
+ t += 7 + *ip++;
+ }
+#if defined(COPY_DICT)
+#if defined(LZO1Z)
+ m_off += (ip[0] << 6) + (ip[1] >> 2);
+#else
+ m_off += (ip[0] >> 2) + (ip[1] << 6);
+#endif
+ ip += 2;
+ if (m_off == 0)
+ goto eof_found;
+ m_off += 0x4000;
+#if defined(LZO1Z)
+ last_m_off = m_off;
+#endif
+#else
+#if defined(LZO1Z)
+ m_pos -= (ip[0] << 6) + (ip[1] >> 2);
+#elif defined(LZO_UNALIGNED_OK_2) && defined(LZO_ABI_LITTLE_ENDIAN)
+ m_pos -= UA_GET16(ip) >> 2;
+#else
+ m_pos -= (ip[0] >> 2) + (ip[1] << 6);
+#endif
+ ip += 2;
+ if (m_pos == op)
+ goto eof_found;
+ m_pos -= 0x4000;
+#if defined(LZO1Z)
+ last_m_off = pd((const lzo_bytep)op, m_pos);
+#endif
+#endif
+ }
+ else
+ {
+#if defined(COPY_DICT)
+#if defined(LZO1Z)
+ m_off = 1 + (t << 6) + (*ip++ >> 2);
+ last_m_off = m_off;
+#else
+ m_off = 1 + (t >> 2) + (*ip++ << 2);
+#endif
+ NEED_OP(2);
+ t = 2; COPY_DICT(t,m_off)
+#else
+#if defined(LZO1Z)
+ t = 1 + (t << 6) + (*ip++ >> 2);
+ m_pos = op - t;
+ last_m_off = t;
+#else
+ m_pos = op - 1;
+ m_pos -= t >> 2;
+ m_pos -= *ip++ << 2;
+#endif
+ TEST_LB(m_pos); NEED_OP(2);
+ *op++ = *m_pos++; *op++ = *m_pos;
+#endif
+ goto match_done;
+ }
+
+#if defined(COPY_DICT)
+
+ NEED_OP(t+3-1);
+ t += 3-1; COPY_DICT(t,m_off)
+
+#else
+
+ TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1);
+#if defined(LZO_UNALIGNED_OK_8) && defined(LZO_UNALIGNED_OK_4)
+ if (op - m_pos >= 8)
+ {
+ t += (3 - 1);
+ if (t >= 8) do
+ {
+ UA_COPY64(op,m_pos);
+ op += 8; m_pos += 8; t -= 8;
+ } while (t >= 8);
+ if (t >= 4)
+ {
+ UA_COPY32(op,m_pos);
+ op += 4; m_pos += 4; t -= 4;
+ }
+ if (t > 0)
+ {
+ *op++ = m_pos[0];
+ if (t > 1) { *op++ = m_pos[1]; if (t > 2) { *op++ = m_pos[2]; } }
+ }
+ }
+ else
+#elif defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4)
+#if !defined(LZO_UNALIGNED_OK_4)
+ if (t >= 2 * 4 - (3 - 1) && PTR_ALIGNED2_4(op,m_pos))
+ {
+ assert((op - m_pos) >= 4);
+#else
+ if (t >= 2 * 4 - (3 - 1) && (op - m_pos) >= 4)
+ {
+#endif
+ UA_COPY32(op,m_pos);
+ op += 4; m_pos += 4; t -= 4 - (3 - 1);
+ do {
+ UA_COPY32(op,m_pos);
+ op += 4; m_pos += 4; t -= 4;
+ } while (t >= 4);
+ if (t > 0) do *op++ = *m_pos++; while (--t > 0);
+ }
+ else
+#endif
+ {
+copy_match:
+ *op++ = *m_pos++; *op++ = *m_pos++;
+ do *op++ = *m_pos++; while (--t > 0);
+ }
+
+#endif
+
+match_done:
+#if defined(LZO1Z)
+ t = ip[-1] & 3;
+#else
+ t = ip[-2] & 3;
+#endif
+ if (t == 0)
+ break;
+
+match_next:
+ assert(t > 0); assert(t < 4); NEED_OP(t); NEED_IP(t+1);
+#if 0
+ do *op++ = *ip++; while (--t > 0);
+#else
+ *op++ = *ip++;
+ if (t > 1) { *op++ = *ip++; if (t > 2) { *op++ = *ip++; } }
+#endif
+ t = *ip++;
+ } while (TEST_IP && TEST_OP);
+ }
+
+#if defined(HAVE_TEST_IP) || defined(HAVE_TEST_OP)
+ *out_len = pd(op, out);
+ return LZO_E_EOF_NOT_FOUND;
+#endif
+
+eof_found:
+ assert(t == 1);
+ *out_len = pd(op, out);
+ return (ip == ip_end ? LZO_E_OK :
+ (ip < ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN));
+
+#if defined(HAVE_NEED_IP)
+input_overrun:
+ *out_len = pd(op, out);
+ return LZO_E_INPUT_OVERRUN;
+#endif
+
+#if defined(HAVE_NEED_OP)
+output_overrun:
+ *out_len = pd(op, out);
+ return LZO_E_OUTPUT_OVERRUN;
+#endif
+
+#if defined(LZO_TEST_OVERRUN_LOOKBEHIND)
+lookbehind_overrun:
+ *out_len = pd(op, out);
+ return LZO_E_LOOKBEHIND_OVERRUN;
+#endif
+}
+
+#endif
+
+/***** End of minilzo.c *****/
+
--- /dev/null
+/* minilzo.h -- mini subset of the LZO real-time data compression library
+
+ This file is part of the LZO real-time data compression library.
+
+ Copyright (C) 2011 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2010 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2009 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
+ All Rights Reserved.
+
+ The LZO library 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 2 of
+ the License, or (at your option) any later version.
+
+ The LZO library 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 the LZO library; see the file COPYING.
+ If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ Markus F.X.J. Oberhumer
+ <markus@oberhumer.com>
+ http://www.oberhumer.com/opensource/lzo/
+ */
+
+/*
+ * NOTE:
+ * the full LZO package can be found at
+ * http://www.oberhumer.com/opensource/lzo/
+ */
+
+
+#ifndef __MINILZO_H
+#define __MINILZO_H 1
+
+#define MINILZO_VERSION 0x2050
+
+#ifdef __LZOCONF_H
+# error "you cannot use both LZO and miniLZO"
+#endif
+
+#undef LZO_HAVE_CONFIG_H
+#include "lzoconf.h"
+
+#if !defined(LZO_VERSION) || (LZO_VERSION != MINILZO_VERSION)
+# error "version mismatch in header files"
+#endif
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/***********************************************************************
+//
+************************************************************************/
+
+/* Memory required for the wrkmem parameter.
+ * When the required size is 0, you can also pass a NULL pointer.
+ */
+
+#define LZO1X_MEM_COMPRESS LZO1X_1_MEM_COMPRESS
+#define LZO1X_1_MEM_COMPRESS ((lzo_uint32) (16384L * lzo_sizeof_dict_t))
+#define LZO1X_MEM_DECOMPRESS (0)
+
+
+/* compression */
+LZO_EXTERN(int)
+lzo1x_1_compress ( const lzo_bytep src, lzo_uint src_len,
+ lzo_bytep dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem );
+
+/* decompression */
+LZO_EXTERN(int)
+lzo1x_decompress ( const lzo_bytep src, lzo_uint src_len,
+ lzo_bytep dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem /* NOT USED */ );
+
+/* safe decompression with overrun testing */
+LZO_EXTERN(int)
+lzo1x_decompress_safe ( const lzo_bytep src, lzo_uint src_len,
+ lzo_bytep dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem /* NOT USED */ );
+
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* already included */
+
--- /dev/null
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2011 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/arc/arc.h>
+#include <grub/misc.h>
+#include <grub/time.h>
+#include <grub/term.h>
+
+void
+grub_reboot (void)
+{
+ GRUB_ARC_FIRMWARE_VECTOR->restart ();
+
+ grub_millisleep (1500);
+
+ grub_printf ("Reboot failed\n");
+ grub_refresh ();
+ while (1);
+}
--- /dev/null
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2011 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/machine/ec.h>
+#include <grub/machine/kernel.h>
+#include <grub/machine/memory.h>
+#include <grub/misc.h>
+#include <grub/pci.h>
+#include <grub/cs5536.h>
+#include <grub/time.h>
+#include <grub/term.h>
+
+void
+grub_reboot (void)
+{
+ switch (grub_arch_machine)
+ {
+ case GRUB_ARCH_MACHINE_FULOONG2E:
+ grub_outb (grub_inb (0xbfe00104) & ~4, 0xbfe00104);
+ grub_outb (grub_inb (0xbfe00104) | 4, 0xbfe00104);
+ break;
+ case GRUB_ARCH_MACHINE_FULOONG2F:
+ {
+ grub_pci_device_t dev;
+ if (!grub_cs5536_find (&dev))
+ break;
+ grub_cs5536_write_msr (dev, GRUB_CS5536_MSR_DIVIL_RESET,
+ grub_cs5536_read_msr (dev,
+ GRUB_CS5536_MSR_DIVIL_RESET)
+ | 1);
+ break;
+ }
+ case GRUB_ARCH_MACHINE_YEELOONG:
+ grub_write_ec (GRUB_MACHINE_EC_COMMAND_REBOOT);
+ break;
+ }
+ grub_millisleep (1500);
+
+ grub_printf ("Reboot failed\n");
+ grub_refresh ();
+ while (1);
+}
--- /dev/null
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2011 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/misc.h>
+
+void
+grub_reboot (void)
+{
+ while (1);
+}
*/
#include <grub/symbol.h>
+#include <grub/dl.h>
.file "setjmp.S"
+GRUB_MOD_LICENSE ("GPLv3+")
+
.text
/*
#include <grub/crypto.h>
#include <grub/mm.h>
#include <grub/misc.h>
+#include <grub/dl.h>
+
+GRUB_MOD_LICENSE ("GPLv2+");
/* Implement PKCS#5 PBKDF2 as per RFC 2898. The PRF to use is HMAC variant
of digest supplied by MD. Inputs are the password P of length PLEN,
static inline int
isxdigit (int c)
{
- return (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')
- || (c >= '0' && c <= '9');
+ return grub_isxdigit (c);
}
static inline int
+/*
+ * 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/>.
+ */
+
+#ifndef GRUB_POSIX_LIMITS_H
+#define GRUB_POSIX_LIMITS_H
+
+#include <grub/types.h>
+
+#define UCHAR_MAX GRUB_UCHAR_MAX
+#define USHRT_MAX GRUB_USHRT_MAX
+#define UINT_MAX GRUB_UINT_MAX
+#define ULONG_MAX GRUB_ULONG_MAX
+
+#define CHAR_BIT 8
+
+#endif
typedef grub_size_t size_t;
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;
*/
#include <grub/symbol.h>
+#include <grub/dl.h>
.file "setjmp.S"
+GRUB_MOD_LICENSE ("GPLv3+")
+
.text
/*
syndroms (m, s, rs, sy);
+ for (i = 0; i < (int) rs; i++)
+ if (sy[i] != 0)
+ break;
+
+ /* No error detected. */
+ if (i == (int) rs)
+ {
+#ifndef STANDALONE
+ free (sigma);
+ free (errpot);
+ free (errpos);
+ free (sy);
+#else
+ scratch -= rs2 * sizeof (gf_single_t);
+ scratch -= rs2 * sizeof (gf_single_t);
+ scratch -= rs2 * sizeof (int);
+ scratch -= rs * sizeof (gf_single_t);
+#endif
+ return;
+ }
+
{
gf_single_t *eq;
scratch += rs2 * (rs2 + 1) * sizeof (gf_single_t);
#endif
- for (i = 0; i < (int) rs; i++)
- if (sy[i] != 0)
- break;
-
- /* No error detected. */
- if (i == (int) rs)
- return;
-
for (i = 0; i < (int) rs2; i++)
for (j = 0; j < (int) rs2 + 1; j++)
eq[i * (rs2 + 1) + j] = sy[i+j];
rs = s / 3;
buf = xmalloc (s + rs + SECTOR_SIZE);
fread (buf, 1, s, in);
+ fclose (in);
grub_reed_solomon_add_redundancy (buf, s, rs);
#include <grub/misc.h>
#include <grub/cache.h>
#include <grub/memory.h>
+#include <grub/dl.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
struct grub_relocator
{
int inreg = 0, regbeg = 0, ncol = 0;
#if GRUB_RELOCATOR_HAVE_FIRMWARE_REQUESTS
int fwin = 0, fwb = 0, fwlefto = 0;
+#endif
+#if GRUB_RELOCATOR_HAVE_LEFTOVERS
+ int last_lo = 0;
#endif
int last_start = 0;
for (j = 0; j < N; j++)
unsigned offend = alloc_end
% GRUB_RELOCATOR_FIRMWARE_REQUESTS_QUANT;
struct grub_relocator_fw_leftover *lo
- = events[last_start].leftover;
+ = events[last_lo].leftover;
lo->freebytes[offstart / 8]
&= ((1 << (8 - (start % 8))) - 1);
grub_memset (lo->freebytes + (offstart + 7) / 8, 0,
#if GRUB_RELOCATOR_HAVE_LEFTOVERS
case REG_LEFTOVER_START:
fwlefto++;
+ last_lo = j;
break;
case REG_LEFTOVER_END:
curschu->extra = ne;
}
}
-#if GRUB_RELOCATOR_HAVE_FIRMWARE_REQUESTS
+
+#if GRUB_RELOCATOR_HAVE_LEFTOVERS
if (!oom && typepre == CHUNK_TYPE_FIRMWARE)
{
grub_addr_t fstart, fend;
= ALIGN_UP (alloc_end,
GRUB_RELOCATOR_FIRMWARE_REQUESTS_QUANT);
-#if GRUB_RELOCATOR_HAVE_LEFTOVERS
{
struct grub_relocator_fw_leftover *lo1 = NULL;
struct grub_relocator_fw_leftover *lo2 = NULL;
curschu->pre = lo1;
curschu->post = lo2;
}
-#endif
}
-#if GRUB_RELOCATOR_HAVE_LEFTOVERS
if (typepre == CHUNK_TYPE_LEFTOVER)
{
curschu->pre = events[last_start].leftover;
}
#endif
-#endif
if (!oom)
cural++;
else
#include "./mips/setjmp.S"
#elif defined(__powerpc__)
#include "./powerpc/setjmp.S"
+#elif defined(__ia64__)
+#include "./ia64/setjmp.S"
#else
-#error "Unknwon target cpu type"
+#error "Unknown target cpu type"
#endif
*/
#include <grub/symbol.h>
+#include <grub/dl.h>
.file "setjmp.S"
+GRUB_MOD_LICENSE ("GPLv3+")
+
.text
/*
*/
#include <grub/symbol.h>
+#include <grub/dl.h>
.file "setjmp.S"
+GRUB_MOD_LICENSE ("GPLv3+")
+
.text
/*
#include <grub/misc.h>
#include <grub/aout.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
int
grub_aout_get_type (union grub_aout_header *header)
{
#include <grub/command.h>
#include <grub/i18n.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
static grub_dl_t my_mod;
static grub_efi_handle_t image_handle;
struct grub_efi_device_path end;
};
-/* early 2006 Core Duo / Core Solo models */
-static struct piwg_full_device_path devpath_1 =
-{
- .comp1 =
- {
- .header = {
- .type = GRUB_EFI_HARDWARE_DEVICE_PATH_TYPE,
- .subtype = GRUB_EFI_MEMORY_MAPPED_DEVICE_PATH_SUBTYPE,
- .length = {sizeof (struct grub_efi_memory_mapped_device_path), 0}
- },
- .memory_type = GRUB_EFI_MEMORY_MAPPED_IO,
- .start_address = 0xffe00000,
- .end_address = 0xfff9ffff
- },
- .comp2 =
- {
- .header = {
- .type = GRUB_EFI_MEDIA_DEVICE_PATH_TYPE,
- .subtype = GRUB_EFI_PIWG_DEVICE_PATH_SUBTYPE,
- .length = {sizeof (struct grub_efi_piwg_device_path), 0}
- },
- .guid = {0x2B0585EB, 0xD8B8, 0x49A9, {0x8B, 0x8C, 0xE2, 0x1B,
- 0x01, 0xAE, 0xF2, 0xB7}}
- },
- .end =
- {
- .type = GRUB_EFI_END_DEVICE_PATH_TYPE,
- .subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE,
- .length = {sizeof (struct grub_efi_device_path), 0}
+#define MAKE_PIWG_PATH(st, en) \
+ { \
+ .comp1 = \
+ { \
+ .header = { \
+ .type = GRUB_EFI_HARDWARE_DEVICE_PATH_TYPE, \
+ .subtype = GRUB_EFI_MEMORY_MAPPED_DEVICE_PATH_SUBTYPE, \
+ .length = {sizeof (struct grub_efi_memory_mapped_device_path), 0} \
+ }, \
+ .memory_type = GRUB_EFI_MEMORY_MAPPED_IO, \
+ .start_address = st, \
+ .end_address = en \
+ }, \
+ .comp2 = \
+ { \
+ .header = { \
+ .type = GRUB_EFI_MEDIA_DEVICE_PATH_TYPE, \
+ .subtype = GRUB_EFI_PIWG_DEVICE_PATH_SUBTYPE, \
+ .length = {sizeof (struct grub_efi_piwg_device_path), 0} \
+ }, \
+ .guid = {0x2B0585EB, 0xD8B8, 0x49A9, {0x8B, 0x8C, 0xE2, 0x1B, \
+ 0x01, 0xAE, 0xF2, 0xB7}} \
+ }, \
+ .end = \
+ { \
+ .type = GRUB_EFI_END_DEVICE_PATH_TYPE, \
+ .subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE, \
+ .length = {sizeof (struct grub_efi_device_path), 0} \
+ } \
}
-};
+
+/* early 2006 Core Duo / Core Solo models */
+static struct piwg_full_device_path devpath_1 = MAKE_PIWG_PATH (0xffe00000,
+ 0xfff9ffff);
/* mid-2006 Mac Pro (and probably other Core 2 models) */
-static struct piwg_full_device_path devpath_2 =
-{
- .comp1 =
- {
- .header = {
- .type = GRUB_EFI_HARDWARE_DEVICE_PATH_TYPE,
- .subtype = GRUB_EFI_MEMORY_MAPPED_DEVICE_PATH_SUBTYPE,
- .length = {sizeof (struct grub_efi_memory_mapped_device_path), 0}
- },
- .memory_type = GRUB_EFI_MEMORY_MAPPED_IO,
- .start_address = 0xffe00000,
- .end_address = 0xfff7ffff
- },
- .comp2 =
- {
- .header = {
- .type = GRUB_EFI_MEDIA_DEVICE_PATH_TYPE,
- .subtype = GRUB_EFI_PIWG_DEVICE_PATH_SUBTYPE,
- .length = {sizeof (struct grub_efi_piwg_device_path), 0}
- },
- .guid = {0x2B0585EB, 0xD8B8, 0x49A9, {0x8B, 0x8C, 0xE2, 0x1B,
- 0x01, 0xAE, 0xF2, 0xB7}}
- },
- .end =
- {
- .type = GRUB_EFI_END_DEVICE_PATH_TYPE,
- .subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE,
- .length = {sizeof (struct grub_efi_device_path), 0}
- }
-};
+static struct piwg_full_device_path devpath_2 = MAKE_PIWG_PATH (0xffe00000,
+ 0xfff7ffff);
/* mid-2007 MBP ("Santa Rosa" based models) */
-static struct piwg_full_device_path devpath_3 =
-{
- .comp1 =
- {
- .header = {
- .type = GRUB_EFI_HARDWARE_DEVICE_PATH_TYPE,
- .subtype = GRUB_EFI_MEMORY_MAPPED_DEVICE_PATH_SUBTYPE,
- .length = {sizeof (struct grub_efi_memory_mapped_device_path), 0}
- },
- .memory_type = GRUB_EFI_MEMORY_MAPPED_IO,
- .start_address = 0xffe00000,
- .end_address = 0xfff8ffff
- },
- .comp2 =
- {
- .header = {
- .type = GRUB_EFI_MEDIA_DEVICE_PATH_TYPE,
- .subtype = GRUB_EFI_PIWG_DEVICE_PATH_SUBTYPE,
- .length = {sizeof (struct grub_efi_piwg_device_path), 0}
- },
- .guid = {0x2B0585EB, 0xD8B8, 0x49A9, {0x8B, 0x8C, 0xE2, 0x1B,
- 0x01, 0xAE, 0xF2, 0xB7}}
- },
- .end =
- {
- .type = GRUB_EFI_END_DEVICE_PATH_TYPE,
- .subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE,
- .length = {sizeof (struct grub_efi_device_path), 0}
- }
-};
+static struct piwg_full_device_path devpath_3 = MAKE_PIWG_PATH (0xffe00000,
+ 0xfff8ffff);
/* early-2008 MBA */
-static struct piwg_full_device_path devpath_4 =
-{
- .comp1 =
- {
- .header = {
- .type = GRUB_EFI_HARDWARE_DEVICE_PATH_TYPE,
- .subtype = GRUB_EFI_MEMORY_MAPPED_DEVICE_PATH_SUBTYPE,
- .length = {sizeof (struct grub_efi_memory_mapped_device_path), 0}
- },
- .memory_type = GRUB_EFI_MEMORY_MAPPED_IO,
- .start_address = 0xffc00000,
- .end_address = 0xfff8ffff
- },
- .comp2 =
- {
- .header = {
- .type = GRUB_EFI_MEDIA_DEVICE_PATH_TYPE,
- .subtype = GRUB_EFI_PIWG_DEVICE_PATH_SUBTYPE,
- .length = {sizeof (struct grub_efi_piwg_device_path), 0}
- },
- .guid = {0x2B0585EB, 0xD8B8, 0x49A9, {0x8B, 0x8C, 0xE2, 0x1B,
- 0x01, 0xAE, 0xF2, 0xB7}}
- },
- .end =
- {
- .type = GRUB_EFI_END_DEVICE_PATH_TYPE,
- .subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE,
- .length = {sizeof (struct grub_efi_device_path), 0}
- }
-};
+static struct piwg_full_device_path devpath_4 = MAKE_PIWG_PATH (0xffc00000,
+ 0xfff8ffff);
/* late-2008 MB/MBP (NVidia chipset) */
-static struct piwg_full_device_path devpath_5 =
-{
- .comp1 =
- {
- .header = {
- .type = GRUB_EFI_HARDWARE_DEVICE_PATH_TYPE,
- .subtype = GRUB_EFI_MEMORY_MAPPED_DEVICE_PATH_SUBTYPE,
- .length = {sizeof (struct grub_efi_memory_mapped_device_path), 0}
- },
- .memory_type = GRUB_EFI_MEMORY_MAPPED_IO,
- .start_address = 0xffcb4000,
- .end_address = 0xffffbfff
- },
- .comp2 =
- {
- .header = {
- .type = GRUB_EFI_MEDIA_DEVICE_PATH_TYPE,
- .subtype = GRUB_EFI_PIWG_DEVICE_PATH_SUBTYPE,
- .length = {sizeof (struct grub_efi_piwg_device_path), 0}
- },
- .guid = {0x2B0585EB, 0xD8B8, 0x49A9, {0x8B, 0x8C, 0xE2, 0x1B,
- 0x01, 0xAE, 0xF2, 0xB7}}
- },
- .end =
- {
- .type = GRUB_EFI_END_DEVICE_PATH_TYPE,
- .subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE,
- .length = {sizeof (struct grub_efi_device_path), 0}
- }
-};
+static struct piwg_full_device_path devpath_5 = MAKE_PIWG_PATH (0xffcb4000,
+ 0xffffbfff);
+
+/* mid-2010 MB/MBP (NVidia chipset) */
+static struct piwg_full_device_path devpath_6 = MAKE_PIWG_PATH (0xffcc4000,
+ 0xffffbfff);
struct devdata
{
{"MBP", (grub_efi_device_path_t *) &devpath_3},
{"MBA", (grub_efi_device_path_t *) &devpath_4},
{"MB NV", (grub_efi_device_path_t *) &devpath_5},
+ {"MB NV2", (grub_efi_device_path_t *) &devpath_6},
{NULL, NULL},
};
#include <grub/command.h>
#include <grub/i18n.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
static grub_dl_t my_mod;
static grub_efi_physical_address_t address;
grub_free (file_path);
grub_free (cmdline);
cmdline = 0;
+ file_path = 0;
grub_dl_unref (my_mod);
return GRUB_ERR_NONE;
grub_efi_boot_services_t *b;
grub_efi_status_t status;
grub_efi_uintn_t exit_data_size;
- grub_efi_char16_t *exit_data;
+ grub_efi_char16_t *exit_data = NULL;
b = grub_efi_system_table->boot_services;
status = efi_call_3 (b->start_image, image_handle, &exit_data_size, &exit_data);
if (exit_data)
efi_call_1 (b->free_pool, exit_data);
- grub_chainloader_unload ();
+ grub_loader_unset ();
return grub_errno;
}
grub_efi_print_device_path (file_path);
size = grub_file_size (file);
+ if (!size)
+ {
+ grub_error (GRUB_ERR_BAD_OS, "file is empty");
+ goto fail;
+ }
pages = (((grub_efi_uintn_t) size + ((1 << 12) - 1)) >> 12);
status = efi_call_4 (b->allocate_pages, GRUB_EFI_ALLOCATE_ANY_PAGES,
if (file)
grub_file_close (file);
- if (file_path)
- grub_free (file_path);
+ grub_free (file_path);
if (address)
efi_call_2 (b->free_pages, address, pages);
#include <grub/extcmd.h>
#include <grub/i18n.h>
#include <grub/ns8250.h>
+#include <grub/bsdlabel.h>
+#include <grub/crypto.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
#include <grub/video.h>
#ifdef GRUB_MACHINE_PCBIOS
return err;
}
+/*
+ * Adds NetBSD bootinfo bootdisk and bootwedge. The partition identified
+ * in these bootinfo fields is the root device.
+ */
+static void
+grub_netbsd_add_boot_disk_and_wedge (void)
+{
+ grub_device_t dev;
+ grub_disk_t disk;
+ grub_partition_t part;
+ grub_uint32_t biosdev;
+ grub_uint32_t partmapsector;
+ struct grub_partition_bsd_disk_label *label;
+ grub_uint64_t buf[GRUB_DISK_SECTOR_SIZE / 8];
+ grub_uint8_t *hash;
+ grub_uint64_t ctx[(GRUB_MD_MD5->contextsize + 7) / 8];
+
+ dev = grub_device_open (0);
+ if (! (dev && dev->disk && dev->disk->partition))
+ goto fail;
+
+ disk = dev->disk;
+ part = disk->partition;
+
+ if (disk->dev && disk->dev->id == GRUB_DISK_DEVICE_BIOSDISK_ID)
+ biosdev = (grub_uint32_t) disk->id & 0xff;
+ else
+ biosdev = 0xff;
+
+ /* Absolute sector of the partition map describing this partition. */
+ partmapsector = grub_partition_get_start (part->parent) + part->offset;
+
+ disk->partition = part->parent;
+ if (grub_disk_read (disk, part->offset, 0, GRUB_DISK_SECTOR_SIZE, buf) != GRUB_ERR_NONE)
+ goto fail;
+ disk->partition = part;
+
+ /* Fill bootwedge. */
+ {
+ struct grub_netbsd_btinfo_bootwedge biw;
+
+ grub_memset (&biw, 0, sizeof (biw));
+ biw.biosdev = biosdev;
+ biw.startblk = grub_partition_get_start (part);
+ biw.nblks = part->len;
+ biw.matchblk = partmapsector;
+ biw.matchnblks = 1;
+
+ GRUB_MD_MD5->init (&ctx);
+ GRUB_MD_MD5->write (&ctx, buf, GRUB_DISK_SECTOR_SIZE);
+ GRUB_MD_MD5->final (&ctx);
+ hash = GRUB_MD_MD5->read (&ctx);
+ memcpy (biw.matchhash, hash, 16);
+
+ grub_bsd_add_meta (NETBSD_BTINFO_BOOTWEDGE, &biw, sizeof (biw));
+ }
+
+ /* Fill bootdisk if this a NetBSD disk label. */
+ label = (struct grub_partition_bsd_disk_label *) &buf;
+ if (part->partmap != NULL &&
+ (grub_strcmp (part->partmap->name, "netbsd") == 0) &&
+ label->magic == grub_cpu_to_le32 (GRUB_PC_PARTITION_BSD_LABEL_MAGIC))
+ {
+ struct grub_netbsd_btinfo_bootdisk bid;
+
+ grub_memset (&bid, 0, sizeof (bid));
+ bid.labelsector = partmapsector;
+ bid.label.type = label->type;
+ bid.label.checksum = label->checksum;
+ memcpy (bid.label.packname, label->packname, 16);
+ bid.biosdev = biosdev;
+ bid.partition = part->number;
+ grub_bsd_add_meta (NETBSD_BTINFO_BOOTDISK, &bid, sizeof (bid));
+ }
+
+fail:
+ if (dev)
+ grub_device_close (dev);
+}
+
static grub_err_t
grub_netbsd_boot (void)
{
goto fail;
relocator = grub_relocator_new ();
+ if (!relocator)
+ {
+ grub_file_close (file);
+ goto fail;
+ }
elf = grub_elf_file (file);
if (elf)
fail:
if (grub_errno != GRUB_ERR_NONE)
- grub_dl_unref (my_mod);
+ grub_dl_unref (my_mod);
return grub_errno;
}
grub_bsd_add_meta (NETBSD_BTINFO_CONSOLE, &cons, sizeof (cons));
}
+ grub_netbsd_add_boot_disk_and_wedge ();
+
grub_loader_set (grub_netbsd_boot, grub_bsd_unload, 0);
}
--- /dev/null
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2011 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/loader.h>
+#include <grub/memory.h>
+#include <grub/i386/memory.h>
+#include <grub/file.h>
+#include <grub/err.h>
+#include <grub/dl.h>
+#include <grub/mm.h>
+#include <grub/elfload.h>
+#include <grub/video.h>
+#include <grub/relocator.h>
+#include <grub/i386/relocator.h>
+#include <grub/command.h>
+#include <grub/i18n.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
+
+static grub_addr_t entry;
+static struct grub_relocator *relocator = NULL;
+
+static grub_err_t
+grub_chain_boot (void)
+{
+ struct grub_relocator32_state state;
+
+ grub_video_set_mode ("text", 0, 0);
+
+ state.eip = entry;
+ return grub_relocator32_boot (relocator, state);
+}
+
+static grub_err_t
+grub_chain_unload (void)
+{
+ grub_relocator_unload (relocator);
+ relocator = NULL;
+
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_chain_elf32_hook (Elf32_Phdr * phdr, grub_addr_t * addr, int *do_load)
+{
+ grub_err_t err;
+ grub_relocator_chunk_t ch;
+
+ if (phdr->p_type != PT_LOAD)
+ {
+ *do_load = 0;
+ return 0;
+ }
+
+ *do_load = 1;
+ err = grub_relocator_alloc_chunk_addr (relocator, &ch,
+ phdr->p_paddr, phdr->p_memsz);
+ if (err)
+ return err;
+
+ *addr = (grub_addr_t) get_virtual_current_address (ch);
+
+ return GRUB_ERR_NONE;
+}
+
+
+static grub_err_t
+grub_cmd_chain (grub_command_t cmd __attribute__ ((unused)),
+ int argc, char *argv[])
+{
+ grub_err_t err;
+ grub_file_t file;
+ grub_elf_t elf;
+
+ if (argc != 1)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "filename expected");
+
+ grub_loader_unset ();
+
+ file = grub_file_open (argv[0]);
+ if (!file)
+ return grub_errno;
+
+ relocator = grub_relocator_new ();
+ if (!relocator)
+ {
+ grub_file_close (file);
+ return grub_errno;
+ }
+
+ elf = grub_elf_file (file);
+ if (!elf)
+ {
+ grub_relocator_unload (relocator);
+ relocator = 0;
+ grub_file_close (file);
+ }
+
+ if (!grub_elf_is_elf32 (elf))
+ {
+ grub_relocator_unload (relocator);
+ relocator = 0;
+ grub_elf_close (elf);
+ }
+
+ entry = elf->ehdr.ehdr32.e_entry & 0xFFFFFF;
+
+ err = grub_elf32_load (elf, grub_chain_elf32_hook, 0, 0);
+
+ grub_elf_close (elf);
+ if (err)
+ return err;
+
+ grub_loader_set (grub_chain_boot, grub_chain_unload, 0);
+ return GRUB_ERR_NONE;
+}
+
+static grub_command_t cmd_chain;
+
+GRUB_MOD_INIT (chain)
+{
+ cmd_chain = grub_register_command ("chainloader", grub_cmd_chain,
+ N_("FILE"), N_("Load another payload"));
+}
+
+GRUB_MOD_FINI (chain)
+{
+ grub_unregister_command (cmd_chain);
+ grub_chain_unload ();
+}
#include <grub/i18n.h>
#include <grub/lib/cmdline.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
#ifdef GRUB_MACHINE_PCBIOS
#include <grub/i386/pc/vesa_modes_table.h>
#endif
#include <grub/efi/efi.h>
#define HAS_VGA_TEXT 0
#define DEFAULT_VIDEO_MODE "auto"
+#define ACCEPTS_PURE_TEXT 0
#elif defined (GRUB_MACHINE_IEEE1275)
#include <grub/ieee1275/ieee1275.h>
#define HAS_VGA_TEXT 0
#define DEFAULT_VIDEO_MODE "text"
+#define ACCEPTS_PURE_TEXT 1
#else
#include <grub/i386/pc/vbe.h>
#include <grub/i386/pc/console.h>
#define HAS_VGA_TEXT 1
#define DEFAULT_VIDEO_MODE "text"
+#define ACCEPTS_PURE_TEXT 1
#endif
#define GRUB_LINUX_CL_OFFSET 0x1000
-#define GRUB_LINUX_CL_END_OFFSET 0x2000
static grub_dl_t my_mod;
static grub_uint32_t initrd_pages;
static struct grub_relocator *relocator = NULL;
static void *efi_mmap_buf;
+static grub_size_t maximal_cmdline_size;
#ifdef GRUB_MACHINE_EFI
static grub_efi_uintn_t efi_mmap_size;
#else
grub_err_t err;
/* Make sure that each size is aligned to a page boundary. */
- real_size = GRUB_LINUX_CL_END_OFFSET;
+ real_size = GRUB_LINUX_CL_OFFSET + maximal_cmdline_size;
prot_size = page_align (prot_size);
mmap_size = find_mmap_size ();
/* FIXME: check if better id is available. */
case GRUB_VIDEO_DRIVER_SM712:
+ case GRUB_VIDEO_DRIVER_SIS315PRO:
case GRUB_VIDEO_DRIVER_VGA:
case GRUB_VIDEO_DRIVER_CIRRUS:
case GRUB_VIDEO_DRIVER_BOCHS:
+ case GRUB_VIDEO_DRIVER_RADEON_FULOONG2E:
/* Make gcc happy. */
case GRUB_VIDEO_DRIVER_SDL:
case GRUB_VIDEO_DRIVER_NONE:
tmp = grub_xasprintf ("%s;" DEFAULT_VIDEO_MODE, modevar);
if (! tmp)
return grub_errno;
+#if ACCEPTS_PURE_TEXT
err = grub_video_set_mode (tmp, 0, 0);
+#else
+ err = grub_video_set_mode (tmp, GRUB_VIDEO_MODE_TYPE_PURE_TEXT, 0);
+#endif
grub_free (tmp);
}
else
- err = grub_video_set_mode (DEFAULT_VIDEO_MODE, 0, 0);
-
+ {
+#if ACCEPTS_PURE_TEXT
+ err = grub_video_set_mode (DEFAULT_VIDEO_MODE, 0, 0);
+#else
+ err = grub_video_set_mode (DEFAULT_VIDEO_MODE,
+ GRUB_VIDEO_MODE_TYPE_PURE_TEXT, 0);
+#endif
+ }
if (err)
{
grub_print_error ();
#ifdef GRUB_MACHINE_EFI
{
grub_efi_uintn_t efi_desc_size;
+ grub_size_t efi_mmap_target;
grub_efi_uint32_t efi_desc_version;
err = grub_efi_finish_boot_services (&efi_mmap_size, efi_mmap_buf, NULL,
&efi_desc_size, &efi_desc_version);
return err;
/* Note that no boot services are available from here. */
-
+ efi_mmap_target = real_mode_target
+ + ((grub_uint8_t *) efi_mmap_buf - (grub_uint8_t *) real_mode_mem);
/* Pass EFI parameters. */
if (grub_le_to_cpu16 (params->version) >= 0x0206)
{
params->v0206.efi_mem_desc_size = efi_desc_size;
params->v0206.efi_mem_desc_version = efi_desc_version;
- params->v0206.efi_mmap = (grub_uint32_t) (unsigned long) efi_mmap_buf;
+ params->v0206.efi_mmap = efi_mmap_target;
params->v0206.efi_mmap_size = efi_mmap_size;
#ifdef __x86_64__
- params->v0206.efi_mmap_hi = (grub_uint32_t) ((grub_uint64_t) efi_mmap_buf >> 32);
+ params->v0206.efi_mmap_hi = (efi_mmap_target >> 32);
#endif
}
else if (grub_le_to_cpu16 (params->version) >= 0x0204)
{
params->v0204.efi_mem_desc_size = efi_desc_size;
params->v0204.efi_mem_desc_version = efi_desc_version;
- params->v0204.efi_mmap = (grub_uint32_t) (unsigned long) efi_mmap_buf;
+ params->v0204.efi_mmap = efi_mmap_target;
params->v0204.efi_mmap_size = efi_mmap_size;
}
}
goto fail;
}
+ if (grub_le_to_cpu16 (lh.version) >= 0x0206)
+ maximal_cmdline_size = grub_le_to_cpu32 (lh.cmdline_size) + 1;
+ else
+ maximal_cmdline_size = 256;
+
+ if (maximal_cmdline_size < 128)
+ maximal_cmdline_size = 128;
+
setup_sects = lh.setup_sects;
/* If SETUP_SECTS is not set, set it to the default (4). */
goto fail;
params = (struct linux_kernel_params *) real_mode_mem;
- grub_memset (params, 0, GRUB_LINUX_CL_END_OFFSET);
+ grub_memset (params, 0, GRUB_LINUX_CL_OFFSET + maximal_cmdline_size);
grub_memcpy (¶ms->setup_sects, &lh.setup_sects, sizeof (lh) - 0x1F1);
params->ps_mouse = params->padding10 = 0;
grub_create_loader_cmdline (argc, argv,
(char *)real_mode_mem + GRUB_LINUX_CL_OFFSET
+ sizeof (LINUX_IMAGE) - 1,
- GRUB_LINUX_CL_END_OFFSET - GRUB_LINUX_CL_OFFSET
+ maximal_cmdline_size
- (sizeof (LINUX_IMAGE) - 1));
len = prot_size;
#include <grub/relocator.h>
#include <grub/video.h>
#include <grub/file.h>
+#include <grub/net.h>
/* The bits in the required part of flags field we don't support. */
#define UNSUPPORTED_FLAGS 0x0000fff8
static grub_size_t
grub_multiboot_get_mbi_size (void)
{
- return sizeof (struct multiboot_info) + ALIGN_UP (cmdline_size, 4)
+ grub_size_t ret;
+ struct grub_net_network_level_interface *net;
+
+ ret = sizeof (struct multiboot_info) + ALIGN_UP (cmdline_size, 4)
+ modcnt * sizeof (struct multiboot_mod_list) + total_modcmd
+ ALIGN_UP (sizeof(PACKAGE_STRING), 4)
+ grub_get_multiboot_mmap_count () * sizeof (struct multiboot_mmap_entry)
+ sizeof (struct grub_vbe_mode_info_block)
#endif
+ ALIGN_UP (sizeof (struct multiboot_apm_info), 4);
+
+ FOR_NET_NETWORK_LEVEL_INTERFACES(net)
+ if (net->dhcp_ack)
+ {
+ ret += net->dhcp_acklen;
+ break;
+ }
+
+ return ret;
}
/* Fill previously allocated Multiboot mmap. */
mbi->flags |= MULTIBOOT_INFO_BOOTDEV;
}
+ {
+ struct grub_net_network_level_interface *net;
+ FOR_NET_NETWORK_LEVEL_INTERFACES(net)
+ if (net->dhcp_ack)
+ {
+ grub_memcpy (ptrorig, net->dhcp_ack, net->dhcp_acklen);
+ mbi->drives_addr = ptrdest;
+ mbi->drives_length = net->dhcp_acklen;
+ ptrorig += net->dhcp_acklen;
+ ptrdest += net->dhcp_acklen;
+ break;
+ }
+ }
+
if (elf_sec_num)
{
mbi->u.elf_sec.addr = ptrdest;
#include <grub/i18n.h>
#include <grub/video.h>
#include <grub/mm.h>
+#include <grub/fat.h>
+#include <grub/ntfs.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
static grub_dl_t my_mod;
static int boot_drive;
static void *boot_part_addr;
+typedef enum
+ {
+ GRUB_CHAINLOADER_FORCE = 0x1,
+ GRUB_CHAINLOADER_BPB = 0x2,
+ } grub_chainloader_flags_t;
+
static grub_err_t
grub_chainloader_boot (void)
{
return GRUB_ERR_NONE;
}
+void
+grub_chainloader_patch_bpb (void *bs, grub_device_t dev, grub_uint8_t dl)
+{
+ grub_uint32_t part_start = 0;
+ if (dev && dev->disk)
+ part_start = grub_partition_get_start (dev->disk->partition);
+ if (grub_memcmp ((char *) &((struct grub_ntfs_bpb *) bs)->oem_name,
+ "NTFS", 4) == 0)
+ {
+ struct grub_ntfs_bpb *bpb = (struct grub_ntfs_bpb *) bs;
+ bpb->num_hidden_sectors = grub_cpu_to_le32 (part_start);
+ bpb->bios_drive = dl;
+ return;
+ }
+
+ do
+ {
+ struct grub_fat_bpb *bpb = (struct grub_fat_bpb *) bs;
+ if (grub_strncmp((const char *) bpb->version_specific.fat12_or_fat16.fstype, "FAT12", 5)
+ && grub_strncmp((const char *) bpb->version_specific.fat12_or_fat16.fstype, "FAT16", 5)
+ && grub_strncmp((const char *) bpb->version_specific.fat32.fstype, "FAT32", 5))
+ break;
+
+ if (grub_le_to_cpu16 (bpb->bytes_per_sector) < 512
+ || (grub_le_to_cpu16 (bpb->bytes_per_sector)
+ & (grub_le_to_cpu16 (bpb->bytes_per_sector) - 1)))
+ break;
+
+ if (bpb->sectors_per_cluster == 0
+ || (bpb->sectors_per_cluster & (bpb->sectors_per_cluster - 1)))
+ break;
+
+ if (bpb->num_reserved_sectors == 0)
+ break;
+ if (bpb->num_total_sectors_16 == 0 || bpb->num_total_sectors_32 == 0)
+ break;
+
+ if (bpb->num_fats == 0)
+ break;
+
+ if (bpb->sectors_per_fat_16)
+ {
+ bpb->num_hidden_sectors = grub_cpu_to_le32 (part_start);
+ bpb->version_specific.fat12_or_fat16.num_ph_drive = dl;
+ return;
+ }
+ if (bpb->version_specific.fat32.sectors_per_fat_32)
+ {
+ bpb->num_hidden_sectors = grub_cpu_to_le32 (part_start);
+ bpb->version_specific.fat32.num_ph_drive = dl;
+ return;
+ }
+ break;
+ }
+ while (0);
+}
+
static void
grub_chainloader_cmd (const char *filename, grub_chainloader_flags_t flags)
{
}
}
+ if (flags & GRUB_CHAINLOADER_BPB)
+ grub_chainloader_patch_bpb ((void *) 0x7C00, dev, drive);
+
if (dev)
grub_device_close (dev);
{
grub_chainloader_flags_t flags = 0;
- if (argc > 0 && grub_strcmp (argv[0], "--force") == 0)
+ while (argc > 0)
{
- flags |= GRUB_CHAINLOADER_FORCE;
- argc--;
- argv++;
+ if (grub_strcmp (argv[0], "--force") == 0)
+ {
+ flags |= GRUB_CHAINLOADER_FORCE;
+ argc--;
+ argv++;
+ continue;
+ }
+ if (grub_strcmp (argv[0], "--bpb") == 0)
+ {
+ flags |= GRUB_CHAINLOADER_BPB;
+ argc--;
+ argv++;
+ continue;
+ }
+ break;
}
if (argc == 0)
GRUB_MOD_INIT(chainloader)
{
cmd = grub_register_command ("chainloader", grub_cmd_chainloader,
- 0, N_("Load another boot loader."));
+ "[--force|--bpb] FILE",
+ N_("Load another boot loader."));
my_mod = mod;
}
--- /dev/null
+/* chainloader.c - boot another boot loader */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2002,2004,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/loader.h>
+#include <grub/file.h>
+#include <grub/err.h>
+#include <grub/device.h>
+#include <grub/disk.h>
+#include <grub/misc.h>
+#include <grub/types.h>
+#include <grub/partition.h>
+#include <grub/dl.h>
+#include <grub/command.h>
+#include <grub/machine/biosnum.h>
+#include <grub/i18n.h>
+#include <grub/video.h>
+#include <grub/mm.h>
+#include <grub/cpu/relocator.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
+
+static grub_dl_t my_mod;
+static struct grub_relocator *rel;
+static grub_uint32_t ebx = 0xffffffff;
+
+#define GRUB_FREEDOS_SEGMENT 0x60
+#define GRUB_FREEDOS_STACK_SEGMENT 0x1fe0
+#define GRUB_FREEDOS_STACK_POINTER 0x8000
+
+static grub_err_t
+grub_freedos_boot (void)
+{
+ struct grub_relocator16_state state = {
+ .cs = GRUB_FREEDOS_SEGMENT,
+ .ip = 0,
+ .ds = 0,
+ .es = 0,
+ .fs = 0,
+ .gs = 0,
+ .ss = GRUB_FREEDOS_STACK_SEGMENT,
+ .sp = GRUB_FREEDOS_STACK_POINTER,
+ .ebx = ebx,
+ .edx = 0
+ };
+ grub_video_set_mode ("text", 0, 0);
+
+ return grub_relocator16_boot (rel, state);
+}
+
+static grub_err_t
+grub_freedos_unload (void)
+{
+ grub_relocator_unload (rel);
+ rel = NULL;
+ grub_dl_unref (my_mod);
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_cmd_freedos (grub_command_t cmd __attribute__ ((unused)),
+ int argc, char *argv[])
+{
+ grub_file_t file = 0;
+ grub_err_t err;
+ void *kernelsys;
+ grub_size_t kernelsyssize;
+
+ if (argc == 0)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "no file specified");
+
+ grub_dl_ref (my_mod);
+
+ rel = grub_relocator_new ();
+ if (!rel)
+ goto fail;
+
+ file = grub_file_open (argv[0]);
+ if (! file)
+ goto fail;
+
+ ebx = grub_get_root_biosnumber ();
+
+ kernelsyssize = grub_file_size (file);
+ {
+ grub_relocator_chunk_t ch;
+ err = grub_relocator_alloc_chunk_addr (rel, &ch, GRUB_FREEDOS_SEGMENT << 4,
+ kernelsyssize);
+ if (err)
+ goto fail;
+ kernelsys = get_virtual_current_address (ch);
+ }
+
+ if (grub_file_read (file, kernelsys, kernelsyssize)
+ != (grub_ssize_t) kernelsyssize)
+ goto fail;
+
+ grub_loader_set (grub_freedos_boot, grub_freedos_unload, 1);
+ return GRUB_ERR_NONE;
+
+ fail:
+
+ if (file)
+ grub_file_close (file);
+
+ grub_freedos_unload ();
+
+ return grub_errno;
+}
+
+static grub_command_t cmd;
+
+GRUB_MOD_INIT(freedos)
+{
+ cmd = grub_register_command ("freedos", grub_cmd_freedos,
+ 0, N_("Load FreeDOS kernel.sys."));
+ my_mod = mod;
+}
+
+GRUB_MOD_FINI(freedos)
+{
+ grub_unregister_command (cmd);
+}
#include <grub/i386/floppy.h>
#include <grub/lib/cmdline.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
#define GRUB_LINUX_CL_OFFSET 0x9000
-#define GRUB_LINUX_CL_END_OFFSET 0x90FF
static grub_dl_t my_mod;
static grub_addr_t grub_linux_real_target;
static char *grub_linux_real_chunk;
static grub_size_t grub_linux16_prot_size;
+static grub_size_t maximal_cmdline_size;
static grub_err_t
grub_linux16_boot (void)
setup_sects = lh.setup_sects;
linux_mem_size = 0;
+ maximal_cmdline_size = 256;
+
if (lh.header == grub_cpu_to_le32 (GRUB_LINUX_MAGIC_SIGNATURE)
&& grub_le_to_cpu16 (lh.version) >= 0x0200)
{
grub_linux_is_bzimage = (lh.loadflags & GRUB_LINUX_FLAG_BIG_KERNEL);
lh.type_of_loader = GRUB_LINUX_BOOT_LOADER_TYPE;
+ if (grub_le_to_cpu16 (lh.version) >= 0x0206)
+ maximal_cmdline_size = grub_le_to_cpu32 (lh.cmdline_size) + 1;
+
/* Put the real mode part at as a high location as possible. */
grub_linux_real_target = grub_mmap_get_lower ()
- - GRUB_LINUX_SETUP_MOVE_SIZE;
+ - (GRUB_LINUX_CL_OFFSET + maximal_cmdline_size);
/* But it must not exceed the traditional area. */
if (grub_linux_real_target > GRUB_LINUX_OLD_REAL_MODE_ADDR)
grub_linux_real_target = GRUB_LINUX_OLD_REAL_MODE_ADDR;
{
lh.cl_magic = grub_cpu_to_le16 (GRUB_LINUX_CL_MAGIC);
lh.cl_offset = grub_cpu_to_le16 (GRUB_LINUX_CL_OFFSET);
- lh.setup_move_size = grub_cpu_to_le16 (GRUB_LINUX_SETUP_MOVE_SIZE);
+ lh.setup_move_size = grub_cpu_to_le16 (GRUB_LINUX_CL_OFFSET
+ + maximal_cmdline_size);
}
}
else
goto fail;
}
- if (grub_linux_real_target + GRUB_LINUX_SETUP_MOVE_SIZE
+ if (grub_linux_real_target + GRUB_LINUX_CL_OFFSET + maximal_cmdline_size
> grub_mmap_get_lower ())
{
grub_error (GRUB_ERR_OUT_OF_RANGE,
"too small lower memory (0x%x > 0x%x)",
- grub_linux_real_target + GRUB_LINUX_SETUP_MOVE_SIZE,
+ grub_linux_real_target + GRUB_LINUX_CL_OFFSET
+ + maximal_cmdline_size,
(int) grub_mmap_get_lower ());
goto fail;
}
grub_relocator_chunk_t ch;
err = grub_relocator_alloc_chunk_addr (relocator, &ch,
grub_linux_real_target,
- GRUB_LINUX_SETUP_MOVE_SIZE);
+ GRUB_LINUX_CL_OFFSET
+ + maximal_cmdline_size);
if (err)
return err;
grub_linux_real_chunk = get_virtual_current_address (ch);
grub_create_loader_cmdline (argc, argv,
(char *)grub_linux_real_chunk
+ GRUB_LINUX_CL_OFFSET + sizeof (LINUX_IMAGE) - 1,
- GRUB_LINUX_CL_END_OFFSET - GRUB_LINUX_CL_OFFSET
+ maximal_cmdline_size
- (sizeof (LINUX_IMAGE) - 1));
if (grub_linux_is_bzimage)
#include <grub/video.h>
#include <grub/mm.h>
#include <grub/cpu/relocator.h>
+#include <grub/machine/chainloader.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
static grub_dl_t my_mod;
static struct grub_relocator *rel;
grub_device_close (dev);
goto fail;
}
+ grub_chainloader_patch_bpb (bs, dev, edx);
}
if (dev)
}
devprop = grub_xnu_create_value (&(efikey->first_child), "device-properties");
- if (devprop)
- {
- devprop->data = grub_malloc (total_length);
- devprop->datasize = total_length;
- }
+ if (!devprop)
+ return grub_errno;
+
+ devprop->data = grub_malloc (total_length);
+ devprop->datasize = total_length;
ptr = devprop->data;
head = ptr;
--- /dev/null
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2008,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/loader.h>
+#include <grub/file.h>
+#include <grub/disk.h>
+#include <grub/err.h>
+#include <grub/misc.h>
+#include <grub/types.h>
+#include <grub/command.h>
+#include <grub/dl.h>
+#include <grub/mm.h>
+#include <grub/cache.h>
+#include <grub/kernel.h>
+#include <grub/efi/api.h>
+#include <grub/efi/efi.h>
+#include <grub/elf.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
+
+#define ALIGN_MIN (256*1024*1024)
+
+#define GRUB_ELF_SEARCH 1024
+
+#define BOOT_PARAM_SIZE 16384
+
+struct ia64_boot_param
+{
+ grub_uint64_t command_line; /* physical address of command line. */
+ grub_uint64_t efi_systab; /* physical address of EFI system table */
+ grub_uint64_t efi_memmap; /* physical address of EFI memory map */
+ grub_uint64_t efi_memmap_size; /* size of EFI memory map */
+ grub_uint64_t efi_memdesc_size; /* size of an EFI memory map descriptor */
+ grub_uint32_t efi_memdesc_version; /* memory descriptor version */
+ struct
+ {
+ grub_uint16_t num_cols; /* number of columns on console output dev */
+ grub_uint16_t num_rows; /* number of rows on console output device */
+ grub_uint16_t orig_x; /* cursor's x position */
+ grub_uint16_t orig_y; /* cursor's y position */
+ } console_info;
+ grub_uint64_t fpswa; /* physical address of the fpswa interface */
+ grub_uint64_t initrd_start;
+ grub_uint64_t initrd_size;
+ grub_uint64_t domain_start; /* boot domain address. */
+ grub_uint64_t domain_size; /* how big is the boot domain */
+ grub_uint64_t payloads_chain;
+ grub_uint64_t payloads_nbr;
+};
+
+struct ia64_boot_payload
+{
+ grub_uint64_t start;
+ grub_uint64_t length;
+
+ /* Payload command line */
+ grub_uint64_t cmdline;
+
+ grub_uint64_t next;
+};
+
+typedef struct
+{
+ grub_uint32_t revision;
+ grub_uint32_t reserved;
+ void *fpswa;
+} fpswa_interface_t;
+static fpswa_interface_t *fpswa;
+
+#define NEXT_MEMORY_DESCRIPTOR(desc, size) \
+ ((grub_efi_memory_descriptor_t *) ((char *) (desc) + (size)))
+
+static grub_dl_t my_mod;
+
+static int loaded;
+
+/* Kernel base and size. */
+static void *kernel_mem;
+static grub_efi_uintn_t kernel_pages;
+static grub_uint64_t entry;
+
+/* Initrd base and size. */
+static void *initrd_mem;
+static grub_efi_uintn_t initrd_pages;
+static grub_efi_uintn_t initrd_size;
+
+static struct ia64_boot_param *boot_param;
+static grub_efi_uintn_t boot_param_pages;
+static struct ia64_boot_payload *last_payload = NULL;
+
+/* Can linux kernel be relocated ? */
+#define RELOCATE_OFF 0 /* No. */
+#define RELOCATE_ON 1 /* Yes. */
+#define RELOCATE_FORCE 2 /* Always - used to debug. */
+static int relocate = RELOCATE_OFF;
+
+static inline grub_size_t
+page_align (grub_size_t size)
+{
+ return (size + (1 << 12) - 1) & (~((1 << 12) - 1));
+}
+
+static void
+query_fpswa (void)
+{
+ grub_efi_handle_t fpswa_image;
+ grub_efi_boot_services_t *bs;
+ grub_efi_status_t status;
+ grub_efi_uintn_t size;
+ static const grub_efi_guid_t fpswa_protocol =
+ { 0xc41b6531, 0x97b9, 0x11d3,
+ {0x9a, 0x29, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d} };
+
+ if (fpswa != NULL)
+ return;
+
+ size = sizeof(grub_efi_handle_t);
+
+ bs = grub_efi_system_table->boot_services;
+ status = bs->locate_handle (GRUB_EFI_BY_PROTOCOL,
+ (void *)&fpswa_protocol,
+ NULL, &size, &fpswa_image);
+ if (status != GRUB_EFI_SUCCESS)
+ {
+ grub_printf("Could not locate FPSWA driver\n");
+ return;
+ }
+ status = bs->handle_protocol (fpswa_image,
+ (void *)&fpswa_protocol, (void *)&fpswa);
+ if (status != GRUB_EFI_SUCCESS)
+ {
+ grub_printf ("Fpswa protocol not able find the interface\n");
+ return;
+ }
+}
+
+/* Find the optimal number of pages for the memory map. Is it better to
+ move this code to efi/mm.c? */
+static grub_efi_uintn_t
+find_mmap_size (void)
+{
+ static grub_efi_uintn_t mmap_size = 0;
+
+ if (mmap_size != 0)
+ return mmap_size;
+
+ mmap_size = (1 << 12);
+ while (1)
+ {
+ int ret;
+ grub_efi_memory_descriptor_t *mmap;
+ grub_efi_uintn_t desc_size;
+
+ mmap = grub_malloc (mmap_size);
+ if (! mmap)
+ return 0;
+
+ ret = grub_efi_get_memory_map (&mmap_size, mmap, 0, &desc_size, 0);
+ grub_free (mmap);
+
+ if (ret < 0)
+ grub_fatal ("cannot get memory map");
+ else if (ret > 0)
+ break;
+
+ mmap_size += (1 << 12);
+ }
+
+ /* Increase the size a bit for safety, because GRUB allocates more on
+ later, and EFI itself may allocate more. */
+ mmap_size += (1 << 12);
+
+ return page_align (mmap_size);
+}
+
+static void
+free_pages (void)
+{
+ if (kernel_mem)
+ {
+ grub_efi_free_pages ((grub_addr_t) kernel_mem, kernel_pages);
+ kernel_mem = 0;
+ }
+
+ if (initrd_mem)
+ {
+ grub_efi_free_pages ((grub_addr_t) initrd_mem, initrd_pages);
+ initrd_mem = 0;
+ }
+
+ if (boot_param)
+ {
+ struct ia64_boot_payload *payload;
+ struct ia64_boot_payload *next_payload;
+
+ /* Free payloads. */
+ payload = (struct ia64_boot_payload *)boot_param->payloads_chain;
+ while (payload != 0)
+ {
+ next_payload = (struct ia64_boot_payload *)payload->next;
+
+ grub_efi_free_pages
+ (payload->start, page_align (payload->length) >> 12);
+ grub_efi_free_pages ((grub_efi_physical_address_t)payload, 1);
+
+ payload = next_payload;
+ }
+
+ /* Free bootparam. */
+ grub_efi_free_pages ((grub_efi_physical_address_t)boot_param,
+ boot_param_pages);
+ boot_param = 0;
+ }
+}
+
+static void *
+allocate_pages (grub_uint64_t align, grub_uint64_t size_pages,
+ grub_uint64_t nobase)
+{
+ grub_uint64_t size;
+ grub_efi_uintn_t desc_size;
+ grub_efi_memory_descriptor_t *mmap, *mmap_end;
+ grub_efi_uintn_t mmap_size, tmp_mmap_size;
+ grub_efi_memory_descriptor_t *desc;
+ void *mem = NULL;
+
+ size = size_pages << 12;
+
+ mmap_size = find_mmap_size ();
+
+ /* Read the memory map temporarily, to find free space. */
+ mmap = grub_malloc (mmap_size);
+ if (! mmap)
+ return 0;
+
+ tmp_mmap_size = mmap_size;
+ if (grub_efi_get_memory_map (&tmp_mmap_size, mmap, 0, &desc_size, 0) <= 0)
+ grub_fatal ("cannot get memory map");
+
+ mmap_end = NEXT_MEMORY_DESCRIPTOR (mmap, tmp_mmap_size);
+
+ /* First, find free pages for the real mode code
+ and the memory map buffer. */
+ for (desc = mmap;
+ desc < mmap_end;
+ desc = NEXT_MEMORY_DESCRIPTOR (desc, desc_size))
+ {
+ grub_uint64_t start, end;
+ grub_uint64_t aligned_start;
+
+ if (desc->type != GRUB_EFI_CONVENTIONAL_MEMORY)
+ continue;
+
+ start = desc->physical_start;
+ end = start + (desc->num_pages << 12);
+ /* Align is a power of 2. */
+ aligned_start = (start + align - 1) & ~(align - 1);
+ if (aligned_start + size > end)
+ continue;
+ if (aligned_start == nobase)
+ aligned_start += align;
+ if (aligned_start + size > end)
+ continue;
+ mem = grub_efi_allocate_pages (aligned_start, size_pages);
+ if (! mem)
+ grub_fatal ("cannot allocate pages");
+ break;
+ }
+
+ if (! mem)
+ {
+ grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate memory");
+ goto fail;
+ }
+
+ grub_free (mmap);
+ return mem;
+
+ fail:
+ grub_free (mmap);
+ free_pages ();
+ return 0;
+}
+
+static void
+set_boot_param_console (void)
+{
+ grub_efi_simple_text_output_interface_t *conout;
+ grub_efi_uintn_t cols, rows;
+
+ conout = grub_efi_system_table->con_out;
+ if (conout->query_mode (conout, conout->mode->mode, &cols, &rows)
+ != GRUB_EFI_SUCCESS)
+ return;
+
+ grub_dprintf("linux",
+ "Console info: cols=%lu rows=%lu x=%u y=%u\n",
+ cols, rows,
+ conout->mode->cursor_column, conout->mode->cursor_row);
+
+ boot_param->console_info.num_cols = cols;
+ boot_param->console_info.num_rows = rows;
+ boot_param->console_info.orig_x = conout->mode->cursor_column;
+ boot_param->console_info.orig_y = conout->mode->cursor_row;
+}
+
+static grub_err_t
+grub_linux_boot (void)
+{
+ grub_efi_uintn_t mmap_size;
+ grub_efi_uintn_t map_key;
+ grub_efi_uintn_t desc_size;
+ grub_efi_uint32_t desc_version;
+ grub_efi_memory_descriptor_t *mmap_buf;
+ grub_err_t err;
+
+ /* FPSWA. */
+ query_fpswa ();
+ boot_param->fpswa = (grub_uint64_t)fpswa;
+
+ /* Initrd. */
+ boot_param->initrd_start = (grub_uint64_t)initrd_mem;
+ boot_param->initrd_size = (grub_uint64_t)initrd_size;
+
+ set_boot_param_console ();
+
+ grub_printf ("Jump to %016lx\n", entry);
+
+ grub_machine_fini ();
+
+ /* MDT.
+ Must be done after grub_machine_fini because map_key is used by
+ exit_boot_services. */
+ mmap_size = find_mmap_size ();
+ mmap_buf = grub_efi_allocate_pages (0, page_align (mmap_size) >> 12);
+ if (! mmap_buf)
+ grub_fatal ("cannot allocate memory map");
+ err = grub_efi_finish_boot_services (&mmap_size, mmap_buf, &map_key,
+ &desc_size, &desc_version);
+ if (err)
+ return err;
+
+ boot_param->efi_memmap = (grub_uint64_t)mmap_buf;
+ boot_param->efi_memmap_size = mmap_size;
+ boot_param->efi_memdesc_size = desc_size;
+ boot_param->efi_memdesc_version = desc_version;
+
+ /* See you next boot. */
+ asm volatile ("mov r28=%1; br.sptk.few %0" :: "b"(entry),"r"(boot_param));
+
+ /* Never reach here. */
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_linux_unload (void)
+{
+ free_pages ();
+ grub_dl_unref (my_mod);
+ loaded = 0;
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_load_elf64 (grub_file_t file, void *buffer)
+{
+ Elf64_Ehdr *ehdr = (Elf64_Ehdr *) buffer;
+ Elf64_Phdr *phdr;
+ int i;
+ grub_uint64_t low_addr;
+ grub_uint64_t high_addr;
+ grub_uint64_t align;
+ grub_uint64_t reloc_offset;
+
+ if (ehdr->e_ident[EI_CLASS] != ELFCLASS64)
+ return grub_error (GRUB_ERR_UNKNOWN_OS, "invalid ELF class");
+
+ if (ehdr->e_ident[EI_MAG0] != ELFMAG0
+ || ehdr->e_ident[EI_MAG1] != ELFMAG1
+ || ehdr->e_ident[EI_MAG2] != ELFMAG2
+ || ehdr->e_ident[EI_MAG3] != ELFMAG3
+ || ehdr->e_version != EV_CURRENT
+ || ehdr->e_ident[EI_DATA] != ELFDATA2LSB
+ || ehdr->e_machine != EM_IA_64)
+ return grub_error(GRUB_ERR_UNKNOWN_OS, "no valid ELF header found");
+
+ if (ehdr->e_type != ET_EXEC)
+ return grub_error (GRUB_ERR_UNKNOWN_OS, "invalid ELF file type");
+
+ /* FIXME: Should we support program headers at strange locations? */
+ if (ehdr->e_phoff + ehdr->e_phnum * ehdr->e_phentsize > GRUB_ELF_SEARCH)
+ return grub_error (GRUB_ERR_BAD_OS, "program header at a too high offset");
+
+ entry = ehdr->e_entry;
+
+ /* Compute low, high and align addresses. */
+ low_addr = ~0UL;
+ high_addr = 0;
+ align = 0;
+ for (i = 0; i < ehdr->e_phnum; i++)
+ {
+ phdr = (Elf64_Phdr *) ((char *) buffer + ehdr->e_phoff
+ + i * ehdr->e_phentsize);
+ if (phdr->p_type == PT_LOAD)
+ {
+ if (phdr->p_paddr < low_addr)
+ low_addr = phdr->p_paddr;
+ if (phdr->p_paddr + phdr->p_memsz > high_addr)
+ high_addr = phdr->p_paddr + phdr->p_memsz;
+ if (phdr->p_align > align)
+ align = phdr->p_align;
+ }
+ }
+
+ if (align < ALIGN_MIN)
+ align = ALIGN_MIN;
+
+ if (high_addr == 0)
+ return grub_error (GRUB_ERR_BAD_OS, "no program entries");
+
+ kernel_pages = page_align (high_addr - low_addr) >> 12;
+
+ if (relocate != RELOCATE_FORCE)
+ {
+ kernel_mem = grub_efi_allocate_pages (low_addr, kernel_pages);
+ reloc_offset = 0;
+ }
+ /* Try to relocate. */
+ if (! kernel_mem && relocate != RELOCATE_OFF)
+ {
+ kernel_mem = allocate_pages (align, kernel_pages, low_addr);
+ if (kernel_mem)
+ {
+ reloc_offset = (grub_uint64_t)kernel_mem - low_addr;
+ grub_printf (" Relocated at %p (offset=%016lx)\n",
+ kernel_mem, reloc_offset);
+ entry += reloc_offset;
+ }
+ }
+ if (! kernel_mem)
+ return grub_error (GRUB_ERR_OUT_OF_MEMORY,
+ "cannot allocate memory for OS");
+
+ /* Load every loadable segment in memory. */
+ for (i = 0; i < ehdr->e_phnum; i++)
+ {
+ phdr = (Elf64_Phdr *) ((char *) buffer + ehdr->e_phoff
+ + i * ehdr->e_phentsize);
+ if (phdr->p_type == PT_LOAD)
+ {
+ grub_printf (" [paddr=%lx load=%lx memsz=%08lx "
+ "off=%lx flags=%x]\n",
+ phdr->p_paddr, phdr->p_paddr + reloc_offset,
+ phdr->p_memsz, phdr->p_offset, phdr->p_flags);
+
+ if (grub_file_seek (file, phdr->p_offset) == (grub_off_t)-1)
+ return grub_error (GRUB_ERR_BAD_OS,
+ "invalid offset in program header");
+
+ if (grub_file_read (file, (void *)(phdr->p_paddr + reloc_offset),
+ phdr->p_filesz)
+ != (grub_ssize_t) phdr->p_filesz)
+ return grub_error (GRUB_ERR_BAD_OS,
+ "couldn't read segment from file");
+
+ if (phdr->p_filesz < phdr->p_memsz)
+ grub_memset
+ ((char *)(phdr->p_paddr + reloc_offset + phdr->p_filesz),
+ 0, phdr->p_memsz - phdr->p_filesz);
+
+ /* Sync caches if necessary. */
+ if (phdr->p_flags & PF_X)
+ grub_arch_sync_caches
+ ((void *)(phdr->p_paddr + reloc_offset), phdr->p_memsz);
+ }
+ }
+ loaded = 1;
+ return 0;
+}
+
+static grub_err_t
+grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+ int argc, char *argv[])
+{
+ grub_file_t file = 0;
+ char buffer[GRUB_ELF_SEARCH];
+ char *cmdline, *p;
+ grub_ssize_t len;
+ int i;
+
+ grub_dl_ref (my_mod);
+
+ grub_loader_unset ();
+
+ if (argc == 0)
+ {
+ grub_error (GRUB_ERR_BAD_ARGUMENT, "No kernel specified");
+ goto fail;
+ }
+
+ file = grub_file_open (argv[0]);
+ if (! file)
+ {
+ grub_error (GRUB_ERR_BAD_ARGUMENT, "Couldn't open file");
+ goto fail;
+ }
+
+ len = grub_file_read (file, buffer, sizeof (buffer));
+ if (len < (grub_ssize_t)sizeof (Elf64_Ehdr))
+ {
+ grub_error (GRUB_ERR_BAD_OS, "File too small");
+ goto fail;
+ }
+
+ grub_printf ("Loading linux: %s\n", argv[0]);
+
+ if (grub_load_elf64 (file, buffer))
+ goto fail;
+
+ len = sizeof("BOOT_IMAGE=") + 8;
+ for (i = 0; i < argc; i++)
+ len += grub_strlen (argv[i]) + 1;
+ len += sizeof (struct ia64_boot_param) + 256; /* Room for extensions. */
+ boot_param_pages = page_align (len) >> 12;
+ boot_param = grub_efi_allocate_pages (0, boot_param_pages);
+ if (boot_param == 0)
+ {
+ grub_error (GRUB_ERR_OUT_OF_MEMORY,
+ "cannot allocate memory for bootparams");
+ goto fail;
+ }
+
+ grub_memset (boot_param, 0, len);
+ cmdline = ((char *)(boot_param + 1)) + 256;
+
+ /* Build cmdline. */
+ p = grub_stpcpy (cmdline, "BOOT_IMAGE");
+ for (i = 0; i < argc; i++)
+ {
+ *p++ = ' ';
+ p = grub_stpcpy (p, argv[i]);
+ }
+ cmdline[10] = '=';
+
+ boot_param->command_line = (grub_uint64_t) cmdline;
+ boot_param->efi_systab = (grub_uint64_t) grub_efi_system_table;
+
+ grub_errno = GRUB_ERR_NONE;
+
+ grub_loader_set (grub_linux_boot, grub_linux_unload, 0);
+
+ fail:
+ if (file)
+ grub_file_close (file);
+
+ if (grub_errno != GRUB_ERR_NONE)
+ {
+ grub_efi_free_pages ((grub_efi_physical_address_t) boot_param,
+ boot_param_pages);
+ grub_dl_unref (my_mod);
+ }
+ return grub_errno;
+}
+
+static grub_err_t
+grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
+ int argc, char *argv[])
+{
+ grub_file_t file = 0;
+
+ if (argc == 0)
+ {
+ grub_error (GRUB_ERR_BAD_ARGUMENT, "No filename specified");
+ goto fail;
+ }
+
+ if (! loaded)
+ {
+ grub_error (GRUB_ERR_BAD_ARGUMENT, "You need to load the kernel first.");
+ goto fail;
+ }
+
+ file = grub_file_open (argv[0]);
+ if (! file)
+ goto fail;
+
+ grub_printf ("Loading initrd: %s\n",argv[0]);
+
+ initrd_size = grub_file_size (file);
+ initrd_pages = (page_align (initrd_size) >> 12);
+ initrd_mem = grub_efi_allocate_pages (0, initrd_pages);
+ if (! initrd_mem)
+ grub_fatal ("cannot allocate pages");
+
+ grub_printf (" [addr=0x%lx, size=0x%lx]\n",
+ (grub_uint64_t)initrd_mem, initrd_size);
+
+ if (grub_file_read (file, initrd_mem, initrd_size)
+ != (grub_ssize_t)initrd_size)
+ {
+ grub_error (GRUB_ERR_FILE_READ_ERROR, "Couldn't read file");
+ goto fail;
+ }
+ fail:
+ if (file)
+ grub_file_close (file);
+ return grub_errno;
+}
+
+static grub_err_t
+grub_cmd_payload (grub_command_t cmd __attribute__ ((unused)),
+ int argc, char *argv[])
+{
+ grub_file_t file = 0;
+ grub_ssize_t size, len = 0;
+ char *base = 0, *cmdline = 0, *p;
+ struct ia64_boot_payload *payload = NULL;
+ int i;
+
+ if (argc == 0)
+ {
+ grub_error (GRUB_ERR_BAD_ARGUMENT, "No module specified");
+ goto fail;
+ }
+
+ if (!boot_param)
+ {
+ grub_error (GRUB_ERR_BAD_ARGUMENT,
+ "You need to load the kernel first");
+ goto fail;
+ }
+
+ file = grub_file_open (argv[0]);
+ if (! file)
+ goto fail;
+
+ size = grub_file_size (file);
+ base = grub_efi_allocate_pages (0, page_align (size) >> 12);
+ if (! base)
+ goto fail;
+
+ grub_printf ("Payload %s [addr=%lx + %lx]\n",
+ argv[0], (grub_uint64_t)base, size);
+
+ if (grub_file_read (file, base, size) != size)
+ {
+ grub_error (GRUB_ERR_FILE_READ_ERROR, "Couldn't read file");
+ goto fail;
+ }
+
+ len = sizeof (struct ia64_boot_payload);
+ for (i = 0; i < argc; i++)
+ len += grub_strlen (argv[i]) + 1;
+
+ if (len > 4096)
+ {
+ grub_error (GRUB_ERR_OUT_OF_RANGE, "payload command line too long");
+ goto fail;
+ }
+ payload = grub_efi_allocate_pages (0, 1);
+ if (! payload)
+ goto fail;
+
+ p = (char *)(payload + 1);
+
+ payload->start = (grub_uint64_t)base;
+ payload->length = size;
+ payload->cmdline = (grub_uint64_t)p;
+ payload->next = 0;
+
+ if (last_payload)
+ last_payload->next = (grub_uint64_t)payload;
+ else
+ {
+ last_payload = payload;
+ boot_param->payloads_chain = (grub_uint64_t)payload;
+ }
+ boot_param->payloads_nbr++;
+
+ /* Copy command line. */
+ for (i = 0; i < argc; i++)
+ {
+ p = grub_stpcpy (p, argv[i]);
+ *(p++) = ' ';
+ }
+
+ /* Remove the space after the last word. */
+ *(--p) = '\0';
+
+
+ fail:
+ if (file)
+ grub_file_close (file);
+
+ if (grub_errno != GRUB_ERR_NONE)
+ {
+ grub_free (base);
+ grub_free (cmdline);
+ }
+ return grub_errno;
+}
+
+static grub_err_t
+grub_cmd_relocate (grub_command_t cmd __attribute__ ((unused)),
+ int argc, char *argv[])
+{
+ static const char * const vals[] = { "off", "on", "force"};
+ unsigned int i;
+
+ if (argc == 0)
+ {
+ grub_printf ("relocate is %s\n", vals[relocate]);
+ return GRUB_ERR_NONE;
+ }
+ else if (argc == 1)
+ {
+ if (kernel_mem != NULL)
+ grub_printf ("Warning: kernel already loaded!\n");
+ for (i = 0; i < sizeof (vals)/sizeof(vals[0]); i++)
+ if (grub_strcmp (argv[0], vals[i]) == 0)
+ {
+ relocate = i;
+ return GRUB_ERR_NONE;
+ }
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "unknown relocate value");
+ }
+ else
+ {
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "accept 0 or 1 argument");
+ }
+
+}
+
+
+static grub_err_t
+grub_cmd_fpswa (grub_command_t cmd __attribute__ ((unused)),
+ int argc, char *argv[] __attribute__((unused)))
+{
+ if (argc != 0)
+ {
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "Arguments not expected");
+ }
+ query_fpswa ();
+ if (fpswa == NULL)
+ grub_printf ("No FPSWA loaded\n");
+ else
+ grub_printf ("FPSWA revision: %x\n", fpswa->revision);
+ return GRUB_ERR_NONE;
+}
+
+static grub_command_t cmd_linux, cmd_initrd, cmd_payload, cmd_relocate, cmd_fpswa;
+
+GRUB_MOD_INIT(linux)
+{
+ cmd_linux = grub_register_command ("linux", grub_cmd_linux,
+ "FILE [ARGS...]", "Load Linux.");
+
+ cmd_initrd = grub_register_command ("initrd", grub_cmd_initrd,
+ "FILE", "Load initrd.");
+
+ cmd_payload = grub_register_command ("payload", grub_cmd_payload,
+ "FILE [ARGS...]",
+ "Load an additional file.");
+
+ cmd_relocate = grub_register_command ("relocate", grub_cmd_relocate,
+ "[on|off|force]",
+ "Set relocate feature.");
+
+ cmd_fpswa = grub_register_command ("fpswa", grub_cmd_fpswa,
+ "", "Display FPSWA version.");
+
+ my_mod = mod;
+}
+
+GRUB_MOD_FINI(linux)
+{
+ grub_unregister_command (cmd_linux);
+ grub_unregister_command (cmd_initrd);
+ grub_unregister_command (cmd_payload);
+ grub_unregister_command (cmd_relocate);
+ grub_unregister_command (cmd_fpswa);
+}
#include <grub/mips/relocator.h>
#include <grub/memory.h>
#include <grub/i18n.h>
+#include <grub/lib/cmdline.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
/* For frequencies. */
-#include <grub/pci.h>
#include <grub/machine/time.h>
-#ifdef GRUB_MACHINE_MIPS_YEELOONG
-/* This can be detected on runtime from PMON, but:
- a) it wouldn't work when GRUB is the firmware
- and
- b) for now we only support Yeeloong anyway. */
-#define LOONGSON_MACHTYPE "machtype=lemote-yeeloong-2f-8.9inches"
+#ifdef GRUB_MACHINE_MIPS_LOONGSON
+#include <grub/pci.h>
+#include <grub/machine/kernel.h>
+
+const char loongson_machtypes[][60] =
+ {
+ [GRUB_ARCH_MACHINE_YEELOONG] = "machtype=lemote-yeeloong-2f-8.9inches",
+ [GRUB_ARCH_MACHINE_FULOONG2F] = "machtype=lemote-fuloong-2f-unknown",
+ [GRUB_ARCH_MACHINE_FULOONG2E] = "machtype=lemote-fuloong-2e-unknown"
+ };
#endif
static grub_dl_t my_mod;
static struct grub_relocator *relocator;
static grub_uint8_t *playground;
static grub_addr_t target_addr, entry_addr;
+#ifdef GRUB_MACHINE_MIPS_QEMU_MIPS
+static char *params;
+#else
static int linux_argc;
-static grub_off_t argv_off, envp_off;
+static grub_off_t argv_off;
+#ifdef GRUB_MACHINE_MIPS_LOONGSON
+static grub_off_t envp_off;
+#endif
static grub_off_t rd_addr_arg_off, rd_size_arg_off;
+#endif
static int initrd_loaded = 0;
static grub_err_t
{
struct grub_relocator32_state state;
+ grub_memset (&state, 0, sizeof (state));
+
/* Boot the kernel. */
state.gpr[1] = entry_addr;
+
+#ifdef GRUB_MACHINE_MIPS_QEMU_MIPS
+ {
+ grub_err_t err;
+ grub_relocator_chunk_t ch;
+ grub_uint32_t *memsize;
+ grub_uint32_t *magic;
+ char *str;
+
+ err = grub_relocator_alloc_chunk_addr (relocator, &ch,
+ ((16 << 20) - 264),
+ grub_strlen (params) + 1 + 8);
+ if (err)
+ return err;
+ memsize = get_virtual_current_address (ch);
+ magic = memsize + 1;
+ *memsize = grub_mmap_get_lower ();
+ *magic = 0x12345678;
+ str = (char *) (magic + 1);
+ grub_strcpy (str, params);
+ }
+#endif
+
+#ifndef GRUB_MACHINE_MIPS_QEMU_MIPS
state.gpr[4] = linux_argc;
state.gpr[5] = target_addr + argv_off;
+#ifdef GRUB_MACHINE_MIPS_LOONGSON
state.gpr[6] = target_addr + envp_off;
+#else
+ state.gpr[6] = 0;
+#endif
+ state.gpr[7] = 0;
+#endif
state.jumpreg = 1;
grub_relocator32_boot (relocator, state);
grub_relocator_unload (relocator);
grub_dl_unref (my_mod);
+#ifdef GRUB_MACHINE_MIPS_QEMU_MIPS
+ grub_free (params);
+ params = 0;
+#endif
+
loaded = 0;
return GRUB_ERR_NONE;
int argc, char *argv[])
{
grub_elf_t elf = 0;
- int i;
int size;
void *extra = NULL;
- grub_uint32_t *linux_argv, *linux_envp;
- char *linux_args, *linux_envs;
+#ifndef GRUB_MACHINE_MIPS_QEMU_MIPS
+ int i;
+ grub_uint32_t *linux_argv;
+ char *linux_args;
+#endif
grub_err_t err;
+#ifdef GRUB_MACHINE_MIPS_LOONGSON
+ char *linux_envs;
+ grub_uint32_t *linux_envp;
+#endif
if (argc == 0)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "no kernel specified");
grub_loader_unset ();
loaded = 0;
+#ifdef GRUB_MACHINE_MIPS_QEMU_MIPS
+ size = 0;
+#else
/* For arguments. */
linux_argc = argc;
-#ifdef LOONGSON_MACHTYPE
+#ifdef GRUB_MACHINE_MIPS_LOONGSON
linux_argc++;
#endif
/* Main arguments. */
/* Normal arguments. */
for (i = 1; i < argc; i++)
size += ALIGN_UP (grub_strlen (argv[i]) + 1, 4);
-#ifdef LOONGSON_MACHTYPE
- size += ALIGN_UP (sizeof (LOONGSON_MACHTYPE), 4);
+#ifdef GRUB_MACHINE_MIPS_LOONGSON
+ size += ALIGN_UP (sizeof (loongson_machtypes[0]), 4);
#endif
/* rd arguments. */
+ ALIGN_UP (sizeof ("highmemsize=XXXXXXXXXXXXXXXXXXXX"), 4)
+ ALIGN_UP (sizeof ("busclock=XXXXXXXXXX"), 4)
+ ALIGN_UP (sizeof ("cpuclock=XXXXXXXXXX"), 4);
+#endif
if (grub_elf_is_elf32 (elf))
err = grub_linux_load32 (elf, &extra, size);
if (err)
return err;
+#ifdef GRUB_MACHINE_MIPS_QEMU_MIPS
+ /* Create kernel command line. */
+ size = grub_loader_cmdline_size(argc, argv);
+ params = grub_malloc (size + sizeof (LINUX_IMAGE));
+ if (! params)
+ {
+ grub_linux_unload ();
+ return grub_errno;
+ }
+
+ grub_memcpy (params, LINUX_IMAGE, sizeof (LINUX_IMAGE));
+ grub_create_loader_cmdline (argc, argv, params + sizeof (LINUX_IMAGE) - 1,
+ size);
+#else
linux_argv = extra;
argv_off = (grub_uint8_t *) linux_argv - (grub_uint8_t *) playground;
extra = linux_argv + (linux_argc + 1 + 2);
linux_argv++;
linux_args += ALIGN_UP (sizeof ("a0"), 4);
-#ifdef LOONGSON_MACHTYPE
- /* In Loongson platform, it is the responsibility of the bootloader/firmware
- to supply the OS kernel with machine type information. */
- grub_memcpy (linux_args, LOONGSON_MACHTYPE, sizeof (LOONGSON_MACHTYPE));
- *linux_argv = (grub_uint8_t *) linux_args - (grub_uint8_t *) playground
- + target_addr;
- linux_argv++;
- linux_args += ALIGN_UP (sizeof (LOONGSON_MACHTYPE), 4);
+#ifdef GRUB_MACHINE_MIPS_LOONGSON
+ {
+ unsigned mtype = grub_arch_machine;
+ if (mtype >= ARRAY_SIZE (loongson_machtypes))
+ mtype = 0;
+ /* In Loongson platform, it is the responsibility of the bootloader/firmware
+ to supply the OS kernel with machine type information. */
+ grub_memcpy (linux_args, loongson_machtypes[mtype],
+ sizeof (loongson_machtypes[mtype]));
+ *linux_argv = (grub_uint8_t *) linux_args - (grub_uint8_t *) playground
+ + target_addr;
+ linux_argv++;
+ linux_args += ALIGN_UP (sizeof (loongson_machtypes[mtype]), 4);
+ }
#endif
for (i = 1; i < argc; i++)
extra = linux_args;
+#ifdef GRUB_MACHINE_MIPS_LOONGSON
linux_envp = extra;
envp_off = (grub_uint8_t *) linux_envp - (grub_uint8_t *) playground;
linux_envs = (char *) (linux_envp + 5);
+ target_addr;
linux_envs += ALIGN_UP (grub_strlen (linux_envs) + 1, 4);
-
linux_envp[4] = 0;
+#endif
+#endif
grub_loader_set (grub_linux_boot, grub_linux_unload, 1);
initrd_loaded = 0;
return grub_errno;
}
+#ifdef GRUB_MACHINE_MIPS_QEMU_MIPS
+ {
+ char *tmp;
+ tmp = grub_xasprintf ("%s rd_start=0x%" PRIxGRUB_ADDR
+ " rd_size=0x%" PRIxGRUB_ADDR, params,
+ initrd_dest, size);
+ if (!tmp)
+ {
+ grub_file_close (file);
+ return grub_errno;
+ }
+ grub_free (params);
+ params = tmp;
+ }
+#else
grub_snprintf ((char *) playground + rd_addr_arg_off,
sizeof ("rd_start=0xXXXXXXXXXXXXXXXX"), "rd_start=0x%llx",
(unsigned long long) initrd_dest);
((grub_uint32_t *) (playground + argv_off))[linux_argc]
= target_addr + rd_size_arg_off;
linux_argc++;
+#endif
initrd_loaded = 1;
#include <grub/memory.h>
#include <grub/i18n.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
#ifdef GRUB_MACHINE_EFI
#include <grub/efi/efi.h>
#endif
# define ELFCLASSXX ELFCLASS32
# define Elf_Ehdr Elf32_Ehdr
# define Elf_Phdr Elf32_Phdr
+# define Elf_Shdr Elf32_Shdr
#elif defined(MULTIBOOT_LOAD_ELF64)
# define XX 64
# define E_MACHINE MULTIBOOT_ELF64_MACHINE
# define ELFCLASSXX ELFCLASS64
# define Elf_Ehdr Elf64_Ehdr
# define Elf_Phdr Elf64_Phdr
+# define Elf_Shdr Elf64_Shdr
#else
#error "I'm confused"
#endif
#undef ELFCLASSXX
#undef Elf_Ehdr
#undef Elf_Phdr
+#undef Elf_Shdr
#include <grub/memory.h>
#include <grub/lib/cmdline.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
#define ELF32_LOADMASK (0xc0000000UL)
#define ELF64_LOADMASK (0xc000000000000000ULL)
#include <grub/memory.h>
#include <grub/lib/cmdline.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
static grub_dl_t my_mod;
static int loaded;
#include <grub/env.h>
#include <grub/i18n.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
#if defined (__i386) && !defined (GRUB_MACHINE_EFI)
#include <grub/autoefi.h>
#endif
--- /dev/null
+/* Compute amount of lower and upper memory till the first hole. */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2009 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/memory.h>
+#include <grub/mm.h>
+#include <grub/misc.h>
+#include <grub/cpu/memory.h>
+
+grub_uint64_t
+grub_mmap_get_lower (void)
+{
+ grub_uint64_t lower = 0;
+
+ auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t,
+ grub_memory_type_t);
+ int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t size,
+ grub_memory_type_t type)
+ {
+ if (type != GRUB_MEMORY_AVAILABLE)
+ return 0;
+ if (addr == 0)
+ lower = size;
+ return 0;
+ }
+
+ grub_mmap_iterate (hook);
+ if (lower > GRUB_ARCH_LOWMEMMAXSIZE)
+ lower = GRUB_ARCH_LOWMEMMAXSIZE;
+ return lower;
+}
+
+grub_uint64_t
+grub_mmap_get_upper (void)
+{
+ grub_uint64_t upper = 0;
+
+ auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t,
+ grub_memory_type_t);
+ int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t size,
+ grub_memory_type_t type)
+ {
+ if (type != GRUB_MEMORY_AVAILABLE)
+ return 0;
+ if (addr <= GRUB_ARCH_HIGHMEMPSTART && addr + size
+ > GRUB_ARCH_HIGHMEMPSTART)
+ upper = addr + size - GRUB_ARCH_HIGHMEMPSTART;
+ return 0;
+ }
+
+ grub_mmap_iterate (hook);
+ return upper;
+}
+++ /dev/null
-/* Compute amount of lower and upper memory till the first hole. */
-/*
- * GRUB -- GRand Unified Bootloader
- * Copyright (C) 2009 Free Software Foundation, Inc.
- *
- * GRUB is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * GRUB is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <grub/memory.h>
-#include <grub/mm.h>
-#include <grub/misc.h>
-#include <grub/machine/memory.h>
-
-grub_uint64_t
-grub_mmap_get_lower (void)
-{
- grub_uint64_t lower = 0;
-
- auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t,
- grub_memory_type_t);
- int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t size,
- grub_memory_type_t type)
- {
- if (type != GRUB_MEMORY_AVAILABLE)
- return 0;
- if (addr == 0)
- lower = size;
- return 0;
- }
-
- grub_mmap_iterate (hook);
- if (lower > GRUB_ARCH_LOWMEMMAXSIZE)
- lower = GRUB_ARCH_LOWMEMMAXSIZE;
- return lower;
-}
-
-grub_uint64_t
-grub_mmap_get_upper (void)
-{
- grub_uint64_t upper = 0;
-
- auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t,
- grub_memory_type_t);
- int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t size,
- grub_memory_type_t type)
- {
- if (type != GRUB_MEMORY_AVAILABLE)
- return 0;
- if (addr <= GRUB_ARCH_HIGHMEMPSTART && addr + size
- > GRUB_ARCH_HIGHMEMPSTART)
- upper = addr + size - GRUB_ARCH_HIGHMEMPSTART;
- return 0;
- }
-
- grub_mmap_iterate (hook);
- return upper;
-}
#include <grub/dl.h>
#include <grub/i18n.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
#ifndef GRUB_MMAP_REGISTER_BY_FIRMWARE
struct grub_mmap_region *grub_mmap_overlays = 0;
--- /dev/null
+#!/bin/sh
+
+grub_modinfo_target_cpu=@target_cpu@
+grub_modinfo_platform=@platform@
--- /dev/null
+#include <grub/net/arp.h>
+#include <grub/net/netbuff.h>
+#include <grub/mm.h>
+#include <grub/net.h>
+#include <grub/net/ethernet.h>
+#include <grub/net/ip.h>
+#include <grub/time.h>
+
+static struct arp_entry arp_table[10];
+static grub_int8_t new_table_entry = -1;
+
+static void
+arp_init_table (void)
+{
+ grub_memset (arp_table, 0, sizeof (arp_table));
+ new_table_entry = 0;
+}
+
+static struct arp_entry *
+arp_find_entry (const grub_net_network_level_address_t *proto)
+{
+ unsigned i;
+ for (i = 0; i < ARRAY_SIZE (arp_table); i++)
+ {
+ if (arp_table[i].avail == 1 &&
+ arp_table[i].nl_address.ipv4 == proto->ipv4)
+ return &(arp_table[i]);
+ }
+ return NULL;
+}
+
+grub_err_t
+grub_net_arp_resolve (struct grub_net_network_level_interface *inf,
+ const grub_net_network_level_address_t *proto_addr,
+ grub_net_link_level_address_t *hw_addr)
+{
+ struct arp_entry *entry;
+ struct grub_net_buff nb;
+ struct arphdr *arp_header;
+ grub_net_link_level_address_t target_hw_addr;
+ char *aux, arp_data[128];
+ grub_err_t err;
+ int i;
+
+ if (proto_addr->type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4
+ && proto_addr->ipv4 == 0xffffffff)
+ {
+ hw_addr->type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET;
+ grub_memset (hw_addr->mac, -1, 6);
+ return GRUB_ERR_NONE;
+ }
+
+ /* Check cache table. */
+ entry = arp_find_entry (proto_addr);
+ if (entry)
+ {
+ *hw_addr = entry->ll_address;
+ return GRUB_ERR_NONE;
+ }
+ /* Build a request packet. */
+ nb.head = arp_data;
+ nb.end = arp_data + sizeof (arp_data);
+ grub_netbuff_clear (&nb);
+ grub_netbuff_reserve (&nb, 128);
+
+ err = grub_netbuff_push (&nb, sizeof (*arp_header) + 2 * (6 + 4));
+ if (err)
+ return err;
+
+ arp_header = (struct arphdr *) nb.data;
+ arp_header->hrd = grub_cpu_to_be16 (GRUB_NET_ARPHRD_ETHERNET);
+ arp_header->pro = grub_cpu_to_be16 (GRUB_NET_ETHERTYPE_IP);
+ /* FIXME Add support to ipv6 address. */
+ arp_header->hln = 6;
+ arp_header->pln = 4;
+ arp_header->op = grub_cpu_to_be16 (ARP_REQUEST);
+ aux = (char *) arp_header + sizeof (*arp_header);
+ /* Sender hardware address. */
+ grub_memcpy (aux, &inf->hwaddress.mac, 6);
+
+ aux += 6;
+ /* Sender protocol address */
+ grub_memcpy (aux, &inf->address.ipv4, 4);
+ aux += 4;
+ /* Target hardware address */
+ for (i = 0; i < 6; i++)
+ aux[i] = 0x00;
+ aux += 6;
+ /* Target protocol address */
+ grub_memcpy (aux, &proto_addr->ipv4, 4);
+ grub_memset (&target_hw_addr.mac, 0xff, 6);
+
+ send_ethernet_packet (inf, &nb, target_hw_addr, GRUB_NET_ETHERTYPE_ARP);
+ for (i = 0; i < 3; i++)
+ {
+ entry = arp_find_entry (proto_addr);
+ if (entry)
+ {
+ grub_memcpy (hw_addr, &entry->ll_address, sizeof (*hw_addr));
+ return GRUB_ERR_NONE;
+ }
+ grub_net_poll_cards (200);
+ }
+
+ return grub_error (GRUB_ERR_TIMEOUT, "timeout: could not resolve hardware address");
+}
+
+grub_err_t
+grub_net_arp_receive (struct grub_net_buff *nb)
+{
+ struct arphdr *arp_header = (struct arphdr *) nb->data;
+ struct arp_entry *entry;
+ grub_uint8_t *sender_hardware_address, *sender_protocol_address;
+ grub_uint8_t *target_hardware_address, *target_protocol_address;
+ grub_net_network_level_address_t hwaddress;
+ struct grub_net_network_level_interface *inf;
+
+ sender_hardware_address =
+ (grub_uint8_t *) arp_header + sizeof (*arp_header);
+ sender_protocol_address = sender_hardware_address + arp_header->hln;
+ target_hardware_address = sender_protocol_address + arp_header->pln;
+ target_protocol_address = target_hardware_address + arp_header->hln;
+ grub_memcpy (&hwaddress.ipv4, sender_protocol_address, 4);
+
+ /* Check if the sender is in the cache table. */
+ entry = arp_find_entry (&hwaddress);
+ /* Update sender hardware address. */
+ if (entry)
+ grub_memcpy (entry->ll_address.mac, sender_hardware_address, 6);
+ else
+ {
+ /* Add sender to cache table. */
+ if (new_table_entry == -1)
+ arp_init_table ();
+ entry = &(arp_table[new_table_entry]);
+ entry->avail = 1;
+ grub_memcpy (&entry->nl_address.ipv4, sender_protocol_address, 4);
+ grub_memcpy (entry->ll_address.mac, sender_hardware_address, 6);
+ new_table_entry++;
+ if (new_table_entry == ARRAY_SIZE (arp_table))
+ new_table_entry = 0;
+ }
+
+ FOR_NET_NETWORK_LEVEL_INTERFACES (inf)
+ {
+ /* Am I the protocol address target? */
+ if (inf->address.type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4
+ && grub_memcmp (target_protocol_address, &inf->address.ipv4, 4) == 0
+ && grub_be_to_cpu16 (arp_header->op) == ARP_REQUEST)
+ {
+ grub_net_link_level_address_t aux;
+ /* Swap hardware fields */
+ grub_memcpy (target_hardware_address, sender_hardware_address,
+ arp_header->hln);
+ grub_memcpy (sender_hardware_address, inf->hwaddress.mac, 6);
+ grub_memcpy (aux.mac, sender_protocol_address, 6);
+ grub_memcpy (sender_protocol_address, target_protocol_address,
+ arp_header->pln);
+ grub_memcpy (target_protocol_address, aux.mac, arp_header->pln);
+ /* Change operation to REPLY and send packet */
+ arp_header->op = grub_be_to_cpu16 (ARP_REPLY);
+ grub_memcpy (aux.mac, target_hardware_address, 6);
+ send_ethernet_packet (inf, nb, aux, GRUB_NET_ETHERTYPE_ARP);
+ }
+ }
+ return GRUB_ERR_NONE;
+}
--- /dev/null
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2010,2011 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/net.h>
+#include <grub/env.h>
+#include <grub/i18n.h>
+#include <grub/command.h>
+#include <grub/net/ip.h>
+#include <grub/net/netbuff.h>
+#include <grub/net/udp.h>
+#include <grub/datetime.h>
+
+static char *
+grub_env_write_readonly (struct grub_env_var *var __attribute__ ((unused)),
+ const char *val __attribute__ ((unused)))
+{
+ return NULL;
+}
+
+static void
+set_env_limn_ro (const char *intername, const char *suffix,
+ char *value, grub_size_t len)
+{
+ char c;
+ char varname[sizeof ("net_") + grub_strlen (intername) + sizeof ("_")
+ + grub_strlen (suffix)];
+ grub_snprintf (varname, sizeof (varname), "net_%s_%s", intername, suffix);
+ c = value[len];
+ value[len] = 0;
+ grub_env_set (varname, value);
+ value[len] = c;
+ grub_register_variable_hook (varname, 0, grub_env_write_readonly);
+}
+
+static void
+parse_dhcp_vendor (const char *name, void *vend, int limit)
+{
+ grub_uint8_t *ptr, *ptr0;
+
+ ptr = ptr0 = vend;
+
+ if (ptr[0] != GRUB_NET_BOOTP_RFC1048_MAGIC_0
+ || ptr[1] != GRUB_NET_BOOTP_RFC1048_MAGIC_1
+ || ptr[2] != GRUB_NET_BOOTP_RFC1048_MAGIC_2
+ || ptr[3] != GRUB_NET_BOOTP_RFC1048_MAGIC_3)
+ return;
+ ptr = ptr + sizeof (grub_uint32_t);
+ while (ptr - ptr0 < limit)
+ {
+ grub_uint8_t tagtype;
+ grub_uint8_t taglength;
+
+ tagtype = *ptr++;
+
+ /* Pad tag. */
+ if (tagtype == 0)
+ continue;
+
+ /* End tag. */
+ if (tagtype == 0xff)
+ return;
+
+ taglength = *ptr++;
+
+ switch (tagtype)
+ {
+ case 12:
+ set_env_limn_ro (name, "hostname", (char *) ptr, taglength);
+ break;
+
+ case 15:
+ set_env_limn_ro (name, "domain", (char *) ptr, taglength);
+ break;
+
+ case 17:
+ set_env_limn_ro (name, "rootpath", (char *) ptr, taglength);
+ break;
+
+ case 18:
+ set_env_limn_ro (name, "extensionspath", (char *) ptr, taglength);
+ break;
+
+ /* If you need any other options please contact GRUB
+ developpement team. */
+ }
+
+ ptr += taglength;
+ }
+}
+
+#define OFFSET_OF(x, y) ((grub_uint8_t *)((y)->x) - (grub_uint8_t *)(y))
+
+struct grub_net_network_level_interface *
+grub_net_configure_by_dhcp_ack (const char *name,
+ struct grub_net_card *card,
+ grub_net_interface_flags_t flags,
+ const struct grub_net_bootp_packet *bp,
+ grub_size_t size,
+ int is_def, char **device, char **path)
+{
+ grub_net_network_level_address_t addr;
+ grub_net_link_level_address_t hwaddr;
+ struct grub_net_network_level_interface *inter;
+
+ addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4;
+ addr.ipv4 = bp->your_ip;
+
+ if (device)
+ *device = 0;
+ if (path)
+ *path = 0;
+
+ grub_memcpy (hwaddr.mac, bp->mac_addr,
+ bp->hw_len < sizeof (hwaddr.mac) ? bp->hw_len
+ : sizeof (hwaddr.mac));
+ hwaddr.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET;
+
+ inter = grub_net_add_addr (name, card, addr, hwaddr, flags);
+ {
+ grub_net_network_level_netaddress_t target;
+ grub_net_network_level_address_t gw;
+ char rname[grub_strlen (name) + sizeof ("_gw")];
+
+ target.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4;
+ target.ipv4.base = bp->server_ip;
+ target.ipv4.masksize = 32;
+ gw.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4;
+ gw.ipv4 = bp->gateway_ip;
+ grub_snprintf (rname, sizeof (rname), "%s_gw", name);
+ grub_net_add_route_gw (rname, target, gw);
+ }
+ {
+ grub_net_network_level_netaddress_t target;
+ target.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4;
+ target.ipv4.base = bp->gateway_ip;
+ target.ipv4.masksize = 32;
+ grub_net_add_route (name, target, inter);
+ }
+
+ if (size > OFFSET_OF (boot_file, bp))
+ set_env_limn_ro (name, "boot_file", (char *) bp->boot_file,
+ sizeof (bp->boot_file));
+ if (is_def)
+ grub_net_default_server = 0;
+ if (size > OFFSET_OF (server_name, bp)
+ && bp->server_name[0])
+ {
+ set_env_limn_ro (name, "dhcp_server_name", (char *) bp->server_name,
+ sizeof (bp->server_name));
+ if (is_def && !grub_net_default_server)
+ {
+ grub_net_default_server = grub_strdup (bp->server_name);
+ grub_print_error ();
+ }
+ if (device && !*device)
+ {
+ *device = grub_xasprintf ("tftp,%s", bp->server_name);
+ grub_print_error ();
+ }
+ }
+ if (is_def && !grub_net_default_server)
+ {
+ grub_net_default_server = grub_xasprintf ("%d.%d.%d.%d",
+ ((grub_uint8_t *) &bp->server_ip)[0],
+ ((grub_uint8_t *) &bp->server_ip)[1],
+ ((grub_uint8_t *) &bp->server_ip)[2],
+ ((grub_uint8_t *) &bp->server_ip)[3]);
+ grub_print_error ();
+ }
+
+ if (device && !*device)
+ {
+ *device = grub_xasprintf ("tftp,%d.%d.%d.%d",
+ ((grub_uint8_t *) &bp->server_ip)[0],
+ ((grub_uint8_t *) &bp->server_ip)[1],
+ ((grub_uint8_t *) &bp->server_ip)[2],
+ ((grub_uint8_t *) &bp->server_ip)[3]);
+ grub_print_error ();
+ }
+ if (size > OFFSET_OF (boot_file, bp) && path)
+ {
+ *path = grub_strndup (bp->boot_file, sizeof (bp->boot_file));
+ grub_print_error ();
+ if (*path)
+ {
+ char *slash;
+ slash = grub_strrchr (*path, '/');
+ if (slash)
+ *slash = 0;
+ else
+ **path = 0;
+ }
+ }
+ if (size > OFFSET_OF (vendor, bp))
+ parse_dhcp_vendor (name, &bp->vendor, size - OFFSET_OF (vendor, bp));
+
+ inter->dhcp_ack = grub_malloc (size);
+ if (inter->dhcp_ack)
+ {
+ grub_memcpy (inter->dhcp_ack, bp, size);
+ inter->dhcp_acklen = size;
+ }
+ else
+ grub_errno = GRUB_ERR_NONE;
+
+ return inter;
+}
+
+void
+grub_net_process_dhcp (struct grub_net_buff *nb,
+ struct grub_net_card *card)
+{
+ char *name;
+ struct grub_net_network_level_interface *inf;
+
+ name = grub_xasprintf ("%s:dhcp", card->name);
+ if (!name)
+ {
+ grub_print_error ();
+ return;
+ }
+ grub_net_configure_by_dhcp_ack (name, card,
+ 0, (const struct grub_net_bootp_packet *) nb->data,
+ (nb->tail - nb->data), 0, 0, 0);
+ grub_free (name);
+ if (grub_errno)
+ grub_print_error ();
+ else
+ {
+ FOR_NET_NETWORK_LEVEL_INTERFACES(inf)
+ if (grub_memcmp (inf->name, card->name, grub_strlen (card->name)) == 0
+ && grub_memcmp (inf->name + grub_strlen (card->name),
+ ":dhcp_tmp", sizeof (":dhcp_tmp") - 1) == 0)
+ {
+ grub_net_network_level_interface_unregister (inf);
+ break;
+ }
+ }
+}
+
+static char
+hexdigit (grub_uint8_t val)
+{
+ if (val < 10)
+ return val + '0';
+ return val + 'a' - 10;
+}
+
+static grub_err_t
+grub_cmd_dhcpopt (struct grub_command *cmd __attribute__ ((unused)),
+ int argc, char **args)
+{
+ struct grub_net_network_level_interface *inter;
+ int num;
+ grub_uint8_t *ptr;
+ grub_uint8_t taglength;
+
+ if (argc < 4)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "4 arguments expected");
+
+ FOR_NET_NETWORK_LEVEL_INTERFACES (inter)
+ if (grub_strcmp (inter->name, args[1]) == 0)
+ break;
+
+ if (!inter)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
+ N_("unrecognised interface %s"), args[1]);
+
+ if (!inter->dhcp_ack)
+ return grub_error (GRUB_ERR_IO, N_("no DHCP info found"));
+
+ if (inter->dhcp_acklen <= OFFSET_OF (vendor, inter->dhcp_ack))
+ return grub_error (GRUB_ERR_IO, N_("no DHCP options found"));
+
+ num = grub_strtoul (args[2], 0, 0);
+ if (grub_errno)
+ return grub_errno;
+
+ ptr = inter->dhcp_ack->vendor;
+
+ if (ptr[0] != GRUB_NET_BOOTP_RFC1048_MAGIC_0
+ || ptr[1] != GRUB_NET_BOOTP_RFC1048_MAGIC_1
+ || ptr[2] != GRUB_NET_BOOTP_RFC1048_MAGIC_2
+ || ptr[3] != GRUB_NET_BOOTP_RFC1048_MAGIC_3)
+ return grub_error (GRUB_ERR_IO, N_("no DHCP options found"));
+ ptr = ptr + sizeof (grub_uint32_t);
+ while (1)
+ {
+ grub_uint8_t tagtype;
+
+ if (ptr >= ((grub_uint8_t *) inter->dhcp_ack) + inter->dhcp_acklen)
+ return grub_error (GRUB_ERR_IO, N_("no DHCP option %d found"), num);
+
+ tagtype = *ptr++;
+
+ /* Pad tag. */
+ if (tagtype == 0)
+ continue;
+
+ /* End tag. */
+ if (tagtype == 0xff)
+ return grub_error (GRUB_ERR_IO, N_("no DHCP option %d found"), num);
+
+ taglength = *ptr++;
+
+ if (tagtype == num)
+ break;
+ ptr += taglength;
+ }
+
+ if (grub_strcmp (args[3], "string") == 0)
+ {
+ char *val = grub_malloc (taglength + 1);
+ if (!val)
+ return grub_errno;
+ grub_memcpy (val, ptr, taglength);
+ val[taglength] = 0;
+ if (args[0][0] == '-' && args[0][1] == 0)
+ grub_printf ("%s\n", val);
+ else
+ return grub_env_set (args[0], val);
+ return GRUB_ERR_NONE;
+ }
+
+ if (grub_strcmp (args[3], "number") == 0)
+ {
+ grub_uint64_t val = 0;
+ int i;
+ for (i = 0; i < taglength; i++)
+ val = (val << 8) | ptr[i];
+ if (args[0][0] == '-' && args[0][1] == 0)
+ grub_printf ("%llu\n", (unsigned long long) val);
+ else
+ {
+ char valn[64];
+ grub_printf (valn, sizeof (valn), "%lld\n", (unsigned long long) val);
+ return grub_env_set (args[0], valn);
+ }
+ return GRUB_ERR_NONE;
+ }
+
+ if (grub_strcmp (args[3], "hex") == 0)
+ {
+ char *val = grub_malloc (2 * taglength + 1);
+ int i;
+ if (!val)
+ return grub_errno;
+ for (i = 0; i < taglength; i++)
+ {
+ val[2 * i] = hexdigit (ptr[i] >> 4);
+ val[2 * i + 1] = hexdigit (ptr[i] & 0xf);
+ }
+ val[2 * taglength] = 0;
+ if (args[0][0] == '-' && args[0][1] == 0)
+ grub_printf ("%s\n", val);
+ else
+ return grub_env_set (args[0], val);
+ return GRUB_ERR_NONE;
+ }
+
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
+ "unrecognised format specification %s", args[3]);
+}
+
+static grub_err_t
+grub_cmd_bootp (struct grub_command *cmd __attribute__ ((unused)),
+ int argc, char **args)
+{
+ struct grub_net_card *card;
+ struct grub_net_network_level_interface *ifaces;
+ grub_size_t ncards = 0;
+ unsigned j = 0;
+ int interval;
+ grub_err_t err;
+
+ FOR_NET_CARDS (card)
+ {
+ if (argc > 0 && grub_strcmp (card->name, args[0]) != 0)
+ continue;
+ ncards++;
+ }
+
+ ifaces = grub_zalloc (ncards * sizeof (ifaces[0]));
+ if (!ifaces)
+ return grub_errno;
+
+ j = 0;
+ FOR_NET_CARDS (card)
+ {
+ if (argc > 0 && grub_strcmp (card->name, args[0]) != 0)
+ continue;
+ ifaces[j].card = card;
+ ifaces[j].next = &ifaces[j+1];
+ if (j)
+ ifaces[j].prev = &ifaces[j-1].next;
+ ifaces[j].name = grub_xasprintf ("%s:dhcp_tmp", card->name);
+ card->num_ifaces++;
+ if (!ifaces[j].name)
+ {
+ unsigned i;
+ for (i = 0; i < j; i++)
+ grub_free (ifaces[i].name);
+ grub_free (ifaces);
+ return grub_errno;
+ }
+ ifaces[j].address.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_DHCP_RECV;
+ grub_memcpy (&ifaces[j].hwaddress, &card->default_address,
+ sizeof (ifaces[j].hwaddress));
+ j++;
+ }
+ ifaces[ncards - 1].next = grub_net_network_level_interfaces;
+ if (grub_net_network_level_interfaces)
+ grub_net_network_level_interfaces->prev = & ifaces[ncards - 1].next;
+ grub_net_network_level_interfaces = &ifaces[0];
+ ifaces[0].prev = &grub_net_network_level_interfaces;
+ for (interval = 200; interval < 10000; interval *= 2)
+ {
+ int done = 0;
+ for (j = 0; j < ncards; j++)
+ {
+ struct grub_net_bootp_packet *pack;
+ struct grub_datetime date;
+ grub_int32_t t;
+ struct grub_net_buff *nb;
+ struct udphdr *udph;
+ grub_net_network_level_address_t target;
+
+ if (!ifaces[j].prev)
+ continue;
+ nb = grub_netbuff_alloc (sizeof (*pack));
+ if (!nb)
+ {
+ grub_netbuff_free (nb);
+ return grub_errno;
+ }
+ err = grub_netbuff_reserve (nb, sizeof (*pack) + 64 + 128);
+ if (err)
+ {
+ grub_netbuff_free (nb);
+ return err;
+ }
+ err = grub_netbuff_push (nb, sizeof (*pack) + 64);
+ if (err)
+ {
+ grub_netbuff_free (nb);
+ return err;
+ }
+ pack = (void *) nb->data;
+ done = 1;
+ grub_memset (pack, 0, sizeof (*pack) + 64);
+ pack->opcode = 1;
+ pack->hw_type = 1;
+ pack->hw_len = 6;
+ err = grub_get_datetime (&date);
+ if (err || !grub_datetime2unixtime (&date, &t))
+ {
+ grub_errno = GRUB_ERR_NONE;
+ t = 0;
+ }
+ pack->ident = grub_cpu_to_be32 (t);
+ pack->seconds = 0;//grub_cpu_to_be16 (t);
+
+ grub_memcpy (&pack->mac_addr, &ifaces[j].hwaddress.mac, 6);
+
+ grub_netbuff_push (nb, sizeof (*udph));
+
+ udph = (struct udphdr *) nb->data;
+ udph->src = grub_cpu_to_be16 (68);
+ udph->dst = grub_cpu_to_be16 (67);
+ udph->chksum = 0;
+ udph->len = grub_cpu_to_be16 (nb->tail - nb->data);
+
+ target.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4;
+ target.ipv4 = 0xffffffff;
+
+ err = grub_net_send_ip_packet (&ifaces[j], &target, nb);
+ grub_netbuff_free (nb);
+ if (err)
+ return err;
+ }
+ if (!done)
+ break;
+ grub_net_poll_cards (interval);
+ }
+
+ err = GRUB_ERR_NONE;
+ for (j = 0; j < ncards; j++)
+ {
+ grub_free (ifaces[j].name);
+ if (!ifaces[j].prev)
+ continue;
+ grub_error_push ();
+ grub_net_network_level_interface_unregister (&ifaces[j]);
+ err = grub_error (GRUB_ERR_FILE_NOT_FOUND, "couldn't configure %s",
+ ifaces[j].card->name);
+ }
+
+ grub_free (ifaces);
+ return err;
+}
+
+static grub_command_t cmd_dhcp, cmd_getdhcp, cmd_bootp;
+
+void
+grub_bootp_init (void)
+{
+ cmd_bootp = grub_register_command ("net_bootp", grub_cmd_bootp,
+ "[CARD]",
+ N_("perform a bootp autoconfiguration"));
+ cmd_dhcp = grub_register_command ("net_dhcp", grub_cmd_bootp,
+ "[CARD]",
+ N_("perform a bootp autoconfiguration"));
+ cmd_getdhcp = grub_register_command ("net_get_dhcp_option", grub_cmd_dhcpopt,
+ N_("VAR INTERFACE NUMBER DESCRIPTION"),
+ N_("retrieve DHCP option and save it into VAR. If VAR is - then print the value."));
+}
+
+void
+grub_bootp_fini (void)
+{
+ grub_unregister_command (cmd_getdhcp);
+ grub_unregister_command (cmd_dhcp);
+ grub_unregister_command (cmd_bootp);
+}
--- /dev/null
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2010,2011 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/net/netbuff.h>
+#include <grub/dl.h>
+#include <grub/net.h>
+#include <grub/time.h>
+#include <grub/efi/api.h>
+#include <grub/efi/efi.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
+
+/* GUID. */
+static grub_efi_guid_t net_io_guid = GRUB_EFI_SIMPLE_NETWORK_GUID;
+static grub_efi_guid_t pxe_io_guid = GRUB_EFI_PXE_GUID;
+
+static grub_err_t
+send_card_buffer (const struct grub_net_card *dev,
+ struct grub_net_buff *pack)
+{
+ grub_efi_status_t st;
+ grub_efi_simple_network_t *net = dev->efi_net;
+ st = efi_call_7 (net->transmit, net, 0, (pack->tail - pack->data),
+ pack->data, NULL, NULL, NULL);
+ if (st != GRUB_EFI_SUCCESS)
+ return grub_error (GRUB_ERR_IO, "Couldn't send network packet.");
+ return GRUB_ERR_NONE;
+}
+
+static grub_ssize_t
+get_card_packet (const struct grub_net_card *dev,
+ struct grub_net_buff *nb)
+{
+ grub_efi_simple_network_t *net = dev->efi_net;
+ grub_err_t err;
+ grub_efi_status_t st;
+ grub_efi_uintn_t bufsize = 1500;
+
+ err = grub_netbuff_clear (nb);
+ if (err)
+ return -1;
+
+ err = grub_netbuff_put (nb, 1500);
+ if (err)
+ return -1;
+
+ st = efi_call_7 (net->receive, net, NULL, &bufsize,
+ nb->data, NULL, NULL, NULL);
+ if (st == GRUB_EFI_BUFFER_TOO_SMALL)
+ {
+ err = grub_netbuff_put (nb, bufsize - 1500);
+ if (err)
+ return -1;
+ st = efi_call_7 (net->receive, net, NULL, &bufsize,
+ nb->data, NULL, NULL, NULL);
+ }
+ if (st != GRUB_EFI_SUCCESS)
+ {
+ grub_netbuff_clear (nb);
+ return -1;
+ }
+ err = grub_netbuff_unput (nb, (nb->tail - nb->data) - bufsize);
+ if (err)
+ return -1;
+
+ return bufsize;
+}
+
+static struct grub_net_card_driver efidriver =
+ {
+ .name = "efinet",
+ .send = send_card_buffer,
+ .recv = get_card_packet
+ };
+
+
+static void
+grub_efinet_findcards (void)
+{
+ grub_efi_uintn_t num_handles;
+ grub_efi_handle_t *handles;
+ grub_efi_handle_t *handle;
+ int i = 0;
+
+ /* Find handles which support the disk io interface. */
+ handles = grub_efi_locate_handle (GRUB_EFI_BY_PROTOCOL, &net_io_guid,
+ 0, &num_handles);
+ if (! handles)
+ return;
+ for (handle = handles; num_handles--; handle++)
+ {
+ grub_efi_simple_network_t *net;
+ struct grub_net_card *card;
+
+ net = grub_efi_open_protocol (*handle, &net_io_guid,
+ GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+ if (! net)
+ /* This should not happen... Why? */
+ continue;
+
+ if (net->mode->state == GRUB_EFI_NETWORK_STOPPED
+ && efi_call_1 (net->start, net) != GRUB_EFI_SUCCESS)
+ continue;
+
+ if (net->mode->state == GRUB_EFI_NETWORK_STOPPED)
+ continue;
+
+ if (net->mode->state == GRUB_EFI_NETWORK_STARTED
+ && efi_call_3 (net->initialize, net, 0, 0) != GRUB_EFI_SUCCESS)
+ continue;
+
+ card = grub_zalloc (sizeof (struct grub_net_card));
+ if (!card)
+ {
+ grub_print_error ();
+ grub_free (handles);
+ return;
+ }
+
+ card->name = grub_xasprintf ("efinet%d", i++);
+ card->driver = &efidriver;
+ card->flags = 0;
+ card->default_address.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET;
+ grub_memcpy (card->default_address.mac,
+ net->mode->current_address,
+ sizeof (card->default_address.mac));
+ card->efi_net = net;
+ card->efi_handle = *handle;
+
+ grub_net_card_register (card);
+ }
+ grub_free (handles);
+}
+
+static void
+grub_efi_net_config_real (grub_efi_handle_t hnd, char **device,
+ char **path)
+{
+ struct grub_net_card *card;
+ grub_efi_device_path_t *dp;
+
+ dp = grub_efi_get_device_path (hnd);
+ if (! dp)
+ return;
+
+ FOR_NET_CARDS (card)
+ {
+ grub_efi_device_path_t *cdp;
+ struct grub_efi_pxe *pxe;
+ struct grub_efi_pxe_mode *pxe_mode;
+ if (card->driver != &efidriver)
+ continue;
+ cdp = grub_efi_get_device_path (card->efi_handle);
+ if (! cdp)
+ continue;
+ if (grub_efi_compare_device_paths (dp, cdp) != 0)
+ continue;
+ pxe = grub_efi_open_protocol (hnd, &pxe_io_guid,
+ GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+ if (! pxe)
+ continue;
+ pxe_mode = pxe->mode;
+ grub_net_configure_by_dhcp_ack (card->name, card, 0,
+ (struct grub_net_bootp_packet *)
+ &pxe_mode->dhcp_ack,
+ sizeof (pxe_mode->dhcp_ack),
+ 1, device, path);
+ return;
+ }
+}
+
+GRUB_MOD_INIT(efinet)
+{
+ grub_efinet_findcards ();
+ grub_efi_net_config = grub_efi_net_config_real;
+}
+
+GRUB_MOD_FINI(efinet)
+{
+ struct grub_net_card *card, *next;
+
+ FOR_NET_CARDS_SAFE (card, next)
+ if (card->driver == &efidriver)
+ grub_net_card_unregister (card);
+}
+
--- /dev/null
+
+#include <grub/dl.h>
+#include <grub/net/netbuff.h>
+#include <sys/socket.h>
+#include <grub/net.h>
+#include <sys/types.h>
+#include <linux/if.h>
+#include <linux/if_tun.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <grub/term.h>
+
+static int fd;
+
+static grub_err_t
+send_card_buffer (const struct grub_net_card *dev __attribute__ ((unused)),
+ struct grub_net_buff *pack)
+{
+ ssize_t actual;
+
+ actual = write (fd, pack->data, pack->tail - pack->data);
+ if (actual < 0)
+ return grub_error (GRUB_ERR_IO, "couldn't send packets");
+
+ return GRUB_ERR_NONE;
+}
+
+static grub_ssize_t
+get_card_packet (const struct grub_net_card *dev __attribute__ ((unused)),
+ struct grub_net_buff *pack)
+{
+ ssize_t actual;
+
+ grub_netbuff_clear (pack);
+ actual = read (fd, pack->data, 1500);
+ if (actual < 0)
+ return -1;
+ grub_netbuff_put (pack, actual);
+
+ return actual;
+}
+
+static struct grub_net_card_driver emudriver =
+ {
+ .name = "emu",
+ .send = send_card_buffer,
+ .recv = get_card_packet
+ };
+
+static struct grub_net_card emucard =
+ {
+ .name = "emu0",
+ .driver = &emudriver,
+ .default_address = {
+ .type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET,
+ {.mac = {0, 1, 2, 3, 4, 5}}
+ },
+ .flags = 0
+ };
+
+GRUB_MOD_INIT(emunet)
+{
+ struct ifreq ifr;
+ fd = open ("/dev/net/tun", O_RDWR | O_NONBLOCK);
+ if (fd < 0)
+ return;
+ grub_memset (&ifr, 0, sizeof (ifr));
+ ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
+ if (ioctl (fd, TUNSETIFF, &ifr) < 0)
+ {
+ close (fd);
+ fd = -1;
+ return;
+ }
+ grub_net_card_register (&emucard);
+}
+
+GRUB_MOD_FINI(emunet)
+{
+ if (fd >= 0)
+ {
+ close (fd);
+ grub_net_card_unregister (&emucard);
+ }
+}
--- /dev/null
+/* pxe.c - Driver to provide access to the pxe filesystem */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2008,2009,2011 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/dl.h>
+#include <grub/net.h>
+#include <grub/mm.h>
+#include <grub/file.h>
+#include <grub/misc.h>
+#include <grub/env.h>
+
+#include <grub/machine/pxe.h>
+#include <grub/machine/int.h>
+#include <grub/machine/memory.h>
+#include <grub/machine/kernel.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
+
+#define SEGMENT(x) ((x) >> 4)
+#define OFFSET(x) ((x) & 0xF)
+#define SEGOFS(x) ((SEGMENT(x) << 16) + OFFSET(x))
+#define LINEAR(x) (void *) ((((x) >> 16) << 4) + ((x) & 0xFFFF))
+
+struct grub_pxe_undi_open
+{
+ grub_uint16_t status;
+ grub_uint16_t open_flag;
+ grub_uint16_t pkt_filter;
+ grub_uint16_t mcast_count;
+ grub_uint8_t mcast[8][6];
+} __attribute__ ((packed));
+
+struct grub_pxe_undi_info
+{
+ grub_uint16_t status;
+ grub_uint16_t base_io;
+ grub_uint16_t int_number;
+ grub_uint16_t mtu;
+ grub_uint16_t hwtype;
+ grub_uint16_t hwaddrlen;
+ grub_uint8_t current_addr[16];
+ grub_uint8_t permanent_addr[16];
+ grub_uint32_t romaddr;
+ grub_uint16_t rxbufct;
+ grub_uint16_t txbufct;
+} __attribute__ ((packed));
+
+
+struct grub_pxe_undi_isr
+{
+ grub_uint16_t status;
+ grub_uint16_t func_flag;
+ grub_uint16_t buffer_len;
+ grub_uint16_t frame_len;
+ grub_uint16_t frame_hdr_len;
+ grub_uint32_t buffer;
+ grub_uint8_t prot_type;
+ grub_uint8_t pkt_type;
+} __attribute__ ((packed));
+
+enum
+ {
+ GRUB_PXE_ISR_IN_START = 1,
+ GRUB_PXE_ISR_IN_PROCESS,
+ GRUB_PXE_ISR_IN_GET_NEXT
+ };
+
+enum
+ {
+ GRUB_PXE_ISR_OUT_OURS = 0,
+ GRUB_PXE_ISR_OUT_NOT_OURS = 1
+ };
+
+enum
+ {
+ GRUB_PXE_ISR_OUT_DONE = 0,
+ GRUB_PXE_ISR_OUT_TRANSMIT = 2,
+ GRUB_PXE_ISR_OUT_RECEIVE = 3,
+ GRUB_PXE_ISR_OUT_BUSY = 4,
+ };
+
+struct grub_pxe_undi_transmit
+{
+ grub_uint16_t status;
+ grub_uint8_t protocol;
+ grub_uint8_t xmitflag;
+ grub_uint32_t dest;
+ grub_uint32_t tbd;
+ grub_uint32_t reserved[2];
+} __attribute__ ((packed));
+
+struct grub_pxe_undi_tbd
+{
+ grub_uint16_t len;
+ grub_uint32_t buf;
+ grub_uint16_t blk_count;
+ struct
+ {
+ grub_uint8_t ptr_type;
+ grub_uint8_t reserved;
+ grub_uint16_t len;
+ grub_uint32_t ptr;
+ } blocks[8];
+} __attribute__ ((packed));
+
+struct grub_pxe_bangpxe *grub_pxe_pxenv;
+static grub_uint32_t pxe_rm_entry = 0;
+
+static struct grub_pxe_bangpxe *
+grub_pxe_scan (void)
+{
+ struct grub_bios_int_registers regs;
+ 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;
+
+ 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 (pxenv->version < 0x201)
+ return NULL;
+
+ bangpxe = (void *) ((((pxenv->pxe_ptr & 0xffff0000) >> 16) << 4)
+ + (pxenv->pxe_ptr & 0xffff));
+
+ if (!bangpxe)
+ return NULL;
+
+ if (grub_memcmp (bangpxe->signature, GRUB_PXE_BANGPXE_SIGNATURE,
+ sizeof (bangpxe->signature)) != 0)
+ return NULL;
+
+ pxe_rm_entry = bangpxe->rm_entry;
+
+ return bangpxe;
+}
+
+static grub_ssize_t
+grub_pxe_recv (const struct grub_net_card *dev __attribute__ ((unused)),
+ struct grub_net_buff *buf)
+{
+ struct grub_pxe_undi_isr *isr;
+ static int in_progress = 0;
+ char *ptr, *end;
+ int len;
+
+ isr = (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
+
+ if (!in_progress)
+ {
+ grub_memset (isr, 0, sizeof (*isr));
+ isr->func_flag = GRUB_PXE_ISR_IN_START;
+ grub_pxe_call (GRUB_PXENV_UNDI_ISR, isr, pxe_rm_entry);
+ if (isr->status || isr->func_flag != GRUB_PXE_ISR_OUT_OURS)
+ {
+ in_progress = 0;
+ return -1;
+ }
+ grub_memset (isr, 0, sizeof (*isr));
+ isr->func_flag = GRUB_PXE_ISR_IN_PROCESS;
+ grub_pxe_call (GRUB_PXENV_UNDI_ISR, isr, pxe_rm_entry);
+ }
+ else
+ {
+ grub_memset (isr, 0, sizeof (*isr));
+ isr->func_flag = GRUB_PXE_ISR_IN_GET_NEXT;
+ grub_pxe_call (GRUB_PXENV_UNDI_ISR, isr, pxe_rm_entry);
+ }
+
+ while (isr->func_flag != GRUB_PXE_ISR_OUT_RECEIVE)
+ {
+ if (isr->status || isr->func_flag == GRUB_PXE_ISR_OUT_DONE)
+ {
+ in_progress = 0;
+ return -1;
+ }
+ grub_memset (isr, 0, sizeof (*isr));
+ isr->func_flag = GRUB_PXE_ISR_IN_GET_NEXT;
+ grub_pxe_call (GRUB_PXENV_UNDI_ISR, isr, pxe_rm_entry);
+ }
+
+ grub_netbuff_put (buf, isr->frame_len);
+ ptr = buf->data;
+ end = ptr + isr->frame_len;
+ len = isr->frame_len;
+ grub_memcpy (ptr, LINEAR (isr->buffer), isr->buffer_len);
+ ptr += isr->buffer_len;
+ while (ptr < end)
+ {
+ grub_memset (isr, 0, sizeof (*isr));
+ isr->func_flag = GRUB_PXE_ISR_IN_GET_NEXT;
+ grub_pxe_call (GRUB_PXENV_UNDI_ISR, isr, pxe_rm_entry);
+ if (isr->status || isr->func_flag != GRUB_PXE_ISR_OUT_RECEIVE)
+ {
+ in_progress = 1;
+ return -1;
+ }
+
+ grub_memcpy (ptr, LINEAR (isr->buffer), isr->buffer_len);
+ ptr += isr->buffer_len;
+ }
+ in_progress = 1;
+
+ return len;
+}
+
+static grub_err_t
+grub_pxe_send (const struct grub_net_card *dev __attribute__ ((unused)),
+ struct grub_net_buff *pack)
+{
+ struct grub_pxe_undi_transmit *trans;
+ struct grub_pxe_undi_tbd *tbd;
+ char *buf;
+
+ trans = (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
+ grub_memset (trans, 0, sizeof (*trans));
+ tbd = (void *) (GRUB_MEMORY_MACHINE_SCRATCH_ADDR + 128);
+ grub_memset (tbd, 0, sizeof (*tbd));
+ buf = (void *) (GRUB_MEMORY_MACHINE_SCRATCH_ADDR + 256);
+ grub_memcpy (buf, pack->data, pack->tail - pack->data);
+
+ trans->tbd = SEGOFS ((grub_addr_t) tbd);
+ trans->protocol = 0;
+ tbd->len = pack->tail - pack->data;
+ tbd->buf = SEGOFS ((grub_addr_t) buf);
+
+ grub_pxe_call (GRUB_PXENV_UNDI_TRANSMIT, trans, pxe_rm_entry);
+ if (trans->status)
+ return grub_error (GRUB_ERR_IO, "PXE send failed (status 0x%x)",
+ trans->status);
+ return 0;
+}
+
+static void
+grub_pxe_close (const struct grub_net_card *dev __attribute__ ((unused)))
+{
+ if (pxe_rm_entry)
+ grub_pxe_call (GRUB_PXENV_UNDI_CLOSE,
+ (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR,
+ pxe_rm_entry);
+}
+
+static grub_err_t
+grub_pxe_open (const struct grub_net_card *dev __attribute__ ((unused)))
+{
+ struct grub_pxe_undi_open *ou;
+ ou = (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
+ grub_memset (ou, 0, sizeof (*ou));
+ ou->pkt_filter = 4;
+ grub_pxe_call (GRUB_PXENV_UNDI_OPEN, ou, pxe_rm_entry);
+
+ if (ou->status)
+ return grub_error (GRUB_ERR_IO, "can't open UNDI");
+ return GRUB_ERR_NONE;
+}
+
+struct grub_net_card_driver grub_pxe_card_driver =
+{
+ .open = grub_pxe_open,
+ .close = grub_pxe_close,
+ .send = grub_pxe_send,
+ .recv = grub_pxe_recv
+};
+
+struct grub_net_card grub_pxe_card =
+{
+ .driver = &grub_pxe_card_driver,
+ .name = "pxe"
+};
+
+static void
+grub_pc_net_config_real (char **device, char **path)
+{
+ struct grub_net_bootp_packet *bp;
+ struct grub_pxenv_get_cached_info ci;
+ ci.packet_type = GRUB_PXENV_PACKET_TYPE_DHCP_ACK;
+ ci.buffer = 0;
+ ci.buffer_size = 0;
+ grub_pxe_call (GRUB_PXENV_GET_CACHED_INFO, &ci, pxe_rm_entry);
+ if (ci.status)
+ return;
+
+ bp = LINEAR (ci.buffer);
+
+ grub_net_configure_by_dhcp_ack ("pxe", &grub_pxe_card, 0,
+ bp, GRUB_PXE_BOOTP_SIZE,
+ 1, device, path);
+
+}
+
+GRUB_MOD_INIT(pxe)
+{
+ struct grub_pxe_bangpxe *pxenv;
+ struct grub_pxe_undi_info *ui;
+ unsigned i;
+
+ pxenv = grub_pxe_scan ();
+ if (! pxenv)
+ return;
+
+ ui = (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
+ grub_memset (ui, 0, sizeof (*ui));
+ grub_pxe_call (GRUB_PXENV_UNDI_GET_INFORMATION, ui, pxe_rm_entry);
+
+ grub_memcpy (grub_pxe_card.default_address.mac, ui->current_addr,
+ sizeof (grub_pxe_card.default_address.mac));
+ for (i = 0; i < sizeof (grub_pxe_card.default_address.mac); i++)
+ if (grub_pxe_card.default_address.mac[i] != 0)
+ break;
+ if (i != sizeof (grub_pxe_card.default_address.mac))
+ {
+ for (i = 0; i < sizeof (grub_pxe_card.default_address.mac); i++)
+ if (grub_pxe_card.default_address.mac[i] != 0xff)
+ break;
+ }
+ if (i == sizeof (grub_pxe_card.default_address.mac))
+ grub_memcpy (grub_pxe_card.default_address.mac, ui->permanent_addr,
+ sizeof (grub_pxe_card.default_address.mac));
+
+ grub_pxe_card.default_address.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET;
+
+ grub_net_card_register (&grub_pxe_card);
+ grub_pc_net_config = grub_pc_net_config_real;
+}
+
+GRUB_MOD_FINI(pxe)
+{
+ grub_pc_net_config = 0;
+ grub_net_card_unregister (&grub_pxe_card);
+}
--- /dev/null
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2010,2011 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/net/netbuff.h>
+#include <grub/ieee1275/ieee1275.h>
+#include <grub/dl.h>
+#include <grub/net.h>
+#include <grub/time.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
+
+struct grub_ofnetcard_data
+{
+ char *path;
+ grub_ieee1275_ihandle_t handle;
+ grub_uint32_t mtu;
+};
+
+static grub_err_t
+card_open (const struct grub_net_card *dev)
+{
+ int status;
+ struct grub_ofnetcard_data *data = dev->data;
+ char path[grub_strlen (data->path) +
+ grub_strlen (":speed=auto,duplex=auto,1.1.1.1,dummy,1.1.1.1,1.1.1.1,5,5,1.1.1.1,512") + 1];
+
+ /* The full string will prevent a bootp packet to be sent. Just put some valid ip in there. */
+ grub_snprintf (path, sizeof (path), "%s%s", data->path,
+ ":speed=auto,duplex=auto,1.1.1.1,dummy,1.1.1.1,1.1.1.1,5,5,1.1.1.1,512");
+ status = grub_ieee1275_open (path, &(data->handle));
+
+ if (status)
+ return grub_error (GRUB_ERR_IO, "Couldn't open network card.");
+
+ return GRUB_ERR_NONE;
+}
+
+static void
+card_close (const struct grub_net_card *dev)
+{
+ struct grub_ofnetcard_data *data = dev->data;
+
+ if (data->handle)
+ grub_ieee1275_close (data->handle);
+}
+
+static grub_err_t
+send_card_buffer (const struct grub_net_card *dev, struct grub_net_buff *pack)
+{
+ grub_ssize_t actual;
+ int status;
+ struct grub_ofnetcard_data *data = dev->data;
+
+ status = grub_ieee1275_write (data->handle, pack->data,
+ pack->tail - pack->data, &actual);
+
+ if (status)
+ return grub_error (GRUB_ERR_IO, "Couldn't send network packet.");
+ return GRUB_ERR_NONE;
+}
+
+static grub_ssize_t
+get_card_packet (const struct grub_net_card *dev, struct grub_net_buff *nb)
+{
+ grub_ssize_t actual;
+ int rc;
+ struct grub_ofnetcard_data *data = dev->data;
+ grub_uint64_t start_time;
+
+ grub_netbuff_clear (nb);
+ start_time = grub_get_time_ms ();
+ do
+ rc = grub_ieee1275_read (data->handle, nb->data, data->mtu, &actual);
+ while ((actual <= 0 || rc < 0) && (grub_get_time_ms () - start_time < 200));
+ if (actual)
+ {
+ grub_netbuff_put (nb, actual);
+ return actual;
+ }
+ return -1;
+}
+
+static struct grub_net_card_driver ofdriver =
+ {
+ .name = "ofnet",
+ .open = card_open,
+ .close = card_close,
+ .send = send_card_buffer,
+ .recv = get_card_packet
+ };
+
+static const struct
+{
+ char *name;
+ int offset;
+}
+
+bootp_response_properties[] =
+ {
+ { .name = "bootp-response", .offset = 0},
+ { .name = "dhcp-response", .offset = 0},
+ { .name = "bootpreply-packet", .offset = 0x2a},
+ };
+
+static void
+grub_ieee1275_net_config_real (const char *devpath, char **device, char **path)
+{
+ struct grub_net_card *card;
+
+ /* FIXME: Check that it's the right card. */
+ FOR_NET_CARDS (card)
+ {
+ char *bootp_response;
+ char *cardpath;
+ char *canon;
+
+ grub_ssize_t size = -1;
+ unsigned int i;
+
+ if (card->driver != &ofdriver)
+ continue;
+
+ cardpath = ((struct grub_ofnetcard_data *) card->data)->path;
+ canon = grub_ieee1275_canonicalise_devname (cardpath);
+ if (grub_strcmp (devpath, canon) != 0)
+ {
+ grub_free (canon);
+ continue;
+ }
+ grub_free (canon);
+
+ for (i = 0; i < ARRAY_SIZE (bootp_response_properties); i++)
+ if (grub_ieee1275_get_property_length (grub_ieee1275_chosen,
+ bootp_response_properties[i].name,
+ &size) >= 0)
+ break;
+
+ if (size < 0)
+ return;
+
+ bootp_response = grub_malloc (size);
+ if (!bootp_response)
+ {
+ grub_print_error ();
+ return;
+ }
+ if (grub_ieee1275_get_property (grub_ieee1275_chosen,
+ bootp_response_properties[i].name,
+ bootp_response, size, 0) < 0)
+ return;
+
+ grub_net_configure_by_dhcp_ack (card->name, card, 0,
+ (struct grub_net_bootp_packet *)
+ &bootp_response
+ + bootp_response_properties[i].offset,
+ size - bootp_response_properties[i].offset,
+ 1, device, path);
+ return;
+ }
+}
+
+static char *
+find_alias (const char *fullname)
+{
+ char *ret = NULL;
+ auto int find_alias_hook (struct grub_ieee1275_devalias *alias);
+
+ int find_alias_hook (struct grub_ieee1275_devalias *alias)
+ {
+ if (grub_strcmp (alias->path, fullname) == 0)
+ {
+ ret = grub_strdup (alias->name);
+ return 1;
+ }
+ return 0;
+ }
+
+ grub_devalias_iterate (find_alias_hook);
+ grub_errno = GRUB_ERR_NONE;
+ return ret;
+}
+
+static void
+grub_ofnet_findcards (void)
+{
+ auto int search_net_devices (struct grub_ieee1275_devalias *alias);
+
+ int search_net_devices (struct grub_ieee1275_devalias *alias)
+ {
+ if (!grub_strcmp (alias->type, "network"))
+ {
+ struct grub_ofnetcard_data *ofdata;
+ struct grub_net_card *card;
+ grub_ieee1275_phandle_t devhandle;
+ grub_net_link_level_address_t lla;
+ char *shortname;
+
+ ofdata = grub_malloc (sizeof (struct grub_ofnetcard_data));
+ if (!ofdata)
+ {
+ grub_print_error ();
+ return 1;
+ }
+ card = grub_zalloc (sizeof (struct grub_net_card));
+ if (!card)
+ {
+ grub_free (ofdata);
+ grub_print_error ();
+ return 1;
+ }
+
+ ofdata->path = grub_strdup (alias->path);
+
+ grub_ieee1275_finddevice (ofdata->path, &devhandle);
+
+ if (grub_ieee1275_get_integer_property
+ (devhandle, "max-frame-size", &(ofdata->mtu),
+ sizeof (ofdata->mtu), 0))
+ {
+ ofdata->mtu = 1500;
+ }
+
+ if (grub_ieee1275_get_property (devhandle, "mac-address",
+ &(lla.mac), 6, 0)
+ && grub_ieee1275_get_property (devhandle, "local-mac-address",
+ &(lla.mac), 6, 0))
+ {
+ grub_error (GRUB_ERR_IO, "Couldn't retrieve mac address.");
+ grub_print_error ();
+ return 0;
+ }
+
+ lla.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET;
+ card->default_address = lla;
+
+ card->driver = NULL;
+ card->data = ofdata;
+ card->flags = 0;
+ shortname = find_alias (alias->path);
+ card->name = grub_xasprintf ("ofnet_%s", shortname ? : alias->path);
+ card->idle_poll_delay_ms = 1;
+ grub_free (shortname);
+
+ card->driver = &ofdriver;
+ grub_net_card_register (card);
+ return 0;
+ }
+ return 0;
+ }
+
+ /* Look at all nodes for devices of the type network. */
+ grub_ieee1275_devices_iterate (search_net_devices);
+}
+
+GRUB_MOD_INIT(ofnet)
+{
+ grub_ofnet_findcards ();
+ grub_ieee1275_net_config = grub_ieee1275_net_config_real;
+}
+
+GRUB_MOD_FINI(ofnet)
+{
+ struct grub_net_card *card, *next;
+
+ FOR_NET_CARDS_SAFE (card, next)
+ if (card->driver && grub_strcmp (card->driver->name, "ofnet") == 0)
+ grub_net_card_unregister (card);
+ grub_ieee1275_net_config = 0;
+}
--- /dev/null
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2010,2011 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/net/ethernet.h>
+#include <grub/net/ip.h>
+#include <grub/net/arp.h>
+#include <grub/net/netbuff.h>
+#include <grub/net.h>
+#include <grub/time.h>
+#include <grub/net/arp.h>
+
+#define LLCADDRMASK 0x7f
+
+struct etherhdr
+{
+ grub_uint8_t dst[6];
+ grub_uint8_t src[6];
+ grub_uint16_t type;
+} __attribute__ ((packed));
+
+struct llchdr
+{
+ grub_uint8_t dsap;
+ grub_uint8_t ssap;
+ grub_uint8_t ctrl;
+} __attribute__ ((packed));
+
+struct snaphdr
+{
+ grub_uint8_t oui[3];
+ grub_uint16_t type;
+} __attribute__ ((packed));
+
+grub_err_t
+send_ethernet_packet (struct grub_net_network_level_interface *inf,
+ struct grub_net_buff *nb,
+ grub_net_link_level_address_t target_addr,
+ grub_uint16_t ethertype)
+{
+ struct etherhdr *eth;
+ grub_err_t err;
+
+ err = grub_netbuff_push (nb, sizeof (*eth));
+ if (err)
+ return err;
+ eth = (struct etherhdr *) nb->data;
+ grub_memcpy (eth->dst, target_addr.mac, 6);
+ grub_memcpy (eth->src, inf->hwaddress.mac, 6);
+
+ eth->type = grub_cpu_to_be16 (ethertype);
+ if (!inf->card->opened)
+ {
+ err = GRUB_ERR_NONE;
+ if (inf->card->driver->open)
+ err = inf->card->driver->open (inf->card);
+ if (err)
+ return err;
+ inf->card->opened = 1;
+ }
+ return inf->card->driver->send (inf->card, nb);
+}
+
+grub_err_t
+grub_net_recv_ethernet_packet (struct grub_net_buff * nb,
+ const struct grub_net_card * card)
+{
+ struct etherhdr *eth;
+ struct llchdr *llch;
+ struct snaphdr *snaph;
+ grub_uint16_t type;
+ grub_net_link_level_address_t hwaddress;
+ grub_err_t err;
+
+ eth = (struct etherhdr *) nb->data;
+ type = grub_be_to_cpu16 (eth->type);
+ err = grub_netbuff_pull (nb, sizeof (*eth));
+ if (err)
+ return err;
+
+ if (type <= 1500)
+ {
+ llch = (struct llchdr *) nb->data;
+ type = llch->dsap & LLCADDRMASK;
+
+ if (llch->dsap == 0xaa && llch->ssap == 0xaa && llch->ctrl == 0x3)
+ {
+ err = grub_netbuff_pull (nb, sizeof (*llch));
+ if (err)
+ return err;
+ snaph = (struct snaphdr *) nb->data;
+ type = snaph->type;
+ }
+ }
+
+ hwaddress.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET;
+ grub_memcpy (hwaddress.mac, eth->dst, sizeof (hwaddress.mac));
+
+ /* ARP packet. */
+ if (type == GRUB_NET_ETHERTYPE_ARP)
+ {
+ grub_net_arp_receive (nb);
+ grub_netbuff_free (nb);
+ return GRUB_ERR_NONE;
+ }
+ /* IP packet. */
+ if (type == GRUB_NET_ETHERTYPE_IP)
+ {
+ grub_net_recv_ip_packets (nb, card, &hwaddress);
+ return GRUB_ERR_NONE;
+ }
+ grub_netbuff_free (nb);
+ return GRUB_ERR_NONE;
+}
--- /dev/null
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2010,2011 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/net/ip.h>
+#include <grub/misc.h>
+#include <grub/net/arp.h>
+#include <grub/net/udp.h>
+#include <grub/net/ethernet.h>
+#include <grub/net.h>
+#include <grub/net/netbuff.h>
+#include <grub/mm.h>
+
+struct iphdr {
+ grub_uint8_t verhdrlen;
+ grub_uint8_t service;
+ grub_uint16_t len;
+ grub_uint16_t ident;
+ grub_uint16_t frags;
+ grub_uint8_t ttl;
+ grub_uint8_t protocol;
+ grub_uint16_t chksum;
+ grub_uint32_t src;
+ grub_uint32_t dest;
+} __attribute__ ((packed)) ;
+
+struct ip6hdr
+{
+ grub_uint8_t version:4, priority:4;
+ grub_uint8_t flow_lbl[3];
+ grub_uint16_t payload_len;
+ grub_uint8_t nexthdr;
+ grub_uint8_t hop_limit;
+ grub_uint8_t saddr[16];
+ grub_uint8_t daddr[16];
+} __attribute__ ((packed));
+
+grub_uint16_t
+grub_net_ip_chksum (void *ipv, int len)
+{
+ grub_uint16_t *ip = (grub_uint16_t *) ipv;
+ grub_uint32_t sum = 0;
+
+ len >>= 1;
+ while (len--)
+ {
+ sum += grub_be_to_cpu16 (*(ip++));
+ if (sum > 0xFFFF)
+ sum -= 0xFFFF;
+ }
+
+ return grub_cpu_to_be16 ((~sum) & 0x0000FFFF);
+}
+
+grub_err_t
+grub_net_send_ip_packet (struct grub_net_network_level_interface * inf,
+ const grub_net_network_level_address_t * target,
+ struct grub_net_buff * nb)
+{
+ struct iphdr *iph;
+ static int id = 0x2400;
+ grub_net_link_level_address_t ll_target_addr;
+ grub_err_t err;
+
+ grub_netbuff_push (nb, sizeof (*iph));
+ iph = (struct iphdr *) nb->data;
+
+ iph->verhdrlen = ((4 << 4) | 5);
+ iph->service = 0;
+ iph->len = grub_cpu_to_be16 (nb->tail - nb->data);
+ iph->ident = grub_cpu_to_be16 (++id);
+ iph->frags = 0;
+ iph->ttl = 0xff;
+ iph->protocol = 0x11;
+ iph->src = inf->address.ipv4;
+ iph->dest = target->ipv4;
+
+ iph->chksum = 0;
+ iph->chksum = grub_net_ip_chksum ((void *) nb->data, sizeof (*iph));
+
+ /* Determine link layer target address via ARP. */
+ err = grub_net_arp_resolve (inf, target, &ll_target_addr);
+ if (err)
+ return err;
+ return send_ethernet_packet (inf, nb, ll_target_addr,
+ GRUB_NET_ETHERTYPE_IP);
+}
+
+grub_err_t
+grub_net_recv_ip_packets (struct grub_net_buff * nb,
+ const struct grub_net_card * card,
+ const grub_net_link_level_address_t * hwaddress)
+{
+ struct iphdr *iph = (struct iphdr *) nb->data;
+ grub_err_t err;
+ struct grub_net_network_level_interface *inf = NULL;
+
+ err = grub_netbuff_pull (nb, sizeof (*iph));
+ if (err)
+ return err;
+
+ /* DHCP needs special treatment since we don't know IP yet. */
+ {
+ struct udphdr *udph;
+ udph = (struct udphdr *) nb->data;
+ if (iph->protocol == IP_UDP && grub_be_to_cpu16 (udph->dst) == 68)
+ {
+ FOR_NET_NETWORK_LEVEL_INTERFACES (inf)
+ if (inf->card == card
+ && inf->address.type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_DHCP_RECV
+ && grub_net_hwaddr_cmp (&inf->hwaddress, hwaddress) == 0)
+ {
+ err = grub_netbuff_pull (nb, sizeof (*udph));
+ if (err)
+ return err;
+ grub_net_process_dhcp (nb, inf->card);
+ grub_netbuff_free (nb);
+ }
+ return GRUB_ERR_NONE;
+ }
+ }
+
+ if (!inf)
+ {
+ FOR_NET_NETWORK_LEVEL_INTERFACES (inf)
+ {
+ if (inf->card == card
+ && inf->address.type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4
+ && inf->address.ipv4 == iph->dest
+ && grub_net_hwaddr_cmp (&inf->hwaddress, hwaddress) == 0)
+ break;
+ }
+ }
+
+ switch (iph->protocol)
+ {
+ case IP_UDP:
+ return grub_net_recv_udp_packet (nb, inf);
+ default:
+ grub_netbuff_free (nb);
+ break;
+ }
+
+ return GRUB_ERR_NONE;
+}
--- /dev/null
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2010,2011 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/net.h>
+#include <grub/net/netbuff.h>
+#include <grub/time.h>
+#include <grub/file.h>
+#include <grub/i18n.h>
+#include <grub/mm.h>
+#include <grub/misc.h>
+#include <grub/dl.h>
+#include <grub/command.h>
+#include <grub/env.h>
+#include <grub/net/ethernet.h>
+#include <grub/loader.h>
+#include <grub/bufio.h>
+#include <grub/kernel.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
+
+char *grub_net_default_server;
+
+struct grub_net_route
+{
+ struct grub_net_route *next;
+ grub_net_network_level_netaddress_t target;
+ char *name;
+ struct grub_net_network_level_protocol *prot;
+ int is_gateway;
+ union
+ {
+ struct grub_net_network_level_interface *interface;
+ grub_net_network_level_address_t gw;
+ };
+};
+
+struct grub_net_route *grub_net_routes = NULL;
+struct grub_net_network_level_interface *grub_net_network_level_interfaces = NULL;
+struct grub_net_card *grub_net_cards = NULL;
+struct grub_net_network_level_protocol *grub_net_network_level_protocols = NULL;
+static struct grub_fs grub_net_fs;
+
+void
+grub_net_card_unregister (struct grub_net_card *card)
+{
+ struct grub_net_network_level_interface *inf, *next;
+ FOR_NET_NETWORK_LEVEL_INTERFACES_SAFE(inf, next)
+ if (inf->card == card)
+ grub_net_network_level_interface_unregister (inf);
+ if (card->opened)
+ {
+ if (card->driver->close)
+ card->driver->close (card);
+ card->opened = 0;
+ }
+ grub_list_remove (GRUB_AS_LIST_P (&grub_net_cards),
+ GRUB_AS_LIST (card));
+}
+
+
+static inline void
+grub_net_route_register (struct grub_net_route *route)
+{
+ grub_list_push (GRUB_AS_LIST_P (&grub_net_routes),
+ GRUB_AS_LIST (route));
+}
+
+static inline void
+grub_net_route_unregister (struct grub_net_route *route)
+{
+ grub_list_remove (GRUB_AS_LIST_P (&grub_net_routes),
+ GRUB_AS_LIST (route));
+}
+
+#define FOR_NET_ROUTES(var) for (var = grub_net_routes; var; var = var->next)
+
+static int
+parse_ip (const char *val, grub_uint32_t *ip, const char **rest)
+{
+ grub_uint32_t newip = 0;
+ unsigned long t;
+ int i;
+ const char *ptr = val;
+
+ for (i = 0; i < 4; i++)
+ {
+ t = grub_strtoul (ptr, (char **) &ptr, 0);
+ if (grub_errno)
+ {
+ grub_errno = GRUB_ERR_NONE;
+ return 0;
+ }
+ if (t & ~0xff)
+ return 0;
+ newip >>= 8;
+ newip |= (t << 24);
+ if (i != 3 && *ptr != '.')
+ return 0;
+ ptr++;
+ }
+ *ip = grub_cpu_to_le32 (newip);
+ if (rest)
+ *rest = ptr - 1;
+ return 1;
+}
+
+static int
+match_net (const grub_net_network_level_netaddress_t *net,
+ const grub_net_network_level_address_t *addr)
+{
+ if (net->type != addr->type)
+ return 0;
+ switch (net->type)
+ {
+ case GRUB_NET_NETWORK_LEVEL_PROTOCOL_DHCP_RECV:
+ return 0;
+ case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4:
+ {
+ grub_int32_t mask = ((1 << net->ipv4.masksize) - 1) << (32 - net->ipv4.masksize);
+ return ((grub_be_to_cpu32 (net->ipv4.base) & mask)
+ == (grub_be_to_cpu32 (addr->ipv4) & mask));
+ }
+ }
+ return 0;
+}
+
+grub_err_t
+grub_net_resolve_address (const char *name,
+ grub_net_network_level_address_t *addr)
+{
+ if (parse_ip (name, &addr->ipv4, NULL))
+ {
+ addr->type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4;
+ return GRUB_ERR_NONE;
+ }
+ return grub_error (GRUB_ERR_NET_BAD_ADDRESS, N_("unrecognised address %s"),
+ name);
+}
+
+grub_err_t
+grub_net_resolve_net_address (const char *name,
+ grub_net_network_level_netaddress_t *addr)
+{
+ const char *rest;
+ if (parse_ip (name, &addr->ipv4.base, &rest))
+ {
+ addr->type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4;
+ if (*rest == '/')
+ {
+ addr->ipv4.masksize = grub_strtoul (rest + 1, NULL, 0);
+ if (!grub_errno)
+ return GRUB_ERR_NONE;
+ }
+ addr->ipv4.masksize = 32;
+ return GRUB_ERR_NONE;
+ }
+ return grub_error (GRUB_ERR_NET_BAD_ADDRESS, N_("unrecognised address %s"),
+ name);
+}
+
+grub_err_t
+grub_net_route_address (grub_net_network_level_address_t addr,
+ grub_net_network_level_address_t *gateway,
+ struct grub_net_network_level_interface **interf)
+{
+ struct grub_net_route *route;
+ int depth = 0;
+ int routecnt = 0;
+ struct grub_net_network_level_protocol *prot = NULL;
+ grub_net_network_level_address_t curtarget = addr;
+
+ *gateway = addr;
+
+ FOR_NET_ROUTES(route)
+ routecnt++;
+
+ for (depth = 0; depth < routecnt + 2; depth++)
+ {
+ FOR_NET_ROUTES(route)
+ {
+ if (depth && prot != route->prot)
+ continue;
+ if (!match_net (&route->target, &curtarget))
+ continue;
+
+ if (route->is_gateway)
+ {
+ if (depth == 0)
+ *gateway = route->gw;
+ curtarget = route->gw;
+ break;
+ }
+ *interf = route->interface;
+ return GRUB_ERR_NONE;
+ }
+ if (route == NULL)
+ return grub_error (GRUB_ERR_NET_NO_ROUTE, "destination unreachable");
+ }
+
+ return grub_error (GRUB_ERR_NET_ROUTE_LOOP, "route loop detected");
+}
+
+static grub_err_t
+grub_cmd_deladdr (struct grub_command *cmd __attribute__ ((unused)),
+ int argc, char **args)
+{
+ struct grub_net_network_level_interface *inter;
+
+ if (argc != 1)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected"));
+
+ FOR_NET_NETWORK_LEVEL_INTERFACES (inter)
+ if (grub_strcmp (inter->name, args[1]) == 0)
+ break;
+ if (inter == NULL)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("address not found"));
+
+ if (inter->flags & GRUB_NET_INTERFACE_PERMANENT)
+ return grub_error (GRUB_ERR_IO,
+ N_("you can't delete this address"));
+
+ grub_net_network_level_interface_unregister (inter);
+ grub_free (inter->name);
+ grub_free (inter);
+
+ return GRUB_ERR_NONE;
+}
+
+void
+grub_net_addr_to_str (const grub_net_network_level_address_t *target, char *buf)
+{
+ switch (target->type)
+ {
+ case GRUB_NET_NETWORK_LEVEL_PROTOCOL_DHCP_RECV:
+ grub_strcpy (buf, "temporary");
+ return;
+ case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4:
+ {
+ grub_uint32_t n = grub_be_to_cpu32 (target->ipv4);
+ grub_snprintf (buf, GRUB_NET_MAX_STR_ADDR_LEN, "%d.%d.%d.%d",
+ ((n >> 24) & 0xff), ((n >> 16) & 0xff),
+ ((n >> 8) & 0xff), ((n >> 0) & 0xff));
+ }
+ return;
+ }
+ grub_printf ("Unknown address type %d\n", target->type);
+}
+
+/*
+ Currently suppoerted adresses:
+ ethernet: XX:XX:XX:XX:XX:XX
+ */
+
+#define MAX_STR_HWADDR_LEN (sizeof ("XX:XX:XX:XX:XX:XX"))
+
+static void
+hwaddr_to_str (const grub_net_link_level_address_t *addr, char *str)
+{
+ str[0] = 0;
+ switch (addr->type)
+ {
+ case GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET:
+ {
+ char *ptr;
+ unsigned i;
+ for (ptr = str, i = 0; i < ARRAY_SIZE (addr->mac); i++)
+ {
+ grub_snprintf (ptr, MAX_STR_HWADDR_LEN - (ptr - str),
+ "%02x:", addr->mac[i] & 0xff);
+ ptr += (sizeof ("XX:") - 1);
+ }
+ return;
+ }
+ }
+ grub_printf ("Unsupported hw address type %d\n", addr->type);
+}
+
+int
+grub_net_hwaddr_cmp (const grub_net_link_level_address_t *a,
+ const grub_net_link_level_address_t *b)
+{
+ if (a->type < b->type)
+ return -1;
+ if (a->type > b->type)
+ return +1;
+ switch (a->type)
+ {
+ case GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET:
+ return grub_memcmp (a->mac, b->mac, sizeof (a->mac));
+ }
+ grub_printf ("Unsupported hw address type %d\n", a->type);
+ return 1;
+}
+
+/* FIXME: implement this. */
+static char *
+hwaddr_set_env (struct grub_env_var *var __attribute__ ((unused)),
+ const char *val __attribute__ ((unused)))
+{
+ return NULL;
+}
+
+/* FIXME: implement this. */
+static char *
+addr_set_env (struct grub_env_var *var __attribute__ ((unused)),
+ const char *val __attribute__ ((unused)))
+{
+ return NULL;
+}
+
+static void
+grub_net_network_level_interface_register (struct grub_net_network_level_interface *inter)
+{
+ {
+ char buf[MAX_STR_HWADDR_LEN];
+ char name[grub_strlen (inter->name) + sizeof ("net__mac")];
+ hwaddr_to_str (&inter->hwaddress, buf);
+ grub_snprintf (name, sizeof (name), "net_%s_mac", inter->name);
+ grub_env_set (name, buf);
+ grub_register_variable_hook (name, 0, hwaddr_set_env);
+ }
+
+ {
+ char buf[GRUB_NET_MAX_STR_ADDR_LEN];
+ char name[grub_strlen (inter->name) + sizeof ("net__ip")];
+ grub_net_addr_to_str (&inter->address, buf);
+ grub_snprintf (name, sizeof (name), "net_%s_ip", inter->name);
+ grub_env_set (name, buf);
+ grub_register_variable_hook (name, 0, addr_set_env);
+ }
+
+ inter->card->num_ifaces++;
+ inter->prev = &grub_net_network_level_interfaces;
+ inter->next = grub_net_network_level_interfaces;
+ if (inter->next)
+ inter->next->prev = &inter->next;
+ grub_net_network_level_interfaces = inter;
+}
+
+struct grub_net_network_level_interface *
+grub_net_add_addr (const char *name,
+ struct grub_net_card *card,
+ grub_net_network_level_address_t addr,
+ grub_net_link_level_address_t hwaddress,
+ grub_net_interface_flags_t flags)
+{
+ struct grub_net_network_level_interface *inter;
+
+ inter = grub_zalloc (sizeof (*inter));
+ if (!inter)
+ return NULL;
+
+ inter->name = grub_strdup (name);
+ grub_memcpy (&(inter->address), &addr, sizeof (inter->address));
+ grub_memcpy (&(inter->hwaddress), &hwaddress, sizeof (inter->hwaddress));
+ inter->flags = flags;
+ inter->card = card;
+ inter->dhcp_ack = NULL;
+ inter->dhcp_acklen = 0;
+
+ grub_net_network_level_interface_register (inter);
+
+ return inter;
+}
+
+/* FIXME: support MAC specifying. */
+static grub_err_t
+grub_cmd_addaddr (struct grub_command *cmd __attribute__ ((unused)),
+ int argc, char **args)
+{
+ struct grub_net_card *card;
+ grub_net_network_level_address_t addr;
+ grub_err_t err;
+ grub_net_interface_flags_t flags = 0;
+
+ if (argc != 3)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("three arguments expected"));
+
+ FOR_NET_CARDS (card)
+ if (grub_strcmp (card->name, args[1]) == 0)
+ break;
+ if (card == NULL)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("card not found"));
+
+ err = grub_net_resolve_address (args[2], &addr);
+ if (err)
+ return err;
+
+ if (card->flags & GRUB_NET_CARD_NO_MANUAL_INTERFACES)
+ return grub_error (GRUB_ERR_IO,
+ "this card doesn't support address addition");
+
+ if (card->flags & GRUB_NET_CARD_HWADDRESS_IMMUTABLE)
+ flags |= GRUB_NET_INTERFACE_HWADDRESS_IMMUTABLE;
+
+ grub_net_add_addr (args[0], card, addr, card->default_address,
+ flags);
+ return grub_errno;
+}
+
+static grub_err_t
+grub_cmd_delroute (struct grub_command *cmd __attribute__ ((unused)),
+ int argc, char **args)
+{
+ struct grub_net_route *route;
+ struct grub_net_route **prev;
+
+ if (argc != 1)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected"));
+
+ for (prev = &grub_net_routes, route = *prev; route; prev = &((*prev)->next),
+ route = *prev)
+ if (grub_strcmp (route->name, args[0]) == 0)
+ {
+ *prev = route->next;
+ grub_free (route->name);
+ grub_free (route);
+ }
+
+ return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_net_add_route (const char *name,
+ grub_net_network_level_netaddress_t target,
+ struct grub_net_network_level_interface *inter)
+{
+ struct grub_net_route *route;
+
+ route = grub_zalloc (sizeof (*route));
+ if (!route)
+ return grub_errno;
+
+ route->name = grub_strdup (name);
+ if (!route->name)
+ {
+ grub_free (route);
+ return grub_errno;
+ }
+
+ route->target = target;
+ route->is_gateway = 0;
+ route->interface = inter;
+
+ grub_net_route_register (route);
+
+ return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_net_add_route_gw (const char *name,
+ grub_net_network_level_netaddress_t target,
+ grub_net_network_level_address_t gw)
+{
+ struct grub_net_route *route;
+
+ route = grub_zalloc (sizeof (*route));
+ if (!route)
+ return grub_errno;
+
+ route->name = grub_strdup (name);
+ if (!route->name)
+ {
+ grub_free (route);
+ return grub_errno;
+ }
+
+ route->target = target;
+ route->is_gateway = 1;
+ route->gw = gw;
+
+ grub_net_route_register (route);
+
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_cmd_addroute (struct grub_command *cmd __attribute__ ((unused)),
+ int argc, char **args)
+{
+ grub_net_network_level_netaddress_t target;
+ if (argc < 3)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
+ N_("At least 3 arguments are expected"));
+
+ grub_net_resolve_net_address (args[1], &target);
+
+ if (grub_strcmp (args[2], "gw") == 0 && argc >= 4)
+ {
+ grub_err_t err;
+ grub_net_network_level_address_t gw;
+
+ err = grub_net_resolve_address (args[3], &gw);
+ if (err)
+ return err;
+ return grub_net_add_route_gw (args[0], target, gw);
+ }
+ else
+ {
+ struct grub_net_network_level_interface *inter;
+
+ FOR_NET_NETWORK_LEVEL_INTERFACES (inter)
+ if (grub_strcmp (inter->name, args[2]) == 0)
+ break;
+
+ if (!inter)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
+ N_("unrecognised interface %s"), args[2]);
+ return grub_net_add_route (args[0], target, inter);
+ }
+}
+
+static void
+print_net_address (const grub_net_network_level_netaddress_t *target)
+{
+ switch (target->type)
+ {
+ case GRUB_NET_NETWORK_LEVEL_PROTOCOL_DHCP_RECV:
+ grub_printf ("temporary\n");
+ break;
+ case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4:
+ {
+ grub_uint32_t n = grub_be_to_cpu32 (target->ipv4.base);
+ grub_printf ("%d.%d.%d.%d/%d ", ((n >> 24) & 0xff),
+ ((n >> 16) & 0xff),
+ ((n >> 8) & 0xff),
+ ((n >> 0) & 0xff),
+ target->ipv4.masksize);
+ }
+ return;
+ }
+ grub_printf ("Unknown address type %d\n", target->type);
+}
+
+static void
+print_address (const grub_net_network_level_address_t *target)
+{
+ char buf[GRUB_NET_MAX_STR_ADDR_LEN];
+ grub_net_addr_to_str (target, buf);
+ grub_xputs (buf);
+}
+
+static grub_err_t
+grub_cmd_listroutes (struct grub_command *cmd __attribute__ ((unused)),
+ int argc __attribute__ ((unused)),
+ char **args __attribute__ ((unused)))
+{
+ struct grub_net_route *route;
+ FOR_NET_ROUTES(route)
+ {
+ grub_printf ("%s ", route->name);
+ print_net_address (&route->target);
+ if (route->is_gateway)
+ {
+ grub_printf ("gw ");
+ print_address (&route->gw);
+ }
+ else
+ grub_printf ("%s", route->interface->name);
+ grub_printf ("\n");
+ }
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_cmd_listcards (struct grub_command *cmd __attribute__ ((unused)),
+ int argc __attribute__ ((unused)),
+ char **args __attribute__ ((unused)))
+{
+ struct grub_net_card *card;
+ FOR_NET_CARDS(card)
+ {
+ char buf[MAX_STR_HWADDR_LEN];
+ hwaddr_to_str (&card->default_address, buf);
+ grub_printf ("%s %s\n", card->name, buf);
+ }
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_cmd_listaddrs (struct grub_command *cmd __attribute__ ((unused)),
+ int argc __attribute__ ((unused)),
+ char **args __attribute__ ((unused)))
+{
+ struct grub_net_network_level_interface *inf;
+ FOR_NET_NETWORK_LEVEL_INTERFACES (inf)
+ {
+ char bufh[MAX_STR_HWADDR_LEN];
+ char bufn[GRUB_NET_MAX_STR_ADDR_LEN];
+ hwaddr_to_str (&inf->hwaddress, bufh);
+ grub_net_addr_to_str (&inf->address, bufn);
+ grub_printf ("%s %s %s\n", inf->name, bufh, bufn);
+ }
+ return GRUB_ERR_NONE;
+}
+
+grub_net_app_level_t grub_net_app_level_list;
+struct grub_net_socket *grub_net_sockets;
+
+static grub_net_t
+grub_net_open_real (const char *name)
+{
+ grub_net_app_level_t proto;
+ const char *protname, *server;
+ grub_size_t protnamelen;
+
+ if (grub_strncmp (name, "pxe:", sizeof ("pxe:") - 1) == 0)
+ {
+ protname = "tftp";
+ protnamelen = sizeof ("tftp") - 1;
+ server = name + sizeof ("pxe:") - 1;
+ }
+ else if (grub_strcmp (name, "pxe") == 0)
+ {
+ protname = "tftp";
+ protnamelen = sizeof ("tftp") - 1;
+ server = grub_net_default_server;
+ }
+ else
+ {
+ const char *comma;
+ comma = grub_strchr (name, ',');
+ if (comma)
+ {
+ protnamelen = comma - name;
+ server = comma + 1;
+ protname = name;
+ }
+ else
+ {
+ protnamelen = grub_strlen (name);
+ server = grub_net_default_server;
+ protname = name;
+ }
+ }
+ if (!server)
+ {
+ grub_error (GRUB_ERR_NET_BAD_ADDRESS, "no server");
+ return NULL;
+ }
+
+ FOR_NET_APP_LEVEL (proto)
+ {
+ if (grub_memcmp (proto->name, protname, protnamelen) == 0
+ && proto->name[protnamelen] == 0)
+ {
+ grub_net_t ret = grub_zalloc (sizeof (*ret));
+ if (!ret)
+ return NULL;
+ ret->protocol = proto;
+ if (server)
+ {
+ ret->server = grub_strdup (server);
+ if (!ret->server)
+ {
+ grub_free (ret);
+ return NULL;
+ }
+ }
+ else
+ ret->server = NULL;
+ ret->fs = &grub_net_fs;
+ ret->offset = 0;
+ ret->eof = 0;
+ return ret;
+ }
+ }
+ grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no such device");
+
+ return NULL;
+}
+
+static grub_err_t
+grub_net_fs_dir (grub_device_t device, const char *path __attribute__ ((unused)),
+ int (*hook) (const char *filename,
+ const struct grub_dirhook_info *info) __attribute__ ((unused)))
+{
+ if (!device->net)
+ return grub_error (GRUB_ERR_BAD_FS, "invalid extent");
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_net_fs_open (struct grub_file *file_out, const char *name)
+{
+ grub_err_t err;
+ struct grub_file *file, *bufio;
+
+ file = grub_malloc (sizeof (*file));
+ if (!file)
+ return grub_errno;
+
+ grub_memcpy (file, file_out, sizeof (struct grub_file));
+ file->device->net->packs.first = NULL;
+ file->device->net->packs.last = NULL;
+ file->device->net->name = grub_strdup (name);
+ if (!file->device->net->name)
+ return grub_errno;
+
+ err = file->device->net->protocol->open (file, name);
+ if (err)
+ return err;
+ bufio = grub_bufio_open (file, 32768);
+ if (! bufio)
+ {
+ file->device->net->protocol->close (file);
+ grub_free (file->device->net->name);
+ grub_free (file);
+ return grub_errno;
+ }
+
+ grub_memcpy (file_out, bufio, sizeof (struct grub_file));
+ grub_free (bufio);
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_net_fs_close (grub_file_t file)
+{
+ while (file->device->net->packs.first)
+ {
+ grub_netbuff_free (file->device->net->packs.first->nb);
+ grub_net_remove_packet (file->device->net->packs.first);
+ }
+ file->device->net->protocol->close (file);
+ grub_free (file->device->net->name);
+ return GRUB_ERR_NONE;
+}
+
+static void
+receive_packets (struct grub_net_card *card)
+{
+ if (card->num_ifaces == 0)
+ return;
+ if (!card->opened)
+ {
+ grub_err_t err = GRUB_ERR_NONE;
+ if (card->driver->open)
+ err = card->driver->open (card);
+ if (err)
+ {
+ grub_errno = GRUB_ERR_NONE;
+ return;
+ }
+ card->opened = 1;
+ }
+ while (1)
+ {
+ /* Maybe should be better have a fixed number of packets for each card
+ and just mark them as used and not used. */
+ struct grub_net_buff *nb;
+ grub_ssize_t actual;
+ nb = grub_netbuff_alloc (1500);
+ if (!nb)
+ {
+ grub_print_error ();
+ card->last_poll = grub_get_time_ms ();
+ return;
+ }
+
+ actual = card->driver->recv (card, nb);
+ if (actual < 0)
+ {
+ grub_netbuff_free (nb);
+ card->last_poll = grub_get_time_ms ();
+ break;
+ }
+ grub_net_recv_ethernet_packet (nb, card);
+ }
+ grub_print_error ();
+}
+
+void
+grub_net_poll_cards (unsigned time)
+{
+ struct grub_net_card *card;
+ grub_uint64_t start_time;
+ FOR_NET_CARDS (card)
+ {
+ start_time = grub_get_time_ms ();
+ while ((grub_get_time_ms () - start_time) < time)
+ receive_packets (card);
+ }
+}
+
+static void
+grub_net_poll_cards_idle_real (void)
+{
+ struct grub_net_card *card;
+ FOR_NET_CARDS (card)
+ {
+ grub_uint64_t ctime = grub_get_time_ms ();
+
+ if (ctime < card->last_poll
+ || ctime >= card->last_poll + card->idle_poll_delay_ms)
+ receive_packets (card);
+ }
+}
+
+/* Read from the packets list*/
+static grub_ssize_t
+grub_net_fs_read_real (grub_file_t file, char *buf, grub_size_t len)
+{
+ grub_net_t sock = file->device->net;
+ struct grub_net_buff *nb;
+ char *ptr = buf;
+ grub_size_t amount, total = 0;
+ int try = 0;
+ while (try <= 3)
+ {
+ while (sock->packs.first)
+ {
+ try = 0;
+ nb = sock->packs.first->nb;
+ amount = nb->tail - nb->data;
+ if (amount > len)
+ amount = len;
+ len -= amount;
+ total += amount;
+ file->device->net->offset += amount;
+ if (buf)
+ {
+ grub_memcpy (ptr, nb->data, amount);
+ ptr += amount;
+ }
+ if (amount == (grub_size_t) (nb->tail - nb->data))
+ {
+ grub_netbuff_free (nb);
+ grub_net_remove_packet (sock->packs.first);
+ }
+ else
+ nb->data += amount;
+
+ if (!len)
+ return total;
+ }
+ if (!sock->eof)
+ {
+ try++;
+ grub_net_poll_cards (200);
+ }
+ else
+ return total;
+ }
+ return total;
+}
+
+static grub_err_t
+grub_net_seek_real (struct grub_file *file, grub_off_t offset)
+{
+ grub_size_t len = offset - file->device->net->offset;
+
+ if (!len)
+ return GRUB_ERR_NONE;
+
+ if (file->device->net->offset > offset)
+ {
+ grub_err_t err;
+ while (file->device->net->packs.first)
+ {
+ grub_netbuff_free (file->device->net->packs.first->nb);
+ grub_net_remove_packet (file->device->net->packs.first);
+ }
+ file->device->net->protocol->close (file);
+
+ file->device->net->packs.first = NULL;
+ file->device->net->packs.last = NULL;
+ file->device->net->offset = 0;
+ file->device->net->eof = 0;
+ err = file->device->net->protocol->open (file, file->device->net->name);
+ if (err)
+ return err;
+ len = offset;
+ }
+
+ grub_net_fs_read_real (file, NULL, len);
+ return GRUB_ERR_NONE;
+}
+
+static grub_ssize_t
+grub_net_fs_read (grub_file_t file, char *buf, grub_size_t len)
+{
+ if (file->offset != file->device->net->offset)
+ {
+ grub_err_t err;
+ err = grub_net_seek_real (file, file->offset);
+ if (err)
+ return err;
+ }
+ return grub_net_fs_read_real (file, buf, len);
+}
+
+static struct grub_fs grub_net_fs =
+ {
+ .name = "netfs",
+ .dir = grub_net_fs_dir,
+ .open = grub_net_fs_open,
+ .read = grub_net_fs_read,
+ .close = grub_net_fs_close,
+ .label = NULL,
+ .uuid = NULL,
+ .mtime = NULL,
+ };
+
+static grub_err_t
+grub_net_fini_hw (int noreturn __attribute__ ((unused)))
+{
+ struct grub_net_card *card;
+ FOR_NET_CARDS (card)
+ if (card->opened)
+ {
+ if (card->driver->close)
+ card->driver->close (card);
+ card->opened = 0;
+ }
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_net_restore_hw (void)
+{
+ return GRUB_ERR_NONE;
+}
+
+static void *fini_hnd;
+
+static grub_command_t cmd_addaddr, cmd_deladdr, cmd_addroute, cmd_delroute;
+static grub_command_t cmd_lsroutes, cmd_lscards;
+static grub_command_t cmd_lsaddr;
+
+GRUB_MOD_INIT(net)
+{
+ cmd_addaddr = grub_register_command ("net_add_addr", grub_cmd_addaddr,
+ "SHORTNAME CARD ADDRESS [HWADDRESS]",
+ N_("Add a network address."));
+ cmd_deladdr = grub_register_command ("net_del_addr", grub_cmd_deladdr,
+ "SHORTNAME",
+ N_("Delete a network address."));
+ cmd_addroute = grub_register_command ("net_add_route", grub_cmd_addroute,
+ "SHORTNAME NET [INTERFACE| gw GATEWAY]",
+ N_("Add a network route."));
+ cmd_delroute = grub_register_command ("net_del_route", grub_cmd_delroute,
+ "SHORTNAME",
+ N_("Delete a network route."));
+ cmd_lsroutes = grub_register_command ("net_ls_routes", grub_cmd_listroutes,
+ "", N_("list network routes"));
+ cmd_lscards = grub_register_command ("net_ls_cards", grub_cmd_listcards,
+ "", N_("list network cards"));
+ cmd_lsaddr = grub_register_command ("net_ls_addr", grub_cmd_listaddrs,
+ "", N_("list network addresses"));
+ grub_bootp_init ();
+
+ grub_fs_register (&grub_net_fs);
+ grub_net_open = grub_net_open_real;
+ fini_hnd = grub_loader_register_preboot_hook (grub_net_fini_hw,
+ grub_net_restore_hw,
+ GRUB_LOADER_PREBOOT_HOOK_PRIO_DISK);
+ grub_net_poll_cards_idle = grub_net_poll_cards_idle_real;
+}
+
+GRUB_MOD_FINI(net)
+{
+ grub_bootp_fini ();
+ grub_unregister_command (cmd_addaddr);
+ grub_unregister_command (cmd_deladdr);
+ grub_unregister_command (cmd_addroute);
+ grub_unregister_command (cmd_delroute);
+ grub_unregister_command (cmd_lsroutes);
+ grub_unregister_command (cmd_lscards);
+ grub_unregister_command (cmd_lsaddr);
+ grub_fs_unregister (&grub_net_fs);
+ grub_net_open = NULL;
+ grub_net_fini_hw (0);
+ grub_loader_unregister_preboot_hook (fini_hnd);
+ grub_net_poll_cards_idle = grub_net_poll_cards_idle_real;
+}
--- /dev/null
+/*
+ * 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/misc.h>
+#include <grub/mm.h>
+#include <grub/net/netbuff.h>
+
+
+grub_err_t
+grub_netbuff_put (struct grub_net_buff *nb, grub_size_t len)
+{
+ nb->tail += len;
+ if (nb->tail > nb->end)
+ return grub_error (GRUB_ERR_OUT_OF_RANGE, "put out of the packet range.");
+ return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_netbuff_unput (struct grub_net_buff *nb, grub_size_t len)
+{
+ nb->tail -= len;
+ if (nb->tail < nb->head)
+ return grub_error (GRUB_ERR_OUT_OF_RANGE,
+ "unput out of the packet range.");
+ return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_netbuff_push (struct grub_net_buff *nb, grub_size_t len)
+{
+ nb->data -= len;
+ if (nb->data < nb->head)
+ return grub_error (GRUB_ERR_OUT_OF_RANGE,
+ "push out of the packet range.");
+ return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_netbuff_pull (struct grub_net_buff *nb, grub_size_t len)
+{
+ nb->data += len;
+ if (nb->data > nb->end)
+ return grub_error (GRUB_ERR_OUT_OF_RANGE,
+ "pull out of the packet range.");
+ return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_netbuff_reserve (struct grub_net_buff *nb, grub_size_t len)
+{
+ nb->data += len;
+ nb->tail += len;
+ if ((nb->tail > nb->end) || (nb->data > nb->end))
+ return grub_error (GRUB_ERR_OUT_OF_RANGE,
+ "reserve out of the packet range.");
+ return GRUB_ERR_NONE;
+}
+
+struct grub_net_buff *
+grub_netbuff_alloc (grub_size_t len)
+{
+ struct grub_net_buff *nb;
+ void *data;
+
+ if (len < NETBUFFMINLEN)
+ len = NETBUFFMINLEN;
+
+ len = ALIGN_UP (len, NETBUFF_ALIGN);
+ data = grub_memalign (NETBUFF_ALIGN, len + sizeof (*nb));
+ if (!data)
+ return NULL;
+ nb = (struct grub_net_buff *) ((grub_uint8_t *) data + len);
+ nb->head = nb->data = nb->tail = data;
+ nb->end = (char *) nb;
+ return nb;
+}
+
+grub_err_t
+grub_netbuff_free (struct grub_net_buff *nb)
+{
+ grub_free (nb->head);
+ return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_netbuff_clear (struct grub_net_buff *nb)
+{
+ nb->data = nb->tail = nb->head;
+ return GRUB_ERR_NONE;
+}
--- /dev/null
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2010,2011 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/misc.h>
+#include <grub/net/udp.h>
+#include <grub/net/ip.h>
+#include <grub/net/ethernet.h>
+#include <grub/net/netbuff.h>
+#include <grub/net.h>
+#include <grub/mm.h>
+#include <grub/dl.h>
+#include <grub/file.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
+
+/* IP port for the MTFTP server used for Intel's PXE */
+enum
+ {
+ MTFTP_SERVER_PORT = 75,
+ MTFTP_CLIENT_PORT = 76,
+ /* IP port for the TFTP server */
+ TFTP_SERVER_PORT = 69
+ };
+
+enum
+ {
+ TFTP_DEFAULTSIZE_PACKET = 512,
+ TFTP_MAX_PACKET = 1432
+ };
+
+enum
+ {
+ TFTP_CODE_EOF = 1,
+ TFTP_CODE_MORE = 2,
+ TFTP_CODE_ERROR = 3,
+ TFTP_CODE_BOOT = 4,
+ TFTP_CODE_CFG = 5
+ };
+
+enum
+ {
+ TFTP_RRQ = 1,
+ TFTP_WRQ = 2,
+ TFTP_DATA = 3,
+ TFTP_ACK = 4,
+ TFTP_ERROR = 5,
+ TFTP_OACK = 6
+ };
+
+enum
+ {
+ TFTP_EUNDEF = 0, /* not defined */
+ TFTP_ENOTFOUND = 1, /* file not found */
+ TFTP_EACCESS = 2, /* access violation */
+ TFTP_ENOSPACE = 3, /* disk full or allocation exceeded */
+ TFTP_EBADOP = 4, /* illegal TFTP operation */
+ TFTP_EBADID = 5, /* unknown transfer ID */
+ TFTP_EEXISTS = 6, /* file already exists */
+ TFTP_ENOUSER = 7 /* no such user */
+ };
+
+struct tftphdr {
+ grub_uint16_t opcode;
+ union {
+ grub_int8_t rrq[TFTP_DEFAULTSIZE_PACKET];
+ struct {
+ grub_uint16_t block;
+ grub_int8_t download[TFTP_MAX_PACKET];
+ } data;
+ struct {
+ grub_uint16_t block;
+ } ack;
+ struct {
+ grub_uint16_t errcode;
+ grub_int8_t errmsg[TFTP_DEFAULTSIZE_PACKET];
+ } err;
+ struct {
+ grub_int8_t data[TFTP_DEFAULTSIZE_PACKET+2];
+ } oack;
+ } u;
+} __attribute__ ((packed)) ;
+
+
+typedef struct tftp_data
+{
+ grub_uint64_t file_size;
+ grub_uint64_t block;
+ grub_uint32_t block_size;
+ int have_oack;
+ grub_net_socket_t sock;
+} *tftp_data_t;
+
+static grub_err_t
+tftp_receive (grub_net_socket_t sock __attribute__ ((unused)),
+ struct grub_net_buff *nb,
+ void *f)
+{
+ grub_file_t file = f;
+ struct tftphdr *tftph = (void *) nb->data;
+ char nbdata[512];
+ tftp_data_t data = file->data;
+ grub_err_t err;
+ char *ptr;
+ struct grub_net_buff nb_ack;
+
+ nb_ack.head = nbdata;
+ nb_ack.end = nbdata + sizeof (nbdata);
+
+ tftph = (struct tftphdr *) nb->data;
+ switch (grub_be_to_cpu16 (tftph->opcode))
+ {
+ case TFTP_OACK:
+ data->block_size = TFTP_DEFAULTSIZE_PACKET;
+ data->have_oack = 1;
+ for (ptr = nb->data + sizeof (tftph->opcode); ptr < nb->tail;)
+ {
+ if (grub_memcmp (ptr, "tsize\0", sizeof ("tsize\0") - 1) == 0)
+ {
+ data->file_size = grub_strtoul (ptr + sizeof ("tsize\0") - 1,
+ 0, 0);
+ }
+ if (grub_memcmp (ptr, "blksize\0", sizeof ("blksize\0") - 1) == 0)
+ {
+ data->block_size = grub_strtoul (ptr + sizeof ("blksize\0") - 1,
+ 0, 0);
+ }
+ while (ptr < nb->tail && *ptr)
+ ptr++;
+ ptr++;
+ }
+ data->block = 0;
+ grub_netbuff_free (nb);
+ break;
+ case TFTP_DATA:
+ err = grub_netbuff_pull (nb, sizeof (tftph->opcode) +
+ sizeof (tftph->u.data.block));
+ if (err)
+ return err;
+ if (grub_be_to_cpu16 (tftph->u.data.block) == data->block + 1)
+ {
+ unsigned size = nb->tail - nb->data;
+ data->block++;
+ if (size < data->block_size)
+ {
+ file->device->net->eof = 1;
+ }
+ /* Prevent garbage in broken cards. */
+ if (size > data->block_size)
+ {
+ err = grub_netbuff_unput (nb, size - data->block_size);
+ if (err)
+ return err;
+ }
+ /* If there is data, puts packet in socket list. */
+ if ((nb->tail - nb->data) > 0)
+ grub_net_put_packet (&file->device->net->packs, nb);
+ else
+ grub_netbuff_free (nb);
+ }
+ else
+ {
+ grub_netbuff_free (nb);
+ return GRUB_ERR_NONE;
+ }
+ break;
+ case TFTP_ERROR:
+ grub_netbuff_free (nb);
+ return grub_error (GRUB_ERR_IO, (char *) tftph->u.err.errmsg);
+ }
+ grub_netbuff_clear (&nb_ack);
+ grub_netbuff_reserve (&nb_ack, 512);
+ err = grub_netbuff_push (&nb_ack, sizeof (tftph->opcode)
+ + sizeof (tftph->u.ack.block));
+ if (err)
+ return err;
+
+ tftph = (struct tftphdr *) nb_ack.data;
+ tftph->opcode = grub_cpu_to_be16 (TFTP_ACK);
+ tftph->u.ack.block = grub_cpu_to_be16 (data->block);
+
+ err = grub_net_send_udp_packet (data->sock, &nb_ack);
+ if (file->device->net->eof)
+ {
+ grub_net_udp_close (data->sock);
+ data->sock = NULL;
+ }
+ return err;
+}
+
+static grub_err_t
+tftp_open (struct grub_file *file, const char *filename)
+{
+ struct tftphdr *tftph;
+ char *rrq;
+ int i;
+ int rrqlen;
+ int hdrlen;
+ char open_data[1500];
+ struct grub_net_buff nb;
+ tftp_data_t data;
+ grub_err_t err;
+
+ data = grub_zalloc (sizeof (*data));
+ if (!data)
+ return grub_errno;
+
+ nb.head = open_data;
+ nb.end = open_data + sizeof (open_data);
+ grub_netbuff_clear (&nb);
+
+ grub_netbuff_reserve (&nb, 1500);
+ err = grub_netbuff_push (&nb, sizeof (*tftph));
+ if (err)
+ return err;
+
+ tftph = (struct tftphdr *) nb.data;
+
+ rrq = (char *) tftph->u.rrq;
+ rrqlen = 0;
+
+ tftph->opcode = grub_cpu_to_be16 (TFTP_RRQ);
+ grub_strcpy (rrq, filename);
+ rrqlen += grub_strlen (filename) + 1;
+ rrq += grub_strlen (filename) + 1;
+
+ grub_strcpy (rrq, "octet");
+ rrqlen += grub_strlen ("octet") + 1;
+ rrq += grub_strlen ("octet") + 1;
+
+ grub_strcpy (rrq, "blksize");
+ rrqlen += grub_strlen ("blksize") + 1;
+ rrq += grub_strlen ("blksize") + 1;
+
+ grub_strcpy (rrq, "1024");
+ rrqlen += grub_strlen ("1024") + 1;
+ rrq += grub_strlen ("1024") + 1;
+
+ grub_strcpy (rrq, "tsize");
+ rrqlen += grub_strlen ("tsize") + 1;
+ rrq += grub_strlen ("tsize") + 1;
+
+ grub_strcpy (rrq, "0");
+ rrqlen += grub_strlen ("0") + 1;
+ rrq += grub_strlen ("0") + 1;
+ hdrlen = sizeof (tftph->opcode) + rrqlen;
+
+ err = grub_netbuff_unput (&nb, nb.tail - (nb.data + hdrlen));
+ if (err)
+ return err;
+
+ file->not_easily_seekable = 1;
+ file->data = data;
+ data->sock = grub_net_udp_open (file->device->net->server,
+ TFTP_SERVER_PORT, tftp_receive,
+ file);
+ if (!data->sock)
+ return grub_errno;
+
+ err = grub_net_send_udp_packet (data->sock, &nb);
+ if (err)
+ {
+ grub_net_udp_close (data->sock);
+ return err;
+ }
+
+ /* Receive OACK packet. */
+ for (i = 0; i < 3; i++)
+ {
+ grub_net_poll_cards (100);
+ if (grub_errno)
+ return grub_errno;
+ if (data->have_oack)
+ break;
+ /* Retry. */
+ err = grub_net_send_udp_packet (data->sock, &nb);
+ if (err)
+ {
+ grub_net_udp_close (data->sock);
+ return err;
+ }
+ }
+
+ if (!data->have_oack)
+ {
+ grub_net_udp_close (data->sock);
+ return grub_error (GRUB_ERR_TIMEOUT, "Time out opening tftp.");
+ }
+ file->size = data->file_size;
+
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+tftp_close (struct grub_file *file)
+{
+ tftp_data_t data = file->data;
+
+ if (data->sock)
+ {
+ char nbdata[512];
+ grub_err_t err;
+ struct grub_net_buff nb_err;
+ struct tftphdr *tftph;
+
+ nb_err.head = nbdata;
+ nb_err.end = nbdata + sizeof (nbdata);
+
+ grub_netbuff_clear (&nb_err);
+ grub_netbuff_reserve (&nb_err, 512);
+ err = grub_netbuff_push (&nb_err, sizeof (tftph->opcode)
+ + sizeof (tftph->u.err.errcode)
+ + sizeof ("closed"));
+ if (!err)
+ {
+ tftph = (struct tftphdr *) nb_err.data;
+ tftph->opcode = grub_cpu_to_be16 (TFTP_ERROR);
+ tftph->u.err.errcode = grub_cpu_to_be16 (TFTP_EUNDEF);
+ grub_memcpy (tftph->u.err.errmsg, "closed", sizeof ("closed"));
+
+ err = grub_net_send_udp_packet (data->sock, &nb_err);
+ }
+ if (err)
+ grub_print_error ();
+ grub_net_udp_close (data->sock);
+ }
+ grub_free (data);
+ return GRUB_ERR_NONE;
+}
+
+static struct grub_net_app_protocol grub_tftp_protocol =
+ {
+ .name = "tftp",
+ .open = tftp_open,
+ .close = tftp_close
+ };
+
+GRUB_MOD_INIT (tftp)
+{
+ grub_net_app_level_register (&grub_tftp_protocol);
+}
+
+GRUB_MOD_FINI (tftp)
+{
+ grub_net_app_level_unregister (&grub_tftp_protocol);
+}
--- /dev/null
+#include <grub/net.h>
+#include <grub/net/udp.h>
+#include <grub/net/ip.h>
+#include <grub/net/netbuff.h>
+#include <grub/time.h>
+
+grub_net_socket_t
+grub_net_udp_open (char *server,
+ grub_uint16_t out_port,
+ grub_err_t (*recv_hook) (grub_net_socket_t sock,
+ struct grub_net_buff *nb,
+ void *data),
+ void *recv_hook_data)
+{
+ grub_err_t err;
+ grub_net_network_level_address_t addr;
+ struct grub_net_network_level_interface *inf;
+ grub_net_network_level_address_t gateway;
+ grub_net_socket_t socket;
+ static int in_port = 25300;
+
+ err = grub_net_resolve_address (server, &addr);
+ if (err)
+ return NULL;
+
+ err = grub_net_route_address (addr, &gateway, &inf);
+ if (err)
+ return NULL;
+
+ socket = grub_zalloc (sizeof (*socket));
+ if (socket == NULL)
+ return NULL;
+
+ socket->x_out_port = out_port;
+ socket->x_inf = inf;
+ socket->x_out_nla = addr;
+ socket->x_in_port = in_port++;
+ socket->x_status = GRUB_NET_SOCKET_START;
+ socket->recv_hook = recv_hook;
+ socket->recv_hook_data = recv_hook_data;
+
+ grub_net_socket_register (socket);
+
+ return socket;
+}
+
+grub_err_t
+grub_net_send_udp_packet (const grub_net_socket_t socket,
+ struct grub_net_buff *nb)
+{
+ struct udphdr *udph;
+ grub_err_t err;
+
+ err = grub_netbuff_push (nb, sizeof (*udph));
+ if (err)
+ return err;
+
+ udph = (struct udphdr *) nb->data;
+ udph->src = grub_cpu_to_be16 (socket->x_in_port);
+ udph->dst = grub_cpu_to_be16 (socket->x_out_port);
+
+ /* No chechksum. */
+ udph->chksum = 0;
+ udph->len = grub_cpu_to_be16 (nb->tail - nb->data);
+
+ return grub_net_send_ip_packet (socket->x_inf, &(socket->x_out_nla), nb);
+}
+
+grub_err_t
+grub_net_recv_udp_packet (struct grub_net_buff * nb,
+ struct grub_net_network_level_interface * inf)
+{
+ struct udphdr *udph;
+ grub_net_socket_t sock;
+ grub_err_t err;
+ udph = (struct udphdr *) nb->data;
+ err = grub_netbuff_pull (nb, sizeof (*udph));
+ if (err)
+ return err;
+
+ FOR_NET_SOCKETS (sock)
+ {
+ if (grub_be_to_cpu16 (udph->dst) == sock->x_in_port
+ && inf == sock->x_inf && sock->recv_hook)
+ {
+ if (sock->x_status == GRUB_NET_SOCKET_START)
+ {
+ sock->x_out_port = grub_be_to_cpu16 (udph->src);
+ sock->x_status = GRUB_NET_SOCKET_ESTABLISHED;
+ }
+
+ /* App protocol remove its own reader. */
+ sock->recv_hook (sock, nb, sock->recv_hook_data);
+ return GRUB_ERR_NONE;
+ }
+ }
+ grub_netbuff_free (nb);
+ return GRUB_ERR_NONE;
+}
case GRUB_TERM_CTRL | 'k':
if (lpos < llen)
{
- if (kill_buf)
- grub_free (kill_buf);
+ grub_free (kill_buf);
kill_buf = grub_malloc ((llen - lpos + 1)
* sizeof (grub_uint32_t));
{
grub_size_t n = lpos;
- if (kill_buf)
- grub_free (kill_buf);
+ grub_free (kill_buf);
kill_buf = grub_malloc (n + 1);
if (grub_errno)
#include <grub/charset.h>
#include <grub/script_sh.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
#define GRUB_DEFAULT_HISTORY_SIZE 50
static int nested_level = 0;
static grub_command_t cmd_clear;
static void (*grub_xputs_saved) (const char *str);
+static const char *features[] = {
+ "feature_chainloader_bpb", "feature_ntldr"
+};
GRUB_MOD_INIT(normal)
{
+ unsigned i;
+
/* Previously many modules depended on gzio. Be nice to user and load it. */
grub_dl_load ("gzio");
/* Set default color names. */
grub_env_set ("color_normal", "white/black");
grub_env_set ("color_highlight", "black/white");
+
+ for (i = 0; i < ARRAY_SIZE (features); i++)
+ {
+ grub_env_set (features[i], "y");
+ grub_env_export (features[i]);
+ }
}
GRUB_MOD_FINI(normal)
grub_env_export ("chosen");
grub_free (buf);
}
- for (ptr = def; *ptr; ptr++)
+
+ for (ptr = def; ptr && *ptr; ptr++)
{
if (ptr[0] == '>' && ptr[1] == '>')
{
if (ptr[0] == '>')
break;
}
- if (ptr[0] && ptr[1])
+
+ if (ptr && ptr[0] && ptr[1])
grub_env_set ("default", ptr + 1);
else
grub_env_unset ("default");
+
grub_script_execute_sourcecode (entry->sourcecode, entry->argc, entry->args);
if (errs_before != grub_err_printed_errors)
#include <grub/partition.h>
#include <grub/acorn_filecore.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
#define LINUX_NATIVE_MAGIC grub_cpu_to_le32 (0xdeafa1de)
#define LINUX_SWAP_MAGIC grub_cpu_to_le32 (0xdeafab1e)
#define LINUX_MAP_ENTRIES (512 / 12)
struct grub_acorn_boot_block
{
- grub_uint8_t misc[0x1C0];
- struct grub_filecore_disc_record disc_record;
- grub_uint8_t flags;
- grub_uint16_t start_cylinder;
- grub_uint8_t checksum;
+ union
+ {
+ struct
+ {
+ grub_uint8_t misc[0x1C0];
+ struct grub_filecore_disc_record disc_record;
+ grub_uint8_t flags;
+ grub_uint16_t start_cylinder;
+ grub_uint8_t checksum;
+ } __attribute__ ((packed, aligned));
+ grub_uint8_t bin[0x200];
+ };
} __attribute__ ((packed, aligned));
struct linux_part
goto fail;
for (i = 0; i != 0x1ff; ++i)
- checksum = (checksum & 0xff) + (checksum >> 8) + boot.misc[i];
+ checksum = ((checksum & 0xff) + (checksum >> 8) + boot.bin[i]);
if ((grub_uint8_t) checksum != boot.checksum)
goto fail;
#include <grub/partition.h>
#include <grub/dl.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
struct grub_amiga_rdsk
{
/* "RDSK". */
grub_uint32_t partitionlst;
grub_uint32_t fslst;
- /* The other information is not important for us. */
+ grub_uint32_t unused[128 - 9];
} __attribute__ ((packed));
struct grub_amiga_partition
grub_uint32_t highcyl;
grub_uint32_t firstcyl;
+ grub_uint32_t unused[128 - 44];
} __attribute__ ((packed));
static struct grub_partition_map grub_amiga_partition_map;
\f
+static grub_uint32_t
+amiga_partition_map_checksum (void *buf, grub_size_t sz)
+{
+ grub_uint32_t *ptr = buf;
+ grub_uint32_t r = 0;
+ sz /= sizeof (grub_uint32_t);
+ for (; sz; sz--, ptr++)
+ r += grub_be_to_cpu32 (*ptr);
+ return r;
+}
+
static grub_err_t
amiga_partition_map_iterate (grub_disk_t disk,
int (*hook) (grub_disk_t disk,
return grub_errno;
if (grub_memcmp (rdsk.magic, GRUB_AMIGA_RDSK_MAGIC,
- sizeof (rdsk.magic)) == 0)
+ sizeof (rdsk.magic)) == 0
+ && amiga_partition_map_checksum (&rdsk, sizeof (rdsk)) == 0)
{
/* Found the first PART block. */
next = grub_be_to_cpu32 (rdsk.partitionlst);
return grub_errno;
if (grub_memcmp (apart.magic, GRUB_AMIGA_PART_MAGIC,
- sizeof (apart.magic)) == 0)
-
+ sizeof (apart.magic)) != 0
+ || amiga_partition_map_checksum (&apart, sizeof (apart)) != 0)
+ return grub_error (GRUB_ERR_BAD_PART_TABLE,
+ "invalid Amiga partition map");
/* Calculate the first block and the size of the partition. */
part.start = (grub_be_to_cpu32 (apart.lowcyl)
* grub_be_to_cpu32 (apart.heads)
#include <grub/mm.h>
#include <grub/partition.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
#define GRUB_APPLE_HEADER_MAGIC 0x4552
#define GRUB_APPLE_PART_MAGIC 0x504D
#include <grub/dl.h>
#include <grub/msdos_partition.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
#ifdef GRUB_UTIL
#include <grub/emu/misc.h>
#endif
--- /dev/null
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2002,2005,2006,2007,2011 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/partition.h>
+#include <grub/disk.h>
+#include <grub/mm.h>
+#include <grub/misc.h>
+#include <grub/dl.h>
+#include <grub/symbol.h>
+#include <grub/types.h>
+#include <grub/err.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
+
+#define DVH_MAGIC 0x0be5a941
+
+struct grub_dvh_partition_descriptor
+{
+ grub_uint32_t length;
+ grub_uint32_t start;
+ grub_uint32_t type;
+} __attribute__ ((packed));
+
+struct grub_dvh_block
+{
+ grub_uint32_t magic;
+ grub_uint8_t unused[308];
+ struct grub_dvh_partition_descriptor parts[16];
+ grub_uint32_t checksum;
+ grub_uint32_t unused2;
+} __attribute__ ((packed));
+
+static struct grub_partition_map grub_dvh_partition_map;
+
+/* Verify checksum (true=ok). */
+static int
+grub_dvh_is_valid (struct grub_dvh_block *label)
+{
+ grub_uint32_t *pos;
+ grub_uint32_t sum = 0;
+
+ for (pos = (grub_uint32_t *) label;
+ pos < (grub_uint32_t *) (label + 1);
+ pos++)
+ sum += *pos;
+
+ return ! sum;
+}
+
+static grub_err_t
+dvh_partition_map_iterate (grub_disk_t disk,
+ int (*hook) (grub_disk_t disk,
+ const grub_partition_t partition))
+{
+ struct grub_partition p;
+ struct grub_dvh_block block;
+ unsigned partnum;
+ grub_err_t err;
+
+ p.partmap = &grub_dvh_partition_map;
+ err = grub_disk_read (disk, 0, 0, sizeof (struct grub_dvh_block),
+ &block);
+ if (err)
+ return err;
+
+ if (DVH_MAGIC != grub_be_to_cpu32 (block.magic))
+ return grub_error (GRUB_ERR_BAD_PART_TABLE, "not a dvh partition table");
+
+ if (! grub_dvh_is_valid (&block))
+ return grub_error (GRUB_ERR_BAD_PART_TABLE, "invalid checksum");
+
+ /* Maybe another error value would be better, because partition
+ table _is_ recognized but invalid. */
+ for (partnum = 0; partnum < ARRAY_SIZE (block.parts); partnum++)
+ {
+ if (block.parts[partnum].length == 0)
+ continue;
+
+ if (partnum == 10)
+ continue;
+
+ p.start = grub_be_to_cpu32 (block.parts[partnum].start);
+ p.len = grub_be_to_cpu32 (block.parts[partnum].length);
+ p.number = p.index = partnum;
+ if (hook (disk, &p))
+ break;
+ }
+
+ return grub_errno;
+}
+
+
+/* Partition map type. */
+static struct grub_partition_map grub_dvh_partition_map =
+ {
+ .name = "dvh",
+ .iterate = dvh_partition_map_iterate,
+ };
+
+GRUB_MOD_INIT(part_dvh)
+{
+ grub_partition_map_register (&grub_dvh_partition_map);
+}
+
+GRUB_MOD_FINI(part_dvh)
+{
+ grub_partition_map_unregister (&grub_dvh_partition_map);
+}
+
#include <grub/msdos_partition.h>
#include <grub/gpt_partition.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
static grub_uint8_t grub_gpt_magic[8] =
{
0x45, 0x46, 0x49, 0x20, 0x50, 0x41, 0x52, 0x54
#include <grub/misc.h>
#include <grub/dl.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
static struct grub_partition_map grub_msdos_partition_map;
\f
{
e = mbr.entries + p.index;
- p.start = p.offset + grub_le_to_cpu32 (e->start) - delta;
- p.len = grub_le_to_cpu32 (e->length);
+ p.start = p.offset
+ + (grub_le_to_cpu32 (e->start)
+ << (disk->log_sector_size - GRUB_DISK_SECTOR_BITS)) - delta;
+ p.len = grub_le_to_cpu32 (e->length)
+ << (disk->log_sector_size - GRUB_DISK_SECTOR_BITS);
p.msdostype = e->type;
grub_dprintf ("partition",
if (grub_msdos_partition_is_extended (e->type))
{
- p.offset = ext_offset + grub_le_to_cpu32 (e->start);
+ p.offset = ext_offset
+ + (grub_le_to_cpu32 (e->start)
+ << (disk->log_sector_size - GRUB_DISK_SECTOR_BITS));
if (! ext_offset)
ext_offset = p.offset;
e = mbr.entries + i;
if (!grub_msdos_partition_is_empty (e->type)
- && end > offset + grub_le_to_cpu32 (e->start))
- end = offset + grub_le_to_cpu32 (e->start);
+ && end > offset
+ + (grub_le_to_cpu32 (e->start)
+ << (disk->log_sector_size - GRUB_DISK_SECTOR_BITS)))
+ end = offset + (grub_le_to_cpu32 (e->start)
+ << (disk->log_sector_size - GRUB_DISK_SECTOR_BITS));
/* If this is a GPT partition, this MBR is just a dummy. */
if (e->type == GRUB_PC_PARTITION_TYPE_GPT_DISK && i == 0)
if (grub_msdos_partition_is_extended (e->type))
{
- offset = ext_offset + grub_le_to_cpu32 (e->start);
+ offset = ext_offset
+ + (grub_le_to_cpu32 (e->start)
+ << (disk->log_sector_size - GRUB_DISK_SECTOR_BITS));
if (! ext_offset)
ext_offset = offset;
#include <grub/types.h>
#include <grub/err.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
#define GRUB_PARTMAP_SUN_MAGIC 0xDABE
#define GRUB_PARTMAP_SUN_MAX_PARTS 8
#define GRUB_PARTMAP_SUN_WHOLE_DISK_ID 0x05
#include <grub/types.h>
#include <grub/err.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
#define GRUB_PARTMAP_SUN_PC_MAGIC 0xDABE
#define GRUB_PARTMAP_SUN_PC_MAX_PARTS 16
#define GRUB_PARTMAP_SUN_PC_WHOLE_DISK_ID 0x05
#include <grub/partition.h>
#include <grub/parttool.h>
+GRUB_MOD_LICENSE ("GPLv2+");
+
static int activate_table_handle = -1;
static int type_table_handle = -1;
%token <arg> GRUB_PARSER_TOKEN_THEN "then"
%token <arg> GRUB_PARSER_TOKEN_UNTIL "until"
%token <arg> GRUB_PARSER_TOKEN_WHILE "while"
-%token <arg> GRUB_PARSER_TOKEN_TIME "time"
%token <arg> GRUB_PARSER_TOKEN_FUNCTION "function"
%token <arg> GRUB_PARSER_TOKEN_NAME "name"
%token <arg> GRUB_PARSER_TOKEN_WORD "word"
| "until" { $$ = grub_script_add_arglist (state, 0, $1); }
| "while" { $$ = grub_script_add_arglist (state, 0, $1); }
| "function" { $$ = grub_script_add_arglist (state, 0, $1); }
- | "time" { $$ = grub_script_add_arglist (state, 0, $1); }
| word { $$ = $1; }
;
"}" { RECORD; return GRUB_PARSER_TOKEN_RBR; }
"[[" { RECORD; return GRUB_PARSER_TOKEN_RSQBR2; }
"]]" { RECORD; return GRUB_PARSER_TOKEN_LSQBR2; }
-"time" { RECORD; return GRUB_PARSER_TOKEN_TIME; }
"case" { RECORD; return GRUB_PARSER_TOKEN_CASE; }
"do" { RECORD; return GRUB_PARSER_TOKEN_DO; }
"done" { RECORD; return GRUB_PARSER_TOKEN_DONE; }
{
struct grub_lexer_param *lexerstate = yyget_extra (yyscanner)->lexerstate;
- if (lexerstate->prefix)
- grub_free (lexerstate->prefix);
+ grub_free (lexerstate->prefix);
lexerstate->prefix = grub_strdup (text);
if (! lexerstate->prefix)
--- /dev/null
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2011 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/arc/arc.h>
+#include <grub/arc/console.h>
+#include <grub/term.h>
+#include <grub/terminfo.h>
+
+/* FIXME: use unicode. */
+
+static int
+readkey (struct grub_term_input *term __attribute__ ((unused)))
+{
+ unsigned long count;
+ char chr;
+
+ if (GRUB_ARC_FIRMWARE_VECTOR->get_read_status (GRUB_ARC_STDIN))
+ return -1;
+
+ if (GRUB_ARC_FIRMWARE_VECTOR->read (GRUB_ARC_STDIN, &chr, 1, &count))
+ return -1;
+ if (!count)
+ return -1;
+ return chr;
+}
+
+static void
+put (struct grub_term_output *term __attribute__ ((unused)), const int c)
+{
+ unsigned long count;
+ char chr = c;
+
+ GRUB_ARC_FIRMWARE_VECTOR->write (GRUB_ARC_STDOUT, &chr, 1, &count);
+}
+
+static struct grub_terminfo_output_state grub_console_terminfo_output;
+
+static grub_err_t
+grub_console_init_output (struct grub_term_output *term)
+{
+ struct grub_arc_display_status *info = NULL;
+ if (GRUB_ARC_SYSTEM_PARAMETER_BLOCK->firmware_vector_length
+ >= ((char *) (&GRUB_ARC_FIRMWARE_VECTOR->getdisplaystatus + 1)
+ - (char *) GRUB_ARC_FIRMWARE_VECTOR)
+ && GRUB_ARC_FIRMWARE_VECTOR->getdisplaystatus)
+ info = GRUB_ARC_FIRMWARE_VECTOR->getdisplaystatus (GRUB_ARC_STDOUT);
+ if (info)
+ {
+ grub_console_terminfo_output.width = info->w;
+ grub_console_terminfo_output.height = info->h;
+ }
+ grub_terminfo_output_init (term);
+
+ return 0;
+}
+
+static struct grub_terminfo_input_state grub_console_terminfo_input =
+ {
+ .readkey = readkey
+ };
+
+static struct grub_terminfo_output_state grub_console_terminfo_output =
+ {
+ .put = put,
+ .width = 80,
+ .height = 36
+ };
+
+static struct grub_term_input grub_console_term_input =
+ {
+ .name = "console",
+ .init = grub_terminfo_input_init,
+ .getkey = grub_terminfo_getkey,
+ .data = &grub_console_terminfo_input
+ };
+
+static struct grub_term_output grub_console_term_output =
+ {
+ .name = "console",
+ .init = grub_console_init_output,
+ .putchar = grub_terminfo_putchar,
+ .getxy = grub_terminfo_getxy,
+ .getwh = grub_terminfo_getwh,
+ .gotoxy = grub_terminfo_gotoxy,
+ .cls = grub_terminfo_cls,
+ .setcolorstate = grub_terminfo_setcolorstate,
+ .setcursor = grub_terminfo_setcursor,
+ .flags = GRUB_TERM_CODE_TYPE_ASCII,
+ .data = &grub_console_terminfo_output,
+ .normal_color = GRUB_TERM_DEFAULT_NORMAL_COLOR,
+ .highlight_color = GRUB_TERM_DEFAULT_HIGHLIGHT_COLOR,
+ };
+
+void
+grub_console_init_early (void)
+{
+ grub_term_register_input ("console", &grub_console_term_input);
+ grub_term_register_output ("console", &grub_console_term_output);
+}
+
+void grub_terminfo_init (void);
+
+void
+grub_console_init_lately (void)
+{
+ grub_terminfo_init ();
+ grub_terminfo_output_register (&grub_console_term_output, "arc");
+}
#include <grub/time.h>
#include <grub/loader.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
static short at_keyboard_status = 0;
static int e0_received = 0;
static int f0_received = 0;
{0x38, GRUB_KEYBOARD_KEY_RIGHT_ALT},
{0x47, GRUB_KEYBOARD_KEY_HOME},
{0x48, GRUB_KEYBOARD_KEY_UP},
- {0x49, GRUB_KEYBOARD_KEY_NPAGE},
+ {0x49, GRUB_KEYBOARD_KEY_PPAGE},
{0x4b, GRUB_KEYBOARD_KEY_LEFT},
{0x4d, GRUB_KEYBOARD_KEY_RIGHT},
{0x4f, GRUB_KEYBOARD_KEY_END},
{0x50, GRUB_KEYBOARD_KEY_DOWN},
- {0x51, GRUB_KEYBOARD_KEY_PPAGE},
+ {0x51, GRUB_KEYBOARD_KEY_NPAGE},
{0x52, GRUB_KEYBOARD_KEY_INSERT},
{0x53, GRUB_KEYBOARD_KEY_DELETE},
};
grub_outb (c, KEYBOARD_REG_DATA);
}
-#if !defined (GRUB_MACHINE_MIPS_YEELOONG) && !defined (GRUB_MACHINE_QEMU)
+#if !defined (GRUB_MACHINE_MIPS_LOONGSON) && !defined (GRUB_MACHINE_QEMU) && !defined (GRUB_MACHINE_MIPS_QEMU_MIPS)
static grub_uint8_t
grub_keyboard_controller_read (void)
return;
}
-#if !(defined (GRUB_MACHINE_MIPS_YEELOONG) || defined (GRUB_MACHINE_QEMU))
+#if !(defined (GRUB_MACHINE_MIPS_LOONGSON) || defined (GRUB_MACHINE_QEMU))
current_set = 1;
return;
#endif
if (!ret)
{
if (was_ext)
- grub_printf ("Unknown key 0xe0+0x%02x from set %d\n",
- at_key, current_set);
+ grub_dprintf ("atkeyb", "Unknown key 0xe0+0x%02x from set %d\n",
+ at_key, current_set);
else
- grub_printf ("Unknown key 0x%02x from set %d\n",
- at_key, current_set);
+ grub_dprintf ("atkeyb", "Unknown key 0x%02x from set %d\n",
+ at_key, current_set);
return -1;
}
return ret;
keyboard_controller_wait_until_ready ();
grub_inb (KEYBOARD_REG_DATA);
}
-#if defined (GRUB_MACHINE_MIPS_YEELOONG) || defined (GRUB_MACHINE_QEMU)
+#if defined (GRUB_MACHINE_MIPS_LOONGSON) || defined (GRUB_MACHINE_QEMU) || defined (GRUB_MACHINE_MIPS_QEMU_MIPS)
grub_keyboard_controller_orig = 0;
grub_keyboard_orig_set = 2;
#else
#include <grub/bitmap_scale.h>
#include <grub/i18n.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
#define DEFAULT_VIDEO_MODE "auto"
#define DEFAULT_BORDER_WIDTH 10
static unsigned int bitmap_width;
static unsigned int bitmap_height;
static struct grub_video_bitmap *bitmap;
+static int blend_text_bg;
+static grub_video_rgba_color_t default_bg_color = { 0, 0, 0, 0 };
static struct grub_dirty_region dirty_region;
grub_video_set_active_render_target (render_target);
- virtual_screen.bg_color_display = grub_video_map_rgba(0, 0, 0, 0);
+ virtual_screen.bg_color_display =
+ grub_video_map_rgba_color (default_bg_color);
/* Clear out text buffer. */
for (i = 0; i < virtual_screen.columns * virtual_screen.rows; i++)
double_redraw = mode_info.mode_type & GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED
&& !(mode_info.mode_type & GRUB_VIDEO_MODE_TYPE_UPDATING_SWAP);
- /* Make sure screen is black. */
- color = grub_video_map_rgb (0, 0, 0);
+ /* Make sure screen is set to the default background color. */
+ color = grub_video_map_rgba_color (default_bg_color);
grub_video_fill_rect (color, 0, 0, mode_info.width, mode_info.height);
if (double_redraw)
{
grub_video_swap_buffers ();
grub_video_fill_rect (color, 0, 0, mode_info.width, mode_info.height);
}
- bitmap = 0;
/* Select the font to use. */
font_name = grub_env_get ("gfxterm_font");
static void
destroy_window (void)
{
- if (bitmap)
- {
- grub_video_bitmap_destroy (bitmap);
- bitmap = 0;
- }
-
repaint_callback = 0;
grub_virtual_screen_free ();
}
/* Render background layer. */
grub_video_fill_rect (color, x, ty, width, h);
}
-
- /* Render text layer as blended. */
- grub_video_blit_render_target (text_layer, GRUB_VIDEO_BLIT_BLEND, x, y,
- x - virtual_screen.offset_x,
- y - virtual_screen.offset_y,
- width, height);
}
else
{
/* Render background layer. */
color = virtual_screen.bg_color_display;
grub_video_fill_rect (color, x, y, width, height);
-
- /* Render text layer as replaced (to get texts background color). */
- grub_video_blit_render_target (text_layer, GRUB_VIDEO_BLIT_REPLACE, x, y,
- x - virtual_screen.offset_x,
- y - virtual_screen.offset_y,
- width, height);
}
+ if (blend_text_bg)
+ /* Render text layer as blended. */
+ grub_video_blit_render_target (text_layer, GRUB_VIDEO_BLIT_BLEND, x, y,
+ x - virtual_screen.offset_x,
+ y - virtual_screen.offset_y,
+ width, height);
+ else
+ /* Render text layer as replaced (to get texts background color). */
+ grub_video_blit_render_target (text_layer, GRUB_VIDEO_BLIT_REPLACE, x, y,
+ x - virtual_screen.offset_x,
+ y - virtual_screen.offset_y,
+ width, height);
+
/* Restore saved viewport. */
grub_video_set_viewport (saved_view.x, saved_view.y,
saved_view.width, saved_view.height);
{
grub_video_bitmap_destroy (bitmap);
bitmap = 0;
+ blend_text_bg = 0;
/* Mark whole screen as dirty. */
dirty_region_add (0, 0, window.width, window.height);
/* If bitmap was loaded correctly, display it. */
if (bitmap)
{
+ blend_text_bg = 1;
+
/* Determine bitmap dimensions. */
bitmap_width = grub_video_bitmap_get_width (bitmap);
bitmap_height = grub_video_bitmap_get_height (bitmap);
return grub_errno;
}
+static grub_err_t
+grub_gfxterm_background_color_cmd (grub_command_t cmd __attribute__ ((unused)),
+ int argc, char **args)
+{
+ struct grub_video_render_target *old_target;
+
+ if (argc != 1)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "missing operand");
+
+ /* Check that we have video adapter active. */
+ if (grub_video_get_info (NULL) != GRUB_ERR_NONE)
+ return grub_errno;
+
+ if (grub_video_parse_color (args[0], &default_bg_color) != GRUB_ERR_NONE)
+ return grub_errno;
+
+ /* Destroy existing background bitmap if loaded. */
+ if (bitmap)
+ {
+ grub_video_bitmap_destroy (bitmap);
+ bitmap = 0;
+
+ /* Mark whole screen as dirty. */
+ dirty_region_add (0, 0, window.width, window.height);
+ }
+
+ /* Set the background and border colors. The background color needs to be
+ compatible with the text layer. */
+ grub_video_get_active_render_target (&old_target);
+ grub_video_set_active_render_target (text_layer);
+ virtual_screen.bg_color = grub_video_map_rgba_color (default_bg_color);
+ grub_video_set_active_render_target (old_target);
+ virtual_screen.bg_color_display =
+ grub_video_map_rgba_color (default_bg_color);
+ blend_text_bg = 1;
+
+ /* Mark whole screen as dirty. */
+ dirty_region_add (0, 0, window.width, window.height);
+
+ return GRUB_ERR_NONE;
+}
+
static struct grub_term_output grub_video_term =
{
.name = "gfxterm",
};
static grub_extcmd_t background_image_cmd_handle;
+static grub_command_t background_color_cmd_handle;
GRUB_MOD_INIT(gfxterm)
{
N_("[-m (stretch|normal)] FILE"),
N_("Load background image for active terminal."),
background_image_cmd_options);
+ background_color_cmd_handle =
+ grub_register_command ("background_color",
+ grub_gfxterm_background_color_cmd,
+ N_("COLOR"),
+ N_("Set background color for active terminal."));
}
GRUB_MOD_FINI(gfxterm)
{
+ grub_unregister_command (background_color_cmd_handle);
grub_unregister_extcmd (background_image_cmd_handle);
grub_term_unregister_output (&grub_video_term);
}
#include <grub/dl.h>
#include <grub/i386/vga_common.h>
-#include <grub/i386/io.h>
+#include <grub/cpu/io.h>
#include <grub/types.h>
#include <grub/vga.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
#define COLS 80
#define ROWS 25
static int grub_curr_x, grub_curr_y;
+#ifdef __mips__
+#define VGA_TEXT_SCREEN ((grub_uint16_t *) 0xb00b8000)
+#else
#define VGA_TEXT_SCREEN ((grub_uint16_t *) 0xb8000)
+#endif
static void
screen_write_char (int x, int y, short c)
/* Convert speed to divisor. */
static unsigned short
-serial_get_divisor (unsigned int speed)
+serial_get_divisor (const struct grub_serial_port *port __attribute__ ((unused)),
+ const struct grub_serial_config *config)
{
unsigned int i;
/* Set the baud rate. */
for (i = 0; i < ARRAY_SIZE (divisor_tab); i++)
- if (divisor_tab[i].speed == speed)
- /* UART in Yeeloong runs twice the usual rate. */
-#ifdef GRUB_MACHINE_MIPS_YEELOONG
- return 2 * divisor_tab[i].div;
-#else
- return divisor_tab[i].div;
+ if (divisor_tab[i].speed == config->speed)
+ {
+ /* internal Loongson UART runs twice the usual rate. */
+#ifdef GRUB_MACHINE_MIPS_LOONGSON
+ if (port->port == 0xbff003f8)
+ return 2 * divisor_tab[i].div;
+ else
#endif
+ return divisor_tab[i].div;
+ }
return 0;
}
port->broken = 0;
- divisor = serial_get_divisor (port->config.speed);
+ divisor = serial_get_divisor (port, &port->config);
/* Turn off the interrupt. */
grub_outb (0, port->port + UART_IER);
| stop_bits[port->config.stop_bits]);
grub_outb (status, port->port + UART_LCR);
- /* In Yeeloong serial port has only 3 wires. */
-#ifndef GRUB_MACHINE_MIPS_YEELOONG
+ /* On Loongson machines serial port has only 3 wires. */
+#ifndef GRUB_MACHINE_MIPS_LOONGSON
/* Enable the FIFO. */
grub_outb (UART_ENABLE_FIFO_TRIGGER1, port->port + UART_FCR);
{
unsigned short divisor;
- divisor = serial_get_divisor (config->speed);
+ divisor = serial_get_divisor (port, config);
if (divisor == 0)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "bad speed");
#include <grub/extcmd.h>
#include <grub/i18n.h>
#include <grub/list.h>
+#ifdef GRUB_MACHINE_MIPS_LOONGSON
+#include <grub/machine/kernel.h>
+#endif
+
+GRUB_MOD_LICENSE ("GPLv3+");
#define FOR_SERIAL_PORTS(var) FOR_LIST_ELEMENTS((var), (grub_serial_ports))
#ifndef GRUB_MACHINE_EMU
if (!port && grub_memcmp (name, "port", sizeof ("port") - 1) == 0
- && grub_isdigit (name [sizeof ("port") - 1]))
+ && grub_isxdigit (name [sizeof ("port") - 1]))
{
name = grub_serial_ns8250_add_port (grub_strtoul (&name[sizeof ("port") - 1],
0, 16));
return GRUB_ERR_NONE;
}
+#ifdef GRUB_MACHINE_MIPS_LOONGSON
+const char loongson_defserial[][6] =
+ {
+ [GRUB_ARCH_MACHINE_YEELOONG] = "com0",
+ [GRUB_ARCH_MACHINE_FULOONG2F] = "com2",
+ [GRUB_ARCH_MACHINE_FULOONG2E] = "com1"
+ };
+#endif
+
grub_err_t
grub_serial_register (struct grub_serial_port *port)
{
port->term_in = in;
port->term_out = out;
grub_terminfo_output_register (out, "vt100");
-#ifdef GRUB_MACHINE_MIPS_YEELOONG
+#ifdef GRUB_MACHINE_MIPS_LOONGSON
+ if (grub_strcmp (port->name, loongson_defserial[grub_arch_machine]) == 0)
+ {
+ grub_term_register_input_active ("serial_*", in);
+ grub_term_register_output_active ("serial_*", out);
+ }
+ else
+ {
+ grub_term_register_input_inactive ("serial_*", in);
+ grub_term_register_output_inactive ("serial_*", out);
+ }
+#elif defined (GRUB_MACHINE_MIPS_QEMU_MIPS)
if (grub_strcmp (port->name, "com0") == 0)
{
grub_term_register_input_active ("serial_*", in);
grub_term_register_output_active ("serial_*", out);
}
else
-#endif
{
- grub_term_register_input ("serial_*", in);
- grub_term_register_output ("serial_*", out);
+ grub_term_register_input_inactive ("serial_*", in);
+ grub_term_register_output_inactive ("serial_*", out);
}
+#else
+ grub_term_register_input ("serial_*", in);
+ grub_term_register_output ("serial_*", out);
+#endif
return GRUB_ERR_NONE;
}
#include <grub/i18n.h>
#include <grub/time.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
+#define ANSI_C0 0x9b
+#define ANSI_C0_STR "\x9b"
+
static struct grub_term_output *terminfo_outputs;
/* Get current terminfo name. */
return grub_errno;
}
+ if (grub_strcmp ("arc", str) == 0)
+ {
+ data->name = grub_strdup ("arc");
+ data->gotoxy = grub_strdup (ANSI_C0_STR "%i%p1%d;%p2%dH");
+ data->cls = grub_strdup (ANSI_C0_STR "2J");
+ data->reverse_video_on = grub_strdup (ANSI_C0_STR "7m");
+ data->reverse_video_off = grub_strdup (ANSI_C0_STR "0m");
+ data->cursor_on = 0;
+ data->cursor_off = 0;
+ data->setcolor = grub_strdup (ANSI_C0_STR "3%p1%dm"
+ ANSI_C0_STR "4%p2%dm");
+ return grub_errno;
+ }
+
if (grub_strcmp ("ieee1275", str) == 0)
{
data->name = grub_strdup ("ieee1275");
return (data->width << 8) | data->height;
}
-#define ANSI_C0 0x9b
-
static void
grub_terminfo_readkey (struct grub_term_input *term, int *keys, int *len,
int (*readkey) (struct grub_term_input *term))
{'K', GRUB_TERM_KEY_END},
{'P', GRUB_TERM_KEY_DC},
{'?', GRUB_TERM_KEY_PPAGE},
- {'/', GRUB_TERM_KEY_NPAGE}
+ {'/', GRUB_TERM_KEY_NPAGE},
+ {'@', GRUB_TERM_KEY_INSERT},
};
static struct
{'5', GRUB_TERM_KEY_PPAGE},
{'6', GRUB_TERM_KEY_NPAGE}
};
+ char fx_key[] =
+ { 'P', 'Q', 'w', 'x', 't', 'u',
+ 'q', 'r', 'p', 'M', 'A', 'B' };
+ unsigned fx_code[] =
+ { GRUB_TERM_KEY_F1, GRUB_TERM_KEY_F2, GRUB_TERM_KEY_F3,
+ GRUB_TERM_KEY_F4, GRUB_TERM_KEY_F5, GRUB_TERM_KEY_F6,
+ GRUB_TERM_KEY_F7, GRUB_TERM_KEY_F8, GRUB_TERM_KEY_F9,
+ GRUB_TERM_KEY_F10, GRUB_TERM_KEY_F11, GRUB_TERM_KEY_F12 };
unsigned i;
if (c == '\e')
return;
}
- for (i = 0; i < ARRAY_SIZE (four_code_table); i++)
- if (four_code_table[i].key == c)
+ switch (c)
+ {
+ case 'O':
+ CONTINUE_READ;
+ for (i = 0; i < ARRAY_SIZE (fx_key); i++)
+ if (fx_key[i] == c)
+ {
+ keys[0] = fx_code[i];
+ *len = 1;
+ return;
+ }
+ return;
+
+ case '0':
{
+ int num = 0;
CONTINUE_READ;
- if (c != '~')
+ if (c != '0' && c != '1')
return;
- keys[0] = three_code_table[i].ascii;
+ num = (c - '0') * 10;
+ CONTINUE_READ;
+ if (c < '0' || c > '9')
+ return;
+ num += (c - '0');
+ if (num == 0 || num > 12)
+ return;
+ CONTINUE_READ;
+ if (c != 'q')
+ return;
+ keys[0] = fx_code[num - 1];
*len = 1;
return;
- }
- return;
+ }
+
+ default:
+ for (i = 0; i < ARRAY_SIZE (four_code_table); i++)
+ if (four_code_table[i].key == c)
+ {
+ CONTINUE_READ;
+ if (c != '~')
+ return;
+ keys[0] = three_code_table[i].ascii;
+ *len = 1;
+ return;
+ }
+ return;
+ }
}
#undef CONTINUE_READ
}
#include <grub/time.h>
#include <grub/keyboard_layouts.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
\f
enum
/* All tests need to include test.h for GRUB testing framework. */
#include <grub/test.h>
+#include <grub/dl.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
/* Functional test main method. */
static void
#include <grub/misc.h>
#include <grub/extcmd.h>
#include <grub/test.h>
+#include <grub/dl.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
static grub_err_t
grub_functional_test (grub_extcmd_context_t ctxt __attribute__ ((unused)),
#include <grub/extcmd.h>
#include <grub/script_sh.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
static grub_err_t
test_blockarg (grub_extcmd_context_t ctxt, int argc, char **args)
{
#include <grub/mm.h>
#include <grub/misc.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
/* List of bitmap readers registered to system. */
static grub_video_bitmap_reader_t bitmap_readers_list;
#include <grub/bitmap.h>
#include <grub/bitmap_scale.h>
#include <grub/types.h>
+#include <grub/dl.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
/* Prototypes for module-local functions. */
static grub_err_t scale_nn (struct grub_video_bitmap *dst,
#include <grub/pci.h>
#include <grub/vga.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
static struct
{
struct grub_video_mode_info mode_info;
#include <grub/pci.h>
#include <grub/vga.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
static struct
{
struct grub_video_mode_info mode_info;
--- /dev/null
+/* named_colors.c - Named color values. */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2008 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/types.h>
+#include <grub/gui.h>
+#include <grub/gui_string_util.h>
+#include <grub/misc.h>
+#include <grub/dl.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
+
+struct named_color
+{
+ const char *name;
+ grub_video_rgba_color_t color;
+};
+
+/*
+ Named color list generated from the list of SVG color keywords from
+ <http://www.w3.org/TR/css3-color/#svg-color>,
+ processed through the following Perl command:
+ perl -ne 'chomp;split;print "{ \"$_[0]\", RGB_COLOR($_[2]) },\n"'
+ */
+
+#define RGB_COLOR(r,g,b) {.red = r, .green = g, .blue = b, .alpha = 255}
+
+static struct named_color named_colors[] =
+{
+ { "aliceblue", RGB_COLOR(240,248,255) },
+ { "antiquewhite", RGB_COLOR(250,235,215) },
+ { "aqua", RGB_COLOR(0,255,255) },
+ { "aquamarine", RGB_COLOR(127,255,212) },
+ { "azure", RGB_COLOR(240,255,255) },
+ { "beige", RGB_COLOR(245,245,220) },
+ { "bisque", RGB_COLOR(255,228,196) },
+ { "black", RGB_COLOR(0,0,0) },
+ { "blanchedalmond", RGB_COLOR(255,235,205) },
+ { "blue", RGB_COLOR(0,0,255) },
+ { "blueviolet", RGB_COLOR(138,43,226) },
+ { "brown", RGB_COLOR(165,42,42) },
+ { "burlywood", RGB_COLOR(222,184,135) },
+ { "cadetblue", RGB_COLOR(95,158,160) },
+ { "chartreuse", RGB_COLOR(127,255,0) },
+ { "chocolate", RGB_COLOR(210,105,30) },
+ { "coral", RGB_COLOR(255,127,80) },
+ { "cornflowerblue", RGB_COLOR(100,149,237) },
+ { "cornsilk", RGB_COLOR(255,248,220) },
+ { "crimson", RGB_COLOR(220,20,60) },
+ { "cyan", RGB_COLOR(0,255,255) },
+ { "darkblue", RGB_COLOR(0,0,139) },
+ { "darkcyan", RGB_COLOR(0,139,139) },
+ { "darkgoldenrod", RGB_COLOR(184,134,11) },
+ { "darkgray", RGB_COLOR(169,169,169) },
+ { "darkgreen", RGB_COLOR(0,100,0) },
+ { "darkgrey", RGB_COLOR(169,169,169) },
+ { "darkkhaki", RGB_COLOR(189,183,107) },
+ { "darkmagenta", RGB_COLOR(139,0,139) },
+ { "darkolivegreen", RGB_COLOR(85,107,47) },
+ { "darkorange", RGB_COLOR(255,140,0) },
+ { "darkorchid", RGB_COLOR(153,50,204) },
+ { "darkred", RGB_COLOR(139,0,0) },
+ { "darksalmon", RGB_COLOR(233,150,122) },
+ { "darkseagreen", RGB_COLOR(143,188,143) },
+ { "darkslateblue", RGB_COLOR(72,61,139) },
+ { "darkslategray", RGB_COLOR(47,79,79) },
+ { "darkslategrey", RGB_COLOR(47,79,79) },
+ { "darkturquoise", RGB_COLOR(0,206,209) },
+ { "darkviolet", RGB_COLOR(148,0,211) },
+ { "deeppink", RGB_COLOR(255,20,147) },
+ { "deepskyblue", RGB_COLOR(0,191,255) },
+ { "dimgray", RGB_COLOR(105,105,105) },
+ { "dimgrey", RGB_COLOR(105,105,105) },
+ { "dodgerblue", RGB_COLOR(30,144,255) },
+ { "firebrick", RGB_COLOR(178,34,34) },
+ { "floralwhite", RGB_COLOR(255,250,240) },
+ { "forestgreen", RGB_COLOR(34,139,34) },
+ { "fuchsia", RGB_COLOR(255,0,255) },
+ { "gainsboro", RGB_COLOR(220,220,220) },
+ { "ghostwhite", RGB_COLOR(248,248,255) },
+ { "gold", RGB_COLOR(255,215,0) },
+ { "goldenrod", RGB_COLOR(218,165,32) },
+ { "gray", RGB_COLOR(128,128,128) },
+ { "green", RGB_COLOR(0,128,0) },
+ { "greenyellow", RGB_COLOR(173,255,47) },
+ { "grey", RGB_COLOR(128,128,128) },
+ { "honeydew", RGB_COLOR(240,255,240) },
+ { "hotpink", RGB_COLOR(255,105,180) },
+ { "indianred", RGB_COLOR(205,92,92) },
+ { "indigo", RGB_COLOR(75,0,130) },
+ { "ivory", RGB_COLOR(255,255,240) },
+ { "khaki", RGB_COLOR(240,230,140) },
+ { "lavender", RGB_COLOR(230,230,250) },
+ { "lavenderblush", RGB_COLOR(255,240,245) },
+ { "lawngreen", RGB_COLOR(124,252,0) },
+ { "lemonchiffon", RGB_COLOR(255,250,205) },
+ { "lightblue", RGB_COLOR(173,216,230) },
+ { "lightcoral", RGB_COLOR(240,128,128) },
+ { "lightcyan", RGB_COLOR(224,255,255) },
+ { "lightgoldenrodyellow", RGB_COLOR(250,250,210) },
+ { "lightgray", RGB_COLOR(211,211,211) },
+ { "lightgreen", RGB_COLOR(144,238,144) },
+ { "lightgrey", RGB_COLOR(211,211,211) },
+ { "lightpink", RGB_COLOR(255,182,193) },
+ { "lightsalmon", RGB_COLOR(255,160,122) },
+ { "lightseagreen", RGB_COLOR(32,178,170) },
+ { "lightskyblue", RGB_COLOR(135,206,250) },
+ { "lightslategray", RGB_COLOR(119,136,153) },
+ { "lightslategrey", RGB_COLOR(119,136,153) },
+ { "lightsteelblue", RGB_COLOR(176,196,222) },
+ { "lightyellow", RGB_COLOR(255,255,224) },
+ { "lime", RGB_COLOR(0,255,0) },
+ { "limegreen", RGB_COLOR(50,205,50) },
+ { "linen", RGB_COLOR(250,240,230) },
+ { "magenta", RGB_COLOR(255,0,255) },
+ { "maroon", RGB_COLOR(128,0,0) },
+ { "mediumaquamarine", RGB_COLOR(102,205,170) },
+ { "mediumblue", RGB_COLOR(0,0,205) },
+ { "mediumorchid", RGB_COLOR(186,85,211) },
+ { "mediumpurple", RGB_COLOR(147,112,219) },
+ { "mediumseagreen", RGB_COLOR(60,179,113) },
+ { "mediumslateblue", RGB_COLOR(123,104,238) },
+ { "mediumspringgreen", RGB_COLOR(0,250,154) },
+ { "mediumturquoise", RGB_COLOR(72,209,204) },
+ { "mediumvioletred", RGB_COLOR(199,21,133) },
+ { "midnightblue", RGB_COLOR(25,25,112) },
+ { "mintcream", RGB_COLOR(245,255,250) },
+ { "mistyrose", RGB_COLOR(255,228,225) },
+ { "moccasin", RGB_COLOR(255,228,181) },
+ { "navajowhite", RGB_COLOR(255,222,173) },
+ { "navy", RGB_COLOR(0,0,128) },
+ { "oldlace", RGB_COLOR(253,245,230) },
+ { "olive", RGB_COLOR(128,128,0) },
+ { "olivedrab", RGB_COLOR(107,142,35) },
+ { "orange", RGB_COLOR(255,165,0) },
+ { "orangered", RGB_COLOR(255,69,0) },
+ { "orchid", RGB_COLOR(218,112,214) },
+ { "palegoldenrod", RGB_COLOR(238,232,170) },
+ { "palegreen", RGB_COLOR(152,251,152) },
+ { "paleturquoise", RGB_COLOR(175,238,238) },
+ { "palevioletred", RGB_COLOR(219,112,147) },
+ { "papayawhip", RGB_COLOR(255,239,213) },
+ { "peachpuff", RGB_COLOR(255,218,185) },
+ { "peru", RGB_COLOR(205,133,63) },
+ { "pink", RGB_COLOR(255,192,203) },
+ { "plum", RGB_COLOR(221,160,221) },
+ { "powderblue", RGB_COLOR(176,224,230) },
+ { "purple", RGB_COLOR(128,0,128) },
+ { "red", RGB_COLOR(255,0,0) },
+ { "rosybrown", RGB_COLOR(188,143,143) },
+ { "royalblue", RGB_COLOR(65,105,225) },
+ { "saddlebrown", RGB_COLOR(139,69,19) },
+ { "salmon", RGB_COLOR(250,128,114) },
+ { "sandybrown", RGB_COLOR(244,164,96) },
+ { "seagreen", RGB_COLOR(46,139,87) },
+ { "seashell", RGB_COLOR(255,245,238) },
+ { "sienna", RGB_COLOR(160,82,45) },
+ { "silver", RGB_COLOR(192,192,192) },
+ { "skyblue", RGB_COLOR(135,206,235) },
+ { "slateblue", RGB_COLOR(106,90,205) },
+ { "slategray", RGB_COLOR(112,128,144) },
+ { "slategrey", RGB_COLOR(112,128,144) },
+ { "snow", RGB_COLOR(255,250,250) },
+ { "springgreen", RGB_COLOR(0,255,127) },
+ { "steelblue", RGB_COLOR(70,130,180) },
+ { "tan", RGB_COLOR(210,180,140) },
+ { "teal", RGB_COLOR(0,128,128) },
+ { "thistle", RGB_COLOR(216,191,216) },
+ { "tomato", RGB_COLOR(255,99,71) },
+ { "turquoise", RGB_COLOR(64,224,208) },
+ { "violet", RGB_COLOR(238,130,238) },
+ { "wheat", RGB_COLOR(245,222,179) },
+ { "white", RGB_COLOR(255,255,255) },
+ { "whitesmoke", RGB_COLOR(245,245,245) },
+ { "yellow", RGB_COLOR(255,255,0) },
+ { "yellowgreen", RGB_COLOR(154,205,50) },
+ { 0, { 0, 0, 0, 0 } } /* Terminator. */
+};
+
+/* Get the color named NAME. If the color was found, returns 1 and
+ stores the color into *COLOR. If the color was not found, returns 0 and
+ does not modify *COLOR. */
+int
+grub_video_get_named_color (const char *name,
+ grub_video_rgba_color_t *color)
+{
+ int i;
+ for (i = 0; named_colors[i].name; i++)
+ {
+ if (grub_strcmp (named_colors[i].name, name) == 0)
+ {
+ *color = named_colors[i].color;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static int
+parse_hex_color_component (const char *s, unsigned start, unsigned end)
+{
+ unsigned len;
+ char buf[3];
+
+ len = end - start;
+ /* Check the limits so we don't overrun the buffer. */
+ if (len < 1 || len > 2)
+ return 0;
+
+ if (len == 1)
+ {
+ buf[0] = s[start]; /* Get the first and only hex digit. */
+ buf[1] = buf[0]; /* Duplicate the hex digit. */
+ }
+ else if (len == 2)
+ {
+ buf[0] = s[start];
+ buf[1] = s[start + 1];
+ }
+
+ buf[2] = '\0';
+
+ return grub_strtoul (buf, 0, 16);
+}
+
+/* Parse a color string of the form "r, g, b", "#RGB", "#RGBA",
+ "#RRGGBB", or "#RRGGBBAA". */
+grub_err_t
+grub_video_parse_color (const char *s, grub_video_rgba_color_t *color)
+{
+ grub_video_rgba_color_t c;
+
+ /* Skip whitespace. */
+ while (*s && grub_isspace (*s))
+ s++;
+
+ if (*s == '#')
+ {
+ /* HTML-style. Number if hex digits:
+ [6] #RRGGBB [3] #RGB
+ [8] #RRGGBBAA [4] #RGBA */
+
+ s++; /* Skip the '#'. */
+ /* Count the hexits to determine the format. */
+ int hexits = 0;
+ const char *end = s;
+ while (grub_isxdigit (*end))
+ {
+ end++;
+ hexits++;
+ }
+
+ /* Parse the color components based on the format. */
+ if (hexits == 3 || hexits == 4)
+ {
+ c.red = parse_hex_color_component (s, 0, 1);
+ c.green = parse_hex_color_component (s, 1, 2);
+ c.blue = parse_hex_color_component (s, 2, 3);
+ if (hexits == 4)
+ c.alpha = parse_hex_color_component (s, 3, 4);
+ else
+ c.alpha = 255;
+ }
+ else if (hexits == 6 || hexits == 8)
+ {
+ c.red = parse_hex_color_component (s, 0, 2);
+ c.green = parse_hex_color_component (s, 2, 4);
+ c.blue = parse_hex_color_component (s, 4, 6);
+ if (hexits == 8)
+ c.alpha = parse_hex_color_component (s, 6, 8);
+ else
+ c.alpha = 255;
+ }
+ else
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
+ "invalid HTML-type color string `%s'", s);
+ }
+ else if (grub_isdigit (*s))
+ {
+ /* Comma separated decimal values. */
+ c.red = grub_strtoul (s, 0, 0);
+ if ((s = grub_strchr (s, ',')) == 0)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
+ "missing 1st comma separator in color `%s'", s);
+ s++;
+ c.green = grub_strtoul (s, 0, 0);
+ if ((s = grub_strchr (s, ',')) == 0)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
+ "missing 2nd comma separator in color `%s'", s);
+ s++;
+ c.blue = grub_strtoul (s, 0, 0);
+ if ((s = grub_strchr (s, ',')) == 0)
+ c.alpha = 255;
+ else
+ {
+ s++;
+ c.alpha = grub_strtoul (s, 0, 0);
+ }
+ }
+ else
+ {
+ if (! grub_video_get_named_color (s, &c))
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
+ "invalid named color `%s'", s);
+ }
+
+ if (grub_errno == GRUB_ERR_NONE)
+ *color = c;
+ return grub_errno;
+}
#include <grub/efi/efi.h>
#include <grub/efi/graphics_output.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
static grub_efi_guid_t graphics_output_guid = GRUB_EFI_GOP_GUID;
static struct grub_efi_gop *gop;
static unsigned old_mode;
#include <grub/efi/uga_draw.h>
#include <grub/pci.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
static grub_efi_guid_t uga_draw_guid = GRUB_EFI_UGA_DRAW_GUID;
static struct grub_efi_uga_draw_protocol *uga;
static grub_uint32_t uga_fb;
#include <grub/video_fb.h>
#include <SDL/SDL.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
static SDL_Surface *window = 0;
static struct grub_video_render_target *sdl_render_target;
static struct grub_video_mode_info mode_info;
#include <grub/fbfill.h>
#include <grub/fbutil.h>
#include <grub/bitmap.h>
+#include <grub/dl.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
static struct
{
#include <grub/err.h>
#include <grub/machine/memory.h>
-#include <grub/machine/vga.h>
-#include <grub/machine/vbe.h>
+#include <grub/i386/pc/vbe.h>
#include <grub/video_fb.h>
#include <grub/types.h>
#include <grub/dl.h>
#include <grub/misc.h>
#include <grub/mm.h>
#include <grub/video.h>
-#include <grub/machine/int.h>
+#include <grub/i386/pc/int.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
static int vbe_detected = -1;
return regs.eax & 0xffff;
}
+/* Call VESA BIOS 0x4f11 to get flat panel information, return status. */
+static grub_vbe_status_t
+grub_vbe_bios_get_flat_panel_info (struct grub_vbe_flat_panel_info *flat_panel_info)
+{
+ struct grub_bios_int_registers regs;
+
+ regs.eax = 0x4f11;
+ regs.ebx = 0x0001;
+ regs.es = (((grub_addr_t) flat_panel_info) & 0xffff0000) >> 4;
+ regs.edi = ((grub_addr_t) flat_panel_info) & 0xffff;
+ regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT;
+ grub_bios_interrupt (0x10, ®s);
+ return regs.eax & 0xffff;
+}
+
+/* Call VESA BIOS 0x4f15 to get DDC availability, return status. */
+static grub_vbe_status_t
+grub_vbe_bios_get_ddc_capabilities (grub_uint8_t *level)
+{
+ struct grub_bios_int_registers regs;
+
+ regs.eax = 0x4f15;
+ regs.ebx = 0x0000;
+ regs.ecx = 0x0000;
+ regs.es = 0x0000;
+ regs.edi = 0x0000;
+ regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT;
+ grub_bios_interrupt (0x10, ®s);
+
+ *level = regs.ebx & 0xff;
+ return regs.eax & 0xffff;
+}
+
+/* Call VESA BIOS 0x4f15 to read EDID information, return status. */
+static grub_vbe_status_t
+grub_vbe_bios_read_edid (struct grub_video_edid_info *edid_info)
+{
+ struct grub_bios_int_registers regs;
+
+ regs.eax = 0x4f15;
+ regs.ebx = 0x0001;
+ regs.ecx = 0x0000;
+ regs.edx = 0x0000;
+ regs.es = (((grub_addr_t) edid_info) & 0xffff0000) >> 4;
+ regs.edi = ((grub_addr_t) edid_info) & 0xffff;
+ regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT;
+ grub_bios_interrupt (0x10, ®s);
+ return regs.eax & 0xffff;
+}
+
grub_err_t
grub_vbe_probe (struct grub_vbe_info_block *info_block)
return GRUB_ERR_NONE;
}
+static grub_err_t
+grub_video_vbe_get_edid (struct grub_video_edid_info *edid_info)
+{
+ struct grub_video_edid_info *edid_info_lowmem;
+
+ /* Use low memory scratch area as temporary storage for VESA BIOS calls. */
+ edid_info_lowmem =
+ (struct grub_video_edid_info *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
+ grub_memset (edid_info_lowmem, 0, sizeof (*edid_info_lowmem));
+
+ if (grub_vbe_bios_read_edid (edid_info_lowmem) != GRUB_VBE_STATUS_OK)
+ return grub_error (GRUB_ERR_BAD_DEVICE, "EDID information not available");
+
+ grub_memcpy (edid_info, edid_info_lowmem, sizeof (*edid_info));
+
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_vbe_get_preferred_mode (unsigned int *width, unsigned int *height)
+{
+ grub_vbe_status_t status;
+ grub_uint8_t ddc_level;
+ struct grub_video_edid_info edid_info;
+ struct grub_vbe_flat_panel_info *flat_panel_info;
+
+ /* Use low memory scratch area as temporary storage for VESA BIOS calls. */
+ flat_panel_info = (struct grub_vbe_flat_panel_info *)
+ (GRUB_MEMORY_MACHINE_SCRATCH_ADDR + sizeof (struct grub_video_edid_info));
+ grub_memset (flat_panel_info, 0, sizeof (*flat_panel_info));
+
+ if (controller_info.version >= 0x200
+ && (grub_vbe_bios_get_ddc_capabilities (&ddc_level) & 0xff)
+ == GRUB_VBE_STATUS_OK)
+ {
+ if (grub_video_vbe_get_edid (&edid_info) == GRUB_ERR_NONE
+ && grub_video_edid_checksum (&edid_info) == GRUB_ERR_NONE
+ && grub_video_edid_preferred_mode (&edid_info, width, height)
+ == GRUB_ERR_NONE)
+ return GRUB_ERR_NONE;
+
+ grub_errno = GRUB_ERR_NONE;
+ }
+
+ status = grub_vbe_bios_get_flat_panel_info (flat_panel_info);
+ if (status == GRUB_VBE_STATUS_OK)
+ {
+ *width = flat_panel_info->horizontal_size;
+ *height = flat_panel_info->vertical_size;
+ return GRUB_ERR_NONE;
+ }
+
+ return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "cannot get preferred mode");
+}
+
grub_err_t
grub_vbe_set_video_mode (grub_uint32_t vbe_mode,
struct grub_vbe_mode_info_block *vbe_mode_info)
if (vbe_mode < 0x100)
{
/* If this is not a VESA mode, guess address. */
- framebuffer.ptr = (grub_uint8_t *) GRUB_MEMORY_MACHINE_VGA_ADDR;
+ framebuffer.ptr = (grub_uint8_t *) 0xa0000;
}
else
{
struct grub_vbe_mode_info_block best_vbe_mode_info;
grub_uint32_t best_vbe_mode = 0;
int depth;
+ int preferred_mode = 0;
/* Decode depth from mode_type. If it is zero, then autodetect. */
depth = (mode_type & GRUB_VIDEO_MODE_TYPE_DEPTH_MASK)
>> GRUB_VIDEO_MODE_TYPE_DEPTH_POS;
+ if (width == 0 && height == 0)
+ {
+ grub_vbe_get_preferred_mode (&width, &height);
+ if (grub_errno == GRUB_ERR_NONE)
+ preferred_mode = 1;
+ else
+ {
+ /* Fall back to 640x480. This is conservative, but the largest
+ mode supported by the graphics card may not be safe for the
+ display device. */
+ grub_errno = GRUB_ERR_NONE;
+ width = 640;
+ height = 480;
+ }
+ }
+
/* Walk thru mode list and try to find matching mode. */
for (p = vbe_mode_list; *p != 0xFFFF; p++)
{
/* Unsupported bitdepth . */
continue;
- if (((vbe_mode_info.x_resolution != width)
- || (vbe_mode_info.y_resolution != height)) && width != 0 && height != 0)
- /* Non matching resolution. */
- continue;
+ if (preferred_mode)
+ {
+ if (vbe_mode_info.x_resolution > width
+ || vbe_mode_info.y_resolution > height)
+ /* Resolution exceeds that of preferred mode. */
+ continue;
+ }
+ else
+ {
+ if (((vbe_mode_info.x_resolution != width)
+ || (vbe_mode_info.y_resolution != height))
+ && width != 0 && height != 0)
+ /* Non matching resolution. */
+ continue;
+ }
/* Check if user requested RGB or index color mode. */
if ((mode_mask & GRUB_VIDEO_MODE_TYPE_COLOR_MASK) != 0)
.set_active_render_target = grub_video_fb_set_active_render_target,
.get_active_render_target = grub_video_fb_get_active_render_target,
.iterate = grub_video_vbe_iterate,
+ .get_edid = grub_video_vbe_get_edid,
.print_adapter_specific_info = grub_video_vbe_print_adapter_specific_info,
.next = 0
#define grub_video_render_target grub_video_fbrender_target
-#include <grub/machine/vga.h>
-#include <grub/machine/int.h>
+#include <grub/i386/pc/int.h>
#include <grub/machine/console.h>
#include <grub/cpu/io.h>
#include <grub/mm.h>
#include <grub/misc.h>
#include <grub/vga.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
#define VGA_WIDTH 640
#define VGA_HEIGHT 350
-#define VGA_MEM ((grub_uint8_t *) GRUB_MEMORY_MACHINE_VGA_ADDR)
+#define VGA_MEM ((grub_uint8_t *) 0xa0000)
#define PAGE_OFFSET(x) ((x) * (VGA_WIDTH * VGA_HEIGHT / 8))
static unsigned char text_mode;
#include <grub/video_fb.h>
#include <grub/ieee1275/ieee1275.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
/* Only 8-bit indexed color is supported for now. */
static unsigned old_width, old_height;
--- /dev/null
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2005,2006,2007,2008,2009,2010,2011 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define grub_video_render_target grub_video_fbrender_target
+
+#include <grub/err.h>
+#include <grub/types.h>
+#include <grub/dl.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/video.h>
+#include <grub/video_fb.h>
+#include <grub/pci.h>
+#include <grub/vga.h>
+
+#define GRUB_RADEON_FULOONG2E_TOTAL_MEMORY_SPACE 1048576
+
+static struct
+{
+ struct grub_video_mode_info mode_info;
+ struct grub_video_render_target *render_target;
+
+ grub_uint8_t *ptr;
+ int mapped;
+ grub_uint32_t base;
+ grub_pci_device_t dev;
+} framebuffer;
+
+static grub_err_t
+grub_video_radeon_fuloong2e_video_init (void)
+{
+ /* Reset frame buffer. */
+ grub_memset (&framebuffer, 0, sizeof(framebuffer));
+
+ return grub_video_fb_init ();
+}
+
+static grub_err_t
+grub_video_radeon_fuloong2e_video_fini (void)
+{
+ if (framebuffer.mapped)
+ grub_pci_device_unmap_range (framebuffer.dev, framebuffer.ptr,
+ GRUB_RADEON_FULOONG2E_TOTAL_MEMORY_SPACE);
+
+ return grub_video_fb_fini ();
+}
+
+static grub_err_t
+grub_video_radeon_fuloong2e_setup (unsigned int width, unsigned int height,
+ unsigned int mode_type, unsigned int mode_mask __attribute__ ((unused)))
+{
+ int depth;
+ grub_err_t err;
+ int found = 0;
+
+#ifndef TEST
+ auto int NESTED_FUNC_ATTR find_card (grub_pci_device_t dev, grub_pci_id_t pciid __attribute__ ((unused)));
+ int NESTED_FUNC_ATTR find_card (grub_pci_device_t dev, grub_pci_id_t pciid __attribute__ ((unused)))
+ {
+ grub_pci_address_t addr;
+ grub_uint32_t class;
+
+ addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS);
+ class = grub_pci_read (addr);
+
+ if (((class >> 16) & 0xffff) != GRUB_PCI_CLASS_SUBCLASS_VGA
+ || pciid != 0x515a1002)
+ return 0;
+
+ found = 1;
+
+ addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0);
+ framebuffer.base = grub_pci_read (addr);
+ framebuffer.dev = dev;
+
+ return 1;
+ }
+
+ /* Decode depth from mode_type. If it is zero, then autodetect. */
+ depth = (mode_type & GRUB_VIDEO_MODE_TYPE_DEPTH_MASK)
+ >> GRUB_VIDEO_MODE_TYPE_DEPTH_POS;
+
+ if ((width != 640 && width != 0) || (height != 480 && height != 0)
+ || (depth != 16 && depth != 0))
+ return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
+ "Only 1024x600x16 is supported");
+
+ grub_pci_iterate (find_card);
+ if (!found)
+ return grub_error (GRUB_ERR_IO, "Couldn't find graphics card");
+#endif
+ /* Fill mode info details. */
+ framebuffer.mode_info.width = 640;
+ framebuffer.mode_info.height = 480;
+ framebuffer.mode_info.mode_type = GRUB_VIDEO_MODE_TYPE_RGB;
+ framebuffer.mode_info.bpp = 16;
+ framebuffer.mode_info.bytes_per_pixel = 2;
+ framebuffer.mode_info.pitch = 640 * 2;
+ framebuffer.mode_info.number_of_colors = 256;
+ framebuffer.mode_info.red_mask_size = 5;
+ framebuffer.mode_info.red_field_pos = 11;
+ framebuffer.mode_info.green_mask_size = 6;
+ framebuffer.mode_info.green_field_pos = 5;
+ framebuffer.mode_info.blue_mask_size = 5;
+ framebuffer.mode_info.blue_field_pos = 0;
+ framebuffer.mode_info.reserved_mask_size = 0;
+ framebuffer.mode_info.reserved_field_pos = 0;
+#ifndef TEST
+ framebuffer.mode_info.blit_format
+ = grub_video_get_blit_format (&framebuffer.mode_info);
+#endif
+
+ /* We can safely discard volatile attribute. */
+#ifndef TEST
+ framebuffer.ptr
+ = (void *) grub_pci_device_map_range (framebuffer.dev,
+ framebuffer.base,
+ GRUB_RADEON_FULOONG2E_TOTAL_MEMORY_SPACE);
+#endif
+ framebuffer.mapped = 1;
+
+ /* Prevent garbage from appearing on the screen. */
+ grub_memset (framebuffer.ptr, 0x55,
+ framebuffer.mode_info.height * framebuffer.mode_info.pitch);
+
+#ifndef TEST
+ err = grub_video_fb_create_render_target_from_pointer (&framebuffer
+ .render_target,
+ &framebuffer.mode_info,
+ framebuffer.ptr);
+
+ if (err)
+ return err;
+
+ err = grub_video_fb_set_active_render_target (framebuffer.render_target);
+
+ if (err)
+ return err;
+
+ /* Copy default palette to initialize emulated palette. */
+ err = grub_video_fb_set_palette (0, GRUB_VIDEO_FBSTD_NUMCOLORS,
+ grub_video_fbstd_colors);
+#endif
+ return err;
+}
+
+static grub_err_t
+grub_video_radeon_fuloong2e_swap_buffers (void)
+{
+ /* TODO: Implement buffer swapping. */
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_video_radeon_fuloong2e_set_active_render_target (struct grub_video_render_target *target)
+{
+ if (target == GRUB_VIDEO_RENDER_TARGET_DISPLAY)
+ target = framebuffer.render_target;
+
+ return grub_video_fb_set_active_render_target (target);
+}
+
+static grub_err_t
+grub_video_radeon_fuloong2e_get_info_and_fini (struct grub_video_mode_info *mode_info,
+ void **framebuf)
+{
+ grub_memcpy (mode_info, &(framebuffer.mode_info), sizeof (*mode_info));
+ *framebuf = (char *) framebuffer.ptr;
+
+ grub_video_fb_fini ();
+
+ return GRUB_ERR_NONE;
+}
+
+static struct grub_video_adapter grub_video_radeon_fuloong2e_adapter =
+ {
+ .name = "RADEON RV100 QZ (Fuloong2E) Video Driver",
+ .id = GRUB_VIDEO_DRIVER_RADEON_FULOONG2E,
+
+ .prio = GRUB_VIDEO_ADAPTER_PRIO_NATIVE,
+
+ .init = grub_video_radeon_fuloong2e_video_init,
+ .fini = grub_video_radeon_fuloong2e_video_fini,
+ .setup = grub_video_radeon_fuloong2e_setup,
+ .get_info = grub_video_fb_get_info,
+ .get_info_and_fini = grub_video_radeon_fuloong2e_get_info_and_fini,
+ .set_palette = grub_video_fb_set_palette,
+ .get_palette = grub_video_fb_get_palette,
+ .set_viewport = grub_video_fb_set_viewport,
+ .get_viewport = grub_video_fb_get_viewport,
+ .map_color = grub_video_fb_map_color,
+ .map_rgb = grub_video_fb_map_rgb,
+ .map_rgba = grub_video_fb_map_rgba,
+ .unmap_color = grub_video_fb_unmap_color,
+ .fill_rect = grub_video_fb_fill_rect,
+ .blit_bitmap = grub_video_fb_blit_bitmap,
+ .blit_render_target = grub_video_fb_blit_render_target,
+ .scroll = grub_video_fb_scroll,
+ .swap_buffers = grub_video_radeon_fuloong2e_swap_buffers,
+ .create_render_target = grub_video_fb_create_render_target,
+ .delete_render_target = grub_video_fb_delete_render_target,
+ .set_active_render_target = grub_video_radeon_fuloong2e_set_active_render_target,
+ .get_active_render_target = grub_video_fb_get_active_render_target,
+
+ .next = 0
+ };
+
+GRUB_MOD_INIT(video_radeon_fuloong2e)
+{
+ grub_video_register (&grub_video_radeon_fuloong2e_adapter);
+}
+
+GRUB_MOD_FINI(video_radeon_fuloong2e)
+{
+ grub_video_unregister (&grub_video_radeon_fuloong2e_adapter);
+}
#include <grub/misc.h>
#include <grub/bufio.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
/* Uncomment following define to enable JPEG debug. */
//#define JPEG_DEBUG
#define JPEG_MARKER_DQT 0xdb
#define JPEG_MARKER_SOF0 0xc0
#define JPEG_MARKER_SOS 0xda
+#define JPEG_MARKER_DRI 0xdd
+#define JPEG_MARKER_RST0 0xd0
+#define JPEG_MARKER_RST1 0xd1
+#define JPEG_MARKER_RST2 0xd2
+#define JPEG_MARKER_RST3 0xd3
+#define JPEG_MARKER_RST4 0xd4
+#define JPEG_MARKER_RST5 0xd5
+#define JPEG_MARKER_RST6 0xd6
+#define JPEG_MARKER_RST7 0xd7
#define SHIFT_BITS 8
#define CONST(x) ((int) ((x) * (1L << SHIFT_BITS) + 0.5))
{
grub_file_t file;
struct grub_video_bitmap **bitmap;
+ grub_uint8_t *bitmap_ptr;
int image_width;
int image_height;
jpeg_data_unit_t cbdu;
int vs, hs;
+ int dri;
+ int r1;
int dc_value[3];
return grub_errno;
}
+static grub_err_t
+grub_jpeg_decode_dri (struct grub_jpeg_data *data)
+{
+ if (grub_jpeg_get_word (data) != 4)
+ return grub_error (GRUB_ERR_BAD_FILE_TYPE,
+ "jpeg: DRI marker length must be 4");
+
+ data->dri = grub_jpeg_get_word (data);
+
+ return grub_errno;
+}
+
static void
grub_jpeg_idct_transform (jpeg_data_unit_t du)
{
static grub_err_t
grub_jpeg_decode_sos (struct grub_jpeg_data *data)
{
- int i, cc, r1, c1, nr1, nc1, vb, hb;
- grub_uint8_t *ptr1;
+ int i, cc;
grub_uint32_t data_offset;
data_offset = data->file->offset;
GRUB_VIDEO_BLIT_FORMAT_RGB_888))
return grub_errno;
- data->bit_mask = 0x0;
+ data->bitmap_ptr = (*data->bitmap)->data;
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_jpeg_decode_data (struct grub_jpeg_data *data)
+{
+ int c1, vb, hb, nr1, nc1;
+ int rst = data->dri;
vb = data->vs * 8;
hb = data->hs * 8;
nr1 = (data->image_height + vb - 1) / vb;
nc1 = (data->image_width + hb - 1) / hb;
- ptr1 = (*data->bitmap)->data;
- for (r1 = 0; r1 < nr1;
- r1++, ptr1 += (vb * data->image_width - hb * nc1) * 3)
- for (c1 = 0; c1 < nc1; c1++, ptr1 += hb * 3)
+ for (; data->r1 < nr1 && (!data->dri || rst);
+ data->r1++, data->bitmap_ptr += (vb * data->image_width - hb * nc1) * 3)
+ for (c1 = 0; c1 < nc1 && (!data->dri || rst);
+ c1++, rst--, data->bitmap_ptr += hb * 3)
{
int r2, c2, nr2, nc2;
grub_uint8_t *ptr2;
if (grub_errno)
return grub_errno;
- nr2 = (r1 == nr1 - 1) ? (data->image_height - r1 * vb) : vb;
+ nr2 = (data->r1 == nr1 - 1) ? (data->image_height - data->r1 * vb) : vb;
nc2 = (c1 == nc1 - 1) ? (data->image_width - c1 * hb) : hb;
- ptr2 = ptr1;
+ ptr2 = data->bitmap_ptr;
for (r2 = 0; r2 < nr2; r2++, ptr2 += (data->image_width - nc2) * 3)
for (c2 = 0; c2 < nc2; c2++, ptr2 += 3)
{
i0 = (r2 / data->vs) * 8 + (c2 / data->hs);
cr = data->crdu[i0];
cb = data->cbdu[i0];
- yy =
- data->ydu[(r2 / 8) * 2 + (c2 / 8)][(r2 % 8) * 8 + (c2 % 8)];
+ yy = data->ydu[(r2 / 8) * 2 + (c2 / 8)][(r2 % 8) * 8 + (c2 % 8)];
grub_jpeg_ycrcb_to_rgb (yy, cr, cb, ptr2);
}
return grub_errno;
}
+static void
+grub_jpeg_reset (struct grub_jpeg_data *data)
+{
+ data->bit_mask = 0x0;
+
+ data->dc_value[0] = 0;
+ data->dc_value[1] = 0;
+ data->dc_value[2] = 0;
+}
+
static grub_uint8_t
grub_jpeg_get_marker (struct grub_jpeg_data *data)
{
case JPEG_MARKER_SOF0: /* Start Of Frame 0. */
grub_jpeg_decode_sof (data);
break;
+ case JPEG_MARKER_DRI: /* Define Restart Interval. */
+ grub_jpeg_decode_dri (data);
+ break;
case JPEG_MARKER_SOS: /* Start Of Scan. */
- grub_jpeg_decode_sos (data);
+ if (grub_jpeg_decode_sos (data))
+ break;
+ case JPEG_MARKER_RST0: /* Restart. */
+ case JPEG_MARKER_RST1:
+ case JPEG_MARKER_RST2:
+ case JPEG_MARKER_RST3:
+ case JPEG_MARKER_RST4:
+ case JPEG_MARKER_RST5:
+ case JPEG_MARKER_RST6:
+ case JPEG_MARKER_RST7:
+ grub_jpeg_decode_data (data);
+ grub_jpeg_reset (data);
break;
case JPEG_MARKER_EOI: /* End Of Image. */
return grub_errno;
grub_jpeg_decode_jpeg (data);
for (i = 0; i < 4; i++)
- if (data->huff_value[i])
- grub_free (data->huff_value[i]);
+ grub_free (data->huff_value[i]);
grub_free (data);
}
#include <grub/misc.h>
#include <grub/bufio.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
/* Uncomment following define to enable PNG debug. */
//#define PNG_DEBUG
}
}
- if (blank_line)
- grub_free (blank_line);
+ grub_free (blank_line);
data->cur_column = 0;
data->first_line = 0;
#include <grub/misc.h>
#include <grub/bufio.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
/* Uncomment following define to enable TGA debug. */
//#define TGA_DEBUG
--- /dev/null
+static const struct { grub_uint8_t reg; grub_uint8_t val; } sr_dump [] =
+{
+ { 0x28, 0x81 },
+ { 0x2a, 0x00 },
+ { 0x29, 0xe1 },
+ { 0x2b, 0x81 },
+ { 0x2d, 0x00 },
+ { 0x2c, 0xe1 },
+ { 0x2e, 0x81 },
+ { 0x30, 0x00 },
+ { 0x2f, 0xe1 },
+ { 0x28, 0x01 },
+ { 0x29, 0x22 },
+ { 0x28, 0x3b },
+ { 0x29, 0x22 },
+ { 0x2a, 0x01 },
+ { 0x2e, 0x01 },
+ { 0x2f, 0x22 },
+ { 0x2e, 0x3b },
+ { 0x2f, 0x22 },
+ { 0x30, 0x01 },
+ { 0x15, 0x00 },
+ { 0x1b, 0x30 },
+
+ { 0x16, 0x0f },
+ { 0x16, 0x8f },
+ { 0x17, 0xba },
+ { 0x16, 0x0f },
+ { 0x16, 0x8f },
+ { 0x1f, 0x00 },
+ { 0x20, 0x20 },
+ { 0x23, 0xf6 },
+ { 0x24, 0x0d },
+ { 0x25, 0x33 },
+ { 0x21, 0x84 },
+ { 0x22, 0x00 },
+ { 0x27, 0x1f },
+ { 0x31, 0x00 },
+ { 0x33, 0x00 },
+ { 0x32, 0x11 },
+
+ { 0x25, 0x33 },
+
+ { 0x05, 0x86 },
+ { 0x01, 0x20 },
+ { 0x32, 0x11 },
+ { 0x1e, 0x00 },
+ { 0x1d, 0x00 },
+ { 0x00, 0x03 },
+ { 0x01, 0x21 },
+ { 0x02, 0x0f },
+ { 0x03, 0x00 },
+ { 0x04, 0x0e },
+
+ { 0x0a, 0x00 },
+ { 0x0b, 0x00 },
+ { 0x0c, 0x00 },
+ { 0x0d, 0x00 },
+ { 0x0e, 0x00 },
+ { 0x37, 0x00 },
+
+ { 0x0a, 0x00 },
+ { 0x0b, 0x00 },
+ { 0x0c, 0x05 },
+ { 0x0e, 0x00 },
+
+ { 0x0e, 0x00 },
+
+ { 0x10, 0x0b },
+ { 0x31, 0x00 },
+ { 0x2b, 0x01 },
+ { 0x2c, 0xe1 },
+ { 0x2b, 0x1b },
+ { 0x2c, 0xe1 },
+ { 0x2d, 0x01 },
+ { 0x3d, 0x00 },
+ { 0x08, 0x84 },
+ { 0x09, 0x00 },
+ { 0x3d, 0x01 },
+ { 0x1f, 0x00 },
+ { 0x06, 0x02 },
+
+ { 0x0f, 0x00 },
+ { 0x17, 0xba },
+ { 0x21, 0xa4 },
+ { 0x32, 0x11 },
+ { 0x07, 0x18 },
+
+ { 0x1d, 0x00 },
+ { 0x1d, 0x00 },
+ { 0x1d, 0x00 },
+ { 0x1d, 0x00 },
+ { 0x1d, 0x00 },
+ { 0x1d, 0x00 },
+ { 0x1d, 0x00 },
+ { 0x1d, 0x00 },
+ { 0x1d, 0x00 },
+ { 0x1d, 0x00 },
+ { 0x1d, 0x00 },
+ { 0x1d, 0x00 },
+ { 0x1d, 0x00 },
+ { 0x1d, 0x00 },
+ { 0x1d, 0x00 },
+ { 0x1d, 0x00 },
+ { 0x1d, 0x00 },
+
+ { 0x01, 0x01 },
+ { 0x21, 0x84 },
+ { 0x01, 0x21 },
+ { 0x16, 0x8f },
+ { 0x18, 0xa9 },
+ { 0x19, 0xa0 },
+ { 0x1b, 0x30 },
+ { 0x17, 0xb8 },
+ { 0x19, 0xa3 },
+ { 0x13, 0x00 },
+ { 0x14, 0x00 },
+ { 0x14, 0x02 },
+ { 0x15, 0x00 },
+ { 0x16, 0x0f },
+ { 0x16, 0x8f },
+ { 0x1d, 0x00 },
+ { 0x14, 0x00 },
+ { 0x14, 0x01 },
+ { 0x15, 0x00 },
+ { 0x16, 0x0f },
+ { 0x16, 0x8f },
+ { 0x1d, 0x00 },
+ { 0x14, 0x01 },
+ { 0x14, 0x01 },
+ { 0x15, 0x10 },
+ { 0x13, 0x35 },
+ { 0x14, 0x51 },
+ { 0x16, 0x0f },
+ { 0x16, 0x8f },
+ { 0x1d, 0x00 },
+ { 0x1d, 0x00 },
+ { 0x1d, 0x11 },
+ { 0x1d, 0x11 },
+ { 0x1d, 0x00 },
+ { 0x1d, 0x00 },
+ { 0x1d, 0x00 },
+ { 0x17, 0xba },
+ { 0x19, 0xa0 },
+ { 0x19, 0xa0 },
+ { 0x01, 0x01 },
+ { 0x16, 0x0f },
+ { 0x18, 0xa9 },
+ { 0x19, 0xa0 },
+ { 0x1b, 0x30 },
+ { 0x21, 0xa4 },
+ { 0x05, 0x86 },
+};
+
+static const grub_uint8_t gr[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0f,
+ 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
--- /dev/null
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2005,2006,2007,2008,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/>.
+ */
+
+#define grub_video_render_target grub_video_fbrender_target
+
+#include <grub/err.h>
+#include <grub/types.h>
+#include <grub/dl.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/video.h>
+#include <grub/video_fb.h>
+#include <grub/pci.h>
+#include <grub/vga.h>
+
+#define GRUB_SIS315PRO_PCIID 0x03251039
+#define GRUB_SIS315PRO_TOTAL_MEMORY_SPACE 0x800000
+#define GRUB_SIS315PRO_MMIO_SPACE 0x1000
+
+static struct
+{
+ struct grub_video_mode_info mode_info;
+ struct grub_video_render_target *render_target;
+
+ grub_uint8_t *ptr;
+ int mapped;
+ grub_uint32_t base;
+ grub_uint32_t mmiobase;
+ volatile grub_uint32_t *mmioptr;
+ grub_pci_device_t dev;
+ grub_port_t io;
+} framebuffer;
+
+static grub_uint8_t
+read_sis_cmd (grub_uint8_t addr)
+{
+ grub_outb (addr, framebuffer.io + 0x44);
+ return grub_inb (framebuffer.io + 0x45);
+}
+
+static void
+write_sis_cmd (grub_uint8_t val, grub_uint8_t addr)
+{
+ grub_outb (addr, framebuffer.io + 0x44);
+ grub_outb (val, framebuffer.io + 0x45);
+}
+
+#ifndef TEST
+static grub_err_t
+grub_video_sis315pro_video_init (void)
+{
+ /* Reset frame buffer. */
+ grub_memset (&framebuffer, 0, sizeof(framebuffer));
+
+ return grub_video_fb_init ();
+}
+
+static grub_err_t
+grub_video_sis315pro_video_fini (void)
+{
+ if (framebuffer.mapped)
+ grub_pci_device_unmap_range (framebuffer.dev, framebuffer.ptr,
+ GRUB_SIS315PRO_TOTAL_MEMORY_SPACE);
+
+ return grub_video_fb_fini ();
+}
+#endif
+
+#include "sis315_init.c"
+
+static grub_err_t
+grub_video_sis315pro_setup (unsigned int width, unsigned int height,
+ unsigned int mode_type,
+ unsigned int mode_mask __attribute__ ((unused)))
+{
+ int depth;
+ grub_err_t err;
+ int found = 0;
+ unsigned i;
+
+#ifndef TEST
+ auto int NESTED_FUNC_ATTR find_card (grub_pci_device_t dev, grub_pci_id_t pciid __attribute__ ((unused)));
+ int NESTED_FUNC_ATTR find_card (grub_pci_device_t dev, grub_pci_id_t pciid __attribute__ ((unused)))
+ {
+ grub_pci_address_t addr;
+ grub_uint32_t class;
+
+ addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS);
+ class = grub_pci_read (addr);
+
+ if (((class >> 16) & 0xffff) != GRUB_PCI_CLASS_SUBCLASS_VGA
+ || pciid != GRUB_SIS315PRO_PCIID)
+ return 0;
+
+ found = 1;
+
+ addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0);
+ framebuffer.base = grub_pci_read (addr) & GRUB_PCI_ADDR_MEM_MASK;
+ addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG1);
+ framebuffer.mmiobase = grub_pci_read (addr) & GRUB_PCI_ADDR_MEM_MASK;
+ addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG2);
+ framebuffer.io = (grub_pci_read (addr) & GRUB_PCI_ADDR_IO_MASK)
+ + GRUB_MACHINE_PCI_IO_BASE;
+ framebuffer.dev = dev;
+
+ return 1;
+ }
+
+ /* Decode depth from mode_type. If it is zero, then autodetect. */
+ depth = (mode_type & GRUB_VIDEO_MODE_TYPE_DEPTH_MASK)
+ >> GRUB_VIDEO_MODE_TYPE_DEPTH_POS;
+
+ if ((width != 640 && width != 0) || (height != 480 && height != 0)
+ || (depth != 8 && depth != 0))
+ return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
+ "Only 640x400x8 is supported");
+
+ grub_pci_iterate (find_card);
+ if (!found)
+ return grub_error (GRUB_ERR_IO, "Couldn't find graphics card");
+#endif
+ /* Fill mode info details. */
+ framebuffer.mode_info.width = 640;
+ framebuffer.mode_info.height = 480;
+ framebuffer.mode_info.mode_type = GRUB_VIDEO_MODE_TYPE_INDEX_COLOR;
+ framebuffer.mode_info.bpp = 8;
+ framebuffer.mode_info.bytes_per_pixel = 1;
+ framebuffer.mode_info.pitch = 640 * 1;
+ framebuffer.mode_info.number_of_colors = 256;
+ framebuffer.mode_info.red_mask_size = 0;
+ framebuffer.mode_info.red_field_pos = 0;
+ framebuffer.mode_info.green_mask_size = 0;
+ framebuffer.mode_info.green_field_pos = 0;
+ framebuffer.mode_info.blue_mask_size = 0;
+ framebuffer.mode_info.blue_field_pos = 0;
+ framebuffer.mode_info.reserved_mask_size = 0;
+ framebuffer.mode_info.reserved_field_pos = 0;
+#ifndef TEST
+ framebuffer.mode_info.blit_format
+ = grub_video_get_blit_format (&framebuffer.mode_info);
+#endif
+
+#ifndef TEST
+ if (found && (framebuffer.base == 0 || framebuffer.mmiobase == 0))
+ {
+ grub_pci_address_t addr;
+ /* FIXME: choose address dynamically if needed. */
+ framebuffer.base = 0x40000000;
+ framebuffer.mmiobase = 0x04000000;
+ framebuffer.io = 0xb300;
+
+ addr = grub_pci_make_address (framebuffer.dev, GRUB_PCI_REG_ADDRESS_REG0);
+ grub_pci_write (addr, framebuffer.base | GRUB_PCI_ADDR_MEM_PREFETCH);
+
+ addr = grub_pci_make_address (framebuffer.dev, GRUB_PCI_REG_ADDRESS_REG1);
+ grub_pci_write (addr, framebuffer.mmiobase);
+
+ addr = grub_pci_make_address (framebuffer.dev, GRUB_PCI_REG_ADDRESS_REG2);
+ grub_pci_write (addr, framebuffer.io | GRUB_PCI_ADDR_SPACE_IO);
+
+ /* Set latency. */
+ addr = grub_pci_make_address (framebuffer.dev, GRUB_PCI_REG_CACHELINE);
+ grub_pci_write (addr, 0x80004700);
+
+ /* Enable address spaces. */
+ addr = grub_pci_make_address (framebuffer.dev, GRUB_PCI_REG_COMMAND);
+ grub_pci_write (addr, 0x7);
+
+ addr = grub_pci_make_address (framebuffer.dev, 0x30);
+ grub_pci_write (addr, 0x04060001);
+
+ framebuffer.io += GRUB_MACHINE_PCI_IO_BASE;
+ }
+#endif
+
+
+ /* We can safely discard volatile attribute. */
+#ifndef TEST
+ framebuffer.ptr
+ = (void *) grub_pci_device_map_range (framebuffer.dev,
+ framebuffer.base,
+ GRUB_SIS315PRO_TOTAL_MEMORY_SPACE);
+ framebuffer.mmioptr = grub_pci_device_map_range (framebuffer.dev,
+ framebuffer.mmiobase,
+ GRUB_SIS315PRO_MMIO_SPACE);
+#endif
+ framebuffer.mapped = 1;
+
+#ifndef TEST
+ /* Prevent garbage from appearing on the screen. */
+ grub_memset (framebuffer.ptr, 0,
+ framebuffer.mode_info.height * framebuffer.mode_info.pitch);
+#endif
+
+ grub_outb (GRUB_VGA_IO_MISC_NEGATIVE_VERT_POLARITY
+ | GRUB_VGA_IO_MISC_NEGATIVE_HORIZ_POLARITY
+ | GRUB_VGA_IO_MISC_UPPER_64K
+ | GRUB_VGA_IO_MISC_EXTERNAL_CLOCK_0
+ | GRUB_VGA_IO_MISC_28MHZ
+ | GRUB_VGA_IO_MISC_ENABLE_VRAM_ACCESS
+ | GRUB_VGA_IO_MISC_COLOR,
+ GRUB_VGA_IO_MISC_WRITE + GRUB_MACHINE_PCI_IO_BASE);
+
+ grub_vga_sr_write (0x86, 5);
+ for (i = 6; i <= 0x27; i++)
+ grub_vga_sr_write (0, i);
+
+ for (i = 0x31; i <= 0x3d; i++)
+ grub_vga_sr_write (0, i);
+
+ for (i = 0; i < ARRAY_SIZE (sr_dump); i++)
+ grub_vga_sr_write (sr_dump[i].val, sr_dump[i].reg);
+
+ for (i = 0x30; i < 0x40; i++)
+ grub_vga_cr_write (0, i);
+
+ grub_vga_cr_write (0x77, 0x40);
+ grub_vga_cr_write (0x77, 0x41);
+ grub_vga_cr_write (0x00, 0x42);
+ grub_vga_cr_write (0x5b, 0x43);
+ grub_vga_cr_write (0x00, 0x44);
+ grub_vga_cr_write (0x23, 0x48);
+ grub_vga_cr_write (0xaa, 0x49);
+ grub_vga_cr_write (0x02, 0x37);
+ grub_vga_cr_write (0x20, 0x5b);
+ grub_vga_cr_write (0x00, 0x83);
+ grub_vga_cr_write (0x80, 0x63);
+
+ grub_vga_cr_write (0x0c, GRUB_VGA_CR_VSYNC_END);
+ grub_vga_cr_write (0x5f, GRUB_VGA_CR_HTOTAL);
+ grub_vga_cr_write (0x4f, GRUB_VGA_CR_HORIZ_END);
+ grub_vga_cr_write (0x50, GRUB_VGA_CR_HBLANK_START);
+ grub_vga_cr_write (0x82, GRUB_VGA_CR_HBLANK_END);
+ grub_vga_cr_write (0x54, GRUB_VGA_CR_HORIZ_SYNC_PULSE_START);
+ grub_vga_cr_write (0x80, GRUB_VGA_CR_HORIZ_SYNC_PULSE_END);
+ grub_vga_cr_write (0x0b, GRUB_VGA_CR_VERT_TOTAL);
+ grub_vga_cr_write (0x3e, GRUB_VGA_CR_OVERFLOW);
+ grub_vga_cr_write (0x00, GRUB_VGA_CR_BYTE_PANNING);
+ grub_vga_cr_write (0x40, GRUB_VGA_CR_CELL_HEIGHT);
+ grub_vga_cr_write (0x00, GRUB_VGA_CR_CURSOR_START);
+ grub_vga_cr_write (0x00, GRUB_VGA_CR_CURSOR_END);
+ grub_vga_cr_write (0x00, GRUB_VGA_CR_START_ADDR_HIGH_REGISTER);
+ grub_vga_cr_write (0x00, GRUB_VGA_CR_START_ADDR_LOW_REGISTER);
+ grub_vga_cr_write (0x00, GRUB_VGA_CR_CURSOR_ADDR_HIGH);
+ grub_vga_cr_write (0x00, GRUB_VGA_CR_CURSOR_ADDR_LOW);
+ grub_vga_cr_write (0xea, GRUB_VGA_CR_VSYNC_START);
+ grub_vga_cr_write (0x8c, GRUB_VGA_CR_VSYNC_END);
+ grub_vga_cr_write (0xdf, GRUB_VGA_CR_VDISPLAY_END);
+ grub_vga_cr_write (0x28, GRUB_VGA_CR_PITCH);
+ grub_vga_cr_write (0x40, GRUB_VGA_CR_UNDERLINE_LOCATION);
+ grub_vga_cr_write (0xe7, GRUB_VGA_CR_VERTICAL_BLANK_START);
+ grub_vga_cr_write (0x04, GRUB_VGA_CR_VERTICAL_BLANK_END);
+ grub_vga_cr_write (0xa3, GRUB_VGA_CR_MODE);
+ grub_vga_cr_write (0xff, GRUB_VGA_CR_LINE_COMPARE);
+
+ grub_vga_cr_write (0x0c, GRUB_VGA_CR_VSYNC_END);
+ grub_vga_cr_write (0x5f, GRUB_VGA_CR_HTOTAL);
+ grub_vga_cr_write (0x4f, GRUB_VGA_CR_HORIZ_END);
+ grub_vga_cr_write (0x50, GRUB_VGA_CR_HBLANK_START);
+ grub_vga_cr_write (0x82, GRUB_VGA_CR_HBLANK_END);
+ grub_vga_cr_write (0x55, GRUB_VGA_CR_HORIZ_SYNC_PULSE_START);
+ grub_vga_cr_write (0x81, GRUB_VGA_CR_HORIZ_SYNC_PULSE_END);
+ grub_vga_cr_write (0x0b, GRUB_VGA_CR_VERT_TOTAL);
+ grub_vga_cr_write (0x3e, GRUB_VGA_CR_OVERFLOW);
+ grub_vga_cr_write (0xe9, GRUB_VGA_CR_VSYNC_START);
+ grub_vga_cr_write (0x8b, GRUB_VGA_CR_VSYNC_END);
+ grub_vga_cr_write (0xdf, GRUB_VGA_CR_VDISPLAY_END);
+ grub_vga_cr_write (0xe7, GRUB_VGA_CR_VERTICAL_BLANK_START);
+ grub_vga_cr_write (0x04, GRUB_VGA_CR_VERTICAL_BLANK_END);
+ grub_vga_cr_write (0x40, GRUB_VGA_CR_CELL_HEIGHT);
+ grub_vga_cr_write (0x50, GRUB_VGA_CR_PITCH);
+
+ grub_vga_cr_write (0x00, 0x19);
+ grub_vga_cr_write (0x00, 0x1a);
+ grub_vga_cr_write (0x6c, 0x52);
+ grub_vga_cr_write (0x2e, 0x34);
+ grub_vga_cr_write (0x00, 0x31);
+
+
+ grub_vga_cr_write (0, GRUB_VGA_CR_START_ADDR_HIGH_REGISTER);
+ grub_vga_cr_write (0, GRUB_VGA_CR_START_ADDR_LOW_REGISTER);
+
+ for (i = 0; i < 16; i++)
+ grub_vga_write_arx (i, i);
+ grub_vga_write_arx (1, GRUB_VGA_ARX_MODE);
+ grub_vga_write_arx (0, GRUB_VGA_ARX_OVERSCAN);
+ grub_vga_write_arx (0, GRUB_VGA_ARX_COLOR_PLANE_ENABLE);
+ grub_vga_write_arx (0, GRUB_VGA_ARX_HORIZONTAL_PANNING);
+ grub_vga_write_arx (0, GRUB_VGA_ARX_COLOR_SELECT);
+
+ grub_outb (0xff, GRUB_VGA_IO_PIXEL_MASK + GRUB_MACHINE_PCI_IO_BASE);
+
+ for (i = 0; i < ARRAY_SIZE (gr); i++)
+ grub_vga_gr_write (gr[i], i);
+
+ for (i = 0; i < GRUB_VIDEO_FBSTD_NUMCOLORS; i++)
+ grub_vga_palette_write (i, grub_video_fbstd_colors[i].r,
+ grub_video_fbstd_colors[i].g,
+ grub_video_fbstd_colors[i].b);
+
+#if 1
+ {
+ if (read_sis_cmd (0x5) != 0xa1)
+ write_sis_cmd (0x86, 0x5);
+
+ write_sis_cmd (read_sis_cmd (0x20) | 0xa1, 0x20);
+ write_sis_cmd (read_sis_cmd (0x1e) | 0xda, 0x1e);
+
+#define IND_SIS_CMDQUEUE_SET 0x26
+#define IND_SIS_CMDQUEUE_THRESHOLD 0x27
+
+#define COMMAND_QUEUE_THRESHOLD 0x1F
+#define SIS_CMD_QUEUE_RESET 0x01
+
+#define SIS_AGP_CMDQUEUE_ENABLE 0x80 /* 315/330/340 series SR26 */
+#define SIS_VRAM_CMDQUEUE_ENABLE 0x40
+#define SIS_MMIO_CMD_ENABLE 0x20
+#define SIS_CMD_QUEUE_SIZE_512k 0x00
+#define SIS_CMD_QUEUE_SIZE_1M 0x04
+#define SIS_CMD_QUEUE_SIZE_2M 0x08
+#define SIS_CMD_QUEUE_SIZE_4M 0x0C
+#define SIS_CMD_QUEUE_RESET 0x01
+#define SIS_CMD_AUTO_CORR 0x02
+
+
+ write_sis_cmd (COMMAND_QUEUE_THRESHOLD, IND_SIS_CMDQUEUE_THRESHOLD);
+ write_sis_cmd (SIS_CMD_QUEUE_RESET, IND_SIS_CMDQUEUE_SET);
+ framebuffer.mmioptr[0x85C4 / 4] = framebuffer.mmioptr[0x85C8 / 4];
+ write_sis_cmd (SIS_MMIO_CMD_ENABLE | SIS_CMD_AUTO_CORR, IND_SIS_CMDQUEUE_SET);
+ framebuffer.mmioptr[0x85C0 / 4] = (0x1000000 - (512 * 1024));
+ }
+#endif
+
+#ifndef TEST
+ err = grub_video_fb_create_render_target_from_pointer (&framebuffer
+ .render_target,
+ &framebuffer.mode_info,
+ framebuffer.ptr);
+
+ if (err)
+ return err;
+
+ err = grub_video_fb_set_active_render_target (framebuffer.render_target);
+
+ if (err)
+ return err;
+
+ /* Copy default palette to initialize emulated palette. */
+ err = grub_video_fb_set_palette (0, GRUB_VIDEO_FBSTD_NUMCOLORS,
+ grub_video_fbstd_colors);
+#endif
+ return err;
+}
+
+#ifndef TEST
+
+static grub_err_t
+grub_video_sis315pro_swap_buffers (void)
+{
+ /* TODO: Implement buffer swapping. */
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_video_sis315pro_set_active_render_target (struct grub_video_render_target *target)
+{
+ if (target == GRUB_VIDEO_RENDER_TARGET_DISPLAY)
+ target = framebuffer.render_target;
+
+ return grub_video_fb_set_active_render_target (target);
+}
+
+static grub_err_t
+grub_video_sis315pro_get_info_and_fini (struct grub_video_mode_info *mode_info,
+ void **framebuf)
+{
+ grub_memcpy (mode_info, &(framebuffer.mode_info), sizeof (*mode_info));
+ *framebuf = (char *) framebuffer.ptr;
+
+ grub_video_fb_fini ();
+
+ return GRUB_ERR_NONE;
+}
+
+static struct grub_video_adapter grub_video_sis315pro_adapter =
+ {
+ .name = "SIS315PRO Video Driver",
+ .id = GRUB_VIDEO_DRIVER_SIS315PRO,
+
+ .prio = GRUB_VIDEO_ADAPTER_PRIO_NATIVE,
+
+ .init = grub_video_sis315pro_video_init,
+ .fini = grub_video_sis315pro_video_fini,
+ .setup = grub_video_sis315pro_setup,
+ .get_info = grub_video_fb_get_info,
+ .get_info_and_fini = grub_video_sis315pro_get_info_and_fini,
+ .set_palette = grub_video_fb_set_palette,
+ .get_palette = grub_video_fb_get_palette,
+ .set_viewport = grub_video_fb_set_viewport,
+ .get_viewport = grub_video_fb_get_viewport,
+ .map_color = grub_video_fb_map_color,
+ .map_rgb = grub_video_fb_map_rgb,
+ .map_rgba = grub_video_fb_map_rgba,
+ .unmap_color = grub_video_fb_unmap_color,
+ .fill_rect = grub_video_fb_fill_rect,
+ .blit_bitmap = grub_video_fb_blit_bitmap,
+ .blit_render_target = grub_video_fb_blit_render_target,
+ .scroll = grub_video_fb_scroll,
+ .swap_buffers = grub_video_sis315pro_swap_buffers,
+ .create_render_target = grub_video_fb_create_render_target,
+ .delete_render_target = grub_video_fb_delete_render_target,
+ .set_active_render_target = grub_video_sis315pro_set_active_render_target,
+ .get_active_render_target = grub_video_fb_get_active_render_target,
+
+ .next = 0
+ };
+
+GRUB_MOD_INIT(video_sis315pro)
+{
+ grub_video_register (&grub_video_sis315pro_adapter);
+}
+
+GRUB_MOD_FINI(video_sis315pro)
+{
+ grub_video_unregister (&grub_video_sis315pro_adapter);
+}
+#else
+int
+main ()
+{
+ grub_video_sis315pro_setup (640, 400, 0, 0);
+}
+#endif
#include <grub/misc.h>
#include <grub/mm.h>
+GRUB_MOD_LICENSE ("GPLv3+");
+
/* The list of video adapters registered to system. */
grub_video_adapter_t grub_video_adapter_list = NULL;
return grub_video_adapter_active->get_active_render_target (target);
}
+grub_err_t
+grub_video_edid_checksum (struct grub_video_edid_info *edid_info)
+{
+ const char *edid_bytes = (const char *) edid_info;
+ int i;
+ char checksum = 0;
+
+ /* Check EDID checksum. */
+ for (i = 0; i < 128; ++i)
+ checksum += edid_bytes[i];
+
+ if (checksum != 0)
+ return grub_error (GRUB_ERR_BAD_DEVICE,
+ "invalid EDID checksum %d", checksum);
+
+ grub_errno = GRUB_ERR_NONE;
+ return grub_errno;
+}
+
+grub_err_t
+grub_video_edid_preferred_mode (struct grub_video_edid_info *edid_info,
+ unsigned int *width, unsigned int *height)
+{
+ /* Bit 1 in the Feature Support field indicates that the first
+ Detailed Timing Description is the preferred timing mode. */
+ if (edid_info->version == 1 /* we don't understand later versions */
+ && (edid_info->feature_support
+ & GRUB_VIDEO_EDID_FEATURE_PREFERRED_TIMING_MODE)
+ && edid_info->detailed_timings[0].pixel_clock)
+ {
+ *width = edid_info->detailed_timings[0].horizontal_active_lo
+ | (((unsigned int)
+ (edid_info->detailed_timings[0].horizontal_hi & 0xf0))
+ << 4);
+ *height = edid_info->detailed_timings[0].vertical_active_lo
+ | (((unsigned int)
+ (edid_info->detailed_timings[0].vertical_hi & 0xf0))
+ << 4);
+ return GRUB_ERR_NONE;
+ }
+
+ return grub_error (GRUB_ERR_BAD_DEVICE, "no preferred mode available");
+}
+
/* Parse <width>x<height>[x<depth>]*/
static grub_err_t
parse_modespec (const char *current_mode, int *width, int *height, int *depth)
--- /dev/null
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2011 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_ARC_HEADER
+#define GRUB_ARC_HEADER 1
+
+#include <grub/types.h>
+#include <grub/symbol.h>
+
+typedef unsigned grub_arc_enum_t;
+typedef grub_uint64_t grub_arc_ularge_t;
+typedef unsigned long grub_arc_ulong_t;
+typedef long grub_arc_long_t;
+typedef unsigned short grub_arc_ushort_t;
+typedef unsigned char grub_arc_uchar_t;
+
+typedef grub_arc_long_t grub_arc_err_t;
+typedef grub_arc_ulong_t grub_arc_fileno_t;
+
+struct grub_arc_memory_descriptor
+{
+ grub_arc_enum_t type;
+ grub_arc_ulong_t start_page;
+ grub_arc_ulong_t num_pages;
+};
+
+enum grub_arc_memory_type
+ {
+ GRUB_ARC_MEMORY_EXCEPTION_BLOCK,
+ GRUB_ARC_MEMORY_SYSTEM_PARAMETER_BLOCK,
+#ifdef GRUB_CPU_WORDS_BIGENDIAN
+ GRUB_ARC_MEMORY_FREE_CONTIGUOUS,
+#endif
+ GRUB_ARC_MEMORY_FREE,
+ GRUB_ARC_MEMORY_BADRAM,
+ GRUB_ARC_MEMORY_LOADED, GRUB_ARC_MEMORY_FW_TEMPORARY,
+ GRUB_ARC_MEMORY_FW_PERMANENT,
+#ifndef GRUB_CPU_WORDS_BIGENDIAN
+ GRUB_ARC_MEMORY_FREE_CONTIGUOUS,
+#endif
+ } grub_arc_memory_type_t;
+
+struct grub_arc_timeinfo
+{
+ grub_arc_ushort_t y;
+ grub_arc_ushort_t m;
+ grub_arc_ushort_t d;
+ grub_arc_ushort_t h;
+ grub_arc_ushort_t min;
+ grub_arc_ushort_t s;
+ grub_arc_ushort_t ms;
+};
+
+struct grub_arc_display_status
+{
+ grub_arc_ushort_t x;
+ grub_arc_ushort_t y;
+ grub_arc_ushort_t w;
+ grub_arc_ushort_t h;
+ grub_arc_uchar_t fgcolor;
+ grub_arc_uchar_t bgcolor;
+ grub_arc_uchar_t high_intensity;
+ grub_arc_uchar_t underscored;
+ grub_arc_uchar_t reverse_video;
+};
+
+struct grub_arc_component
+{
+ grub_arc_enum_t class;
+ grub_arc_enum_t type;
+ grub_arc_enum_t flags;
+ grub_arc_ushort_t version;
+ grub_arc_ushort_t rev;
+ grub_arc_ulong_t key;
+ grub_arc_ulong_t affinity;
+ grub_arc_ulong_t configdatasize;
+ grub_arc_ulong_t idlen;
+ const char *idstr;
+};
+
+enum
+ {
+#ifdef GRUB_CPU_WORDS_BIGENDIAN
+ GRUB_ARC_COMPONENT_TYPE_ARC = 1,
+#else
+ GRUB_ARC_COMPONENT_TYPE_ARC,
+#endif
+ GRUB_ARC_COMPONENT_TYPE_CPU,
+ GRUB_ARC_COMPONENT_TYPE_FPU,
+ GRUB_ARC_COMPONENT_TYPE_PRI_I_CACHE,
+ GRUB_ARC_COMPONENT_TYPE_PRI_D_CACHE,
+ GRUB_ARC_COMPONENT_TYPE_SEC_I_CACHE,
+ GRUB_ARC_COMPONENT_TYPE_SEC_D_CACHE,
+ GRUB_ARC_COMPONENT_TYPE_SEC_CACHE,
+ GRUB_ARC_COMPONENT_TYPE_EISA,
+ GRUB_ARC_COMPONENT_TYPE_TCA,
+ GRUB_ARC_COMPONENT_TYPE_SCSI,
+ GRUB_ARC_COMPONENT_TYPE_DTIA,
+ GRUB_ARC_COMPONENT_TYPE_MULTIFUNC,
+ GRUB_ARC_COMPONENT_TYPE_DISK_CONTROLLER,
+ GRUB_ARC_COMPONENT_TYPE_TAPE_CONTROLLER,
+ GRUB_ARC_COMPONENT_TYPE_CDROM_CONTROLLER,
+ GRUB_ARC_COMPONENT_TYPE_WORM_CONTROLLER,
+ GRUB_ARC_COMPONENT_TYPE_SERIAL_CONTROLLER,
+ GRUB_ARC_COMPONENT_TYPE_NET_CONTROLLER,
+ GRUB_ARC_COMPONENT_TYPE_DISPLAY_CONTROLLER,
+ GRUB_ARC_COMPONENT_TYPE_PARALLEL_CONTROLLER,
+ GRUB_ARC_COMPONENT_TYPE_POINTER_CONTROLLER,
+ GRUB_ARC_COMPONENT_TYPE_KBD_CONTROLLER,
+ GRUB_ARC_COMPONENT_TYPE_AUDIO_CONTROLLER,
+ GRUB_ARC_COMPONENT_TYPE_OTHER_CONTROLLER,
+ GRUB_ARC_COMPONENT_TYPE_DISK,
+ GRUB_ARC_COMPONENT_TYPE_FLOPPY,
+ GRUB_ARC_COMPONENT_TYPE_TAPE,
+ GRUB_ARC_COMPONENT_TYPE_MODEM,
+ GRUB_ARC_COMPONENT_TYPE_MONITOR,
+ GRUB_ARC_COMPONENT_TYPE_PRINTER,
+ GRUB_ARC_COMPONENT_TYPE_POINTER,
+ GRUB_ARC_COMPONENT_TYPE_KBD,
+ GRUB_ARC_COMPONENT_TYPE_TERMINAL,
+ GRUB_ARC_COMPONENT_TYPE_OTHER_PERIPHERAL,
+ GRUB_ARC_COMPONENT_TYPE_LINE,
+ GRUB_ARC_COMPONENT_TYPE_NET,
+ GRUB_ARC_COMPONENT_TYPE_MEMORY_UNIT,
+ };
+
+struct grub_arc_fileinfo
+{
+ grub_arc_ularge_t start;
+ grub_arc_ularge_t end;
+ grub_arc_ularge_t current;
+ grub_arc_enum_t type;
+ grub_arc_ulong_t fnamelength;
+ grub_arc_uchar_t attr;
+ char filename[32];
+};
+
+struct grub_arc_firmware_vector
+{
+ /* 0x00. */
+ void *load;
+ void *invoke;
+ void *execute;
+ void *halt;
+
+ /* 0x10. */
+ void (*powerdown) (void);
+ void (*restart) (void);
+ void (*reboot) (void);
+ void (*exit) (void);
+
+ /* 0x20. */
+ void *reserved1;
+ const struct grub_arc_component * (*getpeer) (const struct grub_arc_component *comp);
+ const struct grub_arc_component * (*getchild) (const struct grub_arc_component *comp);
+ void *getparent;
+
+ /* 0x30. */
+ void *getconfigurationdata;
+ void *addchild;
+ void *deletecomponent;
+ void *getcomponent;
+
+ /* 0x40. */
+ void *saveconfiguration;
+ void *getsystemid;
+ struct grub_arc_memory_descriptor *(*getmemorydescriptor) (struct grub_arc_memory_descriptor *current);
+ void *reserved2;
+
+ /* 0x50. */
+ struct grub_arc_timeinfo *(*gettime) (void);
+ void *getrelativetime;
+ void *getdirectoryentry;
+ grub_arc_err_t (*open) (const char *path, grub_arc_enum_t mode,
+ grub_arc_fileno_t *fileno);
+
+ /* 0x60. */
+ grub_arc_err_t (*close) (grub_arc_fileno_t fileno);
+ grub_arc_err_t (*read) (grub_arc_fileno_t fileno, void *buf,
+ grub_arc_ulong_t n,
+ grub_arc_ulong_t *count);
+ grub_arc_err_t (*get_read_status) (grub_arc_fileno_t fileno);
+ grub_arc_err_t (*write) (grub_arc_fileno_t fileno, void *buf,
+ grub_arc_ulong_t n,
+ grub_arc_ulong_t *count);
+
+ /* 0x70. */
+ grub_arc_err_t (*seek) (grub_arc_fileno_t fileno,
+ grub_arc_ularge_t *pos, grub_arc_enum_t mode);
+ void *mount;
+ void *getenvironmentvariable;
+ void *setenvironmentvariable;
+
+ /* 0x80. */
+ grub_arc_err_t (*getfileinformation) (grub_arc_fileno_t fileno,
+ struct grub_arc_fileinfo *info);
+ void *setfileinformation;
+ void *flushallcaches;
+ void *testunicodecharacter;
+
+ /* 0x90. */
+ struct grub_arc_display_status * (*getdisplaystatus) (grub_arc_fileno_t fileno);
+};
+
+struct grub_arc_adapter
+{
+ grub_arc_ulong_t adapter_type;
+ grub_arc_ulong_t adapter_vector_length;
+ void *adapter_vector;
+};
+
+struct grub_arc_system_parameter_block
+{
+ grub_arc_ulong_t signature;
+ grub_arc_ulong_t length;
+ grub_arc_ushort_t version;
+ grub_arc_ushort_t revision;
+ void *restartblock;
+ void *debugblock;
+ void *gevector;
+ void *utlbmissvector;
+ grub_arc_ulong_t firmware_vector_length;
+ struct grub_arc_firmware_vector *firmwarevector;
+ grub_arc_ulong_t private_vector_length;
+ void *private_vector;
+ grub_arc_ulong_t adapter_count;
+ struct grub_arc_adapter adapters[0];
+};
+
+
+#define GRUB_ARC_SYSTEM_PARAMETER_BLOCK ((struct grub_arc_system_parameter_block *) 0xa0001000)
+#define GRUB_ARC_FIRMWARE_VECTOR (GRUB_ARC_SYSTEM_PARAMETER_BLOCK->firmwarevector)
+#define GRUB_ARC_STDIN 0
+#define GRUB_ARC_STDOUT 1
+
+int EXPORT_FUNC (grub_arc_iterate_devs) (int (*hook) (const char *name, const struct grub_arc_component *comp), int alt_names);
+
+#define FOR_ARC_CHILDREN(comp, parent) for (comp = GRUB_ARC_FIRMWARE_VECTOR->getchild (parent); comp; comp = GRUB_ARC_FIRMWARE_VECTOR->getpeer (comp))
+
+extern void grub_arcdisk_init (void);
+extern void grub_arcdisk_fini (void);
+
+
+#endif
--- /dev/null
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2008 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_CONSOLE_MACHINE_HEADER
+#define GRUB_CONSOLE_MACHINE_HEADER 1
+
+#include <grub/symbol.h>
+
+/* Initialize the console system. */
+void grub_console_init_early (void);
+void grub_console_init_lately (void);
+
+/* Finish the console system. */
+void grub_console_fini (void);
+
+#endif /* ! GRUB_CONSOLE_MACHINE_HEADER */
#include <grub/misc.h>
#include <grub/symbol.h>
+#include <grub/disk.h>
/* XXX: For now this only works on i386. */
#include <grub/cpu/io.h>
GRUB_ATA_CMD_PACKET = 0xa0,
GRUB_ATA_CMD_READ_SECTORS = 0x20,
GRUB_ATA_CMD_READ_SECTORS_EXT = 0x24,
+ GRUB_ATA_CMD_READ_SECTORS_DMA = 0xc8,
+ GRUB_ATA_CMD_READ_SECTORS_DMA_EXT = 0x25,
+
GRUB_ATA_CMD_SECURITY_FREEZE_LOCK = 0xf5,
GRUB_ATA_CMD_SET_FEATURES = 0xef,
GRUB_ATA_CMD_SLEEP = 0xe6,
GRUB_ATA_CMD_STANDBY_IMMEDIATE = 0xe0,
GRUB_ATA_CMD_WRITE_SECTORS = 0x30,
GRUB_ATA_CMD_WRITE_SECTORS_EXT = 0x34,
+ GRUB_ATA_CMD_WRITE_SECTORS_DMA_EXT = 0x35,
+ GRUB_ATA_CMD_WRITE_SECTORS_DMA = 0xca,
};
enum grub_ata_timeout_milliseconds
{
GRUB_ATA_TOUT_STD = 1000, /* 1s standard timeout. */
- GRUB_ATA_TOUT_DATA = 10000 /* 10s DATA I/O timeout. */
+ GRUB_ATA_TOUT_DATA = 10000, /* 10s DATA I/O timeout. */
+ GRUB_ATA_TOUT_SPINUP = 10000, /* Give the device 10s on first try to spinon. */
};
-struct grub_ata_device
+typedef union
{
- /* IDE port to use. */
- int port;
-
- /* IO addresses on which the registers for this device can be
- found. */
- grub_port_t ioaddress;
- grub_port_t ioaddress2;
+ grub_uint8_t raw[11];
+ struct
+ {
+ union
+ {
+ grub_uint8_t features;
+ grub_uint8_t error;
+ };
+ union
+ {
+ grub_uint8_t sectors;
+ grub_uint8_t atapi_ireason;
+ };
+ union
+ {
+ grub_uint8_t lba_low;
+ grub_uint8_t sectnum;
+ };
+ union
+ {
+ grub_uint8_t lba_mid;
+ grub_uint8_t cyllsb;
+ grub_uint8_t atapi_cntlow;
+ };
+ union
+ {
+ grub_uint8_t lba_high;
+ grub_uint8_t cylmsb;
+ grub_uint8_t atapi_cnthigh;
+ };
+ grub_uint8_t disk;
+ union
+ {
+ grub_uint8_t cmd;
+ grub_uint8_t status;
+ };
+ grub_uint8_t sectors48;
+ grub_uint8_t lba48_low;
+ grub_uint8_t lba48_mid;
+ grub_uint8_t lba48_high;
+ };
+} grub_ata_regs_t;
- /* Two devices can be connected to a single cable. Use this field
- to select device 0 (commonly known as "master") or device 1
- (commonly known as "slave"). */
- int device;
+/* ATA pass through parameters and function. */
+struct grub_disk_ata_pass_through_parms
+{
+ grub_ata_regs_t taskfile;
+ void * buffer;
+ grub_size_t size;
+ int write;
+ void *cmd;
+ int cmdsize;
+ int dma;
+};
+struct grub_ata
+{
/* Addressing methods available for accessing this device. If CHS
is only available, use that. Otherwise use LBA, except for the
high sectors. In that case use LBA48. */
/* Sector count. */
grub_uint64_t size;
+ grub_uint32_t log_sector_size;
/* CHS maximums. */
grub_uint16_t cylinders;
/* Set to 0 for ATA, set to 1 for ATAPI. */
int atapi;
- struct grub_ata_device *next;
+ int dma;
+
+ int *present;
+
+ void *data;
+
+ struct grub_ata_dev *dev;
};
-grub_err_t EXPORT_FUNC(grub_ata_wait_not_busy) (struct grub_ata_device *dev,
- int milliseconds);
-grub_err_t EXPORT_FUNC(grub_ata_wait_drq) (struct grub_ata_device *dev,
- int rw, int milliseconds);
-void EXPORT_FUNC(grub_ata_pio_read) (struct grub_ata_device *dev,
- char *buf, grub_size_t size);
+typedef struct grub_ata *grub_ata_t;
-static inline void
-grub_ata_regset (struct grub_ata_device *dev, int reg, int val)
+struct grub_ata_dev
{
- grub_outb (val, dev->ioaddress + reg);
-}
+ /* Call HOOK with each device name, until HOOK returns non-zero. */
+ int (*iterate) (int (*hook) (int id, int bus),
+ grub_disk_pull_t pull);
-static inline grub_uint8_t
-grub_ata_regget (struct grub_ata_device *dev, int reg)
-{
- return grub_inb (dev->ioaddress + reg);
-}
+ /* Open the device named NAME, and set up SCSI. */
+ grub_err_t (*open) (int id, int bus, struct grub_ata *scsi);
-static inline void
-grub_ata_regset2 (struct grub_ata_device *dev, int reg, int val)
-{
- grub_outb (val, dev->ioaddress2 + reg);
-}
+ /* Close the scsi device SCSI. */
+ void (*close) (struct grub_ata *ata);
-static inline grub_uint8_t
-grub_ata_regget2 (struct grub_ata_device *dev, int reg)
-{
- return grub_inb (dev->ioaddress2 + reg);
-}
+ /* Read SIZE bytes from the device SCSI into BUF after sending the
+ command CMD of size CMDSIZE. */
+ grub_err_t (*readwrite) (struct grub_ata *ata,
+ struct grub_disk_ata_pass_through_parms *parms,
+ int spinup);
-static inline grub_err_t
-grub_ata_check_ready (struct grub_ata_device *dev)
-{
- if (grub_ata_regget (dev, GRUB_ATA_REG_STATUS) & GRUB_ATA_STATUS_BUSY)
- return grub_ata_wait_not_busy (dev, GRUB_ATA_TOUT_STD);
+ /* The next scsi device. */
+ struct grub_ata_dev *next;
+};
+
+typedef struct grub_ata_dev *grub_ata_dev_t;
- return GRUB_ERR_NONE;
-}
+void grub_ata_dev_register (grub_ata_dev_t dev);
+void grub_ata_dev_unregister (grub_ata_dev_t dev);
#endif /* ! GRUB_ATA_HEADER */
struct grub_partition_bsd_disk_label
{
grub_uint32_t magic;
- grub_uint8_t padding[128];
+ grub_uint16_t type;
+ grub_uint8_t unused1[18];
+ grub_uint8_t packname[16];
+ grub_uint8_t unused2[92];
grub_uint32_t magic2;
grub_uint16_t checksum;
grub_uint16_t num_partitions;
void EXPORT_FUNC(grub_arch_sync_caches) (void *address, grub_size_t len);
#endif
+#ifdef _mips
+void EXPORT_FUNC(grub_arch_sync_dma_caches) (void *address, grub_size_t len);
+#else
+static inline void
+grub_arch_sync_dma_caches (void *address __attribute__ ((unused)),
+ grub_size_t len __attribute__ ((unused)))
+{
+}
+#endif
+
#endif /* ! GRUB_CACHE_HEADER */
#define GRUB_CMOS_H 1
#include <grub/types.h>
+#if !defined (__powerpc__) && !defined (__sparc__)
#include <grub/cpu/io.h>
#include <grub/cpu/cmos.h>
+#endif
#define GRUB_CMOS_INDEX_SECOND 0
#define GRUB_CMOS_INDEX_SECOND_ALARM 1
return (((a / 10) << 4) + (a % 10));
}
-static inline grub_uint8_t
-grub_cmos_read (grub_uint8_t index)
+#if !defined (__powerpc__) && !defined (__sparc__)
+static inline grub_err_t
+grub_cmos_read (grub_uint8_t index, grub_uint8_t *val)
{
grub_outb (index, GRUB_CMOS_ADDR_REG);
- return grub_inb (GRUB_CMOS_DATA_REG);
+ *val = grub_inb (GRUB_CMOS_DATA_REG);
+ return GRUB_ERR_NONE;
}
-static inline void
+static inline grub_err_t
grub_cmos_write (grub_uint8_t index, grub_uint8_t value)
{
grub_outb (index, GRUB_CMOS_ADDR_REG);
grub_outb (value, GRUB_CMOS_DATA_REG);
+ return GRUB_ERR_NONE;
+}
+#else
+grub_err_t grub_cmos_find_port (void);
+extern volatile grub_uint8_t *grub_cmos_port;
+
+static inline grub_err_t
+grub_cmos_read (grub_uint8_t index, grub_uint8_t *val)
+{
+ if (!grub_cmos_port)
+ {
+ grub_err_t err;
+ err = grub_cmos_find_port ();
+ if (err)
+ return err;
+ }
+ grub_cmos_port[0] = index;
+ *val = grub_cmos_port[1];
+ return GRUB_ERR_NONE;
}
+static inline grub_err_t
+grub_cmos_write (grub_uint8_t index, grub_uint8_t val)
+{
+ if (!grub_cmos_port)
+ {
+ grub_err_t err;
+ err = grub_cmos_find_port ();
+ if (err)
+ return err;
+ }
+ grub_cmos_port[0] = index;
+ grub_cmos_port[1] = val;
+ return GRUB_ERR_NONE;
+}
+
+#endif
+
#endif /* GRUB_CMOS_H */
gcry_cipher_decrypt_t decrypt;
gcry_cipher_stencrypt_t stencrypt;
gcry_cipher_stdecrypt_t stdecrypt;
+#ifdef GRUB_UTIL
+ const char *modname;
+#endif
struct gcry_cipher_spec *next;
} gcry_cipher_spec_t;
grub_size_t contextsize; /* allocate this amount of context */
/* Block size, needed for HMAC. */
grub_size_t blocksize;
+#ifdef GRUB_UTIL
+ const char *modname;
+#endif
struct gcry_md_spec *next;
} gcry_md_spec_t;
gcry_err_code_t
grub_crypto_ecb_decrypt (grub_crypto_cipher_handle_t cipher,
- void *out, void *in, grub_size_t size);
+ void *out, const void *in, grub_size_t size);
gcry_err_code_t
grub_crypto_ecb_encrypt (grub_crypto_cipher_handle_t cipher,
void *iv_in);
gcry_err_code_t
grub_crypto_cbc_decrypt (grub_crypto_cipher_handle_t cipher,
- void *out, void *in, grub_size_t size,
+ void *out, const void *in, grub_size_t size,
void *iv);
void
grub_cipher_register (gcry_cipher_spec_t *cipher);
grub_crypto_hmac_init (const struct gcry_md_spec *md,
const void *key, grub_size_t keylen);
void
-grub_crypto_hmac_write (struct grub_crypto_hmac_handle *hnd, void *data,
+grub_crypto_hmac_write (struct grub_crypto_hmac_handle *hnd,
+ const void *data,
grub_size_t datalen);
gcry_err_code_t
grub_crypto_hmac_fini (struct grub_crypto_hmac_handle *hnd, void *out);
gcry_err_code_t
grub_crypto_hmac_buffer (const struct gcry_md_spec *md,
const void *key, grub_size_t keylen,
- void *data, grub_size_t datalen, void *out);
+ const void *data, grub_size_t datalen, void *out);
extern gcry_md_spec_t _gcry_digest_spec_md5;
extern gcry_md_spec_t _gcry_digest_spec_sha1;
extern void (*grub_crypto_autoload_hook) (const char *name);
+#ifdef GRUB_UTIL
+void grub_gcry_init_all (void);
+void grub_gcry_fini_all (void);
+#endif
+
+
#endif
--- /dev/null
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2002,2003,2004,2005,2006,2007,2008,2009 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_CRYPTODISK_HEADER
+#define GRUB_CRYPTODISK_HEADER 1
+
+#include <grub/disk.h>
+#include <grub/crypto.h>
+#include <grub/list.h>
+
+typedef enum
+ {
+ GRUB_CRYPTODISK_MODE_ECB,
+ GRUB_CRYPTODISK_MODE_CBC,
+ GRUB_CRYPTODISK_MODE_PCBC,
+ GRUB_CRYPTODISK_MODE_XTS,
+ GRUB_CRYPTODISK_MODE_LRW
+ } grub_cryptodisk_mode_t;
+
+typedef enum
+ {
+ GRUB_CRYPTODISK_MODE_IV_NULL,
+ GRUB_CRYPTODISK_MODE_IV_PLAIN,
+ GRUB_CRYPTODISK_MODE_IV_PLAIN64,
+ GRUB_CRYPTODISK_MODE_IV_ESSIV,
+ GRUB_CRYPTODISK_MODE_IV_BENBI,
+ GRUB_CRYPTODISK_MODE_IV_BYTECOUNT64,
+ GRUB_CRYPTODISK_MODE_IV_BYTECOUNT64_HASH
+ } grub_cryptodisk_mode_iv_t;
+
+#define GRUB_CRYPTODISK_MAX_UUID_LENGTH 71
+
+#define GRUB_CRYPTODISK_GF_LOG_SIZE 7
+#define GRUB_CRYPTODISK_GF_SIZE (1U << GRUB_CRYPTODISK_GF_LOG_SIZE)
+#define GRUB_CRYPTODISK_GF_LOG_BYTES (GRUB_CRYPTODISK_GF_LOG_SIZE - 3)
+#define GRUB_CRYPTODISK_GF_BYTES (1U << GRUB_CRYPTODISK_GF_LOG_BYTES)
+
+struct grub_cryptodisk;
+
+typedef gcry_err_code_t
+(*grub_cryptodisk_rekey_func_t) (struct grub_cryptodisk *dev,
+ grub_uint64_t zoneno);
+
+struct grub_cryptodisk
+{
+ struct grub_cryptodisk *next;
+
+ char *source;
+ grub_disk_addr_t offset;
+ grub_disk_addr_t total_length;
+ grub_disk_t source_disk;
+ int ref;
+ grub_crypto_cipher_handle_t cipher;
+ grub_crypto_cipher_handle_t secondary_cipher;
+ grub_crypto_cipher_handle_t essiv_cipher;
+ const gcry_md_spec_t *essiv_hash, *hash, *iv_hash;
+ grub_cryptodisk_mode_t mode;
+ grub_cryptodisk_mode_iv_t mode_iv;
+ int benbi_log;
+ unsigned long id, source_id;
+ enum grub_disk_dev_id source_dev_id;
+ char uuid[GRUB_CRYPTODISK_MAX_UUID_LENGTH + 1];
+ grub_uint8_t lrw_key[GRUB_CRYPTODISK_GF_BYTES];
+ grub_uint8_t *lrw_precalc;
+ grub_uint8_t iv_prefix[64];
+ grub_size_t iv_prefix_len;
+#ifdef GRUB_UTIL
+ char *cheat;
+ const char *modname;
+ int cheat_fd;
+#endif
+ int log_sector_size;
+ grub_cryptodisk_rekey_func_t rekey;
+ int rekey_shift;
+ grub_uint8_t rekey_key[64];
+ grub_uint64_t last_rekey;
+ int rekey_derived_size;
+};
+typedef struct grub_cryptodisk *grub_cryptodisk_t;
+
+struct grub_cryptodisk_dev
+{
+ struct grub_cryptodisk_dev *next;
+
+ grub_cryptodisk_t (*scan) (grub_disk_t disk, const char *check_uuid,
+ int boot_only);
+ grub_err_t (*recover_key) (grub_disk_t disk, grub_cryptodisk_t dev);
+};
+typedef struct grub_cryptodisk_dev *grub_cryptodisk_dev_t;
+
+extern grub_cryptodisk_dev_t EXPORT_VAR (grub_cryptodisk_list);
+
+#ifndef GRUB_LST_GENERATOR
+static inline void
+grub_cryptodisk_dev_register (grub_cryptodisk_dev_t cr)
+{
+ grub_list_push (GRUB_AS_LIST_P (&grub_cryptodisk_list), GRUB_AS_LIST (cr));
+}
+#endif
+
+static inline void
+grub_cryptodisk_dev_unregister (grub_cryptodisk_dev_t cr)
+{
+ grub_list_remove (GRUB_AS_LIST_P (&grub_cryptodisk_list), GRUB_AS_LIST (cr));
+}
+
+#define FOR_CRYPTODISK_DEVS(var) FOR_LIST_ELEMENTS((var), (grub_cryptodisk_list))
+
+gcry_err_code_t
+grub_cryptodisk_setkey (grub_cryptodisk_t dev,
+ grub_uint8_t *key, grub_size_t keysize);
+gcry_err_code_t
+grub_cryptodisk_decrypt (struct grub_cryptodisk *dev,
+ grub_uint8_t * data, grub_size_t len,
+ grub_disk_addr_t sector);
+grub_err_t
+grub_cryptodisk_insert (grub_cryptodisk_t newdev, const char *name,
+ grub_disk_t source);
+#ifdef GRUB_UTIL
+grub_err_t
+grub_cryptodisk_cheat_insert (grub_cryptodisk_t newdev, const char *name,
+ grub_disk_t source, const char *cheat);
+void
+grub_util_cryptodisk_print_abstraction (grub_disk_t disk);
+char *
+grub_util_get_geli_uuid (const char *dev);
+#endif
+
+grub_cryptodisk_t grub_cryptodisk_get_by_uuid (const char *uuid);
+grub_cryptodisk_t grub_cryptodisk_get_by_source_disk (grub_disk_t disk);
+
+#endif
#endif
#define GRUB_CS5536_PCIID 0x208f1022
-#define GRUB_CS5536_MSR_MAILBOX_ADDR 0xf4
-#define GRUB_CS5536_MSR_MAILBOX_DATA0 0xf8
-#define GRUB_CS5536_MSR_MAILBOX_DATA1 0xfc
+#define GRUB_CS5536_MSR_MAILBOX_CONFIG_ENABLED 0x1
+#define GRUB_CS5536_MSR_MAILBOX_CONFIG 0xf0
+#define GRUB_CS5536_MSR_MAILBOX_ADDR 0xf4
+#define GRUB_CS5536_MSR_MAILBOX_DATA0 0xf8
+#define GRUB_CS5536_MSR_MAILBOX_DATA1 0xfc
#define GRUB_CS5536_MSR_IRQ_MAP_BAR 0x80000008
#define GRUB_CS5536_MSR_SMB_BAR 0x8000000b
#define GRUB_CS5536_MSR_DIVIL_LEG_IO_RTC_ENABLE1 0x00000002
#define GRUB_CS5536_MSR_DIVIL_LEG_IO_MODE_X86 0x10000000
#define GRUB_CS5536_MSR_DIVIL_LEG_IO_F_REMAP 0x04000000
+#define GRUB_CS5536_MSR_DIVIL_LEG_IO_UART1_COM1 0x00070000
+#define GRUB_CS5536_MSR_DIVIL_LEG_IO_UART2_COM3 0x00500000
+#define GRUB_CS5536_MSR_DIVIL_RESET 0x80000017
#define GRUB_CS5536_MSR_DIVIL_IRQ_MAPPER_PRIMARY_MASK 0x80000024
#define GRUB_CS5536_MSR_DIVIL_IRQ_MAPPER_LPC_MASK 0x80000025
#define GRUB_CS5536_DIVIL_LPC_INTERRUPTS 0x1002
#define GRUB_CS5536_MSR_DIVIL_LPC_SERIAL_IRQ_CONTROL 0x8000004e
#define GRUB_CS5536_MSR_DIVIL_LPC_SERIAL_IRQ_CONTROL_ENABLE 0x80
+#define GRUB_CS5536_MSR_DIVIL_UART1_CONF 0x8000003a
+#define GRUB_CS5536_MSR_DIVIL_UART2_CONF 0x8000003e
#define GRUB_CS5536_MSR_USB_OHCI_BASE 0x40000008
#define GRUB_CS5536_MSR_USB_EHCI_BASE 0x40000009
void grub_unixtime2datetime (grub_int32_t nix,
struct grub_datetime *datetime);
+static inline int
+grub_datetime2unixtime (const struct grub_datetime *datetime, grub_int32_t *nix)
+{
+ grub_int32_t ret;
+ int y4, ay;
+ const grub_uint16_t monthssum[12]
+ = { 0,
+ 31,
+ 31 + 28,
+ 31 + 28 + 31,
+ 31 + 28 + 31 + 30,
+ 31 + 28 + 31 + 30 + 31,
+ 31 + 28 + 31 + 30 + 31 + 30,
+ 31 + 28 + 31 + 30 + 31 + 30 + 31,
+ 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31,
+ 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30,
+ 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31,
+ 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30};
+ const grub_uint8_t months[12] = {31, 28, 31, 30, 31, 30,
+ 31, 31, 30, 31, 30, 31};
+ const int SECPERMIN = 60;
+ const int SECPERHOUR = 60 * SECPERMIN;
+ const int SECPERDAY = 24 * SECPERHOUR;
+ const int SECPERYEAR = 365 * SECPERDAY;
+ const int SECPER4YEARS = 4 * SECPERYEAR + SECPERDAY;
+
+ if (datetime->year > 2038 || datetime->year < 1901)
+ return 0;
+ if (datetime->month > 12 || datetime->month < 1)
+ return 0;
+
+ /* In the period of validity of unixtime all years divisible by 4
+ are bissextile*/
+ /* Convenience: let's have 3 consecutive non-bissextile years
+ at the beginning of the epoch. So count from 1971 instead of 1970 */
+ ret = SECPERYEAR + SECPERDAY;
+
+ /* Transform C divisions and modulos to mathematical ones */
+ y4 = (datetime->year - 1971) / 4;
+ if (datetime->year < 1971)
+ y4--;
+ ay = datetime->year - 1971 - 4 * y4;
+ ret += y4 * SECPER4YEARS;
+ ret += ay * SECPERYEAR;
+
+ ret += monthssum[datetime->month - 1] * SECPERDAY;
+ if (ay == 0 && datetime->month >= 3)
+ ret += SECPERDAY;
+
+ ret += (datetime->day - 1) * SECPERDAY;
+ if ((datetime->day > months[datetime->month - 1]
+ && (!ay || datetime->month != 2 || datetime->day != 29))
+ || datetime->day < 1)
+ return 0;
+
+ ret += datetime->hour * SECPERHOUR;
+ if (datetime->hour > 23)
+ return 0;
+ ret += datetime->minute * 60;
+ if (datetime->minute > 59)
+ return 0;
+
+ ret += datetime->second;
+ /* Accept leap seconds. */
+ if (datetime->second > 60)
+ return 0;
+
+ if ((datetime->year > 1980 && ret < 0)
+ || (datetime->year < 1960 && ret > 0))
+ return 0;
+ *nix = ret;
+ return 1;
+}
+
+#if defined (__powerpc__) || defined (__sparc__)
+grub_err_t
+grub_get_datetime_cmos (struct grub_datetime *datetime);
+grub_err_t
+grub_set_datetime_cmos (struct grub_datetime *datetime);
+#endif
#endif /* ! KERNEL_DATETIME_HEADER */
--- /dev/null
+/*
+ * 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/>.
+ */
+
+#ifndef GRUB_DEFLATE_HEADER
+#define GRUB_DEFLATE_HEADER 1
+
+grub_ssize_t
+grub_zlib_decompress (char *inbuf, grub_size_t insize, grub_off_t off,
+ char *outbuf, grub_size_t outsize);
+
+grub_err_t
+grub_zlib_disk_read (grub_disk_t disk, grub_disk_addr_t zlibstart,
+ grub_off_t off, char *outbuf, grub_size_t outsize);
+
+#endif
struct grub_disk;
struct grub_net;
-struct grub_fs;
struct grub_device
{
GRUB_DISK_DEVICE_PXE_ID,
GRUB_DISK_DEVICE_SCSI_ID,
GRUB_DISK_DEVICE_FILE_ID,
- GRUB_DISK_DEVICE_LUKS_ID
+ GRUB_DISK_DEVICE_CRYPTODISK_ID,
+ GRUB_DISK_DEVICE_ARCDISK_ID,
};
struct grub_disk;
struct grub_disk_memberlist;
#endif
+typedef enum
+ {
+ GRUB_DISK_PULL_NONE,
+ GRUB_DISK_PULL_REMOVABLE,
+ GRUB_DISK_PULL_RESCAN,
+ GRUB_DISK_PULL_MAX
+ } grub_disk_pull_t;
+
/* Disk device. */
struct grub_disk_dev
{
enum grub_disk_dev_id id;
/* Call HOOK with each device name, until HOOK returns non-zero. */
- int (*iterate) (int (*hook) (const char *name));
+ int (*iterate) (int (*hook) (const char *name),
+ grub_disk_pull_t pull);
/* Open the device named NAME, and set up DISK. */
grub_err_t (*open) (const char *name, struct grub_disk *disk);
/* The total number of sectors. */
grub_uint64_t total_sectors;
+ /* Logarithm of sector size. */
+ unsigned int log_sector_size;
+
/* The id used by the disk cache manager. */
unsigned long id;
/* The maximum number of disk caches. */
#define GRUB_DISK_CACHE_NUM 1021
-/* The size of a disk cache in sector units. */
-#define GRUB_DISK_CACHE_SIZE 8
-#define GRUB_DISK_CACHE_BITS 3
+/* The size of a disk cache in 512B units. Must be at least as big as the
+ largest supported sector size, currently 16K. */
+#define GRUB_DISK_CACHE_BITS 6
+#define GRUB_DISK_CACHE_SIZE (1 << GRUB_DISK_CACHE_BITS)
/* Return value of grub_disk_get_size() in case disk size is unknown. */
#define GRUB_DISK_SIZE_UNKNOWN 0xffffffffffffffffULL
grub_uint64_t EXPORT_FUNC(grub_disk_get_size) (grub_disk_t disk);
+#if DISK_CACHE_STATS
+void
+EXPORT_FUNC(grub_disk_cache_get_performance) (unsigned long *hits, unsigned long *misses);
+#endif
+
extern void (* EXPORT_VAR(grub_disk_firmware_fini)) (void);
extern int EXPORT_VAR(grub_disk_firmware_is_tainted);
-/* ATA pass through parameters and function. */
-struct grub_disk_ata_pass_through_parms
-{
- grub_uint8_t taskfile[8];
- void * buffer;
- int size;
-};
-
-extern grub_err_t (* EXPORT_VAR(grub_disk_ata_pass_through)) (grub_disk_t,
- struct grub_disk_ata_pass_through_parms *);
-
#if defined (GRUB_UTIL) || defined (GRUB_MACHINE_EMU)
void grub_lvm_init (void);
void grub_mdraid09_init (void);
#define GRUB_DL_H 1
#include <grub/symbol.h>
+#ifndef ASM_FILE
#include <grub/err.h>
#include <grub/types.h>
#include <grub/elf.h>
+#endif
/*
* Macros GRUB_MOD_INIT and GRUB_MOD_FINI are also used by build rules
* to collect module names, so we define them only when they are not
* defined already.
*/
+#ifndef ASM_FILE
#ifndef GRUB_MOD_INIT
#define GRUB_MOD_INIT(name) \
grub_mod_fini (void)
#endif
+#endif
+
+#ifndef ASM_FILE
#ifdef APPLE_CC
-#define GRUB_MOD_NAME(name) \
-static char grub_modname[] __attribute__ ((section ("_modname, _modname"), used)) = #name;
+#define GRUB_MOD_SECTION(x) "_" #x ", _" #x ""
+#else
+#define GRUB_MOD_SECTION(x) "." #x
+#endif
+#else
+#ifdef APPLE_CC
+#define GRUB_MOD_SECTION(x) _ ## x , _ ##x
+#else
+#define GRUB_MOD_SECTION(x) . ## x
+#endif
+#endif
+#ifndef ASM_FILE
#define GRUB_MOD_DEP(name) \
-__asm__ (".section _moddeps, _moddeps\n.asciz \"" #name "\"\n")
-#else
+static const char grub_module_depend_##name[] \
+ __attribute__((section(GRUB_MOD_SECTION(moddeps)), __used__)) = #name
#define GRUB_MOD_NAME(name) \
-__asm__ (".section .modname\n.asciz \"" #name "\"\n")
+static const char grub_module_name_##name[] \
+ __attribute__((section(GRUB_MOD_SECTION(modname)), __used__)) = #name
+#endif
+/* Me, Vladimir Serbinenko, hereby I add this module check as per new
+ GNU module policy. Note that this license check is informative only.
+ Modules have to be licensed under GPLv3 or GPLv3+ (optionally
+ multi-licensed under other licences as well) independently of the
+ presence of this check and solely by linking (module loading in GRUB
+ constitutes linking) and GRUB core being licensed under GPLv3+.
+ Be sure to understand your license obligations.
+*/
+#ifndef ASM_FILE
+#define GRUB_MOD_LICENSE(license) \
+ static char grub_module_license[] __attribute__ ((section (GRUB_MOD_SECTION (module_license)), used)) = "LICENSE=" license;
#define GRUB_MOD_DEP(name) \
-__asm__ (".section .moddeps\n.asciz \"" #name "\"\n")
+static const char grub_module_depend_##name[] \
+ __attribute__((section(GRUB_MOD_SECTION(moddeps)), __used__)) = #name
+#else
+#define GRUB_MOD_LICENSE(license) \
+ .section GRUB_MOD_SECTION(module_license), "a"; \
+ .ascii "LICENSE="; \
+ .ascii license; \
+ .byte 0
#endif
+/* Under GPL license obligations you have to distribute your module
+ under GPLv3(+). However, you can also distribute the same code under
+ another license as long as GPLv3(+) version is provided.
+*/
+#define GRUB_MOD_DUAL_LICENSE(x)
+
+#ifndef ASM_FILE
+
struct grub_dl_segment
{
struct grub_dl_segment *next;
Elf_Sym *symtab;
void (*init) (struct grub_dl *mod);
void (*fini) (void);
+#ifdef __ia64__
+ void *got;
+ void *tramp;
+#endif
+ void *base;
struct grub_dl *next;
};
typedef struct grub_dl *grub_dl_t;
grub_dl_t EXPORT_FUNC(grub_dl_get) (const char *name);
grub_err_t grub_dl_register_symbol (const char *name, void *addr,
- grub_dl_t mod);
+ int isfunc, grub_dl_t mod);
grub_err_t grub_arch_dl_check_header (void *ehdr);
grub_err_t grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr);
void grub_arch_dl_init_linker (void);
#endif
+#define GRUB_IA64_DL_TRAMP_ALIGN 16
+#define GRUB_IA64_DL_TRAMP_SIZE 48
+#define GRUB_IA64_DL_GOT_ALIGN 16
+
+void
+grub_ia64_dl_get_tramp_got_size (const void *ehdr, grub_size_t *tramp,
+ grub_size_t *got);
+
+#ifdef __ia64__
+#define GRUB_ARCH_DL_TRAMP_ALIGN 16
+#define GRUB_ARCH_DL_GOT_ALIGN 16
+#define grub_arch_dl_get_tramp_got_size grub_ia64_dl_get_tramp_got_size
+#endif
+
+#endif
+
#endif /* ! GRUB_DL_H */
{ 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b } \
}
+#define GRUB_EFI_SIMPLE_NETWORK_GUID \
+ { 0xa19832b9, 0xac25, 0x11d3, \
+ { 0x9a, 0x2d, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \
+ }
+
+#define GRUB_EFI_PXE_GUID \
+ { 0x03c4e603, 0xac28, 0x11d3, \
+ { 0x9a, 0x2d, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \
+ }
+
#define GRUB_EFI_DEVICE_PATH_GUID \
{ 0x09576e91, 0x6d3f, 0x11d2, \
{ 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b } \
};
typedef struct grub_efi_simple_text_output_interface grub_efi_simple_text_output_interface_t;
+typedef grub_uint8_t grub_efi_pxe_packet_t[1472];
+
+typedef struct grub_efi_pxe_mode
+{
+ grub_uint8_t unused[52];
+ grub_efi_pxe_packet_t dhcp_discover;
+ grub_efi_pxe_packet_t dhcp_ack;
+ grub_efi_pxe_packet_t proxy_offer;
+ grub_efi_pxe_packet_t pxe_discover;
+ grub_efi_pxe_packet_t pxe_reply;
+} grub_efi_pxe_mode_t;
+
+typedef struct grub_efi_pxe
+{
+ grub_uint64_t rev;
+ void (*start) (void);
+ void (*stop) (void);
+ void (*dhcp) (void);
+ void (*discover) (void);
+ void (*mftp) (void);
+ void (*udpwrite) (void);
+ void (*udpread) (void);
+ void (*setipfilter) (void);
+ void (*arp) (void);
+ void (*setparams) (void);
+ void (*setstationip) (void);
+ void (*setpackets) (void);
+ struct grub_efi_pxe_mode *mode;
+} grub_efi_pxe_t;
+
#define GRUB_EFI_BLACK 0x00
#define GRUB_EFI_BLUE 0x01
#define GRUB_EFI_GREEN 0x02
};
typedef struct grub_efi_block_io_media grub_efi_block_io_media_t;
+typedef grub_uint8_t grub_efi_mac_t[32];
+
+struct grub_efi_simple_network_mode
+{
+ grub_uint32_t state;
+ grub_uint32_t hwaddr_size;
+ grub_uint32_t media_header_size;
+ grub_uint32_t max_packet_size;
+ grub_uint32_t nvram_size;
+ grub_uint32_t nvram_access_size;
+ grub_uint32_t receive_filter_mask;
+ grub_uint32_t receive_filter_setting;
+ grub_uint32_t max_mcast_filter_count;
+ grub_uint32_t mcast_filter_count;
+ grub_efi_mac_t mcast_filter[16];
+ grub_efi_mac_t current_address;
+ grub_efi_mac_t broadcast_address;
+ grub_efi_mac_t permanent_address;
+ grub_uint8_t if_type;
+ grub_uint8_t mac_changeable;
+ grub_uint8_t multitx_supported;
+ grub_uint8_t media_present_supported;
+ grub_uint8_t media_present;
+};
+
+enum
+ {
+ GRUB_EFI_NETWORK_STOPPED,
+ GRUB_EFI_NETWORK_STARTED,
+ GRUB_EFI_NETWORK_INITIALIZED,
+ };
+
+struct grub_efi_simple_network
+{
+ grub_uint64_t revision;
+ grub_efi_status_t (*start) (struct grub_efi_simple_network *this);
+ void (*stop) (void);
+ grub_efi_status_t (*initialize) (struct grub_efi_simple_network *this,
+ grub_efi_uintn_t extra_rx,
+ grub_efi_uintn_t extra_tx);
+ void (*reset) (void);
+ void (*shutdown) (void);
+ void (*receive_filters) (void);
+ void (*station_address) (void);
+ void (*statistics) (void);
+ void (*mcastiptomac) (void);
+ void (*nvdata) (void);
+ void (*getstatus) (void);
+ grub_efi_status_t (*transmit) (struct grub_efi_simple_network *this,
+ grub_efi_uintn_t header_size,
+ grub_efi_uintn_t buffer_size,
+ void *buffer,
+ grub_efi_mac_t *src_addr,
+ grub_efi_mac_t *dest_addr,
+ grub_efi_uint16_t *protocol);
+ grub_efi_status_t (*receive) (struct grub_efi_simple_network *this,
+ grub_efi_uintn_t *header_size,
+ grub_efi_uintn_t *buffer_size,
+ void *buffer,
+ grub_efi_mac_t *src_addr,
+ grub_efi_mac_t *dest_addr,
+ grub_uint16_t *protocol);
+ void (*waitforpacket) (void);
+ struct grub_efi_simple_network_mode *mode;
+};
+typedef struct grub_efi_simple_network grub_efi_simple_network_t;
+
+
struct grub_efi_block_io
{
grub_efi_uint64_t revision;
};
typedef struct grub_efi_block_io grub_efi_block_io_t;
-#if GRUB_TARGET_SIZEOF_VOID_P == 4
+#if (GRUB_TARGET_SIZEOF_VOID_P == 4) || defined (__ia64__)
#define efi_call_0(func) func()
#define efi_call_1(func, a) func(a)
#define efi_call_4(func, a, b, c, d) func(a, b, c, d)
#define efi_call_5(func, a, b, c, d, e) func(a, b, c, d, e)
#define efi_call_6(func, a, b, c, d, e, f) func(a, b, c, d, e, f)
+#define efi_call_7(func, a, b, c, d, e, f, g) func(a, b, c, d, e, f, g)
#define efi_call_10(func, a, b, c, d, e, f, g, h, i, j) func(a, b, c, d, e, f, g, h, i, j)
#else
#define efi_call_0(func) \
efi_wrap_0(func)
#define efi_call_1(func, a) \
- efi_wrap_1(func, (grub_uint64_t) a)
+ efi_wrap_1(func, (grub_uint64_t) (a))
#define efi_call_2(func, a, b) \
- efi_wrap_2(func, (grub_uint64_t) a, (grub_uint64_t) b)
+ efi_wrap_2(func, (grub_uint64_t) (a), (grub_uint64_t) (b))
#define efi_call_3(func, a, b, c) \
- efi_wrap_3(func, (grub_uint64_t) a, (grub_uint64_t) b, (grub_uint64_t) c)
+ efi_wrap_3(func, (grub_uint64_t) (a), (grub_uint64_t) (b), \
+ (grub_uint64_t) (c))
#define efi_call_4(func, a, b, c, d) \
- efi_wrap_4(func, (grub_uint64_t) a, (grub_uint64_t) b, (grub_uint64_t) c, \
- (grub_uint64_t) d)
+ efi_wrap_4(func, (grub_uint64_t) (a), (grub_uint64_t) (b), \
+ (grub_uint64_t) (c), (grub_uint64_t) (d))
#define efi_call_5(func, a, b, c, d, e) \
- efi_wrap_5(func, (grub_uint64_t) a, (grub_uint64_t) b, (grub_uint64_t) c, \
- (grub_uint64_t) d, (grub_uint64_t) e)
+ efi_wrap_5(func, (grub_uint64_t) (a), (grub_uint64_t) (b), \
+ (grub_uint64_t) (c), (grub_uint64_t) (d), (grub_uint64_t) (e))
#define efi_call_6(func, a, b, c, d, e, f) \
- efi_wrap_6(func, (grub_uint64_t) a, (grub_uint64_t) b, (grub_uint64_t) c, \
- (grub_uint64_t) d, (grub_uint64_t) e, (grub_uint64_t) f)
+ efi_wrap_6(func, (grub_uint64_t) (a), (grub_uint64_t) (b), \
+ (grub_uint64_t) (c), (grub_uint64_t) (d), (grub_uint64_t) (e), \
+ (grub_uint64_t) (f))
+#define efi_call_7(func, a, b, c, d, e, f, g) \
+ efi_wrap_7(func, (grub_uint64_t) (a), (grub_uint64_t) (b), \
+ (grub_uint64_t) (c), (grub_uint64_t) (d), (grub_uint64_t) (e), \
+ (grub_uint64_t) (f), (grub_uint64_t) (g))
#define efi_call_10(func, a, b, c, d, e, f, g, h, i, j) \
- efi_wrap_10(func, (grub_uint64_t) a, (grub_uint64_t) b, (grub_uint64_t) c, \
- (grub_uint64_t) d, (grub_uint64_t) e, (grub_uint64_t) f, (grub_uint64_t) g, \
- (grub_uint64_t) h, (grub_uint64_t) i, (grub_uint64_t) j)
+ efi_wrap_10(func, (grub_uint64_t) (a), (grub_uint64_t) (b), \
+ (grub_uint64_t) (c), (grub_uint64_t) (d), (grub_uint64_t) (e), \
+ (grub_uint64_t) (f), (grub_uint64_t) (g), (grub_uint64_t) (h), \
+ (grub_uint64_t) (i), (grub_uint64_t) (j))
grub_uint64_t EXPORT_FUNC(efi_wrap_0) (void *func);
grub_uint64_t EXPORT_FUNC(efi_wrap_1) (void *func, grub_uint64_t arg1);
grub_uint64_t arg2, grub_uint64_t arg3,
grub_uint64_t arg4, grub_uint64_t arg5,
grub_uint64_t arg6);
+grub_uint64_t EXPORT_FUNC(efi_wrap_7) (void *func, grub_uint64_t arg1,
+ grub_uint64_t arg2, grub_uint64_t arg3,
+ grub_uint64_t arg4, grub_uint64_t arg5,
+ grub_uint64_t arg6, grub_uint64_t arg7);
grub_uint64_t EXPORT_FUNC(efi_wrap_10) (void *func, grub_uint64_t arg1,
grub_uint64_t arg2, grub_uint64_t arg3,
grub_uint64_t arg4, grub_uint64_t arg5,
grub_efi_uint32_t descriptor_version,
grub_efi_memory_descriptor_t *virtual_map);
+int
+EXPORT_FUNC (grub_efi_compare_device_paths) (const grub_efi_device_path_t *dp1,
+ const grub_efi_device_path_t *dp2);
+
+extern void (*EXPORT_VAR(grub_efi_net_config)) (grub_efi_handle_t hnd,
+ char **device,
+ char **path);
+
+grub_addr_t grub_efi_modules_addr (void);
+
void grub_efi_mm_init (void);
void grub_efi_mm_fini (void);
void grub_efi_init (void);
};
#define GRUB_PE32_MACHINE_I386 0x14c
+#define GRUB_PE32_MACHINE_IA64 0x200
#define GRUB_PE32_MACHINE_X86_64 0x8664
#define GRUB_PE32_RELOCS_STRIPPED 0x0001
#include <grub/symbol.h>
-/* This is destined to overflow when one hour passes by. */
-#define GRUB_TICKS_PER_SECOND ((1UL << 31) / 60 / 60 * 2)
+#define GRUB_TICKS_PER_SECOND 1000
/* Return the real time in ticks. */
grub_uint32_t EXPORT_FUNC (grub_get_rtc) (void);
#define ELF_ST_BIND(val) ELF32_ST_BIND(val)
#define ELF_ST_TYPE(val) ELF32_ST_TYPE(val)
+#define ELF_ST_INFO(a,b) ELF32_ST_INFO(a,b)
+
#define ELF_R_SYM(val) ELF32_R_SYM(val)
#define ELF_R_TYPE(val) ELF32_R_TYPE(val)
#define ELF_R_INFO(sym, type) ELF32_R_INFO(sym, type)
#define ELF_ST_BIND(val) ELF64_ST_BIND (val)
#define ELF_ST_TYPE(val) ELF64_ST_TYPE (val)
+#define ELF_ST_INFO(a,b) ELF64_ST_INFO(a,b)
#define ELF_R_SYM(val) ELF64_R_SYM(val)
#define ELF_R_TYPE(val) ELF64_R_TYPE(val)
#define ELF_R_INFO(sym, type) ELF64_R_INFO(sym, type)
--- /dev/null
+void EXPORT_FUNC (open64) (void);
+void EXPORT_FUNC (close) (void);
+void EXPORT_FUNC (read) (void);
+void EXPORT_FUNC (write) (void);
+void EXPORT_FUNC (ioctl) (void);
+
GRUB_DEV_ABSTRACTION_NONE,
GRUB_DEV_ABSTRACTION_LVM,
GRUB_DEV_ABSTRACTION_RAID,
+ GRUB_DEV_ABSTRACTION_LUKS,
+ GRUB_DEV_ABSTRACTION_GELI,
};
char *grub_find_device (const char *dir, dev_t dev);
char *grub_make_system_path_relative_to_its_root (const char *path);
const char *grub_util_check_block_device (const char *blk_dev);
const char *grub_util_check_char_device (const char *blk_dev);
+#ifdef __linux__
+char **grub_util_raid_getmembers (const char *name, int bootable);
+#endif
+#if defined (__FreeBSD__) || defined(__FreeBSD_kernel__)
+void grub_util_follow_gpart_up (const char *name, grub_disk_addr_t *off_out,
+ char **name_out);
+#endif
#endif /* ! GRUB_UTIL_GETROOT_HEADER */
#define GRUB_BIOSDISK_MACHINE_UTIL_HEADER 1
#include <grub/disk.h>
+#include <sys/types.h>
void grub_util_biosdisk_init (const char *dev_map);
void grub_util_biosdisk_fini (void);
const char *grub_util_biosdisk_get_osdev (grub_disk_t disk);
int grub_util_biosdisk_is_present (const char *name);
int grub_util_biosdisk_is_floppy (grub_disk_t disk);
+grub_err_t grub_util_biosdisk_flush (struct grub_disk *disk);
+void grub_util_pull_device (const char *osname);
+grub_err_t
+grub_util_fd_seek (int fd, const char *name, grub_uint64_t sector);
+ssize_t grub_util_fd_read (int fd, char *buf, size_t len);
+grub_err_t
+grub_cryptodisk_cheat_mount (const char *sourcedev, const char *cheat);
+void grub_util_cryptodisk_print_uuid (grub_disk_t disk);
+#if !defined(__MINGW32__)
+grub_uint64_t
+grub_util_get_fd_sectors (int fd, unsigned *log_secsize);
+#endif
#endif /* ! GRUB_BIOSDISK_MACHINE_UTIL_HEADER */
char *grub_make_system_path_relative_to_its_root (const char *path)
__attribute__ ((warn_unused_result));
+int
+grub_util_device_is_mapped (const char *dev);
void * EXPORT_FUNC(xmalloc) (grub_size_t size) __attribute__ ((warn_unused_result));
void * EXPORT_FUNC(xrealloc) (void *ptr, grub_size_t size) __attribute__ ((warn_unused_result));
int grub_device_mapper_supported (void);
#endif
+char *grub_find_root_device_from_mountinfo (const char *dir, char **relroot);
+
+void EXPORT_FUNC(grub_reboot) (void);
+
+
#endif /* GRUB_EMU_MISC_H */
GRUB_ERR_TIMEOUT,
GRUB_ERR_IO,
GRUB_ERR_ACCESS_DENIED,
- GRUB_ERR_EXTRACTOR
+ GRUB_ERR_EXTRACTOR,
+ GRUB_ERR_NET_BAD_ADDRESS,
+ GRUB_ERR_NET_ROUTE_LOOP,
+ GRUB_ERR_NET_NO_ROUTE,
+ GRUB_ERR_WAIT,
+ GRUB_ERR_BUG
}
grub_err_t;
--- /dev/null
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2000,2001,2002,2003,2004,2005,2007,2008,2009 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_FAT_H
+#define GRUB_FAT_H 1
+
+#include <grub/types.h>
+
+struct grub_fat_bpb
+{
+ grub_uint8_t jmp_boot[3];
+ grub_uint8_t oem_name[8];
+ grub_uint16_t bytes_per_sector;
+ grub_uint8_t sectors_per_cluster;
+ grub_uint16_t num_reserved_sectors;
+ grub_uint8_t num_fats;
+ grub_uint16_t num_root_entries;
+ grub_uint16_t num_total_sectors_16;
+ grub_uint8_t media;
+ grub_uint16_t sectors_per_fat_16;
+ grub_uint16_t sectors_per_track;
+ grub_uint16_t num_heads;
+ grub_uint32_t num_hidden_sectors;
+ grub_uint32_t num_total_sectors_32;
+ union
+ {
+ struct
+ {
+ grub_uint8_t num_ph_drive;
+ grub_uint8_t reserved;
+ grub_uint8_t boot_sig;
+ grub_uint32_t num_serial;
+ grub_uint8_t label[11];
+ grub_uint8_t fstype[8];
+ } __attribute__ ((packed)) fat12_or_fat16;
+ struct
+ {
+ grub_uint32_t sectors_per_fat_32;
+ grub_uint16_t extended_flags;
+ grub_uint16_t fs_version;
+ grub_uint32_t root_cluster;
+ grub_uint16_t fs_info;
+ grub_uint16_t backup_boot_sector;
+ grub_uint8_t reserved[12];
+ grub_uint8_t num_ph_drive;
+ grub_uint8_t reserved1;
+ grub_uint8_t boot_sig;
+ grub_uint32_t num_serial;
+ grub_uint8_t label[11];
+ grub_uint8_t fstype[8];
+ } __attribute__ ((packed)) fat32;
+ } __attribute__ ((packed)) version_specific;
+} __attribute__ ((packed));
+
+#endif
{
GRUB_FILE_FILTER_GZIO,
GRUB_FILE_FILTER_XZIO,
+ GRUB_FILE_FILTER_LZOPIO,
GRUB_FILE_FILTER_MAX,
GRUB_FILE_FILTER_COMPRESSION_FIRST = GRUB_FILE_FILTER_GZIO,
- GRUB_FILE_FILTER_COMPRESSION_LAST = GRUB_FILE_FILTER_XZIO,
+ GRUB_FILE_FILTER_COMPRESSION_LAST = GRUB_FILE_FILTER_LZOPIO,
} grub_file_filter_id_t;
typedef grub_file_t (*grub_file_filter_t) (grub_file_t in);
grub_font_t title_font;
grub_font_t message_font;
char *terminal_font_name;
- grub_gui_color_t title_color;
- grub_gui_color_t message_color;
- grub_gui_color_t message_bg_color;
+ grub_video_rgba_color_t title_color;
+ grub_video_rgba_color_t message_color;
+ grub_video_rgba_color_t message_bg_color;
struct grub_video_bitmap *desktop_image;
- grub_gui_color_t desktop_color;
+ grub_video_rgba_color_t desktop_color;
grub_gfxmenu_box_t terminal_box;
char *title_text;
char *progress_message_text;
void (*draw) (grub_gfxmenu_box_t self, int x, int y);
void (*set_content_size) (grub_gfxmenu_box_t self,
int width, int height);
+ int (*get_border_width) (grub_gfxmenu_box_t self);
int (*get_left_pad) (grub_gfxmenu_box_t self);
int (*get_top_pad) (grub_gfxmenu_box_t self);
int (*get_right_pad) (grub_gfxmenu_box_t self);
status changes. */
#define GRUB_GFXMENU_TIMEOUT_COMPONENT_ID "__timeout__"
-/* A representation of a color. Unlike grub_video_color_t, this
- representation is independent of any video mode specifics. */
-typedef struct grub_gui_color
-{
- grub_uint8_t red;
- grub_uint8_t green;
- grub_uint8_t blue;
- grub_uint8_t alpha;
-} grub_gui_color_t;
-
typedef struct grub_gui_component *grub_gui_component_t;
typedef struct grub_gui_container *grub_gui_container_t;
typedef struct grub_gui_list *grub_gui_list_t;
r->height);
}
-static __inline grub_gui_color_t
-grub_gui_color_rgb (int r, int g, int b)
-{
- grub_gui_color_t c;
- c.red = r;
- c.green = g;
- c.blue = b;
- c.alpha = 255;
- return c;
-}
-
-static __inline grub_video_color_t
-grub_gui_map_color (grub_gui_color_t c)
-{
- return grub_video_map_rgba (c.red, c.green, c.blue, c.alpha);
-}
-
static inline int
grub_video_have_common_points (const grub_video_rect_t *a,
const grub_video_rect_t *b)
char *grub_get_dirname (const char *file_path);
-int grub_gui_get_named_color (const char *name, grub_gui_color_t *color);
-
-grub_err_t grub_gui_parse_color (const char *s, grub_gui_color_t *color);
-
#endif /* GRUB_GUI_STRING_UTIL_HEADER */
struct grub_hfs_sblock
{
grub_uint16_t magic;
- grub_uint8_t unused[18];
+ grub_uint32_t ctime;
+ grub_uint32_t mtime;
+ grub_uint8_t unused[10];
grub_uint32_t blksz;
grub_uint8_t unused2[4];
grub_uint16_t first_block;
#include <grub/memory.h>
#endif
+#define GRUB_MEMORY_MACHINE_SCRATCH_ADDR 0x68000
+#define GRUB_MEMORY_MACHINE_SCRATCH_SEG (GRUB_MEMORY_MACHINE_SCRATCH_ADDR >> 4)
+#define GRUB_MEMORY_MACHINE_SCRATCH_SIZE 0x10000
+
#define GRUB_MEMORY_MACHINE_LOWER_USABLE 0x9fc00 /* 640 kiB - 1 kiB */
#define GRUB_MEMORY_MACHINE_UPPER_START 0x100000 /* 1 MiB */
#define GRUB_LINUX_VID_MODE_ASK 0xFFFD
#define GRUB_LINUX_VID_MODE_VESA_START 0x0300
-#define GRUB_LINUX_SETUP_MOVE_SIZE 0x9100
#define GRUB_LINUX_CL_MAGIC 0xA33F
#ifdef __x86_64__
grub_uint16_t pad1; /* Unused */
grub_uint32_t cmd_line_ptr; /* Points to the kernel command line */
grub_uint32_t initrd_addr_max; /* Highest address for initrd */
+ grub_uint32_t kernel_alignment;
+ grub_uint8_t relocatable;
+ grub_uint8_t pad[3];
+ grub_uint32_t cmdline_size;
} __attribute__ ((packed));
/* Boot parameters for Linux based on 2.6.12. This is used by the setup
#define NETBSD_BTINFO_BOOTPATH 0
#define NETBSD_BTINFO_ROOTDEVICE 1
+#define NETBSD_BTINFO_BOOTDISK 3
#define NETBSD_BTINFO_CONSOLE 6
#define NETBSD_BTINFO_SYMTAB 8
#define NETBSD_BTINFO_MEMMAP 9
+#define NETBSD_BTINFO_BOOTWEDGE 10
#define NETBSD_BTINFO_MODULES 11
#define NETBSD_BTINFO_FRAMEBUF 12
grub_uint32_t partition;
};
+struct grub_netbsd_btinfo_bootwedge {
+ grub_uint32_t biosdev;
+ grub_disk_addr_t startblk;
+ grub_uint64_t nblks;
+ grub_disk_addr_t matchblk;
+ grub_uint64_t matchnblks;
+ grub_uint8_t matchhash[16]; /* MD5 hash */
+} __packed;
+
struct grub_netbsd_btinfo_symtab
{
grub_uint32_t nsyms;
#include <grub/dl.h>
-/* Common function for normal and rescue mode commands. */
-typedef enum
- {
- GRUB_CHAINLOADER_FORCE = 0x1
- } grub_chainloader_flags_t;
+void
+grub_chainloader_patch_bpb (void *bs, grub_device_t dev, grub_uint8_t dl);
#endif /* GRUB_CHAINLOADER_MACHINE_HEADER */
#define GRUB_CPU_INT_FLAGS_INTERRUPT 0x200
#define GRUB_CPU_INT_FLAGS_DIRECTION 0x400
#define GRUB_CPU_INT_FLAGS_OVERFLOW 0x800
+#ifdef GRUB_MACHINE_PCBIOS
#define GRUB_CPU_INT_FLAGS_DEFAULT GRUB_CPU_INT_FLAGS_INTERRUPT
+#else
+#define GRUB_CPU_INT_FLAGS_DEFAULT 0
+#endif
+
void EXPORT_FUNC (grub_bios_interrupt) (grub_uint8_t intno,
struct grub_bios_int_registers *regs);
/* The boot BIOS drive number. */
extern grub_uint8_t EXPORT_VAR(grub_boot_drive);
+extern void (*EXPORT_VAR(grub_pc_net_config)) (char **device, char **path);
+
#endif /* ! ASM_FILE */
#endif /* ! KERNEL_MACHINE_HEADER */
#define GRUB_PXE_BOOTP_BCAST 0x8000
#if 1
-#define GRUB_PXE_BOOTP_DHCPVEND 1024 /* DHCP extended vendor field size. */
+#define GRUB_PXE_BOOTP_SIZE (1024 + 236) /* DHCP extended vendor field size. */
#else
-#define GRUB_PXE_BOOTP_DHCPVEND 312 /* DHCP standard vendor field size. */
+#define GRUB_PXE_BOOTP_SIZE (312 + 236) /* DHCP standard vendor field size. */
#endif
#define GRUB_PXE_MIN_BLKSIZE 512
#define GRUB_PXE_TFTP_PORT 69
-#define GRUB_PXE_VM_RFC1048 0x63825363L
-
#define GRUB_PXE_ERR_LEN 0xFFFFFFFF
#ifndef ASM_FILE
grub_uint16_t buffer_limit;
} __attribute__ ((packed));
-#define GRUB_PXE_MAC_ADDR_LEN 16
-
-typedef grub_uint8_t grub_pxe_mac_addr_t[GRUB_PXE_MAC_ADDR_LEN];
-
-struct grub_pxenv_boot_player
-{
- grub_uint8_t opcode;
- grub_uint8_t hw_type; /* hardware type. */
- grub_uint8_t hw_len; /* hardware addr len. */
- grub_uint8_t gate_hops; /* zero it. */
- grub_uint32_t ident; /* random number chosen by client. */
- grub_uint16_t seconds; /* seconds since did initial bootstrap. */
- grub_uint16_t flags;
- grub_uint32_t client_ip;
- grub_uint32_t your_ip;
- grub_uint32_t server_ip;
- grub_uint32_t gateway_ip;
- grub_pxe_mac_addr_t mac_addr;
- grub_uint8_t server_name[64];
- grub_uint8_t boot_file[128];
- union
- {
- grub_uint8_t d[GRUB_PXE_BOOTP_DHCPVEND]; /* raw array of vendor/dhcp options. */
- struct
- {
- grub_uint32_t magic; /* DHCP magic cookie. */
- grub_uint32_t flags; /* bootp flags/opcodes. */
- grub_uint8_t padding[56];
- } v;
- } vendor;
-} __attribute__ ((packed));
-
struct grub_pxenv_tftp_open
{
grub_uint16_t status;
extern struct grub_pxe_bangpxe *grub_pxe_pxenv;
-void grub_pxe_unload (void);
-
#endif
#endif /* GRUB_CPU_PXE_H */
#ifndef GRUB_VBE_MACHINE_HEADER
#define GRUB_VBE_MACHINE_HEADER 1
+#include <grub/video.h>
+
/* Default video mode to be used. */
#define GRUB_VBE_DEFAULT_VIDEO_MODE 0x101
grub_uint8_t alignment;
} __attribute__ ((packed));
+struct grub_vbe_flat_panel_info
+{
+ grub_uint16_t horizontal_size;
+ grub_uint16_t vertical_size;
+ grub_uint16_t panel_type;
+ grub_uint8_t red_bpp;
+ grub_uint8_t green_bpp;
+ grub_uint8_t blue_bpp;
+ grub_uint8_t reserved_bpp;
+ grub_uint32_t reserved_offscreen_mem_size;
+ grub_vbe_farptr_t reserved_offscreen_mem_ptr;
+
+ grub_uint8_t reserved[14];
+} __attribute__ ((packed));
+
/* Prototypes for helper functions. */
/* Call VESA BIOS 0x4f00 to get VBE Controller Information, return status. */
grub_vbe_status_t
+++ /dev/null
-/*
- * GRUB -- GRand Unified Bootloader
- * Copyright (C) 2003,2007,2008 Free Software Foundation, Inc.
- *
- * GRUB is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * GRUB is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef GRUB_VGA_MACHINE_HEADER
-#define GRUB_VGA_MACHINE_HEADER 1
-
-#include <grub/symbol.h>
-#include <grub/machine/memory.h>
-
-/* The VGA (at the beginning of upper memory). */
-#define GRUB_MEMORY_MACHINE_VGA_ADDR GRUB_MEMORY_MACHINE_UPPER
-
-#endif /* ! GRUB_VGA_MACHINE_HEADER */
--- /dev/null
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2011 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_REBOOT_H
+#define GRUB_REBOOT_H 1
+
+#ifndef ASM_FILE
+
+extern grub_uint8_t grub_reboot_end[], grub_reboot_start[];
+
+#endif
+
+#endif
grub_uint16_t ss;
grub_uint16_t sp;
grub_uint16_t ip;
+ grub_uint32_t ebx;
grub_uint32_t edx;
};
--- /dev/null
+#include <grub/efi/memory.h>
--- /dev/null
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2008 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef GRUB_MACHINE_TIME_HEADER
+#define GRUB_MACHINE_TIME_HEADER 1
+
+#include <grub/efi/time.h>
+
+#endif /* ! GRUB_MACHINE_TIME_HEADER */
--- /dev/null
+/*
+ * 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/>.
+ */
+
+#ifndef GRUB_CPU_KERNEL_HEADER
+#define GRUB_CPU_KERNEL_HEADER 1
+
+#define GRUB_MOD_ALIGN 0x1
+#define GRUB_MOD_GAP 0x0
+
+#endif /* ! GRUB_CPU_KERNEL_HEADER */
--- /dev/null
+/* Define the machine-dependent type `jmp_buf'. Linux/IA-64 version.
+ Copyright (C) 1999, 2000, 2008 Free Software Foundation, Inc.
+ Contributed by David Mosberger-Tang <davidm@hpl.hp.com>.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+/* User code must not depend on the internal representation of jmp_buf. */
+
+#define _JBLEN 70
+
+/* the __jmp_buf element type should be __float80 per ABI... */
+typedef long grub_jmp_buf[_JBLEN] __attribute__ ((aligned (16))); /* guarantees 128-bit alignment! */
+
+int grub_setjmp (grub_jmp_buf env);
+void grub_longjmp (grub_jmp_buf env, int val) __attribute__ ((noreturn));
--- /dev/null
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2007, 2008 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef KERNEL_CPU_TIME_HEADER
+#define KERNEL_CPU_TIME_HEADER 1
+
+static __inline void
+grub_cpu_idle (void)
+{
+ /* FIXME: not implemented */
+}
+
+#endif /* ! KERNEL_CPU_TIME_HEADER */
--- /dev/null
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2008 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_TYPES_CPU_HEADER
+#define GRUB_TYPES_CPU_HEADER 1
+
+/* The size of void *. */
+#define GRUB_TARGET_SIZEOF_VOID_P 8
+
+/* The size of long. */
+#define GRUB_TARGET_SIZEOF_LONG 8
+
+/* ia64 is little-endian (usually). */
+#undef GRUB_TARGET_WORDS_BIGENDIAN
+
+
+#endif /* ! GRUB_TYPES_CPU_HEADER */
#include <grub/types.h>
#include <grub/machine/ieee1275.h>
-/* Maps a device alias to a pathname. */
struct grub_ieee1275_devalias
{
char *name;
typedef grub_uint32_t grub_ieee1275_ihandle_t;
typedef grub_uint32_t grub_ieee1275_phandle_t;
+extern void (*EXPORT_VAR(grub_ieee1275_net_config)) (const char *dev,
+ char **device,
+ char **path);
+
+/* Maps a device alias to a pathname. */
extern grub_ieee1275_phandle_t EXPORT_VAR(grub_ieee1275_chosen);
extern grub_ieee1275_ihandle_t EXPORT_VAR(grub_ieee1275_mmu);
extern int (* EXPORT_VAR(grub_ieee1275_entry_fn)) (void *);
char *EXPORT_FUNC(grub_ieee1275_encode_devname) (const char *path);
char *EXPORT_FUNC(grub_ieee1275_get_filename) (const char *path);
-
int EXPORT_FUNC(grub_ieee1275_devices_iterate) (int (*hook)
(struct grub_ieee1275_devalias *
alias));
-
+char *EXPORT_FUNC(grub_ieee1275_get_aliasdevname) (const char *path);
char *EXPORT_FUNC(grub_ieee1275_canonicalise_devname) (const char *path);
+char *EXPORT_FUNC(grub_ieee1275_get_device_type) (const char *path);
#endif /* ! GRUB_IEEE1275_HEADER */
{
OBJ_TYPE_ELF,
OBJ_TYPE_MEMDISK,
- OBJ_TYPE_CONFIG
+ OBJ_TYPE_CONFIG,
+ OBJ_TYPE_PREFIX
};
/* The module header. */
#define grub_module_info grub_module_info32
#endif
-extern grub_addr_t grub_arch_modules_addr (void);
+extern grub_addr_t EXPORT_VAR (grub_modbase);
-extern void EXPORT_FUNC(grub_module_iterate) (int (*hook) (struct grub_module_header *));
+#define FOR_MODULES(var) for (\
+ var = grub_modbase ? (struct grub_module_header *) \
+ (grub_modbase + (((struct grub_module_info *) grub_modbase)->offset)) : 0;\
+ var && (grub_addr_t) var \
+ < (grub_modbase + (((struct grub_module_info *) grub_modbase)->size)); \
+ var = (struct grub_module_header *) \
+ ((char *) var + ((struct grub_module_header *) var)->size))
grub_addr_t grub_modules_get_end (void);
void EXPORT_FUNC(grub_machine_fini) (void);
/* The machine-specific prefix initialization. */
-void grub_machine_set_prefix (void);
+void
+grub_machine_get_bootlocation (char **device, char **path);
/* Register all the exported symbols. This is automatically generated. */
void grub_register_exported_symbols (void);
-#if ! defined (ASM_FILE) && !defined (GRUB_MACHINE_EMU)
-extern char grub_prefix[];
-#endif
+extern void (*EXPORT_VAR(grub_net_poll_cards_idle)) (void);
#endif /* ! GRUB_KERNEL_HEADER */
--- /dev/null
+/* crc.h - prototypes for crc */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2008 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_CRC_H
+#define GRUB_CRC_H 1
+
+grub_uint32_t grub_getcrc32c (grub_uint32_t crc, const void *buf, int size);
+
+#endif /* ! GRUB_CRC_H */
# ifdef HAVE___BSWAPDI2
void EXPORT_FUNC (__bswapdi2) (void);
# endif
+# ifdef HAVE___UDIVSI3
+void EXPORT_FUNC (__udivsi3) (void);
+# endif
+# ifdef HAVE___UMODSI3
+void EXPORT_FUNC (__umodsi3) (void);
+# endif
+# ifdef HAVE___UMODDI3
+void EXPORT_FUNC (__umoddi3) (void);
+# endif
+# ifdef HAVE___UDIVDI3
+void EXPORT_FUNC (__udivdi3) (void);
+# endif
+# ifdef HAVE___MODDI3
+void EXPORT_FUNC (__moddi3) (void);
+# endif
+# ifdef HAVE___DIVDI3
+void EXPORT_FUNC (__divdi3) (void);
+# endif
+# ifdef HAVE___DIVSI3
+void EXPORT_FUNC (__divsi3) (void);
+# endif
+# ifdef HAVE___MODSI3
+void EXPORT_FUNC (__modsi3) (void);
+# endif
+# ifdef HAVE___CTZDI2
+void EXPORT_FUNC (__ctzdi2) (void);
+# endif
+# ifdef HAVE___CTZSI2
+void EXPORT_FUNC (__ctzsi2) (void);
+# endif
#endif
+# ifdef HAVE___IA64_TRAMPOLINE
+void EXPORT_FUNC (__ia64_trampoline) (void);
+# endif
+
#ifdef HAVE___TRAMPOLINE_SETUP
void EXPORT_FUNC (__trampoline_setup) (void);
#endif
grub_loader_preboot_hook_prio_t prio);
/* Unregister given preboot hook. */
-void grub_loader_unregister_preboot_hook (void *hnd);
+void EXPORT_FUNC (grub_loader_unregister_preboot_hook) (void *hnd);
#endif /* ! GRUB_LOADER_HEADER */
struct grub_lvm_lv {
char *name;
+ char *fullname;
+ char *compatname;
unsigned int number;
unsigned int segment_count;
grub_uint64_t size;
--- /dev/null
+#include <grub/cpu/kernel.h>
+
--- /dev/null
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2009 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_MEMORY_MACHINE_HEADER
+#define GRUB_MEMORY_MACHINE_HEADER 1
+
+#define GRUB_MACHINE_MEMORY_STACK_HIGH 0x8bfffff0
+
+#ifndef ASM_FILE
+
+static inline grub_err_t
+grub_machine_mmap_register (grub_uint64_t start __attribute__ ((unused)),
+ grub_uint64_t size __attribute__ ((unused)),
+ int type __attribute__ ((unused)),
+ int handle __attribute__ ((unused)))
+{
+ return GRUB_ERR_NONE;
+}
+static inline grub_err_t
+grub_machine_mmap_unregister (int handle __attribute__ ((unused)))
+{
+ return GRUB_ERR_NONE;
+}
+
+#endif
+
+#endif
--- /dev/null
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2005,2006,2007,2008,2009 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_KERNEL_CPU_HEADER
+#define GRUB_KERNEL_CPU_HEADER 1
+
+#include <grub/symbol.h>
+
+#ifndef ASM_FILE
+
+void EXPORT_FUNC (grub_halt) (void) __attribute__ ((noreturn));
+
+#endif
+
+#endif /* ! GRUB_KERNEL_MACHINE_HEADER */
#ifndef GRUB_LOONGSON_CPU_HEADER
#define GRUB_LOONGSON_CPU_HEADER 1
-#ifdef ASM_FILE
-#define GRUB_CPU_REGISTER_WRAP(x) x
-#else
-#define GRUB_CPU_REGISTER_WRAP(x) #x
-#endif
+#include <grub/cpu/mips.h>
#define GRUB_CPU_LOONGSON_FLASH_START 0xbfc00000
#define GRUB_CPU_LOONGSON_FLASH_TLB_REFILL 0xbfc00200
#define GRUB_CPU_LOONGSON_SECONDARY_CACHE_LOG_SIZE 19
#define GRUB_CPU_LOONGSON_COP0_BADVADDR GRUB_CPU_REGISTER_WRAP($8)
-#define GRUB_CPU_LOONGSON_COP0_TIMER_COUNT GRUB_CPU_REGISTER_WRAP($9)
#define GRUB_CPU_LOONGSON_COP0_CAUSE GRUB_CPU_REGISTER_WRAP($13)
#define GRUB_CPU_LOONGSON_COP0_EPC GRUB_CPU_REGISTER_WRAP($14)
+#define GRUB_CPU_LOONGSON_COP0_PRID GRUB_CPU_REGISTER_WRAP($15)
#define GRUB_CPU_LOONGSON_COP0_CACHE_TAGLO GRUB_CPU_REGISTER_WRAP($28)
#define GRUB_CPU_LOONGSON_COP0_CACHE_TAGHI GRUB_CPU_REGISTER_WRAP($29)
#define GRUB_CPU_LOONGSON_PCI_HIT1_SEL_HI 0xbfe00154
#define GRUB_CPU_LOONGSON_GPIOCFG 0xbfe00120
-#define GRUB_CPU_LOONGSON_SHUTDOWN_GPIO 1
+#define GRUB_CPU_YEELOONG_SHUTDOWN_GPIO 1
#endif
--- /dev/null
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2007,2008,2009 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_MACHINE_AT_KEYBOARD_HEADER
+#define GRUB_MACHINE_AT_KEYBOARD_HEADER 1
+
+#define KEYBOARD_REG_DATA 0xbfd00060
+#define KEYBOARD_REG_STATUS 0xbfd00064
+
+#endif
--- /dev/null
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2008 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_CPU_CMOS_H
+#define GRUB_CPU_CMOS_H 1
+
+#include <grub/types.h>
+#include <grub/cpu/io.h>
+
+#define GRUB_CMOS_ADDR_REG 0xbfd00070
+#define GRUB_CMOS_DATA_REG 0xbfd00071
+
+#endif /* GRUB_CPU_CMOS_H */
--- /dev/null
+/*
+ * 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/>.
+ */
+
+#ifndef GRUB_EC_MACHINE_HEADER
+#define GRUB_EC_MACHINE_HEADER 1
+
+#include <grub/types.h>
+#include <grub/cpu/io.h>
+#include <grub/pci.h>
+
+#define GRUB_MACHINE_EC_MAGIC_PORT1 0x381
+#define GRUB_MACHINE_EC_MAGIC_PORT2 0x382
+#define GRUB_MACHINE_EC_DATA_PORT 0x383
+
+#define GRUB_MACHINE_EC_MAGIC_VAL1 0xf4
+#define GRUB_MACHINE_EC_MAGIC_VAL2 0xec
+
+#define GRUB_MACHINE_EC_COMMAND_REBOOT 1
+
+static inline void
+grub_write_ec (grub_uint8_t value)
+{
+ grub_outb (GRUB_MACHINE_EC_MAGIC_VAL1,
+ GRUB_MACHINE_PCI_IO_BASE + GRUB_MACHINE_EC_MAGIC_PORT1);
+ grub_outb (GRUB_MACHINE_EC_MAGIC_VAL2,
+ GRUB_MACHINE_PCI_IO_BASE + GRUB_MACHINE_EC_MAGIC_PORT2);
+ grub_outb (value, GRUB_MACHINE_PCI_IO_BASE + GRUB_MACHINE_EC_DATA_PORT);
+}
+
+#endif
--- /dev/null
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2005,2006,2007,2008,2009 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_KERNEL_MACHINE_HEADER
+#define GRUB_KERNEL_MACHINE_HEADER 1
+
+#include <grub/symbol.h>
+#include <grub/cpu/kernel.h>
+
+#define GRUB_ARCH_MACHINE_YEELOONG 0
+#define GRUB_ARCH_MACHINE_FULOONG2F 1
+#define GRUB_ARCH_MACHINE_FULOONG2E 2
+
+#ifndef ASM_FILE
+
+extern grub_uint32_t EXPORT_VAR (grub_arch_machine);
+
+#endif
+
+#endif /* ! GRUB_KERNEL_MACHINE_HEADER */
--- /dev/null
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2009 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_MEMORY_MACHINE_HEADER
+#define GRUB_MEMORY_MACHINE_HEADER 1
+
+#ifndef ASM_FILE
+#include <grub/symbol.h>
+#include <grub/err.h>
+#include <grub/types.h>
+#endif
+
+#define GRUB_MACHINE_MEMORY_STACK_HIGH 0x801ffff0
+
+#ifndef ASM_FILE
+
+static inline grub_err_t
+grub_machine_mmap_register (grub_uint64_t start __attribute__ ((unused)),
+ grub_uint64_t size __attribute__ ((unused)),
+ int type __attribute__ ((unused)),
+ int handle __attribute__ ((unused)))
+{
+ return GRUB_ERR_NONE;
+}
+static inline grub_err_t
+grub_machine_mmap_unregister (int handle __attribute__ ((unused)))
+{
+ return GRUB_ERR_NONE;
+}
+
+extern grub_uint32_t EXPORT_VAR (grub_arch_memsize);
+extern grub_uint32_t EXPORT_VAR (grub_arch_highmemsize);
+
+#endif
+
+#endif
--- /dev/null
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2008 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_MACHINE_PCI_H
+#define GRUB_MACHINE_PCI_H 1
+
+#ifndef ASM_FILE
+#include <grub/types.h>
+#include <grub/cpu/io.h>
+#endif
+
+#define GRUB_LOONGSON_OHCI_PCIID 0x00351033
+#define GRUB_LOONGSON_EHCI_PCIID 0x00e01033
+
+#define GRUB_PCI_NUM_BUS 1
+#define GRUB_PCI_NUM_DEVICES 16
+
+#define GRUB_MACHINE_PCI_IO_BASE 0xbfd00000
+#define GRUB_MACHINE_PCI_CONFSPACE 0xbfe80000
+#define GRUB_MACHINE_PCI_CONTROLLER_HEADER 0xbfe00000
+
+#define GRUB_MACHINE_PCI_CONF_CTRL_REG_ADDR 0xbfe00118
+
+#ifndef ASM_FILE
+#define GRUB_MACHINE_PCI_CONF_CTRL_REG (*(volatile grub_uint32_t *) \
+ GRUB_MACHINE_PCI_CONF_CTRL_REG_ADDR)
+#define GRUB_MACHINE_PCI_IO_CTRL_REG (*(volatile grub_uint32_t *) 0xbfe00110)
+#endif
+#define GRUB_MACHINE_PCI_WIN_MASK_SIZE 6
+#define GRUB_MACHINE_PCI_WIN_MASK ((1 << GRUB_MACHINE_PCI_WIN_MASK_SIZE) - 1)
+
+/* We have 3 PCI windows. */
+#define GRUB_MACHINE_PCI_NUM_WIN 3
+/* Each window is 64MiB. */
+#define GRUB_MACHINE_PCI_WIN_SHIFT 26
+#define GRUB_MACHINE_PCI_WIN_OFFSET_MASK ((1 << GRUB_MACHINE_PCI_WIN_SHIFT) - 1)
+
+#define GRUB_MACHINE_PCI_WIN_SIZE 0x04000000
+/* Graphical acceleration takes 1 MiB away. */
+#define GRUB_MACHINE_PCI_WIN1_SIZE 0x03f00000
+
+#define GRUB_MACHINE_PCI_WIN1_ADDR 0xb0000000
+#define GRUB_MACHINE_PCI_WIN2_ADDR 0xb4000000
+#define GRUB_MACHINE_PCI_WIN3_ADDR 0xb8000000
+
+#ifndef ASM_FILE
+static inline grub_uint32_t
+grub_pci_read (grub_pci_address_t addr)
+{
+ GRUB_MACHINE_PCI_CONF_CTRL_REG = 1 << ((addr >> 11) & 0xf);
+ return *(volatile grub_uint32_t *) (GRUB_MACHINE_PCI_CONFSPACE
+ | (addr & 0x07ff));
+}
+
+static inline grub_uint16_t
+grub_pci_read_word (grub_pci_address_t addr)
+{
+ GRUB_MACHINE_PCI_CONF_CTRL_REG = 1 << ((addr >> 11) & 0xf);
+ return *(volatile grub_uint16_t *) (GRUB_MACHINE_PCI_CONFSPACE
+ | (addr & 0x07ff));
+}
+
+static inline grub_uint8_t
+grub_pci_read_byte (grub_pci_address_t addr)
+{
+ GRUB_MACHINE_PCI_CONF_CTRL_REG = 1 << ((addr >> 11) & 0xf);
+ return *(volatile grub_uint8_t *) (GRUB_MACHINE_PCI_CONFSPACE
+ | (addr & 0x07ff));
+}
+
+static inline void
+grub_pci_write (grub_pci_address_t addr, grub_uint32_t data)
+{
+ GRUB_MACHINE_PCI_CONF_CTRL_REG = 1 << ((addr >> 11) & 0xf);
+ *(volatile grub_uint32_t *) (GRUB_MACHINE_PCI_CONFSPACE
+ | (addr & 0x07ff)) = data;
+}
+
+static inline void
+grub_pci_write_word (grub_pci_address_t addr, grub_uint16_t data)
+{
+ GRUB_MACHINE_PCI_CONF_CTRL_REG = 1 << ((addr >> 11) & 0xf);
+ *(volatile grub_uint16_t *) (GRUB_MACHINE_PCI_CONFSPACE
+ | (addr & 0x07ff)) = data;
+}
+
+static inline void
+grub_pci_write_byte (grub_pci_address_t addr, grub_uint8_t data)
+{
+ GRUB_MACHINE_PCI_CONF_CTRL_REG = 1 << ((addr >> 11) & 0xf);
+ *(volatile grub_uint8_t *) (GRUB_MACHINE_PCI_CONFSPACE
+ | (addr & 0x07ff)) = data;
+}
+
+volatile void *
+EXPORT_FUNC (grub_pci_device_map_range) (grub_pci_device_t dev,
+ grub_addr_t base, grub_size_t size);
+void
+EXPORT_FUNC (grub_pci_device_unmap_range) (grub_pci_device_t dev,
+ volatile void *mem,
+ grub_size_t size);
+#endif
+
+#endif /* GRUB_MACHINE_PCI_H */
--- /dev/null
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2009 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_MACHINE_SERIAL_HEADER
+#define GRUB_MACHINE_SERIAL_HEADER 1
+
+#define GRUB_MACHINE_SERIAL_PORT0_DIVISOR_115200 2
+#define GRUB_MACHINE_SERIAL_PORT2_DIVISOR_115200 1
+#define GRUB_MACHINE_SERIAL_PORT0 0xbff003f8
+#define GRUB_MACHINE_SERIAL_PORT1 0xbfd003f8
+#define GRUB_MACHINE_SERIAL_PORT2 0xbfd002f8
+
+#ifndef ASM_FILE
+#define GRUB_MACHINE_SERIAL_PORTS { GRUB_MACHINE_SERIAL_PORT0, GRUB_MACHINE_SERIAL_PORT1, GRUB_MACHINE_SERIAL_PORT2 }
+#else
+#endif
+
+#endif
--- /dev/null
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2003,2004,2005,2007 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/>.
+ */
+
+#ifndef KERNEL_MACHINE_TIME_HEADER
+#define KERNEL_MACHINE_TIME_HEADER 1
+
+#include <grub/symbol.h>
+#include <grub/cpu/time.h>
+
+extern grub_uint32_t EXPORT_VAR (grub_arch_busclock);
+
+#endif /* ! KERNEL_MACHINE_TIME_HEADER */
-#include <grub/machine/memory.h>
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2009 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_MEMORY_CPU_HEADER
+#define GRUB_MEMORY_CPU_HEADER 1
+
+#ifndef ASM_FILE
+#include <grub/symbol.h>
+#include <grub/err.h>
+#include <grub/types.h>
+#endif
+
+#define GRUB_ARCH_LOWMEMVSTART 0x80000000
+#define GRUB_ARCH_LOWMEMPSTART 0x00000000
+#define GRUB_ARCH_LOWMEMMAXSIZE 0x10000000
+#define GRUB_ARCH_HIGHMEMPSTART 0x10000000
+
+#ifndef ASM_FILE
+
+typedef grub_addr_t grub_phys_addr_t;
+
+static inline grub_phys_addr_t
+grub_vtop (void *a)
+{
+ return ((grub_phys_addr_t) a) & 0x1fffffff;
+}
+
+static inline void *
+grub_map_memory (grub_phys_addr_t a, grub_size_t size __attribute__ ((unused)))
+{
+ return (void *) (a | 0x80000000);
+}
+
+static inline void
+grub_unmap_memory (void *a __attribute__ ((unused)),
+ grub_size_t size __attribute__ ((unused)))
+{
+}
+
+grub_uint64_t grub_mmap_get_lower (void);
+grub_uint64_t grub_mmap_get_upper (void);
+
+#endif
+
+#endif
--- /dev/null
+/*
+ * 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/>.
+ */
+
+#ifndef GRUB_REGISTERS_CPU_HEADER
+#define GRUB_REGISTERS_CPU_HEADER 1
+
+#ifdef ASM_FILE
+#define GRUB_CPU_REGISTER_WRAP(x) x
+#else
+#define GRUB_CPU_REGISTER_WRAP(x) #x
+#endif
+
+#define GRUB_CPU_MIPS_COP0_TIMER_COUNT GRUB_CPU_REGISTER_WRAP($9)
+
+#endif
+++ /dev/null
-/*
- * GRUB -- GRand Unified Bootloader
- * Copyright (C) 2005,2006,2007,2008,2009 Free Software Foundation, Inc.
- *
- * GRUB is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * GRUB is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef GRUB_KERNEL_MACHINE_HEADER
-#define GRUB_KERNEL_MACHINE_HEADER 1
-
-#include <grub/symbol.h>
-#include <grub/cpu/kernel.h>
-
-#ifndef ASM_FILE
-
-void EXPORT_FUNC (grub_reboot) (void);
-void EXPORT_FUNC (grub_halt) (void);
-
-#endif
-
-#endif /* ! GRUB_KERNEL_MACHINE_HEADER */
+++ /dev/null
-/*
- * GRUB -- GRand Unified Bootloader
- * Copyright (C) 2009 Free Software Foundation, Inc.
- *
- * GRUB is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * GRUB is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef GRUB_MEMORY_MACHINE_HEADER
-#define GRUB_MEMORY_MACHINE_HEADER 1
-
-#ifndef ASM_FILE
-#include <grub/symbol.h>
-#include <grub/err.h>
-#include <grub/types.h>
-#endif
-
-#define GRUB_MACHINE_MEMORY_STACK_HIGH 0x80f00000
-#define GRUB_MACHINE_MEMORY_USABLE 0x81000000
-
-#ifndef ASM_FILE
-grub_err_t EXPORT_FUNC (grub_machine_mmap_iterate)
-(int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uint64_t, grub_uint32_t));
-grub_err_t EXPORT_FUNC(grub_machine_mmap_iterate)
- (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uint64_t, grub_uint32_t));
-
-static inline grub_err_t
-grub_machine_mmap_register (grub_uint64_t start __attribute__ ((unused)),
- grub_uint64_t size __attribute__ ((unused)),
- int type __attribute__ ((unused)),
- int handle __attribute__ ((unused)))
-{
- return GRUB_ERR_NONE;
-}
-static inline grub_err_t
-grub_machine_mmap_unregister (int handle __attribute__ ((unused)))
-{
- return GRUB_ERR_NONE;
-}
-#endif
-
-#endif
+++ /dev/null
-/*
- * GRUB -- GRand Unified Bootloader
- * Copyright (C) 2009 Free Software Foundation, Inc.
- *
- * GRUB is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * GRUB is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef GRUB_MACHINE_SERIAL_HEADER
-#define GRUB_MACHINE_SERIAL_HEADER 1
-
-#define GRUB_MACHINE_SERIAL_PORTS { 0x140003f8 }
-
-#endif
+++ /dev/null
-/*
- * GRUB -- GRand Unified Bootloader
- * Copyright (C) 2003,2004,2005,2007 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/>.
- */
-
-#ifndef KERNEL_MACHINE_TIME_HEADER
-#define KERNEL_MACHINE_TIME_HEADER 1
-
-#include <grub/symbol.h>
-
-#define GRUB_TICKS_PER_SECOND 1000
-
-/* Return the real time in ticks. */
-grub_uint32_t EXPORT_FUNC (grub_get_rtc) (void);
-
-static inline void
-grub_cpu_idle(void)
-{
-}
-
-#endif /* ! KERNEL_MACHINE_TIME_HEADER */
--- /dev/null
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2007,2008,2009 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_MACHINE_AT_KEYBOARD_HEADER
+#define GRUB_MACHINE_AT_KEYBOARD_HEADER 1
+
+#define KEYBOARD_REG_DATA 0xb4000060
+#define KEYBOARD_REG_STATUS 0xb4000064
+
+#endif
--- /dev/null
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2008 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_CPU_CMOS_H
+#define GRUB_CPU_CMOS_H 1
+
+#include <grub/types.h>
+#include <grub/cpu/io.h>
+
+#define GRUB_CMOS_ADDR_REG 0xb4000070
+#define GRUB_CMOS_DATA_REG 0xb4000071
+
+#endif /* GRUB_CPU_CMOS_H */
--- /dev/null
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2005,2006,2007,2008,2009 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_KERNEL_MACHINE_HEADER
+#define GRUB_KERNEL_MACHINE_HEADER 1
+
+#include <grub/symbol.h>
+
+#ifndef ASM_FILE
+
+void EXPORT_FUNC (grub_halt) (void);
+void grub_qemu_init_cirrus (void);
+
+#endif
+
+#endif /* ! GRUB_KERNEL_MACHINE_HEADER */
--- /dev/null
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2009 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_MEMORY_MACHINE_HEADER
+#define GRUB_MEMORY_MACHINE_HEADER 1
+
+#ifndef ASM_FILE
+#include <grub/symbol.h>
+#include <grub/err.h>
+#include <grub/types.h>
+#endif
+
+#define GRUB_MACHINE_MEMORY_STACK_HIGH 0x80f00000
+#define GRUB_MACHINE_MEMORY_USABLE 0x81000000
+
+#ifndef ASM_FILE
+
+extern grub_uint32_t grub_arch_memsize;
+
+static inline grub_err_t
+grub_machine_mmap_register (grub_uint64_t start __attribute__ ((unused)),
+ grub_uint64_t size __attribute__ ((unused)),
+ int type __attribute__ ((unused)),
+ int handle __attribute__ ((unused)))
+{
+ return GRUB_ERR_NONE;
+}
+static inline grub_err_t
+grub_machine_mmap_unregister (int handle __attribute__ ((unused)))
+{
+ return GRUB_ERR_NONE;
+}
+#endif
+
+#endif
--- /dev/null
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2009 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_MACHINE_SERIAL_HEADER
+#define GRUB_MACHINE_SERIAL_HEADER 1
+
+#define GRUB_MACHINE_SERIAL_PORTS { 0xb40003f8 }
+
+#endif
--- /dev/null
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2003,2004,2005,2007 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/>.
+ */
+
+#ifndef KERNEL_MACHINE_TIME_HEADER
+#define KERNEL_MACHINE_TIME_HEADER 1
+
+#include <grub/symbol.h>
+#include <grub/cpu/time.h>
+
+#endif /* ! KERNEL_MACHINE_TIME_HEADER */
-#ifdef GRUB_MACHINE_EMU
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2003,2004,2005,2007 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/>.
+ */
+
+#ifndef KERNEL_CPU_TIME_HEADER
+#define KERNEL_CPU_TIME_HEADER 1
+
+#ifndef GRUB_UTIL
+
+#define GRUB_TICKS_PER_SECOND (grub_arch_cpuclock / 2)
+
+/* Return the real time in ticks. */
+grub_uint64_t EXPORT_FUNC (grub_get_rtc) (void);
+
+extern grub_uint32_t EXPORT_VAR (grub_arch_cpuclock);
+#endif
+
static inline void
grub_cpu_idle(void)
{
}
+
#endif
+++ /dev/null
-/*
- * GRUB -- GRand Unified Bootloader
- * Copyright (C) 2007,2008,2009 Free Software Foundation, Inc.
- *
- * GRUB is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * GRUB is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef GRUB_MACHINE_AT_KEYBOARD_HEADER
-#define GRUB_MACHINE_AT_KEYBOARD_HEADER 1
-
-#define KEYBOARD_REG_DATA 0xbfd00060
-#define KEYBOARD_REG_STATUS 0xbfd00064
-
-#endif
+++ /dev/null
-/*
- * GRUB -- GRand Unified Bootloader
- * Copyright (C) 2008 Free Software Foundation, Inc.
- *
- * GRUB is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * GRUB is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef GRUB_CPU_CMOS_H
-#define GRUB_CPU_CMOS_H 1
-
-#include <grub/types.h>
-#include <grub/cpu/io.h>
-
-#define GRUB_CMOS_ADDR_REG 0xbfd00070
-#define GRUB_CMOS_DATA_REG 0xbfd00071
-
-#endif /* GRUB_CPU_CMOS_H */
+++ /dev/null
-/*
- * 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/>.
- */
-
-#ifndef GRUB_EC_MACHINE_HEADER
-#define GRUB_EC_MACHINE_HEADER 1
-
-#define GRUB_MACHINE_EC_MAGIC_PORT1 0x381
-#define GRUB_MACHINE_EC_MAGIC_PORT2 0x382
-#define GRUB_MACHINE_EC_DATA_PORT 0x383
-
-#define GRUB_MACHINE_EC_MAGIC_VAL1 0xf4
-#define GRUB_MACHINE_EC_MAGIC_VAL2 0xec
-
-#define GRUB_MACHINE_EC_COMMAND_REBOOT 1
-
-static inline void
-grub_write_ec (grub_uint8_t value)
-{
- grub_outb (GRUB_MACHINE_EC_MAGIC_VAL1,
- GRUB_MACHINE_PCI_IO_BASE + GRUB_MACHINE_EC_MAGIC_PORT1);
- grub_outb (GRUB_MACHINE_EC_MAGIC_VAL2,
- GRUB_MACHINE_PCI_IO_BASE + GRUB_MACHINE_EC_MAGIC_PORT2);
- grub_outb (value, GRUB_MACHINE_PCI_IO_BASE + GRUB_MACHINE_EC_DATA_PORT);
-}
-
-#endif
+++ /dev/null
-/*
- * GRUB -- GRand Unified Bootloader
- * Copyright (C) 2005,2006,2007,2008,2009 Free Software Foundation, Inc.
- *
- * GRUB is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * GRUB is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef GRUB_KERNEL_MACHINE_HEADER
-#define GRUB_KERNEL_MACHINE_HEADER 1
-
-#include <grub/symbol.h>
-
-#ifndef ASM_FILE
-
-void EXPORT_FUNC (grub_reboot) (void) __attribute__ ((noreturn));
-void EXPORT_FUNC (grub_halt) (void) __attribute__ ((noreturn));
-
-#endif
-
-#endif /* ! GRUB_KERNEL_MACHINE_HEADER */
+++ /dev/null
-/*
- * GRUB -- GRand Unified Bootloader
- * Copyright (C) 2009 Free Software Foundation, Inc.
- *
- * GRUB is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * GRUB is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef GRUB_MEMORY_MACHINE_HEADER
-#define GRUB_MEMORY_MACHINE_HEADER 1
-
-#ifndef ASM_FILE
-#include <grub/symbol.h>
-#include <grub/err.h>
-#include <grub/types.h>
-#endif
-
-#define GRUB_MACHINE_MEMORY_STACK_HIGH 0x801ffff0
-#define GRUB_ARCH_LOWMEMVSTART 0x80000000
-#define GRUB_ARCH_LOWMEMPSTART 0x00000000
-#define GRUB_ARCH_LOWMEMMAXSIZE 0x10000000
-#define GRUB_ARCH_HIGHMEMPSTART 0x10000000
-
-#ifndef ASM_FILE
-
-typedef grub_addr_t grub_phys_addr_t;
-
-static inline grub_phys_addr_t
-grub_vtop (void *a)
-{
- return ((grub_phys_addr_t) a) & 0x1fffffff;
-}
-
-static inline void *
-grub_map_memory (grub_phys_addr_t a, grub_size_t size __attribute__ ((unused)))
-{
- return (void *) (a | 0x80000000);
-}
-
-static inline void
-grub_unmap_memory (void *a __attribute__ ((unused)),
- grub_size_t size __attribute__ ((unused)))
-{
-}
-
-grub_err_t EXPORT_FUNC (grub_machine_mmap_iterate)
-(int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uint64_t, grub_uint32_t));
-
-static inline grub_err_t
-grub_machine_mmap_register (grub_uint64_t start __attribute__ ((unused)),
- grub_uint64_t size __attribute__ ((unused)),
- int type __attribute__ ((unused)),
- int handle __attribute__ ((unused)))
-{
- return GRUB_ERR_NONE;
-}
-static inline grub_err_t
-grub_machine_mmap_unregister (int handle __attribute__ ((unused)))
-{
- return GRUB_ERR_NONE;
-}
-
-grub_uint64_t grub_mmap_get_lower (void);
-grub_uint64_t grub_mmap_get_upper (void);
-
-extern grub_uint32_t EXPORT_VAR (grub_arch_memsize);
-extern grub_uint32_t EXPORT_VAR (grub_arch_highmemsize);
-
-#endif
-
-#endif
+++ /dev/null
-/*
- * GRUB -- GRand Unified Bootloader
- * Copyright (C) 2008 Free Software Foundation, Inc.
- *
- * GRUB is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * GRUB is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef GRUB_MACHINE_PCI_H
-#define GRUB_MACHINE_PCI_H 1
-
-#ifndef ASM_FILE
-#include <grub/types.h>
-#include <grub/cpu/io.h>
-#endif
-
-#define GRUB_YEELOONG_OHCI_PCIID 0x00351033
-#define GRUB_YEELOONG_EHCI_PCIID 0x00e01033
-#define GRUB_YEELOONG_OHCI_GHOST_FUNCTION 4
-#define GRUB_YEELOONG_EHCI_GHOST_FUNCTION 5
-
-#define GRUB_PCI_NUM_BUS 1
-#define GRUB_PCI_NUM_DEVICES 16
-
-#define GRUB_MACHINE_PCI_IO_BASE 0xbfd00000
-#define GRUB_MACHINE_PCI_CONFSPACE 0xbfe80000
-#define GRUB_MACHINE_PCI_CONTROLLER_HEADER 0xbfe00000
-
-#define GRUB_MACHINE_PCI_CONF_CTRL_REG_ADDR 0xbfe00118
-
-#ifndef ASM_FILE
-#define GRUB_MACHINE_PCI_CONF_CTRL_REG (*(volatile grub_uint32_t *) \
- GRUB_MACHINE_PCI_CONF_CTRL_REG_ADDR)
-#define GRUB_MACHINE_PCI_IO_CTRL_REG (*(volatile grub_uint32_t *) 0xbfe00110)
-#endif
-#define GRUB_MACHINE_PCI_WIN_MASK_SIZE 6
-#define GRUB_MACHINE_PCI_WIN_MASK ((1 << GRUB_MACHINE_PCI_WIN_MASK_SIZE) - 1)
-
-/* We have 3 PCI windows. */
-#define GRUB_MACHINE_PCI_NUM_WIN 3
-/* Each window is 64MiB. */
-#define GRUB_MACHINE_PCI_WIN_SHIFT 26
-#define GRUB_MACHINE_PCI_WIN_OFFSET_MASK ((1 << GRUB_MACHINE_PCI_WIN_SHIFT) - 1)
-
-#define GRUB_MACHINE_PCI_WIN_SIZE 0x04000000
-/* Graphical acceleration takes 1 MiB away. */
-#define GRUB_MACHINE_PCI_WIN1_SIZE 0x03f00000
-
-#define GRUB_MACHINE_PCI_WIN1_ADDR 0xb0000000
-#define GRUB_MACHINE_PCI_WIN2_ADDR 0xb4000000
-#define GRUB_MACHINE_PCI_WIN3_ADDR 0xb8000000
-
-#ifndef ASM_FILE
-static inline grub_uint32_t
-grub_pci_read (grub_pci_address_t addr)
-{
- GRUB_MACHINE_PCI_CONF_CTRL_REG = 1 << ((addr >> 11) & 0xf);
- return *(volatile grub_uint32_t *) (GRUB_MACHINE_PCI_CONFSPACE
- | (addr & 0x03ff));
-}
-
-static inline grub_uint16_t
-grub_pci_read_word (grub_pci_address_t addr)
-{
- GRUB_MACHINE_PCI_CONF_CTRL_REG = 1 << ((addr >> 11) & 0xf);
- return *(volatile grub_uint16_t *) (GRUB_MACHINE_PCI_CONFSPACE
- | (addr & 0x03ff));
-}
-
-static inline grub_uint8_t
-grub_pci_read_byte (grub_pci_address_t addr)
-{
- GRUB_MACHINE_PCI_CONF_CTRL_REG = 1 << ((addr >> 11) & 0xf);
- return *(volatile grub_uint8_t *) (GRUB_MACHINE_PCI_CONFSPACE
- | (addr & 0x03ff));
-}
-
-static inline void
-grub_pci_write (grub_pci_address_t addr, grub_uint32_t data)
-{
- GRUB_MACHINE_PCI_CONF_CTRL_REG = 1 << ((addr >> 11) & 0xf);
- *(volatile grub_uint32_t *) (GRUB_MACHINE_PCI_CONFSPACE
- | (addr & 0x03ff)) = data;
-}
-
-static inline void
-grub_pci_write_word (grub_pci_address_t addr, grub_uint16_t data)
-{
- GRUB_MACHINE_PCI_CONF_CTRL_REG = 1 << ((addr >> 11) & 0xf);
- *(volatile grub_uint16_t *) (GRUB_MACHINE_PCI_CONFSPACE
- | (addr & 0x03ff)) = data;
-}
-
-static inline void
-grub_pci_write_byte (grub_pci_address_t addr, grub_uint8_t data)
-{
- GRUB_MACHINE_PCI_CONF_CTRL_REG = 1 << ((addr >> 11) & 0xf);
- *(volatile grub_uint8_t *) (GRUB_MACHINE_PCI_CONFSPACE
- | (addr & 0x03ff)) = data;
-}
-
-volatile void *
-EXPORT_FUNC (grub_pci_device_map_range) (grub_pci_device_t dev,
- grub_addr_t base, grub_size_t size);
-void
-EXPORT_FUNC (grub_pci_device_unmap_range) (grub_pci_device_t dev,
- volatile void *mem,
- grub_size_t size);
-#endif
-
-#endif /* GRUB_MACHINE_PCI_H */
+++ /dev/null
-/*
- * GRUB -- GRand Unified Bootloader
- * Copyright (C) 2009 Free Software Foundation, Inc.
- *
- * GRUB is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * GRUB is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef GRUB_MACHINE_SERIAL_HEADER
-#define GRUB_MACHINE_SERIAL_HEADER 1
-
-#define GRUB_MACHINE_SERIAL_DIVISOR_115200 2
-#define GRUB_MACHINE_SERIAL_PORT 0xbff003f8
-
-#ifndef ASM_FILE
-#define GRUB_MACHINE_SERIAL_PORTS { GRUB_MACHINE_SERIAL_PORT }
-#else
-#endif
-
-#endif
+++ /dev/null
-/*
- * GRUB -- GRand Unified Bootloader
- * Copyright (C) 2003,2004,2005,2007 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/>.
- */
-
-#ifndef KERNEL_MACHINE_TIME_HEADER
-#define KERNEL_MACHINE_TIME_HEADER 1
-
-#include <grub/symbol.h>
-
-#define GRUB_TICKS_PER_SECOND (grub_arch_cpuclock / 2)
-
-/* Return the real time in ticks. */
-grub_uint64_t EXPORT_FUNC (grub_get_rtc) (void);
-
-extern grub_uint32_t EXPORT_VAR (grub_arch_busclock);
-extern grub_uint32_t EXPORT_VAR (grub_arch_cpuclock);
-
-static inline void
-grub_cpu_idle(void)
-{
-}
-
-#endif /* ! KERNEL_MACHINE_TIME_HEADER */
return (c >= '0' && c <= '9');
}
+static inline int
+grub_isxdigit (int c)
+{
+ return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F');
+}
+
static inline int
grub_isalnum (int c)
{
void EXPORT_FUNC(grub_exit) (void) __attribute__ ((noreturn));
void EXPORT_FUNC(grub_abort) (void) __attribute__ ((noreturn));
grub_uint64_t EXPORT_FUNC(grub_divmod64) (grub_uint64_t n,
- grub_uint32_t d, grub_uint32_t *r);
+ grub_uint64_t d,
+ grub_uint64_t *r);
#if NEED_ENABLE_EXECUTE_STACK && !defined(GRUB_UTIL)
void EXPORT_FUNC(__enable_execute_stack) (void *addr);
}
/* Reboot the machine. */
-void EXPORT_FUNC (grub_reboot) (void) __attribute__ ((noreturn));
+void grub_reboot (void) __attribute__ ((noreturn));
#ifdef GRUB_MACHINE_PCBIOS
/* Halt the system, using APM if possible. If NO_APM is true, don't
/*
* GRUB -- GRand Unified Bootloader
- * Copyright (C) 2002,2007 Free Software Foundation, Inc.
+ * Copyright (C) 2010,2011 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
#ifndef GRUB_NET_HEADER
#define GRUB_NET_HEADER 1
-#include <grub/symbol.h>
-#include <grub/err.h>
#include <grub/types.h>
+#include <grub/err.h>
+#include <grub/list.h>
+#include <grub/fs.h>
+#include <grub/file.h>
+#include <grub/mm.h>
+#include <grub/net/netbuff.h>
+
+typedef enum grub_link_level_protocol_id
+{
+ GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET
+} grub_link_level_protocol_id_t;
+
+typedef struct grub_net_link_level_address
+{
+ grub_link_level_protocol_id_t type;
+ union
+ {
+ grub_uint8_t mac[6];
+ };
+} grub_net_link_level_address_t;
+
+typedef enum grub_net_interface_flags
+ {
+ GRUB_NET_INTERFACE_HWADDRESS_IMMUTABLE = 1,
+ GRUB_NET_INTERFACE_ADDRESS_IMMUTABLE = 2,
+ GRUB_NET_INTERFACE_PERMANENT = 4
+ } grub_net_interface_flags_t;
+
+typedef enum grub_net_card_flags
+ {
+ GRUB_NET_CARD_HWADDRESS_IMMUTABLE = 1,
+ GRUB_NET_CARD_NO_MANUAL_INTERFACES = 2
+ } grub_net_card_flags_t;
+
+struct grub_net_card;
+
+struct grub_net_card_driver
+{
+ struct grub_net_card_driver *next;
+ char *name;
+ grub_err_t (*open) (const struct grub_net_card *dev);
+ void (*close) (const struct grub_net_card *dev);
+ grub_err_t (*send) (const struct grub_net_card *dev,
+ struct grub_net_buff *buf);
+ grub_ssize_t (*recv) (const struct grub_net_card *dev,
+ struct grub_net_buff *buf);
+};
+
+typedef struct grub_net_packet
+{
+ struct grub_net_packet *next;
+ struct grub_net_packet *prev;
+ struct grub_net_packets *up;
+ struct grub_net_buff *nb;
+} grub_net_packet_t;
+
+typedef struct grub_net_packets
+{
+ grub_net_packet_t *first;
+ grub_net_packet_t *last;
+} grub_net_packets_t;
+
+#ifdef GRUB_MACHINE_EFI
+#include <grub/efi/api.h>
+#endif
+
+struct grub_net_card
+{
+ struct grub_net_card *next;
+ char *name;
+ struct grub_net_card_driver *driver;
+ grub_net_link_level_address_t default_address;
+ grub_net_card_flags_t flags;
+ int num_ifaces;
+ int opened;
+ unsigned idle_poll_delay_ms;
+ grub_uint64_t last_poll;
+ union
+ {
+#ifdef GRUB_MACHINE_EFI
+ struct
+ {
+ struct grub_efi_simple_network *efi_net;
+ grub_efi_handle_t efi_handle;
+ };
+#endif
+ void *data;
+ int data_num;
+ };
+};
+
+struct grub_net_network_level_interface;
+
+typedef enum grub_network_level_protocol_id
+{
+ GRUB_NET_NETWORK_LEVEL_PROTOCOL_DHCP_RECV,
+ GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4
+} grub_network_level_protocol_id_t;
+
+typedef struct grub_net_network_level_address
+{
+ grub_network_level_protocol_id_t type;
+ union
+ {
+ grub_uint32_t ipv4;
+ };
+} grub_net_network_level_address_t;
+
+typedef struct grub_net_network_level_netaddress
+{
+ grub_network_level_protocol_id_t type;
+ union
+ {
+ struct {
+ grub_uint32_t base;
+ int masksize;
+ } ipv4;
+ };
+} grub_net_network_level_netaddress_t;
+
+#define FOR_PACKETS(cont,var) for (var = (cont).first; var; var = var->next)
+
+static inline grub_err_t
+grub_net_put_packet (grub_net_packets_t *pkts, struct grub_net_buff *nb)
+{
+ struct grub_net_packet *n;
+
+ n = grub_malloc (sizeof (*n));
+ if (!n)
+ return grub_errno;
+
+ n->nb = nb;
+ n->next = NULL;
+ n->prev = NULL;
+ n->up = pkts;
+ if (pkts->first)
+ {
+ pkts->last->next = n;
+ pkts->last = n;
+ n->prev = pkts->last;
+ }
+ else
+ pkts->first = pkts->last = n;
+
+ return GRUB_ERR_NONE;
+}
+
+static inline void
+grub_net_remove_packet (grub_net_packet_t *pkt)
+{
+ if (pkt->prev)
+ pkt->prev->next = pkt->next;
+ else
+ pkt->up->first = pkt->next;
+ if (pkt->next)
+ pkt->next->prev = pkt->prev;
+ else
+ pkt->up->last = pkt->prev;
+ grub_free (pkt);
+}
+
+typedef struct grub_net_app_protocol *grub_net_app_level_t;
-struct grub_net;
+typedef struct grub_net_socket *grub_net_socket_t;
-struct grub_net_dev
+struct grub_net_app_protocol
{
- /* The device name. */
- const char *name;
+ struct grub_net_app_protocol *next;
+ char *name;
+ grub_err_t (*dir) (grub_device_t device, const char *path,
+ int (*hook) (const char *filename,
+ const struct grub_dirhook_info *info));
+ grub_err_t (*open) (struct grub_file *file, const char *filename);
+ grub_err_t (*close) (struct grub_file *file);
+};
- /* FIXME: Just a template. */
- int (*probe) (struct grub_net *net, const void *addr);
- void (*reset) (struct grub_net *net);
- int (*poll) (struct grub_net *net);
- void (*transmit) (struct grub_net *net, const void *destip,
- unsigned srcsock, unsigned destsock, const void *packet);
- void (*disable) (struct grub_net *net);
+struct grub_net_socket
+{
+ struct grub_net_socket *next;
- /* The next net device. */
- struct grub_net_dev *next;
+ enum { GRUB_NET_SOCKET_START,
+ GRUB_NET_SOCKET_ESTABLISHED,
+ GRUB_NET_SOCKET_CLOSED } x_status;
+ int x_in_port;
+ int x_out_port;
+ grub_err_t (*recv_hook) (grub_net_socket_t sock, struct grub_net_buff *nb,
+ void *recv);
+ void *recv_hook_data;
+ grub_net_network_level_address_t x_out_nla;
+ struct grub_net_network_level_interface *x_inf;
};
-typedef struct grub_net_dev *grub_net_dev_t;
-struct grub_fs;
+extern struct grub_net_socket *grub_net_sockets;
+
+static inline void
+grub_net_socket_register (grub_net_socket_t sock)
+{
+ grub_list_push (GRUB_AS_LIST_P (&grub_net_sockets),
+ GRUB_AS_LIST (sock));
+}
+
+static inline void
+grub_net_socket_unregister (grub_net_socket_t sock)
+{
+ grub_list_remove (GRUB_AS_LIST_P (&grub_net_sockets),
+ GRUB_AS_LIST (sock));
+}
+
+#define FOR_NET_SOCKETS(var) for (var = grub_net_sockets; var; var = var->next)
-struct grub_net
+typedef struct grub_net
{
- /* The net name. */
- const char *name;
+ char *server;
+ char *name;
+ grub_net_app_level_t protocol;
+ grub_net_packets_t packs;
+ grub_off_t offset;
+ grub_fs_t fs;
+ int eof;
+} *grub_net_t;
+
+extern grub_net_t (*EXPORT_VAR (grub_net_open)) (const char *name);
- /* The underlying disk device. */
- grub_net_dev_t dev;
+struct grub_net_network_level_interface
+{
+ struct grub_net_network_level_interface *next;
+ struct grub_net_network_level_interface **prev;
+ char *name;
+ struct grub_net_card *card;
+ grub_net_network_level_address_t address;
+ grub_net_link_level_address_t hwaddress;
+ grub_net_interface_flags_t flags;
+ struct grub_net_bootp_packet *dhcp_ack;
+ grub_size_t dhcp_acklen;
+ void *data;
+};
- /* The binding filesystem. */
- struct grub_fs *fs;
+struct grub_net_session;
- /* FIXME: More data would be required, such as an IP address, a mask,
- a gateway, etc. */
+struct grub_net_session_level_protocol
+{
+ void (*close) (struct grub_net_session *session);
+ grub_ssize_t (*recv) (struct grub_net_session *session, void *buf,
+ grub_size_t size);
+ grub_err_t (*send) (struct grub_net_session *session, void *buf,
+ grub_size_t size);
+};
- /* Device-specific data. */
+struct grub_net_session
+{
+ struct grub_net_session_level_protocol *protocol;
void *data;
};
-typedef struct grub_net *grub_net_t;
-/* FIXME: How to abstract networks? More consideration is necessary. */
+static inline void
+grub_net_session_close (struct grub_net_session *session)
+{
+ session->protocol->close (session);
+}
+
+static inline grub_err_t
+grub_net_session_send (struct grub_net_session *session, void *buf,
+ grub_size_t size)
+{
+ return session->protocol->send (session, buf, size);
+}
+
+static inline grub_ssize_t
+grub_net_session_recv (struct grub_net_session *session, void *buf,
+ grub_size_t size)
+{
+ return session->protocol->recv (session, buf, size);
+}
+
+struct grub_net_network_level_interface *
+grub_net_add_addr (const char *name,
+ struct grub_net_card *card,
+ grub_net_network_level_address_t addr,
+ grub_net_link_level_address_t hwaddress,
+ grub_net_interface_flags_t flags);
+
+extern struct grub_net_network_level_interface *grub_net_network_level_interfaces;
+
+extern grub_net_app_level_t grub_net_app_level_list;
+
+#ifndef GRUB_LST_GENERATOR
+static inline void
+grub_net_app_level_register (grub_net_app_level_t proto)
+{
+ grub_list_push (GRUB_AS_LIST_P (&grub_net_app_level_list),
+ GRUB_AS_LIST (proto));
+}
+#endif
+
+static inline void
+grub_net_app_level_unregister (grub_net_app_level_t proto)
+{
+ grub_list_remove (GRUB_AS_LIST_P (&grub_net_app_level_list),
+ GRUB_AS_LIST (proto));
+}
+
+#define FOR_NET_APP_LEVEL(var) FOR_LIST_ELEMENTS((var), \
+ (grub_net_app_level_list))
+
+extern struct grub_net_card *grub_net_cards;
+
+static inline void
+grub_net_card_register (struct grub_net_card *card)
+{
+ grub_list_push (GRUB_AS_LIST_P (&grub_net_cards),
+ GRUB_AS_LIST (card));
+}
+
+void
+grub_net_card_unregister (struct grub_net_card *card);
+
+#define FOR_NET_CARDS(var) for (var = grub_net_cards; var; var = var->next)
+#define FOR_NET_CARDS_SAFE(var, next) for (var = grub_net_cards, next = var->next; var; var = next, next = var->next)
+
+
+struct grub_net_session *
+grub_net_open_tcp (char *address, grub_uint16_t port);
+
+grub_err_t
+grub_net_resolve_address (const char *name,
+ grub_net_network_level_address_t *addr);
+
+grub_err_t
+grub_net_resolve_net_address (const char *name,
+ grub_net_network_level_netaddress_t *addr);
+
+grub_err_t
+grub_net_route_address (grub_net_network_level_address_t addr,
+ grub_net_network_level_address_t *gateway,
+ struct grub_net_network_level_interface **interf);
+
+
+grub_err_t
+grub_net_add_route (const char *name,
+ grub_net_network_level_netaddress_t target,
+ struct grub_net_network_level_interface *inter);
+
+grub_err_t
+grub_net_add_route_gw (const char *name,
+ grub_net_network_level_netaddress_t target,
+ grub_net_network_level_address_t gw);
+
+
+#define GRUB_NET_BOOTP_MAC_ADDR_LEN 16
+
+typedef grub_uint8_t grub_net_bootp_mac_addr_t[GRUB_NET_BOOTP_MAC_ADDR_LEN];
+
+struct grub_net_bootp_packet
+{
+ grub_uint8_t opcode;
+ grub_uint8_t hw_type; /* hardware type. */
+ grub_uint8_t hw_len; /* hardware addr len. */
+ grub_uint8_t gate_hops; /* zero it. */
+ grub_uint32_t ident; /* random number chosen by client. */
+ grub_uint16_t seconds; /* seconds since did initial bootstrap. */
+ grub_uint16_t flags;
+ grub_uint32_t client_ip;
+ grub_uint32_t your_ip;
+ grub_uint32_t server_ip;
+ grub_uint32_t gateway_ip;
+ grub_net_bootp_mac_addr_t mac_addr;
+ char server_name[64];
+ char boot_file[128];
+ grub_uint8_t vendor[0];
+} __attribute__ ((packed));
+
+#define GRUB_NET_BOOTP_RFC1048_MAGIC_0 0x63
+#define GRUB_NET_BOOTP_RFC1048_MAGIC_1 0x82
+#define GRUB_NET_BOOTP_RFC1048_MAGIC_2 0x53
+#define GRUB_NET_BOOTP_RFC1048_MAGIC_3 0x63
+
+struct grub_net_network_level_interface *
+grub_net_configure_by_dhcp_ack (const char *name,
+ struct grub_net_card *card,
+ grub_net_interface_flags_t flags,
+ const struct grub_net_bootp_packet *bp,
+ grub_size_t size,
+ int is_def, char **device, char **path);
+
+void
+grub_net_process_dhcp (struct grub_net_buff *nb,
+ struct grub_net_card *card);
+
+int
+grub_net_hwaddr_cmp (const grub_net_link_level_address_t *a,
+ const grub_net_link_level_address_t *b);
+
+
+/*
+ Currently suppoerted adresses:
+ IPv4: XXX.XXX.XXX.XXX
+ */
+#define GRUB_NET_MAX_STR_ADDR_LEN sizeof ("XXX.XXX.XXX.XXX")
+
+void
+grub_net_addr_to_str (const grub_net_network_level_address_t *target,
+ char *buf);
+
+extern struct grub_net_network_level_interface *grub_net_network_level_interfaces;
+#define FOR_NET_NETWORK_LEVEL_INTERFACES(var) for (var = grub_net_network_level_interfaces; var; var = var->next)
+
+#define FOR_NET_NETWORK_LEVEL_INTERFACES_SAFE(var,next) for (var = grub_net_network_level_interfaces, next = var->next; var; var = next, next = var->next)
+
+void
+grub_net_poll_cards (unsigned time);
+
+void grub_bootp_init (void);
+void grub_bootp_fini (void);
+
+static inline void
+grub_net_network_level_interface_unregister (struct grub_net_network_level_interface *inter)
+{
+ inter->card->num_ifaces--;
+ *inter->prev = inter->next;
+ if (inter->next)
+ inter->next->prev = inter->prev;
+ inter->next = 0;
+ inter->prev = 0;
+}
-/* Note: Networks are very different from disks, because networks must
- be initialized before used, and the status is persistent. */
+extern char *grub_net_default_server;
#endif /* ! GRUB_NET_HEADER */
--- /dev/null
+#ifndef GRUB_NET_ARP_HEADER
+#define GRUB_NET_ARP_HEADER 1
+#include <grub/misc.h>
+#include <grub/net.h>
+
+enum
+{
+/* IANA ARP constant to define hardware type as ethernet. */
+ GRUB_NET_ARPHRD_ETHERNET = 1
+};
+
+/* ARP header operation codes */
+#define ARP_REQUEST 1
+#define ARP_REPLY 2
+
+struct arp_entry {
+ int avail;
+ grub_net_network_level_address_t nl_address;
+ grub_net_link_level_address_t ll_address;
+};
+
+struct arphdr {
+ grub_uint16_t hrd;
+ grub_uint16_t pro;
+ grub_uint8_t hln;
+ grub_uint8_t pln;
+ grub_uint16_t op;
+} __attribute__ ((packed));
+
+extern grub_err_t grub_net_arp_receive(struct grub_net_buff *nb);
+
+extern grub_err_t grub_net_arp_resolve(struct grub_net_network_level_interface *inf,
+ const grub_net_network_level_address_t *addr,
+ grub_net_link_level_address_t *hw_addr);
+
+#endif
--- /dev/null
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2010,2011 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_NET_ETHERNET_HEADER
+#define GRUB_NET_ETHERNET_HEADER 1
+#include <grub/types.h>
+#include <grub/net.h>
+
+/* IANA Ethertype */
+enum
+{
+ GRUB_NET_ETHERTYPE_IP = 0x0800,
+ GRUB_NET_ETHERTYPE_ARP = 0x0806
+};
+
+grub_err_t
+send_ethernet_packet (struct grub_net_network_level_interface *inf,
+ struct grub_net_buff *nb,
+ grub_net_link_level_address_t target_addr,
+ grub_uint16_t ethertype);
+grub_err_t
+grub_net_recv_ethernet_packet (struct grub_net_buff *nb,
+ const struct grub_net_card *card);
+
+#endif
--- /dev/null
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2010,2011 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_NET_IP_HEADER
+#define GRUB_NET_IP_HEADER 1
+#include <grub/misc.h>
+#include <grub/net.h>
+
+enum
+ {
+ IP_UDP = 0x11 /* UDP protocol */
+ };
+#define IP_BROADCAST 0xFFFFFFFF
+
+grub_uint16_t grub_net_ip_chksum(void *ipv, int len);
+
+grub_err_t
+grub_net_recv_ip_packets (struct grub_net_buff *nb,
+ const struct grub_net_card *card,
+ const grub_net_link_level_address_t *hwaddress);
+
+grub_err_t
+grub_net_send_ip_packet (struct grub_net_network_level_interface *inf,
+ const grub_net_network_level_address_t *target,
+ struct grub_net_buff *nb);
+
+#endif
--- /dev/null
+#ifndef GRUB_NETBUFF_HEADER
+#define GRUB_NETBUFF_HEADER
+
+#include <grub/misc.h>
+
+#define NETBUFF_ALIGN 2048
+#define NETBUFFMINLEN 64
+
+struct grub_net_buff
+{
+ /*Pointer to the start of the buffer*/
+ char *head;
+ /*Pointer to the data */
+ char *data;
+ /*Pointer to the tail */
+ char *tail;
+ /*Pointer to the end of the buffer*/
+ char *end;
+};
+
+grub_err_t grub_netbuff_put (struct grub_net_buff *net_buff ,grub_size_t len);
+grub_err_t grub_netbuff_unput (struct grub_net_buff *net_buff ,grub_size_t len);
+grub_err_t grub_netbuff_push (struct grub_net_buff *net_buff ,grub_size_t len);
+grub_err_t grub_netbuff_pull (struct grub_net_buff *net_buff ,grub_size_t len);
+grub_err_t grub_netbuff_reserve (struct grub_net_buff *net_buff ,grub_size_t len);
+grub_err_t grub_netbuff_clear (struct grub_net_buff *net_buff);
+struct grub_net_buff * grub_netbuff_alloc ( grub_size_t len );
+grub_err_t grub_netbuff_free (struct grub_net_buff *net_buff);
+
+#endif
--- /dev/null
+#ifndef GRUB_NET_UDP_HEADER
+#define GRUB_NET_UDP_HEADER 1
+#include <grub/types.h>
+#include <grub/net.h>
+
+struct udphdr
+{
+ grub_uint16_t src;
+ grub_uint16_t dst;
+ grub_uint16_t len;
+ grub_uint16_t chksum;
+} __attribute__ ((packed));
+
+
+grub_net_socket_t
+grub_net_udp_open (char *server,
+ grub_uint16_t out_port,
+ grub_err_t (*recv_hook) (grub_net_socket_t sock,
+ struct grub_net_buff *nb,
+ void *data),
+ void *recv_hook_data);
+
+static inline void
+grub_net_udp_close (grub_net_socket_t sock)
+{
+ grub_net_socket_unregister (sock);
+ grub_free (sock);
+}
+
+grub_err_t
+grub_net_send_udp_packet (const grub_net_socket_t socket, struct grub_net_buff *nb);
+
+grub_err_t
+grub_net_recv_udp_packet (struct grub_net_buff *nb,
+ struct grub_net_network_level_interface *inf);
+
+
+#endif
grub_uint16_t sectors_per_track;
grub_uint16_t num_heads;
grub_uint32_t num_hidden_sectors;
- grub_uint32_t reserved_3[2];
+ grub_uint32_t reserved_3;
+ grub_uint8_t bios_drive;
+ grub_uint8_t reserved_4[3];
grub_uint64_t num_total_sectors;
grub_uint64_t mft_lcn;
grub_uint64_t mft_mirr_lcn;
grub_int8_t clusters_per_mft;
- grub_int8_t reserved_4[3];
- grub_int8_t clusters_per_index;
grub_int8_t reserved_5[3];
+ grub_int8_t clusters_per_index;
+ grub_int8_t reserved_6[3];
grub_uint64_t num_serial;
grub_uint32_t checksum;
} __attribute__ ((packed));
struct grub_ntfs_data *data;
char *buf;
grub_uint64_t size;
+ grub_uint64_t mtime;
grub_uint32_t ino;
int inode_read;
struct grub_ntfs_attr attr;
#define GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART 0x730
-/* The offset of GRUB_PREFIX. */
-#define GRUB_KERNEL_I386_PC_PREFIX GRUB_KERNEL_I386_PC_RAW_SIZE
-
-/* End of the data section. */
-#define GRUB_KERNEL_I386_PC_PREFIX_END (GRUB_KERNEL_I386_PC_PREFIX + 0x40)
-
/* The segment where the kernel is loaded. */
#define GRUB_BOOT_I386_PC_KERNEL_SEG 0x800
/* The offset of GRUB_KERNEL_IMAGE_SIZE. */
#define GRUB_KERNEL_I386_QEMU_KERNEL_IMAGE_SIZE 0xc
-/* The offset of GRUB_PREFIX. */
-#define GRUB_KERNEL_I386_QEMU_PREFIX 0x10
-
-/* End of the data section. */
-#define GRUB_KERNEL_I386_QEMU_PREFIX_END 0x50
-
#define GRUB_KERNEL_I386_QEMU_LINK_ADDR 0x8200
/* The offset of GRUB_TOTAL_MODULE_SIZE. */
/* The offset of GRUB_COMPRESSED_SIZE. */
#define GRUB_KERNEL_SPARC64_IEEE1275_COMPRESSED_SIZE 0x10
-/* The offset of GRUB_PREFIX. */
-#define GRUB_KERNEL_SPARC64_IEEE1275_PREFIX 0x14
-
-/* End of the data section. */
-#define GRUB_KERNEL_SPARC64_IEEE1275_PREFIX_END 0x114
-
#define GRUB_BOOT_SPARC64_IEEE1275_LIST_SIZE 12
#define GRUB_BOOT_SPARC64_IEEE1275_IMAGE_ADDRESS 0x4400
#define GRUB_KERNEL_SPARC64_IEEE1275_RAW_SIZE 0
#define GRUB_KERNEL_SPARC64_IEEE1275_LINK_ADDR 0x4400
-#define GRUB_KERNEL_POWERPC_IEEE1275_PREFIX 0x4
-#define GRUB_KERNEL_POWERPC_IEEE1275_PREFIX_END 0x44
#define GRUB_KERNEL_POWERPC_IEEE1275_LINK_ALIGN 4
#define GRUB_KERNEL_POWERPC_IEEE1275_LINK_ADDR 0x200000
-#define GRUB_KERNEL_MIPS_YEELOONG_LINK_ADDR 0x80200000
+#define GRUB_KERNEL_MIPS_LOONGSON_LINK_ADDR 0x80200000
-#define GRUB_KERNEL_MIPS_YEELOONG_LINK_ALIGN 32
+#define GRUB_KERNEL_MIPS_LOONGSON_LINK_ALIGN 32
-#define GRUB_KERNEL_MIPS_YEELOONG_COMPRESSED_SIZE 0x8
-#define GRUB_KERNEL_MIPS_YEELOONG_UNCOMPRESSED_SIZE 0xc
+#define GRUB_KERNEL_MIPS_LOONGSON_COMPRESSED_SIZE 0x8
+#define GRUB_KERNEL_MIPS_LOONGSON_UNCOMPRESSED_SIZE 0xc
+#define GRUB_KERNEL_MIPS_LOONGSON_UNCOMPRESSED_ADDR 0x10
-#define GRUB_KERNEL_MIPS_YEELOONG_TOTAL_MODULE_SIZE 0x08
-#define GRUB_KERNEL_MIPS_YEELOONG_PREFIX 0x0c
-#define GRUB_KERNEL_MIPS_YEELOONG_PREFIX_END 0x54
+#define GRUB_KERNEL_MIPS_LOONGSON_TOTAL_MODULE_SIZE 0x08
-/* The offset of GRUB_PREFIX. */
-#define GRUB_KERNEL_I386_EFI_PREFIX 0x8
+#define GRUB_KERNEL_MIPS_QEMU_MIPS_LINK_ADDR 0x80200000
+#define GRUB_KERNEL_MIPS_QEMU_MIPS_LINK_ALIGN 32
+#define GRUB_KERNEL_MIPS_QEMU_MIPS_COMPRESSED_SIZE 0x8
+#define GRUB_KERNEL_MIPS_QEMU_MIPS_UNCOMPRESSED_SIZE 0xc
+#define GRUB_KERNEL_MIPS_QEMU_MIPS_UNCOMPRESSED_ADDR 0x10
+#define GRUB_KERNEL_MIPS_QEMU_MIPS_TOTAL_MODULE_SIZE 0x08
-/* End of the data section. */
-#define GRUB_KERNEL_I386_EFI_PREFIX_END 0x50
+#define GRUB_KERNEL_MIPS_ARC_LINK_ADDR 0x8bd00000
-/* The offset of GRUB_PREFIX. */
-#define GRUB_KERNEL_X86_64_EFI_PREFIX 0x8
+#define GRUB_KERNEL_MIPS_ARC_LINK_ALIGN 32
-/* End of the data section. */
-#define GRUB_KERNEL_X86_64_EFI_PREFIX_END 0x50
+#define GRUB_KERNEL_MIPS_ARC_COMPRESSED_SIZE 0x8
+#define GRUB_KERNEL_MIPS_ARC_UNCOMPRESSED_SIZE 0xc
+#define GRUB_KERNEL_MIPS_ARC_UNCOMPRESSED_ADDR 0x10
-#define GRUB_KERNEL_I386_COREBOOT_PREFIX 0x2
-#define GRUB_KERNEL_I386_COREBOOT_PREFIX_END 0x42
-#define GRUB_KERNEL_I386_COREBOOT_LINK_ADDR 0x8200
+#define GRUB_KERNEL_MIPS_ARC_TOTAL_MODULE_SIZE 0x08
-#define GRUB_KERNEL_I386_MULTIBOOT_PREFIX GRUB_KERNEL_I386_COREBOOT_PREFIX
-#define GRUB_KERNEL_I386_MULTIBOOT_PREFIX_END GRUB_KERNEL_I386_COREBOOT_PREFIX_END
+#define GRUB_KERNEL_I386_COREBOOT_LINK_ADDR 0x8200
-#define GRUB_KERNEL_I386_IEEE1275_PREFIX 0x2
-#define GRUB_KERNEL_I386_IEEE1275_PREFIX_END 0x42
#define GRUB_KERNEL_I386_IEEE1275_LINK_ADDR 0x10000
#define GRUB_KERNEL_I386_IEEE1275_MOD_ALIGN 0x1000
/* Non-zero value is only needed for PowerMacs. */
#define GRUB_KERNEL_I386_IEEE1275_MOD_GAP 0x0
#define GRUB_KERNEL_I386_COREBOOT_MOD_GAP 0x0
+#define GRUB_KERNEL_SPARC64_IEEE1275_MOD_GAP 0x0
#define GRUB_KERNEL_POWERPC_IEEE1275_MOD_ALIGN 0x1000
+#define GRUB_KERNEL_SPARC64_IEEE1275_MOD_ALIGN 0x1
-#define GRUB_KERNEL_MIPS_YEELOONG_MOD_ALIGN 0x1
+#define GRUB_KERNEL_MIPS_LOONGSON_MOD_ALIGN 0x1
+#define GRUB_KERNEL_MIPS_ARC_MOD_ALIGN 0x1
+#define GRUB_KERNEL_MIPS_QEMU_MIPS_MOD_ALIGN 0x1
/* Minimal gap between _end and the start of the modules. It's a hack
for PowerMac to prevent "CLAIM failed" error. The real fix is to
#define GRUB_KERNEL_MACHINE_KERNEL_IMAGE_SIZE GRUB_OFFSETS_CONCAT (GRUB_KERNEL_, GRUB_MACHINE, _KERNEL_IMAGE_SIZE)
#define GRUB_KERNEL_MACHINE_COMPRESSED_SIZE GRUB_OFFSETS_CONCAT (GRUB_KERNEL_, GRUB_MACHINE, _COMPRESSED_SIZE)
#define GRUB_KERNEL_MACHINE_UNCOMPRESSED_SIZE GRUB_OFFSETS_CONCAT (GRUB_KERNEL_, GRUB_MACHINE, _UNCOMPRESSED_SIZE)
+#define GRUB_KERNEL_MACHINE_UNCOMPRESSED_ADDR GRUB_OFFSETS_CONCAT (GRUB_KERNEL_, GRUB_MACHINE, _UNCOMPRESSED_ADDR)
-#define GRUB_KERNEL_MACHINE_PREFIX GRUB_OFFSETS_CONCAT (GRUB_KERNEL_, GRUB_MACHINE, _PREFIX)
-#define GRUB_KERNEL_MACHINE_PREFIX_END GRUB_OFFSETS_CONCAT (GRUB_KERNEL_, GRUB_MACHINE, _PREFIX_END)
#define GRUB_BOOT_MACHINE_KERNEL_SEG GRUB_OFFSETS_CONCAT (GRUB_BOOT_, GRUB_MACHINE, _KERNEL_SEG)
#define GRUB_MEMORY_MACHINE_UPPER GRUB_OFFSETS_CONCAT (GRUB_MEMORY_, GRUB_MACHINE, _UPPER)
#define GRUB_KERNEL_MACHINE_RAW_SIZE GRUB_OFFSETS_CONCAT (GRUB_KERNEL_, GRUB_MACHINE, _RAW_SIZE)
#define GRUB_KERNEL_MACHINE_INSTALL_BSD_PART GRUB_OFFSETS_CONCAT (GRUB_KERNEL_, GRUB_MACHINE, _INSTALL_BSD_PART)
#define GRUB_KERNEL_MACHINE_INSTALL_DOS_PART GRUB_OFFSETS_CONCAT (GRUB_KERNEL_, GRUB_MACHINE, _INSTALL_DOS_PART)
+#define GRUB_MACHINE_LINK_ADDR GRUB_OFFSETS_CONCAT (GRUB_KERNEL_, GRUB_MACHINE, _LINK_ADDR)
#endif
#ifndef ASM_FILE
int number; /* The device number, taken from md_minor so we
are consistent with the device name in
Linux. */
+ int became_readable_at;
int level; /* RAID levels, only 0, 1 or 5 at the moment. */
int layout; /* Layout for RAID 5/6. */
unsigned int total_devs; /* Total number of devices in the array. */
#ifndef GRUB_SCSI_H
#define GRUB_SCSI_H 1
+#include <grub/disk.h>
+
typedef struct grub_scsi_dev *grub_scsi_dev_t;
void grub_scsi_dev_register (grub_scsi_dev_t dev);
enum
{
GRUB_SCSI_SUBSYSTEM_USBMS,
- GRUB_SCSI_SUBSYSTEM_ATAPI
+ GRUB_SCSI_SUBSYSTEM_PATA,
+ GRUB_SCSI_SUBSYSTEM_AHCI,
+ GRUB_SCSI_NUM_SUBSYSTEMS
};
+extern const char grub_scsi_names[GRUB_SCSI_NUM_SUBSYSTEMS][5];
+
#define GRUB_SCSI_ID_SUBSYSTEM_SHIFT 24
#define GRUB_SCSI_ID_BUS_SHIFT 8
#define GRUB_SCSI_ID_LUN_SHIFT 0
struct grub_scsi_dev
{
- /* The device name. */
- const char *name;
-
- grub_uint8_t id;
-
/* Call HOOK with each device name, until HOOK returns non-zero. */
- int (*iterate) (int (*hook) (int bus, int luns));
+ int (*iterate) (int NESTED_FUNC_ATTR (*hook) (int id, int bus, int luns),
+ grub_disk_pull_t pull);
/* Open the device named NAME, and set up SCSI. */
- grub_err_t (*open) (int bus, struct grub_scsi *scsi);
+ grub_err_t (*open) (int id, int bus, struct grub_scsi *scsi);
/* Close the scsi device SCSI. */
void (*close) (struct grub_scsi *scsi);
{
struct grub_serial_config config =
{
-#ifdef GRUB_MACHINE_MIPS_YEELOONG
+#ifdef GRUB_MACHINE_MIPS_LOONGSON
.speed = 115200,
#else
.speed = 9600,
}
}
+static inline void
+grub_term_register_input_inactive (const char *name __attribute__ ((unused)),
+ grub_term_input_t term)
+{
+ grub_list_push (GRUB_AS_LIST_P (&grub_term_inputs_disabled),
+ GRUB_AS_LIST (term));
+}
+
static inline void
grub_term_register_input_active (const char *name __attribute__ ((unused)),
grub_term_input_t term)
}
}
+static inline void
+grub_term_register_output_inactive (const char *name __attribute__ ((unused)),
+ grub_term_output_t term)
+{
+ grub_list_push (GRUB_AS_LIST_P (&grub_term_outputs_disabled),
+ GRUB_AS_LIST (term));
+}
+
static inline void
grub_term_register_output_active (const char *name __attribute__ ((unused)),
grub_term_output_t term)
grub_err_t EXPORT_FUNC(grub_terminfo_set_current) (struct grub_term_output *term,
const char *);
-#define GRUB_TERMINFO_READKEY_MAX_LEN 4
+#define GRUB_TERMINFO_READKEY_MAX_LEN 6
struct grub_terminfo_input_state
{
int input_buf[GRUB_TERMINFO_READKEY_MAX_LEN];
# if GRUB_CPU_SIZEOF_LONG == 8
# define PRIxGRUB_SIZE "lx"
+# define PRIxGRUB_ADDR "lx"
# define PRIuGRUB_SIZE "lu"
# else
# define PRIxGRUB_SIZE "llx"
+# define PRIxGRUB_ADDR "llx"
# define PRIuGRUB_SIZE "llu"
# endif
#else
typedef grub_int32_t grub_ssize_t;
# define PRIxGRUB_SIZE "x"
+# define PRIxGRUB_ADDR "x"
# define PRIuGRUB_SIZE "u"
#endif
+#define GRUB_UCHAR_MAX 0xFF
+#define GRUB_USHRT_MAX 65535
+#define GRUB_UINT_MAX 4294967295U
+
#if GRUB_CPU_SIZEOF_LONG == 8
# define GRUB_ULONG_MAX 18446744073709551615UL
# define GRUB_LONG_MAX 9223372036854775807L
# define grub_cpu_to_le32_compile_time(x) ((grub_uint32_t) (x))
#endif /* ! WORDS_BIGENDIAN */
+static inline grub_uint16_t grub_get_unaligned16(void *ptr)
+{
+ struct
+ {
+ grub_uint16_t d;
+ } __attribute__((packed)) *dd = ptr;
+ return dd->d;
+}
+
+static inline grub_uint32_t grub_get_unaligned32(void *ptr)
+{
+ struct
+ {
+ grub_uint32_t d;
+ } __attribute__((packed)) *dd = ptr;
+ return dd->d;
+}
+
+static inline grub_uint64_t grub_get_unaligned64(void *ptr)
+{
+ struct
+ {
+ grub_uint64_t d;
+ } __attribute__((packed)) *dd = ptr;
+ return dd->d;
+}
+
#endif /* ! GRUB_TYPES_HEADER */
GRUB_USB_ERR_BABBLE,
GRUB_USB_ERR_TIMEOUT,
GRUB_USB_ERR_BITSTUFF,
- GRUB_USB_ERR_UNRECOVERABLE
+ GRUB_USB_ERR_UNRECOVERABLE,
+ GRUB_USB_ERR_BADDEVICE
} grub_usb_err_t;
typedef enum
/* lvm.h - LVM support for GRUB utils. */
/*
* GRUB -- GRand Unified Bootloader
- * Copyright (C) 2006,2007 Free Software Foundation, Inc.
+ * Copyright (C) 2006,2007,2011 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
#ifndef GRUB_LVM_UTIL_HEADER
#define GRUB_LVM_UTIL_HEADER 1
+#if defined(__linux__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
+
#ifdef __linux__
+#define LVM_DEV_MAPPER_STRING "/dev/mapper/"
+#else
+#define LVM_DEV_MAPPER_STRING "/dev/linux_lvm/"
+#endif
+
int grub_util_lvm_isvolume (char *name);
#endif
void sync (void);
int fsync (int fno);
-void sleep(int s);
grub_int64_t grub_util_get_disk_size (char *name);
+++ /dev/null
-/* raid.h - RAID support for GRUB utils. */
-/*
- * GRUB -- GRand Unified Bootloader
- * Copyright (C) 2006,2007 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/>.
- */
-
-#ifndef GRUB_RAID_UTIL_HEADER
-#define GRUB_RAID_UTIL_HEADER 1
-
-#ifdef __linux__
-char** grub_util_raid_getmembers (const char *name);
-#endif
-
-#endif /* ! GRUB_RAID_UTIL_HEADER */
#ifndef GRUB_VGA_HEADER
#define GRUB_VGA_HEADER 1
+#ifndef GRUB_MACHINE_MIPS_QEMU_MIPS
#include <grub/pci.h>
+#else
+#include <grub/cpu/io.h>
+#define GRUB_MACHINE_PCI_IO_BASE 0xb4000000
+#endif
enum
{
{
GRUB_VGA_IO_MISC_COLOR = 0x01,
GRUB_VGA_IO_MISC_ENABLE_VRAM_ACCESS = 0x02,
- GRUB_VGA_IO_MISC_EXTERNAL_CLOCK_0 = 0x08,
GRUB_VGA_IO_MISC_28MHZ = 0x04,
+ GRUB_VGA_IO_MISC_EXTERNAL_CLOCK_0 = 0x08,
GRUB_VGA_IO_MISC_UPPER_64K = 0x20,
GRUB_VGA_IO_MISC_NEGATIVE_HORIZ_POLARITY = 0x40,
GRUB_VGA_IO_MISC_NEGATIVE_VERT_POLARITY = 0x80,
grub_vga_write_arx (grub_uint8_t val, grub_uint8_t addr)
{
grub_inb (GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_INPUT_STATUS1_REGISTER);
+ grub_inb (GRUB_MACHINE_PCI_IO_BASE + 0x3ba);
+
grub_outb (addr, GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_ARX);
grub_inb (GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_ARX_READ);
grub_outb (val, GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_ARX);
}
+static inline grub_uint8_t
+grub_vga_read_arx (grub_uint8_t addr)
+{
+ grub_uint8_t val;
+ grub_inb (GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_INPUT_STATUS1_REGISTER);
+ grub_outb (addr, GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_ARX);
+ val = grub_inb (GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_ARX_READ);
+ grub_outb (val, GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_ARX);
+ return val;
+}
+
struct grub_video_hw_config
{
unsigned vertical_total;
specific coding format. */
typedef grub_uint32_t grub_video_color_t;
+/* Video color in hardware independent format. */
+typedef struct grub_video_rgba_color
+{
+ grub_uint8_t red;
+ grub_uint8_t green;
+ grub_uint8_t blue;
+ grub_uint8_t alpha;
+} grub_video_rgba_color_t;
+
/* This structure is driver specific and should not be accessed directly by
outside code. */
struct grub_video_render_target;
grub_uint8_t a; /* Reserved bits value (0-255). */
};
+struct grub_video_edid_info
+{
+ grub_uint8_t header[8];
+ grub_uint16_t manufacturer_id;
+ grub_uint16_t product_id;
+ grub_uint32_t serial_number;
+ grub_uint8_t week_of_manufacture;
+ grub_uint8_t year_of_manufacture;
+ grub_uint8_t version;
+ grub_uint8_t revision;
+
+ grub_uint8_t video_input_definition;
+ grub_uint8_t max_horizontal_image_size;
+ grub_uint8_t max_vertical_image_size;
+ grub_uint8_t display_gamma;
+ grub_uint8_t feature_support;
+#define GRUB_VIDEO_EDID_FEATURE_PREFERRED_TIMING_MODE (1 << 1)
+
+ grub_uint8_t red_green_lo;
+ grub_uint8_t blue_white_lo;
+ grub_uint8_t red_x_hi;
+ grub_uint8_t red_y_hi;
+ grub_uint8_t green_x_hi;
+ grub_uint8_t green_y_hi;
+ grub_uint8_t blue_x_hi;
+ grub_uint8_t blue_y_hi;
+ grub_uint8_t white_x_hi;
+ grub_uint8_t white_y_hi;
+
+ grub_uint8_t established_timings_1;
+ grub_uint8_t established_timings_2;
+ grub_uint8_t manufacturer_reserved_timings;
+
+ grub_uint16_t standard_timings[8];
+
+ struct {
+ grub_uint16_t pixel_clock;
+ /* Only valid if the pixel clock is non-null. */
+ grub_uint8_t horizontal_active_lo;
+ grub_uint8_t horizontal_blanking_lo;
+ grub_uint8_t horizontal_hi;
+ grub_uint8_t vertical_active_lo;
+ grub_uint8_t vertical_blanking_lo;
+ grub_uint8_t vertical_hi;
+ grub_uint8_t horizontal_sync_offset_lo;
+ grub_uint8_t horizontal_sync_pulse_width_lo;
+ grub_uint8_t vertical_sync_lo;
+ grub_uint8_t sync_hi;
+ grub_uint8_t horizontal_image_size_lo;
+ grub_uint8_t vertical_image_size_lo;
+ grub_uint8_t image_size_hi;
+ grub_uint8_t horizontal_border;
+ grub_uint8_t vertical_border;
+ grub_uint8_t flags;
+ } detailed_timings[4];
+
+ grub_uint8_t extension_flag;
+ grub_uint8_t checksum;
+} __attribute__ ((packed));
+
typedef enum grub_video_driver_id
{
GRUB_VIDEO_DRIVER_NONE,
GRUB_VIDEO_DRIVER_VGA,
GRUB_VIDEO_DRIVER_CIRRUS,
GRUB_VIDEO_DRIVER_BOCHS,
- GRUB_VIDEO_DRIVER_SDL
+ GRUB_VIDEO_DRIVER_SDL,
+ GRUB_VIDEO_DRIVER_SIS315PRO,
+ GRUB_VIDEO_DRIVER_RADEON_FULOONG2E,
} grub_video_driver_id_t;
typedef enum grub_video_adapter_prio
int (*iterate) (int (*hook) (const struct grub_video_mode_info *info));
+ grub_err_t (*get_edid) (struct grub_video_edid_info *edid_info);
+
void (*print_adapter_specific_info) (void);
};
typedef struct grub_video_adapter *grub_video_adapter_t;
grub_err_t grub_video_get_active_render_target (struct grub_video_render_target **target);
+grub_err_t EXPORT_FUNC (grub_video_edid_checksum) (struct grub_video_edid_info *edid_info);
+grub_err_t EXPORT_FUNC (grub_video_edid_preferred_mode) (struct grub_video_edid_info *edid_info,
+ unsigned int *width,
+ unsigned int *height);
+
grub_err_t EXPORT_FUNC (grub_video_set_mode) (const char *modestring,
unsigned int modemask,
unsigned int modevalue);
grub_video_driver_id_t EXPORT_FUNC (grub_video_get_driver_id) (void);
+static __inline grub_video_rgba_color_t
+grub_video_rgba_color_rgb (int r, int g, int b)
+{
+ grub_video_rgba_color_t c;
+ c.red = r;
+ c.green = g;
+ c.blue = b;
+ c.alpha = 255;
+ return c;
+}
+
+static __inline grub_video_color_t
+grub_video_map_rgba_color (grub_video_rgba_color_t c)
+{
+ return grub_video_map_rgba (c.red, c.green, c.blue, c.alpha);
+}
+
+int EXPORT_FUNC (grub_video_get_named_color) (const char *name,
+ grub_video_rgba_color_t *color);
+
+grub_err_t EXPORT_FUNC (grub_video_parse_color) (const char *s,
+ grub_video_rgba_color_t *color);
+
#endif /* ! GRUB_VIDEO_HEADER */
{
grub_uint8_t la_array[ZAP_LEAF_ARRAY_BYTES];
grub_uint64_t la_array64;
- };
+ } __attribute__ ((packed));
grub_uint16_t la_next; /* next blk or CHAIN_END */
} l_array;
struct zap_leaf_free {
ZIO_COMPRESS_OFF,
ZIO_COMPRESS_LZJB,
ZIO_COMPRESS_EMPTY,
- ZIO_COMPRESS_GZIP,
+ ZIO_COMPRESS_GZIP1,
+ ZIO_COMPRESS_GZIP2,
+ ZIO_COMPRESS_GZIP3,
+ ZIO_COMPRESS_GZIP4,
+ ZIO_COMPRESS_GZIP5,
+ ZIO_COMPRESS_GZIP6,
+ ZIO_COMPRESS_GZIP7,
+ ZIO_COMPRESS_GZIP8,
+ ZIO_COMPRESS_GZIP9,
ZIO_COMPRESS_FUNCTIONS
};
-# List of files which contain translatable strings.
-grub-core/commands/acpi.c
-grub-core/commands/blocklist.c
-grub-core/commands/boot.c
-grub-core/commands/cat.c
-grub-core/commands/cmp.c
-grub-core/commands/configfile.c
-grub-core/commands/date.c
-grub-core/commands/echo.c
-grub-core/commands/efi/fixvideo.c
-grub-core/commands/efi/loadbios.c
-grub-core/commands/gptsync.c
-grub-core/commands/halt.c
-grub-core/commands/hashsum.c
-grub-core/commands/hdparm.c
-grub-core/commands/help.c
-grub-core/commands/hexdump.c
-grub-core/commands/i386/cpuid.c
-grub-core/commands/i386/pc/drivemap.c
-grub-core/commands/i386/pc/halt.c
-grub-core/commands/i386/pc/lsapm.c
-grub-core/commands/i386/pc/play.c
-grub-core/commands/i386/pc/pxecmd.c
-grub-core/commands/ieee1275/suspend.c
-grub-core/commands/iorw.c
-grub-core/commands/keylayouts.c
-grub-core/commands/keystatus.c
-grub-core/commands/legacycfg.c
-grub-core/commands/loadenv.c
-grub-core/commands/ls.c
-grub-core/commands/lsacpi.c
-grub-core/commands/lsmmap.c
-grub-core/commands/lspci.c
-grub-core/commands/memrw.c
-grub-core/commands/menuentry.c
-grub-core/commands/minicmd.c
-grub-core/commands/parttool.c
-grub-core/commands/password.c
-grub-core/commands/password_pbkdf2.c
-grub-core/commands/probe.c
-grub-core/commands/read.c
-grub-core/commands/reboot.c
-grub-core/commands/regexp.c
-grub-core/commands/search.c
-grub-core/commands/search_file.c
-grub-core/commands/search_label.c
-grub-core/commands/search_uuid.c
-grub-core/commands/search_wrap.c
-grub-core/commands/setpci.c
-grub-core/commands/sleep.c
-grub-core/commands/terminal.c
-grub-core/commands/test.c
-grub-core/commands/testload.c
-grub-core/commands/true.c
-grub-core/commands/usbtest.c
-grub-core/commands/videoinfo.c
-grub-core/commands/videotest.c
-grub-core/commands/xnu_uuid.c
-
-grub-core/disk/loopback.c
-
-grub-core/efiemu/main.c
-
-grub-core/font/font_cmd.c
-
-grub-core/gettext/gettext.c
-
-grub-core/gfxmenu/gui_progress_bar.c
-
-grub-core/hello/hello.c
-
-grub-core/kern/corecmd.c
-grub-core/kern/emu/hostdisk.c
-grub-core/kern/emu/misc.c
-grub-core/kern/err.c
-
-grub-core/lib/arg.c
-
-grub-core/loader/efi/appleloader.c
-grub-core/loader/efi/chainloader.c
-grub-core/loader/i386/bsd.c
-grub-core/loader/i386/linux.c
-grub-core/loader/i386/pc/chainloader.c
-grub-core/loader/i386/pc/linux.c
-grub-core/loader/i386/pc/ntldr.c
-grub-core/loader/i386/xnu.c
-grub-core/loader/mips/linux.c
-grub-core/loader/multiboot.c
-grub-core/loader/powerpc/ieee1275/linux.c
-grub-core/loader/sparc64/ieee1275/linux.c
-grub-core/loader/xnu.c
-
-grub-core/mmap/mmap.c
-
-grub-core/normal/auth.c
-grub-core/normal/cmdline.c
-grub-core/normal/color.c
-grub-core/normal/context.c
-grub-core/normal/dyncmd.c
-grub-core/normal/main.c
-grub-core/normal/menu.c
-grub-core/normal/menu_entry.c
-grub-core/normal/menu_text.c
-grub-core/normal/misc.c
-
-grub-core/script/main.c
-
-grub-core/term/gfxterm.c
-grub-core/term/serial.c
-grub-core/term/terminfo.c
-
-grub-core/tests/test_blockarg.c
-
-util/grub-editenv.c
-util/grub-fstest.c
-util/grub-mkimage.c
-util/grub-setup.c
+./grub-core/boot/decompressor/minilib.c
+./grub-core/boot/decompressor/none.c
+./grub-core/boot/decompressor/xz.c
+./grub-core/bus/bonito.c
+./grub-core/bus/cs5536.c
+./grub-core/bus/emu/pci.c
+./grub-core/bus/pci.c
+./grub-core/bus/usb/emu/usb.c
+./grub-core/bus/usb/ohci.c
+./grub-core/bus/usb/serial/common.c
+./grub-core/bus/usb/serial/ftdi.c
+./grub-core/bus/usb/serial/pl2303.c
+./grub-core/bus/usb/uhci.c
+./grub-core/bus/usb/usb.c
+./grub-core/bus/usb/usbhub.c
+./grub-core/bus/usb/usbtrans.c
+./grub-core/commands/acpi.c
+./grub-core/commands/acpihalt.c
+./grub-core/commands/arc/lsdev.c
+./grub-core/commands/blocklist.c
+./grub-core/commands/boot.c
+./grub-core/commands/cat.c
+./grub-core/commands/cmp.c
+./grub-core/commands/configfile.c
+./grub-core/commands/date.c
+./grub-core/commands/echo.c
+./grub-core/commands/efi/acpi.c
+./grub-core/commands/efi/fixvideo.c
+./grub-core/commands/efi/loadbios.c
+./grub-core/commands/efi/lsefimmap.c
+./grub-core/commands/efi/lsefisystab.c
+./grub-core/commands/efi/lssal.c
+./grub-core/commands/extcmd.c
+./grub-core/commands/gptsync.c
+./grub-core/commands/halt.c
+./grub-core/commands/hashsum.c
+./grub-core/commands/hdparm.c
+./grub-core/commands/help.c
+./grub-core/commands/hexdump.c
+./grub-core/commands/i386/cmostest.c
+./grub-core/commands/i386/cpuid.c
+./grub-core/commands/i386/pc/acpi.c
+./grub-core/commands/i386/pc/drivemap.c
+./grub-core/commands/i386/pc/halt.c
+./grub-core/commands/i386/pc/lsapm.c
+./grub-core/commands/i386/pc/play.c
+./grub-core/commands/i386/pc/sendkey.c
+./grub-core/commands/ieee1275/suspend.c
+./grub-core/commands/iorw.c
+./grub-core/commands/keylayouts.c
+./grub-core/commands/keystatus.c
+./grub-core/commands/legacycfg.c
+./grub-core/commands/loadenv.c
+./grub-core/commands/lsacpi.c
+./grub-core/commands/ls.c
+./grub-core/commands/lsmmap.c
+./grub-core/commands/lspci.c
+./grub-core/commands/memrw.c
+./grub-core/commands/menuentry.c
+./grub-core/commands/minicmd.c
+./grub-core/commands/mips/loongson/lsspd.c
+./grub-core/commands/parttool.c
+./grub-core/commands/password.c
+./grub-core/commands/password_pbkdf2.c
+./grub-core/commands/probe.c
+./grub-core/commands/read.c
+./grub-core/commands/reboot.c
+./grub-core/commands/regexp.c
+./grub-core/commands/search.c
+./grub-core/commands/search_file.c
+./grub-core/commands/search_label.c
+./grub-core/commands/search_uuid.c
+./grub-core/commands/search_wrap.c
+./grub-core/commands/setpci.c
+./grub-core/commands/sleep.c
+./grub-core/commands/terminal.c
+./grub-core/commands/test.c
+./grub-core/commands/testload.c
+./grub-core/commands/time.c
+./grub-core/commands/true.c
+./grub-core/commands/usbtest.c
+./grub-core/commands/videoinfo.c
+./grub-core/commands/videotest.c
+./grub-core/commands/wildcard.c
+./grub-core/commands/xnu_uuid.c
+./grub-core/disk/AFSplitter.c
+./grub-core/disk/ahci.c
+./grub-core/disk/arc/arcdisk.c
+./grub-core/disk/ata.c
+./grub-core/disk/cryptodisk.c
+./grub-core/disk/dmraid_nvidia.c
+./grub-core/disk/efi/efidisk.c
+./grub-core/disk/geli.c
+./grub-core/disk/host.c
+./grub-core/disk/i386/pc/biosdisk.c
+./grub-core/disk/ieee1275/nand.c
+./grub-core/disk/ieee1275/ofdisk.c
+./grub-core/disk/loopback.c
+./grub-core/disk/luks.c
+./grub-core/disk/lvm.c
+./grub-core/disk/mdraid1x_linux.c
+./grub-core/disk/mdraid_linux.c
+./grub-core/disk/memdisk.c
+./grub-core/disk/pata.c
+./grub-core/disk/raid5_recover.c
+./grub-core/disk/raid6_recover.c
+./grub-core/disk/raid.c
+./grub-core/disk/scsi.c
+./grub-core/disk/usbms.c
+./grub-core/efiemu/i386/coredetect.c
+./grub-core/efiemu/i386/loadcore32.c
+./grub-core/efiemu/i386/loadcore64.c
+./grub-core/efiemu/i386/nocfgtables.c
+./grub-core/efiemu/i386/pc/cfgtables.c
+./grub-core/efiemu/loadcore32.c
+./grub-core/efiemu/loadcore64.c
+./grub-core/efiemu/loadcore.c
+./grub-core/efiemu/loadcore_common.c
+./grub-core/efiemu/main.c
+./grub-core/efiemu/mm.c
+./grub-core/efiemu/pnvram.c
+./grub-core/efiemu/prepare32.c
+./grub-core/efiemu/prepare64.c
+./grub-core/efiemu/prepare.c
+./grub-core/efiemu/runtime/efiemu.c
+./grub-core/efiemu/symbols.c
+./grub-core/font/font.c
+./grub-core/font/font_cmd.c
+./grub-core/fs/affs.c
+./grub-core/fs/afs_be.c
+./grub-core/fs/afs.c
+./grub-core/fs/befs_be.c
+./grub-core/fs/befs.c
+./grub-core/fs/btrfs.c
+./grub-core/fs/cpio.c
+./grub-core/fs/ext2.c
+./grub-core/fs/fat.c
+./grub-core/fs/fshelp.c
+./grub-core/fs/hfs.c
+./grub-core/fs/hfsplus.c
+./grub-core/fs/iso9660.c
+./grub-core/fs/jfs.c
+./grub-core/fs/minix2.c
+./grub-core/fs/minix3.c
+./grub-core/fs/minix.c
+./grub-core/fs/nilfs2.c
+./grub-core/fs/ntfs.c
+./grub-core/fs/ntfscomp.c
+./grub-core/fs/reiserfs.c
+./grub-core/fs/romfs.c
+./grub-core/fs/sfs.c
+./grub-core/fs/squash4.c
+./grub-core/fs/tar.c
+./grub-core/fs/udf.c
+./grub-core/fs/ufs2.c
+./grub-core/fs/ufs.c
+./grub-core/fs/xfs.c
+./grub-core/fs/zfs/zfs.c
+./grub-core/fs/zfs/zfs_fletcher.c
+./grub-core/fs/zfs/zfsinfo.c
+./grub-core/fs/zfs/zfs_lzjb.c
+./grub-core/fs/zfs/zfs_sha256.c
+./grub-core/gentrigtables.c
+./grub-core/gettext/gettext.c
+./grub-core/gfxmenu/font.c
+./grub-core/gfxmenu/gfxmenu.c
+./grub-core/gfxmenu/gui_box.c
+./grub-core/gfxmenu/gui_canvas.c
+./grub-core/gfxmenu/gui_circular_progress.c
+./grub-core/gfxmenu/gui_image.c
+./grub-core/gfxmenu/gui_label.c
+./grub-core/gfxmenu/gui_list.c
+./grub-core/gfxmenu/gui_progress_bar.c
+./grub-core/gfxmenu/gui_string_util.c
+./grub-core/gfxmenu/gui_util.c
+./grub-core/gfxmenu/icon_manager.c
+./grub-core/gfxmenu/model.c
+./grub-core/gfxmenu/theme_loader.c
+./grub-core/gfxmenu/view.c
+./grub-core/gfxmenu/widget-box.c
+./grub-core/gnulib/alloca.c
+./grub-core/gnulib/argp-ba.c
+./grub-core/gnulib/argp-eexst.c
+./grub-core/gnulib/argp-fmtstream.c
+./grub-core/gnulib/argp-fs-xinl.c
+./grub-core/gnulib/argp-help.c
+./grub-core/gnulib/argp-parse.c
+./grub-core/gnulib/argp-pin.c
+./grub-core/gnulib/argp-pv.c
+./grub-core/gnulib/argp-pvh.c
+./grub-core/gnulib/argp-xinl.c
+./grub-core/gnulib/asnprintf.c
+./grub-core/gnulib/basename-lgpl.c
+./grub-core/gnulib/btowc.c
+./grub-core/gnulib/dirname-lgpl.c
+./grub-core/gnulib/error.c
+./grub-core/gnulib/fnmatch.c
+./grub-core/gnulib/fnmatch_loop.c
+./grub-core/gnulib/getdelim.c
+./grub-core/gnulib/getline.c
+./grub-core/gnulib/getopt1.c
+./grub-core/gnulib/getopt.c
+./grub-core/gnulib/localcharset.c
+./grub-core/gnulib/malloc.c
+./grub-core/gnulib/mbrtowc.c
+./grub-core/gnulib/mbsinit.c
+./grub-core/gnulib/mbsrtowcs.c
+./grub-core/gnulib/mbsrtowcs-state.c
+./grub-core/gnulib/memchr.c
+./grub-core/gnulib/mempcpy.c
+./grub-core/gnulib/nl_langinfo.c
+./grub-core/gnulib/printf-args.c
+./grub-core/gnulib/printf-parse.c
+./grub-core/gnulib/progname.c
+./grub-core/gnulib/rawmemchr.c
+./grub-core/gnulib/realloc.c
+./grub-core/gnulib/regcomp.c
+./grub-core/gnulib/regex.c
+./grub-core/gnulib/regexec.c
+./grub-core/gnulib/regex_internal.c
+./grub-core/gnulib/sleep.c
+./grub-core/gnulib/stdio-write.c
+./grub-core/gnulib/strcasecmp.c
+./grub-core/gnulib/strchrnul.c
+./grub-core/gnulib/strerror.c
+./grub-core/gnulib/stripslash.c
+./grub-core/gnulib/strncasecmp.c
+./grub-core/gnulib/strndup.c
+./grub-core/gnulib/strnlen1.c
+./grub-core/gnulib/strnlen.c
+./grub-core/gnulib/vasnprintf.c
+./grub-core/gnulib/vsnprintf.c
+./grub-core/gnulib/wcrtomb.c
+./grub-core/hello/hello.c
+./grub-core/hook/datehook.c
+./grub-core/io/bufio.c
+./grub-core/io/gzio.c
+./grub-core/io/xzio.c
+./grub-core/kern/command.c
+./grub-core/kern/corecmd.c
+./grub-core/kern/device.c
+./grub-core/kern/disk.c
+./grub-core/kern/dl.c
+./grub-core/kern/efi/efi.c
+./grub-core/kern/efi/init.c
+./grub-core/kern/efi/mm.c
+./grub-core/kern/elf.c
+./grub-core/kern/emu/cache.c
+./grub-core/kern/emu/console.c
+./grub-core/kern/emu/full.c
+./grub-core/kern/emu/hostdisk.c
+./grub-core/kern/emu/hostfs.c
+./grub-core/kern/emu/lite.c
+./grub-core/kern/emu/main.c
+./grub-core/kern/emu/misc.c
+./grub-core/kern/emu/mm.c
+./grub-core/kern/emu/time.c
+./grub-core/kern/env.c
+./grub-core/kern/err.c
+./grub-core/kern/file.c
+./grub-core/kern/fs.c
+./grub-core/kern/generic/millisleep.c
+./grub-core/kern/generic/rtc_get_time_ms.c
+./grub-core/kern/i386/coreboot/init.c
+./grub-core/kern/i386/coreboot/mmap.c
+./grub-core/kern/i386/dl.c
+./grub-core/kern/i386/efi/init.c
+./grub-core/kern/i386/multiboot_mmap.c
+./grub-core/kern/i386/pc/init.c
+./grub-core/kern/i386/pc/mmap.c
+./grub-core/kern/i386/pit.c
+./grub-core/kern/i386/qemu/mmap.c
+./grub-core/kern/i386/tsc.c
+./grub-core/kern/ia64/dl.c
+./grub-core/kern/ia64/dl_helper.c
+./grub-core/kern/ia64/efi/init.c
+./grub-core/kern/ieee1275/cmain.c
+./grub-core/kern/ieee1275/ieee1275.c
+./grub-core/kern/ieee1275/init.c
+./grub-core/kern/ieee1275/mmap.c
+./grub-core/kern/ieee1275/openfw.c
+./grub-core/kern/list.c
+./grub-core/kern/main.c
+./grub-core/kern/mips/arc/init.c
+./grub-core/kern/mips/dl.c
+./grub-core/kern/mips/init.c
+./grub-core/kern/mips/loongson/init.c
+./grub-core/kern/mips/qemu_mips/init.c
+./grub-core/kern/misc.c
+./grub-core/kern/mm.c
+./grub-core/kern/parser.c
+./grub-core/kern/partition.c
+./grub-core/kern/powerpc/dl.c
+./grub-core/kern/rescue_parser.c
+./grub-core/kern/rescue_reader.c
+./grub-core/kern/sparc64/dl.c
+./grub-core/kern/sparc64/ieee1275/ieee1275.c
+./grub-core/kern/term.c
+./grub-core/kern/time.c
+./grub-core/kern/vga_init.c
+./grub-core/kern/x86_64/dl.c
+./grub-core/lib/arc/datetime.c
+./grub-core/lib/arg.c
+./grub-core/lib/cmdline.c
+./grub-core/lib/cmos_datetime.c
+./grub-core/lib/crc.c
+./grub-core/lib/crypto.c
+./grub-core/lib/efi/datetime.c
+./grub-core/lib/efi/halt.c
+./grub-core/lib/efi/relocator.c
+./grub-core/lib/emu/halt.c
+./grub-core/lib/envblk.c
+./grub-core/lib/hexdump.c
+./grub-core/lib/i386/halt.c
+./grub-core/lib/i386/pc/biosnum.c
+./grub-core/lib/i386/pc/vesa_modes_table.c
+./grub-core/lib/i386/relocator.c
+./grub-core/lib/ieee1275/cmos.c
+./grub-core/lib/ieee1275/datetime.c
+./grub-core/lib/ieee1275/halt.c
+./grub-core/lib/ieee1275/relocator.c
+./grub-core/lib/legacy_parse.c
+./grub-core/lib/libgcrypt/cipher/ac.c
+./grub-core/lib/libgcrypt/cipher/arcfour.c
+./grub-core/lib/libgcrypt/cipher/blowfish.c
+./grub-core/lib/libgcrypt/cipher/camellia.c
+./grub-core/lib/libgcrypt/cipher/camellia-glue.c
+./grub-core/lib/libgcrypt/cipher/cast5.c
+./grub-core/lib/libgcrypt/cipher/cipher.c
+./grub-core/lib/libgcrypt/cipher/crc.c
+./grub-core/lib/libgcrypt/cipher/des.c
+./grub-core/lib/libgcrypt/cipher/dsa.c
+./grub-core/lib/libgcrypt/cipher/ecc.c
+./grub-core/lib/libgcrypt/cipher/elgamal.c
+./grub-core/lib/libgcrypt/cipher/hash-common.c
+./grub-core/lib/libgcrypt/cipher/hmac-tests.c
+./grub-core/lib/libgcrypt/cipher/md4.c
+./grub-core/lib/libgcrypt/cipher/md5.c
+./grub-core/lib/libgcrypt/cipher/md.c
+./grub-core/lib/libgcrypt/cipher/primegen.c
+./grub-core/lib/libgcrypt/cipher/pubkey.c
+./grub-core/lib/libgcrypt/cipher/rfc2268.c
+./grub-core/lib/libgcrypt/cipher/rijndael.c
+./grub-core/lib/libgcrypt/cipher/rmd160.c
+./grub-core/lib/libgcrypt/cipher/rsa.c
+./grub-core/lib/libgcrypt/cipher/seed.c
+./grub-core/lib/libgcrypt/cipher/serpent.c
+./grub-core/lib/libgcrypt/cipher/sha1.c
+./grub-core/lib/libgcrypt/cipher/sha256.c
+./grub-core/lib/libgcrypt/cipher/sha512.c
+./grub-core/lib/libgcrypt/cipher/tiger.c
+./grub-core/lib/libgcrypt/cipher/twofish.c
+./grub-core/lib/libgcrypt/cipher/whirlpool.c
+./grub-core/lib/libgcrypt-grub/cipher/arcfour.c
+./grub-core/lib/libgcrypt-grub/cipher/blowfish.c
+./grub-core/lib/libgcrypt-grub/cipher/camellia.c
+./grub-core/lib/libgcrypt-grub/cipher/camellia-glue.c
+./grub-core/lib/libgcrypt-grub/cipher/cast5.c
+./grub-core/lib/libgcrypt-grub/cipher/crc.c
+./grub-core/lib/libgcrypt-grub/cipher/des.c
+./grub-core/lib/libgcrypt-grub/cipher/dsa.c
+./grub-core/lib/libgcrypt-grub/cipher/ecc.c
+./grub-core/lib/libgcrypt-grub/cipher/elgamal.c
+./grub-core/lib/libgcrypt-grub/cipher/init.c
+./grub-core/lib/libgcrypt-grub/cipher/md4.c
+./grub-core/lib/libgcrypt-grub/cipher/md5.c
+./grub-core/lib/libgcrypt-grub/cipher/primegen.c
+./grub-core/lib/libgcrypt-grub/cipher/rfc2268.c
+./grub-core/lib/libgcrypt-grub/cipher/rijndael.c
+./grub-core/lib/libgcrypt-grub/cipher/rmd160.c
+./grub-core/lib/libgcrypt-grub/cipher/rsa.c
+./grub-core/lib/libgcrypt-grub/cipher/seed.c
+./grub-core/lib/libgcrypt-grub/cipher/serpent.c
+./grub-core/lib/libgcrypt-grub/cipher/sha1.c
+./grub-core/lib/libgcrypt-grub/cipher/sha256.c
+./grub-core/lib/libgcrypt-grub/cipher/sha512.c
+./grub-core/lib/libgcrypt-grub/cipher/tiger.c
+./grub-core/lib/libgcrypt-grub/cipher/twofish.c
+./grub-core/lib/libgcrypt-grub/cipher/whirlpool.c
+./grub-core/lib/LzFind.c
+./grub-core/lib/LzmaDec.c
+./grub-core/lib/LzmaEnc.c
+./grub-core/lib/mips/relocator.c
+./grub-core/lib/pbkdf2.c
+./grub-core/lib/powerpc/relocator.c
+./grub-core/lib/reed_solomon.c
+./grub-core/lib/relocator.c
+./grub-core/lib/xzembed/xz_dec_bcj.c
+./grub-core/lib/xzembed/xz_dec_lzma2.c
+./grub-core/lib/xzembed/xz_dec_stream.c
+./grub-core/loader/aout.c
+./grub-core/loader/efi/appleloader.c
+./grub-core/loader/efi/chainloader.c
+./grub-core/loader/i386/bsd32.c
+./grub-core/loader/i386/bsd64.c
+./grub-core/loader/i386/bsd.c
+./grub-core/loader/i386/bsd_pagetable.c
+./grub-core/loader/i386/bsdXX.c
+./grub-core/loader/i386/coreboot/chainloader.c
+./grub-core/loader/i386/linux.c
+./grub-core/loader/i386/multiboot_mbi.c
+./grub-core/loader/i386/pc/chainloader.c
+./grub-core/loader/i386/pc/freedos.c
+./grub-core/loader/i386/pc/linux.c
+./grub-core/loader/i386/pc/ntldr.c
+./grub-core/loader/i386/xnu.c
+./grub-core/loader/ia64/efi/linux.c
+./grub-core/loader/macho32.c
+./grub-core/loader/macho64.c
+./grub-core/loader/macho.c
+./grub-core/loader/machoXX.c
+./grub-core/loader/mips/linux.c
+./grub-core/loader/multiboot.c
+./grub-core/loader/multiboot_elfxx.c
+./grub-core/loader/multiboot_mbi2.c
+./grub-core/loader/powerpc/ieee1275/linux.c
+./grub-core/loader/sparc64/ieee1275/linux.c
+./grub-core/loader/xnu.c
+./grub-core/loader/xnu_resume.c
+./grub-core/mmap/efi/mmap.c
+./grub-core/mmap/i386/mmap.c
+./grub-core/mmap/i386/pc/mmap.c
+./grub-core/mmap/i386/uppermem.c
+./grub-core/mmap/mips/uppermem.c
+./grub-core/mmap/mmap.c
+./grub-core/net/arp.c
+./grub-core/net/bootp.c
+./grub-core/net/drivers/efi/efinet.c
+./grub-core/net/drivers/emu/emunet.c
+./grub-core/net/drivers/i386/pc/pxe.c
+./grub-core/net/drivers/ieee1275/ofnet.c
+./grub-core/net/ethernet.c
+./grub-core/net/ip.c
+./grub-core/net/netbuff.c
+./grub-core/net/net.c
+./grub-core/net/tftp.c
+./grub-core/net/udp.c
+./grub-core/normal/auth.c
+./grub-core/normal/autofs.c
+./grub-core/normal/charset.c
+./grub-core/normal/cmdline.c
+./grub-core/normal/color.c
+./grub-core/normal/completion.c
+./grub-core/normal/context.c
+./grub-core/normal/crypto.c
+./grub-core/normal/datetime.c
+./grub-core/normal/dyncmd.c
+./grub-core/normal/main.c
+./grub-core/normal/menu.c
+./grub-core/normal/menu_entry.c
+./grub-core/normal/menu_text.c
+./grub-core/normal/misc.c
+./grub-core/normal/term.c
+./grub-core/partmap/acorn.c
+./grub-core/partmap/amiga.c
+./grub-core/partmap/apple.c
+./grub-core/partmap/bsdlabel.c
+./grub-core/partmap/dvh.c
+./grub-core/partmap/gpt.c
+./grub-core/partmap/msdos.c
+./grub-core/partmap/sun.c
+./grub-core/partmap/sunpc.c
+./grub-core/parttool/msdospart.c
+./grub-core/script/argv.c
+./grub-core/script/execute.c
+./grub-core/script/function.c
+./grub-core/script/lexer.c
+./grub-core/script/main.c
+./grub-core/script/script.c
+./grub-core/term/arc/console.c
+./grub-core/term/at_keyboard.c
+./grub-core/term/efi/console.c
+./grub-core/term/gfxterm.c
+./grub-core/term/i386/pc/console.c
+./grub-core/term/i386/pc/vga_text.c
+./grub-core/term/i386/vga_common.c
+./grub-core/term/ieee1275/ofconsole.c
+./grub-core/term/ns8250.c
+./grub-core/term/serial.c
+./grub-core/term/terminfo.c
+./grub-core/term/tparm.c
+./grub-core/term/usb_keyboard.c
+./grub-core/tests/example_functional_test.c
+./grub-core/tests/lib/functional_test.c
+./grub-core/tests/lib/test.c
+./grub-core/tests/test_blockarg.c
+./grub-core/unidata.c
+./grub-core/video/bitmap.c
+./grub-core/video/bitmap_scale.c
+./grub-core/video/bochs.c
+./grub-core/video/cirrus.c
+./grub-core/video/colors.c
+./grub-core/video/efi_gop.c
+./grub-core/video/efi_uga.c
+./grub-core/video/emu/sdl.c
+./grub-core/video/fb/fbblit.c
+./grub-core/video/fb/fbfill.c
+./grub-core/video/fb/fbutil.c
+./grub-core/video/fb/video_fb.c
+./grub-core/video/i386/pc/vbe.c
+./grub-core/video/i386/pc/vga.c
+./grub-core/video/ieee1275.c
+./grub-core/video/readers/jpeg.c
+./grub-core/video/readers/png.c
+./grub-core/video/readers/tga.c
+./grub-core/video/sis315_init.c
+./grub-core/video/sis315pro.c
+./grub-core/video/sm712.c
+./grub-core/video/sm712_init.c
+./grub-core/video/video.c
+./tests/example_unit_test.c
+./tests/lib/unit_test.c
+./util/bin2h.c
+./util/deviceiter.c
+./util/devicemap.c
+./util/getroot.c
+./util/grub-editenv.c
+./util/grub-fstest.c
+./util/grub-macho2img.c
+./util/grub-menulst2cfg.c
+./util/grub-mkdevicemap.c
+./util/grub-mkfont.c
+./util/grub-mkimage.c
+./util/grub-mkimagexx.c
+./util/grub-mklayout.c
+./util/grub-mkpasswd-pbkdf2.c
+./util/grub-mkrelpath.c
+./util/grub-pe2elf.c
+./util/grub-probe.c
+./util/grub-script-check.c
+./util/grub-setup.c
+./util/ieee1275/devicemap.c
+./util/ieee1275/grub-ofpathname.c
+./util/ieee1275/ofpath.c
+./util/lvm.c
+./util/misc.c
+./util/raid.c
+./util/resolve.c
rsync -Lrtvz translationproject.org::tp/latest/grub/ po
+ Then create a po/LINGUAS file listing all the language codes:
+
+ (cd po && ls *.po | cut -d. -f1 | xargs) >po/LINGUAS
+
GRUB's build system will automatically detect those and include them
in your install.
-#!/bin/sh -e
+#!/bin/sh
+set -e
true
-#! /bin/bash -e
+#! /bin/bash
+set -e
# Run GRUB script in a Qemu instance
# Copyright (C) 2010 Free Software Foundation, Inc.
-#! /bin/sh -e
+#! /bin/sh
+set -e
@builddir@/grub-script-check <<EOF
# comment 1
-#! /bin/sh -e
+#! /bin/sh
+set -e
@builddir@/grub-script-check << EOF
echo "\\\$"
-#! /bin/bash -e
+#! /bin/bash
+set -e
# Run GRUB script in a Qemu instance
# Copyright (C) 2010 Free Software Foundation, Inc.
-#! /bin/sh -e
+#! /bin/sh
+set -e
@builddir@/grub-script-check <<EOF
echo one;
-#! /bin/sh -e
-#
+#! /bin/sh
+set -e
+
# Copyright (C) 2010 Free Software Foundation, Inc.
#
# GRUB is free software: you can redistribute it and/or modify
# You should have received a copy of the GNU General Public License
# along with GRUB. If not, see <http://www.gnu.org/licenses/>.
-parted=/sbin/parted
+parted=parted
grubshell=@builddir@/grub-shell
create_disk_image () {
-#! /bin/sh -e
+#! /bin/sh
+set -e
# Compares GRUB script output with BASH output.
# Copyright (C) 2009,2010 Free Software Foundation, Inc.
PACKAGE_NAME=@PACKAGE_NAME@
PACKAGE_TARNAME=@PACKAGE_TARNAME@
PACKAGE_VERSION=@PACKAGE_VERSION@
-target_cpu=@target_cpu@
# Force build directory components
PATH=${builddir}:$PATH
-#! /bin/sh -e
+#! /bin/sh
+set -e
# Run GRUB script in a Qemu instance
# Copyright (C) 2009,2010 Free Software Foundation, Inc.
#
# grub-mkpasswd-pbkdf2
#
-_grub_mkpasswd-pbkdf2 () {
+_grub_mkpasswd_pbkdf2 () {
local cur
COMPREPLY=()
}
__grub_mkpasswd_pbkdf2_program=$( echo grub-mkpasswd-pbkdf2 | sed "@program_transform_name@" )
have ${__grub_mkpasswd_pbkdf2_program} && \
- complete -F _grub_mkpasswd-pbkdf2 -o filenames ${__grub_mkpasswd_pbkdf2_program}
+ complete -F _grub_mkpasswd_pbkdf2 -o filenames ${__grub_mkpasswd_pbkdf2_program}
unset __grub_mkpasswd_pbkdf2_program
#
# grub-script-check
#
-_grub_script-check () {
+_grub_script_check () {
local cur
COMPREPLY=()
}
__grub_script_check_program=$( echo grub-script-check | sed "@program_transform_name@" )
have ${__grub_script_check_program} && \
- complete -F _grub_script-check -o filenames ${__grub_script_check_program}
+ complete -F _grub_script_check -o filenames ${__grub_script_check_program}
# Local variables:
/* deviceiter.c - iterate over system devices */
/*
* GRUB -- GRand Unified Bootloader
- * Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2007,2008 Free Software Foundation, Inc.
+ * Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2007,2008,2011 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
#endif
}
+#ifdef __FreeBSD_kernel__
+static void
+get_ada_disk_name (char *name, int unit)
+{
+ sprintf (name, "/dev/ada%d", unit);
+}
+
+static void
+get_ataraid_disk_name (char *name, int unit)
+{
+ sprintf (name, "/dev/ar%d", unit);
+}
+
+static void
+get_mfi_disk_name (char *name, int unit)
+{
+ sprintf (name, "/dev/mfid%d", unit);
+}
+#endif
+
#ifdef __linux__
static void
get_virtio_disk_name (char *name, int unit)
}
}
+#ifdef __FreeBSD_kernel__
+ /* IDE disks using ATA Direct Access driver. */
+ if (get_kfreebsd_version () >= 800000)
+ for (i = 0; i < 96; i++)
+ {
+ char name[16];
+
+ get_ada_disk_name (name, i);
+ if (check_device_readable_unique (name))
+ {
+ if (hook (name, 0))
+ goto out;
+ }
+ }
+
+ /* ATARAID disks. */
+ for (i = 0; i < 8; i++)
+ {
+ char name[20];
+
+ get_ataraid_disk_name (name, i);
+ if (check_device_readable_unique (name))
+ {
+ if (hook (name, 0))
+ goto out;
+ }
+ }
+
+ /* LSI MegaRAID SAS. */
+ for (i = 0; i < 32; i++)
+ {
+ char name[20];
+
+ get_mfi_disk_name (name, i);
+ if (check_device_readable_unique (name))
+ {
+ if (hook (name, 0))
+ goto out;
+ }
+ }
+#endif
+
#ifdef __linux__
/* Virtio disks. */
for (i = 0; i < 26; i++)
--- /dev/null
+/* getroot.c - Get root device */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 1999,2000,2001,2002,2003,2006,2007,2008,2009,2010,2011 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config-util.h>
+#include <config.h>
+
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <dirent.h>
+#include <errno.h>
+#include <error.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <grub/util/misc.h>
+#include <grub/util/lvm.h>
+#include <grub/cryptodisk.h>
+
+#ifdef HAVE_DEVICE_MAPPER
+# include <libdevmapper.h>
+#endif
+
+#ifdef __GNU__
+#include <hurd.h>
+#include <hurd/lookup.h>
+#include <hurd/fs.h>
+#include <sys/mman.h>
+#endif
+
+#ifdef __linux__
+# include <sys/types.h>
+# include <sys/wait.h>
+#endif
+
+#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
+# include <sys/mount.h>
+#endif
+
+#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR)
+# include <grub/util/libzfs.h>
+# include <grub/util/libnvpair.h>
+#endif
+
+#include <grub/mm.h>
+#include <grub/misc.h>
+#include <grub/emu/misc.h>
+#include <grub/emu/hostdisk.h>
+#include <grub/emu/getroot.h>
+
+static void
+strip_extra_slashes (char *dir)
+{
+ char *p = dir;
+
+ while ((p = strchr (p, '/')) != 0)
+ {
+ if (p[1] == '/')
+ {
+ memmove (p, p + 1, strlen (p));
+ continue;
+ }
+ else if (p[1] == '\0')
+ {
+ if (p > dir)
+ p[0] = '\0';
+ break;
+ }
+
+ p++;
+ }
+}
+
+static char *
+xgetcwd (void)
+{
+ size_t size = 10;
+ char *path;
+
+ path = xmalloc (size);
+ while (! getcwd (path, size))
+ {
+ size <<= 1;
+ path = xrealloc (path, size);
+ }
+
+ return path;
+}
+
+#ifdef __linux__
+
+struct mountinfo_entry
+{
+ int id;
+ int major, minor;
+ char enc_root[PATH_MAX], enc_path[PATH_MAX];
+ char fstype[PATH_MAX], device[PATH_MAX];
+};
+
+/* Statting something on a btrfs filesystem always returns a virtual device
+ major/minor pair rather than the real underlying device, because btrfs
+ can span multiple underlying devices (and even if it's currently only
+ using a single device it can be dynamically extended onto another). We
+ can't deal with the multiple-device case yet, but in the meantime, we can
+ at least cope with the single-device case by scanning
+ /proc/self/mountinfo. */
+char *
+grub_find_root_device_from_mountinfo (const char *dir, char **relroot)
+{
+ FILE *fp;
+ char *buf = NULL;
+ size_t len = 0;
+ char *ret = NULL;
+ int entry_len = 0, entry_max = 4;
+ struct mountinfo_entry *entries;
+ struct mountinfo_entry parent_entry = { 0, 0, 0, "", "", "", "" };
+ int i;
+
+ if (! *dir)
+ dir = "/";
+ if (relroot)
+ *relroot = NULL;
+
+ fp = fopen ("/proc/self/mountinfo", "r");
+ if (! fp)
+ return NULL; /* fall through to other methods */
+
+ entries = xmalloc (entry_max * sizeof (*entries));
+
+ /* First, build a list of relevant visible mounts. */
+ while (getline (&buf, &len, fp) > 0)
+ {
+ struct mountinfo_entry entry;
+ int count;
+ size_t enc_path_len;
+ const char *sep;
+
+ if (sscanf (buf, "%d %d %u:%u %s %s%n",
+ &entry.id, &parent_entry.id, &entry.major, &entry.minor,
+ entry.enc_root, entry.enc_path, &count) < 6)
+ continue;
+
+ enc_path_len = strlen (entry.enc_path);
+ /* Check that enc_path is a prefix of dir. The prefix must either be
+ the entire string, or end with a slash, or be immediately followed
+ by a slash. */
+ if (strncmp (dir, entry.enc_path, enc_path_len) != 0 ||
+ (enc_path_len && dir[enc_path_len - 1] != '/' &&
+ dir[enc_path_len] && dir[enc_path_len] != '/'))
+ continue;
+
+ sep = strstr (buf + count, " - ");
+ if (!sep)
+ continue;
+
+ sep += sizeof (" - ") - 1;
+ if (sscanf (sep, "%s %s", entry.fstype, entry.device) != 2)
+ continue;
+
+ /* Using the mount IDs, find out where this fits in the list of
+ visible mount entries we've seen so far. There are three
+ interesting cases. Firstly, it may be inserted at the end: this is
+ the usual case of /foo/bar being mounted after /foo. Secondly, it
+ may be inserted at the start: for example, this can happen for
+ filesystems that are mounted before / and later moved under it.
+ Thirdly, it may occlude part or all of the existing filesystem
+ tree, in which case the end of the list needs to be pruned and this
+ new entry will be inserted at the end. */
+ if (entry_len >= entry_max)
+ {
+ entry_max <<= 1;
+ entries = xrealloc (entries, entry_max * sizeof (*entries));
+ }
+
+ if (!entry_len)
+ {
+ /* Initialise list. */
+ entry_len = 2;
+ entries[0] = parent_entry;
+ entries[1] = entry;
+ }
+ else
+ {
+ for (i = entry_len - 1; i >= 0; i--)
+ {
+ if (entries[i].id == parent_entry.id)
+ {
+ /* Insert at end, pruning anything previously above this. */
+ entry_len = i + 2;
+ entries[i + 1] = entry;
+ break;
+ }
+ else if (i == 0 && entries[i].id == entry.id)
+ {
+ /* Insert at start. */
+ entry_len++;
+ memmove (entries + 1, entries,
+ (entry_len - 1) * sizeof (*entries));
+ entries[0] = parent_entry;
+ entries[1] = entry;
+ break;
+ }
+ }
+ }
+ }
+
+ /* Now scan visible mounts for the ones we're interested in. */
+ for (i = entry_len - 1; i >= 0; i--)
+ {
+ if (!*entries[i].device)
+ continue;
+
+ ret = strdup (entries[i].device);
+ if (relroot)
+ *relroot = strdup (entries[i].enc_root);
+ break;
+ }
+
+ free (buf);
+ free (entries);
+ fclose (fp);
+ return ret;
+}
+
+#endif /* __linux__ */
+
+#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR)
+static char *
+find_root_device_from_libzfs (const char *dir)
+{
+ char *device = NULL;
+ char *poolname;
+ char *poolfs;
+
+ grub_find_zpool_from_dir (dir, &poolname, &poolfs);
+ if (! poolname)
+ return NULL;
+
+ {
+ zpool_handle_t *zpool;
+ libzfs_handle_t *libzfs;
+ nvlist_t *config, *vdev_tree;
+ nvlist_t **children, **path;
+ unsigned int nvlist_count;
+ unsigned int i;
+
+ libzfs = grub_get_libzfs_handle ();
+ if (! libzfs)
+ return NULL;
+
+ zpool = zpool_open (libzfs, poolname);
+ config = zpool_get_config (zpool, NULL);
+
+ if (nvlist_lookup_nvlist (config, "vdev_tree", &vdev_tree) != 0)
+ error (1, errno, "nvlist_lookup_nvlist (\"vdev_tree\")");
+
+ if (nvlist_lookup_nvlist_array (vdev_tree, "children", &children, &nvlist_count) != 0)
+ error (1, errno, "nvlist_lookup_nvlist_array (\"children\")");
+ assert (nvlist_count > 0);
+
+ while (nvlist_lookup_nvlist_array (children[0], "children",
+ &children, &nvlist_count) == 0)
+ assert (nvlist_count > 0);
+
+ for (i = 0; i < nvlist_count; i++)
+ {
+ if (nvlist_lookup_string (children[i], "path", &device) != 0)
+ error (1, errno, "nvlist_lookup_string (\"path\")");
+
+ struct stat st;
+ if (stat (device, &st) == 0)
+ {
+ device = xstrdup (device);
+ break;
+ }
+
+ device = NULL;
+ }
+
+ zpool_close (zpool);
+ }
+
+ free (poolname);
+ if (poolfs)
+ free (poolfs);
+
+ return device;
+}
+#endif
+
+#ifdef __MINGW32__
+
+char *
+grub_find_device (const char *dir __attribute__ ((unused)),
+ dev_t dev __attribute__ ((unused)))
+{
+ return 0;
+}
+
+#elif ! defined(__CYGWIN__)
+
+char *
+grub_find_device (const char *dir, dev_t dev)
+{
+ DIR *dp;
+ char *saved_cwd;
+ struct dirent *ent;
+
+ if (! dir)
+ {
+#ifdef __CYGWIN__
+ return NULL;
+#else
+ dir = "/dev";
+#endif
+ }
+
+ dp = opendir (dir);
+ if (! dp)
+ return 0;
+
+ saved_cwd = xgetcwd ();
+
+ grub_util_info ("changing current directory to %s", dir);
+ if (chdir (dir) < 0)
+ {
+ free (saved_cwd);
+ closedir (dp);
+ return 0;
+ }
+
+ while ((ent = readdir (dp)) != 0)
+ {
+ struct stat st;
+
+ /* Avoid:
+ - dotfiles (like "/dev/.tmp.md0") since they could be duplicates.
+ - dotdirs (like "/dev/.static") since they could contain duplicates. */
+ if (ent->d_name[0] == '.')
+ continue;
+
+ if (lstat (ent->d_name, &st) < 0)
+ /* Ignore any error. */
+ continue;
+
+ if (S_ISLNK (st.st_mode)) {
+#ifdef __linux__
+ if (strcmp (dir, "mapper") == 0 || strcmp (dir, "/dev/mapper") == 0) {
+ /* Follow symbolic links under /dev/mapper/; the canonical name
+ may be something like /dev/dm-0, but the names under
+ /dev/mapper/ are more human-readable and so we prefer them if
+ we can get them. */
+ if (stat (ent->d_name, &st) < 0)
+ continue;
+ } else
+#endif /* __linux__ */
+ /* Don't follow other symbolic links. */
+ continue;
+ }
+
+ if (S_ISDIR (st.st_mode))
+ {
+ /* Find it recursively. */
+ char *res;
+
+ res = grub_find_device (ent->d_name, dev);
+
+ if (res)
+ {
+ if (chdir (saved_cwd) < 0)
+ grub_util_error ("cannot restore the original directory");
+
+ free (saved_cwd);
+ closedir (dp);
+ return res;
+ }
+ }
+
+#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__APPLE__)
+ if (S_ISCHR (st.st_mode) && st.st_rdev == dev)
+#else
+ if (S_ISBLK (st.st_mode) && st.st_rdev == dev)
+#endif
+ {
+#ifdef __linux__
+ /* Skip device names like /dev/dm-0, which are short-hand aliases
+ to more descriptive device names, e.g. those under /dev/mapper */
+ if (ent->d_name[0] == 'd' &&
+ ent->d_name[1] == 'm' &&
+ ent->d_name[2] == '-' &&
+ ent->d_name[3] >= '0' &&
+ ent->d_name[3] <= '9')
+ continue;
+#endif
+
+ /* Found! */
+ char *res;
+ char *cwd;
+#if defined(__NetBSD__)
+ /* Convert this block device to its character (raw) device. */
+ const char *template = "%s/r%s";
+#else
+ /* Keep the device name as it is. */
+ const char *template = "%s/%s";
+#endif
+
+ cwd = xgetcwd ();
+ res = xmalloc (strlen (cwd) + strlen (ent->d_name) + 3);
+ sprintf (res, template, cwd, ent->d_name);
+ strip_extra_slashes (res);
+ free (cwd);
+
+ /* /dev/root is not a real block device keep looking, takes care
+ of situation where root filesystem is on the same partition as
+ grub files */
+
+ if (strcmp(res, "/dev/root") == 0)
+ continue;
+
+ if (chdir (saved_cwd) < 0)
+ grub_util_error ("cannot restore the original directory");
+
+ free (saved_cwd);
+ closedir (dp);
+ return res;
+ }
+ }
+
+ if (chdir (saved_cwd) < 0)
+ grub_util_error ("cannot restore the original directory");
+
+ free (saved_cwd);
+ closedir (dp);
+ return 0;
+}
+
+#else /* __CYGWIN__ */
+
+/* Read drive/partition serial number from mbr/boot sector,
+ return 0 on read error, ~0 on unknown serial. */
+static unsigned
+get_bootsec_serial (const char *os_dev, int mbr)
+{
+ /* Read boot sector. */
+ int fd = open (os_dev, O_RDONLY);
+ if (fd < 0)
+ return 0;
+ unsigned char buf[0x200];
+ int n = read (fd, buf, sizeof (buf));
+ close (fd);
+ if (n != sizeof(buf))
+ return 0;
+
+ /* Check signature. */
+ if (!(buf[0x1fe] == 0x55 && buf[0x1ff] == 0xaa))
+ return ~0;
+
+ /* Serial number offset depends on boot sector type. */
+ if (mbr)
+ n = 0x1b8;
+ else if (memcmp (buf + 0x03, "NTFS", 4) == 0)
+ n = 0x048;
+ else if (memcmp (buf + 0x52, "FAT32", 5) == 0)
+ n = 0x043;
+ else if (memcmp (buf + 0x36, "FAT", 3) == 0)
+ n = 0x027;
+ else
+ return ~0;
+
+ unsigned serial = *(unsigned *)(buf + n);
+ if (serial == 0)
+ return ~0;
+ return serial;
+}
+
+char *
+grub_find_device (const char *path, dev_t dev)
+{
+ /* No root device for /cygdrive. */
+ if (dev == (DEV_CYGDRIVE_MAJOR << 16))
+ return 0;
+
+ /* Convert to full POSIX and Win32 path. */
+ char fullpath[PATH_MAX], winpath[PATH_MAX];
+ cygwin_conv_to_full_posix_path (path, fullpath);
+ cygwin_conv_to_full_win32_path (fullpath, winpath);
+
+ /* If identical, this is no real filesystem path. */
+ if (strcmp (fullpath, winpath) == 0)
+ return 0;
+
+ /* Check for floppy drive letter. */
+ if (winpath[0] && winpath[1] == ':' && strchr ("AaBb", winpath[0]))
+ return xstrdup (strchr ("Aa", winpath[0]) ? "/dev/fd0" : "/dev/fd1");
+
+ /* Cygwin returns the partition serial number in stat.st_dev.
+ This is never identical to the device number of the emulated
+ /dev/sdXN device, so above grub_find_device () does not work.
+ Search the partition with the same serial in boot sector instead. */
+ char devpath[sizeof ("/dev/sda15") + 13]; /* Size + Paranoia. */
+ int d;
+ for (d = 'a'; d <= 'z'; d++)
+ {
+ sprintf (devpath, "/dev/sd%c", d);
+ if (get_bootsec_serial (devpath, 1) == 0)
+ continue;
+ int p;
+ for (p = 1; p <= 15; p++)
+ {
+ sprintf (devpath, "/dev/sd%c%d", d, p);
+ unsigned ser = get_bootsec_serial (devpath, 0);
+ if (ser == 0)
+ break;
+ if (ser != (unsigned)~0 && dev == (dev_t)ser)
+ return xstrdup (devpath);
+ }
+ }
+ return 0;
+}
+
+#endif /* __CYGWIN__ */
+
+char *
+grub_guess_root_device (const char *dir)
+{
+ char *os_dev = NULL;
+#ifdef __GNU__
+ file_t file;
+ mach_port_t *ports;
+ int *ints;
+ loff_t *offsets;
+ char *data;
+ error_t err;
+ mach_msg_type_number_t num_ports = 0, num_ints = 0, num_offsets = 0, data_len = 0;
+ size_t name_len;
+
+ file = file_name_lookup (dir, 0, 0);
+ if (file == MACH_PORT_NULL)
+ return 0;
+
+ err = file_get_storage_info (file,
+ &ports, &num_ports,
+ &ints, &num_ints,
+ &offsets, &num_offsets,
+ &data, &data_len);
+
+ if (num_ints < 1)
+ grub_util_error ("Storage info for `%s' does not include type", dir);
+ if (ints[0] != STORAGE_DEVICE)
+ grub_util_error ("Filesystem of `%s' is not stored on local disk", dir);
+
+ if (num_ints < 5)
+ grub_util_error ("Storage info for `%s' does not include name", dir);
+ name_len = ints[4];
+ if (name_len < data_len)
+ grub_util_error ("Bogus name length for storage info for `%s'", dir);
+ if (data[name_len - 1] != '\0')
+ grub_util_error ("Storage name for `%s' not NUL-terminated", dir);
+
+ os_dev = xmalloc (strlen ("/dev/") + data_len);
+ memcpy (os_dev, "/dev/", strlen ("/dev/"));
+ memcpy (os_dev + strlen ("/dev/"), data, data_len);
+
+ if (ports && num_ports > 0)
+ {
+ mach_msg_type_number_t i;
+ for (i = 0; i < num_ports; i++)
+ {
+ mach_port_t port = ports[i];
+ if (port != MACH_PORT_NULL)
+ mach_port_deallocate (mach_task_self(), port);
+ }
+ munmap ((caddr_t) ports, num_ports * sizeof (*ports));
+ }
+
+ if (ints && num_ints > 0)
+ munmap ((caddr_t) ints, num_ints * sizeof (*ints));
+ if (offsets && num_offsets > 0)
+ munmap ((caddr_t) offsets, num_offsets * sizeof (*offsets));
+ if (data && data_len > 0)
+ munmap (data, data_len);
+ mach_port_deallocate (mach_task_self (), file);
+#else /* !__GNU__ */
+ struct stat st;
+ dev_t dev;
+
+#ifdef __linux__
+ if (!os_dev)
+ os_dev = grub_find_root_device_from_mountinfo (dir, NULL);
+#endif /* __linux__ */
+
+#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR)
+ if (!os_dev)
+ os_dev = find_root_device_from_libzfs (dir);
+#endif
+
+ if (os_dev)
+ {
+ char *tmp = os_dev;
+ os_dev = canonicalize_file_name (os_dev);
+ free (tmp);
+ }
+
+ if (os_dev)
+ {
+ int dm = (strncmp (os_dev, "/dev/dm-", sizeof ("/dev/dm-") - 1) == 0);
+ int root = (strcmp (os_dev, "/dev/root") == 0);
+ if (!dm && !root)
+ return os_dev;
+ if (stat (os_dev, &st) >= 0)
+ {
+ free (os_dev);
+ dev = st.st_rdev;
+ return grub_find_device (dm ? "/dev/mapper" : "/dev", dev);
+ }
+ free (os_dev);
+ }
+
+ if (stat (dir, &st) < 0)
+ grub_util_error ("cannot stat `%s'", dir);
+
+ dev = st.st_dev;
+
+#ifdef __CYGWIN__
+ /* Cygwin specific function. */
+ os_dev = grub_find_device (dir, dev);
+
+#else
+
+ /* This might be truly slow, but is there any better way? */
+ os_dev = grub_find_device ("/dev", dev);
+#endif
+#endif /* !__GNU__ */
+
+ return os_dev;
+}
+
+#ifdef HAVE_DEVICE_MAPPER
+
+static int
+grub_util_open_dm (const char *os_dev, struct dm_tree **tree,
+ struct dm_tree_node **node)
+{
+ uint32_t maj, min;
+ struct stat st;
+
+ *node = NULL;
+ *tree = NULL;
+
+ if ((strncmp ("/dev/mapper/", os_dev, 12) != 0))
+ return 0;
+
+ if (stat (os_dev, &st) < 0)
+ return 0;
+
+ *tree = dm_tree_create ();
+ if (! *tree)
+ {
+ grub_printf ("Failed to create tree\n");
+ grub_dprintf ("hostdisk", "dm_tree_create failed\n");
+ return 0;
+ }
+
+ maj = major (st.st_rdev);
+ min = minor (st.st_rdev);
+
+ if (! dm_tree_add_dev (*tree, maj, min))
+ {
+ grub_dprintf ("hostdisk", "dm_tree_add_dev failed\n");
+ dm_tree_free (*tree);
+ *tree = NULL;
+ return 0;
+ }
+
+ *node = dm_tree_find_node (*tree, maj, min);
+ if (! *node)
+ {
+ grub_dprintf ("hostdisk", "dm_tree_find_node failed\n");
+ dm_tree_free (*tree);
+ *tree = NULL;
+ return 0;
+ }
+ return 1;
+}
+
+#endif
+
+static char *
+get_dm_uuid (const char *os_dev)
+{
+ if ((strncmp ("/dev/mapper/", os_dev, 12) != 0))
+ return NULL;
+
+#ifdef HAVE_DEVICE_MAPPER
+ {
+ struct dm_tree *tree;
+ struct dm_tree_node *node;
+ const char *node_uuid;
+ char *ret;
+
+ if (!grub_util_open_dm (os_dev, &tree, &node))
+ return NULL;
+
+ node_uuid = dm_tree_node_get_uuid (node);
+ if (! node_uuid)
+ {
+ grub_dprintf ("hostdisk", "%s has no DM uuid\n", os_dev);
+ dm_tree_free (tree);
+ return NULL;
+ }
+
+ ret = grub_strdup (node_uuid);
+
+ dm_tree_free (tree);
+
+ return ret;
+ }
+#endif
+
+ return NULL;
+}
+
+static enum grub_dev_abstraction_types
+grub_util_get_dm_abstraction (const char *os_dev)
+{
+#ifdef HAVE_DEVICE_MAPPER
+ char *uuid;
+
+ uuid = get_dm_uuid (os_dev);
+
+ if (uuid == NULL)
+ return GRUB_DEV_ABSTRACTION_NONE;
+
+ if (strncmp (uuid, "LVM-", 4) == 0)
+ {
+ grub_free (uuid);
+ return GRUB_DEV_ABSTRACTION_LVM;
+ }
+ if (strncmp (uuid, "CRYPT-LUKS1-", 4) == 0)
+ {
+ grub_free (uuid);
+ return GRUB_DEV_ABSTRACTION_LUKS;
+ }
+
+ grub_free (uuid);
+ return GRUB_DEV_ABSTRACTION_NONE;
+#else
+ if ((strncmp ("/dev/mapper/", os_dev, 12) != 0))
+ return GRUB_DEV_ABSTRACTION_NONE;
+ return GRUB_DEV_ABSTRACTION_LVM;
+#endif
+}
+
+#if defined (__FreeBSD__) || defined(__FreeBSD_kernel__)
+#include <libgeom.h>
+
+/* FIXME: geom actually gives us the whole container hierarchy.
+ It can be used more efficiently than this. */
+void
+grub_util_follow_gpart_up (const char *name, grub_disk_addr_t *off_out, char **name_out)
+{
+ struct gmesh mesh;
+ struct gclass *class;
+ int error;
+ struct ggeom *geom;
+
+ grub_util_info ("following geom '%s'", name);
+
+ error = geom_gettree (&mesh);
+ if (error != 0)
+ grub_util_error ("couldn't open geom");
+
+ LIST_FOREACH (class, &mesh.lg_class, lg_class)
+ if (strcasecmp (class->lg_name, "part") == 0)
+ break;
+ if (!class)
+ grub_util_error ("couldn't open geom part");
+
+ LIST_FOREACH (geom, &class->lg_geom, lg_geom)
+ {
+ struct gprovider *provider;
+ LIST_FOREACH (provider, &geom->lg_provider, lg_provider)
+ if (strcmp (provider->lg_name, name) == 0)
+ {
+ char *name_tmp = xstrdup (geom->lg_name);
+ grub_disk_addr_t off = 0;
+ struct gconfig *config;
+ grub_util_info ("geom '%s' has parent '%s'", name, geom->lg_name);
+
+ grub_util_follow_gpart_up (name_tmp, &off, name_out);
+ free (name_tmp);
+ LIST_FOREACH (config, &provider->lg_config, lg_config)
+ if (strcasecmp (config->lg_name, "start") == 0)
+ off += strtoull (config->lg_val, 0, 10);
+ if (off_out)
+ *off_out = off;
+ return;
+ }
+ }
+ grub_util_info ("geom '%s' has no parent", name);
+ if (name_out)
+ *name_out = xstrdup (name);
+ if (off_out)
+ *off_out = 0;
+}
+
+static const char *
+grub_util_get_geom_abstraction (const char *dev)
+{
+ char *whole;
+ struct gmesh mesh;
+ struct gclass *class;
+ const char *name;
+ int error;
+
+ if (strncmp (dev, "/dev/", sizeof ("/dev/") - 1) != 0)
+ return 0;
+ name = dev + sizeof ("/dev/") - 1;
+ grub_util_follow_gpart_up (name, NULL, &whole);
+
+ grub_util_info ("following geom '%s'", name);
+
+ error = geom_gettree (&mesh);
+ if (error != 0)
+ grub_util_error ("couldn't open geom");
+
+ LIST_FOREACH (class, &mesh.lg_class, lg_class)
+ {
+ struct ggeom *geom;
+ LIST_FOREACH (geom, &class->lg_geom, lg_geom)
+ {
+ struct gprovider *provider;
+ LIST_FOREACH (provider, &geom->lg_provider, lg_provider)
+ if (strcmp (provider->lg_name, name) == 0)
+ return class->lg_name;
+ }
+ }
+ return NULL;
+}
+#endif
+
+int
+grub_util_get_dev_abstraction (const char *os_dev __attribute__((unused)))
+{
+#if defined(__linux__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
+ /* User explicitly claims that this drive is visible by BIOS. */
+ if (grub_util_biosdisk_is_present (os_dev))
+ return GRUB_DEV_ABSTRACTION_NONE;
+#endif
+
+#ifdef __linux__
+ enum grub_dev_abstraction_types ret;
+
+ /* Check for LVM and LUKS. */
+ ret = grub_util_get_dm_abstraction (os_dev);
+
+ if (ret != GRUB_DEV_ABSTRACTION_NONE)
+ return ret;
+
+ /* Check for RAID. */
+ if (!strncmp (os_dev, "/dev/md", 7) && ! grub_util_device_is_mapped (os_dev))
+ return GRUB_DEV_ABSTRACTION_RAID;
+#endif
+
+#if defined (__FreeBSD__) || defined(__FreeBSD_kernel__)
+ const char *abs;
+ abs = grub_util_get_geom_abstraction (os_dev);
+ grub_util_info ("abstraction of %s is %s", os_dev, abs);
+ if (abs && grub_strcasecmp (abs, "eli") == 0)
+ return GRUB_DEV_ABSTRACTION_GELI;
+
+ /* Check for LVM. */
+ if (!strncmp (os_dev, LVM_DEV_MAPPER_STRING, sizeof(LVM_DEV_MAPPER_STRING)-1))
+ return GRUB_DEV_ABSTRACTION_LVM;
+#endif
+
+ /* No abstraction found. */
+ return GRUB_DEV_ABSTRACTION_NONE;
+}
+
+#ifdef __linux__
+static char *
+get_mdadm_uuid (const char *os_dev)
+{
+ int mdadm_pipe[2];
+ pid_t mdadm_pid;
+ char *name = NULL;
+
+ if (pipe (mdadm_pipe) < 0)
+ {
+ grub_util_warn ("Unable to create pipe for mdadm: %s", strerror (errno));
+ return NULL;
+ }
+
+ mdadm_pid = fork ();
+ if (mdadm_pid < 0)
+ grub_util_warn ("Unable to fork mdadm: %s", strerror (errno));
+ else if (mdadm_pid == 0)
+ {
+ /* Child. */
+ char *argv[5];
+
+ close (mdadm_pipe[0]);
+ dup2 (mdadm_pipe[1], STDOUT_FILENO);
+ close (mdadm_pipe[1]);
+
+ /* execvp has inconvenient types, hence the casts. None of these
+ strings will actually be modified. */
+ argv[0] = (char *) "mdadm";
+ argv[1] = (char *) "--detail";
+ argv[2] = (char *) "--export";
+ argv[3] = (char *) os_dev;
+ argv[4] = NULL;
+ execvp ("mdadm", argv);
+ exit (127);
+ }
+ else
+ {
+ /* Parent. Read mdadm's output. */
+ FILE *mdadm;
+ char *buf = NULL;
+ size_t len = 0;
+
+ close (mdadm_pipe[1]);
+ mdadm = fdopen (mdadm_pipe[0], "r");
+ if (! mdadm)
+ {
+ grub_util_warn ("Unable to open stream from mdadm: %s",
+ strerror (errno));
+ goto out;
+ }
+
+ while (getline (&buf, &len, mdadm) > 0)
+ {
+ if (strncmp (buf, "MD_UUID=", sizeof ("MD_UUID=") - 1) == 0)
+ {
+ char *name_start, *ptri, *ptro;
+ size_t name_len;
+
+ free (name);
+ name_start = buf + sizeof ("MD_UUID=") - 1;
+ ptro = name = xmalloc (strlen (name_start) + 1);
+ for (ptri = name_start; *ptri && *ptri != '\n' && *ptri != '\r';
+ ptri++)
+ if ((*ptri >= '0' && *ptri <= '9')
+ || (*ptri >= 'a' && *ptri <= 'f')
+ || (*ptri >= 'A' && *ptri <= 'F'))
+ *ptro++ = *ptri;
+ *ptro = 0;
+ }
+ }
+
+out:
+ close (mdadm_pipe[0]);
+ waitpid (mdadm_pid, NULL, 0);
+ }
+
+ return name;
+}
+#endif /* __linux__ */
+
+void
+grub_util_pull_device (const char *os_dev)
+{
+ int ab;
+ ab = grub_util_get_dev_abstraction (os_dev);
+ switch (ab)
+ {
+ case GRUB_DEV_ABSTRACTION_GELI:
+#if defined (__FreeBSD__) || defined(__FreeBSD_kernel__)
+ {
+ char *whole;
+ struct gmesh mesh;
+ struct gclass *class;
+ const char *name;
+ int error;
+ char *lastsubdev = NULL;
+
+ if (strncmp (os_dev, "/dev/", sizeof ("/dev/") - 1) != 0)
+ return;
+ name = os_dev + sizeof ("/dev/") - 1;
+ grub_util_follow_gpart_up (name, NULL, &whole);
+
+ grub_util_info ("following geom '%s'", name);
+
+ error = geom_gettree (&mesh);
+ if (error != 0)
+ grub_util_error ("couldn't open geom");
+
+ LIST_FOREACH (class, &mesh.lg_class, lg_class)
+ {
+ struct ggeom *geom;
+ LIST_FOREACH (geom, &class->lg_geom, lg_geom)
+ {
+ struct gprovider *provider;
+ LIST_FOREACH (provider, &geom->lg_provider, lg_provider)
+ if (strcmp (provider->lg_name, name) == 0)
+ {
+ struct gconsumer *consumer;
+ char *fname;
+ char *uuid;
+
+ LIST_FOREACH (consumer, &geom->lg_consumer, lg_consumer)
+ break;
+ if (!consumer)
+ grub_util_error ("couldn't find geli consumer");
+ fname = xasprintf ("/dev/%s", consumer->lg_provider->lg_name);
+ grub_util_info ("consumer %s", consumer->lg_provider->lg_name);
+ lastsubdev = consumer->lg_provider->lg_name;
+ grub_util_pull_device (fname);
+ free (fname);
+ }
+ }
+ }
+ if (ab == GRUB_DEV_ABSTRACTION_GELI && lastsubdev)
+ {
+ char *fname = xasprintf ("/dev/%s", lastsubdev);
+ char *grdev = grub_util_get_grub_dev (fname);
+ free (fname);
+
+ if (grdev)
+ {
+ grub_err_t err;
+ err = grub_cryptodisk_cheat_mount (grdev, os_dev);
+ if (err)
+ grub_util_error ("Can't mount crypto: %s", grub_errmsg);
+ }
+
+ grub_free (grdev);
+ }
+ }
+#endif
+ break;
+
+ case GRUB_DEV_ABSTRACTION_LVM:
+ case GRUB_DEV_ABSTRACTION_LUKS:
+#ifdef HAVE_DEVICE_MAPPER
+ {
+ struct dm_tree *tree;
+ struct dm_tree_node *node;
+ struct dm_tree_node *child;
+ void *handle = NULL;
+ char *lastsubdev = NULL;
+
+ if (!grub_util_open_dm (os_dev, &tree, &node))
+ return;
+
+ while ((child = dm_tree_next_child (&handle, node, 0)))
+ {
+ const struct dm_info *dm = dm_tree_node_get_info (child);
+ char *subdev;
+ if (!dm)
+ continue;
+ subdev = grub_find_device ("/dev", makedev (dm->major, dm->minor));
+ if (subdev)
+ {
+ lastsubdev = subdev;
+ grub_util_pull_device (subdev);
+ }
+ }
+ if (ab == GRUB_DEV_ABSTRACTION_LUKS && lastsubdev)
+ {
+ char *grdev = grub_util_get_grub_dev (lastsubdev);
+ dm_tree_free (tree);
+ if (grdev)
+ {
+ grub_err_t err;
+ err = grub_cryptodisk_cheat_mount (grdev, os_dev);
+ if (err)
+ grub_util_error ("Can't mount crypto: %s", grub_errmsg);
+ }
+ grub_free (grdev);
+ }
+ else
+ dm_tree_free (tree);
+ }
+#endif
+ return;
+ case GRUB_DEV_ABSTRACTION_RAID:
+#ifdef __linux__
+ {
+ char **devicelist = grub_util_raid_getmembers (os_dev, 0);
+ int i;
+ for (i = 0; devicelist[i];i++)
+ grub_util_pull_device (devicelist[i]);
+ free (devicelist);
+ }
+#endif
+ return;
+
+ default: /* GRUB_DEV_ABSTRACTION_NONE */
+ grub_util_biosdisk_get_grub_dev (os_dev);
+ return;
+ }
+}
+
+char *
+grub_util_get_grub_dev (const char *os_dev)
+{
+ char *grub_dev = NULL;
+
+ grub_util_pull_device (os_dev);
+
+ switch (grub_util_get_dev_abstraction (os_dev))
+ {
+#if defined(__linux__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
+ case GRUB_DEV_ABSTRACTION_LVM:
+
+ {
+ unsigned short i, len;
+ grub_size_t offset = sizeof (LVM_DEV_MAPPER_STRING) - 1;
+
+ len = strlen (os_dev) - offset + 1;
+ grub_dev = xmalloc (len + sizeof ("lvm/"));
+
+ grub_memcpy (grub_dev, "lvm/", sizeof ("lvm/") - 1);
+ grub_memcpy (grub_dev + sizeof ("lvm/") - 1, os_dev + offset, len);
+ }
+
+ break;
+#endif
+
+#ifdef __linux__
+ case GRUB_DEV_ABSTRACTION_LUKS:
+ {
+ char *uuid, *dash;
+ uuid = get_dm_uuid (os_dev);
+ if (!uuid)
+ break;
+ dash = grub_strchr (uuid + sizeof ("CRYPT-LUKS1-") - 1, '-');
+ if (dash)
+ *dash = 0;
+ grub_dev = grub_xasprintf ("cryptouuid/%s",
+ uuid + sizeof ("CRYPT-LUKS1-") - 1);
+ grub_free (uuid);
+ }
+ break;
+#endif
+
+#if defined (__FreeBSD__) || defined(__FreeBSD_kernel__)
+ case GRUB_DEV_ABSTRACTION_GELI:
+ {
+ char *whole;
+ struct gmesh mesh;
+ struct gclass *class;
+ const char *name;
+ int error;
+
+ if (strncmp (os_dev, "/dev/", sizeof ("/dev/") - 1) != 0)
+ return 0;
+ name = os_dev + sizeof ("/dev/") - 1;
+ grub_util_follow_gpart_up (name, NULL, &whole);
+
+ grub_util_info ("following geom '%s'", name);
+
+ error = geom_gettree (&mesh);
+ if (error != 0)
+ grub_util_error ("couldn't open geom");
+
+ LIST_FOREACH (class, &mesh.lg_class, lg_class)
+ {
+ struct ggeom *geom;
+ LIST_FOREACH (geom, &class->lg_geom, lg_geom)
+ {
+ struct gprovider *provider;
+ LIST_FOREACH (provider, &geom->lg_provider, lg_provider)
+ if (strcmp (provider->lg_name, name) == 0)
+ {
+ struct gconsumer *consumer;
+ char *fname;
+ char *uuid;
+
+ LIST_FOREACH (consumer, &geom->lg_consumer, lg_consumer)
+ break;
+ if (!consumer)
+ grub_util_error ("couldn't find geli consumer");
+ fname = xasprintf ("/dev/%s", consumer->lg_provider->lg_name);
+ uuid = grub_util_get_geli_uuid (fname);
+ if (!uuid)
+ grub_util_error ("couldn't retrieve geli UUID");
+ grub_dev = xasprintf ("cryptouuid/%s", uuid);
+ free (fname);
+ free (uuid);
+ }
+ }
+ }
+ }
+ break;
+#endif
+
+#ifdef __linux__
+ case GRUB_DEV_ABSTRACTION_RAID:
+
+ if (os_dev[7] == '_' && os_dev[8] == 'd')
+ {
+ /* This a partitionable RAID device of the form /dev/md_dNNpMM. */
+
+ char *p, *q;
+
+ p = strdup (os_dev + sizeof ("/dev/md_d") - 1);
+
+ q = strchr (p, 'p');
+ if (q)
+ *q = ',';
+
+ grub_dev = xasprintf ("md%s", p);
+ free (p);
+ }
+ else if (os_dev[7] == '/' && os_dev[8] == 'd')
+ {
+ /* This a partitionable RAID device of the form /dev/md/dNNpMM. */
+
+ char *p, *q;
+
+ p = strdup (os_dev + sizeof ("/dev/md/d") - 1);
+
+ q = strchr (p, 'p');
+ if (q)
+ *q = ',';
+
+ grub_dev = xasprintf ("md%s", p);
+ free (p);
+ }
+ else if (os_dev[7] >= '0' && os_dev[7] <= '9')
+ {
+ char *p , *q;
+
+ p = strdup (os_dev + sizeof ("/dev/md") - 1);
+
+ q = strchr (p, 'p');
+ if (q)
+ *q = ',';
+
+ grub_dev = xasprintf ("md%s", p);
+ free (p);
+ }
+ else if (os_dev[7] == '/' && os_dev[8] >= '0' && os_dev[8] <= '9')
+ {
+ char *p , *q;
+
+ p = strdup (os_dev + sizeof ("/dev/md/") - 1);
+
+ q = strchr (p, 'p');
+ if (q)
+ *q = ',';
+
+ grub_dev = xasprintf ("md%s", p);
+ free (p);
+ }
+ else if (os_dev[7] == '/')
+ {
+ /* mdraid 1.x with a free name. */
+ char *p , *q;
+
+ p = strdup (os_dev + sizeof ("/dev/md/") - 1);
+
+ q = strchr (p, 'p');
+ if (q)
+ *q = ',';
+
+ grub_dev = xasprintf ("md/%s", p);
+ free (p);
+ }
+ else
+ grub_util_error ("unknown kind of RAID device `%s'", os_dev);
+
+ {
+ char *mdadm_name = get_mdadm_uuid (os_dev);
+ struct stat st;
+
+ if (mdadm_name)
+ {
+ const char *q;
+
+ for (q = os_dev + strlen (os_dev) - 1; q >= os_dev
+ && grub_isdigit (*q); q--);
+
+ if (q >= os_dev && *q == 'p')
+ {
+ free (grub_dev);
+ grub_dev = xasprintf ("mduuid/%s,%s", mdadm_name, q + 1);
+ goto done;
+ }
+ free (grub_dev);
+ grub_dev = xasprintf ("mduuid/%s", mdadm_name);
+
+ done:
+ free (mdadm_name);
+ }
+ }
+ break;
+#endif /* __linux__ */
+
+ default: /* GRUB_DEV_ABSTRACTION_NONE */
+ grub_dev = grub_util_biosdisk_get_grub_dev (os_dev);
+ }
+
+ return grub_dev;
+}
+
+const char *
+grub_util_check_block_device (const char *blk_dev)
+{
+ struct stat st;
+
+ if (stat (blk_dev, &st) < 0)
+ grub_util_error ("cannot stat `%s'", blk_dev);
+
+ if (S_ISBLK (st.st_mode))
+ return (blk_dev);
+ else
+ return 0;
+}
+
+const char *
+grub_util_check_char_device (const char *blk_dev)
+{
+ struct stat st;
+
+ if (stat (blk_dev, &st) < 0)
+ grub_util_error ("cannot stat `%s'", blk_dev);
+
+ if (S_ISCHR (st.st_mode))
+ return (blk_dev);
+ else
+ return 0;
+}
+
+#ifdef __CYGWIN__
+/* Convert POSIX path to Win32 path,
+ remove drive letter, replace backslashes. */
+static char *
+get_win32_path (const char *path)
+{
+ char winpath[PATH_MAX];
+ if (cygwin_conv_path (CCP_POSIX_TO_WIN_A, path, winpath, sizeof(winpath)))
+ grub_util_error ("cygwin_conv_path() failed");
+
+ int len = strlen (winpath);
+ int offs = (len > 2 && winpath[1] == ':' ? 2 : 0);
+
+ int i;
+ for (i = offs; i < len; i++)
+ if (winpath[i] == '\\')
+ winpath[i] = '/';
+ return xstrdup (winpath + offs);
+}
+#endif
+
+#ifdef HAVE_LIBZFS
+static libzfs_handle_t *__libzfs_handle;
+
+static void
+fini_libzfs (void)
+{
+ libzfs_fini (__libzfs_handle);
+}
+
+libzfs_handle_t *
+grub_get_libzfs_handle (void)
+{
+ if (! __libzfs_handle)
+ {
+ __libzfs_handle = libzfs_init ();
+
+ if (__libzfs_handle)
+ atexit (fini_libzfs);
+ }
+
+ return __libzfs_handle;
+}
+#endif /* HAVE_LIBZFS */
+
+#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR)
+/* ZFS has similar problems to those of btrfs (see above). */
+void
+grub_find_zpool_from_dir (const char *dir, char **poolname, char **poolfs)
+{
+ char *slash;
+
+ *poolname = *poolfs = NULL;
+
+#if defined(HAVE_STRUCT_STATFS_F_FSTYPENAME) && defined(HAVE_STRUCT_STATFS_F_MNTFROMNAME)
+ /* FreeBSD and GNU/kFreeBSD. */
+ {
+ struct statfs mnt;
+
+ if (statfs (dir, &mnt) != 0)
+ return;
+
+ 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)
+ {
+ *slash = '\0';
+ *poolfs = xstrdup (slash + 1);
+ }
+ else
+ *poolfs = xstrdup ("");
+}
+#endif
+
+/* This function never prints trailing slashes (so that its output
+ can be appended a slash unconditionally). */
+char *
+grub_make_system_path_relative_to_its_root (const char *path)
+{
+ struct stat st;
+ char *p, *buf, *buf2, *buf3, *ret;
+ uintptr_t offset = 0;
+ dev_t num;
+ size_t len;
+
+#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR)
+ char *poolfs = NULL;
+#endif
+
+ /* canonicalize. */
+ p = canonicalize_file_name (path);
+ if (p == NULL)
+ grub_util_error ("failed to get canonical path of %s", path);
+
+#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR)
+ /* For ZFS sub-pool filesystems, could be extended to others (btrfs?). */
+ {
+ char *dummy;
+ grub_find_zpool_from_dir (p, &dummy, &poolfs);
+ }
+#endif
+
+ len = strlen (p) + 1;
+ buf = xstrdup (p);
+ free (p);
+
+ if (stat (buf, &st) < 0)
+ grub_util_error ("cannot stat %s: %s", buf, strerror (errno));
+
+ buf2 = xstrdup (buf);
+ num = st.st_dev;
+
+ /* This loop sets offset to the number of chars of the root
+ directory we're inspecting. */
+ while (1)
+ {
+ p = strrchr (buf, '/');
+ if (p == NULL)
+ /* This should never happen. */
+ grub_util_error ("FIXME: no / in buf. (make_system_path_relative_to_its_root)");
+ if (p != buf)
+ *p = 0;
+ else
+ *++p = 0;
+
+ if (stat (buf, &st) < 0)
+ grub_util_error ("cannot stat %s: %s", buf, strerror (errno));
+
+ /* buf is another filesystem; we found it. */
+ if (st.st_dev != num)
+ {
+ /* offset == 0 means path given is the mount point.
+ This works around special-casing of "/" in Un*x. This function never
+ prints trailing slashes (so that its output can be appended a slash
+ unconditionally). Each slash in is considered a preceding slash, and
+ therefore the root directory is an empty string. */
+ if (offset == 0)
+ {
+ free (buf);
+#ifdef __linux__
+ {
+ char *bind;
+ grub_free (grub_find_root_device_from_mountinfo (buf2, &bind));
+ if (bind && bind[0] && bind[1])
+ {
+ buf3 = bind;
+ goto parsedir;
+ }
+ grub_free (bind);
+ }
+#endif
+ free (buf2);
+#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR)
+ if (poolfs)
+ return xasprintf ("/%s/@", poolfs);
+#endif
+ return xstrdup ("");
+ }
+ else
+ break;
+ }
+
+ offset = p - buf;
+ /* offset == 1 means root directory. */
+ if (offset == 1)
+ {
+ /* Include leading slash. */
+ offset = 0;
+ break;
+ }
+ }
+ free (buf);
+ buf3 = xstrdup (buf2 + offset);
+ buf2[offset] = 0;
+#ifdef __linux__
+ {
+ char *bind;
+ grub_free (grub_find_root_device_from_mountinfo (buf2, &bind));
+ if (bind && bind[0] && bind[1])
+ {
+ char *temp = buf3;
+ buf3 = grub_xasprintf ("%s%s%s", bind, buf3[0] == '/' ?"":"/", buf3);
+ grub_free (temp);
+ }
+ grub_free (bind);
+ }
+#endif
+
+ free (buf2);
+
+#ifdef __CYGWIN__
+ if (st.st_dev != (DEV_CYGDRIVE_MAJOR << 16))
+ {
+ /* Reached some mount point not below /cygdrive.
+ GRUB does not know Cygwin's emulated mounts,
+ convert to Win32 path. */
+ grub_util_info ("Cygwin path = %s\n", buf3);
+ char * temp = get_win32_path (buf3);
+ free (buf3);
+ buf3 = temp;
+ }
+#endif
+
+ parsedir:
+ /* Remove trailing slashes, return empty string if root directory. */
+ len = strlen (buf3);
+ while (len > 0 && buf3[len - 1] == '/')
+ {
+ buf3[len - 1] = '\0';
+ len--;
+ }
+
+#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR)
+ if (poolfs)
+ {
+ ret = xasprintf ("/%s/@%s", poolfs, buf3);
+ free (buf3);
+ }
+ else
+#endif
+ ret = buf3;
+
+ return ret;
+}
return (cmd->func) (cmd, n, args);
}
-#define CMD_LS 1
-#define CMD_CP 2
-#define CMD_CMP 3
-#define CMD_HEX 4
-#define CMD_CRC 6
-#define CMD_BLOCKLIST 7
+enum {
+ CMD_LS = 1,
+ CMD_CP,
+ CMD_CAT,
+ CMD_CMP,
+ CMD_HEX,
+ CMD_CRC,
+ CMD_BLOCKLIST,
+ CMD_TESTLOAD
+};
#define BUF_SIZE 32256
static grub_disk_addr_t skip, leng;
+static int uncompress = 0;
static void
read_file (char *pathname, int (*hook) (grub_off_t ofs, char *buf, int len))
return;
}
- grub_file_filter_disable_compression ();
+ if (uncompress == 0)
+ grub_file_filter_disable_compression ();
file = grub_file_open (pathname);
if (!file)
{
fclose (ff);
}
+static void
+cmd_cat (char *src)
+{
+ auto int cat_hook (grub_off_t ofs, char *buf, int len);
+ int cat_hook (grub_off_t ofs, char *buf, int len)
+ {
+ (void) ofs;
+
+ if ((int) fwrite (buf, 1, len, stdout) != len)
+ {
+ grub_util_error (_("write error"));
+ return 1;
+ }
+
+ return 0;
+ }
+
+ read_file (src, cat_hook);
+}
+
static void
cmd_cmp (char *src, char *dest)
{
static int cmd = 0;
static char *debug_str = NULL;
static char **args = NULL;
+static int mount_crypt = 0;
static void
fstest (int n, char **args)
grub_free (host_file);
}
+ {
+ char *argv[2] = { "-a", NULL};
+ if (mount_crypt)
+ {
+ if (execute_command ("cryptomount", 1, argv))
+ grub_util_error (_("cryptomount command fails: %s"), grub_errmsg);
+ }
+ }
+
grub_lvm_fini ();
grub_mdraid09_fini ();
grub_mdraid1x_fini ();
case CMD_CP:
cmd_cp (args[0], args[1]);
break;
+ case CMD_CAT:
+ cmd_cat (args[0]);
+ break;
case CMD_CMP:
cmd_cmp (args[0], args[1]);
break;
case CMD_BLOCKLIST:
execute_command ("blocklist", n, args);
grub_printf ("\n");
+ case CMD_TESTLOAD:
+ execute_command ("testload", n, args);
+ grub_printf ("\n");
}
for (i = 0; i < num_disks; i++)
{0, 0, 0 , OPTION_DOC, N_("Commands:"), 1},
{N_("ls PATH"), 0, 0 , OPTION_DOC, N_("List files in PATH."), 1},
{N_("cp FILE LOCAL"), 0, 0, OPTION_DOC, N_("Copy FILE to local file LOCAL."), 1},
+ {N_("cat FILE"), 0, 0 , OPTION_DOC, N_("Copy FILE to standard output."), 1},
{N_("cmp FILE LOCAL"), 0, 0, OPTION_DOC, N_("Compare FILE with local file LOCAL."), 1},
{N_("hex FILE"), 0, 0 , OPTION_DOC, N_("Hex dump FILE."), 1},
{N_("crc FILE"), 0, 0 , OPTION_DOC, N_("Get crc32 checksum of FILE."), 1},
{"length", 'n', "N", 0, N_("Handle N bytes in output file."), 2},
{"diskcount", 'c', "N", 0, N_("N input files."), 2},
{"debug", 'd', "S", 0, N_("Set debug environment variable."), 2},
+ {"crypto", 'C', NULL, OPTION_ARG_OPTIONAL, N_("Mount crypto devices."), 2},
{"verbose", 'v', NULL, OPTION_ARG_OPTIONAL, N_("Print verbose messages."), 2},
+ {"uncompress", 'u', NULL, OPTION_ARG_OPTIONAL, N_("Uncompress data."), 2},
{0, 0, 0, 0, 0, 0}
};
root = arg;
return 0;
+ case 'C':
+ mount_crypt = 1;
+ return 0;
+
case 's':
skip = grub_strtoul (arg, &p, 0);
if (*p == 's')
verbosity++;
return 0;
+ case 'u':
+ uncompress = 1;
+ return 0;
+
case ARGP_KEY_END:
if (args_count < num_disks)
{
cmd = CMD_CP;
nparm = 2;
}
+ else if (!grub_strcmp (arg, "cat"))
+ {
+ cmd = CMD_CAT;
+ nparm = 1;
+ }
else if (!grub_strcmp (arg, "cmp"))
{
cmd = CMD_CMP;
cmd = CMD_BLOCKLIST;
nparm = 1;
}
+ else if (!grub_strcmp (arg, "testload"))
+ {
+ cmd = CMD_TESTLOAD;
+ nparm = 1;
+ }
else
{
fprintf (stderr, _("Invalid command %s.\n"), arg);
/* Initialize all modules. */
grub_init_all ();
+ grub_gcry_init_all ();
if (debug_str)
grub_env_set ("debug", debug_str);
fstest (args_count - 1 - num_disks, args);
/* Free resources. */
+ grub_gcry_fini_all ();
grub_fini_all ();
return 0;
elif [ "${platform}" = "ieee1275" ] || [ "${platform}" = "efi" ] ; then
disk_module=
else
- disk_module=ata
+ disk_module=native
fi
# Usage: usage
EOF
if [ "${target_cpu}-${platform}" = "i386-pc" ] ; then
cat <<EOF
- --disk-module=MODULE disk module to use
+ --disk-module=MODULE disk module to use (biosdisk or native)
EOF
fi
if [ "${target_cpu}-${platform}" = "i386-ieee1275" ] || [ "${target_cpu}-${platform}" = "powerpc-ieee1275" ] ; then
esac
done
+. ${libdir}/@PACKAGE@/grub-mkconfig_lib
+
if test "x$install_device" = x && ([ "${target_cpu}-${platform}" = "i386-pc" ] \
|| [ "${target_cpu}-${platform}" = "sparc64-ieee1275" ]); then
echo "install_device not specified." 1>&2
if test "x$install_device" != "x`"$grub_mkdevicemap" --device-map=/dev/stdout | "$grub_probe" --target=device --device-map=/dev/stdin "${bootdir}"`"; then
efidir="${bootdir}/efi"
fi
+ elif test -d "${bootdir}/EFI"; then
+ install_device="`"$grub_mkdevicemap" --device-map=/dev/stdout | "$grub_probe" --target=device --device-map=/dev/stdin "${bootdir}/EFI"`"
+ # Is it a mount point?
+ if test "x$install_device" != "x`"$grub_mkdevicemap" --device-map=/dev/stdout | "$grub_probe" --target=device --device-map=/dev/stdin "${bootdir}"`"; then
+ efidir="${bootdir}/EFI"
+ fi
elif test -n "$rootdir" && test "x$rootdir" != "x/"; then
# The EFI System Partition may have been given directly using
# --root-directory.
fi
done
+is_path_readable_by_grub "${grubdir}" || (echo "${grubdir}" not readable 1>&2 ; exit 1)
+
# Write device to a variable so we don't have to traverse /dev every time.
grub_device="`"$grub_probe" --device-map="${device_map}" --target=device "${grubdir}"`" || exit 1
# Device abstraction module, if any (lvm, raid).
devabstraction_module="`"$grub_probe" --device-map="${device_map}" --target=abstraction --device "${grub_device}"`"
+if [ "x$disk_module" = xata ]; then
+ disk_module=pata
+fi
+
+if [ "x$disk_module" = xnative ]; then
+ disk_module="pata ahci ohci"
+ if [ "x$target_cpu" = "xi386" ] || [ "x$target_cpu" = "xx86_64" ]; then
+ disk_module="$disk_module uhci"
+ fi
+ disk_module="$disk_module usbms"
+fi
+
# The order in this list is critical. Be careful when modifying it.
modules="$modules $disk_module"
modules="$modules $fs_module $partmap_module $devabstraction_module"
# Strip partition number
grub_partition="`echo "${grub_drive}" | sed -e 's/^[^,]*[,)]//; s/)$//'`"
grub_drive="`echo "${grub_drive}" | sed -e s/,[a-z0-9,]*//g`"
- if [ "$disk_module" = ata ] || [ "x${grub_drive}" != "x${install_drive}" ] || ([ "x$platform" != xefi ] && [ "x$platform" != xpc ] && [ x"${target_cpu}-${platform}" != x"sparc64-ieee1275" ]) ; then
+ if ([ "x$disk_module" != x ] && [ "x$disk_module" != xbiosdisk ]) || [ "x${grub_drive}" != "x${install_drive}" ] || ([ "x$platform" != xefi ] && [ "x$platform" != xpc ] && [ x"${target_cpu}-${platform}" != x"sparc64-ieee1275" ]); then
# generic method (used on coreboot and ata mod)
uuid="`"$grub_probe" --device-map="${device_map}" --target=fs_uuid --device "${grub_device}"`"
if [ "x${uuid}" = "x" ] ; then
exit 1
fi
+
echo "search.fs_uuid ${uuid} root " >> "${grubdir}/load.cfg"
echo 'set prefix=($root)'"${relative_grubdir}" >> "${grubdir}/load.cfg"
config_opt="-c ${grubdir}/load.cfg "
fi
fi
else
+ if [ x$GRUB_CRYPTODISK_ENABLE = xy ]; then
+ for uuid in "`"${grub_probe}" --device "${grub_device}" --target=cryptodisk_uuid`"; do
+ echo "cryptomount -u $uuid" >> "${grubdir}/load.cfg"
+ done
+ fi
+
+ config_opt="-c ${grubdir}/load.cfg "
+
prefix_drive=`"$grub_probe" --device-map="${device_map}" --target=drive --device "${grub_device}"` || exit 1
fi
case "${target_cpu}-${platform}" in
sparc64-ieee1275) mkimage_target=sparc64-ieee1275-raw ;;
- mips-yeeloong) mkimage_target=mipsel-yeeloong-elf ;;
+ mipsel-loongson) mkimage_target=mipsel-loongson-elf ;;
*) mkimage_target="${target_cpu}-${platform}" ;;
esac
case "${target_cpu}-${platform}" in
i386-efi | x86_64-efi) imgext=efi ;;
- mips-yeeloong | i386-coreboot | i386-multiboot | i386-ieee1275 \
+ mipsel-loongson | i386-coreboot | i386-multiboot | i386-ieee1275 \
| powerpc-ieee1275) imgext=elf ;;
*) imgext=img ;;
esac
"$grub_mkimage" ${config_opt} -d "${pkglibdir}" -O ${mkimage_target} --output="${grubdir}/core.${imgext}" --prefix="${prefix_drive}${relative_grubdir}" $modules || exit 1
# Backward-compatibility kludges
-if [ "${target_cpu}-${platform}" = "mips-yeeloong" ]; then
+if [ "${target_cpu}-${platform}" = "mipsel-loongson" ]; then
cp "${grubdir}/core.${imgext}" "${bootdir}"/grub.elf
elif [ "${target_cpu}-${platform}" = "i386-ieee1275" ] || [ "${target_cpu}-${platform}" = "powerpc-ieee1275" ]; then
cp "${grubdir}/core.${imgext}" "${grubdir}/grub"
exit 1
}
fi
+elif [ x"${target_cpu}-${platform}" = xmips-arc ]; then
+ dvhtool -d "${install_device}" --unix-to-vh "{grubdir}/core.${imgext}" grub
+ echo "You will have to set SystemPartition and OSLoader manually."
elif [ x"$platform" = xefi ]; then
cp "${grubdir}/core.${imgext}" "${efidir}/${efi_file}"
# For old macs. Suggested by Peter Jones.
esac
done
-. ${libdir}/grub/grub-mkconfig_lib
+. ${libdir}/@PACKAGE@/grub-mkconfig_lib
if [ "x$EUID" = "x" ] ; then
EUID=`id -u`
GRUB_CMDLINE_LINUX_DEFAULT \
GRUB_CMDLINE_XEN \
GRUB_CMDLINE_XEN_DEFAULT \
+ GRUB_CMDLINE_LINUX_XEN_REPLACE \
+ GRUB_CMDLINE_LINUX_XEN_REPLACE_DEFAULT \
GRUB_CMDLINE_NETBSD \
GRUB_CMDLINE_NETBSD_DEFAULT \
GRUB_TERMINAL_INPUT \
GRUB_DISABLE_OS_PROBER \
GRUB_INIT_TUNE \
GRUB_SAVEDEFAULT \
+ GRUB_ENABLE_CRYPTODISK \
GRUB_BADRAM
if test "x${grub_cfg}" != "x"; then
# ... or if we can't figure out the abstraction module, for example if
# memberlist fails on an LVM volume group.
- if ${grub_probe} -t abstraction $path > /dev/null 2>&1 ; then : ; else
+ if abstractions="`"${grub_probe}" -t abstraction "$path"`" 2>&1 ; then
+ :
+ else
return 1
fi
+ if [ x$GRUB_CRYPTODISK_ENABLE = xy ]; then
+ return 0
+ fi
+
+ for abstraction in $abstractions; do
+ if [ "x$abstraction" = xcryptodisk ]; then
+ return 1
+ fi
+ done
+
return 0
}
{
device="$1"
- # Abstraction modules aren't auto-loaded.
- abstraction="`"${grub_probe}" --device "${device}" --target=abstraction`"
- for module in ${abstraction} ; do
- echo "insmod ${module}"
- done
-
partmap="`"${grub_probe}" --device "${device}" --target=partmap`"
for module in ${partmap} ; do
case "${module}" in
esac
done
+ # Abstraction modules aren't auto-loaded.
+ abstraction="`"${grub_probe}" --device "${device}" --target=abstraction`"
+ for module in ${abstraction} ; do
+ echo "insmod ${module}"
+ done
+
fs="`"${grub_probe}" --device "${device}" --target=fs`"
for module in ${fs} ; do
echo "insmod ${module}"
done
+ if [ x$GRUB_CRYPTODISK_ENABLE = xy ]; then
+ for uuid in "`"${grub_probe}" --device "${device}" --target=cryptodisk_uuid`"; do
+ echo "cryptomount -u $uuid"
+ done
+ fi
+
# If there's a filesystem UUID that GRUB is capable of identifying, use it;
# otherwise set root as per value in device.map.
echo "set root='`"${grub_probe}" --device "${device}" --target=drive`'"
if test -f "$1" ; then
case "$1" in
*.dpkg-*) return 1 ;; # debian dpkg
- README*) return 1 ;; # documentation
+ README*|*/README*) return 1 ;; # documentation
esac
else
return 1
#include <grub/misc.h>
#include <grub/offsets.h>
#include <grub/crypto.h>
+#include <grub/dl.h>
#include <time.h>
#include <stdio.h>
struct image_target_desc
{
- const char *name;
+ const char *dirname;
+ const char *names[6];
grub_size_t voidp_sizeof;
int bigendian;
enum {
IMAGE_I386_PC, IMAGE_EFI, IMAGE_COREBOOT,
IMAGE_SPARC64_AOUT, IMAGE_SPARC64_RAW, IMAGE_I386_IEEE1275,
- IMAGE_YEELOONG_ELF, IMAGE_QEMU, IMAGE_PPC, IMAGE_YEELOONG_FLASH,
- IMAGE_I386_PC_PXE
+ IMAGE_LOONGSON_ELF, IMAGE_QEMU, IMAGE_PPC, IMAGE_YEELOONG_FLASH,
+ IMAGE_FULOONG2F_FLASH, IMAGE_I386_PC_PXE, IMAGE_MIPS_ARC,
+ IMAGE_QEMU_MIPS_FLASH
} id;
enum
{
PLATFORM_FLAGS_NONE = 0,
PLATFORM_FLAGS_LZMA = 1,
- PLATFORM_FLAGS_DECOMPRESSORS = 2
+ PLATFORM_FLAGS_DECOMPRESSORS = 2,
+ PLATFORM_FLAGS_MODULES_BEFORE_KERNEL = 4,
} flags;
- unsigned prefix;
- unsigned prefix_end;
unsigned raw_size;
unsigned total_module_size;
unsigned kernel_image_size;
grub_uint64_t link_addr;
unsigned mod_gap, mod_align;
grub_compression_t default_compression;
+ grub_uint16_t pe_target;
};
+#define EFI64_HEADER_SIZE ALIGN_UP (GRUB_PE32_MSDOS_STUB_SIZE \
+ + GRUB_PE32_SIGNATURE_SIZE \
+ + sizeof (struct grub_pe32_coff_header) \
+ + sizeof (struct grub_pe64_optional_header) \
+ + 4 * sizeof (struct grub_pe32_section_table), \
+ GRUB_PE32_SECTION_ALIGNMENT)
+
struct image_target_desc image_targets[] =
{
{
- .name = "i386-coreboot",
+ .dirname = "i386-coreboot",
+ .names = { "i386-coreboot", NULL },
.voidp_sizeof = 4,
.bigendian = 0,
.id = IMAGE_COREBOOT,
.flags = PLATFORM_FLAGS_NONE,
- .prefix = GRUB_KERNEL_I386_COREBOOT_PREFIX,
- .prefix_end = GRUB_KERNEL_I386_COREBOOT_PREFIX_END,
.raw_size = 0,
.total_module_size = TARGET_NO_FIELD,
.kernel_image_size = TARGET_NO_FIELD,
.mod_align = GRUB_KERNEL_I386_COREBOOT_MOD_ALIGN
},
{
- .name = "i386-multiboot",
+ .dirname = "i386-multiboot",
+ .names = { "i386-multiboot", NULL},
.voidp_sizeof = 4,
.bigendian = 0,
.id = IMAGE_COREBOOT,
.flags = PLATFORM_FLAGS_NONE,
- .prefix = GRUB_KERNEL_I386_MULTIBOOT_PREFIX,
- .prefix_end = GRUB_KERNEL_I386_MULTIBOOT_PREFIX_END,
.raw_size = 0,
.total_module_size = TARGET_NO_FIELD,
.kernel_image_size = TARGET_NO_FIELD,
.mod_align = GRUB_KERNEL_I386_COREBOOT_MOD_ALIGN
},
{
- .name = "i386-pc",
+ .dirname = "i386-pc",
+ .names = { "i386-pc", NULL },
.voidp_sizeof = 4,
.bigendian = 0,
.id = IMAGE_I386_PC,
.flags = PLATFORM_FLAGS_LZMA,
- .prefix = GRUB_KERNEL_I386_PC_PREFIX,
- .prefix_end = GRUB_KERNEL_I386_PC_PREFIX_END,
.raw_size = GRUB_KERNEL_I386_PC_RAW_SIZE,
.total_module_size = GRUB_KERNEL_I386_PC_TOTAL_MODULE_SIZE,
.kernel_image_size = GRUB_KERNEL_I386_PC_KERNEL_IMAGE_SIZE,
.link_addr = GRUB_KERNEL_I386_PC_LINK_ADDR
},
{
- .name = "i386-pc-pxe",
+ .dirname = "i386-pc",
+ .names = { "i386-pc-pxe", NULL },
.voidp_sizeof = 4,
.bigendian = 0,
.id = IMAGE_I386_PC_PXE,
.flags = PLATFORM_FLAGS_LZMA,
- .prefix = GRUB_KERNEL_I386_PC_PREFIX,
- .prefix_end = GRUB_KERNEL_I386_PC_PREFIX_END,
.raw_size = GRUB_KERNEL_I386_PC_RAW_SIZE,
.total_module_size = GRUB_KERNEL_I386_PC_TOTAL_MODULE_SIZE,
.kernel_image_size = GRUB_KERNEL_I386_PC_KERNEL_IMAGE_SIZE,
.link_addr = GRUB_KERNEL_I386_PC_LINK_ADDR
},
{
- .name = "i386-efi",
+ .dirname = "i386-efi",
+ .names = { "i386-efi", NULL },
.voidp_sizeof = 4,
.bigendian = 0,
.id = IMAGE_EFI,
.flags = PLATFORM_FLAGS_NONE,
- .prefix = GRUB_KERNEL_I386_EFI_PREFIX,
- .prefix_end = GRUB_KERNEL_I386_EFI_PREFIX_END,
.raw_size = 0,
.total_module_size = TARGET_NO_FIELD,
.kernel_image_size = TARGET_NO_FIELD,
GRUB_PE32_SECTION_ALIGNMENT),
.install_dos_part = TARGET_NO_FIELD,
.install_bsd_part = TARGET_NO_FIELD,
+ .pe_target = GRUB_PE32_MACHINE_I386,
+ .elf_target = EM_386,
},
{
- .name = "i386-ieee1275",
+ .dirname = "i386-ieee1275",
+ .names = { "i386-ieee1275", NULL },
.voidp_sizeof = 4,
.bigendian = 0,
.id = IMAGE_I386_IEEE1275,
.flags = PLATFORM_FLAGS_NONE,
- .prefix = GRUB_KERNEL_I386_IEEE1275_PREFIX,
- .prefix_end = GRUB_KERNEL_I386_IEEE1275_PREFIX_END,
.raw_size = 0,
.total_module_size = TARGET_NO_FIELD,
.kernel_image_size = TARGET_NO_FIELD,
.link_align = 4,
},
{
- .name = "i386-qemu",
+ .dirname = "i386-qemu",
+ .names = { "i386-qemu", NULL },
.voidp_sizeof = 4,
.bigendian = 0,
.id = IMAGE_QEMU,
.flags = PLATFORM_FLAGS_NONE,
- .prefix = GRUB_KERNEL_I386_QEMU_PREFIX,
- .prefix_end = GRUB_KERNEL_I386_QEMU_PREFIX_END,
.raw_size = 0,
.total_module_size = TARGET_NO_FIELD,
.compressed_size = TARGET_NO_FIELD,
.link_addr = GRUB_KERNEL_I386_QEMU_LINK_ADDR
},
{
- .name = "x86_64-efi",
+ .dirname = "x86_64-efi",
+ .names = { "x86_64-efi", NULL },
.voidp_sizeof = 8,
.bigendian = 0,
.id = IMAGE_EFI,
.flags = PLATFORM_FLAGS_NONE,
- .prefix = GRUB_KERNEL_X86_64_EFI_PREFIX,
- .prefix_end = GRUB_KERNEL_X86_64_EFI_PREFIX_END,
.raw_size = 0,
.total_module_size = TARGET_NO_FIELD,
.kernel_image_size = TARGET_NO_FIELD,
.compressed_size = TARGET_NO_FIELD,
.section_align = GRUB_PE32_SECTION_ALIGNMENT,
- .vaddr_offset = ALIGN_UP (GRUB_PE32_MSDOS_STUB_SIZE
- + GRUB_PE32_SIGNATURE_SIZE
- + sizeof (struct grub_pe32_coff_header)
- + sizeof (struct grub_pe64_optional_header)
- + 4 * sizeof (struct grub_pe32_section_table),
- GRUB_PE32_SECTION_ALIGNMENT),
+ .vaddr_offset = EFI64_HEADER_SIZE,
.install_dos_part = TARGET_NO_FIELD,
.install_bsd_part = TARGET_NO_FIELD,
+ .pe_target = GRUB_PE32_MACHINE_X86_64,
+ .elf_target = EM_X86_64,
},
{
- .name = "mipsel-yeeloong-flash",
+ .dirname = "mipsel-loongson",
+ .names = { "mipsel-yeeloong-flash", NULL },
.voidp_sizeof = 4,
.bigendian = 0,
.id = IMAGE_YEELOONG_FLASH,
.flags = PLATFORM_FLAGS_DECOMPRESSORS,
- .prefix = GRUB_KERNEL_MIPS_YEELOONG_PREFIX,
- .prefix_end = GRUB_KERNEL_MIPS_YEELOONG_PREFIX_END,
.raw_size = 0,
- .total_module_size = GRUB_KERNEL_MIPS_YEELOONG_TOTAL_MODULE_SIZE,
+ .total_module_size = GRUB_KERNEL_MIPS_LOONGSON_TOTAL_MODULE_SIZE,
.compressed_size = TARGET_NO_FIELD,
.kernel_image_size = TARGET_NO_FIELD,
.section_align = 1,
.vaddr_offset = 0,
.install_dos_part = TARGET_NO_FIELD,
.install_bsd_part = TARGET_NO_FIELD,
- .link_addr = GRUB_KERNEL_MIPS_YEELOONG_LINK_ADDR,
+ .link_addr = GRUB_KERNEL_MIPS_LOONGSON_LINK_ADDR,
.elf_target = EM_MIPS,
- .link_align = GRUB_KERNEL_MIPS_YEELOONG_LINK_ALIGN,
+ .link_align = GRUB_KERNEL_MIPS_LOONGSON_LINK_ALIGN,
.default_compression = COMPRESSION_NONE
},
{
- .name = "mipsel-yeeloong-elf",
+ .dirname = "mipsel-loongson",
+ .names = { "mipsel-fuloong2f-flash", NULL },
.voidp_sizeof = 4,
.bigendian = 0,
- .id = IMAGE_YEELOONG_ELF,
+ .id = IMAGE_FULOONG2F_FLASH,
.flags = PLATFORM_FLAGS_DECOMPRESSORS,
- .prefix = GRUB_KERNEL_MIPS_YEELOONG_PREFIX,
- .prefix_end = GRUB_KERNEL_MIPS_YEELOONG_PREFIX_END,
.raw_size = 0,
- .total_module_size = GRUB_KERNEL_MIPS_YEELOONG_TOTAL_MODULE_SIZE,
+ .total_module_size = GRUB_KERNEL_MIPS_LOONGSON_TOTAL_MODULE_SIZE,
.compressed_size = TARGET_NO_FIELD,
.kernel_image_size = TARGET_NO_FIELD,
.section_align = 1,
.vaddr_offset = 0,
.install_dos_part = TARGET_NO_FIELD,
.install_bsd_part = TARGET_NO_FIELD,
- .link_addr = GRUB_KERNEL_MIPS_YEELOONG_LINK_ADDR,
+ .link_addr = GRUB_KERNEL_MIPS_LOONGSON_LINK_ADDR,
.elf_target = EM_MIPS,
- .link_align = GRUB_KERNEL_MIPS_YEELOONG_LINK_ALIGN,
+ .link_align = GRUB_KERNEL_MIPS_LOONGSON_LINK_ALIGN,
.default_compression = COMPRESSION_NONE
},
{
- .name = "powerpc-ieee1275",
+ .dirname = "mipsel-loongson",
+ .names = { "mipsel-loongson-elf", "mipsel-yeeloong-elf",
+ "mipsel-fuloong2f-elf", "mipsel-fuloong2e-elf",
+ "mipsel-fuloong-elf", NULL },
+ .voidp_sizeof = 4,
+ .bigendian = 0,
+ .id = IMAGE_LOONGSON_ELF,
+ .flags = PLATFORM_FLAGS_DECOMPRESSORS,
+ .raw_size = 0,
+ .total_module_size = GRUB_KERNEL_MIPS_LOONGSON_TOTAL_MODULE_SIZE,
+ .compressed_size = TARGET_NO_FIELD,
+ .kernel_image_size = TARGET_NO_FIELD,
+ .section_align = 1,
+ .vaddr_offset = 0,
+ .install_dos_part = TARGET_NO_FIELD,
+ .install_bsd_part = TARGET_NO_FIELD,
+ .link_addr = GRUB_KERNEL_MIPS_LOONGSON_LINK_ADDR,
+ .elf_target = EM_MIPS,
+ .link_align = GRUB_KERNEL_MIPS_LOONGSON_LINK_ALIGN,
+ .default_compression = COMPRESSION_NONE
+ },
+ {
+ .dirname = "powerpc-ieee1275",
+ .names = { "powerpc-ieee1275", NULL },
.voidp_sizeof = 4,
.bigendian = 1,
.id = IMAGE_PPC,
.flags = PLATFORM_FLAGS_NONE,
- .prefix = GRUB_KERNEL_POWERPC_IEEE1275_PREFIX,
- .prefix_end = GRUB_KERNEL_POWERPC_IEEE1275_PREFIX_END,
.raw_size = 0,
.total_module_size = TARGET_NO_FIELD,
.kernel_image_size = TARGET_NO_FIELD,
.link_align = 4
},
{
- .name = "sparc64-ieee1275-raw",
+ .dirname = "sparc64-ieee1275",
+ .names = { "sparc64-ieee1275-raw", NULL },
.voidp_sizeof = 8,
.bigendian = 1,
.id = IMAGE_SPARC64_RAW,
.flags = PLATFORM_FLAGS_NONE,
- .prefix = GRUB_KERNEL_SPARC64_IEEE1275_PREFIX,
- .prefix_end = GRUB_KERNEL_SPARC64_IEEE1275_PREFIX_END,
.raw_size = GRUB_KERNEL_SPARC64_IEEE1275_RAW_SIZE,
.total_module_size = GRUB_KERNEL_SPARC64_IEEE1275_TOTAL_MODULE_SIZE,
.kernel_image_size = GRUB_KERNEL_SPARC64_IEEE1275_KERNEL_IMAGE_SIZE,
.link_addr = GRUB_KERNEL_SPARC64_IEEE1275_LINK_ADDR
},
{
- .name = "sparc64-ieee1275-aout",
+ .dirname = "sparc64-ieee1275",
+ .names = { "sparc64-ieee1275-aout", NULL },
.voidp_sizeof = 8,
.bigendian = 1,
.id = IMAGE_SPARC64_AOUT,
.flags = PLATFORM_FLAGS_NONE,
- .prefix = GRUB_KERNEL_SPARC64_IEEE1275_PREFIX,
- .prefix_end = GRUB_KERNEL_SPARC64_IEEE1275_PREFIX_END,
.raw_size = GRUB_KERNEL_SPARC64_IEEE1275_RAW_SIZE,
.total_module_size = GRUB_KERNEL_SPARC64_IEEE1275_TOTAL_MODULE_SIZE,
.kernel_image_size = GRUB_KERNEL_SPARC64_IEEE1275_KERNEL_IMAGE_SIZE,
.install_bsd_part = TARGET_NO_FIELD,
.link_addr = GRUB_KERNEL_SPARC64_IEEE1275_LINK_ADDR
},
+ {
+ .dirname = "ia64-efi",
+ .names = {"ia64-efi", NULL},
+ .voidp_sizeof = 8,
+ .bigendian = 0,
+ .id = IMAGE_EFI,
+ .flags = PLATFORM_FLAGS_NONE,
+ .raw_size = 0,
+ .total_module_size = TARGET_NO_FIELD,
+ .kernel_image_size = TARGET_NO_FIELD,
+ .compressed_size = TARGET_NO_FIELD,
+ .section_align = GRUB_PE32_SECTION_ALIGNMENT,
+ .vaddr_offset = EFI64_HEADER_SIZE,
+ .install_dos_part = TARGET_NO_FIELD,
+ .install_bsd_part = TARGET_NO_FIELD,
+ .pe_target = GRUB_PE32_MACHINE_IA64,
+ .elf_target = EM_IA_64,
+ },
+ {
+ .dirname = "mips-arc",
+ .names = {"mips-arc", NULL},
+ .voidp_sizeof = 4,
+ .bigendian = 1,
+ .id = IMAGE_MIPS_ARC,
+ .flags = (PLATFORM_FLAGS_DECOMPRESSORS
+ | PLATFORM_FLAGS_MODULES_BEFORE_KERNEL),
+ .raw_size = 0,
+ .total_module_size = GRUB_KERNEL_MIPS_ARC_TOTAL_MODULE_SIZE,
+ .compressed_size = TARGET_NO_FIELD,
+ .kernel_image_size = TARGET_NO_FIELD,
+ .section_align = 1,
+ .vaddr_offset = 0,
+ .install_dos_part = TARGET_NO_FIELD,
+ .install_bsd_part = TARGET_NO_FIELD,
+ .link_addr = GRUB_KERNEL_MIPS_ARC_LINK_ADDR,
+ .elf_target = EM_MIPS,
+ .link_align = GRUB_KERNEL_MIPS_ARC_LINK_ALIGN,
+ .default_compression = COMPRESSION_NONE
+ },
+ {
+ .dirname = "mipsel-qemu_mips",
+ .names = { "mipsel-qemu_mips-elf", NULL },
+ .voidp_sizeof = 4,
+ .bigendian = 0,
+ .id = IMAGE_LOONGSON_ELF,
+ .flags = PLATFORM_FLAGS_DECOMPRESSORS,
+ .raw_size = 0,
+ .total_module_size = GRUB_KERNEL_MIPS_QEMU_MIPS_TOTAL_MODULE_SIZE,
+ .compressed_size = TARGET_NO_FIELD,
+ .kernel_image_size = TARGET_NO_FIELD,
+ .section_align = 1,
+ .vaddr_offset = 0,
+ .install_dos_part = TARGET_NO_FIELD,
+ .install_bsd_part = TARGET_NO_FIELD,
+ .link_addr = GRUB_KERNEL_MIPS_QEMU_MIPS_LINK_ADDR,
+ .elf_target = EM_MIPS,
+ .link_align = GRUB_KERNEL_MIPS_QEMU_MIPS_LINK_ALIGN,
+ .default_compression = COMPRESSION_NONE
+ },
+ {
+ .dirname = "mips-qemu_mips",
+ .names = { "mips-qemu_mips-flash", NULL },
+ .voidp_sizeof = 4,
+ .bigendian = 1,
+ .id = IMAGE_QEMU_MIPS_FLASH,
+ .flags = PLATFORM_FLAGS_DECOMPRESSORS,
+ .raw_size = 0,
+ .total_module_size = GRUB_KERNEL_MIPS_QEMU_MIPS_TOTAL_MODULE_SIZE,
+ .compressed_size = TARGET_NO_FIELD,
+ .kernel_image_size = TARGET_NO_FIELD,
+ .section_align = 1,
+ .vaddr_offset = 0,
+ .install_dos_part = TARGET_NO_FIELD,
+ .install_bsd_part = TARGET_NO_FIELD,
+ .link_addr = GRUB_KERNEL_MIPS_QEMU_MIPS_LINK_ADDR,
+ .elf_target = EM_MIPS,
+ .link_align = GRUB_KERNEL_MIPS_QEMU_MIPS_LINK_ALIGN,
+ .default_compression = COMPRESSION_NONE
+ },
+ {
+ .dirname = "mipsel-qemu_mips",
+ .names = { "mipsel-qemu_mips-flash", NULL },
+ .voidp_sizeof = 4,
+ .bigendian = 0,
+ .id = IMAGE_QEMU_MIPS_FLASH,
+ .flags = PLATFORM_FLAGS_DECOMPRESSORS,
+ .raw_size = 0,
+ .total_module_size = GRUB_KERNEL_MIPS_QEMU_MIPS_TOTAL_MODULE_SIZE,
+ .compressed_size = TARGET_NO_FIELD,
+ .kernel_image_size = TARGET_NO_FIELD,
+ .section_align = 1,
+ .vaddr_offset = 0,
+ .install_dos_part = TARGET_NO_FIELD,
+ .install_bsd_part = TARGET_NO_FIELD,
+ .link_addr = GRUB_KERNEL_MIPS_QEMU_MIPS_LINK_ADDR,
+ .elf_target = EM_MIPS,
+ .link_align = GRUB_KERNEL_MIPS_QEMU_MIPS_LINK_ALIGN,
+ .default_compression = COMPRESSION_NONE
+ },
+ {
+ .dirname = "mips-qemu_mips",
+ .names = { "mips-qemu_mips-elf", NULL },
+ .voidp_sizeof = 4,
+ .bigendian = 1,
+ .id = IMAGE_LOONGSON_ELF,
+ .flags = PLATFORM_FLAGS_DECOMPRESSORS,
+ .raw_size = 0,
+ .total_module_size = GRUB_KERNEL_MIPS_QEMU_MIPS_TOTAL_MODULE_SIZE,
+ .compressed_size = TARGET_NO_FIELD,
+ .kernel_image_size = TARGET_NO_FIELD,
+ .section_align = 1,
+ .vaddr_offset = 0,
+ .install_dos_part = TARGET_NO_FIELD,
+ .install_bsd_part = TARGET_NO_FIELD,
+ .link_addr = GRUB_KERNEL_MIPS_QEMU_MIPS_LINK_ADDR,
+ .elf_target = EM_MIPS,
+ .link_align = GRUB_KERNEL_MIPS_QEMU_MIPS_LINK_ALIGN,
+ .default_compression = COMPRESSION_NONE
+ },
};
#define grub_target_to_host32(x) (grub_target_to_host32_real (image_target, (x)))
char *kernel_img, *core_img;
size_t kernel_size, total_module_size, core_size, exec_size;
size_t memdisk_size = 0, config_size = 0, config_size_pure = 0;
+ size_t prefix_size = 0;
char *kernel_path;
size_t offset;
struct grub_util_path_list *path_list, *p, *next;
grub_uint64_t start_address;
void *rel_section;
grub_size_t reloc_size, align;
+ size_t decompress_size;
if (comp == COMPRESSION_AUTO)
comp = image_target->default_compression;
total_module_size += config_size + sizeof (struct grub_module_header);
}
+ if (prefix)
+ {
+ prefix_size = ALIGN_ADDR (strlen (prefix) + 1);
+ total_module_size += prefix_size + sizeof (struct grub_module_header);
+ }
+
for (p = path_list; p; p = p->next)
total_module_size += (ALIGN_ADDR (grub_util_get_image_size (p->name))
+ sizeof (struct grub_module_header));
total_module_size, &start_address, &rel_section,
&reloc_size, &align, image_target);
- if (image_target->prefix + strlen (prefix) + 1 > image_target->prefix_end)
- grub_util_error (_("prefix is too long"));
- strcpy (kernel_img + image_target->prefix, prefix);
+ if ((image_target->flags & PLATFORM_FLAGS_DECOMPRESSORS)
+ && (image_target->total_module_size != TARGET_NO_FIELD))
+ *((grub_uint32_t *) (kernel_img + image_target->total_module_size))
+ = grub_host_to_target32 (total_module_size);
+
+ if (image_target->flags & PLATFORM_FLAGS_MODULES_BEFORE_KERNEL)
+ memmove (kernel_img + total_module_size, kernel_img, kernel_size);
if (image_target->voidp_sizeof == 8)
{
/* Fill in the grub_module_info structure. */
struct grub_module_info64 *modinfo;
- modinfo = (struct grub_module_info64 *) (kernel_img + kernel_size);
+ if (image_target->flags & PLATFORM_FLAGS_MODULES_BEFORE_KERNEL)
+ modinfo = (struct grub_module_info64 *) kernel_img;
+ else
+ modinfo = (struct grub_module_info64 *) (kernel_img + kernel_size);
memset (modinfo, 0, sizeof (struct grub_module_info64));
modinfo->magic = grub_host_to_target32 (GRUB_MODULE_MAGIC);
modinfo->offset = grub_host_to_target_addr (sizeof (struct grub_module_info64));
modinfo->size = grub_host_to_target_addr (total_module_size);
- offset = kernel_size + sizeof (struct grub_module_info64);
+ if (image_target->flags & PLATFORM_FLAGS_MODULES_BEFORE_KERNEL)
+ offset = sizeof (struct grub_module_info64);
+ else
+ offset = kernel_size + sizeof (struct grub_module_info64);
}
else
{
/* Fill in the grub_module_info structure. */
struct grub_module_info32 *modinfo;
- modinfo = (struct grub_module_info32 *) (kernel_img + kernel_size);
+ if (image_target->flags & PLATFORM_FLAGS_MODULES_BEFORE_KERNEL)
+ modinfo = (struct grub_module_info32 *) kernel_img;
+ else
+ modinfo = (struct grub_module_info32 *) (kernel_img + kernel_size);
memset (modinfo, 0, sizeof (struct grub_module_info32));
modinfo->magic = grub_host_to_target32 (GRUB_MODULE_MAGIC);
modinfo->offset = grub_host_to_target_addr (sizeof (struct grub_module_info32));
modinfo->size = grub_host_to_target_addr (total_module_size);
- offset = kernel_size + sizeof (struct grub_module_info32);
+ if (image_target->flags & PLATFORM_FLAGS_MODULES_BEFORE_KERNEL)
+ offset = sizeof (struct grub_module_info32);
+ else
+ offset = kernel_size + sizeof (struct grub_module_info32);
}
for (p = path_list; p; p = p->next)
offset += config_size;
}
- if ((image_target->flags & PLATFORM_FLAGS_DECOMPRESSORS)
- && (image_target->total_module_size != TARGET_NO_FIELD))
- *((grub_uint32_t *) (kernel_img + image_target->total_module_size))
- = grub_host_to_target32 (total_module_size);
+ if (prefix)
+ {
+ struct grub_module_header *header;
+
+ header = (struct grub_module_header *) (kernel_img + offset);
+ memset (header, 0, sizeof (struct grub_module_header));
+ header->type = grub_host_to_target32 (OBJ_TYPE_PREFIX);
+ header->size = grub_host_to_target32 (prefix_size + sizeof (*header));
+ offset += sizeof (*header);
+
+ grub_memset (kernel_img + offset, 0, prefix_size);
+ grub_strcpy (kernel_img + offset, prefix);
+ offset += prefix_size;
+ }
grub_util_info ("kernel_img=%p, kernel_size=0x%x", kernel_img, kernel_size);
compress_kernel (image_target, kernel_img, kernel_size + total_module_size,
&core_img, &core_size, comp);
+ free (kernel_img);
+
+ if (image_target->flags & PLATFORM_FLAGS_DECOMPRESSORS)
+ kernel_img = core_img + total_module_size;
+ else
+ kernel_img = core_img;
grub_util_info ("the core size is 0x%x", core_size);
if (!(image_target->flags & PLATFORM_FLAGS_DECOMPRESSORS)
&& image_target->total_module_size != TARGET_NO_FIELD)
- *((grub_uint32_t *) (core_img + image_target->total_module_size))
+ *((grub_uint32_t *) (kernel_img + image_target->total_module_size))
= grub_host_to_target32 (total_module_size);
if (image_target->kernel_image_size != TARGET_NO_FIELD)
- *((grub_uint32_t *) (core_img + image_target->kernel_image_size))
+ *((grub_uint32_t *) (kernel_img + image_target->kernel_image_size))
= grub_host_to_target32 (kernel_size);
if (image_target->compressed_size != TARGET_NO_FIELD)
- *((grub_uint32_t *) (core_img + image_target->compressed_size))
+ *((grub_uint32_t *) (kernel_img + image_target->compressed_size))
= grub_host_to_target32 (core_size - image_target->raw_size);
/* If we included a drive in our prefix, let GRUB know it doesn't have to
if (image_target->install_dos_part != TARGET_NO_FIELD
&& image_target->install_bsd_part != TARGET_NO_FIELD && prefix[0] == '(')
{
- *((grub_int32_t *) (core_img + image_target->install_dos_part))
+ *((grub_int32_t *) (kernel_img + image_target->install_dos_part))
= grub_host_to_target32 (-2);
- *((grub_int32_t *) (core_img + image_target->install_bsd_part))
+ *((grub_int32_t *) (kernel_img + image_target->install_bsd_part))
= grub_host_to_target32 (-2);
}
char *full_img;
size_t full_size;
char *decompress_path, *decompress_img;
- size_t decompress_size;
const char *name;
switch (comp)
decompress_size = grub_util_get_image_size (decompress_path);
decompress_img = grub_util_read_image (decompress_path);
- *((grub_uint32_t *) (decompress_img + GRUB_KERNEL_MIPS_YEELOONG_COMPRESSED_SIZE))
+ *((grub_uint32_t *) (decompress_img + GRUB_KERNEL_MIPS_LOONGSON_COMPRESSED_SIZE))
= grub_host_to_target32 (core_size);
- *((grub_uint32_t *) (decompress_img + GRUB_KERNEL_MIPS_YEELOONG_UNCOMPRESSED_SIZE))
+ *((grub_uint32_t *) (decompress_img + GRUB_KERNEL_MIPS_LOONGSON_UNCOMPRESSED_SIZE))
= grub_host_to_target32 (kernel_size + total_module_size);
+ if (image_target->flags & PLATFORM_FLAGS_MODULES_BEFORE_KERNEL)
+ *((grub_uint32_t *) (decompress_img + GRUB_KERNEL_MIPS_LOONGSON_UNCOMPRESSED_ADDR))
+ = grub_host_to_target_addr (image_target->link_addr - total_module_size);
+ else
+ *((grub_uint32_t *) (decompress_img + GRUB_KERNEL_MIPS_LOONGSON_UNCOMPRESSED_ADDR))
+ = grub_host_to_target_addr (image_target->link_addr);
+
full_size = core_size + decompress_size;
full_img = xmalloc (full_size);
+ 4 * sizeof (struct grub_pe32_section_table),
GRUB_PE32_SECTION_ALIGNMENT);
else
- header_size = ALIGN_UP (GRUB_PE32_MSDOS_STUB_SIZE
- + GRUB_PE32_SIGNATURE_SIZE
- + sizeof (struct grub_pe32_coff_header)
- + sizeof (struct grub_pe64_optional_header)
- + 4 * sizeof (struct grub_pe32_section_table),
- GRUB_PE32_SECTION_ALIGNMENT);
+ header_size = EFI64_HEADER_SIZE;
reloc_addr = ALIGN_UP (header_size + core_size,
image_target->section_align);
/* The COFF file header. */
c = (struct grub_pe32_coff_header *) (header + GRUB_PE32_MSDOS_STUB_SIZE
+ GRUB_PE32_SIGNATURE_SIZE);
- if (image_target->voidp_sizeof == 4)
- c->machine = grub_host_to_target16 (GRUB_PE32_MACHINE_I386);
- else
- c->machine = grub_host_to_target16 (GRUB_PE32_MACHINE_X86_64);
+ c->machine = grub_host_to_target16 (image_target->pe_target);
c->num_sections = grub_host_to_target16 (4);
c->time = grub_host_to_target32 (time (0));
rom_img = xmalloc (rom_size);
memset (rom_img, 0, rom_size);
- *((grub_int32_t *) (core_img + GRUB_KERNEL_I386_QEMU_CORE_ENTRY_ADDR))
+ *((grub_int32_t *) (kernel_img + GRUB_KERNEL_I386_QEMU_CORE_ENTRY_ADDR))
= grub_host_to_target32 ((grub_uint32_t) -rom_size);
memcpy (rom_img, core_img, core_size);
aout_size = core_size + sizeof (*aout_head);
aout_img = xmalloc (aout_size);
aout_head = aout_img;
+ grub_memset (aout_head, 0, sizeof (*aout_head));
aout_head->a_midmag = grub_host_to_target32 ((AOUT_MID_SUN << 16)
| AOUT32_OMAGIC);
aout_head->a_text = grub_host_to_target32 (core_size);
}
break;
case IMAGE_YEELOONG_FLASH:
+ case IMAGE_FULOONG2F_FLASH:
{
char *rom_img;
size_t rom_size;
char *boot_path, *boot_img;
size_t boot_size;
grub_uint8_t context[GRUB_MD_SHA512->contextsize];
- /* fwstart.img is the only part which can't be testes by using *-elf
- target. Check it against the checksum. This checksum is obtained with
- sha512sum utility after compiling on Gnewsense.
- */
- const grub_uint8_t fwstart_good_hash[] =
- { 0x75, 0xbf, 0xa3, 0x0e, 0x7c, 0xd1, 0x03, 0x82,
- 0xe1, 0x34, 0x55, 0xd7, 0x09, 0x1e, 0x6c, 0xcc,
- 0xef, 0x08, 0x61, 0xc1, 0x3c, 0xd8, 0xc7, 0x9f,
- 0xe8, 0x2d, 0x3d, 0xb2, 0xda, 0x41, 0xd3, 0x83,
- 0xd7, 0xb8, 0xe3, 0xd7, 0x13, 0xec, 0x9b, 0xf6,
- 0xf6, 0xae, 0x6b, 0x32, 0x29, 0xc1, 0x69, 0x82,
- 0xfa, 0x65, 0x2d, 0x97, 0x3e, 0x83, 0x6e, 0x6c,
- 0xce, 0x34, 0x10, 0x59, 0x74, 0x0e, 0x96, 0x26 };
-
- boot_path = grub_util_get_path (dir, "fwstart.img");
+ /* fwstart.img is the only part which can't be tested by using *-elf
+ target. Check it against the checksum. */
+ const grub_uint8_t yeeloong_fwstart_good_hash[512 / 8] =
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+ /* None yet. */
+ const grub_uint8_t fuloong2f_fwstart_good_hash[512 / 8] =
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ };
+ const grub_uint8_t *fwstart_good_hash;
+
+ if (image_target->id == IMAGE_FULOONG2F_FLASH)
+ {
+ fwstart_good_hash = fuloong2f_fwstart_good_hash;
+ boot_path = grub_util_get_path (dir, "fwstart_fuloong2f.img");
+ }
+ else
+ {
+ fwstart_good_hash = yeeloong_fwstart_good_hash;
+ boot_path = grub_util_get_path (dir, "fwstart.img");
+ }
+
boot_size = grub_util_get_image_size (boot_path);
boot_img = grub_util_read_image (boot_path);
core_size = rom_size;
}
break;
- case IMAGE_YEELOONG_ELF:
+ case IMAGE_QEMU_MIPS_FLASH:
+ {
+ char *rom_img;
+ size_t rom_size;
+
+ if (core_size > 512 * 1024)
+ grub_util_error ("firmware image is too big");
+ rom_size = 512 * 1024;
+
+ rom_img = xmalloc (rom_size);
+ memset (rom_img, 0, rom_size);
+
+ memcpy (rom_img, core_img, core_size);
+
+ memset (rom_img + core_size, 0,
+ rom_size - core_size);
+
+ free (core_img);
+ core_img = rom_img;
+ core_size = rom_size;
+ }
+ break;
+ case IMAGE_MIPS_ARC:
+ {
+ char *ecoff_img;
+ struct ecoff_header {
+ grub_uint16_t magic;
+ grub_uint16_t nsec;
+ grub_uint32_t time;
+ grub_uint32_t syms;
+ grub_uint32_t nsyms;
+ grub_uint16_t opt;
+ grub_uint16_t flags;
+ grub_uint16_t magic2;
+ grub_uint16_t version;
+ grub_uint32_t textsize;
+ grub_uint32_t datasize;
+ grub_uint32_t bsssize;
+ grub_uint32_t entry;
+ grub_uint32_t text_start;
+ grub_uint32_t data_start;
+ grub_uint32_t bss_start;
+ grub_uint32_t gprmask;
+ grub_uint32_t cprmask[4];
+ grub_uint32_t gp_value;
+ };
+ struct ecoff_section
+ {
+ char name[8];
+ grub_uint32_t paddr;
+ grub_uint32_t vaddr;
+ grub_uint32_t size;
+ grub_uint32_t file_offset;
+ grub_uint32_t reloc;
+ grub_uint32_t gp;
+ grub_uint16_t nreloc;
+ grub_uint16_t ngp;
+ grub_uint32_t flags;
+ };
+ struct ecoff_header *head;
+ struct ecoff_section *section;
+ grub_uint32_t target_addr;
+ size_t program_size;
+
+ program_size = ALIGN_ADDR (core_size);
+ if (comp == COMPRESSION_NONE)
+ target_addr = (image_target->link_addr
+ - total_module_size - decompress_size);
+ else
+ target_addr = (image_target->link_addr
+ - ALIGN_UP(total_module_size + core_size, 1048576)
+ - (1 << 20));
+
+ ecoff_img = xmalloc (program_size + sizeof (*head) + sizeof (*section));
+ grub_memset (ecoff_img, 0, program_size + sizeof (*head) + sizeof (*section));
+ head = (void *) ecoff_img;
+ section = (void *) (head + 1);
+ head->magic = grub_host_to_target16 (0x160);
+ head->nsec = grub_host_to_target16 (1);
+ head->time = grub_host_to_target32 (0);
+ head->opt = grub_host_to_target16 (0x38);
+ head->flags = grub_host_to_target16 (0x207);
+ head->magic2 = grub_host_to_target16 (0x107);
+ head->textsize = grub_host_to_target32 (program_size);
+ head->entry = grub_host_to_target32 (target_addr);
+ head->text_start = grub_host_to_target32 (target_addr);
+ head->data_start = grub_host_to_target32 (target_addr + program_size);
+ grub_memcpy (section->name, ".text", sizeof (".text") - 1);
+ section->vaddr = grub_host_to_target32 (target_addr);
+ section->size = grub_host_to_target32 (program_size);
+ section->file_offset = grub_host_to_target32 (sizeof (*head) + sizeof (*section));
+ memcpy (section + 1, core_img, core_size);
+ free (core_img);
+ core_img = ecoff_img;
+ core_size = program_size + sizeof (*head) + sizeof (*section);
+ }
+ break;
+ case IMAGE_LOONGSON_ELF:
case IMAGE_PPC:
case IMAGE_COREBOOT:
case IMAGE_I386_IEEE1275:
int header_size, footer_size = 0;
int phnum = 1;
- if (image_target->id != IMAGE_YEELOONG_ELF)
+ if (image_target->id != IMAGE_LOONGSON_ELF)
phnum += 2;
if (note)
/* No section headers. */
ehdr->e_shoff = grub_host_to_target32 (0);
- if (image_target->id == IMAGE_YEELOONG_ELF)
+ if (image_target->id == IMAGE_LOONGSON_ELF)
ehdr->e_shentsize = grub_host_to_target16 (0);
else
ehdr->e_shentsize = grub_host_to_target16 (sizeof (Elf32_Shdr));
phdr->p_offset = grub_host_to_target32 (header_size);
phdr->p_flags = grub_host_to_target32 (PF_R | PF_W | PF_X);
- if (image_target->id == IMAGE_YEELOONG_ELF)
- target_addr = ALIGN_UP (image_target->link_addr
- + kernel_size + total_module_size, 32);
+ if (image_target->id == IMAGE_LOONGSON_ELF)
+ {
+ if (comp == COMPRESSION_NONE)
+ target_addr = (image_target->link_addr - decompress_size);
+ else
+ target_addr = ALIGN_UP (image_target->link_addr
+ + kernel_size + total_module_size, 32);
+ }
else
target_addr = image_target->link_addr;
ehdr->e_entry = grub_host_to_target32 (target_addr);
phdr->p_vaddr = grub_host_to_target32 (target_addr);
phdr->p_paddr = grub_host_to_target32 (target_addr);
phdr->p_align = grub_host_to_target32 (align > image_target->link_align ? align : image_target->link_align);
- if (image_target->id == IMAGE_YEELOONG_ELF)
+ if (image_target->id == IMAGE_LOONGSON_ELF)
ehdr->e_flags = grub_host_to_target32 (0x1000 | EF_MIPS_NOREORDER
| EF_MIPS_PIC | EF_MIPS_CPIC);
else
ehdr->e_flags = 0;
- if (image_target->id == IMAGE_YEELOONG_ELF)
+ if (image_target->id == IMAGE_LOONGSON_ELF)
{
phdr->p_filesz = grub_host_to_target32 (core_size);
phdr->p_memsz = grub_host_to_target32 (core_size);
}
grub_util_write_image (core_img, core_size, out);
- free (kernel_img);
free (core_img);
free (kernel_path);
char *ptr;
unsigned i;
for (i = 0; i < ARRAY_SIZE (image_targets); i++)
- format_len += strlen (image_targets[i].name) + 2;
+ format_len += strlen (image_targets[i].names[0]) + 2;
ptr = formats = xmalloc (format_len);
for (i = 0; i < ARRAY_SIZE (image_targets); i++)
{
- strcpy (ptr, image_targets[i].name);
- ptr += strlen (image_targets[i].name);
+ strcpy (ptr, image_targets[i].names[0]);
+ ptr += strlen (image_targets[i].names[0]);
*ptr++ = ',';
*ptr++ = ' ';
}
case 'O':
{
- unsigned i;
+ unsigned i, j;
for (i = 0; i < ARRAY_SIZE (image_targets); i++)
- if (strcmp (optarg, image_targets[i].name) == 0)
- image_target = &image_targets[i];
+ for (j = 0; image_targets[i].names[j]
+ && j < ARRAY_SIZE (image_targets[i].names); j++)
+ if (strcmp (optarg, image_targets[i].names[j]) == 0)
+ image_target = &image_targets[i];
if (!image_target)
{
printf ("unknown target format %s\n", optarg);
if (!dir)
{
- const char *last;
- last = strchr (image_target->name, '-');
- if (last)
- last = strchr (last + 1, '-');
- if (!last)
- last = image_target->name + strlen (image_target->name);
- dir = xmalloc (sizeof (GRUB_PKGLIBROOTDIR) + (last - image_target->name)
- + 1);
+ dir = xmalloc (sizeof (GRUB_PKGLIBROOTDIR)
+ + grub_strlen (image_target->dirname) + 1);
memcpy (dir, GRUB_PKGLIBROOTDIR, sizeof (GRUB_PKGLIBROOTDIR) - 1);
*(dir + sizeof (GRUB_PKGLIBROOTDIR) - 1) = '/';
- if (strncmp (image_target->name, "mipsel-yeeloong",
- last - image_target->name) == 0)
- {
- memcpy (dir + sizeof (GRUB_PKGLIBROOTDIR), "mips-yeeloong",
- sizeof ("mips-yeeloong"));
- }
- else
- {
- memcpy (dir + sizeof (GRUB_PKGLIBROOTDIR), image_target->name,
- last - image_target->name);
- *(dir + sizeof (GRUB_PKGLIBROOTDIR) + (last - image_target->name))
- = 0;
- }
+ strcpy (dir + sizeof (GRUB_PKGLIBROOTDIR), image_target->dirname);
}
generate_image (dir, prefix ? : DEFAULT_DIRECTORY, fp,
argv + optind, memdisk, config,
image_target, note, comp);
+ fflush (fp);
+ fsync (fileno (fp));
fclose (fp);
if (dir)
SUFFIX (relocate_symbols) (Elf_Ehdr *e, Elf_Shdr *sections,
Elf_Shdr *symtab_section, Elf_Addr *section_addresses,
Elf_Half section_entsize, Elf_Half num_sections,
+ void *jumpers, Elf_Addr jumpers_addr,
struct image_target_desc *image_target)
{
Elf_Word symtab_size, sym_size, num_syms;
Elf_Word i;
Elf_Shdr *strtab_section;
const char *strtab;
+ grub_uint64_t *jptr = jumpers;
strtab_section
= (Elf_Shdr *) ((char *) sections
else if (index >= num_sections)
grub_util_error ("section %d does not exist", index);
- sym->st_value = (grub_target_to_host32 (sym->st_value)
+ sym->st_value = (grub_target_to_host (sym->st_value)
+ section_addresses[index]);
- grub_util_info ("locating %s at 0x%x", name, sym->st_value);
+
+ if (image_target->elf_target == EM_IA_64 && ELF_ST_TYPE (sym->st_info)
+ == STT_FUNC)
+ {
+ *jptr = sym->st_value;
+ sym->st_value = (char *) jptr - (char *) jumpers + jumpers_addr;
+ jptr++;
+ *jptr = 0;
+ jptr++;
+ }
+ grub_util_info ("locating %s at 0x%x", name, sym->st_value, section_addresses[index]);
if (! start_address)
if (strcmp (name, "_start") == 0 || strcmp (name, "start") == 0)
return (Elf_Addr *) ((char *) e + grub_target_to_host32 (s->sh_offset) + offset);
}
+static Elf_Addr
+SUFFIX (count_funcs) (Elf_Ehdr *e, Elf_Shdr *symtab_section,
+ struct image_target_desc *image_target)
+{
+ Elf_Word symtab_size, sym_size, num_syms;
+ Elf_Off symtab_offset;
+ Elf_Addr start_address = 0;
+ Elf_Sym *sym;
+ Elf_Word i;
+ int ret = 0;
+
+ symtab_size = grub_target_to_host (symtab_section->sh_size);
+ sym_size = grub_target_to_host (symtab_section->sh_entsize);
+ symtab_offset = grub_target_to_host (symtab_section->sh_offset);
+ num_syms = symtab_size / sym_size;
+
+ for (i = 0, sym = (Elf_Sym *) ((char *) e + symtab_offset);
+ i < num_syms;
+ i++, sym = (Elf_Sym *) ((char *) sym + sym_size))
+ if (ELF_ST_TYPE (sym->st_info) == STT_FUNC)
+ ret++;
+
+ return ret;
+}
+
+#ifdef MKIMAGE_ELF64
+struct unaligned_uint32
+{
+ grub_uint32_t val;
+} __attribute__ ((packed));
+
+#define MASK20 ((1 << 20) - 1)
+#define MASK19 ((1 << 19) - 1)
+
+static void
+add_value_to_slot_20b (grub_addr_t addr, grub_uint32_t value)
+{
+ struct unaligned_uint32 *p;
+ switch (addr & 3)
+ {
+ case 0:
+ p = (struct unaligned_uint32 *) ((addr & ~3ULL) + 2);
+ p->val = ((((((p->val >> 2) & MASK20) + value) & MASK20) << 2)
+ | (p->val & ~(MASK20 << 2)));
+ break;
+ case 1:
+ p = (struct unaligned_uint32 *) ((grub_uint8_t *) (addr & ~3ULL) + 7);
+ p->val = ((((((p->val >> 3) & MASK20) + value) & MASK20) << 3)
+ | (p->val & ~(MASK20 << 3)));
+ break;
+ case 2:
+ p = (struct unaligned_uint32 *) ((grub_uint8_t *) (addr & ~3ULL) + 12);
+ p->val = ((((((p->val >> 4) & MASK20) + value) & MASK20) << 4)
+ | (p->val & ~(MASK20 << 4)));
+ break;
+ }
+}
+
+#define MASKF21 ( ((1 << 23) - 1) & ~((1 << 7) | (1 << 8)) )
+
+static grub_uint32_t
+add_value_to_slot_21_real (grub_uint32_t a, grub_uint32_t value)
+{
+ grub_uint32_t high, mid, low, c;
+ low = (a & 0x00007f);
+ mid = (a & 0x7fc000) >> 7;
+ high = (a & 0x003e00) << 7;
+ c = (low | mid | high) + value;
+ return (c & 0x7f) | ((c << 7) & 0x7fc000) | ((c >> 7) & 0x0003e00); //0x003e00
+}
+
+static void
+add_value_to_slot_21 (grub_addr_t addr, grub_uint32_t value)
+{
+ struct unaligned_uint32 *p;
+ switch (addr & 3)
+ {
+ case 0:
+ p = (struct unaligned_uint32 *) ((addr & ~3ULL) + 2);
+ p->val = ((add_value_to_slot_21_real (((p->val >> 2) & MASKF21), value) & MASKF21) << 2) | (p->val & ~(MASKF21 << 2));
+ break;
+ case 1:
+ p = (struct unaligned_uint32 *) ((grub_uint8_t *) (addr & ~3ULL) + 7);
+ p->val = ((add_value_to_slot_21_real (((p->val >> 3) & MASKF21), value) & MASKF21) << 3) | (p->val & ~(MASKF21 << 3));
+ break;
+ case 2:
+ p = (struct unaligned_uint32 *) ((grub_uint8_t *) (addr & ~3ULL) + 12);
+ p->val = ((add_value_to_slot_21_real (((p->val >> 4) & MASKF21), value) & MASKF21) << 4) | (p->val & ~(MASKF21 << 4));
+ break;
+ }
+}
+
+
+struct ia64_kernel_trampoline
+{
+ /* nop.m */
+ grub_uint8_t nop[5];
+ /* movl r15 = addr*/
+ grub_uint8_t addr_hi[6];
+ grub_uint8_t e0;
+ grub_uint8_t addr_lo[4];
+ grub_uint8_t jump[0x20];
+};
+
+static grub_uint8_t nopm[5] =
+ {
+ /* [MLX] nop.m 0x0 */
+ 0x05, 0x00, 0x00, 0x00, 0x01
+ };
+
+static grub_uint8_t jump[0x20] =
+ {
+ /* [MMI] add r15=r15,r1;; */
+ 0x0b, 0x78, 0x3c, 0x02, 0x00, 0x20,
+ /* ld8 r16=[r15],8 */
+ 0x00, 0x41, 0x3c, 0x30, 0x28, 0xc0,
+ /* mov r14=r1;; */
+ 0x01, 0x08, 0x00, 0x84,
+ /* [MIB] ld8 r1=[r15] */
+ 0x11, 0x08, 0x00, 0x1e, 0x18, 0x10,
+ /* mov b6=r16 */
+ 0x60, 0x80, 0x04, 0x80, 0x03, 0x00,
+ /* br.few b6;; */
+ 0x60, 0x00, 0x80, 0x00
+ };
+
+static void
+make_trampoline (struct ia64_kernel_trampoline *tr, grub_uint64_t addr)
+{
+ grub_memcpy (tr->nop, nopm, sizeof (tr->nop));
+ tr->addr_hi[0] = ((addr & 0xc00000) >> 16);
+ tr->addr_hi[1] = (addr >> 24) & 0xff;
+ tr->addr_hi[2] = (addr >> 32) & 0xff;
+ tr->addr_hi[3] = (addr >> 40) & 0xff;
+ tr->addr_hi[4] = (addr >> 48) & 0xff;
+ tr->addr_hi[5] = (addr >> 56) & 0xff;
+ tr->e0 = 0xe0;
+ tr->addr_lo[0] = ((addr & 0x000f) << 4) | 0x01;
+ tr->addr_lo[1] = (((addr & 0x0070) >> 4) | ((addr & 0x070000) >> 11)
+ | ((addr & 0x200000) >> 17));
+ tr->addr_lo[2] = ((addr & 0x1f80) >> 5) | ((addr & 0x180000) >> 19);
+ tr->addr_lo[3] = ((addr & 0xe000) >> 13) | 0x60;
+ grub_memcpy (tr->jump, jump, sizeof (tr->jump));
+}
+#endif
+
/* Deal with relocation information. This function relocates addresses
within the virtual address space starting from 0. So only relative
addresses can be fully resolved. Absolute addresses must be relocated
SUFFIX (relocate_addresses) (Elf_Ehdr *e, Elf_Shdr *sections,
Elf_Addr *section_addresses,
Elf_Half section_entsize, Elf_Half num_sections,
- const char *strtab, struct image_target_desc *image_target)
+ const char *strtab,
+ char *pe_target, Elf_Addr tramp_off,
+ Elf_Addr got_off,
+ struct image_target_desc *image_target)
{
Elf_Half i;
Elf_Shdr *s;
+ struct ia64_kernel_trampoline *tr = (void *) (pe_target + tramp_off);
+ grub_uint64_t *gpptr = (void *) (pe_target + got_off);
for (i = 0, s = sections;
i < num_sections;
addend = (s->sh_type == grub_target_to_host32 (SHT_RELA)) ?
r->r_addend : 0;
- if (image_target->voidp_sizeof == 4)
+ switch (image_target->elf_target)
+ {
+ case EM_386:
switch (ELF_R_TYPE (info))
{
case R_386_NONE:
*target, offset);
break;
default:
- grub_util_error ("unknown relocation type %d",
+ grub_util_error ("unknown relocation type 0x%x",
ELF_R_TYPE (info));
break;
}
- else
+ break;
+ case EM_X86_64:
switch (ELF_R_TYPE (info))
{
ELF_R_TYPE (info));
break;
}
+ break;
+#ifdef MKIMAGE_ELF64
+ case EM_IA_64:
+ switch (ELF_R_TYPE (info))
+ {
+ case R_IA64_PCREL21B:
+ {
+ grub_uint64_t noff;
+ make_trampoline (tr, addend + sym_addr);
+ noff = ((char *) tr - (char *) pe_target
+ - target_section_addr - (offset & ~3)) >> 4;
+ tr++;
+ if (noff & ~MASK19)
+ grub_util_error ("trampoline offset too big (%lx)",
+ noff);
+ add_value_to_slot_20b ((grub_addr_t) target, noff);
+ }
+ break;
+
+ case R_IA64_LTOFF22X:
+ case R_IA64_LTOFF22:
+ {
+ Elf_Sym *sym;
+
+ sym = (Elf_Sym *) ((char *) e
+ + grub_target_to_host32 (symtab_section->sh_offset)
+ + ELF_R_SYM (info) * grub_target_to_host32 (symtab_section->sh_entsize));
+ if (ELF_ST_TYPE (sym->st_info) == STT_FUNC)
+ sym_addr = grub_target_to_host64 (*(grub_uint64_t *) (pe_target
+ + sym->st_value
+ - image_target->vaddr_offset));
+ }
+ case R_IA64_LTOFF_FPTR22:
+ *gpptr = grub_host_to_target64 (addend + sym_addr);
+ add_value_to_slot_21 ((grub_addr_t) target,
+ (char *) gpptr - (char *) pe_target
+ + image_target->vaddr_offset);
+ gpptr++;
+ break;
+
+ case R_IA64_GPREL22:
+ add_value_to_slot_21 ((grub_addr_t) target,
+ addend + sym_addr);
+ break;
+ case R_IA64_PCREL64LSB:
+ *target = grub_host_to_target64 (grub_target_to_host64 (*target)
+ + addend + sym_addr
+ - target_section_addr - offset
+ - image_target->vaddr_offset);
+ break;
+
+ case R_IA64_SEGREL64LSB:
+ *target = grub_host_to_target64 (grub_target_to_host64 (*target)
+ + addend + sym_addr - target_section_addr);
+ break;
+ case R_IA64_DIR64LSB:
+ case R_IA64_FPTR64LSB:
+ *target = grub_host_to_target64 (grub_target_to_host64 (*target)
+ + addend + sym_addr);
+ grub_util_info ("relocating a direct entry to 0x%"
+ PRIxGRUB_UINT64_T " at the offset 0x%x",
+ *target, offset);
+ break;
+
+ /* We treat LTOFF22X as LTOFF22, so we can ignore LDXMOV. */
+ case R_IA64_LDXMOV:
+ break;
+
+ default:
+ grub_util_error ("unknown relocation type 0x%x",
+ ELF_R_TYPE (info));
+ break;
+ }
+ break;
+#endif
+ default:
+ grub_util_error ("unknown architecture type %d",
+ image_target->elf_target);
+ }
}
}
}
b->block_size += 2;
}
}
- else if (b->block_size & (8 - 1))
+ else while (b->block_size & (8 - 1))
{
/* If not aligned with a 32-bit boundary, add
a padding entry. */
SUFFIX (make_reloc_section) (Elf_Ehdr *e, void **out,
Elf_Addr *section_addresses, Elf_Shdr *sections,
Elf_Half section_entsize, Elf_Half num_sections,
- const char *strtab, struct image_target_desc *image_target)
+ const char *strtab,
+ Elf_Addr jumpers, grub_size_t njumpers,
+ struct image_target_desc *image_target)
{
- Elf_Half i;
+ unsigned i;
Elf_Shdr *s;
struct fixup_block_list *lst, *lst0;
Elf_Addr current_address = 0;
lst = lst0 = xmalloc (sizeof (*lst) + 2 * 0x1000);
memset (lst, 0, sizeof (*lst) + 2 * 0x1000);
- for (i = 0, s = sections;
- i < num_sections;
+ for (i = 0, s = sections; i < num_sections;
i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
if ((s->sh_type == grub_cpu_to_le32 (SHT_REL)) ||
(s->sh_type == grub_cpu_to_le32 (SHT_RELA)))
info = grub_le_to_cpu32 (r->r_info);
/* Necessary to relocate only absolute addresses. */
- if (image_target->voidp_sizeof == 4)
+ switch (image_target->elf_target)
{
+ case EM_386:
if (ELF_R_TYPE (info) == R_386_32)
{
Elf_Addr addr;
addr, 0, current_address,
image_target);
}
- }
- else
- {
+ break;
+ case EM_X86_64:
if ((ELF_R_TYPE (info) == R_X86_64_32) ||
(ELF_R_TYPE (info) == R_X86_64_32S))
{
0, current_address,
image_target);
}
+ break;
+ case EM_IA_64:
+ switch (ELF_R_TYPE (info))
+ {
+ case R_IA64_PCREL64LSB:
+ case R_IA64_LDXMOV:
+ case R_IA64_PCREL21B:
+ case R_IA64_LTOFF_FPTR22:
+ case R_IA64_LTOFF22X:
+ case R_IA64_LTOFF22:
+ case R_IA64_GPREL22:
+ case R_IA64_SEGREL64LSB:
+ break;
+
+ case R_IA64_FPTR64LSB:
+ case R_IA64_DIR64LSB:
+#if 1
+ {
+ Elf_Addr addr;
+
+ addr = section_address + offset;
+ grub_util_info ("adding a relocation entry for 0x%llx", addr);
+ current_address
+ = SUFFIX (add_fixup_entry) (&lst,
+ GRUB_PE32_REL_BASED_DIR64,
+ addr,
+ 0, current_address,
+ image_target);
+ }
+#endif
+ break;
+ default:
+ grub_util_error ("unknown relocation type 0x%x",
+ ELF_R_TYPE (info));
+ break;
+ }
+ break;
+ default:
+ grub_util_error ("unknown machine type 0x%x", image_target->elf_target);
}
}
}
+ if (image_target->elf_target == EM_IA_64)
+ for (i = 0; i < njumpers; i++)
+ current_address = SUFFIX (add_fixup_entry) (&lst,
+ GRUB_PE32_REL_BASED_DIR64,
+ jumpers + 8 * i,
+ 0, current_address,
+ image_target);
+
current_address = SUFFIX (add_fixup_entry) (&lst, 0, 0, 1, current_address, image_target);
{
Elf_Off section_offset;
Elf_Half section_entsize;
grub_size_t kernel_size;
+ grub_size_t ia64jmp_off = 0, ia64_toff = 0, ia64_got_off = 0;
+ unsigned ia64jmpnum = 0;
Elf_Shdr *symtab_section;
+ grub_size_t got = 0;
*start = 0;
break;
}
+#ifdef MKIMAGE_ELF64
+ if (image_target->elf_target == EM_IA_64)
+ {
+ grub_size_t tramp;
+
+ *kernel_sz = ALIGN_UP (*kernel_sz, 16);
+
+ grub_ia64_dl_get_tramp_got_size (e, &tramp, &got);
+ tramp *= sizeof (struct ia64_kernel_trampoline);
+
+ ia64_toff = *kernel_sz;
+ *kernel_sz += ALIGN_UP (tramp, 16);
+
+ ia64jmp_off = *kernel_sz;
+ ia64jmpnum = SUFFIX (count_funcs) (e, symtab_section,
+ image_target);
+ *kernel_sz += 16 * ia64jmpnum;
+
+ ia64_got_off = *kernel_sz;
+ *kernel_sz += ALIGN_UP (got * sizeof (grub_uint64_t), 16);
+ }
+#endif
+
if (! symtab_section)
grub_util_error ("no symbol table");
+ }
+ else
+ {
+ *reloc_size = 0;
+ *reloc_section = NULL;
+ }
+
+ out_img = xmalloc (*kernel_sz + total_module_size);
+ if (image_target->id == IMAGE_EFI)
+ {
*start = SUFFIX (relocate_symbols) (e, sections, symtab_section,
section_vaddresses, section_entsize,
- num_sections, image_target);
+ num_sections,
+ (char *) out_img + ia64jmp_off,
+ ia64jmp_off
+ + image_target->vaddr_offset,
+ image_target);
if (*start == 0)
grub_util_error ("start symbol is not defined");
/* Resolve addresses in the virtual address space. */
- SUFFIX (relocate_addresses) (e, sections, section_addresses, section_entsize,
- num_sections, strtab, image_target);
+ SUFFIX (relocate_addresses) (e, sections, section_addresses,
+ section_entsize,
+ num_sections, strtab,
+ out_img, ia64_toff, ia64_got_off,
+ image_target);
*reloc_size = SUFFIX (make_reloc_section) (e, reloc_section,
section_vaddresses, sections,
section_entsize, num_sections,
- strtab, image_target);
- }
- else
- {
- *reloc_size = 0;
- *reloc_section = NULL;
+ strtab, ia64jmp_off
+ + image_target->vaddr_offset,
+ 2 * ia64jmpnum + got,
+ image_target);
}
- out_img = xmalloc (*kernel_sz + total_module_size);
-
for (i = 0, s = sections;
i < num_sections;
i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
PACKAGE_NAME=@PACKAGE_NAME@
PACKAGE_TARNAME=@PACKAGE_TARNAME@
PACKAGE_VERSION=@PACKAGE_VERSION@
-target_cpu=@target_cpu@
-platform=@platform@
host_os=@host_os@
-pkglibdir=${libdir}/`echo ${PACKAGE_TARNAME}/${target_cpu}-${platform} | sed ${transform}`
localedir=@datadir@/locale
-native_platform=@platform@
pkglib_DATA="moddep.lst command.lst fs.lst partmap.lst parttool.lst handler.lst video.lst crypto.lst terminal.lst"
self=`basename $0`
debug_image=
subdir=`echo /boot/grub | sed ${transform}`
pc_dir=${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/i386-pc
+ppc_dir=${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/powerpc-ieee1275
+sparc_dir=${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/sparc64-ieee1275
+i386_ieee1275_dir=${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/i386-ieee1275
+efi32_dir=${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/i386-efi
+efi64_dir=${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/x86_64-efi
+itanium_dir=${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/ia64-efi
# Usage: usage
# Print the usage.
--subdir=DIR relative subdirectory on network server
--grub-mkimage=FILE use FILE as grub-mkimage
-$self copies GRUB images into net_directory/subdir/${target_cpu}-${platform}
+$self copies GRUB images into net_directory/subdir/target_cpu-platform
Report bugs to <bug-grub@gnu.org>.
EOF
config_opt="-c ${grubdir}/load.cfg "
fi
+ prefix="/${subdir}/${platform}";
case "${platform}" in
i386-pc) mkimage_target=i386-pc-pxe;
netmodules="pxe";
- prefix="(pxe)/${subdir}/${platform}";
ext=0 ;;
+ sparc64-ieee1275) mkimage_target=sparc64-ieee1275-aout;
+ netmodules="ofnet";
+ ext=img ;;
+ *-ieee1275) mkimage_target="${platform}";
+ netmodules="ofnet";
+ ext=elf ;;
+ *-efi) mkimage_target="${platform}";
+ netmodules="efinet";
+ ext=efi ;;
*) echo Unsupported platform ${platform};
exit 1;;
esac
source ${subdir}/grub.cfg
EOF
- $grub_mkimage ${config_opt} -d "${input_dir}" -O ${mkimage_target} --output=${grubdir}/core.$ext --prefix=$prefix $modules $netmodules || exit 1
+ $grub_mkimage ${config_opt} -d "${input_dir}" -O ${mkimage_target} --output=${grubdir}/core.$ext --prefix=$prefix $modules $netmodules tftp || exit 1
echo "Netboot directory for ${platform} created. Configure your DHCP server to point to ${subdir}/${platform}/core.$ext"
}
if [ "${override_dir}" = "" ] ; then
if test -e "${pc_dir}" ; then
- process_input_dir ${pc_dir} i386-pc
+ process_input_dir "${pc_dir}" i386-pc
+ fi
+ if test -e "${ppc_dir}" ; then
+ process_input_dir "${ppc_dir}" powerpc-ieee1275
+ fi
+ if test -e "${sparc_dir}" ; then
+ process_input_dir ${sparc_dir} sparc64-ieee1275
+ fi
+ if test -e "${i386_ieee1275_dir}" ; then
+ process_input_dir "${i386_ieee1275_dir}" i386-ieee1275
+ fi
+ if test -e "${efi32_dir}" ; then
+ process_input_dir "${efi32_dir}" i386-efi
+ fi
+ if test -e "${efi64_dir}" ; then
+ process_input_dir "${efi64_dir}" x86_64-efi
+ fi
+ if test -e "${itanium_dir}" ; then
+ process_input_dir "${itanium_dir}" ia64-efi
fi
else
- process_input_dir ${override_dir} ${target_cpu}-${native_platform}
+ source "${override_dir}"/modinfo.sh
+ process_input_dir "${override_dir}" ${grub_modinfo_target_cpu}-${grub_modinfo_platform}
fi
#include <grub/types.h>
#include <grub/crypto.h>
+#include <grub/auth.h>
#include <grub/emu/misc.h>
#include <grub/util/misc.h>
#include <grub/i18n.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
-#include <termios.h>
#include "progname.h"
main (int argc, char *argv[])
{
unsigned int count = 10000, buflen = 64, saltlen = 64;
- char *pass1, *pass2;
char *bufhex, *salthex;
gcry_err_code_t gcry_err;
grub_uint8_t *buf, *salt;
ssize_t nr;
- FILE *in, *out;
- struct termios s, t;
- int tty_changed;
+ char pass1[GRUB_AUTH_MAX_PASSLEN];
+ char pass2[GRUB_AUTH_MAX_PASSLEN];
set_program_name (argv[0]);
free (buf);
grub_util_error ("out of memory");
}
-
- /* Disable echoing. Based on glibc. */
- in = fopen ("/dev/tty", "w+c");
- if (in == NULL)
- {
- in = stdin;
- out = stderr;
- }
- else
- out = in;
-
- if (tcgetattr (fileno (in), &t) == 0)
- {
- /* Save the old one. */
- s = t;
- /* Tricky, tricky. */
- t.c_lflag &= ~(ECHO|ISIG);
- tty_changed = (tcsetattr (fileno (in), TCSAFLUSH, &t) == 0);
- }
- else
- tty_changed = 0;
printf ("Enter password: ");
- pass1 = NULL;
- {
- grub_size_t n;
- nr = getline (&pass1, &n, stdin);
- }
- if (nr < 0 || !pass1)
+ if (!grub_password_get (pass1, GRUB_AUTH_MAX_PASSLEN))
{
free (buf);
free (bufhex);
free (salthex);
free (salt);
- /* Restore the original setting. */
- if (tty_changed)
- (void) tcsetattr (fileno (in), TCSAFLUSH, &s);
grub_util_error ("failure to read password");
}
- if (nr >= 1 && pass1[nr-1] == '\n')
- pass1[nr-1] = 0;
-
printf ("\nReenter password: ");
- pass2 = NULL;
- {
- grub_size_t n;
- nr = getline (&pass2, &n, stdin);
- }
- /* Restore the original setting. */
- if (tty_changed)
- (void) tcsetattr (fileno (in), TCSAFLUSH, &s);
- printf ("\n");
-
- if (nr < 0 || !pass2)
+ if (!grub_password_get (pass2, GRUB_AUTH_MAX_PASSLEN))
{
- memset (pass1, 0, strlen (pass1));
- free (pass1);
free (buf);
free (bufhex);
free (salthex);
free (salt);
grub_util_error ("failure to read password");
}
- if (nr >= 1 && pass2[nr-1] == '\n')
- pass2[nr-1] = 0;
if (strcmp (pass1, pass2) != 0)
{
- memset (pass1, 0, strlen (pass1));
- memset (pass2, 0, strlen (pass2));
- free (pass1);
- free (pass2);
+ memset (pass1, 0, sizeof (pass1));
+ memset (pass2, 0, sizeof (pass2));
free (buf);
free (bufhex);
free (salthex);
free (salt);
grub_util_error ("passwords don't match");
}
- memset (pass2, 0, strlen (pass2));
- free (pass2);
+ memset (pass2, 0, sizeof (pass2));
#if ! defined (__linux__) && ! defined (__FreeBSD__)
printf ("WARNING: your random generator isn't known to be secure\n");
{
FILE *f;
size_t rd;
- f = fopen ("/dev/random", "rb");
+ f = fopen ("/dev/urandom", "rb");
if (!f)
{
- memset (pass1, 0, strlen (pass1));
- free (pass1);
+ memset (pass1, 0, sizeof (pass1));
free (buf);
free (bufhex);
free (salthex);
if (rd != saltlen)
{
fclose (f);
- memset (pass1, 0, strlen (pass1));
- free (pass1);
+ memset (pass1, 0, sizeof (pass1));
free (buf);
free (bufhex);
free (salthex);
free (salt);
- fclose (f);
grub_util_error ("couldn't retrieve random data for salt");
}
fclose (f);
(grub_uint8_t *) pass1, strlen (pass1),
salt, saltlen,
count, buf, buflen);
- memset (pass1, 0, strlen (pass1));
- free (pass1);
+ memset (pass1, 0, sizeof (pass1));
if (gcry_err)
{
PACKAGE_NAME=@PACKAGE_NAME@
PACKAGE_TARNAME=@PACKAGE_TARNAME@
PACKAGE_VERSION=@PACKAGE_VERSION@
-target_cpu=@target_cpu@
-native_platform=@platform@
pkglib_DATA="moddep.lst command.lst fs.lst partmap.lst parttool.lst handler.lst video.lst crypto.lst terminal.lst"
self=`basename $0`
-multiboot_dir=${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/i386-multiboot
-coreboot_dir=${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/i386-coreboot
-qemu_dir=${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/i386-qemu
-pc_dir=${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/i386-pc
-efi32_dir=${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/i386-efi
-efi64_dir=${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/x86_64-efi
+multiboot_dir="${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/i386-multiboot"
+coreboot_dir="${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/i386-coreboot"
+qemu_dir="${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/i386-qemu"
+pc_dir="${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/i386-pc"
+efi32_dir="${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/i386-efi"
+efi64_dir="${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/x86_64-efi"
rom_directory=
override_dir=
-grub_mkimage=${bindir}/`echo grub-mkimage | sed ${transform}`
+grub_mkimage="${bindir}/`echo grub-mkimage | sed ${transform}`"
xorriso=xorriso
input_dir="$1"
platform="$2"
mkdir -p ${iso9660_dir}/boot/grub/${platform}
- for file in ${input_dir}/*.mod; do
+ for file in "${input_dir}/"*.mod "${input_dir}/"efiemu32.o "${input_dir}/"efiemu64.o; do
if test -f "$file"; then
cp -f "$file" ${iso9660_dir}/boot/grub/${platform}/
fi
process_input_dir ${efi64_dir} x86_64-efi
fi
else
- process_input_dir ${override_dir} ${target_cpu}-${native_platform}
+ . "${override_dir}"/modinfo.sh
+ process_input_dir "${override_dir}" ${grub_modinfo_target_cpu}-${grub_modinfo_platform}
multiboot_dir=
pc_dir=
efi32_dir=
efi64_dir=
coreboot_dir=
qemu_dir=
- case "${target_cpu}-${native_platform}" in
+ case "${grub_modinfo_target_cpu}-${grub_modinfo_platform}" in
i386-multiboot) multiboot_dir=${override_dir} ;;
i386-coreboot) coreboot_dir=${override_dir} ;;
i386-qemu) qemu_dir=${override_dir} ;;
fi
# build multiboot core.img
-make_image "${multiboot_dir}" i386-multiboot "${iso9660_dir}/boot/multiboot.img" "ata at_keyboard"
+make_image "${multiboot_dir}" i386-multiboot "${iso9660_dir}/boot/multiboot.img" "pata ahci at_keyboard"
if test -e "${efi64_dir}" || test -e "${efi32_dir}"; then
efi_dir=`mktemp -d "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` || exit 1
grub_mkisofs_arguments="${grub_mkisofs_arguments} --efi-boot efi.img"
fi
-make_image "${qemu_dir}" i386-qemu "${iso9660_dir}/boot/qemu.img" "ata at_keyboard"
+make_image "${qemu_dir}" i386-qemu "${iso9660_dir}/boot/qemu.img" "pata at_keyboard"
if [ -e "${iso9660_dir}/boot/qemu.img" ] && [ -d "${rom_directory}" ]; then
cp "${iso9660_dir}/boot/qemu.img" "${rom_directory}/qemu.img"
fi
-make_image "${coreboot_dir}" i386-coreboot "${iso9660_dir}/boot/coreboot.elf" "ata at_keyboard"
+make_image "${coreboot_dir}" i386-coreboot "${iso9660_dir}/boot/coreboot.elf" "pata ahci at_keyboard"
if [ -e "${iso9660_dir}/boot/coreboot.elf" ] && [ -d "${rom_directory}" ]; then
cp "${iso9660_dir}/boot/coreboot.elf" "${rom_directory}/coreboot.elf"
fi
--- /dev/null
+#! /bin/sh
+set -e
+
+# Make GRUB rescue image
+# Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,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/>.
+
+# Initialize some variables.
+transform="@program_transform_name@"
+
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+bindir=@bindir@
+libdir=@libdir@
+PACKAGE_NAME=@PACKAGE_NAME@
+PACKAGE_TARNAME=@PACKAGE_TARNAME@
+PACKAGE_VERSION=@PACKAGE_VERSION@
+pkglib_DATA="moddep.lst command.lst fs.lst partmap.lst parttool.lst handler.lst video.lst crypto.lst terminal.lst"
+
+self=`basename $0`
+
+source_dirrectory=
+compression=auto
+format=
+grub_mkimage=${bindir}/`echo grub-mkimage | sed ${transform}`
+source=
+
+# Usage: usage
+# Print the usage.
+usage () {
+ cat <<EOF
+Usage: $self [OPTION] SOURCE...
+Make GRUB rescue image.
+
+ -h, --help print this message and exit
+ -v, --version print the version information and exit
+ -o, --output=FILE save output in FILE [required]
+ -d, --directory=DIR use images and modules under DIR [default=%s/@platform@]
+ -O, --format=FORMAT generate an image in format
+ available formats: %s
+ -C, --compression=(xz|none|auto) choose the compression to use
+ --modules=MODULES pre-load specified modules MODULES
+ --grub-mkimage=FILE use FILE as grub-mkimage
+
+$self generates a standalone image (containing all modules) in the selected format
+
+Report bugs to <bug-grub@gnu.org>.
+EOF
+}
+
+argument () {
+ opt=$1
+ shift
+
+ if test $# -eq 0; then
+ echo "$0: option requires an argument -- '$opt'" 1>&2
+ exit 1
+ fi
+ echo $1
+}
+
+# Check the arguments.
+while test $# -gt 0
+do
+ option=$1
+ shift
+
+ case "$option" in
+ -h | --help)
+ usage
+ exit 0 ;;
+ -v | --version)
+ echo "$self (${PACKAGE_NAME}) ${PACKAGE_VERSION}"
+ exit 0 ;;
+
+ --modules)
+ modules=`argument $option "$@"`; shift ;;
+ --modules=*)
+ modules=`echo "$option" | sed 's/--modules=//'` ;;
+
+ -o | --output)
+ output_image=`argument $option "$@"`; shift ;;
+ --output=*)
+ output_image=`echo "$option" | sed 's/--output=//'` ;;
+
+ --directory | -d)
+ source_directory=`argument $option "$@"`; shift ;;
+ --directory=*)
+ source_directory=`echo "$option" | sed 's/--rom-directory=//'` ;;
+
+ --grub-mkimage)
+ grub_mkimage=`argument $option "$@"`; shift ;;
+ --grub-mkimage=*)
+ grub_mkimage=`echo "$option" | sed 's/--grub-mkimage=//'` ;;
+
+ --compression | -C)
+ compression=`argument $option "$@"`; shift ;;
+ --compression=*)
+ compression=`echo "${option}/" | sed 's/--xorriso=//'` ;;
+
+ --format | -O)
+ format=`argument $option "$@"`; shift ;;
+ --format=*)
+ format=`echo "${option}/" | sed 's/--xorriso=//'` ;;
+
+ *)
+ source="${source} ${option} $@"; break ;;
+ esac
+done
+
+if [ "x${output_image}" = x ] ; then
+ echo "output file must be given" >&2
+ usage
+ exit 1
+fi
+
+if [ "x${format}" = x ] ; then
+ echo "format must be given" >&2
+ usage
+ exit 1
+fi
+
+if [ "x$source_directory" = x ] ; then
+ cpu="`echo $format | awk -F - '{ print $1; }'`"
+ platform="`echo $format | awk -F - '{ print $2; }'`"
+ case "$platform" in
+ yeeloong | fuloong | fuloong2f | fuloong2e)
+ platform=loongson ;;
+ esac
+ case "$cpu-$platform" in
+ mips-loongson)
+ cpu=mipsel ;;
+ esac
+ source_directory="${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/$cpu-$platform"
+fi
+
+set $grub_mkimage dummy
+if test -f "$1"; then
+ :
+else
+ echo "$1: Not found." 1>&2
+ exit 1
+fi
+
+memdisk_dir="`mktemp -d "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"`" || exit 1
+mkdir -p "${memdisk_dir}"/boot/grub
+
+for file in "${source_directory}/"*.mod "${source_directory}/"efiemu32.o "${source_directory}/"efiemu64.o; do
+ if test -f "$file"; then
+ cp -f "$file" "${memdisk_dir}"/boot/grub/
+ fi
+done
+for file in ${pkglib_DATA}; do
+ if test -f "${source_directory}/${file}"; then
+ cp -f "${source_directory}/${file}" "${memdisk_dir}"/boot/grub/
+ fi
+done
+
+mkdir -p "${memdisk_dir}"/boot/grub/locale
+for file in "${source_directory}"/po/*.mo; do
+ if test -f "$file"; then
+ cp -f "$file" "${memdisk_dir}"/boot/grub/locale/
+ fi
+done
+
+for file in $source; do
+ cp -f "$file" "${memdisk_dir}"/"$file";
+done
+
+memdisk_img=`mktemp "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` || exit 1
+
+(cd "${memdisk_dir}"; tar -cf - * $source) > "${memdisk_img}"
+rm -rf "${memdisk_dir}"
+$grub_mkimage -O "${format}" -C "$compression" -d "${source_directory}" -m "${memdisk_img}" -o "$output_image" --prefix='(memdisk)/boot/grub' memdisk tar $modules
+rm -rf "${memdisk_img}"
+
+exit 0
#define BSS_SECTION 4
#define MODNAME_SECTION 5
#define MODDEPS_SECTION 6
-#define SYMTAB_SECTION 7
-#define STRTAB_SECTION 8
+#define MODLICENSE_SECTION 7
+#define SYMTAB_SECTION 8
+#define STRTAB_SECTION 9
-#define REL_SECTION 9
-#define MAX_SECTIONS 12
+#define REL_SECTION 10
+#define MAX_SECTIONS 16
#define STRTAB_BLOCK 256
grub_uint32_t offset;
static int
-insert_string (char *name)
+insert_string (const char *name)
{
int len, result;
{
int *section_map;
int i;
+ char *pe_strtab = (image + pe_chdr->symtab_offset
+ + pe_chdr->num_symbols * sizeof (struct grub_pe32_symbol));
section_map = xmalloc ((pe_chdr->num_sections + 1) * sizeof (int));
section_map[0] = 0;
for (i = 0; i < pe_chdr->num_sections; i++, pe_shdr++)
{
grub_uint32_t idx;
+ const char *name = pe_shdr->name;
- if (! strcmp (pe_shdr->name, ".text"))
+ if (name[0] == '/' && isdigit (name[1]))
+ {
+ char t[sizeof (pe_shdr->name) + 1];
+ memcpy (t, name, sizeof (pe_shdr->name));
+ t[sizeof (pe_shdr->name)] = 0;
+ name = pe_strtab + atoi (t + 1);
+ }
+
+ if (! strcmp (name, ".text"))
{
idx = TEXT_SECTION;
shdr[idx].sh_flags = SHF_ALLOC | SHF_EXECINSTR;
}
- else if (! strcmp (pe_shdr->name, ".rdata"))
+ else if (! strcmp (name, ".rdata"))
{
idx = RDATA_SECTION;
shdr[idx].sh_flags = SHF_ALLOC;
}
- else if (! strcmp (pe_shdr->name, ".data"))
+ else if (! strcmp (name, ".data"))
{
idx = DATA_SECTION;
shdr[idx].sh_flags = SHF_ALLOC | SHF_WRITE;
}
- else if (! strcmp (pe_shdr->name, ".bss"))
+ else if (! strcmp (name, ".bss"))
{
idx = BSS_SECTION;
shdr[idx].sh_flags = SHF_ALLOC | SHF_WRITE;
}
- else if (! strcmp (pe_shdr->name, ".modname"))
+ else if (! strcmp (name, ".modname"))
idx = MODNAME_SECTION;
- else if (! strcmp (pe_shdr->name, ".moddeps"))
+ else if (! strcmp (name, ".moddeps"))
idx = MODDEPS_SECTION;
+ else if (strcmp (name, ".module_license") == 0)
+ idx = MODLICENSE_SECTION;
else
{
section_map[i + 1] = -1;
if (pe_shdr->relocations_offset)
{
- char name[5 + strlen (pe_shdr->name)];
+ char relname[5 + strlen (name)];
if (num_sections >= MAX_SECTIONS)
grub_util_error ("too many sections");
- sprintf (name, ".rel%s", pe_shdr->name);
+ sprintf (relname, ".rel%s", name);
- shdr[num_sections].sh_name = insert_string (name);
+ shdr[num_sections].sh_name = insert_string (relname);
shdr[num_sections].sh_link = i;
shdr[num_sections].sh_info = idx;
num_sections++;
}
else
- shdr[idx].sh_name = insert_string (pe_shdr->name);
+ shdr[idx].sh_name = insert_string (name);
}
return section_map;
#include <grub/types.h>
#include <grub/emu/misc.h>
#include <grub/util/misc.h>
-#include <grub/util/misc.h>
#include <grub/device.h>
#include <grub/disk.h>
#include <grub/file.h>
#include <grub/env.h>
#include <grub/raid.h>
#include <grub/i18n.h>
+#include <grub/crypto.h>
+#include <grub/cryptodisk.h>
#include <stdio.h>
#include <unistd.h>
PRINT_DEVICE,
PRINT_PARTMAP,
PRINT_ABSTRACTION,
+ PRINT_CRYPTODISK_UUID
};
int print = PRINT_FS;
probe_partmap (grub_disk_t disk)
{
grub_partition_t part;
+ grub_disk_memberlist_t list = NULL, tmp;
if (disk->partition == NULL)
{
grub_util_info ("no partition map found for %s", disk->name);
- return;
}
for (part = disk->partition; part; part = part->parent)
- printf ("%s\n", part->partmap->name);
+ printf ("%s ", part->partmap->name);
+
+ /* In case of LVM/RAID, check the member devices as well. */
+ if (disk->dev->memberlist)
+ {
+ list = disk->dev->memberlist (disk);
+ }
+ while (list)
+ {
+ probe_partmap (list->disk);
+ tmp = list->next;
+ free (list);
+ list = tmp;
+ }
+}
+
+static void
+probe_cryptodisk_uuid (grub_disk_t disk)
+{
+ grub_disk_memberlist_t list = NULL, tmp;
+
+ /* In case of LVM/RAID, check the member devices as well. */
+ if (disk->dev->memberlist)
+ {
+ list = disk->dev->memberlist (disk);
+ }
+ while (list)
+ {
+ probe_cryptodisk_uuid (list->disk);
+ tmp = list->next;
+ free (list);
+ list = tmp;
+ }
+ if (disk->dev->id == GRUB_DISK_DEVICE_CRYPTODISK_ID)
+ grub_util_cryptodisk_print_uuid (disk);
}
static int
return ((struct grub_raid_array *) disk->data)->level;
}
+static void
+probe_abstraction (grub_disk_t disk)
+{
+ grub_disk_memberlist_t list = NULL, tmp;
+ int raid_level;
+
+ if (disk->dev->memberlist)
+ list = disk->dev->memberlist (disk);
+ while (list)
+ {
+ probe_abstraction (list->disk);
+
+ tmp = list->next;
+ free (list);
+ list = tmp;
+ }
+
+ if (disk->dev->id == GRUB_DISK_DEVICE_LVM_ID)
+ printf ("lvm ");
+
+ if (disk->dev->id == GRUB_DISK_DEVICE_CRYPTODISK_ID)
+ grub_util_cryptodisk_print_abstraction (disk);
+
+ raid_level = probe_raid_level (disk);
+ if (raid_level >= 0)
+ {
+ printf ("raid ");
+ if (disk->dev->raidname)
+ printf ("%s ", disk->dev->raidname (disk));
+ }
+ if (raid_level == 5)
+ printf ("raid5rec ");
+ if (raid_level == 6)
+ printf ("raid6rec ");
+}
+
static void
probe (const char *path, char *device_name)
{
#endif
}
else
- device_name = grub_guess_root_device (path);
+ {
+ grub_path = canonicalize_file_name (path);
+ device_name = grub_guess_root_device (grub_path);
+ }
if (! device_name)
grub_util_error ("cannot find a device for %s (is /dev mounted?)", path);
if (print == PRINT_ABSTRACTION)
{
- grub_disk_memberlist_t list = NULL, tmp;
- const int is_lvm = (dev->disk->dev->id == GRUB_DISK_DEVICE_LVM_ID);
- int is_raid = 0;
- int is_raid5 = 0;
- int is_raid6 = 0;
- int raid_level;
- grub_disk_t raid_disk;
-
- raid_level = probe_raid_level (dev->disk);
- if (raid_level >= 0)
- {
- is_raid = 1;
- is_raid5 |= (raid_level == 5);
- is_raid6 |= (raid_level == 6);
- raid_disk = dev->disk;
- }
-
- if ((is_lvm) && (dev->disk->dev->memberlist))
- list = dev->disk->dev->memberlist (dev->disk);
- while (list)
- {
- raid_level = probe_raid_level (list->disk);
- if (raid_level >= 0)
- {
- is_raid = 1;
- is_raid5 |= (raid_level == 5);
- is_raid6 |= (raid_level == 6);
- raid_disk = list->disk;
- }
-
- tmp = list->next;
- free (list);
- list = tmp;
- }
-
- if (is_raid)
- {
- printf ("raid ");
- if (is_raid5)
- printf ("raid5rec ");
- if (is_raid6)
- printf ("raid6rec ");
- if (raid_disk->dev->raidname)
- printf ("%s ", raid_disk->dev->raidname (raid_disk));
- }
-
- if (is_lvm)
- printf ("lvm ");
-
+ probe_abstraction (dev->disk);
printf ("\n");
+ goto end;
+ }
+ if (print == PRINT_CRYPTODISK_UUID)
+ {
+ probe_cryptodisk_uuid (dev->disk);
+ printf ("\n");
goto end;
}
if (print == PRINT_PARTMAP)
{
- grub_disk_memberlist_t list = NULL, tmp;
-
/* Check if dev->disk itself is contained in a partmap. */
probe_partmap (dev->disk);
-
- /* In case of LVM/RAID, check the member devices as well. */
- if (dev->disk->dev->memberlist)
- list = dev->disk->dev->memberlist (dev->disk);
- while (list)
- {
- probe_partmap (list->disk);
- /* LVM on RAID */
- if (list->disk->dev->memberlist)
- {
- grub_disk_memberlist_t sub_list;
-
- sub_list = list->disk->dev->memberlist (list->disk);
- while (sub_list)
- {
- probe_partmap (sub_list->disk);
- tmp = sub_list->next;
- free (sub_list);
- sub_list = tmp;
- }
- }
- tmp = list->next;
- free (list);
- list = tmp;
- }
+ printf ("\n");
goto end;
}
\n\
-d, --device given argument is a system device, not a path\n\
-m, --device-map=FILE use FILE as the device map [default=%s]\n\
- -t, --target=(fs|fs_uuid|fs_label|drive|device|partmap|abstraction)\n\
- print filesystem module, GRUB drive, system device, partition map module or abstraction module [default=fs]\n\
+ -t, --target=(fs|fs_uuid|fs_label|drive|device|partmap|abstraction|cryptodisk_uuid)\n\
+ print filesystem module, GRUB drive, system device, partition map module, abstraction module or CRYPTO UUID [default=fs]\n\
-h, --help display this message and exit\n\
-V, --version print version information and exit\n\
-v, --verbose print verbose messages\n\
print = PRINT_PARTMAP;
else if (!strcmp (optarg, "abstraction"))
print = PRINT_ABSTRACTION;
+ else if (!strcmp (optarg, "cryptodisk_uuid"))
+ print = PRINT_CRYPTODISK_UUID;
else
usage (1);
break;
/* Initialize all modules. */
grub_init_all ();
+ grub_gcry_init_all ();
grub_lvm_fini ();
grub_mdraid09_fini ();
probe (argument, NULL);
/* Free resources. */
+ grub_gcry_fini_all ();
grub_fini_all ();
grub_util_biosdisk_fini ();
/* grub-setup.c - make GRUB usable */
/*
* GRUB -- GRand Unified Bootloader
- * Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010 Free Software Foundation, Inc.
+ * Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2011 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
#include <grub/machine/kernel.h>
#include <grub/term.h>
#include <grub/i18n.h>
-#include <grub/util/raid.h>
#include <grub/util/lvm.h>
#ifdef GRUB_MACHINE_IEEE1275
#include <grub/util/ofpath.h>
core_path_dev = grub_make_system_path_relative_to_its_root (core_path_dev_full);
free (core_path_dev_full);
- /* It is a Good Thing to sync two times. */
- sync ();
- sync ();
+ grub_util_biosdisk_flush (root_dev->disk);
#define MAX_TRIES 5
grub_util_info ("error message = %s", grub_errmsg);
grub_errno = GRUB_ERR_NONE;
- sync ();
+ grub_util_biosdisk_flush (root_dev->disk);
sleep (1);
}
grub_util_error ("%s", grub_errmsg);
- /* Sync is a Good Thing. */
- sync ();
+ grub_util_biosdisk_flush (root_dev->disk);
+ grub_util_biosdisk_flush (dest_dev->disk);
free (core_path);
free (core_img);
/* Initialize all modules. */
grub_init_all ();
+ grub_gcry_init_all ();
grub_lvm_fini ();
grub_mdraid09_fini ();
arguments.dir ? : DEFAULT_DIRECTORY);
}
-#ifdef __linux__
+#if defined(__linux__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
if (grub_util_lvm_isvolume (root_dev))
must_embed = 1;
+#endif
+#ifdef __linux__
if (root_dev[0] == 'm' && root_dev[1] == 'd'
&& ((root_dev[2] >= '0' && root_dev[2] <= '9') || root_dev[2] == '/'))
{
int i;
if (arguments.device[0] == '/')
- devicelist = grub_util_raid_getmembers (arguments.device);
+ devicelist = grub_util_raid_getmembers (arguments.device, 1);
else
{
char *devname;
devname = xasprintf ("/dev/%s", dest_dev);
- devicelist = grub_util_raid_getmembers (dest_dev);
+ devicelist = grub_util_raid_getmembers (dest_dev, 1);
free (devname);
}
locale_dir=`echo ${GRUB_PREFIX}/locale | sed ${transform}`
grub_lang=`echo $LANG | cut -d . -f 1`
-. ${libdir}/grub/grub-mkconfig_lib
+. ${libdir}/@PACKAGE@/grub-mkconfig_lib
# Do this as early as possible, since other commands might depend on it.
# (e.g. the `loadfont' command might need lvm or raid modules)
if [ "x${GRUB_DEFAULT}" = "x" ] ; then GRUB_DEFAULT=0 ; fi
if [ "x${GRUB_DEFAULT}" = "xsaved" ] ; then GRUB_DEFAULT='${saved_entry}' ; fi
if [ "x${GRUB_TIMEOUT}" = "x" ] ; then GRUB_TIMEOUT=5 ; fi
-if [ "x${GRUB_GFXMODE}" = "x" ] ; then GRUB_GFXMODE=640x480 ; fi
+if [ "x${GRUB_GFXMODE}" = "x" ] ; then GRUB_GFXMODE=auto ; fi
if [ "x${GRUB_DEFAULT_BUTTON}" = "x" ] ; then GRUB_DEFAULT_BUTTON="$GRUB_DEFAULT" ; fi
if [ "x${GRUB_DEFAULT_BUTTON}" = "xsaved" ] ; then GRUB_DEFAULT_BUTTON='${saved_entry}' ; fi
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
-. ${libdir}/grub/grub-mkconfig_lib
+. ${libdir}/@PACKAGE@/grub-mkconfig_lib
CLASS="--class gnu --class os"
set -e
# grub-mkconfig helper script.
-# Copyright (C) 2006,2007,2008,2009,2010 Free Software Foundation, Inc.
+# Copyright (C) 2006,2007,2008,2009,2010,2011 Free Software Foundation, Inc.
#
# GRUB is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
exec_prefix=@exec_prefix@
bindir=@bindir@
libdir=@libdir@
-. ${libdir}/grub/grub-mkconfig_lib
+. ${libdir}/@PACKAGE@/grub-mkconfig_lib
export TEXTDOMAIN=@PACKAGE@
export TEXTDOMAINDIR=@localedir@
load_kfreebsd_module acpi true
+ for abstraction in dummy $(grub-probe -t abstraction --device ${GRUB_DEVICE}) ; do
+ case $abstraction in
+ lvm) load_kfreebsd_module geom_linux_lvm false ;;
+ esac
+ done
+
case "${kfreebsd_fs}" in
zfs)
load_kfreebsd_module opensolaris false
exec_prefix=@exec_prefix@
bindir=@bindir@
libdir=@libdir@
-. ${libdir}/grub/grub-mkconfig_lib
+. ${libdir}/@PACKAGE@/grub-mkconfig_lib
export TEXTDOMAIN=@PACKAGE@
export TEXTDOMAINDIR=@localedir@
LINUX_ROOT_DEVICE=UUID=${GRUB_DEVICE_UUID}
fi
+if [ "x`${grub_probe} --device ${GRUB_DEVICE} --target=fs 2>/dev/null || true`" = xbtrfs ]; then
+ rootsubvol="`make_system_path_relative_to_its_root /`"
+ rootsubvol="${rootsubvol#/}"
+ if [ "x${rootsubvol}" != x ]; then
+ GRUB_CMDLINE_LINUX="rootflags=subvol=${rootsubvol} ${GRUB_CMDLINE_LINUX}"
+ fi
+fi
+
linux_entry ()
{
os="$1"
EOF
fi
- if [ -z "${prepare_boot_cache}" ]; then
- prepare_boot_cache="$(prepare_grub_to_access_device ${GRUB_DEVICE_BOOT} | sed -e "s/^/\t/")"
+ cat << EOF
+ insmod gzio
+EOF
+
+ if [ x$dirname = x/ ]; then
+ if [ -z "${prepare_root_cache}" ]; then
+ prepare_root_cache="$(prepare_grub_to_access_device ${GRUB_DEVICE} | sed -e "s/^/\t/")"
+ fi
+ printf '%s\n' "${prepare_root_cache}"
+ else
+ if [ -z "${prepare_boot_cache}" ]; then
+ prepare_boot_cache="$(prepare_grub_to_access_device ${GRUB_DEVICE_BOOT} | sed -e "s/^/\t/")"
+ fi
+ printf '%s\n' "${prepare_boot_cache}"
fi
- printf '%s\n' "${prepare_boot_cache}"
message="$(gettext_printf "Loading Linux %s ..." ${version})"
cat << EOF
echo '$message'
esac
prepare_boot_cache=
+prepare_root_cache=
while [ "x$list" != "x" ] ; do
linux=`version_find_latest $list`
exec_prefix=@exec_prefix@
bindir=@bindir@
libdir=@libdir@
-. ${libdir}/grub/grub-mkconfig_lib
+. ${libdir}/@PACKAGE@/grub-mkconfig_lib
export TEXTDOMAIN=@PACKAGE@
export TEXTDOMAINDIR=@localedir@
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
-. ${libdir}/grub/grub-mkconfig_lib
+. ${libdir}/@PACKAGE@/grub-mkconfig_lib
case "`uname 2>/dev/null`" in
CYGWIN*) ;;
exec_prefix=@exec_prefix@
bindir=@bindir@
libdir=@libdir@
-. ${libdir}/grub/grub-mkconfig_lib
+. ${libdir}/@PACKAGE@/grub-mkconfig_lib
export TEXTDOMAIN=@PACKAGE@
export TEXTDOMAINDIR=@localedir@
LINUX_ROOT_DEVICE=UUID=${GRUB_DEVICE_UUID}
fi
+# Allow overriding GRUB_CMDLINE_LINUX and GRUB_CMDLINE_LINUX_DEFAULT.
+if [ "${GRUB_CMDLINE_LINUX_XEN_REPLACE}" ]; then
+ GRUB_CMDLINE_LINUX="${GRUB_CMDLINE_LINUX_XEN_REPLACE}"
+fi
+if [ "${GRUB_CMDLINE_LINUX_XEN_REPLACE_DEFAULT}" ]; then
+ GRUB_CMDLINE_LINUX_DEFAULT="${GRUB_CMDLINE_LINUX_XEN_REPLACE_DEFAULT}"
+fi
+
+if [ "x`${grub_probe} --device ${GRUB_DEVICE} --target=fs 2>/dev/null || true`" = xbtrfs ]; then
+ rootsubvol="`make_system_path_relative_to_its_root /`"
+ rootsubvol="${rootsubvol#/}"
+ if [ "x${rootsubvol}" != x ]; then
+ GRUB_CMDLINE_LINUX="rootflags=subvol=${rootsubvol} ${GRUB_CMDLINE_LINUX}"
+ fi
+fi
+
linux_entry ()
{
os="$1"
exec_prefix=@exec_prefix@
libdir=@libdir@
-. ${libdir}/grub/grub-mkconfig_lib
+. ${libdir}/@PACKAGE@/grub-mkconfig_lib
if [ "x${GRUB_DISABLE_OS_PROBER}" = "xtrue" ]; then
exit 0
grub_util_init_nls ();
- if (argc != 2)
+ if (argc != 2 || strcmp (argv[1], "--help") == 0)
{
printf("Usage: %s DEVICE\n", program_name);
return 1;
}
+ if (strcmp (argv[1], "--version") == 0)
+ {
+ printf ("%s\n", PACKAGE_STRING);
+ return 1;
+ }
of_path = grub_util_devname_to_ofpath (argv[1]);
printf("%s\n", of_path);
free (path);
free (p);
+ close (fd);
}
static void
of_path = grub_util_devname_to_ofpath (argv[1]);
printf("%s\n", of_path);
+ free (of_path);
return 0;
}
import sys
import os
import datetime
+import codecs
if len (sys.argv) < 3:
print ("Usage: %s SOURCE DESTINATION" % sys.argv[0])
print ("WARNING: %s already exists" % cipher_dir_out)
cipher_files = os.listdir (cipher_dir_in)
-conf = open (os.path.join ("grub-core", "Makefile.gcry.def"), "w")
+conf = codecs.open (os.path.join ("grub-core", "Makefile.gcry.def"), "w", "utf-8")
conf.write ("AutoGen definitions Makefile.tpl;\n\n")
+confutil = codecs.open ("Makefile.utilgcry.def", "w", "utf-8")
+confutil.write ("AutoGen definitions Makefile.tpl;\n\n")
+confutil.write ("library = {\n");
+confutil.write (" name = libgrubgcry.a;\n");
+confutil.write (" cflags = '$(CFLAGS_GCRY)';\n");
+confutil.write (" cppflags = '$(CPPFLAGS_GCRY)';\n");
+confutil.write ("\n");
chlog = ""
+modules = []
# Strictly speaking CRC32/CRC24 work on bytes so this value should be 1
# But libgcrypt uses 64. Let's keep the value for compatibility. Since
"_gcry_digest_spec_tiger" : 64,
"_gcry_digest_spec_whirlpool" : 64}
-cryptolist = open (os.path.join (cipher_dir_out, "crypto.lst"), "w")
+cryptolist = codecs.open (os.path.join (cipher_dir_out, "crypto.lst"), "w", "utf-8")
# rijndael is the only cipher using aliases. So no need for mangling, just
# hardcode it
cryptolist.write ("AES-192: gcry_rijndael\n");
cryptolist.write ("AES-256: gcry_rijndael\n");
+cryptolist.write ("ADLER32: adler32\n");
+
for cipher_file in cipher_files:
infile = os.path.join (cipher_dir_in, cipher_file)
outfile = os.path.join (cipher_dir_out, cipher_file)
nch = False
if re.match (".*\.[ch]$", cipher_file):
isc = re.match (".*\.c$", cipher_file)
- f = open (infile, "r")
- fw = open (outfile, "w")
+ f = codecs.open (infile, "r", "utf-8")
+ fw = codecs.open (outfile, "w", "utf-8")
fw.write ("/* This file was automatically imported with \n")
- fw.write (" import_gcry.py. Please don't modify it */\n");
+ fw.write (" import_gcry.py. Please don't modify it */\n")
+ fw.write ("#include <grub/dl.h>\n")
+ # Whole libgcrypt is distributed under GPLv3+ or compatible
+ if isc:
+ fw.write ("GRUB_MOD_LICENSE (\"GPLv3+\");\n")
+
ciphernames = []
mdnames = []
hold = False
skip = False
skip2 = False
ismd = False
+ iscipher = False
iscryptostart = False
iscomma = False
isglue = False
isglue = True
modname = "gcry_%s" % modname
for line in f:
+ line = line
if skip_statement:
if not re.search (";", line) is None:
skip_statement = False
sg = s.groups()[0]
cryptolist.write (("%s: %s\n") % (sg, modname))
iscryptostart = False
- if ismd:
+ if ismd or iscipher:
if not re.search (" *};", line) is None:
- if not mdblocksizes.has_key (mdname):
- print ("ERROR: Unknown digest blocksize: %s\n" % mdname)
- exit (1)
if not iscomma:
fw.write (" ,\n")
- fw.write (" .blocksize = %s\n" % mdblocksizes [mdname])
+ fw.write ("#ifdef GRUB_UTIL\n");
+ fw.write (" .modname = \"%s\",\n" % modname);
+ fw.write ("#endif\n");
+ if ismd:
+ if not (mdname in mdblocksizes):
+ print ("ERROR: Unknown digest blocksize: %s\n"
+ % mdname)
+ exit (1)
+ fw.write (" .blocksize = %s\n"
+ % mdblocksizes [mdname])
ismd = False
+ iscipher = False
iscomma = not re.search (",$", line) is None
# Used only for selftests.
m = re.match ("(static byte|static unsigned char) (weak_keys_chksum)\[[0-9]*\] =", line)
continue
m = re.match ("gcry_cipher_spec_t", line)
if isc and not m is None:
+ assert (not iscryptostart)
+ assert (not iscipher)
assert (not iscryptostart)
ciphername = line [len ("gcry_cipher_spec_t"):].strip ()
ciphername = re.match("[a-zA-Z0-9_]*",ciphername).group ()
ciphernames.append (ciphername)
+ iscipher = True
iscryptostart = True
m = re.match ("gcry_md_spec_t", line)
if isc and not m is None:
assert (not ismd)
+ assert (not iscipher)
assert (not iscryptostart)
mdname = line [len ("gcry_md_spec_t"):].strip ()
mdname = re.match("[a-zA-Z0-9_]*",mdname).group ()
% (cipher_file, cipher_file.replace ("-glue.c", ".c"))
else:
modfiles = "lib/libgcrypt-grub/cipher/%s" % cipher_file
+ modules.append (modname)
chmsg = "(GRUB_MOD_INIT(%s)): New function\n" % modname
if nch:
chlognew = "%s\n %s" % (chlognew, chmsg)
conf.write (" name = %s;\n" % modname)
for src in modfiles.split():
conf.write (" common = %s;\n" % src)
+ confutil.write (" common = grub-core/%s;\n" % src)
conf.write (" cflags = '$(CFLAGS_GCRY)';\n");
conf.write (" cppflags = '$(CPPFLAGS_GCRY)';\n");
conf.write ("};\n\n")
chlog = "%s * crypto.lst: New file.\n" % chlog
outfile = os.path.join (cipher_dir_out, "types.h")
-fw=open (outfile, "w")
+fw=codecs.open (outfile, "w", "utf-8")
fw.write ("#include <grub/types.h>\n")
fw.write ("#include <cipher_wrap.h>\n")
chlog = "%s * types.h: New file.\n" % chlog
fw.close ()
outfile = os.path.join (cipher_dir_out, "memory.h")
-fw=open (outfile, "w")
+fw=codecs.open (outfile, "w", "utf-8")
fw.write ("#include <cipher_wrap.h>\n")
chlog = "%s * memory.h: New file.\n" % chlog
fw.close ()
outfile = os.path.join (cipher_dir_out, "cipher.h")
-fw=open (outfile, "w")
+fw=codecs.open (outfile, "w", "utf-8")
fw.write ("#include <grub/crypto.h>\n")
fw.write ("#include <cipher_wrap.h>\n")
chlog = "%s * cipher.h: Likewise.\n" % chlog
fw.close ()
outfile = os.path.join (cipher_dir_out, "g10lib.h")
-fw=open (outfile, "w")
+fw=codecs.open (outfile, "w", "utf-8")
fw.write ("#include <cipher_wrap.h>\n")
chlog = "%s * g10lib.h: Likewise.\n" % chlog
fw.close ()
infile = os.path.join (cipher_dir_in, "ChangeLog")
outfile = os.path.join (cipher_dir_out, "ChangeLog")
+conf.close ();
+
+initfile = codecs.open (os.path.join (cipher_dir_out, "init.c"), "w", "utf-8")
+for module in modules:
+ initfile.write ("extern void grub_%s_init (void);\n" % module)
+ initfile.write ("extern void grub_%s_fini (void);\n" % module)
+initfile.write ("\n")
+initfile.write ("void\n")
+initfile.write ("grub_gcry_init_all (void)\n")
+initfile.write ("{\n")
+for module in modules:
+ initfile.write (" grub_%s_init ();\n" % module)
+initfile.write ("}\n")
+initfile.write ("\n")
+initfile.write ("void\n")
+initfile.write ("grub_gcry_fini_all (void)\n")
+initfile.write ("{\n")
+for module in modules:
+ initfile.write (" grub_%s_fini ();\n" % module)
+initfile.write ("}\n")
+initfile.close ()
+
+confutil.write (" common = grub-core/lib/libgcrypt-grub/cipher/init.c;\n")
+confutil.write ("};\n");
+confutil.close ();
+
-f=open (infile, "r")
-fw=open (outfile, "w")
+f=codecs.open (infile, "r", "utf-8")
+fw=codecs.open (outfile, "w", "utf-8")
dt = datetime.date.today ()
fw.write ("%04d-%02d-%02d Automatic import tool\n" % \
(dt.year,dt.month, dt.day))
/* lvm.c - LVM support for GRUB utils. */
/*
* GRUB -- GRand Unified Bootloader
- * Copyright (C) 2006,2007,2008 Free Software Foundation, Inc.
+ * Copyright (C) 2006,2007,2008,2011 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
-/* We only support LVM on Linux. */
-#ifdef __linux__
+#if defined(__linux__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
#include <grub/emu/misc.h>
#include <grub/util/misc.h>
#include <grub/util/lvm.h>
#include <string.h>
#include <sys/stat.h>
-#define LVM_DEV_MAPPER_STRING "/dev/mapper/"
-
int
grub_util_lvm_isvolume (char *name)
{
return 1;
}
-#endif /* ! __linux__ */
+#endif
#ifdef __MINGW32__
#include <windows.h>
#include <winioctl.h>
+#include "dirname.h"
#endif
#ifdef GRUB_UTIL
return 0;
}
-void sleep (int s)
-{
- Sleep (s * 1000);
-}
-
grub_int64_t
grub_util_get_disk_size (char *name)
{
HANDLE hd;
grub_int64_t size = -1LL;
+ strip_trailing_slashes(name);
hd = CreateFile (name, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
0, OPEN_EXISTING, 0, 0);
#ifdef __linux__
#include <grub/emu/misc.h>
#include <grub/util/misc.h>
-#include <grub/util/raid.h>
#include <grub/emu/getroot.h>
#include <string.h>
#include <linux/raid/md_u.h>
char **
-grub_util_raid_getmembers (const char *name)
+grub_util_raid_getmembers (const char *name, int bootable)
{
int fd, ret, i, j;
char **devicelist;
if (ret != 0)
grub_util_error ("ioctl RAID_VERSION error: %s", strerror (errno));
- if (version.major != 0 || version.minor != 90)
+ if ((version.major != 0 || version.minor != 90)
+ && (version.major != 1 || version.minor != 0)
+ && (version.major != 1 || version.minor != 1)
+ && (version.major != 1 || version.minor != 2))
+ grub_util_error ("unsupported RAID version: %d.%d",
+ version.major, version.minor);
+
+ if (bootable && (version.major != 0 || version.minor != 90))
grub_util_error ("unsupported RAID version: %d.%d",
version.major, version.minor);
devicelist[j] = NULL;
+ close (fd);
+
return devicelist;
}
exec_prefix=@exec_prefix@
libdir=@libdir@
-. ${libdir}/grub/grub-mkconfig_lib
+. ${libdir}/@PACKAGE@/grub-mkconfig_lib
grub_warn "update-grub_lib is deprecated, use grub-mkconfig_lib instead"