]> git.proxmox.com Git - grub2.git/commitdiff
ExFAT support.
authorVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Wed, 19 Oct 2011 18:19:25 +0000 (20:19 +0200)
committerVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Wed, 19 Oct 2011 18:19:25 +0000 (20:19 +0200)
* 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.

524 files changed:
.bzrignore
ChangeLog
Makefile.am
Makefile.util.def
NEWS
acinclude.m4
autogen.sh
conf/Makefile.common
config.h.in
configure.ac
docs/grub-dev.texi
docs/grub.texi
docs/man/grub-bin2h.h2m [deleted file]
docs/man/grub-editenv.h2m
docs/man/grub-emu.h2m
docs/man/grub-fstest.h2m
docs/man/grub-install.h2m
docs/man/grub-macho2img.h2m
docs/man/grub-menulst2cfg.h2m
docs/man/grub-mkconfig.h2m
docs/man/grub-mkdevicemap.h2m
docs/man/grub-mkfont.h2m
docs/man/grub-mkimage.h2m
docs/man/grub-mklayout.h2m
docs/man/grub-mknetdir.h2m
docs/man/grub-mkpasswd-pbkdf2.h2m
docs/man/grub-mkrelpath.h2m
docs/man/grub-mkrescue.h2m
docs/man/grub-mkstandalone.h2m [new file with mode: 0644]
docs/man/grub-ofpathname.h2m
docs/man/grub-pe2elf.h2m
docs/man/grub-probe.h2m
docs/man/grub-reboot.h2m
docs/man/grub-script-check.h2m
docs/man/grub-set-default.h2m
docs/man/grub-setup.h2m
gentpl.py
grub-core/Makefile.am
grub-core/Makefile.core.def
grub-core/boot/decompressor/none.c
grub-core/boot/mips/loongson/fuloong2f.S [new file with mode: 0644]
grub-core/boot/mips/loongson/fwstart.S [new file with mode: 0644]
grub-core/boot/mips/startup_raw.S
grub-core/boot/mips/yeeloong/fwstart.S [deleted file]
grub-core/bus/cs5536.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/commands/acpi.c
grub-core/commands/arc/lsdev.c [new file with mode: 0644]
grub-core/commands/blocklist.c
grub-core/commands/boot.c
grub-core/commands/cacheinfo.c [new file with mode: 0644]
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/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/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 [deleted file]
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/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/mips/loongson/lsspd.c [new file with mode: 0644]
grub-core/commands/mips/yeeloong/lsspd.c [deleted file]
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_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 [new file with mode: 0644]
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 [new file with mode: 0644]
grub-core/disk/ahci.c [new file with mode: 0644]
grub-core/disk/arc/arcdisk.c [new file with mode: 0644]
grub-core/disk/ata.c
grub-core/disk/ata_pthru.c [deleted file]
grub-core/disk/cryptodisk.c [new file with mode: 0644]
grub-core/disk/dmraid_nvidia.c
grub-core/disk/efi/efidisk.c
grub-core/disk/geli.c [new file with mode: 0644]
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 [new file with mode: 0644]
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 [new file with mode: 0644]
grub-core/disk/raid.c
grub-core/disk/raid5_recover.c
grub-core/disk/raid6_recover.c
grub-core/disk/scsi.c
grub-core/disk/usbms.c
grub-core/efiemu/main.c
grub-core/font/font.c
grub-core/font/font_cmd.c
grub-core/fs/affs.c
grub-core/fs/afs.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/i386/pc/pxe.c [deleted file]
grub-core/fs/iso9660.c
grub-core/fs/jfs.c
grub-core/fs/minix.c
grub-core/fs/minix3.c [new file with mode: 0644]
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 [new file with mode: 0644]
grub-core/fs/sfs.c
grub-core/fs/squash4.c [new file with mode: 0644]
grub-core/fs/udf.c
grub-core/fs/ufs.c
grub-core/fs/xfs.c
grub-core/fs/zfs/zfs.c
grub-core/fs/zfs/zfsinfo.c
grub-core/genmod.sh.in
grub-core/gensyminfo.sh.in
grub-core/gensymlist.sh
grub-core/gentrigtables.c
grub-core/gettext/gettext.c
grub-core/gfxmenu/gfxmenu.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/icon_manager.c
grub-core/gfxmenu/named_colors.c [deleted file]
grub-core/gfxmenu/theme_loader.c
grub-core/gfxmenu/view.c
grub-core/gfxmenu/widget-box.c
grub-core/hello/hello.c
grub-core/hook/datehook.c
grub-core/io/bufio.c
grub-core/io/gzio.c
grub-core/io/lzopio.c [new file with mode: 0644]
grub-core/io/xzio.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/elf.c
grub-core/kern/emu/cache.S [deleted file]
grub-core/kern/emu/cache.c [new file with mode: 0644]
grub-core/kern/emu/cache_s.S [new file with mode: 0644]
grub-core/kern/emu/full.c
grub-core/kern/emu/getroot.c [deleted file]
grub-core/kern/emu/hostdisk.c
grub-core/kern/emu/lite.c
grub-core/kern/emu/main.c
grub-core/kern/emu/misc.c
grub-core/kern/file.c
grub-core/kern/fs.c
grub-core/kern/i386/coreboot/init.c
grub-core/kern/i386/coreboot/startup.S
grub-core/kern/i386/efi/init.c
grub-core/kern/i386/efi/startup.S
grub-core/kern/i386/ieee1275/startup.S
grub-core/kern/i386/int.S [new file with mode: 0644]
grub-core/kern/i386/pc/init.c
grub-core/kern/i386/pc/startup.S
grub-core/kern/i386/qemu/init.c [deleted file]
grub-core/kern/i386/qemu/mmap.c
grub-core/kern/i386/qemu/startup.S
grub-core/kern/i386/realmode.S
grub-core/kern/ia64/dl.c [new file with mode: 0644]
grub-core/kern/ia64/dl_helper.c [new file with mode: 0644]
grub-core/kern/ia64/efi/init.c [new file with mode: 0644]
grub-core/kern/ia64/efi/startup.S [new file with mode: 0644]
grub-core/kern/ieee1275/cmain.c
grub-core/kern/ieee1275/init.c
grub-core/kern/ieee1275/openfw.c
grub-core/kern/main.c
grub-core/kern/mips/arc/init.c [new file with mode: 0644]
grub-core/kern/mips/cache.S
grub-core/kern/mips/cache_flush.S
grub-core/kern/mips/dl.c
grub-core/kern/mips/init.c
grub-core/kern/mips/loongson/init.c [new file with mode: 0644]
grub-core/kern/mips/qemu-mips/init.c [deleted file]
grub-core/kern/mips/qemu_mips/init.c [new file with mode: 0644]
grub-core/kern/mips/startup.S
grub-core/kern/mips/yeeloong/init.c [deleted file]
grub-core/kern/misc.c
grub-core/kern/mm.c
grub-core/kern/powerpc/ieee1275/startup.S
grub-core/kern/sparc64/ieee1275/crt0.S
grub-core/kern/sparc64/ieee1275/init.c [deleted file]
grub-core/kern/term.c
grub-core/kern/vga_init.c [new file with mode: 0644]
grub-core/kern/x86_64/efi/callwrap.S
grub-core/kern/x86_64/efi/startup.S
grub-core/lib/adler32.c [new file with mode: 0644]
grub-core/lib/arc/datetime.c [new file with mode: 0644]
grub-core/lib/cmos_datetime.c
grub-core/lib/crc.c [new file with mode: 0644]
grub-core/lib/crypto.c
grub-core/lib/efi/datetime.c
grub-core/lib/efi/halt.c
grub-core/lib/efi/reboot.c [new file with mode: 0644]
grub-core/lib/i386/reboot.c [new file with mode: 0644]
grub-core/lib/i386/reboot_trampoline.S [new file with mode: 0644]
grub-core/lib/i386/relocator.c
grub-core/lib/i386/relocator16.S
grub-core/lib/i386/setjmp.S
grub-core/lib/ia64/longjmp.S [new file with mode: 0644]
grub-core/lib/ia64/setjmp.S [new file with mode: 0644]
grub-core/lib/ieee1275/cmos.c [new file with mode: 0644]
grub-core/lib/ieee1275/datetime.c
grub-core/lib/ieee1275/reboot.c [new file with mode: 0644]
grub-core/lib/legacy_parse.c
grub-core/lib/minilzo/lzoconf.h [new file with mode: 0644]
grub-core/lib/minilzo/lzodefs.h [new file with mode: 0644]
grub-core/lib/minilzo/minilzo.c [new file with mode: 0644]
grub-core/lib/minilzo/minilzo.h [new file with mode: 0644]
grub-core/lib/mips/arc/reboot.c [new file with mode: 0644]
grub-core/lib/mips/loongson/reboot.c [new file with mode: 0644]
grub-core/lib/mips/qemu_mips/reboot.c [new file with mode: 0644]
grub-core/lib/mips/setjmp.S
grub-core/lib/pbkdf2.c
grub-core/lib/posix_wrap/ctype.h
grub-core/lib/posix_wrap/limits.h
grub-core/lib/posix_wrap/sys/types.h
grub-core/lib/powerpc/setjmp.S
grub-core/lib/reed_solomon.c
grub-core/lib/relocator.c
grub-core/lib/setjmp.S
grub-core/lib/sparc64/setjmp.S
grub-core/lib/x86_64/setjmp.S
grub-core/loader/aout.c
grub-core/loader/efi/appleloader.c
grub-core/loader/efi/chainloader.c
grub-core/loader/i386/bsd.c
grub-core/loader/i386/coreboot/chainloader.c [new file with mode: 0644]
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 [new file with mode: 0644]
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 [new file with mode: 0644]
grub-core/loader/mips/linux.c
grub-core/loader/multiboot.c
grub-core/loader/multiboot_elfxx.c
grub-core/loader/powerpc/ieee1275/linux.c
grub-core/loader/sparc64/ieee1275/linux.c
grub-core/loader/xnu.c
grub-core/mmap/mips/uppermem.c [new file with mode: 0644]
grub-core/mmap/mips/yeeloong/uppermem.c [deleted file]
grub-core/mmap/mmap.c
grub-core/modinfo.sh.in [new file with mode: 0644]
grub-core/net/arp.c [new file with mode: 0644]
grub-core/net/bootp.c [new file with mode: 0644]
grub-core/net/drivers/efi/efinet.c [new file with mode: 0644]
grub-core/net/drivers/emu/emunet.c [new file with mode: 0644]
grub-core/net/drivers/i386/pc/pxe.c [new file with mode: 0644]
grub-core/net/drivers/ieee1275/ofnet.c [new file with mode: 0644]
grub-core/net/ethernet.c [new file with mode: 0644]
grub-core/net/ip.c [new file with mode: 0644]
grub-core/net/net.c [new file with mode: 0644]
grub-core/net/netbuff.c [new file with mode: 0644]
grub-core/net/tftp.c [new file with mode: 0644]
grub-core/net/udp.c [new file with mode: 0644]
grub-core/normal/cmdline.c
grub-core/normal/main.c
grub-core/normal/menu.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 [new file with mode: 0644]
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/parser.y
grub-core/script/yylex.l
grub-core/term/arc/console.c [new file with mode: 0644]
grub-core/term/at_keyboard.c
grub-core/term/gfxterm.c
grub-core/term/i386/pc/vga_text.c
grub-core/term/ns8250.c
grub-core/term/serial.c
grub-core/term/terminfo.c
grub-core/term/usb_keyboard.c
grub-core/tests/example_functional_test.c
grub-core/tests/lib/functional_test.c
grub-core/tests/test_blockarg.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 [new file with mode: 0644]
grub-core/video/efi_gop.c
grub-core/video/efi_uga.c
grub-core/video/emu/sdl.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/radeon_fuloong2e.c [new file with mode: 0644]
grub-core/video/readers/jpeg.c
grub-core/video/readers/png.c
grub-core/video/readers/tga.c
grub-core/video/sis315_init.c [new file with mode: 0644]
grub-core/video/sis315pro.c [new file with mode: 0644]
grub-core/video/video.c
include/grub/arc/arc.h [new file with mode: 0644]
include/grub/arc/console.h [new file with mode: 0644]
include/grub/ata.h
include/grub/bsdlabel.h
include/grub/cache.h
include/grub/cmos.h
include/grub/crypto.h
include/grub/cryptodisk.h [new file with mode: 0644]
include/grub/cs5536.h
include/grub/datetime.h
include/grub/deflate.h [new file with mode: 0644]
include/grub/device.h
include/grub/disk.h
include/grub/dl.h
include/grub/efi/api.h
include/grub/efi/efi.h
include/grub/efi/pe32.h
include/grub/efi/time.h
include/grub/elf.h
include/grub/emu/export.h [new file with mode: 0644]
include/grub/emu/getroot.h
include/grub/emu/hostdisk.h
include/grub/emu/misc.h
include/grub/err.h
include/grub/fat.h [new file with mode: 0644]
include/grub/file.h
include/grub/gfxmenu_view.h
include/grub/gfxwidgets.h
include/grub/gui.h
include/grub/gui_string_util.h
include/grub/hfs.h
include/grub/i386/coreboot/memory.h
include/grub/i386/linux.h
include/grub/i386/netbsd_bootinfo.h
include/grub/i386/pc/chainloader.h
include/grub/i386/pc/int.h
include/grub/i386/pc/kernel.h
include/grub/i386/pc/pxe.h
include/grub/i386/pc/vbe.h
include/grub/i386/pc/vga.h [deleted file]
include/grub/i386/reboot.h [new file with mode: 0644]
include/grub/i386/relocator.h
include/grub/ia64/efi/memory.h [new file with mode: 0644]
include/grub/ia64/efi/time.h [new file with mode: 0644]
include/grub/ia64/kernel.h [new file with mode: 0644]
include/grub/ia64/setjmp.h [new file with mode: 0644]
include/grub/ia64/time.h [new file with mode: 0644]
include/grub/ia64/types.h [new file with mode: 0644]
include/grub/ieee1275/ieee1275.h
include/grub/kernel.h
include/grub/lib/crc.h [new file with mode: 0644]
include/grub/libgcc.h
include/grub/loader.h
include/grub/lvm.h
include/grub/mips/arc/kernel.h [new file with mode: 0644]
include/grub/mips/arc/memory.h [new file with mode: 0644]
include/grub/mips/arc/time.h [new file with mode: 0644]
include/grub/mips/kernel.h [new file with mode: 0644]
include/grub/mips/loongson.h
include/grub/mips/loongson/at_keyboard.h [new file with mode: 0644]
include/grub/mips/loongson/cmos.h [new file with mode: 0644]
include/grub/mips/loongson/ec.h [new file with mode: 0644]
include/grub/mips/loongson/kernel.h [new file with mode: 0644]
include/grub/mips/loongson/memory.h [new file with mode: 0644]
include/grub/mips/loongson/pci.h [new file with mode: 0644]
include/grub/mips/loongson/serial.h [new file with mode: 0644]
include/grub/mips/loongson/time.h [new file with mode: 0644]
include/grub/mips/memory.h
include/grub/mips/mips.h [new file with mode: 0644]
include/grub/mips/qemu-mips/kernel.h [deleted file]
include/grub/mips/qemu-mips/loader.h [deleted file]
include/grub/mips/qemu-mips/memory.h [deleted file]
include/grub/mips/qemu-mips/serial.h [deleted file]
include/grub/mips/qemu-mips/time.h [deleted file]
include/grub/mips/qemu_mips/at_keyboard.h [new file with mode: 0644]
include/grub/mips/qemu_mips/cmos.h [new file with mode: 0644]
include/grub/mips/qemu_mips/kernel.h [new file with mode: 0644]
include/grub/mips/qemu_mips/loader.h [new file with mode: 0644]
include/grub/mips/qemu_mips/memory.h [new file with mode: 0644]
include/grub/mips/qemu_mips/serial.h [new file with mode: 0644]
include/grub/mips/qemu_mips/time.h [new file with mode: 0644]
include/grub/mips/time.h
include/grub/mips/yeeloong/at_keyboard.h [deleted file]
include/grub/mips/yeeloong/cmos.h [deleted file]
include/grub/mips/yeeloong/ec.h [deleted file]
include/grub/mips/yeeloong/kernel.h [deleted file]
include/grub/mips/yeeloong/memory.h [deleted file]
include/grub/mips/yeeloong/pci.h [deleted file]
include/grub/mips/yeeloong/serial.h [deleted file]
include/grub/mips/yeeloong/time.h [deleted file]
include/grub/misc.h
include/grub/net.h
include/grub/net/arp.h [new file with mode: 0644]
include/grub/net/ethernet.h [new file with mode: 0644]
include/grub/net/ip.h [new file with mode: 0644]
include/grub/net/netbuff.h [new file with mode: 0644]
include/grub/net/udp.h [new file with mode: 0644]
include/grub/ntfs.h
include/grub/offsets.h
include/grub/raid.h
include/grub/scsi.h
include/grub/serial.h
include/grub/term.h
include/grub/terminfo.h
include/grub/types.h
include/grub/usb.h
include/grub/util/lvm.h
include/grub/util/misc.h
include/grub/util/raid.h [deleted file]
include/grub/vga.h
include/grub/video.h
include/grub/zfs/zap_leaf.h
include/grub/zfs/zio.h
po/POTFILES.in
po/README
tests/example_scripted_test.in
tests/grub_cmd_regexp.in
tests/grub_script_blanklines.in
tests/grub_script_dollar.in
tests/grub_script_expansion.in
tests/grub_script_final_semicolon.in
tests/partmap_test.in
tests/util/grub-shell-tester.in
tests/util/grub-shell.in
util/bash-completion.d/grub-completion.bash.in
util/deviceiter.c
util/getroot.c [new file with mode: 0644]
util/grub-fstest.c
util/grub-install.in
util/grub-mkconfig.in
util/grub-mkconfig_lib.in
util/grub-mkimage.c
util/grub-mkimagexx.c
util/grub-mknetdir.in
util/grub-mkpasswd-pbkdf2.c
util/grub-mkrescue.in
util/grub-mkstandalone.in [new file with mode: 0644]
util/grub-pe2elf.c
util/grub-probe.c
util/grub-setup.c
util/grub.d/00_header.in
util/grub.d/10_hurd.in
util/grub.d/10_kfreebsd.in
util/grub.d/10_linux.in
util/grub.d/10_netbsd.in
util/grub.d/10_windows.in
util/grub.d/20_linux_xen.in
util/grub.d/30_os-prober.in
util/ieee1275/grub-ofpathname.c
util/ieee1275/ofpath.c
util/import_gcry.py
util/lvm.c
util/misc.c
util/raid.c
util/update-grub_lib.in

index 55cbdaeebec34f44a31a083e92fe64aba0dc7183..6e0253c604d125f44afe9c96965c269eeb0b1e7f 100644 (file)
@@ -26,12 +26,16 @@ docs/*.info
 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
@@ -49,9 +53,28 @@ grub-probe
 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
@@ -75,6 +98,7 @@ Makefile
 *.mod
 mod-*.c
 missing
+partmap_test
 *.pf2
 *.pp
 po/*.mo
@@ -109,6 +133,7 @@ grub-core/Makefile.gcry.def
 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
@@ -135,3 +160,4 @@ widthspec.bin
 widthspec.h
 docs/stamp-1
 docs/version-dev.texi
+Makefile.utilgcry.def
index dbcbb96519d3b7bca86fda0f9aa15d8988904a44..d6641921694954cfe7baf838dc4ff15e3dc2f6ec 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
+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>
 
index 60e041a8d3a5d64f767daaa278100dffd62c0e27..c5f486e0d52529730b82a6a956550b7e79684247 100644 (file)
@@ -1,4 +1,4 @@
-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
@@ -147,28 +147,28 @@ linux.init.i386: $(srcdir)/grub-core/tests/boot/linux.init-i386.S
        $(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 $@
index a1d00a683e8464dba1cffa4df617c2ad97336aa4..759e164d26aedc4b4213c627b4d30af3ddb405e4 100644 (file)
@@ -9,7 +9,8 @@ library = {
   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;
@@ -20,12 +21,20 @@ library = {
   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;
@@ -34,7 +43,7 @@ library = {
   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;
@@ -61,11 +70,14 @@ library = {
   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;
@@ -75,15 +87,12 @@ library = {
   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;
@@ -92,6 +101,7 @@ library = {
   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;
@@ -99,16 +109,21 @@ library = {
   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 = {
@@ -120,6 +135,7 @@ program = {
   extra_dist = util/grub-mkimagexx.c;
 
   ldadd = libgrubmods.a;
+  ldadd = libgrubgcry.a;
   ldadd = libgrubkern.a;
   ldadd = grub-core/gnulib/libgnu.a;
   ldadd = '$(LIBLZMA)';
@@ -134,9 +150,10 @@ program = {
   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 = {
@@ -146,6 +163,7 @@ 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)';
@@ -158,6 +176,7 @@ program = {
   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)';
@@ -170,6 +189,7 @@ program = {
   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)';
@@ -190,6 +210,7 @@ program = {
   common = util/grub-pe2elf.c;
 
   ldadd = libgrubmods.a;
+  ldadd = libgrubgcry.a;
   ldadd = libgrubkern.a;
   ldadd = grub-core/gnulib/libgnu.a;
   ldadd = '$(LIBINTL)';
@@ -208,9 +229,10 @@ program = {
   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 = {
@@ -222,6 +244,7 @@ program = {
   cflags = '$(freetype_cflags)';
 
   ldadd = libgrubmods.a;
+  ldadd = libgrubgcry.a;
   ldadd = libgrubkern.a;
   ldadd = grub-core/gnulib/libgnu.a;
   ldadd = '$(freetype_libs)';
@@ -242,6 +265,7 @@ program = {
   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)';
@@ -254,6 +278,7 @@ program = {
   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)';
@@ -264,7 +289,6 @@ program = {
   installdir = sbin;
   mansection = 8;
   common = util/grub-setup.c;
-  common = util/raid.c;
   common = util/lvm.c;
   common = grub-core/lib/reed_solomon.c;
 
@@ -272,6 +296,7 @@ program = {
 
   ldadd = libgrubmods.a;
   ldadd = libgrubkern.a;
+  ldadd = libgrubgcry.a;
   ldadd = grub-core/gnulib/libgnu.a;
   ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)';
 
@@ -282,10 +307,12 @@ program = {
 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)';
@@ -300,6 +327,7 @@ program = {
   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)';
@@ -382,13 +410,20 @@ script = {
   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;
@@ -610,6 +645,7 @@ program = {
   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)';
@@ -623,6 +659,7 @@ program = {
   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)';
diff --git a/NEWS b/NEWS
index 36e3f25bf7481611ad5d19ccbf97a0aa9e934d3f..2a93c25269386385f0068cb65fc903edcc0e00d5 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -29,7 +29,7 @@ New in 1.99:
 
 * 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
@@ -83,10 +83,6 @@ New in 1.99:
 
 * 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.
index 7c38155d47ff52a7ba43a31b18365ca6aeebc815..5c623baeefd0237c237d912a6aae55a41a7e23ae 100644 (file)
@@ -316,14 +316,14 @@ fi
 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
@@ -346,7 +346,9 @@ AC_DEFUN([grub_CHECK_STACK_PROTECTOR],[
 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]
@@ -364,7 +366,9 @@ AC_DEFUN([grub_CHECK_STACK_ARG_PROBE],[
 [# 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'?
@@ -399,7 +403,7 @@ AC_DEFUN([grub_CHECK_PIE],[
 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;
@@ -407,7 +411,7 @@ int main() {
 #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?
index d14707aadd5641b7e4a8b548cca6f298688b355c..db719cd1decaed9f75dfbe70a95087c9d0d9aacf 100755 (executable)
@@ -26,7 +26,7 @@ if [ "x${GRUB_CONTRIB}" != x ]; then
   [ "${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
index 5aa13cdd629595ade4a1b920f111577dd1168073..751188b26160c528ec8b4769fc5e260ea37bfb79 100644 (file)
@@ -25,13 +25,13 @@ endif
 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
index 3974ad7d5ef9be7de235bb027d8fb452cb040850..92d7a07f268cc03760d3642e16220ddc038537cd 100644 (file)
@@ -36,6 +36,8 @@
 #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)))
index f9e974bcad7667299ae52b93594a1022e564186a..6aafdf13db7a24ce8f14383b9180cf570c49ffda 100644 (file)
@@ -32,7 +32,7 @@ dnl type, so there is no conflict. Variables with the prefix "TARGET_"
 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])
 
@@ -72,7 +72,7 @@ case "$target_cpu" in
   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)
@@ -96,7 +96,9 @@ if test "x$with_platform" = x; then
     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
@@ -122,8 +124,15 @@ case "$target_cpu"-"$platform" in
   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
@@ -156,14 +165,19 @@ case "$platform" in
   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"
@@ -219,8 +233,8 @@ for ext in pcf pcf.gz bdf bdf.gz ttf ttf.gz; do
   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])
@@ -398,23 +412,6 @@ if test "x$grub_cv_cc_fno_dwarf2_cfi_asm" = xyes; then
   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"
@@ -590,7 +587,7 @@ CFLAGS="$CFLAGS -Wl,--defsym,abort=main"
 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"
@@ -703,6 +700,17 @@ AC_ARG_ENABLE([mm-debug],
               [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)])])
@@ -852,6 +860,9 @@ enable_grub_mkfont=yes
 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])
@@ -945,16 +956,18 @@ AC_SUBST(NEED_REGISTER_FRAME_INFO)
 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])
@@ -971,24 +984,29 @@ AM_CONDITIONAL([COND_HAVE_FONT_SOURCE], [test x$FONT_SOURCE != x])
 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
 
@@ -1033,6 +1051,11 @@ echo With memory debugging: Yes
 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
index a45b8b1981e8e88ea543e072bff09a623cce4950..93d2bdb4dd63367a3892f86fe31ce894b382f5d8 100644 (file)
@@ -451,7 +451,7 @@ request. Instead, please subscribe to the mailing list, and communicate first
 @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
index 0c59975cdb8eb6d5b9f9da131de14f4cc4f51cae..2c6b3802ea3290ae4a95de9c4880be53b790ee54 100644 (file)
@@ -528,21 +528,15 @@ system (@pxref{Obtaining and Building GRUB}). You can do this either
 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
@@ -556,27 +550,18 @@ the @dfn{boot directory}.
 @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}
@@ -588,37 +573,22 @@ Likewise, under GNU/Hurd, this has the same effect:
 # @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:
@@ -1199,8 +1169,14 @@ NetBSD.
 
 @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
@@ -1227,7 +1203,8 @@ listed in @file{/boot/grub/video.lst}.
 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.
@@ -1486,14 +1463,14 @@ reside anywhere on the file system, and may be removed after running
 @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
@@ -3089,6 +3066,8 @@ you forget a command, you can run the command @command{help}
 * 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
@@ -3545,6 +3524,34 @@ name syntax}), then list the contents of that directory.
 @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
 
@@ -3936,6 +3943,7 @@ X86 support is summarised in the following table. ``Yes'' means that the kernel
 @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)
@@ -3960,6 +3968,7 @@ X86 support is summarised in the following table. ``Yes'' means that the kernel
 @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)
@@ -3984,6 +3993,7 @@ X86 support is summarised in the following table. ``Yes'' means that the kernel
 @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
@@ -4008,6 +4018,7 @@ X86 support is summarised in the following table. ``Yes'' means that the kernel
 @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)
@@ -4082,7 +4093,7 @@ GRUB's normal start-up procedure involves setting the @samp{prefix}
 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.
 
@@ -4097,6 +4108,8 @@ device), then you can correct this and enter normal mode manually:
 @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)
@@ -4163,15 +4176,28 @@ Print a summary of the command-line options and exit.
 @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
@@ -4305,11 +4331,11 @@ how to get the latest version.
 @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:
 
diff --git a/docs/man/grub-bin2h.h2m b/docs/man/grub-bin2h.h2m
deleted file mode 100644 (file)
index ef463f3..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-[NAME]
-grub-bin2h \- convert a binary file to a C header
index efbd790709b0462a3ddded44f50d068e61dde80d..3859d3d4c4f2236af6d32f7da6b1c3efe92eba9e 100644 (file)
@@ -1,2 +1,5 @@
 [NAME]
 grub-editenv \- edit GRUB environment block
+[SEE ALSO]
+.BR grub-reboot (8),
+.BR grub-set-default (8)
index 09a1f88c17319c5591bac56133e2d8e73ba2fc69..ef1c000656ad1f978f18847d2d68d86e67d9db8c 100644 (file)
@@ -1,2 +1,6 @@
 [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.
index be39429b519422d3570eb1eab29abcc765b5b79b..9676b159afdaeda8d106bb2404f2d413ffb6a8ec 100644 (file)
@@ -1,2 +1,4 @@
 [NAME]
 grub-fstest \- debug tool for GRUB filesystem drivers
+[SEE ALSO]
+.BR grub-probe (8)
index 65252155c24d3831f699be215ded329fc645d266..2de371a3fddd2516df9c20b748d8b76ab3c0b286 100644 (file)
@@ -1,2 +1,7 @@
 [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)
index 412bf926acb4ada5c72ae083a05dbddeea42a4c6..d79aaeed8f9c12f4bf569d1f8790ef9053f31f16 100644 (file)
@@ -1,2 +1,4 @@
 [NAME]
 grub-macho2img \- convert Mach-O to raw image
+[SEE ALSO]
+.BR grub-mkimage (1)
index 0c0570f27bab85966ec27e313659a3cb8d0ca340..c2e0055ed7e71f09bc573ab9a656107f69d1c747 100644 (file)
@@ -1,3 +1,4 @@
 [NAME]
 grub-menulst2cfg \- transform legacy menu.lst into grub.cfg
-
+[SEE ALSO]
+.BR grub-mkconfig (8)
index b0d33ec613fb034c7c737f6430e57e4880d09154..9b42f81301099a1c9dc69cf73ca2e74d83274282 100644 (file)
@@ -1,2 +1,4 @@
 [NAME]
 grub-mkconfig \- generate a GRUB configuration file
+[SEE ALSO]
+.BR grub-install (8)
index 8ab34ac866aa3a6b22c49f483d515fe0e404cf7e..3ef8e971276ccc8b5787c46070e1f4b95226cf62 100644 (file)
@@ -1,2 +1,4 @@
 [NAME]
 grub-mkdevicemap \- generate a GRUB device map file automatically
+[SEE ALSO]
+.BR grub-install (8)
index d8580186f45598b85c9065882dd66bf4cb6417c8..d46fe600eca221521bdbf5552e4101b3cf736adc 100644 (file)
@@ -1,2 +1,4 @@
 [NAME]
 grub-mkfont \- make GRUB font files
+[SEE ALSO]
+.BR grub-mkconfig (8)
index 71f270940c30a3155fe094f1a5e27f640f1d7c42..ca08b0c5c4764cdd305c5d55580c91c3f4612f75 100644 (file)
@@ -1,2 +1,7 @@
 [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)
index e0ae9dedb663324728c3d5c3adfd1fd8e73d1a46..1e43409c0ab83a3e07e3eeead254ff0777c27bf0 100644 (file)
@@ -1,2 +1,10 @@
 [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)
index 26defe8762efbe59a3b691ef44755f699602ec47..a2ef13ec111f7b1ee9dab535f068b0fe6c092589 100644 (file)
@@ -1,2 +1,4 @@
 [NAME]
 grub-mknetdir \- prepare a GRUB netboot directory.
+[SEE ALSO]
+.BR grub-mkimage (1)
index 5b2b2ef7fe3e7d46d25b10a6669822a6ff07f035..4d202f3da7e9f8bc8337807f0caf5b772e850734 100644 (file)
@@ -1,2 +1,4 @@
 [NAME]
 grub-mkpasswd-pbkdf2 \- generate hashed password for GRUB
+[SEE ALSO]
+.BR grub-mkconfig (8)
index ccc0880fa346672a6da8da669b7df6a7cca8c87e..d01f3961e3f64a3dc5abfcfb54a4798c8e58d3e8 100644 (file)
@@ -1,2 +1,4 @@
 [NAME]
 grub-mkrelpath \- make a system path relative to its root
+[SEE ALSO]
+.BR grub-probe (8)
index 5e92e0d9955f56a589da4fa12e193910b7b0882c..a427f02e3c6f2f573ca4a80efb4b5132616768e6 100644 (file)
@@ -1,2 +1,4 @@
 [NAME]
 grub-mkrescue \- make a GRUB rescue image
+[SEE ALSO]
+.BR grub-mkimage (1)
diff --git a/docs/man/grub-mkstandalone.h2m b/docs/man/grub-mkstandalone.h2m
new file mode 100644 (file)
index 0000000..c773139
--- /dev/null
@@ -0,0 +1,4 @@
+[NAME]
+grub-mkstandalone \- make a memdisk-based GRUB image
+[SEE ALSO]
+.BR grub-mkimage (1)
index f07158cb34e1da1ba1a866177875d4ae4f2bdd3d..74b43eea039972fad8aa908806dfaa9ea2dec24c 100644 (file)
@@ -1,2 +1,4 @@
 [NAME]
 grub-ofpathname \- find OpenBOOT path for a device
+[SEE ALSO]
+.BR grub-probe (8)
index 3fdb88b430542a1c3c6ed3b8db5924ce10f75082..7ca29bd703c6695444fb5415e8abcb3370ef5cde 100644 (file)
@@ -1,2 +1,4 @@
 [NAME]
 grub-pe2elf \- convert PE image to ELF
+[SEE ALSO]
+.BR grub-mkimage (1)
index 817ba8ef680a4ebbac2d416997df906768f09e48..6e1ffdcf937ce9299b0218cc7d15bde7d4a2ff71 100644 (file)
@@ -1,2 +1,4 @@
 [NAME]
 grub-probe \- probe device information for GRUB
+[SEE ALSO]
+.BR grub-fstest (1)
index 957e4b7979608da301be6fc41a7848acf6d3f952..e4acace65cea72bbd69c6d1ab360c52d87eecaba 100644 (file)
@@ -1,2 +1,5 @@
 [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)
index 39c0a3ef6e8d86f59ccff08ab4d4ea0e419f5c0b..3653682671a33edd24eac2acde98f0bac7072e08 100644 (file)
@@ -1,2 +1,4 @@
 [NAME]
 grub-script-check \- check grub.cfg for syntax errors
+[SEE ALSO]
+.BR grub-mkconfig (8)
index dd0793cfdf67ae562ed62ac490582041377011fc..7945001c15432116f4b91b676347b7f24cabcae4 100644 (file)
@@ -1,2 +1,5 @@
 [NAME]
 grub-set-default \- set the saved default boot entry for GRUB
+[SEE ALSO]
+.BR grub-reboot (8),
+.BR grub-editenv (1)
index e70e465a468396c3c7478a63d8dccff5671c5b7c..eebe3ef3897324e5d10f523f6a358f296ab0768a 100644 (file)
@@ -1,2 +1,6 @@
 [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)
index a42a6066748b22c4dca2b3a6c81eb74299fd6400..af210a04015c4e5cf24a215be07ba8813cc01dd1 100644 (file)
--- a/gentpl.py
+++ b/gentpl.py
@@ -6,8 +6,9 @@
 
 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 = {}
 
@@ -17,29 +18,31 @@ GROUPS["common"]   = GRUB_PLATFORMS[:]
 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)
 
@@ -180,6 +183,17 @@ def foreach_platform_specific_value(platform, suffix, nonetag, closure):
     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:
@@ -238,14 +252,22 @@ def foreach_enabled_platform(closure):
 #    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):
@@ -258,18 +280,69 @@ def platform_values(platform, suffix):
 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.
@@ -486,7 +559,6 @@ def script_rules():
 def data_rules():
     return rules("data", data)
 
-print "[+ AutoGen5 template +]\n"
 a = module_rules()
 b = kernel_rules()
 c = image_rules()
@@ -496,11 +568,28 @@ f = script_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)
index 94f7f3ffe7483aaedfca73654a228780ada91bb7..f300146351caf13be30bfa364151b2c18a69ae9d 100644 (file)
@@ -1,4 +1,4 @@
-AUTOMAKE_OPTIONS = subdir-objects
+AUTOMAKE_OPTIONS = subdir-objects -Wno-portability
 
 DEPDIR=.deps-core
 
@@ -79,6 +79,7 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/term.h
 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/time.h
 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/mm_private.h
 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/boot.h
+KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/net.h
 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/libgcc.h
 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/memory.h
 
@@ -99,10 +100,12 @@ endif
 
 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
@@ -125,7 +128,39 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/disk.h
 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
@@ -145,6 +180,11 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.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
@@ -163,6 +203,7 @@ endif
 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
@@ -305,6 +346,7 @@ CLEANFILES += config.log syminfo.lst moddep.lst
 $(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
index 3ec41ac7f8c813ff991c5f1eadf8313270ce57d4..7cb83924ce984e35abe6b3f4ab3815ac15483c49 100644 (file)
@@ -12,14 +12,26 @@ script = {
   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';
@@ -32,11 +44,13 @@ kernel = {
   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)';
@@ -48,7 +62,7 @@ kernel = {
   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;
 
@@ -77,11 +91,10 @@ kernel = {
   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;
@@ -89,6 +102,7 @@ kernel = {
   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;
@@ -105,18 +119,24 @@ kernel = {
 
   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;
@@ -124,7 +144,7 @@ kernel = {
   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;
 
@@ -134,43 +154,55 @@ kernel = {
   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;
@@ -178,6 +210,7 @@ kernel = {
   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;
@@ -186,6 +219,7 @@ kernel = {
 
   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;
@@ -295,12 +329,12 @@ image = {
   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;
@@ -311,10 +345,12 @@ image = {
   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;
@@ -322,10 +358,18 @@ image = {
 
 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 = {
@@ -349,18 +393,22 @@ 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 = {
@@ -395,17 +443,29 @@ 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 = {
@@ -440,12 +500,12 @@ module = {
   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;
@@ -456,7 +516,7 @@ module = {
 
   common = commands/lsacpi.c;
 
-  enable = x86_efi;
+  enable = efi;
   enable = i386_pc;
   enable = i386_coreboot;
   enable = i386_multiboot;
@@ -467,7 +527,7 @@ module = {
 
   common = commands/efi/lsefisystab.c;
 
-  enable = x86_efi;
+  enable = efi;
 };
 
 module = {
@@ -475,7 +535,7 @@ module = {
 
   common = commands/efi/lssal.c;
 
-  enable = x86_efi;
+  enable = efi;
 };
 
 module = {
@@ -483,7 +543,7 @@ module = {
 
   common = commands/efi/lsefimmap.c;
 
-  enable = x86_efi;
+  enable = efi;
 };
 
 module = {
@@ -546,8 +606,9 @@ 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 = {
@@ -562,15 +623,30 @@ 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;
@@ -581,6 +657,7 @@ module = {
   common = commands/hdparm.c;
   common = lib/hexdump.c;
   enable = pci;
+  enable = mips_qemu_mips;
 };
 
 module = {
@@ -601,8 +678,9 @@ 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 = {
@@ -664,22 +742,11 @@ 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;
@@ -738,8 +805,6 @@ module = {
   name = usbtest;
   common = commands/usbtest.c;
   enable = usb;
-  enable = emu;
-  emu_condition = COND_GRUB_EMU_USB;
 };
 
 module = {
@@ -767,6 +832,22 @@ 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;
@@ -811,12 +892,20 @@ module = {
   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 = {
@@ -829,8 +918,6 @@ module = {
   name = usbms;
   common = disk/usbms.c;
   enable = usb;
-  enable = emu;
-  emu_condition = COND_GRUB_EMU_USB;
 };
 
 module = {
@@ -906,6 +993,9 @@ 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 = {
@@ -963,6 +1053,11 @@ module = {
   common = fs/minix2.c;
 };
 
+module = {
+  name = minix3;
+  common = fs/minix3.c;
+};
+
 module = {
   name = nilfs2;
   common = fs/nilfs2.c;
@@ -983,11 +1078,21 @@ module = {
   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;
@@ -1028,7 +1133,7 @@ module = {
 
 module = {
   name = pxe;
-  i386_pc = fs/i386/pc/pxe.c;
+  i386_pc = net/drivers/i386/pc/pxe.c;
   enable = i386_pc;
 };
 
@@ -1055,7 +1160,6 @@ module = {
   common = gfxmenu/gui_progress_bar.c;
   common = gfxmenu/gui_util.c;
   common = gfxmenu/gui_string_util.c;
-  common = gfxmenu/named_colors.c;
 };
 
 module = {
@@ -1101,7 +1205,7 @@ 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;
@@ -1118,9 +1222,13 @@ module = {
 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;
 };
 
@@ -1132,6 +1240,7 @@ module = {
   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 = {
@@ -1165,6 +1274,12 @@ module = {
   enable = i386_pc;
 };
 
+module = {
+  name = freedos;
+  i386_pc = loader/i386/pc/freedos.c;
+  enable = i386_pc;
+};
+
 module = {
   name = multiboot2;
   cppflags = "-DGRUB_USE_MULTIBOOT2";
@@ -1190,6 +1305,7 @@ module = {
   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;
 };
@@ -1209,16 +1325,19 @@ module = {
 
 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 = {
@@ -1230,12 +1349,13 @@ 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 = {
@@ -1309,6 +1429,11 @@ module = {
   common = partmap/sun.c;
 };
 
+module = {
+  name = part_dvh;
+  common = partmap/dvh.c;
+};
+
 module = {
   name = part_bsd;
   common = partmap/bsdlabel.c;
@@ -1341,10 +1466,7 @@ module = {
   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 = {
@@ -1368,8 +1490,10 @@ 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 = {
@@ -1419,14 +1543,15 @@ 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 = {
@@ -1446,8 +1571,10 @@ 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 = {
@@ -1462,13 +1589,14 @@ 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 = {
@@ -1483,6 +1611,40 @@ 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;
@@ -1506,6 +1668,14 @@ module = {
   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;
@@ -1522,3 +1692,19 @@ module = {
   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;
+};
index 44f56ce90b4525d75804eb39e98b58bc62ad9e45..911e861e3ea1c55e3d6480143330e116d0ae7deb 100644 (file)
@@ -25,6 +25,9 @@ grub_decompress_core (void *src, void *dest, unsigned long n,
   char *d = (char *) dest;
   const char *s = (const char *) src;
 
+  if (d == s)
+    return;
+
   if (d < s)
     while (n--)
       *d++ = *s++;
diff --git a/grub-core/boot/mips/loongson/fuloong2f.S b/grub-core/boot/mips/loongson/fuloong2f.S
new file mode 100644 (file)
index 0000000..a88c81e
--- /dev/null
@@ -0,0 +1,2 @@
+#define FULOONG2F 1
+#include "fwstart.S"
diff --git a/grub-core/boot/mips/loongson/fwstart.S b/grub-core/boot/mips/loongson/fwstart.S
new file mode 100644 (file)
index 0000000..7ed5d30
--- /dev/null
@@ -0,0 +1,749 @@
+/*
+ *  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:
index c41ce8257925e2cdbaa6f198c562dd928e095fe4..aefd387b6c1e550af7ab158800e3325eb5e82dac 100644 (file)
@@ -20,6 +20,7 @@
 #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
@@ -43,21 +44,45 @@ compressed_size:
        . = _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:       
@@ -72,11 +97,19 @@ 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       
@@ -120,8 +153,49 @@ busclockstr:       .asciiz "busclock="
 cpuclockstr:   .asciiz "cpuclock="
 memsizestr:    .asciiz "memsize="
 highmemsizestr:        .asciiz "highmemsize="
+machtype_yeeloong_str1:        .asciiz "machtype=8.9"
+machtype_yeeloong_str2:        .asciiz "machtype=lemote-yeeloong-"
+machtype_fuloong2f_str:        .asciiz "machtype=lemote-fuloong-2f"
+machtype_fuloong2e_str:        .asciiz "machtype=lemote-fuloong-2e"
+pmon_yeeloong_str:     .asciiz "PMON_VER=LM8"
+pmon_fuloong2f_str:    .asciiz "PMON_VER=LM6"
+pmon_yeeloong_verstr:  .asciiz "Version=LM8"
+pmon_fuloong2f_verstr: .asciiz "Version=LM6"
        .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)
@@ -150,6 +224,13 @@ argdone:
        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)
@@ -159,8 +240,7 @@ argdone:
        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
@@ -170,9 +250,11 @@ argdone:
        */
        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
diff --git a/grub-core/boot/mips/yeeloong/fwstart.S b/grub-core/boot/mips/yeeloong/fwstart.S
deleted file mode 100644 (file)
index 9e81df1..0000000
+++ /dev/null
@@ -1,631 +0,0 @@
-/*
- *  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
index 088f4dfc1d52cf6da4e46a0c7ffd2a9661e29848..1aae7852e1480f89610238e538014a966236e789 100644 (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)
@@ -213,26 +220,6 @@ grub_cs5536_read_spd (grub_port_t smbbase, grub_uint8_t dev,
   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)
@@ -273,17 +260,6 @@ set_p2d (grub_pci_device_t dev, int num, int dest, grub_uint32_t start)
 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);
@@ -295,11 +271,27 @@ grub_cs5536_init_geode (grub_pci_device_t dev)
                         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,
index 11101d42b77bf316f91f351fa46fd57b505306e7..f007ec33aaed7fff9c0608de4107dbd11b993b5a 100644 (file)
 #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)
 {
@@ -99,16 +115,6 @@ grub_pci_iterate (grub_pci_iteratefunc_t hook)
                    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;
 
index 7d52decb2969fe05c6a0c2384183a195e84b6a41..38c5f01f1025430bf581c5154a3d71d95c7313a9 100644 (file)
@@ -24,6 +24,8 @@
 #include <grub/usb.h>
 #include <grub/dl.h>
 
+GRUB_MOD_LICENSE ("GPLv3+");
+
 \f
 static struct grub_usb_controller_dev usb_controller =
 {
index 8adaee6e0c2915f94358be7f9263c6dcd181f724..b659c3f626b1ddb086ff4b7bbb28981f6c635c52 100644 (file)
@@ -29,6 +29,8 @@
 #include <grub/cs5536.h>
 #include <grub/loader.h>
 
+GRUB_MOD_LICENSE ("GPLv3+");
+
 struct grub_ohci_hcca
 {
   /* Pointers to Interrupt Endpoint Descriptors.  Not used by
@@ -452,10 +454,12 @@ grub_ohci_pci_iter (grub_pci_device_t dev,
 
  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;
@@ -1422,18 +1426,22 @@ static struct grub_usb_controller_dev usb_controller =
   .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);
 }
index ee8794de0900fce7b2697392025fff61fb7b48dd..55d1884ccefc79042332393324904530bf6b3ca2 100644 (file)
@@ -18,6 +18,9 @@
 
 #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)
index bd1713b27c046d3b04c794ce21a5cf65de377c70..07ac7ac521d92c483091d91e6c0ad03144c3a463 100644 (file)
@@ -24,6 +24,8 @@
 #include <grub/usb.h>
 #include <grub/usbserial.h>
 
+GRUB_MOD_LICENSE ("GPLv3+");
+
 enum
   {
     GRUB_FTDI_MODEM_CTRL = 0x01,
index 9e3b9ae7eb948e38e8546878a0eefae6fee3ed10..b9954116ba2b945d4e77a5eca7afb60d85fd6f33 100644 (file)
@@ -24,6 +24,8 @@
 #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)
index 71142846b005fd2ca74596de33bcc8673f191bb9..260b7e8764906b6c0cecccf9f7579b6928d069f9 100644 (file)
@@ -26,6 +26,8 @@
 #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
 
@@ -179,6 +203,11 @@ grub_uhci_pci_iter (grub_pci_device_t dev,
   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);
@@ -193,6 +222,19 @@ grub_uhci_pci_iter (grub_pci_device_t dev,
 
   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)
@@ -250,9 +292,6 @@ grub_uhci_pci_iter (grub_pci_device_t dev,
   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.  */
@@ -283,7 +322,8 @@ grub_uhci_pci_iter (grub_pci_device_t dev,
   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");
index 70173b7ea8ee594aa4bc440a9269a135a6ef4266..cde57ced8750edae7c2bd573638fb490c0fb16df 100644 (file)
@@ -24,6 +24,8 @@
 #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;
 
@@ -183,6 +185,12 @@ grub_usb_device_initialize (grub_usb_device_t dev)
   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;
index 82bb2da1cd2dc676f115ff892726d589a9cae866..b59f2f51d75533513cf041406559f30f10bf3148 100644 (file)
@@ -215,6 +215,8 @@ attach_root_port (struct grub_usb_hub *hub, int portno,
     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;
@@ -350,8 +352,8 @@ poll_nonroot_hub (grub_usb_device_t dev)
                                  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;
index 4f03997e0df80f7cbf0d350dad20384038b71f90..8f44296277262e992dc38d580ab107a6d586bf70 100644 (file)
@@ -33,6 +33,8 @@
 #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."),
diff --git a/grub-core/commands/arc/lsdev.c b/grub-core/commands/arc/lsdev.c
new file mode 100644 (file)
index 0000000..5d4b0cd
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ *  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);
+}
index 4651fb32ae56a321933c623c8d620b486822f355..5eb12e4348931a975564855bf89e31576de96d9e 100644 (file)
@@ -26,6 +26,8 @@
 #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)
index 1ec1e6f77f75c1425c4ca8d261667ad94190d6ca..7714011bfc45be4d073a485b9c9823fed96ab6d6 100644 (file)
@@ -25,6 +25,8 @@
 #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;
diff --git a/grub-core/commands/cacheinfo.c b/grub-core/commands/cacheinfo.c
new file mode 100644 (file)
index 0000000..771763c
--- /dev/null
@@ -0,0 +1,58 @@
+/* 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);
+}
index 79ecf75c7009a998af0387e39d0f10dae8c27e60..9be6cbc8ff99e1e81d366357a27b2b6a6c002668 100644 (file)
@@ -25,6 +25,8 @@
 #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},
index d9e76a4d72407dd91c7ed6274a976daa1c5459fa..5264593113cc533649cbe868085abafaa557eceb 100644 (file)
@@ -24,6 +24,8 @@
 #include <grub/command.h>
 #include <grub/i18n.h>
 
+GRUB_MOD_LICENSE ("GPLv3+");
+
 #define BUFFER_SIZE 512
 
 static grub_err_t
@@ -92,10 +94,8 @@ grub_cmd_cmp (grub_command_t cmd __attribute__ ((unused)),
 
 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)
index 2568b7ee6035380521248c68e1799036d9044ca1..124a09a9e0096c1e4e01b5bd9c76ae7a017bdce9 100644 (file)
@@ -24,6 +24,8 @@
 #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)
 {
index 623db494305114afb944a15c1d8605bd0f3de4cf..d27162077fc28443512cd14c140b9004818f7e6d 100644 (file)
@@ -24,6 +24,8 @@
 #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
index 93a452fc8eb776e15bc2459bd3d1f2546f3d800d..81ba50d6850c34c9f19f9d8ff7d52c93ac698c29 100644 (file)
@@ -23,6 +23,8 @@
 #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},
index 6430be5e34aec36aa88de291a1946ef274acd609..c53e47d8a089d2f820b3d98894a59cad16c5de69 100644 (file)
@@ -24,6 +24,8 @@
 #include <grub/command.h>
 #include <grub/i18n.h>
 
+GRUB_MOD_LICENSE ("GPLv3+");
+
 static struct grub_video_patch
 {
   const char *name;
index 8c7c25abd477ae84107a1ee1c186259513b9efa4..138311222d1a4b9b6d801cae99aad5bf830b4734 100644 (file)
@@ -25,6 +25,8 @@
 #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;
index 2bb5dcb5db8021509627e1c09ce5dde67f4a1775..215b45bff8076b6c34c35164e8cce9efe2da5f94 100644 (file)
@@ -23,6 +23,8 @@
 #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)))
 
index aa3e05aee877dd68a19df6e030b2d600184fdd36..b2359253adc52487b16b2877895d26ef1581895c 100644 (file)
  */
 #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;
index 2ee99303340d6bb1640f62394e3d6845d59a1620..fa8005b88060250b92582b5b43d701dfbffd1276 100644 (file)
@@ -23,6 +23,9 @@
 #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)
index e9274fbab412ea9b12cdcc4c958db4c2d2ee5895..69574e2b05b90f84b9d6d8855ede15178fa2f8b2 100644 (file)
@@ -22,6 +22,9 @@
 #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,
index 6364c13f77c4f3a48ab5f1198d647993bbd38ff6..e92dc20ec558b077116fcf0874ced7fd4cbc83d7 100644 (file)
@@ -29,6 +29,8 @@
 #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.
index 3400115a0b81f5371f4d609a0aa10f068cbbe8e9..317f7753fd8779f639854ef0d6b3b16b8214a89e 100644 (file)
@@ -22,6 +22,8 @@
 #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)),
index 664fe9c247c6fd02ad487ff508738f488a362110..6825d481168f3969b101ab4bb69e5eb5385d99a1 100644 (file)
@@ -26,6 +26,8 @@
 #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},
index b6ab7875516c24b12a16ccdfd0df94e4728bce18..2401707346683672a0a844b0f6adfe16fcbf303f 100644 (file)
@@ -18,6 +18,7 @@
  */
 
 #include <grub/ata.h>
+#include <grub/scsi.h>
 #include <grub/disk.h>
 #include <grub/dl.h>
 #include <grub/misc.h>
@@ -26,6 +27,8 @@
 #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)."),
@@ -61,60 +64,64 @@ enum grub_ata_smart_commands
 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;
@@ -124,12 +131,12 @@ grub_hdparm_do_smart_cmd (grub_disk_t disk, grub_uint8_t features)
 
 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");
@@ -138,7 +145,7 @@ grub_hdparm_simple_cmd (const char * msg,
 
 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)
@@ -149,7 +156,7 @@ grub_hdparm_set_val_cmd (const char * msg, int val,
        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)
@@ -273,6 +280,7 @@ static grub_err_t
 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)
@@ -283,9 +291,6 @@ grub_cmd_hdparm (grub_extcmd_context_t ctxt, int argc, char **args) // state????
     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;
@@ -311,15 +316,37 @@ grub_cmd_hdparm (grub_extcmd_context_t ctxt, int argc, char **args) // state????
       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)
     {
@@ -330,28 +357,28 @@ grub_cmd_hdparm (grub_extcmd_context_t ctxt, int argc, char **args) // state????
          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
@@ -367,7 +394,7 @@ grub_cmd_hdparm (grub_extcmd_context_t ctxt, int argc, char **args) // state????
   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
@@ -383,7 +410,7 @@ grub_cmd_hdparm (grub_extcmd_context_t ctxt, int argc, char **args) // state????
     {
       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*"));
@@ -392,11 +419,11 @@ grub_cmd_hdparm (grub_extcmd_context_t ctxt, int argc, char **args) // state????
 
   /* 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);
index ff6d7ed2e783e2e85e87a4bf037237f46850ddbb..82f3200c71d0257d6b26babfa726cd31c12c6b32 100644 (file)
@@ -26,6 +26,8 @@
 #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)
index 629f2a0695d0d75cf5ef45b47789a7b2cf7b3042..9ba83598a866a34704c5ce774ceb97b62b90528a 100644 (file)
@@ -25,6 +25,8 @@
 #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},
index 994da11b00fce887fc0cbad4c7b7f4502b8b3dc9..6439159bd02abe7bda5f22f63a28b090528dd083 100644 (file)
@@ -21,6 +21,8 @@
 #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)
 {
@@ -44,12 +46,17 @@ grub_cmd_cmostest (struct grub_command *cmd __attribute__ ((unused)),
 {
   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");
@@ -61,13 +68,16 @@ grub_cmd_cmosclean (struct grub_command *cmd __attribute__ ((unused)),
 {
   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;
index f5f0f15a8c73a9f8aa0185301af3e7ee3457146b..6a771ba74fd60a42c890f1a266d61e2e3d2af407 100644 (file)
@@ -27,6 +27,8 @@
 #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)  \
index ed4211ccad8b78ded4b833332016ee079197daa6..c9c8881b4ef1eab8b1cbfa94caaa85819122d8a8 100644 (file)
@@ -29,6 +29,7 @@
 #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);
index 81eb6a1bb0fcb8d8de1912d6fa9554a2a8d49b8d..e7c191de3f387ff81886b7c7469898941f560b55 100644 (file)
@@ -24,6 +24,8 @@
 #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},
index 30475d2ecbe62589f201b4ae644e76a3ab565990..17bcfd6eb80d48d0cfcc2a7efbd4936117184432 100644 (file)
@@ -22,6 +22,8 @@
 #include <grub/command.h>
 #include <grub/i18n.h>
 
+GRUB_MOD_LICENSE ("GPLv3+");
+
 int
 grub_apm_get_info (struct grub_apm_info *info)
 {
index 4ed937d4a5b82b7d0b8df764b2ed6c16e9f5d315..1adf296ec80b4b1546b7694f37bb566e7e23af5f 100644 (file)
@@ -29,6 +29,8 @@
 #include <grub/command.h>
 #include <grub/i18n.h>
 
+GRUB_MOD_LICENSE ("GPLv3+");
+
 #define BASE_TEMPO (60 * GRUB_TICKS_PER_SECOND)
 
 /* The speaker port.  */
@@ -190,7 +192,7 @@ grub_cmd_play (grub_command_t cmd __attribute__ ((unused)),
       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))
         {
@@ -225,7 +227,7 @@ grub_cmd_play (grub_command_t cmd __attribute__ ((unused)),
 
       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);
 
diff --git a/grub-core/commands/i386/pc/pxecmd.c b/grub-core/commands/i386/pc/pxecmd.c
deleted file mode 100644 (file)
index b576a8e..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-/* 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);
-}
index c777ea60ac76be4ea31c41382e75b02982dd84a3..a55d17bd0148664fad65e5c8293307e5491144c6 100644 (file)
@@ -27,6 +27,8 @@
 #include <grub/cpu/io.h>
 #include <grub/loader.h>
 
+GRUB_MOD_LICENSE ("GPLv2+");
+
 static char sendkey[0x20];
 /* Length of sendkey.  */
 static int keylen = 0;
index f096cc9baec7f77b9f932a9cade72792b5f26c99..de068951d94bee2e3bc48fa41faac91716328649 100644 (file)
@@ -24,6 +24,8 @@
 #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)),
index 20d203e9222c4734dae353bde567bc0398064e36..e7035b528d38adca0bf19b0aede6f7705ccd4a3f 100644 (file)
@@ -24,6 +24,8 @@
 #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;
 
index deb482a850c6f2b81a7b0b7fdb4dc811e2acc7ef..6c5913a54a980502d58800ee70106d6a7cea09de 100644 (file)
@@ -28,6 +28,8 @@
 #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.  */
index 9e1486c9d3de3f9bcef25bc2fb7d67d5dce1963c..f3a66994258588859d845cf08d382fd35027eceb 100644 (file)
@@ -23,6 +23,8 @@
 #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},
index 23c1c1908db6fd0c694d7ac8e7c96978f79d68e0..e68b3315a3d4be58af2a74a5f8a4199c175b5e15 100644 (file)
@@ -33,6 +33,8 @@
 #include <grub/disk.h>
 #include <grub/partition.h>
 
+GRUB_MOD_LICENSE ("GPLv3+");
+
 static grub_err_t
 legacy_file (const char *filename)
 {
index 38b3a84c673dd88aa800cd987b1e6f8dcb9c1ccb..5d53a8e662c5b04431cd439a0c004207f2b7040e 100644 (file)
@@ -28,6 +28,8 @@
 #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},
index 481d17db050386432f75015e25154504da976e3b..db93077803d90fe6267fac54d1ec835e72547c3c 100644 (file)
@@ -31,6 +31,9 @@
 #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[] =
   {
@@ -58,6 +61,22 @@ grub_ls_list_devices (int longlist)
 
   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;
@@ -132,11 +151,12 @@ grub_ls_list_files (char *dirname, int longlist, int all, int human)
 
              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);
                }
index 64b5596651f66f5f3d6855b8cc688a4ca92ca1a8..fd19e380a79002ed2738f33a3b4fe8fd093d7c57 100644 (file)
@@ -25,6 +25,8 @@
 #include <grub/i18n.h>
 #include <grub/dl.h>
 
+GRUB_MOD_LICENSE ("GPLv3+");
+
 static void
 print_strn (grub_uint8_t *str, grub_size_t len)
 {
index 657f81387bf45ddc9e626436a60624a8fdc005c8..44598f0df3624b839063e874578fac32490fe99b 100644 (file)
@@ -22,6 +22,8 @@
 #include <grub/i18n.h>
 #include <grub/memory.h>
 
+GRUB_MOD_LICENSE ("GPLv3+");
+
 static const char *names[] =
   {
     [GRUB_MEMORY_AVAILABLE] = "available", 
index fd2d4eaf22b4c4525329ec6921d95606e3c55328..03541df6c275441f45127b4e5c6b264bde19a32f 100644 (file)
@@ -23,6 +23,8 @@
 #include <grub/extcmd.h>
 #include <grub/i18n.h>
 
+GRUB_MOD_LICENSE ("GPLv3+");
+
 struct grub_pci_classname
 {
   int class;
index 28aac7d811cedd77d42460a5992cafe690e7c02f..3b51189d6def543ef069b0f02933403056e74c10 100644 (file)
@@ -23,6 +23,8 @@
 #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;
 
index 4dab1783a2e9bad98b75a1fe168c01894f5a12f5..4849f8bb81cd27012a0ec6756e38827c4a584031 100644 (file)
@@ -91,7 +91,7 @@ grub_normal_add_menu_entry (int argc, const char **args, char **classes,
   if (! menu_sourcecode)
     return grub_errno;
 
-  if (classes)
+  if (classes && classes[0])
     {
       int i;
       for (i = 0; classes[i]; i++); /* count # of menuentry classes */
@@ -255,7 +255,8 @@ grub_cmd_menuentry (grub_extcmd_context_t ctxt, int argc, char **args)
 
   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');
index 5cf109fde7fab36dc9d97e817fcdd6b40434d610..b9cbd06c14a00962a30694275504a8d03d182ad2 100644 (file)
@@ -29,6 +29,8 @@
 #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)),
@@ -88,26 +90,6 @@ grub_mini_cmd_help (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)),
diff --git a/grub-core/commands/mips/loongson/lsspd.c b/grub-core/commands/mips/loongson/lsspd.c
new file mode 100644 (file)
index 0000000..c1c5e2e
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ *  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);
+}
diff --git a/grub-core/commands/mips/yeeloong/lsspd.c b/grub-core/commands/mips/yeeloong/lsspd.c
deleted file mode 100644 (file)
index 539cda3..0000000
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- *  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);
-}
index 31e7685537647a0aab07a8bf3a3b7d094e02bd92..a542861619bc6839b108710bb9494a185b30d292 100644 (file)
@@ -31,6 +31,8 @@
 #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;
index db5951cbb20eaaab333f38a9c8a0f112b58c63fc..8821607b801d37f32092f3411237eb35981fb21e 100644 (file)
@@ -26,6 +26,8 @@
 #include <grub/dl.h>
 #include <grub/i18n.h>
 
+GRUB_MOD_LICENSE ("GPLv3+");
+
 static grub_dl_t my_mod;
 
 static grub_err_t
index 6886987da83bd24b20588e36d522e264532a836c..05a627219b15a16d7f1255fcc1326be433403174 100644 (file)
@@ -26,6 +26,8 @@
 #include <grub/dl.h>
 #include <grub/i18n.h>
 
+GRUB_MOD_LICENSE ("GPLv3+");
+
 static grub_dl_t my_mod;
 
 struct pbkdf2_password
index 3ace596d8ca2e41d0e73ff4afa2a8f62bdef84c9..ce1e9aac06217a59e6ccbebfe1cf35610bb8c7ab 100644 (file)
@@ -32,6 +32,8 @@
 #include <grub/extcmd.h>
 #include <grub/i18n.h>
 
+GRUB_MOD_LICENSE ("GPLv3+");
+
 static const struct grub_arg_option options[] =
   {
     {"set",             's', 0,
@@ -72,7 +74,7 @@ grub_cmd_probe (grub_extcmd_context_t ctxt, int argc, char **args)
     {
       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)
index 6a187fc3e4d573b6f40abe7321ccc0801dfcbcc7..fe3e88b1517ae71653b26c1053a23c32e8030c81 100644 (file)
@@ -26,6 +26,8 @@
 #include <grub/command.h>
 #include <grub/i18n.h>
 
+GRUB_MOD_LICENSE ("GPLv3+");
+
 static char *
 grub_getline (void)
 {
index eedd53c91771e55d25d0adb38bd1ac8e8603fde5..8e18083c0247a60255a3d1727c08ac64677198e9 100644 (file)
@@ -22,6 +22,8 @@
 #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)),
index 83c0d8d43bf9df4ef6d71b4c09662c93f313ad8b..1e8a6f309791c55f998f0f2fa3697d50ee4d6723 100644 (file)
@@ -27,6 +27,8 @@
 #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,
index f265f86d62c8a9e5ba0cf16ada3d363a35ddd764..ba80d80ef23997279d531f35ba0d0d75e5ea6b63 100644 (file)
@@ -31,6 +31,8 @@
 #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)
index 80741d7abe0c9bfbf5659ca07e77af8a17cbc033..7b0a99565cf1f51e2c127ff07cc369a7f98f9e3e 100644 (file)
@@ -27,6 +27,8 @@
 #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},
index 88dfa4c08d529175efdb5df588b7099d1a55a5b9..70f5bcdad9113b8d04417215bcd3001a915ff3aa 100644 (file)
@@ -25,6 +25,8 @@
 #include <grub/mm.h>
 #include <grub/i18n.h>
 
+GRUB_MOD_LICENSE ("GPLv3+");
+
 struct pci_register
 {
   const char *name;
index da642fcd94aca9fcd4595341ece0a4cf2dd7eaf4..97e7a40a63bfadbaecbaf550f9a67efdfb55d4de 100644 (file)
@@ -25,6 +25,8 @@
 #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},
index c2d9550f6081e55996972307c307196c933eb9d6..0adfd3d2e8438c3cf07e57443cddad84fb11c806 100644 (file)
@@ -23,6 +23,8 @@
 #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;
 
index e981c945a7dff3392405607a76452252ae10711b..50d5aba5e58f4ecbafacd9fbd535ee5d1c8e7a2e 100644 (file)
@@ -27,6 +27,8 @@
 #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)
index 86b8a92530883ffd0fbc99caf6540967c8f6dc1c..fe06f3d1e386125fa7d19ae30271108ce26bf2d7 100644 (file)
@@ -29,6 +29,8 @@
 #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[])
diff --git a/grub-core/commands/time.c b/grub-core/commands/time.c
new file mode 100644 (file)
index 0000000..6874959
--- /dev/null
@@ -0,0 +1,68 @@
+/* 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);
+}
index aa812585380025ca43ec0da56fe723fe23318657..82775e7ef7ae9731d26812ec61e973e0747dc23e 100644 (file)
@@ -21,6 +21,8 @@
 #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)),
index 7f00c8856168b57b38cb9ed46cda39d8e4ab5217..4a051ad1febc3850a777071ab42c31e5b4a412aa 100644 (file)
@@ -27,6 +27,8 @@
 #include <grub/command.h>
 #include <grub/i18n.h>
 
+GRUB_MOD_LICENSE ("GPLv3+");
+
 static const char *usb_classes[] =
   {
     "Unknown",
index 10f77915bf7bc020f6375d890fcebe57f2d20211..7ff172fd7e1cbc7b5cae185dd40410098b16d5f7 100644 (file)
 #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)
@@ -39,7 +42,13 @@ 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)
@@ -77,6 +86,30 @@ hook (const struct grub_video_mode_info *info)
   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)
@@ -120,6 +153,9 @@ grub_cmd_videoinfo (grub_command_t cmd __attribute__ ((unused)),
 
   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)
@@ -128,7 +164,17 @@ grub_cmd_videoinfo (grub_command_t cmd __attribute__ ((unused)),
        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 ())
          {
@@ -143,6 +189,13 @@ grub_cmd_videoinfo (grub_command_t cmd __attribute__ ((unused)),
 
     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 ())
index 435ac29377501dd7d3b6269ad421d59e2ae770c6..dc7a6485f98320a7e7a812d7a27139e8646462d6 100644 (file)
@@ -28,6 +28,8 @@
 #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)
index 32561abe6e58e21925a9dabb49ff5b41a63fae1e..256c07e51cbff126ebaf2f4d91b7c6f5122705b5 100644 (file)
@@ -139,6 +139,7 @@ make_regex (const char *start, const char *end, regex_t *regexp)
        case '.':
        case '(':
        case ')':
+       case '@':
          buffer[i++] = '\\';
          buffer[i++] = ch;
          break;
@@ -255,8 +256,7 @@ match_devices (const regex_t *regexp, int noparts)
   for (i = 0; devs && devs[i]; i++)
     grub_free (devs[i]);
 
-  if (devs)
-    grub_free (devs);
+  grub_free (devs);
 
   return 0;
 }
@@ -288,6 +288,8 @@ match_files (const char *prefix, const char *suffix, const char *end,
     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;
@@ -340,20 +342,17 @@ match_files (const char *prefix, const char *suffix, const char *end,
 
  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;
@@ -423,8 +422,6 @@ wildcard_expand (const char *s, char ***strs)
   while (*start)
     {
       split_path (start, &noregexop, &regexop);
-      if (noregexop >= regexop) /* no more wildcards */
-       break;
 
       if (make_regex (noregexop, regexop, &regexp))
        goto fail;
index 382d3196b779db4eba0dfa58572315f064d850c5..f618b4ec027d65dee370c7bd0db98b4fa14b20dc 100644 (file)
@@ -34,6 +34,8 @@
 #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]
diff --git a/grub-core/disk/AFSplitter.c b/grub-core/disk/AFSplitter.c
new file mode 100644 (file)
index 0000000..ebcc352
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * 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;
+}
diff --git a/grub-core/disk/ahci.c b/grub-core/disk/ahci.c
new file mode 100644 (file)
index 0000000..38c4d5e
--- /dev/null
@@ -0,0 +1,738 @@
+/*
+ *  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);
+}
diff --git a/grub-core/disk/arc/arcdisk.c b/grub-core/disk/arc/arcdisk.c
new file mode 100644 (file)
index 0000000..170bf52
--- /dev/null
@@ -0,0 +1,299 @@
+/* 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);
+}
index fe677e2a02412cab69f18e565ab122078bbd6baa..330635f57a09b2c818f39f93bfa5d101cc961abf 100644 (file)
 #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
@@ -105,30 +40,8 @@ grub_ata_strncpy (char *dst, char *src, grub_size_t len)
   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];
 
@@ -144,35 +57,40 @@ grub_ata_dumpinfo (struct grub_ata_device *dev, char *info)
     {
       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;
 
@@ -184,120 +102,51 @@ grub_atapi_identify (struct grub_ata_device *dev)
 }
 
 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.  */
@@ -322,6 +171,21 @@ grub_ata_identify (struct grub_ata_device *dev)
   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];
@@ -335,194 +199,11 @@ grub_ata_identify (struct grub_ata_device *dev)
 }
 
 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)
     {
@@ -544,14 +225,11 @@ grub_ata_setaddress (struct grub_ata_device *dev,
          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;
       }
@@ -559,26 +237,31 @@ grub_ata_setaddress (struct grub_ata_device *dev,
     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;
     }
@@ -590,70 +273,74 @@ static grub_err_t
 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;
     }
@@ -663,75 +350,119 @@ grub_ata_readwrite (grub_disk_t disk, grub_disk_addr_t sector,
 
 \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
@@ -766,70 +497,35 @@ static struct grub_disk_dev grub_atadisk_dev =
 \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;
 }
 
@@ -845,64 +541,100 @@ grub_atapi_write (struct grub_scsi *scsi __attribute__((unused)),
 }
 
 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.  */
diff --git a/grub-core/disk/ata_pthru.c b/grub-core/disk/ata_pthru.c
deleted file mode 100644 (file)
index f52725a..0000000
+++ /dev/null
@@ -1,107 +0,0 @@
-/* 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;
-}
diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
new file mode 100644 (file)
index 0000000..2852b65
--- /dev/null
@@ -0,0 +1,883 @@
+/*
+ *  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 ();
+}
index d3f45935c0f3bdfb8a82dbff1e2e1f2a749f0149..154193eb0372ff0898e4e8c4d1f34290354618af 100644 (file)
@@ -24,6 +24,8 @@
 #include <grub/misc.h>
 #include <grub/raid.h>
 
+GRUB_MOD_LICENSE ("GPLv3+");
+
 #define NV_SIGNATURES          4
 
 #define NV_IDLE                        0
index 08094fa5c9ec06f59e92cbffd2691ee6a3cb62e5..0baeb8e4b5660248e584ec163776006350432a6e 100644 (file)
@@ -33,12 +33,10 @@ struct grub_efidisk_data
   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;
@@ -86,54 +84,6 @@ find_last_device_path (const grub_efi_device_path_t *dp)
   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)
 {
@@ -143,7 +93,7 @@ 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;
@@ -155,7 +105,6 @@ make_devices (void)
       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)
@@ -168,9 +117,7 @@ make_devices (void)
 
       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;
 
@@ -186,7 +133,6 @@ make_devices (void)
       d->device_path = dp;
       d->last_device_path = ldp;
       d->block_io = bio;
-      d->disk_io = dio;
       d->next = devices;
       devices = d;
     }
@@ -220,7 +166,7 @@ find_parent_device (struct grub_efidisk_data *devices,
       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)
@@ -255,7 +201,7 @@ iterate_child_devices (struct grub_efidisk_data *devices,
       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);
@@ -279,11 +225,11 @@ add_device (struct grub_efidisk_data **devices, struct grub_efidisk_data *d)
     {
       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)
@@ -432,34 +378,43 @@ enumerate_disks (void)
 }
 
 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;
@@ -536,8 +491,13 @@ grub_efidisk_open (const char *name, struct grub_disk *disk)
      and total sectors should be replaced with total blocks.  */
   grub_dprintf ("efidisk", "m = %p, last block = %llx, block size = %x\n",
                m, (unsigned long long) m->last_block, m->block_size);
-  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);
@@ -558,22 +518,20 @@ grub_efidisk_read (struct grub_disk *disk, grub_disk_addr_t sector,
 {
   /* 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");
 
@@ -586,21 +544,19 @@ grub_efidisk_write (struct grub_disk *disk, grub_disk_addr_t sector,
 {
   /* 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");
@@ -711,7 +667,35 @@ grub_efidisk_get_device_handle (grub_disk_t disk)
 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)
@@ -725,40 +709,12 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle)
       && (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)
@@ -766,7 +722,7 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle)
          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;
            }
 
@@ -785,7 +741,11 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle)
       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)
@@ -793,19 +753,24 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle)
 
       /* 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;
@@ -813,36 +778,17 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle)
   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;
     }
 
diff --git a/grub-core/disk/geli.c b/grub-core/disk/geli.c
new file mode 100644 (file)
index 0000000..d2ae5da
--- /dev/null
@@ -0,0 +1,536 @@
+/*
+ *  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);
+}
index c5196629336e13d89bf0a909f114618b008f5d00..5ee0d2e56a8ead53ca94f15b298ed12cde89af4e 100644 (file)
 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;
index 069bb0b595bce99297d270c0490fadff48ea0bab..e152b9d896c86e1119f5452a508e6d5417390602 100644 (file)
@@ -28,6 +28,8 @@
 #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);
 
@@ -282,37 +284,46 @@ grub_biosdisk_call_hook (int (*hook) (const char *name), int drive)
 }
 
 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;
 }
 
@@ -338,7 +349,8 @@ grub_biosdisk_open (const char *name, grub_disk_t disk)
   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;
     }
@@ -347,6 +359,8 @@ grub_biosdisk_open (const char *name, grub_disk_t disk)
       /* HDD */
       int version;
 
+      disk->log_sector_size = 9;
+
       version = grub_biosdisk_check_int13_extensions (drive);
       if (version)
        {
@@ -367,6 +381,15 @@ grub_biosdisk_open (const char *name, grub_disk_t disk)
                    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++);
+               }
            }
        }
     }
@@ -429,7 +452,7 @@ grub_biosdisk_rw (int cmd, grub_disk_t disk,
 
       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;
@@ -443,9 +466,6 @@ grub_biosdisk_rw (int cmd, grub_disk_t disk,
          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;
@@ -501,10 +521,12 @@ grub_biosdisk_rw (int cmd, grub_disk_t disk,
 
 /* 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);
@@ -512,8 +534,8 @@ get_safe_sectors (grub_disk_addr_t sector, grub_uint32_t sectors)
   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;
 }
@@ -522,21 +544,11 @@ static grub_err_t
 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;
@@ -545,9 +557,10 @@ grub_biosdisk_read (grub_disk_t disk, grub_disk_addr_t sector,
                            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;
     }
@@ -568,18 +581,18 @@ grub_biosdisk_write (grub_disk_t disk, grub_disk_addr_t sector,
     {
       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;
     }
index a2c717cdb5603bf02cae2adafe76c7eff57f73ce..94d62bc4f37b7faac84de0d0c4d780e270b34fd0 100644 (file)
@@ -23,6 +23,8 @@
 #include <grub/dl.h>
 #include <grub/ieee1275/ieee1275.h>
 
+GRUB_MOD_LICENSE ("GPLv3+");
+
 struct grub_nand_data
 {
   grub_ieee1275_ihandle_t handle;
@@ -30,7 +32,8 @@ struct grub_nand_data
 };
 
 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)
@@ -44,6 +47,9 @@ grub_nand_iterate (int (*hook) (const char *name))
       return 0;
     }
 
+  if (pull != GRUB_DISK_PULL_NONE)
+    return 0;
+
   return grub_devalias_iterate (dev_iterate);
 }
 
index 0a935d5c2b8e5db3d955e28988b63c2a38cab3d3..2cd43d80a98c284260657ba1fbc1112d57670c20 100644 (file)
@@ -152,9 +152,14 @@ scan (void)
 }
 
 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++)
@@ -243,14 +248,24 @@ grub_ofdisk_open (const char *name, grub_disk_t disk)
   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
index 939043f017831e9cacba3e18c06e0ea4407f3aea..dca83b7c674960d6a637b2aafac7a166d1d9fec4 100644 (file)
@@ -25,6 +25,8 @@
 #include <grub/extcmd.h>
 #include <grub/i18n.h>
 
+GRUB_MOD_LICENSE ("GPLv3+");
+
 struct grub_loopback
 {
   char *devname;
@@ -131,9 +133,12 @@ fail:
 
 \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))
diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c
new file mode 100644 (file)
index 0000000..0ec95fc
--- /dev/null
@@ -0,0 +1,470 @@
+/*
+ *  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);
+}
index 00c6d8f9b72d3c0ebff655bb3e3b43169208b920..7c19f08de1d2e2495c6b04209b0bcca804292b77 100644 (file)
 
 #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
@@ -93,17 +99,660 @@ grub_lvm_check_flag (char *p, char *str, char *flag)
     }
 }
 
+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;
@@ -136,17 +785,23 @@ grub_lvm_memberlist (grub_disk_t disk)
 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)
@@ -245,9 +900,9 @@ read_lv (struct grub_lvm_lv *lv, grub_disk_addr_t sector,
          /* 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);
@@ -283,6 +938,49 @@ read_lv (struct grub_lvm_lv *lv, grub_disk_addr_t sector,
   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)
@@ -299,565 +997,6 @@ grub_lvm_write (grub_disk_t disk __attribute ((unused)),
   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",
@@ -876,13 +1015,6 @@ static struct grub_disk_dev grub_lvm_dev =
 \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);
 }
 
index e308783651bc633f34a5f5dfb3547a5f90968e37..19c43f45593568176bd5e286d7a2350e462f31d7 100644 (file)
@@ -24,6 +24,8 @@
 #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.  */
 
index 06d3498a8f13c41075da0a27f5e76ef124cf8a69..0e2d85009f2b4d3fc2546f35f0ff38c4c55a9f51 100644 (file)
@@ -27,6 +27,8 @@
 /* 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)
 
@@ -219,10 +221,10 @@ grub_mdraid_detect (grub_disk_t disk, struct grub_raid_array *array,
       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;
 
index e00280dd7bfd92cffcc6ae566ae73ee40fe0099c..4de0971ae10934ae25c4d4171098f1c191971922 100644 (file)
 #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");
 }
 
@@ -80,30 +86,24 @@ static struct grub_disk_dev grub_memdisk_dev =
 
 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)
diff --git a/grub-core/disk/pata.c b/grub-core/disk/pata.c
new file mode 100644 (file)
index 0000000..c54fe91
--- /dev/null
@@ -0,0 +1,538 @@
+/* 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);
+}
index ac2b9fefe1412827dafdb03dc5066e86cbf4fcc4..5d8326dafb97560d1dc40494f0a61dc23c6754ab 100644 (file)
 #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
@@ -76,14 +83,98 @@ grub_is_array_readable (struct grub_raid_array *array)
   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;
     }
@@ -120,17 +211,72 @@ grub_raid_getname (struct grub_disk *disk)
 }
 #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)
@@ -212,7 +358,7 @@ grub_raid_read (grub_disk_t disk, grub_disk_addr_t sector,
     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;
@@ -318,7 +464,7 @@ grub_raid_read (grub_disk_t disk, grub_disk_addr_t sector,
     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;
@@ -491,6 +637,7 @@ insert_array (grub_disk_t disk, struct grub_raid_array *new_array,
              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.  */
@@ -501,6 +648,8 @@ insert_array (grub_disk_t disk, struct grub_raid_array *new_array,
         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)
@@ -646,6 +795,49 @@ insert_array (grub_disk_t disk, struct grub_raid_array *new_array,
                      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;
@@ -660,12 +852,12 @@ insert_array (grub_disk_t disk, struct grub_raid_array *new_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)
 {
@@ -696,45 +888,8 @@ 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
index 349eb0291d081d4e78914bf7a1c905307242a4d1..c26d05e94f273135e3d3d1629449dd6f0611fc23 100644 (file)
@@ -24,6 +24,8 @@
 #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)
index dfaa60ea4d1126b4bfdc83c472c6580f54430209..25b50eb6b5d4024c374d9f80f36a5f734397f28d 100644 (file)
@@ -24,6 +24,8 @@
 #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];
 
index a40de278f899aff4a9979cf50b582be472a76f03..610cc4dc5b1df58a55b1579969fee0a897505c2c 100644 (file)
 #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)
 {
@@ -314,13 +322,14 @@ grub_scsi_write12 (grub_disk_t disk, grub_disk_addr_t sector,
 
 \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;
 
@@ -329,7 +338,7 @@ grub_scsi_iterate (int (*hook) (const char *name))
        {
          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);
@@ -343,7 +352,7 @@ grub_scsi_iterate (int (*hook) (const char *name))
        {
          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);
@@ -355,7 +364,7 @@ grub_scsi_iterate (int (*hook) (const char *name))
     }
 
   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;
@@ -370,6 +379,7 @@ grub_scsi_open (const char *name, grub_disk_t disk)
   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
@@ -394,15 +404,25 @@ grub_scsi_open (const char *name, grub_disk_t disk)
   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;
@@ -463,22 +483,26 @@ grub_scsi_open (const char *name, grub_disk_t disk)
          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");
 }
 
@@ -501,36 +525,36 @@ grub_scsi_read (grub_disk_t disk, grub_disk_addr_t sector,
 
   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, &sector_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
index fcfe9e5d40c8cda11166bfc07250acd84538b83c..a4c2addf100d7d0e392dea79be2c2967b3cf32ec 100644 (file)
@@ -24,6 +24,8 @@
 #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.  */
@@ -209,16 +211,20 @@ grub_usbms_attach (grub_usb_device_t usbdev, int configno, int interfno)
 \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;
       }
 
@@ -388,8 +394,12 @@ grub_usbms_write (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd,
 }
 
 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])
@@ -404,8 +414,6 @@ grub_usbms_open (int devnum, struct grub_scsi *scsi)
 
 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,
index da813b00d72a9a2f49da496a575aea1e492856c4..7ad3abb0d4806fb3aa3a596d58deba04664335a4 100644 (file)
@@ -32,6 +32,8 @@
 #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;
@@ -191,7 +193,7 @@ grub_efiemu_load_file (const char *filename)
 
   file = grub_file_open (filename);
   if (! file)
-    return 0;
+    return grub_errno;
 
   err = grub_efiemu_mm_init ();
   if (err)
index b5ec43bb28eae543be78bafcf1bb2b6015a5495d..26eac4c0591434a3349162e8c25580ab5192bea3 100644 (file)
@@ -30,6 +30,8 @@
 #include <grub/unicode.h>
 #include <grub/fontformat.h>
 
+GRUB_MOD_LICENSE ("GPLv3+");
+
 #ifdef USE_ASCII_FAILBACK
 #include "ascii.h"
 #endif
@@ -314,10 +316,7 @@ load_font_index (grub_file_t file, grub_uint32_t sect_length, struct
     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));
 
 
@@ -492,7 +491,7 @@ grub_font_load (const char *filename)
 #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;
 
@@ -638,6 +637,11 @@ grub_font_load (const char *filename)
   return 0;
 
 fail:
+  if (file)
+    grub_file_close (file);
+  if (font)
+    font->file = 0;
+
   free_font (font);
   return 1;
 }
@@ -797,6 +801,7 @@ free_font (grub_font_t font)
       grub_free (font->name);
       grub_free (font->family);
       grub_free (font->char_index);
+      grub_free (font->bmp_idx);
       grub_free (font);
     }
 }
index 8b00dd8b92d3f579b9b56f66bca0d9d8edb92815..98f0b88d68d3f43375ae2cc09850a856dbbb99b4 100644 (file)
@@ -33,7 +33,11 @@ loadfont_command (grub_command_t cmd __attribute__ ((unused)),
 
   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;
 }
index 40be4b2f61c7671339ba89db6b336ac817967ef2..adf2932bdf87d0929b3ff78bf9ecf9e783be2dea 100644 (file)
@@ -26,6 +26,8 @@
 #include <grub/types.h>
 #include <grub/fshelp.h>
 
+GRUB_MOD_LICENSE ("GPLv3+");
+
 /* The affs bootblock.  */
 struct grub_affs_bblock
 {
@@ -50,12 +52,20 @@ struct grub_affs_rblock
   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];
@@ -85,9 +95,9 @@ struct grub_affs_file
 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.  */
@@ -115,7 +125,7 @@ grub_affs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
   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.  */
@@ -150,11 +160,11 @@ static grub_ssize_t
 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);
 }
 
 
@@ -166,7 +176,6 @@ grub_affs_mount (grub_disk_t disk)
   struct grub_affs_rblock *rblock;
 
   int checksum = 0;
-  int checksumr = 0;
   int blocksize = 0;
 
   data = grub_malloc (sizeof (struct grub_affs_data));
@@ -216,8 +225,6 @@ grub_affs_mount (grub_disk_t disk)
   /* 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;
@@ -226,10 +233,10 @@ grub_affs_mount (grub_disk_t disk)
       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;
@@ -241,6 +248,8 @@ grub_affs_mount (grub_disk_t disk)
   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);
 
@@ -291,12 +300,15 @@ grub_affs_iterate_dir (grub_fshelp_node_t dir,
   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)
        {
@@ -304,10 +316,19 @@ grub_affs_iterate_dir (grub_fshelp_node_t dir,
          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))
        {
@@ -317,6 +338,24 @@ grub_affs_iterate_dir (grub_fshelp_node_t dir,
       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;
@@ -326,16 +365,8 @@ grub_affs_iterate_dir (grub_fshelp_node_t dir,
   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])
@@ -356,17 +387,7 @@ grub_affs_iterate_dir (grub_fshelp_node_t dir,
 
          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);
@@ -401,7 +422,7 @@ grub_affs_open (struct grub_file *file, const char *name)
   if (grub_errno)
     goto fail;
 
-  file->size = fdiro->size;
+  file->size = grub_be_to_cpu32 (fdiro->di.size);
   data->diropen = *fdiro;
   grub_free (fdiro);
 
@@ -465,6 +486,11 @@ grub_affs_dir (grub_device_t device, const char *path,
       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);
     }
index cd61f4db9b71adc2e9d84aece8b37e5356a538b5..b64ebb52c51e926257af68a0f62484054d766da1 100644 (file)
@@ -26,6 +26,8 @@
 #include <grub/types.h>
 #include <grub/fshelp.h>
 
+GRUB_MOD_LICENSE ("GPLv3+");
+
 #ifdef MODE_BIGENDIAN
 #define GRUB_AFS_FSNAME_SUFFIX "_be"
 #else
@@ -334,7 +336,7 @@ static grub_ssize_t
 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,
index 179891da8a3121b03f2140c42787e27066ae506b..93642f78931246ed634175a3d43bb088f485b5bb 100644 (file)
 #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)
 {
@@ -97,8 +1554,8 @@ 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",
@@ -111,25 +1568,48 @@ grub_btrfs_uuid (grub_device_t device, char **uuid)
                          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);
 }
index 2c92404c348986d6ae0104d9c8afc05f0e9fc7a2..0d84382acc098b45a9ba2d2bcc8f6dcc6a5faf23 100644 (file)
@@ -23,6 +23,8 @@
 #include <grub/disk.h>
 #include <grub/dl.h>
 
+GRUB_MOD_LICENSE ("GPLv3+");
+
 #ifndef MODE_USTAR
 /* cpio support */
 #define        MAGIC_BCPIO     070707
@@ -78,7 +80,7 @@ static grub_dl_t my_mod;
 
 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;
@@ -91,6 +93,8 @@ grub_cpio_find_file (struct grub_cpio_data *data, char **name,
        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++;
@@ -139,6 +143,8 @@ grub_cpio_find_file (struct grub_cpio_data *data, char **name,
       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;
 }
@@ -204,7 +210,9 @@ grub_cpio_dir (grub_device_t device, const char *path,
   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)
@@ -227,10 +235,11 @@ grub_cpio_dir (grub_device_t device, const char *path,
              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
@@ -241,11 +250,8 @@ grub_cpio_dir (grub_device_t device, const char *path,
 
 fail:
 
-  if (prev)
-    grub_free (prev);
-
-  if (data)
-    grub_free (data);
+  grub_free (prev);
+  grub_free (data);
 
   grub_dl_unref (my_mod);
 
@@ -269,7 +275,7 @@ grub_cpio_open (grub_file_t file, const char *name)
   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)
@@ -316,8 +322,7 @@ grub_cpio_open (grub_file_t file, const char *name)
 
 fail:
 
-  if (data)
-    grub_free (data);
+  grub_free (data);
 
   grub_dl_unref (my_mod);
 
index 9d7bbfd36229305c874ae7f692dc486f48a22ef8..0fdf151a2f90acb4fa8d4134ba1c4c1442d805b5 100644 (file)
@@ -51,6 +51,8 @@
 #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)
index 49bb3a599e3620d6ebe6c716120972d223184fc1..ae705bcfb33452924163c138813bcd8981e53d76 100644 (file)
 #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];
@@ -78,53 +80,9 @@ struct grub_fat_bpb
   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
@@ -268,7 +226,7 @@ fat_log2 (unsigned x)
 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;
 
@@ -294,8 +252,6 @@ grub_fat_mount (grub_disk_t disk)
     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;
@@ -352,13 +308,11 @@ grub_fat_mount (grub_disk_t disk)
   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));
@@ -481,6 +435,8 @@ grub_fat_mount (grub_disk_t disk)
      they overwrite the media descriptor.  */
   if ((first_fat | 0x8) != (magic | bpb.media | 0x8))
     goto fail;
+#else
+  (void) magic;
 #endif
 
   /* Start from the root directory.  */
@@ -867,6 +823,7 @@ grub_fat_find_dir (grub_disk_t disk, struct grub_fat_data *data,
                                const struct grub_dirhook_info *info))
 {
   char *dirname, *dirp;
+  char *origpath = NULL;
   int call_hook;
   int found = 0;
 
@@ -917,6 +874,10 @@ grub_fat_find_dir (grub_disk_t disk, struct grub_fat_data *data,
       return 0;
     }
 
+  origpath = grub_strdup (path);
+  if (!origpath)
+    return 0;
+
   /* Extract a directory name.  */
   while (*path == '/')
     path++;
@@ -928,7 +889,7 @@ grub_fat_find_dir (grub_disk_t disk, struct grub_fat_data *data,
 
       dirname = grub_malloc (len + 1);
       if (! dirname)
-       return 0;
+       goto fail;
 
       grub_memcpy (dirname, path, len);
       dirname[len] = '\0';
@@ -941,9 +902,11 @@ grub_fat_find_dir (grub_disk_t disk, struct grub_fat_data *data,
 
   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;
 }
@@ -1196,6 +1159,7 @@ GRUB_MOD_INIT(exfat)
 GRUB_MOD_INIT(fat)
 #endif
 {
+  COMPILE_TIME_ASSERT (sizeof (struct grub_fat_dir_entry) == 32);
   grub_fs_register (&grub_fat_fs);
   my_mod = mod;
 }
index d0b1e493e711250378cf60208e4fb940c3acbd1c..275cb9e1b4cf3c01ccd7fa489bf673b1750254ce 100644 (file)
@@ -22,7 +22,9 @@
 #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
@@ -59,7 +61,6 @@ grub_fshelp_find_file (const char *path, grub_fshelp_node_t rootnode,
       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;
@@ -195,7 +196,7 @@ grub_fshelp_find_file (const char *path, grub_fshelp_node_t rootnode,
          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] != '/')
index cef856326948a625ad96a08ba0f449f35578a94c..973a2d2ef313f8e0fdefd376a9893c465df6fd72 100644 (file)
@@ -29,6 +29,8 @@
 #include <grub/types.h>
 #include <grub/hfs.h>
 
+GRUB_MOD_LICENSE ("GPLv3+");
+
 #define        GRUB_HFS_SBLOCK         2
 #define GRUB_HFS_EMBED_HFSPLUS_SIG 0x482B
 
@@ -131,6 +133,8 @@ struct grub_hfs_dirrec
   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.  */
@@ -142,7 +146,9 @@ struct grub_hfs_filerec
   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.  */
@@ -238,22 +244,24 @@ static grub_ssize_t
 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;
@@ -261,7 +269,7 @@ grub_hfs_read_file (struct grub_hfs_data *data,
       /* 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)
@@ -269,7 +277,7 @@ grub_hfs_read_file (struct grub_hfs_data *data,
        }
 
       /* First block.  */
-      if (i == pos / data->blksz)
+      if (i == grub_divmod64 (pos, data->blksz, 0))
        {
          skipfirst = blockoff;
          blockend -= skipfirst;
@@ -915,7 +923,7 @@ grub_hfs_find_dir (struct grub_hfs_data *data, const char *path,
       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;
        }
 
@@ -951,19 +959,29 @@ grub_hfs_dir (grub_device_t device, const char *path,
   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;
     }
 
@@ -1072,6 +1090,22 @@ grub_hfs_label (grub_device_t device, char **label)
   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)
 {
@@ -1107,6 +1141,7 @@ static struct grub_fs grub_hfs_fs =
     .close = grub_hfs_close,
     .label = grub_hfs_label,
     .uuid = grub_hfs_uuid,
+    .mtime = grub_hfs_mtime,
     .next = 0
   };
 
index 7d7115ce36efac468601febc69ce777545d6b984..245cd93a5d181fd111e60131b0eadc22d34f65be 100644 (file)
@@ -30,6 +30,8 @@
 #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
@@ -212,7 +214,7 @@ struct grub_fshelp_node
 struct grub_hfsplus_btree
 {
   grub_uint32_t root;
-  int nodesize;
+  grub_size_t nodesize;
 
   /* Catalog file node.  */
   struct grub_fshelp_node file;
@@ -234,7 +236,7 @@ struct grub_hfsplus_data
 
   /* 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;
 };
 
@@ -243,7 +245,7 @@ static grub_dl_t my_mod;
 \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)
 {
@@ -261,7 +263,7 @@ grub_hfsplus_btree_recptr (struct grub_hfsplus_btree *btree,
                           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];
 }
@@ -270,12 +272,12 @@ grub_hfsplus_btree_recptr (struct grub_hfsplus_btree *btree,
 /* 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++)
@@ -286,7 +288,7 @@ grub_hfsplus_find_block (struct grub_hfsplus_extent *extent,
     }
 
   *fileblock = blksleft;
-  return -1;
+  return 0xffffffffffffffffULL;
 }
 
 static grub_err_t
@@ -294,7 +296,8 @@ grub_hfsplus_btree_search (struct grub_hfsplus_btree *btree,
                           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);
@@ -305,15 +308,15 @@ static grub_disk_addr_t
 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);
@@ -323,7 +326,7 @@ grub_hfsplus_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
       grub_free (nnode);
       nnode = 0;
 
-      if (blk != -1)
+      if (blk != 0xffffffffffffffffULL)
        return (blk
                + (node->data->embedded_offset >> (node->data->log2blksize
                                                   - GRUB_DISK_SECTOR_BITS)));
@@ -374,7 +377,7 @@ static grub_ssize_t
 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,
@@ -409,9 +412,9 @@ grub_hfsplus_mount (grub_disk_t disk)
   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)
@@ -599,10 +602,10 @@ grub_hfsplus_read_symlink (grub_fshelp_node_t node)
 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 (;;)
     {
@@ -640,12 +643,13 @@ grub_hfsplus_btree_search (struct grub_hfsplus_btree *btree,
                           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)
@@ -823,7 +827,7 @@ grub_hfsplus_iterate_dir (grub_fshelp_node_t dir,
 
   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;
@@ -892,7 +896,6 @@ grub_hfsplus_close (grub_file_t file)
   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)
@@ -900,13 +903,10 @@ 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,
diff --git a/grub-core/fs/i386/pc/pxe.c b/grub-core/fs/i386/pc/pxe.c
deleted file mode 100644 (file)
index c800ea2..0000000
+++ /dev/null
@@ -1,650 +0,0 @@
-/* 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, &regs);
-
-  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 ();
-}
index f72249d2094c21f988229f320cef812939619c26..5b53ca597100186d007ef22f6d36e67c1be618ee 100644 (file)
@@ -27,6 +27,9 @@
 #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
@@ -53,6 +56,17 @@ struct grub_iso9660_voldesc
   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
 {
@@ -62,7 +76,7 @@ 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;
@@ -144,6 +158,7 @@ struct grub_iso9660_data
 struct grub_fshelp_node
 {
   struct grub_iso9660_data *data;
+  struct grub_iso9660_dir dirent;
   unsigned int size;
   unsigned int blk;
   unsigned int dir_blk;
@@ -153,6 +168,52 @@ struct grub_fshelp_node
 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.  */
@@ -364,7 +425,6 @@ grub_iso9660_mount (grub_disk_t disk)
 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;
@@ -442,13 +502,10 @@ grub_iso9660_read_symlink (grub_fshelp_node_t node)
       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)
@@ -541,7 +598,7 @@ grub_iso9660_iterate_dir (grub_fshelp_node_t dir,
       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)
@@ -619,10 +676,9 @@ grub_iso9660_iterate_dir (grub_fshelp_node_t dir,
            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;
          }
@@ -645,6 +701,7 @@ grub_iso9660_iterate_dir (grub_fshelp_node_t dir,
             filename_alloc = 1;
           }
 
+       node->dirent = dirent;
        if (hook (filename, type, node))
          {
            if (filename_alloc)
@@ -654,8 +711,6 @@ grub_iso9660_iterate_dir (grub_fshelp_node_t dir,
        if (filename_alloc)
          grub_free (filename);
       }
-
-      offset += dirent.len;
     }
 
   return 0;
@@ -683,6 +738,8 @@ grub_iso9660_dir (grub_device_t device, const char *path,
       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);
     }
@@ -880,6 +937,32 @@ grub_iso9660_uuid (grub_device_t device, char **uuid)
   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 =
@@ -891,6 +974,7 @@ 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
   };
 
index 6857c4a2cdd4c846dc737a55c146417b22b41b1c..ebc2c688ae6c5cf9717c6f5fdc3c06ab751af8db 100644 (file)
@@ -26,6 +26,8 @@
 #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
@@ -153,6 +155,12 @@ struct grub_jfs_leaf_next_dirent
   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;
@@ -162,7 +170,10 @@ struct grub_jfs_inode
   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
@@ -603,7 +614,8 @@ grub_jfs_read_file (struct grub_jfs_data *data,
 /* 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;
@@ -612,7 +624,7 @@ grub_jfs_find_file (struct grub_jfs_data *data, const char *path)
 
   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.  */
@@ -688,7 +700,7 @@ grub_jfs_find_file (struct grub_jfs_data *data, const char *path)
     }
 
   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;
 }
 
@@ -713,11 +725,7 @@ grub_jfs_lookup_symlink (struct grub_jfs_data *data, grub_uint32_t ino)
   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);
 
@@ -739,7 +747,7 @@ grub_jfs_dir (grub_device_t device, const char *path,
   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);
@@ -758,6 +766,8 @@ grub_jfs_dir (grub_device_t device, const char *path,
 
       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;
     }
@@ -788,7 +798,7 @@ grub_jfs_open (struct grub_file *file, const char *name)
   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;
 
index 679e1ec510ffbe36853945a6e1d4bad7b21dafd3..055f890959887226d22eea560d6101b1f464aa79 100644 (file)
 #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
@@ -41,7 +46,7 @@
 #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
@@ -50,6 +55,13 @@ typedef grub_uint16_t grub_minix_uintn_t;
 #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))
@@ -60,39 +72,53 @@ typedef grub_uint16_t grub_minix_uintn_t;
 #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;
@@ -109,6 +135,19 @@ struct grub_minix_inode
   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
 
@@ -121,6 +160,7 @@ struct grub_minix_data
   int linknest;
   grub_disk_t disk;
   int filename_size;
+  grub_size_t block_size;
 };
 
 static grub_dl_t my_mod;
@@ -131,7 +171,6 @@ static grub_err_t grub_minix_find_file (struct grub_minix_data *data,
 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);
@@ -141,18 +180,18 @@ grub_minix_get_file_block (struct grub_minix_data *data, unsigned int blk)
     {
       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);
@@ -185,25 +224,26 @@ static grub_ssize_t
 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)
@@ -212,28 +252,28 @@ grub_minix_read_file (struct grub_minix_data *data,
       /* 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;
@@ -248,16 +288,13 @@ grub_minix_read_inode (struct grub_minix_data *data, int ino)
   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))
@@ -333,7 +370,7 @@ grub_minix_find_file (struct grub_minix_data *data, const char *path)
 
   do
     {
-      grub_uint16_t ino;
+      grub_minix_ino_t ino;
       char filename[data->filename_size + 1];
 
       if (grub_strlen (name) == 0)
@@ -353,7 +390,7 @@ grub_minix_find_file (struct grub_minix_data *data, const char *path)
       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)
@@ -387,7 +424,7 @@ grub_minix_find_file (struct grub_minix_data *data, const char *path)
       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;
 }
 
@@ -409,20 +446,35 @@ grub_minix_mount (grub_disk_t disk)
     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");
@@ -458,7 +510,7 @@ grub_minix_dir (grub_device_t device, const char *path,
 
   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;
@@ -474,12 +526,22 @@ grub_minix_dir (grub_device_t device, const char *path,
                                (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;
 
@@ -556,7 +618,9 @@ grub_minix_close (grub_file_t file)
 \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",
@@ -568,7 +632,9 @@ static struct grub_fs grub_minix_fs =
     .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)
@@ -578,7 +644,9 @@ 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)
diff --git a/grub-core/fs/minix3.c b/grub-core/fs/minix3.c
new file mode 100644 (file)
index 0000000..58a21d2
--- /dev/null
@@ -0,0 +1,2 @@
+#define MODE_MINIX3 1
+#include "minix.c"
index e529775f42d56449802696cea75a4f0ebd3fd99f..62cf167c723957263946077ec078bdd4163fcfbc 100644 (file)
@@ -35,6 +35,8 @@
 #include <grub/types.h>
 #include <grub/fshelp.h>
 
+GRUB_MOD_LICENSE ("GPLv3+");
+
 #define NILFS_INODE_BMAP_SIZE  7
 
 #define NILFS_SUPORT_REV       2
@@ -301,7 +303,7 @@ grub_nilfs2_palloc_entries_per_group (struct grub_nilfs2_data *data)
 
 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);
@@ -366,13 +368,15 @@ grub_nilfs2_palloc_entry_offset (struct grub_nilfs2_data *data,
                                 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);
 
 }
 
@@ -575,7 +579,7 @@ grub_nilfs2_dat_translate (struct grub_nilfs2_data *data, grub_uint64_t key)
   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,
@@ -624,7 +628,7 @@ grub_nilfs2_read_file (grub_fshelp_node_t node,
                                                           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,
@@ -639,7 +643,7 @@ grub_nilfs2_read_checkpoint (struct grub_nilfs2_data *data,
                             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));
@@ -677,7 +681,7 @@ grub_nilfs2_read_inode (struct grub_nilfs2_data *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));
@@ -862,7 +866,7 @@ grub_nilfs2_iterate_dir (grub_fshelp_node_t dir,
                                  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)
index 414f6513d9450b5aac07299e7a388f43a54cc795..5d128bcc0b2de15492ac42bee64ed253fcbf9c84 100644 (file)
@@ -26,6 +26,8 @@
 #include <grub/ntfs.h>
 #include <grub/charset.h>
 
+GRUB_MOD_LICENSE ("GPLv3+");
+
 static grub_dl_t my_mod;
 
 ntfscomp_func_t grub_ntfscomp_func;
@@ -429,7 +431,7 @@ read_data (struct grub_ntfs_attr *at, char *pa, char *dest,
   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);
 
@@ -610,6 +612,10 @@ list_file (struct grub_ntfs_file *diro, char *pos,
 
          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)
@@ -880,6 +886,10 @@ grub_ntfs_dir (grub_device_t device, const char *path,
       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);
   }
index c29979edc41115237a23e4edb4fa5fd4ec095a4e..d2893cb9971237bb30c54a5d598c8e965dae8ff8 100644 (file)
@@ -24,6 +24,8 @@
 #include <grub/fshelp.h>
 #include <grub/ntfs.h>
 
+GRUB_MOD_LICENSE ("GPLv3+");
+
 static grub_err_t
 decomp_nextvcn (struct grub_ntfs_comp *cc)
 {
index e922795540a8e926f76ba2ac6fce949866c40d72..d5bc52d14b68012378fe57dfd5efd8a21f6a6e47 100644 (file)
@@ -39,6 +39,8 @@
 #include <grub/types.h>
 #include <grub/fshelp.h>
 
+GRUB_MOD_LICENSE ("GPLv3+");
+
 #define MIN(a, b) \
   ({ typeof (a) _a = (a); \
      typeof (b) _b = (b); \
@@ -222,6 +224,7 @@ struct grub_fshelp_node
   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;
 };
@@ -868,6 +871,7 @@ grub_reiserfs_iterate_dir (grub_fshelp_node_t item,
                                         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;
@@ -914,6 +918,7 @@ grub_reiserfs_iterate_dir (grub_fshelp_node_t item,
                                         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;
@@ -1276,6 +1281,8 @@ grub_reiserfs_dir (grub_device_t device, const char *path,
       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);
     }
diff --git a/grub-core/fs/romfs.c b/grub-core/fs/romfs.c
new file mode 100644 (file)
index 0000000..58dc98f
--- /dev/null
@@ -0,0 +1,460 @@
+/*
+ *  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);
+}
index b49420de12871afa61a4761bddfa3f34736bf493..f1e09ccbd65ece7f2b1882ba62ec20b365816796 100644 (file)
@@ -26,6 +26,8 @@
 #include <grub/types.h>
 #include <grub/fshelp.h>
 
+GRUB_MOD_LICENSE ("GPLv3+");
+
 /* The common header for a block.  */
 struct grub_sfs_bheader
 {
@@ -66,7 +68,7 @@ struct grub_sfs_obj
       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];
@@ -119,6 +121,7 @@ struct grub_fshelp_node
   struct grub_sfs_data *data;
   int block;
   int size;
+  grub_uint32_t mtime;
 };
 
 /* Information about a "mounted" sfs filesystem.  */
@@ -247,7 +250,7 @@ static grub_ssize_t
 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,
@@ -355,10 +358,12 @@ grub_sfs_iterate_dir (grub_fshelp_node_t dir,
   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)
@@ -367,6 +372,7 @@ grub_sfs_iterate_dir (grub_fshelp_node_t dir,
       node->data = data;
       node->size = size;
       node->block = block;
+      node->mtime = mtime;
 
       return hook (name, type, node);
     }
@@ -426,7 +432,7 @@ grub_sfs_iterate_dir (grub_fshelp_node_t dir,
 
          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;
@@ -525,6 +531,8 @@ grub_sfs_dir (grub_device_t device, const char *path,
       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);
     }
diff --git a/grub-core/fs/squash4.c b/grub-core/fs/squash4.c
new file mode 100644 (file)
index 0000000..4f12655
--- /dev/null
@@ -0,0 +1,548 @@
+/* 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);
+}
+
index 1672aab1be085f823a232760d2b021b1b2af922b..e1f1150153bfab96fe94e210cb349f3fb86a562e 100644 (file)
@@ -26,6 +26,9 @@
 #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
@@ -543,8 +546,7 @@ grub_udf_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
     }
 
 fail:
-  if (buf)
-    grub_free (buf);
+  grub_free (buf);
 
   return 0;
 }
@@ -883,6 +885,8 @@ grub_udf_iterate_dir (grub_fshelp_node_t dir,
 
              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,
@@ -910,6 +914,25 @@ grub_udf_iterate_dir (grub_fshelp_node_t dir,
   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,
@@ -928,8 +951,36 @@ grub_udf_dir (grub_device_t device, const char *path,
                                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);
   }
@@ -945,7 +996,8 @@ grub_udf_dir (grub_device_t device, const char *path,
 
   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);
@@ -979,7 +1031,8 @@ grub_udf_open (struct grub_file *file, const char *name)
 
   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;
index 2b1021db65a3587d38a60872d69166a66fd18b20..435fec6a5e80eb94aedea50dfc9e6c7f570853a7 100644 (file)
@@ -25,6 +25,8 @@
 #include <grub/dl.h>
 #include <grub/types.h>
 
+GRUB_MOD_LICENSE ("GPLv3+");
+
 #ifdef MODE_UFS2
 #define GRUB_UFS_MAGIC         0x19540119
 #else
@@ -283,26 +285,29 @@ static grub_ssize_t
 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;
@@ -310,14 +315,14 @@ grub_ufs_read_file (struct grub_ufs_data *data,
       /* 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;
@@ -512,7 +517,7 @@ grub_ufs_find_file (struct grub_ufs_data *data, const char *path)
       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;
 }
 
index 9f8dc28def6ebc5fdbf1aa79e4f0788ca378f554..3dc5e0af052ba3912fdddb8533faa48d8413e6e5 100644 (file)
@@ -26,6 +26,8 @@
 #include <grub/types.h>
 #include <grub/fshelp.h>
 
+GRUB_MOD_LICENSE ("GPLv3+");
+
 #define        XFS_INODE_EXTENTS       9
 
 #define XFS_INODE_FORMAT_INO   1
@@ -98,18 +100,29 @@ struct grub_xfs_btree_root
   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];
@@ -143,7 +156,7 @@ struct grub_xfs_data
   grub_disk_t disk;
   int pos;
   int bsize;
-  int agsize;
+  grub_uint32_t agsize;
   struct grub_fshelp_node diropen;
 };
 
@@ -157,33 +170,67 @@ static grub_dl_t my_mod;
 #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,
@@ -239,13 +286,23 @@ grub_xfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
   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;
@@ -262,12 +319,9 @@ grub_xfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
               grub_free (leaf);
               return 0;
             }
-
           if (grub_disk_read (node->data->disk,
-                              grub_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))
@@ -279,7 +333,11 @@ grub_xfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
 
           nrec = grub_be_to_cpu16 (leaf->numrecs);
           keys = &leaf->keys[0];
-        } 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)
@@ -313,8 +371,7 @@ grub_xfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
         }
     }
 
-  if (leaf)
-    grub_free (leaf);
+  grub_free (leaf);
 
   return GRUB_XFS_FSB_TO_BLOCK(node->data, ret);
 }
@@ -326,7 +383,7 @@ static grub_ssize_t
 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,
@@ -652,6 +709,11 @@ grub_xfs_dir (grub_device_t device, const char *path,
     {
       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);
index 8e83ea0b51426ef63cb6f76c38557053ee45e076..1eea13b263e54b786f295852b7e5fda331edbdca 100644 (file)
@@ -51,6 +51,9 @@
 #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"
 
@@ -161,13 +164,30 @@ struct grub_zfs_data
   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,
@@ -525,7 +545,7 @@ zio_read (blkptr_t * bp, grub_zfs_endian_t endian, void **buf,
   *buf = NULL;
 
   checksum = (grub_zfs_to_cpu64((bp)->blk_prop, endian) >> 40) & 0xff;
-  comp = (grub_zfs_to_cpu64((bp)->blk_prop, endian)>>32) & 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));
index 224a97792a3bcdac2723926ed8632b674b862ab2..1968ed554eb78db2f4f5c826d390a968cefd03ea 100644 (file)
@@ -26,6 +26,8 @@
 #include <grub/dl.h>
 #include <grub/env.h>
 
+GRUB_MOD_LICENSE ("GPLv3+");
+
 static inline void
 print_tabs (int n)
 {
index 023cd10625a0209cdf87073d47799ad8e5182769..4cab8e50ec00cd885dc1984b7f501ca9601a9fc4 100644 (file)
@@ -1,5 +1,6 @@
-#! /bin/sh -e
-#
+#! /bin/sh
+set -e
+
 # Copyright (C) 2010 Free Software Foundation, Inc.
 #
 # This gensymlist.sh is free software; the author
index 4f5184913fce44b07a4cc2706706854ee4f65322..d383f2640e47018370fa88bb64347227710ed03f 100644 (file)
@@ -1,5 +1,6 @@
-#! /bin/sh -e
-#
+#! /bin/sh
+set -e
+
 # Copyright (C) 2010 Free Software Foundation, Inc.
 #
 # This gensymlist.sh is free software; the author
index 0ab56e9cb361a1b69eae485976e1f68f98b44d7b..5f402ea8753bf8bc440124db30f7bd7c4e5ba08d 100644 (file)
@@ -47,7 +47,7 @@ grub_register_exported_symbols (void)
 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[] =
     {
@@ -56,16 +56,16 @@ EOF
 (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
index bef2b083cb06f356ab2fe6d3e25cb8eec9cfeff4..8c039570d421c23c37f5bc73be2d5b13fa6dbc8d 100644 (file)
@@ -30,6 +30,14 @@ main (int argc __attribute__ ((unused)),
   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{"); \
index 84937f19bfe72325b9248abb8e6a17df46d9adda..cca8b901fcc253306a9e7205b08f395efa2c440b 100644 (file)
@@ -28,6 +28,8 @@
 #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 .
index 564a87634d79a232c0b1a700ecf87d2f913dcbcb..2f210e02baf26b758ab6460211ca906c3099d3ca 100644 (file)
@@ -37,6 +37,8 @@
 #include <grub/gfxmenu_view.h>
 #include <grub/time.h>
 
+GRUB_MOD_LICENSE ("GPLv3+");
+
 static grub_gfxmenu_view_t cached_view;
 
 static void 
index 3988f4ba81de106802275f14d4233750b47fa19d..60e4a46de70a27c872fd94991397151eb996dd75 100644 (file)
@@ -101,6 +101,9 @@ image_get_parent (void *vself)
 static grub_err_t
 rescale_image (grub_gui_image_t self)
 {
+  signed width;
+  signed height;
+
   if (! self->raw_bitmap)
     {
       if (self->bitmap)
@@ -111,12 +114,12 @@ rescale_image (grub_gui_image_t self)
       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;
@@ -131,15 +134,15 @@ rescale_image (grub_gui_image_t self)
 
   /* 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.  */
index 15a352f84c25379fb51123b2893a14a30cc74c82..a7dc95afc03bc87b4f573abcd328592bd7300e81 100644 (file)
@@ -48,7 +48,7 @@ struct grub_gui_label
   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;
 };
@@ -107,7 +107,7 @@ label_paint (void *vself, const grub_video_rect_t *region)
   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);
@@ -186,7 +186,7 @@ label_set_property (void *vself, const char *name, const char *value)
     }
   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)
     {
index b6b07dfd6221b02ed949da1790c2652eb5146d3d..2ff6e0f973b6640997b4f0882a1a7b97b9661c4d 100644 (file)
@@ -41,9 +41,9 @@ struct grub_gui_list_impl
   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;
@@ -248,8 +248,10 @@ draw_menu (list_impl_t self, int num_shown_items)
 
       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);
         }
@@ -267,13 +269,13 @@ draw_menu (list_impl_t self, int num_shown_items)
         (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));
@@ -429,7 +431,7 @@ list_set_property (void *vself, const char *name, const char *value)
     }
   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)
     {
@@ -439,7 +441,7 @@ list_set_property (void *vself, const char *name, const char *value)
         }
       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;
         }
@@ -562,7 +564,7 @@ grub_gui_list_new (void)
 {
   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)
@@ -574,7 +576,7 @@ grub_gui_list_new (void)
   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;
index e1b31794fb7810b02c2adb04f825c3db1bcaeacb..db89ccbf77cf0c6500906b4f5d8a8a921168d88a 100644 (file)
@@ -40,10 +40,10 @@ struct grub_gui_progress_bar
   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;
@@ -109,7 +109,7 @@ draw_filled_rect_bar (grub_gui_progress_bar_t self)
   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);
 
@@ -117,12 +117,12 @@ draw_filled_rect_bar (grub_gui_progress_bar_t self)
   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);
 }
@@ -161,7 +161,8 @@ draw_text (grub_gui_progress_bar_t self)
   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;
@@ -298,19 +299,19 @@ progress_bar_set_property (void *vself, const char *name, const char *value)
     }
   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)
     {
@@ -379,9 +380,9 @@ grub_gui_progress_bar_new (void)
   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;
index 8c51e396a692f6cafee55ab87954ec037502fe10..a9a415e312906722930501929c67fe77343e5d0e 100644 (file)
@@ -204,124 +204,3 @@ grub_get_dirname (const char *file_path)
 
   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;
-}
index 0c304ede0f61d7c76077450e240e3b3353dae86f..6990d05d421ed893a7d6c5cc14fa03bbc64433ea 100644 (file)
@@ -257,7 +257,7 @@ grub_gfxmenu_icon_manager_get_icon (grub_gfxmenu_icon_manager_t mgr,
 
   /* 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;
 }
diff --git a/grub-core/gfxmenu/named_colors.c b/grub-core/gfxmenu/named_colors.c
deleted file mode 100644 (file)
index eedbc47..0000000
+++ /dev/null
@@ -1,209 +0,0 @@
-/* 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;
-}
index 3854c6c53c8d2d2b1c9e4a9cdd672e188e983e7f..f9c711d3e455fb735d0a87aae455f58355e48265 100644 (file)
@@ -135,11 +135,11 @@ theme_set_string (grub_gfxmenu_view_t view,
         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;
@@ -170,7 +170,7 @@ theme_set_string (grub_gfxmenu_view_t view,
       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;
index 901cdc8894dfc7476963f2c5fb88e693ca545e68..836a9884df83269c0a3185647251db88cfacd6ae 100644 (file)
@@ -50,8 +50,8 @@ grub_gfxmenu_view_new (const char *theme_path,
 {
   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)
@@ -63,8 +63,8 @@ grub_gfxmenu_view_new (const char *theme_path,
   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;
 
@@ -131,7 +131,7 @@ redraw_background (grub_gfxmenu_view_t view,
     }
   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);
     }
@@ -150,7 +150,7 @@ draw_title (grub_gfxmenu_view_t view)
   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);
 }
 
@@ -244,13 +244,13 @@ draw_message (grub_gfxmenu_view_t view)
     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. */
index 244fe1e6c4f283702a9a98f790d31a221c275057..41ca7f53645011911f544e823788e482b7e9a068 100644 (file)
@@ -178,6 +178,13 @@ set_content_size (grub_gfxmenu_box_t self,
     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)
 {
@@ -288,6 +295,8 @@ grub_gfxmenu_create_box (const char *pixmaps_prefix,
 
   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;
index 77c4c96b1f110b475ade66511fd2cb188bd92a68..2c9e90f7257bdd271599014d14a8dee17bd94b8d 100644 (file)
@@ -26,6 +26,8 @@
 #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)),
index d855311d3a86bdeafc38e65f62caaeaa5ed3848b..f64fac0744d1fbd390fd0e42f7ba45c5a0d66910 100644 (file)
@@ -24,6 +24,8 @@
 #include <grub/normal.h>
 #include <grub/datetime.h>
 
+GRUB_MOD_LICENSE ("GPLv3+");
+
 static char *grub_datetime_names[] =
 {
   "YEAR",
index 891fb78e9226d356d64218e1142d28d9982a3491..adb38af5617bb4ecc7b1e2c48db82f3c2038f21b 100644 (file)
@@ -23,6 +23,9 @@
 #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
@@ -103,7 +106,7 @@ grub_bufio_read (grub_file_t file, char *buf, grub_size_t len)
 {
   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))
index 47df23833af184469ecba004f403d558116486b7..7380221aac76b8a932559f1412c0b93834c6441a 100644 (file)
 #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
@@ -58,6 +62,12 @@ struct grub_gzio
 {
   /* 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.  */
@@ -100,7 +110,7 @@ typedef struct grub_gzio *grub_gzio_t;
 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
@@ -162,7 +172,7 @@ typedef unsigned short ush;
 typedef unsigned long ulg;
 
 static int
-test_header (grub_file_t file)
+test_gzip_header (grub_file_t file)
 {
   struct {
     grub_uint16_t magic;
@@ -225,7 +235,7 @@ test_header (grub_file_t file)
     file->size = grub_le_to_cpu32 (orig_len);
   }
 
-  initialize_tables (file);
+  initialize_tables (gzio);
 
   return 1;
 }
@@ -365,16 +375,34 @@ static ush mask_bits[] =
   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);
@@ -383,11 +411,28 @@ get_byte (grub_file_t file)
   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
@@ -614,7 +659,7 @@ huft_free (struct huft *t)
  */
 
 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 */
@@ -623,7 +668,6 @@ inflate_codes_in_window (grub_file_t file)
   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;
@@ -751,11 +795,10 @@ inflate_codes_in_window (grub_file_t file)
 /* 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 */
@@ -785,11 +828,10 @@ init_stored_block (grub_file_t file)
    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++)
@@ -832,7 +874,7 @@ init_fixed_block (grub_file_t file)
 /* 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;
@@ -845,7 +887,6 @@ init_dynamic_block (grub_file_t file)
   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;
@@ -976,11 +1017,10 @@ init_dynamic_block (grub_file_t file)
 
 
 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;
@@ -1003,13 +1043,13 @@ get_new_block (grub_file_t file)
   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;
@@ -1018,10 +1058,8 @@ get_new_block (grub_file_t file)
 
 
 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;
 
@@ -1036,7 +1074,7 @@ inflate_window (grub_file_t file)
          if (gzio->last_block)
            break;
 
-         get_new_block (file);
+         get_new_block (gzio);
        }
 
       if (gzio->block_type > INFLATE_DYNAMIC)
@@ -1059,7 +1097,7 @@ inflate_window (grub_file_t file)
 
          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--;
            }
 
@@ -1072,7 +1110,7 @@ inflate_window (grub_file_t file)
        *  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);
@@ -1088,12 +1126,10 @@ inflate_window (grub_file_t file)
 
 
 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;
@@ -1138,32 +1174,62 @@ grub_gzio_open (grub_file_t io)
   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
@@ -1171,15 +1237,13 @@ grub_gzio_read (grub_file_t file, char *buf, grub_size_t len)
    *  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;
@@ -1200,6 +1264,12 @@ grub_gzio_read (grub_file_t file, char *buf, grub_size_t len)
   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)
@@ -1217,6 +1287,61 @@ 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 =
diff --git a/grub-core/io/lzopio.c b/grub-core/io/lzopio.c
new file mode 100644 (file)
index 0000000..02a70f4
--- /dev/null
@@ -0,0 +1,564 @@
+/* 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);
+}
index 3daf6a3fe6ce4cd9d5257394361192e5fd32d4f0..1575ca236aca921dcf8d895d84c81d2f4cf35f70 100644 (file)
@@ -24,6 +24,8 @@
 #include <grub/fs.h>
 #include <grub/dl.h>
 
+GRUB_MOD_LICENSE ("GPLv3+");
+
 #include "xz.h"
 #include "xz_stream.h"
 
@@ -46,7 +48,7 @@ static struct grub_fs grub_xzio_fs;
 
 static grub_size_t
 decode_vli (const grub_uint8_t buf[], grub_size_t size_max,
-           grub_uint64_t * num)
+           grub_uint64_t *num)
 {
   if (size_max == 0)
     return 0;
@@ -69,7 +71,7 @@ decode_vli (const grub_uint8_t buf[], grub_size_t size_max,
 }
 
 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;
@@ -90,6 +92,8 @@ static int
 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);
 
@@ -99,7 +103,7 @@ test_header (grub_file_t file)
       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)
     {
@@ -130,8 +134,8 @@ test_footer (grub_file_t file)
   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;
 
@@ -148,8 +152,8 @@ test_footer (grub_file_t file)
                  xzio->file->size - XZ_STREAM_FOOTER_SIZE - backsize);
 
   /* Test index marker.  */
-  if (grub_file_read (xzio->file, &imarker, sizeof (imarker)) !=
-      sizeof (imarker) && imarker != 0x00)
+  if (grub_file_read (xzio->file, &imarker, sizeof (imarker))
+      != sizeof (imarker) && imarker != 0x00)
     goto ERROR;
 
   if (read_vli (xzio->file, &records) <= 0)
index 3db14f50e09c31462948af233fc430d7b3754642..c998d4d4b934c9f57783c7ab1dba367f280a3839 100644 (file)
@@ -26,6 +26,8 @@
 #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)
 {
@@ -35,7 +37,7 @@ 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;
@@ -46,15 +48,19 @@ grub_device_open (const char *name)
   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)
@@ -71,6 +77,12 @@ grub_device_close (grub_device_t device)
   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;
index 807ee4277b1048b4901f5b6fb76d9f46230ad9c4..f296b9d0faabb30a00bf62467be86f573f54ff12 100644 (file)
@@ -46,11 +46,7 @@ static struct grub_disk_cache grub_disk_cache_table[GRUB_DISK_CACHE_NUM];
 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;
 
@@ -123,13 +119,13 @@ grub_disk_cache_fetch (unsigned long dev_id, unsigned long disk_id,
       && 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
 
@@ -207,10 +203,12 @@ int
 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;
 }
@@ -247,6 +245,7 @@ grub_disk_open (const char *name)
   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)
@@ -266,7 +265,6 @@ grub_disk_open (const char *name)
   if (! disk->name)
     goto fail;
 
-
   for (dev = grub_disk_dev_list; dev; dev = dev->next)
     {
       if ((dev->open) (raw, disk) == GRUB_ERR_NONE)
@@ -282,6 +280,14 @@ grub_disk_open (const char *name)
       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;
 
@@ -373,21 +379,110 @@ grub_disk_adjust_range (grub_disk_t disk, grub_disk_addr_t *sector,
       *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, &sector, &offset, size) != GRUB_ERR_NONE)
@@ -399,126 +494,125 @@ grub_disk_read (grub_disk_t disk, grub_disk_addr_t sector,
       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;
 }
@@ -528,25 +622,31 @@ grub_disk_write (grub_disk_t disk, grub_disk_addr_t sector,
                 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, &sector, &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;
@@ -554,7 +654,7 @@ grub_disk_write (grub_disk_t disk, grub_disk_addr_t sector,
            }
          disk->partition = part;
 
-         len = GRUB_DISK_SECTOR_SIZE - real_offset;
+         len = (1 << disk->log_sector_size) - real_offset;
          if (len > size)
            len = size;
 
@@ -565,7 +665,7 @@ grub_disk_write (grub_disk_t disk, grub_disk_addr_t sector,
          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;
@@ -575,8 +675,8 @@ grub_disk_write (grub_disk_t disk, grub_disk_addr_t sector,
          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;
@@ -599,6 +699,8 @@ grub_disk_get_size (grub_disk_t disk)
 {
   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;
 }
index 02d785b9b94d196c4c183ae419b61e8eefb87040..1841bf1f5e1acc8f4dcc3c4815d1b2c3ad10b8b9 100644 (file)
 #define GRUB_MODULES_MACHINE_READONLY
 #endif
 
+#ifdef GRUB_MACHINE_EMU
+#include <sys/mman.h>
+#endif
+
 \f
 
 grub_dl_t grub_dl_head = 0;
@@ -86,6 +90,7 @@ struct grub_symbol
   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;
@@ -110,21 +115,22 @@ grub_symbol_hash (const char *s)
 
 /* 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;
@@ -147,6 +153,7 @@ grub_dl_register_symbol (const char *name, void *addr, grub_dl_t mod)
 
   sym->addr = addr;
   sym->mod = mod;
+  sym->isfunc = isfunc;
 
   k = grub_symbol_hash (name);
   sym->next = grub_symtab[k];
@@ -225,6 +232,48 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e)
 {
   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;
@@ -242,12 +291,9 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e)
            {
              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)
                {
@@ -270,6 +316,14 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e)
          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;
 }
@@ -320,17 +374,20 @@ grub_dl_resolve_symbols (grub_dl_t mod, Elf_Ehdr *e)
          /* 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;
@@ -338,10 +395,21 @@ grub_dl_resolve_symbols (grub_dl_t mod, Elf_Ehdr *e)
        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)
@@ -373,6 +441,38 @@ grub_dl_call_init (grub_dl_t mod)
     (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)
 {
@@ -519,7 +619,16 @@ grub_dl_load_core (void *addr, grub_size_t size)
   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)
@@ -579,13 +688,11 @@ grub_dl_load_file (const char *filename)
   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;
 }
 
@@ -642,8 +749,7 @@ grub_dl_unload (grub_dl_t mod)
     {
       depn = dep->next;
 
-      if (! grub_dl_unref (dep->mod))
-       grub_dl_unload (dep->mod);
+      grub_dl_unload (dep->mod);
 
       grub_free (dep);
     }
index fa1d0c730fab85c9e5d1912b7caa002f46e8f246..9a2c5e64d3eea3193156c1449a1d31c8aafa7c3b 100644 (file)
@@ -24,6 +24,7 @@
 #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>
@@ -162,18 +163,6 @@ grub_exit (void)
   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,
@@ -193,8 +182,8 @@ grub_efi_set_virtual_address_map (grub_efi_uintn_t memory_map_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;
@@ -204,15 +193,20 @@ grub_get_rtc (void)
     /* 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;
@@ -740,3 +734,51 @@ grub_efi_print_device_path (grub_efi_device_path_t *dp)
       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;
+}
index 1b0a872b4cafa03f16e37e58f5fd2c92cbb78b0a..942ab0256b948b65736d5858e36d52fa97044d5d 100644 (file)
 #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 ();
@@ -42,84 +45,28 @@ grub_efi_init (void)
   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
index 56218b4e4615f99cd11fba0c2596bf3ec111eb21..9c7b8cec24e0fa32a2634b7f607e66b5e4e6a87e 100644 (file)
@@ -23,6 +23,9 @@
 #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
diff --git a/grub-core/kern/emu/cache.S b/grub-core/kern/emu/cache.S
deleted file mode 100644 (file)
index abd81c9..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-#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
diff --git a/grub-core/kern/emu/cache.c b/grub-core/kern/emu/cache.c
new file mode 100644 (file)
index 0000000..543e457
--- /dev/null
@@ -0,0 +1,13 @@
+
+#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
+
diff --git a/grub-core/kern/emu/cache_s.S b/grub-core/kern/emu/cache_s.S
new file mode 100644 (file)
index 0000000..8ca695c
--- /dev/null
@@ -0,0 +1,29 @@
+#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
index 70bcae78f7ebacde72c81aa298dab74d784b566a..87317c9168b9253aabd0b382625662cc626ba4d3 100644 (file)
@@ -50,6 +50,15 @@ grub_emu_init (void)
   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)
diff --git a/grub-core/kern/emu/getroot.c b/grub-core/kern/emu/getroot.c
deleted file mode 100644 (file)
index 8f65d92..0000000
+++ /dev/null
@@ -1,876 +0,0 @@
-/* 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;
-}
index f01e21aa07f9c41da49287428654f33a3bf2abc5..23417a64d6a5f7858326cd6e6dce08b18eac8199 100644 (file)
@@ -24,6 +24,7 @@
 #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>
@@ -42,6 +43,7 @@
 
 #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.  */
@@ -104,9 +106,7 @@ struct hd_geometry
 # 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 */
@@ -212,10 +212,14 @@ find_free_slot (void)
 }
 
 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;
@@ -223,6 +227,85 @@ grub_util_biosdisk_iterate (int (*hook) (const char *name))
   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, &sector_size))
+      goto fail;
+# elif defined(__NetBSD__)
+    sector_size = label.d_secsize;
+# else
+    if (ioctl (fd, BLKSSZGET, &sector_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)
 {
@@ -258,142 +341,51 @@ 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)
@@ -401,10 +393,11 @@ 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)
@@ -418,7 +411,7 @@ 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;
@@ -550,7 +543,7 @@ struct linux_partition_cache
 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;
@@ -558,6 +551,7 @@ linux_find_partition (char *dev, unsigned long sector)
   int i;
   char real_dev[PATH_MAX];
   struct linux_partition_cache *cache;
+  int missing = 0;
 
   strcpy(real_dev, dev);
 
@@ -566,6 +560,12 @@ linux_find_partition (char *dev, unsigned long sector)
       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;
@@ -596,7 +596,13 @@ linux_find_partition (char *dev, unsigned long sector)
 
       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);
@@ -623,6 +629,37 @@ linux_find_partition (char *dev, unsigned long sector)
 }
 #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)
 {
@@ -678,6 +715,7 @@ open_device (const grub_disk_t disk, grub_disk_addr_t sector, int flags)
              }
 
            close (data->fd);
+           data->fd = -1;
          }
 
        /* Open the partition.  */
@@ -736,6 +774,7 @@ open_device (const grub_disk_t disk, grub_disk_addr_t sector, int flags)
 #endif
              }
            close (data->fd);
+           data->fd = -1;
        }
 
       fd = open (map[disk->id].device, flags);
@@ -773,44 +812,20 @@ open_device (const grub_disk_t disk, grub_disk_addr_t sector, int 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;
 
@@ -893,19 +908,20 @@ grub_util_biosdisk_read (grub_disk_t disk, grub_disk_addr_t sector,
         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;
@@ -938,13 +954,34 @@ grub_util_biosdisk_write (grub_disk_t disk, grub_disk_addr_t sector,
   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)
 {
@@ -954,13 +991,7 @@ 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);
@@ -1132,6 +1163,54 @@ make_device_name (int drive, int dos_part, int bsd_part)
   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, &params);
+  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)
 {
@@ -1308,9 +1387,40 @@ 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;
            }
@@ -1385,7 +1495,7 @@ 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);
@@ -1544,6 +1654,8 @@ grub_util_biosdisk_get_grub_dev (const char *os_dev)
   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);
@@ -1729,6 +1841,9 @@ grub_util_biosdisk_is_floppy (grub_disk_t disk)
   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)
@@ -1736,7 +1851,12 @@ grub_util_biosdisk_is_floppy (grub_disk_t disk)
 
   /* 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)
index 32e12a079eb4a79736bf6069053b8c6647950bd5..947c669aa8912177a10dd2735986974a7dcf075c 100644 (file)
@@ -15,6 +15,8 @@
 #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
index 0a7645992b10512afcea369ba9a91cb8eba26afc..8d15f17c54ab70cb230a0190228773c4d0136b55 100644 (file)
 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)
@@ -71,11 +67,10 @@ grub_machine_init (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
@@ -110,7 +105,7 @@ usage (int status)
       "\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"
@@ -132,22 +127,24 @@ void grub_emu_init (void);
 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;
@@ -201,27 +198,9 @@ main (int argc, char *argv[])
 
   /* 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)
index c8b95443b22fd2ed6b3b5b98ba31bf7739d196bf..6f5ea9fb9aa50716b8bdfddccd95665948a06de2 100644 (file)
 # 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
@@ -232,7 +224,11 @@ char *
 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;
@@ -242,237 +238,6 @@ canonicalize_file_name (const char *path)
   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)),
index 9d5a51c48d1107d90f5fc08aa77bf8f6859c3c49..f69ef6fd487a6309f2968b3c28bddba6448ba077 100644 (file)
 #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];
 
@@ -148,7 +151,6 @@ grub_file_read (grub_file_t file, void *buf, grub_size_t len)
 
   if (len == 0)
     return 0;
-
   res = (file->fs->read) (file, buf, len);
   if (res > 0)
     file->offset += res;
@@ -179,8 +181,9 @@ grub_file_seek (grub_file_t file, grub_off_t offset)
                  "attempt to seek outside of the file");
       return -1;
     }
-
+  
   old = file->offset;
   file->offset = offset;
+    
   return old;
 }
index cf800f4cc4c92ae89f04478bba2ec16dad0b67e4..14d389e07b457f86ab08ee84198852868cf15544 100644 (file)
@@ -94,7 +94,7 @@ grub_fs_probe (grub_device_t device)
          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");
index 434b9b5a83930b21098324cda75c6d391fb27339..b7510ff98b5d6fcb55b8e0e60c86c3fb69ba03bc 100644 (file)
@@ -56,10 +56,18 @@ grub_exit (void)
     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.  */
@@ -107,10 +115,9 @@ grub_machine_init (void)
 }
 
 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
@@ -119,14 +126,3 @@ grub_machine_fini (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
-}
index cac023ddffa32b6dd30e387c438aa8e389108a7d..5e7767bb96534f85847c9ded6f70f465eedf472f 100644 (file)
@@ -40,21 +40,6 @@ 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
-
 /*
  *  Support for booting GRUB from a Multiboot boot loader (e.g. GRUB itself).
  */
@@ -87,3 +72,4 @@ codestart:
  */
 #include "../realmode.S"
 
+#include "../int.S"
index f73f828c6ef5da6502980cbf4ceaead31ef39a32..6bd8f3e87854dac53f3d8e007b9b9befe40492e6 100644 (file)
@@ -39,9 +39,3 @@ grub_machine_fini (void)
 {
   grub_efi_fini ();
 }
-
-void
-grub_machine_set_prefix (void)
-{
-  grub_efi_set_prefix ();
-}
index 5b464ab83c3fe70048785053b238fa834adcc795..0f904d7b38c2e9c78f0ea5181395bf5aff13ba1a 100644 (file)
@@ -41,17 +41,6 @@ _start:
          *  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.
@@ -62,5 +51,3 @@ codestart:
        movl    %eax, EXT_C(grub_efi_system_table)
        call    EXT_C(grub_main)
        ret
-
-#include "../realmode.S"
index 82087323b5137fcc4ae4da121311edd5281b436f..245583bdb7133c4cf8f08745d12d44dc5c30311c 100644 (file)
 
 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"
-
diff --git a/grub-core/kern/i386/int.S b/grub-core/kern/i386/int.S
new file mode 100644 (file)
index 0000000..58ccfda
--- /dev/null
@@ -0,0 +1,140 @@
+/*
+ *  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
index d8c337bdee7aa85331eb46e736aa9236c6115d73..62269de781200aef86cf0afa07b7b4fce1e061ce 100644 (file)
@@ -45,52 +45,41 @@ struct mem_region
 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.  */
@@ -140,6 +129,8 @@ compact_mem_regions (void)
       }
 }
 
+grub_addr_t grub_modbase;
+
 void
 grub_machine_init (void)
 {
@@ -148,6 +139,9 @@ 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 ();
 
@@ -211,24 +205,9 @@ grub_machine_init (void)
   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);
-}
index e78a0aa9aacb5a7cb429c66ce2e7b4811275b480..a70a2a7db29e5efe16f30aa8e21ac3bc2b7ef856 100644 (file)
@@ -455,17 +455,6 @@ gate_a20_check_state:
  */
        . = _start + GRUB_KERNEL_MACHINE_RAW_SIZE
 
-       . = _start + GRUB_KERNEL_MACHINE_PREFIX
-VARIABLE(grub_prefix)
-       /* to be filled by grub-mkimage */
-
-       /*
-        *  Leave some breathing room for the prefix.
-        */
-       . = _start + GRUB_KERNEL_MACHINE_PREFIX_END
-
-
-
 /*
  * grub_exit()
  *
@@ -476,7 +465,10 @@ FUNCTION(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
 
 /*
@@ -910,102 +902,4 @@ FUNCTION(grub_pxe_call)
        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"
diff --git a/grub-core/kern/i386/qemu/init.c b/grub-core/kern/i386/qemu/init.c
deleted file mode 100644 (file)
index 054dfa8..0000000
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- *  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);
-}
index 208f36b7e3a6b1eef01e8f7b423583e1c5c88e9b..2b0c7f6a7b6bf883fb46ad25e01378dcb1e892e4 100644 (file)
@@ -41,8 +41,11 @@ static grub_uint64_t mem_size, above_4g;
 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... */
@@ -50,15 +53,19 @@ grub_machine_mmap_init ()
     }
   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
index 7834d1df57af52b0c6e7dd3cf73279b60e4fc5ed..6500de6203fd4ba8a247ca92a7554ebf19b7864d 100644 (file)
@@ -34,14 +34,6 @@ VARIABLE(grub_core_entry_addr)
        .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.
index 578c8d2a8bbcf378ea7380aaab779010bfa1748e..3e8a13892aa3a503f37fdf1d30deb4cc069359d9 100644 (file)
@@ -225,18 +225,3 @@ realcseg:
        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
diff --git a/grub-core/kern/ia64/dl.c b/grub-core/kern/ia64/dl.c
new file mode 100644 (file)
index 0000000..3904f73
--- /dev/null
@@ -0,0 +1,276 @@
+/* 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;
+}
diff --git a/grub-core/kern/ia64/dl_helper.c b/grub-core/kern/ia64/dl_helper.c
new file mode 100644 (file)
index 0000000..91f2802
--- /dev/null
@@ -0,0 +1,73 @@
+/* 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;
+}
+
diff --git a/grub-core/kern/ia64/efi/init.c b/grub-core/kern/ia64/efi/init.c
new file mode 100644 (file)
index 0000000..e2fa580
--- /dev/null
@@ -0,0 +1,54 @@
+/* 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;;");
+}
diff --git a/grub-core/kern/ia64/efi/startup.S b/grub-core/kern/ia64/efi/startup.S
new file mode 100644 (file)
index 0000000..d75c6d7
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ *  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
index 2fbe809b23c3288a6737e3ee94572905071f6d65..9e80757f42cedbe892a4086cff83e20c70622c3d 100644 (file)
@@ -60,6 +60,10 @@ grub_ieee1275_find_options (void)
   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);
index 682a8b5a44cd6b9d4d20cc1add919574784aa20e..76f932d099d2c2be15d0a10668645d893c93e393 100644 (file)
 #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)
 {
@@ -68,37 +76,51 @@ grub_translate_ieee1275_path (char *filepath)
     }
 }
 
+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.  */
@@ -107,23 +129,22 @@ grub_machine_set_prefix (void)
          *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;
 
@@ -191,23 +212,14 @@ static void grub_claim_heap (void)
   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)
@@ -240,6 +252,26 @@ grub_machine_init (void)
            }
        }
     }
+}
+
+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);
 }
@@ -266,9 +298,3 @@ grub_get_rtc (void)
 {
   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);
-}
index f5dc8efb1bd6ad1194c2391e79be8b1ac581d93a..23065e3e3117c24cba855de54b8e1cc2e19f2b73 100644 (file)
 #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.  */
@@ -317,14 +320,9 @@ grub_ieee1275_parse_args (const char *path, enum grub_ieee1275_parse_type ptype)
 {
   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))
@@ -339,48 +337,92 @@ grub_ieee1275_parse_args (const char *path, enum grub_ieee1275_parse_type ptype)
       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)
 {
@@ -414,16 +456,6 @@ grub_ieee1275_encode_devname (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)
@@ -467,3 +499,4 @@ grub_ieee1275_canonicalise_devname (const char *path)
   grub_free (buf);
   return NULL;
 }
+
index da7123234fb00e28f89a9222f45d3e13f74ec5c7..77be114220cb3dd44182cab98a33845400d6aa32 100644 (file)
 #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
 
@@ -76,42 +51,36 @@ grub_modules_get_end (void)
 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
@@ -129,27 +98,81 @@ grub_env_write_root (struct grub_env_var *var __attribute__ ((unused)),
   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.  */
@@ -159,7 +182,7 @@ grub_load_normal_mode (void)
   /* 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;
 
@@ -187,8 +210,7 @@ grub_main (void)
 
   /* 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");
 
diff --git a/grub-core/kern/mips/arc/init.c b/grub-core/kern/mips/arc/init.c
new file mode 100644 (file)
index 0000000..ec0fa52
--- /dev/null
@@ -0,0 +1,197 @@
+/*
+ *  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);
+}
+
index 999872f6b53dc57ec2c33e34c52d6dfd227de895..a4aa06fb099c329f60b566804b5f41bf463d8ee7 100644 (file)
@@ -8,3 +8,38 @@ FUNCTION (grub_cpu_flush_cache)
 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
index 11096c0353d0f21272478b7d5190747d1ce9b147..c03c337b584615b60d3157a5de68ccc9ea479d97 100644 (file)
@@ -9,15 +9,22 @@
        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
index 485955e7fde449bf049f6d9523de8071fcfb26d0..ad934068386036d0465c17df19dbc69cd5dfc618 100644 (file)
@@ -34,7 +34,7 @@ grub_arch_dl_check_header (void *ehdr)
   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)
@@ -144,14 +144,14 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr)
                 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)
@@ -163,7 +163,11 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr)
                    {
                      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. 
                       */
@@ -175,13 +179,20 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr)
                            && 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:
@@ -208,11 +219,16 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr)
                  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);
@@ -232,6 +248,6 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr)
 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);
 }
 
index f220108d489b55784f359698d360e7af1dea550d..353f679e60c54902712f916327ca9397ecf0eada 100644 (file)
 
 #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;
 }
diff --git a/grub-core/kern/mips/loongson/init.c b/grub-core/kern/mips/loongson/init.c
new file mode 100644 (file)
index 0000000..6ddf151
--- /dev/null
@@ -0,0 +1,270 @@
+/*
+ *  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;
+
diff --git a/grub-core/kern/mips/qemu-mips/init.c b/grub-core/kern/mips/qemu-mips/init.c
deleted file mode 100644 (file)
index f2bb652..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-#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;
-}
diff --git a/grub-core/kern/mips/qemu_mips/init.c b/grub-core/kern/mips/qemu_mips/init.c
new file mode 100644 (file)
index 0000000..d331e1b
--- /dev/null
@@ -0,0 +1,111 @@
+#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;
+
index ae0e0b187a3cb7f21cb3483c7a224d0314d34b26..2476038bc0478b6504a07ea7d94d2fdaa57e0270 100644 (file)
@@ -20,6 +20,7 @@
 #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    
@@ -35,22 +36,10 @@ start:
        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)
@@ -59,21 +48,32 @@ VARIABLE (grub_arch_memsize)
        .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)
        
@@ -103,6 +103,7 @@ modulesmovcont:
        b modulesmovcont
         addiu $t3, $t3, -1
 modulesmovdone:
+#endif
 
        /* Clean BSS.  */
        
diff --git a/grub-core/kern/mips/yeeloong/init.c b/grub-core/kern/mips/yeeloong/init.c
deleted file mode 100644 (file)
index 7a48d69..0000000
+++ /dev/null
@@ -1,253 +0,0 @@
-/*
- *  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);
-}
-
index 37ce8decdc9d5951637345cbcc5c410169eb3069..ebf80f100eaa4db74a93a42634973f969d37db05 100644 (file)
@@ -210,6 +210,7 @@ grub_vprintf (const char *fmt, va_list args)
          buf[PREALLOC_SIZE - 2] = '.';
          buf[PREALLOC_SIZE - 1] = '.';
          buf[PREALLOC_SIZE] = 0;
+         curbuf = buf;
        }
       else
        s = grub_vsnprintf_real (curbuf, s, fmt, ap2);
@@ -597,23 +598,23 @@ grub_reverse (char *str)
 
 /* 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--)
@@ -666,7 +667,7 @@ grub_lltoa (char *str, int c, unsigned long long n)
     /* BASE == 10 */
     do
       {
-       unsigned m;
+       grub_uint64_t m;
 
        n = grub_divmod64 (n, 10, &m);
        *p++ = m + '0';
index 8d9b5db78ad6ccb9c1132f447c1893b356b3cd14..ee4d58d817ca8851f3e50b0c54b8b46e54bf3550 100644 (file)
@@ -311,11 +311,13 @@ grub_memalign (grub_size_t align, grub_size_t size)
       count++;
       goto again;
 
+#if 0
     case 1:
       /* Unload unneeded modules.  */
       grub_dl_unload_unneeded ();
       count++;
       goto again;
+#endif
 
     default:
       break;
@@ -513,7 +515,7 @@ grub_debug_malloc (const char *file, int line, grub_size_t size)
   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);
@@ -526,7 +528,7 @@ grub_debug_zalloc (const char *file, int line, grub_size_t size)
   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);
@@ -545,7 +547,7 @@ void *
 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);
@@ -559,8 +561,8 @@ grub_debug_memalign (const char *file, int line, grub_size_t align,
   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);
index 0b1c233465a2ad58ad6eb4f77a198ca621a864e2..b26c47edbaca7984e1bed93702d23f67d1589a36 100644 (file)
        .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
 
index cebdca2b60e67022a8bd75b676f7ab5f0e1a0c83..1466a56f8a12a512d1d91f69ca531b5e2508eaa4 100644 (file)
@@ -35,14 +35,6 @@ VARIABLE(grub_kernel_image_size)
        .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.
diff --git a/grub-core/kern/sparc64/ieee1275/init.c b/grub-core/kern/sparc64/ieee1275/init.c
deleted file mode 100644 (file)
index 72ee1f1..0000000
+++ /dev/null
@@ -1,174 +0,0 @@
-/*  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 ();
-}
index 7b3593161bf660174ee2a0e13bb438a8f41054c4..d7c65dd8242ebda9c5f2ab3cf8cf889fb01ee6e2 100644 (file)
@@ -29,6 +29,7 @@ struct grub_term_output *grub_term_outputs;
 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
@@ -91,6 +92,9 @@ grub_checkkey (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);
diff --git a/grub-core/kern/vga_init.c b/grub-core/kern/vga_init.c
new file mode 100644 (file)
index 0000000..889d012
--- /dev/null
@@ -0,0 +1,162 @@
+/*
+ *  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);
+}
index aae267872a6c24f703f6327127c6f83d373aa368..cc2c8aa05881a589dc56d4ed54ec6696cc5ca3e5 100644 (file)
@@ -95,6 +95,20 @@ FUNCTION(efi_wrap_6)
        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
index fb4fc7b64b6d66bcf105a35afba9568a080c3c50..37efde7fcf78169e95f89ebd7bf3a533238d638f 100644 (file)
@@ -39,21 +39,6 @@ _start:
         . = _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)
diff --git a/grub-core/lib/adler32.c b/grub-core/lib/adler32.c
new file mode 100644 (file)
index 0000000..6fb0b00
--- /dev/null
@@ -0,0 +1,151 @@
+/* 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);
+}
diff --git a/grub-core/lib/arc/datetime.c b/grub-core/lib/arc/datetime.c
new file mode 100644 (file)
index 0000000..b8d910e
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ *  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");
+}
index 8db60b48cc5da536ad6e00e460003928e2b1780c..86cd911804281ea24feaa21556e68b6756dcfec0 100644 (file)
 
 #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);
 
@@ -51,7 +68,9 @@ grub_get_datetime (struct grub_datetime *datetime)
 
   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);
@@ -68,13 +87,18 @@ grub_get_datetime (struct grub_datetime *datetime)
 
   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);
 
@@ -84,12 +108,15 @@ grub_get_datetime (struct grub_datetime *datetime)
 }
 
 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);
 
@@ -99,21 +126,27 @@ grub_set_datetime (struct grub_datetime *datetime)
   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;
 
@@ -135,21 +168,27 @@ grub_set_datetime (struct grub_datetime *datetime)
   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;
 }
diff --git a/grub-core/lib/crc.c b/grub-core/lib/crc.c
new file mode 100644 (file)
index 0000000..ffc3ef3
--- /dev/null
@@ -0,0 +1,75 @@
+/* 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;
+}
index f5768b8b5e6a3522e767ee5cf8d71258cd74a744..8876cc32695435b16b57a9ba7ed1c1560eed5333 100644 (file)
 #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
 {
@@ -183,9 +193,10 @@ grub_crypto_xor (void *out, const void *in1, const void *in2, grub_size_t size)
 
 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)
@@ -239,10 +250,11 @@ grub_crypto_cbc_encrypt (grub_crypto_cipher_handle_t cipher,
 
 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;
@@ -333,7 +345,8 @@ grub_crypto_hmac_init (const struct gcry_md_spec *md,
 }
 
 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);
@@ -375,7 +388,7 @@ 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)
 {
   struct grub_crypto_hmac_handle *hnd;
 
@@ -411,10 +424,43 @@ grub_crypto_memcmp (const void *a, const void *b, grub_size_t n)
   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;
 
@@ -449,5 +495,5 @@ grub_password_get (char buf[], unsigned buf_size)
   grub_refresh ();
 
   return (key != '\e');
-}
 #endif
+}
index 0a91c345a88d818e960a196d48997368ab211c36..0fd1b5fbd615cfec38fd96f34b384e0c48480eb8 100644 (file)
@@ -22,6 +22,9 @@
 #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)
index c195368975909bd9c99bd317d45c590722871597..5ebf2cd1d1e0ba7ae1ba52ca5b484b4faec331b6 100644 (file)
@@ -28,7 +28,9 @@ void
 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);
 
diff --git a/grub-core/lib/efi/reboot.c b/grub-core/lib/efi/reboot.c
new file mode 100644 (file)
index 0000000..9382370
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ *  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 (;;) ;
+}
diff --git a/grub-core/lib/i386/reboot.c b/grub-core/lib/i386/reboot.c
new file mode 100644 (file)
index 0000000..ef28f7f
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ *  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);
+}
+
diff --git a/grub-core/lib/i386/reboot_trampoline.S b/grub-core/lib/i386/reboot_trampoline.S
new file mode 100644 (file)
index 0000000..18bcfb2
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ *  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)
index 1bc4240c360a0b1f2dff50af8ebcfb75442dd0bc..2f10feb5e9344bf7a2b09722a98fe76eea4bf368 100644 (file)
@@ -50,6 +50,7 @@ extern grub_uint16_t grub_relocator16_gs;
 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;
@@ -212,6 +213,7 @@ grub_relocator16_boot (struct grub_relocator *rel,
   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,
index c3768f4eb3e0a3399d6109ed666ab50470594bdb..d6673fade12473a9fcabcc1dcdaefde88d49d2fe 100644 (file)
@@ -130,13 +130,18 @@ VARIABLE(grub_relocator16_ss)
        .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
index a2002ae3d49c9d043a283bfdfa8961d4b33efb91..5b7aa158bcf0f53e1c2202851c8dd42a9e6c16a7 100644 (file)
  */
 
 #include <grub/symbol.h>
+#include <grub/dl.h>
 
        .file   "setjmp.S"
 
+GRUB_MOD_LICENSE ("GPLv3+")
+
        .text
 
 /*
diff --git a/grub-core/lib/ia64/longjmp.S b/grub-core/lib/ia64/longjmp.S
new file mode 100644 (file)
index 0000000..729bdc7
--- /dev/null
@@ -0,0 +1,162 @@
+/* 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
diff --git a/grub-core/lib/ia64/setjmp.S b/grub-core/lib/ia64/setjmp.S
new file mode 100644 (file)
index 0000000..190623d
--- /dev/null
@@ -0,0 +1,177 @@
+/* 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
diff --git a/grub-core/lib/ieee1275/cmos.c b/grub-core/lib/ieee1275/cmos.c
new file mode 100644 (file)
index 0000000..fa57db9
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ *  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;
+}
index 7e6f8d1f16515d3ff9f3c4539ec87cb9f9c61aa3..1947135fe01d1f1ab432c994725a851f732a8a61 100644 (file)
 #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)
@@ -39,6 +46,8 @@ find_rtc (void)
   }
   
   grub_ieee1275_devices_iterate (hook);
+  if (!rtc)
+    no_ieee1275_rtc = 1;
 }
 
 grub_err_t
@@ -61,10 +70,12 @@ grub_get_datetime (struct grub_datetime *datetime)
   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)
@@ -111,10 +122,12 @@ grub_set_datetime (struct grub_datetime *datetime)
   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)
diff --git a/grub-core/lib/ieee1275/reboot.c b/grub-core/lib/ieee1275/reboot.c
new file mode 100644 (file)
index 0000000..91c8779
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ *  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 (;;) ;
+}
index 0248490558d762fe512159b79c69c8f68ae4ef8b..659fa7061a9ec7db0bb671ba7fb980e64114ede7 100644 (file)
@@ -680,7 +680,10 @@ grub_legacy_parse (const char *buf, char **entryname, char **suffix)
              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++)
diff --git a/grub-core/lib/minilzo/lzoconf.h b/grub-core/lib/minilzo/lzoconf.h
new file mode 100644 (file)
index 0000000..1d0fe14
--- /dev/null
@@ -0,0 +1,446 @@
+/* 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: */
diff --git a/grub-core/lib/minilzo/lzodefs.h b/grub-core/lib/minilzo/lzodefs.h
new file mode 100644 (file)
index 0000000..0e40e33
--- /dev/null
@@ -0,0 +1,1852 @@
+/* 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: */
diff --git a/grub-core/lib/minilzo/minilzo.c b/grub-core/lib/minilzo/minilzo.c
new file mode 100644 (file)
index 0000000..25a1f68
--- /dev/null
@@ -0,0 +1,4562 @@
+/* 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 *****/
+
diff --git a/grub-core/lib/minilzo/minilzo.h b/grub-core/lib/minilzo/minilzo.h
new file mode 100644 (file)
index 0000000..74fefa9
--- /dev/null
@@ -0,0 +1,109 @@
+/* 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 */
+
diff --git a/grub-core/lib/mips/arc/reboot.c b/grub-core/lib/mips/arc/reboot.c
new file mode 100644 (file)
index 0000000..f0d0857
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ *  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);
+}
diff --git a/grub-core/lib/mips/loongson/reboot.c b/grub-core/lib/mips/loongson/reboot.c
new file mode 100644 (file)
index 0000000..f099ba2
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ *  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);
+}
diff --git a/grub-core/lib/mips/qemu_mips/reboot.c b/grub-core/lib/mips/qemu_mips/reboot.c
new file mode 100644 (file)
index 0000000..a5c41ee
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ *  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);
+}
index 8ab6222c4e90991fa33c493e6b0f9f99c0602567..8259c9d22328b770e6bc66555ec09aaa05b1caa0 100644 (file)
  */
 
 #include <grub/symbol.h>
+#include <grub/dl.h>
 
        .file   "setjmp.S"
 
+GRUB_MOD_LICENSE ("GPLv3+")
+
        .text
 
 /*
index 083446ab9ddecfe6882dc4be63a1f06c0476a71f..09b8c7360dcb4ca9dc88de95ca5380f6da1343a5 100644 (file)
@@ -21,6 +21,9 @@
 #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,
index 2dc3e53e9dba59b05cd8c1f509edc6fe457123ae..9589778b6af340bd928b3da9d0d71def06499816 100644 (file)
@@ -54,8 +54,7 @@ isupper (int c)
 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 
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..fe8523e685f8a9ecef462da097ebb2412463c1fb 100644 (file)
@@ -0,0 +1,31 @@
+/*
+ *  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
index 69e49509eef1fd5a92a11c67e1c3378cddda1697..0c58d6c44152644e7da0387f25d1cacc1d334a0c 100644 (file)
@@ -24,9 +24,6 @@
 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;
index 25cbaa3e93707b99d11a3500aaac6c79cddce923..8c7540e3c9c1f4f0665c9c5db604fe3ef2918080 100644 (file)
  */
 
 #include <grub/symbol.h>
+#include <grub/dl.h>
 
        .file   "setjmp.S"
 
+GRUB_MOD_LICENSE ("GPLv3+")
+
        .text
 
 /*
index e500ba32dbdd575906ee87d9072f4e03a39b0a3a..365b7600339151043509ca2e1283e5212801306c 100644 (file)
@@ -265,6 +265,27 @@ rs_recover (gf_single_t *m, grub_size_t s, grub_size_t rs)
 
   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;
 
@@ -275,14 +296,6 @@ rs_recover (gf_single_t *m, grub_size_t s, grub_size_t rs)
     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];
@@ -504,6 +517,7 @@ main (int argc, char **argv)
   rs = s / 3;
   buf = xmalloc (s + rs + SECTOR_SIZE);
   fread (buf, 1, s, in);
+  fclose (in);
 
   grub_reed_solomon_add_redundancy (buf, s, rs);
 
index 3642de9dc639708dc97212982d892370229a639d..aa404731f6b6b370016a1d2ffed4cca99e3f092c 100644 (file)
@@ -22,6 +22,9 @@
 #include <grub/misc.h>
 #include <grub/cache.h>
 #include <grub/memory.h>
+#include <grub/dl.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
 
 struct grub_relocator
 {
@@ -761,6 +764,9 @@ malloc_in_range (struct grub_relocator *rel,
     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++)
@@ -852,7 +858,7 @@ malloc_in_range (struct grub_relocator *rel,
                      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,
@@ -907,6 +913,7 @@ malloc_in_range (struct grub_relocator *rel,
 #if GRUB_RELOCATOR_HAVE_LEFTOVERS
          case REG_LEFTOVER_START:
            fwlefto++;
+           last_lo = j;
            break;
 
          case REG_LEFTOVER_END:
@@ -1006,7 +1013,8 @@ malloc_in_range (struct grub_relocator *rel,
                        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;
@@ -1018,7 +1026,6 @@ malloc_in_range (struct grub_relocator *rel,
                      = 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;
@@ -1078,10 +1085,8 @@ malloc_in_range (struct grub_relocator *rel,
                      curschu->pre = lo1;
                      curschu->post = lo2;
                    }
-#endif
                  }
 
-#if GRUB_RELOCATOR_HAVE_LEFTOVERS
                if (typepre == CHUNK_TYPE_LEFTOVER)
                  {
                    curschu->pre = events[last_start].leftover;
@@ -1089,7 +1094,6 @@ malloc_in_range (struct grub_relocator *rel,
                  }
 #endif
 
-#endif
                if (!oom)
                  cural++;
                else
index c39c91b9c30db73f24e2d1de94adc2d88964ea5c..b04fd7439b58bbb9a38ffbbe9ecd64e8ab9d2600 100644 (file)
@@ -8,6 +8,8 @@
 #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
index 0e23ecfa15262629706cd5851c3e3cbfc637151f..5c2ec2cf3a4fcb4ff1828d115ad10683e5215005 100644 (file)
  */
 
 #include <grub/symbol.h>
+#include <grub/dl.h>
 
         .file   "setjmp.S"
 
+GRUB_MOD_LICENSE ("GPLv3+")
+
         .text
 
 /*
index 621b09b93ec818ab1171a79b06ea2cd3ab950a81..b1f1b22cb26340835db6a0c97faf81a439e8e204 100644 (file)
  */
 
 #include <grub/symbol.h>
+#include <grub/dl.h>
 
        .file   "setjmp.S"
 
+GRUB_MOD_LICENSE ("GPLv3+")
+
        .text
 
 /*
index 611960f9274e43fa8530c3cbcce2605f4e72fc9c..69bf6e6adb9efdb7bc3af692f7cd024741ca6544 100644 (file)
@@ -21,6 +21,8 @@
 #include <grub/misc.h>
 #include <grub/aout.h>
 
+GRUB_MOD_LICENSE ("GPLv3+");
+
 int
 grub_aout_get_type (union grub_aout_header *header)
 {
index dc42683a6536ccffcf5222139e347d948e7ed0e0..db57a573c30dc941ba11faeab5a0acfa11c4a944 100644 (file)
@@ -27,6 +27,8 @@
 #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;
@@ -67,165 +69,60 @@ struct piwg_full_device_path
   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
 {
@@ -240,6 +137,7 @@ struct devdata devs[] =
   {"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},
 };
 
index a095ad9317b09325c70fc0b587a86f40910c565d..3ecdca5340d5dcc5b32be96588b23457c7b5989a 100644 (file)
@@ -35,6 +35,8 @@
 #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;
@@ -55,6 +57,7 @@ grub_chainloader_unload (void)
   grub_free (file_path);
   grub_free (cmdline);
   cmdline = 0;
+  file_path = 0;
 
   grub_dl_unref (my_mod);
   return GRUB_ERR_NONE;
@@ -66,7 +69,7 @@ grub_chainloader_boot (void)
   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);
@@ -93,7 +96,7 @@ grub_chainloader_boot (void)
   if (exit_data)
     efi_call_1 (b->free_pool, exit_data);
 
-  grub_chainloader_unload ();
+  grub_loader_unset ();
 
   return grub_errno;
 }
@@ -236,6 +239,11 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
   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,
@@ -321,8 +329,7 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
   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);
index ecd5bd5cd1b8986de7f15189134bf05de67ee8ad..18ebeb760be9194ee49afba1d4fd0053dfb84505 100644 (file)
 #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
@@ -944,6 +948,86 @@ grub_netbsd_add_modules (void)
   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)
 {
@@ -1320,6 +1404,11 @@ grub_bsd_load (int argc, char *argv[])
     goto fail;
 
   relocator = grub_relocator_new ();
+  if (!relocator)
+    {
+      grub_file_close (file);
+      goto fail;
+    }
 
   elf = grub_elf_file (file);
   if (elf)
@@ -1341,7 +1430,7 @@ grub_bsd_load (int argc, char *argv[])
 fail:
 
   if (grub_errno != GRUB_ERR_NONE)
-    grub_dl_unref (my_mod);
+    grub_dl_unref (my_mod);    
 
   return grub_errno;
 }
@@ -1600,6 +1689,8 @@ grub_cmd_netbsd (grub_extcmd_context_t ctxt, int argc, char *argv[])
          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);
     }
 
diff --git a/grub-core/loader/i386/coreboot/chainloader.c b/grub-core/loader/i386/coreboot/chainloader.c
new file mode 100644 (file)
index 0000000..3f85aa3
--- /dev/null
@@ -0,0 +1,145 @@
+/*
+ *  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 ();
+}
index 0178e2fd48e3b652985b26ef588a23f7f74611bf..fded7bb0ad97df728fb086842e9774d2a4655078 100644 (file)
@@ -35,6 +35,8 @@
 #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;
 
@@ -72,6 +76,7 @@ static grub_uint32_t prot_mode_pages;
 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
@@ -187,7 +192,7 @@ allocate_pages (grub_size_t prot_size)
   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 ();
 
@@ -365,9 +370,11 @@ grub_linux_setup_video (struct linux_kernel_params *params)
 
          /* 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:
@@ -480,12 +487,22 @@ grub_linux_boot (void)
       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 ();
@@ -547,6 +564,7 @@ grub_linux_boot (void)
 #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);
@@ -554,23 +572,24 @@ grub_linux_boot (void)
       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;
       }
   }
@@ -658,6 +677,14 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
       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).  */
@@ -671,7 +698,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
     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 (&params->setup_sects, &lh.setup_sects, sizeof (lh) - 0x1F1);
 
   params->ps_mouse = params->padding10 =  0;
@@ -866,7 +893,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
   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;
index bef534296f28408da5b1303690c6e0258b70d717..abd4ae96decde49f77328ec19cb6a2aa9021a6f4 100644 (file)
@@ -33,6 +33,7 @@
 #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
@@ -194,7 +195,10 @@ grub_multiboot_load (grub_file_t file)
 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)
@@ -205,6 +209,15 @@ grub_multiboot_get_mbi_size (void)
     + 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.  */
@@ -530,6 +543,20 @@ grub_multiboot_make_mbi (grub_uint32_t *target)
       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;
index fd99c81d583b1a32775be3d4e3491e390be9184e..8d6ec8f2012e3b3aaddc7208b0e4aa2299637f3d 100644 (file)
 #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)
 {
@@ -59,6 +69,63 @@ grub_chainloader_unload (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)
 {
@@ -119,6 +186,9 @@ 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);
  
@@ -145,11 +215,23 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
 {
   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)
@@ -165,7 +247,8 @@ static grub_command_t cmd;
 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;
 }
 
diff --git a/grub-core/loader/i386/pc/freedos.c b/grub-core/loader/i386/pc/freedos.c
new file mode 100644 (file)
index 0000000..f796e08
--- /dev/null
@@ -0,0 +1,138 @@
+/* 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);
+}
index 96d00f927195bd16ef56ca2f6a0116e386ff14ca..adc6e8b995be3265e5df3ee3d6963998447b3bd9 100644 (file)
@@ -36,8 +36,9 @@
 #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;
 
@@ -47,6 +48,7 @@ static struct grub_relocator *relocator = NULL;
 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)
@@ -126,15 +128,20 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
   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;
@@ -151,7 +158,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
        {
          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
@@ -183,12 +191,13 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
       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;
     }
@@ -261,7 +270,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
     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);
@@ -292,7 +302,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
   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)
index 0c33a068049de230be23710820b81804bb8029d4..b2909c191834cffe267e435a744dae1cd06834e2 100644 (file)
@@ -32,6 +32,9 @@
 #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;
@@ -110,6 +113,7 @@ grub_cmd_ntldr (grub_command_t cmd __attribute__ ((unused)),
          grub_device_close (dev);
          goto fail;
        }
+      grub_chainloader_patch_bpb (bs, dev, edx);
     }
 
   if (dev)
index b877b0ea5ef76872b7563c6b5ca475c45fbd91df..6128ec384c55e35462d53ee97c7ecdaa075b6844 100644 (file)
@@ -452,11 +452,11 @@ grub_cpu_xnu_fill_devprop (void)
     }
 
   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;
diff --git a/grub-core/loader/ia64/efi/linux.c b/grub-core/loader/ia64/efi/linux.c
new file mode 100644 (file)
index 0000000..247eeba
--- /dev/null
@@ -0,0 +1,797 @@
+/*
+ *  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);
+}
index 9accfc2705caeb9ca7d0890ed762afc002bcf583..2b48759835f60c7ccabe186b1e28dd69192561aa 100644 (file)
 #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;
@@ -49,9 +55,16 @@ static grub_size_t linux_size;
 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
@@ -59,11 +72,43 @@ grub_linux_boot (void)
 {
   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);
 
@@ -76,6 +121,11 @@ grub_linux_unload (void)
   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;
@@ -195,12 +245,18 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
                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");
@@ -220,9 +276,12 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
   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.  */
@@ -237,8 +296,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
   /* 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.  */
@@ -252,6 +311,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
     + 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);
@@ -266,6 +326,20 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
   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);
@@ -277,14 +351,20 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
   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++)
@@ -311,6 +391,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
 
   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);
@@ -338,8 +419,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
     + 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;
@@ -402,6 +484,21 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
       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);
@@ -415,6 +512,7 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
   ((grub_uint32_t *) (playground + argv_off))[linux_argc]
     = target_addr + rd_size_arg_off;
   linux_argc++;
+#endif
 
   initrd_loaded = 1;
 
index 4bfc2c191218d59dabfd251e05cd0f6b6719b661..d9e74b3c753e048ec72b84db70bbd9dec3344dec 100644 (file)
@@ -43,6 +43,8 @@
 #include <grub/memory.h>
 #include <grub/i18n.h>
 
+GRUB_MOD_LICENSE ("GPLv3+");
+
 #ifdef GRUB_MACHINE_EFI
 #include <grub/efi/efi.h>
 #endif
index 0c29fe9c21f4c552ee43accb51b82d5d8a7baa9f..c6c88f177446ca3ec635a40b87ccd80113b18548 100644 (file)
 # 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
@@ -223,3 +225,4 @@ CONCAT(grub_multiboot_load_elf, XX) (grub_file_t file, void *buffer)
 #undef ELFCLASSXX
 #undef Elf_Ehdr
 #undef Elf_Phdr
+#undef Elf_Shdr
index 0cf0eb825b39e46c6e6d9dfe52e0f6b51868e61b..12a3fa9f6afe5cc81c60e71de19ee85e6bb9cad5 100644 (file)
@@ -29,6 +29,8 @@
 #include <grub/memory.h>
 #include <grub/lib/cmdline.h>
 
+GRUB_MOD_LICENSE ("GPLv3+");
+
 #define ELF32_LOADMASK (0xc0000000UL)
 #define ELF64_LOADMASK (0xc000000000000000ULL)
 
index a262049a70ec28e868d15d46f2953a24993d886a..8ed61f8bf9889b6e9c64a7677b1ca83d50f41ea6 100644 (file)
@@ -29,6 +29,8 @@
 #include <grub/memory.h>
 #include <grub/lib/cmdline.h>
 
+GRUB_MOD_LICENSE ("GPLv3+");
+
 static grub_dl_t my_mod;
 
 static int loaded;
index 73158fd1073c000b7e42ce1f92ae11898f434c86..a98d60c20c4788be8e5344ebcd8bf88478d73974 100644 (file)
@@ -34,6 +34,8 @@
 #include <grub/env.h>
 #include <grub/i18n.h>
 
+GRUB_MOD_LICENSE ("GPLv3+");
+
 #if defined (__i386) && !defined (GRUB_MACHINE_EFI)
 #include <grub/autoefi.h>
 #endif
diff --git a/grub-core/mmap/mips/uppermem.c b/grub-core/mmap/mips/uppermem.c
new file mode 100644 (file)
index 0000000..8326185
--- /dev/null
@@ -0,0 +1,68 @@
+/* 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;
+}
diff --git a/grub-core/mmap/mips/yeeloong/uppermem.c b/grub-core/mmap/mips/yeeloong/uppermem.c
deleted file mode 100644 (file)
index 723b6a8..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-/* 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;
-}
index 1c18254903d56c874701cd27e96dfe42286efbd1..07a71336ba5fa4a7f8bc054cd5ba1362241bcf6b 100644 (file)
@@ -26,6 +26,8 @@
 #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;
diff --git a/grub-core/modinfo.sh.in b/grub-core/modinfo.sh.in
new file mode 100644 (file)
index 0000000..ff31ca8
--- /dev/null
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+grub_modinfo_target_cpu=@target_cpu@
+grub_modinfo_platform=@platform@
diff --git a/grub-core/net/arp.c b/grub-core/net/arp.c
new file mode 100644 (file)
index 0000000..d726f2c
--- /dev/null
@@ -0,0 +1,167 @@
+#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;
+}
diff --git a/grub-core/net/bootp.c b/grub-core/net/bootp.c
new file mode 100644 (file)
index 0000000..84bdc04
--- /dev/null
@@ -0,0 +1,539 @@
+/*
+ *  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);
+}
diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c
new file mode 100644 (file)
index 0000000..5c6aac6
--- /dev/null
@@ -0,0 +1,201 @@
+/*
+ *  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);
+}
+
diff --git a/grub-core/net/drivers/emu/emunet.c b/grub-core/net/drivers/emu/emunet.c
new file mode 100644 (file)
index 0000000..d1e49a2
--- /dev/null
@@ -0,0 +1,86 @@
+
+#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);
+    }
+}
diff --git a/grub-core/net/drivers/i386/pc/pxe.c b/grub-core/net/drivers/i386/pc/pxe.c
new file mode 100644 (file)
index 0000000..cd598ea
--- /dev/null
@@ -0,0 +1,359 @@
+/* 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, &regs);
+
+  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);
+}
diff --git a/grub-core/net/drivers/ieee1275/ofnet.c b/grub-core/net/drivers/ieee1275/ofnet.c
new file mode 100644 (file)
index 0000000..20d45ee
--- /dev/null
@@ -0,0 +1,284 @@
+/*
+ *  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;
+}
diff --git a/grub-core/net/ethernet.c b/grub-core/net/ethernet.c
new file mode 100644 (file)
index 0000000..acd33bc
--- /dev/null
@@ -0,0 +1,130 @@
+/*
+ *  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;
+}
diff --git a/grub-core/net/ip.c b/grub-core/net/ip.c
new file mode 100644 (file)
index 0000000..642a67f
--- /dev/null
@@ -0,0 +1,159 @@
+/*
+ *  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;
+}
diff --git a/grub-core/net/net.c b/grub-core/net/net.c
new file mode 100644 (file)
index 0000000..0f8a604
--- /dev/null
@@ -0,0 +1,991 @@
+/*
+ *  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;
+}
diff --git a/grub-core/net/netbuff.c b/grub-core/net/netbuff.c
new file mode 100644 (file)
index 0000000..d20104a
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ *  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;
+}
diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c
new file mode 100644 (file)
index 0000000..be15340
--- /dev/null
@@ -0,0 +1,360 @@
+/*
+ *  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);
+}
diff --git a/grub-core/net/udp.c b/grub-core/net/udp.c
new file mode 100644 (file)
index 0000000..47a67a9
--- /dev/null
@@ -0,0 +1,99 @@
+#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;
+}
index 09f2271ea95805ef40939f475b9baeb6d9055a0b..ea06b4cc7db90f266774fd2592c106e28e089fb2 100644 (file)
@@ -500,8 +500,7 @@ grub_cmdline_get (const char *prompt)
        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));
@@ -566,8 +565,7 @@ grub_cmdline_get (const char *prompt)
            {
              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)
index cefb1cb9b167865346f0df5718c6b4a8f76831a3..f372b6798f1ec3953e9c46ad49d6b6be735504c3 100644 (file)
@@ -33,6 +33,8 @@
 #include <grub/charset.h>
 #include <grub/script_sh.h>
 
+GRUB_MOD_LICENSE ("GPLv3+");
+
 #define GRUB_DEFAULT_HISTORY_SIZE      50
 
 static int nested_level = 0;
@@ -471,9 +473,14 @@ grub_mini_cmd_clear (struct grub_command *cmd __attribute__ ((unused)),
 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");
 
@@ -515,6 +522,12 @@ GRUB_MOD_INIT(normal)
   /* 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)
index 5844cb2f0dc12b3f8c65c46a69b840dadfebf32d..2c127794b0fc6cd1238b2b051c8d0e1d22e28265 100644 (file)
@@ -232,7 +232,8 @@ grub_menu_execute_entry(grub_menu_entry_t entry, int auto_boot)
       grub_env_export ("chosen");
       grub_free (buf);
     }
-  for (ptr = def; *ptr; ptr++)
+
+  for (ptr = def; ptr && *ptr; ptr++)
     {
       if (ptr[0] == '>' && ptr[1] == '>')
        {
@@ -242,10 +243,12 @@ grub_menu_execute_entry(grub_menu_entry_t entry, int auto_boot)
       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)
index 677ec61d59630d81530659c12013d1f752c39797..341b8ac5fda16db0bbe511d20335d4b15d52c3e0 100644 (file)
@@ -23,6 +23,8 @@
 #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
@@ -69,7 +78,7 @@ acorn_partition_map_find (grub_disk_t disk, struct linux_part *m,
     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;
index 1e0f23402872a0b85d1268bf0e0ad51ed0eb165a..0b89cdc111a541dcff169dd18d68a79d7dd01b6b 100644 (file)
@@ -23,6 +23,8 @@
 #include <grub/partition.h>
 #include <grub/dl.h>
 
+GRUB_MOD_LICENSE ("GPLv3+");
+
 struct grub_amiga_rdsk
 {
   /* "RDSK".  */
@@ -37,7 +39,7 @@ struct grub_amiga_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
@@ -65,12 +67,24 @@ 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,
@@ -90,7 +104,8 @@ amiga_partition_map_iterate (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);
@@ -112,8 +127,10 @@ amiga_partition_map_iterate (grub_disk_t disk,
        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)
index e162d18d7d16ff2b0f8b908843841cba74ae6b91..c08cae589255260a97d932a4c630e267dbfe6d90 100644 (file)
@@ -22,6 +22,8 @@
 #include <grub/mm.h>
 #include <grub/partition.h>
 
+GRUB_MOD_LICENSE ("GPLv3+");
+
 #define GRUB_APPLE_HEADER_MAGIC        0x4552
 #define GRUB_APPLE_PART_MAGIC  0x504D
 
index 4dec3851c352d15f1a35939c6b34ad80ca3d52df..888100aa219d843e87bc78219cb47517bca25752 100644 (file)
@@ -25,6 +25,8 @@
 #include <grub/dl.h>
 #include <grub/msdos_partition.h>
 
+GRUB_MOD_LICENSE ("GPLv3+");
+
 #ifdef GRUB_UTIL
 #include <grub/emu/misc.h>
 #endif
diff --git a/grub-core/partmap/dvh.c b/grub-core/partmap/dvh.c
new file mode 100644 (file)
index 0000000..1184016
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ *  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);
+}
+
index 7f2c36143bbe95ecd678a85828bce8aaa136922d..73a1c3b195d35d4dbacc80f4fad8a6b7d806b919 100644 (file)
@@ -25,6 +25,8 @@
 #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
index 31a0a0707642a4d4c2fd82b39a4ddc1d7a2f9ff2..c8ab6acaba3d478c2070b37f5e7174c32a4a7536 100644 (file)
@@ -24,6 +24,8 @@
 #include <grub/misc.h>
 #include <grub/dl.h>
 
+GRUB_MOD_LICENSE ("GPLv3+");
+
 static struct grub_partition_map grub_msdos_partition_map;
 \f
 
@@ -90,8 +92,11 @@ grub_partition_msdos_iterate (grub_disk_t disk,
        {
          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",
@@ -126,7 +131,9 @@ grub_partition_msdos_iterate (grub_disk_t disk,
 
          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;
 
@@ -204,8 +211,11 @@ pc_partition_map_embed (struct grub_disk *disk, unsigned int *nsectors,
          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)
@@ -219,7 +229,9 @@ pc_partition_map_embed (struct grub_disk *disk, unsigned int *nsectors,
 
          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;
 
index 7af95c9397a9204059108d00f88b22a29f739c2d..c7ef681c48014d0b07bdcd2bb45cc540e9b0bb5d 100644 (file)
@@ -26,6 +26,8 @@
 #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
index ea69c28b9df32c5e67e1a36e44ce28c6bf2a80d8..28dc4f5be4d41710d266859dee932e07330191eb 100644 (file)
@@ -26,6 +26,8 @@
 #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
index 006a87defb94594c94eb0303ee7ca24e2e1cf5e6..ecaca140ad0415b66386b7c2c3a4fca3a2810b58 100644 (file)
@@ -28,6 +28,8 @@
 #include <grub/partition.h>
 #include <grub/parttool.h>
 
+GRUB_MOD_LICENSE ("GPLv2+");
+
 static int activate_table_handle = -1;
 static int type_table_handle = -1;
 
index 683b3ac4b98528f3956b6b23b50fc4220af8fa76..cc20b54797e0655335fb8645527a2606647d004d 100644 (file)
@@ -74,7 +74,6 @@
 %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"
@@ -147,7 +146,6 @@ argument : "case"      { $$ = grub_script_add_arglist (state, 0, $1); }
          | "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; }
 ;
 
index 53ae4c54f8c49fde38a46b9903fc3df9b084a53d..7195a880dc4b381f28b59721e73a672ce134566c 100644 (file)
@@ -161,7 +161,6 @@ MULTILINE       {WORD}?((\"{DQCHR}*)|(\'{SQCHR}*)|(\\\n))
 "}"             { 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;      }
@@ -355,8 +354,7 @@ grub_lexer_unput (const char *text, yyscan_t yyscanner)
 {
   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)
diff --git a/grub-core/term/arc/console.c b/grub-core/term/arc/console.c
new file mode 100644 (file)
index 0000000..b7e4287
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ *  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");
+}
index 7ce287ecc3aab534547c6b0c3c9ab8f4e2742a6e..b81e76230b58d032a820225dbb7d1b8b59210e2d 100644 (file)
@@ -26,6 +26,8 @@
 #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;
@@ -109,12 +111,12 @@ static const struct
     {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}, 
   };
@@ -257,7 +259,7 @@ grub_keyboard_controller_write (grub_uint8_t c)
   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)
@@ -330,7 +332,7 @@ set_scancodes (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
@@ -429,11 +431,11 @@ fetch_key (int *is_break)
   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;
@@ -567,7 +569,7 @@ grub_keyboard_controller_init (struct grub_term_input *term __attribute__ ((unus
       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
index 44d1a9be8bacdec048038ffa1c8522b0174a7881..2f8deac18e12eece624d7606e8653b1f76f0aee3 100644 (file)
@@ -31,6 +31,8 @@
 #include <grub/bitmap_scale.h>
 #include <grub/i18n.h>
 
+GRUB_MOD_LICENSE ("GPLv3+");
+
 #define DEFAULT_VIDEO_MODE     "auto"
 #define DEFAULT_BORDER_WIDTH   10
 
@@ -128,6 +130,8 @@ static struct grub_video_render_target *text_layer;
 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;
 
@@ -263,7 +267,8 @@ grub_virtual_screen_setup (unsigned int x, unsigned int y,
 
   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++)
@@ -335,15 +340,14 @@ grub_gfxterm_fullscreen (void)
   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");
@@ -392,12 +396,6 @@ grub_gfxterm_term_init (struct grub_term_output *term __attribute__ ((unused)))
 static void
 destroy_window (void)
 {
-  if (bitmap)
-    {
-      grub_video_bitmap_destroy (bitmap);
-      bitmap = 0;
-    }
-
   repaint_callback = 0;
   grub_virtual_screen_free ();
 }
@@ -481,26 +479,27 @@ redraw_screen_rect (unsigned int x, unsigned int y,
           /* 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);
@@ -1132,6 +1131,7 @@ grub_gfxterm_background_image_cmd (grub_extcmd_context_t ctxt,
     {
       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);
@@ -1171,6 +1171,8 @@ grub_gfxterm_background_image_cmd (grub_extcmd_context_t ctxt,
       /* 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);
@@ -1185,6 +1187,48 @@ grub_gfxterm_background_image_cmd (grub_extcmd_context_t ctxt,
   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",
@@ -1206,6 +1250,7 @@ static struct grub_term_output grub_video_term =
   };
 
 static grub_extcmd_t background_image_cmd_handle;
+static grub_command_t background_color_cmd_handle;
 
 GRUB_MOD_INIT(gfxterm)
 {
@@ -1216,10 +1261,16 @@ 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);
 }
index fbb65ae0cf3023fe6d183bfff59f33eeed6164f1..9abffcc0a6108561aa993969d0ad9b5237034089 100644 (file)
 
 #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)
index 4be528df8c5a1767eb6176b0b02ca9eea20a7397..996fc81f34ea1ef7811c90c5286f462fc45208b7 100644 (file)
@@ -37,7 +37,8 @@ static const grub_port_t serial_hw_io_addr[] = GRUB_MACHINE_SERIAL_PORTS;
 
 /* 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;
 
@@ -63,13 +64,16 @@ serial_get_divisor (unsigned int speed)
 
   /* 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;
 }
 
@@ -93,7 +97,7 @@ do_real_config (struct grub_serial_port *port)
 
   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);
@@ -111,8 +115,8 @@ do_real_config (struct grub_serial_port *port)
             | 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);
 
@@ -188,7 +192,7 @@ serial_hw_configure (struct grub_serial_port *port,
 {
   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");
 
index 32628dbaede9e9052bfbe9efeb5dc9774b20eeb3..306694192a430346c0f9447c24354cb92a053ebd 100644 (file)
 #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))
 
@@ -131,7 +136,7 @@ grub_serial_find (char *name)
 
 #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));
@@ -234,6 +239,15 @@ grub_cmd_serial (grub_extcmd_context_t ctxt, int argc, char **args)
   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)
 {
@@ -295,18 +309,32 @@ 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;
 }
index 0a8c75c740f3ce8d766030a0084e90789563d458..3419a5117e5a9cd4c90653dcafb091765fc7968d 100644 (file)
 #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.  */
@@ -121,6 +126,20 @@ grub_terminfo_set_current (struct grub_term_output *term,
       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");
@@ -367,8 +386,6 @@ grub_terminfo_getwh (struct grub_term_output *term)
   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))
@@ -428,7 +445,8 @@ grub_terminfo_readkey (struct grub_term_input *term, int *keys, int *len,
        {'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
@@ -443,6 +461,14 @@ grub_terminfo_readkey (struct grub_term_input *term, int *keys, int *len,
        {'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')
@@ -463,17 +489,53 @@ grub_terminfo_readkey (struct grub_term_input *term, int *keys, int *len,
          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
 }
index 23c0c10cabdd3e7e0910beab9cb030ec4ba84f4a..ae00936b8039df05194447200453b0d69df8f8a3 100644 (file)
@@ -27,6 +27,8 @@
 #include <grub/time.h>
 #include <grub/keyboard_layouts.h>
 
+GRUB_MOD_LICENSE ("GPLv3+");
+
 \f
 
 enum
index 52598814592c18357990bc05c0a38fb7f6b86425..8020887912ab84f380e54b1027e461a8de2d1a65 100644 (file)
@@ -18,6 +18,9 @@
 
 /* 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
index 521f4ad226db0418f66e0c6f18893bfd79fe356e..fd199bd63848c54511bb8ad1f48e1b1b07d68e3e 100644 (file)
@@ -20,6 +20,9 @@
 #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)),
index 41460fb7e1c80360bfeb58a6b7477d06a7a37cab..ddd46e1f62433c0e1193507bdb362e5e9c4e85d4 100644 (file)
@@ -24,6 +24,8 @@
 #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)
 {
index 659ab9a574f51aff9b55d306711e2535b2ed5aa2..32e9358a34d5b92e43901871afed69c8bd2cb1ce 100644 (file)
@@ -23,6 +23,8 @@
 #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;
 
index 6f8ff247ecfd52949d592c0755d7c33d96a15f9d..8da5697f8e90681787e8312b9e4ce0e3770dd213 100644 (file)
@@ -23,6 +23,9 @@
 #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,
index 832cd990311cc14059a61a4049880593fc5c75a0..79cae6547a9d649384ac759b54aadb32e99cd2bd 100644 (file)
@@ -28,6 +28,8 @@
 #include <grub/pci.h>
 #include <grub/vga.h>
 
+GRUB_MOD_LICENSE ("GPLv3+");
+
 static struct
 {
   struct grub_video_mode_info mode_info;
index a964c85cdd795e314197f328a91f56a28da028a0..7fad50e5b8760ebd0f91b0c2203f22b338c69b7e 100644 (file)
@@ -28,6 +28,8 @@
 #include <grub/pci.h>
 #include <grub/vga.h>
 
+GRUB_MOD_LICENSE ("GPLv3+");
+
 static struct
 {
   struct grub_video_mode_info mode_info;
diff --git a/grub-core/video/colors.c b/grub-core/video/colors.c
new file mode 100644 (file)
index 0000000..0662518
--- /dev/null
@@ -0,0 +1,325 @@
+/* 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;
+}
index f02dc9cb643a2b997f39961b5e80b0c629bfa4e0..d14ae98d2390c87a33a440cee0aa0970c98b8ade 100644 (file)
@@ -29,6 +29,8 @@
 #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;
index a8f70edea009dbf782cc3249342a644514fa8d13..1e709a52d01b0202cb7e61c9c818f676a450e59d 100644 (file)
@@ -30,6 +30,8 @@
 #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;
index d66b8b0c0ff31fc585867f6b5abc372547d4b22f..f4c1a6ab68ba5fe45cb6b4b13bbfd0d8d28a5afb 100644 (file)
@@ -27,6 +27,8 @@
 #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;
index 2226d6583cbe2ad9e9695b466987fd2027ff8011..2cffcb3d93d3ea9cfe2089d34ccb947c29e48abf 100644 (file)
@@ -24,6 +24,9 @@
 #include <grub/fbfill.h>
 #include <grub/fbutil.h>
 #include <grub/bitmap.h>
+#include <grub/dl.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
 
 static struct
 {
index 08bf124b6e7b88aeea55c4ac6549ba7f0e3d55c4..438ac92b2423a49132504079b47fcc9b7bef20c5 100644 (file)
 
 #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;
 
@@ -273,6 +274,56 @@ grub_vbe_bios_get_pm_interface (grub_uint16_t *segment, grub_uint16_t *offset,
   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, &regs);
+  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, &regs);
+
+  *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, &regs);
+  return regs.eax & 0xffff;
+}
+
 
 grub_err_t
 grub_vbe_probe (struct grub_vbe_info_block *info_block)
@@ -327,6 +378,61 @@ 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)
@@ -375,7 +481,7 @@ grub_vbe_set_video_mode (grub_uint32_t vbe_mode,
   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
     {
@@ -696,11 +802,28 @@ grub_video_vbe_setup (unsigned int width, unsigned int height,
   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++)
     {
@@ -743,10 +866,21 @@ grub_video_vbe_setup (unsigned int width, unsigned int height,
        /* 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)
@@ -900,6 +1034,7 @@ static struct grub_video_adapter grub_video_vbe_adapter =
     .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
index 19770ce0af225b90c5764175ad5f5d2a366f19fc..08c9ca37df70383d6164b49e7995787a3e97eac2 100644 (file)
@@ -18,8 +18,7 @@
 
 #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;
index 501ba7c2f38c8a8f4a47610539e9d4efd9fff8d2..913ea8376640f904441d6d36d2477f20315f087d 100644 (file)
@@ -27,6 +27,8 @@
 #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;
diff --git a/grub-core/video/radeon_fuloong2e.c b/grub-core/video/radeon_fuloong2e.c
new file mode 100644 (file)
index 0000000..3a65b67
--- /dev/null
@@ -0,0 +1,231 @@
+/*
+ *  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);
+}
index 9d88163bd2d46045cd5e05307228e086cdd69da6..f2351dee92ab4265cc882c9fa1476510b4fcaf02 100644 (file)
@@ -24,6 +24,8 @@
 #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))
@@ -64,6 +75,7 @@ struct grub_jpeg_data
 {
   grub_file_t file;
   struct grub_video_bitmap **bitmap;
+  grub_uint8_t *bitmap_ptr;
 
   int image_width;
   int image_height;
@@ -80,6 +92,8 @@ struct grub_jpeg_data
   jpeg_data_unit_t cbdu;
 
   int vs, hs;
+  int dri;
+  int r1;
 
   int dc_value[3];
 
@@ -313,6 +327,18 @@ grub_jpeg_decode_sof (struct grub_jpeg_data *data)
   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)
 {
@@ -524,8 +550,7 @@ grub_jpeg_ycrcb_to_rgb (int yy, int cr, int cb, grub_uint8_t * rgb)
 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;
@@ -561,17 +586,25 @@ grub_jpeg_decode_sos (struct grub_jpeg_data *data)
                                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;
@@ -586,10 +619,10 @@ grub_jpeg_decode_sos (struct grub_jpeg_data *data)
        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)
            {
@@ -598,8 +631,7 @@ grub_jpeg_decode_sos (struct grub_jpeg_data *data)
              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);
            }
@@ -608,6 +640,16 @@ grub_jpeg_decode_sos (struct grub_jpeg_data *data)
   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)
 {
@@ -653,8 +695,22 @@ grub_jpeg_decode_jpeg (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;
@@ -694,8 +750,7 @@ grub_video_reader_jpeg (struct grub_video_bitmap **bitmap,
       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);
     }
index 2cec49e2f848ec6d1ca2c18a6044431e18ab4b14..ae9879b1642369888cef6805d8d1bdf37100dd2b 100644 (file)
@@ -24,6 +24,8 @@
 #include <grub/misc.h>
 #include <grub/bufio.h>
 
+GRUB_MOD_LICENSE ("GPLv3+");
+
 /* Uncomment following define to enable PNG debug.  */
 //#define PNG_DEBUG
 
@@ -623,8 +625,7 @@ grub_png_output_byte (struct grub_png_data *data, grub_uint8_t n)
          }
        }
 
-      if (blank_line)
-       grub_free (blank_line);
+      grub_free (blank_line);
 
       data->cur_column = 0;
       data->first_line = 0;
index 6c9e9d691566c37aa1a0167722a109cd7f80845f..84be68a0a4b9f691c40d5eb7c9a76fefd30b30ad 100644 (file)
@@ -24,6 +24,8 @@
 #include <grub/misc.h>
 #include <grub/bufio.h>
 
+GRUB_MOD_LICENSE ("GPLv3+");
+
 /* Uncomment following define to enable TGA debug.  */
 //#define TGA_DEBUG
 
diff --git a/grub-core/video/sis315_init.c b/grub-core/video/sis315_init.c
new file mode 100644 (file)
index 0000000..ae5c141
--- /dev/null
@@ -0,0 +1,158 @@
+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,
+};
diff --git a/grub-core/video/sis315pro.c b/grub-core/video/sis315pro.c
new file mode 100644 (file)
index 0000000..22064c9
--- /dev/null
@@ -0,0 +1,448 @@
+/*
+ *  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
index 7a1a446e4329bd4cfdcb66631fbf30c06abe7082..ad87a69ffd19fc580c9a1cb36ffe25a4c000c167 100644 (file)
@@ -22,6 +22,8 @@
 #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;
 
@@ -374,6 +376,50 @@ grub_video_get_active_render_target (struct grub_video_render_target **target)
   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)
diff --git a/include/grub/arc/arc.h b/include/grub/arc/arc.h
new file mode 100644 (file)
index 0000000..aae7305
--- /dev/null
@@ -0,0 +1,259 @@
+/*
+ *  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
diff --git a/include/grub/arc/console.h b/include/grub/arc/console.h
new file mode 100644 (file)
index 0000000..e054f54
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ *  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 */
index 9e3aaf0e69407eec652328ec1d781c69fbad0088..1a19f27aaf920012000e08b920c485e12660c248 100644 (file)
@@ -22,6 +22,7 @@
 
 #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>
 
@@ -82,6 +83,9 @@ enum grub_ata_commands
     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,
@@ -89,29 +93,76 @@ enum grub_ata_commands
     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.  */
@@ -119,6 +170,7 @@ struct grub_ata_device
 
   /* Sector count.  */
   grub_uint64_t size;
+  grub_uint32_t log_sector_size;
 
   /* CHS maximums.  */
   grub_uint16_t cylinders;
@@ -128,47 +180,42 @@ struct grub_ata_device
   /* 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 */
index 636bd41a188a09b47558e6d3347b2158b2b33315..b10336c0100e8a19c5d6d8756559ee6720abb68c 100644 (file)
@@ -80,7 +80,10 @@ struct grub_partition_bsd_entry
 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;
index 4f913f5c85c3e74cd9de31342010cea3eab3be39..292830566604cfc72318ddc20a31613dee5a6b9a 100644 (file)
@@ -37,4 +37,14 @@ grub_arch_sync_caches (void *address __attribute__ ((unused)),
 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 */
index f508e3bf6ec988721c6f0cc0cdd371fce1a7b4bd..331513cd7f21a3de92cda1d033aa6350ff73dd37 100644 (file)
 #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
@@ -55,18 +57,56 @@ grub_num_to_bcd (grub_uint8_t a)
   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 */
index ebe78e7a1a1468b20c8f183815ab4c89a423e664..10368d99fc57832a8344ab73386784836cd46202 100644 (file)
@@ -126,6 +126,9 @@ typedef struct gcry_cipher_spec
   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;
 
@@ -161,6 +164,9 @@ typedef struct gcry_md_spec
   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;
 
@@ -193,7 +199,7 @@ grub_crypto_xor (void *out, const void *in1, const void *in2, grub_size_t size);
 
 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,
@@ -204,7 +210,7 @@ grub_crypto_cbc_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);
@@ -229,7 +235,8 @@ struct grub_crypto_hmac_handle *
 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);
@@ -237,7 +244,7 @@ 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;
@@ -274,4 +281,10 @@ grub_password_get (char buf[], unsigned buf_size);
 
 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
diff --git a/include/grub/cryptodisk.h b/include/grub/cryptodisk.h
new file mode 100644 (file)
index 0000000..c6d1ce8
--- /dev/null
@@ -0,0 +1,147 @@
+/*
+ *  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
index cd17e11fcbb2d0b31a6dcfbaaa08d47434397b7a..fcacb23e888ed826fbd06b35a9b349c9890feea1 100644 (file)
 #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
index e721e89af4808d9dec98de7e47826bd7c841c05b..dea0f8ea9f8999f21ee36338ba9bda1bbe4e1da7 100644 (file)
@@ -51,5 +51,85 @@ char *grub_get_weekday_name (struct grub_datetime *datetime);
 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 */
diff --git a/include/grub/deflate.h b/include/grub/deflate.h
new file mode 100644 (file)
index 0000000..ae4a1f2
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ *  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
index f0e8a8ca8ab621be83a81248c7d30e9950f7e359..f3e43bf601d76c0c557c7cab978c03fe63fa5fc1 100644 (file)
@@ -25,7 +25,6 @@
 
 struct grub_disk;
 struct grub_net;
-struct grub_fs;
 
 struct grub_device
 {
index 66db1149a4394810d29ebce9c35cbfb5169a2341..d9afd5b7b6544dfc251c0cf381118bd6ea10f89c 100644 (file)
@@ -42,7 +42,8 @@ enum grub_disk_dev_id
     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;
@@ -50,6 +51,14 @@ 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
 {
@@ -60,7 +69,8 @@ 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);
@@ -100,6 +110,9 @@ struct grub_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;
 
@@ -132,9 +145,10 @@ typedef struct grub_disk_memberlist *grub_disk_memberlist_t;
 /* 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
@@ -161,20 +175,14 @@ grub_err_t EXPORT_FUNC(grub_disk_write) (grub_disk_t disk,
 
 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);
index afc4af41aace8077e81a577b3b3f707553b36c3a..75cd71758998ac86c0a4cb8337fcc16d4d879933 100644 (file)
 #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)    \
@@ -51,20 +54,61 @@ static void \
 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;
@@ -92,6 +136,11 @@ struct grub_dl
   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;
@@ -109,7 +158,7 @@ extern grub_dl_t EXPORT_VAR(grub_dl_head);
 
 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);
@@ -119,4 +168,20 @@ 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 */
index cb6b1113b129a69ef90a2b709a3afd3601489c3b..b20baa015d34ddff44031ffb4ac02f05f4a5afc0 100644 (file)
     { 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 } \
@@ -1113,6 +1123,36 @@ struct grub_efi_simple_text_output_interface
 };
 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
@@ -1214,6 +1254,74 @@ struct grub_efi_block_io_media
 };
 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;
@@ -1234,7 +1342,7 @@ struct grub_efi_block_io
 };
 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)
@@ -1243,6 +1351,7 @@ typedef struct grub_efi_block_io grub_efi_block_io_t;
 #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
@@ -1250,24 +1359,31 @@ typedef struct grub_efi_block_io grub_efi_block_io_t;
 #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);
@@ -1285,6 +1401,10 @@ grub_uint64_t EXPORT_FUNC(efi_wrap_6) (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,
index e9c57dd11d4279200eafa4354e154375642a2e66..7ecda58abb6d860cad5da8aadb31975b6e8675e8 100644 (file)
@@ -62,6 +62,16 @@ grub_err_t EXPORT_FUNC (grub_efi_set_virtual_address_map) (grub_efi_uintn_t memo
                                                           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);
index 81a1a579767c3a0ffe6122ada012a44b76e4ac7c..c3efa9b3d906c64ec603f6d420b77a9bbc30ced4 100644 (file)
@@ -64,6 +64,7 @@ struct grub_pe32_coff_header
 };
 
 #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
index 540f6fc0462f2bc28e014821d4d6175541d357b6..51b3373096322abfc5e6f0e35f0e76cda28739d6 100644 (file)
@@ -21,8 +21,7 @@
 
 #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);
index b9401f241468871dc05dc5440675d4191e5b23c3..a02b902389113bde8bbcfbf1e6a514f78e7caa8b 100644 (file)
@@ -2348,6 +2348,8 @@ typedef Elf32_Xword Elf_Xword;
 
 #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)
@@ -2369,6 +2371,7 @@ typedef Elf64_Xword Elf_Xword;
 
 #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)
diff --git a/include/grub/emu/export.h b/include/grub/emu/export.h
new file mode 100644 (file)
index 0000000..1e2f043
--- /dev/null
@@ -0,0 +1,6 @@
+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);
+
index 581ea8056822caeb710d36292dd9aae26777abcd..6921e567c75b016d53b80b8fd54cb97ffa76fcf8 100644 (file)
@@ -25,6 +25,8 @@ enum grub_dev_abstraction_types {
   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);
@@ -34,5 +36,12 @@ char *grub_util_get_grub_dev (const char *os_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 */
index d8cc02e145d667bb3516bb0c166c3f1cede06eb5..719faa29b5334009bf6d41ea60ae5810b8adcd71 100644 (file)
@@ -21,6 +21,7 @@
 #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);
@@ -28,5 +29,17 @@ char *grub_util_biosdisk_get_grub_dev (const char *os_dev);
 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 */
index ef0d18300b625843a4d5d6fac3c54cb299c7423e..b4b8f7d285edb5a98b531f27fe837d072bac68dd 100644 (file)
@@ -54,6 +54,8 @@ void grub_find_zpool_from_dir (const char *dir,
 
 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));
@@ -78,4 +80,9 @@ extern char * canonicalize_file_name (const char *path);
 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 */
index 22334038d13a0cb71eca1aa663e5b6ed4adb522a..40f39dd5dd4957f3901ce61872e6c57e957573d7 100644 (file)
@@ -55,7 +55,12 @@ typedef enum
     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;
 
diff --git a/include/grub/fat.h b/include/grub/fat.h
new file mode 100644 (file)
index 0000000..7d8e51a
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ *  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
index 3adb1706f520bcadc3094cd78e09dd98db4989e9..e08ac2e26d2c9a07cb18bd1634d610b8ffaf6c0e 100644 (file)
@@ -56,9 +56,10 @@ typedef enum grub_file_filter_id
   {
     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);
index c52a3c71cb2479eb9dc93de7aad45721b0444a82..f858e9d493899e63b26f8ac80e2e803dd7d25409 100644 (file)
@@ -87,11 +87,11 @@ struct grub_gfxmenu_view
   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;
index f9678bf9e9c40e72677e962cf40821faf5fa1294..8ce666c5c0bd8e0b65143933ab300bebcef24329 100644 (file)
@@ -36,6 +36,7 @@ struct grub_gfxmenu_box
   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);
index 6e4a11cbe85b5746cee0c71f18563d2ebdf53fd3..ef0795cf7c1845a0a099aec250c557dfced8c342 100644 (file)
    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;
@@ -242,23 +232,6 @@ grub_gui_set_viewport (const grub_video_rect_t *r, grub_video_rect_t *old)
                            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)
index 1baa2eedee42ad138c9955a8d89e72b33993326a..34f9a090d1eb4b4e478e2d7655a4a62f71732fac 100644 (file)
@@ -30,8 +30,4 @@ char *grub_resolve_relative_path (const char *base, const char *path);
 
 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 */
index d93b9a2c9d80abb4bfc7517e5adc7542a780d28a..bf98610d9830f1fcc7edaf5ad60dea1e9ae0fa62 100644 (file)
@@ -39,7 +39,9 @@ typedef struct grub_hfs_extent grub_hfs_datarecord_t[3];
 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;
index 0642280b9a828b34e1bbe84e40a7ea96137b45f9..2859b1d7c7fcd044430709d6ffa0a8fc2b1c28b9 100644 (file)
 #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 */
index fed58a63049dad1cb65a039c1b5c3476b6bff209..6aa23910340fd598071b39a1200b6666a707650e 100644 (file)
@@ -41,7 +41,6 @@
 #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__
@@ -130,6 +129,10 @@ struct linux_kernel_header
   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
index fd429a2515f306229f4a9a9778df47fba05e017e..228f26aaa17c4babf68fce572ddc427de53ceecc 100644 (file)
 
 #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
 
@@ -83,6 +85,15 @@ struct grub_netbsd_btinfo_bootdisk
   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;
index ca1da23a744bb070740f339525db520050013a68..4776b181bbd4af1d64579229acda782a376669bf 100644 (file)
 
 #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 */
index de23775d08206d660345450c71dcf1ef1ed1389d..3377525874d2d8bdce641a17a71049a55a59b507 100644 (file)
@@ -45,7 +45,12 @@ struct grub_bios_int_registers
 #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);
index 1de37a5d5d9167f7917ad2790bdd00b062af7ecc..dd50aa8338ed0456cbf5bbe386914199e95292d9 100644 (file)
@@ -44,6 +44,8 @@ extern grub_int32_t grub_install_bsd_part;
 /* 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 */
index 62ece21b07a849e0a60cf11499aa58eaee3bf4d2..376a18962972e01793b357a13b7f71f66f19da1b 100644 (file)
 #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
@@ -214,38 +212,6 @@ struct grub_pxenv_get_cached_info
   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;
@@ -321,8 +287,6 @@ int EXPORT_FUNC(grub_pxe_call) (int func, void * data, grub_uint32_t pxe_rm_entr
 
 extern struct grub_pxe_bangpxe *grub_pxe_pxenv;
 
-void grub_pxe_unload (void);
-
 #endif
 
 #endif /* GRUB_CPU_PXE_H */
index fba3ee642fae91f95e1881bc220c932cf9fcd04b..09ad7eb6451407d5952dd3f0946336249ec5784a 100644 (file)
@@ -19,6 +19,8 @@
 #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
 
@@ -169,6 +171,21 @@ struct grub_vbe_palette_data
   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 
diff --git a/include/grub/i386/pc/vga.h b/include/grub/i386/pc/vga.h
deleted file mode 100644 (file)
index ecc1690..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- *  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 */
diff --git a/include/grub/i386/reboot.h b/include/grub/i386/reboot.h
new file mode 100644 (file)
index 0000000..c2716f3
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ *  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
index 6ff5c66319ca65ced025d0f97e8ffe392dca3cd6..778049eefc402f6f40e591d085c3f30634aecb7e 100644 (file)
@@ -46,6 +46,7 @@ struct grub_relocator16_state
   grub_uint16_t ss;
   grub_uint16_t sp;
   grub_uint16_t ip;
+  grub_uint32_t ebx;
   grub_uint32_t edx;
 };
 
diff --git a/include/grub/ia64/efi/memory.h b/include/grub/ia64/efi/memory.h
new file mode 100644 (file)
index 0000000..c9a61bb
--- /dev/null
@@ -0,0 +1 @@
+#include <grub/efi/memory.h>
diff --git a/include/grub/ia64/efi/time.h b/include/grub/ia64/efi/time.h
new file mode 100644 (file)
index 0000000..897ce9c
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ *  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 */
diff --git a/include/grub/ia64/kernel.h b/include/grub/ia64/kernel.h
new file mode 100644 (file)
index 0000000..c5496a0
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ *  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 */
diff --git a/include/grub/ia64/setjmp.h b/include/grub/ia64/setjmp.h
new file mode 100644 (file)
index 0000000..a71c9c5
--- /dev/null
@@ -0,0 +1,28 @@
+/* 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));
diff --git a/include/grub/ia64/time.h b/include/grub/ia64/time.h
new file mode 100644 (file)
index 0000000..03ee79f
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ *  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 */
diff --git a/include/grub/ia64/types.h b/include/grub/ia64/types.h
new file mode 100644 (file)
index 0000000..91a546d
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ *  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 */
index 4c56cc20f733e74974bac2885d4232cc7c1f2f75..81590ee4b8a76a6a0f0dec33a277204d374501e9 100644 (file)
@@ -24,7 +24,6 @@
 #include <grub/types.h>
 #include <grub/machine/ieee1275.h>
 
-/* Maps a device alias to a pathname.  */
 struct grub_ieee1275_devalias
 {
   char *name;
@@ -65,6 +64,11 @@ struct grub_ieee1275_common_hdr
 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 *);
@@ -191,11 +195,11 @@ EXPORT_FUNC(grub_ieee1275_map) (grub_addr_t phys, grub_addr_t virt,
 
 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 */
index 2ecc73df4fe2e02b63d33232ab61770e283048c1..2ff6b246915d58b4ea268638d7d09fb22f5db0c2 100644 (file)
@@ -26,7 +26,8 @@ enum
 {
   OBJ_TYPE_ELF,
   OBJ_TYPE_MEMDISK,
-  OBJ_TYPE_CONFIG
+  OBJ_TYPE_CONFIG,
+  OBJ_TYPE_PREFIX
 };
 
 /* The module header.  */
@@ -68,9 +69,15 @@ struct grub_module_info64
 #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);
 
@@ -84,13 +91,12 @@ void grub_machine_init (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 */
diff --git a/include/grub/lib/crc.h b/include/grub/lib/crc.h
new file mode 100644 (file)
index 0000000..c5098a8
--- /dev/null
@@ -0,0 +1,25 @@
+/* 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 */
index 8c4c19d8c323f668c25892b32a3d720084584363..7a433dc6804004f48be68beacbb392c76f67d3c2 100644 (file)
@@ -39,8 +39,42 @@ void EXPORT_FUNC (__bswapsi2) (void);
 # 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
index c71e8dd10a4180c4a7957e10b11454ae01e6f1dc..f38deb96a7e4f7e070d9ef16145ada12c0756618 100644 (file)
@@ -61,6 +61,6 @@ void *EXPORT_FUNC(grub_loader_register_preboot_hook) (grub_err_t (*preboot_func)
                                         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 */
index b962dfd6c42f25032c15858e5fc35e7734f1fbd1..b5352c75c72f06d9770c469a9f867761a5c5ba13 100644 (file)
@@ -44,6 +44,8 @@ struct grub_lvm_pv {
 
 struct grub_lvm_lv {
   char *name;
+  char *fullname;
+  char *compatname;
   unsigned int number;
   unsigned int segment_count;
   grub_uint64_t size;
diff --git a/include/grub/mips/arc/kernel.h b/include/grub/mips/arc/kernel.h
new file mode 100644 (file)
index 0000000..5069486
--- /dev/null
@@ -0,0 +1,2 @@
+#include <grub/cpu/kernel.h>
+
diff --git a/include/grub/mips/arc/memory.h b/include/grub/mips/arc/memory.h
new file mode 100644 (file)
index 0000000..b960d2a
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ *  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
diff --git a/include/grub/mips/arc/time.h b/include/grub/mips/arc/time.h
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/include/grub/mips/kernel.h b/include/grub/mips/kernel.h
new file mode 100644 (file)
index 0000000..d351f17
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ *  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 */
index 6cb1178d52e6a280e546ba3de8899972aeb905f2..e6f0241f2d53963454890e79923f89c755f0ec8c 100644 (file)
 #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
@@ -68,9 +64,9 @@
 #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)
 
@@ -85,6 +81,6 @@
 #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
diff --git a/include/grub/mips/loongson/at_keyboard.h b/include/grub/mips/loongson/at_keyboard.h
new file mode 100644 (file)
index 0000000..f279ac8
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ *  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
diff --git a/include/grub/mips/loongson/cmos.h b/include/grub/mips/loongson/cmos.h
new file mode 100644 (file)
index 0000000..f2a32d7
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ *  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 */
diff --git a/include/grub/mips/loongson/ec.h b/include/grub/mips/loongson/ec.h
new file mode 100644 (file)
index 0000000..3f8ff99
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ *  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
diff --git a/include/grub/mips/loongson/kernel.h b/include/grub/mips/loongson/kernel.h
new file mode 100644 (file)
index 0000000..ba94e43
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ *  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 */
diff --git a/include/grub/mips/loongson/memory.h b/include/grub/mips/loongson/memory.h
new file mode 100644 (file)
index 0000000..a288eb6
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ *  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
diff --git a/include/grub/mips/loongson/pci.h b/include/grub/mips/loongson/pci.h
new file mode 100644 (file)
index 0000000..57c7dd1
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ *  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 */
diff --git a/include/grub/mips/loongson/serial.h b/include/grub/mips/loongson/serial.h
new file mode 100644 (file)
index 0000000..45e6d84
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ *  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 
diff --git a/include/grub/mips/loongson/time.h b/include/grub/mips/loongson/time.h
new file mode 100644 (file)
index 0000000..8b8ee42
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ *  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 */
index e51bcc1f2b58d29fd589ebf54b63dcc09e3f88fc..a85bbe752f137b21af601e72a5507b451d3f8bc9 100644 (file)
@@ -1 +1,60 @@
-#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
diff --git a/include/grub/mips/mips.h b/include/grub/mips/mips.h
new file mode 100644 (file)
index 0000000..bafb2bd
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ *  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
diff --git a/include/grub/mips/qemu-mips/kernel.h b/include/grub/mips/qemu-mips/kernel.h
deleted file mode 100644 (file)
index 230455d..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- *  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 */
diff --git a/include/grub/mips/qemu-mips/loader.h b/include/grub/mips/qemu-mips/loader.h
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/include/grub/mips/qemu-mips/memory.h b/include/grub/mips/qemu-mips/memory.h
deleted file mode 100644 (file)
index 99d9ef2..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- *  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
diff --git a/include/grub/mips/qemu-mips/serial.h b/include/grub/mips/qemu-mips/serial.h
deleted file mode 100644 (file)
index 1f8ce08..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- *  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 
diff --git a/include/grub/mips/qemu-mips/time.h b/include/grub/mips/qemu-mips/time.h
deleted file mode 100644 (file)
index a73f64d..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- *  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 */
diff --git a/include/grub/mips/qemu_mips/at_keyboard.h b/include/grub/mips/qemu_mips/at_keyboard.h
new file mode 100644 (file)
index 0000000..37cc625
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ *  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
diff --git a/include/grub/mips/qemu_mips/cmos.h b/include/grub/mips/qemu_mips/cmos.h
new file mode 100644 (file)
index 0000000..4aef40e
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ *  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 */
diff --git a/include/grub/mips/qemu_mips/kernel.h b/include/grub/mips/qemu_mips/kernel.h
new file mode 100644 (file)
index 0000000..1e7e324
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ *  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 */
diff --git a/include/grub/mips/qemu_mips/loader.h b/include/grub/mips/qemu_mips/loader.h
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/include/grub/mips/qemu_mips/memory.h b/include/grub/mips/qemu_mips/memory.h
new file mode 100644 (file)
index 0000000..48a9b69
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ *  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
diff --git a/include/grub/mips/qemu_mips/serial.h b/include/grub/mips/qemu_mips/serial.h
new file mode 100644 (file)
index 0000000..1708678
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ *  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 
diff --git a/include/grub/mips/qemu_mips/time.h b/include/grub/mips/qemu_mips/time.h
new file mode 100644 (file)
index 0000000..164b61e
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ *  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 */
index b143a48e0a7db56498fe1a6064fb8c98f11b8c51..1139b24bb71c6081b0b99a57ceb181ad339822e5 100644 (file)
@@ -1,6 +1,37 @@
-#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
diff --git a/include/grub/mips/yeeloong/at_keyboard.h b/include/grub/mips/yeeloong/at_keyboard.h
deleted file mode 100644 (file)
index f279ac8..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- *  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
diff --git a/include/grub/mips/yeeloong/cmos.h b/include/grub/mips/yeeloong/cmos.h
deleted file mode 100644 (file)
index f2a32d7..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- *  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 */
diff --git a/include/grub/mips/yeeloong/ec.h b/include/grub/mips/yeeloong/ec.h
deleted file mode 100644 (file)
index 62d1d33..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- *  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
diff --git a/include/grub/mips/yeeloong/kernel.h b/include/grub/mips/yeeloong/kernel.h
deleted file mode 100644 (file)
index 15cf9f9..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- *  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 */
diff --git a/include/grub/mips/yeeloong/memory.h b/include/grub/mips/yeeloong/memory.h
deleted file mode 100644 (file)
index 9d53b5e..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- *  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
diff --git a/include/grub/mips/yeeloong/pci.h b/include/grub/mips/yeeloong/pci.h
deleted file mode 100644 (file)
index 199bac0..0000000
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- *  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 */
diff --git a/include/grub/mips/yeeloong/serial.h b/include/grub/mips/yeeloong/serial.h
deleted file mode 100644 (file)
index ebe3638..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- *  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 
diff --git a/include/grub/mips/yeeloong/time.h b/include/grub/mips/yeeloong/time.h
deleted file mode 100644 (file)
index 7f468bf..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- *  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 */
index 6fcaa148ba3ef5a30b8b01df427db1b442c7aaa6..0a0a4135ea79e0d6a32a1575aaebc5409bd64eb6 100644 (file)
@@ -136,6 +136,12 @@ grub_isdigit (int c)
   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)
 {
@@ -288,7 +294,8 @@ char *EXPORT_FUNC(grub_xvasprintf) (const char *fmt, va_list args) __attribute__
 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);
@@ -336,7 +343,7 @@ grub_div_roundup (unsigned int x, unsigned int y)
 }
 
 /* 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
index c6d71d5b62834f4273cad0922789ae35ef0a50d3..45d08f3f566e6397b6ec2ea7e769bf33bde0eb37 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  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 */
diff --git a/include/grub/net/arp.h b/include/grub/net/arp.h
new file mode 100644 (file)
index 0000000..c60ea33
--- /dev/null
@@ -0,0 +1,36 @@
+#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 
diff --git a/include/grub/net/ethernet.h b/include/grub/net/ethernet.h
new file mode 100644 (file)
index 0000000..a68aafd
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ *  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 
diff --git a/include/grub/net/ip.h b/include/grub/net/ip.h
new file mode 100644 (file)
index 0000000..9bed1e1
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ *  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 
diff --git a/include/grub/net/netbuff.h b/include/grub/net/netbuff.h
new file mode 100644 (file)
index 0000000..245e813
--- /dev/null
@@ -0,0 +1,30 @@
+#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
diff --git a/include/grub/net/udp.h b/include/grub/net/udp.h
new file mode 100644 (file)
index 0000000..5aacf8a
--- /dev/null
@@ -0,0 +1,38 @@
+#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 
index 31b99398bed04644e282c7647198be2498a94c5c..e220fecf40b251ce3ab06bc1c239b7f6dafe0c1d 100644 (file)
@@ -106,14 +106,16 @@ struct grub_ntfs_bpb
   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));
@@ -135,6 +137,7 @@ struct grub_fshelp_node
   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;
index 31deb5031db7b426527b69d907f62118f18046e2..526cfee68abc3bb8183b07a39590ed5468adda82 100644 (file)
 
 #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
index d5853639d53edda619f8829fe5ac8b0afa727335..1eb43721af948c016c85bfb8320a08c75989a1a5 100644 (file)
@@ -42,6 +42,7 @@ struct grub_raid_array
   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. */
index b30d317c71c3b60868143276fa548ce5bcb9b0e0..dfee69c625c11f54dfe204a88e2d35e39210d301 100644 (file)
@@ -19,6 +19,8 @@
 #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);
@@ -29,9 +31,13 @@ struct grub_scsi;
 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
@@ -45,16 +51,12 @@ grub_make_scsi_id (int subsystem, int bus, int lun)
 
 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);
index 9540bee64e1a23059eb3994ce42a101252db5152..41b720891f063e0bb5d5493c324f11698e8f7376 100644 (file)
@@ -102,7 +102,7 @@ grub_serial_config_defaults (struct grub_serial_port *port)
 {
   struct grub_serial_config config =
     {
-#ifdef GRUB_MACHINE_MIPS_YEELOONG
+#ifdef GRUB_MACHINE_MIPS_LOONGSON
       .speed = 115200,
 #else
       .speed = 9600,
index 726c84dbfebc4c921e43dbcd0b18074c02e0f359..4c997cdaf06961b5cc307813ee2603b463aec141 100644 (file)
@@ -248,6 +248,14 @@ grub_term_register_input (const char *name __attribute__ ((unused)),
     }
 }
 
+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)
@@ -272,6 +280,14 @@ grub_term_register_output (const char *name __attribute__ ((unused)),
     }
 }
 
+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)
index 5a552b3277541a7b4a1e32a8eb073f943949772c..e3b28ce88ab8b89f7bc69e333ecab9a7cbe09e16 100644 (file)
@@ -27,7 +27,7 @@ char *EXPORT_FUNC(grub_terminfo_get_current) (struct grub_term_output *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];
index 8632eacd0e4519def0714ed62542b8a0abf09e08..f057dd3d3a644117f9cb231af265c45cdb92e6ac 100644 (file)
@@ -99,9 +99,11 @@ typedef grub_int64_t grub_ssize_t;
 
 # 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
@@ -110,9 +112,14 @@ typedef grub_uint32_t      grub_size_t;
 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
@@ -215,4 +222,31 @@ static inline grub_uint64_t grub_swap_bytes64(grub_uint64_t x)
 # 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 */
index 6f838e4f943a7d871e3b413bfafc55326b8eef84..ee133dbf51926bdd5d3e0a260cf478ef83008a96 100644 (file)
@@ -38,7 +38,8 @@ typedef enum
     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
index 7a4c76c6bbfe8cf1bc786b90142d681bddc31dab..ff268f83f190583fb534b62554f1fbed37624602 100644 (file)
@@ -1,7 +1,7 @@
 /* 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
 
index 48dfbb8686db9353616a2a92a19e3192d3bdb374..419c8661cc1e1db16a32a67c9ad8ba336c92508d 100644 (file)
@@ -47,7 +47,6 @@ void grub_util_write_image_at (const void *img, size_t size, off_t offset,
 
 void sync (void);
 int fsync (int fno);
-void sleep(int s);
 
 grub_int64_t grub_util_get_disk_size (char *name);
 
diff --git a/include/grub/util/raid.h b/include/grub/util/raid.h
deleted file mode 100644 (file)
index 4da5eaa..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-/* 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 */
index 7f112d83acca3afbae638c3665767781af3913d7..58ec3ba1514c2c66240aacd40c96b08f790fa4cc 100644 (file)
 #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
   {
@@ -84,8 +89,8 @@ 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,
@@ -290,11 +295,24 @@ static inline void
 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;
index 5350d87eb36cb9ac10060607651c63ceb80f6be8..352544c85b8f2aac99a34c0aec62968d3573ad5c 100644 (file)
    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;
@@ -201,6 +210,66 @@ struct grub_video_palette_data
   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,
@@ -211,7 +280,9 @@ typedef enum grub_video_driver_id
     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
@@ -302,6 +373,8 @@ struct grub_video_adapter
 
   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;
@@ -414,6 +487,11 @@ grub_err_t EXPORT_FUNC (grub_video_set_active_render_target) (struct grub_video_
 
 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);
@@ -428,4 +506,27 @@ grub_video_check_mode_flag (grub_video_mode_type_t flags,
 
 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 */
index 1ef65405494b0b744f6da9b4f9b471561b86f894..5adfdc2900f7d25c7199fe8cdbabe09d0502834a 100644 (file)
@@ -90,7 +90,7 @@ typedef union zap_leaf_chunk {
                {
                        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 {
index 797d4f9b3a8584a14a9e662e44e7c1dc5fc5dda6..3dafb402800577e6020c8bf08fb348bc1b0afa33 100644 (file)
@@ -77,7 +77,15 @@ enum zio_compress {
        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
 };
 
index 8329fdf0a81f719a2705f0ce3e4e6e665dee89e5..ebb0aadaa5746da38b4da2459cd42cbec78e603c 100644 (file)
-# 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
index 80159958385d806574b5c1a1f4ba9a8dc03b1c1f..5541f42298fac2fe78d5b012983750ee49f1361f 100644 (file)
--- a/po/README
+++ b/po/README
@@ -8,6 +8,10 @@ that will hopefully clarify the situation.
 
       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.
 
index 9ac0424c08ff18df6315d74ec50cefa630b40e91..09633e89341e079a05fda7461d867e1541df4287 100644 (file)
@@ -1,3 +1,4 @@
-#!/bin/sh -e
+#!/bin/sh
+set -e
 
 true
index 43b479fec8cc1203ee02ae0e7f35a662ebe5a6f5..e7e6257011525ee42ca6945485208155fe717d24 100644 (file)
@@ -1,4 +1,5 @@
-#! /bin/bash -e
+#! /bin/bash
+set -e
 
 # Run GRUB script in a Qemu instance
 # Copyright (C) 2010  Free Software Foundation, Inc.
index 71b869bd3f7811feba84e67d036825f7bba6de4a..89ed763d3f4e0bb2a3ac3a61de9e0ec49b2eaccf 100644 (file)
@@ -1,4 +1,5 @@
-#! /bin/sh -e
+#! /bin/sh
+set -e
 
 @builddir@/grub-script-check <<EOF
 # comment 1
index 3819b8bc988141fdafa90c5e2a86d4dcfdfddd03..2e076427afbc86e05260b58e9f22f7e3fe48ce4e 100644 (file)
@@ -1,4 +1,5 @@
-#! /bin/sh -e
+#! /bin/sh
+set -e
 
 @builddir@/grub-script-check << EOF
 echo "\\\$"
index d1e8d55c99541464662840170c58d59c778f6598..1575bff619542ec9ab868c542103cb4336a3ec67 100644 (file)
@@ -1,4 +1,5 @@
-#! /bin/bash -e
+#! /bin/bash
+set -e
 
 # Run GRUB script in a Qemu instance
 # Copyright (C) 2010  Free Software Foundation, Inc.
index 99e55e5458c153d734ee7081b3034cb846aba595..3ac26540bbd7cf4614dc199534417b139c2bb7f0 100644 (file)
@@ -1,4 +1,5 @@
-#! /bin/sh -e
+#! /bin/sh
+set -e
 
 @builddir@/grub-script-check <<EOF
 echo one;
index 5a9c1a93d8d94c921f1cb202adcc3e9c622a1709..d8cdf7175f44d795ce20ab736beeadd4428a7f65 100644 (file)
@@ -1,5 +1,6 @@
-#! /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
@@ -15,7 +16,7 @@
 # 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 () {
index 02e49d3a448a87ae3e7fbef83d1f8862c0da24d4..04d0ad5d9c21130d0bab145292035867aa5d25bf 100644 (file)
@@ -1,4 +1,5 @@
-#! /bin/sh -e
+#! /bin/sh
+set -e
 
 # Compares GRUB script output with BASH output.
 # Copyright (C) 2009,2010  Free Software Foundation, Inc.
@@ -27,7 +28,6 @@ builddir=@builddir@
 PACKAGE_NAME=@PACKAGE_NAME@
 PACKAGE_TARNAME=@PACKAGE_TARNAME@
 PACKAGE_VERSION=@PACKAGE_VERSION@
-target_cpu=@target_cpu@
 
 # Force build directory components
 PATH=${builddir}:$PATH
index 0213376d0d24bbfda4e68936b21adaba0056cdef..77853217f584c6fbf1a244e34bdfc807375e2290 100644 (file)
@@ -1,4 +1,5 @@
-#! /bin/sh -e
+#! /bin/sh
+set -e
 
 # Run GRUB script in a Qemu instance
 # Copyright (C) 2009,2010  Free Software Foundation, Inc.
index 65cbb80ee0faae72c2c20129d4f5f8ec816035ad..64d49fe0bc8dfc7e72d6d303bfdb0b821ba0efb5 100644 (file)
@@ -402,7 +402,7 @@ unset __grub_mkimage_program
 #
 # grub-mkpasswd-pbkdf2
 #
-_grub_mkpasswd-pbkdf2 () {
+_grub_mkpasswd_pbkdf2 () {
     local cur
 
     COMPREPLY=()
@@ -417,7 +417,7 @@ _grub_mkpasswd-pbkdf2 () {
 }
 __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
 
 
@@ -462,7 +462,7 @@ unset __grub_probe_program
 #
 # grub-script-check
 #
-_grub_script-check () {
+_grub_script_check () {
     local cur
 
     COMPREPLY=()
@@ -477,7 +477,7 @@ _grub_script-check () {
 }
 __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:
index 30c18beea3345d099048b4b8ee6d41828d0f0e6b..208dcfdde104997b25e8ce1b63642d9691e18fa6 100644 (file)
@@ -1,7 +1,7 @@
 /* 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
@@ -286,6 +286,26 @@ get_scsi_disk_name (char *name, int unit)
 #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)
@@ -620,6 +640,48 @@ grub_util_iterate_devices (int NESTED_FUNC_ATTR (*hook) (const char *, int),
        }
     }
 
+#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++)
diff --git a/util/getroot.c b/util/getroot.c
new file mode 100644 (file)
index 0000000..3d6f937
--- /dev/null
@@ -0,0 +1,1605 @@
+/* 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;
+}
index 293bdf74a5885c50372c7d2dba5a419fbca7fe93..ad64701a2d3ca375f4365d2485af0d8d7c862647 100644 (file)
@@ -54,16 +54,21 @@ execute_command (char *name, int n, char **args)
   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))
@@ -107,7 +112,8 @@ 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)
     {
@@ -182,6 +188,26 @@ cmd_cp (char *src, char *dest)
   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)
 {
@@ -275,6 +301,7 @@ static char **images = NULL;
 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)
@@ -304,6 +331,15 @@ 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 ();
@@ -321,6 +357,9 @@ fstest (int n, char **args)
     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;
@@ -333,6 +372,9 @@ fstest (int n, char **args)
     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++)
@@ -356,6 +398,7 @@ static struct argp_option options[] = {
   {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},
@@ -366,7 +409,9 @@ static struct argp_option options[] = {
   {"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}
 };
 
@@ -389,6 +434,10 @@ argp_parser (int key, char *arg, struct argp_state *state)
       root = arg;
       return 0;
 
+    case 'C':
+      mount_crypt = 1;
+      return 0;
+
     case 's':
       skip = grub_strtoul (arg, &p, 0);
       if (*p == 's')
@@ -423,6 +472,10 @@ argp_parser (int key, char *arg, struct argp_state *state)
       verbosity++;
       return 0;
 
+    case 'u':
+      uncompress = 1;
+      return 0;
+
     case ARGP_KEY_END:
       if (args_count < num_disks)
        {
@@ -468,6 +521,11 @@ argp_parser (int key, char *arg, struct argp_state *state)
          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;
@@ -488,6 +546,11 @@ argp_parser (int key, char *arg, struct argp_state *state)
          cmd = CMD_BLOCKLIST;
           nparm = 1;
        }
+      else if (!grub_strcmp (arg, "testload"))
+       {
+         cmd = CMD_TESTLOAD;
+          nparm = 1;
+       }
       else
        {
          fprintf (stderr, _("Invalid command %s.\n"), arg);
@@ -523,6 +586,7 @@ main (int argc, char *argv[])
 
   /* Initialize all modules. */
   grub_init_all ();
+  grub_gcry_init_all ();
 
   if (debug_str)
     grub_env_set ("debug", debug_str);
@@ -551,6 +615,7 @@ main (int argc, char *argv[])
   fstest (args_count - 1 - num_disks, args);
 
   /* Free resources.  */
+  grub_gcry_fini_all ();
   grub_fini_all ();
 
   return 0;
index ff8bea87c3cabd717410ae18992858e3d74c6758..d11d24421077d57bc18ddeeeaf18f323fad656bf 100644 (file)
@@ -74,7 +74,7 @@ if [ "${target_cpu}-${platform}" = "i386-pc" ] ; then
 elif [ "${platform}" = "ieee1275" ] || [ "${platform}" = "efi" ] ; then
     disk_module=
 else
-    disk_module=ata
+    disk_module=native
 fi
 
 # Usage: usage
@@ -111,7 +111,7 @@ Install GRUB on your drive.
 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
@@ -263,6 +263,8 @@ do
     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
@@ -333,6 +335,12 @@ if [ x"$platform" = xefi ]; then
        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.
@@ -456,6 +464,8 @@ for dir in "${localedir}"/*; do
     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
 
@@ -489,6 +499,18 @@ done
 # 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"
@@ -522,7 +544,7 @@ if [ "x${devabstraction_module}" = "x" ] ; then
     # 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
@@ -536,6 +558,7 @@ if [ "x${devabstraction_module}" = "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 "
@@ -549,18 +572,26 @@ if [ "x${devabstraction_module}" = "x" ] ; then
        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
@@ -569,7 +600,7 @@ 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"
@@ -619,6 +650,9 @@ elif [ "${target_cpu}-${platform}" = "i386-ieee1275" ] || [ "${target_cpu}-${pla
            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.
index afc66f886b416ab5063c320ea8696343baa45df0..e317279f40c661c1fceb0d73f2afe987fad63196 100644 (file)
@@ -95,7 +95,7 @@ do
     esac
 done
 
-. ${libdir}/grub/grub-mkconfig_lib
+. ${libdir}/@PACKAGE@/grub-mkconfig_lib
 
 if [ "x$EUID" = "x" ] ; then
   EUID=`id -u`
@@ -239,6 +239,8 @@ export GRUB_DEFAULT \
   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 \
@@ -254,6 +256,7 @@ export GRUB_DEFAULT \
   GRUB_DISABLE_OS_PROBER \
   GRUB_INIT_TUNE \
   GRUB_SAVEDEFAULT \
+  GRUB_ENABLE_CRYPTODISK \
   GRUB_BADRAM
 
 if test "x${grub_cfg}" != "x"; then
index 2c5fd8c6f51f460a9a54b4453040386c14f9b35f..a453a6bb5ddc3b48763af1d24c38e80432e9d2f1 100644 (file)
@@ -63,10 +63,22 @@ is_path_readable_by_grub ()
 
   # ... 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
 }
 
@@ -105,12 +117,6 @@ prepare_grub_to_access_device ()
 {
   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
@@ -121,11 +127,23 @@ prepare_grub_to_access_device ()
     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`'"
@@ -139,7 +157,7 @@ grub_file_is_not_garbage ()
   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
index 70c5ef6a92f0622044db05846ceacbc67631ce0c..4440fdd127a1bbc0c448a3b55eb2727c2dd01cfb 100644 (file)
@@ -30,6 +30,7 @@
 #include <grub/misc.h>
 #include <grub/offsets.h>
 #include <grub/crypto.h>
+#include <grub/dl.h>
 #include <time.h>
 
 #include <stdio.h>
@@ -58,23 +59,24 @@ typedef enum {
 
 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;
@@ -87,18 +89,25 @@ struct image_target_desc
   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,
@@ -114,13 +123,12 @@ struct image_target_desc image_targets[] =
       .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,
@@ -136,13 +144,12 @@ struct image_target_desc image_targets[] =
       .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,
@@ -154,13 +161,12 @@ struct image_target_desc image_targets[] =
       .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,
@@ -172,13 +178,12 @@ struct image_target_desc image_targets[] =
       .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,
@@ -192,15 +197,16 @@ struct image_target_desc image_targets[] =
                                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,
@@ -216,13 +222,12 @@ struct image_target_desc image_targets[] =
       .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,
@@ -234,77 +239,92 @@ struct image_target_desc image_targets[] =
       .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,
@@ -320,13 +340,12 @@ struct image_target_desc image_targets[] =
       .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,
@@ -338,13 +357,12 @@ struct image_target_desc image_targets[] =
       .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,
@@ -355,6 +373,125 @@ struct image_target_desc image_targets[] =
       .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)))
@@ -618,6 +755,7 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[],
   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;
@@ -625,6 +763,7 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[],
   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;
@@ -653,6 +792,12 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[],
       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));
@@ -668,31 +813,47 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[],
                               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)
@@ -743,26 +904,42 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[],
       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
@@ -770,9 +947,9 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[],
   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);
     }
 
@@ -781,7 +958,6 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[],
       char *full_img;
       size_t full_size;
       char *decompress_path, *decompress_img;
-      size_t decompress_size;
       const char *name;
 
       switch (comp)
@@ -800,12 +976,19 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[],
       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);
@@ -902,12 +1085,7 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[],
                                  + 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);
@@ -928,10 +1106,7 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[],
        /* 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));
@@ -1098,7 +1273,7 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[],
        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);
@@ -1125,6 +1300,7 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[],
        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);
@@ -1163,27 +1339,48 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[],
       }
       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);
 
@@ -1215,7 +1412,104 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[],
       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:
@@ -1228,7 +1522,7 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[],
        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)
@@ -1263,7 +1557,7 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[],
 
        /* 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));
@@ -1276,21 +1570,26 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[],
        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);
@@ -1361,7 +1660,6 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[],
     }
 
   grub_util_write_image (core_img, core_size, out);
-  free (kernel_img);
   free (core_img);
   free (kernel_path);
 
@@ -1405,12 +1703,12 @@ usage (int status)
       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++ = ' ';
        }
@@ -1480,10 +1778,12 @@ main (int argc, char *argv[])
 
          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);
@@ -1578,35 +1878,19 @@ main (int argc, char *argv[])
 
   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)
index ce51f2fbc0a518edbb1a77d9513427baa49451b4..35229107056c20e672c2ab9a5bde76b0b8991703 100644 (file)
@@ -56,6 +56,7 @@ static Elf_Addr
 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;
@@ -65,6 +66,7 @@ SUFFIX (relocate_symbols) (Elf_Ehdr *e, Elf_Shdr *sections,
   Elf_Word i;
   Elf_Shdr *strtab_section;
   const char *strtab;
+  grub_uint64_t *jptr = jumpers;
 
   strtab_section
     = (Elf_Shdr *) ((char *) sections
@@ -101,9 +103,19 @@ SUFFIX (relocate_symbols) (Elf_Ehdr *e, Elf_Shdr *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)
@@ -134,6 +146,152 @@ SUFFIX (get_target_address) (Elf_Ehdr *e, Elf_Shdr *s, Elf_Addr offset,
   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
@@ -142,10 +300,15 @@ static void
 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;
@@ -200,7 +363,9 @@ SUFFIX (relocate_addresses) (Elf_Ehdr *e, Elf_Shdr *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:
@@ -224,11 +389,12 @@ SUFFIX (relocate_addresses) (Elf_Ehdr *e, Elf_Shdr *sections,
                                  *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))
                {
 
@@ -270,6 +436,85 @@ SUFFIX (relocate_addresses) (Elf_Ehdr *e, Elf_Shdr *sections,
                                   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);
+            }
          }
       }
 }
@@ -312,7 +557,7 @@ SUFFIX (add_fixup_entry) (struct fixup_block_list **cblock, grub_uint16_t type,
                  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.  */
@@ -374,9 +619,11 @@ static Elf_Addr
 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;
@@ -384,8 +631,7 @@ SUFFIX (make_reloc_section) (Elf_Ehdr *e, void **out,
   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)))
@@ -417,8 +663,9 @@ SUFFIX (make_reloc_section) (Elf_Ehdr *e, void **out,
            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;
@@ -431,9 +678,8 @@ SUFFIX (make_reloc_section) (Elf_Ehdr *e, void **out,
                                                  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))
                  {
@@ -452,10 +698,57 @@ SUFFIX (make_reloc_section) (Elf_Ehdr *e, void **out,
                                                  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);
 
   {
@@ -617,7 +910,10 @@ SUFFIX (load_image) (const char *kernel_path, grub_size_t *exec_size,
   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;
 
@@ -696,32 +992,68 @@ SUFFIX (load_image) (const char *kernel_path, grub_size_t *exec_size,
            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))
index b353e98b9d41b43549192343bffaee4af9929ace..52598a8c9e5a62e6623d3cc51db36b0a57e7b5d1 100644 (file)
@@ -27,12 +27,8 @@ libdir=@libdir@
 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`
@@ -49,6 +45,12 @@ debug=no
 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.
@@ -64,7 +66,7 @@ Install GRUB on your drive.
   --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
@@ -200,11 +202,20 @@ process_input_dir ()
        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
@@ -213,16 +224,35 @@ process_input_dir ()
 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
 
 
index fe1887f8ff23b493e7206b03030bde46c260992e..f75f276114029f8092c1bef11f9bc5e2af532119 100644 (file)
@@ -20,6 +20,7 @@
 
 #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>
@@ -29,7 +30,6 @@
 #include <stdlib.h>
 #include <string.h>
 #include <getopt.h>
-#include <termios.h>
 
 #include "progname.h"
 
@@ -85,14 +85,12 @@ int
 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]);
 
@@ -160,86 +158,37 @@ main (int argc, char *argv[])
       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");
@@ -248,11 +197,10 @@ main (int argc, char *argv[])
   {
     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);
@@ -264,13 +212,11 @@ main (int argc, char *argv[])
     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);
@@ -280,8 +226,7 @@ main (int argc, char *argv[])
                                 (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)
     {
index 455534009fc731446dab173a280bc30a59f57c62..4c96dd42ba021882312156a5ebbe7d73b715b6b3 100644 (file)
@@ -27,21 +27,19 @@ libdir=@libdir@
 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
 
@@ -160,7 +158,7 @@ process_input_dir ()
     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
@@ -231,14 +229,15 @@ if [ "${override_dir}" = "" ] ; then
         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} ;;
@@ -276,7 +275,7 @@ if test -e "${pc_dir}" ; then
 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
@@ -297,11 +296,11 @@ if test -e "${efi64_dir}" || test -e "${efi32_dir}"; then
     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
diff --git a/util/grub-mkstandalone.in b/util/grub-mkstandalone.in
new file mode 100644 (file)
index 0000000..e140ecc
--- /dev/null
@@ -0,0 +1,189 @@
+#! /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
index cf690841f36a9ba872aa1b79de5b4100d3abef33..4b93faa052524affc9a4cb67a0b1621a75060dae 100644 (file)
@@ -79,11 +79,12 @@ Report bugs to <%s>.\n", program_name, PACKAGE_BUGREPORT);
 #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
 
@@ -96,7 +97,7 @@ int num_sections;
 grub_uint32_t offset;
 
 static int
-insert_string (char *name)
+insert_string (const char *name)
 {
   int len, result;
 
@@ -124,6 +125,8 @@ write_section_data (FILE* fp, char *image,
 {
   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;
@@ -131,31 +134,42 @@ write_section_data (FILE* fp, char *image,
   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;
@@ -181,14 +195,14 @@ write_section_data (FILE* fp, char *image,
 
       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;
 
@@ -197,7 +211,7 @@ write_section_data (FILE* fp, char *image,
           num_sections++;
         }
       else
-        shdr[idx].sh_name = insert_string (pe_shdr->name);
+        shdr[idx].sh_name = insert_string (name);
     }
 
   return section_map;
index 0d5dac9021df260df50884d2271f1445c2b8155b..ae58c89f32f0e88efc184f4fb3288bc8b58e2b4a 100644 (file)
@@ -21,7 +21,6 @@
 #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>
@@ -34,6 +33,8 @@
 #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>
@@ -54,6 +55,7 @@ enum {
   PRINT_DEVICE,
   PRINT_PARTMAP,
   PRINT_ABSTRACTION,
+  PRINT_CRYPTODISK_UUID
 };
 
 int print = PRINT_FS;
@@ -63,15 +65,49 @@ static void
 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
@@ -88,6 +124,42 @@ probe_raid_level (grub_disk_t disk)
   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)
 {
@@ -108,7 +180,10 @@ 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);
@@ -136,91 +211,23 @@ probe (const char *path, char *device_name)
 
   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;
     }
 
@@ -289,8 +296,8 @@ Probe device information for a given path (or device, if the -d option is given)
 \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\
@@ -348,6 +355,8 @@ main (int argc, char *argv[])
              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;
@@ -393,6 +402,7 @@ main (int argc, char *argv[])
 
   /* Initialize all modules. */
   grub_init_all ();
+  grub_gcry_init_all ();
 
   grub_lvm_fini ();
   grub_mdraid09_fini ();
@@ -410,6 +420,7 @@ main (int argc, char *argv[])
     probe (argument, NULL);
 
   /* Free resources.  */
+  grub_gcry_fini_all ();
   grub_fini_all ();
   grub_util_biosdisk_fini ();
 
index ed2d63fdd24f3eb62670290f51a34c3785a4159b..b3a6c5c763bdbca78a60b00d6a9f8685f9cba79d 100644 (file)
@@ -1,7 +1,7 @@
 /* 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
@@ -32,7 +32,6 @@
 #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>
@@ -520,9 +519,7 @@ unable_to_embed:
   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
 
@@ -583,7 +580,7 @@ unable_to_embed:
        grub_util_info ("error message = %s", grub_errmsg);
 
       grub_errno = GRUB_ERR_NONE;
-      sync ();
+      grub_util_biosdisk_flush (root_dev->disk);
       sleep (1);
     }
 
@@ -674,8 +671,8 @@ unable_to_embed:
     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);
@@ -896,6 +893,7 @@ main (int argc, char *argv[])
 
   /* Initialize all modules. */
   grub_init_all ();
+  grub_gcry_init_all ();
 
   grub_lvm_fini ();
   grub_mdraid09_fini ();
@@ -956,10 +954,12 @@ main (int argc, char *argv[])
                       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] == '/'))
     {
@@ -974,12 +974,12 @@ main (int argc, char *argv[])
       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);
        }
 
index 9da1511f5e48f3113f1eb257af31ba2729191547..54012f854814d1900836c2c992a02849d8cf9ef6 100644 (file)
@@ -25,7 +25,7 @@ libdir=@libdir@
 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)
@@ -36,7 +36,7 @@ done
 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
index 8c54eab97b2e650dfb412f49fd465d1f975118b6..9ca01f0a897c04217a931cedf6e8a31ae661bf5b 100644 (file)
@@ -20,7 +20,7 @@ set -e
 prefix=@prefix@
 exec_prefix=@exec_prefix@
 libdir=@libdir@
-. ${libdir}/grub/grub-mkconfig_lib
+. ${libdir}/@PACKAGE@/grub-mkconfig_lib
 
 CLASS="--class gnu --class os"
 
index 3600c74f96fcbe81bd5d9498c91bd92f1f84535d..e4bfc06cb5a892976ffbf339970754ed6e29e5e2 100644 (file)
@@ -2,7 +2,7 @@
 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
@@ -21,7 +21,7 @@ prefix=@prefix@
 exec_prefix=@exec_prefix@
 bindir=@bindir@
 libdir=@libdir@
-. ${libdir}/grub/grub-mkconfig_lib
+. ${libdir}/@PACKAGE@/grub-mkconfig_lib
 
 export TEXTDOMAIN=@PACKAGE@
 export TEXTDOMAINDIR=@localedir@
@@ -98,6 +98,12 @@ EOF
 
   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
index 930ce06ef9655d964a94fd48866e2b95ccd88cf1..97e7c65233492fd68c97bff7223ca99b05414c8e 100644 (file)
@@ -21,7 +21,7 @@ prefix=@prefix@
 exec_prefix=@exec_prefix@
 bindir=@bindir@
 libdir=@libdir@
-. ${libdir}/grub/grub-mkconfig_lib
+. ${libdir}/@PACKAGE@/grub-mkconfig_lib
 
 export TEXTDOMAIN=@PACKAGE@
 export TEXTDOMAINDIR=@localedir@
@@ -51,6 +51,14 @@ else
   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"
@@ -90,10 +98,21 @@ EOF
 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'
@@ -123,6 +142,7 @@ case x`uname -m` in
 esac
 
 prepare_boot_cache=
+prepare_root_cache=
 
 while [ "x$list" != "x" ] ; do
   linux=`version_find_latest $list`
index ffd31ad93b574bcf6c8a0d65dbf240e3d9b7b9c8..c257aeb3cf03d9aaa2db3ab6415afdfa71e5bf1c 100644 (file)
@@ -21,7 +21,7 @@ prefix=@prefix@
 exec_prefix=@exec_prefix@
 bindir=@bindir@
 libdir=@libdir@
-. ${libdir}/grub/grub-mkconfig_lib
+. ${libdir}/@PACKAGE@/grub-mkconfig_lib
 
 export TEXTDOMAIN=@PACKAGE@
 export TEXTDOMAINDIR=@localedir@
index fd068dd2dec4a4e89d8c5b3030a09dfa9b512972..941267a9f113e2713b4c13c050f461f20a104752 100644 (file)
@@ -20,7 +20,7 @@ set -e
 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*)  ;;
index 858627aa3cc053ecc103c7811082ba95d5cdbcdc..c0b255598bdaa1308df59ef270030c1f7e1ddfc5 100644 (file)
@@ -21,7 +21,7 @@ prefix=@prefix@
 exec_prefix=@exec_prefix@
 bindir=@bindir@
 libdir=@libdir@
-. ${libdir}/grub/grub-mkconfig_lib
+. ${libdir}/@PACKAGE@/grub-mkconfig_lib
 
 export TEXTDOMAIN=@PACKAGE@
 export TEXTDOMAINDIR=@localedir@
@@ -51,6 +51,22 @@ else
   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"
index d9d4b0a96d0ff3bce49f1e9815dcad74e95c73af..c0b5d7cd729479e5028e86186e9113c8bb21e026 100644 (file)
@@ -21,7 +21,7 @@ prefix=@prefix@
 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
index 3ac6fce8bd7fa69e0af097dd0e1c929c464a4a4f..a9bc2cfda4f1116780d9d30e22b57b06bc8bb321 100644 (file)
@@ -32,11 +32,16 @@ int main(int argc, char **argv)
 
   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);
index 1a433345d7bdf0921ed243737b5404bda520a2f8..f72bea8a5f8ed1c3832626a479fb9f8a1c441354 100644 (file)
@@ -297,6 +297,7 @@ check_sas (char *sysfs_path, int *tgt)
 
   free (path);
   free (p);
+  close (fd);
 }
 
 static void
@@ -419,6 +420,7 @@ int main(int argc, char **argv)
 
   of_path = grub_util_devname_to_ofpath (argv[1]);
   printf("%s\n", of_path);
+  free (of_path);
 
   return 0;
 }
index 494a4ae7b64ed36a5aaf389a79d7e69851593725..720f1930312a6ab5fac556980ec6e7607000bea1 100644 (file)
@@ -20,6 +20,7 @@ import re
 import sys
 import os
 import datetime
+import codecs
 
 if len (sys.argv) < 3:
     print ("Usage: %s SOURCE DESTINATION" % sys.argv[0])
@@ -40,9 +41,17 @@ except:
     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
@@ -61,7 +70,7 @@ mdblocksizes = {"_gcry_digest_spec_crc32" : 64,
                 "_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
@@ -73,6 +82,8 @@ cryptolist.write ("AES-128: gcry_rijndael\n");
 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)
@@ -88,16 +99,22 @@ for cipher_file in cipher_files:
     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
@@ -109,6 +126,7 @@ for cipher_file in cipher_files:
                 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
@@ -127,15 +145,22 @@ for cipher_file in cipher_files:
                     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)
@@ -176,14 +201,18 @@ for cipher_file in cipher_files:
                 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 ()
@@ -244,6 +273,7 @@ for cipher_file in cipher_files:
                     % (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)
@@ -278,6 +308,7 @@ for cipher_file in cipher_files:
             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")
@@ -295,28 +326,28 @@ cryptolist.close ()
 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 ()
@@ -324,9 +355,35 @@ 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))
index bb2c19fe31de401db25063fef19e606e568fcfbf..0bc271e465b498799801908bfca679fb64528268 100644 (file)
@@ -1,7 +1,7 @@
 /* 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
@@ -17,8 +17,7 @@
  *  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>
@@ -26,8 +25,6 @@
 #include <string.h>
 #include <sys/stat.h>
 
-#define LVM_DEV_MAPPER_STRING "/dev/mapper/"
-
 int
 grub_util_lvm_isvolume (char *name)
 {
@@ -49,4 +46,4 @@ grub_util_lvm_isvolume (char *name)
     return 1;
 }
 
-#endif /* ! __linux__ */
+#endif
index cfbae609b711a03e40003d6f223ded0c244a4111..72bedde0c66988654f3c344d2115e96da2c7b00d 100644 (file)
@@ -55,6 +55,7 @@
 #ifdef __MINGW32__
 #include <windows.h>
 #include <winioctl.h>
+#include "dirname.h"
 #endif
 
 #ifdef GRUB_UTIL
@@ -316,17 +317,13 @@ int fsync (int fno __attribute__ ((unused)))
   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);
 
index a6aa5f95e19dc79e4e267c3b5799d9f28d3d1830..1e312491b0765217f834ac9a3cf4d1980bb2b0e0 100644 (file)
@@ -21,7 +21,6 @@
 #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>
@@ -36,7 +35,7 @@
 #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;
@@ -53,7 +52,14 @@ grub_util_raid_getmembers (const char *name)
   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);
 
@@ -80,6 +86,8 @@ grub_util_raid_getmembers (const char *name)
 
   devicelist[j] = NULL;
 
+  close (fd);
+
   return devicelist;
 }
 
index 998452e67c102fe076f31c839abb81f0357a02cf..430ce130824f91e5958ea28839f422d121195a8e 100644 (file)
@@ -18,6 +18,6 @@ prefix=@prefix@
 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"